Merge pull request #22796 from anupamvs/variance-report-fix

fix: Target variance report signs
diff --git a/erpnext/communication/doctype/call_log/call_log.json b/erpnext/communication/doctype/call_log/call_log.json
index cfc08eb..31e79f1 100644
--- a/erpnext/communication/doctype/call_log/call_log.json
+++ b/erpnext/communication/doctype/call_log/call_log.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "field:id",
  "creation": "2019-06-05 12:07:02.634534",
  "doctype": "DocType",
@@ -14,6 +15,7 @@
   "contact",
   "contact_name",
   "column_break_10",
+  "customer",
   "lead",
   "lead_name",
   "section_break_5",
@@ -28,7 +30,8 @@
   },
   {
    "fieldname": "section_break_5",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Call Details"
   },
   {
    "fieldname": "id",
@@ -125,10 +128,19 @@
    "in_list_view": 1,
    "label": "Lead Name",
    "read_only": 1
+  },
+  {
+   "fieldname": "customer",
+   "fieldtype": "Link",
+   "label": "Customer",
+   "options": "Customer",
+   "read_only": 1
   }
  ],
  "in_create": 1,
- "modified": "2019-08-06 05:46:53.144683",
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2020-08-25 17:08:34.085731",
  "modified_by": "Administrator",
  "module": "Communication",
  "name": "Call Log",
diff --git a/erpnext/communication/doctype/call_log/call_log.py b/erpnext/communication/doctype/call_log/call_log.py
index 5fe3c4e..b31b757 100644
--- a/erpnext/communication/doctype/call_log/call_log.py
+++ b/erpnext/communication/doctype/call_log/call_log.py
@@ -16,6 +16,9 @@
 		self.contact = get_contact_with_phone_number(number)
 		self.lead = get_lead_with_phone_number(number)
 
+		contact = frappe.get_doc("Contact", self.contact)
+		self.customer = contact.get_link_for("Customer")
+
 	def after_insert(self):
 		self.trigger_call_popup()
 
diff --git a/erpnext/erpnext_integrations/desk_page/erpnext_integrations/erpnext_integrations.json b/erpnext/erpnext_integrations/desk_page/erpnext_integrations/erpnext_integrations.json
new file mode 100644
index 0000000..8dcc77d
--- /dev/null
+++ b/erpnext/erpnext_integrations/desk_page/erpnext_integrations/erpnext_integrations.json
@@ -0,0 +1,40 @@
+{
+ "cards": [
+  {
+   "hidden": 0,
+   "label": "Marketplace",
+   "links": "[\n    {\n        \"description\": \"Woocommerce marketplace settings\",\n        \"label\": \"Woocommerce Settings\",\n        \"name\": \"Woocommerce Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Amazon MWS settings\",\n        \"label\": \"Amazon MWS Settings\",\n        \"name\": \"Amazon MWS Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Shopify settings\",\n        \"label\": \"Shopify Settings\",\n        \"name\": \"Shopify Settings\",\n        \"type\": \"doctype\"\n    }\n]"
+  },
+  {
+   "hidden": 0,
+   "label": "Payments",
+   "links": "[\n    {\n        \"description\": \"GoCardless payment gateway settings\",\n        \"label\": \"GoCardless Settings\",\n        \"name\": \"GoCardless Settings\",\n        \"type\": \"doctype\"\n    }\n]"
+  },
+  {
+   "hidden": 0,
+   "label": "Settings",
+   "links": "[\n    {\n        \"description\": \"Plaid settings\",\n        \"label\": \"Plaid Settings\",\n        \"name\": \"Plaid Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Exotel settings\",\n        \"label\": \"Exotel Settings\",\n        \"name\": \"Exotel Settings\",\n        \"type\": \"doctype\"\n    }\n]"
+  }
+ ],
+ "category": "Modules",
+ "charts": [],
+ "creation": "2020-08-20 19:30:48.138801",
+ "developer_mode_only": 0,
+ "disable_user_customization": 0,
+ "docstatus": 0,
+ "doctype": "Desk Page",
+ "extends": "Integrations",
+ "extends_another_page": 1,
+ "hide_custom": 1,
+ "idx": 0,
+ "is_standard": 1,
+ "label": "ERPNext Integrations",
+ "modified": "2020-08-23 16:30:51.494655",
+ "modified_by": "Administrator",
+ "module": "ERPNext Integrations",
+ "name": "ERPNext Integrations",
+ "owner": "Administrator",
+ "pin_to_bottom": 0,
+ "pin_to_top": 0,
+ "shortcuts": []
+}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/member/member.json b/erpnext/non_profit/doctype/member/member.json
index bb73a84..77cdb94 100644
--- a/erpnext/non_profit/doctype/member/member.json
+++ b/erpnext/non_profit/doctype/member/member.json
@@ -133,7 +133,8 @@
   {
    "fieldname": "email_id",
    "fieldtype": "Data",
-   "label": "Email Address"
+   "label": "Email Address",
+   "options": "Email"
   },
   {
    "fieldname": "subscription_id",
@@ -176,7 +177,7 @@
  ],
  "image_field": "image",
  "links": [],
