103 lines
3.6 KiB
PHP
103 lines
3.6 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../includes/uuid.php';
|
|
require_once __DIR__ . '/../db/config.php';
|
|
require_once __DIR__ . '/../includes/journal_helpers.php';
|
|
require_once __DIR__ . '/../includes/audit_helpers.php';
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
http_response_code(405);
|
|
echo json_encode(['error' => 'Method not allowed']);
|
|
exit();
|
|
}
|
|
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
|
|
// Basic validation
|
|
if (empty($data['vendor_id']) || empty($data['bill_date']) || empty($data['due_date']) || empty($data['lines']) || !is_array($data['lines'])) {
|
|
http_response_code(400);
|
|
echo json_encode(['error' => 'Missing required fields: vendor_id, bill_date, due_date, and lines array.']);
|
|
exit();
|
|
}
|
|
|
|
$pdo = db();
|
|
|
|
try {
|
|
$pdo->beginTransaction();
|
|
|
|
// 1. Calculate total amount and prepare journal entry lines
|
|
$total_amount = 0;
|
|
$journal_lines = [];
|
|
$ap_account_code = '2100-AP'; // Accounts Payable
|
|
|
|
foreach ($data['lines'] as $line) {
|
|
if (empty($line['expense_account_code']) || empty($line['amount'])) {
|
|
throw new Exception('Each bill line must have expense_account_code and amount.');
|
|
}
|
|
$amount = (float)$line['amount'];
|
|
$total_amount += $amount;
|
|
|
|
// Debit the expense account for this line
|
|
$journal_lines[] = [
|
|
'account_code' => $line['expense_account_code'],
|
|
'type' => 'DEBIT',
|
|
'amount' => $amount
|
|
];
|
|
}
|
|
|
|
// Credit Accounts Payable for the total amount
|
|
$journal_lines[] = [
|
|
'account_code' => $ap_account_code,
|
|
'type' => 'CREDIT',
|
|
'amount' => $total_amount
|
|
];
|
|
|
|
// 2. Create the Journal Entry
|
|
$journal_entry_payload = [
|
|
'entry_date' => $data['bill_date'],
|
|
'description' => 'Vendor bill from ' . ($data['vendor_name'] ?? $data['vendor_id']),
|
|
'lines' => $journal_lines
|
|
];
|
|
|
|
// Use a function to post the journal entry
|
|
$journal_entry_result = post_journal_entry($pdo, $journal_entry_payload);
|
|
if (empty($journal_entry_result['journal_entry_id'])) {
|
|
throw new Exception("Failed to post journal entry: " . ($journal_entry_result['error'] ?? 'Unknown error'));
|
|
}
|
|
$journal_entry_id = $journal_entry_result['journal_entry_id'];
|
|
|
|
// 3. Create the Bill
|
|
$bill_id = uuid_v4();
|
|
$stmt = $pdo->prepare(
|
|
"INSERT INTO bills (bill_id, vendor_id, journal_entry_id, bill_date, due_date, total_amount, status) VALUES (?, ?, ?, ?, ?, ?, 'SUBMITTED')"
|
|
);
|
|
$stmt->execute([$bill_id, $data['vendor_id'], $journal_entry_id, $data['bill_date'], $data['due_date'], $total_amount]);
|
|
|
|
// 4. Create Bill Lines
|
|
$stmt_lines = $pdo->prepare(
|
|
"INSERT INTO bill_lines (bill_line_id, bill_id, expense_account_code, description, amount) VALUES (?, ?, ?, ?, ?)"
|
|
);
|
|
foreach ($data['lines'] as $line) {
|
|
$stmt_lines->execute([uuid_v4(), $bill_id, $line['expense_account_code'], $line['description'] ?? null, $line['amount']]);
|
|
}
|
|
|
|
// Log audit trail
|
|
log_audit_trail($pdo, 'create_bill', ['bill_id' => $bill_id, 'vendor_id' => $data['vendor_id'], 'total_amount' => $total_amount]);
|
|
|
|
$pdo->commit();
|
|
|
|
// 5. Fetch and return the created bill
|
|
$stmt = $pdo->prepare("SELECT * FROM bills WHERE bill_id = ?");
|
|
$stmt->execute([$bill_id]);
|
|
$new_bill = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
http_response_code(201);
|
|
echo json_encode($new_bill);
|
|
|
|
} catch (Exception $e) {
|
|
$pdo->rollBack();
|
|
http_response_code(500);
|
|
echo json_encode(['error' => 'Operation failed: ' . $e->getMessage()]);
|
|
}
|