accounting modules

This commit is contained in:
Thanakorn S
2026-05-13 15:11:24 +07:00
parent 511360faa2
commit 04a683bd02
70 changed files with 4451 additions and 42 deletions
+107
View File
@@ -0,0 +1,107 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
$action = $data['action'] ?? '';
$id = (int)($data['id'] ?? 0);
// ── Generate quotation number ─────────────────────────────────────────────────
function generate_quotation_number(PDO $pdo, int $cid): string {
$prefix = 'QT-' . date('Ym') . '-';
$sql = "SELECT quotation_number FROM ac_quotation
WHERE company_id = :cid AND quotation_number LIKE :prefix
ORDER BY id DESC LIMIT 1";
$sth = $pdo->prepare($sql);
$sth->execute([':cid' => $cid, ':prefix' => $prefix . '%']);
$last = $sth->fetchColumn();
$seq = $last ? ((int)substr($last, -4) + 1) : 1;
return $prefix . str_pad($seq, 4, '0', STR_PAD_LEFT);
}
// ── Compute totals from items ─────────────────────────────────────────────────
function compute_totals(array $items, float $discount, float $tax): array {
$subtotal = array_sum(array_map(fn($i) => (float)($i['total_price'] ?? 0), $items));
$grand = $subtotal - $discount + $tax;
return [round($subtotal, 4), round(max(0, $grand), 4)];
}
if ($action === 'create') {
$items = json_decode($data['items'] ?? '[]', true) ?: [];
$discount = (float)($data['discount'] ?? 0);
$tax = (float)($data['tax'] ?? 0);
[$subtotal, $grand] = compute_totals($items, $discount, $tax);
$qnum = generate_quotation_number($pdo2, $company_id);
$sql = "INSERT INTO ac_quotation
(company_id, uuid, quotation_number, contact_id, quotation_date, valid_until,
status, subtotal, discount, tax, grand_total, items, notes, log, created_at)
VALUES
(:cid, :uuid, :qnum, :contact_id, :qdate, :valid_until,
0, :sub, :disc, :tax, :grand, :items, :notes, :log, NOW())";
$sth = $pdo2->prepare($sql);
$sth->execute([
':cid' => $company_id,
':uuid' => $uuid,
':qnum' => $qnum,
':contact_id' => (int)($data['contact_id'] ?? 0),
':qdate' => $data['quotation_date'] ?: null,
':valid_until'=> $data['valid_until'] ?: null,
':sub' => $subtotal,
':disc' => $discount,
':tax' => $tax,
':grand' => $grand,
':items' => json_encode($items),
':notes' => $data['notes'] ?? '',
':log' => json_encode($logging),
]);
$answer['success'] = 1;
$answer['message'] = 'Quotation created';
$answer['new_id'] = (int)$pdo2->lastInsertId();
$answer['quotation_number'] = $qnum;
} elseif ($action === 'update') {
if (!$id) { exit(json_encode(['success' => 0, 'message' => 'ID required'])); }
$items = json_decode($data['items'] ?? '[]', true) ?: [];
$discount = (float)($data['discount'] ?? 0);
$tax = (float)($data['tax'] ?? 0);
[$subtotal, $grand] = compute_totals($items, $discount, $tax);
$sql = "UPDATE ac_quotation SET
contact_id = :contact_id,
quotation_date = :qdate,
valid_until = :valid_until,
subtotal = :sub,
discount = :disc,
tax = :tax,
grand_total = :grand,
items = :items,
notes = :notes
WHERE id = :id AND company_id = :cid AND status = 0";
$sth = $pdo2->prepare($sql);
$sth->execute([
':contact_id' => (int)($data['contact_id'] ?? 0),
':qdate' => $data['quotation_date'] ?: null,
':valid_until' => $data['valid_until'] ?: null,
':sub' => $subtotal,
':disc' => $discount,
':tax' => $tax,
':grand' => $grand,
':items' => json_encode($items),
':notes' => $data['notes'] ?? '',
':id' => $id,
':cid' => $company_id,
]);
$answer['success'] = 1;
$answer['message'] = 'Quotation updated';
} else {
$answer['message'] = 'Unknown action';
}
exit(json_encode($answer));