Merge pull request #5839 from saurabh6790/payment_request_demo

Payment request demo
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js
index e73da4c..afc3804 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.js
+++ b/erpnext/accounts/doctype/payment_request/payment_request.js
@@ -31,5 +31,21 @@
 			});
 		});
 	}
+	
+	if(!frm.doc.payment_gateway_account && frm.doc.status == "Initiated") {
+		frm.add_custom_button(__('Make Payment Entry'), function(){
+			frappe.call({
+				method: "erpnext.accounts.doctype.payment_request.payment_request.make_payment_entry",
+				args: {"docname": frm.doc.name},
+				freeze: true,
+				callback: function(r){
+					if(!r.exc) {
+						var doc = frappe.model.sync(r.message);
+						frappe.set_route("Form", r.message.doctype, r.message.name);
+					}
+				}
+			});
+		}).addClass("btn-primary");
+	}
 });
 
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json
index eca0ad0..3a3802f 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.json
+++ b/erpnext/accounts/doctype/payment_request/payment_request.json
@@ -3,11 +3,13 @@
  "allow_import": 0, 
  "allow_rename": 0, 
  "autoname": "PR.######", 
+ "beta": 0, 
  "creation": "2015-12-15 22:23:24.745065", 
  "custom": 0, 
  "docstatus": 0, 
  "doctype": "DocType", 
  "document_type": "", 
+ "editable_grid": 0, 
  "fields": [
   {
    "allow_on_submit": 0, 
@@ -156,7 +158,7 @@
    "print_hide_if_no_value": 0, 
    "read_only": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
    "unique": 0
@@ -404,30 +406,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_list_view": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "column_break_16", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
+   "label": "Payment Gateway Details", 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -599,13 +578,14 @@
  "hide_heading": 0, 
  "hide_toolbar": 0, 
  "idx": 0, 
+ "image_view": 0, 
  "in_create": 1, 
  "in_dialog": 0, 
  "is_submittable": 1, 
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2016-05-03 10:31:45.692016", 
+ "modified": "2016-07-21 19:11:57.517964", 
  "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 0c8df02..30d043f 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -13,7 +13,6 @@
 
 class PaymentRequest(Document):
 	def validate(self):
-		self.validate_payment_gateway_account()
 		self.validate_payment_request()
 		self.validate_currency()
 
@@ -24,19 +23,9 @@
 
 	def validate_currency(self):
 		ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
-		if ref_doc.currency != frappe.db.get_value("Account", self.payment_account, "account_currency"):
+		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_payment_gateway_account(self):
-		if not self.payment_gateway:
-			frappe.throw(_("Payment Gateway Account is not configured"))
-
-	def validate_payment_gateway(self):
-		if self.payment_gateway == "PayPal":
-			if not frappe.db.get_value("PayPal Settings", None, "api_username"):
-				if not frappe.conf.paypal_username:
-					frappe.throw(_("PayPal Settings missing"))
-
 	def on_submit(self):
 		send_mail = True
 		self.make_communication_entry()
@@ -45,7 +34,7 @@
 		if hasattr(ref_doc, "order_type") and getattr(ref_doc, "order_type") == "Shopping Cart":
 			send_mail = False
 
-		if send_mail:
+		if send_mail and not self.flags.mute_email:
 			self.send_payment_request()
 			self.send_email()
 
@@ -66,9 +55,13 @@
 			si.submit()
 
 	def send_payment_request(self):
-		self.payment_url = get_url("/api/method/erpnext.accounts.doctype.payment_request.payment_request.generate_payment_request?name={0}".format(self.name))
+		if self.payment_account:
+			self.payment_url = get_url("/api/method/erpnext.accounts.doctype.payment_request.payment_request.generate_payment_request?name={0}".format(self.name))
+		
 		if self.payment_url:
 			self.db_set('payment_url', self.payment_url)
+			
+		if self.payment_url or not self.payment_gateway_account:
 			self.db_set('status', 'Initiated')
 
 	def set_as_paid(self):
@@ -80,7 +73,7 @@
 
 		return payment_entry
 
-	def create_payment_entry(self):
+	def create_payment_entry(self, submit=True):
 		"""create entry"""
 		frappe.flags.ignore_account_permission = True
 
@@ -111,18 +104,18 @@
 				self.reference_name, self.name)
 		})
 
