diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 1b933ce2c8..1ba9221b38 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -21,9 +21,11 @@
"in_filter": 0,
"in_list_view": 1,
"label": "Make Accounting Entry For Every Stock Movement",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
+ "print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@@ -43,9 +45,11 @@
"in_filter": 0,
"in_list_view": 1,
"label": "Accounts Frozen Upto",
+ "length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
+ "print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@@ -65,10 +69,12 @@
"in_filter": 0,
"in_list_view": 1,
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
+ "length": 0,
"no_copy": 0,
"options": "Role",
"permlevel": 0,
"print_hide": 0,
+ "print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@@ -88,10 +94,12 @@
"in_filter": 0,
"in_list_view": 1,
"label": "Credit Controller",
+ "length": 0,
"no_copy": 0,
"options": "Role",
"permlevel": 0,
"print_hide": 0,
+ "print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@@ -110,10 +118,12 @@
"in_filter": 0,
"in_list_view": 0,
"label": "Check Supplier Invoice Number Uniqueness",
+ "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,
@@ -131,7 +141,8 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
- "modified": "2015-07-14 00:51:48.095525",
+ "max_attachments": 0,
+ "modified": "2015-12-24 21:42:01.274459",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 670661c01f..7deca523c9 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -508,7 +508,7 @@ class JournalEntry(AccountsController):
d.party_balance = party_balance[(d.party_type, d.party)]
@frappe.whitelist()
-def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
+def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None, account=None):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_bank_cash_account
if mode_of_payment:
account = get_bank_cash_account(mode_of_payment, company)
@@ -516,16 +516,18 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
account.update({"balance": get_balance_on(account.get("account"))})
return account
- if voucher_type=="Bank Entry":
- account = frappe.db.get_value("Company", company, "default_bank_account")
- if not account:
- account = frappe.db.get_value("Account",
- {"company": company, "account_type": "Bank", "is_group": 0})
- elif voucher_type=="Cash Entry":
- account = frappe.db.get_value("Company", company, "default_cash_account")
- if not account:
- account = frappe.db.get_value("Account",
- {"company": company, "account_type": "Cash", "is_group": 0})
+ if not account:
+ if voucher_type=="Bank Entry":
+ account = frappe.db.get_value("Company", company, "default_bank_account")
+ if not account:
+ account = frappe.db.get_value("Account",
+ {"company": company, "account_type": "Bank", "is_group": 0})
+
+ elif voucher_type=="Cash Entry":
+ account = frappe.db.get_value("Company", company, "default_cash_account")
+ if not account:
+ account = frappe.db.get_value("Account",
+ {"company": company, "account_type": "Cash", "is_group": 0})
if account:
account_details = frappe.db.get_value("Account", account,
@@ -538,7 +540,7 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
}
@frappe.whitelist()
-def get_payment_entry_against_order(dt, dn):
+def get_payment_entry_against_order(dt, dn, amount=None, journal_entry=False, bank_account=None):
ref_doc = frappe.get_doc(dt, dn)
if flt(ref_doc.per_billed, 2) > 0:
@@ -556,10 +558,11 @@ def get_payment_entry_against_order(dt, dn):
party_account = get_party_account(party_type, ref_doc.get(party_type.lower()), ref_doc.company)
party_account_currency = get_account_currency(party_account)
- if party_account_currency == ref_doc.company_currency:
- amount = flt(ref_doc.base_grand_total) - flt(ref_doc.advance_paid)
- else:
- amount = flt(ref_doc.grand_total) - flt(ref_doc.advance_paid)
+ if not amount:
+ if party_account_currency == ref_doc.company_currency:
+ amount = flt(ref_doc.base_grand_total) - flt(ref_doc.advance_paid)
+ else:
+ amount = flt(ref_doc.grand_total) - flt(ref_doc.advance_paid)
return get_payment_entry(ref_doc, {
"party_type": party_type,
@@ -569,11 +572,13 @@ def get_payment_entry_against_order(dt, dn):
"amount_field_bank": amount_field_bank,
"amount": amount,
"remarks": 'Advance Payment received against {0} {1}'.format(dt, dn),
- "is_advance": "Yes"
+ "is_advance": "Yes",
+ "bank_account": bank_account,
+ "journal_entry": journal_entry
})
@frappe.whitelist()
-def get_payment_entry_against_invoice(dt, dn):
+def get_payment_entry_against_invoice(dt, dn, amount=None, journal_entry=False, bank_account=None):
ref_doc = frappe.get_doc(dt, dn)
if dt == "Sales Invoice":
party_type = "Customer"
@@ -597,9 +602,11 @@ def get_payment_entry_against_invoice(dt, dn):
"party_account_currency": ref_doc.party_account_currency,
"amount_field_party": amount_field_party,
"amount_field_bank": amount_field_bank,
- "amount": abs(ref_doc.outstanding_amount),
+ "amount": amount if amount else abs(ref_doc.outstanding_amount),
"remarks": 'Payment received against {0} {1}. {2}'.format(dt, dn, ref_doc.remarks),
- "is_advance": "No"
+ "is_advance": "No",
+ "bank_account": bank_account,
+ "journal_entry": journal_entry
})
def get_payment_entry(ref_doc, args):
@@ -607,14 +614,14 @@ def get_payment_entry(ref_doc, args):
exchange_rate = get_exchange_rate(args.get("party_account"), args.get("party_account_currency"),
ref_doc.company, ref_doc.doctype, ref_doc.name)
- jv = frappe.new_doc("Journal Entry")
- jv.update({
+ je = frappe.new_doc("Journal Entry")
+ je.update({
"voucher_type": "Bank Entry",
"company": ref_doc.company,
"remark": args.get("remarks")
})
- party_row = jv.append("accounts", {
+ party_row = je.append("accounts", {
"account": args.get("party_account"),
"party_type": args.get("party_type"),
"party": ref_doc.get(args.get("party_type").lower()),
@@ -631,8 +638,10 @@ def get_payment_entry(ref_doc, args):
"reference_name": ref_doc.name
})
- bank_row = jv.append("accounts")
- bank_account = get_default_bank_cash_account(ref_doc.company, "Bank Entry")
+ bank_row = je.append("accounts")
+
+ #make it bank_details
+ bank_account = get_default_bank_cash_account(ref_doc.company, "Bank Entry", account=args.get("bank_account"))
if bank_account:
bank_row.update(bank_account)
bank_row.exchange_rate = get_exchange_rate(bank_account["account"],
@@ -648,12 +657,12 @@ def get_payment_entry(ref_doc, args):
# set multi currency check
if party_row.account_currency != ref_doc.company_currency \
or (bank_row.account_currency and bank_row.account_currency != ref_doc.company_currency):
- jv.multi_currency = 1
+ je.multi_currency = 1
- jv.set_amounts_in_company_currency()
- jv.set_total_debit_credit()
-
- return jv.as_dict()
+ je.set_amounts_in_company_currency()
+ je.set_total_debit_credit()
+
+ return je if args.get("journal_entry") else je.as_dict()
@frappe.whitelist()
def get_opening_accounts(company):
diff --git a/erpnext/accounts/doctype/payment_gateway/__init__.py b/erpnext/accounts/doctype/payment_gateway/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/accounts/doctype/payment_gateway/payment_gateway.json b/erpnext/accounts/doctype/payment_gateway/payment_gateway.json
new file mode 100644
index 0000000000..9b480665c6
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_gateway/payment_gateway.json
@@ -0,0 +1,118 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "field:gateway",
+ "creation": "2015-12-15 22:26:45.221162",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "gateway",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Gateway",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2015-12-29 12:04:17.371619",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Gateway",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Administrator",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 0,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 0,
+ "read": 1,
+ "report": 0,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
+ "write": 0
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 0,
+ "delete": 0,
+ "email": 0,
+ "export": 0,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 0,
+ "read": 1,
+ "report": 0,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 0,
+ "submit": 0,
+ "write": 0
+ }
+ ],
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_gateway/payment_gateway.py b/erpnext/accounts/doctype/payment_gateway/payment_gateway.py
new file mode 100644
index 0000000000..80799e311b
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_gateway/payment_gateway.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class PaymentGateway(Document):
+ pass
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_gateway/test_payment_gateway.py b/erpnext/accounts/doctype/payment_gateway/test_payment_gateway.py
new file mode 100644
index 0000000000..2faf1a7fb4
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_gateway/test_payment_gateway.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+# test_records = frappe.get_test_records('Payment Gateway')
+
+class TestPaymentGateway(unittest.TestCase):
+ pass
diff --git a/erpnext/accounts/doctype/payment_gateway_account/__init__.py b/erpnext/accounts/doctype/payment_gateway_account/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.js b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.js
new file mode 100644
index 0000000000..c9bdc9b80a
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.js
@@ -0,0 +1,6 @@
+cur_frm.cscript.refresh = function(doc, dt, dn){
+ if(!doc.__islocal){
+ var df = frappe.meta.get_docfield(doc.doctype, "gateway", doc.name);
+ df.read_only = 1;
+ }
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.json b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.json
new file mode 100644
index 0000000000..c3a47724fb
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.json
@@ -0,0 +1,291 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "creation": "2015-12-23 21:31:52.699821",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "gateway_acount_details",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Gateway Acount Details",
+ "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": "is_default",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Is Default",
+ "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": "gateway",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Gateway",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Gateway",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "payment_account",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Payment Account",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "currency",
+ "fieldtype": "Read Only",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Currency",
+ "length": 0,
+ "no_copy": 0,
+ "options": "payment_account.account_currency",
+ "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": "payment_request_message",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Payment Request Message",
+ "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": "message",
+ "fieldtype": "Text Editor",
+ "hidden": 0,
+ "ignore_user_permissions": 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": "payment_url_message",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Payment URL Message",
+ "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": "payment_success_url",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Payment Success URL",
+ "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
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2016-01-11 05:55:41.117089",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Gateway Account",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Administrator",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py
new file mode 100644
index 0000000000..dd971ad5d2
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class PaymentGatewayAccount(Document):
+ def autoname(self):
+ self.name = self.gateway + " - " + self.currency
+
+ def validate(self):
+ self.update_default_payment_gateway()
+ self.set_as_default_if_not_set()
+
+ def update_default_payment_gateway(self):
+ if self.is_default:
+ frappe.db.sql("""update `tabPayment Gateway Account` set is_default = 0
+ where is_default = 1 """)
+
+ def set_as_default_if_not_set(self):
+ if not frappe.db.get_value("Payment Gateway Account", {"is_default": 1, "name": ("!=", self.name)}, "name"):
+ self.is_default = 1
diff --git a/erpnext/accounts/doctype/payment_gateway_account/test_payment_gateway_account.py b/erpnext/accounts/doctype/payment_gateway_account/test_payment_gateway_account.py
new file mode 100644
index 0000000000..84c3bc4a60
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_gateway_account/test_payment_gateway_account.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+# test_records = frappe.get_test_records('Payment Gateway Account')
+
+class TestPaymentGatewayAccount(unittest.TestCase):
+ pass
diff --git a/erpnext/accounts/doctype/payment_request/__init__.py b/erpnext/accounts/doctype/payment_request/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js
new file mode 100644
index 0000000000..b28a889be8
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_request/payment_request.js
@@ -0,0 +1,43 @@
+cur_frm.add_fetch("payment_gateway", "payment_account", "payment_account")
+cur_frm.add_fetch("payment_gateway", "gateway", "gateway")
+cur_frm.add_fetch("payment_gateway", "message", "message")
+cur_frm.add_fetch("payment_gateway", "payment_url_message", "payment_url_message")
+cur_frm.add_fetch("payment_gateway", "payment_success_url", "payment_success_url")
+
+frappe.ui.form.on("Payment Request", "onload", function(frm, dt, dn){
+ if (frm.doc.reference_doctype) {
+ frappe.call({
+ method:"erpnext.accounts.doctype.payment_request.payment_request.get_print_format_list",
+ args: {"ref_doctype": frm.doc.reference_doctype},
+ callback:function(r){
+ set_field_options("print_format", r.message["print_format"])
+ }
+ })
+ }
+})
+
+frappe.ui.form.on("Payment Request", "refresh", function(frm) {
+ frm.add_custom_button(__('Resend Payment Email'), function(){
+ frappe.call({
+ method:"erpnext.accounts.doctype.payment_request.payment_request.resend_payment_email",
+ args: {"docname": frm.doc.name},
+ freeze: true,
+ freeze_message: __("Sending"),
+ callback:function(r){
+ if(!r.exc) {
+ frappe.msgprint(__("Message Sent"))
+ }
+ }
+ })
+ })
+
+ frm.add_custom_button(__("Show Paypal Express Payment"), function() {
+ frappe.route_options = {
+ "Paypal Express Payment.reference_doctype": frm.doc.doctype,
+ "Paypal Express Payment.reference_docname": frm.doc.name
+ };
+
+ frappe.set_route("List", "Paypal Express Payment");
+ });
+})
+
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json
new file mode 100644
index 0000000000..7655b5872e
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_request/payment_request.json
@@ -0,0 +1,678 @@
+{
+ "allow_copy": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "PR.######",
+ "creation": "2015-12-15 22:23:24.745065",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "fields": [
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "payment_details",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Payment Details",
+ "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": "amount",
+ "fieldtype": "Currency",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Amount",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "2",
+ "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": "currency",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Currency",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Currency",
+ "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,
+ "depends_on": "eval:doc.reference_doctype==\"Sales Order\"",
+ "fieldname": "make_sales_invoice",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Make Sales Invoice",
+ "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_5",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 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,
+ "default": "Draft",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Status",
+ "length": 0,
+ "no_copy": 0,
+ "options": "\nDraft\nInitiated\nPaid\nFailed\nCancelled",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 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": "payment_gateway",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 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,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "payment_success_url",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Payment Success URL",
+ "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_9",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 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": "gateway",
+ "fieldtype": "Read Only",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Gateway",
+ "length": 0,
+ "no_copy": 0,
+ "options": "payment_gateway.gateway",
+ "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": "payment_account",
+ "fieldtype": "Read Only",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Payment Account",
+ "length": 0,
+ "no_copy": 0,
+ "options": "payment_gateway.payment_account",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "recipient_and_message",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Recipient and Message",
+ "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,
+ "default": "",
+ "fieldname": "print_format",
+ "fieldtype": "Select",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Print Format",
+ "length": 0,
+ "no_copy": 0,
+ "options": "",
+ "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": "mute_email",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Mute Email",
+ "length": 0,
+ "no_copy": 1,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 1,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "email_to",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Email To",
+ "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": 1,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "subject",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Subject",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "message",
+ "fieldtype": "Text Editor",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Message",
+ "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": "payment_url_message",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Payment URL Message",
+ "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": "payment_url",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "payment_url",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "reference_details",
+ "fieldtype": "Section Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Reference Details",
+ "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": "reference_doctype",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Reference Doctype",
+ "length": 0,
+ "no_copy": 1,
+ "options": "DocType",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 1,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "reference_name",
+ "fieldtype": "Dynamic Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Reference Name",
+ "length": 0,
+ "no_copy": 1,
+ "options": "reference_doctype",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 1,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Amended From",
+ "length": 0,
+ "no_copy": 1,
+ "options": "Payment Request",
+ "permlevel": 0,
+ "print_hide": 1,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ }
+ ],
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "in_create": 0,
+ "in_dialog": 0,
+ "is_submittable": 1,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2016-01-11 05:49:28.342786",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Request",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "apply_user_permissions": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "apply_user_permissions": 0,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Administrator",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "read_only": 0,
+ "read_only_onload": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
new file mode 100644
index 0000000000..23fd5a8952
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -0,0 +1,238 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, 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.model.document import Document
+from frappe.utils import flt, nowdate, get_url, cstr
+from erpnext.accounts.party import get_party_account
+from erpnext.accounts.utils import get_account_currency, get_balance_on
+from erpnext.accounts.doctype.journal_entry.journal_entry import (get_payment_entry_against_invoice,
+get_payment_entry_against_order)
+
+from itertools import chain
+
+class PaymentRequest(Document):
+ def validate(self):
+ self.validate_payment_gateway_account()
+ self.validate_payment_request()
+ self.validate_currency()
+
+ def validate_payment_request(self):
+ if frappe.db.get_value("Payment Request", {"reference_name": self.reference_name,
+ "name": ("!=", self.name), "status": ("not in", ["Initiated", "Paid"]), "docstatus": 1}, "name"):
+ frappe.throw(_("Payment Request already exists {0}".fomart(self.reference_name)))
+
+ 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"):
+ 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.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):
+ if not self.mute_email:
+ self.send_payment_request()
+ self.send_email()
+
+ self.make_communication_entry()
+
+ def on_cancel(self):
+ self.set_as_cancelled()
+
+ def on_update_after_submit(self):
+ pass
+
+ def set_status(self):
+ pass
+
+ def get_payment_url(self):
+ pass
+
+ def make_invoice(self):
+ if self.make_sales_invoice:
+ from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
+ si = make_sales_invoice(self.reference_name, ignore_permissions=True)
+ si = si.insert(ignore_permissions=True)
+ 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_url:
+ frappe.db.set_value(self.doctype, self.name, "status", "Initiated")
+
+ def set_as_paid(self):
+ if frappe.session.user == "Guest":
+ frappe.set_user("Administrator")
+
+ jv = self.create_journal_entry()
+ self.make_invoice()
+
+ return jv
+
+ def create_journal_entry(self):
+ """create entry"""
+ payment_details = {
+ "amount": self.amount,
+ "journal_entry": True,
+ "bank_account": self.payment_account
+ }
+
+ frappe.flags.ignore_account_permission = True
+
+ if self.reference_doctype == "Sales Order":
+ jv = get_payment_entry_against_order(self.reference_doctype, self.reference_name,\
+ amount=self.amount, journal_entry=True, bank_account=self.payment_account)
+
+ if self.reference_doctype == "Sales Invoice":
+ jv = get_payment_entry_against_invoice(self.reference_doctype, self.reference_name,\
+ amount=self.amount, journal_entry=True, bank_account=self.payment_account)
+
+ jv.update({
+ "voucher_type": "Journal Entry",
+ "posting_date": nowdate()
+ })
+ jv.insert(ignore_permissions=True)
+ jv.submit()
+
+ #set status as paid for Payment Request
+ frappe.db.set_value(self.doctype, self.name, "status", "Paid")
+
+ return jv
+
+ def send_email(self):
+ """send email with payment link"""
+ frappe.sendmail(recipients=self.email_to, sender=None, subject=self.subject,
+ message=self.get_message(), attachments=[frappe.attach_print(self.reference_doctype,
+ self.reference_name, file_name=self.reference_name, print_format=self.print_format)])
+
+ def get_message(self):
+ """return message with payment gateway link"""
+ return cstr(self.message) + " {1}".format(self.payment_url, \
+ self.payment_url_message or _(" Click here to pay"))
+
+ def set_failed(self):
+ pass
+
+ def set_as_cancelled(self):
+ frappe.db.set_value(self.doctype, self.name, "status", "Cancelled")
+
+ def make_communication_entry(self):
+ """Make communication entry"""
+ comm = frappe.get_doc({
+ "doctype":"Communication",
+ "subject": self.subject,
+ "content": self.get_message(),
+ "sent_or_received": "Sent",
+ "reference_doctype": self.reference_doctype,
+ "reference_name": self.reference_name
+ })
+ comm.insert(ignore_permissions=True)
+
+ def get_payment_success_url(self):
+ return self.payment_success_url
+
+@frappe.whitelist(allow_guest=True)
+def make_payment_request(**args):
+ """Make payment request"""
+
+ args = frappe._dict(args)
+ ref_doc = frappe.get_doc(args.dt, args.dn)
+ gateway_account = get_gateway_details(args)
+
+ pr = frappe.new_doc("Payment Request")
+ pr.update({
+ "payment_gateway": gateway_account.name,
+ "gateway": gateway_account.gateway,
+ "payment_account": gateway_account.payment_account,
+ "currency": ref_doc.currency,
+ "make_sales_invoice": args.cart or 0,
+ "amount": get_amount(ref_doc, args.dt),
+ "mute_email": args.mute_email or 0,
+ "email_to": args.recipient_id or "",
+ "subject": "Payment Request for %s"%args.dn,
+ "message": gateway_account.message,
+ "payment_url_message": gateway_account.payment_url_message,
+ "payment_success_url": gateway_account.payment_success_url,
+ "reference_doctype": args.dt,
+ "reference_name": args.dn
+ })
+
+ if args.return_doc:
+ return pr
+
+ if args.submit_doc:
+ pr.insert(ignore_permissions=True)
+ pr.submit()
+
+ if args.cart:
+ generate_payment_request(pr.name)
+ frappe.db.commit()
+
+ if not args.cart:
+ return pr
+
+ return pr.as_dict()
+
+def get_amount(ref_doc, dt):
+ """get amount based on doctype"""
+ if dt == "Sales Order":
+ amount = flt(ref_doc.base_grand_total) - flt(ref_doc.advance_paid)
+
+ if dt == "Sales Invoice":
+ amount = abs(ref_doc.outstanding_amount)
+
+ if amount > 0:
+ return amount
+ else:
+ frappe.throw(_("Payment Entry is already created"))
+
+def get_gateway_details(args):
+ """return gateway and payment account of default payment gateway"""
+ if args.payemnt_gateway:
+ gateway_account = frappe.db.get_value("Payment Gateway Account", args.payemnt_gateway,
+ ["name", "gateway", "payment_account", "message", "payment_url_message", "payment_success_url"],
+ as_dict=1)
+
+ gateway_account = frappe.db.get_value("Payment Gateway Account", {"is_default": 1},
+ ["name", "gateway", "payment_account", "message", "payment_url_message", "payment_success_url"],
+ as_dict=1)
+
+ if not gateway_account:
+ frappe.throw(_("Payment Gateway Account is not configured"))
+
+ return gateway_account
+
+@frappe.whitelist()
+def get_print_format_list(ref_doctype):
+ print_format_list = ["Standard"]
+
+ print_format_list.extend([p.name for p in frappe.get_all("Print Format",
+ filters={"doc_type": ref_doctype})])
+
+ return {
+ "print_format": print_format_list
+ }
+
+@frappe.whitelist(allow_guest=True)
+def generate_payment_request(name):
+ payment_url = frappe.get_doc("Payment Request", name).run_method("get_payment_url")
+ if payment_url:
+ frappe.local.response["type"] = "redirect"
+ frappe.local.response["location"] = payment_url
+
+@frappe.whitelist(allow_guest=True)
+def resend_payment_email(docname):
+ return frappe.get_doc("Payment Request", docname).send_email()
+
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_request/payment_request_list.js b/erpnext/accounts/doctype/payment_request/payment_request_list.js
new file mode 100644
index 0000000000..0caf1c2f7f
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_request/payment_request_list.js
@@ -0,0 +1,17 @@
+frappe.listview_settings['Payment Request'] = {
+ add_fields: ["status"],
+ get_indicator: function(doc) {
+ if(doc.status == "Draft") {
+ return [__("Draft"), "darkgrey", "status,=,Draft"];
+ }
+ else if(doc.status == "Initiated") {
+ return [__("Initiated"), "green", "status,=,Initiated"];
+ }
+ else if(doc.status == "Paid") {
+ return [__("Paid"), "blue", "status,=,Paid"];
+ }
+ else if(doc.status == "Cancelled") {
+ return [__("Cancelled"), "orange", "status,=,Cancelled"];
+ }
+ }
+}
diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py
new file mode 100644
index 0000000000..a1e975a984
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
+from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+# test_records = frappe.get_test_records('Payment Request')
+
+test_dependencies = ["Currency Exchange", "Journal Entry", "Contact", "Address"]
+
+payment_gateway = {
+ "doctype": "Payment Gateway",
+ "gateway": "_Test Gateway"
+}
+
+payment_method = [
+ {
+ "doctype": "Payment Gateway Account",
+ "is_default": 1,
+ "gateway": "_Test Gateway",
+ "payment_account": "_Test Bank - _TC",
+ "currency": "INR"
+ },
+ {
+ "doctype": "Payment Gateway Account",
+ "gateway": "_Test Gateway",
+ "payment_account": "_Test Bank - _TC",
+ "currency": "USD"
+ }
+]
+
+class TestPaymentRequest(unittest.TestCase):
+ def setUp(self):
+ if not frappe.db.get_value("Payment Gateway", payment_gateway["gateway"], "name"):
+ frappe.get_doc(payment_gateway).insert(ignore_permissions=True)
+
+ for method in payment_method:
+ if not frappe.db.get_value("Payment Gateway Account", {"gateway": method["gateway"],
+ "currency": method["currency"]}, "name"):
+ frappe.get_doc(method).insert(ignore_permissions=True)
+
+ def test_payment_request_linkings(self):
+ SO_INR = make_sales_order(currency="INR")
+ pr = make_payment_request(dt="Sales Order", dn=SO_INR.name, recipient_id="saurabh@erpnext.com")
+
+ self.assertEquals(pr.reference_doctype, "Sales Order")
+ self.assertEquals(pr.reference_name, SO_INR.name)
+ self.assertEquals(pr.currency, "INR")
+
+ SI_USD = create_sales_invoice(currency="USD", conversion_rate=50)
+ pr = make_payment_request(dt="Sales Invoice", dn=SI_USD.name, recipient_id="saurabh@erpnext.com")
+
+ self.assertEquals(pr.reference_doctype, "Sales Invoice")
+ self.assertEquals(pr.reference_name, SI_USD.name)
+ self.assertEquals(pr.currency, "USD")
+
+ def test_payment_entry(self):
+ SO_INR = make_sales_order(currency="INR")
+ pr = make_payment_request(dt="Sales Order", dn=SO_INR.name, recipient_id="saurabh@erpnext.com",
+ mute_email=1, submit_doc=1)
+ jv = pr.set_as_paid()
+
+ SO_INR = frappe.get_doc("Sales Order", SO_INR.name)
+
+ self.assertEquals(SO_INR.advance_paid, jv.total_debit)
+
+ SI_USD = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
+ currency="USD", conversion_rate=50)
+
+ pr = make_payment_request(dt="Sales Invoice", dn=SI_USD.name, recipient_id="saurabh@erpnext.com",
+ mute_email=1, return_doc=1, payemnt_gateway="_Test Gateway - USD")
+
+ self.assertRaises(frappe.ValidationError, pr.save)
+
+
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 1b541cf063..6b03afa3ee 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -75,6 +75,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
if(doc.outstanding_amount!=0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry).addClass("btn-primary");
+ cur_frm.add_custom_button(__('Make Payment Request'), this.make_payment_request);
}
}
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index e7f2b8ab0e..6f02a54742 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -247,7 +247,7 @@ def update_against_doc(d, jv_obj):
# will work as update after submit
jv_obj.flags.ignore_validate_update_after_submit = True
- jv_obj.save()
+ jv_obj.save(ignore_permissions=True)
def remove_against_link_from_jv(ref_type, ref_no):
linked_jv = frappe.db.sql_list("""select parent from `tabJournal Entry Account`
diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py
index 8a27394509..859764d301 100644
--- a/erpnext/config/accounts.py
+++ b/erpnext/config/accounts.py
@@ -32,6 +32,11 @@ def get_data():
"name": "Supplier",
"description": _("Supplier database.")
},
+ {
+ "type": "doctype",
+ "name": "Payment Request",
+ "description": _("Payment Request")
+ },
{
"type": "page",
"name": "Accounts Browser",
@@ -83,6 +88,11 @@ def get_data():
"name": "Fiscal Year",
"description": _("Financial / accounting year.")
},
+ {
+ "type": "doctype",
+ "name": "Payment Gateway Account",
+ "description": _("Setup Gateway accounts.")
+ },
{
"type": "page",
"name": "Accounts Browser",
diff --git a/erpnext/docs/assets/img/accounts/pr-details-1.png b/erpnext/docs/assets/img/accounts/pr-details-1.png
new file mode 100644
index 0000000000..12e40a6a89
Binary files /dev/null and b/erpnext/docs/assets/img/accounts/pr-details-1.png differ
diff --git a/erpnext/docs/assets/img/accounts/pr-details-2.png b/erpnext/docs/assets/img/accounts/pr-details-2.png
new file mode 100644
index 0000000000..43122e30c8
Binary files /dev/null and b/erpnext/docs/assets/img/accounts/pr-details-2.png differ
diff --git a/erpnext/docs/assets/img/accounts/pr-email.png b/erpnext/docs/assets/img/accounts/pr-email.png
new file mode 100644
index 0000000000..de1a86890f
Binary files /dev/null and b/erpnext/docs/assets/img/accounts/pr-email.png differ
diff --git a/erpnext/docs/assets/img/accounts/pr-from-si.png b/erpnext/docs/assets/img/accounts/pr-from-si.png
new file mode 100644
index 0000000000..c9e654ae0e
Binary files /dev/null and b/erpnext/docs/assets/img/accounts/pr-from-si.png differ
diff --git a/erpnext/docs/assets/img/accounts/pr-from-so.png b/erpnext/docs/assets/img/accounts/pr-from-so.png
new file mode 100644
index 0000000000..b41ea4fd75
Binary files /dev/null and b/erpnext/docs/assets/img/accounts/pr-from-so.png differ
diff --git a/erpnext/docs/user/manual/en/accounts/index.txt b/erpnext/docs/user/manual/en/accounts/index.txt
index 391a1852b7..5f1b5d5417 100644
--- a/erpnext/docs/user/manual/en/accounts/index.txt
+++ b/erpnext/docs/user/manual/en/accounts/index.txt
@@ -1,6 +1,7 @@
journal-entry
sales-invoice
purchase-invoice
+payment-request
chart-of-accounts
making-payments
advance-payment-entry
diff --git a/erpnext/docs/user/manual/en/accounts/pyament-request.md b/erpnext/docs/user/manual/en/accounts/pyament-request.md
new file mode 100644
index 0000000000..ca696c648c
--- /dev/null
+++ b/erpnext/docs/user/manual/en/accounts/pyament-request.md
@@ -0,0 +1,28 @@
+Payment Request will act as mediator between Payment Gateway and ERPNext. You can create payment request via Sales Order or Sales Invoice.
+
+- Create Payment Request via Sales Order
+
+
+- Create payment Request via Sales Invoice
+
+
+---
+
+Select appropriate Payment Gateway Account on Payment Request. Account head specified on payment gateway will
+considered to create journal entry.
+
+Note: Invoice/Order Currency and Payment Gateway Account corruncy should be same.
+
+
+
+---
+
+##### Notify Customer
+You can notify customer from Payment Request with print format. If customer contact email is mentioned, it will automatically fetch email. If not so you can set email id on Payment Request.
+
+
+
+##### Request Mail
+
+
+
diff --git a/erpnext/public/js/shopping_cart.js b/erpnext/public/js/shopping_cart.js
index d437d74e96..b667177157 100644
--- a/erpnext/public/js/shopping_cart.js
+++ b/erpnext/public/js/shopping_cart.js
@@ -4,13 +4,12 @@
// shopping cart
frappe.provide("shopping_cart");
-$(function() {
+frappe.ready(function() {
// update user
if(full_name) {
$('.navbar li[data-label="User"] a')
.html(' ' + full_name);
}
-
// update login
shopping_cart.set_cart_count();
});
@@ -33,10 +32,9 @@ $.extend(shopping_cart, {
},
btn: opts.btn,
callback: function(r) {
+ shopping_cart.set_cart_count();
if(opts.callback)
opts.callback(r);
-
- shopping_cart.set_cart_count();
}
});
}
@@ -44,13 +42,29 @@ $.extend(shopping_cart, {
set_cart_count: function() {
var cart_count = getCookie("cart_count");
- var $cart = $('.dropdown [data-label="Cart"]');
- var $badge = $cart.find(".badge");
+
+ if($(".cart-icon").length == 0) {
+ $('