Hi everyone,
I’m working on a custom function to create a Sales Invoice from a Sales Order.
Here’s the basic flow:
- Fetch the Sales Order
- Create a Sales Invoice document
- Map the items from the Sales Order
- If advance payments exist, map the Payment Entry to the Sales Invoice’s advances table.
However, when I call .insert()
on the Sales Invoice, I get this server error:
TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'
apps/erpnext/erpnext/controllers/accounts_controller.py", line 1272, in set_advance_gain_or_loss
base_allocated_amount_in_ref_rate = advance_exchange_rate * d.allocated_amount
It seems that the advance_exchange_rate
is coming as None
.
I already check that the Payment Entry
’s source_exchange_rate
is not None and not zero before appending it to the advances.
Here’s a simplified version of the code I use for the advances part:
if sales_order_doc.advance_paid and sales_order_doc.advance_paid > 0:
payment_entry = frappe.db.get_value("Payment Entry Reference", {
"reference_doctype": "Sales Order",
"reference_name": sales_order_doc.name,
"docstatus": 1
}, "parent")
if payment_entry:
payment_entry_doc = frappe.get_doc("Payment Entry", payment_entry)
if payment_entry_doc.source_exchange_rate is None or payment_entry_doc.source_exchange_rate == 0:
frappe.throw(f"Payment Entry {payment_entry} has an invalid or missing source_exchange_rate.")
sales_invoice.append("advances", {
"reference_type": "Payment Entry",
"reference_name": payment_entry,
"allocated_amount": sales_order_doc.advance_paid
})
My Questions:
- Is there something else I need to set when adding an advance manually?
- Is there a required field like
exchange_rate
on theSales Invoice Advance
child table that I’m missing? - How should I correctly link an advance payment into a Sales Invoice programmatically?
Thanks in advance for any help!