- "modified": "2020-04-07 14:20:33.215700",
+ "modified": "2020-08-06 10:06:01.153564",
  "modified_by": "Administrator",
  "module": "Non Profit",
  "name": "Member",
diff --git a/erpnext/non_profit/doctype/member/member.py b/erpnext/non_profit/doctype/member/member.py
index c52082c..797736a 100644
--- a/erpnext/non_profit/doctype/member/member.py
+++ b/erpnext/non_profit/doctype/member/member.py
@@ -9,6 +9,7 @@
 from frappe.contacts.address_and_contact import load_address_and_contact
 from frappe.utils import cint
 from frappe.integrations.utils import get_payment_gateway_controller
+from erpnext.non_profit.doctype.membership_type.membership_type import get_membership_type
 
 class Member(Document):
 	def onload(self):
@@ -74,19 +75,23 @@
 		return create_member(user_details)
 
 def create_member(user_details):
+	user_details = frappe._dict(user_details)
 	member = frappe.new_doc("Member")
 	member.update({
 		"member_name": user_details.fullname,
 		"email_id": user_details.email,
-		"pan_number": user_details.pan,
+		"pan_number": user_details.pan or None,
 		"membership_type": user_details.plan_id,
-		"customer": create_customer(user_details)
+		"subscription_id": user_details.subscription_id or None
 	})
 
 	member.insert(ignore_permissions=True)
+	member.customer = create_customer(user_details, member.name)
+	member.save(ignore_permissions=True)
+
 	return member
 
-def create_customer(user_details):
+def create_customer(user_details, member=None):
 	customer = frappe.new_doc("Customer")
 	customer.customer_name = user_details.fullname
 	customer.customer_type = "Individual"
@@ -107,7 +112,13 @@
 			"link_name": customer.name
 		})
 
-		contact.save()
+		if member:
+			contact.append("links", {
+				"link_doctype": "Member",
+				"link_name": member
+			})
+
+		contact.save(ignore_permissions=True)
 
 	except frappe.DuplicateEntryError:
 		return customer.name
@@ -139,12 +150,31 @@
 
 	user_details = frappe._dict(user_details)
 	member = get_or_create_member(user_details)
-	if not member:
-		member = create_member(user_details)
 
 	subscription = member.setup_subscription()
 
 	member.subscription_id = subscription.get('subscription_id')
 	member.save(ignore_permissions=True)
 
