Corrections to Subscriptions

This commit is contained in:
Charles-Henri Decultot 2018-06-20 14:53:47 +00:00
parent ba6f6d976d
commit f7ca908ea9
5 changed files with 1265 additions and 984 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,14 +8,15 @@ import frappe
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, flt
from erpnext.utilities.product import get_price
class Subscription(Document):
def before_insert(self):
# update start just before the subscription doc is created
self.update_subscription_period(self.start)
self.update_subscription_period(self.start, init=True)
def update_subscription_period(self, date=None):
def update_subscription_period(self, date=None, init=False):
"""
Subscription period is the period to be billed. This method updates the
beginning of the billing period and end of the billing period.
@ -25,7 +26,7 @@ class Subscription(Document):
as `current_invoice_end`.
"""
self.set_current_invoice_start(date)
self.set_current_invoice_end()
self.set_current_invoice_end(init=False)
def set_current_invoice_start(self, date=None):
"""
@ -40,7 +41,7 @@ class Subscription(Document):
else:
self.current_invoice_start = nowdate()
def set_current_invoice_end(self):
def set_current_invoice_end(self, init=False):
"""
This sets the date of the end of the current billing period.
@ -51,7 +52,9 @@ class Subscription(Document):
current billing period where `x` is the billing interval from the
`Subscription Plan` in the `Subscription`.
"""
if self.is_trialling():
if init==True:
return
elif self.is_trialling():
self.current_invoice_end = self.trial_period_end
else:
billing_cycle_info = self.get_billing_cycle_data()
@ -272,6 +275,10 @@ class Subscription(Document):
discount_on = self.apply_additional_discount
invoice.apply_additional_discount = discount_on if discount_on else 'Grand Total'
# Subscription period
invoice.from_date = self.current_invoice_start
invoice.to_date = self.current_invoice_end
invoice.flags.ignore_mandatory = True
invoice.save()
invoice.submit()
@ -283,28 +290,33 @@ class Subscription(Document):
"""
Returns the `Customer` linked to the `Subscriber`
"""
return frappe.get_value('Subscriber', subscriber_name, 'customer')
return frappe.db.get_value('Subscriber', subscriber_name, 'customer')
def get_items_from_plans(self, plans, prorate=0):
"""
Returns the `Item`s linked to `Subscription Plan`
"""
plan_items = [plan.plan for plan in plans]
item_details = None
if prorate:
prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start)
if plan_items:
item_details = frappe.db.sql(
'select item as item_code, cost as rate from `tabSubscription Plan` where name in %s',
(plan_items,), as_dict=1
)
items = []
for plan in plans:
subscription_plan = frappe.get_doc("Subscription Plan", plan.plan)
if subscription_plan.price_determination == "Fixed rate":
if not prorate:
items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': subscription_plan.cost})
else:
items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': (subscription_plan.cost * prorate_factor)})
elif subscription_plan.price_determination == "Based on price list":
customer = self.get_customer(self.subscriber)
customer_group = frappe.db.get_value("Customer", customer, "customer_group")
rate = get_price(item_code=subscription_plan.item, price_list=subscription_plan.price_list, customer_group=customer_group, company=None, qty=plan.qty)
if not prorate:
items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': rate})
else:
items.append({'item_code': subscription_plan.item, 'qty': plan.qty, 'rate': (rate * prorate_factor)})
if prorate:
prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start)
for item in item_details:
item['rate'] = item['rate'] * prorate_factor
return item_details
return items
def process(self):
"""
@ -329,7 +341,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) and not self.has_outstanding_invoice():
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():
self.generate_invoice()
if self.current_invoice_is_past_due():
self.status = 'Past Due Date'
@ -363,7 +375,7 @@ class Subscription(Document):
else:
if self.is_not_outstanding(current_invoice):
self.status = 'Active'
self.update_subscription_period(nowdate())
self.update_subscription_period(add_days(self.current_invoice_end, 1))
else:
self.set_status_grace_period()

View File

@ -1,2 +1,9 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Subscription Plan', {
price_determination: function(frm) {
frm.toggle_reqd("cost", frm.doc.price_determination === 'Fixed rate');
frm.toggle_reqd("price_list", frm.doc.price_determination === 'Based on price list');
}
})

View File

@ -15,6 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -42,42 +43,11 @@
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item",
"length": 0,
"no_copy": 0,
"options": "Item",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -110,10 +80,172 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"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,
"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,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item",
"length": 0,
"no_copy": 0,
"options": "Item",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_5",
"fieldtype": "Section Break",
"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,
"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,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"fieldname": "price_determination",
"fieldtype": "Select",
"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": "Price Determination",
"length": 0,
"no_copy": 0,
"options": "\nFixed rate\nBased on price list",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_7",
"fieldtype": "Column Break",
"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,
"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,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.price_determination==\"Fixed rate\"",
"fieldname": "cost",
"fieldtype": "Currency",
"hidden": 0,
@ -133,7 +265,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@ -141,6 +273,72 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.price_determination==\"Based on price list\"",
"fieldname": "price_list",
"fieldtype": "Link",
"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": "Price List",
"length": 0,
"no_copy": 0,
"options": "Price List",
"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,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_11",
"fieldtype": "Section Break",
"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,
"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,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -174,6 +372,38 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_13",
"fieldtype": "Column Break",
"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,
"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,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -216,7 +446,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-02-27 09:12:58.330140",
"modified": "2018-06-20 15:43:10.152762",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription Plan",
@ -225,7 +455,6 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@ -244,7 +473,7 @@
"write": 1
}
],
"quick_entry": 1,
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,

View File

@ -14,6 +14,39 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "qty",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Quantity",
"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": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -55,7 +88,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-02-25 07:35:07.736146",
"modified": "2018-06-20 15:35:13.514699",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription Plan Detail",