'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()]); }