-	return subscription
\ No newline at end of file
+	return subscription
+
+@frappe.whitelist(allow_guest=True)
+def register_member(fullname, email, rzpay_plan_id, subscription_id, pan=None, mobile=None):
+	plan = get_membership_type(rzpay_plan_id)
+	if not plan:
+		raise frappe.DoesNotExistError
+
+	member = frappe.db.exists("Member", {'email': email, 'subscription_id': subscription_id })
+	if member:
+		return member
+	else:
+		member = create_member(dict(
+			fullname=fullname,
+			email=email,
+			plan_id=plan,
+			subscription_id=subscription_id,
+			pan=pan,
+			mobile=mobile
+		))
+
+		return member.name
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership/membership.js b/erpnext/non_profit/doctype/membership/membership.js
index 554549a..ee8a8c0 100644
--- a/erpnext/non_profit/doctype/membership/membership.js
+++ b/erpnext/non_profit/doctype/membership/membership.js
@@ -8,6 +8,24 @@
 		})
 	},
 
+	refresh: function(frm) {
+		!frm.doc.invoice && frm.add_custom_button("Generate Invoice", () => {
+			frm.call("generate_invoice", {
+				save: true
+			}).then(() => {
+				frm.reload_doc();
+			});
+		});
+
+		frappe.db.get_single_value("Membership Settings", "send_email").then(val => {
+			if (val) frm.add_custom_button("Send Acknowledgement", () => {
+				frm.call("send_acknowlement").then(() => {
+					frm.reload_doc();
+				});
+			});
+		})
+	},
+
 	onload: function(frm) {
 		frm.add_fetch('membership_type', 'amount', 'amount');
 	}
diff --git a/erpnext/non_profit/doctype/membership/membership.json b/erpnext/non_profit/doctype/membership/membership.json
index 238f4c3..95bb3a5 100644
--- a/erpnext/non_profit/doctype/membership/membership.json
+++ b/erpnext/non_profit/doctype/membership/membership.json
@@ -19,10 +19,10 @@
   "paid",
   "currency",
   "amount",
+  "invoice",
   "razorpay_details_section",
   "subscription_id",
