This commit is contained in:
tundebabzy 2018-03-02 11:00:15 +01:00
parent 49d34df8f4
commit c15dc21b7d
2 changed files with 44 additions and 39 deletions

View File

@ -3,10 +3,11 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe.utils.data import now, nowdate, getdate, cint, add_days, date_diff, get_last_day, get_first_day, add_to_date
from frappe import _
from frappe.model.document import Document
from frappe.utils.data import nowdate, getdate, cint, add_days, date_diff, get_last_day, add_to_date
class Subscriptions(Document):
@ -67,7 +68,8 @@ class Subscriptions(Document):
"""
return self.get_billing_cycle_data()
def validate_plans_billing_cycle(self, billing_cycle_data):
@staticmethod
def validate_plans_billing_cycle(billing_cycle_data):
"""
Makes sure that all `Subscription Plan` in the `Subscription` have the
same billing interval
@ -112,7 +114,7 @@ class Subscriptions(Document):
elif interval == 'Month':
data['months'] = interval_count
elif interval == 'Year':
data['years'] == interval_count
data['years'] = interval_count
# todo: test week
elif interval == 'Week':
data['days'] = interval_count * 7 - 1
@ -154,7 +156,8 @@ class Subscriptions(Document):
"""
return not self.period_has_passed(self.trial_period_end) and self.is_new_subscription()
def period_has_passed(self, end_date):
@staticmethod
def period_has_passed(end_date):
"""
Returns true if the given `end_date` has passed
"""
@ -198,7 +201,7 @@ class Subscriptions(Document):
doc = frappe.get_doc('Sales Invoice', current.invoice)
return doc
else:
frappe.throw(_('Invoice {0} no longer exists'.format(invoice.invoice)))
frappe.throw(_('Invoice {0} no longer exists'.format(current.invoice)))
def is_new_subscription(self):
"""
@ -282,7 +285,8 @@ class Subscriptions(Document):
return invoice
def get_customer(self, subscriber_name):
@staticmethod
def get_customer(subscriber_name):
"""
Returns the `Customer` linked to the `Subscriber`
"""
@ -302,7 +306,7 @@ class Subscriptions(Document):
)
elif plan_items:
prorate_factor = self.get_proration_factor(self.current_invoice_end, self.current_invoice_start)
prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start)
item_names = frappe.db.sql(
'select item as item_code, cost * %s as rate from `tabSubscription Plan` where name in %s',
@ -311,13 +315,6 @@ class Subscriptions(Document):
return item_names
def get_proration_factor(self, period_end, period_start):
diff = date_diff(nowdate(), period_start) + 1
plan_days = date_diff(period_end, period_start) + 1
prorate_factor = diff/plan_days
return prorate_factor
def process(self):
"""
To be called by task periodically. It checks the subscription and takes appropriate action
@ -379,7 +376,8 @@ class Subscriptions(Document):
else:
self.set_status_grace_period()
def is_not_outstanding(self, invoice):
@staticmethod
def is_not_outstanding(invoice):
"""
Return `True` if the given invoice is paid
"""
@ -394,7 +392,6 @@ class Subscriptions(Document):
return False
else:
return not self.is_not_outstanding(current_invoice)
return True
def cancel_subscription(self):
"""
@ -457,6 +454,14 @@ def process(data):
frappe.db.commit()
def get_prorata_factor(period_end, period_start):
diff = date_diff(nowdate(), period_start) + 1
plan_days = date_diff(period_end, period_start) + 1
prorate_factor = diff/plan_days
return prorate_factor
@frappe.whitelist()
def cancel_subscription(name):
"""

View File

@ -3,10 +3,11 @@
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
from frappe.utils.data import nowdate, add_days, get_last_day, cint, getdate, add_to_date, get_datetime_str, add_months, date_diff
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
import frappe
from erpnext.accounts.doctype.subscriptions.subscriptions import get_prorata_factor
from frappe.utils.data import nowdate, add_days, add_to_date, add_months, date_diff
class TestSubscriptions(unittest.TestCase):
@ -156,7 +157,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.append('plans', {'plan': '_Test Plan Name'})
subscription.start = '2018-01-01'
subscription.insert()
subscription.process() # generate first invoice
subscription.process() # generate first invoice
self.assertEqual(subscription.status, 'Past Due Date')
@ -179,7 +180,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.append('plans', {'plan': '_Test Plan Name'})
subscription.start = '2018-01-01'
subscription.insert()
subscription.process() # generate first invoice
subscription.process() # generate first invoice
self.assertEqual(subscription.status, 'Past Due Date')
@ -198,13 +199,13 @@ class TestSubscriptions(unittest.TestCase):
subscription.days_until_due = 10
subscription.start = add_months(nowdate(), -1)
subscription.insert()
subscription.process() # generate first invoice
subscription.process() # generate first invoice
self.assertEqual(len(subscription.invoices), 1)
self.assertEqual(subscription.status, 'Active')
subscription.delete()
def test_subcription_is_past_due_doesnt_change_within_grace_period(self):
def test_subscription_is_past_due_doesnt_change_within_grace_period(self):
settings = frappe.get_single('Subscription Settings')
grace_period = settings.grace_period
settings.grace_period = 1000
@ -215,7 +216,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.append('plans', {'plan': '_Test Plan Name'})
subscription.start = '2018-01-01'
subscription.insert()
subscription.process() # generate first invoice
subscription.process() # generate first invoice
self.assertEqual(subscription.status, 'Past Due Date')
@ -238,20 +239,20 @@ class TestSubscriptions(unittest.TestCase):
subscription.subscriber = '_Test Customer'
subscription.append('plans', {'plan': '_Test Plan Name'})
subscription.save()
subscription.process() # no changes expected
subscription.process() # no changes expected
self.assertEqual(subscription.status, 'Active')
self.assertEqual(subscription.current_invoice_start, nowdate())
self.assertEqual(subscription.current_invoice_end, add_to_date(nowdate(), months=1, days=-1))
self.assertEqual(len(subscription.invoices), 0)
subscription.process() # no changes expected still
subscription.process() # no changes expected still
self.assertEqual(subscription.status, 'Active')
self.assertEqual(subscription.current_invoice_start, nowdate())
self.assertEqual(subscription.current_invoice_end, add_to_date(nowdate(), months=1, days=-1))
self.assertEqual(len(subscription.invoices), 0)
subscription.process() # no changes expected yet still
subscription.process() # no changes expected yet still
self.assertEqual(subscription.status, 'Active')
self.assertEqual(subscription.current_invoice_start, nowdate())
self.assertEqual(subscription.current_invoice_end, add_to_date(nowdate(), months=1, days=-1))
@ -259,7 +260,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.delete()
def test_subcription_cancelation(self):
def test_subscription_cancelation(self):
subscription = frappe.new_doc('Subscriptions')
subscription.subscriber = '_Test Customer'
subscription.append('plans', {'plan': '_Test Plan Name'})
@ -270,7 +271,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.delete()
def test_subscription_cancelation_invoices(self):
def test_subscription_cancellation_invoices(self):
subscription = frappe.new_doc('Subscriptions')
subscription.subscriber = '_Test Customer'
subscription.append('plans', {'plan': '_Test Plan Name'})
@ -288,16 +289,15 @@ class TestSubscriptions(unittest.TestCase):
prorate_factor = diff/plan_days
self.assertEqual(
subscription.get_proration_factor(
subscription.current_invoice_end,
subscription.current_invoice_start
), prorate_factor)
get_prorata_factor(subscription.current_invoice_end, subscription.current_invoice_start),
prorate_factor
)
self.assertEqual(invoice.grand_total, prorate_factor * 900)
self.assertEqual(subscription.status, 'Canceled')
subscription.delete()
def test_subscription_cancellation_invoices_with_proration_false(self):
def test_subscription_cancellation_invoices_with_prorata_false(self):
settings = frappe.get_single('Subscription Settings')
to_prorate = settings.prorate
settings.prorate = 0
@ -317,7 +317,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.delete()
def test_subscription_cancellation_invoices_with_proration_true(self):
def test_subscription_cancellation_invoices_with_prorata_true(self):
settings = frappe.get_single('Subscription Settings')
to_prorate = settings.prorate
settings.prorate = 1
@ -341,7 +341,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.delete()
def test_subcription_cancelation_and_process(self):
def test_subcription_cancellation_and_process(self):
settings = frappe.get_single('Subscription Settings')
default_grace_period_action = settings.cancel_after_grace
settings.cancel_after_grace = 1
@ -386,7 +386,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.append('plans', {'plan': '_Test Plan Name'})
subscription.start = '2018-01-01'
subscription.insert()
subscription.process() # generate first invoice
subscription.process() # generate first invoice
self.assertEqual(subscription.status, 'Past Due Date')
@ -423,7 +423,7 @@ class TestSubscriptions(unittest.TestCase):
subscription.append('plans', {'plan': '_Test Plan Name'})
subscription.start = '2018-01-01'
subscription.insert()
subscription.process() # generate first invoice
subscription.process() # generate first invoice
self.assertEqual(subscription.status, 'Past Due Date')