diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 937597bc55..72648753a7 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -643,7 +643,10 @@ class JournalEntry(AccountsController): for d in self.accounts: if d.reference_type=="Expense Claim" and d.reference_name: doc = frappe.get_doc("Expense Claim", d.reference_name) - update_reimbursed_amount(doc, jv=self.name) + if self.docstatus == 2: + update_reimbursed_amount(doc, -1 * d.debit) + else: + update_reimbursed_amount(doc, d.debit) def validate_expense_claim(self): diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index b259b11c63..a5fcad4996 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -75,9 +75,9 @@ class PaymentEntry(AccountsController): if self.difference_amount: frappe.throw(_("Difference Amount must be zero")) self.make_gl_entries() + self.update_expense_claim() self.update_outstanding_amounts() self.update_advance_paid() - self.update_expense_claim() self.update_donation() self.update_payment_schedule() self.set_status() @@ -85,9 +85,9 @@ class PaymentEntry(AccountsController): def on_cancel(self): self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry') self.make_gl_entries(cancel=1) + self.update_expense_claim() self.update_outstanding_amounts() self.update_advance_paid() - self.update_expense_claim() self.update_donation(cancel=1) self.delink_advance_entry_references() self.update_payment_schedule(cancel=1) @@ -831,7 +831,10 @@ class PaymentEntry(AccountsController): for d in self.get("references"): if d.reference_doctype=="Expense Claim" and d.reference_name: doc = frappe.get_doc("Expense Claim", d.reference_name) - update_reimbursed_amount(doc, self.name) + if self.docstatus == 2: + update_reimbursed_amount(doc, -1 * d.allocated_amount) + else: + update_reimbursed_amount(doc, d.allocated_amount) def update_donation(self, cancel=0): if self.payment_type == "Receive" and self.party_type == "Donor" and self.party: diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index 95e2806aed..4dc089cb1d 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -77,7 +77,7 @@ class ExpenseClaim(AccountsController): self.make_gl_entries() if self.is_paid: - update_reimbursed_amount(self) + update_reimbursed_amount(self, self.grand_total) self.set_status(update=True) self.update_claimed_amount_in_employee_advance() @@ -89,7 +89,7 @@ class ExpenseClaim(AccountsController): self.make_gl_entries(cancel=True) if self.is_paid: - update_reimbursed_amount(self) + update_reimbursed_amount(self, -1 * self.grand_total) self.update_claimed_amount_in_employee_advance() @@ -270,20 +270,10 @@ class ExpenseClaim(AccountsController): if not expense.default_account or not validate: expense.default_account = get_expense_claim_account(expense.expense_type, self.company)["account"] -def update_reimbursed_amount(doc, jv=None): +def update_reimbursed_amount(doc, amount): - condition = "" - - if jv: - condition += "and voucher_no = '{0}'".format(jv) - - amt = frappe.db.sql("""select ifnull(sum(debit_in_account_currency), 0) - ifnull(sum(credit_in_account_currency), 0)as amt - from `tabGL Entry` where against_voucher_type = 'Expense Claim' and against_voucher = %s - and party = %s {condition}""".format(condition=condition), #nosec - (doc.name, doc.employee) ,as_dict=1)[0].amt - - doc.total_amount_reimbursed = amt - frappe.db.set_value("Expense Claim", doc.name , "total_amount_reimbursed", amt) + doc.total_amount_reimbursed += amount + frappe.db.set_value("Expense Claim", doc.name , "total_amount_reimbursed", doc.total_amount_reimbursed) doc.set_status() frappe.db.set_value("Expense Claim", doc.name , "status", doc.status) diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py index c2bd1e9f9f..b5fc1fbe75 100644 --- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe import unittest -from frappe.utils import random_string, nowdate +from frappe.utils import random_string, nowdate, flt from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry from erpnext.accounts.doctype.account.test_account import create_account from erpnext.hr.doctype.employee.test_employee import make_employee @@ -138,6 +138,31 @@ class TestExpenseClaim(unittest.TestCase): expense_claim.submit() frappe.set_user("Administrator") + def test_multiple_payment_entries_against_expense(self): + # Creating expense claim + payable_account = get_payable_account("_Test Company") + expense_claim = make_expense_claim(payable_account, 5500, 5500, "_Test Company", "Travel Expenses - _TC") + expense_claim.save() + expense_claim.submit() + + # Payment entry 1: paying 500 + make_payment_entry(expense_claim, payable_account,500) + outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim) + self.assertEqual(outstanding_amount, 5000) + self.assertEqual(total_amount_reimbursed, 500) + + # Payment entry 1: paying 2000 + make_payment_entry(expense_claim, payable_account,2000) + outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim) + self.assertEqual(outstanding_amount, 3000) + self.assertEqual(total_amount_reimbursed, 2500) + + # Payment entry 1: paying 3000 + make_payment_entry(expense_claim, payable_account,3000) + outstanding_amount, total_amount_reimbursed = get_outstanding_and_total_reimbursed_amounts(expense_claim) + self.assertEqual(outstanding_amount, 0) + self.assertEqual(total_amount_reimbursed, 5500) + def get_payable_account(company): return frappe.get_cached_value('Company', company, 'default_payable_account') @@ -191,3 +216,23 @@ def make_expense_claim(payable_account, amount, sanctioned_amount, company, acco return expense_claim expense_claim.submit() return expense_claim + +def get_outstanding_and_total_reimbursed_amounts(expense_claim): + outstanding_amount = flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_sanctioned_amount")) - \ + flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_amount_reimbursed")) + total_amount_reimbursed = flt(frappe.db.get_value("Expense Claim", expense_claim.name, "total_amount_reimbursed")) + + return outstanding_amount,total_amount_reimbursed + +def make_payment_entry(expense_claim, payable_account, amt): + from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry + + pe = get_payment_entry("Expense Claim", expense_claim.name, bank_account="_Test Bank USD - _TC", bank_amount=amt) + pe.reference_no = "1" + pe.reference_date = nowdate() + pe.source_exchange_rate = 1 + pe.paid_to = payable_account + pe.references[0].allocated_amount = amt + pe.insert() + pe.submit() +