-  "payment_id",
-  "webhook_payload"
+  "payment_id"
  ],
  "fields": [
   {
@@ -118,17 +118,15 @@
    "read_only": 1
   },
   {
-   "fieldname": "webhook_payload",
-   "fieldtype": "Code",
-   "hidden": 1,
-   "label": "Webhook Payload",
-   "options": "JSON",
-   "read_only": 1
+   "fieldname": "invoice",
+   "fieldtype": "Link",
+   "label": "Invoice",
+   "options": "Sales Invoice"
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2020-07-27 14:28:11.532696",
+ "modified": "2020-07-31 13:57:02.328995",
  "modified_by": "Administrator",
  "module": "Non Profit",
  "name": "Membership",
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index 729e111..f058004 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -10,6 +10,7 @@
 from frappe.model.document import Document
 from frappe.email import sendmail_to_system_managers
 from frappe.utils import add_days, add_years, nowdate, getdate, add_months, get_link_to_form
+from erpnext.non_profit.doctype.member.member import create_member
 from frappe import _
 import erpnext
 
@@ -57,11 +58,95 @@
 			self.load_from_db()
 			self.db_set('paid', 1)
 
+	def generate_invoice(self, save=True):
+		if not (self.paid or self.currency or self.amount):
+			frappe.throw(_("The payment for this membership is not paid. To generate invoice fill the payment details"))
+
+		if self.invoice:
+			frappe.throw(_("An invoice is already linked to this document"))
+
+		member = frappe.get_doc("Member", self.member)
+		plan = frappe.get_doc("Membership Type", self.membership_type)
+		settings = frappe.get_doc("Membership Settings")
+
+		if not member.customer:
+			frappe.throw(_("No customer linked to member {}", [member.name]))
+
+		if not settings.debit_account:
+			frappe.throw(_("You need to set <b>Debit Account</b> in Membership Settings"))
+
+		if not settings.company:
+			frappe.throw(_("You need to set <b>Default Company</b> for invoicing in Membership Settings"))
+
+		invoice = make_invoice(self, member, plan, settings)
+		self.invoice = invoice.name
+
+		if save:
+			self.save()
+
+		return invoice
+
+	def send_acknowlement(self):
+		settings = frappe.get_doc("Membership Settings")
+		if not settings.send_email:
+			frappe.throw(_("You need to enable <b>Send Acknowledge Email</b> in Membership Settings"))
+
+		member = frappe.get_doc("Member", self.member)
+		plan = frappe.get_doc("Membership Type", self.membership_type)
+		email = member.email_id if member.email_id else member.email
+		attachments = [frappe.attach_print("Membership", self.name, print_format=settings.membership_print_format)]
+
+		if self.invoice and settings.send_invoice:
+			attachments.append(frappe.attach_print("Sales Invoice", self.invoice, print_format=settings.inv_print_format))
+
+		email_template = frappe.get_doc("Email Template", settings.email_template)
+		context = { "doc": self, "member": member}
+
+		email_args = {
+			"recipients": [email],
+			"message": frappe.render_template(email_template.get("response"), context),
+			"subject": frappe.render_template(email_template.get("subject"), context),
+			"attachments": attachments,
+			"reference_doctype": self.doctype,
+			"reference_name": self.name
+		}
+
+		if not frappe.flags.in_test:
+			frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, is_async=True, **email_args)
+		else:
+			frappe.sendmail(**email_args)
+
+	def generate_and_send_invoice(self):
+		invoice = self.generate_invoice(False)
+		self.send_acknowlement()
+
+def make_invoice(membership, member, plan, settings):
+	invoice = frappe.get_doc({
+		'doctype': 'Sales Invoice',
+		'customer': member.customer,
+		'debit_to': settings.debit_account,
+		'currency': membership.currency,
+		'is_pos': 0,
+		'items': [
+			{
+				'item_code': plan.linked_item,
+				'rate': membership.amount,
+				'qty': 1
+			}
+		]
+	})
+
+	invoice.insert(ignore_permissions=True)
+	invoice.submit()
+
+	return invoice
+
 def get_member_based_on_subscription(subscription_id, email):
 	members = frappe.get_all("Member", filters={
 					'subscription_id': subscription_id,
 					'email_id': email
 				}, order_by="creation desc")
+
 	try:
 		return frappe.get_doc("Member", members[0]['name'])
 	except:
@@ -77,16 +162,15 @@
 
 	controller.verify_signature(data, signature, key)
 
-
 @frappe.whitelist(allow_guest=True)
 def trigger_razorpay_subscription(*args, **kwargs):
 	data = frappe.request.get_data(as_text=True)
 	try:
 		verify_signature(data)
 	except Exception as e:
-		signature = frappe.request.headers.get('X-Razorpay-Signature')
-		log = "{0} \n\n {1} \n\n {2} \n\n {3}".format(e, frappe.get_traceback(), signature, data)
-		frappe.log_error(e, "Webhook Verification Error")
+		log = frappe.log_error(e, "Webhook Verification Error")
+		notify_failure(log)
+		return { 'status': 'Failed', 'reason': e}
 
 	if isinstance(data, six.string_types):
 		data = json.loads(data)
@@ -99,35 +183,42 @@
 	payment = frappe._dict(payment)
 
 	try:
-		data_json = json.dumps(data, indent=4, sort_keys=True)
+		if not data.event == "subscription.charged":
+			return
+
 		member = get_member_based_on_subscription(subscription.id, payment.email)
-	except Exception as e:
-		error_log = frappe.log_error(frappe.get_traceback() + '\n' + data_json , _("Membership Webhook Failed"))
-		notify_failure(error_log)
-		return { status: 'Failed' }
+		if not member:
+			member = create_member(frappe._dict({
+				'fullname': payment.email,
+				'email': payment.email,
+				'plan_id': get_plan_from_razorpay_id(subscription.plan_id)
+			}))
 
-	if not member:
-		return { status: 'Failed' }
-	try:
-		if data.event == "subscription.activated":
+			member.subscription_id = subscription.id
 			member.customer_id = payment.customer_id
-		elif data.event == "subscription.charged":
-			membership = frappe.new_doc("Membership")
-			membership.update({
-				"member": member.name,
-				"membership_status": "Current",
-				"membership_type": member.membership_type,
-				"currency": "INR",
-				"paid": 1,
-				"payment_id": payment.id,
-				"webhook_payload": data_json,
-				"from_date": datetime.fromtimestamp(subscription.current_start),
-				"to_date": datetime.fromtimestamp(subscription.current_end),
-				"amount": payment.amount / 100 # Convert to rupees from paise
-			})
-			membership.insert(ignore_permissions=True)
+			if subscription.notes and type(subscription.notes) == dict:
+				notes = '\n'.join("{}: {}".format(k, v) for k, v in subscription.notes.items())
+				member.add_comment("Comment", notes)
+			elif subscription.notes and type(subscription.notes) == str:
+				member.add_comment("Comment", subscription.notes)
 
-		# Update these values anyway
+
+		# Update Membership
+		membership = frappe.new_doc("Membership")
+		membership.update({
+			"member": member.name,
+			"membership_status": "Current",
+			"membership_type": member.membership_type,
+			"currency": "INR",
+			"paid": 1,
+			"payment_id": payment.id,
+			"from_date": datetime.fromtimestamp(subscription.current_start),
+			"to_date": datetime.fromtimestamp(subscription.current_end),
+			"amount": payment.amount / 100 # Convert to rupees from paise
+		})
+		membership.insert(ignore_permissions=True)
+
+		# Update membership values
 		member.subscription_start = datetime.fromtimestamp(subscription.start_at)
 		member.subscription_end = datetime.fromtimestamp(subscription.end_at)
 		member.subscription_activated = 1
@@ -135,9 +226,9 @@
 	except Exception as e:
 		log = frappe.log_error(e, "Error creating membership entry")
 		notify_failure(log)
-		return { status: 'Failed' }
+		return { 'status': 'Failed', 'reason': e}
 
-	return { status: 'Success' }
+	return { 'status': 'Success' }
 
 
 def notify_failure(log):
@@ -152,3 +243,11 @@
 		sendmail_to_system_managers("[Important] [ERPNext] Razorpay membership webhook failed , please check.", content)
 	except:
 		pass
+
+def get_plan_from_razorpay_id(plan_id):
+	plan = frappe.get_all("Membership Type", filters={'razorpay_plan_id': plan_id}, order_by="creation desc")
+
+	try:
+		return plan[0]['name']
+	except:
+		return None
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_settings/membership_settings.js b/erpnext/non_profit/doctype/membership_settings/membership_settings.js
index 8c0e3a4..1d89402 100644
--- a/erpnext/non_profit/doctype/membership_settings/membership_settings.js
+++ b/erpnext/non_profit/doctype/membership_settings/membership_settings.js
@@ -10,7 +10,39 @@
 				})
 			});
 		}
