mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-23 06:59:20 +00:00
Merge pull request #44010 from frappe/mergify/bp/version-15-hotfix/pr-43689
refactor: allow multiple payment requests through customer portal (backport #43689)
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _, qb
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.query_builder.functions import Sum
|
from frappe.query_builder.functions import Sum
|
||||||
from frappe.utils import flt, nowdate
|
from frappe.utils import flt, nowdate
|
||||||
@@ -564,11 +564,24 @@ def make_payment_request(**args):
|
|||||||
# fetches existing payment request `grand_total` amount
|
# fetches existing payment request `grand_total` amount
|
||||||
existing_payment_request_amount = get_existing_payment_request_amount(ref_doc.doctype, ref_doc.name)
|
existing_payment_request_amount = get_existing_payment_request_amount(ref_doc.doctype, ref_doc.name)
|
||||||
|
|
||||||
if existing_payment_request_amount:
|
def validate_and_calculate_grand_total(grand_total, existing_payment_request_amount):
|
||||||
grand_total -= existing_payment_request_amount
|
grand_total -= existing_payment_request_amount
|
||||||
|
|
||||||
if not grand_total:
|
if not grand_total:
|
||||||
frappe.throw(_("Payment Request is already created"))
|
frappe.throw(_("Payment Request is already created"))
|
||||||
|
return grand_total
|
||||||
|
|
||||||
|
if existing_payment_request_amount:
|
||||||
|
if args.order_type == "Shopping Cart":
|
||||||
|
# If Payment Request is in an advanced stage, then create for remaining amount.
|
||||||
|
if get_existing_payment_request_amount(
|
||||||
|
ref_doc.doctype, ref_doc.name, ["Initiated", "Partially Paid", "Payment Ordered", "Paid"]
|
||||||
|
):
|
||||||
|
grand_total = validate_and_calculate_grand_total(grand_total, existing_payment_request_amount)
|
||||||
|
else:
|
||||||
|
# If PR's are processed, cancel all of them.
|
||||||
|
cancel_old_payment_requests(ref_doc.doctype, ref_doc.name)
|
||||||
|
else:
|
||||||
|
grand_total = validate_and_calculate_grand_total(grand_total, existing_payment_request_amount)
|
||||||
|
|
||||||
if draft_payment_request:
|
if draft_payment_request:
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
@@ -678,21 +691,65 @@ def get_amount(ref_doc, payment_account=None):
|
|||||||
frappe.throw(_("Payment Entry is already created"))
|
frappe.throw(_("Payment Entry is already created"))
|
||||||
|
|
||||||
|
|
||||||
def get_existing_payment_request_amount(ref_dt, ref_dn):
|
def get_irequest_status(payment_requests: None | list = None) -> list:
|
||||||
|
IR = frappe.qb.DocType("Integration Request")
|
||||||
|
res = []
|
||||||
|
if payment_requests:
|
||||||
|
res = (
|
||||||
|
frappe.qb.from_(IR)
|
||||||
|
.select(IR.name)
|
||||||
|
.where(IR.reference_doctype.eq("Payment Request"))
|
||||||
|
.where(IR.reference_docname.isin(payment_requests))
|
||||||
|
.where(IR.status.isin(["Authorized", "Completed"]))
|
||||||
|
.run(as_dict=True)
|
||||||
|
)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def cancel_old_payment_requests(ref_dt, ref_dn):
|
||||||
|
PR = frappe.qb.DocType("Payment Request")
|
||||||
|
|
||||||
|
if res := (
|
||||||
|
frappe.qb.from_(PR)
|
||||||
|
.select(PR.name)
|
||||||
|
.where(PR.reference_doctype == ref_dt)
|
||||||
|
.where(PR.reference_name == ref_dn)
|
||||||
|
.where(PR.docstatus == 1)
|
||||||
|
.where(PR.status.isin(["Draft", "Requested"]))
|
||||||
|
.run(as_dict=True)
|
||||||
|
):
|
||||||
|
if get_irequest_status([x.name for x in res]):
|
||||||
|
frappe.throw(_("Another Payment Request is already processed"))
|
||||||
|
else:
|
||||||
|
for x in res:
|
||||||
|
doc = frappe.get_doc("Payment Request", x.name)
|
||||||
|
doc.flags.ignore_permissions = True
|
||||||
|
doc.cancel()
|
||||||
|
|
||||||
|
if ireqs := get_irequests_of_payment_request(doc.name):
|
||||||
|
for ireq in ireqs:
|
||||||
|
frappe.db.set_value("Integration Request", ireq.name, "status", "Cancelled")
|
||||||
|
|
||||||
|
|
||||||
|
def get_existing_payment_request_amount(ref_dt, ref_dn, statuses: list | None = None) -> list:
|
||||||
"""
|
"""
|
||||||
Return the total amount of Payment Requests against a reference document.
|
Return the total amount of Payment Requests against a reference document.
|
||||||
"""
|
"""
|
||||||
PR = frappe.qb.DocType("Payment Request")
|
PR = frappe.qb.DocType("Payment Request")
|
||||||
|
|
||||||
response = (
|
query = (
|
||||||
frappe.qb.from_(PR)
|
frappe.qb.from_(PR)
|
||||||
.select(Sum(PR.grand_total))
|
.select(Sum(PR.grand_total))
|
||||||
.where(PR.reference_doctype == ref_dt)
|
.where(PR.reference_doctype == ref_dt)
|
||||||
.where(PR.reference_name == ref_dn)
|
.where(PR.reference_name == ref_dn)
|
||||||
.where(PR.docstatus == 1)
|
.where(PR.docstatus == 1)
|
||||||
.run()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if statuses:
|
||||||
|
query = query.where(PR.status.isin(statuses))
|
||||||
|
|
||||||
|
response = query.run()
|
||||||
|
|
||||||
return response[0][0] if response[0] else 0
|
return response[0][0] if response[0] else 0
|
||||||
|
|
||||||
|
|
||||||
@@ -915,3 +972,17 @@ def get_open_payment_requests_query(doctype, txt, searchfield, start, page_len,
|
|||||||
)
|
)
|
||||||
for pr in open_payment_requests
|
for pr in open_payment_requests
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_irequests_of_payment_request(doc: str | None = None) -> list:
|
||||||
|
res = []
|
||||||
|
if doc:
|
||||||
|
res = frappe.db.get_all(
|
||||||
|
"Integration Request",
|
||||||
|
{
|
||||||
|
"reference_doctype": "Payment Request",
|
||||||
|
"reference_docname": doc,
|
||||||
|
"status": "Queued",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return res
|
||||||
|
|||||||
Reference in New Issue
Block a user