add ability to cancel, restart and refresh subscription
This commit is contained in:
parent
2cccad0274
commit
8f37926ca8
@ -3,6 +3,75 @@
|
||||
|
||||
frappe.ui.form.on('Subscriptions', {
|
||||
refresh: function(frm) {
|
||||
if(!frm.is_new()){
|
||||
if(frm.doc.status !== 'Canceled'){
|
||||
frm.add_custom_button(
|
||||
__('Cancel Subscription'),
|
||||
() => frm.events.cancel_this_subscription(frm)
|
||||
);
|
||||
frm.add_custom_button(
|
||||
__('Fetch Subscription Updates'),
|
||||
() => frm.events.get_subscription_updates(frm)
|
||||
);
|
||||
}
|
||||
else if(frm.doc.status === 'Canceled'){
|
||||
frm.add_custom_button(
|
||||
__('Restart Subscription'),
|
||||
() => frm.events.renew_this_subscription(frm)
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
cancel_this_subscription: function(frm) {
|
||||
const doc = frm.doc;
|
||||
frappe.confirm(
|
||||
__('This action will stop future billing. Are you sure you want to cancel this subscription?'),
|
||||
function() {
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.subscriptions.subscriptions.cancel_subscription",
|
||||
args: {name: doc.name},
|
||||
callback: function(data){
|
||||
if(!data.exc){
|
||||
frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
renew_this_subscription: function(frm) {
|
||||
const doc = frm.doc;
|
||||
frappe.confirm(
|
||||
__('You will lose records of previously generated invoices. Are you sure you want to restart this subscription?'),
|
||||
function() {
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.subscriptions.subscriptions.restart_subscription",
|
||||
args: {name: doc.name},
|
||||
callback: function(data){
|
||||
if(!data.exc){
|
||||
frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
get_subscription_updates: function(frm) {
|
||||
const doc = frm.doc;
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.subscriptions.subscriptions.get_subscription_updates",
|
||||
args: {name: doc.name},
|
||||
callback: function(data){
|
||||
if(!data.exc){
|
||||
frm.reload_doc();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -14,8 +14,8 @@ class Subscriptions(Document):
|
||||
# update start just before the subscription doc is created
|
||||
self.update_subscription_period()
|
||||
|
||||
def update_subscription_period(self):
|
||||
self.set_current_invoice_start()
|
||||
def update_subscription_period(self, date=None):
|
||||
self.set_current_invoice_start(date)
|
||||
self.set_current_invoice_end()
|
||||
|
||||
def set_current_invoice_start(self, date=None):
|
||||
@ -228,16 +228,19 @@ class Subscriptions(Document):
|
||||
"""
|
||||
if self.status == 'Active':
|
||||
self.process_for_active()
|
||||
elif self.status == 'Past Due Date':
|
||||
elif self.status in ['Past Due Date', 'Unpaid']:
|
||||
self.process_for_past_due_date()
|
||||
self.save()
|
||||
# process_for_unpaid()
|
||||
|
||||
if self.status != 'Canceled':
|
||||
self.save()
|
||||
|
||||
def process_for_active(self):
|
||||
if getdate(nowdate()) > getdate(self.current_invoice_end) and not self.has_outstanding_invoice():
|
||||
self.generate_invoice()
|
||||
if self.current_invoice_is_past_due():
|
||||
self.status = 'Past Due Date'
|
||||
|
||||
if self.current_invoice_is_past_due():
|
||||
if self.current_invoice_is_past_due() and getdate(nowdate()) > getdate(self.current_invoice_end):
|
||||
self.status = 'Past Due Date'
|
||||
|
||||
def process_for_past_due_date(self):
|
||||
@ -247,7 +250,7 @@ class Subscriptions(Document):
|
||||
else:
|
||||
if self.is_not_outstanding(current_invoice):
|
||||
self.status = 'Active'
|
||||
self.update_subscription_period()
|
||||
self.update_subscription_period(nowdate())
|
||||
else:
|
||||
self.set_status_grace_period()
|
||||
|
||||
@ -261,3 +264,41 @@ class Subscriptions(Document):
|
||||
else:
|
||||
return not self.is_not_outstanding(current_invoice)
|
||||
return True
|
||||
|
||||
def cancel_subscription(self):
|
||||
"""
|
||||
This sets the subscription as cancelled. It will stop invoices from being generated
|
||||
but it will not affect already created invoices.
|
||||
"""
|
||||
self.status = 'Canceled'
|
||||
self.cancelation_date = nowdate()
|
||||
self.save()
|
||||
|
||||
def restart_subscription(self):
|
||||
"""
|
||||
This sets the subscription as active. The subscription will be made to be like a new
|
||||
subscription but new trial periods will not be allowed.
|
||||
"""
|
||||
self.status = 'Active'
|
||||
self.cancelation_date = None
|
||||
self.update_subscription_period(nowdate())
|
||||
self.invoices = []
|
||||
self.save()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def cancel_subscription(name):
|
||||
subscription = frappe.get_doc('Subscriptions', name)
|
||||
subscription.cancel_subscription()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def restart_subscription(name):
|
||||
subscription = frappe.get_doc('Subscriptions', name)
|
||||
subscription.restart_subscription()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_subscription_updates(name):
|
||||
subscription = frappe.get_doc('Subscriptions', name)
|
||||
subscription.process()
|
@ -267,5 +267,123 @@ class TestSubscriptions(unittest.TestCase):
|
||||
|
||||
subscription.delete()
|
||||
|
||||
def test_subcription_cancelation(self):
|
||||
subscription = frappe.new_doc('Subscriptions')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name'})
|
||||
subscription.save()
|
||||
subscription.cancel_subscription()
|
||||
|
||||
self.assertEqual(subscription.status, 'Canceled')
|
||||
|
||||
subscription.delete()
|
||||
|
||||
def test_subcription_cancelation_and_process(self):
|
||||
settings = frappe.get_single('Subscription Settings')
|
||||
default_grace_period_action = settings.cancel_after_grace
|
||||
settings.cancel_after_grace = 1
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscriptions')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name'})
|
||||
subscription.insert()
|
||||
subscription.set_current_invoice_start('2018-01-01')
|
||||
subscription.set_current_invoice_end()
|
||||
subscription.process() # generate first invoice
|
||||
invoices = len(subscription.invoices)
|
||||
|
||||
self.assertEqual(subscription.status, 'Past Due Date')
|
||||
self.assertEqual(len(subscription.invoices), invoices)
|
||||
|
||||
subscription.cancel_subscription()
|
||||
self.assertEqual(subscription.status, 'Canceled')
|
||||
self.assertEqual(len(subscription.invoices), invoices)
|
||||
|
||||
subscription.process()
|
||||
self.assertEqual(subscription.status, 'Canceled')
|
||||
self.assertEqual(len(subscription.invoices), invoices)
|
||||
|
||||
subscription.process()
|
||||
self.assertEqual(subscription.status, 'Canceled')
|
||||
self.assertEqual(len(subscription.invoices), invoices)
|
||||
|
||||
settings.cancel_after_grace = default_grace_period_action
|
||||
settings.save()
|
||||
subscription.delete()
|
||||
|
||||
def test_subscription_restart_and_process(self):
|
||||
settings = frappe.get_single('Subscription Settings')
|
||||
default_grace_period_action = settings.cancel_after_grace
|
||||
settings.grace_period = 0
|
||||
settings.cancel_after_grace = 0
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscriptions')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name'})
|
||||
subscription.insert()
|
||||
subscription.set_current_invoice_start('2018-01-01')
|
||||
subscription.set_current_invoice_end()
|
||||
subscription.process() # generate first invoice
|
||||
|
||||
self.assertEqual(subscription.status, 'Past Due Date')
|
||||
|
||||
subscription.process()
|
||||
self.assertEqual(subscription.status, 'Unpaid')
|
||||
|
||||
subscription.cancel_subscription()
|
||||
self.assertEqual(subscription.status, 'Canceled')
|
||||
|
||||
subscription.restart_subscription()
|
||||
self.assertEqual(subscription.status, 'Active')
|
||||
self.assertEqual(len(subscription.invoices), 0)
|
||||
|
||||
subscription.process()
|
||||
self.assertEqual(subscription.status, 'Active')
|
||||
self.assertEqual(len(subscription.invoices), 0)
|
||||
|
||||
subscription.process()
|
||||
self.assertEqual(subscription.status, 'Active')
|
||||
self.assertEqual(len(subscription.invoices), 0)
|
||||
|
||||
settings.cancel_after_grace = default_grace_period_action
|
||||
settings.save()
|
||||
subscription.delete()
|
||||
|
||||
def test_subscription_unpaid_back_to_active(self):
|
||||
settings = frappe.get_single('Subscription Settings')
|
||||
default_grace_period_action = settings.cancel_after_grace
|
||||
settings.cancel_after_grace = 0
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscriptions')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name'})
|
||||
subscription.insert()
|
||||
subscription.set_current_invoice_start('2018-01-01')
|
||||
subscription.set_current_invoice_end()
|
||||
subscription.process() # generate first invoice
|
||||
|
||||
self.assertEqual(subscription.status, 'Past Due Date')
|
||||
|
||||
subscription.process()
|
||||
# This should change status to Canceled since grace period is 0
|
||||
self.assertEqual(subscription.status, 'Unpaid')
|
||||
|
||||
invoice = subscription.get_current_invoice()
|
||||
invoice.db_set('outstanding_amount', 0)
|
||||
invoice.db_set('status', 'Paid')
|
||||
|
||||
subscription.process()
|
||||
self.assertEqual(subscription.status, 'Active')
|
||||
|
||||
subscription.process()
|
||||
self.assertEqual(subscription.status, 'Active')
|
||||
|
||||
settings.cancel_after_grace = default_grace_period_action
|
||||
settings.save()
|
||||
subscription.delete()
|
||||
|
||||
def test_subscription_creation_with_multiple_plans(self):
|
||||
pass
|
||||
|
Loading…
x
Reference in New Issue
Block a user