+
+		frm.set_query('inv_print_format', function(doc) {
+			return {
+				filters: {
+					"doc_type": "Sales Invoice"
+				}
+			};
+		});
+
+		frm.set_query('membership_print_format', function(doc) {
+			return {
+				filters: {
+					"doc_type": "Membership"
+				}
+			};
+		});
+
+		frm.set_query('debit_account', function(doc) {
+			return {
+				filters: {
+					'account_type': 'Receivable',
+					'is_group': 0,
+					'company': frm.doc.company
+				}
+			};
+		});
+
+		let docs_url = "https://docs.erpnext.com/docs/user/manual/en/non_profit/membership";
+
+		frm.set_intro(__("You can learn more about memberships in the manual. ") + `<a href='${docs_url}'>${__('ERPNext Docs')}</a>`, true);
+
 		frm.trigger("add_generate_button");
+		frm.trigger("add_copy_buttonn");
 	},
 
 	add_generate_button: function(frm) {
@@ -27,4 +59,12 @@
 			});
 		});
 	},
+
+	add_copy_buttonn: function(frm) {
+		if (frm.doc.webhook_secret) {
+			frm.add_custom_button(__("Copy Webhook URL"), () => {
+				frappe.utils.copy_to_clipboard(`https://${frappe.boot.sitename}/api/method/erpnext.non_profit.doctype.membership.membership.trigger_razorpay_subscription`);
+			});
+		}
+	}
 });
