131 lines
4.7 KiB
PHP
131 lines
4.7 KiB
PHP
<?php
|
|
/**
|
|
* Approve Invoice & Submit to JoFotara
|
|
*/
|
|
|
|
use App\Core\Database;
|
|
use App\Core\JoFotara;
|
|
use App\Core\AuditLogger;
|
|
use App\Middleware\AuthMiddleware;
|
|
use App\Middleware\RoleMiddleware;
|
|
use App\Middleware\CompanyAccessMiddleware;
|
|
|
|
// Only admin, accountant, and super_admin can approve. Viewers cannot.
|
|
$decoded = RoleMiddleware::require(['super_admin', 'admin', 'accountant']);
|
|
$db = Database::getInstance();
|
|
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
$id = $data['id'] ?? null;
|
|
|
|
if (!$id) {
|
|
json_error('Invoice ID is required', 422);
|
|
}
|
|
|
|
try {
|
|
$db->beginTransaction();
|
|
|
|
// 1. Fetch Invoice & Company
|
|
$stmt = $db->prepare("
|
|
SELECT i.*, c.name as company_name, c.tax_identification_number as company_tin,
|
|
c.address as company_address, c.jofotara_client_id_encrypted, c.jofotara_secret_key_encrypted
|
|
FROM invoices i
|
|
JOIN companies c ON i.company_id = c.id
|
|
WHERE i.id = ? FOR UPDATE
|
|
");
|
|
$stmt->execute([$id]);
|
|
$invoice = $stmt->fetch();
|
|
|
|
if (!$invoice) json_error('Invoice not found', 404);
|
|
if ($invoice['status'] === 'approved') json_error('Already approved', 400);
|
|
|
|
// 2. Fetch Line Items
|
|
$stmtLines = $db->prepare("SELECT * FROM invoice_lines WHERE invoice_id = ?");
|
|
$stmtLines->execute([$id]);
|
|
$invoice['items'] = $stmtLines->fetchAll();
|
|
|
|
// 3. Decrypt Company Keys for JoFotara
|
|
$clientId = \App\Core\Encryption::decrypt($invoice['jofotara_client_id_encrypted'] ?? '');
|
|
$secretKey = \App\Core\Encryption::decrypt($invoice['jofotara_secret_key_encrypted'] ?? '');
|
|
|
|
$jofotara = new JoFotara();
|
|
$apiResponse = ['success' => false];
|
|
$xmlContent = null;
|
|
|
|
// 4. Try JoFotara Submission if credentials exist
|
|
if ($clientId && $secretKey) {
|
|
$companyData = [
|
|
'name' => $invoice['company_name'],
|
|
'tax_identification_number' => $invoice['company_tin'],
|
|
'address' => $invoice['company_address']
|
|
];
|
|
|
|
// Decrypt Buyer Info for XML
|
|
$invoice['buyer_name'] = \App\Core\Encryption::decrypt($invoice['buyer_name'] ?? '') ?: ($invoice['buyer_name'] ?? '');
|
|
$invoice['buyer_tin'] = \App\Core\Encryption::decrypt($invoice['buyer_tin'] ?? '') ?: ($invoice['buyer_tin'] ?? '');
|
|
|
|
$xmlContent = $jofotara->generateXML($invoice, $companyData);
|
|
$apiResponse = $jofotara->submitInvoice($xmlContent, $clientId, $secretKey);
|
|
}
|
|
|
|
// 5. Fallback: Generate Local QR if API failed or no credentials
|
|
$qrCode = $apiResponse['qrCode'] ?? $jofotara->generateQRCode([
|
|
'supplier_name' => $invoice['company_name'],
|
|
'supplier_tin' => $invoice['company_tin'],
|
|
'invoice_date' => $invoice['invoice_date'],
|
|
'grand_total' => $invoice['grand_total'],
|
|
'tax_amount' => $invoice['tax_amount']
|
|
]);
|
|
|
|
// 6. Record Submission (Audit Log)
|
|
$submissionId = \App\Core\Database::generateUuid();
|
|
$stmtSub = $db->prepare("
|
|
INSERT INTO jofotara_submissions
|
|
(id, invoice_id, company_id, tenant_id, xml_payload, xml_hash,
|
|
jofotara_uuid, qr_code_raw, response_code, response_body, status, submitted_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
|
");
|
|
|
|
$status = $apiResponse['success'] ? 'accepted' : 'error';
|
|
$stmtSub->execute([
|
|
$submissionId,
|
|
$id,
|
|
$invoice['company_id'],
|
|
$invoice['tenant_id'],
|
|
$xmlContent,
|
|
$xmlContent ? hash('sha256', $xmlContent) : null,
|
|
$apiResponse['uuid'] ?? null,
|
|
$qrCode,
|
|
$apiResponse['_http_code'] ?? '0',
|
|
json_encode($apiResponse['raw'] ?? ['info' => 'Local approval / No credentials']),
|
|
$status
|
|
]);
|
|
|
|
// 7. Update Invoice
|
|
$updateStmt = $db->prepare("
|
|
UPDATE invoices SET status = 'approved', jofotara_uuid = ?, qr_code = ?, updated_at = NOW() WHERE id = ?
|
|
");
|
|
$updateStmt->execute([$apiResponse['uuid'] ?? null, $qrCode, $id]);
|
|
|
|
$db->commit();
|
|
|
|
json_success([
|
|
'message' => $apiResponse['success'] ? 'تم الاعتماد والإرسال إلى جوفوترة بنجاح' : 'تم الاعتماد محلياً (نظام جوفوترة غير متصل)',
|
|
'uuid' => $apiResponse['uuid'] ?? null,
|
|
'qr_code' => $qrCode,
|
|
'is_api_success' => $apiResponse['success']
|
|
]);
|
|
|
|
AuditLogger::log('invoice.approved', 'invoice', $id, [
|
|
'old_status' => $invoice['status'],
|
|
], [
|
|
'new_status' => 'approved',
|
|
'jofotara_uuid' => $apiResponse['uuid'] ?? null,
|
|
'api_success' => $apiResponse['success'],
|
|
], $decoded);
|
|
|
|
} catch (\Exception $e) {
|
|
if ($db->inTransaction()) $db->rollBack();
|
|
error_log("JoFotara Approve Error: " . $e->getMessage());
|
|
json_error('خطأ غير متوقع: ' . $e->getMessage(), 500);
|
|
}
|