diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index 0c15d6a207..1f2d12f47f 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -49,15 +49,8 @@ class AccountingPeriod(Document): @frappe.whitelist() def get_doctypes_for_closing(self): docs_for_closing = [] - doctypes = [ - "Sales Invoice", - "Purchase Invoice", - "Journal Entry", - "Payroll Entry", - "Bank Clearance", - "Asset", - "Stock Entry", - ] + doctypes = frappe.get_hooks("period_closing_doctypes") + closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes] for closed_doctype in closed_doctypes: docs_for_closing.append(closed_doctype) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index 3cc28a3dc8..b539bfec4c 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -240,25 +240,6 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro me.frm.set_query("reference_name", "accounts", function(doc, cdt, cdn) { var jvd = frappe.get_doc(cdt, cdn); - // expense claim - if(jvd.reference_type==="Expense Claim") { - return { - filters: { - 'total_sanctioned_amount': ['>', 0], - 'status': ['!=', 'Paid'], - 'docstatus': 1 - } - }; - } - - if(jvd.reference_type==="Employee Advance") { - return { - filters: { - 'docstatus': 1 - } - }; - } - // journal entry if(jvd.reference_type==="Journal Entry") { frappe.model.validate_missing(jvd, "account"); @@ -271,13 +252,6 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro }; } - // payroll entry - if(jvd.reference_type==="Payroll Entry") { - return { - query: "erpnext.payroll.doctype.payroll_entry.payroll_entry.get_payroll_entries_for_jv", - }; - } - var out = { filters: [ [jvd.reference_type, "docstatus", "=", 1] diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 0260eae857..56909119ba 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -83,7 +83,6 @@ class JournalEntry(AccountsController): self.update_advance_paid() self.update_inter_company_jv() self.update_invoice_discounting() - self.update_status_for_full_and_final_statement() def on_cancel(self): from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries @@ -97,7 +96,6 @@ class JournalEntry(AccountsController): self.unlink_inter_company_jv() self.unlink_asset_adjustment_entry() self.update_invoice_discounting() - self.update_status_for_full_and_final_statement() def get_title(self): return self.pay_to_recd_from or self.accounts[0].account @@ -106,21 +104,13 @@ class JournalEntry(AccountsController): advance_paid = frappe._dict() for d in self.get("accounts"): if d.is_advance: - if d.reference_type in ("Sales Order", "Purchase Order", "Employee Advance"): + if d.reference_type in frappe.get_hooks("advance_payment_doctypes"): advance_paid.setdefault(d.reference_type, []).append(d.reference_name) for voucher_type, order_list in advance_paid.items(): for voucher_no in list(set(order_list)): frappe.get_doc(voucher_type, voucher_no).set_total_advance_paid() - def update_status_for_full_and_final_statement(self): - for entry in self.accounts: - if entry.reference_type == "Full and Final Statement": - if self.docstatus == 1: - frappe.db.set_value("Full and Final Statement", entry.reference_name, "status", "Paid") - elif self.docstatus == 2: - frappe.db.set_value("Full and Final Statement", entry.reference_name, "status", "Unpaid") - def validate_inter_company_accounts(self): if ( self.voucher_type == "Inter Company Journal Entry" diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index d7fae6d2a3..0f53079403 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -110,8 +110,6 @@ frappe.ui.form.on('Payment Entry', { var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"]; } else if (frm.doc.party_type == "Supplier") { var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"]; - } else if (frm.doc.party_type == "Employee") { - var doctypes = ["Expense Claim", "Journal Entry"]; } else { var doctypes = ["Journal Entry"]; } @@ -140,17 +138,12 @@ frappe.ui.form.on('Payment Entry', { const child = locals[cdt][cdn]; const filters = {"docstatus": 1, "company": doc.company}; const party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice', - 'Purchase Order', 'Expense Claim', 'Fees', 'Dunning']; + 'Purchase Order', 'Dunning']; if (in_list(party_type_doctypes, child.reference_doctype)) { filters[doc.party_type.toLowerCase()] = doc.party; } - if(child.reference_doctype == "Expense Claim") { - filters["docstatus"] = 1; - filters["is_paid"] = 0; - } - return { filters: filters }; @@ -730,7 +723,7 @@ frappe.ui.form.on('Payment Entry', { c.payment_term = d.payment_term; c.allocated_amount = d.allocated_amount; - if(!in_list(["Sales Order", "Purchase Order", "Expense Claim", "Fees"], d.voucher_type)) { + if(!in_list(frm.events.get_order_doctypes(frm), d.voucher_type)) { if(flt(d.outstanding_amount) > 0) total_positive_outstanding += flt(d.outstanding_amount); else @@ -745,7 +738,7 @@ frappe.ui.form.on('Payment Entry', { } else { c.exchange_rate = 1; } - if (in_list(['Sales Invoice', 'Purchase Invoice', "Expense Claim", "Fees"], d.reference_doctype)){ + if (in_list(frm.events.get_invoice_doctypes(frm), d.reference_doctype)){ c.due_date = d.due_date; } }); @@ -776,6 +769,14 @@ frappe.ui.form.on('Payment Entry', { }); }, + get_order_doctypes: function(frm) { + return ["Sales Order", "Purchase Order"]; + }, + + get_invoice_doctypes: function(frm) { + return ["Sales Invoice", "Purchase Invoice"]; + }, + allocate_party_amount_against_ref_docs: function(frm, paid_amount, paid_amount_change) { var total_positive_outstanding_including_order = 0; var total_negative_outstanding = 0; @@ -946,14 +947,6 @@ frappe.ui.form.on('Payment Entry', { frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Purchase Order, Purchase Invoice or Journal Entry", [row.idx])); return false; } - - if(frm.doc.party_type=="Employee" && - !in_list(["Expense Claim", "Journal Entry"], row.reference_doctype) - ) { - frappe.model.set_value(row.doctype, row.name, "against_voucher_type", null); - frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Expense Claim or Journal Entry", [row.idx])); - return false; - } } if (row) { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index c9746aba73..c8a574687f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -293,14 +293,7 @@ class PaymentEntry(AccountsController): frappe.throw(_("{0} is mandatory").format(self.meta.get_label(field))) def validate_reference_documents(self): - if self.party_type == "Customer": - valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning") - elif self.party_type == "Supplier": - valid_reference_doctypes = ("Purchase Order", "Purchase Invoice", "Journal Entry") - elif self.party_type == "Employee": - valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance", "Gratuity") - elif self.party_type == "Shareholder": - valid_reference_doctypes = "Journal Entry" + valid_reference_doctypes = self.get_valid_reference_doctypes() for d in self.get("references"): if not d.allocated_amount: @@ -326,7 +319,7 @@ class PaymentEntry(AccountsController): else: self.validate_journal_entry() - if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim", "Fees"): + if d.reference_doctype in frappe.get_hooks("invoice_doctypes"): if self.party_type == "Customer": ref_party_account = ( get_party_account_based_on_invoice_discounting(d.reference_name) or ref_doc.debit_to @@ -352,6 +345,16 @@ class PaymentEntry(AccountsController): if ref_doc.docstatus != 1: frappe.throw(_("{0} {1} must be submitted").format(d.reference_doctype, d.reference_name)) + def get_valid_reference_doctypes(self): + if self.party_type == "Customer": + return ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning") + elif self.party_type == "Supplier": + return ("Purchase Order", "Purchase Invoice", "Journal Entry") + elif self.party_type == "Shareholder": + return ("Journal Entry",) + elif self.party_type == "Employee": + return ("Journal Entry",) + def validate_paid_invoices(self): no_oustanding_refs = {} @@ -974,12 +977,7 @@ class PaymentEntry(AccountsController): def update_advance_paid(self): if self.payment_type in ("Receive", "Pay") and self.party: for d in self.get("references"): - if d.allocated_amount and d.reference_doctype in ( - "Sales Order", - "Purchase Order", - "Employee Advance", - "Gratuity", - ): + if d.allocated_amount and d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"): frappe.get_doc(d.reference_doctype, d.reference_name).set_total_advance_paid() def on_recurring(self, reference_doc, auto_repeat_doc): @@ -1235,7 +1233,7 @@ def get_outstanding_reference_documents(args): for d in outstanding_invoices: d["exchange_rate"] = 1 if party_account_currency != company_currency: - if d.voucher_type in ("Sales Invoice", "Purchase Invoice", "Expense Claim"): + if d.voucher_type in frappe.get_hooks("invoice_doctypes"): d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate") elif d.voucher_type == "Journal Entry": d["exchange_rate"] = get_exchange_rate( @@ -1562,20 +1560,17 @@ def get_outstanding_on_journal_entry(name): @frappe.whitelist() def get_reference_details(reference_doctype, reference_name, party_account_currency): - total_amount = outstanding_amount = exchange_rate = bill_no = None + total_amount = outstanding_amount = exchange_rate = None + ref_doc = frappe.get_doc(reference_doctype, reference_name) company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency( ref_doc.company ) - if reference_doctype == "Fees": - total_amount = ref_doc.get("grand_total") + if reference_doctype == "Dunning": + total_amount = outstanding_amount = ref_doc.get("dunning_amount") exchange_rate = 1 - outstanding_amount = ref_doc.get("outstanding_amount") - elif reference_doctype == "Dunning": - total_amount = ref_doc.get("dunning_amount") - exchange_rate = 1 - outstanding_amount = ref_doc.get("dunning_amount") + elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1: total_amount = ref_doc.get("total_amount") if ref_doc.multi_currency: @@ -1585,16 +1580,8 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre else: exchange_rate = 1 outstanding_amount = get_outstanding_on_journal_entry(reference_name) + elif reference_doctype != "Journal Entry": - if ref_doc.doctype == "Expense Claim": - total_amount = flt(ref_doc.total_sanctioned_amount) + flt(ref_doc.total_taxes_and_charges) - elif ref_doc.doctype == "Employee Advance": - total_amount = ref_doc.advance_amount - exchange_rate = ref_doc.get("exchange_rate") - if party_account_currency != ref_doc.currency: - total_amount = flt(total_amount) * flt(exchange_rate) - elif ref_doc.doctype == "Gratuity": - total_amount = ref_doc.amount if not total_amount: if party_account_currency == company_currency: total_amount = ref_doc.base_grand_total @@ -1607,26 +1594,12 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre exchange_rate = ref_doc.get("conversion_rate") or get_exchange_rate( party_account_currency, company_currency, ref_doc.posting_date ) + if reference_doctype in ("Sales Invoice", "Purchase Invoice"): outstanding_amount = ref_doc.get("outstanding_amount") - bill_no = ref_doc.get("bill_no") - elif reference_doctype == "Expense Claim": - outstanding_amount = ( - flt(ref_doc.get("total_sanctioned_amount")) - + flt(ref_doc.get("total_taxes_and_charges")) - - flt(ref_doc.get("total_amount_reimbursed")) - - flt(ref_doc.get("total_advance_amount")) - ) - elif reference_doctype == "Employee Advance": - outstanding_amount = flt(ref_doc.advance_amount) - flt(ref_doc.paid_amount) - if party_account_currency != ref_doc.currency: - outstanding_amount = flt(outstanding_amount) * flt(exchange_rate) - if party_account_currency == company_currency: - exchange_rate = 1 - elif reference_doctype == "Gratuity": - outstanding_amount = ref_doc.amount - flt(ref_doc.paid_amount) else: outstanding_amount = flt(total_amount) - flt(ref_doc.advance_paid) + else: # Get the exchange rate based on the posting date of the ref doc. exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date) @@ -1637,114 +1610,11 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre "total_amount": flt(total_amount), "outstanding_amount": flt(outstanding_amount), "exchange_rate": flt(exchange_rate), - "bill_no": bill_no, + "bill_no": ref_doc.get("bill_no"), } ) -def get_amounts_based_on_reference_doctype( - reference_doctype, ref_doc, party_account_currency, company_currency, reference_name -): - total_amount = outstanding_amount = exchange_rate = None - if reference_doctype == "Fees": - total_amount = ref_doc.get("grand_total") - exchange_rate = 1 - outstanding_amount = ref_doc.get("outstanding_amount") - elif reference_doctype == "Dunning": - total_amount = ref_doc.get("dunning_amount") - exchange_rate = 1 - outstanding_amount = ref_doc.get("dunning_amount") - elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1: - total_amount = ref_doc.get("total_amount") - if ref_doc.multi_currency: - exchange_rate = get_exchange_rate( - party_account_currency, company_currency, ref_doc.posting_date - ) - else: - exchange_rate = 1 - outstanding_amount = get_outstanding_on_journal_entry(reference_name) - - return total_amount, outstanding_amount, exchange_rate - - -def get_amounts_based_on_ref_doc( - reference_doctype, ref_doc, party_account_currency, company_currency -): - total_amount = outstanding_amount = exchange_rate = None - if ref_doc.doctype == "Expense Claim": - total_amount = flt(ref_doc.total_sanctioned_amount) + flt(ref_doc.total_taxes_and_charges) - elif ref_doc.doctype == "Employee Advance": - total_amount, exchange_rate = get_total_amount_exchange_rate_for_employee_advance( - party_account_currency, ref_doc - ) - - if not total_amount: - total_amount, exchange_rate = get_total_amount_exchange_rate_base_on_currency( - party_account_currency, company_currency, ref_doc - ) - - if not exchange_rate: - # Get the exchange rate from the original ref doc - # or get it based on the posting date of the ref doc - exchange_rate = ref_doc.get("conversion_rate") or get_exchange_rate( - party_account_currency, company_currency, ref_doc.posting_date - ) - - outstanding_amount, exchange_rate, bill_no = get_bill_no_and_update_amounts( - reference_doctype, ref_doc, total_amount, exchange_rate, party_account_currency, company_currency - ) - - return total_amount, outstanding_amount, exchange_rate, bill_no - - -def get_total_amount_exchange_rate_for_employee_advance(party_account_currency, ref_doc): - total_amount = ref_doc.advance_amount - exchange_rate = ref_doc.get("exchange_rate") - if party_account_currency != ref_doc.currency: - total_amount = flt(total_amount) * flt(exchange_rate) - - return total_amount, exchange_rate - - -def get_total_amount_exchange_rate_base_on_currency( - party_account_currency, company_currency, ref_doc -): - exchange_rate = None - if party_account_currency == company_currency: - total_amount = ref_doc.base_grand_total - exchange_rate = 1 - else: - total_amount = ref_doc.grand_total - - return total_amount, exchange_rate - - -def get_bill_no_and_update_amounts( - reference_doctype, ref_doc, total_amount, exchange_rate, party_account_currency, company_currency -): - outstanding_amount = bill_no = None - if reference_doctype in ("Sales Invoice", "Purchase Invoice"): - outstanding_amount = ref_doc.get("outstanding_amount") - bill_no = ref_doc.get("bill_no") - elif reference_doctype == "Expense Claim": - outstanding_amount = ( - flt(ref_doc.get("total_sanctioned_amount")) - + flt(ref_doc.get("total_taxes_and_charges")) - - flt(ref_doc.get("total_amount_reimbursed")) - - flt(ref_doc.get("total_advance_amount")) - ) - elif reference_doctype == "Employee Advance": - outstanding_amount = flt(ref_doc.advance_amount) - flt(ref_doc.paid_amount) - if party_account_currency != ref_doc.currency: - outstanding_amount = flt(outstanding_amount) * flt(exchange_rate) - if party_account_currency == company_currency: - exchange_rate = 1 - else: - outstanding_amount = flt(total_amount) - flt(ref_doc.advance_paid) - - return outstanding_amount, exchange_rate, bill_no - - @frappe.whitelist() def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=None): reference_doc = None @@ -1863,8 +1733,6 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= pe.set_missing_values() if party_account and bank: - if dt == "Employee Advance": - reference_doc = doc pe.set_exchange_rate(ref_doc=reference_doc) pe.set_amounts() if discount_amount: @@ -1899,8 +1767,6 @@ def set_party_type(dt): party_type = "Customer" elif dt in ("Purchase Invoice", "Purchase Order"): party_type = "Supplier" - elif dt in ("Expense Claim", "Employee Advance", "Gratuity"): - party_type = "Employee" return party_type @@ -1911,12 +1777,6 @@ def set_party_account(dt, dn, doc, party_type): party_account = doc.credit_to elif dt == "Fees": party_account = doc.receivable_account - elif dt == "Employee Advance": - party_account = doc.advance_account - elif dt == "Expense Claim": - party_account = doc.payable_account - elif dt == "Gratuity": - party_account = doc.payable_account else: party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company) return party_account @@ -1951,24 +1811,12 @@ def set_grand_total_and_outstanding_amount(party_amount, dt, party_account_curre else: grand_total = doc.rounded_total or doc.grand_total outstanding_amount = doc.outstanding_amount - elif dt in ("Expense Claim"): - grand_total = doc.total_sanctioned_amount + doc.total_taxes_and_charges - outstanding_amount = doc.grand_total - doc.total_amount_reimbursed - elif dt == "Employee Advance": - grand_total = flt(doc.advance_amount) - outstanding_amount = flt(doc.advance_amount) - flt(doc.paid_amount) - if party_account_currency != doc.currency: - grand_total = flt(doc.advance_amount) * flt(doc.exchange_rate) - outstanding_amount = (flt(doc.advance_amount) - flt(doc.paid_amount)) * flt(doc.exchange_rate) elif dt == "Fees": grand_total = doc.grand_total outstanding_amount = doc.outstanding_amount elif dt == "Dunning": grand_total = doc.grand_total outstanding_amount = doc.grand_total - elif dt == "Gratuity": - grand_total = doc.amount - outstanding_amount = flt(doc.amount) - flt(doc.paid_amount) else: if party_account_currency == doc.company_currency: grand_total = flt(doc.get("base_rounded_total") or doc.base_grand_total) @@ -1990,8 +1838,6 @@ def set_paid_amount_and_received_amount( received_amount = bank_amount else: received_amount = paid_amount * doc.get("conversion_rate", 1) - if dt == "Employee Advance": - received_amount = paid_amount * doc.get("exchange_rate", 1) else: received_amount = abs(outstanding_amount) if bank_amount: @@ -1999,8 +1845,6 @@ def set_paid_amount_and_received_amount( else: # if party account currency and bank currency is different then populate paid amount as well paid_amount = received_amount * doc.get("conversion_rate", 1) - if dt == "Employee Advance": - paid_amount = received_amount * doc.get("exchange_rate", 1) return paid_amount, received_amount diff --git a/erpnext/hooks.py b/erpnext/hooks.py index d629b70268..a2dc20586f 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -472,6 +472,19 @@ payment_gateway_enabled = "erpnext.accounts.utils.create_payment_gateway_account communication_doctypes = ["Customer", "Supplier"] +advance_payment_doctypes = ["Sales Order", "Purchase Order"] + +invoice_doctypes = ["Sales Invoice", "Purchase Invoice"] + +period_closing_doctypes = [ + "Sales Invoice", + "Purchase Invoice", + "Journal Entry", + "Bank Clearance", + "Asset", + "Stock Entry", +] + accounting_dimension_doctypes = [ "GL Entry", "Payment Ledger Entry", @@ -479,12 +492,8 @@ accounting_dimension_doctypes = [ "Purchase Invoice", "Payment Entry", "Asset", - "Expense Claim", - "Expense Claim Detail", - "Expense Taxes and Charges", "Stock Entry", "Budget", - "Payroll Entry", "Delivery Note", "Sales Invoice Item", "Purchase Invoice Item",