Merge pull request #15700 from joeirimpan/staging-fixes
feat: Add provision for prebilled subscription invoices
This commit is contained in:
commit
19be730b9c
@ -437,6 +437,38 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "generate_invoice_at_period_start",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Generate Invoice At Beginning Of Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -814,7 +846,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-08-21 16:15:44.533482",
|
||||
"modified": "2018-10-04 10:29:03.338893",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Subscription",
|
||||
|
@ -321,6 +321,23 @@ class Subscription(Document):
|
||||
|
||||
self.save()
|
||||
|
||||
@property
|
||||
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()
|
||||
|
||||
@property
|
||||
def is_prepaid_to_invoice(self):
|
||||
if not self.generate_invoice_at_period_start:
|
||||
return False
|
||||
|
||||
if self.is_new_subscription():
|
||||
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()
|
||||
|
||||
def process_for_active(self):
|
||||
"""
|
||||
Called by `process` if the status of the `Subscription` is 'Active'.
|
||||
@ -330,7 +347,7 @@ class Subscription(Document):
|
||||
2. Change the `Subscription` status to 'Past Due Date'
|
||||
3. Change the `Subscription` status to 'Cancelled'
|
||||
"""
|
||||
if 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():
|
||||
if 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'
|
||||
@ -338,7 +355,7 @@ class Subscription(Document):
|
||||
if self.current_invoice_is_past_due() and getdate(nowdate()) > getdate(self.current_invoice_end):
|
||||
self.status = 'Past Due Date'
|
||||
|
||||
if self.cancel_at_period_end and getdate(nowdate()) > self.current_invoice_end:
|
||||
if self.cancel_at_period_end and getdate(nowdate()) > getdate(self.current_invoice_end):
|
||||
self.cancel_subscription_at_period_end()
|
||||
|
||||
def cancel_subscription_at_period_end(self):
|
||||
|
@ -500,3 +500,51 @@ class TestSubscription(unittest.TestCase):
|
||||
self.assertEqual(invoice.apply_discount_on, 'Grand Total')
|
||||
|
||||
subscription.delete()
|
||||
|
||||
def test_prepaid_subscriptions(self):
|
||||
# Create a non pre-billed subscription, processing should not create
|
||||
# invoices.
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
subscription.process()
|
||||
|
||||
self.assertEqual(len(subscription.invoices), 0)
|
||||
|
||||
# Change the subscription type to prebilled and process it.
|
||||
# Prepaid invoice should be generated
|
||||
subscription.generate_invoice_at_period_start = True
|
||||
subscription.save()
|
||||
subscription.process()
|
||||
|
||||
self.assertEqual(len(subscription.invoices), 1)
|
||||
|
||||
def test_prepaid_subscriptions_with_prorate_true(self):
|
||||
settings = frappe.get_single('Subscription Settings')
|
||||
to_prorate = settings.prorate
|
||||
settings.prorate = 1
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.generate_invoice_at_period_start = True
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
subscription.cancel_subscription()
|
||||
|
||||
self.assertEqual(len(subscription.invoices), 1)
|
||||
|
||||
current_inv = subscription.get_current_invoice()
|
||||
self.assertEqual(current_inv.status, "Unpaid")
|
||||
|
||||
diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1)
|
||||
plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1)
|
||||
prorate_factor = flt(diff / plan_days)
|
||||
|
||||
self.assertEqual(flt(current_inv.grand_total, 2), flt(prorate_factor * 900, 2))
|
||||
|
||||
settings.prorate = to_prorate
|
||||
settings.save()
|
||||
|
||||
subscription.delete()
|
||||
|
Loading…
x
Reference in New Issue
Block a user