-		company_details = get_company_defaults(ref_doc.company)
 		if payment_entry.difference_amount:
+			company_details = get_company_defaults(ref_doc.company)
+
 			payment_entry.append("deductions", {
 				"account": company_details.exchange_gain_loss_account,
 				"cost_center": company_details.cost_center,
 				"amount": payment_entry.difference_amount
 			})
-		payment_entry.insert(ignore_permissions=True)
-		payment_entry.submit()
 
-		#set status as paid for Payment Request
-		self.db_set('status', 'Paid')
+		if submit:
+			payment_entry.insert(ignore_permissions=True)
+			payment_entry.submit()
 
 		return payment_entry
 
@@ -140,7 +133,8 @@
 			"payment_url": self.payment_url
 		}
 
-		return frappe.render_template(self.message, context)
+		if self.message:
+			return frappe.render_template(self.message, context)
 
 	def set_failed(self):
 		pass
@@ -171,7 +165,7 @@
 
 	ref_doc = frappe.get_doc(args.dt, args.dn)
 
-	gateway_account = get_gateway_details(args)
+	gateway_account = get_gateway_details(args) or frappe._dict()
 
 	grand_total = get_amount(ref_doc, args.dt)
 
@@ -184,20 +178,24 @@
 	else:
 		pr = frappe.new_doc("Payment Request")
 		pr.update({
-			"payment_gateway_account": gateway_account.name,
-			"payment_gateway": gateway_account.payment_gateway,
-			"payment_account": gateway_account.payment_account,
+			"payment_gateway_account": gateway_account.get("name"),
+			"payment_gateway": gateway_account.get("payment_gateway"),
+			"payment_account": gateway_account.get("payment_account"),
 			"currency": ref_doc.currency,
 			"grand_total": grand_total,
 			"email_to": args.recipient_id or "",
 			"subject": "Payment Request for %s"%args.dn,
-			"message": gateway_account.message,
+			"message": gateway_account.get("message") or get_dummy_message(args.use_dummy_message),
 			"reference_doctype": args.dt,
 			"reference_name": args.dn
 		})
 
 		if args.return_doc:
 			return pr
+
+		if args.mute_email:
+			pr.flags.mute_email = True
+
 		if args.submit_doc:
 			pr.insert(ignore_permissions=True)
 			pr.submit()
@@ -239,9 +237,6 @@
 
 	gateway_account = get_payment_gateway_account({"is_default": 1})
 
-	if not gateway_account:
-		frappe.throw(_("Payment Gateway Account is not configured"))
-
 	return gateway_account
 
 def get_payment_gateway_account(args):
@@ -267,3 +262,29 @@
 @frappe.whitelist(allow_guest=True)
 def resend_payment_email(docname):
 	return frappe.get_doc("Payment Request", docname).send_email()
+
+@frappe.whitelist()
+def make_payment_entry(docname):
+	doc = frappe.get_doc("Payment Request", docname)
+	return doc.create_payment_entry(submit=False).as_dict()
+
+def make_status_as_paid(doc, method):
+	for ref in doc.references:
+		payment_request_name = frappe.db.get_value("Payment Request",
+			{"reference_doctype": ref.reference_doctype, "reference_name": ref.reference_name,
+			"docstatus": 1})
+		
+		if payment_request_name:
+			doc = frappe.get_doc("Payment Request", payment_request_name)
+			if doc.status != "Paid":
+				doc.db_set('status', 'Paid')
+
+def get_dummy_message(use_dummy_message=True):
+	return """
+		<p> Hope you are enjoying a service. Please consider bank details for payment </p>
+		<p> Bank Details <p><br>
+		<p> Bank Name : National Bank </p>
+		<p> Account Number : 123456789000872 </p>
+		<p> IFSC code : NB000001 </p>
+		<p> Account Name : Wind Power LLC </p>
+	"""
diff --git a/erpnext/demo/user/accounts.py b/erpnext/demo/user/accounts.py
index e7dceb3..052d456 100644
--- a/erpnext/demo/user/accounts.py
+++ b/erpnext/demo/user/accounts.py
@@ -10,6 +10,8 @@
 from frappe.desk import query_report
 from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry_against_invoice
 from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
