diff --git a/l10n_us_nc_hr_payroll/data/rules_2018.xml b/l10n_us_nc_hr_payroll/data/rules_2018.xml index cacad79a..58e1f83a 100755 --- a/l10n_us_nc_hr_payroll/data/rules_2018.xml +++ b/l10n_us_nc_hr_payroll/data/rules_2018.xml @@ -55,7 +55,7 @@ if result_rate == 0.0: code wages = categories.GROSS -exemptions = contract.nc_nc4_allowances +allowances = contract.nc_nc4_allowances schedule_pay = contract.schedule_pay val = 0.00 @@ -95,10 +95,8 @@ else: if contract.nc_nc4_filing_status == 'exempt': result = 0 else: - if contract.w4_is_nonresident_alien: - result = round(((wages - (PST + (allowance_multiplier * exemptions))) * 0.05599) - contract.nc_nc4_additional_wh) - else: - result = round((wages - (PST + (allowance_multiplier * exemptions))) * 0.05599) + result = -round(((wages - (PST + (allowance_multiplier * allowances))) * 0.05599) + contract.nc_nc4_additional_wh) + diff --git a/l10n_us_nc_hr_payroll/hr_payroll.py b/l10n_us_nc_hr_payroll/hr_payroll.py index 8a0143bf..a4eb8572 100755 --- a/l10n_us_nc_hr_payroll/hr_payroll.py +++ b/l10n_us_nc_hr_payroll/hr_payroll.py @@ -12,7 +12,9 @@ class USNCHrContract(models.Model): ('surviving_spouse', 'Surviving Spouse'), ('head_household', 'Head of Household') ], string='NC Filing Status', default='single') - nc_nc4_additional_wh = fields.Float(string="Additional Witholding", default=0.0) + nc_nc4_additional_wh = fields.Float(string="Additional Witholding", default=0.0, + help="If you are filling out NC-4 NRA, this would be box 4; " \ + "otherwise box 2.") @api.multi def nc_unemp_rate(self, year): diff --git a/l10n_us_nc_hr_payroll/tests/test_us_nc_payslip_2018.py b/l10n_us_nc_hr_payroll/tests/test_us_nc_payslip_2018.py index 87fde82b..249acc27 100755 --- a/l10n_us_nc_hr_payroll/tests/test_us_nc_payslip_2018.py +++ b/l10n_us_nc_hr_payroll/tests/test_us_nc_payslip_2018.py @@ -19,7 +19,7 @@ class TestUsNCPayslip(TestUsPayslip): exemption = 1 # Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf - wh = round((salary - (PST + (allowance_multiplier * exemption))) * 0.05599) + wh = -round((salary - (PST + (allowance_multiplier * exemption))) * 0.05599) employee = self._createEmployee() employee.company_id.nc_unemp_rate_2018 = 0.06 @@ -119,16 +119,16 @@ class TestUsNCPayslip(TestUsPayslip): allowance_multiplier = 96.15 PST = 336.54 - exceptions = 2 + allowances = 2 # Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf - wh = round((salary - (PST + (allowance_multiplier * exceptions))) * 0.05599) + wh = -round((salary - (PST + (allowance_multiplier * allowances))) * 0.05599) employee = self._createEmployee() employee.company_id.nc_unemp_rate_2018 = 0.06 contract = self._createContract(employee, salary, struct_id=self.ref('l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay) - contract.nc_nc4_allowances = exceptions + contract.nc_nc4_allowances = allowances self.assertEqual(contract.schedule_pay, 'bi-weekly') @@ -172,17 +172,17 @@ class TestUsNCPayslip(TestUsPayslip): allowance_multiplier = 104.17 PST = 583.33 - exceptions = 1 + allowances = 1 # Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf - wh = round((salary - (PST + (allowance_multiplier * exceptions))) * 0.05599) + wh = -round((salary - (PST + (allowance_multiplier * allowances))) * 0.05599) employee = self._createEmployee() employee.company_id.nc_unemp_rate_2018 = 0.06 contract = self._createContract(employee, salary, struct_id=self.ref( 'l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay) - contract.nc_nc4_allowances = exceptions + contract.nc_nc4_allowances = allowances contract.nc_nc4_filing_status = nc_nc4_filing_status self.assertEqual(contract.schedule_pay, 'semi-monthly') @@ -219,24 +219,23 @@ class TestUsNCPayslip(TestUsPayslip): self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp) def test_2018_taxes_monthly(self): - self.debug = True salary = 4000.0 schedule_pay = 'monthly' # allowance_multiplier and Portion of Standard Deduction for weekly allowance_multiplier = 208.33 PST = 729.17 - exceptions = 1 + allowances = 1 # Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf - wh = round((salary - (PST + (allowance_multiplier * exceptions))) * 0.05599) + wh = -round((salary - (PST + (allowance_multiplier * allowances))) * 0.05599) employee = self._createEmployee() employee.company_id.nc_unemp_rate_2018 = 0.06 contract = self._createContract(employee, salary, struct_id=self.ref( 'l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), schedule_pay=schedule_pay) - contract.nc_nc4_allowances = exceptions + contract.nc_nc4_allowances = allowances self.assertEqual(contract.schedule_pay, 'monthly') @@ -320,3 +319,63 @@ class TestUsNCPayslip(TestUsPayslip): self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], remaining_nc_unemp_wages) self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp) + + def test_additional_withholding(self): + salary = 4000.0 + schedule_pay = 'weekly' + # allowance_multiplier and Portion of Standard Deduction for weekly + allowance_multiplier = 48.08 + PST = 168.27 + additional_wh = 40.0 + + #4000 - (168.27 + (48.08 * 1) + + allowances = 1 + # Algorithm derived from percentage method in https://files.nc.gov/ncdor/documents/files/nc-30_book_web.pdf + + wh = -round(((salary - (PST + (allowance_multiplier * allowances))) * 0.05599) + additional_wh) + + employee = self._createEmployee() + employee.company_id.nc_unemp_rate_2018 = 0.06 + + contract = self._createContract(employee, + salary, + struct_id=self.ref('l10n_us_nc_hr_payroll.hr_payroll_salary_structure_us_nc_employee'), + schedule_pay=schedule_pay) + contract.w4_is_nonresident_alien = True + contract.nc_nc4_additional_wh = additional_wh + contract.nc_nc4_allowances = allowances + + self.assertEqual(contract.schedule_pay, 'weekly') + self.assertEqual(contract.w4_is_nonresident_alien, True) + + # tax rates + nc_unemp = contract.nc_unemp_rate(2018) / -100.0 + + self._log('2018 North Carolina tax first payslip weekly:') + payslip = self._createPayslip(employee, '2018-01-01', '2018-01-31') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + + self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], salary) + self.assertPayrollEqual(cats['NC_UNEMP'], cats['NC_UNEMP_WAGES'] * nc_unemp) + self.assertPayrollEqual(cats['NC_INC_WITHHOLD'], wh) + + process_payslip(payslip) + + # Make a new payslip, this one will have maximums + + remaining_nc_unemp_wages = self.NC_UNEMP_MAX_WAGE - salary if (self.NC_UNEMP_MAX_WAGE - 2 * salary < salary) \ + else salary + + self._log('2018 North Carolina tax second payslip weekly:') + payslip = self._createPayslip(employee, '2018-02-01', '2018-02-28') + + payslip.compute_sheet() + + cats = self._getCategories(payslip) + + self.assertPayrollEqual(cats['NC_UNEMP_WAGES'], remaining_nc_unemp_wages) + self.assertPayrollEqual(cats['NC_UNEMP'], remaining_nc_unemp_wages * nc_unemp)