From d3fdcd9da586bc27613184fd33de40ef8575ea11 Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Mon, 26 Feb 2018 16:03:56 +0100 Subject: [PATCH] set `after_insert` methods: - if subscription is not in trial period, generate sales invoice --- .../doctype/subscriptions/subscriptions.py | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/erpnext/accounts/doctype/subscriptions/subscriptions.py b/erpnext/accounts/doctype/subscriptions/subscriptions.py index 435c364d99..1a07190e7d 100644 --- a/erpnext/accounts/doctype/subscriptions/subscriptions.py +++ b/erpnext/accounts/doctype/subscriptions/subscriptions.py @@ -42,6 +42,17 @@ class Subscriptions(Document): self.status = 'Active' # todo: then generate new invoice + def is_trialling(self): + return not self.period_has_passed(self.trial_period_end) and self.is_new_subscription() + + def period_has_passed(self, end_date): + # todo: test for illegal time + if not end_date: + return True + + end_date = getdate(end_date) + return nowdate() > end_date + def is_past_grace_period(self): current_invoice = self.get_current_invoice() if self.current_invoice_is_past_due(current_invoice): @@ -58,6 +69,12 @@ class Subscriptions(Document): else: return nowdate() > current_invoice.due_date + def get_current_invoice(self): + if len(self.invoices): + current = self.invoices[-1] + doc = frappe.get_doc('Sales Invoice', current) + return doc + def is_new_subscription(self): return len(self.invoices) == 0 @@ -72,3 +89,67 @@ class Subscriptions(Document): elif self.trial_period_start or self.trial_period_end: frappe.throw(_('Both Trial Period Start Date and Trial Period End Date must be set')) + def after_insert(self): + if not self.is_trialling(): + self.generate_invoice() + + def generate_invoice(self): + invoice = self.create_invoice() + invoice.save() + invoice.submit() + self.append('invoices', {'invoice': invoice.name}) + self.subscription_updated(invoice) + + return invoice + + def create_invoice(self): + invoice = frappe.new_doc('Sales Invoice') + invoice.customer = self.get_customer(self.subscriber) + + # Subscription is better suited for service items. I won't update `update_stock` + # for that reason + items_list = self.get_items_from_plans(self.plans) + for item in items_list: + item['qty'] = self.quantity + invoice.append('items', item) + + # Taxes + # todo: tax template does not populate tax table + if self.tax_template: + invoice.taxes_and_charges = self.tax_template + + # Due date + if cint(self.days_until_due): + invoice.append( + 'payment_schedule', + { + 'due_date': add_days(nowdate(), cint(self.days_until_due)), + 'invoice_portion': 100 + } + ) + + # Discounts + if self.apply_additional_discount: + invoice.apply_discount_on = self.apply_additional_discount + + if self.additional_discount_percentage: + invoice.additional_discount_percentage = self.additional_discount_percentage + + if self.additional_discount_amount: + invoice.additional_discount_amount = self.additional_discount_amount + + return invoice + + def get_customer(self, subscriber_name): + return frappe.get_value('Subscriber', subscriber_name) + + def get_items_from_plans(self, plans): + plan_items = [plan.plan for plan in plans] + + if plan_items: + item_names = frappe.db.sql( + 'select item as item_code, cost as rate from `tabSubscription Plan` where name=%s', + plan_items, as_dict=1 + ) + return item_names +