Merge pull request #4859 from saurabh6790/cart_fixes

Shopping Cart with multi currency and checkout fixes
This commit is contained in:
Nabin Hait 2016-02-24 17:29:55 +05:30
commit ef3d18f127
17 changed files with 470 additions and 242 deletions

View File

@ -551,7 +551,7 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None, a
}
@frappe.whitelist()
def get_payment_entry_against_order(dt, dn, amount=None, journal_entry=False, bank_account=None):
def get_payment_entry_against_order(dt, dn, amount=None, debit_in_account_currency=None, journal_entry=False, bank_account=None):
ref_doc = frappe.get_doc(dt, dn)
if flt(ref_doc.per_billed, 2) > 0:
@ -582,6 +582,7 @@ def get_payment_entry_against_order(dt, dn, amount=None, journal_entry=False, ba
"amount_field_party": amount_field_party,
"amount_field_bank": amount_field_bank,
"amount": amount,
"debit_in_account_currency": debit_in_account_currency,
"remarks": 'Advance Payment received against {0} {1}'.format(dt, dn),
"is_advance": "Yes",
"bank_account": bank_account,
@ -589,7 +590,7 @@ def get_payment_entry_against_order(dt, dn, amount=None, journal_entry=False, ba
})
@frappe.whitelist()
def get_payment_entry_against_invoice(dt, dn, amount=None, journal_entry=False, bank_account=None):
def get_payment_entry_against_invoice(dt, dn, amount=None, debit_in_account_currency=None, journal_entry=False, bank_account=None):
ref_doc = frappe.get_doc(dt, dn)
if dt == "Sales Invoice":
party_type = "Customer"
@ -614,6 +615,7 @@ def get_payment_entry_against_invoice(dt, dn, amount=None, journal_entry=False,
"amount_field_party": amount_field_party,
"amount_field_bank": amount_field_bank,
"amount": amount if amount else abs(ref_doc.outstanding_amount),
"debit_in_account_currency": debit_in_account_currency,
"remarks": 'Payment received against {0} {1}. {2}'.format(dt, dn, ref_doc.remarks),
"is_advance": "No",
"bank_account": bank_account,
@ -662,10 +664,12 @@ def get_payment_entry(ref_doc, args):
bank_row.cost_center = cost_center
amount = args.get("debit_in_account_currency") or args.get("amount")
if bank_row.account_currency == args.get("party_account_currency"):
bank_row.set(args.get("amount_field_bank"), args.get("amount"))
bank_row.set(args.get("amount_field_bank"), amount)
else:
bank_row.set(args.get("amount_field_bank"), args.get("amount") * exchange_rate)
bank_row.set(args.get("amount_field_bank"), amount * exchange_rate)
# set multi currency check
if party_row.account_currency != ref_doc.company_currency \

View File

@ -1,6 +1,6 @@
cur_frm.cscript.refresh = function(doc, dt, dn){
if(!doc.__islocal){
var df = frappe.meta.get_docfield(doc.doctype, "gateway", doc.name);
var df = frappe.meta.get_docfield(doc.doctype, "payment_gateway", doc.name);
df.read_only = 1;
}
}

View File

@ -12,7 +12,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "gateway",
"fieldname": "payment_gateway",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@ -203,30 +203,6 @@
"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,
@ -238,7 +214,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-01-18 03:53:50.534673",
"modified": "2016-01-21 11:32:10.311015",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Gateway Account",

View File

@ -8,7 +8,7 @@ from frappe.model.document import Document
class PaymentGatewayAccount(Document):
def autoname(self):
self.name = self.gateway + " - " + self.currency
self.name = self.payment_gateway + " - " + self.currency
def validate(self):
self.currency = frappe.db.get_value("Account", self.payment_account, "account_currency")
@ -24,4 +24,4 @@ class PaymentGatewayAccount(Document):
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
self.is_default = 1

View File

@ -1,8 +1,7 @@
cur_frm.add_fetch("payment_gateway", "payment_account", "payment_account")
cur_frm.add_fetch("payment_gateway", "gateway", "gateway")
cur_frm.add_fetch("payment_gateway", "payment_gateway", "payment_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) {
@ -17,18 +16,20 @@ frappe.ui.form.on("Payment Request", "onload", function(frm, dt, dn){
})
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"));
if(!in_list(["Initiated", "Paid"], frm.doc.status) && !frm.doc.__islocal){
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"));
}
}
}
});
});
});
}
});

