From f35bc432423c80a057638b8d965d142acadc1a61 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 12 Aug 2024 17:37:48 +0530 Subject: [PATCH 1/6] fix: force fetch updates for subcription (cherry picked from commit 1ef890db732caff9fc77716fd3932ae9c4055b4f) # Conflicts: # erpnext/accounts/doctype/subscription/subscription.js --- .../doctype/subscription/subscription.js | 36 +++++++++++++++++++ .../doctype/subscription/subscription.py | 19 ++++++++++ 2 files changed, 55 insertions(+) diff --git a/erpnext/accounts/doctype/subscription/subscription.js b/erpnext/accounts/doctype/subscription/subscription.js index 60981f4b1d1..6d11044f614 100644 --- a/erpnext/accounts/doctype/subscription/subscription.js +++ b/erpnext/accounts/doctype/subscription/subscription.js @@ -29,6 +29,7 @@ frappe.ui.form.on("Subscription", { }, refresh: function (frm) { +<<<<<<< HEAD if (!frm.is_new()) { if (frm.doc.status !== "Cancelled") { frm.add_custom_button(__("Cancel Subscription"), () => @@ -42,6 +43,34 @@ frappe.ui.form.on("Subscription", { frm.events.renew_this_subscription(frm) ); } +======= + if (frm.is_new()) return; + + if (frm.doc.status !== "Cancelled") { + frm.add_custom_button( + __("Fetch Subscription Updates"), + () => frm.trigger("get_subscription_updates"), + __("Actions") + ); + + frm.add_custom_button( + __("Force Fetch Subscription Updates"), + () => frm.trigger("force_fetch_subscription_updates"), + __("Actions") + ); + + frm.add_custom_button( + __("Cancel Subscription"), + () => frm.trigger("cancel_this_subscription"), + __("Actions") + ); + } else if (frm.doc.status === "Cancelled") { + frm.add_custom_button( + __("Restart Subscription"), + () => frm.trigger("renew_this_subscription"), + __("Actions") + ); +>>>>>>> 1ef890db73 (fix: force fetch updates for subcription) } }, @@ -96,4 +125,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..c4e4114857b 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -674,6 +674,25 @@ 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' + """ + 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 = [] From f0f663e55218cc4c6b0104ad5f1dd242a4c5f276 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 13 Aug 2024 12:34:10 +0530 Subject: [PATCH 2/6] refactor: don't process future subscriptions (cherry picked from commit 3a115774114a1986435739936c195a17a0b65af3) --- erpnext/accounts/doctype/subscription/subscription.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index c4e4114857b..96c97659ad8 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -680,6 +680,12 @@ class Subscription(Document): 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 From 7752de3a1cc2f7f6f735a6d5b89b8bebf20bef70 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 13 Aug 2024 12:35:16 +0530 Subject: [PATCH 3/6] chore: minor naming change (cherry picked from commit d8b6767697afe6e59b33e62466ffcb8653b23b96) --- erpnext/accounts/doctype/subscription/subscription.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/subscription/subscription.js b/erpnext/accounts/doctype/subscription/subscription.js index 6d11044f614..48bbc733fe4 100644 --- a/erpnext/accounts/doctype/subscription/subscription.js +++ b/erpnext/accounts/doctype/subscription/subscription.js @@ -54,7 +54,7 @@ frappe.ui.form.on("Subscription", { ); frm.add_custom_button( - __("Force Fetch Subscription Updates"), + __("Force-Fetch Subscription Updates"), () => frm.trigger("force_fetch_subscription_updates"), __("Actions") ); From 366f383d1f8e0678f1c33f1814605b941e56d70d Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 13 Aug 2024 16:05:06 +0530 Subject: [PATCH 4/6] refactor: test for force-fetch on future subscription (cherry picked from commit fd680380bbb93313a0d0853eaf9144726c44551c) # Conflicts: # erpnext/accounts/doctype/subscription/test_subscription.py --- .../doctype/subscription/test_subscription.py | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py index 2f0b87e9ea2..3b32c727731 100644 --- a/erpnext/accounts/doctype/subscription/test_subscription.py +++ b/erpnext/accounts/doctype/subscription/test_subscription.py @@ -711,4 +711,113 @@ class TestSubscription(FrappeTestCase): pi = frappe.get_doc("Purchase Invoice", subscription.invoices[0].invoice) self.assertEqual(pi.total, 55333.33) +<<<<<<< HEAD subscription.delete() +======= + subscription.process(posting_date="2023-01-22") + self.assertEqual(len(subscription.invoices), 2) + + def test_future_subscription(self): + """Force-Fetch should not process future subscriptions""" + subscription = create_subscription( + start_date=add_months(nowdate(), 1), + submit_invoice=0, + generate_new_invoices_past_due_date=1, + party="_Test Subscription Customer John Doe", + ) + subscription.force_fetch_subscription_updates() + subscription.reload() + self.assertEqual(len(subscription.invoices), 0) + + +def make_plans(): + create_plan(plan_name="_Test Plan Name", cost=900, currency="INR") + create_plan(plan_name="_Test Plan Name 2", cost=1999, currency="INR") + create_plan( + plan_name="_Test Plan Name 3", + cost=1999, + billing_interval="Day", + billing_interval_count=14, + currency="INR", + ) + create_plan( + plan_name="_Test Plan Name 4", + cost=20000, + billing_interval="Month", + billing_interval_count=3, + currency="INR", + ) + create_plan(plan_name="_Test Plan Multicurrency", cost=50, billing_interval="Month", currency="USD") + + +def create_plan(**kwargs): + if not frappe.db.exists("Subscription Plan", kwargs.get("plan_name")): + plan = frappe.new_doc("Subscription Plan") + plan.plan_name = kwargs.get("plan_name") or "_Test Plan Name" + plan.item = kwargs.get("item") or "_Test Non Stock Item" + plan.price_determination = kwargs.get("price_determination") or "Fixed Rate" + plan.cost = kwargs.get("cost") or 1000 + plan.billing_interval = kwargs.get("billing_interval") or "Month" + plan.billing_interval_count = kwargs.get("billing_interval_count") or 1 + plan.currency = kwargs.get("currency") + plan.insert() + + +def create_parties(): + if not frappe.db.exists("Supplier", "_Test Supplier"): + supplier = frappe.new_doc("Supplier") + supplier.supplier_name = "_Test Supplier" + supplier.supplier_group = "All Supplier Groups" + supplier.insert() + + if not frappe.db.exists("Customer", "_Test Subscription Customer"): + customer = frappe.new_doc("Customer") + customer.customer_name = "_Test Subscription Customer" + customer.default_currency = "USD" + customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable USD - _TC"}) + customer.insert() + + if not frappe.db.exists("Customer", "_Test Subscription Customer John Doe"): + customer = frappe.new_doc("Customer") + customer.customer_name = "_Test Subscription Customer John Doe" + customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable - _TC"}) + customer.insert() + + +def reset_settings(): + settings = frappe.get_single("Subscription Settings") + settings.grace_period = 0 + settings.cancel_after_grace = 0 + settings.save() + + +def create_subscription(**kwargs): + subscription = frappe.new_doc("Subscription") + subscription.party_type = (kwargs.get("party_type") or "Customer",) + subscription.company = kwargs.get("company") or "_Test Company" + subscription.party = kwargs.get("party") or "_Test Customer" + subscription.trial_period_start = kwargs.get("trial_period_start") + subscription.trial_period_end = kwargs.get("trial_period_end") + subscription.start_date = kwargs.get("start_date") + subscription.generate_invoice_at = kwargs.get("generate_invoice_at") + subscription.additional_discount_percentage = kwargs.get("additional_discount_percentage") + subscription.additional_discount_amount = kwargs.get("additional_discount_amount") + subscription.follow_calendar_months = kwargs.get("follow_calendar_months") + subscription.generate_new_invoices_past_due_date = kwargs.get("generate_new_invoices_past_due_date") + subscription.submit_invoice = kwargs.get("submit_invoice") + subscription.days_until_due = kwargs.get("days_until_due") + subscription.number_of_days = kwargs.get("number_of_days") + + if not kwargs.get("plans"): + subscription.append("plans", {"plan": "_Test Plan Name", "qty": 1}) + else: + for plan in kwargs.get("plans"): + subscription.append("plans", plan) + + if kwargs.get("do_not_save"): + return subscription + + subscription.save() + + return subscription +>>>>>>> fd680380bb (refactor: test for force-fetch on future subscription) From cca5aa8a96ec9a3e03b580711d7e9233db552ff9 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 13 Aug 2024 16:28:07 +0530 Subject: [PATCH 5/6] chore: resolve conflict --- .../doctype/subscription/subscription.js | 35 ++++--------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/erpnext/accounts/doctype/subscription/subscription.js b/erpnext/accounts/doctype/subscription/subscription.js index 48bbc733fe4..caaa60b5757 100644 --- a/erpnext/accounts/doctype/subscription/subscription.js +++ b/erpnext/accounts/doctype/subscription/subscription.js @@ -29,7 +29,6 @@ frappe.ui.form.on("Subscription", { }, refresh: function (frm) { -<<<<<<< HEAD if (!frm.is_new()) { if (frm.doc.status !== "Cancelled") { frm.add_custom_button(__("Cancel Subscription"), () => @@ -38,39 +37,17 @@ 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) ); } -======= - if (frm.is_new()) return; - - if (frm.doc.status !== "Cancelled") { - frm.add_custom_button( - __("Fetch Subscription Updates"), - () => frm.trigger("get_subscription_updates"), - __("Actions") - ); - - frm.add_custom_button( - __("Force-Fetch Subscription Updates"), - () => frm.trigger("force_fetch_subscription_updates"), - __("Actions") - ); - - frm.add_custom_button( - __("Cancel Subscription"), - () => frm.trigger("cancel_this_subscription"), - __("Actions") - ); - } else if (frm.doc.status === "Cancelled") { - frm.add_custom_button( - __("Restart Subscription"), - () => frm.trigger("renew_this_subscription"), - __("Actions") - ); ->>>>>>> 1ef890db73 (fix: force fetch updates for subcription) } }, From 2d0dca943a29acb950af9948e6a0433ee01cd77c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 13 Aug 2024 16:31:50 +0530 Subject: [PATCH 6/6] chore: resolve conflict --- .../doctype/subscription/test_subscription.py | 112 ++---------------- 1 file changed, 9 insertions(+), 103 deletions(-) diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py index 3b32c727731..26dcb2413f4 100644 --- a/erpnext/accounts/doctype/subscription/test_subscription.py +++ b/erpnext/accounts/doctype/subscription/test_subscription.py @@ -711,113 +711,19 @@ class TestSubscription(FrappeTestCase): pi = frappe.get_doc("Purchase Invoice", subscription.invoices[0].invoice) self.assertEqual(pi.total, 55333.33) -<<<<<<< HEAD subscription.delete() -======= - subscription.process(posting_date="2023-01-22") - self.assertEqual(len(subscription.invoices), 2) def test_future_subscription(self): """Force-Fetch should not process future subscriptions""" - subscription = create_subscription( - start_date=add_months(nowdate(), 1), - submit_invoice=0, - generate_new_invoices_past_due_date=1, - party="_Test Subscription Customer John Doe", - ) + 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) - - -def make_plans(): - create_plan(plan_name="_Test Plan Name", cost=900, currency="INR") - create_plan(plan_name="_Test Plan Name 2", cost=1999, currency="INR") - create_plan( - plan_name="_Test Plan Name 3", - cost=1999, - billing_interval="Day", - billing_interval_count=14, - currency="INR", - ) - create_plan( - plan_name="_Test Plan Name 4", - cost=20000, - billing_interval="Month", - billing_interval_count=3, - currency="INR", - ) - create_plan(plan_name="_Test Plan Multicurrency", cost=50, billing_interval="Month", currency="USD") - - -def create_plan(**kwargs): - if not frappe.db.exists("Subscription Plan", kwargs.get("plan_name")): - plan = frappe.new_doc("Subscription Plan") - plan.plan_name = kwargs.get("plan_name") or "_Test Plan Name" - plan.item = kwargs.get("item") or "_Test Non Stock Item" - plan.price_determination = kwargs.get("price_determination") or "Fixed Rate" - plan.cost = kwargs.get("cost") or 1000 - plan.billing_interval = kwargs.get("billing_interval") or "Month" - plan.billing_interval_count = kwargs.get("billing_interval_count") or 1 - plan.currency = kwargs.get("currency") - plan.insert() - - -def create_parties(): - if not frappe.db.exists("Supplier", "_Test Supplier"): - supplier = frappe.new_doc("Supplier") - supplier.supplier_name = "_Test Supplier" - supplier.supplier_group = "All Supplier Groups" - supplier.insert() - - if not frappe.db.exists("Customer", "_Test Subscription Customer"): - customer = frappe.new_doc("Customer") - customer.customer_name = "_Test Subscription Customer" - customer.default_currency = "USD" - customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable USD - _TC"}) - customer.insert() - - if not frappe.db.exists("Customer", "_Test Subscription Customer John Doe"): - customer = frappe.new_doc("Customer") - customer.customer_name = "_Test Subscription Customer John Doe" - customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable - _TC"}) - customer.insert() - - -def reset_settings(): - settings = frappe.get_single("Subscription Settings") - settings.grace_period = 0 - settings.cancel_after_grace = 0 - settings.save() - - -def create_subscription(**kwargs): - subscription = frappe.new_doc("Subscription") - subscription.party_type = (kwargs.get("party_type") or "Customer",) - subscription.company = kwargs.get("company") or "_Test Company" - subscription.party = kwargs.get("party") or "_Test Customer" - subscription.trial_period_start = kwargs.get("trial_period_start") - subscription.trial_period_end = kwargs.get("trial_period_end") - subscription.start_date = kwargs.get("start_date") - subscription.generate_invoice_at = kwargs.get("generate_invoice_at") - subscription.additional_discount_percentage = kwargs.get("additional_discount_percentage") - subscription.additional_discount_amount = kwargs.get("additional_discount_amount") - subscription.follow_calendar_months = kwargs.get("follow_calendar_months") - subscription.generate_new_invoices_past_due_date = kwargs.get("generate_new_invoices_past_due_date") - subscription.submit_invoice = kwargs.get("submit_invoice") - subscription.days_until_due = kwargs.get("days_until_due") - subscription.number_of_days = kwargs.get("number_of_days") - - if not kwargs.get("plans"): - subscription.append("plans", {"plan": "_Test Plan Name", "qty": 1}) - else: - for plan in kwargs.get("plans"): - subscription.append("plans", plan) - - if kwargs.get("do_not_save"): - return subscription - - subscription.save() - - return subscription ->>>>>>> fd680380bb (refactor: test for force-fetch on future subscription)