diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index b0b189e6d0..fc1ff24109 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -12,25 +12,20 @@ from frappe.model.document import Document class PaymentReconciliation(Document): def get_unreconciled_entries(self): - self.set('payment_reconciliation_payment', []) - jve = self.get_jv_entries() - self.add_payment_entries(jve) + jv_entries = self.get_jv_entries() + self.add_payment_entries(jv_entries) + invoice_entries = self.get_invoice_entries() + + self.add_invoice_entries(invoice_entries) def get_jv_entries(self): - self.validation() + self.check_mandatory() dr_or_cr = "credit" if self.party_type == "Customer" else "debit" - - #Add conditions for debit/credit, sorting by date and amount - cond = self.from_date and " and t1.posting_date >= '" + self.from_date + "'" or "" - cond += self.to_date and " and t1.posting_date <= '" + self.to_date + "'" or "" - if self.minimum_amount: - cond += (" and ifnull(t2.%s), 0) >= %s") % (dr_or_cr, self.minimum_amount) - if self.maximum_amount: - cond += " and ifnull(t2.%s, 0) <= %s" % (dr_or_cr, self.maximum_amount) + cond = self.check_condition(dr_or_cr) - jve = frappe.db.sql(""" + jv_entries = frappe.db.sql(""" select t1.name as voucher_no, t1.posting_date, t1.remark, t2.account, t2.name as voucher_detail_no, t2.%s, t2.is_advance @@ -42,21 +37,83 @@ class PaymentReconciliation(Document): and ifnull(t2.against_jv, '')='' %s group by t1.name, t2.name """ % (dr_or_cr, '%s', dr_or_cr, cond), (self.party_account), as_dict = True) + return jv_entries - return jve - - def add_payment_entries(self, jve): + def add_payment_entries(self, jv_entries): self.set('payment_reconciliation_payments', []) - for e in jve: + for e in jv_entries: ent = self.append('payment_reconciliation_payments', {}) ent.journal_voucher = e.get('voucher_no') ent.posting_date = e.get('posting_date') - ent.amount = flt(e.get('credit' or 'debit')) + ent.amount = flt(e.get('credit')) or flt(e.get('debit')) ent.remark = e.get('remark') ent.voucher_detail_number = e.get('voucher_detail_no') - def validation(self): + def get_invoice_entries(self): + #Fetch JVs, Sales and Purchase Invoices for 'payment_reconciliation_invoices' to reconcile against + non_reconciled_invoices = [] self.check_mandatory() + dr_or_cr = "debit" if self.party_type == "Customer" else "credit" + + cond = self.check_condition(dr_or_cr) + + invoice_list = frappe.db.sql(""" + select + voucher_no, voucher_type, posting_date, ifnull(sum(ifnull(%s, 0)), 0) as amount + from + `tabGL Entry` + where + account = %s and ifnull(%s, 0) > 0 %s + group by voucher_no, voucher_type""" % (dr_or_cr, "%s", + dr_or_cr, cond), (self.party_account), as_dict=True) + + for d in invoice_list: + payment_amount = frappe.db.sql(""" + select + ifnull(sum(ifnull(%s, 0)), 0) + from + `tabGL Entry` + where + account = %s and against_voucher_type = %s and ifnull(against_voucher, '') = %s""", + (("credit" if self.party_type == "Customer" else "debit"), self.party_account, + d.voucher_type, d.voucher_no)) + + payment_amount = payment_amount[0][0] if payment_amount else 0 + + if d.amount > payment_amount: + non_reconciled_invoices.append({'voucher_no': d.voucher_no, + 'voucher_type': d.voucher_type, + 'posting_date': d.posting_date, + 'amount': flt(d.amount), + 'outstanding_amount': d.amount - payment_amount}) + + return non_reconciled_invoices + + + def add_invoice_entries(self, non_reconciled_invoices): + #Populate 'payment_reconciliation_invoices' with JVs and Invoices to reconcile against + self.set('payment_reconciliation_invoices', []) + if not non_reconciled_invoices: + return + for e in non_reconciled_invoices: + ent = self.append('payment_reconciliation_invoices', {}) + ent.invoice_type = e.get('voucher_type') + ent.invoice_number = e.get('voucher_no') + ent.invoice_date = e.get('posting_date') + ent.amount = flt(e.get('amount')) + ent.outstanding_amount = e.get('outstanding_amount') + def check_mandatory(self): pass + + def check_condition(self, dr_or_cr): + cond = self.from_date and " and posting_date >= '" + self.from_date + "'" or "" + cond += self.to_date and " and posting_date <= '" + self.to_date + "'" or "" + + if self.minimum_amount: + cond += (" and ifnull(%s), 0) >= %s") % (dr_or_cr, self.minimum_amount) + if self.maximum_amount: + cond += " and ifnull(%s, 0) <= %s" % (dr_or_cr, self.maximum_amount) + + return cond \ No newline at end of file