View File

@ -17,6 +17,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Payment Details",
@ -33,30 +34,6 @@
"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,
@ -65,9 +42,10 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Currency",
"label": "Transaction Currency",
"length": 0,
"no_copy": 0,
"options": "Currency",
@ -86,18 +64,20 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:doc.reference_doctype==\"Sales Order\"",
"fieldname": "make_sales_invoice",
"fieldtype": "Check",
"description": "Amount in customer's currency",
"fieldname": "grand_total",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Make Sales Invoice",
"label": "Grand Total",
"length": 0,
"no_copy": 0,
"options": "currency",
"permlevel": 0,
"precision": "",
"precision": "2",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@ -115,6 +95,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@ -139,6 +120,7 @@
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Status",
@ -156,6 +138,32 @@
"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,
"ignore_xss_filter": 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,
@ -164,6 +172,57 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"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": "payment_gateway_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Payment Gateway Account",
"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": "column_break_9",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@ -184,87 +243,16 @@
"bold": 0,
"collapsible": 0,
"fieldname": "payment_gateway",
"fieldtype": "Link",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 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",
"options": "payment_gateway_account.payment_gateway",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@ -284,12 +272,13 @@
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Payment Account",
"length": 0,
"no_copy": 0,
"options": "payment_gateway.payment_account",
"options": "payment_gateway_account.payment_account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@ -309,6 +298,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Recipient and Message",
@ -334,6 +324,7 @@
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Print Format",
@ -359,6 +350,7 @@
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Mute Email",
@ -383,6 +375,7 @@
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Email To",
@ -407,6 +400,7 @@
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Subject",
@ -431,6 +425,7 @@
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Message",
@ -455,6 +450,7 @@
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Payment URL Message",
@ -479,6 +475,7 @@
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "payment_url",
@ -503,6 +500,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference Details",
@ -527,6 +525,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference Doctype",
@ -552,6 +551,7 @@
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference Name",
@ -577,6 +577,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Amended From",
@ -603,7 +604,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-01-11 05:49:28.342786",
"modified": "2016-02-24 16:49:46.832403",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Request",

View File