diff --git a/erpnext/non_profit/doctype/membership_settings/membership_settings.json b/erpnext/non_profit/doctype/membership_settings/membership_settings.json
index 52b9d01..5b6bab5 100644
--- a/erpnext/non_profit/doctype/membership_settings/membership_settings.json
+++ b/erpnext/non_profit/doctype/membership_settings/membership_settings.json
@@ -9,7 +9,17 @@
   "razorpay_settings_section",
   "billing_cycle",
   "billing_frequency",
-  "webhook_secret"
+  "webhook_secret",
+  "column_break_6",
+  "enable_auto_invoicing",
+  "company",
+  "debit_account",
+  "column_break_9",
+  "send_email",
+  "send_invoice",
+  "membership_print_format",
+  "inv_print_format",
+  "email_template"
  ],
  "fields": [
   {
@@ -41,11 +51,79 @@
    "fieldtype": "Password",
    "label": "Webhook Secret",
    "read_only": 1
+  },
+  {
+   "fieldname": "column_break_6",
+   "fieldtype": "Section Break",
+   "label": "Invoicing"
+  },
+  {
+   "default": "0",
+   "fieldname": "enable_auto_invoicing",
+   "fieldtype": "Check",
+   "label": "Enable Auto Invoicing",
+   "mandatory_depends_on": "eval:doc.send_invoice"
+  },
+  {
+   "depends_on": "eval:doc.enable_auto_invoicing",
+   "fieldname": "debit_account",
+   "fieldtype": "Link",
+   "label": "Debit Account",
+   "mandatory_depends_on": "eval:doc.enable_auto_invoicing",
+   "options": "Account"
+  },
+  {
+   "fieldname": "column_break_9",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:doc.enable_auto_invoicing",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "mandatory_depends_on": "eval:doc.enable_auto_invoicing",
+   "options": "Company"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.enable_auto_invoicing && doc.send_email",
+   "fieldname": "send_invoice",
+   "fieldtype": "Check",
+   "label": "Send Invoice with Email"
+  },
+  {
+   "default": "0",
+   "fieldname": "send_email",
+   "fieldtype": "Check",
+   "label": "Send Membership Acknowledgement"
+  },
+  {
+   "depends_on": "eval: doc.send_invoice",
+   "fieldname": "inv_print_format",
+   "fieldtype": "Link",
+   "label": "Invoice Print Format",
+   "mandatory_depends_on": "eval: doc.send_invoice",
+   "options": "Print Format"
+  },
+  {
+   "depends_on": "eval:doc.send_email",
+   "fieldname": "membership_print_format",
+   "fieldtype": "Link",
+   "label": "Membership Print Format",
+   "options": "Print Format"
+  },
+  {
+   "depends_on": "eval:doc.send_email",
+   "fieldname": "email_template",
+   "fieldtype": "Link",
+   "label": "Email Template",
+   "mandatory_depends_on": "eval:doc.send_email",
+   "options": "Email Template"
   }
  ],
  "issingle": 1,
  "links": [],
- "modified": "2020-05-22 12:38:27.103759",
+ "modified": "2020-08-05 17:26:37.287395",
  "modified_by": "Administrator",
  "module": "Non Profit",
  "name": "Membership Settings",
@@ -60,6 +138,23 @@
    "role": "System Manager",
    "share": 1,
    "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Non Profit Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Non Profit Member",
+   "share": 1
   }
  ],
  "quick_entry": 1,
diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.js b/erpnext/non_profit/doctype/membership_type/membership_type.js
index 226981d..43311a2 100644
--- a/erpnext/non_profit/doctype/membership_type/membership_type.js
+++ b/erpnext/non_profit/doctype/membership_type/membership_type.js
@@ -5,6 +5,10 @@
 	refresh: function(frm) {
 		frappe.db.get_single_value("Membership Settings", "enable_razorpay").then(val => {
 			if (val) frm.set_df_property('razorpay_plan_id', 'hidden', false);
-		})
+		});
+
+		frappe.db.get_single_value("Membership Settings", "enable_auto_invoicing").then(val => {
+			if (val) frm.set_df_property('linked_item', 'hidden', false);
+		});
 	}
 });
diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.json b/erpnext/non_profit/doctype/membership_type/membership_type.json
index 319078f..6ce1ecd 100644
--- a/erpnext/non_profit/doctype/membership_type/membership_type.json
+++ b/erpnext/non_profit/doctype/membership_type/membership_type.json
@@ -8,7 +8,8 @@
  "field_order": [
   "membership_type",
   "amount",
-  "razorpay_plan_id"
+  "razorpay_plan_id",
+  "linked_item"
  ],
  "fields": [
   {
@@ -33,10 +34,17 @@
    "hidden": 1,
    "label": "Razorpay Plan ID",
    "unique": 1
+  },
+  {
+   "fieldname": "linked_item",
+   "fieldtype": "Link",
+   "label": "Linked Item",
+   "options": "Item",
+   "unique": 1
   }
  ],
  "links": [],
- "modified": "2020-03-30 12:54:07.850857",
+ "modified": "2020-08-05 15:21:43.595745",
  "modified_by": "Administrator",
  "module": "Non Profit",
  "name": "Membership Type",
diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.py b/erpnext/non_profit/doctype/membership_type/membership_type.py
index ed6b549..b95b043 100644
--- a/erpnext/non_profit/doctype/membership_type/membership_type.py
+++ b/erpnext/non_profit/doctype/membership_type/membership_type.py
@@ -4,6 +4,10 @@
 
 from __future__ import unicode_literals
 from frappe.model.document import Document
+import frappe
 
 class MembershipType(Document):
 	pass
+
+def get_membership_type(razorpay_id):
+	return frappe.db.exists("Membership Type", {"razorpay_plan_id": razorpay_id})
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index a8648f5..4b9c566 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -722,4 +722,5 @@
 erpnext.patches.v13_0.stock_entry_enhancements
 erpnext.patches.v12_0.update_state_code_for_daman_and_diu
 erpnext.patches.v12_0.rename_lost_reason_detail
+erpnext.patches.v13_0.drop_razorpay_payload_column
 erpnext.patches.v13_0.update_start_end_date_for_old_shift_assignment
