Skip to content

Commit 915315e

Browse files
authored
Merge pull request #53541 from frappe/version-15-hotfix
2 parents 1ffd814 + 526dc68 commit 915315e

61 files changed

Lines changed: 1178 additions & 492 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

erpnext/accounts/doctype/accounts_settings/accounts_settings.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@
216216
"description": "Payment Terms from orders will be fetched into the invoices as is",
217217
"fieldname": "automatically_fetch_payment_terms",
218218
"fieldtype": "Check",
219-
"label": "Automatically Fetch Payment Terms from Order"
219+
"label": "Automatically Fetch Payment Terms from Order/Quotation"
220220
},
221221
{
222222
"description": "The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ",
@@ -307,7 +307,7 @@
307307
},
308308
{
309309
"default": "0",
310-
"description": "Learn about <a href=\"https://docs.frappe.io/erpnext/user/manual/en/common_party_accounting\">Common Party</a>",
310+
"description": "Learn about <a href=\"https://docs.erpnext.com/docs/v13/user/manual/en/accounts/articles/common_party_accounting#:~:text=Common%20Party%20Accounting%20in%20ERPNext,Invoice%20against%20a%20primary%20Supplier.\">Common Party</a>",
311311
"fieldname": "enable_common_party_accounting",
312312
"fieldtype": "Check",
313313
"label": "Enable Common Party Accounting"
@@ -671,7 +671,7 @@
671671
"index_web_pages_for_search": 1,
672672
"issingle": 1,
673673
"links": [],
674-
"modified": "2025-12-26 19:46:55.093717",
674+
"modified": "2026-03-06 14:49:11.467716",
675675
"modified_by": "Administrator",
676676
"module": "Accounts",
677677
"name": "Accounts Settings",
@@ -701,4 +701,4 @@
701701
"sort_order": "ASC",
702702
"states": [],
703703
"track_changes": 1
704-
}
704+
}

erpnext/accounts/doctype/bank_clearance/bank_clearance.py

Lines changed: 160 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import frappe
66
from frappe import _, msgprint
77
from frappe.model.document import Document
8+
from frappe.query_builder import Case
89
from frappe.query_builder.custom import ConstantColumn
10+
from frappe.query_builder.functions import Coalesce, Sum
911
from frappe.utils import flt, fmt_money, get_link_to_form, getdate
1012
from pypika import Order
1113

@@ -136,65 +138,162 @@ def get_payment_entries_for_bank_clearance(
136138
):
137139
entries = []
138140