@ -8,12 +8,10 @@ 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.utils import get_account_currency
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()
@ -35,7 +33,7 @@ class PaymentRequest(Document):
frappe.throw(_("Payment Gateway Account is not configured"))
def validate_payment_gateway(self):
if self.gateway == "PayPal":
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"))
@ -49,14 +47,10 @@ class PaymentRequest(Document):
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):
""" This is blanck method to trigger hooks call from individual payment gateway app
which will return respective payment gateway"""
pass
def make_invoice(self):
@ -69,6 +63,7 @@ class PaymentRequest(Document):
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, "payment_url", self.payment_url)
frappe.db.set_value(self.doctype, self.name, "status", "Initiated")
def set_as_paid(self):
@ -82,29 +77,44 @@ class PaymentRequest(Document):
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
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
party_account = get_party_account("Customer", ref_doc.get("customer"), ref_doc.company)
party_account_currency = get_account_currency(party_account)
debit_in_account_currency = 0.0
if party_account_currency == ref_doc.company_currency:
amount = flt(flt(self.grand_total) * \
flt(ref_doc.conversion_rate, ref_doc.precision("conversion_rate")), \
ref_doc.precision("base_grand_total"))
if self.currency != ref_doc.company_currency:
debit_in_account_currency = self.grand_total
else:
amount = debit_in_account_currency = self.grand_total
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)
jv = get_payment_entry_against_order(self.reference_doctype, self.reference_name,
amount=amount, debit_in_account_currency=debit_in_account_currency , 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)
if self.reference_doctype == "Sales Invoice":
jv = get_payment_entry_against_invoice(self.reference_doctype, self.reference_name,
amount=amount, debit_in_account_currency=debit_in_account_currency, 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")
@ -148,22 +158,26 @@ def make_payment_request(**args):
args = frappe._dict(args)
ref_doc = frappe.get_doc(args.dt, args.dn)
gateway_account = get_gateway_details(args)
grand_total = get_amount(ref_doc, args.dt)
existing_payment_request = frappe.db.get_value("Payment Request",
{"reference_doctype": args.dt, "reference_name": args.dn})
if existing_payment_request:
pr = frappe.get_doc("Payment Request", existing_payment_request)
else:
else:
pr = frappe.new_doc("Payment Request")
pr.update({
"payment_gateway": gateway_account.name,
"gateway": gateway_account.gateway,
"payment_gateway_account": gateway_account.name,
"payment_gateway": gateway_account.payment_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),
"grand_total": grand_total,
"mute_email": args.mute_email or 0,
"email_to": args.recipient_id or "",
"subject": "Payment Request for %s"%args.dn,
@ -180,11 +194,12 @@ def make_payment_request(**args):
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
@ -193,31 +208,37 @@ def make_payment_request(**args):
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)
grand_total = flt(ref_doc.grand_total) - flt(ref_doc.advance_paid)
if dt == "Sales Invoice":
amount = abs(ref_doc.outstanding_amount)
if amount > 0:
return amount
grand_total = flt(ref_doc.outstanding_amount)
if grand_total > 0 :
return grand_total
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)
if args.get("payment_gateway"):
return get_payment_gateway_account(args.get("payment_gateway"))
if args.cart:
payment_gateway_account = frappe.get_doc("Shopping Cart Settings").payment_gateway_account
return get_payment_gateway_account(payment_gateway_account)
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)
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):
return frappe.db.get_value("Payment Gateway Account", args,
["name", "payment_gateway", "payment_account", "message", "payment_url_message"],
as_dict=1)
@frappe.whitelist()
def get_print_format_list(ref_doctype):

View File

@ -6,8 +6,9 @@ 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.payment_request.payment_request import make_payment_request, get_gateway_details
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.setup.utils import get_exchange_rate
# test_records = frappe.get_test_records('Payment Request')
test_dependencies = ["Currency Exchange", "Journal Entry", "Contact", "Address"]
@ -21,13 +22,13 @@ payment_method = [
{
"doctype": "Payment Gateway Account",
"is_default": 1,
"gateway": "_Test Gateway",
"payment_gateway": "_Test Gateway",
"payment_account": "_Test Bank - _TC",
"currency": "INR"
},
{
"doctype": "Payment Gateway Account",
"gateway": "_Test Gateway",
"payment_gateway": "_Test Gateway",
"payment_account": "_Test Bank USD - _TC",
"currency": "USD"
}
@ -39,41 +40,49 @@ class TestPaymentRequest(unittest.TestCase):
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"],
if not frappe.db.get_value("Payment Gateway Account", {"payment_gateway": method["payment_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")
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.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")
conversion_rate = get_exchange_rate("USD", "INR")
si_usd = create_sales_invoice(currency="USD", conversion_rate=conversion_rate)
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.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)
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)
conversion_rate = get_exchange_rate("USD", "INR")
si_usd = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
currency="USD", conversion_rate=conversion_rate)
pr = make_payment_request(dt="Sales Invoice", dn=si_usd.name, recipient_id="saurabh@erpnext.com",
mute_email=1, return_doc=1, payment_gateway="_Test Gateway - USD")
jv = pr.set_as_paid()
payment_gateway_details = get_gateway_details({"payment_gateway": "_Test Gateway - USD"})
self.assertEquals(jv.accounts[0].account, "_Test Receivable USD - _TC")
self.assertEquals(jv.accounts[1].account, payment_gateway_details.payment_account)

View File

@ -477,3 +477,15 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
})
return outstanding_invoices
def get_account(account_type=None, root_type=None, is_group=None, account_currency=None, company=None):
"""return account based on matching conditions"""
return frappe.db.get_value("Account", {
"account_type": account_type or '',
"root_type": root_type or '',
"is_group": is_group or 0,
"account_currency": account_currency or frappe.defaults.get_defaults().currency,
"company": company or frappe.defaults.get_defaults().company
}, "name")

View File

@ -246,6 +246,6 @@ erpnext.patches.v6_16.update_billing_status_in_dn_and_pr
erpnext.patches.v6_16.create_manufacturer_records
execute:frappe.db.sql("update `tabPricing Rule` set title=name where title='' or title is null") #2016-01-27
erpnext.patches.v6_20.set_party_account_currency_in_orders
erpnext.patches.v6_19.comment_feed_communication
#erpnext.patches.v6_19.comment_feed_communication
erpnext.patches.v6_21.fix_reorder_level
erpnext.patches.v6_21.rename_material_request_fields

View File

@ -9,6 +9,7 @@ from frappe.utils import cint, flt, get_fullname, cstr
from erpnext.utilities.doctype.address.address import get_address_display
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import get_shopping_cart_settings
from frappe.utils.nestedset import get_root_of
from erpnext.accounts.utils import get_account
class WebsitePriceListMissingError(frappe.ValidationError): pass
@ -280,7 +281,13 @@ def get_customer(user=None):
user = frappe.session.user
customer = frappe.db.get_value("Contact", {"email_id": user}, "customer")
cart_settings = frappe.get_doc("Shopping Cart Settings")
debtors_account = ''
if cart_settings.enable_checkout:
debtors_account = get_debtors_account(cart_settings)
if customer:
return frappe.get_doc("Customer", customer)
@ -293,6 +300,15 @@ def get_customer(user=None):
"customer_group": get_shopping_cart_settings().default_customer_group,
"territory": get_root_of("Territory")
})
if debtors_account:
customer.update({
"accounts": [{
"company": cart_settings.company,
"account": debtors_account.name
}]
})
customer.flags.ignore_mandatory = True
customer.insert(ignore_permissions=True)
@ -307,6 +323,32 @@ def get_customer(user=None):
return customer
def get_debtors_account(cart_settings):
payment_gateway_account_currency = \
frappe.get_doc("Payment Gateway Account", cart_settings.payment_gateway_account).currency
account_name = _("Debtors ({0})".format(payment_gateway_account_currency))
debtors_account = get_account("Receivable", "Asset", is_group=0,\
account_currency=payment_gateway_account_currency, company=cart_settings.company)
if not debtors_account:
debtors_account = frappe.get_doc({
"doctype": "Account",
"account_type": "Receivable",
"root_type": "Asset",
"is_group": 0,
"parent_account": get_account(root_type="Asset", is_group=1, company=cart_settings.company),
"account_name": account_name,
"currency": payment_gateway_account_currency
}).insert(ignore_permissions=True)
return debtors_account
else:
return debtors_account
def get_address_docs(doctype=None, txt=None, filters=None, limit_start=0, limit_page_length=20, party=None):
if not party:
party = get_customer()

View File

@ -6,5 +6,19 @@ $.extend(cur_frm.cscript, {
if(cur_frm.doc.__onload && cur_frm.doc.__onload.quotation_series) {
cur_frm.fields_dict.quotation_series.df.options = cur_frm.doc.__onload.quotation_series;
}
},
refresh: function(){
toggle_mandatory(cur_frm)
},
enable_checkout: function(){
toggle_mandatory(cur_frm)
}
});
function toggle_mandatory (cur_frm){
cur_frm.toggle_reqd("payment_gateway_account", false);
if(cur_frm.doc.enabled && cur_frm.doc.enable_checkout) {
cur_frm.toggle_reqd("payment_gateway_account", true);
}
}

View File

