fix(checkout): create ERPNext Sales Order for compliance_batch orders
Batch orders (CB-XXXX, used by the trucking new-carrier flow and any multi- service cart) never created an ERPNext Sales Order -- the SO-creation branch was gated to order_type 'compliance' only. So those paid orders never reached ERPNext for fulfillment/accounting (0 of all paid batch orders had an erpnext_sales_order). Added a compliance_batch branch that creates ONE Sales Order with a line item per service in the batch (+ government-fee + processing- fee lines), then stamps the SO name on every batch row. Non-blocking like the others. Also created the missing ERPNext Items the new slugs reference (DOT-NEW-CARRIER-BUNDLE, LLC-FORMATION, CORP-FORMATION, NEW-CARRIER-BUNDLE which was missing too, GOVERNMENT-FILING-FEE).
This commit is contained in:
parent
90bccfda32
commit
baa40443de
1 changed files with 69 additions and 0 deletions
|
|
@ -966,6 +966,75 @@ router.post("/api/v1/checkout/create-session", async (req, res) => {
|
|||
}
|
||||
}
|
||||
|
||||
// ── Create ERPNext Sales Order (compliance BATCH) ───────────────────────
|
||||
// A batch (CB-XXXX) is one customer paying for several services at once, so
|
||||
// it becomes ONE Sales Order with a line item per service (plus the
|
||||
// processing-fee line). Previously batches created no SO at all, so trucking
|
||||
// new-carrier orders (which always use the batch path) never reached ERPNext.
|
||||
if (order_type === "compliance_batch" && erpnextCustomer) {
|
||||
try {
|
||||
const { COMPLIANCE_SERVICES } = await import("./compliance-orders.js");
|
||||
const { rows: batchRows } = await pool.query(
|
||||
`SELECT * FROM compliance_orders WHERE batch_id = $1 ORDER BY created_at`,
|
||||
[order_id],
|
||||
);
|
||||
|
||||
const lineItems = batchRows.map((o: Record<string, any>) => {
|
||||
const info = COMPLIANCE_SERVICES[(o.service_slug as string) || ""];
|
||||
const svcCents = (o.service_fee_cents as number) || 0;
|
||||
const govCents = (o.gov_fee_cents as number) || 0;
|
||||
const items: Array<{ item_code: string; description: string; qty: number; rate: number }> = [{
|
||||
item_code: info?.erpnext_item || "COMPLIANCE-SERVICE",
|
||||
description: (o.service_name as string) || info?.name || "Compliance Service",
|
||||
qty: 1,
|
||||
rate: toDollars(svcCents),
|
||||
}];
|
||||
if (govCents > 0) {
|
||||
items.push({
|
||||
item_code: "GOVERNMENT-FILING-FEE",
|
||||
description: (o.gov_fee_label as string) || "Government filing fee",
|
||||
qty: 1,
|
||||
rate: toDollars(govCents),
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}).flat();
|
||||
|
||||
if (surcharge_cents > 0) {
|
||||
lineItems.push({
|
||||
item_code: "PAYMENT-PROCESSING-FEE",
|
||||
description: `${GATEWAY_LABELS[payment_method] || payment_method} ${surcharge_pct}%`,
|
||||
qty: 1,
|
||||
rate: toDollars(surcharge_cents),
|
||||
});
|
||||
}
|
||||
|
||||
const so = (await createResource("Sales Order", {
|
||||
customer: erpnextCustomer,
|
||||
delivery_date: new Date(Date.now() + 30 * 86400000).toISOString().split("T")[0],
|
||||
custom_external_order_id: order_id,
|
||||
custom_order_type: "compliance_batch",
|
||||
custom_payment_gateway: GATEWAY_LABELS[payment_method] || payment_method,
|
||||
custom_surcharge_pct: surcharge_pct,
|
||||
workflow_state: "Received",
|
||||
items: lineItems,
|
||||
})) as { name: string };
|
||||
|
||||
try {
|
||||
await callMethod("frappe.client.submit", { doc: { doctype: "Sales Order", name: so.name } });
|
||||
} catch { /* submit may fail if workflow doesn't require it */ }
|
||||
|
||||
await pool.query(
|
||||
`UPDATE compliance_orders SET erpnext_sales_order = $1 WHERE batch_id = $2`,
|
||||
[so.name, order_id],
|
||||
);
|
||||
|
||||
console.log(`[checkout] Created ERPNext Sales Order ${so.name} for batch ${order_id} (${lineItems.length} line items)`);
|
||||
} catch (soErr) {
|
||||
console.warn("[checkout] Batch Sales Order creation failed (non-blocking):", soErr);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Create ERPNext Sales Order (US business formation) ──────────────────
|
||||
if (order_type === "formation" && erpnextCustomer) {
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue