mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-20 01:55:01 +00:00
Merge pull request #42761 from frappe/mergify/bp/version-15-hotfix/pr-42720
fix: incorrect 'against_voucher' for Pos return with 'Update Outstanding for Self' disabled. (backport #42720)
This commit is contained in:
@@ -1479,6 +1479,10 @@ class SalesInvoice(SellingController):
|
||||
if skip_change_gl_entries and payment_mode.account == self.account_for_change_amount:
|
||||
payment_mode.base_amount -= flt(self.change_amount)
|
||||
|
||||
against_voucher = self.name
|
||||
if self.is_return and self.return_against and not self.update_outstanding_for_self:
|
||||
against_voucher = self.return_against
|
||||
|
||||
if payment_mode.base_amount:
|
||||
# POS, make payment entries
|
||||
gl_entries.append(
|
||||
@@ -1492,7 +1496,7 @@ class SalesInvoice(SellingController):
|
||||
"credit_in_account_currency": payment_mode.base_amount
|
||||
if self.party_account_currency == self.company_currency
|
||||
else payment_mode.amount,
|
||||
"against_voucher": self.name,
|
||||
"against_voucher": against_voucher,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center,
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@ import copy
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import qb
|
||||
from frappe.model.dynamic_links import get_dynamic_link_map
|
||||
from frappe.tests.utils import FrappeTestCase, change_settings
|
||||
from frappe.utils import add_days, flt, getdate, nowdate, today
|
||||
@@ -3836,6 +3837,40 @@ class TestSalesInvoice(FrappeTestCase):
|
||||
]
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_pos_returns_without_update_outstanding_for_self(self):
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_sales_return
|
||||
|
||||
pos_profile = make_pos_profile()
|
||||
pos_profile.payments = []
|
||||
pos_profile.append("payments", {"default": 1, "mode_of_payment": "Cash"})
|
||||
pos_profile.save()
|
||||
|
||||
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.save().submit()
|
||||
|
||||
pos_return = make_sales_return(pos.name)
|
||||
pos_return.update_outstanding_for_self = False
|
||||
pos_return.save().submit()
|
||||
|
||||
gle = qb.DocType("GL Entry")
|
||||
res = (
|
||||
qb.from_(gle)
|
||||
.select(gle.against_voucher)
|
||||
.distinct()
|
||||
.where(
|
||||
gle.is_cancelled.eq(0) & gle.voucher_no.eq(pos_return.name) & gle.against_voucher.notnull()
|
||||
)
|
||||
.run(as_list=1)
|
||||
)
|
||||
self.assertEqual(len(res), 1)
|
||||
self.assertEqual(res[0][0], pos_return.return_against)
|
||||
|
||||
|
||||
def set_advance_flag(company, flag, default_account):
|
||||
frappe.db.set_value(
|
||||
|
||||
@@ -357,6 +357,7 @@ erpnext.patches.v14_0.create_accounting_dimensions_in_reconciliation_tool
|
||||
erpnext.patches.v15_0.allow_on_submit_dimensions_for_repostable_doctypes
|
||||
erpnext.patches.v14_0.update_flag_for_return_invoices #2024-03-22
|
||||
erpnext.patches.v15_0.create_accounting_dimensions_in_payment_request
|
||||
erpnext.patches.v14_0.update_pos_return_ledger_entries
|
||||
# below migration patch should always run last
|
||||
erpnext.patches.v14_0.migrate_gl_to_payment_ledger
|
||||
erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index # 2023-12-20
|
||||
|
||||
61
erpnext/patches/v14_0/update_pos_return_ledger_entries.py
Normal file
61
erpnext/patches/v14_0/update_pos_return_ledger_entries.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import frappe
|
||||
from frappe import qb
|
||||
|
||||
|
||||
def execute():
|
||||
sinv = qb.DocType("Sales Invoice")
|
||||
pos_returns_without_self = (
|
||||
qb.from_(sinv)
|
||||
.select(sinv.name)
|
||||
.where(
|
||||
sinv.docstatus.eq(1)
|
||||
& sinv.is_pos.eq(1)
|
||||
& sinv.is_return.eq(1)
|
||||
& sinv.return_against.notnull()
|
||||
& sinv.update_outstanding_for_self.eq(0)
|
||||
)
|
||||
.run()
|
||||
)
|
||||
if pos_returns_without_self:
|
||||
pos_returns_without_self = [x[0] for x in pos_returns_without_self]
|
||||
|
||||
gle = qb.DocType("GL Entry")
|
||||
gl_against_references = (
|
||||
qb.from_(gle)
|
||||
.select(gle.voucher_no, gle.against_voucher)
|
||||
.where(
|
||||
gle.voucher_no.isin(pos_returns_without_self)
|
||||
& gle.against_voucher.notnull()
|
||||
& gle.against_voucher.eq(gle.voucher_no)
|
||||
& gle.is_cancelled.eq(0)
|
||||
)
|
||||
.run()
|
||||
)
|
||||
|
||||
_vouchers = list(set([x[0] for x in gl_against_references]))
|
||||
invoice_return_against = (
|
||||
qb.from_(sinv)
|
||||
.select(sinv.name, sinv.return_against)
|
||||
.where(sinv.name.isin(_vouchers) & sinv.return_against.notnull())
|
||||
.orderby(sinv.name)
|
||||
.run()
|
||||
)
|
||||
|
||||
valid_references = set(invoice_return_against)
|
||||
actual_references = set(gl_against_references)
|
||||
|
||||
invalid_references = actual_references.difference(valid_references)
|
||||
|
||||
if invalid_references:
|
||||
# Repost Accounting Ledger
|
||||
pos_for_reposting = (
|
||||
qb.from_(sinv)
|
||||
.select(sinv.company, sinv.name)
|
||||
.where(sinv.name.isin([x[0] for x in invalid_references]))
|
||||
.run(as_dict=True)
|
||||
)
|
||||
for x in pos_for_reposting:
|
||||
ral = frappe.new_doc("Repost Accounting Ledger")
|
||||
ral.company = x.company
|
||||
ral.append("vouchers", {"voucher_type": "Sales Invoice", "voucher_no": x.name})
|
||||
ral.save().submit()
|
||||
Reference in New Issue
Block a user