refactor: payment reconciliation tool (#27128)
This commit is contained in:
parent
c37cec9b9d
commit
3e404f15ff
@ -2,46 +2,10 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.provide("erpnext.accounts");
|
frappe.provide("erpnext.accounts");
|
||||||
|
|
||||||
frappe.ui.form.on("Payment Reconciliation Payment", {
|
|
||||||
invoice_number: function(frm, cdt, cdn) {
|
|
||||||
var row = locals[cdt][cdn];
|
|
||||||
if(row.invoice_number) {
|
|
||||||
var parts = row.invoice_number.split(' | ');
|
|
||||||
var invoice_type = parts[0];
|
|
||||||
var invoice_number = parts[1];
|
|
||||||
|
|
||||||
var invoice_amount = frm.doc.invoices.filter(function(d) {
|
|
||||||
return d.invoice_type === invoice_type && d.invoice_number === invoice_number;
|
|
||||||
})[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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationController extends frappe.ui.form.Controller {
|
erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationController extends frappe.ui.form.Controller {
|
||||||
onload() {
|
onload() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
this.frm.set_query("party", function() {
|
|
||||||
check_mandatory(me.frm);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.frm.set_query("party_type", function() {
|
this.frm.set_query("party_type", function() {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
"filters": {
|
||||||
@ -88,15 +52,36 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
this.frm.disable_save();
|
this.frm.disable_save();
|
||||||
this.toggle_primary_action();
|
|
||||||
|
if (this.frm.doc.receivable_payable_account) {
|
||||||
|
this.frm.add_custom_button(__('Get Unreconciled Entries'), () =>
|
||||||
|
this.frm.trigger("get_unreconciled_entries")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (this.frm.doc.invoices.length && this.frm.doc.payments.length) {
|
||||||
|
this.frm.add_custom_button(__('Allocate'), () =>
|
||||||
|
this.frm.trigger("allocate")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (this.frm.doc.allocation.length) {
|
||||||
|
this.frm.add_custom_button(__('Reconcile'), () =>
|
||||||
|
this.frm.trigger("reconcile")
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onload_post_render() {
|
company() {
|
||||||
this.toggle_primary_action();
|
var me = this;
|
||||||
|
this.frm.set_value('receivable_payable_account', '');
|
||||||
|
me.frm.clear_table("allocation");
|
||||||
|
me.frm.clear_table("invoices");
|
||||||
|
me.frm.clear_table("payments");
|
||||||
|
me.frm.refresh_fields();
|
||||||
|
me.frm.trigger('party');
|
||||||
}
|
}
|
||||||
|
|
||||||
party() {
|
party() {
|
||||||
var me = this
|
var me = this;
|
||||||
if (!me.frm.doc.receivable_payable_account && me.frm.doc.party_type && me.frm.doc.party) {
|
if (!me.frm.doc.receivable_payable_account && me.frm.doc.party_type && me.frm.doc.party) {
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
method: "erpnext.accounts.party.get_party_account",
|
method: "erpnext.accounts.party.get_party_account",
|
||||||
@ -109,6 +94,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
if (!r.exc && r.message) {
|
if (!r.exc && r.message) {
|
||||||
me.frm.set_value("receivable_payable_account", r.message);
|
me.frm.set_value("receivable_payable_account", r.message);
|
||||||
}
|
}
|
||||||
|
me.frm.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -120,16 +106,41 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
doc: me.frm.doc,
|
doc: me.frm.doc,
|
||||||
method: 'get_unreconciled_entries',
|
method: 'get_unreconciled_entries',
|
||||||
callback: function(r, rt) {
|
callback: function(r, rt) {
|
||||||
me.set_invoice_options();
|
if (!(me.frm.doc.payments.length || me.frm.doc.invoices.length)) {
|
||||||
me.toggle_primary_action();
|
frappe.throw({message: __("No invoice and payment records found for this party")});
|
||||||
|
}
|
||||||
|
me.frm.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allocate() {
|
||||||
|
var me = this;
|
||||||
|
let payments = me.frm.fields_dict.payments.grid.get_selected_children();
|
||||||
|
if (!(payments.length)) {
|
||||||
|
payments = me.frm.doc.payments;
|
||||||
|
}
|
||||||
|
let invoices = me.frm.fields_dict.invoices.grid.get_selected_children();
|
||||||
|
if (!(invoices.length)) {
|
||||||
|
invoices = me.frm.doc.invoices;
|
||||||
|
}
|
||||||
|
return me.frm.call({
|
||||||
|
doc: me.frm.doc,
|
||||||
|
method: 'allocate_entries',
|
||||||
|
args: {
|
||||||
|
payments: payments,
|
||||||
|
invoices: invoices
|
||||||
|
},
|
||||||
|
callback: function() {
|
||||||
|
me.frm.refresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
reconcile() {
|
reconcile() {
|
||||||
var me = this;
|
var me = this;
|
||||||
var show_dialog = me.frm.doc.payments.filter(d => d.difference_amount && !d.difference_account);
|
var show_dialog = me.frm.doc.allocation.filter(d => d.difference_amount && !d.difference_account);
|
||||||
|
|
||||||
if (show_dialog && show_dialog.length) {
|
if (show_dialog && show_dialog.length) {
|
||||||
|
|
||||||
@ -138,7 +149,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
title: __("Select Difference Account"),
|
title: __("Select Difference Account"),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: "payments", fieldtype: "Table", label: __("Payments"),
|
fieldname: "allocation", fieldtype: "Table", label: __("Allocation"),
|
||||||
data: this.data, in_place_edit: true,
|
data: this.data, in_place_edit: true,
|
||||||
get_data: () => {
|
get_data: () => {
|
||||||
return this.data;
|
return this.data;
|
||||||
@ -179,10 +190,10 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
const args = dialog.get_values()["payments"];
|
const args = dialog.get_values()["allocation"];
|
||||||
|
|
||||||
args.forEach(d => {
|
args.forEach(d => {
|
||||||
frappe.model.set_value("Payment Reconciliation Payment", d.docname,
|
frappe.model.set_value("Payment Reconciliation Allocation", d.docname,
|
||||||
"difference_account", d.difference_account);
|
"difference_account", d.difference_account);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -192,9 +203,9 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
primary_action_label: __('Reconcile Entries')
|
primary_action_label: __('Reconcile Entries')
|
||||||
});
|
});
|
||||||
|
|
||||||
this.frm.doc.payments.forEach(d => {
|
this.frm.doc.allocation.forEach(d => {
|
||||||
if (d.difference_amount && !d.difference_account) {
|
if (d.difference_amount && !d.difference_account) {
|
||||||
dialog.fields_dict.payments.df.data.push({
|
dialog.fields_dict.allocation.df.data.push({
|
||||||
'docname': d.name,
|
'docname': d.name,
|
||||||
'reference_name': d.reference_name,
|
'reference_name': d.reference_name,
|
||||||
'difference_amount': d.difference_amount,
|
'difference_amount': d.difference_amount,
|
||||||
@ -203,8 +214,8 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.data = dialog.fields_dict.payments.df.data;
|
this.data = dialog.fields_dict.allocation.df.data;
|
||||||
dialog.fields_dict.payments.grid.refresh();
|
dialog.fields_dict.allocation.grid.refresh();
|
||||||
dialog.show();
|
dialog.show();
|
||||||
} else {
|
} else {
|
||||||
this.reconcile_payment_entries();
|
this.reconcile_payment_entries();
|
||||||
@ -218,48 +229,12 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
doc: me.frm.doc,
|
doc: me.frm.doc,
|
||||||
method: 'reconcile',
|
method: 'reconcile',
|
||||||
callback: function(r, rt) {
|
callback: function(r, rt) {
|
||||||
me.set_invoice_options();
|
me.frm.clear_table("allocation");
|
||||||
me.toggle_primary_action();
|
me.frm.refresh_fields();
|
||||||
|
me.frm.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
set_invoice_options() {
|
|
||||||
var me = this;
|
|
||||||
var invoices = [];
|
|
||||||
|
|
||||||
$.each(me.frm.doc.invoices || [], function(i, row) {
|
|
||||||
if (row.invoice_number && !in_list(invoices, row.invoice_number))
|
|
||||||
invoices.push(row.invoice_type + " | " + row.invoice_number);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (invoices) {
|
|
||||||
this.frm.fields_dict.payments.grid.update_docfield_property(
|
|
||||||
'invoice_number', 'options', "\n" + invoices.join("\n")
|
|
||||||
);
|
|
||||||
|
|
||||||
$.each(me.frm.doc.payments || [], function(i, p) {
|
|
||||||
if(!in_list(invoices, cstr(p.invoice_number))) p.invoice_number = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh_field("payments");
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle_primary_action() {
|
|
||||||
if ((this.frm.doc.payments || []).length) {
|
|
||||||
this.frm.fields_dict.reconcile.$input
|
|
||||||
&& this.frm.fields_dict.reconcile.$input.addClass("btn-primary");
|
|
||||||
this.frm.fields_dict.get_unreconciled_entries.$input
|
|
||||||
&& this.frm.fields_dict.get_unreconciled_entries.$input.removeClass("btn-primary");
|
|
||||||
} else {
|
|
||||||
this.frm.fields_dict.reconcile.$input
|
|
||||||
&& this.frm.fields_dict.reconcile.$input.removeClass("btn-primary");
|
|
||||||
this.frm.fields_dict.get_unreconciled_entries.$input
|
|
||||||
&& this.frm.fields_dict.get_unreconciled_entries.$input.addClass("btn-primary");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extend_cscript(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
|
extend_cscript(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
|
||||||
|
@ -1,622 +1,206 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"allow_copy": 1,
|
"allow_copy": 1,
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2014-07-09 12:04:51.681583",
|
"creation": "2014-07-09 12:04:51.681583",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 0,
|
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"company",
|
||||||
|
"party_type",
|
||||||
|
"column_break_4",
|
||||||
|
"party",
|
||||||
|
"receivable_payable_account",
|
||||||
|
"col_break1",
|
||||||
|
"from_invoice_date",
|
||||||
|
"to_invoice_date",
|
||||||
|
"minimum_invoice_amount",
|
||||||
|
"maximum_invoice_amount",
|
||||||
|
"invoice_limit",
|
||||||
|
"column_break_13",
|
||||||
|
"from_payment_date",
|
||||||
|
"to_payment_date",
|
||||||
|
"minimum_payment_amount",
|
||||||
|
"maximum_payment_amount",
|
||||||
|
"payment_limit",
|
||||||
|
"bank_cash_account",
|
||||||
|
"sec_break1",
|
||||||
|
"invoices",
|
||||||
|
"column_break_15",
|
||||||
|
"payments",
|
||||||
|
"sec_break2",
|
||||||
|
"allocation"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"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": "Company",
|
"label": "Company",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "party_type",
|
"fieldname": "party_type",
|
||||||
"fieldtype": "Link",
|
"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": "Party Type",
|
"label": "Party Type",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "DocType",
|
"options": "DocType",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"depends_on": "eval:doc.party_type",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "party",
|
"fieldname": "party",
|
||||||
"fieldtype": "Dynamic Link",
|
"fieldtype": "Dynamic 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": "Party",
|
"label": "Party",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "party_type",
|
"options": "party_type",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"depends_on": "eval:doc.company && doc.party",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "receivable_payable_account",
|
"fieldname": "receivable_payable_account",
|
||||||
"fieldtype": "Link",
|
"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": "Receivable / Payable Account",
|
"label": "Receivable / Payable Account",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Account",
|
"options": "Account",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"description": "This filter will be applied to Journal Entry.",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "bank_cash_account",
|
"fieldname": "bank_cash_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Bank / Cash Account",
|
"label": "Bank / Cash Account",
|
||||||
"length": 0,
|
"options": "Account"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Account",
|
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"collapsible": 1,
|
||||||
"allow_in_quick_entry": 0,
|
"collapsible_depends_on": "eval: doc.invoices.length == 0",
|
||||||
"allow_on_submit": 0,
|
"depends_on": "eval:doc.receivable_payable_account",
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "col_break1",
|
"fieldname": "col_break1",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Filters"
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"depends_on": "eval:(doc.payments).length || (doc.invoices).length",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "from_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"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": "From Invoice Date",
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "to_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"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": "To Invoice Date",
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "minimum_amount",
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"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": "Minimum Invoice Amount",
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "maximum_amount",
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"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": "Maximum Invoice Amount",
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "System will fetch all the entries if limit value is zero.",
|
|
||||||
"fieldname": "limit",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"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": "Limit",
|
|
||||||
"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": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "get_unreconciled_entries",
|
|
||||||
"fieldtype": "Button",
|
|
||||||
"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": "Get Unreconciled Entries",
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "sec_break1",
|
"fieldname": "sec_break1",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Unreconciled Entries"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Unreconciled Payment Details",
|
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "payments",
|
"fieldname": "payments",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"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": "Payments",
|
"label": "Payments",
|
||||||
"length": 0,
|
"options": "Payment Reconciliation Payment"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Payment Reconciliation Payment",
|
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"depends_on": "allocation",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "reconcile",
|
|
||||||
"fieldtype": "Button",
|
|
||||||
"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": "Reconcile",
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "sec_break2",
|
"fieldname": "sec_break2",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Allocated Entries"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Invoice/Journal Entry Details",
|
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "invoices",
|
"fieldname": "invoices",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"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": "Invoices",
|
"label": "Invoices",
|
||||||
"length": 0,
|
"options": "Payment Reconciliation Invoice"
|
||||||
"no_copy": 0,
|
},
|
||||||
"options": "Payment Reconciliation Invoice",
|
{
|
||||||
"permlevel": 0,
|
"fieldname": "column_break_15",
|
||||||
"print_hide": 0,
|
"fieldtype": "Column Break"
|
||||||
"print_hide_if_no_value": 0,
|
},
|
||||||
"read_only": 1,
|
{
|
||||||
"remember_last_selected_value": 0,
|
"fieldname": "allocation",
|
||||||
"report_hide": 0,
|
"fieldtype": "Table",
|
||||||
"reqd": 0,
|
"label": "Allocation",
|
||||||
"search_index": 0,
|
"options": "Payment Reconciliation Allocation"
|
||||||
"set_only_once": 0,
|
},
|
||||||
"translatable": 0,
|
{
|
||||||
"unique": 0
|
"fieldname": "column_break_4",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "from_invoice_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "From Invoice Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "to_invoice_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "To Invoice Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "minimum_invoice_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Minimum Invoice Amount"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "System will fetch all the entries if limit value is zero.",
|
||||||
|
"fieldname": "invoice_limit",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Invoice Limit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_13",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "from_payment_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "From Payment Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "to_payment_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "To Payment Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "minimum_payment_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Minimum Payment Amount"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "maximum_payment_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Maximum Payment Amount"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "payment_limit",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Payment Limit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "maximum_invoice_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Maximum Invoice Amount"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
"icon": "icon-resize-horizontal",
|
"icon": "icon-resize-horizontal",
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"links": [],
|
||||||
"max_attachments": 0,
|
"modified": "2021-08-30 13:05:51.977861",
|
||||||
"menu_index": 0,
|
|
||||||
"modified": "2019-01-15 17:42:21.135214",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Reconciliation",
|
"name": "Payment Reconciliation",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 0,
|
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 0,
|
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 0,
|
|
||||||
"role": "Accounts Manager",
|
"role": "Accounts Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 0,
|
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 0,
|
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 0,
|
|
||||||
"role": "Accounts User",
|
"role": "Accounts User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
from frappe.utils import flt, today
|
from frappe.utils import flt, today, getdate, nowdate
|
||||||
from frappe import msgprint, _
|
from frappe import msgprint, _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.accounts.utils import (get_outstanding_invoices,
|
from erpnext.accounts.utils import (get_outstanding_invoices,
|
||||||
@ -27,24 +27,32 @@ class PaymentReconciliation(Document):
|
|||||||
else:
|
else:
|
||||||
dr_or_cr_notes = []
|
dr_or_cr_notes = []
|
||||||
|
|
||||||
self.add_payment_entries(payment_entries + journal_entries + dr_or_cr_notes)
|
non_reconciled_payments = payment_entries + journal_entries + dr_or_cr_notes
|
||||||
|
|
||||||
|
if self.payment_limit:
|
||||||
|
non_reconciled_payments = non_reconciled_payments[:self.payment_limit]
|
||||||
|
|
||||||
|
non_reconciled_payments = sorted(non_reconciled_payments, key=lambda k: k['posting_date'] or getdate(nowdate()))
|
||||||
|
|
||||||
|
self.add_payment_entries(non_reconciled_payments)
|
||||||
|
|
||||||
def get_payment_entries(self):
|
def get_payment_entries(self):
|
||||||
order_doctype = "Sales Order" if self.party_type=="Customer" else "Purchase Order"
|
order_doctype = "Sales Order" if self.party_type=="Customer" else "Purchase Order"
|
||||||
|
condition = self.get_conditions(get_payments=True)
|
||||||
payment_entries = get_advance_payment_entries(self.party_type, self.party,
|
payment_entries = get_advance_payment_entries(self.party_type, self.party,
|
||||||
self.receivable_payable_account, order_doctype, against_all_orders=True, limit=self.limit)
|
self.receivable_payable_account, order_doctype, against_all_orders=True, limit=self.payment_limit,
|
||||||
|
condition=condition)
|
||||||
|
|
||||||
return payment_entries
|
return payment_entries
|
||||||
|
|
||||||
def get_jv_entries(self):
|
def get_jv_entries(self):
|
||||||
|
condition = self.get_conditions()
|
||||||
dr_or_cr = ("credit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
|
dr_or_cr = ("credit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
|
||||||
else "debit_in_account_currency")
|
else "debit_in_account_currency")
|
||||||
|
|
||||||
bank_account_condition = "t2.against_account like %(bank_cash_account)s" \
|
bank_account_condition = "t2.against_account like %(bank_cash_account)s" \
|
||||||
if self.bank_cash_account else "1=1"
|
if self.bank_cash_account else "1=1"
|
||||||
|
|
||||||
limit_cond = "limit %s" % self.limit if self.limit else ""
|
|
||||||
|
|
||||||
journal_entries = frappe.db.sql("""
|
journal_entries = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
"Journal Entry" as reference_type, t1.name as reference_name,
|
"Journal Entry" as reference_type, t1.name as reference_name,
|
||||||
@ -56,7 +64,7 @@ class PaymentReconciliation(Document):
|
|||||||
where
|
where
|
||||||
t1.name = t2.parent and t1.docstatus = 1 and t2.docstatus = 1
|
t1.name = t2.parent and t1.docstatus = 1 and t2.docstatus = 1
|
||||||
and t2.party_type = %(party_type)s and t2.party = %(party)s
|
and t2.party_type = %(party_type)s and t2.party = %(party)s
|
||||||
and t2.account = %(account)s and {dr_or_cr} > 0
|
and t2.account = %(account)s and {dr_or_cr} > 0 {condition}
|
||||||
and (t2.reference_type is null or t2.reference_type = '' or
|
and (t2.reference_type is null or t2.reference_type = '' or
|
||||||
(t2.reference_type in ('Sales Order', 'Purchase Order')
|
(t2.reference_type in ('Sales Order', 'Purchase Order')
|
||||||
and t2.reference_name is not null and t2.reference_name != ''))
|
and t2.reference_name is not null and t2.reference_name != ''))
|
||||||
@ -65,11 +73,11 @@ class PaymentReconciliation(Document):
|
|||||||
THEN 1=1
|
THEN 1=1
|
||||||
ELSE {bank_account_condition}
|
ELSE {bank_account_condition}
|
||||||
END)
|
END)
|
||||||
order by t1.posting_date {limit_cond}
|
order by t1.posting_date
|
||||||
""".format(**{
|
""".format(**{
|
||||||
"dr_or_cr": dr_or_cr,
|
"dr_or_cr": dr_or_cr,
|
||||||
"bank_account_condition": bank_account_condition,
|
"bank_account_condition": bank_account_condition,
|
||||||
"limit_cond": limit_cond
|
"condition": condition
|
||||||
}), {
|
}), {
|
||||||
"party_type": self.party_type,
|
"party_type": self.party_type,
|
||||||
"party": self.party,
|
"party": self.party,
|
||||||
@ -80,6 +88,7 @@ class PaymentReconciliation(Document):
|
|||||||
return list(journal_entries)
|
return list(journal_entries)
|
||||||
|
|
||||||
def get_dr_or_cr_notes(self):
|
def get_dr_or_cr_notes(self):
|
||||||
|
condition = self.get_conditions(get_return_invoices=True)
|
||||||
dr_or_cr = ("credit_in_account_currency"
|
dr_or_cr = ("credit_in_account_currency"
|
||||||
if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency")
|
if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency")
|
||||||
|
|
||||||
@ -90,7 +99,7 @@ class PaymentReconciliation(Document):
|
|||||||
if self.party_type == 'Customer' else "Purchase Invoice")
|
if self.party_type == 'Customer' else "Purchase Invoice")
|
||||||
|
|
||||||
return frappe.db.sql(""" SELECT doc.name as reference_name, %(voucher_type)s as reference_type,
|
return frappe.db.sql(""" SELECT doc.name as reference_name, %(voucher_type)s as reference_type,
|
||||||
(sum(gl.{dr_or_cr}) - sum(gl.{reconciled_dr_or_cr})) as amount,
|
(sum(gl.{dr_or_cr}) - sum(gl.{reconciled_dr_or_cr})) as amount, doc.posting_date,
|
||||||
account_currency as currency
|
account_currency as currency
|
||||||
FROM `tab{doc}` doc, `tabGL Entry` gl
|
FROM `tab{doc}` doc, `tabGL Entry` gl
|
||||||
WHERE
|
WHERE
|
||||||
@ -100,15 +109,17 @@ class PaymentReconciliation(Document):
|
|||||||
and gl.against_voucher_type = %(voucher_type)s
|
and gl.against_voucher_type = %(voucher_type)s
|
||||||
and doc.docstatus = 1 and gl.party = %(party)s
|
and doc.docstatus = 1 and gl.party = %(party)s
|
||||||
and gl.party_type = %(party_type)s and gl.account = %(account)s
|
and gl.party_type = %(party_type)s and gl.account = %(account)s
|
||||||
and gl.is_cancelled = 0
|
and gl.is_cancelled = 0 {condition}
|
||||||
GROUP BY doc.name
|
GROUP BY doc.name
|
||||||
Having
|
Having
|
||||||
amount > 0
|
amount > 0
|
||||||
|
ORDER BY doc.posting_date
|
||||||
""".format(
|
""".format(
|
||||||
doc=voucher_type,
|
doc=voucher_type,
|
||||||
dr_or_cr=dr_or_cr,
|
dr_or_cr=dr_or_cr,
|
||||||
reconciled_dr_or_cr=reconciled_dr_or_cr,
|
reconciled_dr_or_cr=reconciled_dr_or_cr,
|
||||||
party_type_field=frappe.scrub(self.party_type)),
|
party_type_field=frappe.scrub(self.party_type),
|
||||||
|
condition=condition or ""),
|
||||||
{
|
{
|
||||||
'party': self.party,
|
'party': self.party,
|
||||||
'party_type': self.party_type,
|
'party_type': self.party_type,
|
||||||
@ -116,22 +127,23 @@ class PaymentReconciliation(Document):
|
|||||||
'account': self.receivable_payable_account
|
'account': self.receivable_payable_account
|
||||||
}, as_dict=1)
|
}, as_dict=1)
|
||||||
|
|
||||||
def add_payment_entries(self, entries):
|
def add_payment_entries(self, non_reconciled_payments):
|
||||||
self.set('payments', [])
|
self.set('payments', [])
|
||||||
for e in entries:
|
|
||||||
|
for payment in non_reconciled_payments:
|
||||||
row = self.append('payments', {})
|
row = self.append('payments', {})
|
||||||
row.update(e)
|
row.update(payment)
|
||||||
|
|
||||||
def get_invoice_entries(self):
|
def get_invoice_entries(self):
|
||||||
#Fetch JVs, Sales and Purchase Invoices for 'invoices' to reconcile against
|
#Fetch JVs, Sales and Purchase Invoices for 'invoices' to reconcile against
|
||||||
|
|
||||||
condition = self.check_condition()
|
condition = self.get_conditions(get_invoices=True)
|
||||||
|
|
||||||
non_reconciled_invoices = get_outstanding_invoices(self.party_type, self.party,
|
non_reconciled_invoices = get_outstanding_invoices(self.party_type, self.party,
|
||||||
self.receivable_payable_account, condition=condition)
|
self.receivable_payable_account, condition=condition)
|
||||||
|
|
||||||
if self.limit:
|
if self.invoice_limit:
|
||||||
non_reconciled_invoices = non_reconciled_invoices[:self.limit]
|
non_reconciled_invoices = non_reconciled_invoices[:self.invoice_limit]
|
||||||
|
|
||||||
self.add_invoice_entries(non_reconciled_invoices)
|
self.add_invoice_entries(non_reconciled_invoices)
|
||||||
|
|
||||||
@ -139,41 +151,78 @@ class PaymentReconciliation(Document):
|
|||||||
#Populate 'invoices' with JVs and Invoices to reconcile against
|
#Populate 'invoices' with JVs and Invoices to reconcile against
|
||||||
self.set('invoices', [])
|
self.set('invoices', [])
|
||||||
|
|
||||||
for e in non_reconciled_invoices:
|
for entry in non_reconciled_invoices:
|
||||||
ent = self.append('invoices', {})
|
inv = self.append('invoices', {})
|
||||||
ent.invoice_type = e.get('voucher_type')
|
inv.invoice_type = entry.get('voucher_type')
|
||||||
ent.invoice_number = e.get('voucher_no')
|
inv.invoice_number = entry.get('voucher_no')
|
||||||
ent.invoice_date = e.get('posting_date')
|
inv.invoice_date = entry.get('posting_date')
|
||||||
ent.amount = flt(e.get('invoice_amount'))
|
inv.amount = flt(entry.get('invoice_amount'))
|
||||||
ent.currency = e.get('currency')
|
inv.currency = entry.get('currency')
|
||||||
ent.outstanding_amount = e.get('outstanding_amount')
|
inv.outstanding_amount = flt(entry.get('outstanding_amount'))
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def reconcile(self, args):
|
def allocate_entries(self, args):
|
||||||
for e in self.get('payments'):
|
self.validate_entries()
|
||||||
e.invoice_type = None
|
entries = []
|
||||||
if e.invoice_number and " | " in e.invoice_number:
|
for pay in args.get('payments'):
|
||||||
e.invoice_type, e.invoice_number = e.invoice_number.split(" | ")
|
pay.update({'unreconciled_amount': pay.get('amount')})
|
||||||
|
for inv in args.get('invoices'):
|
||||||
|
if pay.get('amount') >= inv.get('outstanding_amount'):
|
||||||
|
res = self.get_allocated_entry(pay, inv, inv['outstanding_amount'])
|
||||||
|
pay['amount'] = flt(pay.get('amount')) - flt(inv.get('outstanding_amount'))
|
||||||
|
inv['outstanding_amount'] = 0
|
||||||
|
else:
|
||||||
|
res = self.get_allocated_entry(pay, inv, pay['amount'])
|
||||||
|
inv['outstanding_amount'] = flt(inv.get('outstanding_amount')) - flt(pay.get('amount'))
|
||||||
|
pay['amount'] = 0
|
||||||
|
if pay.get('amount') == 0:
|
||||||
|
entries.append(res)
|
||||||
|
break
|
||||||
|
elif inv.get('outstanding_amount') == 0:
|
||||||
|
entries.append(res)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
self.get_invoice_entries()
|
self.set('allocation', [])
|
||||||
self.validate_invoice()
|
for entry in entries:
|
||||||
|
if entry['allocated_amount'] != 0:
|
||||||
|
row = self.append('allocation', {})
|
||||||
|
row.update(entry)
|
||||||
|
|
||||||
|
def get_allocated_entry(self, pay, inv, allocated_amount):
|
||||||
|
return frappe._dict({
|
||||||
|
'reference_type': pay.get('reference_type'),
|
||||||
|
'reference_name': pay.get('reference_name'),
|
||||||
|
'reference_row': pay.get('reference_row'),
|
||||||
|
'invoice_type': inv.get('invoice_type'),
|
||||||
|
'invoice_number': inv.get('invoice_number'),
|
||||||
|
'unreconciled_amount': pay.get('unreconciled_amount'),
|
||||||
|
'amount': pay.get('amount'),
|
||||||
|
'allocated_amount': allocated_amount,
|
||||||
|
'difference_amount': pay.get('difference_amount')
|
||||||
|
})
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def reconcile(self):
|
||||||
|
self.validate_allocation()
|
||||||
dr_or_cr = ("credit_in_account_currency"
|
dr_or_cr = ("credit_in_account_currency"
|
||||||
if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency")
|
if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit_in_account_currency")
|
||||||
|
|
||||||
lst = []
|
entry_list = []
|
||||||
dr_or_cr_notes = []
|
dr_or_cr_notes = []
|
||||||
for e in self.get('payments'):
|
for row in self.get('allocation'):
|
||||||
reconciled_entry = []
|
reconciled_entry = []
|
||||||
if e.invoice_number and e.allocated_amount:
|
if row.invoice_number and row.allocated_amount:
|
||||||
if e.reference_type in ['Sales Invoice', 'Purchase Invoice']:
|
if row.reference_type in ['Sales Invoice', 'Purchase Invoice']:
|
||||||
reconciled_entry = dr_or_cr_notes
|
reconciled_entry = dr_or_cr_notes
|
||||||
else:
|
else:
|
||||||
reconciled_entry = lst
|
reconciled_entry = entry_list
|
||||||
|
|
||||||
reconciled_entry.append(self.get_payment_details(e, dr_or_cr))
|
reconciled_entry.append(self.get_payment_details(row, dr_or_cr))
|
||||||
|
|
||||||
if lst:
|
if entry_list:
|
||||||
reconcile_against_document(lst)
|
reconcile_against_document(entry_list)
|
||||||
|
|
||||||
if dr_or_cr_notes:
|
if dr_or_cr_notes:
|
||||||
reconcile_dr_cr_note(dr_or_cr_notes, self.company)
|
reconcile_dr_cr_note(dr_or_cr_notes, self.company)
|
||||||
@ -183,98 +232,104 @@ class PaymentReconciliation(Document):
|
|||||||
|
|
||||||
def get_payment_details(self, row, dr_or_cr):
|
def get_payment_details(self, row, dr_or_cr):
|
||||||
return frappe._dict({
|
return frappe._dict({
|
||||||
'voucher_type': row.reference_type,
|
'voucher_type': row.get('reference_type'),
|
||||||
'voucher_no' : row.reference_name,
|
'voucher_no' : row.get('reference_name'),
|
||||||
'voucher_detail_no' : row.reference_row,
|
'voucher_detail_no' : row.get('reference_row'),
|
||||||
'against_voucher_type' : row.invoice_type,
|
'against_voucher_type' : row.get('invoice_type'),
|
||||||
'against_voucher' : row.invoice_number,
|
'against_voucher' : row.get('invoice_number'),
|
||||||
'account' : self.receivable_payable_account,
|
'account' : self.receivable_payable_account,
|
||||||
'party_type': self.party_type,
|
'party_type': self.party_type,
|
||||||
'party': self.party,
|
'party': self.party,
|
||||||
'is_advance' : row.is_advance,
|
'is_advance' : row.get('is_advance'),
|
||||||
'dr_or_cr' : dr_or_cr,
|
'dr_or_cr' : dr_or_cr,
|
||||||
'unadjusted_amount' : flt(row.amount),
|
'unreconciled_amount': flt(row.get('unreconciled_amount')),
|
||||||
'allocated_amount' : flt(row.allocated_amount),
|
'unadjusted_amount' : flt(row.get('amount')),
|
||||||
'difference_amount': row.difference_amount,
|
'allocated_amount' : flt(row.get('allocated_amount')),
|
||||||
'difference_account': row.difference_account
|
'difference_amount': flt(row.get('difference_amount')),
|
||||||
|
'difference_account': row.get('difference_account')
|
||||||
})
|
})
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
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):
|
def check_mandatory_to_fetch(self):
|
||||||
for fieldname in ["company", "party_type", "party", "receivable_payable_account"]:
|
for fieldname in ["company", "party_type", "party", "receivable_payable_account"]:
|
||||||
if not self.get(fieldname):
|
if not self.get(fieldname):
|
||||||
frappe.throw(_("Please select {0} first").format(self.meta.get_label(fieldname)))
|
frappe.throw(_("Please select {0} first").format(self.meta.get_label(fieldname)))
|
||||||
|
|
||||||
def validate_invoice(self):
|
def validate_entries(self):
|
||||||
if not self.get("invoices"):
|
if not self.get("invoices"):
|
||||||
frappe.throw(_("No records found in the Invoice table"))
|
frappe.throw(_("No records found in the Invoices table"))
|
||||||
|
|
||||||
if not self.get("payments"):
|
if not self.get("payments"):
|
||||||
frappe.throw(_("No records found in the Payment table"))
|
frappe.throw(_("No records found in the Payments table"))
|
||||||
|
|
||||||
|
def validate_allocation(self):
|
||||||
unreconciled_invoices = frappe._dict()
|
unreconciled_invoices = frappe._dict()
|
||||||
for d in self.get("invoices"):
|
|
||||||
unreconciled_invoices.setdefault(d.invoice_type, {}).setdefault(d.invoice_number, d.outstanding_amount)
|
for inv in self.get("invoices"):
|
||||||
|
unreconciled_invoices.setdefault(inv.invoice_type, {}).setdefault(inv.invoice_number, inv.outstanding_amount)
|
||||||
|
|
||||||
invoices_to_reconcile = []
|
invoices_to_reconcile = []
|
||||||
for p in self.get("payments"):
|
for row in self.get("allocation"):
|
||||||
if p.invoice_type and p.invoice_number and p.allocated_amount:
|
if row.invoice_type and row.invoice_number and row.allocated_amount:
|
||||||
invoices_to_reconcile.append(p.invoice_number)
|
invoices_to_reconcile.append(row.invoice_number)
|
||||||
|
|
||||||
if p.invoice_number not in unreconciled_invoices.get(p.invoice_type, {}):
|
if flt(row.amount) - flt(row.allocated_amount) < 0:
|
||||||
frappe.throw(_("{0}: {1} not found in Invoice Details table")
|
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equal to remaining payment amount {2}")
|
||||||
.format(p.invoice_type, p.invoice_number))
|
.format(row.idx, row.allocated_amount, row.amount))
|
||||||
|
|
||||||
if flt(p.allocated_amount) > flt(p.amount):
|
invoice_outstanding = unreconciled_invoices.get(row.invoice_type, {}).get(row.invoice_number)
|
||||||
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to Payment Entry amount {2}")
|
if flt(row.allocated_amount) - invoice_outstanding > 0.009:
|
||||||
.format(p.idx, p.allocated_amount, p.amount))
|
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equal to invoice outstanding amount {2}")
|
||||||
|
.format(row.idx, row.allocated_amount, invoice_outstanding))
|
||||||
invoice_outstanding = unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)
|
|
||||||
if flt(p.allocated_amount) - invoice_outstanding > 0.009:
|
|
||||||
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
|
|
||||||
.format(p.idx, p.allocated_amount, invoice_outstanding))
|
|
||||||
|
|
||||||
if not invoices_to_reconcile:
|
if not invoices_to_reconcile:
|
||||||
frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row"))
|
frappe.throw(_("No records found in Allocation table"))
|
||||||
|
|
||||||
def check_condition(self):
|
def get_conditions(self, get_invoices=False, get_payments=False, get_return_invoices=False):
|
||||||
cond = " and posting_date >= {0}".format(frappe.db.escape(self.from_date)) if self.from_date else ""
|
condition = " and company = '{0}' ".format(self.company)
|
||||||
cond += " and posting_date <= {0}".format(frappe.db.escape(self.to_date)) if self.to_date else ""
|
|
||||||
|
if get_invoices:
|
||||||
|
condition += " and posting_date >= {0}".format(frappe.db.escape(self.from_invoice_date)) if self.from_invoice_date else ""
|
||||||
|
condition += " and posting_date <= {0}".format(frappe.db.escape(self.to_invoice_date)) if self.to_invoice_date else ""
|
||||||
dr_or_cr = ("debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
|
dr_or_cr = ("debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
|
||||||
else "credit_in_account_currency")
|
else "credit_in_account_currency")
|
||||||
|
|
||||||
if self.minimum_amount:
|
if self.minimum_invoice_amount:
|
||||||
cond += " and `{0}` >= {1}".format(dr_or_cr, flt(self.minimum_amount))
|
condition += " and `{0}` >= {1}".format(dr_or_cr, flt(self.minimum_invoice_amount))
|
||||||
if self.maximum_amount:
|
if self.maximum_invoice_amount:
|
||||||
cond += " and `{0}` <= {1}".format(dr_or_cr, flt(self.maximum_amount))
|
condition += " and `{0}` <= {1}".format(dr_or_cr, flt(self.maximum_invoice_amount))
|
||||||
|
|
||||||
return cond
|
elif get_return_invoices:
|
||||||
|
condition = " and doc.company = '{0}' ".format(self.company)
|
||||||
|
condition += " and doc.posting_date >= {0}".format(frappe.db.escape(self.from_payment_date)) if self.from_payment_date else ""
|
||||||
|
condition += " and doc.posting_date <= {0}".format(frappe.db.escape(self.to_payment_date)) if self.to_payment_date else ""
|
||||||
|
dr_or_cr = ("gl.debit_in_account_currency" if erpnext.get_party_account_type(self.party_type) == 'Receivable'
|
||||||
|
else "gl.credit_in_account_currency")
|
||||||
|
|
||||||
|
if self.minimum_invoice_amount:
|
||||||
|
condition += " and `{0}` >= {1}".format(dr_or_cr, flt(self.minimum_payment_amount))
|
||||||
|
if self.maximum_invoice_amount:
|
||||||
|
condition += " and `{0}` <= {1}".format(dr_or_cr, flt(self.maximum_payment_amount))
|
||||||
|
|
||||||
|
else:
|
||||||
|
condition += " and posting_date >= {0}".format(frappe.db.escape(self.from_payment_date)) if self.from_payment_date else ""
|
||||||
|
condition += " and posting_date <= {0}".format(frappe.db.escape(self.to_payment_date)) if self.to_payment_date else ""
|
||||||
|
|
||||||
|
if self.minimum_payment_amount:
|
||||||
|
condition += " and unallocated_amount >= {0}".format(flt(self.minimum_payment_amount)) if get_payments \
|
||||||
|
else " and total_debit >= {0}".format(flt(self.minimum_payment_amount))
|
||||||
|
if self.maximum_payment_amount:
|
||||||
|
condition += " and unallocated_amount <= {0}".format(flt(self.maximum_payment_amount)) if get_payments \
|
||||||
|
else " and total_debit <= {0}".format(flt(self.maximum_payment_amount))
|
||||||
|
|
||||||
|
return condition
|
||||||
|
|
||||||
def reconcile_dr_cr_note(dr_cr_notes, company):
|
def reconcile_dr_cr_note(dr_cr_notes, company):
|
||||||
for d in dr_cr_notes:
|
for inv in dr_cr_notes:
|
||||||
voucher_type = ('Credit Note'
|
voucher_type = ('Credit Note'
|
||||||
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
|
if inv.voucher_type == 'Sales Invoice' else 'Debit Note')
|
||||||
|
|
||||||
reconcile_dr_or_cr = ('debit_in_account_currency'
|
reconcile_dr_or_cr = ('debit_in_account_currency'
|
||||||
if d.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
|
if inv.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
|
||||||
|
|
||||||
company_currency = erpnext.get_company_currency(company)
|
company_currency = erpnext.get_company_currency(company)
|
||||||
|
|
||||||
@ -283,25 +338,25 @@ def reconcile_dr_cr_note(dr_cr_notes, company):
|
|||||||
"voucher_type": voucher_type,
|
"voucher_type": voucher_type,
|
||||||
"posting_date": today(),
|
"posting_date": today(),
|
||||||
"company": company,
|
"company": company,
|
||||||
"multi_currency": 1 if d.currency != company_currency else 0,
|
"multi_currency": 1 if inv.currency != company_currency else 0,
|
||||||
"accounts": [
|
"accounts": [
|
||||||
{
|
{
|
||||||
'account': d.account,
|
'account': inv.account,
|
||||||
'party': d.party,
|
'party': inv.party,
|
||||||
'party_type': d.party_type,
|
'party_type': inv.party_type,
|
||||||
d.dr_or_cr: abs(d.allocated_amount),
|
inv.dr_or_cr: abs(inv.allocated_amount),
|
||||||
'reference_type': d.against_voucher_type,
|
'reference_type': inv.against_voucher_type,
|
||||||
'reference_name': d.against_voucher,
|
'reference_name': inv.against_voucher,
|
||||||
'cost_center': erpnext.get_default_cost_center(company)
|
'cost_center': erpnext.get_default_cost_center(company)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'account': d.account,
|
'account': inv.account,
|
||||||
'party': d.party,
|
'party': inv.party,
|
||||||
'party_type': d.party_type,
|
'party_type': inv.party_type,
|
||||||
reconcile_dr_or_cr: (abs(d.allocated_amount)
|
reconcile_dr_or_cr: (abs(inv.allocated_amount)
|
||||||
if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
|
if abs(inv.unadjusted_amount) > abs(inv.allocated_amount) else abs(inv.unadjusted_amount)),
|
||||||
'reference_type': d.voucher_type,
|
'reference_type': inv.voucher_type,
|
||||||
'reference_name': d.voucher_no,
|
'reference_name': inv.voucher_no,
|
||||||
'cost_center': erpnext.get_default_cost_center(company)
|
'cost_center': erpnext.get_default_cost_center(company)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestPaymentReconciliation(unittest.TestCase):
|
||||||
|
pass
|
@ -0,0 +1,137 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"creation": "2021-08-16 17:04:40.185167",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"reference_type",
|
||||||
|
"reference_name",
|
||||||
|
"column_break_3",
|
||||||
|
"invoice_type",
|
||||||
|
"invoice_number",
|
||||||
|
"section_break_6",
|
||||||
|
"allocated_amount",
|
||||||
|
"unreconciled_amount",
|
||||||
|
"amount",
|
||||||
|
"column_break_8",
|
||||||
|
"is_advance",
|
||||||
|
"section_break_5",
|
||||||
|
"difference_amount",
|
||||||
|
"column_break_7",
|
||||||
|
"difference_account"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "invoice_number",
|
||||||
|
"fieldtype": "Dynamic Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Invoice Number",
|
||||||
|
"options": "invoice_type",
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "allocated_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Allocated Amount",
|
||||||
|
"options": "Currency",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_3",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_5",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "difference_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Difference Account",
|
||||||
|
"options": "Account",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_7",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "difference_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Difference Amount",
|
||||||
|
"options": "Currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "reference_name",
|
||||||
|
"fieldtype": "Dynamic Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Reference Name",
|
||||||
|
"options": "reference_type",
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "is_advance",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Is Advance",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "reference_type",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Reference Type",
|
||||||
|
"options": "DocType",
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "invoice_type",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Invoice Type",
|
||||||
|
"options": "DocType",
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_6",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_8",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "unreconciled_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Unreconciled Amount",
|
||||||
|
"options": "Currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Amount",
|
||||||
|
"options": "Currency",
|
||||||
|
"read_only": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2021-08-30 10:58:42.665107",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Payment Reconciliation Allocation",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class PaymentReconciliationAllocation(Document):
|
||||||
|
pass
|
@ -44,7 +44,6 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "amount",
|
"fieldname": "amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Amount",
|
"label": "Amount",
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
@ -67,7 +66,7 @@
|
|||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-19 18:12:27.964073",
|
"modified": "2021-08-24 22:42:40.923179",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Reconciliation Invoice",
|
"name": "Payment Reconciliation Invoice",
|
||||||
|
@ -11,11 +11,7 @@
|
|||||||
"is_advance",
|
"is_advance",
|
||||||
"reference_row",
|
"reference_row",
|
||||||
"col_break1",
|
"col_break1",
|
||||||
"invoice_number",
|
|
||||||
"amount",
|
"amount",
|
||||||
"allocated_amount",
|
|
||||||
"section_break_10",
|
|
||||||
"difference_account",
|
|
||||||
"difference_amount",
|
"difference_amount",
|
||||||
"sec_break1",
|
"sec_break1",
|
||||||
"remark",
|
"remark",
|
||||||
@ -41,6 +37,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "posting_date",
|
"fieldname": "posting_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Posting Date",
|
"label": "Posting Date",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
@ -62,14 +59,6 @@
|
|||||||
"fieldname": "col_break1",
|
"fieldname": "col_break1",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"columns": 2,
|
|
||||||
"fieldname": "invoice_number",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Invoice Number",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "amount",
|
"fieldname": "amount",
|
||||||
@ -79,15 +68,6 @@
|
|||||||
"options": "currency",
|
"options": "currency",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"columns": 2,
|
|
||||||
"fieldname": "allocated_amount",
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Allocated amount",
|
|
||||||
"options": "currency",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "sec_break1",
|
"fieldname": "sec_break1",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
@ -95,41 +75,27 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "remark",
|
"fieldname": "remark",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Small Text",
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Remark",
|
"label": "Remark",
|
||||||
"read_only": 1
|
"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",
|
|
||||||
"options": "currency",
|
|
||||||
"print_hide": 1,
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_10",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "currency",
|
"fieldname": "currency",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Currency",
|
"label": "Currency",
|
||||||
"options": "Currency"
|
"options": "Currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "difference_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Difference Amount",
|
||||||
|
"options": "currency",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-19 18:12:41.682347",
|
"modified": "2021-08-30 10:51:48.140062",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Reconciliation Payment",
|
"name": "Payment Reconciliation Payment",
|
||||||
|
@ -341,31 +341,42 @@ def add_cc(args=None):
|
|||||||
|
|
||||||
def reconcile_against_document(args):
|
def reconcile_against_document(args):
|
||||||
"""
|
"""
|
||||||
Cancel JV, Update aginst document, split if required and resubmit jv
|
Cancel PE or JV, Update against document, split if required and resubmit
|
||||||
"""
|
"""
|
||||||
for d in args:
|
# To optimize making GL Entry for PE or JV with multiple references
|
||||||
|
reconciled_entries = {}
|
||||||
|
for row in args:
|
||||||
|
if not reconciled_entries.get((row.voucher_type, row.voucher_no)):
|
||||||
|
reconciled_entries[(row.voucher_type, row.voucher_no)] = []
|
||||||
|
|
||||||
check_if_advance_entry_modified(d)
|
reconciled_entries[(row.voucher_type, row.voucher_no)].append(row)
|
||||||
validate_allocated_amount(d)
|
|
||||||
|
for key, entries in reconciled_entries.items():
|
||||||
|
voucher_type = key[0]
|
||||||
|
voucher_no = key[1]
|
||||||
|
|
||||||
# cancel advance entry
|
# cancel advance entry
|
||||||
doc = frappe.get_doc(d.voucher_type, d.voucher_no)
|
doc = frappe.get_doc(voucher_type, voucher_no)
|
||||||
|
|
||||||
frappe.flags.ignore_party_validation = True
|
frappe.flags.ignore_party_validation = True
|
||||||
doc.make_gl_entries(cancel=1, adv_adj=1)
|
doc.make_gl_entries(cancel=1, adv_adj=1)
|
||||||
|
|
||||||
# update ref in advance entry
|
for entry in entries:
|
||||||
if d.voucher_type == "Journal Entry":
|
check_if_advance_entry_modified(entry)
|
||||||
update_reference_in_journal_entry(d, doc)
|
validate_allocated_amount(entry)
|
||||||
else:
|
|
||||||
update_reference_in_payment_entry(d, doc)
|
|
||||||
|
|
||||||
|
# update ref in advance entry
|
||||||
|
if voucher_type == "Journal Entry":
|
||||||
|
update_reference_in_journal_entry(entry, doc, do_not_save=True)
|
||||||
|
else:
|
||||||
|
update_reference_in_payment_entry(entry, doc, do_not_save=True)
|
||||||
|
|
||||||
|
doc.save(ignore_permissions=True)
|
||||||
# re-submit advance entry
|
# re-submit advance entry
|
||||||
doc = frappe.get_doc(d.voucher_type, d.voucher_no)
|
doc = frappe.get_doc(entry.voucher_type, entry.voucher_no)
|
||||||
doc.make_gl_entries(cancel = 0, adv_adj =1)
|
doc.make_gl_entries(cancel = 0, adv_adj =1)
|
||||||
frappe.flags.ignore_party_validation = False
|
frappe.flags.ignore_party_validation = False
|
||||||
|
|
||||||
if d.voucher_type in ('Payment Entry', 'Journal Entry'):
|
if entry.voucher_type in ('Payment Entry', 'Journal Entry'):
|
||||||
doc.update_expense_claim()
|
doc.update_expense_claim()
|
||||||
|
|
||||||
def check_if_advance_entry_modified(args):
|
def check_if_advance_entry_modified(args):
|
||||||
@ -374,6 +385,9 @@ def check_if_advance_entry_modified(args):
|
|||||||
check if amount is same
|
check if amount is same
|
||||||
check if jv is submitted
|
check if jv is submitted
|
||||||
"""
|
"""
|
||||||
|
if not args.get('unreconciled_amount'):
|
||||||
|
args.update({'unreconciled_amount': args.get('unadjusted_amount')})
|
||||||
|
|
||||||
ret = None
|
ret = None
|
||||||
if args.voucher_type == "Journal Entry":
|
if args.voucher_type == "Journal Entry":
|
||||||
ret = frappe.db.sql("""
|
ret = frappe.db.sql("""
|
||||||
@ -395,14 +409,14 @@ def check_if_advance_entry_modified(args):
|
|||||||
and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
|
and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
|
||||||
and t1.party_type = %(party_type)s and t1.party = %(party)s and t1.{0} = %(account)s
|
and t1.party_type = %(party_type)s and t1.party = %(party)s and t1.{0} = %(account)s
|
||||||
and t2.reference_doctype in ("", "Sales Order", "Purchase Order")
|
and t2.reference_doctype in ("", "Sales Order", "Purchase Order")
|
||||||
and t2.allocated_amount = %(unadjusted_amount)s
|
and t2.allocated_amount = %(unreconciled_amount)s
|
||||||
""".format(party_account_field), args)
|
""".format(party_account_field), args)
|
||||||
else:
|
else:
|
||||||
ret = frappe.db.sql("""select name from `tabPayment Entry`
|
ret = frappe.db.sql("""select name from `tabPayment Entry`
|
||||||
where
|
where
|
||||||
name = %(voucher_no)s and docstatus = 1
|
name = %(voucher_no)s and docstatus = 1
|
||||||
and party_type = %(party_type)s and party = %(party)s and {0} = %(account)s
|
and party_type = %(party_type)s and party = %(party)s and {0} = %(account)s
|
||||||
and unallocated_amount = %(unadjusted_amount)s
|
and unallocated_amount = %(unreconciled_amount)s
|
||||||
""".format(party_account_field), args)
|
""".format(party_account_field), args)
|
||||||
|
|
||||||
if not ret:
|
if not ret:
|
||||||
@ -415,58 +429,44 @@ def validate_allocated_amount(args):
|
|||||||
elif flt(args.get("allocated_amount"), precision) > flt(args.get("unadjusted_amount"), precision):
|
elif flt(args.get("allocated_amount"), precision) > flt(args.get("unadjusted_amount"), precision):
|
||||||
throw(_("Allocated amount cannot be greater than unadjusted amount"))
|
throw(_("Allocated amount cannot be greater than unadjusted amount"))
|
||||||
|
|
||||||
def update_reference_in_journal_entry(d, jv_obj):
|
def update_reference_in_journal_entry(d, journal_entry, do_not_save=False):
|
||||||
"""
|
"""
|
||||||
Updates against document, if partial amount splits into rows
|
Updates against document, if partial amount splits into rows
|
||||||
"""
|
"""
|
||||||
jv_detail = jv_obj.get("accounts", {"name": d["voucher_detail_no"]})[0]
|
jv_detail = journal_entry.get("accounts", {"name": d["voucher_detail_no"]})[0]
|
||||||
jv_detail.set(d["dr_or_cr"], d["allocated_amount"])
|
|
||||||
jv_detail.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit',
|
if flt(d['unadjusted_amount']) - flt(d['allocated_amount']) != 0:
|
||||||
|
# adjust the unreconciled balance
|
||||||
|
amount_in_account_currency = flt(d['unadjusted_amount']) - flt(d['allocated_amount'])
|
||||||
|
amount_in_company_currency = amount_in_account_currency * flt(jv_detail.exchange_rate)
|
||||||
|
jv_detail.set(d['dr_or_cr'], amount_in_account_currency)
|
||||||
|
jv_detail.set('debit' if d['dr_or_cr'] == 'debit_in_account_currency' else 'credit', amount_in_company_currency)
|
||||||
|
else:
|
||||||
|
journal_entry.remove(jv_detail)
|
||||||
|
|
||||||
|
# new row with references
|
||||||
|
new_row = journal_entry.append("accounts")
|
||||||
|
new_row.update(jv_detail.as_dict().copy())
|
||||||
|
|
||||||
|
new_row.set(d["dr_or_cr"], d["allocated_amount"])
|
||||||
|
new_row.set('debit' if d['dr_or_cr'] == 'debit_in_account_currency' else 'credit',
|
||||||
d["allocated_amount"] * flt(jv_detail.exchange_rate))
|
d["allocated_amount"] * flt(jv_detail.exchange_rate))
|
||||||
|
|
||||||
original_reference_type = jv_detail.reference_type
|
new_row.set('credit_in_account_currency' if d['dr_or_cr'] == 'debit_in_account_currency'
|
||||||
original_reference_name = jv_detail.reference_name
|
|
||||||
|
|
||||||
jv_detail.set("reference_type", d["against_voucher_type"])
|
|
||||||
jv_detail.set("reference_name", d["against_voucher"])
|
|
||||||
|
|
||||||
if d['allocated_amount'] < d['unadjusted_amount']:
|
|
||||||
jvd = frappe.db.sql("""
|
|
||||||
select cost_center, balance, against_account, is_advance,
|
|
||||||
account_type, exchange_rate, account_currency
|
|
||||||
from `tabJournal Entry Account` where name = %s
|
|
||||||
""", d['voucher_detail_no'], as_dict=True)
|
|
||||||
|
|
||||||
amount_in_account_currency = flt(d['unadjusted_amount']) - flt(d['allocated_amount'])
|
|
||||||
amount_in_company_currency = amount_in_account_currency * flt(jvd[0]['exchange_rate'])
|
|
||||||
|
|
||||||
# new entry with balance amount
|
|
||||||
ch = jv_obj.append("accounts")
|
|
||||||
ch.account = d['account']
|
|
||||||
ch.account_type = jvd[0]['account_type']
|
|
||||||
ch.account_currency = jvd[0]['account_currency']
|
|
||||||
ch.exchange_rate = jvd[0]['exchange_rate']
|
|
||||||
ch.party_type = d["party_type"]
|
|
||||||
ch.party = d["party"]
|
|
||||||
ch.cost_center = cstr(jvd[0]["cost_center"])
|
|
||||||
ch.balance = flt(jvd[0]["balance"])
|
|
||||||
|
|
||||||
ch.set(d['dr_or_cr'], amount_in_account_currency)
|
|
||||||
ch.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit', amount_in_company_currency)
|
|
||||||
|
|
||||||
ch.set('credit_in_account_currency' if d['dr_or_cr']== 'debit_in_account_currency'
|
|
||||||
else 'debit_in_account_currency', 0)
|
else 'debit_in_account_currency', 0)
|
||||||
ch.set('credit' if d['dr_or_cr']== 'debit_in_account_currency' else 'debit', 0)
|
new_row.set('credit' if d['dr_or_cr'] == 'debit_in_account_currency' else 'debit', 0)
|
||||||
|
|
||||||
ch.against_account = cstr(jvd[0]["against_account"])
|
new_row.set("reference_type", d["against_voucher_type"])
|
||||||
ch.reference_type = original_reference_type
|
new_row.set("reference_name", d["against_voucher"])
|
||||||
ch.reference_name = original_reference_name
|
|
||||||
ch.is_advance = cstr(jvd[0]["is_advance"])
|
new_row.against_account = cstr(jv_detail.against_account)
|
||||||
ch.docstatus = 1
|
new_row.is_advance = cstr(jv_detail.is_advance)
|
||||||
|
new_row.docstatus = 1
|
||||||
|
|
||||||
# will work as update after submit
|
# will work as update after submit
|
||||||
jv_obj.flags.ignore_validate_update_after_submit = True
|
journal_entry.flags.ignore_validate_update_after_submit = True
|
||||||
jv_obj.save(ignore_permissions=True)
|
if not do_not_save:
|
||||||
|
journal_entry.save(ignore_permissions=True)
|
||||||
|
|
||||||
def update_reference_in_payment_entry(d, payment_entry, do_not_save=False):
|
def update_reference_in_payment_entry(d, payment_entry, do_not_save=False):
|
||||||
reference_details = {
|
reference_details = {
|
||||||
|
@ -1587,7 +1587,7 @@ def get_advance_journal_entries(party_type, party, party_account, amount_field,
|
|||||||
|
|
||||||
|
|
||||||
def get_advance_payment_entries(party_type, party, party_account, order_doctype,
|
def get_advance_payment_entries(party_type, party, party_account, order_doctype,
|
||||||
order_list=None, include_unallocated=True, against_all_orders=False, limit=None):
|
order_list=None, include_unallocated=True, against_all_orders=False, limit=None, condition=None):
|
||||||
party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
|
party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
|
||||||
currency_field = "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency"
|
currency_field = "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency"
|
||||||
payment_type = "Receive" if party_type == "Customer" else "Pay"
|
payment_type = "Receive" if party_type == "Customer" else "Pay"
|
||||||
@ -1622,14 +1622,14 @@ def get_advance_payment_entries(party_type, party, party_account, order_doctype,
|
|||||||
|
|
||||||
if include_unallocated:
|
if include_unallocated:
|
||||||
unallocated_payment_entries = frappe.db.sql("""
|
unallocated_payment_entries = frappe.db.sql("""
|
||||||
select "Payment Entry" as reference_type, name as reference_name,
|
select "Payment Entry" as reference_type, name as reference_name, posting_date,
|
||||||
remarks, unallocated_amount as amount, {2} as exchange_rate
|
remarks, unallocated_amount as amount, {2} as exchange_rate, {3} as currency
|
||||||
from `tabPayment Entry`
|
from `tabPayment Entry`
|
||||||
where
|
where
|
||||||
{0} = %s and party_type = %s and party = %s and payment_type = %s
|
{0} = %s and party_type = %s and party = %s and payment_type = %s
|
||||||
and docstatus = 1 and unallocated_amount > 0
|
and docstatus = 1 and unallocated_amount > 0 {condition}
|
||||||
order by posting_date {1}
|
order by posting_date {1}
|
||||||
""".format(party_account_field, limit_cond, exchange_rate_field),
|
""".format(party_account_field, limit_cond, exchange_rate_field, currency_field, condition=condition or ""),
|
||||||
(party_account, party_type, party, payment_type), as_dict=1)
|
(party_account, party_type, party, payment_type), as_dict=1)
|
||||||
|
|
||||||
return list(payment_entries_against_order) + list(unallocated_payment_entries)
|
return list(payment_entries_against_order) + list(unallocated_payment_entries)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user