108 lines
4.2 KiB
PHP
108 lines
4.2 KiB
PHP
<?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));
|