From 3d825e5689bf9cf6376f24d321e09806729ab339 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Fri, 13 Jul 2018 17:41:36 +0530 Subject: [PATCH] Subscription test and fixes (#14875) * Add dashboard on subscriber screen * Add Subscription and Subscription Plan to Account Dashboard * Fetch customer name while creating subscriber * [fix] add section for Subscription Period * minor fixes * optimization --- .../doctype/subscriber/subscriber.json | 69 ++--- .../subscriber/subscriber_dashboard.py | 14 + .../doctype/subscription/subscription.json | 247 ++++++++++++------ .../doctype/subscription/subscription.py | 31 +-- erpnext/config/accounts.py | 22 ++ 5 files changed, 248 insertions(+), 135 deletions(-) create mode 100644 erpnext/accounts/doctype/subscriber/subscriber_dashboard.py diff --git a/erpnext/accounts/doctype/subscriber/subscriber.json b/erpnext/accounts/doctype/subscriber/subscriber.json index 28a57d8b1a..3fb7fdb087 100644 --- a/erpnext/accounts/doctype/subscriber/subscriber.json +++ b/erpnext/accounts/doctype/subscriber/subscriber.json @@ -15,37 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "subscriber_name", - "fieldtype": "Data", - "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": "Subscriber Name", - "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, @@ -75,6 +45,40 @@ "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, + "fetch_from": "customer.customer_name", + "fieldname": "subscriber_name", + "fieldtype": "Data", + "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": "Subscriber Name", + "length": 0, + "no_copy": 0, + "options": "", + "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": 1 } ], "has_web_view": 0, @@ -87,7 +91,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-02-26 04:40:16.510290", + "modified": "2018-07-11 15:13:30.056470", "modified_by": "Administrator", "module": "Accounts", "name": "Subscriber", @@ -96,7 +100,6 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, diff --git a/erpnext/accounts/doctype/subscriber/subscriber_dashboard.py b/erpnext/accounts/doctype/subscriber/subscriber_dashboard.py new file mode 100644 index 0000000000..3120384c6a --- /dev/null +++ b/erpnext/accounts/doctype/subscriber/subscriber_dashboard.py @@ -0,0 +1,14 @@ +from frappe import _ + +def get_data(): + return { + 'heatmap': True, + 'heatmap_message': _('This is based on transactions against this Subscriber. See timeline below for details'), + 'fieldname': 'subscriber', + 'transactions': [ + { + 'label': _('Subscriptions'), + 'items': ['Subscription'] + } + ] + } \ No newline at end of file diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json index 1165bede2d..5d64d9a1a0 100644 --- a/erpnext/accounts/doctype/subscription/subscription.json +++ b/erpnext/accounts/doctype/subscription/subscription.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,12 +48,13 @@ }, { "allow_bulk_edit": 0, - "allow_on_submit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "cancel_at_period_end", - "fieldtype": "Check", + "fieldname": "cb_1", + "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -60,10 +62,9 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Cancel At End Of Period", + "label": "", "length": 0, "no_copy": 0, - "options": "", "permlevel": 0, "precision": "", "print_hide": 0, @@ -79,6 +80,105 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "status", + "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": "Status", + "length": 0, + "no_copy": 0, + "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "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": "1", + "fieldname": "quantity", + "fieldtype": "Int", + "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": "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": 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": "subscription_period", + "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, + "label": "Subscription 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, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -111,6 +211,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -143,68 +244,7 @@ }, { "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "current_invoice_start", - "fieldtype": "Date", - "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": "Current Invoice Start Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "current_invoice_end", - "fieldtype": "Date", - "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": "Current Invoice End Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "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": 1, "bold": 0, "collapsible": 0, @@ -236,6 +276,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -268,11 +309,12 @@ }, { "allow_bulk_edit": 0, - "allow_on_submit": 1, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "cb_1", + "fieldname": "column_break_11", "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, @@ -281,7 +323,6 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "", "length": 0, "no_copy": 0, "permlevel": 0, @@ -299,12 +340,13 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "status", - "fieldtype": "Select", + "fieldname": "current_invoice_start", + "fieldtype": "Date", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -312,10 +354,9 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Status", + "label": "Current Invoice Start Date", "length": 0, "no_copy": 0, - "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid", "permlevel": 0, "precision": "", "print_hide": 0, @@ -331,6 +372,39 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "current_invoice_end", + "fieldtype": "Date", + "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": "Current Invoice End Date", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "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, @@ -365,13 +439,13 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "default": "1", - "fieldname": "quantity", - "fieldtype": "Int", + "fieldname": "cancel_at_period_end", + "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -379,9 +453,10 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Quantity", + "label": "Cancel At End Of Period", "length": 0, "no_copy": 0, + "options": "", "permlevel": 0, "precision": "", "print_hide": 0, @@ -397,6 +472,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -429,6 +505,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -461,6 +538,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -492,6 +570,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -524,6 +603,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -557,6 +637,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -589,6 +670,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -621,6 +703,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -654,6 +737,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -686,6 +770,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -719,6 +804,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -761,7 +847,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-03-12 00:34:52.243133", + "modified": "2018-07-11 19:34:44.582203", "modified_by": "Administrator", "module": "Accounts", "name": "Subscription", @@ -770,7 +856,6 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -790,7 +875,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -810,7 +894,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 77ceecec7c..72f86f2f60 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -35,10 +35,10 @@ class Subscription(Document): """ if self.trial_period_start and self.is_trialling(): self.current_invoice_start = self.trial_period_start - elif not date: - self.current_invoice_start = nowdate() elif date: self.current_invoice_start = date + else: + self.current_invoice_start = nowdate() def set_current_invoice_end(self): """ @@ -54,19 +54,12 @@ class Subscription(Document): if self.is_trialling(): self.current_invoice_end = self.trial_period_end else: - billing_cycle_info = self.get_billing_cycle() + billing_cycle_info = self.get_billing_cycle_data() if billing_cycle_info: self.current_invoice_end = add_to_date(self.current_invoice_start, **billing_cycle_info) else: self.current_invoice_end = get_last_day(self.current_invoice_start) - def get_billing_cycle(self): - """ - Returns a dict containing billing cycle information deduced from the - `Subscription Plan` in the `Subscription`. - """ - return self.get_billing_cycle_data() - @staticmethod def validate_plans_billing_cycle(billing_cycle_data): """ @@ -297,23 +290,21 @@ class Subscription(Document): Returns the `Item`s linked to `Subscription Plan` """ plan_items = [plan.plan for plan in plans] - item_names = None + item_details = None - if plan_items and not prorate: - item_names = frappe.db.sql( + 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 ) - elif plan_items: - prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start) + if prorate: + 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', - (prorate_factor, plan_items,), as_dict=1 - ) + for item in item_details: + item['rate'] = item['rate'] * prorate_factor - return item_names + return item_details def process(self): """ diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py index a53442115c..f86ea37d6c 100644 --- a/erpnext/config/accounts.py +++ b/erpnext/config/accounts.py @@ -496,6 +496,28 @@ def get_data(): } ] }, + { + "label": _("Subscription Management"), + "icon": "fa fa-microchip ", + "items": [ + { + "type": "doctype", + "name":"Subscriber", + }, + { + "type": "doctype", + "name":"Subscription Plan", + }, + { + "type": "doctype", + "name":"Subscription" + }, + { + "type": "doctype", + "name": "Subscription Settings" + } + ] + }, { "label": _("Help"), "icon": "fa fa-facetime-video",