fix: allow local order creation without economic dependency
This commit is contained in:
parent
4b5e154dc1
commit
ebdb13168d
@ -465,18 +465,18 @@ async def send_selected_to_invoices(payload: BulkSendRequest, request: Request):
|
|||||||
if not rows:
|
if not rows:
|
||||||
raise HTTPException(status_code=400, detail="No eligible entries found")
|
raise HTTPException(status_code=400, detail="No eligible entries found")
|
||||||
|
|
||||||
# Ensure selected invoice candidates are approved and invoice-billable.
|
# Local order creation must not depend on e-conomic data/mapping.
|
||||||
selected_invoice_ids = [
|
# We only require billable entries; billing_method can be invoice/prepaid/fixed_price/internal.
|
||||||
|
selected_order_ids = [
|
||||||
int(r["id"])
|
int(r["id"])
|
||||||
for r in rows
|
for r in rows
|
||||||
if bool(r.get("billable", True))
|
if bool(r.get("billable", True))
|
||||||
and (r.get("billing_method") or "invoice") == "invoice"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if not selected_invoice_ids:
|
if not selected_order_ids:
|
||||||
raise HTTPException(status_code=400, detail="No selected entries are invoice-billable")
|
raise HTTPException(status_code=400, detail="No selected entries are billable")
|
||||||
|
|
||||||
placeholders_invoice = ",".join(["%s"] * len(selected_invoice_ids))
|
placeholders_invoice = ",".join(["%s"] * len(selected_order_ids))
|
||||||
execute_update(
|
execute_update(
|
||||||
f"""
|
f"""
|
||||||
UPDATE tmodule_times
|
UPDATE tmodule_times
|
||||||
@ -488,19 +488,35 @@ async def send_selected_to_invoices(payload: BulkSendRequest, request: Request):
|
|||||||
WHERE id IN ({placeholders_invoice})
|
WHERE id IN ({placeholders_invoice})
|
||||||
AND status <> 'billed'
|
AND status <> 'billed'
|
||||||
""",
|
""",
|
||||||
tuple(selected_invoice_ids),
|
tuple(selected_order_ids),
|
||||||
)
|
)
|
||||||
|
|
||||||
rows_by_customer: Dict[int, List[Dict[str, Any]]] = defaultdict(list)
|
rows_by_customer: Dict[int, List[Dict[str, Any]]] = defaultdict(list)
|
||||||
|
skipped_missing_customer: List[int] = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
if int(row["id"]) in selected_invoice_ids:
|
if int(row["id"]) not in selected_order_ids:
|
||||||
rows_by_customer[int(row["customer_id"])].append(row)
|
continue
|
||||||
|
|
||||||
|
cust_id = row.get("customer_id")
|
||||||
|
if cust_id is None:
|
||||||
|
skipped_missing_customer.append(int(row["id"]))
|
||||||
|
continue
|
||||||
|
|
||||||
|
rows_by_customer[int(cust_id)].append(row)
|
||||||
|
|
||||||
created_orders = []
|
created_orders = []
|
||||||
for cust_id, cust_rows in rows_by_customer.items():
|
for cust_id, cust_rows in rows_by_customer.items():
|
||||||
order_id = _create_order_from_selected(cust_id, cust_rows, user_id)
|
order_id = _create_order_from_selected(cust_id, cust_rows, user_id)
|
||||||
created_orders.append({"customer_id": cust_id, "order_id": order_id})
|
created_orders.append({"customer_id": cust_id, "order_id": order_id})
|
||||||
|
|
||||||
|
if not created_orders:
|
||||||
|
if skipped_missing_customer:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=400,
|
||||||
|
detail="No local orders created: selected entries are missing customer linkage",
|
||||||
|
)
|
||||||
|
raise HTTPException(status_code=400, detail="No local orders created")
|
||||||
|
|
||||||
# Time queue must never push directly to e-conomic.
|
# Time queue must never push directly to e-conomic.
|
||||||
# Orders are created locally and can be transferred manually from Orders page.
|
# Orders are created locally and can be transferred manually from Orders page.
|
||||||
order_ids = [o["order_id"] for o in created_orders]
|
order_ids = [o["order_id"] for o in created_orders]
|
||||||
@ -511,8 +527,9 @@ async def send_selected_to_invoices(payload: BulkSendRequest, request: Request):
|
|||||||
return {
|
return {
|
||||||
"success": True,
|
"success": True,
|
||||||
"selected": len(ids),
|
"selected": len(ids),
|
||||||
"invoice_candidates": len(selected_invoice_ids),
|
"billable_candidates": len(selected_order_ids),
|
||||||
"created_orders": created_orders,
|
"created_orders": created_orders,
|
||||||
|
"skipped_missing_customer": skipped_missing_customer,
|
||||||
"orders_url": orders_url,
|
"orders_url": orders_url,
|
||||||
"message": "Lokale ordrer oprettet. Overfoer til e-conomic fra Ordre-siden.",
|
"message": "Lokale ordrer oprettet. Overfoer til e-conomic fra Ordre-siden.",
|
||||||
}
|
}
|
||||||
|
|||||||
@ -458,9 +458,11 @@
|
|||||||
const orders = (result.created_orders || []).map((x) => {
|
const orders = (result.created_orders || []).map((x) => {
|
||||||
return `customer ${x.customer_id}, order ${x.order_id}`;
|
return `customer ${x.customer_id}, order ${x.order_id}`;
|
||||||
}).join('\n');
|
}).join('\n');
|
||||||
|
const skipped = (result.skipped_missing_customer || []);
|
||||||
const orderMessage = orders || 'Ingen ordrer oprettet';
|
const orderMessage = orders || 'Ingen ordrer oprettet';
|
||||||
const nextStep = result.orders_url ? `\n\nAabn ordre: ${result.orders_url}` : '';
|
const nextStep = result.orders_url ? `\n\nAabn ordre: ${result.orders_url}` : '';
|
||||||
alert(`Lokale ordrer oprettet:\n${orderMessage}${nextStep}`);
|
const skippedMsg = skipped.length ? `\n\nSprunget over (mangler kunde-link): ${skipped.join(', ')}` : '';
|
||||||
|
alert(`Lokale ordrer oprettet:\n${orderMessage}${skippedMsg}${nextStep}`);
|
||||||
await loadCustomers();
|
await loadCustomers();
|
||||||
await loadEntries();
|
await loadEntries();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user