Update: 2026-05-04 02:18:52
This commit is contained in:
33
app/modules_app/invoices/file.php
Normal file
33
app/modules_app/invoices/file.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Secure File Proxy for Invoices
|
||||
*/
|
||||
|
||||
use App\Core\Database;
|
||||
use App\Middleware\AuthMiddleware;
|
||||
|
||||
$decoded = AuthMiddleware::check();
|
||||
$db = Database::getInstance();
|
||||
|
||||
$id = input('id');
|
||||
if (!$id) die('Forbidden');
|
||||
|
||||
$stmt = $db->prepare("SELECT tenant_id, original_file_path FROM invoices WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$invoice = $stmt->fetch();
|
||||
|
||||
if (!$invoice) die('Not found');
|
||||
|
||||
// Authorization
|
||||
if ($decoded['role'] !== 'super_admin' && $invoice['tenant_id'] !== $decoded['tenant_id']) {
|
||||
die('Unauthorized');
|
||||
}
|
||||
|
||||
$filePath = $invoice['original_file_path'];
|
||||
if (!file_exists($filePath)) die('File missing');
|
||||
|
||||
$mime = mime_content_type($filePath);
|
||||
header("Content-Type: $mime");
|
||||
header("Content-Length: " . filesize($filePath));
|
||||
readfile($filePath);
|
||||
exit;
|
||||
67
app/modules_app/invoices/view.php
Normal file
67
app/modules_app/invoices/view.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* View Invoice Details Endpoint (with Line Items)
|
||||
*/
|
||||
|
||||
use App\Core\Database;
|
||||
use App\Core\Encryption;
|
||||
use App\Middleware\AuthMiddleware;
|
||||
|
||||
// 1. Auth Check
|
||||
$decoded = AuthMiddleware::check();
|
||||
$db = Database::getInstance();
|
||||
|
||||
$id = input('id');
|
||||
if (!$id) {
|
||||
json_error('Invoice ID is required', 422);
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. Fetch Invoice
|
||||
$stmt = $db->prepare("
|
||||
SELECT i.*, c.name as company_name
|
||||
FROM invoices i
|
||||
LEFT JOIN companies c ON i.company_id = c.id
|
||||
WHERE i.id = ?
|
||||
");
|
||||
$stmt->execute([$id]);
|
||||
$invoice = $stmt->fetch();
|
||||
|
||||
if (!$invoice) {
|
||||
json_error('Invoice not found', 404);
|
||||
}
|
||||
|
||||
// 3. Authorization Check
|
||||
if ($decoded['role'] !== 'super_admin') {
|
||||
if ($invoice['tenant_id'] !== $decoded['tenant_id']) {
|
||||
json_error('Unauthorized access to this invoice', 403);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Fetch Line Items
|
||||
$stmtLines = $db->prepare("SELECT * FROM invoice_lines WHERE invoice_id = ? ORDER BY line_number ASC");
|
||||
$stmtLines->execute([$id]);
|
||||
$invoice['items'] = $stmtLines->fetchAll();
|
||||
|
||||
// 5. Decrypt Fields
|
||||
$invoice['supplier_tin'] = Encryption::decrypt($invoice['supplier_tin'] ?? '') ?: $invoice['supplier_tin'];
|
||||
$invoice['supplier_name'] = Encryption::decrypt($invoice['supplier_name'] ?? '') ?: $invoice['supplier_name'];
|
||||
$invoice['supplier_address'] = Encryption::decrypt($invoice['supplier_address'] ?? '') ?: $invoice['supplier_address'];
|
||||
$invoice['buyer_tin'] = Encryption::decrypt($invoice['buyer_tin'] ?? '') ?: $invoice['buyer_tin'];
|
||||
$invoice['buyer_name'] = Encryption::decrypt($invoice['buyer_name'] ?? '') ?: $invoice['buyer_name'];
|
||||
$invoice['buyer_national_id'] = Encryption::decrypt($invoice['buyer_national_id'] ?? '') ?: $invoice['buyer_national_id'];
|
||||
|
||||
if (!empty($invoice['company_name'])) {
|
||||
$invoice['company_name'] = Encryption::decrypt($invoice['company_name']) ?: $invoice['company_name'];
|
||||
}
|
||||
|
||||
// 6. Generate Public URL for File (Assuming storage is symlinked or served)
|
||||
// For now, let's just return the relative path or a proxy route
|
||||
// We'll add a proxy route later if needed.
|
||||
$invoice['file_url'] = '/index.php?route=v1/invoices/file&id=' . $invoice['id'];
|
||||
|
||||
json_success($invoice);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
json_error('Error fetching invoice: ' . $e->getMessage(), 500);
|
||||
}
|
||||
Reference in New Issue
Block a user