Merge pull request #14707 from chdecultot/stripe_improvements_4

Stripe Subscriptions
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js
index afc3804..8820161 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.js
+++ b/erpnext/accounts/doctype/payment_request/payment_request.js
@@ -31,7 +31,7 @@
 			});
 		});
 	}
-	
+
 	if(!frm.doc.payment_gateway_account && frm.doc.status == "Initiated") {
 		frm.add_custom_button(__('Make Payment Entry'), function(){
 			frappe.call({
@@ -49,3 +49,25 @@
 	}
 });
 
+frappe.ui.form.on("Payment Request", "is_a_subscription", function(frm) {
+	frm.toggle_reqd("payment_gateway_account", frm.doc.is_a_subscription);
+	frm.toggle_reqd("subscription_plans", frm.doc.is_a_subscription);
+
+	if (frm.doc.is_a_subscription) {
+		frappe.call({
+			method: "erpnext.accounts.doctype.payment_request.payment_request.get_subscription_details",
+			args: {"reference_doctype": frm.doc.reference_doctype, "reference_name": frm.doc.reference_name},
+			freeze: true,
+			callback: function(data){
+				if(!data.exc) {
+					$.each(data.message || [], function(i, v){
+						var d = frappe.model.add_child(frm.doc, "Subscription Plan Detail", "subscription_plans");
+						d.qty = v.qty;
+						d.plan = v.plan;
+					});
+					frm.refresh_field("subscription_plans");
+				}
+			}
+		});
+	}
+});
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json
index e21afa4..4148dce 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.json
+++ b/erpnext/accounts/doctype/payment_request/payment_request.json
@@ -15,6 +15,7 @@
  "fields": [
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -42,11 +43,12 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 1, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -73,11 +75,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -106,11 +109,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -137,11 +141,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -168,11 +173,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -198,11 +204,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -230,11 +237,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -262,11 +270,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -295,11 +304,44 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 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": "is_a_subscription", 
+   "fieldtype": "Check", 
+   "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": "Is a Subscription", 
+   "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, 
@@ -328,11 +370,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -360,11 +403,79 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "collapsible_depends_on": "", 
+   "columns": 0, 
+   "depends_on": "eval:doc.is_a_subscription", 
+   "fieldname": "subscription_section", 
+   "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 Section", 
+   "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_plans", 
+   "fieldtype": "Table", 
+   "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 Plans", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Subscription Plan Detail", 
+   "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, 
@@ -390,11 +501,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -421,11 +533,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -453,11 +566,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -484,11 +598,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -515,11 +630,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
@@ -547,16 +663,17 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 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": "payment_gateway_account.payment_gateway",
+   "fetch_from": "payment_gateway_account.payment_gateway", 
    "fieldname": "payment_gateway", 
    "fieldtype": "Read Only", 
    "hidden": 0, 
@@ -580,16 +697,17 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 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": "payment_gateway_account.payment_account",
+   "fetch_from": "payment_gateway_account.payment_account", 
    "fieldname": "payment_account", 
    "fieldtype": "Read Only", 
    "hidden": 0, 
@@ -613,11 +731,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -644,11 +763,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -676,11 +796,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -708,11 +829,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -739,7 +861,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }
  ], 
@@ -753,7 +875,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-05-16 22:43:28.136835",
+ "modified": "2018-06-20 17:06:43.850174", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Payment Request", 
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index a633cc3..c58b185 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -12,12 +12,15 @@
 from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, get_company_defaults
 from frappe.integrations.utils import get_payment_gateway_controller
 from frappe.utils.background_jobs import enqueue
+from erpnext.erpnext_integrations.stripe_integration import create_stripe_subscription
+from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
 
 class PaymentRequest(Document):
 	def validate(self):
 		self.validate_reference_document()
 		self.validate_payment_request()
 		self.validate_currency()
+		self.validate_subscription_details()
 
 	def validate_reference_document(self):
 		if not self.reference_doctype or not self.reference_name:
@@ -33,6 +36,21 @@
 		if self.payment_account and ref_doc.currency != frappe.db.get_value("Account", self.payment_account, "account_currency"):
 			frappe.throw(_("Transaction currency must be same as Payment Gateway currency"))
 
+	def validate_subscription_details(self):
+		if self.is_a_subscription:
+			amount = 0
+			for subscription_plan in self.subscription_plans:
+				payment_gateway = frappe.db.get_value("Subscription Plan", subscription_plan.plan, "payment_gateway")
+				if payment_gateway != self.payment_gateway_account:
+					frappe.throw(_('The payment gateway account in plan {0} is different from the payment gateway account in this payment request'.format(subscription_plan.name)))
+
+				rate = get_plan_rate(subscription_plan.plan, quantity=subscription_plan.qty)
+
+				amount += rate
+
+			if amount != self.grand_total:
+				frappe.msgprint(_("The amount of {0} set in this payment request is different from the calculated amount of all payment plans: {1}. Make sure this is correct before submitting the document.".format(self.grand_total, amount)))
+
 	def on_submit(self):
 		send_mail = self.payment_gateway_validation()
 		ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
@@ -235,6 +253,10 @@
 
 			return redirect_to
 
+	def create_subscription(self, payment_provider, gateway_controller, data):
+		if payment_provider == "stripe":
+			return create_stripe_subscription(gateway_controller, data)
+
 @frappe.whitelist(allow_guest=True)
 def make_payment_request(**args):
 	"""Make payment request"""
@@ -375,3 +397,14 @@
 
 <p>{{ _("Thank you for your business!") }}</p>
 """, dict(doc=doc, payment_url = '{{ payment_url }}'))
+
+@frappe.whitelist()
+def get_subscription_details(reference_doctype, reference_name):
+	if reference_doctype == "Sales Invoice":
+		subscriptions = frappe.db.sql("""SELECT parent as sub_name FROM `tabSubscription Invoice` WHERE invoice=%s""",reference_name, as_dict=1)
+		subscription_plans = []
+		for subscription in subscriptions:
+			plans = frappe.get_doc("Subscription", subscription.sub_name).plans
+			for plan in plans:
+				subscription_plans.append(plan)
+		return subscription_plans
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.js b/erpnext/accounts/doctype/payment_request/test_payment_request.js
new file mode 100644
index 0000000..070b595
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_request/test_payment_request.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Payment Request", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Payment Request
+		() => frappe.tests.make('Payment Request', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json
index 5d64d9a..a58ac3e 100644
--- a/erpnext/accounts/doctype/subscription/subscription.json
+++ b/erpnext/accounts/doctype/subscription/subscription.json
@@ -118,39 +118,6 @@
    "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, 
@@ -847,7 +814,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-07-11 19:34:44.582203", 
+ "modified": "2018-07-13 15:18:49.016010", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Subscription", 
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 72f86f2..fe39161 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -8,6 +8,7 @@
 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.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
 
 
 class Subscription(Document):
@@ -244,7 +245,6 @@
 		# for that reason
 		items_list = self.get_items_from_plans(self.plans, prorate)
 		for item in items_list:
-			item['qty'] = self.quantity
 			invoice.append('items',	item)
 
 		# Taxes
@@ -272,6 +272,10 @@
 			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 +287,25 @@
 		"""
 		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 = []
+		customer = self.get_customer(self.subscriber)
+		for plan in plans:
+			item_code = frappe.db.get_value("Subscription Plan", plan.plan, "item")
+			if not prorate:
+				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': get_plan_rate(plan.plan, plan.qty, customer)})
+			else:
+				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': (get_plan_rate(plan.plan, plan.qty, customer) * 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 +330,7 @@
 		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 +364,7 @@
 		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()
 
diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py
index 47efa45..c42b8e8 100644
--- a/erpnext/accounts/doctype/subscription/test_subscription.py
+++ b/erpnext/accounts/doctype/subscription/test_subscription.py
@@ -15,6 +15,7 @@
 		plan = frappe.new_doc('Subscription Plan')
 		plan.plan_name = '_Test Plan Name'
 		plan.item = '_Test Non Stock Item'
+		plan.price_determination = "Fixed rate"
 		plan.cost = 900
 		plan.billing_interval = 'Month'
 		plan.billing_interval_count = 1
@@ -24,6 +25,7 @@
 		plan = frappe.new_doc('Subscription Plan')
 		plan.plan_name = '_Test Plan Name 2'
 		plan.item = '_Test Non Stock Item'
+		plan.price_determination = "Fixed rate"
 		plan.cost = 1999
 		plan.billing_interval = 'Month'
 		plan.billing_interval_count = 1
@@ -33,6 +35,7 @@
 		plan = frappe.new_doc('Subscription Plan')
 		plan.plan_name = '_Test Plan Name 3'
 		plan.item = '_Test Non Stock Item'
+		plan.price_determination = "Fixed rate"
 		plan.cost = 1999
 		plan.billing_interval = 'Day'
 		plan.billing_interval_count = 14
@@ -58,7 +61,7 @@
 		subscription.subscriber = '_Test Customer'
 		subscription.trial_period_start = nowdate()
 		subscription.trial_period_end = add_days(nowdate(), 30)
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 
 		self.assertEqual(subscription.trial_period_start, nowdate())
@@ -73,7 +76,7 @@
 	def test_create_subscription_without_trial_with_correct_period(self):
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 
 		self.assertEqual(subscription.trial_period_start, None)
@@ -91,7 +94,7 @@
 		subscription.subscriber = '_Test Customer'
 		subscription.trial_period_end = nowdate()
 		subscription.trial_period_start = add_days(nowdate(), 30)
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 
 		self.assertRaises(frappe.ValidationError, subscription.save)
 		subscription.delete()
@@ -101,8 +104,8 @@
 		subscription.subscriber = '_Test Customer'
 		subscription.trial_period_end = nowdate()
 		subscription.trial_period_start = add_days(nowdate(), 30)
-		subscription.append('plans', {'plan': '_Test Plan Name'})
-		subscription.append('plans', {'plan': '_Test Plan Name 3'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
+		subscription.append('plans', {'plan': '_Test Plan Name 3', 'qty': 1})
 
 		self.assertRaises(frappe.ValidationError, subscription.save)
 		subscription.delete()
@@ -111,7 +114,7 @@
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
 		subscription.start = '2018-01-01'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.insert()
 
 		self.assertEqual(subscription.status, 'Active')
@@ -127,7 +130,7 @@
 	def test_status_goes_back_to_active_after_invoice_is_paid(self):
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.start = '2018-01-01'
 		subscription.insert()
 		subscription.process()	# generate first invoice
@@ -144,7 +147,7 @@
 		subscription.process()
 
 		self.assertEqual(subscription.status, 'Active')
-		self.assertEqual(subscription.current_invoice_start, nowdate())
+		self.assertEqual(subscription.current_invoice_start, add_months(subscription.start, 1))
 		self.assertEqual(len(subscription.invoices), 1)
 
 		subscription.delete()
@@ -157,7 +160,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.start = '2018-01-01'
 		subscription.insert()
 		subscription.process()		# generate first invoice
@@ -180,7 +183,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.start = '2018-01-01'
 		subscription.insert()
 		subscription.process()		# generate first invoice
@@ -198,7 +201,7 @@
 	def test_subscription_invoice_days_until_due(self):
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.days_until_due = 10
 		subscription.start = add_months(nowdate(), -1)
 		subscription.insert()
@@ -216,7 +219,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.start = '2018-01-01'
 		subscription.insert()
 		subscription.process()		# generate first invoice
@@ -240,7 +243,7 @@
 	def test_subscription_remains_active_during_invoice_period(self):
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.process()		# no changes expected
 
@@ -266,7 +269,7 @@
 	def test_subscription_cancelation(self):
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.cancel_subscription()
 
@@ -282,7 +285,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 
 		self.assertEqual(subscription.status, 'Active')
@@ -317,7 +320,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.cancel_subscription()
 		invoice = subscription.get_current_invoice()
@@ -337,7 +340,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.cancel_subscription()
 
@@ -361,7 +364,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.start = '2018-01-01'
 		subscription.insert()
 		subscription.process()	# generate first invoice
@@ -395,7 +398,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.start = '2018-01-01'
 		subscription.insert()
 		subscription.process()		# generate first invoice
@@ -432,7 +435,7 @@
 
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.start = '2018-01-01'
 		subscription.insert()
 		subscription.process()		# generate first invoice
@@ -450,8 +453,9 @@
 		subscription.process()
 		self.assertEqual(subscription.status, 'Active')
 
+		# A new invoice is generated
 		subscription.process()
-		self.assertEqual(subscription.status, 'Active')
+		self.assertEqual(subscription.status, 'Past Due Date')
 
 		settings.cancel_after_grace = default_grace_period_action
 		settings.save()
@@ -460,7 +464,7 @@
 	def test_restart_active_subscription(self):
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 
 		self.assertRaises(frappe.ValidationError, subscription.restart_subscription)
@@ -471,7 +475,7 @@
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
 		subscription.additional_discount_percentage = 10
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.cancel_subscription()
 
@@ -486,7 +490,7 @@
 		subscription = frappe.new_doc('Subscription')
 		subscription.subscriber = '_Test Customer'
 		subscription.additional_discount_amount = 11
-		subscription.append('plans', {'plan': '_Test Plan Name'})
+		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.cancel_subscription()
 
diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.js b/erpnext/accounts/doctype/subscription_plan/subscription_plan.js
index f5ea804..aaa32cf 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.js
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.js
@@ -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');
+	}
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
index ab58e7c..453521d 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
@@ -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
+   "unique": 1
   }, 
   {
    "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
-  }, 
-  {
-   "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, 
@@ -204,6 +434,134 @@
    "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": "payment_plan_section", 
+   "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": "Payment Plan", 
+   "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": "payment_plan_id", 
+   "fieldtype": "Data", 
+   "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": "Payment Plan", 
+   "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": "column_break_16", 
+   "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": "payment_gateway", 
+   "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": "Payment Gateway", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Payment Gateway Account", 
+   "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
   }
  ], 
  "has_web_view": 0, 
