diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 8284528a9ad..cb1d1d6b5a3 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -912,7 +912,8 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre if ref_doc.doctype == "Expense Claim": total_amount = flt(ref_doc.total_sanctioned_amount) + flt(ref_doc.total_taxes_and_charges) elif ref_doc.doctype == "Employee Advance": - total_amount = ref_doc.advance_amount + total_amount = ref_doc.advance_amount + if party_account_currency != company_currency: exchange_rate = ref_doc.get("exchange_rate") if not total_amount: if party_account_currency == company_currency: @@ -934,7 +935,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre outstanding_amount = flt(ref_doc.get("total_sanctioned_amount")) + flt(ref_doc.get("total_taxes_and_charges"))\ - flt(ref_doc.get("total_amount_reimbursed")) - flt(ref_doc.get("total_advance_amount")) elif reference_doctype == "Employee Advance": - outstanding_amount = ref_doc.advance_amount - flt(ref_doc.paid_amount) + outstanding_amount = (flt(ref_doc.advance_amount) - flt(ref_doc.paid_amount)) else: outstanding_amount = flt(total_amount) - flt(ref_doc.advance_paid) else: @@ -957,70 +958,14 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) > 0: frappe.throw(_("Can only make payment against unbilled {0}").format(dt)) - if dt in ("Sales Invoice", "Sales Order", "Dunning"): - party_type = "Customer" - elif dt in ("Purchase Invoice", "Purchase Order"): - party_type = "Supplier" - elif dt in ("Expense Claim", "Employee Advance"): - party_type = "Employee" - elif dt in ("Fees"): - party_type = "Student" - - # party account - if dt == "Sales Invoice": - party_account = get_party_account_based_on_invoice_discounting(dn) or doc.debit_to - elif dt == "Purchase Invoice": - party_account = doc.credit_to - elif dt == "Fees": - party_account = doc.receivable_account - elif dt == "Employee Advance": - party_account = doc.advance_account - elif dt == "Expense Claim": - party_account = doc.payable_account - else: - party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company) - - if dt not in ("Sales Invoice", "Purchase Invoice"): - party_account_currency = get_account_currency(party_account) - else: - party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account) - - # payment type - if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \ - or (dt=="Purchase Invoice" and doc.outstanding_amount < 0): - payment_type = "Receive" - else: - payment_type = "Pay" - - # amounts - grand_total = outstanding_amount = 0 - if party_amount: - grand_total = outstanding_amount = party_amount - elif dt in ("Sales Invoice", "Purchase Invoice"): - if party_account_currency == doc.company_currency: - grand_total = doc.base_rounded_total or doc.base_grand_total - else: - grand_total = doc.rounded_total or doc.grand_total - outstanding_amount = doc.outstanding_amount - elif dt in ("Expense Claim"): - grand_total = doc.total_sanctioned_amount + doc.total_taxes_and_charges - outstanding_amount = doc.grand_total \ - - doc.total_amount_reimbursed - elif dt == "Employee Advance": - grand_total = doc.advance_amount - outstanding_amount = flt(doc.advance_amount) - flt(doc.paid_amount) - elif dt == "Fees": - grand_total = doc.grand_total - outstanding_amount = doc.outstanding_amount - elif dt == "Dunning": - grand_total = doc.grand_total - outstanding_amount = doc.grand_total - else: - if party_account_currency == doc.company_currency: - grand_total = flt(doc.get("base_rounded_total") or doc.base_grand_total) - else: - grand_total = flt(doc.get("rounded_total") or doc.grand_total) - outstanding_amount = grand_total - flt(doc.advance_paid) + party_type = set_party_type(dt) + party_account = set_party_account(dt, doc, party_type) + exchange_rate = 1 + party_account_currency = set_party_account_currency(dt, party_account, doc) + if party_account_currency != doc.currency: + exchange_rate = doc.get('exchange_rate', 1) + payment_type = set_payment_type(dt, doc) + grand_total, outstanding_amount = set_grand_total_and_outstanding_amount(party_amount, dt, party_account_currency, doc, exchange_rate) # bank or cash bank = get_default_bank_cash_account(doc.company, "Bank", mode_of_payment=doc.get("mode_of_payment"), @@ -1030,22 +975,7 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= bank = get_default_bank_cash_account(doc.company, "Cash", mode_of_payment=doc.get("mode_of_payment"), account=bank_account) - paid_amount = received_amount = 0 - if party_account_currency == bank.account_currency: - paid_amount = received_amount = abs(outstanding_amount) - elif payment_type == "Receive": - paid_amount = abs(outstanding_amount) - if bank_amount: - received_amount = bank_amount - else: - received_amount = paid_amount * doc.get('conversion_rate', 1) - else: - received_amount = abs(outstanding_amount) - if bank_amount: - paid_amount = bank_amount - else: - # if party account currency and bank currency is different then populate paid amount as well - paid_amount = received_amount * doc.get('conversion_rate', 1) + paid_amount, received_amount = set_paid_amount_and_received_amount(dt, party_account_currency, bank, outstanding_amount, payment_type, bank_amount, doc) pe = frappe.new_doc("Payment Entry") pe.payment_type = payment_type @@ -1121,6 +1051,101 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= pe.set_amounts() return pe +def set_party_type(dt): + if dt in ("Sales Invoice", "Sales Order", "Dunning"): + party_type = "Customer" + elif dt in ("Purchase Invoice", "Purchase Order"): + party_type = "Supplier" + elif dt in ("Expense Claim", "Employee Advance"): + party_type = "Employee" + elif dt in ("Fees"): + party_type = "Student" + return party_type + +def set_party_account(dt, doc, party_type): + if dt == "Sales Invoice": + party_account = get_party_account_based_on_invoice_discounting(dn) or doc.debit_to + elif dt == "Purchase Invoice": + party_account = doc.credit_to + elif dt == "Fees": + party_account = doc.receivable_account + elif dt == "Employee Advance": + party_account = doc.advance_account + elif dt == "Expense Claim": + party_account = doc.payable_account + else: + party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company) + return party_account + +def set_party_account_currency(dt, party_account, doc): + if dt not in ("Sales Invoice", "Purchase Invoice"): + party_account_currency = get_account_currency(party_account) + else: + party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account) + return party_account_currency + +def set_payment_type(dt, doc): + if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \ + or (dt=="Purchase Invoice" and doc.outstanding_amount < 0): + payment_type = "Receive" + else: + payment_type = "Pay" + return payment_type + +def set_grand_total_and_outstanding_amount(party_amount, dt, party_account_currency, doc, exchange_rate): + grand_total = outstanding_amount = 0 + if party_amount: + grand_total = outstanding_amount = party_amount + elif dt in ("Sales Invoice", "Purchase Invoice"): + if party_account_currency == doc.company_currency: + grand_total = doc.base_rounded_total or doc.base_grand_total + else: + grand_total = doc.rounded_total or doc.grand_total + outstanding_amount = doc.outstanding_amount + elif dt in ("Expense Claim"): + grand_total = doc.total_sanctioned_amount + doc.total_taxes_and_charges + outstanding_amount = doc.grand_total \ + - doc.total_amount_reimbursed + elif dt == "Employee Advance": + grand_total = flt(doc.advance_amount) * flt(exchange_rate) + outstanding_amount = (flt(doc.advance_amount) - flt(doc.paid_amount)) * flt(exchange_rate) + elif dt == "Fees": + grand_total = doc.grand_total + outstanding_amount = doc.outstanding_amount + elif dt == "Dunning": + grand_total = doc.grand_total + outstanding_amount = doc.grand_total + else: + if party_account_currency == doc.company_currency: + grand_total = flt(doc.get("base_rounded_total") or doc.base_grand_total) + else: + grand_total = flt(doc.get("rounded_total") or doc.grand_total) + outstanding_amount = grand_total - flt(doc.advance_paid) + return grand_total, outstanding_amount + +def set_paid_amount_and_received_amount(dt, party_account_currency, bank, outstanding_amount, payment_type, bank_amount, doc): + paid_amount = received_amount = 0 + if party_account_currency == bank.account_currency: + paid_amount = received_amount = abs(outstanding_amount) + elif payment_type == "Receive": + paid_amount = abs(outstanding_amount) + if bank_amount: + received_amount = bank_amount + else: + received_amount = paid_amount * doc.get('conversion_rate', 1) + if dt == "Employee Advance": + received_amount = paid_amount * doc.get('exchange_rate', 1) + else: + received_amount = abs(outstanding_amount) + if bank_amount: + paid_amount = bank_amount + else: + # if party account currency and bank currency is different then populate paid amount as well + paid_amount = received_amount * doc.get('conversion_rate', 1) + if dt == "Employee Advance": + paid_amount = received_amount * doc.get('exchange_rate', 1) + return paid_amount, received_amount + def get_reference_as_per_payment_terms(payment_schedule, dt, dn, doc, grand_total, outstanding_amount): references = [] for payment_term in payment_schedule: diff --git a/erpnext/accounts/doctype/salary_component_account/salary_component_account.json b/erpnext/accounts/doctype/salary_component_account/salary_component_account.json index 9808a9e85c2..f1ed8efa319 100644 --- a/erpnext/accounts/doctype/salary_component_account/salary_component_account.json +++ b/erpnext/accounts/doctype/salary_component_account/salary_component_account.json @@ -6,8 +6,7 @@ "engine": "InnoDB", "field_order": [ "company", - "default_account", - "account_currency" + "account" ], "fields": [ { @@ -19,24 +18,16 @@ }, { "description": "Default Bank / Cash account will be automatically updated in Salary Journal Entry when this mode is selected.", - "fieldname": "default_account", + "fieldname": "account", "fieldtype": "Link", "in_list_view": 1, - "label": "Default Account", + "label": "Account", "options": "Account" - }, - { - "fetch_from": "default_account.account_currency", - "fieldname": "account_currency", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Account Currency", - "read_only": 1 } ], "istable": 1, "links": [], - "modified": "2020-09-30 13:50:06.809353", + "modified": "2020-10-18 17:57:57.110257", "modified_by": "Administrator", "module": "Accounts", "name": "Salary Component Account", diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js index 66988fb8e2d..04771108e9a 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.js +++ b/erpnext/hr/doctype/employee_advance/employee_advance.js @@ -18,12 +18,13 @@ frappe.ui.form.on('Employee Advance', { 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, - "account_currency": frm.doc.currency, + "account_currency": ["in",[frm.doc.currency, company_currency]], } }; }); @@ -142,33 +143,39 @@ frappe.ui.form.on('Employee Advance', { employee: function (frm) { if (frm.doc.employee) { - 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.call({ - method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_payroll_payable_account_currency", - args: { - employee: frm.doc.employee, - }, - callback: function(r) { - if(r.message) { - frm.set_value('currency', r.message); - frm.set_df_property('currency', 'hidden', 0); - frm.refresh_fields() - } - } - }); + frm.trigger('get_pending_amount'); + frm.trigger('get_employee_currency'); } }, + 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; if (!frm.doc.company) { @@ -177,26 +184,15 @@ frappe.ui.form.on('Employee Advance', { else { var company_currency = erpnext.get_currency(frm.doc.company); } - if(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); - cur_frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency - + " = [?] " + company_currency); - frm.refresh_fields(); - } - }); - } else { + if(from_currency == company_currency) { 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(); + } else { + frm.set_value("exchange_rate", ''); + frm.set_df_property('exchange_rate', 'hidden', 0); + frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency + " = [?] " + company_currency); } + frm.refresh_fields(); }, }); diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json index 24739cbdbbf..4dcedba0711 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.json +++ b/erpnext/hr/doctype/employee_advance/employee_advance.json @@ -197,13 +197,12 @@ "label": "Exchange Rate", "precision": "9", "print_hide": 1, - "read_only": 1, "reqd": 1 } ], "is_submittable": 1, "links": [], - "modified": "2020-09-30 19:05:42.364629", + "modified": "2020-10-22 03:48:09.386149", "modified_by": "Administrator", "module": "HR", "name": "Employee Advance", diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py index d53fa760c63..0953610eeb9 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance.py @@ -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,32 +37,42 @@ 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 + paid_amount = 0 + return_amount = 0 + + paid_amount_data = frappe.db.sql(""" + select debit_in_account_currency as paid_amount, account from `tabGL Entry` where against_voucher_type = 'Employee Advance' and against_voucher = %s and party_type = 'Employee' and party = %s - """, (self.name, self.employee), as_dict=1)[0].paid_amount + """, (self.name, self.employee), as_dict=1) - return_amount = frappe.db.sql(""" - select name, ifnull(sum(credit_in_account_currency), 0) as return_amount + return_amount_data = frappe.db.sql(""" + select credit_in_account_currency as return_amount, account from `tabGL Entry` where against_voucher_type = 'Employee Advance' and voucher_type != 'Expense Claim' and against_voucher = %s and party_type = 'Employee' and party = %s - """, (self.name, self.employee), as_dict=1)[0].return_amount + """, (self.name, self.employee), as_dict=1) + + for pmd in paid_amount_data: + account_currency = frappe.db.get_value('Account', pmd.account, 'account_currency') + if account_currency != self.currency: + paid_amount += flt(pmd.paid_amount) / flt(self.exchange_rate) + else: + paid_amount += flt(pmd.paid_amount) + + for rmd in return_amount_data: + account_currency = frappe.db.get_value('Account', rmd.account, 'account_currency') + if account_currency != self.currency: + return_amount += flt(rmd.paid_amount) / flt(self.exchange_rate) + else: + return_amount += flt(rmd.paid_amount) if flt(paid_amount) > self.advance_amount: frappe.throw(_("Row {0}# Paid Amount cannot be greater than requested advance amount"), @@ -109,24 +118,26 @@ def make_bank_entry(dt, dn): mode_of_payment=doc.mode_of_payment) if not payment_account: frappe.throw(_("Please set a Default Cash Account in Company defaults")) - multi_currency = 0 - credit_in_account_currency = flt(doc.advance_amount) - company_currency = erpnext.get_company_currency(doc.company) + + advance_account_currency = frappe.db.get_value('Account', doc.advance_account, 'account_currency') + + 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 if payment_account.account_currency != doc.currency: - if return_account.account_currency != company_currency: - frappe.throw(_("""Account currency of default Cash or Bank account in Mode of Payment for - account type: {0} for company: {1} is different than company currency: {2} and currency: {3} specified - in employee advance {4}. Please set default Cash or Bank account in either currency: {5} or {6}""") - .format("Cash", doc.company, company_currency, doc.currency, doc.name, - company_currency, doc.currency), title=_("Currency Mismatch")) - else: - multi_currency = 1 - credit_in_account_currency = flt(doc.advance_amount) * flt(doc.exchange_rate) + 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 - # if doc.currency != payment_account.account_currency: - # multi_currency = 1 - # credit_in_account_currency = flt(doc.advance_amount) * flt(doc.exchange_rate) + multi_currency = 0 + if advance_account_currency != payment_account.account_currency: + multi_currency = 1 je = frappe.new_doc("Journal Entry") je.posting_date = nowdate() @@ -137,9 +148,9 @@ def make_bank_entry(dt, dn): je.append("accounts", { "account": doc.advance_account, - "account_currency": doc.currency, - "exchange_rate": doc.exchange_rate, - "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", @@ -151,9 +162,10 @@ 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": credit_in_account_currency, + "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() @@ -177,22 +189,28 @@ def make_return_entry(employee, company, employee_advance_name, return_amount, return_account = get_default_bank_cash_account(company, account_type='Cash', mode_of_payment = mode_of_payment) if not return_account: frappe.throw(_("Please set a Default Cash Account in Company defaults")) - company_currency = erpnext.get_company_currency(company) + + advance_account_currency = frappe.db.get_value('Account', advance_account, 'account_currency') employee_advance_doc = frappe.get_doc("Employee Advance", employee_advance_name) - multi_currency = 0 - exchange_rate = 1 + if advance_account_currency != employee_advance_doc.currency: + advance_amount = flt(return_amount) * flt(employee_advance_doc.exchange_rate) + advance_exchange_rate = 1 + else: + advance_amount = return_amount + advance_exchange_rate = employee_advance_doc.exchange_rate + if return_account.account_currency != employee_advance_doc.currency: - if return_account.account_currency != company_currency: - frappe.throw(_("""Account currency of default Cash or Bank account in Mode of Payment for - account type: {0} for company: {1} is different than company currency: {2} and currency: {3} specified - in employee advance {4}. Please set default Cash or Bank account in either currency: {5} or {6}""") - .format("Cash", company, company_currency, employee_advance_doc.currency, employee_advance_name, - company_currency, employee_advance_doc.currency), title=_("Currency Mismatch")) - else: - exchange_rate = employee_advance_doc.exchange_rate - multi_currency = 1 + returning_amount = flt(return_amount) * flt(employee_advance_doc.exchange_rate) + returning_exchange_rate = 1 + else: + returning_amount = return_amount + returning_exchange_rate = employee_advance_doc.exchange_rate + + multi_currency = 0 + if advance_account_currency != return_account.account_currency: + multi_currency = 1 mode_of_payment_type = '' if mode_of_payment: @@ -211,9 +229,9 @@ def make_return_entry(employee, company, employee_advance_name, return_amount, je.append('accounts', { 'account': advance_account, - 'credit_in_account_currency': return_amount, - 'account_currency': employee_advance_doc.currency, - 'exchange_rate': exchange_rate, + 'credit_in_account_currency': advance_amount, + 'account_currency': advance_account_currency, + 'exchange_rate': advance_exchange_rate, 'reference_type': 'Employee Advance', 'reference_name': employee_advance_name, 'party_type': 'Employee', @@ -223,9 +241,10 @@ def make_return_entry(employee, company, employee_advance_name, return_amount, je.append("accounts", { "account": return_account.account, - "debit_in_account_currency": flt(return_amount) * exchange_rate, + "debit_in_account_currency": returning_amount, "account_currency": return_account.account_currency, - "account_type": return_account.account_type + "account_type": return_account.account_type, + "exchange_rate": returning_exchange_rate }) return je.as_dict() diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.js b/erpnext/hr/doctype/leave_encashment/leave_encashment.js index 93cf21943d4..bd3065d210f 100644 --- a/erpnext/hr/doctype/leave_encashment/leave_encashment.js +++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.js @@ -23,6 +23,7 @@ frappe.ui.form.on('Leave Encashment', { }, employee: function(frm) { frm.trigger("get_leave_details_for_encashment"); + frm.trigger('get_employee_currency'); }, leave_type: function(frm) { frm.trigger("get_leave_details_for_encashment"); @@ -37,21 +38,23 @@ frappe.ui.form.on('Leave Encashment', { doc: frm.doc, callback: function(r) { frm.refresh_fields(); - frappe.call({ - method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_payroll_payable_account_currency", - args: { - employee: frm.doc.employee, - }, - callback: function(r) { - if(r.message) { - frm.set_value('currency', r.message); - frm.set_df_property('currency', 'hidden', 0); - frm.refresh_fields(); - } - } - }); } }); } - } + }, + + 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(); + } + } + }); + }, }); diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.json b/erpnext/hr/doctype/leave_encashment/leave_encashment.json index f04ab01ca58..ed4691f9f01 100644 --- a/erpnext/hr/doctype/leave_encashment/leave_encashment.json +++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.json @@ -130,9 +130,9 @@ }, { "default": "Company:company:default_currency", + "depends_on": "eval:(doc.docstatus==1 || doc.employee)", "fieldname": "currency", "fieldtype": "Link", - "hidden": 1, "label": "Currency", "options": "Currency", "print_hide": 1, @@ -146,7 +146,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-09-24 19:21:56.856605", + "modified": "2020-10-20 17:44:14.590652", "modified_by": "Administrator", "module": "HR", "name": "Leave Encashment", diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json index aa5e21b426b..3a3496042d6 100644 --- a/erpnext/loan_management/doctype/loan/loan.json +++ b/erpnext/loan_management/doctype/loan/loan.json @@ -26,11 +26,11 @@ "disbursed_amount", "column_break_11", "maximum_loan_amount", - "is_term_loan", "repayment_method", "repayment_periods", "monthly_repayment_amount", "repayment_start_date", + "is_term_loan", "account_info", "mode_of_payment", "payment_account", @@ -334,7 +334,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-08-01 12:36:11.255233", + "modified": "2020-10-21 13:30:51.709754", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan", diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py index d1b7589a17e..0b51d169a7a 100644 --- a/erpnext/loan_management/doctype/loan/loan.py +++ b/erpnext/loan_management/doctype/loan/loan.py @@ -12,6 +12,8 @@ from erpnext.controllers.accounts_controller import AccountsController class Loan(AccountsController): def validate(self): + if self.applicant_type == 'Employee': + validate_employe_currency_with_company_currency(self.applicant, self.company) self.set_loan_amount() self.validate_loan_amount() self.set_missing_fields() @@ -274,5 +276,14 @@ def create_loan_security_unpledge(unpledge_map, loan, company, applicant_type, a return unpledge_request - - +def validate_employe_currency_with_company_currency(applicant, company): + from erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment import get_employee_currency + if not applicant: + frappe.throw(_("Please select Applicant")) + if not company: + frappe.throw(_("Please select Company")) + employee_currency = get_employee_currency(applicant) + company_currency = erpnext.get_company_currency(company) + if employee_currency != company_currency: + frappe.throw(_("Currency in salary structure for employee {0} should be in {1}") + .format(applicant, company_currency)) diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.py b/erpnext/loan_management/doctype/loan_application/loan_application.py index bac6e638d74..1537faf81a0 100644 --- a/erpnext/loan_management/doctype/loan_application/loan_application.py +++ b/erpnext/loan_management/doctype/loan_application/loan_application.py @@ -3,7 +3,7 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, math +import frappe, math, erpnext from frappe import _ from frappe.utils import flt, rounded, cint from frappe.model.mapper import get_mapped_doc @@ -16,6 +16,9 @@ from six import string_types class LoanApplication(Document): def validate(self): + if self.applicant_type == 'Employee': + from erpnext.loan_management.doctype.loan.loan import validate_employe_currency_with_company_currency + validate_employe_currency_with_company_currency(self.applicant, self.company) self.set_pledge_amount() self.set_loan_amount() self.validate_loan_amount() diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py index 2bb6fd84e58..b5450899241 100644 --- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py +++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py @@ -12,6 +12,9 @@ from erpnext.loan_management.doctype.loan_security_price.loan_security_price imp class LoanSecurityPledge(Document): def validate(self): + if self.applicant_type == 'Employee': + from erpnext.loan_management.doctype.loan.loan import validate_employe_currency_with_company_currency + validate_employe_currency_with_company_currency(self.applicant, self.company) self.set_pledge_amount() self.validate_duplicate_securities() self.validate_loan_security_type() diff --git a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py index b3eb6001e42..b5caabf413e 100644 --- a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py +++ b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py @@ -13,6 +13,9 @@ from erpnext.loan_management.doctype.loan_security_price.loan_security_price imp class LoanSecurityUnpledge(Document): def validate(self): + if self.applicant_type == 'Employee': + from erpnext.loan_management.doctype.loan.loan import validate_employe_currency_with_company_currency + validate_employe_currency_with_company_currency(self.applicant, self.company) self.validate_duplicate_securities() self.validate_unpledge_qty() diff --git a/erpnext/loan_management/doctype/sanctioned_loan_amount/sanctioned_loan_amount.py b/erpnext/loan_management/doctype/sanctioned_loan_amount/sanctioned_loan_amount.py index 74a131015b5..b2171a1025f 100644 --- a/erpnext/loan_management/doctype/sanctioned_loan_amount/sanctioned_loan_amount.py +++ b/erpnext/loan_management/doctype/sanctioned_loan_amount/sanctioned_loan_amount.py @@ -8,6 +8,9 @@ from frappe.model.document import Document class SanctionedLoanAmount(Document): def validate(self): + if self.applicant_type == 'Employee': + from erpnext.loan_management.doctype.loan.loan import validate_employe_currency_with_company_currency + validate_employe_currency_with_company_currency(self.applicant, self.company) sanctioned_doc = frappe.db.exists('Sanctioned Loan Amount', {'applicant': self.applicant, 'company': self.company}) if sanctioned_doc and sanctioned_doc != self.name: diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.js b/erpnext/payroll/doctype/additional_salary/additional_salary.js index 36afd133242..d35bb2472ff 100644 --- a/erpnext/payroll/doctype/additional_salary/additional_salary.js +++ b/erpnext/payroll/doctype/additional_salary/additional_salary.js @@ -23,37 +23,44 @@ frappe.ui.form.on('Additional Salary', { }, employee: function(frm) { - debugger; if (frm.doc.employee) { - frappe.call({ - method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_payroll_payable_account_currency", - args: { - employee: frm.doc.employee, - }, - callback: function(r) { - if(r.message) { - frm.set_value('currency', r.message); - frm.set_df_property('currency', 'hidden', 0); - } - } - }); - frappe.call({ - method: "frappe.client.get_value", - args:{ - doctype: "Employee", - fieldname: "company", - filters:{ - name: frm.doc.employee - } - }, - callback: function(data) { - if(data.message){ - frm.set_value("company", data.message.company); - } - } - }); + frm.trigger('set_company'); + frm.trigger('get_employee_currency'); } else { frm.set_value("company", null); } }, + + set_company: function(frm) { + frappe.call({ + method: "frappe.client.get_value", + args:{ + doctype: "Employee", + fieldname: "company", + filters:{ + name: frm.doc.employee + } + }, + callback: function(data) { + if(data.message){ + frm.set_value("company", data.message.company); + } + } + }); + }, + + 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(); + } + } + }); + }, }); diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.json b/erpnext/payroll/doctype/additional_salary/additional_salary.json index f3bbaffe505..2b29f667fbc 100644 --- a/erpnext/payroll/doctype/additional_salary/additional_salary.json +++ b/erpnext/payroll/doctype/additional_salary/additional_salary.json @@ -164,9 +164,9 @@ }, { "default": "Company:company:default_currency", + "depends_on": "eval:(doc.docstatus==1 || doc.employee)", "fieldname": "currency", "fieldtype": "Link", - "hidden": 1, "label": "Currency", "options": "Currency", "print_hide": 1, @@ -176,7 +176,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-09-24 12:55:51.660506", + "modified": "2020-10-20 17:51:13.419716", "modified_by": "Administrator", "module": "Payroll", "name": "Additional Salary", diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.js index 8f865e44d9b..e6301cc6e14 100644 --- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.js @@ -3,6 +3,7 @@ frappe.ui.form.on('Employee Benefit Application', { employee: function(frm) { + frm.trigger('get_employee_currency'); frm.trigger('set_earning_component'); var method, args; if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){ @@ -36,9 +37,12 @@ frappe.ui.form.on('Employee Benefit Application', { filters: {date: frm.doc.date, employee: frm.doc.employee} }; }); + }, + + get_employee_currency: function(frm) { if (frm.doc.employee) { frappe.call({ - method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_payroll_payable_account_currency", + method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency", args: { employee: frm.doc.employee, }, @@ -70,7 +74,6 @@ frappe.ui.form.on('Employee Benefit Application', { }); var get_max_benefits=function(frm, method, args) { - debugger; frappe.call({ method: method, args: args, diff --git a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.js b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.js index a65843eaef4..96dc258f15f 100644 --- a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.js +++ b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.js @@ -14,7 +14,7 @@ frappe.ui.form.on('Employee Benefit Claim', { frm.set_value("earning_component", null); if (frm.doc.employee) { frappe.call({ - method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_payroll_payable_account_currency", + method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_employee_currency", args: { employee: frm.doc.employee, }, diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.js b/erpnext/payroll/doctype/employee_incentive/employee_incentive.js index 8326d5f7904..d042cffd89c 100644 --- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.js +++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.js @@ -22,37 +22,44 @@ frappe.ui.form.on('Employee Incentive', { }, employee: function(frm) { - frm.trigger("get_leave_details_for_encashment"); if (frm.doc.employee) { - frappe.call({ - method: "erpnext.payroll.doctype.salary_structure_assignment.salary_structure_assignment.get_payroll_payable_account_currency", - args: { - employee: frm.doc.employee, - }, - callback: function(r) { - if(r.message) { - frm.set_value('currency', r.message); - frm.set_df_property('currency', 'hidden', 0); - } - } - }); - frappe.call({ - method: "frappe.client.get_value", - args:{ - doctype: "Employee", - fieldname: "company", - filters:{ - name: frm.doc.employee - } - }, - callback: function(data) { - if(data.message){ - frm.set_value("company", data.message.company); - } - } - }); + frm.trigger('set_company'); + frm.trigger('get_employee_currency'); } else { frm.set_value("company", null); } }, + + set_company: function(frm) { + frappe.call({ + method: "frappe.client.get_value", + args:{ + doctype: "Employee", + fieldname: "company", + filters:{ + name: frm.doc.employee + } + }, + callback: function(data) { + if(data.message){ + frm.set_value("company", data.message.company); + } + } + }); + }, + + 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(); + } + } + }); + }, }); diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.json b/erpnext/payroll/doctype/employee_incentive/employee_incentive.json index 0bec4b1b664..e5b1052b3a5 100644 --- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.json +++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.json @@ -79,7 +79,6 @@ "depends_on": "eval:(doc.docstatus==1 || doc.employee)", "fieldname": "currency", "fieldtype": "Link", - "hidden": 1, "label": "Currency", "options": "Currency", "print_hide": 1, @@ -96,7 +95,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-09-30 17:59:57.754477", + "modified": "2020-10-20 17:22:16.468042", "modified_by": "Administrator", "module": "Payroll", "name": "Employee Incentive", diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json b/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json index de7c348bb2c..83d4ae53df8 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json +++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json @@ -14,6 +14,7 @@ "column_break_2", "payroll_period", "company", + "currency", "amended_from", "section_break_8", "declarations", @@ -92,6 +93,7 @@ "fieldname": "total_declared_amount", "fieldtype": "Currency", "label": "Total Declared Amount", + "options": "currency", "read_only": 1 }, { @@ -102,12 +104,22 @@ "fieldname": "total_exemption_amount", "fieldtype": "Currency", "label": "Total Exemption Amount", + "options": "currency", "read_only": 1 + }, + { + "default": "Company:company:default_currency", + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency", + "print_hide": 1, + "reqd": 1 } ], "is_submittable": 1, "links": [], - "modified": "2020-06-22 22:49:43.829892", + "modified": "2020-10-20 16:42:24.493761", "modified_by": "Administrator", "module": "Payroll", "name": "Employee Tax Exemption Declaration", diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json b/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json index 8c2f9aa370a..723a3df3c7f 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json +++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration_category/employee_tax_exemption_declaration_category.json @@ -35,6 +35,7 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Maximum Exempted Amount", + "options": "currency", "read_only": 1, "reqd": 1 }, @@ -43,12 +44,13 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Declared Amount", + "options": "currency", "reqd": 1 } ], "istable": 1, "links": [], - "modified": "2020-06-22 23:41:03.638739", + "modified": "2020-10-20 16:43:09.606265", "modified_by": "Administrator", "module": "Payroll", "name": "Employee Tax Exemption Declaration Category", diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js index 715d7553b00..497f35c41e3 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js +++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.js @@ -54,5 +54,9 @@ frappe.ui.form.on('Employee Tax Exemption Proof Submission', { }); }); } + }, + + currency: function(frm) { + frm.refresh_fields(); } }); diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json index b62b5aab0b4..53f18cb1fe3 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json +++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json @@ -11,6 +11,7 @@ "employee", "employee_name", "department", + "currency", "column_break_2", "submission_date", "payroll_period", @@ -97,6 +98,7 @@ "fieldname": "total_actual_amount", "fieldtype": "Currency", "label": "Total Actual Amount", + "options": "currency", "read_only": 1 }, { @@ -107,6 +109,7 @@ "fieldname": "exemption_amount", "fieldtype": "Currency", "label": "Total Exemption Amount", + "options": "currency", "read_only": 1 }, { @@ -126,11 +129,20 @@ "options": "Employee Tax Exemption Proof Submission", "print_hide": 1, "read_only": 1 + }, + { + "default": "Company:company:default_currency", + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency", + "print_hide": 1, + "reqd": 1 } ], "is_submittable": 1, "links": [], - "modified": "2020-06-22 22:53:10.412321", + "modified": "2020-10-20 16:47:03.410020", "modified_by": "Administrator", "module": "Payroll", "name": "Employee Tax Exemption Proof Submission", diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json index c1f532050ac..2fd8b94efdb 100644 --- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json +++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission_detail/employee_tax_exemption_proof_submission_detail.json @@ -34,6 +34,7 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Maximum Exemption Amount", + "options": "currency", "read_only": 1, "reqd": 1 }, @@ -48,12 +49,13 @@ "fieldname": "amount", "fieldtype": "Currency", "in_list_view": 1, - "label": "Actual Amount" + "label": "Actual Amount", + "options": "currency" } ], "istable": 1, "links": [], - "modified": "2020-06-22 23:37:08.265600", + "modified": "2020-10-20 16:47:31.480870", "modified_by": "Administrator", "module": "Payroll", "name": "Employee Tax Exemption Proof Submission Detail", diff --git a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.js b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.js index 73a54eb8dd9..7d780d3b040 100644 --- a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.js +++ b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.js @@ -2,5 +2,7 @@ // For license information, please see license.txt frappe.ui.form.on('Income Tax Slab', { - + currency: function(frm) { + frm.refresh_fields(); + } }); diff --git a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json index 6337d5a6d3e..9fa261dea2d 100644 --- a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json +++ b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json @@ -9,8 +9,9 @@ "effective_from", "company", "column_break_3", - "allow_tax_exemption", + "currency", "standard_tax_exemption_amount", + "allow_tax_exemption", "disabled", "amended_from", "taxable_salary_slabs_section", @@ -70,7 +71,7 @@ "fieldname": "standard_tax_exemption_amount", "fieldtype": "Currency", "label": "Standard Tax Exemption Amount", - "options": "Company:company:default_currency" + "options": "currency" }, { "fieldname": "company", @@ -90,11 +91,20 @@ "fieldtype": "Table", "label": "Other Taxes and Charges", "options": "Income Tax Slab Other Charges" + }, + { + "default": "Company:company:default_currency", + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency", + "print_hide": 1, + "reqd": 1 } ], "is_submittable": 1, "links": [], - "modified": "2020-06-22 20:27:13.425084", + "modified": "2020-10-19 13:54:24.728075", "modified_by": "Administrator", "module": "Payroll", "name": "Income Tax Slab", diff --git a/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json b/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json index 7f21204591a..0dba3382504 100644 --- a/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json +++ b/erpnext/payroll/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json @@ -45,7 +45,7 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Min Taxable Income", - "options": "Company:company:default_currency" + "options": "currency" }, { "fieldname": "column_break_7", @@ -57,12 +57,12 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Max Taxable Income", - "options": "Company:company:default_currency" + "options": "currency" } ], "istable": 1, "links": [], - "modified": "2020-06-22 23:33:17.931912", + "modified": "2020-10-19 13:45:12.850090", "modified_by": "Administrator", "module": "Payroll", "name": "Income Tax Slab Other Charges", diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js index 58a4faf30c7..1051ce2adc8 100644 --- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js +++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js @@ -24,7 +24,6 @@ frappe.ui.form.on('Payroll Entry', { "company": frm.doc.company, "root_type": "Liability", "is_group": 0, - "account_currency": frm.doc.currency } } }); @@ -151,7 +150,6 @@ frappe.ui.form.on('Payroll Entry', { }, currency: function (frm) { - debugger; if (!frm.doc.company) { var company_currency = erpnext.get_currency(frappe.defaults.get_default("Company")); } diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.json b/erpnext/payroll/doctype/payroll_entry/payroll_entry.json index bfaf6248d09..681d075ce8a 100644 --- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.json +++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.json @@ -282,7 +282,7 @@ "depends_on": "company", "fieldname": "default_payroll_payable_account", "fieldtype": "Link", - "label": "Default Payroll Payable Account", + "label": "Payroll Payable Account", "options": "Account", "reqd": 1 } @@ -290,7 +290,7 @@ "icon": "fa fa-cog", "is_submittable": 1, "links": [], - "modified": "2020-09-30 12:47:45.729777", + "modified": "2020-10-22 01:57:27.226066", "modified_by": "Administrator", "module": "Payroll", "name": "Payroll Entry", diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py index a97f8f88f85..5e31367abfa 100644 --- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py @@ -125,7 +125,8 @@ class PayrollEntry(Document): "posting_date": self.posting_date, "deduct_tax_for_unclaimed_employee_benefits": self.deduct_tax_for_unclaimed_employee_benefits, "deduct_tax_for_unsubmitted_tax_exemption_proof": self.deduct_tax_for_unsubmitted_tax_exemption_proof, - "payroll_entry": self.name + "payroll_entry": self.name, + "exchange_rate": self.exchange_rate }) if len(emp_list) > 30: frappe.enqueue(create_salary_slips_for_employees, timeout=600, employees=emp_list, args=args) @@ -205,21 +206,10 @@ class PayrollEntry(Document): account_dict[(account, key[1])] = account_dict.get((account, key[1]), 0) + amount return account_dict - def get_default_payroll_payable_account(self): - payroll_payable_account = frappe.get_cached_value('Company', - {"company_name": self.company}, "default_payroll_payable_account") - - if not payroll_payable_account: - frappe.throw(_("Please set Default Payroll Payable Account in Company {0}") - .format(self.company)) - - return payroll_payable_account - def make_accrual_jv_entry(self): self.check_permission('write') earnings = self.get_salary_component_total(component_type = "earnings") or {} deductions = self.get_salary_component_total(component_type = "deductions") or {} - # default_payroll_payable_account = self.get_default_payroll_payable_account() default_payroll_payable_account = self.default_payroll_payable_account jv_name = "" precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency") @@ -329,7 +319,6 @@ class PayrollEntry(Document): self.create_journal_entry(salary_slip_total, "salary") def create_journal_entry(self, je_payment_amount, user_remark): - # default_payroll_payable_account = self.get_default_payroll_payable_account() default_payroll_payable_account = self.default_payroll_payable_account precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency") @@ -528,6 +517,25 @@ def create_salary_slips_for_employees(employees, args, publish_progress=True): if publish_progress: frappe.publish_progress(count*100/len(set(employees) - set(salary_slips_exists_for)), title = _("Creating Salary Slips...")) + else: + salary_slip_name = frappe.db.sql( + '''SELECT + name + FROM + `tabSalary Slip` + WHERE + company=%s + AND + start_date >= %s + AND + end_date <= %s + AND + employee = %s + ''', (args.company, args.start_date, args.end_date, emp), as_dict=True) + + salary_slip_doc = frappe.get_doc('Salary Slip', salary_slip_name[0].name) + salary_slip_doc.exchange_rate = args.exchange_rate + salary_slip_doc.set_base_amounts_after_exchange_rate_change() payroll_entry = frappe.get_doc("Payroll Entry", args.payroll_entry) payroll_entry.db_set("salary_slips_created", 1) diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.js b/erpnext/payroll/doctype/retention_bonus/retention_bonus.js index 64e726db857..d91236c19fd 100644 --- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.js +++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.js @@ -18,5 +18,22 @@ frappe.ui.form.on('Retention Bonus', { } }; }); + }, + + employee: function(frm) { + if (frm.doc.employee) { + 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(); + } + } + }); + } } }); diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.json b/erpnext/payroll/doctype/retention_bonus/retention_bonus.json index da884c2f289..66472300788 100644 --- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.json +++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.json @@ -17,7 +17,8 @@ "column_break_6", "employee_name", "department", - "date_of_joining" + "date_of_joining", + "currency" ], "fields": [ { @@ -46,6 +47,7 @@ "fieldname": "bonus_amount", "fieldtype": "Currency", "label": "Bonus Amount", + "options": "currency", "reqd": 1 }, { @@ -89,11 +91,22 @@ "label": "Salary Component", "options": "Salary Component", "reqd": 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 } ], "is_submittable": 1, "links": [], - "modified": "2020-06-22 22:42:05.251951", + "modified": "2020-10-20 17:27:47.003134", "modified_by": "Administrator", "module": "Payroll", "name": "Retention Bonus", @@ -151,7 +164,6 @@ "share": 1 } ], - "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.js b/erpnext/payroll/doctype/salary_slip/salary_slip.js index 0dee370d65f..98173f4e23d 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.js +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.js @@ -73,42 +73,67 @@ frappe.ui.form.on("Salary Slip", { var company = locals[':Company'][frm.doc.company]; if(!frm.doc.letter_head && company.default_letter_head) { frm.set_value('letter_head', company.default_letter_head); - } + }; + frm.trigger("set_dynamic_labels") }, currency: function(frm) { - calculate_totals(frm.doc); + calculate_totals(frm); frm.trigger("set_dynamic_labels") - frm.refresh() }, set_dynamic_labels: function(frm) { - debugger; - frm.set_currency_labels(["hour_rate", "gross_pay", "total_deduction", "net_pay", "rounded_total", "total_in_words"], - frm.doc.currency); - - // toggle fields - if(frappe.meta.get_docfield(cur_frm.doctype, "net_total")) - cur_frm.toggle_display("net_total", show); - - frm.set_currency_labels(["amount", "default_amount", "additional_amount", "tax_on_flexible_benefit", "tax_on_additional_salary"], - frm.doc.currency, "earnings"); - - frm.set_currency_labels(["amount", "default_amount", "additional_amount", "tax_on_flexible_benefit", "tax_on_additional_salary"], - frm.doc.currency, "deductions"); - + var company_currency = frm.doc.company? erpnext.get_currency(frm.doc.company): frappe.defaults.get_default("currency"); + // frm.events.set_exchange_rate(frm, company_currency); + if (frm.doc.currency && company_currency!=frm.doc.currency) { + frm.events.hide_loan_section(frm); + } + frm.events.change_form_labels(frm, company_currency); + frm.events.change_grid_labels(frm, company_currency); frm.refresh_fields(); }, + exchange_rate: function(frm) { + calculate_totals(frm); + }, + + hide_loan_section: function(frm) { + frm.set_df_property('section_break_43', 'hidden', 1); + }, + + change_form_labels: function(frm, company_currency) { + frm.set_currency_labels(["base_hour_rate", "base_gross_pay", "base_total_deduction", + "base_net_pay", "base_rounded_total", "base_total_in_words"], + company_currency); + + frm.set_currency_labels(["hour_rate", "gross_pay", "total_deduction", "net_pay", "rounded_total", "total_in_words"], + frm.doc.currency); + + cur_frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency + + " = [?] " + company_currency); + + // toggle fields + frm.toggle_display(["exchange_rate", "base_hour_rate", "base_gross_pay", "base_total_deduction", + "base_net_pay", "base_rounded_total", "base_total_in_words"], + frm.doc.currency != company_currency); + }, + + change_grid_labels: function(frm, company_currency) { + frm.set_currency_labels(["amount", "default_amount", "additional_amount", "tax_on_flexible_benefit", + "tax_on_additional_salary"], frm.doc.currency, "earnings"); + + frm.set_currency_labels(["amount", "default_amount", "additional_amount", "tax_on_flexible_benefit", + "tax_on_additional_salary"], frm.doc.currency, "deductions"); + }, + refresh: function(frm) { - debugger; - frm.trigger("set_dynamic_labels") frm.trigger("toggle_fields") var salary_detail_fields = ["formula", "abbr", "statistical_component", "variable_based_on_taxable_salary"]; - cur_frm.fields_dict['earnings'].grid.set_column_disp(salary_detail_fields,false); - cur_frm.fields_dict['deductions'].grid.set_column_disp(salary_detail_fields,false); - calculate_totals(frm.doc); + frm.fields_dict['earnings'].grid.set_column_disp(salary_detail_fields,false); + frm.fields_dict['deductions'].grid.set_column_disp(salary_detail_fields,false); + calculate_totals(frm); + frm.trigger("set_dynamic_labels") }, salary_slip_based_on_timesheet: function(frm) { @@ -145,104 +170,56 @@ frappe.ui.form.on("Salary Slip", { }, get_emp_and_working_day_details: function(frm) { - debugger; - return frappe.call({ - method: 'get_emp_and_working_day_details', - doc: frm.doc, - callback: function(r, rt) { - frm.refresh(); - if (r.message){ - frm.fields_dict.absent_days.set_description("Unmarked Days is treated as "+ r.message +". You can can change this in " + frappe.utils.get_form_link("Payroll Settings", "Payroll Settings", true)); + if (frm.doc.employee) { + return frappe.call({ + method: 'get_emp_and_working_day_details', + doc: frm.doc, + callback: function(r) { + if (r.message){ + frm.fields_dict.absent_days.set_description("Unmarked Days is treated as "+ r.message +". You can can change this in " + frappe.utils.get_form_link("Payroll Settings", "Payroll Settings", true)); + } + frm.refresh(); } - } - }); + }); + } } }); frappe.ui.form.on('Salary Slip Timesheet', { - time_sheet: function(frm, dt, dn) { - total_work_hours(frm, dt, dn); + time_sheet: function(frm) { + calculate_totals(frm); }, - timesheets_remove: function(frm, dt, dn) { - total_work_hours(frm, dt, dn); + timesheets_remove: function(frm) { + calculate_totals(frm); } }); - -cur_frm.cscript.amount = function(doc, cdt, cdn){ - calculate_totals(doc, cdt, cdn); -}; - -// calculate total working hours, earnings based on hourly wages and totals -var total_work_hours = function(frm, dt, dn) { - debugger; - var total_working_hours = 0.0; - $.each(frm.doc["timesheets"] || [], function(i, timesheet) { - total_working_hours += timesheet.working_hours; - }); - frm.set_value('total_working_hours', total_working_hours); - - var wages_amount = frm.doc.total_working_hours * frm.doc.hour_rate; - - frappe.db.get_value('Salary Structure', {'name': frm.doc.salary_structure}, 'salary_component', (r) => { - var gross_pay = 0.0; - $.each(frm.doc["earnings"], function(i, earning) { - if (earning.salary_component == r.salary_component) { - earning.amount = wages_amount; - frm.refresh_fields('earnings'); - } - gross_pay += earning.amount; - }); - frm.set_value('gross_pay', gross_pay); - - frm.doc.net_pay = flt(frm.doc.gross_pay) - flt(frm.doc.total_deduction); - frm.doc.rounded_total = Math.round(frm.doc.net_pay); - refresh_many(['net_pay', 'rounded_total']); - }); -} - -var calculate_totals = function(doc) { - debugger; - var tbl1 = doc.earnings || []; - var tbl2 = doc.deductions || []; - - var total_earn = 0; var total_ded = 0; - for(var i = 0; i < tbl1.length; i++){ - total_earn += flt(tbl1[i].amount); +var calculate_totals = function(frm) { + if (frm.doc.earnings || frm.doc.deductions) { + frappe.call({ + method: "set_totals", + doc: frm.doc, + callback: function(r) { + frm.refresh_fields() + } + }) } - for(var j = 0; j < tbl2.length; j++){ - total_ded += flt(tbl2[j].amount); - } - doc.gross_pay = total_earn; - doc.total_deduction = total_ded; - doc.net_pay = 0.0 - if(doc.salary_slip_based_on_timesheet == 0){ - doc.net_pay = flt(total_earn) - flt(total_ded) - flt(doc.total_loan_repayment); - doc.rounded_total = Math.round(doc.net_pay) - } - refresh_many(['gross_pay', 'total_deduction', 'net_pay', 'rounded_total']); } -cur_frm.cscript.validate = function(doc, cdt, cdn) { - calculate_totals(doc); -} - - frappe.ui.form.on('Salary Detail', { amount: function(frm) { - calculate_totals(frm.doc); + calculate_totals(frm); }, earnings_remove: function(frm) { - calculate_totals(frm.doc); + calculate_totals(frm); }, deductions_remove: function(frm) { - calculate_totals(frm.doc); + calculate_totals(frm); }, salary_component: function(frm, cdt, cdn) { - debugger; var child = locals[cdt][cdn]; if(child.salary_component){ frappe.call({ diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json index 16a9309c166..386618cf083 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.json +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json @@ -19,6 +19,7 @@ "payroll_entry", "company", "currency", + "exchange_rate", "letter_head", "section_break_10", "start_date", @@ -39,6 +40,7 @@ "column_break_20", "total_working_hours", "hour_rate", + "base_hour_rate", "section_break_26", "bank_name", "bank_account_no", @@ -53,8 +55,10 @@ "deductions", "totals", "gross_pay", + "base_gross_pay", "column_break_25", "total_deduction", + "base_total_deduction", "loan_repayment", "loans", "section_break_43", @@ -64,10 +68,14 @@ "total_loan_repayment", "net_pay_info", "net_pay", + "base_net_pay", "column_break_53", "rounded_total", + "base_rounded_total", "section_break_55", "total_in_words", + "column_break_69", + "base_total_in_words", "section_break_75", "amended_from" ], @@ -374,6 +382,7 @@ "print_hide": 1 }, { + "depends_on": "eval:doc.docstatus != 0", "fieldname": "section_break_43", "fieldtype": "Section Break" }, @@ -411,7 +420,6 @@ "label": "net pay info" }, { - "description": "Gross Pay - Total Deduction - Loan Repayment", "fieldname": "net_pay", "fieldtype": "Currency", "label": "Net Pay", @@ -505,7 +513,6 @@ "read_only": 1 }, { - "description": "Net Pay (in words) will be visible once you save the Salary Slip.", "fieldname": "total_in_words", "fieldtype": "Data", "label": "Total in words", @@ -515,13 +522,69 @@ { "fieldname": "section_break_75", "fieldtype": "Section Break" + }, + { + "fieldname": "base_hour_rate", + "fieldtype": "Currency", + "label": "Hour Rate (Company Currency)", + "options": "Company:company:default_currency", + "print_hide_if_no_value": 1 + }, + { + "fieldname": "base_gross_pay", + "fieldtype": "Currency", + "label": "Gross Pay (Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "default": "1.0", + "fieldname": "exchange_rate", + "fieldtype": "Float", + "hidden": 1, + "label": "Exchange Rate", + "print_hide": 1, + "reqd": 1 + }, + { + "fieldname": "base_total_deduction", + "fieldtype": "Currency", + "label": "Total Deduction (Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "fieldname": "base_net_pay", + "fieldtype": "Currency", + "label": "Net Pay (Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "bold": 1, + "fieldname": "base_rounded_total", + "fieldtype": "Currency", + "label": "Rounded Total (Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "fieldname": "base_total_in_words", + "fieldtype": "Data", + "label": "Total in words (Company Currency)", + "length": 240, + "read_only": 1 + }, + { + "fieldname": "column_break_69", + "fieldtype": "Column Break" } ], "icon": "fa fa-file-text", "idx": 9, "is_submittable": 1, "links": [], - "modified": "2020-09-30 17:31:21.909671", + "modified": "2020-10-21 23:02:59.400249", "modified_by": "Administrator", "module": "Payroll", "name": "Salary Slip", diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index f597f909fda..73ca55717cc 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -50,16 +50,20 @@ class SalarySlip(TransactionBase): self.calculate_net_pay() - doc_currency = self.currency - total = self.net_pay if self.is_rounding_total_disabled() else self.rounded_total - self.total_in_words = money_in_words(total, doc_currency) - if frappe.db.get_single_value("Payroll Settings", "max_working_hours_against_timesheet"): max_working_hours = frappe.db.get_single_value("Payroll Settings", "max_working_hours_against_timesheet") if self.salary_slip_based_on_timesheet and (self.total_working_hours > int(max_working_hours)): frappe.msgprint(_("Total working hours should not be greater than max working hours {0}"). format(max_working_hours), alert=True) + def set_net_total_in_words(self): + doc_currency = self.currency + company_currency = erpnext.get_company_currency(self.company) + total = self.net_pay if self.is_rounding_total_disabled() else self.rounded_total + base_total = self.base_net_pay if self.is_rounding_total_disabled() else self.base_rounded_total + self.total_in_words = money_in_words(total, doc_currency) + self.base_total_in_words = money_in_words(base_total, company_currency) + def on_submit(self): if self.net_pay < 0: frappe.throw(_("Net Pay cannot be less than 0")) @@ -182,6 +186,7 @@ class SalarySlip(TransactionBase): if self.salary_slip_based_on_timesheet: self.salary_structure = self._salary_structure_doc.name self.hour_rate = self._salary_structure_doc.hour_rate + self.base_hour_rate = flt(self.hour_rate) * flt(self.exchange_rate) self.total_working_hours = sum([d.working_hours or 0.0 for d in self.timesheets]) or 0.0 wages_amount = self.hour_rate * self.total_working_hours @@ -391,15 +396,45 @@ class SalarySlip(TransactionBase): if self.salary_structure: self.calculate_component_amounts("earnings") self.gross_pay = self.get_component_totals("earnings") + self.base_gross_pay = flt(self.gross_pay) * flt(self.exchange_rate) if self.salary_structure: self.calculate_component_amounts("deductions") self.total_deduction = self.get_component_totals("deductions") + self.base_total_deduction = flt(self.total_deduction) * flt(self.exchange_rate) self.set_loan_repayment() self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment)) self.rounded_total = rounded(self.net_pay) + self.base_net_pay = flt(self.net_pay) * flt(self.exchange_rate) + self.base_rounded_total = rounded(self.base_net_pay) + if self.hour_rate: + self.base_hour_rate = flt(self.hour_rate) * flt(self.exchange_rate) + self.set_net_total_in_words() + + def set_base_amounts_after_exchange_rate_change(self): + self.db_set("exchange_rate", self.exchange_rate) + base_gross_pay = flt(self.gross_pay) * flt(self.exchange_rate) + self.db_set("base_gross_pay", base_gross_pay) + base_total_deduction = flt(self.total_deduction) * flt(self.exchange_rate) + self.db_set("base_total_deduction", base_total_deduction) + base_net_pay = flt(self.net_pay) * flt(self.exchange_rate) + self.db_set("base_net_pay", base_net_pay) + base_rounded_total = rounded(self.base_net_pay) + self.db_set("base_rounded_total", base_rounded_total) + if self.hour_rate: + base_hour_rate = flt(self.hour_rate) * flt(self.exchange_rate) + self.db_set("base_hour_rate", base_hour_rate) + doc_currency = self.currency + company_currency = erpnext.get_company_currency(self.company) + base_total = base_net_pay if self.is_rounding_total_disabled() else base_rounded_total + base_total_in_words = money_in_words(base_total, company_currency) + self.db_set("base_total_in_words", base_total_in_words) + self.db_set("docstatus", 0) + frappe.db.commit() + self.docstatus = 0 + self.set_status() def calculate_component_amounts(self, component_type): if not getattr(self, '_salary_structure_doc', None): @@ -1047,6 +1082,50 @@ class SalarySlip(TransactionBase): self.get_working_days_details(lwp=self.leave_without_pay) self.calculate_net_pay() + def set_totals(self): + self.gross_pay = 0 + if self.salary_slip_based_on_timesheet == 1: + self.calculate_total_for_salary_slip_based_on_timesheet() + else: + self.total_deduction = 0 + if self.earnings: + for earning in self.earnings: + self.gross_pay += flt(earning.amount) + if self.deductions: + for deduction in self.deductions: + self.total_deduction += flt(deduction.amount) + self.base_gross_pay = flt(self.gross_pay) * flt(self.exchange_rate) + self.base_total_deduction = flt(self.total_deduction) * flt(self.exchange_rate) + self.net_pay = flt(self.gross_pay) - flt(self.total_deduction) - flt(self.total_loan_repayment) + self.rounded_total = rounded(self.net_pay) + self.base_net_pay = flt(self.net_pay) * flt(self.exchange_rate) + self.base_rounded_total = rounded(self.base_net_pay) + self.set_net_total_in_words() + + return + + #calculate total working hours, earnings based on hourly wages and totals + def calculate_total_for_salary_slip_based_on_timesheet(self): + if self.timesheets: + for timesheet in self.timesheets: + if timesheet.working_hours: + self.total_working_hours += timesheet.working_hours + + wages_amount = self.total_working_hours * self.hour_rate + self.base_hour_rate = flt(self.hour_rate) * flt(self.exchange_rate) + salary_component = frappe.db.get_value('Salary Structure', {'name': self.salary_structure}, 'salary_component') + if self.earnings: + for i, earning in enumerate(self.earnings): + if earning.salary_component == salary_component: + self.earnings[i].amount = wages_amount + self.gross_pay += self.earnings[i].amount + self.base_gross_pay = flt(self.gross_pay) * flt(self.exchange_rate) + self.base_total_deduction = flt(self.total_deduction) * flt(self.exchange_rate) + self.net_pay = flt(self.gross_pay) - flt(self.total_deduction) + self.rounded_total = rounded(self.net_pay) + self.base_net_pay = flt(self.net_pay) * flt(self.exchange_rate) + self.base_rounded_total = rounded(self.base_net_pay) + def unlink_ref_doc_from_salary_slip(ref_no): linked_ss = frappe.db.sql_list("""select name from `tabSalary Slip` where journal_entry=%s and docstatus < 2""", (ref_no)) diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.js b/erpnext/payroll/doctype/salary_structure/salary_structure.js index c4e90028f4a..1a5440d8239 100755 --- a/erpnext/payroll/doctype/salary_structure/salary_structure.js +++ b/erpnext/payroll/doctype/salary_structure/salary_structure.js @@ -79,16 +79,9 @@ frappe.ui.form.on('Salary Structure', { }, set_dynamic_labels: function(frm) { - debugger; frm.set_currency_labels(["net_pay","hour_rate", "leave_encashment_amount_per_day", "max_benefits", "total_earning", "total_deduction"], frm.doc.currency); - // toggle fields - frm.toggle_display(["total_earning", "total_deduction"], true); - - if(frappe.meta.get_docfield(cur_frm.doctype, "net_pay")) - cur_frm.toggle_display("net_pay", true); - frm.set_currency_labels(["amount", "additional_amount", "tax_on_flexible_benefit", "tax_on_additional_salary"], frm.doc.currency, "earnings"); @@ -255,7 +248,6 @@ cur_frm.cscript.amount = function(doc, cdt, cdn){ }; var calculate_totals = function(doc) { - debugger; var tbl1 = doc.earnings || []; var tbl2 = doc.deductions || []; diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js index 4033ce8951a..0ea3e08eb04 100644 --- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js +++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.js @@ -23,25 +23,26 @@ frappe.ui.form.on('Salary Structure Assignment', { filters: { company: frm.doc.company, docstatus: 1, - disabled: 0 + disabled: 0, + currency: frm.doc.currency } } }); frm.set_query("default_payroll_payable_account", function() { + var company_currency = erpnext.get_currency(frm.doc.company); return { filters: { "company": frm.doc.company, "root_type": "Liability", "is_group": 0, - "account_currency": frm.doc.currency + "account_currency": ["in",[frm.doc.currency, company_currency]], } } }); }, employee: function(frm) { - debugger; if(frm.doc.employee){ frappe.call({ method: "frappe.client.get_value", diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json index 6a22f33de5e..9bea516b8b5 100644 --- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json +++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json @@ -127,7 +127,7 @@ "depends_on": "salary_structure", "fieldname": "default_payroll_payable_account", "fieldtype": "Link", - "label": "Default Payroll Payable Account", + "label": "Payroll Payable Account", "options": "Account" }, { @@ -145,7 +145,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-09-30 17:35:49.922227", + "modified": "2020-10-21 22:43:55.208492", "modified_by": "Administrator", "module": "Payroll", "name": "Salary Structure Assignment", diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py index a277055a05a..68f598b298c 100644 --- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py +++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.py @@ -13,7 +13,6 @@ class DuplicateAssignment(frappe.ValidationError): pass class SalaryStructureAssignment(Document): def validate(self): self.validate_dates() - self.validate_default_payroll_payable_account() def validate_dates(self): joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, @@ -32,15 +31,6 @@ class SalaryStructureAssignment(Document): frappe.throw(_("From Date {0} cannot be after employee's relieving Date {1}") .format(self.from_date, relieving_date)) - def validate_default_payroll_payable_account(self): - if not self.default_payroll_payable_account: - self.default_payroll_payable_account = frappe.db.get_value('Company', self.company, 'default_payroll_payable_account') - if not self.default_payroll_payable_account: - frappe.throw(_('Please set "Default Payroll Payable Account" in Company Defaults')) - account_currency = frappe.db.get_value('Account', self.default_payroll_payable_account, 'account_currency') - if account_currency != self.currency: - frappe.throw(_("Account currency of Account: {0} is different than what is specified in salary structure: {1}").format(self.default_payroll_payable_account, self.salary_structure)) - def get_assigned_salary_structure(employee, on_date): if not employee or not on_date: return None @@ -55,9 +45,8 @@ def get_assigned_salary_structure(employee, on_date): return salary_structure[0][0] if salary_structure else None @frappe.whitelist() -def get_payroll_payable_account_currency(employee): - default_payroll_payable_account = frappe.db.get_value('Salary Structure Assignment', {'employee': employee}, 'default_payroll_payable_account') - if not default_payroll_payable_account: +def get_employee_currency(employee): + employee_currency = frappe.db.get_value('Salary Structure Assignment', {'employee': employee}, 'currency') + if not employee_currency: frappe.throw(_("There is no Salary Structure assigned to {0}. First assign a Salary Stucture.").format(employee)) - account_currency = frappe.db.get_value('Account', default_payroll_payable_account, 'account_currency') - return account_currency \ No newline at end of file + return employee_currency \ No newline at end of file diff --git a/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json b/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json index 94eda4c043a..65d3824f3aa 100644 --- a/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json +++ b/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json @@ -19,13 +19,15 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "From Amount", + "options": "currency", "reqd": 1 }, { "fieldname": "to_amount", "fieldtype": "Currency", "in_list_view": 1, - "label": "To Amount" + "label": "To Amount", + "options": "currency" }, { "default": "0", @@ -53,7 +55,7 @@ ], "istable": 1, "links": [], - "modified": "2020-06-22 18:16:07.596493", + "modified": "2020-10-19 13:44:39.549337", "modified_by": "Administrator", "module": "Payroll", "name": "Taxable Salary Slab", diff --git a/erpnext/payroll/report/salary_register/salary_register.js b/erpnext/payroll/report/salary_register/salary_register.js index 885e3d13c7f..cae8109597f 100644 --- a/erpnext/payroll/report/salary_register/salary_register.js +++ b/erpnext/payroll/report/salary_register/salary_register.js @@ -8,34 +8,47 @@ frappe.query_reports["Salary Register"] = { "label": __("From"), "fieldtype": "Date", "default": frappe.datetime.add_months(frappe.datetime.get_today(),-1), - "reqd": 1 + "reqd": 1, + "width": "100px" }, { "fieldname":"to_date", "label": __("To"), "fieldtype": "Date", "default": frappe.datetime.get_today(), - "reqd": 1 + "reqd": 1, + "width": "100px" + }, + { + "fieldname": "currency", + "fieldtype": "Link", + "options": "Currency", + "label": __("Currency"), + "default": erpnext.get_currency(frappe.defaults.get_default("Company")), + "width": "50px" }, { "fieldname":"employee", "label": __("Employee"), "fieldtype": "Link", - "options": "Employee" + "options": "Employee", + "width": "100px" }, { "fieldname":"company", "label": __("Company"), "fieldtype": "Link", "options": "Company", - "default": frappe.defaults.get_user_default("Company") + "default": frappe.defaults.get_user_default("Company"), + "width": "100px" }, { "fieldname":"docstatus", "label":__("Document Status"), "fieldtype":"Select", "options":["Draft", "Submitted", "Cancelled"], - "default":"Submitted" + "default":"Submitted", + "width": "100px" } ] } diff --git a/erpnext/payroll/report/salary_register/salary_register.py b/erpnext/payroll/report/salary_register/salary_register.py index 87010855fdb..29f8f371034 100644 --- a/erpnext/payroll/report/salary_register/salary_register.py +++ b/erpnext/payroll/report/salary_register/salary_register.py @@ -2,18 +2,24 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe, erpnext from frappe.utils import flt from frappe import _ def execute(filters=None): if not filters: filters = {} - salary_slips = get_salary_slips(filters) + currency = None + company_currency = None + if filters.get('currency'): + currency = filters.get('currency') + if filters.get("company"): + company_currency = erpnext.get_company_currency(filters.get("company")) + salary_slips = get_salary_slips(filters, company_currency) if not salary_slips: return [], [] columns, earning_types, ded_types = get_columns(salary_slips) - ss_earning_map = get_ss_earning_map(salary_slips) - ss_ded_map = get_ss_ded_map(salary_slips) + ss_earning_map = get_ss_earning_map(salary_slips, currency, company_currency) + ss_ded_map = get_ss_ded_map(salary_slips,currency, company_currency) doj_map = get_employee_doj_map() data = [] @@ -30,14 +36,20 @@ def execute(filters=None): for e in earning_types: row.append(ss_earning_map.get(ss.name, {}).get(e)) - row += [ss.gross_pay] + if currency == company_currency: + row += [flt(ss.gross_pay) * flt(ss.exchange_rate)] + else: + row += [ss.gross_pay] for d in ded_types: row.append(ss_ded_map.get(ss.name, {}).get(d)) row.append(ss.total_loan_repayment) - row += [ss.total_deduction, ss.net_pay] + if currency == company_currency: + row += [flt(ss.total_deduction) * flt(ss.exchange_rate), flt(ss.net_pay) * flt(ss.exchange_rate)] + else: + row += [ss.total_deduction, ss.net_pay] data.append(row) @@ -73,15 +85,15 @@ def get_columns(salary_slips): return columns, salary_components[_("Earning")], salary_components[_("Deduction")] -def get_salary_slips(filters): +def get_salary_slips(filters, company_currency): filters.update({"from_date": filters.get("from_date"), "to_date":filters.get("to_date")}) - conditions, filters = get_conditions(filters) + conditions, filters = get_conditions(filters, company_currency) salary_slips = frappe.db.sql("""select * from `tabSalary Slip` where %s order by employee""" % conditions, filters, as_dict=1) return salary_slips or [] -def get_conditions(filters): +def get_conditions(filters, company_currency): conditions = "" doc_status = {"Draft": 0, "Submitted": 1, "Cancelled": 2} @@ -92,6 +104,8 @@ def get_conditions(filters): if filters.get("to_date"): conditions += " and end_date <= %(to_date)s" if filters.get("company"): conditions += " and company = %(company)s" if filters.get("employee"): conditions += " and employee = %(employee)s" + if filters.get("currency") and filters.get("currency") != company_currency: + conditions += " and currency = %(currency)s" return conditions, filters @@ -103,26 +117,32 @@ def get_employee_doj_map(): FROM `tabEmployee` """)) -def get_ss_earning_map(salary_slips): - ss_earnings = frappe.db.sql("""select parent, salary_component, amount - from `tabSalary Detail` where parent in (%s)""" % +def get_ss_earning_map(salary_slips, currency, company_currency): + ss_earnings = frappe.db.sql("""select sd.parent, sd.salary_component, sd.amount, ss.exchange_rate, ss.name + from `tabSalary Detail` sd, `tabSalary Slip` ss where sd.parent=ss.name and sd.parent in (%s)""" % (', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1) ss_earning_map = {} for d in ss_earnings: ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, []) - ss_earning_map[d.parent][d.salary_component] = flt(d.amount) + if currency == company_currency: + ss_earning_map[d.parent][d.salary_component] = flt(d.amount) * flt(d.exchange_rate if d.exchange_rate else 1) + else: + ss_earning_map[d.parent][d.salary_component] = flt(d.amount) return ss_earning_map -def get_ss_ded_map(salary_slips): - ss_deductions = frappe.db.sql("""select parent, salary_component, amount - from `tabSalary Detail` where parent in (%s)""" % +def get_ss_ded_map(salary_slips, currency, company_currency): + ss_deductions = frappe.db.sql("""select sd.parent, sd.salary_component, sd.amount, ss.exchange_rate, ss.name + from `tabSalary Detail` sd, `tabSalary Slip` ss where sd.parent=ss.name and sd.parent in (%s)""" % (', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1) ss_ded_map = {} for d in ss_deductions: ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, []) - ss_ded_map[d.parent][d.salary_component] = flt(d.amount) + if currency == company_currency: + ss_ded_map[d.parent][d.salary_component] = flt(d.amount) * flt(d.exchange_rate if d.exchange_rate else 1) + else: + ss_ded_map[d.parent][d.salary_component] = flt(d.amount) return ss_ded_map