fix: Check if subscription is already created for current invoicing period (#23143)

* fix: Check if subscription is already created for current invoicing period

* fix: Test for duplicate subscription

* fix: invoice generation at the begining of period fix

* fix: invoice generation at the begining of period fix

* fix: Remove unwanted file

* fix: Generate new invoices even though current invoices are unpaid

* fix: Make invoices table read-only

* fix: Update test cases
This commit is contained in:
Deepesh Garg
2020-09-08 10:30:02 +05:30
committed by GitHub
parent b06c618585
commit 47c535399c
3 changed files with 44 additions and 15 deletions

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"autoname": "ACC-SUB-.YYYY.-.#####",
"creation": "2017-07-18 17:50:43.967266",
"doctype": "DocType",
@@ -184,7 +183,8 @@
"fieldname": "invoices",
"fieldtype": "Table",
"label": "Invoices",
"options": "Subscription Invoice"
"options": "Subscription Invoice",
"read_only": 1
},
{
"collapsible": 1,
@@ -197,8 +197,7 @@
"fieldtype": "Column Break"
}
],
"links": [],
"modified": "2020-01-27 14:37:32.845173",
"modified": "2020-08-27 23:30:02.504042",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription",

View File

@@ -326,8 +326,7 @@ class Subscription(Document):
def is_postpaid_to_invoice(self):
return getdate(nowdate()) > getdate(self.current_invoice_end) or \
(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and \
not self.has_outstanding_invoice()
(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start))
def is_prepaid_to_invoice(self):
if not self.generate_invoice_at_period_start:
@@ -337,8 +336,16 @@ class Subscription(Document):
return True
# Check invoice dates and make sure it doesn't have outstanding invoices
return getdate(nowdate()) >= getdate(self.current_invoice_start) and not self.has_outstanding_invoice()
return getdate(nowdate()) >= getdate(self.current_invoice_start)
def is_current_invoice_generated(self):
invoice = self.get_current_invoice()
if invoice and getdate(self.current_invoice_start) <= getdate(invoice.posting_date) <= getdate(self.current_invoice_end):
return True
return False
def is_current_invoice_paid(self):
if self.is_new_subscription():
return False
@@ -346,7 +353,7 @@ class Subscription(Document):
last_invoice = frappe.get_doc('Sales Invoice', self.invoices[-1].invoice)
if getdate(last_invoice.posting_date) == getdate(self.current_invoice_start) and last_invoice.status == 'Paid':
return True
return False
def process_for_active(self):
@@ -358,7 +365,8 @@ class Subscription(Document):
2. Change the `Subscription` status to 'Past Due Date'
3. Change the `Subscription` status to 'Cancelled'
"""
if not self.is_current_invoice_paid() and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()):
if not self.is_current_invoice_generated() and not self.is_current_invoice_paid() and \
(self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()):
self.generate_invoice()
if self.current_invoice_is_past_due():
self.status = 'Past Due Date'
@@ -369,6 +377,9 @@ class Subscription(Document):
if self.cancel_at_period_end and getdate(nowdate()) > getdate(self.current_invoice_end):
self.cancel_subscription_at_period_end()
if self.is_current_invoice_generated() and getdate() > getdate(self.current_invoice_end):
self.update_subscription_period(add_days(self.current_invoice_end, 1))
def cancel_subscription_at_period_end(self):
"""
Called when `Subscription.cancel_at_period_end` is truthy

View File

@@ -101,19 +101,19 @@ class TestSubscription(unittest.TestCase):
subscription.delete()
def test_invoice_is_generated_at_end_of_billing_period(self):
start_date = add_to_date(nowdate(), months=-1)
subscription = frappe.new_doc('Subscription')
subscription.customer = '_Test Customer'
subscription.start = '2018-01-01'
subscription.start = start_date
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
subscription.insert()
self.assertEqual(subscription.status, 'Active')
self.assertEqual(subscription.current_invoice_start, '2018-01-01')
self.assertEqual(subscription.current_invoice_end, '2018-01-31')
self.assertEqual(subscription.current_invoice_start, start_date)
self.assertEqual(subscription.current_invoice_end, add_days(nowdate(), -1))
subscription.process()
self.assertEqual(len(subscription.invoices), 1)
self.assertEqual(subscription.current_invoice_start, '2018-01-01')
self.assertEqual(subscription.status, 'Past Due Date')
subscription.delete()
@@ -137,7 +137,6 @@ class TestSubscription(unittest.TestCase):
subscription.process()
self.assertEqual(subscription.status, 'Active')
self.assertEqual(subscription.current_invoice_start, add_months(subscription.start, 1))
self.assertEqual(len(subscription.invoices), 1)
subscription.delete()
@@ -538,3 +537,23 @@ class TestSubscription(unittest.TestCase):
settings.save()
subscription.delete()
def test_duplicate_invoice_check(self):
subscription = frappe.new_doc('Subscription')
subscription.customer = '_Test Customer'
subscription.generate_invoice_at_period_start = True
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
subscription.start = nowdate()
subscription.save()
# Generate invoice for the current invoicing period
subscription.process()
subscription.load_from_db()
self.assertEqual(len(subscription.invoices), 1)
# Proccess subscription again for the same period
subscription.process()
subscription.load_from_db()
# No new invoice should be created for current period
self.assertEqual(len(subscription.invoices), 1)