Employee loan fixes (#11495)
* Employee loan fixes * Update update_employee_loan_details.py
This commit is contained in:
parent
3f83afe4e1
commit
43edd5d03c
@ -38,9 +38,8 @@ class TestEmployeeLoan(unittest.TestCase):
|
|||||||
self.assertEquals(employee_loan.total_interest_payable, 22712)
|
self.assertEquals(employee_loan.total_interest_payable, 22712)
|
||||||
self.assertEquals(employee_loan.total_payment, 302712)
|
self.assertEquals(employee_loan.total_payment, 302712)
|
||||||
|
|
||||||
|
|
||||||
def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest):
|
def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest):
|
||||||
if not frappe.db.get_value("Loan Type", loan_name):
|
if not frappe.db.exists("Loan Type", loan_name):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Loan Type",
|
"doctype": "Loan Type",
|
||||||
"loan_name": loan_name,
|
"loan_name": loan_name,
|
||||||
@ -49,6 +48,7 @@ def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest):
|
|||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
def create_employee_loan(employee, loan_type, loan_amount, repayment_method, repayment_periods):
|
def create_employee_loan(employee, loan_type, loan_amount, repayment_method, repayment_periods):
|
||||||
|
create_loan_type(loan_type, 500000, 8.4)
|
||||||
if not frappe.db.get_value("Employee Loan", {"employee":employee}):
|
if not frappe.db.get_value("Employee Loan", {"employee":employee}):
|
||||||
employee_loan = frappe.new_doc("Employee Loan")
|
employee_loan = frappe.new_doc("Employee Loan")
|
||||||
employee_loan.update({
|
employee_loan.update({
|
||||||
|
@ -190,23 +190,28 @@ class ProcessPayroll(Document):
|
|||||||
def format_as_links(self, salary_slip):
|
def format_as_links(self, salary_slip):
|
||||||
return ['<a href="#Form/Salary Slip/{0}">{0}</a>'.format(salary_slip)]
|
return ['<a href="#Form/Salary Slip/{0}">{0}</a>'.format(salary_slip)]
|
||||||
|
|
||||||
def get_total_salary_and_loan_amounts(self):
|
def get_loan_details(self):
|
||||||
"""
|
"""
|
||||||
Get total loan principal, loan interest and salary amount from submitted salary slip based on selected criteria
|
Get loan details from submitted salary slip based on selected criteria
|
||||||
"""
|
"""
|
||||||
cond = self.get_filter_condition()
|
cond = self.get_filter_condition()
|
||||||
totals = frappe.db.sql("""
|
return frappe.db.sql(""" select eld.employee_loan_account,
|
||||||
select sum(principal_amount) as total_principal_amount, sum(interest_amount) as total_interest_amount,
|
eld.interest_income_account, eld.principal_amount, eld.interest_amount, eld.total_payment
|
||||||
sum(total_loan_repayment) as total_loan_repayment, sum(rounded_total) as rounded_total from `tabSalary Slip` t1
|
from
|
||||||
|
`tabSalary Slip` t1, `tabSalary Slip Loan` eld
|
||||||
|
where
|
||||||
|
t1.docstatus = 1 and t1.name = eld.parent and start_date >= %s and end_date <= %s %s
|
||||||
|
""" % ('%s', '%s', cond), (self.start_date, self.end_date), as_dict=True) or []
|
||||||
|
|
||||||
|
def get_total_salary_amount(self):
|
||||||
|
"""
|
||||||
|
Get total salary amount from submitted salary slip based on selected criteria
|
||||||
|
"""
|
||||||
|
cond = self.get_filter_condition()
|
||||||
|
totals = frappe.db.sql(""" select sum(rounded_total) as rounded_total from `tabSalary Slip` t1
|
||||||
where t1.docstatus = 1 and start_date >= %s and end_date <= %s %s
|
where t1.docstatus = 1 and start_date >= %s and end_date <= %s %s
|
||||||
""" % ('%s', '%s', cond), (self.start_date, self.end_date), as_dict=True)
|
""" % ('%s', '%s', cond), (self.start_date, self.end_date), as_dict=True)
|
||||||
return totals[0]
|
return totals and totals[0] or None
|
||||||
|
|
||||||
def get_loan_accounts(self):
|
|
||||||
loan_accounts = frappe.get_all("Employee Loan", fields=["employee_loan_account", "interest_income_account"],
|
|
||||||
filters = {"company": self.company, "docstatus":1})
|
|
||||||
if loan_accounts:
|
|
||||||
return loan_accounts[0]
|
|
||||||
|
|
||||||
def get_salary_component_account(self, salary_component):
|
def get_salary_component_account(self, salary_component):
|
||||||
account = frappe.db.get_value("Salary Component Account",
|
account = frappe.db.get_value("Salary Component Account",
|
||||||
@ -257,8 +262,7 @@ class ProcessPayroll(Document):
|
|||||||
earnings = self.get_salary_component_total(component_type = "earnings") or {}
|
earnings = self.get_salary_component_total(component_type = "earnings") or {}
|
||||||
deductions = self.get_salary_component_total(component_type = "deductions") 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.get_default_payroll_payable_account()
|
||||||
loan_amounts = self.get_total_salary_and_loan_amounts()
|
loan_details = self.get_loan_details()
|
||||||
loan_accounts = self.get_loan_accounts()
|
|
||||||
jv_name = ""
|
jv_name = ""
|
||||||
precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency")
|
precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency")
|
||||||
|
|
||||||
@ -294,18 +298,18 @@ class ProcessPayroll(Document):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Employee loan
|
# Employee loan
|
||||||
if loan_amounts.total_loan_repayment:
|
for data in loan_details:
|
||||||
accounts.append({
|
accounts.append({
|
||||||
"account": loan_accounts.employee_loan_account,
|
"account": data.employee_loan_account,
|
||||||
"credit_in_account_currency": loan_amounts.total_principal_amount
|
"credit_in_account_currency": data.principal_amount
|
||||||
})
|
})
|
||||||
accounts.append({
|
accounts.append({
|
||||||
"account": loan_accounts.interest_income_account,
|
"account": data.interest_income_account,
|
||||||
"credit_in_account_currency": loan_amounts.total_interest_amount,
|
"credit_in_account_currency": data.interest_amount,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
"project": self.project
|
"project": self.project
|
||||||
})
|
})
|
||||||
payable_amount -= flt(loan_amounts.total_loan_repayment, precision)
|
payable_amount -= flt(data.total_payment, precision)
|
||||||
|
|
||||||
# Payable amount
|
# Payable amount
|
||||||
accounts.append({
|
accounts.append({
|
||||||
@ -327,11 +331,11 @@ class ProcessPayroll(Document):
|
|||||||
|
|
||||||
def make_payment_entry(self):
|
def make_payment_entry(self):
|
||||||
self.check_permission('write')
|
self.check_permission('write')
|
||||||
total_salary_amount = self.get_total_salary_and_loan_amounts()
|
total_salary_amount = self.get_total_salary_amount()
|
||||||
default_payroll_payable_account = self.get_default_payroll_payable_account()
|
default_payroll_payable_account = self.get_default_payroll_payable_account()
|
||||||
precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency")
|
precision = frappe.get_precision("Journal Entry Account", "debit_in_account_currency")
|
||||||
|
|
||||||
if total_salary_amount.rounded_total:
|
if total_salary_amount and total_salary_amount.rounded_total:
|
||||||
journal_entry = frappe.new_doc('Journal Entry')
|
journal_entry = frappe.new_doc('Journal Entry')
|
||||||
journal_entry.voucher_type = 'Bank Entry'
|
journal_entry.voucher_type = 'Bank Entry'
|
||||||
journal_entry.user_remark = _('Payment of salary from {0} to {1}')\
|
journal_entry.user_remark = _('Payment of salary from {0} to {1}')\
|
||||||
|
@ -6,9 +6,9 @@ import unittest
|
|||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import nowdate
|
from dateutil.relativedelta import relativedelta
|
||||||
from erpnext.hr.doctype.process_payroll.process_payroll import get_end_date
|
from erpnext.accounts.utils import get_fiscal_year, getdate, nowdate
|
||||||
|
from erpnext.hr.doctype.process_payroll.process_payroll import get_start_end_dates, get_end_date
|
||||||
|
|
||||||
class TestProcessPayroll(unittest.TestCase):
|
class TestProcessPayroll(unittest.TestCase):
|
||||||
def test_process_payroll(self):
|
def test_process_payroll(self):
|
||||||
@ -19,22 +19,9 @@ class TestProcessPayroll(unittest.TestCase):
|
|||||||
if not frappe.db.get_value('Salary Component Account',
|
if not frappe.db.get_value('Salary Component Account',
|
||||||
{'parent': data.name, 'company': erpnext.get_default_company()}, 'name'):
|
{'parent': data.name, 'company': erpnext.get_default_company()}, 'name'):
|
||||||
get_salary_component_account(data.name)
|
get_salary_component_account(data.name)
|
||||||
|
|
||||||
payment_account = frappe.get_value('Account',
|
|
||||||
{'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
|
||||||
|
|
||||||
if not frappe.db.get_value("Salary Slip", {"start_date": "2016-11-01", "end_date": "2016-11-30"}):
|
if not frappe.db.get_value("Salary Slip", {"start_date": "2016-11-01", "end_date": "2016-11-30"}):
|
||||||
process_payroll = frappe.get_doc("Process Payroll", "Process Payroll")
|
make_process_payroll()
|
||||||
process_payroll.company = erpnext.get_default_company()
|
|
||||||
process_payroll.start_date = "2016-11-01"
|
|
||||||
process_payroll.end_date = "2016-11-30"
|
|
||||||
process_payroll.payment_account = payment_account
|
|
||||||
process_payroll.posting_date = nowdate()
|
|
||||||
process_payroll.payroll_frequency = "Monthly"
|
|
||||||
process_payroll.create_salary_slips()
|
|
||||||
process_payroll.submit_salary_slips()
|
|
||||||
if process_payroll.get_sal_slip_list(ss_status = 1):
|
|
||||||
r = process_payroll.make_payment_entry()
|
|
||||||
|
|
||||||
def test_get_end_date(self):
|
def test_get_end_date(self):
|
||||||
self.assertEqual(get_end_date('2017-01-01', 'monthly'), {'end_date': '2017-01-31'})
|
self.assertEqual(get_end_date('2017-01-01', 'monthly'), {'end_date': '2017-01-31'})
|
||||||
@ -45,7 +32,99 @@ class TestProcessPayroll(unittest.TestCase):
|
|||||||
self.assertEqual(get_end_date('2020-02-15', 'bimonthly'), {'end_date': ''})
|
self.assertEqual(get_end_date('2020-02-15', 'bimonthly'), {'end_date': ''})
|
||||||
self.assertEqual(get_end_date('2017-02-15', 'monthly'), {'end_date': '2017-03-14'})
|
self.assertEqual(get_end_date('2017-02-15', 'monthly'), {'end_date': '2017-03-14'})
|
||||||
self.assertEqual(get_end_date('2017-02-15', 'daily'), {'end_date': '2017-02-15'})
|
self.assertEqual(get_end_date('2017-02-15', 'daily'), {'end_date': '2017-02-15'})
|
||||||
|
|
||||||
|
def test_employee_loan(self):
|
||||||
|
from erpnext.hr.doctype.salary_structure.test_salary_structure import (make_employee,
|
||||||
|
make_salary_structure)
|
||||||
|
from erpnext.hr.doctype.employee_loan.test_employee_loan import create_employee_loan
|
||||||
|
|
||||||
|
branch = "Test Employee Branch"
|
||||||
|
employee = make_employee("test_employee@loan.com")
|
||||||
|
company = erpnext.get_default_company()
|
||||||
|
holiday_list = make_holiday("test holiday for loan")
|
||||||
|
|
||||||
|
if not frappe.db.exists('Salary Component', 'Basic Salary'):
|
||||||
|
frappe.get_doc({
|
||||||
|
'doctype': 'Salary Component',
|
||||||
|
'salary_component': 'Basic Salary',
|
||||||
|
'salary_component_abbr': 'BS',
|
||||||
|
'type': 'Earning',
|
||||||
|
'accounts': [{
|
||||||
|
'company': company,
|
||||||
|
'default_account': frappe.db.get_value('Account',
|
||||||
|
{'company': company, 'root_type': 'Expense', 'account_type': ''}, 'name')
|
||||||
|
}]
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
if not frappe.db.get_value('Salary Component Account',
|
||||||
|
{'parent': 'Basic Salary', 'company': company}):
|
||||||
|
salary_component = frappe.get_doc('Salary Component', 'Basic Salary')
|
||||||
|
salary_component.append('accounts', {
|
||||||
|
'company': company,
|
||||||
|
'default_account': 'Salary - WP'
|
||||||
|
})
|
||||||
|
|
||||||
|
company_doc = frappe.get_doc('Company', company)
|
||||||
|
if not company_doc.default_payroll_payable_account:
|
||||||
|
company_doc.default_payroll_payable_account = frappe.db.get_value('Account',
|
||||||
|
{'company': company, 'root_type': 'Liability', 'account_type': ''}, 'name')
|
||||||
|
company_doc.save()
|
||||||
|
|
||||||
|
if not frappe.db.exists('Branch', branch):
|
||||||
|
frappe.get_doc({
|
||||||
|
'doctype': 'Branch',
|
||||||
|
'branch': branch
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
employee_doc = frappe.get_doc('Employee', employee)
|
||||||
|
employee_doc.branch = branch
|
||||||
|
employee_doc.holiday_list = holiday_list
|
||||||
|
employee_doc.save()
|
||||||
|
|
||||||
|
employee_loan = create_employee_loan(employee,
|
||||||
|
"Personal Loan", 280000, "Repay Over Number of Periods", 20)
|
||||||
|
employee_loan.repay_from_salary = 1
|
||||||
|
employee_loan.submit()
|
||||||
|
|
||||||
|
salary_strcture = "Test Salary Structure for Loan"
|
||||||
|
if not frappe.db.exists('Salary Structure', salary_strcture):
|
||||||
|
salary_strcture = make_salary_structure(salary_strcture, [{
|
||||||
|
'employee': employee,
|
||||||
|
'from_date': '2017-01-01',
|
||||||
|
'base': 30000
|
||||||
|
}])
|
||||||
|
|
||||||
|
salary_strcture = frappe.get_doc('Salary Structure', salary_strcture)
|
||||||
|
salary_strcture.set('earnings', [{
|
||||||
|
'salary_component': 'Basic Salary',
|
||||||
|
'abbr': 'BS',
|
||||||
|
'amount_based_on_formula':1,
|
||||||
|
'formula': 'base*.5'
|
||||||
|
}])
|
||||||
|
salary_strcture.save()
|
||||||
|
|
||||||
|
dates = get_start_end_dates('Monthly', nowdate())
|
||||||
|
make_process_payroll(start_date=dates.start_date,
|
||||||
|
end_date=dates.end_date, branch=branch)
|
||||||
|
|
||||||
|
name = frappe.db.get_value('Salary Slip',
|
||||||
|
{'posting_date': nowdate(), 'employee': employee}, 'name')
|
||||||
|
|
||||||
|
salary_slip = frappe.get_doc('Salary Slip', name)
|
||||||
|
for row in salary_slip.loans:
|
||||||
|
if row.employee_loan == employee_loan.name:
|
||||||
|
interest_amount = (280000 * 8.4)/(12*100)
|
||||||
|
principal_amount = employee_loan.monthly_repayment_amount - interest_amount
|
||||||
|
self.assertEqual(row.interest_amount, interest_amount)
|
||||||
|
self.assertEqual(row.principal_amount, principal_amount)
|
||||||
|
self.assertEqual(row.total_payment,
|
||||||
|
interest_amount + principal_amount)
|
||||||
|
|
||||||
|
if salary_slip.docstatus == 0:
|
||||||
|
frappe.delete_doc('Salary Slip', name)
|
||||||
|
|
||||||
|
employee_loan.cancel()
|
||||||
|
frappe.delete_doc('Employee Loan', employee_loan.name)
|
||||||
|
|
||||||
def get_salary_component_account(sal_comp):
|
def get_salary_component_account(sal_comp):
|
||||||
company = erpnext.get_default_company()
|
company = erpnext.get_default_company()
|
||||||
@ -63,4 +142,54 @@ def create_account(company):
|
|||||||
"parent_account": "Indirect Expenses - " + frappe.db.get_value('Company', company, 'abbr'),
|
"parent_account": "Indirect Expenses - " + frappe.db.get_value('Company', company, 'abbr'),
|
||||||
"company": company
|
"company": company
|
||||||
}).insert()
|
}).insert()
|
||||||
return salary_account
|
return salary_account
|
||||||
|
|
||||||
|
def make_process_payroll(**args):
|
||||||
|
args = frappe._dict(args)
|
||||||
|
|
||||||
|
process_payroll = frappe.get_doc("Process Payroll", "Process Payroll")
|
||||||
|
process_payroll.company = erpnext.get_default_company()
|
||||||
|
process_payroll.start_date = args.start_date or "2016-11-01"
|
||||||
|
process_payroll.end_date = args.end_date or "2016-11-30"
|
||||||
|
process_payroll.payment_account = get_payment_account()
|
||||||
|
process_payroll.posting_date = nowdate()
|
||||||
|
process_payroll.payroll_frequency = "Monthly"
|
||||||
|
process_payroll.branch = args.branch or None
|
||||||
|
process_payroll.create_salary_slips()
|
||||||
|
process_payroll.submit_salary_slips()
|
||||||
|
if process_payroll.get_sal_slip_list(ss_status = 1):
|
||||||
|
r = process_payroll.make_payment_entry()
|
||||||
|
|
||||||
|
return process_payroll
|
||||||
|
|
||||||
|
def get_payment_account():
|
||||||
|
return frappe.get_value('Account',
|
||||||
|
{'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||||
|
|
||||||
|
def make_holiday(holiday_list_name):
|
||||||
|
if not frappe.db.exists('Holiday List', holiday_list_name):
|
||||||
|
current_fiscal_year = get_fiscal_year(nowdate(), as_dict=True)
|
||||||
|
dt = getdate(nowdate())
|
||||||
|
|
||||||
|
new_year = dt + relativedelta(month=01, day=01, year=dt.year)
|
||||||
|
republic_day = dt + relativedelta(month=01, day=26, year=dt.year)
|
||||||
|
test_holiday = dt + relativedelta(month=02, day=02, year=dt.year)
|
||||||
|
|
||||||
|
frappe.get_doc({
|
||||||
|
'doctype': 'Holiday List',
|
||||||
|
'from_date': current_fiscal_year.year_start_date,
|
||||||
|
'to_date': current_fiscal_year.year_end_date,
|
||||||
|
'holiday_list_name': holiday_list_name,
|
||||||
|
'holidays': [{
|
||||||
|
'holiday_date': new_year,
|
||||||
|
'description': 'New Year'
|
||||||
|
}, {
|
||||||
|
'holiday_date': republic_day,
|
||||||
|
'description': 'Republic Day'
|
||||||
|
}, {
|
||||||
|
'holiday_date': test_holiday,
|
||||||
|
'description': 'Test Holiday'
|
||||||
|
}]
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
return holiday_list_name
|
||||||
|
@ -1293,7 +1293,68 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "principal_amount",
|
"fieldname": "loans",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Employee Loan",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Salary Slip Loan",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "section_break_43",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "total_principal_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -1302,7 +1363,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Principal Amount",
|
"label": "Total Principal Amount",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
@ -1324,7 +1385,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "interest_amount",
|
"default": "0",
|
||||||
|
"fieldname": "total_interest_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -1333,7 +1395,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Interest Amount",
|
"label": "Total Interest Amount",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
@ -1355,7 +1417,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "column_break_48",
|
"fieldname": "column_break_45",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -1384,6 +1446,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"default": "0",
|
||||||
"fieldname": "total_loan_repayment",
|
"fieldname": "total_loan_repayment",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1604,7 +1667,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-11-10 18:40:33.817074",
|
"modified": "2017-11-13 23:55:37.504856",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Salary Slip",
|
"name": "Salary Slip",
|
||||||
|
@ -375,15 +375,34 @@ class SalarySlip(TransactionBase):
|
|||||||
self.precision("net_pay") if disable_rounded_total else 0)
|
self.precision("net_pay") if disable_rounded_total else 0)
|
||||||
|
|
||||||
def set_loan_repayment(self):
|
def set_loan_repayment(self):
|
||||||
employee_loan = frappe.db.sql("""select sum(principal_amount) as principal_amount, sum(interest_amount) as interest_amount,
|
self.set('loans', [])
|
||||||
sum(total_payment) as total_loan_repayment from `tabRepayment Schedule`
|
self.total_loan_repayment = 0
|
||||||
where payment_date between %s and %s and parent in (select name from `tabEmployee Loan`
|
self.total_interest_amount = 0
|
||||||
where employee = %s and repay_from_salary = 1 and docstatus = 1)""",
|
self.total_principal_amount = 0
|
||||||
(self.start_date, self.end_date, self.employee), as_dict=True)
|
|
||||||
if employee_loan:
|
for loan in self.get_employee_loan_details():
|
||||||
self.principal_amount = employee_loan[0].principal_amount
|
self.append('loans', {
|
||||||
self.interest_amount = employee_loan[0].interest_amount
|
'employee_loan': loan.name,
|
||||||
self.total_loan_repayment = employee_loan[0].total_loan_repayment
|
'total_payment': loan.total_payment,
|
||||||
|
'interest_amount': loan.interest_amount,
|
||||||
|
'principal_amount': loan.principal_amount,
|
||||||
|
'employee_loan_account': loan.employee_loan_account,
|
||||||
|
'interest_income_account': loan.interest_income_account
|
||||||
|
})
|
||||||
|
|
||||||
|
self.total_loan_repayment += loan.total_payment
|
||||||
|
self.total_interest_amount += loan.interest_amount
|
||||||
|
self.total_principal_amount += loan.principal_amount
|
||||||
|
|
||||||
|
def get_employee_loan_details(self):
|
||||||
|
return frappe.db.sql("""select rps.principal_amount, rps.interest_amount, el.name,
|
||||||
|
rps.total_payment, el.employee_loan_account, el.interest_income_account
|
||||||
|
from
|
||||||
|
`tabRepayment Schedule` as rps, `tabEmployee Loan` as el
|
||||||
|
where
|
||||||
|
el.name = rps.parent and rps.payment_date between %s and %s and
|
||||||
|
el.repay_from_salary = 1 and el.docstatus = 1 and el.employee = %s""",
|
||||||
|
(self.start_date, self.end_date, self.employee), as_dict=True) or []
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if self.net_pay < 0:
|
if self.net_pay < 0:
|
||||||
|
0
erpnext/hr/doctype/salary_slip_loan/__init__.py
Normal file
0
erpnext/hr/doctype/salary_slip_loan/__init__.py
Normal file
256
erpnext/hr/doctype/salary_slip_loan/salary_slip_loan.json
Normal file
256
erpnext/hr/doctype/salary_slip_loan/salary_slip_loan.json
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
|
"allow_import": 0,
|
||||||
|
"allow_rename": 0,
|
||||||
|
"beta": 0,
|
||||||
|
"creation": "2017-11-08 12:51:12.834479",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "employee_loan",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Employee Loan",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Employee Loan",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "employee_loan_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Employee Loan Account",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Account",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "interest_income_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Interest Income Account",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Account",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_4",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "principal_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Principal Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "interest_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Interest Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "total_payment",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Total Payment",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 1,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2017-11-13 23:59:47.237689",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "HR",
|
||||||
|
"name": "Salary Slip Loan",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1,
|
||||||
|
"track_seen": 0
|
||||||
|
}
|
10
erpnext/hr/doctype/salary_slip_loan/salary_slip_loan.py
Normal file
10
erpnext/hr/doctype/salary_slip_loan/salary_slip_loan.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class SalarySlipLoan(Document):
|
||||||
|
pass
|
@ -17,11 +17,9 @@ class TestSalaryStructure(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.make_holiday_list()
|
self.make_holiday_list()
|
||||||
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Structure Test Holiday List")
|
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Structure Test Holiday List")
|
||||||
make_earning_salary_component(["Basic Salary", "Special Allowance", "HRA"])
|
|
||||||
make_deduction_salary_component(["Professional Tax", "TDS"])
|
|
||||||
make_employee("test_employee@salary.com")
|
make_employee("test_employee@salary.com")
|
||||||
make_employee("test_employee_2@salary.com")
|
make_employee("test_employee_2@salary.com")
|
||||||
|
|
||||||
def make_holiday_list(self):
|
def make_holiday_list(self):
|
||||||
if not frappe.db.get_value("Holiday List", "Salary Structure Test Holiday List"):
|
if not frappe.db.get_value("Holiday List", "Salary Structure Test Holiday List"):
|
||||||
holiday_list = frappe.get_doc({
|
holiday_list = frappe.get_doc({
|
||||||
@ -33,7 +31,7 @@ class TestSalaryStructure(unittest.TestCase):
|
|||||||
}).insert()
|
}).insert()
|
||||||
holiday_list.get_weekly_off_dates()
|
holiday_list.get_weekly_off_dates()
|
||||||
holiday_list.save()
|
holiday_list.save()
|
||||||
|
|
||||||
def test_amount_totals(self):
|
def test_amount_totals(self):
|
||||||
sal_slip = frappe.get_value("Salary Slip", {"employee_name":"test_employee@salary.com"})
|
sal_slip = frappe.get_value("Salary Slip", {"employee_name":"test_employee@salary.com"})
|
||||||
if not sal_slip:
|
if not sal_slip:
|
||||||
@ -64,7 +62,7 @@ class TestSalaryStructure(unittest.TestCase):
|
|||||||
|
|
||||||
for row in salary_structure.deductions:
|
for row in salary_structure.deductions:
|
||||||
self.assertFalse(("\n" in row.formula) or ("\n" in row.condition))
|
self.assertFalse(("\n" in row.formula) or ("\n" in row.condition))
|
||||||
|
|
||||||
def make_employee(user):
|
def make_employee(user):
|
||||||
if not frappe.db.get_value("User", user):
|
if not frappe.db.get_value("User", user):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
@ -74,7 +72,6 @@ def make_employee(user):
|
|||||||
"new_password": "password",
|
"new_password": "password",
|
||||||
"roles": [{"doctype": "Has Role", "role": "Employee"}]
|
"roles": [{"doctype": "Has Role", "role": "Employee"}]
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
|
|
||||||
if not frappe.db.get_value("Employee", {"user_id": user}):
|
if not frappe.db.get_value("Employee", {"user_id": user}):
|
||||||
emp = frappe.get_doc({
|
emp = frappe.get_doc({
|
||||||
@ -95,7 +92,7 @@ def make_employee(user):
|
|||||||
return emp.name
|
return emp.name
|
||||||
else:
|
else:
|
||||||
return frappe.get_value("Employee", {"employee_name":user}, "name")
|
return frappe.get_value("Employee", {"employee_name":user}, "name")
|
||||||
|
|
||||||
def make_salary_slip_from_salary_structure(employee):
|
def make_salary_slip_from_salary_structure(employee):
|
||||||
sal_struct = make_salary_structure('Salary Structure Sample')
|
sal_struct = make_salary_structure('Salary Structure Sample')
|
||||||
sal_slip = make_salary_slip(sal_struct, employee = employee)
|
sal_slip = make_salary_slip(sal_struct, employee = employee)
|
||||||
@ -106,22 +103,21 @@ def make_salary_slip_from_salary_structure(employee):
|
|||||||
sal_slip.insert()
|
sal_slip.insert()
|
||||||
sal_slip.submit()
|
sal_slip.submit()
|
||||||
return sal_slip
|
return sal_slip
|
||||||
|
|
||||||
def make_salary_structure(sal_struct):
|
def make_salary_structure(sal_struct, employees=None):
|
||||||
if not frappe.db.exists('Salary Structure', sal_struct):
|
if not frappe.db.exists('Salary Structure', sal_struct):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Salary Structure",
|
"doctype": "Salary Structure",
|
||||||
"name": sal_struct,
|
"name": sal_struct,
|
||||||
"company": erpnext.get_default_company(),
|
"company": erpnext.get_default_company(),
|
||||||
"employees": get_employee_details(),
|
"employees": employees or get_employee_details(),
|
||||||
"earnings": get_earnings_component(),
|
"earnings": get_earnings_component(),
|
||||||
"deductions": get_deductions_component(),
|
"deductions": get_deductions_component(),
|
||||||
"payroll_frequency": "Monthly",
|
"payroll_frequency": "Monthly",
|
||||||
"payment_account": frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
"payment_account": frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||||
}).insert()
|
}).insert()
|
||||||
return sal_struct
|
return sal_struct
|
||||||
|
|
||||||
|
|
||||||
def get_employee_details():
|
def get_employee_details():
|
||||||
return [{"employee": frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"),
|
return [{"employee": frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"),
|
||||||
"base": 25000,
|
"base": 25000,
|
||||||
@ -136,8 +132,11 @@ def get_employee_details():
|
|||||||
"idx": 2
|
"idx": 2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_earnings_component():
|
def get_earnings_component():
|
||||||
|
make_earning_salary_component(["Basic Salary", "Special Allowance", "HRA"])
|
||||||
|
make_deduction_salary_component(["Professional Tax", "TDS"])
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"salary_component": 'Basic Salary',
|
"salary_component": 'Basic Salary',
|
||||||
@ -167,7 +166,7 @@ def get_earnings_component():
|
|||||||
"idx": 4
|
"idx": 4
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_deductions_component():
|
def get_deductions_component():
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -191,5 +190,4 @@ def get_deductions_component():
|
|||||||
"formula": 'base*.1',
|
"formula": 'base*.1',
|
||||||
"idx": 3
|
"idx": 3
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -458,4 +458,5 @@ erpnext.patches.v9_0.copy_old_fees_field_data
|
|||||||
erpnext.patches.v9_0.set_pos_profile_name
|
erpnext.patches.v9_0.set_pos_profile_name
|
||||||
erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings
|
erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings
|
||||||
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
|
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
|
||||||
erpnext.patches.v9_2.delete_healthcare_domain_default_items
|
erpnext.patches.v9_0.update_employee_loan_details
|
||||||
|
erpnext.patches.v9_2.delete_healthcare_domain_default_items
|
||||||
|
24
erpnext/patches/v9_0/update_employee_loan_details.py
Normal file
24
erpnext/patches/v9_0/update_employee_loan_details.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Copyright (c) 2017, Frappe and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc('hr', 'doctype', 'salary_slip_loan')
|
||||||
|
frappe.reload_doc('hr', 'doctype', 'salary_slip')
|
||||||
|
|
||||||
|
for data in frappe.db.sql(""" select name,
|
||||||
|
start_date, end_date, total_loan_repayment
|
||||||
|
from
|
||||||
|
`tabSalary Slip`
|
||||||
|
where
|
||||||
|
docstatus < 2 and ifnull(total_loan_repayment, 0) > 0""", as_dict=1):
|
||||||
|
salary_slip = frappe.get_doc('Salary Slip', data.name)
|
||||||
|
salary_slip.set_loan_repayment()
|
||||||
|
|
||||||
|
if salary_slip.total_loan_repayment == data.total_loan_repayment:
|
||||||
|
for row in salary_slip.loans:
|
||||||
|
row.db_update()
|
||||||
|
|
||||||
|
salary_slip.db_update()
|
Loading…
x
Reference in New Issue
Block a user