Merge branch 'develop' of https://github.com/frappe/erpnext into loan_patch_and_fixes
This commit is contained in:
commit
a8807e2696
@ -162,7 +162,8 @@ def get_tds_amount(suppliers, net_total, company, tax_details, fiscal_year_detai
|
|||||||
debit_note_amount = get_debit_note_amount(suppliers, year_start_date, year_end_date)
|
debit_note_amount = get_debit_note_amount(suppliers, year_start_date, year_end_date)
|
||||||
supplier_credit_amount -= debit_note_amount
|
supplier_credit_amount -= debit_note_amount
|
||||||
|
|
||||||
if supplier_credit_amount >= tax_details.get('threshold', 0) or supplier_credit_amount >= tax_details.get('cumulative_threshold', 0):
|
if ((tax_details.get('threshold', 0) and supplier_credit_amount >= tax_details.threshold)
|
||||||
|
or (tax_details.get('cumulative_threshold', 0) and supplier_credit_amount >= tax_details.cumulative_threshold)):
|
||||||
|
|
||||||
if ldc and is_valid_certificate(ldc.valid_from, ldc.valid_upto, posting_date, tds_deducted, net_total,
|
if ldc and is_valid_certificate(ldc.valid_from, ldc.valid_upto, posting_date, tds_deducted, net_total,
|
||||||
ldc.certificate_limit):
|
ldc.certificate_limit):
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
"is_group",
|
"is_group",
|
||||||
"disabled",
|
"disabled",
|
||||||
"section_break_4",
|
"section_break_4",
|
||||||
|
"payroll_cost_center",
|
||||||
|
"column_break_9",
|
||||||
"leave_block_list",
|
"leave_block_list",
|
||||||
"leave_section",
|
"leave_section",
|
||||||
"leave_approvers",
|
"leave_approvers",
|
||||||
@ -125,13 +127,23 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "payroll_cost_center",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Payroll Cost Center",
|
||||||
|
"options": "Cost Center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_9",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-sitemap",
|
"icon": "fa fa-sitemap",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-03-18 18:03:27.784362",
|
"modified": "2020-05-05 18:49:28.503931",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Department",
|
"name": "Department",
|
||||||
|
@ -60,6 +60,8 @@
|
|||||||
"default_shift",
|
"default_shift",
|
||||||
"salary_information",
|
"salary_information",
|
||||||
"salary_mode",
|
"salary_mode",
|
||||||
|
"payroll_cost_center",
|
||||||
|
"column_break_52",
|
||||||
"bank_name",
|
"bank_name",
|
||||||
"bank_ac_no",
|
"bank_ac_no",
|
||||||
"health_insurance_section",
|
"health_insurance_section",
|
||||||
@ -783,13 +785,25 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_19",
|
"fieldname": "column_break_19",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "department.payroll_cost_center",
|
||||||
|
"fetch_if_empty": 1,
|
||||||
|
"fieldname": "payroll_cost_center",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Payroll Cost Center",
|
||||||
|
"options": "Cost Center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_52",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-user",
|
"icon": "fa fa-user",
|
||||||
"idx": 24,
|
"idx": 24,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-08 12:25:34.306695",
|
"modified": "2020-05-05 18:51:03.152503",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Employee",
|
"name": "Employee",
|
||||||
|
@ -45,7 +45,7 @@ class TestEmployee(unittest.TestCase):
|
|||||||
employee1_doc.status = 'Left'
|
employee1_doc.status = 'Left'
|
||||||
self.assertRaises(EmployeeLeftValidationError, employee1_doc.save)
|
self.assertRaises(EmployeeLeftValidationError, employee1_doc.save)
|
||||||
|
|
||||||
def make_employee(user, company=None):
|
def make_employee(user, company=None, **kwargs):
|
||||||
if not frappe.db.get_value("User", user):
|
if not frappe.db.get_value("User", user):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "User",
|
"doctype": "User",
|
||||||
@ -55,7 +55,7 @@ def make_employee(user, company=None):
|
|||||||
"roles": [{"doctype": "Has Role", "role": "Employee"}]
|
"roles": [{"doctype": "Has Role", "role": "Employee"}]
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
if not frappe.db.get_value("Employee", { "user_id": user, "company": company or erpnext.get_default_company() }):
|
if not frappe.db.get_value("Employee", {"user_id": user}):
|
||||||
employee = frappe.get_doc({
|
employee = frappe.get_doc({
|
||||||
"doctype": "Employee",
|
"doctype": "Employee",
|
||||||
"naming_series": "EMP-",
|
"naming_series": "EMP-",
|
||||||
@ -71,7 +71,10 @@ def make_employee(user, company=None):
|
|||||||
"prefered_email": user,
|
"prefered_email": user,
|
||||||
"status": "Active",
|
"status": "Active",
|
||||||
"employment_type": "Intern"
|
"employment_type": "Intern"
|
||||||
}).insert()
|
})
|
||||||
|
if kwargs:
|
||||||
|
employee.update(kwargs)
|
||||||
|
employee.insert()
|
||||||
return employee.name
|
return employee.name
|
||||||
else:
|
else:
|
||||||
return frappe.get_value("Employee", {"employee_name":user}, "name")
|
return frappe.get_value("Employee", {"employee_name":user}, "name")
|
||||||
|
@ -55,6 +55,7 @@ class PayrollEntry(Document):
|
|||||||
ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s
|
ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s
|
||||||
{condition}""".format(condition=condition),
|
{condition}""".format(condition=condition),
|
||||||
{"company": self.company, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
|
{"company": self.company, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
|
||||||
|
|
||||||
if sal_struct:
|
if sal_struct:
|
||||||
cond += "and t2.salary_structure IN %(sal_struct)s "
|
cond += "and t2.salary_structure IN %(sal_struct)s "
|
||||||
cond += "and %(from_date)s >= t2.from_date"
|
cond += "and %(from_date)s >= t2.from_date"
|
||||||
@ -138,7 +139,7 @@ class PayrollEntry(Document):
|
|||||||
cond = self.get_filter_condition()
|
cond = self.get_filter_condition()
|
||||||
|
|
||||||
ss_list = frappe.db.sql("""
|
ss_list = frappe.db.sql("""
|
||||||
select t1.name, t1.salary_structure from `tabSalary Slip` t1
|
select t1.name, t1.salary_structure, t1.payroll_cost_center from `tabSalary Slip` t1
|
||||||
where t1.docstatus = %s and t1.start_date >= %s and t1.end_date <= %s
|
where t1.docstatus = %s and t1.start_date >= %s and t1.end_date <= %s
|
||||||
and (t1.journal_entry is null or t1.journal_entry = "") and ifnull(salary_slip_based_on_timesheet,0) = %s %s
|
and (t1.journal_entry is null or t1.journal_entry = "") and ifnull(salary_slip_based_on_timesheet,0) = %s %s
|
||||||
""" % ('%s', '%s', '%s','%s', cond), (ss_status, self.start_date, self.end_date, self.salary_slip_based_on_timesheet), as_dict=as_dict)
|
""" % ('%s', '%s', '%s','%s', cond), (ss_status, self.start_date, self.end_date, self.salary_slip_based_on_timesheet), as_dict=as_dict)
|
||||||
@ -170,9 +171,13 @@ class PayrollEntry(Document):
|
|||||||
def get_salary_components(self, component_type):
|
def get_salary_components(self, component_type):
|
||||||
salary_slips = self.get_sal_slip_list(ss_status = 1, as_dict = True)
|
salary_slips = self.get_sal_slip_list(ss_status = 1, as_dict = True)
|
||||||
if salary_slips:
|
if salary_slips:
|
||||||
salary_components = frappe.db.sql("""select salary_component, amount, parentfield
|
salary_components = frappe.db.sql("""
|
||||||
from `tabSalary Detail` where parentfield = '%s' and parent in (%s)""" %
|
select ssd.salary_component, ssd.amount, ssd.parentfield, ss.payroll_cost_center
|
||||||
(component_type, ', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=True)
|
from `tabSalary Slip` ss, `tabSalary Detail` ssd
|
||||||
|
where ss.name = ssd.parent and ssd.parentfield = '%s' and ss.name in (%s)
|
||||||
|
""" % (component_type, ', '.join(['%s']*len(salary_slips))),
|
||||||
|
tuple([d.name for d in salary_slips]), as_dict=True)
|
||||||
|
|
||||||
return salary_components
|
return salary_components
|
||||||
|
|
||||||
def get_salary_component_total(self, component_type = None):
|
def get_salary_component_total(self, component_type = None):
|
||||||
@ -186,15 +191,16 @@ class PayrollEntry(Document):
|
|||||||
if is_flexible_benefit == 1 and only_tax_impact ==1:
|
if is_flexible_benefit == 1 and only_tax_impact ==1:
|
||||||
add_component_to_accrual_jv_entry = False
|
add_component_to_accrual_jv_entry = False
|
||||||
if add_component_to_accrual_jv_entry:
|
if add_component_to_accrual_jv_entry:
|
||||||
component_dict[item['salary_component']] = component_dict.get(item['salary_component'], 0) + item['amount']
|
component_dict[(item.salary_component, item.payroll_cost_center)] \
|
||||||
|
= component_dict.get((item.salary_component, item.payroll_cost_center), 0) + flt(item.amount)
|
||||||
account_details = self.get_account(component_dict = component_dict)
|
account_details = self.get_account(component_dict = component_dict)
|
||||||
return account_details
|
return account_details
|
||||||
|
|
||||||
def get_account(self, component_dict = None):
|
def get_account(self, component_dict = None):
|
||||||
account_dict = {}
|
account_dict = {}
|
||||||
for s, a in component_dict.items():
|
for key, amount in component_dict.items():
|
||||||
account = self.get_salary_component_account(s)
|
account = self.get_salary_component_account(key[0])
|
||||||
account_dict[account] = account_dict.get(account, 0) + a
|
account_dict[(account, key[1])] = account_dict.get((account, key[1]), 0) + amount
|
||||||
return account_dict
|
return account_dict
|
||||||
|
|
||||||
def get_default_payroll_payable_account(self):
|
def get_default_payroll_payable_account(self):
|
||||||
@ -227,23 +233,23 @@ class PayrollEntry(Document):
|
|||||||
payable_amount = 0
|
payable_amount = 0
|
||||||
|
|
||||||
# Earnings
|
# Earnings
|
||||||
for acc, amount in earnings.items():
|
for acc_cc, amount in earnings.items():
|
||||||
payable_amount += flt(amount, precision)
|
payable_amount += flt(amount, precision)
|
||||||
accounts.append({
|
accounts.append({
|
||||||
"account": acc,
|
"account": acc_cc[0],
|
||||||
"debit_in_account_currency": flt(amount, precision),
|
"debit_in_account_currency": flt(amount, precision),
|
||||||
"party_type": '',
|
"party_type": '',
|
||||||
"cost_center": self.cost_center,
|
"cost_center": acc_cc[1] or self.cost_center,
|
||||||
"project": self.project
|
"project": self.project
|
||||||
})
|
})
|
||||||
|
|
||||||
# Deductions
|
# Deductions
|
||||||
for acc, amount in deductions.items():
|
for acc_cc, amount in deductions.items():
|
||||||
payable_amount -= flt(amount, precision)
|
payable_amount -= flt(amount, precision)
|
||||||
accounts.append({
|
accounts.append({
|
||||||
"account": acc,
|
"account": acc_cc[0],
|
||||||
"credit_in_account_currency": flt(amount, precision),
|
"credit_in_account_currency": flt(amount, precision),
|
||||||
"cost_center": self.cost_center,
|
"cost_center": acc_cc[1] or self.cost_center,
|
||||||
"party_type": '',
|
"party_type": '',
|
||||||
"project": self.project
|
"project": self.project
|
||||||
})
|
})
|
||||||
@ -253,6 +259,7 @@ class PayrollEntry(Document):
|
|||||||
"account": default_payroll_payable_account,
|
"account": default_payroll_payable_account,
|
||||||
"credit_in_account_currency": flt(payable_amount, precision),
|
"credit_in_account_currency": flt(payable_amount, precision),
|
||||||
"party_type": '',
|
"party_type": '',
|
||||||
|
"cost_center": self.cost_center
|
||||||
})
|
})
|
||||||
|
|
||||||
journal_entry.set("accounts", accounts)
|
journal_entry.set("accounts", accounts)
|
||||||
|
@ -10,14 +10,15 @@ from frappe.utils import add_months
|
|||||||
from erpnext.hr.doctype.payroll_entry.payroll_entry import get_start_end_dates, get_end_date
|
from erpnext.hr.doctype.payroll_entry.payroll_entry import get_start_end_dates, get_end_date
|
||||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||||
from erpnext.hr.doctype.salary_slip.test_salary_slip import get_salary_component_account, \
|
from erpnext.hr.doctype.salary_slip.test_salary_slip import get_salary_component_account, \
|
||||||
make_earning_salary_component, make_deduction_salary_component
|
make_earning_salary_component, make_deduction_salary_component, create_account
|
||||||
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure
|
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure
|
||||||
from erpnext.loan_management.doctype.loan.test_loan import create_loan, make_loan_disbursement_entry
|
from erpnext.loan_management.doctype.loan.test_loan import create_loan, make_loan_disbursement_entry
|
||||||
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
|
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
|
||||||
|
|
||||||
class TestPayrollEntry(unittest.TestCase):
|
class TestPayrollEntry(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
for dt in ["Salary Slip", "Salary Component", "Salary Component Account", "Payroll Entry", "Salary Structure"]:
|
for dt in ["Salary Slip", "Salary Component", "Salary Component Account",
|
||||||
|
"Payroll Entry", "Salary Structure", "Salary Structure Assignment", "Payroll Employee Detail", "Additional Salary"]:
|
||||||
frappe.db.sql("delete from `tab%s`" % dt)
|
frappe.db.sql("delete from `tab%s`" % dt)
|
||||||
|
|
||||||
make_earning_salary_component(setup=True, company_list=["_Test Company"])
|
make_earning_salary_component(setup=True, company_list=["_Test Company"])
|
||||||
@ -33,11 +34,59 @@ class TestPayrollEntry(unittest.TestCase):
|
|||||||
get_salary_component_account(data.name)
|
get_salary_component_account(data.name)
|
||||||
|
|
||||||
employee = frappe.db.get_value("Employee", {'company': company})
|
employee = frappe.db.get_value("Employee", {'company': company})
|
||||||
make_salary_structure("_Test Salary Structure", "Monthly", employee)
|
make_salary_structure("_Test Salary Structure", "Monthly", employee, company=company)
|
||||||
dates = get_start_end_dates('Monthly', nowdate())
|
dates = get_start_end_dates('Monthly', nowdate())
|
||||||
if not frappe.db.get_value("Salary Slip", {"start_date": dates.start_date, "end_date": dates.end_date}):
|
if not frappe.db.get_value("Salary Slip", {"start_date": dates.start_date, "end_date": dates.end_date}):
|
||||||
make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date)
|
make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date)
|
||||||
|
|
||||||
|
def test_payroll_entry_with_employee_cost_center(self): # pylint: disable=no-self-use
|
||||||
|
for data in frappe.get_all('Salary Component', fields = ["name"]):
|
||||||
|
if not frappe.db.get_value('Salary Component Account',
|
||||||
|
{'parent': data.name, 'company': "_Test Company"}, 'name'):
|
||||||
|
get_salary_component_account(data.name)
|
||||||
|
|
||||||
|
if not frappe.db.exists('Department', "cc - _TC"):
|
||||||
|
frappe.get_doc({
|
||||||
|
'doctype': 'Department',
|
||||||
|
'department_name': "cc",
|
||||||
|
"company": "_Test Company"
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
employee1 = make_employee("test_employee1@example.com", payroll_cost_center="_Test Cost Center - _TC",
|
||||||
|
department="cc - _TC", company="_Test Company")
|
||||||
|
employee2 = make_employee("test_employee2@example.com", payroll_cost_center="_Test Cost Center 2 - _TC",
|
||||||
|
department="cc - _TC", company="_Test Company")
|
||||||
|
|
||||||
|
make_salary_structure("_Test Salary Structure 1", "Monthly", employee1, company="_Test Company")
|
||||||
|
make_salary_structure("_Test Salary Structure 2", "Monthly", employee2, company="_Test Company")
|
||||||
|
|
||||||
|
if not frappe.db.exists("Account", "_Test Payroll Payable - _TC"):
|
||||||
|
create_account(account_name="_Test Payroll Payable",
|
||||||
|
company="_Test Company", parent_account="Current Liabilities - _TC")
|
||||||
|
frappe.db.set_value("Company", "_Test Company", "default_payroll_payable_account",
|
||||||
|
"_Test Payroll Payable - _TC")
|
||||||
|
|
||||||
|
dates = get_start_end_dates('Monthly', nowdate())
|
||||||
|
if not frappe.db.get_value("Salary Slip", {"start_date": dates.start_date, "end_date": dates.end_date}):
|
||||||
|
pe = make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date,
|
||||||
|
department="cc - _TC", company="_Test Company", payment_account="Cash - _TC", cost_center="Main - _TC")
|
||||||
|
je = frappe.db.get_value("Salary Slip", {"payroll_entry": pe.name}, "journal_entry")
|
||||||
|
je_entries = frappe.db.sql("""
|
||||||
|
select account, cost_center, debit, credit
|
||||||
|
from `tabJournal Entry Account`
|
||||||
|
where parent=%s
|
||||||
|
order by account, cost_center
|
||||||
|
""", je)
|
||||||
|
expected_je = (
|
||||||
|
('_Test Payroll Payable - _TC', 'Main - _TC', 0.0, 155600.0),
|
||||||
|
('Salary - _TC', '_Test Cost Center - _TC', 78000.0, 0.0),
|
||||||
|
('Salary - _TC', '_Test Cost Center 2 - _TC', 78000.0, 0.0),
|
||||||
|
('Salary Deductions - _TC', '_Test Cost Center - _TC', 0.0, 200.0),
|
||||||
|
('Salary Deductions - _TC', '_Test Cost Center 2 - _TC', 0.0, 200.0)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(je_entries, expected_je)
|
||||||
|
|
||||||
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'})
|
||||||
self.assertEqual(get_end_date('2017-02-01', 'monthly'), {'end_date': '2017-02-28'})
|
self.assertEqual(get_end_date('2017-02-01', 'monthly'), {'end_date': '2017-02-28'})
|
||||||
@ -49,7 +98,6 @@ class TestPayrollEntry(unittest.TestCase):
|
|||||||
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_loan(self):
|
def test_loan(self):
|
||||||
|
|
||||||
branch = "Test Employee Branch"
|
branch = "Test Employee Branch"
|
||||||
applicant = make_employee("test_employee@loan.com", company="_Test Company")
|
applicant = make_employee("test_employee@loan.com", company="_Test Company")
|
||||||
company = "_Test Company"
|
company = "_Test Company"
|
||||||
@ -116,6 +164,7 @@ def make_payroll_entry(**args):
|
|||||||
payroll_entry.posting_date = nowdate()
|
payroll_entry.posting_date = nowdate()
|
||||||
payroll_entry.payroll_frequency = "Monthly"
|
payroll_entry.payroll_frequency = "Monthly"
|
||||||
payroll_entry.branch = args.branch or None
|
payroll_entry.branch = args.branch or None
|
||||||
|
payroll_entry.department = args.department or None
|
||||||
|
|
||||||
if args.cost_center:
|
if args.cost_center:
|
||||||
payroll_entry.cost_center = args.cost_center
|
payroll_entry.cost_center = args.cost_center
|
||||||
@ -123,6 +172,7 @@ def make_payroll_entry(**args):
|
|||||||
if args.payment_account:
|
if args.payment_account:
|
||||||
payroll_entry.payment_account = args.payment_account
|
payroll_entry.payment_account = args.payment_account
|
||||||
|
|
||||||
|
payroll_entry.fill_employee_details()
|
||||||
payroll_entry.save()
|
payroll_entry.save()
|
||||||
payroll_entry.create_salary_slips()
|
payroll_entry.create_salary_slips()
|
||||||
payroll_entry.submit_salary_slips()
|
payroll_entry.submit_salary_slips()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"department",
|
"department",
|
||||||
"designation",
|
"designation",
|
||||||
"branch",
|
"branch",
|
||||||
|
"payroll_cost_center",
|
||||||
"column_break1",
|
"column_break1",
|
||||||
"status",
|
"status",
|
||||||
"journal_entry",
|
"journal_entry",
|
||||||
@ -459,13 +460,22 @@
|
|||||||
"options": "Salary Slip",
|
"options": "Salary Slip",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "employee.payroll_cost_center",
|
||||||
|
"fetch_if_empty": 1,
|
||||||
|
"fieldname": "payroll_cost_center",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Payroll Cost Center",
|
||||||
|
"options": "Cost Center",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 9,
|
"idx": 9,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-14 20:02:53.159827",
|
"modified": "2020-05-05 18:55:26.173629",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Salary Slip",
|
"name": "Salary Slip",
|
||||||
|
@ -422,22 +422,32 @@ def get_salary_component_account(sal_comp, company_list=None):
|
|||||||
sal_comp = frappe.get_doc("Salary Component", sal_comp)
|
sal_comp = frappe.get_doc("Salary Component", sal_comp)
|
||||||
if not sal_comp.get("accounts"):
|
if not sal_comp.get("accounts"):
|
||||||
for d in company_list:
|
for d in company_list:
|
||||||
|
company_abbr = frappe.get_cached_value('Company', d, 'abbr')
|
||||||
|
|
||||||
|
if sal_comp.type == "Earning":
|
||||||
|
account_name = "Salary"
|
||||||
|
parent_account = "Indirect Expenses - " + company_abbr
|
||||||
|
else:
|
||||||
|
account_name = "Salary Deductions"
|
||||||
|
parent_account = "Current Liabilities - " + company_abbr
|
||||||
|
|
||||||
sal_comp.append("accounts", {
|
sal_comp.append("accounts", {
|
||||||
"company": d,
|
"company": d,
|
||||||
"default_account": create_account(d)
|
"default_account": create_account(account_name, d, parent_account)
|
||||||
})
|
})
|
||||||
sal_comp.save()
|
sal_comp.save()
|
||||||
|
|
||||||
def create_account(company):
|
def create_account(account_name, company, parent_account):
|
||||||
salary_account = frappe.db.get_value("Account", "Salary - " + frappe.get_cached_value('Company', company, 'abbr'))
|
company_abbr = frappe.get_cached_value('Company', company, 'abbr')
|
||||||
if not salary_account:
|
account = frappe.db.get_value("Account", account_name + " - " + company_abbr)
|
||||||
|
if not account:
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Account",
|
"doctype": "Account",
|
||||||
"account_name": "Salary",
|
"account_name": account_name,
|
||||||
"parent_account": "Indirect Expenses - " + frappe.get_cached_value('Company', company, 'abbr'),
|
"parent_account": parent_account,
|
||||||
"company": company
|
"company": company
|
||||||
}).insert()
|
}).insert()
|
||||||
return salary_account
|
return account
|
||||||
|
|
||||||
def make_earning_salary_component(setup=False, test_tax=False, company_list=None):
|
def make_earning_salary_component(setup=False, test_tax=False, company_list=None):
|
||||||
data = [
|
data = [
|
||||||
@ -683,7 +693,7 @@ def setup_test():
|
|||||||
make_earning_salary_component(setup=True, company_list=["_Test Company"])
|
make_earning_salary_component(setup=True, company_list=["_Test Company"])
|
||||||
make_deduction_salary_component(setup=True, company_list=["_Test Company"])
|
make_deduction_salary_component(setup=True, company_list=["_Test Company"])
|
||||||
|
|
||||||
for dt in ["Leave Application", "Leave Allocation", "Salary Slip", "Attendance"]:
|
for dt in ["Leave Application", "Leave Allocation", "Salary Slip", "Attendance", "Additional Salary"]:
|
||||||
frappe.db.sql("delete from `tab%s`" % dt)
|
frappe.db.sql("delete from `tab%s`" % dt)
|
||||||
|
|
||||||
make_holiday_list()
|
make_holiday_list()
|
||||||
|
@ -153,12 +153,16 @@ def make_salary_slip(source_name, target_doc = None, employee = None, as_print =
|
|||||||
def postprocess(source, target):
|
def postprocess(source, target):
|
||||||
if employee:
|
if employee:
|
||||||
employee_details = frappe.db.get_value("Employee", employee,
|
employee_details = frappe.db.get_value("Employee", employee,
|
||||||
["employee_name", "branch", "designation", "department"], as_dict=1)
|
["employee_name", "branch", "designation", "department", "payroll_cost_center"], as_dict=1)
|
||||||
target.employee = employee
|
target.employee = employee
|
||||||
target.employee_name = employee_details.employee_name
|
target.employee_name = employee_details.employee_name
|
||||||
target.branch = employee_details.branch
|
target.branch = employee_details.branch
|
||||||
target.designation = employee_details.designation
|
target.designation = employee_details.designation
|
||||||
target.department = employee_details.department
|
target.department = employee_details.department
|
||||||
|
target.payroll_cost_center = employee_details.payroll_cost_center
|
||||||
|
if not target.payroll_cost_center and target.department:
|
||||||
|
target.payroll_cost_center = frappe.db.get_value("Department", target.department, "payroll_cost_center")
|
||||||
|
|
||||||
target.run_method('process_salary_structure', for_preview=for_preview)
|
target.run_method('process_salary_structure', for_preview=for_preview)
|
||||||
|
|
||||||
doc = get_mapped_doc("Salary Structure", source_name, {
|
doc = get_mapped_doc("Salary Structure", source_name, {
|
||||||
|
@ -128,6 +128,7 @@ def make_salary_structure(salary_structure, payroll_frequency, employee=None, do
|
|||||||
salary_structure_doc.insert()
|
salary_structure_doc.insert()
|
||||||
if not dont_submit:
|
if not dont_submit:
|
||||||
salary_structure_doc.submit()
|
salary_structure_doc.submit()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
salary_structure_doc = frappe.get_doc("Salary Structure", salary_structure)
|
salary_structure_doc = frappe.get_doc("Salary Structure", salary_structure)
|
||||||
|
|
||||||
|
@ -685,3 +685,4 @@ execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)
|
|||||||
erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
|
erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
|
||||||
erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
|
erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
|
||||||
erpnext.patches.v13_0.update_old_loans
|
erpnext.patches.v13_0.update_old_loans
|
||||||
|
erpnext.patches.v12_0.set_serial_no_status
|
||||||
|
17
erpnext/patches/v12_0/set_serial_no_status.py
Normal file
17
erpnext/patches/v12_0/set_serial_no_status.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.utils import getdate, nowdate
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc('stock', 'doctype', 'serial_no')
|
||||||
|
|
||||||
|
for serial_no in frappe.db.sql("""select name, delivery_document_type, warranty_expiry_date from `tabSerial No`
|
||||||
|
where (status is NULL OR status='')""", as_dict = 1):
|
||||||
|
if serial_no.get("delivery_document_type"):
|
||||||
|
status = "Delivered"
|
||||||
|
elif serial_no.get("warranty_expiry_date") and getdate(serial_no.get("warranty_expiry_date")) <= getdate(nowdate()):
|
||||||
|
status = "Expired"
|
||||||
|
else:
|
||||||
|
status = "Active"
|
||||||
|
|
||||||
|
frappe.db.set_value("Serial No", serial_no.get("name"), "status", status)
|
Loading…
x
Reference in New Issue
Block a user