Merge branch 'fix/13.0/l10n_us_hr_payroll__category_sum_recursive' into '13.0'

fix/13.0/l10n_us_hr_payroll__category_sum_recursive into 13.0

See merge request hibou-io/hibou-odoo/suite!618
This commit is contained in:
Jared Kipe
2020-11-09 17:54:29 +00:00
3 changed files with 104 additions and 23 deletions

View File

@@ -76,12 +76,35 @@ class Payslips(BrowsableObject):
FROM hr_payslip as hp, hr_payslip_line as pl
WHERE hp.employee_id = %s AND hp.state = 'done'
AND hp.{sum_field} >= %s AND hp.date_to <= %s AND hp.id = pl.slip_id AND pl.code = %s""".format(sum_field=sum_field)
# Original (non-recursive)
# self.__browsable_query_category = """
# SELECT sum(case when hp.credit_note is not True then (pl.total) else (-pl.total) end)
# FROM hr_payslip as hp, hr_payslip_line as pl, hr_salary_rule_category as rc
# WHERE hp.employee_id = %s AND hp.state = 'done'
# AND hp.{sum_field} >= %s AND hp.date_to <= %s AND hp.id = pl.slip_id
# AND rc.id = pl.category_id AND rc.code = %s""".format(sum_field=sum_field)
# Hibou Recursive version
self.__browsable_query_category = """
WITH RECURSIVE
category_by_code as (
SELECT id
FROM hr_salary_rule_category
WHERE code = %s
),
category_ids as (
SELECT COALESCE((SELECT id FROM category_by_code), -1) AS id
UNION ALL
SELECT rc.id
FROM hr_salary_rule_category AS rc
JOIN category_ids AS rcs ON rcs.id = rc.parent_id
)
SELECT sum(case when hp.credit_note is not True then (pl.total) else (-pl.total) end)
FROM hr_payslip as hp, hr_payslip_line as pl, hr_salary_rule_category as rc
FROM hr_payslip as hp, hr_payslip_line as pl
WHERE hp.employee_id = %s AND hp.state = 'done'
AND hp.{sum_field} >= %s AND hp.date_to <= %s AND hp.id = pl.slip_id
AND rc.id = pl.category_id AND rc.code = %s""".format(sum_field=sum_field)
AND pl.category_id in (SELECT id from category_ids)""".format(sum_field=sum_field)
def sum(self, code, from_date, to_date=None):
if to_date is None:
@@ -101,7 +124,10 @@ class Payslips(BrowsableObject):
self.env['hr.payslip.line'].flush(['total', 'slip_id', 'category_id'])
self.env['hr.salary.rule.category'].flush(['code'])
self.env.cr.execute(self.__browsable_query_category, (self.employee_id, from_date, to_date, code))
# standard version
# self.env.cr.execute(self.__browsable_query_category, (self.employee_id, from_date, to_date, code))
# recursive category version
self.env.cr.execute(self.__browsable_query_category, (code, self.employee_id, from_date, to_date))
res = self.env.cr.fetchone()
return res and res[0] or 0.0

View File

@@ -12,17 +12,17 @@ def fica_wage(payslip, categories):
"""
wage = categories.GROSS
wage -= categories.ALW_FICA_EXEMPT + \
categories.ALW_FIT_FICA_EXEMPT + \
categories.ALW_FIT_FICA_FUTA_EXEMPT + \
categories.ALW_FICA_FUTA_EXEMPT
less_exempt = categories.ALW_FICA_EXEMPT + \
categories.ALW_FIT_FICA_EXEMPT + \
categories.ALW_FIT_FICA_FUTA_EXEMPT + \
categories.ALW_FICA_FUTA_EXEMPT
wage += categories.DED_FICA_EXEMPT + \
categories.DED_FIT_FICA_EXEMPT + \
categories.DED_FIT_FICA_FUTA_EXEMPT + \
categories.DED_FICA_FUTA_EXEMPT
return wage
plus_exempt = categories.DED_FICA_EXEMPT + \
categories.DED_FIT_FICA_EXEMPT + \
categories.DED_FIT_FICA_FUTA_EXEMPT + \
categories.DED_FICA_FUTA_EXEMPT
# _logger.info('fica wage GROSS: %0.2f less exempt ALW: %0.2f plus exempt DED: %0.2f' % (wage, less_exempt, plus_exempt))
return wage - less_exempt + plus_exempt
def fica_wage_ytd(payslip, categories):
@@ -34,18 +34,19 @@ def fica_wage_ytd(payslip, categories):
year = payslip.dict.get_year()
ytd_wage = payslip.sum_category('GROSS', str(year) + '-01-01', str(year+1) + '-01-01')
ytd_wage -= payslip.sum_category('ALW_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('ALW_FIT_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('ALW_FIT_FICA_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('ALW_FICA_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01')
less_exempt = payslip.sum_category('ALW_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('ALW_FIT_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('ALW_FIT_FICA_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('ALW_FICA_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01')
ytd_wage += payslip.sum_category('DED_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('DED_FIT_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('DED_FIT_FICA_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('DED_FICA_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01')
plus_exempt = payslip.sum_category('DED_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('DED_FIT_FICA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('DED_FIT_FICA_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01') + \
payslip.sum_category('DED_FICA_FUTA_EXEMPT', str(year) + '-01-01', str(year+1) + '-01-01')
ytd_wage += payslip.contract_id.external_wages
return ytd_wage
external_wages = payslip.dict.contract_id.external_wages
# _logger.info('fica ytd wage GROSS: %0.2f less exempt ALW: %0.2f plus exempt DED: %0.2f plus external: %0.2f' % (ytd_wage, less_exempt, plus_exempt, external_wages))
return ytd_wage - less_exempt + plus_exempt + external_wages
def ee_us_941_fica_ss(payslip, categories, worked_days, inputs):

View File

@@ -63,3 +63,57 @@ elif ytd_rule == 0.0:
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertEqual(cats['test_sum_behavior'], 0.0)
def test_recursive_salary_rule_category(self):
# self.debug = True
us_structure = self.env.ref('l10n_us_hr_payroll.hr_payroll_structure')
# In this scenario, you are in rule code that will check for the category
# and a subcategory will also
alw_category = self.env.ref('hr_payroll.ALW')
ded_category = self.env.ref('hr_payroll.DED')
test_category = self.env['hr.salary.rule.category'].create({
'name': 'Special ALW',
'code': 'ALW_SPECIAL_RECURSIVE',
'parent_id': alw_category.id,
})
test_special_alw = self.env['hr.salary.rule'].create({
'name': 'Flat amount 200',
'code': 'ALW_SPECIAL_RECURSIVE',
'category_id': test_category.id,
'condition_select': 'none',
'amount_select': 'fix',
'amount_fix': 200.0,
'struct_id': us_structure.id,
})
test_recursion = self.env['hr.salary.rule'].create({
'name': 'Actual Test Behavior',
'code': 'RECURSION_TEST',
'category_id': ded_category.id,
'condition_select': 'none',
'amount_select': 'code',
'amount_python_compute': """
# this rule will always be the total of the ALW category and YTD ALW category
result = categories.ALW
year = payslip.dict.get_year()
result += payslip.sum_category('ALW', str(year) + '-01-01', str(year+1) + '-01-01')
""",
'sequence': 101,
'struct_id': us_structure.id,
})
salary = 80000.0
employee = self._createEmployee()
contract = self._createContract(employee, wage=salary, schedule_pay='bi-weekly')
payslip = self._createPayslip(employee, '2020-01-01', '2020-01-14')
payslip.compute_sheet()
cats = self._getCategories(payslip)
rules = self._getRules(payslip)
self.assertEqual(rules['RECURSION_TEST'], 200.0)
process_payslip(payslip)
payslip = self._createPayslip(employee, '2020-01-15', '2020-01-27')
payslip.compute_sheet()
cats = self._getCategories(payslip)
rules = self._getRules(payslip)
# two hundred is in the YTD ALW
self.assertEqual(rules['RECURSION_TEST'], 200.0 + 200.0)