@ -19,9 +19,11 @@
"in_filter": 0,
"in_list_view": 1,
"label": "Enable Shopping Cart",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@ -39,9 +41,11 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@ -60,10 +64,12 @@
"in_filter": 0,
"in_list_view": 1,
"label": "Company",
"length": 0,
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
@ -82,11 +88,13 @@
"in_filter": 0,
"in_list_view": 0,
"label": "Price List",
"length": 0,
"no_copy": 0,
"options": "Price List",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
@ -104,9 +112,11 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@ -126,10 +136,12 @@
"in_filter": 0,
"in_list_view": 0,
"label": "Default Customer Group",
"length": 0,
"no_copy": 0,
"options": "Customer Group",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
@ -148,15 +160,141 @@
"in_filter": 0,
"in_list_view": 0,
"label": "Quotation Series",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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": 1,
"collapsible_depends_on": "eval:doc.enable_checkout",
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Checkout Settings",
"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": "enable_checkout",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Enable Checkout",
"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": "Orders",
"description": "After payment completion redirect user to selected page.",
"fieldname": "payment_success_url",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Payment Success Url",
"length": 0,
"no_copy": 0,
"options": "\nOrders\nInvoices\nMy 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": "column_break_11",
"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": "payment_gateway_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Payment Gateway Account",
"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
}
],
"hide_heading": 0,
@ -168,7 +306,8 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-09-17 07:56:09.176098",
"max_attachments": 0,
"modified": "2016-02-09 15:45:03.389220",
"modified_by": "Administrator",
"module": "Shopping Cart",
"name": "Shopping Cart Settings",
@ -196,5 +335,6 @@
}
],
"read_only": 0,
"read_only_onload": 0
"read_only_onload": 0,
"sort_order": "ASC"
}

View File

@ -1,12 +1,15 @@
{% from "erpnext/templates/includes/cart/cart_macros.html"
import show_address %}
<div class="row">
{% if addresses|length == 1%}
{% set select_address = True %}
{% endif %}
<div class="col-sm-6">
<h4>{{ _("Shipping Address") }}</h4>
<div id="cart-shipping-address" class="panel-group"
data-fieldname="shipping_address_name">
{% for address in addresses %}
{{ show_address(address, doc, "shipping_address_name") }}
{{ show_address(address, doc, "shipping_address_name", select_address) }}
{% endfor %}
</div>
<a class="btn btn-default btn-sm" href="/addresses">
@ -17,7 +20,7 @@
<div id="cart-billing-address" class="panel-group"
data-fieldname="customer_address">
{% for address in addresses %}
{{ show_address(address, doc, "customer_address") }}
{{ show_address(address, doc, "customer_address", select_address) }}
{% endfor %}
</div>
</div>

View File

@ -1,5 +1,6 @@
{% macro show_address(address, doc, fieldname) %}
{% macro show_address(address, doc, fieldname, select_address=False) %}
{% set selected=address.name==doc.get(fieldname) %}
<div class="panel panel-default">
<div class="panel-heading">
<div class="row">

View File

@ -1,4 +1,4 @@
{% extends "templates/web.html" %}
t{% extends "templates/web.html" %}
{% block header %}
<h1>{{ doc.name }}</h1>
@ -82,14 +82,16 @@
<div class="cart-taxes row small">
<div class="col-sm-8"><!-- empty --></div>
<div class="col-sm-4">
{% if (doc.doctype=="Sales Order" and doc.per_billed <= 0)
or (doc.doctype=="Sales Invoice" and doc.outstanding_amount > 0) %}
<div class="page-header-actions-block" data-html-block="header-actions">
<p>
<a href="/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn={{ doc.name }}&dt={{ doc.doctype }}&submit_doc=1&mute_email=1&cart=1"
class="btn btn-primary btn-sm">Pay {{ doc.get_formatted("grand_total") }} </a>
</p>
{% if enabled_checkout %}
{% if (doc.doctype=="Sales Order" and doc.per_billed <= 0)
or (doc.doctype=="Sales Invoice" and doc.outstanding_amount > 0) %}
<div class="page-header-actions-block" data-html-block="header-actions">
<p>
<a href="/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn={{ doc.name }}&dt={{ doc.doctype }}&submit_doc=1&mute_email=1&cart=1"
class="btn btn-primary btn-sm">Pay {{ doc.get_formatted("grand_total") }} </a>
</p>
</div>
{% endif %}
{% endif %}
</div>
</div>

View File

@ -15,6 +15,8 @@ def get_context(context):
context.parents = frappe.form_dict.parents
context.payment_ref = frappe.db.get_value("Payment Request",
{"reference_name": frappe.form_dict.name}, "name")
context.enabled_checkout = frappe.get_doc("Shopping Cart Settings").enable_checkout
if not context.doc.has_website_permission("read"):
frappe.throw(_("Not Permitted"), frappe.PermissionError)