fix: submit customer credit redemption payload from POS#218
Conversation
engahmed1190
left a comment
There was a problem hiding this comment.
Code Review — APPROVE (with suggestions) ✅
Summary
Enables pure customer-credit POS sales by preserving credit metadata through the submit flow and adding a scoped validate_pos_paid_amount override.
Test Results
No test file included. Validated on staging per PR description.
Correctness
Frontend (buildCustomerCreditPayload):
- Well-structured: separates credit payments from regular payments, deduplicates credit sources via Map, allocates FIFO with tolerance check (0.01)
- Edge case handled: if
credit_detailsis missing on anis_customer_creditpayment, the allocation throws — correct, better to fail than silently lose credit serializeInvoicePaymentscorrectly filters outis_customer_creditpayments from the normal payment array
Backend (validate_pos_paid_amount):
- Correctly scoped: only activates when
pos_next_redeemed_customer_creditflag is set AND zero payments AND POS invoice with positive grand total - Falls through to
super().validate_pos_paid_amount()for all other cases - The flag is on
invoice_doc.flags(transient Python attribute, not a DocField) — cannot be injected via Frappe's API or JSON payload
POSSale.vue (...p spread):
- Correctly preserves
is_customer_creditandcredit_detailsmetadata that was previously stripped
Security
The flags pattern is idiomatic Frappe and safe. The only code path that sets pos_next_redeemed_customer_credit is through submit_invoice() which is behind @frappe.whitelist().
Suggestions (non-blocking)
- Add a backend guard: if
redeemed_customer_credit > 0butcustomer_credit_dictis empty/falsy, don't set the flag. Currently, a crafted API call withredeemed_customer_credit=100and nocustomer_credit_dictwould submit a zero-payment invoice that stays fully outstanding - Add tests for the
validate_pos_paid_amountoverride — verify it bypasses with the flag and does NOT bypass without it - Consider filtering the
...pspread in POSSale.vue to only known properties, to prevent unexpected properties leaking into the cart store
Conflict Note
This PR modifies submit_invoice in invoices.py and adds validate_pos_paid_amount to sales_invoice.py. No conflict with the current fix/payment-amount-wiped-by-erpnext branch (which modifies update_invoice).
Verdict
Well-scoped fix. The flags pattern is the right approach for a temporary validation bypass. Good to merge.
engahmed1190
left a comment
There was a problem hiding this comment.
Confirming approval — customer credit payload fix is correct, validate_pos_paid_amount override is properly scoped via flags pattern. Safe to merge.
Summary
Fix customer-credit POS sales so the frontend submits the redemption payload the backend already expects.
Before this change:
Customer Creditentries withis_customer_creditandcredit_detailsPOSSale.vuestripped that metadata before submitsubmit_invoice()never receivedcustomer_credit_dict/redeemed_customer_creditThis patch:
customer_credit_dictandredeemed_customer_creditinuseInvoice.jsCustomer Creditrows from normal invoicepaymentsValidation
frappe 16.12.0,erpnext 16.11.0,pos_next 1.15.0)outstanding_amount = 0Issue
Closes #210