+from frappe.utils.make_random import get_random
+from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request, make_payment_entry
 
 def work():
 	frappe.set_user(frappe.db.get_global('demo_accounts_user'))
@@ -46,10 +48,23 @@
 	if random.random() < 0.5:
 		make_payment_entries("Purchase Invoice", "Accounts Payable")
 
+	if random.random() < 0.1:
+		#make payment request against sales invoice
+		sales_invoice_name = get_random("Sales Invoice", filters={"docstatus": 1})
+		if sales_invoice_name:
+			si = frappe.get_doc("Sales Invoice", sales_invoice_name)
+			if si.outstanding_amount > 0:
+				payment_request = make_payment_request(dt="Sales Invoice", dn=si.name, recipient_id=si.contact_email,
+					submit_doc=True, mute_email=True, use_dummy_message=True)
+
+				payment_entry = frappe.get_doc(make_payment_entry(payment_request.name))
+				payment_entry.posting_date = frappe.flags.current_date
+				payment_entry.submit()
+
 def make_payment_entries(ref_doctype, report):
-	outstanding_invoices = list(set([r[3] for r in query_report.run(report, 
+	outstanding_invoices = list(set([r[3] for r in query_report.run(report,
 	{"report_date": frappe.flags.current_date })["result"] if r[2]==ref_doctype]))
-	
+
 	# make Payment Entry
 	for inv in outstanding_invoices[:random.randint(1, 2)]:
 		pe = get_payment_entry(ref_doctype, inv)
@@ -69,4 +84,4 @@
 		jv.cheque_date = frappe.flags.current_date
 		jv.insert()
 		jv.submit()
-		frappe.db.commit()		
\ No newline at end of file
+		frappe.db.commit()
diff --git a/erpnext/demo/user/sales.py b/erpnext/demo/user/sales.py
index 6b36b46..10df143 100644
--- a/erpnext/demo/user/sales.py
+++ b/erpnext/demo/user/sales.py
@@ -4,9 +4,11 @@
 from __future__ import unicode_literals
 
 import frappe, random
+from frappe.utils import flt
 from frappe.utils.make_random import add_random_children, get_random
 from erpnext.setup.utils import get_exchange_rate
 from erpnext.accounts.party import get_party_account_currency
+from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request, make_payment_entry
 
 def work():
 	frappe.set_user(frappe.db.get_global('demo_sales_user_2'))
@@ -34,6 +36,19 @@
 		for i in xrange(random.randint(1,3)):
 			make_sales_order()
 
+	if random.random() < 0.1:
+		#make payment request against Sales Order
+		sales_order_name = get_random("Sales Order", filters={"docstatus": 1})
+		if sales_order_name:
+			so = frappe.get_doc("Sales Order", sales_order_name)
+			if flt(so.per_billed) != 100:
+				payment_request = make_payment_request(dt="Sales Order", dn=so.name, recipient_id=so.contact_email,
+					submit_doc=True, mute_email=True, use_dummy_message=True)
+
+				payment_entry = frappe.get_doc(make_payment_entry(payment_request.name))
+				payment_entry.posting_date = frappe.flags.current_date
+				payment_entry.submit()
+
 def make_opportunity():
 	b = frappe.get_doc({
 		"doctype": "Opportunity",
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index fd188bc..82d23de 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -158,6 +158,9 @@
 
 	"Website Settings": {
 		"validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products"
+	},
+	"Payment Entry": {
+		"on_submit": "erpnext.accounts.doctype.payment_request.payment_request.make_status_as_paid"
 	}
 }