Update: 2026-05-04 01:52:13

This commit is contained in:
Hamza-Ayed
2026-05-04 01:52:13 +03:00
parent 08106ac4ea
commit 282f33ca3a
4 changed files with 89 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
<?php
/**
* Delete Company Endpoint (Soft Delete)
*/
use App\Core\Database;
use App\Middleware\AuthMiddleware;
$decoded = AuthMiddleware::check();
$db = Database::getInstance();
$companyId = input('id');
if (!$companyId) {
json_error('Company ID is required', 422);
}
// Authorization
if ($decoded['role'] !== 'super_admin' && $decoded['role'] !== 'admin') {
json_error('Unauthorized', 403);
}
// Fetch company to check tenant if admin
$stmt = $db->prepare("SELECT tenant_id FROM companies WHERE id = ?");
$stmt->execute([$companyId]);
$company = $stmt->fetch();
if (!$company) {
json_error('الشركة غير موجودة', 404);
}
if ($decoded['role'] === 'admin' && $company['tenant_id'] !== $decoded['tenant_id']) {
json_error('ليس لديك صلاحية لحذف هذه الشركة', 403);
}
// Soft Delete
$stmt = $db->prepare("UPDATE companies SET deleted_at = NOW() WHERE id = ?");
$stmt->execute([$companyId]);
json_success(null, 'تم حذف الشركة بنجاح');

View File

@@ -14,6 +14,13 @@ $allowedRoles = ['admin', 'accountant', 'employee'];
if (!in_array($decoded['role'], $allowedRoles)) {
json_error('Unauthorized to upload invoices', 403);
}
// 2. Validate Request
$data = input();
$companyId = $data['company_id'] ?? null;
if (!$companyId || !isset($_FILES['invoice'])) {
json_error('Company ID and invoice file are required', 422);
}
// 3. Permission Check
$tenantId = $decoded['tenant_id'];

View File

@@ -24,6 +24,7 @@ $routes = [
'v1/users/delete' => ['POST', 'users/delete.php'],
'v1/companies' => ['GET', 'companies/index.php'],
'v1/companies/create' => ['POST', 'companies/create.php'],
'v1/companies/delete' => ['POST', 'companies/delete.php'],
'v1/invoices' => ['GET', 'invoices/index.php'],
'v1/invoices/upload' => ['POST', 'invoices/upload.php'],
'v1/dashboard/stats' => ['GET', 'dashboard/stats.php'],

View File

@@ -153,6 +153,42 @@
</div>
</div>
<!-- Companies -->
<div x-show="page === 'companies'">
<div class="bg-surface border border-gray-800 rounded-2xl overflow-hidden shadow-2xl">
<table class="w-full text-right divide-y divide-gray-800">
<thead class="bg-gray-900/50">
<tr>
<th class="p-5 text-xs font-bold text-gray-500 uppercase">الشركة</th>
<th class="p-5 text-xs font-bold text-gray-500 uppercase">الأرقام الرسمية</th>
<th class="p-5 text-xs font-bold text-gray-500 uppercase">العنوان</th>
<th class="p-5 text-xs font-bold text-gray-500 uppercase">المكتب</th>
<th class="p-5 text-xs font-bold text-gray-500 uppercase">إجراءات</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-800">
<tr x-show="companies.length === 0"><td colspan="5" class="p-12 text-center text-gray-600">لا توجد شركات بعد</td></tr>
<template x-for="c in companies" :key="c.id">
<tr class="hover:bg-white/[0.01] transition-colors group">
<td class="p-5">
<p class="font-bold text-emerald-500" x-text="c.name"></p>
</td>
<td class="p-5">
<p class="text-xs text-gray-400">TIN: <span class="font-mono" x-text="c.tax_identification_number"></span></p>
<p class="text-xs text-gray-400">CRN: <span class="font-mono" x-text="c.commercial_registration_number"></span></p>
</td>
<td class="p-5 text-sm text-gray-500" x-text="c.address"></td>
<td class="p-5 text-xs text-gray-500" x-text="c.tenant_name || '-'"></td>
<td class="p-5">
<button x-show="user?.role === 'super_admin' || user?.role === 'admin'" @click="confirmDeleteCompany(c)" class="text-gray-500 hover:text-red-500 p-2 rounded-lg hover:bg-red-500/10 transition">🗑️</button>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</div>
<!-- Users List -->
<div x-show="page === 'users'">
<div class="bg-surface border border-gray-800 rounded-2xl overflow-hidden shadow-2xl">
@@ -372,6 +408,12 @@
if (res.success) this.loadUsers();
},
async confirmDeleteCompany(c) {
if (!confirm(`هل أنت متأكد من حذف شركة ${c.name}؟`)) return;
const res = await this.apiPost('v1/companies/delete', { id: c.id });
if (res.success) this.loadCompanies();
},
handleFile(e) { this.selectedFile = e.target.files[0]; },
async uploadInvoice() {