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', 'فشل تحديث الفاتورة.'); }