Update: 2026-05-04 21:34:28
This commit is contained in:
63
app/modules_app/tenants/update.php
Normal file
63
app/modules_app/tenants/update.php
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Update Tenant Endpoint (Super Admin Only)
|
||||||
|
*/
|
||||||
|
|
||||||
|
use App\Core\Database;
|
||||||
|
use App\Core\Validator;
|
||||||
|
use App\Middleware\AuthMiddleware;
|
||||||
|
|
||||||
|
$decoded = AuthMiddleware::check();
|
||||||
|
|
||||||
|
if ($decoded['role'] !== 'super_admin') {
|
||||||
|
json_error('Unauthorized', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = input();
|
||||||
|
|
||||||
|
$errors = Validator::validate($data, [
|
||||||
|
'id' => 'required',
|
||||||
|
'name' => 'required',
|
||||||
|
'email' => 'required|email',
|
||||||
|
'status' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($errors) {
|
||||||
|
json_error('Validation Failed', 422, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = Database::getInstance();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Encrypt sensitive data
|
||||||
|
$encryptedName = \App\Core\Encryption::encrypt($data['name']);
|
||||||
|
$encryptedEmail = \App\Core\Encryption::encrypt($data['email']);
|
||||||
|
|
||||||
|
$stmt = $db->prepare("
|
||||||
|
UPDATE tenants
|
||||||
|
SET name = ?, email = ?, phone = ?, status = ?, updated_at = NOW()
|
||||||
|
WHERE id = ?
|
||||||
|
");
|
||||||
|
|
||||||
|
$stmt->execute([
|
||||||
|
$encryptedName,
|
||||||
|
$encryptedEmail,
|
||||||
|
$data['phone'] ?? null,
|
||||||
|
$data['status'],
|
||||||
|
$data['id']
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($stmt->rowCount() === 0) {
|
||||||
|
// Might be unchanged or ID doesn't exist
|
||||||
|
$check = $db->prepare("SELECT id FROM tenants WHERE id = ?");
|
||||||
|
$check->execute([$data['id']]);
|
||||||
|
if (!$check->fetch()) {
|
||||||
|
json_error('Tenant not found', 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json_success(null, 'تم تحديث بيانات المكتب بنجاح');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
json_error('حدث خطأ أثناء التحديث: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
@@ -36,6 +36,7 @@ $routes = [
|
|||||||
'v1/dashboard/stats' => ['GET', 'dashboard/stats.php'],
|
'v1/dashboard/stats' => ['GET', 'dashboard/stats.php'],
|
||||||
'v1/tenants' => ['GET', 'tenants/index.php'],
|
'v1/tenants' => ['GET', 'tenants/index.php'],
|
||||||
'v1/tenants/create' => ['POST', 'tenants/create.php'],
|
'v1/tenants/create' => ['POST', 'tenants/create.php'],
|
||||||
|
'v1/tenants/update' => ['POST', 'tenants/update.php'],
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isset($routes[$route])) {
|
if (isset($routes[$route])) {
|
||||||
|
|||||||
@@ -274,7 +274,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="p-6 text-xs text-gray-500 font-mono" x-text="t.created_at"></td>
|
<td class="p-6 text-xs text-gray-500 font-mono" x-text="t.created_at"></td>
|
||||||
<td class="p-6">
|
<td class="p-6">
|
||||||
<button class="text-gray-500 hover:text-emerald-400 p-2 transition">⚙️</button>
|
<button @click="openEditTenantModal(t)" class="text-gray-500 hover:text-emerald-400 p-2 rounded-lg hover:bg-emerald-400/10 transition-all">⚙️</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
@@ -504,6 +504,45 @@
|
|||||||
<div x-show="currentInvoice?.status === 'approved'" class="w-full bg-emerald-900/30 text-emerald-400 py-3 rounded-2xl font-bold text-center border border-emerald-900/50">
|
<div x-show="currentInvoice?.status === 'approved'" class="w-full bg-emerald-900/30 text-emerald-400 py-3 rounded-2xl font-bold text-center border border-emerald-900/50">
|
||||||
✅ مدققة وموثقة محلياً
|
✅ مدققة وموثقة محلياً
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Edit Tenant Modal (Super Admin Only) -->
|
||||||
|
<div x-show="showEditTenantModal" x-cloak class="fixed inset-0 bg-black/90 flex items-center justify-center p-6 z-[140]">
|
||||||
|
<div class="bg-surface border border-gray-800 w-full max-w-xl p-10 rounded-[40px] shadow-2xl glass-elevated overflow-y-auto max-h-[90vh]">
|
||||||
|
<h3 class="text-2xl font-bold mb-8 text-emerald-400">تعديل بيانات المكتب</h3>
|
||||||
|
<form @submit.prevent="updateTenant" class="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-bold text-gray-500 uppercase mb-2">اسم المكتب</label>
|
||||||
|
<input type="text" x-model="currentTenant.name" class="w-full bg-gray-950 border border-gray-800 p-4 rounded-2xl outline-none focus:border-emerald-500" required>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-bold text-gray-500 uppercase mb-2">البريد الرسمي</label>
|
||||||
|
<input type="email" x-model="currentTenant.email" class="w-full bg-gray-950 border border-gray-800 p-4 rounded-2xl outline-none focus:border-emerald-500" required>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-bold text-gray-500 uppercase mb-2">رقم الهاتف</label>
|
||||||
|
<input type="text" x-model="currentTenant.phone" class="w-full bg-gray-950 border border-gray-800 p-4 rounded-2xl outline-none focus:border-emerald-500">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-bold text-gray-500 uppercase mb-2">حالة المكتب</label>
|
||||||
|
<select x-model="currentTenant.status" class="w-full bg-gray-950 border border-gray-800 p-4 rounded-2xl outline-none focus:border-emerald-500">
|
||||||
|
<option value="active">نشط (Active)</option>
|
||||||
|
<option value="suspended">معلق (Suspended)</option>
|
||||||
|
<option value="trial">تجريبي (Trial)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex gap-4 pt-6 border-t border-gray-800">
|
||||||
|
<button type="submit" class="flex-1 bg-emerald-600 hover:bg-emerald-500 py-4 rounded-2xl font-bold transition-all btn-glow" :disabled="isBusy">
|
||||||
|
<span x-show="!isBusy">💾 حفظ التعديلات</span>
|
||||||
|
<span x-show="isBusy">⏳ جاري الحفظ...</span>
|
||||||
|
</button>
|
||||||
|
<button type="button" @click="showEditTenantModal = false" class="px-8 py-4 border border-gray-800 rounded-2xl hover:bg-gray-800 transition-colors">إلغاء</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -556,7 +595,7 @@
|
|||||||
|
|
||||||
showAddUserModal: false, showAddCompanyModal: false, showConnectModal: false,
|
showAddUserModal: false, showAddCompanyModal: false, showConnectModal: false,
|
||||||
showUploadModal: false, showViewModal: false, showCompanyStatsModal: false,
|
showUploadModal: false, showViewModal: false, showCompanyStatsModal: false,
|
||||||
showAddTenantModal: false,
|
showAddTenantModal: false, showEditTenantModal: false,
|
||||||
isBusy: false, globalError: '',
|
isBusy: false, globalError: '',
|
||||||
|
|
||||||
newUser: { name: '', email: '', password: '', role: 'accountant' },
|
newUser: { name: '', email: '', password: '', role: 'accountant' },
|
||||||
@@ -564,7 +603,7 @@
|
|||||||
newTenant: { name: '', email: '', phone: '', manager_name: '', manager_email: '', manager_password: '' },
|
newTenant: { name: '', email: '', phone: '', manager_name: '', manager_email: '', manager_password: '' },
|
||||||
connectData: { client_id: '', secret_key: '', income_source_sequence: '1' },
|
connectData: { client_id: '', secret_key: '', income_source_sequence: '1' },
|
||||||
uploadData: { company_id: '' },
|
uploadData: { company_id: '' },
|
||||||
currentCompany: null, currentInvoice: null, companyStats: null,
|
currentCompany: null, currentInvoice: null, companyStats: null, currentTenant: { name: '', email: '', phone: '', status: '' },
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
if (!this.user) { window.location.href = '/login.php'; return; }
|
if (!this.user) { window.location.href = '/login.php'; return; }
|
||||||
@@ -643,6 +682,22 @@
|
|||||||
this.isBusy = false;
|
this.isBusy = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
openEditTenantModal(t) {
|
||||||
|
this.currentTenant = JSON.parse(JSON.stringify(t));
|
||||||
|
this.showEditTenantModal = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
async updateTenant() {
|
||||||
|
this.isBusy = true;
|
||||||
|
const res = await this.apiRequest('v1/tenants/update', 'POST', this.currentTenant);
|
||||||
|
if (res) {
|
||||||
|
this.showEditTenantModal = false;
|
||||||
|
this.loadAll();
|
||||||
|
alert('تم تحديث بيانات المكتب بنجاح');
|
||||||
|
}
|
||||||
|
this.isBusy = false;
|
||||||
|
},
|
||||||
|
|
||||||
openConnectModal(company) {
|
openConnectModal(company) {
|
||||||
this.currentCompany = company;
|
this.currentCompany = company;
|
||||||
this.connectData.client_id = '';
|
this.connectData.client_id = '';
|
||||||
|
|||||||
Reference in New Issue
Block a user