I have a custom subscription implementation with the following structure:
-
1 Sales Order per subscription
-
1 Payment Entry (full advance paid upfront)
-
Multiple Sales Invoices created programmatically — one per delivery
-
Multiple Delivery Notes — one per delivery
Each SI is created via a whitelisted API method and allocates a portion of the PE’s unallocated_amount as an advance.
The Error:
When submitting the SI, ERPNext throws:
Payment Entry has been modified after you pulled it. Please pull it again.
Below Is My actual Code and the ERROR:
def create_sales_invoice_subscription(soname, subscription_delivery):
try:
sd = subscription_delivery
"""
{
"subscription_id":"SUB100",
"delivery_id": "1234",
"delivery_date":"19-02-2026",
"delivery_slot":"10:00AM - 11:00AM",
"item_code":"ITEM100",
"warehouse_id":"WH100",
"rate:"12",
"quantity":"10"
}
"""
print(subscription_delivery)
if isinstance(subscription_delivery, str):
subscription_delivery = json.loads(subscription_delivery)
so = frappe.get_doc("Sales Order", soname)
sm = frappe.get_doc("Subscription Master", sd.get("subscription_id"))
pe = frappe.get_doc("Payment Entry", sm.payment_entry)
pe.reload()
si = frappe.new_doc("Sales Invoice")
# si.series = "SUB"
si.customer = so.customer
si.company = so.company
si.currency = "INR"
si.posting_date = getdate(sd.get("delivery_date")) or nowdate()
si.set_posting_time = 1
si.append("items", {
"item_code": sd.get("item_code"),
"qty": float(sd.get("quantity")),
"rate": float(sd.get("rate")),
"warehouse": sd.get("warehouse_id"),
"income_account": "41100004 - Sales of Finished Goods - Subscription - DV"
})
#"Get advance Payments"
si.insert(ignore_permissions=True)
print("PE UNALLOCATED AMOUNT", pe.unallocated_amount)
if pe.unallocated_amount <= 0:
frappe.log_error("No advance balance available in linked Payment Entry")
return
allocate_amount = min(pe.unallocated_amount, si.grand_total)
si.append("advances", {
"reference_type": "Payment Entry",
"reference_name": pe.name,
"advance_amount": pe.paid_amount,
"allocated_amount": allocate_amount,
"difference_posting_date": getdate(sd.get("delivery_date")) or nowdate()
})
si.save(ignore_permissions=True)
si.submit()
return si
except Exception as e:
frappe.throw(f"Error creating sales invoice: {str(e)}", "Order Sync")
return None
{
"exception": "frappe.exceptions.ValidationError: Error creating sales invoice: Payment Entry has been modified after you pulled it. Please pull it again.",
"exc_type": "ValidationError",
"_exc_source": "delish_vault (app)",
"exc": "[\"Traceback (most recent call last):\\n File \\\"apps/delish_vault/delish_vault/order_sync/order_documents.py\\\", line 333, in create_sales_invoice_subscription\\n si.submit()\\n File \\\"apps/frappe/frappe/utils/typing_validations.py\\\", line 32, in wrapper\\n return func(*args, **kwargs)\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 1097, in submit\\n return self._submit()\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 1080, in _submit\\n return self.save()\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 378, in save\\n return self._save(*args, **kwargs)\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 431, in _save\\n self.run_post_save_methods()\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 1180, in run_post_save_methods\\n self.run_method(\\\"on_submit\\\")\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 1011, in run_method\\n out = Document.hook(fn)(self, *args, **kwargs)\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 1371, in composer\\n return composed(self, method, *args, **kwargs)\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 1353, in runner\\n add_to_return_value(self, fn(self, *args, **kwargs))\\n File \\\"apps/frappe/frappe/model/document.py\\\", line 1008, in fn\\n return method_object(*args, **kwargs)\\n File \\\"apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py\\\", line 480, in on_submit\\n self.update_against_document_in_jv()\\n File \\\"apps/erpnext/erpnext/controllers/accounts_controller.py\\\", line 1899, in update_against_document_in_jv\\n reconcile_against_document(lst, active_dimensions=active_dimensions)\\n File \\\"apps/erpnext/erpnext/accounts/utils.py\\\", line 482, in reconcile_against_document\\n check_if_advance_entry_modified(entry)\\n File \\\"apps/erpnext/erpnext/accounts/utils.py\\\", line 593, in check_if_advance_entry_modified\\n throw(_(\\\"\\\"\\\"Payment Entry has been modified after you pulled it. Please pull it again.\\\"\\\"\\\"))\\n File \\\"apps/frappe/frappe/__init__.py\\\", line 609, in throw\\n msgprint(\\n File \\\"apps/frappe/frappe/__init__.py\\\", line 574, in msgprint\\n _raise_exception()\\n File \\\"apps/frappe/frappe/__init__.py\\\", line 525, in _raise_exception\\n raise exc\\nfrappe.exceptions.ValidationError: Payment Entry has been modified after you pulled it. Please pull it again.\\n\\nDuring handling of the above exception, another exception occurred:\\n\\nTraceback (most recent call last):\\n File \\\"apps/frappe/frappe/app.py\\\", line 120, in application\\n response = frappe.api.handle(request)\\n File \\\"apps/frappe/frappe/api/__init__.py\\\", line 52, in handle\\n data = endpoint(**arguments)\\n File \\\"apps/frappe/frappe/api/v1.py\\\", line 40, in handle_rpc_call\\n return frappe.handler.handle()\\n File \\\"apps/frappe/frappe/handler.py\\\", line 52, in handle\\n data = execute_cmd(cmd)\\n File \\\"apps/frappe/frappe/handler.py\\\", line 85, in execute_cmd\\n return frappe.call(method, **frappe.form_dict)\\n File \\\"apps/frappe/frappe/__init__.py\\\", line 1754, in call\\n return fn(*args, **newargs)\\n File \\\"apps/frappe/frappe/utils/typing_validations.py\\\", line 32, in wrapper\\n return func(*args, **kwargs)\\n File \\\"apps/delish_vault/delish_vault/order_sync/order_documents.py\\\", line 337, in create_sales_invoice_subscription\\n frappe.throw(f\\\"Error creating sales invoice: {str(e)}\\\", \\\"Order Sync\\\")\\n File \\\"apps/frappe/frappe/__init__.py\\\", line 609, in throw\\n msgprint(\\n File \\\"apps/frappe/frappe/__init__.py\\\", line 574, in msgprint\\n _raise_exception()\\n File \\\"apps/frappe/frappe/__init__.py\\\", line 525, in _raise_exception\\n raise exc\\nfrappe.exceptions.ValidationError: Error creating sales invoice: Payment Entry has been modified after you pulled it. Please pull it again.\\n\"]",
"_server_messages": "[\"{\\\"message\\\": \\\"Payment Entry has been modified after you pulled it. Please pull it again.\\\", \\\"title\\\": \\\"Message\\\", \\\"indicator\\\": \\\"red\\\", \\\"raise_exception\\\": 1, \\\"__frappe_exc_id\\\": \\\"1a7b8fec4c235a1bf53bd4748d0534b86eade2bd98be1fed53c9251e\\\"}\", \"{\\\"message\\\": \\\"Error creating sales invoice: Payment Entry has been modified after you pulled it. Please pull it again.\\\", \\\"title\\\": \\\"Message\\\", \\\"indicator\\\": \\\"red\\\", \\\"raise_exception\\\": 1, \\\"__frappe_exc_id\\\": \\\"57aa60b7c4c3f1e13be015d65cb19ce373d98e6ca7b7e5a113713580\\\"}\"]"
}