diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index b7f383fb13..b6c48c81b9 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -228,6 +228,10 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({ frappe.model.validate_missing(jvd, "account"); var party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to"; out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]); + + if (in_list(['Debit Note', 'Credit Note'], doc.voucher_type)) { + out.filters.push([jvd.reference_type, "is_return", "=", 1]); + } } if(in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) { diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index d082b60211..3132c937dd 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -331,7 +331,8 @@ class JournalEntry(AccountsController): for reference_name, total in iteritems(self.reference_totals): reference_type = self.reference_types[reference_name] - if reference_type in ("Sales Invoice", "Purchase Invoice"): + if (reference_type in ("Sales Invoice", "Purchase Invoice") and + self.voucher_type not in ['Debit Note', 'Credit Note']): invoice = frappe.db.get_value(reference_type, reference_name, ["docstatus", "outstanding_amount"], as_dict=1) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 92803a6312..ea76126d8c 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -535,6 +535,20 @@ class PaymentEntry(AccountsController): "amount": self.total_allocated_amount * (tax_details['tax']['rate'] / 100) } + def set_gain_or_loss(self, account_details=None): + if not self.difference_amount: + self.set_difference_amount() + + row = { + 'amount': self.difference_amount + } + + if account_details: + row.update(account_details) + + self.append('deductions', row) + self.set_unallocated_amount() + @frappe.whitelist() def get_outstanding_reference_documents(args): diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js index 4c24a9fc97..d3992d5111 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js @@ -16,6 +16,20 @@ frappe.ui.form.on("Payment Reconciliation Payment", { })[0].outstanding_amount; frappe.model.set_value(cdt, cdn, "allocated_amount", Math.min(invoice_amount, row.amount)); + + frm.call({ + doc: frm.doc, + method: 'get_difference_amount', + args: { + child_row: row + }, + callback: function(r, rt) { + if(r.message) { + frappe.model.set_value(cdt, cdn, + "difference_amount", r.message); + } + } + }); } } }); @@ -104,6 +118,91 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext reconcile: function() { var me = this; + var show_dialog = me.frm.doc.payments.filter(d => d.difference_amount && !d.difference_account); + + if (show_dialog && show_dialog.length) { + + this.data = []; + const dialog = new frappe.ui.Dialog({ + title: __("Select Difference Account"), + fields: [ + { + fieldname: "payments", fieldtype: "Table", label: __("Payments"), + data: this.data, in_place_edit: true, + get_data: () => { + return this.data; + }, + fields: [{ + fieldtype:'Data', + fieldname:"docname", + in_list_view: 1, + hidden: 1 + }, { + fieldtype:'Data', + fieldname:"reference_name", + label: __("Voucher No"), + in_list_view: 1, + read_only: 1 + }, { + fieldtype:'Link', + options: 'Account', + in_list_view: 1, + label: __("Difference Account"), + fieldname: 'difference_account', + reqd: 1, + get_query: function() { + return { + filters: { + company: me.frm.doc.company, + is_group: 0 + } + } + } + }, { + fieldtype:'Currency', + in_list_view: 1, + label: __("Difference Amount"), + fieldname: 'difference_amount', + read_only: 1 + }] + }, + ], + primary_action: function() { + const args = dialog.get_values()["payments"]; + + args.forEach(d => { + frappe.model.set_value("Payment Reconciliation Payment", d.docname, + "difference_account", d.difference_account); + }); + + me.reconcile_payment_entries(); + dialog.hide(); + }, + primary_action_label: __('Reconcile Entries') + }); + + this.frm.doc.payments.forEach(d => { + if (d.difference_amount && !d.difference_account) { + dialog.fields_dict.payments.df.data.push({ + 'docname': d.name, + 'reference_name': d.reference_name, + 'difference_amount': d.difference_amount, + 'difference_account': d.difference_account, + }); + } + }); + + this.data = dialog.fields_dict.payments.df.data; + dialog.fields_dict.payments.grid.refresh(); + dialog.show(); + } else { + this.reconcile_payment_entries(); + } + }, + + reconcile_payment_entries: function() { + var me = this; + return this.frm.call({ doc: me.frm.doc, method: 'reconcile', diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index a625494972..b74eed5841 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -3,10 +3,11 @@ from __future__ import unicode_literals import frappe, erpnext -from frappe.utils import flt +from frappe.utils import flt, today from frappe import msgprint, _ from frappe.model.document import Document -from erpnext.accounts.utils import get_outstanding_invoices +from erpnext.accounts.utils import (get_outstanding_invoices, + update_reference_in_payment_entry, reconcile_against_document) from erpnext.controllers.accounts_controller import get_advance_payment_entries class PaymentReconciliation(Document): @@ -20,7 +21,10 @@ class PaymentReconciliation(Document): payment_entries = self.get_payment_entries() journal_entries = self.get_jv_entries() - self.add_payment_entries(payment_entries + journal_entries) + if self.party_type in ["Customer", "Supplier"]: + dr_or_cr_notes = self.get_dr_or_cr_notes() + + self.add_payment_entries(payment_entries + journal_entries + dr_or_cr_notes) def get_payment_entries(self): order_doctype = "Sales Order" if self.party_type=="Customer" else "Purchase Order" @@ -71,6 +75,34 @@ class PaymentReconciliation(Document): return list(journal_entries) + def get_dr_or_cr_notes(self): + dr_or_cr = ("credit_in_account_currency" + if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency") + + reconciled_dr_or_cr = ("debit_in_account_currency" + if dr_or_cr == "credit_in_account_currency" else "credit_in_account_currency") + + voucher_type = ('Sales Invoice' + if self.party_type == 'Customer' else "Purchase Invoice") + + return frappe.db.sql(""" SELECT `tab{doc}`.name as reference_name, %(voucher_type)s as reference_type, + (sum(`tabGL Entry`.{dr_or_cr}) - sum(`tabGL Entry`.{reconciled_dr_or_cr})) as amount + FROM `tab{doc}`, `tabGL Entry` + WHERE + (`tab{doc}`.name = `tabGL Entry`.against_voucher or `tab{doc}`.name = `tabGL Entry`.voucher_no) + and `tab{doc}`.is_return = 1 and `tabGL Entry`.against_voucher_type = %(voucher_type)s + and `tab{doc}`.docstatus = 1 and `tabGL Entry`.party = %(party)s + and `tabGL Entry`.party_type = %(party_type)s and `tabGL Entry`.account = %(account)s + GROUP BY `tabSales Invoice`.name + Having + amount > 0 + """.format(doc=voucher_type, dr_or_cr=dr_or_cr, reconciled_dr_or_cr=reconciled_dr_or_cr), { + 'party': self.party, + 'party_type': self.party_type, + 'voucher_type': voucher_type, + 'account': self.receivable_payable_account + }, as_dict=1) + def add_payment_entries(self, entries): self.set('payments', []) for e in entries: @@ -114,36 +146,67 @@ class PaymentReconciliation(Document): if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency") lst = [] + dr_or_cr_notes = [] for e in self.get('payments'): + reconciled_entry = [] if e.invoice_number and e.allocated_amount: - lst.append(frappe._dict({ - 'voucher_type': e.reference_type, - 'voucher_no' : e.reference_name, - 'voucher_detail_no' : e.reference_row, - 'against_voucher_type' : e.invoice_type, - 'against_voucher' : e.invoice_number, - 'account' : self.receivable_payable_account, - 'party_type': self.party_type, - 'party': self.party, - 'is_advance' : e.is_advance, - 'dr_or_cr' : dr_or_cr, - 'unadjusted_amount' : flt(e.amount), - 'allocated_amount' : flt(e.allocated_amount) - })) + if e.reference_type in ['Sales Invoice', 'Purchase Invoice']: + reconciled_entry = dr_or_cr_notes + else: + reconciled_entry = lst + + reconciled_entry.append(self.get_payment_details(e, dr_or_cr)) if lst: - from erpnext.accounts.utils import reconcile_against_document reconcile_against_document(lst) - msgprint(_("Successfully Reconciled")) - self.get_unreconciled_entries() + if dr_or_cr_notes: + reconcile_dr_cr_note(dr_or_cr_notes) + + msgprint(_("Successfully Reconciled")) + self.get_unreconciled_entries() + + def get_payment_details(self, row, dr_or_cr): + return frappe._dict({ + 'voucher_type': row.reference_type, + 'voucher_no' : row.reference_name, + 'voucher_detail_no' : row.reference_row, + 'against_voucher_type' : row.invoice_type, + 'against_voucher' : row.invoice_number, + 'account' : self.receivable_payable_account, + 'party_type': self.party_type, + 'party': self.party, + 'is_advance' : row.is_advance, + 'dr_or_cr' : dr_or_cr, + 'unadjusted_amount' : flt(row.amount), + 'allocated_amount' : flt(row.allocated_amount), + 'difference_amount': row.difference_amount, + 'difference_account': row.difference_account + }) + + def get_difference_amount(self, child_row): + if child_row.get("reference_type") != 'Payment Entry': return + + child_row = frappe._dict(child_row) + + if child_row.invoice_number and " | " in child_row.invoice_number: + child_row.invoice_type, child_row.invoice_number = child_row.invoice_number.split(" | ") + + dr_or_cr = ("credit_in_account_currency" + if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency") + + row = self.get_payment_details(child_row, dr_or_cr) + + doc = frappe.get_doc(row.voucher_type, row.voucher_no) + update_reference_in_payment_entry(row, doc, do_not_save=True) + + return doc.difference_amount def check_mandatory_to_fetch(self): for fieldname in ["company", "party_type", "party", "receivable_payable_account"]: if not self.get(fieldname): frappe.throw(_("Please select {0} first").format(self.meta.get_label(fieldname))) - def validate_invoice(self): if not self.get("invoices"): frappe.throw(_("No records found in the Invoice table")) @@ -188,3 +251,41 @@ class PaymentReconciliation(Document): cond += " and `{0}` <= {1}".format(dr_or_cr, flt(self.maximum_amount)) return cond + +def reconcile_dr_cr_note(dr_cr_notes): + for d in dr_cr_notes: + voucher_type = ('Credit Note' + if d.voucher_type == 'Sales Invoice' else 'Debit Note') + + dr_or_cr = ('credit_in_account_currency' + if d.reference_type == 'Sales Invoice' else 'debit_in_account_currency') + + reconcile_dr_or_cr = ('debit_in_account_currency' + if dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency') + + jv = frappe.get_doc({ + "doctype": "Journal Entry", + "voucher_type": voucher_type, + "posting_date": today(), + "accounts": [ + { + 'account': d.account, + 'party': d.party, + 'party_type': d.party_type, + reconcile_dr_or_cr: (abs(d.allocated_amount) + if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)), + 'reference_type': d.against_voucher_type, + 'reference_name': d.against_voucher + }, + { + 'account': d.account, + 'party': d.party, + 'party_type': d.party_type, + dr_or_cr: abs(d.allocated_amount), + 'reference_type': d.voucher_type, + 'reference_name': d.voucher_no + } + ] + }) + + jv.submit() \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json index 814257c047..018bfd028a 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json @@ -1,389 +1,127 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2014-07-09 16:13:35.452759", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, + "creation": "2014-07-09 16:13:35.452759", + "doctype": "DocType", + "editable_grid": 1, + "field_order": [ + "reference_type", + "reference_name", + "posting_date", + "is_advance", + "reference_row", + "col_break1", + "invoice_number", + "amount", + "allocated_amount", + "section_break_10", + "difference_account", + "difference_amount", + "sec_break1", + "remark" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "reference_type", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Reference Type", - "length": 0, - "no_copy": 0, - "options": "DocType", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "reference_type", + "fieldtype": "Link", + "label": "Reference Type", + "options": "DocType", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 3, - "fieldname": "reference_name", - "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Reference Name", - "length": 0, - "no_copy": 0, - "options": "reference_type", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "reference_name", + "fieldtype": "Dynamic Link", + "in_list_view": 1, + "label": "Reference Name", + "options": "reference_type", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "posting_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Posting Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "posting_date", + "fieldtype": "Date", + "label": "Posting Date", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "is_advance", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Is Advance", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "is_advance", + "fieldtype": "Data", + "hidden": 1, + "label": "Is Advance", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "reference_row", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Reference Row", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "reference_row", + "fieldtype": "Data", + "hidden": 1, + "label": "Reference Row", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "col_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "col_break1", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 3, - "fieldname": "invoice_number", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Invoice Number", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "invoice_number", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Invoice Number", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Amount", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 2, - "fieldname": "allocated_amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Allocated amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "columns": 2, + "fieldname": "allocated_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Allocated amount", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sec_break1", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "sec_break1", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "remark", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Remark", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "remark", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Remark", + "read_only": 1 + }, + { + "columns": 2, + "fieldname": "difference_account", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Difference Account", + "options": "Account" + }, + { + "fieldname": "difference_amount", + "fieldtype": "Currency", + "label": "Difference Amount", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "section_break_10", + "fieldtype": "Section Break" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "menu_index": 0, - "modified": "2019-01-07 16:52:07.567027", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Payment Reconciliation Payment", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 + ], + "istable": 1, + "modified": "2019-06-24 00:08:11.150796", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payment Reconciliation Payment", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC" } \ No newline at end of file diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 7a230a7edb..7a1f6c57c2 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -435,7 +435,7 @@ def update_reference_in_journal_entry(d, jv_obj): jv_obj.flags.ignore_validate_update_after_submit = True jv_obj.save(ignore_permissions=True) -def update_reference_in_payment_entry(d, payment_entry): +def update_reference_in_payment_entry(d, payment_entry, do_not_save=False): reference_details = { "reference_doctype": d.against_voucher_type, "reference_name": d.against_voucher, @@ -466,7 +466,17 @@ def update_reference_in_payment_entry(d, payment_entry): payment_entry.setup_party_account_field() payment_entry.set_missing_values() payment_entry.set_amounts() - payment_entry.save(ignore_permissions=True) + + if d.difference_amount and d.difference_account: + payment_entry.set_gain_or_loss(account_details={ + 'account': d.difference_account, + 'cost_center': payment_entry.cost_center or frappe.get_cached_value('Company', + payment_entry.company, "cost_center"), + 'amount': d.difference_amount + }) + + if not do_not_save: + payment_entry.save(ignore_permissions=True) def unlink_ref_doc_from_payment_entries(ref_doc): remove_ref_doc_link_from_jv(ref_doc.doctype, ref_doc.name)