fix: update accounts on change of mode of payment in sales invoice payment (#47381)

* fix: update accounts on change of mode of payment in sales invoice payment

* test: fixed tests
This commit is contained in:
Diptanil Saha
2025-05-05 15:58:53 +05:30
committed by GitHub
parent 5990752416
commit 8067799692
8 changed files with 111 additions and 84 deletions

View File

@@ -7,6 +7,9 @@ from frappe.tests import IntegrationTestCase
from frappe.utils import add_months, getdate
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
from erpnext.accounts.doctype.mode_of_payment.test_mode_of_payment import (
set_default_account_for_mode_of_payment,
)
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
@@ -172,11 +175,13 @@ def make_pos_sales_invoice():
customer = make_customer(customer="_Test Customer")
mode_of_payment = frappe.get_doc("Mode of Payment", "Wire Transfer")
set_default_account_for_mode_of_payment(mode_of_payment, "_Test Company", "_Test Bank Clearance - _TC")
si = create_sales_invoice(customer=customer, item="_Test Item", is_pos=1, qty=1, rate=1000, do_not_save=1)
si.set("payments", [])
si.append(
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank Clearance - _TC", "amount": 1000}
)
si.append("payments", {"mode_of_payment": "Wire Transfer", "amount": 1000})
si.insert()
si.submit()

View File

@@ -12,6 +12,9 @@ from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool
get_linked_payments,
reconcile_vouchers,
)
from erpnext.accounts.doctype.mode_of_payment.test_mode_of_payment import (
set_default_account_for_mode_of_payment,
)
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
@@ -430,15 +433,13 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
except frappe.DuplicateEntryError:
pass
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"})
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Wire Transfer"})
if not frappe.db.get_value("Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}):
mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account})
mode_of_payment.save()
set_default_account_for_mode_of_payment(mode_of_payment, "_Test Company", gl_account)
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
si.is_pos = 1
si.append("payments", {"mode_of_payment": "Cash", "account": gl_account, "amount": 109080})
si.append("payments", {"mode_of_payment": "Wire Transfer", "amount": 109080})
si.insert()
si.submit()

View File

@@ -2,8 +2,26 @@
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
class TestModeofPayment(IntegrationTestCase):
pass
def set_default_account_for_mode_of_payment(mode_of_payment, company, account):
mode_of_payment.reload()
if frappe.db.exists(
"Mode of Payment Account", {"parent": mode_of_payment.mode_of_payment, "company": company}
):
frappe.db.set_value(
"Mode of Payment Account",
{"parent": mode_of_payment.mode_of_payment, "company": company},
"default_account",
account,
)
return
mode_of_payment.append("accounts", {"company": company, "default_account": account})
mode_of_payment.save()

View File

@@ -323,3 +323,15 @@ frappe.ui.form.on("POS Invoice", {
});
},
});
frappe.ui.form.on("Sales Invoice Payment", {
mode_of_payment: function (frm) {
frappe.call({
doc: frm.doc,
method: "set_account_for_mode_of_payment",
callback: function (r) {
refresh_field("payments");
},
});
},
});

View File

