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));