Files
musadaq-saas/app/modules_app/invoices/update.php
2026-05-08 04:58:23 +03:00

117 lines
3.6 KiB
PHP

<?php
/**
* Update Invoice (Before Approval Only)
* POST /v1/invoices/update
* Allows editing extracted data before final approval.
*/
use App\Core\Database;
use App\Core\Encryption;
use App\Core\AuditLogger;
use App\Middleware\AuthMiddleware;
$decoded = AuthMiddleware::check();
$data = input();
$id = $data['id'] ?? null;
if (!$id) json_error('معرّف الفاتورة مطلوب', 422);
$db = Database::getInstance();
$tenantId = $decoded['tenant_id'];
$role = $decoded['role'];
// 1. Fetch & verify access
$query = $role === 'super_admin'
? "SELECT * FROM invoices WHERE id = ?"
: "SELECT * FROM invoices WHERE id = ? AND tenant_id = ?";
$params = $role === 'super_admin' ? [$id] : [$id, $tenantId];
$stmt = $db->prepare($query);
$stmt->execute($params);
$invoice = $stmt->fetch();
if (!$invoice) json_error('الفاتورة غير موجودة', 404);
// 2. Only allow editing extracted (not yet approved) invoices
if (!in_array($invoice['status'], ['extracted', 'pending'])) {
json_error('لا يمكن تعديل الفاتورة بعد اعتمادها', 403);
}
$db->beginTransaction();
try {
// 3. Update main invoice fields
$fields = [];
$values = [];
$plainFields = ['invoice_number', 'invoice_date', 'invoice_type', 'invoice_category',
'subtotal', 'tax_amount', 'discount_total', 'grand_total', 'currency_code'];
foreach ($plainFields as $f) {
if (isset($data[$f])) {
$fields[] = "$f = ?";
$values[] = $data[$f];
}
}
// Encrypted fields
$encryptedFields = [
'supplier_name' => 'supplier_name',
'supplier_tin' => 'supplier_tin',
'supplier_address' => 'supplier_address',
'buyer_name' => 'buyer_name',
'buyer_tin' => 'buyer_tin',
'buyer_national_id' => 'buyer_national_id',
];
foreach ($encryptedFields as $key => $column) {
if (isset($data[$key])) {
$fields[] = "$column = ?";
$values[] = !empty($data[$key]) ? Encryption::encrypt($data[$key]) : '';
}
}
if (!empty($fields)) {
$fields[] = 'updated_at = NOW()';
$values[] = $id;
$sql = "UPDATE invoices SET " . implode(', ', $fields) . " WHERE id = ?";
$db->prepare($sql)->execute($values);
}
// 4. Update line items (if provided)
if (isset($data['items']) && is_array($data['items'])) {
// Delete old lines
$db->prepare("DELETE FROM invoice_lines WHERE invoice_id = ?")->execute([$id]);
// Insert new lines
$lineStmt = $db->prepare(
"INSERT INTO invoice_lines (id, invoice_id, line_number, description, quantity, unit_price, tax_rate, line_total)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
);
foreach ($data['items'] as $idx => $item) {
$lineStmt->execute([
Database::generateUuid(),
$id,
$item['line_number'] ?? ($idx + 1),
$item['description'] ?? '',
$item['quantity'] ?? 1,
$item['unit_price'] ?? 0,
$item['tax_rate'] ?? 0,
$item['line_total'] ?? 0,
]);
}
}
$db->commit();
AuditLogger::log('invoice.updated', 'invoice', $id, null, [
'fields_updated' => array_keys($data),
], $decoded);
json_success(null, 'تم تحديث بيانات الفاتورة بنجاح');
} catch (\Exception $e) {
$db->rollBack();
error_log("Invoice Update Error: " . $e->getMessage());
safe_error($e, 'invoices/update', 'فشل تحديث الفاتورة.');
}