diff --git a/erpnext/accounts/doctype/subscription/subscription.js b/erpnext/accounts/doctype/subscription/subscription.js index 60981f4b1d1..caaa60b5757 100644 --- a/erpnext/accounts/doctype/subscription/subscription.js +++ b/erpnext/accounts/doctype/subscription/subscription.js @@ -37,6 +37,12 @@ frappe.ui.form.on("Subscription", { frm.add_custom_button(__("Fetch Subscription Updates"), () => frm.events.get_subscription_updates(frm) ); + + frm.add_custom_button( + __("Force-Fetch Subscription Updates"), + () => frm.trigger("force_fetch_subscription_updates"), + __("Actions") + ); } else if (frm.doc.status === "Cancelled") { frm.add_custom_button(__("Restart Subscription"), () => frm.events.renew_this_subscription(frm) @@ -96,4 +102,11 @@ frappe.ui.form.on("Subscription", { }, }); }, + force_fetch_subscription_updates: function (frm) { + frm.call("force_fetch_subscription_updates").then((r) => { + if (!r.exec) { + frm.reload_doc(); + } + }); + }, }); diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index fea2ae9bf8e..96c97659ad8 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -674,6 +674,31 @@ class Subscription(Document): if invoice: return invoice.precision("grand_total") + @frappe.whitelist() + def force_fetch_subscription_updates(self): + """ + Process Subscription and create Invoices even if current date doesn't lie between current_invoice_start and currenct_invoice_end + It makes use of 'Proces Subscription' to force processing in a specific 'posting_date' + """ + + # Don't process future subscriptions + if nowdate() < self.current_invoice_start: + frappe.msgprint(_("Subscription for Future dates cannot be processed.")) + return + + processing_date = None + if self.generate_invoice_at == "Beginning of the current subscription period": + processing_date = self.current_invoice_start + elif self.generate_invoice_at == "End of the current subscription period": + processing_date = self.current_invoice_end + elif self.generate_invoice_at == "Days before the current subscription period": + processing_date = add_days(self.current_invoice_start, -self.number_of_days) + + process_subscription = frappe.new_doc("Process Subscription") + process_subscription.posting_date = processing_date + process_subscription.subscription = self.name + process_subscription.save().submit() + def get_calendar_months(billing_interval): calendar_months = [] diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py index 2f0b87e9ea2..26dcb2413f4 100644 --- a/erpnext/accounts/doctype/subscription/test_subscription.py +++ b/erpnext/accounts/doctype/subscription/test_subscription.py @@ -712,3 +712,18 @@ class TestSubscription(FrappeTestCase): self.assertEqual(pi.total, 55333.33) subscription.delete() + + def test_future_subscription(self): + """Force-Fetch should not process future subscriptions""" + subscription = frappe.new_doc("Subscription") + subscription.party_type = "Customer" + subscription.party = "_Test Customer" + subscription.generate_invoice_at_period_start = 1 + subscription.generate_new_invoices_past_due_date = 1 + subscription.start_date = add_months(nowdate(), 1) + subscription.append("plans", {"plan": "_Test Plan Name", "qty": 1}) + subscription.save() + + subscription.force_fetch_subscription_updates() + subscription.reload() + self.assertEqual(len(subscription.invoices), 0)