139-
condition = ""
140-
pe_condition = ""
141+
journal_entry = frappe.qb.DocType("Journal Entry")
142+
journal_entry_account = frappe.qb.DocType("Journal Entry Account")
143+
144+
journal_entry_query = (
145+
frappe.qb.from_(journal_entry_account)
146+
.inner_join(journal_entry)
147+
.on(journal_entry_account.parent == journal_entry.name)
148+
.select(
149+
ConstantColumn("Journal Entry").as_("payment_document"),
150+
journal_entry.name.as_("payment_entry"),
151+
journal_entry.cheque_no.as_("cheque_number"),
152+
journal_entry.cheque_date,
153+
Sum(journal_entry_account.debit_in_account_currency).as_("debit"),
154+
Sum(journal_entry_account.credit_in_account_currency).as_("credit"),
155+
journal_entry.posting_date,
156+
journal_entry_account.against_account,
157+
journal_entry.clearance_date,
158+
journal_entry_account.account_currency,
159+
)
160+
.where(
161+
(journal_entry_account.account == account)
162+
& (journal_entry.docstatus == 1)
163+
& (journal_entry.posting_date >= from_date)
164+
& (journal_entry.posting_date <= to_date)
165+
& (journal_entry.is_opening == "No")
166+
)
167+
)
168+
169+
if not include_reconciled_entries:
170+
journal_entry_query = journal_entry_query.where(
171+
(journal_entry.clearance_date.isnull()) | (journal_entry.clearance_date == "0000-00-00")
172+
)
173+
174+
journal_entries = (
175+
journal_entry_query.groupby(journal_entry_account.account, journal_entry.name)
176+
.orderby(journal_entry.posting_date)
177+
.orderby(journal_entry.name, order=Order.desc)
178+
).run(as_dict=True)
179+
180+
pe = frappe.qb.DocType("Payment Entry")
181+
company = frappe.qb.DocType("Company")
182+
payment_entry_query = (
183+
frappe.qb.from_(pe)
184+
.join(company)
185+
.on(pe.company == company.name)
186+
.select(
187+
ConstantColumn("Payment Entry").as_("payment_document"),
188+
pe.name.as_("payment_entry"),
189+
pe.reference_no.as_("cheque_number"),
190+
pe.reference_date.as_("cheque_date"),
191+
(
192+
Case()
193+
.when(
194+
pe.paid_from == account,
195+
(
196+
pe.paid_amount
197+
+ (
198+
Case()
199+
.when(
200+
(pe.payment_type == "Pay")
201+
& (company.default_currency == pe.paid_from_account_currency),
202+
pe.base_total_taxes_and_charges,
203+
)
204+
.else_(pe.total_taxes_and_charges)
205+
)
206+
),
207+
)
208+
.else_(0)
209+
).as_("credit"),
210+
(
211+
Case()
212+
.when(pe.paid_from == account, 0)
213+
.else_(
214+
pe.received_amount
215+
+ (
216+
Case()
217+
.when(
218+
company.default_currency == pe.paid_to_account_currency,
219+
pe.base_total_taxes_and_charges,
220+
)
221+
.else_(pe.total_taxes_and_charges)
222+
)
223+
)
224+
).as_("debit"),
225+
pe.posting_date,
226+
Coalesce(pe.party, Case().when(pe.paid_from == account, pe.paid_to).else_(pe.paid_from)).as_(
227+
"against_account"
228+
),
229+
pe.clearance_date,
230+
(
231+
Case()
232+
.when(pe.paid_to == account, pe.paid_to_account_currency)
233+
.else_(pe.paid_from_account_currency)
234+
).as_("account_currency"),
235+
)
236+
.where(
237+
((pe.paid_from == account) | (pe.paid_to == account))
238+
& (pe.docstatus == 1)
239+
& (pe.posting_date >= from_date)
240+
& (pe.posting_date <= to_date)
241+
)
242+
)
243+
141244
if not include_reconciled_entries:
142-
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
143-
pe_condition = "and (pe.clearance_date IS NULL or pe.clearance_date='0000-00-00')"
144-
145-
journal_entries = frappe.db.sql(
146-
f"""
147-
select
148-
"Journal Entry" as payment_document, t1.name as payment_entry,
149-
t1.cheque_no as cheque_number, t1.cheque_date,
150-
sum(t2.debit_in_account_currency) as debit, sum(t2.credit_in_account_currency) as credit,
151-
t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency
152-
from
153-
`tabJournal Entry` t1, `tabJournal Entry Account` t2
154-
where
155-
t2.parent = t1.name and t2.account = %(account)s and t1.docstatus=1
156-
and t1.posting_date >= %(from)s and t1.posting_date <= %(to)s
157-
and ifnull(t1.is_opening, 'No') = 'No' {condition}
158-
group by t2.account, t1.name
159-
order by t1.posting_date ASC, t1.name DESC
160-
""",
161-
{"account": account, "from": from_date, "to": to_date},
162-
as_dict=1,
245+
payment_entry_query = payment_entry_query.where(
246+
(pe.clearance_date.isnull()) | (pe.clearance_date == "0000-00-00")
247+
)
248+
249+
payment_entries = (payment_entry_query.orderby(pe.posting_date).orderby(pe.name, order=Order.desc)).run(
250+
as_dict=True
163251
)
164252

165-
payment_entries = frappe.db.sql(
166-
f"""
167-
select
168-
"Payment Entry" as payment_document, pe.name as payment_entry,
169-
pe.reference_no as cheque_number, pe.reference_date as cheque_date,
170-
if(pe.paid_from=%(account)s, pe.paid_amount + if(pe.payment_type = 'Pay' and c.default_currency = pe.paid_from_account_currency, pe.base_total_taxes_and_charges, pe.total_taxes_and_charges) , 0) as credit,
171-
if(pe.paid_from=%(account)s, 0, pe.received_amount + pe.total_taxes_and_charges) as debit,
172-
pe.posting_date, ifnull(pe.party,if(pe.paid_from=%(account)s,pe.paid_to,pe.paid_from)) as against_account, pe.clearance_date,
173-
if(pe.paid_to=%(account)s, pe.paid_to_account_currency, pe.paid_from_account_currency) as account_currency
174-
from `tabPayment Entry` as pe
175-
join `tabCompany` c on c.name = pe.company
176-
where
177-
(pe.paid_from=%(account)s or pe.paid_to=%(account)s) and pe.docstatus=1
178-
and pe.posting_date >= %(from)s and pe.posting_date <= %(to)s
179-
{pe_condition}
180-
order by
181-
pe.posting_date ASC, pe.name DESC
182-
""",
183-
{
184-
"account": account,
185-
"from": from_date,
186-
"to": to_date,
187-
},
188-
as_dict=1,
253+
acc = frappe.qb.DocType("Account")
254+
255+
pi = frappe.qb.DocType("Purchase Invoice")
256+
257+
paid_purchase_invoices_query = (
258+
frappe.qb.from_(pi)
259+
.inner_join(acc)
260+
.on(pi.cash_bank_account == acc.name)
261+
.select(
262+
ConstantColumn("Purchase Invoice").as_("payment_document"),
263+
pi.name.as_("payment_entry"),
264+
pi.paid_amount.as_("credit"),
265+
pi.posting_date,
266+
pi.supplier.as_("against_account"),
267+
pi.bill_no.as_("cheque_number"),
268+
pi.clearance_date,
269+
acc.account_currency,
270+
ConstantColumn(0).as_("debit"),
271+
)
272+
.where(
273+
(pi.docstatus == 1)
274+
& (pi.is_paid == 1)
275+
& (pi.cash_bank_account == account)
276+
& (pi.posting_date >= from_date)
277+
& (pi.posting_date <= to_date)
278+
)
189279
)
190280

191-
pos_sales_invoices, pos_purchase_invoices = [], []
281+
if not include_reconciled_entries:
282+
paid_purchase_invoices_query = paid_purchase_invoices_query.where(
283+
(pi.clearance_date.isnull()) | (pi.clearance_date == "0000-00-00")
284+
)
285+
286+
paid_purchase_invoices = (
287+
paid_purchase_invoices_query.orderby(pi.posting_date).orderby(pi.name, order=Order.desc)
288+
).run(as_dict=True)
289+
290+
pos_sales_invoices = []
291+
192292
if include_pos_transactions:
193293
si_payment = frappe.qb.DocType("Sales Invoice Payment")
194294
si = frappe.qb.DocType("Sales Invoice")
195-
acc = frappe.qb.DocType("Account")
196295

197-
pos_sales_invoices = (
296+
pos_sales_invoices_query = (
198297
frappe.qb.from_(si_payment)
199298
.inner_join(si)
200299
.on(si_payment.parent == si.name)
@@ -217,38 +316,22 @@ def get_payment_entries_for_bank_clearance(
217316
& (si.posting_date >= from_date)
218317
& (si.posting_date <= to_date)
219318
)
220-
.orderby(si.posting_date)
221-
.orderby(si.name, order=Order.desc)
222-
).run(as_dict=True)
223-
224-
pi = frappe.qb.DocType("Purchase Invoice")
319+
)
225320

226-
pos_purchase_invoices = (
227-
frappe.qb.from_(pi)
228-
.inner_join(acc)
229-
.on(pi.cash_bank_account == acc.name)
230-
.select(
231-
ConstantColumn("Purchase Invoice").as_("payment_document"),
232-
pi.name.as_("payment_entry"),
233-
pi.paid_amount.as_("credit"),
234-
pi.posting_date,
235-
pi.supplier.as_("against_account"),
236-
pi.clearance_date,
237-
acc.account_currency,
238-
ConstantColumn(0).as_("debit"),
321+
if not include_reconciled_entries:
322+
pos_sales_invoices_query = pos_sales_invoices_query.where(
323+
(si_payment.clearance_date.isnull()) | (si_payment.clearance_date == "0000-00-00")
239324
)
240-
.where(
241-
(pi.docstatus == 1)
242-
& (pi.cash_bank_account == account)
243-
& (pi.posting_date >= from_date)
244-
& (pi.posting_date <= to_date)
245-
)
246-
.orderby(pi.posting_date)
247-
.orderby(pi.name, order=Order.desc)
325+
326+
pos_sales_invoices = (
327+
pos_sales_invoices_query.orderby(si.posting_date).orderby(si.name, order=Order.desc)
248328
).run(as_dict=True)
249329

250330
entries = (
251-
list(payment_entries) + list(journal_entries) + list(pos_sales_invoices) + list(pos_purchase_invoices)
331+
list(payment_entries)
332+
+ list(journal_entries)
333+
+ list(pos_sales_invoices)
334+
+ list(paid_purchase_invoices)
252335
)
253336

254337
return entries

erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
// For license information, please see license.txt
33

44
frappe.ui.form.on("Bank Statement Import", {
5+
onload(frm) {
6+
frm.set_query("bank_account", function (doc) {
7+
return {
8+
filters: {
9+
company: doc.company,
10+
},
11+
};
12+
});
13+
},
514
setup(frm) {
615
frappe.realtime.on("data_import_refresh", ({ data_import }) => {
716
frm.import_in_progress = false;

erpnext/accounts/doctype/journal_entry/journal_entry.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ def on_update_after_submit(self):
214214
def on_cancel(self):
215215
# References for this Journal are removed on the `on_cancel` event in accounts_controller
216216
super().on_cancel()
217+
218+
from_doc_events = getattr(self, "ignore_linked_doctypes", ())
217219
self.ignore_linked_doctypes = (
218220
"GL Entry",
219221
"Stock Ledger Entry",
@@ -226,6 +228,10 @@ def on_cancel(self):
226228
"Unreconcile Payment Entries",
227229
"Advance Payment Ledger Entry",
228230
)
231+
232+
if from_doc_events and from_doc_events != self.ignore_linked_doctypes:
233+
self.ignore_linked_doctypes = self.ignore_linked_doctypes + from_doc_events
234+
229235
self.make_gl_entries(1)
230236
self.unlink_advance_entry_reference()
231237
self.unlink_asset_reference()
@@ -263,6 +269,9 @@ def validate_depr_entry_voucher_type(self):
263269
frappe.throw(_("Journal Entry type should be set as Depreciation Entry for asset depreciation"))
264270

265271
def validate_stock_accounts(self):
272+
if not erpnext.is_perpetual_inventory_enabled(self.company):
273+
return
274+
266275
stock_accounts = get_stock_accounts(self.company, accounts=self.accounts)
267276
for account in stock_accounts:
268277
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(

erpnext/accounts/doctype/payment_entry/payment_entry.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,14 +2556,9 @@ def get_orders_to_be_billed(
25562556
if not voucher_type:
25572557
return []
25582558

2559-
# Add cost center condition
2560-
doc = frappe.get_doc({"doctype": voucher_type})
2561-
condition = ""
2562-
if doc and hasattr(doc, "cost_center") and doc.cost_center:
2563-
condition = " and cost_center='%s'" % cost_center
2564-
25652559
# dynamic dimension filters
2566-
active_dimensions = get_dimensions()[0]
2560+
condition = ""
2561+
active_dimensions = get_dimensions(True)[0]
25672562
for dim in active_dimensions:
25682563
if filters.get(dim.fieldname):
25692564
condition += f" and {dim.fieldname}='{filters.get(dim.fieldname)}'"

erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"reqd": 1
2323
},
2424
{
25+
"allow_on_submit": 1,
2526
"fieldname": "cost_center",
2627
"fieldtype": "Link",
2728
"in_list_view": 1,
@@ -59,7 +60,7 @@
5960
"index_web_pages_for_search": 1,
6061
"istable": 1,
6162
"links": [],
62-
"modified": "2024-11-05 16:07:47.307971",
63+
"modified": "2026-03-11 14:26:11.312950",
6364
"modified_by": "Administrator",
6465
"module": "Accounts",
6566
"name": "Payment Entry Deduction",

erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@
312312
"fieldname": "posting_date",
313313
"fieldtype": "Date",
314314
"in_list_view": 1,
315-
"label": "Date",
315+
"label": "Posting Date",
316316
"oldfieldname": "posting_date",
317317
"oldfieldtype": "Date",
318318
"print_hide": 1,

0 commit comments

Comments
 (0)