diff --git a/erpnext/patches/v13_0/drop_razorpay_payload_column.py b/erpnext/patches/v13_0/drop_razorpay_payload_column.py
new file mode 100644
index 0000000..8980fd0
--- /dev/null
+++ b/erpnext/patches/v13_0/drop_razorpay_payload_column.py
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	if frappe.db.exists("DocType", "Membership"):
+		if 'webhook_payload' in frappe.db.get_table_columns("Membership"):
+			frappe.db.sql("alter table `tabMembership` drop column webhook_payload")
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index a4cc68b..cb76c87 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -503,11 +503,11 @@
 
 					if(!r.exc && r.message) {
 						remove_empty_first_row(frm);
-						for ( var i=0; i< r.message.length; i++ ) {
+						for (var i=0; i< r.message.length; i++) {
 							var d = frm.add_child("items");
 							var item = r.message[i];
-							for ( var key in  item) {
-								if ( !is_null(item[key]) ) {
+							for (var key in  item) {
+								if (!is_null(item[key]) && key !== "doctype") {
 									d[key] = item[key];
 								}
 							}
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 93d4832..911fe51 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -184,10 +184,10 @@
 	def validate_credit_limit_on_change(self):
 		if self.get("__islocal") or not self.credit_limits:
 			return
-		
+
 		past_credit_limits = [d.credit_limit
 			for d in frappe.db.get_all("Customer Credit Limit", filters={'parent': self.name}, fields=["credit_limit"], order_by="company")]
-		
+
 		current_credit_limits = [d.credit_limit for d in sorted(self.credit_limits, key=lambda k: k.company)]
 
 		if past_credit_limits == current_credit_limits:
diff --git a/erpnext/templates/generators/item/item_add_to_cart.html b/erpnext/templates/generators/item/item_add_to_cart.html
index 2a70d8d..40bc0c7 100644
--- a/erpnext/templates/generators/item/item_add_to_cart.html
+++ b/erpnext/templates/generators/item/item_add_to_cart.html
@@ -27,22 +27,25 @@
 			{% endif %}
 		</div>
 		{% endif %}
-		{% if product_info.price and (cart_settings.allow_items_not_in_stock or product_info.in_stock) %}
 		<div class="mt-3">
-			<a href="/cart"
-				class="btn btn-light btn-view-in-cart {% if not product_info.qty %}hidden{% endif %}"
-				role="button"
-			>
-				{{ _("View in Cart") }}
-			</a>
-			<button
-				data-item-code="{{item_code}}"
-				class="btn btn-outline-primary btn-add-to-cart {% if product_info.qty %}hidden{% endif %}"
-			>
-				{{ _("Add to Cart") }}
-			</button>
+			{% if product_info.price and (cart_settings.allow_items_not_in_stock or product_info.in_stock) %}
+				<a href="/cart"
+					class="btn btn-light btn-view-in-cart {% if not product_info.qty %}hidden{% endif %}"
+					role="button"
+				>
+					{{ _("View in Cart") }}
+				</a>
+				<button
+					data-item-code="{{item_code}}"
+					class="btn btn-outline-primary btn-add-to-cart {% if product_info.qty %}hidden{% endif %}"
+				>
+					{{ _("Add to Cart") }}
+				</button>
+			{% endif %}
+			{% if cart_settings.show_contact_us_button %}
+				{% include "templates/generators/item/item_inquiry.html" %}
+			{% endif %}
 		</div>
-		{% endif %}
 	</div>
 </div>
 
diff --git a/erpnext/templates/generators/item/item_configure.html b/erpnext/templates/generators/item/item_configure.html
index b8b0d98..73f9ec9 100644
--- a/erpnext/templates/generators/item/item_configure.html
+++ b/erpnext/templates/generators/item/item_configure.html
@@ -10,14 +10,11 @@
 		{{ _('Configure') }}
 	</button>
 	{% endif %}
-	{% if cart_settings.show_contact_us_button | int %}
-	<button class="btn btn-link btn-inquiry" data-item-code="{{ doc.name }}">
-		{{ _('Contact Us') }}
-	</button>
+	{% if cart_settings.show_contact_us_button %}
+		{% include "templates/generators/item/item_inquiry.html" %}
 	{% endif %}
 </div>
 <script>
 {% include "templates/generators/item/item_configure.js" %}
-{% include "templates/generators/item/item_inquiry.js" %}
 </script>
 {% endif %}
diff --git a/erpnext/templates/generators/item/item_inquiry.html b/erpnext/templates/generators/item/item_inquiry.html
new file mode 100644
index 0000000..83653b6
--- /dev/null
+++ b/erpnext/templates/generators/item/item_inquiry.html
@@ -0,0 +1,11 @@
+{% if shopping_cart and shopping_cart.cart_settings.enabled %}
+{% set cart_settings = shopping_cart.cart_settings %}
+    {% if cart_settings.show_contact_us_button | int %}
+        <button class="btn btn-inquiry btn-primary-light" data-item-code="{{ doc.name }}">
+            {{ _('Contact Us') }}
+        </button>
+	{% endif %}
+<script>
+{% include "templates/generators/item/item_inquiry.js" %}
+</script>
+{% endif %}