@@ -7,6 +7,9 @@ import frappe
from frappe import _
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.mode_of_payment.test_mode_of_payment import (
set_default_account_for_mode_of_payment,
)
from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.accounts.doctype.sales_invoice.sales_invoice import PartialPaymentValidationError
@@ -34,6 +37,8 @@ class TestPOSInvoice(IntegrationTestCase):
cls.test_user, cls.pos_profile = init_user_and_profile()
create_opening_entry(cls.pos_profile, cls.test_user)
mode_of_payment = frappe.get_doc("Mode of Payment", "Bank Draft")
set_default_account_for_mode_of_payment(mode_of_payment, "_Test Company", "_Test Bank - _TC")
def tearDown(self):
if frappe.session.user != "Administrator":
@@ -236,12 +241,8 @@ class TestPOSInvoice(IntegrationTestCase):
pos = create_pos_invoice(qty=10, do_not_save=True)
pos.set("payments", [])
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 500}
)
pos.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 500, "default": 1}
)
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 500})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 500, "default": 1})
pos.insert()
pos.submit()
@@ -280,9 +281,7 @@ class TestPOSInvoice(IntegrationTestCase):
do_not_save=1,
)
pos.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1000, "default": 1}
)
pos.append("payments", {"mode_of_payment": "Cash", "amount": 1000, "default": 1})
pos.insert()
pos.submit()
@@ -323,9 +322,7 @@ class TestPOSInvoice(IntegrationTestCase):
do_not_save=1,
)
pos.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2000, "default": 1}
)
pos.append("payments", {"mode_of_payment": "Cash", "amount": 2000, "default": 1})
pos.insert()
pos.submit()
@@ -336,9 +333,7 @@ class TestPOSInvoice(IntegrationTestCase):
# partial return 1
pos_return1.get("items")[0].qty = -1
pos_return1.set("payments", [])
pos_return1.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": -1000, "default": 1}
)
pos_return1.append("payments", {"mode_of_payment": "Cash", "amount": -1000, "default": 1})
pos_return1.paid_amount = -1000
pos_return1.submit()
pos_return1.reload()
@@ -355,9 +350,7 @@ class TestPOSInvoice(IntegrationTestCase):
# partial return 2
pos_return2 = make_sales_return(pos.name)
pos_return2.set("payments", [])
pos_return2.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": -1000, "default": 1}
)
pos_return2.append("payments", {"mode_of_payment": "Cash", "amount": -1000, "default": 1})
pos_return2.paid_amount = -1000
pos_return2.submit()
@@ -377,10 +370,8 @@ class TestPOSInvoice(IntegrationTestCase):
)
pos.set("payments", [])
pos.append("payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 50})
pos.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 60, "default": 1}
)
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 50})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 60, "default": 1})
pos.insert()
pos.submit()
@@ -398,7 +389,7 @@ class TestPOSInvoice(IntegrationTestCase):
pos_inv = create_pos_invoice(rate=10000, do_not_save=1)
pos_inv.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 9000},
{"mode_of_payment": "Cash", "amount": 9000},
)
pos_inv.insert()
self.assertRaises(PartialPaymentValidationError, pos_inv.submit)
@@ -430,9 +421,7 @@ class TestPOSInvoice(IntegrationTestCase):
do_not_save=1,
)
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 1000}
)
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 1000})
pos.insert()
pos.submit()
@@ -451,9 +440,7 @@ class TestPOSInvoice(IntegrationTestCase):
do_not_save=1,
)
pos2.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 1000}
)
pos2.append("payments", {"mode_of_payment": "Bank Draft", "amount": 1000})
pos2.insert()
self.assertRaises(frappe.ValidationError, pos2.submit)
@@ -503,9 +490,7 @@ class TestPOSInvoice(IntegrationTestCase):
do_not_save=1,
)
pos2.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 1000}
)
pos2.append("payments", {"mode_of_payment": "Bank Draft", "amount": 1000})
pos2.insert()
self.assertRaises(frappe.ValidationError, pos2.submit)
@@ -570,9 +555,7 @@ class TestPOSInvoice(IntegrationTestCase):
)
pos.get("items")[0].has_serial_no = 1
pos.set("payments", [])
pos.append(
"payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1000, "default": 1}
)
pos.append("payments", {"mode_of_payment": "Cash", "amount": 1000, "default": 1})
pos = pos.save().submit()
# make a return
@@ -618,7 +601,7 @@ class TestPOSInvoice(IntegrationTestCase):
inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1)
inv.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 10000},
{"mode_of_payment": "Cash", "amount": 10000},
)
inv.insert()
inv.submit()
@@ -650,7 +633,7 @@ class TestPOSInvoice(IntegrationTestCase):
pos_inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1)
pos_inv.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 10000},
{"mode_of_payment": "Cash", "amount": 10000},
)
pos_inv.paid_amount = 10000
pos_inv.submit()
@@ -665,7 +648,7 @@ class TestPOSInvoice(IntegrationTestCase):
inv.loyalty_amount = inv.loyalty_points * before_lp_details.conversion_factor
inv.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 10000 - inv.loyalty_amount},
{"mode_of_payment": "Cash", "amount": 10000 - inv.loyalty_amount},
)
inv.paid_amount = 10000
inv.submit()
@@ -686,12 +669,12 @@ class TestPOSInvoice(IntegrationTestCase):
frappe.db.sql("delete from `tabPOS Invoice`")
test_user, pos_profile = init_user_and_profile()
pos_inv = create_pos_invoice(rate=300, additional_discount_percentage=10, do_not_submit=1)
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 270})
pos_inv.append("payments", {"mode_of_payment": "Cash", "amount": 270})
pos_inv.save()
pos_inv.submit()
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
pos_inv2.append("payments", {"mode_of_payment": "Cash", "amount": 3200})
pos_inv2.save()
pos_inv2.submit()
@@ -712,7 +695,7 @@ class TestPOSInvoice(IntegrationTestCase):
frappe.db.sql("delete from `tabPOS Invoice`")
test_user, pos_profile = init_user_and_profile()
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300})
pos_inv.append("payments", {"mode_of_payment": "Cash", "amount": 300})
pos_inv.append(
"taxes",
{
@@ -729,7 +712,7 @@ class TestPOSInvoice(IntegrationTestCase):
pos_inv2 = create_pos_invoice(rate=300, qty=2, do_not_submit=1)
pos_inv2.additional_discount_percentage = 10
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 540})
pos_inv2.append("payments", {"mode_of_payment": "Cash", "amount": 540})
pos_inv2.append(
"taxes",
{
@@ -767,7 +750,7 @@ class TestPOSInvoice(IntegrationTestCase):
frappe.db.sql("delete from `tabPOS Invoice`")
test_user, pos_profile = init_user_and_profile()
pos_inv = create_pos_invoice(item=item, rate=300, do_not_submit=1)
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300})
pos_inv.append("payments", {"mode_of_payment": "Cash", "amount": 300})
pos_inv.append(
"taxes",
{
@@ -782,7 +765,7 @@ class TestPOSInvoice(IntegrationTestCase):
self.assertRaises(frappe.ValidationError, pos_inv.submit)
pos_inv2 = create_pos_invoice(item=item, rate=400, do_not_submit=1)
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 400})
pos_inv2.append("payments", {"mode_of_payment": "Cash", "amount": 400})
pos_inv2.append(
"taxes",
{
@@ -827,7 +810,7 @@ class TestPOSInvoice(IntegrationTestCase):
pos_inv1 = create_pos_invoice(item="_BATCH ITEM Test For Reserve", rate=300, qty=15, do_not_save=1)
pos_inv1.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 4500},
{"mode_of_payment": "Cash", "amount": 4500},
)
pos_inv1.items[0].batch_no = batch_no
pos_inv1.save()
@@ -848,7 +831,7 @@ class TestPOSInvoice(IntegrationTestCase):
)
pos_inv2.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3000},
{"mode_of_payment": "Cash", "amount": 3000},
)
pos_inv2.save()
pos_inv2.submit()
@@ -888,7 +871,7 @@ class TestPOSInvoice(IntegrationTestCase):
)
pos_inv1.append(
"payments",
{"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300},
{"mode_of_payment": "Cash", "amount": 300},
)
pos_inv1.save()
pos_inv1.submit()

View File

@@ -1086,6 +1086,18 @@ frappe.ui.form.on("Sales Invoice Timesheet", {
},
});
frappe.ui.form.on("Sales Invoice Payment", {
mode_of_payment: function (frm) {
frappe.call({
doc: frm.doc,
method: "set_account_for_mode_of_payment",
callback: function (r) {
refresh_field("payments");
},
});
},
});
var set_timesheet_detail_rate = function (cdt, cdn, currency, timelog) {
frappe.call({
method: "erpnext.projects.doctype.timesheet.timesheet.get_timesheet_detail_rate",

View File

@@ -804,10 +804,10 @@ class SalesInvoice(SellingController):
self.paid_amount = paid_amount
self.base_paid_amount = base_paid_amount
@frappe.whitelist()
def set_account_for_mode_of_payment(self):
for payment in self.payments:
if not payment.account:
payment.account = get_bank_cash_account(payment.mode_of_payment, self.company).get("account")
payment.account = get_bank_cash_account(payment.mode_of_payment, self.company).get("account")
def validate_time_sheets_are_submitted(self):
for data in self.timesheets:

View File

@@ -12,6 +12,9 @@ from frappe.utils import add_days, flt, format_date, getdate, nowdate, today
import erpnext
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
from erpnext.accounts.doctype.mode_of_payment.test_mode_of_payment import (
set_default_account_for_mode_of_payment,
)
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import WarehouseMissingError
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
@@ -63,6 +66,11 @@ class TestSalesInvoice(IntegrationTestCase):
create_items(["_Test Internal Transfer Item"], uoms=[{"uom": "Box", "conversion_factor": 10}])
create_internal_parties()
setup_accounts()
mode_of_payment = frappe.get_doc("Mode of Payment", "Bank Draft")
set_default_account_for_mode_of_payment(mode_of_payment, "_Test Company", "_Test Bank - _TC")
set_default_account_for_mode_of_payment(
mode_of_payment, "_Test Company with perpetual inventory", "_Test Bank - TCP1"
)
frappe.db.set_single_value("Accounts Settings", "acc_frozen_upto", None)
def tearDown(self):
@@ -982,10 +990,8 @@ class TestSalesInvoice(IntegrationTestCase):
pos.is_pos = 1
pos.update_stock = 1
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - TCP1", "amount": 50}
)
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - TCP1", "amount": 50})
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 50})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 50})
taxes = get_taxes_and_charges()
pos.taxes = []
@@ -1014,10 +1020,8 @@ class TestSalesInvoice(IntegrationTestCase):
pos.is_pos = 1
pos.pos_profile = pos_profile.name
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 500}
)
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 500})
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 500})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 500})
pos.insert()
pos.submit()
@@ -1060,10 +1064,8 @@ class TestSalesInvoice(IntegrationTestCase):
pos.is_pos = 1
pos.update_stock = 1
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - TCP1", "amount": 50}
)
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - TCP1", "amount": 60})
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 50})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 60})
pos.write_off_outstanding_amount_automatically = 1
pos.insert()
@@ -1103,10 +1105,8 @@ class TestSalesInvoice(IntegrationTestCase):
pos.is_pos = 1
pos.update_stock = 1
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - TCP1", "amount": 50}
)
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - TCP1", "amount": 40})
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 50})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 40})
pos.write_off_outstanding_amount_automatically = 1
pos.insert()
@@ -1120,7 +1120,7 @@ class TestSalesInvoice(IntegrationTestCase):
pos = create_sales_invoice(do_not_save=True)
pos.is_pos = 1
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 100})
pos.save().submit()
self.assertEqual(pos.outstanding_amount, 0.0)
self.assertEqual(pos.status, "Paid")
@@ -1191,10 +1191,8 @@ class TestSalesInvoice(IntegrationTestCase):
for tax in taxes:
pos.append("taxes", tax)
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - TCP1", "amount": 50}
)
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - TCP1", "amount": 60})
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 50})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 60})
pos.insert()
pos.submit()
@@ -3963,10 +3961,8 @@ class TestSalesInvoice(IntegrationTestCase):
pos = create_sales_invoice(qty=10, do_not_save=True)
pos.is_pos = 1
pos.pos_profile = pos_profile.name
pos.append(
"payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 500}
)
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 500})
pos.append("payments", {"mode_of_payment": "Bank Draft", "amount": 500})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 500})
pos.save().submit()
pos_return = make_sales_return(pos.name)
@@ -4337,7 +4333,7 @@ class TestSalesInvoice(IntegrationTestCase):
pos.is_pos = 1
pos.pos_profile = pos_profile.name
pos.debit_to = "_Test Receivable USD - _TC"
pos.append("payments", {"mode_of_payment": "Cash", "account": "_Test Bank - _TC", "amount": 20.35})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 20.35})
pos.save().submit()
pos_return = make_sales_return(pos.name)
@@ -4404,7 +4400,7 @@ class TestSalesInvoice(IntegrationTestCase):
pos.pos_profile = pos_profile.name
pos.is_created_using_pos = 1
pos.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1000})
pos.append("payments", {"mode_of_payment": "Cash", "amount": 1000})
self.assertRaises(frappe.ValidationError, pos.insert)