@@ -216,7 +574,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-02-27 09:12:58.330140", 
+ "modified": "2018-06-20 16:59:54.082358", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Subscription Plan", 
@@ -225,7 +583,6 @@
  "permissions": [
   {
    "amend": 0, 
-   "apply_user_permissions": 0, 
    "cancel": 0, 
    "create": 1, 
    "delete": 1, 
@@ -244,7 +601,7 @@
    "write": 1
   }
  ], 
- "quick_entry": 1, 
+ "quick_entry": 0, 
  "read_only": 0, 
  "read_only_onload": 0, 
  "show_name_in_global_search": 0, 
diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
index 4b8c8fc..d3fef60 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
@@ -5,6 +5,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe.model.document import Document
+from erpnext.utilities.product import get_price
 
 class SubscriptionPlan(Document):
 	def validate(self):
@@ -13,3 +14,21 @@
 	def validate_interval_count(self):
 		if self.billing_interval_count < 1:
 			frappe.throw('Billing Interval Count cannot be less than 1')
+
+@frappe.whitelist()
+def get_plan_rate(plan, quantity=1, customer=None):
+	plan = frappe.get_doc("Subscription Plan", plan)
+	if plan.price_determination == "Fixed rate":
+		return plan.cost
+
+	elif plan.price_determination == "Based on price list":
+		if customer:
+			customer_group = frappe.db.get_value("Customer", customer, "customer_group")
+		else:
+			customer_group = None
+		
+		price = get_price(item_code=plan.item, price_list=plan.price_list, customer_group=customer_group, company=None, qty=quantity)
+		if not price:
+			return 0
+		else:
+			return price.price_list_rate
diff --git a/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json b/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json
index c112923..ca54a16 100644
--- a/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json
+++ b/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json
@@ -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", 
diff --git a/erpnext/config/erpnext_integrations.py b/erpnext/config/integrations.py
similarity index 100%
rename from erpnext/config/erpnext_integrations.py
rename to erpnext/config/integrations.py
diff --git a/erpnext/erpnext_integrations/stripe_integration.py b/erpnext/erpnext_integrations/stripe_integration.py
new file mode 100644
index 0000000..a35ca28
--- /dev/null
+++ b/erpnext/erpnext_integrations/stripe_integration.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.integrations.utils import create_request_log
+import stripe
+
+def create_stripe_subscription(gateway_controller, data):
+	stripe_settings = frappe.get_doc("Stripe Settings", gateway_controller)
+	stripe_settings.data = frappe._dict(data)
+
+	stripe.api_key = stripe_settings.get_password(fieldname="secret_key", raise_exception=False)
+	stripe.default_http_client = stripe.http_client.RequestsClient()
+
+	try:
+		stripe_settings.integration_request = create_request_log(stripe_settings.data, "Host", "Stripe")
+		stripe_settings.payment_plans = frappe.get_doc("Payment Request", stripe_settings.data.reference_docname).subscription_plans
+		return create_subscription_on_stripe(stripe_settings)
+
+	except Exception:
+		frappe.log_error(frappe.get_traceback())
+		return{
+			"redirect_to": frappe.redirect_to_message(_('Server Error'), _("It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.")),
+			"status": 401
+		}
+
+
+def create_subscription_on_stripe(stripe_settings):
+		items = []
+		for payment_plan in stripe_settings.payment_plans:
+			plan = frappe.db.get_value("Subscription Plan", payment_plan.plan, "payment_plan_id")
+			items.append({"plan": plan, "quantity": payment_plan.qty})
+
+		try:
+			customer = stripe.Customer.create(description=stripe_settings.data.payer_name, email=stripe_settings.data.payer_email, source=stripe_settings.data.stripe_token_id)
+			subscription = stripe.Subscription.create(customer=customer, items=items)
+
+			if subscription.status == "active":
+				stripe_settings.integration_request.db_set('status', 'Completed', update_modified=False)
+				stripe_settings.flags.status_changed_to = "Completed"
+
+			else:
+				stripe_settings.integration_request.db_set('status', 'Failed', update_modified=False)
+				frappe.log_error('Subscription N°: ' + subscription.id, 'Stripe Payment not completed')
+
+		except Exception:
+			stripe_settings.integration_request.db_set('status', 'Failed', update_modified=False)
+			frappe.log_error(frappe.get_traceback())
+
+		return stripe_settings.finalize_request()
\ No newline at end of file
diff --git a/erpnext/templates/pages/integrations/gocardless_checkout.html b/erpnext/templates/pages/integrations/gocardless_checkout.html
index eb124ca..bbe5640 100644
--- a/erpnext/templates/pages/integrations/gocardless_checkout.html
+++ b/erpnext/templates/pages/integrations/gocardless_checkout.html
@@ -13,4 +13,4 @@
 	<span class='gocardless-loading'>{{ _("Loading Payment System") }}</span>
 </p>
 
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/templates/pages/integrations/gocardless_checkout.py b/erpnext/templates/pages/integrations/gocardless_checkout.py
index 3c2466e..2ba7001 100644
--- a/erpnext/templates/pages/integrations/gocardless_checkout.py
+++ b/erpnext/templates/pages/integrations/gocardless_checkout.py
@@ -73,4 +73,4 @@
 
 	except Exception as e:
 		frappe.log_error(e, "GoCardless Payment Error")
-		return {"redirect_to": '/integrations/payment-failed'}
+		return {"redirect_to": '/integrations/payment-failed'}
\ No newline at end of file
diff --git a/erpnext/templates/pages/integrations/gocardless_confirmation.html b/erpnext/templates/pages/integrations/gocardless_confirmation.html
index 1baf23b..1567487 100644
--- a/erpnext/templates/pages/integrations/gocardless_confirmation.html
+++ b/erpnext/templates/pages/integrations/gocardless_confirmation.html
@@ -13,4 +13,4 @@
 	<span class='gocardless-loading'>{{ _("Payment Confirmation") }}</span>
 </p>
 
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/templates/pages/integrations/gocardless_confirmation.py b/erpnext/templates/pages/integrations/gocardless_confirmation.py
index fc564c3..069d900 100644
--- a/erpnext/templates/pages/integrations/gocardless_confirmation.py
+++ b/erpnext/templates/pages/integrations/gocardless_confirmation.py
@@ -82,4 +82,4 @@
 			}).insert(ignore_permissions=True)
 
 		except Exception:
-			frappe.log_error(frappe.get_traceback())
+			frappe.log_error(frappe.get_traceback())
\ No newline at end of file