set `after_insert` methods:
- if subscription is not in trial period, generate sales invoice
diff --git a/erpnext/accounts/doctype/subscriptions/subscriptions.py b/erpnext/accounts/doctype/subscriptions/subscriptions.py
index 435c364..1a07190 100644
--- a/erpnext/accounts/doctype/subscriptions/subscriptions.py
+++ b/erpnext/accounts/doctype/subscriptions/subscriptions.py
@@ -42,6 +42,17 @@
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 @@
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 @@
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
+