mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-24 15:39:20 +00:00
fix: Remove Expense Claim from Bank Reconciliation
- add hooks `get_matching_queries` and `bank_reconciliation_doctypes` to extend the functionality in other apps
This commit is contained in:
@@ -10,7 +10,6 @@ from frappe.model.document import Document
|
|||||||
from frappe.query_builder.custom import ConstantColumn
|
from frappe.query_builder.custom import ConstantColumn
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
|
|
||||||
from erpnext import get_company_currency
|
|
||||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_paid_amount
|
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_paid_amount
|
||||||
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import (
|
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import (
|
||||||
get_amounts_not_reflected_in_system,
|
get_amounts_not_reflected_in_system,
|
||||||
@@ -368,6 +367,27 @@ def get_queries(bank_account, company, transaction, document_types):
|
|||||||
account_from_to = "paid_to" if transaction.deposit > 0 else "paid_from"
|
account_from_to = "paid_to" if transaction.deposit > 0 else "paid_from"
|
||||||
queries = []
|
queries = []
|
||||||
|
|
||||||
|
# get matching queries from all the apps
|
||||||
|
for method_name in frappe.get_hooks("get_matching_queries"):
|
||||||
|
queries.extend(
|
||||||
|
frappe.get_attr(method_name)(
|
||||||
|
bank_account,
|
||||||
|
company,
|
||||||
|
transaction,
|
||||||
|
document_types,
|
||||||
|
amount_condition,
|
||||||
|
account_from_to,
|
||||||
|
)
|
||||||
|
or []
|
||||||
|
)
|
||||||
|
|
||||||
|
return queries
|
||||||
|
|
||||||
|
|
||||||
|
def get_matching_queries(
|
||||||
|
bank_account, company, transaction, document_types, amount_condition, account_from_to
|
||||||
|
):
|
||||||
|
queries = []
|
||||||
if "payment_entry" in document_types:
|
if "payment_entry" in document_types:
|
||||||
pe_amount_matching = get_pe_matching_query(amount_condition, account_from_to, transaction)
|
pe_amount_matching = get_pe_matching_query(amount_condition, account_from_to, transaction)
|
||||||
queries.extend([pe_amount_matching])
|
queries.extend([pe_amount_matching])
|
||||||
@@ -385,10 +405,6 @@ def get_queries(bank_account, company, transaction, document_types):
|
|||||||
pi_amount_matching = get_pi_matching_query(amount_condition)
|
pi_amount_matching = get_pi_matching_query(amount_condition)
|
||||||
queries.extend([pi_amount_matching])
|
queries.extend([pi_amount_matching])
|
||||||
|
|
||||||
if "expense_claim" in document_types:
|
|
||||||
ec_amount_matching = get_ec_matching_query(bank_account, company, amount_condition)
|
|
||||||
queries.extend([ec_amount_matching])
|
|
||||||
|
|
||||||
return queries
|
return queries
|
||||||
|
|
||||||
|
|
||||||
@@ -604,37 +620,3 @@ def get_pi_matching_query(amount_condition):
|
|||||||
AND ifnull(clearance_date, '') = ""
|
AND ifnull(clearance_date, '') = ""
|
||||||
AND cash_bank_account = %(bank_account)s
|
AND cash_bank_account = %(bank_account)s
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def get_ec_matching_query(bank_account, company, amount_condition):
|
|
||||||
# get matching Expense Claim query
|
|
||||||
mode_of_payments = [
|
|
||||||
x["parent"]
|
|
||||||
for x in frappe.db.get_all(
|
|
||||||
"Mode of Payment Account", filters={"default_account": bank_account}, fields=["parent"]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
mode_of_payments = "('" + "', '".join(mode_of_payments) + "' )"
|
|
||||||
company_currency = get_company_currency(company)
|
|
||||||
return f"""
|
|
||||||
SELECT
|
|
||||||
( CASE WHEN employee = %(party)s THEN 1 ELSE 0 END
|
|
||||||
+ 1 ) AS rank,
|
|
||||||
'Expense Claim' as doctype,
|
|
||||||
name,
|
|
||||||
total_sanctioned_amount as paid_amount,
|
|
||||||
'' as reference_no,
|
|
||||||
'' as reference_date,
|
|
||||||
employee as party,
|
|
||||||
'Employee' as party_type,
|
|
||||||
posting_date,
|
|
||||||
'{company_currency}' as currency
|
|
||||||
FROM
|
|
||||||
`tabExpense Claim`
|
|
||||||
WHERE
|
|
||||||
total_sanctioned_amount {amount_condition} %(amount)s
|
|
||||||
AND docstatus = 1
|
|
||||||
AND is_paid = 1
|
|
||||||
AND ifnull(clearance_date, '') = ""
|
|
||||||
AND mode_of_payment in {mode_of_payments}
|
|
||||||
"""
|
|
||||||
|
|||||||
@@ -3,28 +3,21 @@
|
|||||||
|
|
||||||
frappe.ui.form.on("Bank Transaction", {
|
frappe.ui.form.on("Bank Transaction", {
|
||||||
onload(frm) {
|
onload(frm) {
|
||||||
frm.set_query("payment_document", "payment_entries", function () {
|
frm.set_query("payment_document", "payment_entries", function() {
|
||||||
|
const payment_doctypes = frm.events.get_payment_doctypes(frm);
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
name: [
|
name: ["in", payment_doctypes],
|
||||||
"in",
|
|
||||||
[
|
|
||||||
"Payment Entry",
|
|
||||||
"Journal Entry",
|
|
||||||
"Sales Invoice",
|
|
||||||
"Purchase Invoice",
|
|
||||||
"Expense Claim",
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
bank_account: function (frm) {
|
|
||||||
|
bank_account: function(frm) {
|
||||||
set_bank_statement_filter(frm);
|
set_bank_statement_filter(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
setup: function (frm) {
|
setup: function(frm) {
|
||||||
frm.set_query("party_type", function () {
|
frm.set_query("party_type", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
@@ -33,6 +26,16 @@ frappe.ui.form.on("Bank Transaction", {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get_payment_doctypes: function() {
|
||||||
|
// get payment doctypes from all the apps
|
||||||
|
return [
|
||||||
|
"Payment Entry",
|
||||||
|
"Journal Entry",
|
||||||
|
"Sales Invoice",
|
||||||
|
"Purchase Invoice",
|
||||||
|
];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("Bank Transaction Payments", {
|
frappe.ui.form.on("Bank Transaction Payments", {
|
||||||
|
|||||||
@@ -58,18 +58,10 @@ class BankTransaction(StatusUpdater):
|
|||||||
|
|
||||||
def clear_linked_payment_entries(self, for_cancel=False):
|
def clear_linked_payment_entries(self, for_cancel=False):
|
||||||
for payment_entry in self.payment_entries:
|
for payment_entry in self.payment_entries:
|
||||||
if payment_entry.payment_document in [
|
if payment_entry.payment_document == "Sales Invoice":
|
||||||
"Payment Entry",
|
|
||||||
"Journal Entry",
|
|
||||||
"Purchase Invoice",
|
|
||||||
"Expense Claim",
|
|
||||||
"Loan Repayment",
|
|
||||||
"Loan Disbursement",
|
|
||||||
]:
|
|
||||||
self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
|
|
||||||
|
|
||||||
elif payment_entry.payment_document == "Sales Invoice":
|
|
||||||
self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
|
self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
|
||||||
|
elif payment_entry.payment_document in get_doctypes_for_bank_reconciliation():
|
||||||
|
self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
|
||||||
|
|
||||||
def clear_simple_entry(self, payment_entry, for_cancel=False):
|
def clear_simple_entry(self, payment_entry, for_cancel=False):
|
||||||
if payment_entry.payment_document == "Payment Entry":
|
if payment_entry.payment_document == "Payment Entry":
|
||||||
@@ -95,6 +87,12 @@ class BankTransaction(StatusUpdater):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_doctypes_for_bank_reconciliation():
|
||||||
|
"""Get Bank Reconciliation doctypes from all the apps"""
|
||||||
|
return frappe.get_hooks("bank_reconciliation_doctypes")
|
||||||
|
|
||||||
|
|
||||||
def get_reconciled_bank_transactions(payment_entry):
|
def get_reconciled_bank_transactions(payment_entry):
|
||||||
reconciled_bank_transactions = frappe.get_all(
|
reconciled_bank_transactions = frappe.get_all(
|
||||||
"Bank Transaction Payments",
|
"Bank Transaction Payments",
|
||||||
|
|||||||
@@ -498,6 +498,15 @@ period_closing_doctypes = [
|
|||||||
"Stock Entry",
|
"Stock Entry",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
bank_reconciliation_doctypes = [
|
||||||
|
"Payment Entry",
|
||||||
|
"Journal Entry",
|
||||||
|
"Purchase Invoice",
|
||||||
|
"Sales Invoice",
|
||||||
|
"Loan Repayment",
|
||||||
|
"Loan Disbursement",
|
||||||
|
]
|
||||||
|
|
||||||
accounting_dimension_doctypes = [
|
accounting_dimension_doctypes = [
|
||||||
"GL Entry",
|
"GL Entry",
|
||||||
"Payment Ledger Entry",
|
"Payment Ledger Entry",
|
||||||
@@ -536,6 +545,11 @@ accounting_dimension_doctypes = [
|
|||||||
"Sales Order",
|
"Sales Order",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# get matching queries for Bank Reconciliation
|
||||||
|
get_matching_queries = (
|
||||||
|
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_matching_queries"
|
||||||
|
)
|
||||||
|
|
||||||
regional_overrides = {
|
regional_overrides = {
|
||||||
"France": {
|
"France": {
|
||||||
"erpnext.tests.test_regional.test_method": "erpnext.regional.france.utils.test_method"
|
"erpnext.tests.test_regional.test_method": "erpnext.regional.france.utils.test_method"
|
||||||
|
|||||||
@@ -169,62 +169,46 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
|
|||||||
label: __("Filters"),
|
label: __("Filters"),
|
||||||
depends_on: "eval:doc.action=='Match Against Voucher'",
|
depends_on: "eval:doc.action=='Match Against Voucher'",
|
||||||
},
|
},
|
||||||
{
|
];
|
||||||
fieldtype: "Check",
|
|
||||||
label: "Payment Entry",
|
frappe.call({
|
||||||
fieldname: "payment_entry",
|
method: "erpnext.accounts.doctype.bank_transaction.bank_transaction.get_doctypes_for_bank_reconciliation",
|
||||||
onchange: () => this.update_options(),
|
callback: (r) => {
|
||||||
},
|
$.each(r.message, (_i, entry) => {
|
||||||
{
|
if (_i % 3 == 0) {
|
||||||
fieldtype: "Check",
|
fields.push({
|
||||||
label: "Journal Entry",
|
fieldtype: "Column Break",
|
||||||
fieldname: "journal_entry",
|
});
|
||||||
onchange: () => this.update_options(),
|
}
|
||||||
},
|
fields.push({
|
||||||
{
|
fieldtype: "Check",
|
||||||
fieldtype: "Check",
|
label: entry,
|
||||||
label: "Loan Repayment",
|
fieldname: frappe.scrub(entry),
|
||||||
fieldname: "loan_repayment",
|
onchange: () => this.update_options(),
|
||||||
onchange: () => this.update_options(),
|
});
|
||||||
},
|
});
|
||||||
{
|
|
||||||
fieldname: "column_break_5",
|
fields.push(...this.get_voucher_fields());
|
||||||
fieldtype: "Column Break",
|
|
||||||
},
|
me.dialog = new frappe.ui.Dialog({
|
||||||
{
|
title: __("Reconcile the Bank Transaction"),
|
||||||
fieldtype: "Check",
|
fields: fields,
|
||||||
label: "Sales Invoice",
|
size: "large",
|
||||||
fieldname: "sales_invoice",
|
primary_action: (values) =>
|
||||||
onchange: () => this.update_options(),
|
this.reconciliation_dialog_primary_action(values),
|
||||||
},
|
});
|
||||||
{
|
}
|
||||||
fieldtype: "Check",
|
});
|
||||||
label: "Purchase Invoice",
|
}
|
||||||
fieldname: "purchase_invoice",
|
|
||||||
onchange: () => this.update_options(),
|
get_voucher_fields() {
|
||||||
},
|
return [
|
||||||
{
|
{
|
||||||
fieldtype: "Check",
|
fieldtype: "Check",
|
||||||
label: "Show Only Exact Amount",
|
label: "Show Only Exact Amount",
|
||||||
fieldname: "exact_match",
|
fieldname: "exact_match",
|
||||||
onchange: () => this.update_options(),
|
onchange: () => this.update_options(),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
fieldname: "column_break_5",
|
|
||||||
fieldtype: "Column Break",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldtype: "Check",
|
|
||||||
label: "Expense Claim",
|
|
||||||
fieldname: "expense_claim",
|
|
||||||
onchange: () => this.update_options(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldtype: "Check",
|
|
||||||
label: "Loan Disbursement",
|
|
||||||
fieldname: "loan_disbursement",
|
|
||||||
onchange: () => this.update_options(),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
fieldtype: "Section Break",
|
fieldtype: "Section Break",
|
||||||
fieldname: "section_break_1",
|
fieldname: "section_break_1",
|
||||||
@@ -404,14 +388,6 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
|
|||||||
read_only: 1,
|
read_only: 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
me.dialog = new frappe.ui.Dialog({
|
|
||||||
title: __("Reconcile the Bank Transaction"),
|
|
||||||
fields: fields,
|
|
||||||
size: "large",
|
|
||||||
primary_action: (values) =>
|
|
||||||
this.reconciliation_dialog_primary_action(values),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get_selected_attributes() {
|
get_selected_attributes() {
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ frappe.ui.form.on("Authorization Rule", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
transaction: function(frm) {
|
transaction: function(frm) {
|
||||||
unhide_field(['system_role', 'system_user','value', 'based_on']);
|
unhide_field(['system_role', 'system_user', 'value', 'based_on']);
|
||||||
hide_field(['to_emp','to_designation']);
|
hide_field(['to_emp', 'to_designation']);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -41,8 +41,8 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
|||||||
else
|
else
|
||||||
unhide_field('value');
|
unhide_field('value');
|
||||||
|
|
||||||
unhide_field(['system_role', 'system_user','value']);
|
unhide_field(['system_role', 'system_user', 'value']);
|
||||||
hide_field(['to_emp','to_designation']);
|
hide_field(['to_emp', 'to_designation']);
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.fields_dict.system_user.get_query = function(doc, cdt, cdn) {
|
cur_frm.fields_dict.system_user.get_query = function(doc, cdt, cdn) {
|
||||||
|
|||||||
Reference in New Issue
Block a user