mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-22 22:49:19 +00:00
feat: multi-currency payroll (#23519)
* feat: multi-currency payroll * fix: refactor and added conditions * fix: uncommented code * style: removed comments * fix: missing argument * style: styling changes * fix: test cases * Update asset_value_adjustment.py * patch: update columns * style: formating * style: formatting * fix: 1st review * fix: refactor * Revert "fix: refactor" This reverts commiteca0e17d11. reverting to previous state * Revert "fix: 1st review" This reverts commit7eac48b102. reverting before 1st review * fix: 2nd review changes * fix: test cases * fix: added call to fetch exchange rate * fix: remove unnecessary code * fix: refactor * fix: refactor patch * fix: refactor * fix: refactor * fix: clear test data * fix: slider * feat: multi-currency payroll * fix: refactor and added conditions * fix: uncommented code * style: removed comments * fix: missing argument * style: styling changes * fix: test cases * patch: update columns * Update asset_value_adjustment.py * style: formating * style: formatting * fix: 1st review * fix: refactor * Revert "fix: refactor" This reverts commiteca0e17d11. reverting to previous state * Revert "fix: 1st review" This reverts commit7eac48b102. reverting before 1st review * fix: 2nd review changes * fix: test cases * fix: added call to fetch exchange rate * fix: remove unnecessary code * fix: refactor * fix: refactor patch * fix: refactor * fix: refactor * fix: clear test data * fix: slider * feat: Added company field in leave encashment and employee benefit * refactor: Refactored multi-currency payroll patch * fix: currency column in salary register * refactor: Refactored code for making bank and return entry against employee advance * fix: minor cleanup * fix: fixed translation * fix: removed salary component type * fix: fixed sider issues * fix: translation and slider * style: formatted msg * fix: fixed slider * fix: travis * fix: refactor * fix: slider * fix: slider * fix: slider * fix: travis * fix: patch * fix: patch * fix: travis * fix: travis * fix: travis * fix: travis * fix: travis * fix: travis * fix: re-run travis * fix: rerun travis * fix: rerun travis * fix: rerun travis * fix: travis rerun * fix: increased throttle_user_limit from 60 to 100 * fix: patch * fix: patch * fix: assign payroll payable account as default payroll payable account in SSA * fix: removed debugger * fix: slider Co-authored-by: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Co-authored-by: Nabin Hait <nabinhait@gmail.com>
This commit is contained in:
@@ -15,11 +15,16 @@ frappe.ui.form.on('Employee Advance', {
|
||||
});
|
||||
|
||||
frm.set_query("advance_account", function() {
|
||||
if (!frm.doc.employee) {
|
||||
frappe.msgprint(__("Please select employee first"));
|
||||
}
|
||||
var company_currency = erpnext.get_currency(frm.doc.company);
|
||||
return {
|
||||
filters: {
|
||||
"root_type": "Asset",
|
||||
"is_group": 0,
|
||||
"company": frm.doc.company
|
||||
"company": frm.doc.company,
|
||||
"account_currency": ["in", [frm.doc.currency, company_currency]],
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -63,7 +68,7 @@ frappe.ui.form.on('Employee Advance', {
|
||||
}, __('Create'));
|
||||
}else if (frm.doc.repay_unclaimed_amount_from_salary == 1 && frappe.model.can_create("Additional Salary")){
|
||||
frm.add_custom_button(__("Deduction from salary"), function() {
|
||||
frm.events.make_deduction_via_additional_salary(frm)
|
||||
frm.events.make_deduction_via_additional_salary(frm);
|
||||
}, __('Create'));
|
||||
}
|
||||
}
|
||||
@@ -127,7 +132,9 @@ frappe.ui.form.on('Employee Advance', {
|
||||
'employee_advance_name': frm.doc.name,
|
||||
'return_amount': flt(frm.doc.paid_amount - frm.doc.claimed_amount),
|
||||
'advance_account': frm.doc.advance_account,
|
||||
'mode_of_payment': frm.doc.mode_of_payment
|
||||
'mode_of_payment': frm.doc.mode_of_payment,
|
||||
'currency': frm.doc.currency,
|
||||
'exchange_rate': frm.doc.exchange_rate
|
||||
},
|
||||
callback: function(r) {
|
||||
const doclist = frappe.model.sync(r.message);
|
||||
@@ -138,16 +145,72 @@ frappe.ui.form.on('Employee Advance', {
|
||||
|
||||
employee: function (frm) {
|
||||
if (frm.doc.employee) {
|
||||
return frappe.call({
|
||||
method: "erpnext.hr.doctype.employee_advance.employee_advance.get_pending_amount",
|
||||
args: {
|
||||
"employee": frm.doc.employee,
|
||||
"posting_date": frm.doc.posting_date
|
||||
},
|
||||
callback: function(r) {
|
||||
frm.set_value("pending_amount",r.message);
|
||||
}
|
||||
});
|
||||
frappe.run_serially([
|
||||
() => frm.trigger('get_employee_currency'),
|
||||
() => frm.trigger('get_pending_amount')
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
get_pending_amount: function(frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.hr.doctype.employee_advance.employee_advance.get_pending_amount",
|
||||
args: {
|
||||
"employee": frm.doc.employee,
|
||||
"posting_date": frm.doc.posting_date
|
||||
},
|
||||
callback: function(r) {
|
||||
frm.set_value("pending_amount", r.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
get_employee_currency: function(frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
|
||||
args: {
|
||||
employee: frm.doc.employee,
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
frm.set_value('currency', r.message);
|
||||
frm.refresh_fields();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
currency: function(frm) {
|
||||
var from_currency = frm.doc.currency;
|
||||
var company_currency;
|
||||
if (!frm.doc.company) {
|
||||
company_currency = erpnext.get_currency(frappe.defaults.get_default("Company"));
|
||||
} else {
|
||||
company_currency = erpnext.get_currency(frm.doc.company);
|
||||
}
|
||||
if (from_currency != company_currency) {
|
||||
frm.events.set_exchange_rate(frm, from_currency, company_currency);
|
||||
} else {
|
||||
frm.set_value("exchange_rate", 1.0);
|
||||
frm.set_df_property('exchange_rate', 'hidden', 1);
|
||||
frm.set_df_property("exchange_rate", "description", "" );
|
||||
}
|
||||
frm.refresh_fields();
|
||||
},
|
||||
|
||||
set_exchange_rate: function(frm, from_currency, company_currency) {
|
||||
frappe.call({
|
||||
method: "erpnext.setup.utils.get_exchange_rate",
|
||||
args: {
|
||||
from_currency: from_currency,
|
||||
to_currency: company_currency,
|
||||
},
|
||||
callback: function(r) {
|
||||
frm.set_value("exchange_rate", flt(r.message));
|
||||
frm.set_df_property('exchange_rate', 'hidden', 0);
|
||||
frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency
|
||||
+ " = [?] " + company_currency);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"department",
|
||||
"column_break_4",
|
||||
"posting_date",
|
||||
"currency",
|
||||
"exchange_rate",
|
||||
"repay_unclaimed_amount_from_salary",
|
||||
"section_break_8",
|
||||
"purpose",
|
||||
@@ -91,7 +93,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Advance Amount",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
@@ -99,7 +101,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"label": "Paid Amount",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -107,7 +109,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"label": "Claimed Amount",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -161,7 +163,7 @@
|
||||
"fieldname": "return_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Returned Amount",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -175,13 +177,31 @@
|
||||
"fieldname": "pending_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Pending Amount",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "Company:company:default_currency",
|
||||
"depends_on": "eval:(doc.docstatus==1 || doc.employee)",
|
||||
"fieldname": "currency",
|
||||
"fieldtype": "Link",
|
||||
"label": "Currency",
|
||||
"options": "Currency",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "currency",
|
||||
"fieldname": "exchange_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Exchange Rate",
|
||||
"precision": "9",
|
||||
"print_hide": 1,
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-06-12 12:42:39.833818",
|
||||
"modified": "2020-11-25 12:01:55.980721",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Advance",
|
||||
|
||||
@@ -19,7 +19,6 @@ class EmployeeAdvance(Document):
|
||||
|
||||
def validate(self):
|
||||
self.set_status()
|
||||
self.validate_employee_advance_account()
|
||||
|
||||
def on_cancel(self):
|
||||
self.ignore_linked_doctypes = ('GL Entry')
|
||||
@@ -38,16 +37,9 @@ class EmployeeAdvance(Document):
|
||||
elif self.docstatus == 2:
|
||||
self.status = "Cancelled"
|
||||
|
||||
def validate_employee_advance_account(self):
|
||||
company_currency = erpnext.get_company_currency(self.company)
|
||||
if (self.advance_account and
|
||||
company_currency != frappe.db.get_value('Account', self.advance_account, 'account_currency')):
|
||||
frappe.throw(_("Advance account currency should be same as company currency {0}")
|
||||
.format(company_currency))
|
||||
|
||||
def set_total_advance_paid(self):
|
||||
paid_amount = frappe.db.sql("""
|
||||
select ifnull(sum(debit_in_account_currency), 0) as paid_amount
|
||||
select ifnull(sum(debit), 0) as paid_amount
|
||||
from `tabGL Entry`
|
||||
where against_voucher_type = 'Employee Advance'
|
||||
and against_voucher = %s
|
||||
@@ -56,7 +48,7 @@ class EmployeeAdvance(Document):
|
||||
""", (self.name, self.employee), as_dict=1)[0].paid_amount
|
||||
|
||||
return_amount = frappe.db.sql("""
|
||||
select name, ifnull(sum(credit_in_account_currency), 0) as return_amount
|
||||
select ifnull(sum(credit), 0) as return_amount
|
||||
from `tabGL Entry`
|
||||
where against_voucher_type = 'Employee Advance'
|
||||
and voucher_type != 'Expense Claim'
|
||||
@@ -65,6 +57,11 @@ class EmployeeAdvance(Document):
|
||||
and party = %s
|
||||
""", (self.name, self.employee), as_dict=1)[0].return_amount
|
||||
|
||||
if paid_amount != 0:
|
||||
paid_amount = flt(paid_amount) / flt(self.exchange_rate)
|
||||
if return_amount != 0:
|
||||
return_amount = flt(return_amount) / flt(self.exchange_rate)
|
||||
|
||||
if flt(paid_amount) > self.advance_amount:
|
||||
frappe.throw(_("Row {0}# Paid Amount cannot be greater than requested advance amount"),
|
||||
EmployeeAdvanceOverPayment)
|
||||
@@ -107,16 +104,27 @@ def make_bank_entry(dt, dn):
|
||||
doc = frappe.get_doc(dt, dn)
|
||||
payment_account = get_default_bank_cash_account(doc.company, account_type="Cash",
|
||||
mode_of_payment=doc.mode_of_payment)
|
||||
if not payment_account:
|
||||
frappe.throw(_("Please set a Default Cash Account in Company defaults"))
|
||||
|
||||
advance_account_currency = frappe.db.get_value('Account', doc.advance_account, 'account_currency')
|
||||
|
||||
advance_amount, advance_exchange_rate = get_advance_amount_advance_exchange_rate(advance_account_currency,doc )
|
||||
|
||||
paying_amount, paying_exchange_rate = get_paying_amount_paying_exchange_rate(payment_account, doc)
|
||||
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
je.posting_date = nowdate()
|
||||
je.voucher_type = 'Bank Entry'
|
||||
je.company = doc.company
|
||||
je.remark = 'Payment against Employee Advance: ' + dn + '\n' + doc.purpose
|
||||
je.multi_currency = 1 if advance_account_currency != payment_account.account_currency else 0
|
||||
|
||||
je.append("accounts", {
|
||||
"account": doc.advance_account,
|
||||
"debit_in_account_currency": flt(doc.advance_amount),
|
||||
"account_currency": advance_account_currency,
|
||||
"exchange_rate": flt(advance_exchange_rate),
|
||||
"debit_in_account_currency": flt(advance_amount),
|
||||
"reference_type": "Employee Advance",
|
||||
"reference_name": doc.name,
|
||||
"party_type": "Employee",
|
||||
@@ -128,19 +136,41 @@ def make_bank_entry(dt, dn):
|
||||
je.append("accounts", {
|
||||
"account": payment_account.account,
|
||||
"cost_center": erpnext.get_default_cost_center(doc.company),
|
||||
"credit_in_account_currency": flt(doc.advance_amount),
|
||||
"credit_in_account_currency": flt(paying_amount),
|
||||
"account_currency": payment_account.account_currency,
|
||||
"account_type": payment_account.account_type
|
||||
"account_type": payment_account.account_type,
|
||||
"exchange_rate": flt(paying_exchange_rate)
|
||||
})
|
||||
|
||||
return je.as_dict()
|
||||
|
||||
def get_advance_amount_advance_exchange_rate(advance_account_currency, doc):
|
||||
if advance_account_currency != doc.currency:
|
||||
advance_amount = flt(doc.advance_amount) * flt(doc.exchange_rate)
|
||||
advance_exchange_rate = 1
|
||||
else:
|
||||
advance_amount = doc.advance_amount
|
||||
advance_exchange_rate = doc.exchange_rate
|
||||
|
||||
return advance_amount, advance_exchange_rate
|
||||
|
||||
def get_paying_amount_paying_exchange_rate(payment_account, doc):
|
||||
if payment_account.account_currency != doc.currency:
|
||||
paying_amount = flt(doc.advance_amount) * flt(doc.exchange_rate)
|
||||
paying_exchange_rate = 1
|
||||
else:
|
||||
paying_amount = doc.advance_amount
|
||||
paying_exchange_rate = doc.exchange_rate
|
||||
|
||||
return paying_amount, paying_exchange_rate
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_return_through_additional_salary(doc):
|
||||
import json
|
||||
doc = frappe._dict(json.loads(doc))
|
||||
additional_salary = frappe.new_doc('Additional Salary')
|
||||
additional_salary.employee = doc.employee
|
||||
additional_salary.currency = doc.currency
|
||||
additional_salary.amount = doc.paid_amount - doc.claimed_amount
|
||||
additional_salary.company = doc.company
|
||||
additional_salary.ref_doctype = doc.doctype
|
||||
@@ -149,26 +179,28 @@ def create_return_through_additional_salary(doc):
|
||||
return additional_salary
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_return_entry(employee, company, employee_advance_name, return_amount, advance_account, mode_of_payment=None):
|
||||
return_account = get_default_bank_cash_account(company, account_type='Cash', mode_of_payment = mode_of_payment)
|
||||
|
||||
mode_of_payment_type = ''
|
||||
if mode_of_payment:
|
||||
mode_of_payment_type = frappe.get_cached_value('Mode of Payment', mode_of_payment, 'type')
|
||||
if mode_of_payment_type not in ["Cash", "Bank"]:
|
||||
# if mode of payment is General then it unset the type
|
||||
mode_of_payment_type = None
|
||||
|
||||
def make_return_entry(employee, company, employee_advance_name, return_amount, advance_account, currency, exchange_rate, mode_of_payment=None):
|
||||
bank_cash_account = get_default_bank_cash_account(company, account_type='Cash', mode_of_payment = mode_of_payment)
|
||||
if not bank_cash_account:
|
||||
frappe.throw(_("Please set a Default Cash Account in Company defaults"))
|
||||
|
||||
advance_account_currency = frappe.db.get_value('Account', advance_account, 'account_currency')
|
||||
|
||||
je = frappe.new_doc('Journal Entry')
|
||||
je.posting_date = nowdate()
|
||||
# if mode of payment is Bank then voucher type is Bank Entry
|
||||
je.voucher_type = '{} Entry'.format(mode_of_payment_type) if mode_of_payment_type else 'Cash Entry'
|
||||
je.voucher_type = get_voucher_type(mode_of_payment)
|
||||
je.company = company
|
||||
je.remark = 'Return against Employee Advance: ' + employee_advance_name
|
||||
je.multi_currency = 1 if advance_account_currency != bank_cash_account.account_currency else 0
|
||||
|
||||
advance_account_amount = flt(return_amount) if advance_account_currency==currency \
|
||||
else flt(return_amount) * flt(exchange_rate)
|
||||
|
||||
je.append('accounts', {
|
||||
'account': advance_account,
|
||||
'credit_in_account_currency': return_amount,
|
||||
'credit_in_account_currency': advance_account_amount,
|
||||
'account_currency': advance_account_currency,
|
||||
'exchange_rate': flt(exchange_rate) if advance_account_currency == currency else 1,
|
||||
'reference_type': 'Employee Advance',
|
||||
'reference_name': employee_advance_name,
|
||||
'party_type': 'Employee',
|
||||
@@ -176,13 +208,25 @@ def make_return_entry(employee, company, employee_advance_name, return_amount,
|
||||
'is_advance': 'Yes'
|
||||
})
|
||||
|
||||
bank_amount = flt(return_amount) if bank_cash_account.account_currency==currency \
|
||||
else flt(return_amount) * flt(exchange_rate)
|
||||
|
||||
je.append("accounts", {
|
||||
"account": return_account.account,
|
||||
"debit_in_account_currency": return_amount,
|
||||
"account_currency": return_account.account_currency,
|
||||
"account_type": return_account.account_type
|
||||
"account": bank_cash_account.account,
|
||||
"debit_in_account_currency": bank_amount,
|
||||
"account_currency": bank_cash_account.account_currency,
|
||||
"account_type": bank_cash_account.account_type,
|
||||
"exchange_rate": flt(exchange_rate) if bank_cash_account.account_currency == currency else 1
|
||||
})
|
||||
|
||||
return je.as_dict()
|
||||
|
||||
def get_voucher_type(mode_of_payment=None):
|
||||
voucher_type = "Cash Entry"
|
||||
|
||||
if mode_of_payment:
|
||||
mode_of_payment_type = frappe.get_cached_value('Mode of Payment', mode_of_payment, 'type')
|
||||
if mode_of_payment_type == "Bank":
|
||||
voucher_type = "Bank Entry"
|
||||
|
||||
return voucher_type
|
||||
@@ -3,15 +3,17 @@
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import frappe, erpnext
|
||||
import unittest
|
||||
from frappe.utils import nowdate
|
||||
from erpnext.hr.doctype.employee_advance.employee_advance import make_bank_entry
|
||||
from erpnext.hr.doctype.employee_advance.employee_advance import EmployeeAdvanceOverPayment
|
||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||
|
||||
class TestEmployeeAdvance(unittest.TestCase):
|
||||
def test_paid_amount_and_status(self):
|
||||
advance = make_employee_advance()
|
||||
employee_name = make_employee("_T@employe.advance")
|
||||
advance = make_employee_advance(employee_name)
|
||||
|
||||
journal_entry = make_payment_entry(advance)
|
||||
journal_entry.submit()
|
||||
@@ -33,11 +35,13 @@ def make_payment_entry(advance):
|
||||
|
||||
return journal_entry
|
||||
|
||||
def make_employee_advance():
|
||||
def make_employee_advance(employee_name):
|
||||
doc = frappe.new_doc("Employee Advance")
|
||||
doc.employee = "_T-Employee-00001"
|
||||
doc.employee = employee_name
|
||||
doc.company = "_Test company"
|
||||
doc.purpose = "For site visit"
|
||||
doc.currency = erpnext.get_company_currency("_Test company")
|
||||
doc.exchange_rate = 1
|
||||
doc.advance_amount = 1000
|
||||
doc.posting_date = nowdate()
|
||||
doc.advance_account = "_Test Employee Advance - _TC"
|
||||
|
||||
@@ -7,6 +7,7 @@ import unittest
|
||||
from frappe.utils import random_string, nowdate
|
||||
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
|
||||
|
||||
test_records = frappe.get_test_records('Expense Claim')
|
||||
test_dependencies = ['Employee']
|
||||
@@ -126,6 +127,9 @@ def generate_taxes():
|
||||
|
||||
def make_expense_claim(payable_account, amount, sanctioned_amount, company, account, project=None, task_name=None, do_not_submit=False, taxes=None):
|
||||
employee = frappe.db.get_value("Employee", {"status": "Active"})
|
||||
if not employee:
|
||||
employee = make_employee("test_employee@expense_claim.com", company=company)
|
||||
|
||||
currency, cost_center = frappe.db.get_value('Company', company, ['default_currency', 'cost_center'])
|
||||
expense_claim = {
|
||||
"doctype": "Expense Claim",
|
||||
|
||||
@@ -71,9 +71,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"oldfieldname": "tax_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency"
|
||||
"options": "currency"
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
@@ -81,9 +79,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Total",
|
||||
"oldfieldname": "total",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -106,7 +102,7 @@
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-05-11 19:01:26.611758",
|
||||
"modified": "2020-09-23 20:27:36.027728",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Expense Taxes and Charges",
|
||||
|
||||
@@ -22,7 +22,12 @@ frappe.ui.form.on('Leave Encashment', {
|
||||
}
|
||||
},
|
||||
employee: function(frm) {
|
||||
frm.trigger("get_leave_details_for_encashment");
|
||||
if (frm.doc.employee) {
|
||||
frappe.run_serially([
|
||||
() => frm.trigger('get_employee_currency'),
|
||||
() => frm.trigger('get_leave_details_for_encashment')
|
||||
]);
|
||||
}
|
||||
},
|
||||
leave_type: function(frm) {
|
||||
frm.trigger("get_leave_details_for_encashment");
|
||||
@@ -40,5 +45,20 @@ frappe.ui.form.on('Leave Encashment', {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get_employee_currency: function(frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency",
|
||||
args: {
|
||||
employee: frm.doc.employee,
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
frm.set_value('currency', r.message);
|
||||
frm.refresh_fields();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"employee",
|
||||
"employee_name",
|
||||
"department",
|
||||
"company",
|
||||
"column_break_4",
|
||||
"leave_type",
|
||||
"leave_allocation",
|
||||
@@ -19,9 +20,11 @@
|
||||
"encashable_days",
|
||||
"amended_from",
|
||||
"payroll",
|
||||
"encashment_amount",
|
||||
"encashment_date",
|
||||
"additional_salary"
|
||||
"additional_salary",
|
||||
"column_break_14",
|
||||
"currency",
|
||||
"encashment_amount"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -109,6 +112,7 @@
|
||||
"in_list_view": 1,
|
||||
"label": "Encashment Amount",
|
||||
"no_copy": 1,
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -124,11 +128,34 @@
|
||||
"no_copy": 1,
|
||||
"options": "Additional Salary",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "Company:company:default_currency",
|
||||
"depends_on": "eval:(doc.docstatus==1 || doc.employee)",
|
||||
"fieldname": "currency",
|
||||
"fieldtype": "Link",
|
||||
"label": "Currency",
|
||||
"options": "Currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_14",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fetch_from": "employee.company",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-16 11:51:57.732223",
|
||||
"modified": "2020-11-25 11:56:06.777241",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Leave Encashment",
|
||||
|
||||
@@ -16,10 +16,16 @@ class LeaveEncashment(Document):
|
||||
def validate(self):
|
||||
set_employee_name(self)
|
||||
self.get_leave_details_for_encashment()
|
||||
self.validate_salary_structure()
|
||||
|
||||
if not self.encashment_date:
|
||||
self.encashment_date = getdate(nowdate())
|
||||
|
||||
def validate_salary_structure(self):
|
||||
if not frappe.db.exists('Salary Structure Assignment', {'employee': self.employee}):
|
||||
frappe.throw(_("There is no Salary Structure assigned to {0}. First assign a Salary Stucture.").format(self.employee))
|
||||
|
||||
|
||||
def before_submit(self):
|
||||
if self.encashment_amount <= 0:
|
||||
frappe.throw(_("You can only submit Leave Encashment for a valid encashment amount"))
|
||||
@@ -30,6 +36,7 @@ class LeaveEncashment(Document):
|
||||
additional_salary = frappe.new_doc("Additional Salary")
|
||||
additional_salary.company = frappe.get_value("Employee", self.employee, "company")
|
||||
additional_salary.employee = self.employee
|
||||
additional_salary.currency = self.currency
|
||||
earning_component = frappe.get_value("Leave Type", self.leave_type, "earning_component")
|
||||
if not earning_component:
|
||||
frappe.throw(_("Please set Earning Component for Leave type: {0}.").format(self.leave_type))
|
||||
|
||||
@@ -48,6 +48,10 @@ class TestLeaveEncashment(unittest.TestCase):
|
||||
frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0]).grant_leave_alloc_for_employee()
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
for dt in ["Leave Period", "Leave Allocation", "Leave Ledger Entry", "Additional Salary", "Leave Encashment", "Salary Structure", "Leave Policy"]:
|
||||
frappe.db.sql("delete from `tab%s`" % dt)
|
||||
|
||||
def test_leave_balance_value_and_amount(self):
|
||||
frappe.db.sql('''delete from `tabLeave Encashment`''')
|
||||
leave_encashment = frappe.get_doc(dict(
|
||||
@@ -55,7 +59,8 @@ class TestLeaveEncashment(unittest.TestCase):
|
||||
employee=self.employee,
|
||||
leave_type="_Test Leave Type Encashment",
|
||||
leave_period=self.leave_period.name,
|
||||
payroll_date=today()
|
||||
payroll_date=today(),
|
||||
currency="INR"
|
||||
)).insert()
|
||||
|
||||
self.assertEqual(leave_encashment.leave_balance, 10)
|
||||
@@ -75,7 +80,8 @@ class TestLeaveEncashment(unittest.TestCase):
|
||||
employee=self.employee,
|
||||
leave_type="_Test Leave Type Encashment",
|
||||
leave_period=self.leave_period.name,
|
||||
payroll_date=today()
|
||||
payroll_date=today(),
|
||||
currency="INR"
|
||||
)).insert()
|
||||
|
||||
leave_encashment.submit()
|
||||
|
||||
Reference in New Issue
Block a user