Merge branch 'develop' into fix-minor-custom-cash-flow
This commit is contained in:
commit
8e7c214e9e
@ -42,10 +42,18 @@ class ExpenseClaim(AccountsController):
|
|||||||
"2": "Cancelled"
|
"2": "Cancelled"
|
||||||
}[cstr(self.docstatus or 0)]
|
}[cstr(self.docstatus or 0)]
|
||||||
|
|
||||||
paid_amount = flt(self.total_amount_reimbursed) + flt(self.total_advance_amount)
|
|
||||||
precision = self.precision("grand_total")
|
precision = self.precision("grand_total")
|
||||||
if (self.is_paid or (flt(self.total_sanctioned_amount) > 0 and self.docstatus == 1
|
|
||||||
and flt(self.grand_total, precision) == flt(paid_amount, precision))) and self.approval_status == 'Approved':
|
if (
|
||||||
|
# set as paid
|
||||||
|
self.is_paid
|
||||||
|
or (flt(self.total_sanctioned_amount > 0) and (
|
||||||
|
# grand total is reimbursed
|
||||||
|
(self.docstatus == 1 and flt(self.grand_total, precision) == flt(self.total_amount_reimbursed, precision))
|
||||||
|
# grand total (to be paid) is 0 since linked advances already cover the claimed amount
|
||||||
|
or (flt(self.grand_total, precision) == 0)
|
||||||
|
))
|
||||||
|
) and self.approval_status == "Approved":
|
||||||
status = "Paid"
|
status = "Paid"
|
||||||
elif flt(self.total_sanctioned_amount) > 0 and self.docstatus == 1 and self.approval_status == 'Approved':
|
elif flt(self.total_sanctioned_amount) > 0 and self.docstatus == 1 and self.approval_status == 'Approved':
|
||||||
status = "Unpaid"
|
status = "Unpaid"
|
||||||
|
@ -72,6 +72,72 @@ class TestExpenseClaim(unittest.TestCase):
|
|||||||
expense_claim = frappe.get_doc("Expense Claim", expense_claim.name)
|
expense_claim = frappe.get_doc("Expense Claim", expense_claim.name)
|
||||||
self.assertEqual(expense_claim.status, "Unpaid")
|
self.assertEqual(expense_claim.status, "Unpaid")
|
||||||
|
|
||||||
|
# expense claim without any sanctioned amount should not have status as Paid
|
||||||
|
claim = make_expense_claim(payable_account, 1000, 0, "_Test Company", "Travel Expenses - _TC")
|
||||||
|
self.assertEqual(claim.total_sanctioned_amount, 0)
|
||||||
|
self.assertEqual(claim.status, "Submitted")
|
||||||
|
|
||||||
|
# no gl entries created
|
||||||
|
gl_entry = frappe.get_all('GL Entry', {'voucher_type': 'Expense Claim', 'voucher_no': claim.name})
|
||||||
|
self.assertEqual(len(gl_entry), 0)
|
||||||
|
|
||||||
|
def test_expense_claim_against_fully_paid_advances(self):
|
||||||
|
from erpnext.hr.doctype.employee_advance.test_employee_advance import (
|
||||||
|
get_advances_for_claim,
|
||||||
|
make_employee_advance,
|
||||||
|
make_payment_entry,
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.delete("Employee Advance")
|
||||||
|
|
||||||
|
payable_account = get_payable_account("_Test Company")
|
||||||
|
claim = make_expense_claim(payable_account, 1000, 1000, "_Test Company", "Travel Expenses - _TC", do_not_submit=True)
|
||||||
|
|
||||||
|
advance = make_employee_advance(claim.employee)
|
||||||
|
pe = make_payment_entry(advance)
|
||||||
|
pe.submit()
|
||||||
|
|
||||||
|
# claim for already paid out advances
|
||||||
|
claim = get_advances_for_claim(claim, advance.name)
|
||||||
|
claim.save()
|
||||||
|
claim.submit()
|
||||||
|
|
||||||
|
self.assertEqual(claim.grand_total, 0)
|
||||||
|
self.assertEqual(claim.status, "Paid")
|
||||||
|
|
||||||
|
def test_expense_claim_partially_paid_via_advance(self):
|
||||||
|
from erpnext.hr.doctype.employee_advance.test_employee_advance import (
|
||||||
|
get_advances_for_claim,
|
||||||
|
make_employee_advance,
|
||||||
|
)
|
||||||
|
from erpnext.hr.doctype.employee_advance.test_employee_advance import (
|
||||||
|
make_payment_entry as make_advance_payment,
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.delete("Employee Advance")
|
||||||
|
|
||||||
|
payable_account = get_payable_account("_Test Company")
|
||||||
|
claim = make_expense_claim(payable_account, 1000, 1000, "_Test Company", "Travel Expenses - _TC", do_not_submit=True)
|
||||||
|
|
||||||
|
# link advance for partial amount
|
||||||
|
advance = make_employee_advance(claim.employee, {'advance_amount': 500})
|
||||||
|
pe = make_advance_payment(advance)
|
||||||
|
pe.submit()
|
||||||
|
|
||||||
|
claim = get_advances_for_claim(claim, advance.name)
|
||||||
|
claim.save()
|
||||||
|
claim.submit()
|
||||||
|
|
||||||
|
self.assertEqual(claim.grand_total, 500)
|
||||||
|
self.assertEqual(claim.status, "Unpaid")
|
||||||
|
|
||||||
|
# reimburse remaning amount
|
||||||
|
make_payment_entry(claim, payable_account, 500)
|
||||||
|
claim.reload()
|
||||||
|
|
||||||
|
self.assertEqual(claim.total_amount_reimbursed, 500)
|
||||||
|
self.assertEqual(claim.status, "Paid")
|
||||||
|
|
||||||
def test_expense_claim_gl_entry(self):
|
def test_expense_claim_gl_entry(self):
|
||||||
payable_account = get_payable_account(company_name)
|
payable_account = get_payable_account(company_name)
|
||||||
taxes = generate_taxes()
|
taxes = generate_taxes()
|
||||||
|
@ -351,7 +351,6 @@
|
|||||||
"hide_border": 1
|
"hide_border": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "get_items_from",
|
|
||||||
"fieldname": "sub_assembly_items",
|
"fieldname": "sub_assembly_items",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Sub Assembly Items",
|
"label": "Sub Assembly Items",
|
||||||
@ -385,7 +384,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-03-14 03:56:23.209247",
|
"modified": "2022-03-25 09:15:25.017664",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Plan",
|
"name": "Production Plan",
|
||||||
|
@ -362,3 +362,4 @@ erpnext.patches.v14_0.update_employee_advance_status
|
|||||||
erpnext.patches.v13_0.add_cost_center_in_loans
|
erpnext.patches.v13_0.add_cost_center_in_loans
|
||||||
erpnext.patches.v13_0.set_return_against_in_pos_invoice_references
|
erpnext.patches.v13_0.set_return_against_in_pos_invoice_references
|
||||||
erpnext.patches.v13_0.remove_unknown_links_to_prod_plan_items # 24-03-2022
|
erpnext.patches.v13_0.remove_unknown_links_to_prod_plan_items # 24-03-2022
|
||||||
|
erpnext.patches.v13_0.update_expense_claim_status_for_paid_advances
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
"""
|
||||||
|
Update Expense Claim status to Paid if:
|
||||||
|
- the entire required amount is already covered via linked advances
|
||||||
|
- the claim is partially paid via advances and the rest is reimbursed
|
||||||
|
"""
|
||||||
|
|
||||||
|
ExpenseClaim = frappe.qb.DocType('Expense Claim')
|
||||||
|
|
||||||
|
(frappe.qb
|
||||||
|
.update(ExpenseClaim)
|
||||||
|
.set(ExpenseClaim.status, 'Paid')
|
||||||
|
.where(
|
||||||
|
((ExpenseClaim.grand_total == 0) | (ExpenseClaim.grand_total == ExpenseClaim.total_amount_reimbursed))
|
||||||
|
& (ExpenseClaim.approval_status == 'Approved')
|
||||||
|
& (ExpenseClaim.docstatus == 1)
|
||||||
|
& (ExpenseClaim.total_sanctioned_amount > 0)
|
||||||
|
)
|
||||||
|
).run()
|
@ -1044,7 +1044,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
var company_currency = this.get_company_currency();
|
var company_currency = this.get_company_currency();
|
||||||
// Added `ignore_price_list` to determine if document is loading after mapping from another doc
|
// Added `ignore_price_list` to determine if document is loading after mapping from another doc
|
||||||
if(this.frm.doc.currency && this.frm.doc.currency !== company_currency
|
if(this.frm.doc.currency && this.frm.doc.currency !== company_currency
|
||||||
&& !this.frm.doc.__onload.ignore_price_list) {
|
&& !(this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list)) {
|
||||||
|
|
||||||
this.get_exchange_rate(transaction_date, this.frm.doc.currency, company_currency,
|
this.get_exchange_rate(transaction_date, this.frm.doc.currency, company_currency,
|
||||||
function(exchange_rate) {
|
function(exchange_rate) {
|
||||||
@ -1145,7 +1145,8 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
|
|
||||||
var company_currency = this.get_company_currency();
|
var company_currency = this.get_company_currency();
|
||||||
// Added `ignore_price_list` to determine if document is loading after mapping from another doc
|
// Added `ignore_price_list` to determine if document is loading after mapping from another doc
|
||||||
if(this.frm.doc.price_list_currency !== company_currency && !this.frm.doc.__onload.ignore_price_list) {
|
if(this.frm.doc.price_list_currency !== company_currency &&
|
||||||
|
!(this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list)) {
|
||||||
this.get_exchange_rate(this.frm.doc.posting_date, this.frm.doc.price_list_currency, company_currency,
|
this.get_exchange_rate(this.frm.doc.posting_date, this.frm.doc.price_list_currency, company_currency,
|
||||||
function(exchange_rate) {
|
function(exchange_rate) {
|
||||||
me.frm.set_value("plc_conversion_rate", exchange_rate);
|
me.frm.set_value("plc_conversion_rate", exchange_rate);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user