fix: refactor and added conditions

This commit is contained in:
Afshan
2020-10-22 15:05:46 +05:30
parent db60c02933
commit bbe2666d3a
42 changed files with 749 additions and 462 deletions

View File

@@ -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:

View File

@@ -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",

View File

@@ -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();
},
});

View File

@@ -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",

View File

@@ -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()

View File

@@ -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();
}
}
});
},
});

View File

@@ -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",

View File

@@ -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",

View File

@@ -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))

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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:

View File

@@ -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();
}
}
});
},
});

View File

@@ -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",

View File

@@ -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,

View File

@@ -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,
},

View File

@@ -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();
}
}
});
},
});

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -54,5 +54,9 @@ frappe.ui.form.on('Employee Tax Exemption Proof Submission', {
});
});
}
},
currency: function(frm) {
frm.refresh_fields();
}
});

View File

@@ -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",

View File

@@ -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",

View File

@@ -2,5 +2,7 @@
// For license information, please see license.txt
frappe.ui.form.on('Income Tax Slab', {
currency: function(frm) {
frm.refresh_fields();
}
});

View File

@@ -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",

View File

@@ -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",

View File

@@ -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"));
}

View File

@@ -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",

View File

@@ -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)

View File

@@ -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();
}
}
});
}
}
});

View File

@@ -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

View File

@@ -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({

View File

@@ -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",

View File

@@ -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))

View File

@@ -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 || [];

View File

@@ -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",

View File

@@ -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",

View File

@@ -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
return employee_currency

View File

@@ -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",

View File

@@ -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"
}
]
}

View File

@@ -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