IMP l10n_us_hr_payroll Add GA Georgia (unemployment, income tax)

This commit is contained in:
Jared Kipe
2020-01-09 11:04:38 -08:00
parent c6ca33cad2
commit fe05ac55c4
9 changed files with 641 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ United States of America - Payroll Rules.
'data/federal/fed_941_fit_parameters.xml',
'data/federal/fed_941_fit_rules.xml',
'data/state/fl_florida.xml',
'data/state/ga_georgia.xml',
'data/state/mt_montana.xml',
'data/state/oh_ohio.xml',
'data/state/pa_pennsylvania.xml',

View File

@@ -0,0 +1,279 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Wage Base -->
<record id="rule_parameter_us_ga_suta_wage_base" model="hr.rule.parameter">
<field name="name">US GA Georgia SUTA Wage Base</field>
<field name="code">us_ga_suta_wage_base</field>
<field name="country_id" ref="base.us"/>
</record>
<data noupdate="1">
<record id="rule_parameter_us_ga_suta_wage_base_2019" model="hr.rule.parameter.value">
<field name="parameter_value">9500.00</field>
<field name="rule_parameter_id" ref="rule_parameter_us_ga_suta_wage_base"/>
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
</record>
<record id="rule_parameter_us_ga_suta_wage_base_2020" model="hr.rule.parameter.value">
<field name="parameter_value">9500.00</field>
<field name="rule_parameter_id" ref="rule_parameter_us_ga_suta_wage_base"/>
<field name="date_from" eval="datetime(2020, 1, 1).date()"/>
</record>
</data>
<!-- Rate -->
<record id="rule_parameter_us_ga_suta_rate" model="hr.rule.parameter">
<field name="name">US GA Georgia SUTA Rate</field>
<field name="code">us_ga_suta_rate</field>
<field name="country_id" ref="base.us"/>
</record>
<data noupdate="1">
<record id="rule_parameter_us_ga_suta_rate_2019" model="hr.rule.parameter.value">
<field name="parameter_value">2.7</field>
<field name="rule_parameter_id" ref="rule_parameter_us_ga_suta_rate"/>
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
</record>
<record id="rule_parameter_us_ga_suta_rate_2020" model="hr.rule.parameter.value">
<field name="parameter_value">2.7</field>
<field name="rule_parameter_id" ref="rule_parameter_us_ga_suta_rate"/>
<field name="date_from" eval="datetime(2020, 1, 1).date()"/>
</record>
</data>
<record id="rule_parameter_us_ga_sit_rate" model="hr.rule.parameter">
<field name="name">US GA Georgia SIT Rate Table</field>
<field name="code">us_ga_sit_rate</field>
<field name="country_id" ref="base.us"/>
</record>
<data noupdate="1">
<record id="rule_parameter_us_ga_sit_rate_2019" model="hr.rule.parameter.value">
<field name="parameter_value">{
'married filing joint, both spouses working': {
'weekly': ((9.50, 0.00, 1.00), (29.00, .10, 2.00), (48.00, .48, 3.00), (67.50, 1.06, 4.00), (96.00, 1.83, 5.00), ('inf', 3.27, 5.75)),
'bi-weekly': ((19.00, 0.00, 1.00), (57.50, .19, 2.00), (96.00, .96, 3.00), (135.00, 2.12, 4.00), (192.00, 3.65, 5.00), ('inf', 6.54, 5.75)),
'semi-monthly': ((21.00, 0.00, 1.00), (62.50, .21, 2.00), (104.00, 1.04, 3.00), (146.00, 2.29, 4.00), (208.00, 3.96, 5.00), ('inf', 7.08, 5.75)),
'monthly': ((41.50, 0.00, 1.00), (125.50, .42, 2.00), (208.00, 2.08, 3.00), (292.00, 4.58, 4.00), (417.00, 7.92, 5.00), ('inf', 14.17, 5.75)),
'quarterly': ((125.00, 0.00, 1.00), (375.00, 1.25, 2.00), (625.00, 6.25, 3.00), (875.00, 13.75, 4.00), (1250.00, 23.75, 5.00), ('inf', 42.50, 5.75)),
'semi-annual': ((250.00, 0.00, 1.00), (750.00, 2.50, 2.00), (1250.00, 12.50, 3.00), (1750.00, 27.50, 4.00), (2500.00, 47.50, 5.00), ('inf', 85.00, 5.75)),
'annual': ((500.00, 0.00, 1.00), (1500.00, 5.00, 2.00), (2500.00, 25.00, 3.00), (3500.00, 55.00, 4.00), (5000.00, 95.00, 5.00), ('inf', 170.00, 5.75)),
},
'married filing joint, one spouse working': {
'weekly': ((19.00, 0.00, 1.00), (57.50, .19, 2.00), (96.00, .96, 3.00), (135.00, 2.12, 4.00), (192.50, 3.65, 5.00), ('inf', 6.54, 5.75)),
'bi-weekly': ((38.50, 0.00, 1.00), (115.00, .38, 2.00), (192.00, 1.92, 3.00), (269.00, 4.23, 4.00), (385.00, 7.31, 5.00), ('inf', 13.08, 5.75)),
'semi-monthly': ((41.50, 0.00, 1.00), (125.00, .42, 2.00), (208.00, 2.08, 3.00), (292.00, 4.58, 4.00), (417.00, 7.92, 5.00), ('inf', 14.17, 5.75)),
'monthly': ((83.00, 0.00, 1.00), (250.00, .83, 2.00), (417.00, 4.17, 3.00), (583.00, 9.17, 4.00), (833.00, 15.83, 5.00), ('inf', 28.33, 5.75)),
'quarterly': ((250.00, 0.00, 1.00), (750.00, 2.50, 2.00), (1250.00, 12.50, 3.00), (1750.00, 27.50, 4.00), (2500.00, 47.50, 5.00), ('inf', 85.00, 5.75)),
'semi-annual': ((500.00, 0.00, 1.00), (1500.00, 5.00, 2.00), (2500.00, 25.00, 3.00), (3500.00, 55.00, 4.00), (5000.00, 95.00, 5.00), ('inf', 170.00, 5.75)),
'annual': ((1000.00, 0.00, 1.00), (3000.00, 10.00, 2.00), (5000.00, 50.00, 3.00), (7000.00, 110.00, 4.00), (10000.00, 190.00, 5.00), ('inf', 340.00, 5.75)),
},
'single': {
'weekly': ((14.50, 0.00, 1.00), (43.50, .14, 2.00), (72.00, .72, 3.00), (101.00, 1.59, 4.00), (135.00, 2.74, 5.00), ('inf', 4.42, 5.75)),
'bi-weekly': ((29.00, 0.00, 1.00), (86.50, .29, 2.00), (144.00, 1.44, 3.00), (202.00, 3.17, 4.00), (269.00, 5.48, 5.00), ('inf', 8.85, 5.75)),
'semi-monthly': ((31.00, 0.00, 1.00), (93.50, .31, 2.00), (156.00, 1.56, 3.00), (219.00, 3.34, 4.00), (292.00, 5.94, 5.00), ('inf', 9.58, 5.75)),
'monthly': ((62.50, 0.00, 1.00), (187.00, .62, 2.00), (312.00, 3.12, 3.00), (437.00, 6.87, 4.00), (583.00, 11.87, 5.00), ('inf', 19.17, 5.75)),
'quarterly': ((187.50, 0.00, 1.00), (562.50, 1.88, 2.00), (937.50, 9.38, 3.00), (1312.00, 20.63, 4.00), (1750.00, 35.63, 5.00), ('inf', 57.50, 5.75)),
'semi-annual': ((375.00, 0.00, 1.00), (1125.00, 3.75, 2.00), (1875.00, 18.75, 3.00), (2625.00, 41.25, 4.00), (3500.00, 71.25, 5.00), ('inf', 115.00, 5.75)),
'annual': ((750.00, 0.00, 1.00), (2250.00, 7.50, 2.00), (3750.00, 37.50, 3.00), (5250.00, 82.50, 4.00), (7000.00, 142.50, 5.00), ('inf', 230.00, 5.75)),
},
'head of household': {
'weekly': ((19.00, 0.00, 1.00), (57.50, .19, 2.00), (96.00, .96, 3.00), (135.00, 2.12, 4.00), (192.50, 3.65, 5.00), ('inf', 6.54, 5.75)),
'bi-weekly': ((38.50, 0.00, 1.00), (115.00, .38, 2.00), (192.00, 1.92, 3.00), (269.00, 4.23, 4.00), (385.00, 7.31, 5.00), ('inf', 13.08, 5.75)),
'semi-monthly': ((41.50, 0.00, 1.00), (125.00, .42, 2.00), (208.00, 2.08, 3.00), (292.00, 4.58, 4.00), (417.00, 7.92, 5.00), ('inf', 14.17, 5.75)),
'monthly': ((83.00, 0.00, 1.00), (250.00, .83, 2.00), (417.00, 4.17, 3.00), (583.00, 9.17, 4.00), (833.00, 15.83, 5.00), ('inf', 28.33, 5.75)),
'quarterly': ((250.00, 0.00, 1.00), (750.00, 2.50, 2.00), (1250.00, 12.50, 3.00), (1750.00, 27.50, 4.00), (2500.00, 47.50, 5.00), ('inf', 85.00, 5.75)),
'semi-annual': ((500.00, 0.00, 1.00), (1500.00, 5.00, 2.00), (2500.00, 25.00, 3.00), (3500.00, 55.00, 4.00), (5000.00, 95.00, 5.00), ('inf', 170.00, 5.75)),
'annual': ((1000.00, 0.00, 1.00), (3000.00, 10.00, 2.00), (5000.00, 50.00, 3.00), (7000.00, 110.00, 4.00), (10000.00, 190.00, 5.00), ('inf', 340.00, 5.75)),
},
'married filing separate': {
'weekly': ((9.50, 0.00, 1.00), (29.00, .10, 2.00), (48.00, .48, 3.00), (67.50, 1.06, 4.00), (96.00, 1.83, 5.00), ('inf', 3.27, 5.75)),
'bi-weekly': ((19.00, 0.00, 1.00), (57.50, .19, 2.00), (96.00, .96, 3.00), (135.00, 2.12, 4.00), (192.00, 3.65, 5.00), ('inf', 6.54, 5.75)),
'semi-monthly': ((21.00, 0.00, 1.00), (62.50, .21, 2.00), (104.00, 1.04, 3.00), (146.00, 2.29, 4.00), (208.00, 3.96, 5.00), ('inf', 7.08, 5.75)),
'monthly': ((41.50, 0.00, 1.00), (125.50, .42, 2.00), (208.00, 2.08, 3.00), (292.00, 4.58, 4.00), (417.00, 7.92, 5.00), ('inf', 14.17, 5.75)),
'quarterly': ((125.00, 0.00, 1.00), (375.00, 1.25, 2.00), (625.00, 6.25, 3.00), (875.00, 13.75, 4.00), (1250.00, 23.75, 5.00), ('inf', 42.50, 5.75)),
'semi-annual': ((250.00, 0.00, 1.00), (750.00, 2.50, 2.00), (1250.00, 12.50, 3.00), (1750.00, 27.50, 4.00), (2500.00, 47.50, 5.00), ('inf', 85.00, 5.75)),
'annual': ((500.00, 0.00, 1.00), (1500.00, 5.00, 2.00), (2500.00, 25.00, 3.00), (3500.00, 55.00, 4.00), (5000.00, 95.00, 5.00), ('inf', 170.00, 5.75)),
},
}</field>
<field name="rule_parameter_id" ref="rule_parameter_us_ga_sit_rate"/>
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
</record>
</data>
<record id="rule_parameter_us_ga_sit_personal_allowance" model="hr.rule.parameter">
<field name="name">US GA Georgia SIT Personal Allowance</field>
<field name="code">us_ga_sit_personal_allowance</field>
<field name="country_id" ref="base.us"/>
</record>
<data noupdate="1">
<record id="rule_parameter_us_ga_sit_personal_allowance_2019" model="hr.rule.parameter.value">
<field name="parameter_value">{
'married filing joint, both spouses working': {
'weekly': 142.30,
'bi-weekly': 284.62,
'semi-monthly': 308.33,
'monthly': 616.67,
'quarterly': 1850.00,
'semi-annual': 3700.00,
'annual': 7400.00,
},
'married filing joint, one spouse working': {
'weekly': 142.30,
'bi-weekly': 284.62,
'semi-monthly': 308.33,
'monthly': 616.67,
'quarterly': 1850.00,
'semi-annual': 3700.00,
'annual': 7400.00,
},
'single': {
'weekly': 51.92,
'bi-weekly': 103.85,
'semi-monthly': 112.50,
'monthly': 225.00,
'quarterly': 675.00,
'semi-annual': 1350.00,
'annual': 2700.00,
},
'head of household': {
'weekly': 51.92,
'bi-weekly': 103.85,
'semi-monthly': 112.50,
'monthly': 225.00,
'quarterly': 675.00,
'semi-annual': 1350.00,
'annual': 2700.00,
},
'married filing separate': {
'weekly': 71.15,
'bi-weekly': 142.30,
'semi-monthly': 154.16,
'monthly': 308.33,
'quarterly': 925.00,
'semi-annual': 1850.00,
'annual': 3700.00,
},
}</field>
<field name="rule_parameter_id" ref="rule_parameter_us_ga_sit_personal_allowance"/>
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
</record>
</data>
<record id="rule_parameter_us_ga_sit_dependent_allowance_rate" model="hr.rule.parameter">
<field name="name">US GA Georgia SIT Dependent Allowance Rate</field>
<field name="code">us_ga_sit_dependent_allowance_rate</field>
<field name="country_id" ref="base.us"/>
</record>
<data noupdate="1">
<record id="rule_parameter_us_ga_sit_dependent_allowance_rate_2019" model="hr.rule.parameter.value">
<field name="parameter_value">{
'weekly': 57.50,
'bi-weekly': 115.00,
'semi-monthly': 125.00,
'monthly': 250.00,
'quarterly': 750.00,
'semi-annual': 1500.00,
'annual': 3000.00,
}</field>
<field name="rule_parameter_id" ref="rule_parameter_us_ga_sit_dependent_allowance_rate"/>
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
</record>
</data>
<record id="rule_parameter_us_ga_sit_deduction" model="hr.rule.parameter">
<field name="name">US GA Georgia SIT Deduction</field>
<field name="code">us_ga_sit_deduction</field>
<field name="country_id" ref="base.us"/>
</record>
<data noupdate="1">
<record id="rule_parameter_us_ga_sit_deduction_2019" model="hr.rule.parameter.value">
<field name="parameter_value">{
'married filing joint, both spouses working': {
'weekly': 115.50,
'bi-weekly': 230.75,
'semi-monthly': 250.00,
'monthly': 500.00,
'quarterly': 1500.00,
'semi-annual': 3000.00,
'annual': 6000.00,
},
'married filing joint, one spouse working': {
'weekly': 115.50,
'bi-weekly': 230.75,
'semi-monthly': 250.00,
'monthly': 500.00,
'quarterly': 1500.00,
'semi-annual': 3000.00,
'annual': 6000.00,
},
'single': {
'weekly': 88.50,
'bi-weekly': 177.00,
'semi-monthly': 191.75,
'monthly': 383.50,
'quarterly': 1150.00,
'semi-annual': 2300.00,
'annual': 4600.00,
},
'head of household': {
'weekly': 88.50,
'bi-weekly': 177.00,
'semi-monthly': 191.75,
'monthly': 383.50,
'quarterly': 1150.00,
'semi-annual': 2300.00,
'annual': 4600.00,
},
'married filing separate': {
'weekly': 57.75,
'bi-weekly': 115.50,
'semi-monthly': 125.00,
'monthly': 250.00,
'quarterly': 750.00,
'semi-annual': 1500.00,
'annual': 3000.00,
},
}</field>
<field name="rule_parameter_id" ref="rule_parameter_us_ga_sit_deduction"/>
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
</record>
</data>
<!-- Partners and Contribution Registers -->
<record id="res_partner_us_ga_dor" model="res.partner">
<field name="name">US Georgia - Department of Taxation - Unemployment Tax</field>
</record>
<record id="res_partner_us_ga_dor_sit" model="res.partner">
<field name="name">US Georgia - Department of Taxation - Income Tax</field>
</record>
<!-- Categories -->
<!-- Rules -->
<record id="hr_payroll_rule_er_us_ga_suta" model="hr.salary.rule">
<field name="sequence" eval="450"/>
<field name="struct_id" ref="hr_payroll_structure"/>
<field name="category_id" ref="hr_payroll_category_er_us_suta"/>
<field name="name">ER: US GA Georgia State Unemployment</field>
<field name="code">ER_US_GA_SUTA</field>
<field name="condition_select">python</field>
<field name="condition_python">result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ga_suta_wage_base', rate='us_ga_suta_rate', state_code='GA')</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ga_suta_wage_base', rate='us_ga_suta_rate', state_code='GA')</field>
<field name="partner_id" ref="res_partner_us_ga_dor"/>
<field name="appears_on_payslip" eval="False"/>
</record>
<record id="hr_payroll_rule_ee_us_ga_sit" model="hr.salary.rule">
<field name="sequence" eval="195"/>
<field name="struct_id" ref="hr_payroll_structure"/>
<field name="category_id" ref="hr_payroll_category_ee_us_sit"/>
<field name="name">EE: US GA Georgia State Income Tax Withholding</field>
<field name="code">EE_US_GA_SIT</field>
<field name="condition_select">python</field>
<field name="condition_python">result, _ = ga_georgia_state_income_withholding(payslip, categories, worked_days, inputs)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result, result_rate = ga_georgia_state_income_withholding(payslip, categories, worked_days, inputs)</field>
<field name="partner_id" ref="res_partner_us_ga_dor_sit"/>
<field name="appears_on_payslip" eval="True"/>
</record>
</odoo>

View File

@@ -12,6 +12,7 @@ from .federal.fed_941 import ee_us_941_fica_ss, \
from .state.general import general_state_unemployment, \
general_state_income_withholding, \
is_us_state
from .state.ga_georgia import ga_georgia_state_income_withholding
from .state.mt_montana import mt_montana_state_income_withholding
from .state.oh_ohio import oh_ohio_state_income_withholding
from .state.va_virginia import va_virginia_state_income_withholding
@@ -48,6 +49,7 @@ class HRPayslip(models.Model):
'general_state_unemployment': general_state_unemployment,
'general_state_income_withholding': general_state_income_withholding,
'is_us_state': is_us_state,
'ga_georgia_state_income_withholding': ga_georgia_state_income_withholding,
'mt_montana_state_income_withholding': mt_montana_state_income_withholding,
'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding,
'va_virginia_state_income_withholding': va_virginia_state_income_withholding,

View File

@@ -0,0 +1,52 @@
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
from .general import _state_applies
def ga_georgia_state_income_withholding(payslip, categories, worked_days, inputs):
"""
Returns SIT eligible wage and rate.
WAGE = GROSS - WAGE_US_941_FIT_EXEMPT
:return: result, result_rate (wage, percent)
"""
state_code = 'GA'
if not _state_applies(payslip, state_code):
return 0.0, 0.0
ga_filing_status = payslip.contract_id.us_payroll_config_value('ga_g4_sit_filing_status')
if not ga_filing_status or ga_filing_status == 'exempt':
return 0.0, 0.0
# Determine Wage
wage = categories.GROSS - categories.WAGE_US_941_FIT_EXEMPT
schedule_pay = payslip.contract_id.schedule_pay
additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding')
dependent_allowances = payslip.contract_id.us_payroll_config_value('ga_g4_sit_dependent_allowances')
additional_allowances = payslip.contract_id.us_payroll_config_value('ga_g4_sit_additional_allowances')
dependent_allowance_rate = payslip.rule_parameter('us_ga_sit_dependent_allowance_rate').get(schedule_pay)
personal_allowance = payslip.rule_parameter('us_ga_sit_personal_allowance').get(ga_filing_status, {}).get(schedule_pay)
deduction = payslip.rule_parameter('us_ga_sit_deduction').get(ga_filing_status, {}).get(schedule_pay)
withholding_rate = payslip.rule_parameter('us_ga_sit_rate').get(ga_filing_status, {}).get(schedule_pay)
if not all((dependent_allowance_rate, personal_allowance, deduction, withholding_rate)) or wage == 0.0:
return 0.0, 0.0
if wage == 0.0:
return 0.0, 0.0
after_standard_deduction = wage - deduction
allowances = dependent_allowances + additional_allowances
working_wages = after_standard_deduction - (personal_allowance + (allowances * dependent_allowance_rate))
withholding = 0.0
if working_wages > 0.0:
prior_row_base = 0.0
for row in withholding_rate:
wage_base, base, rate = row
wage_base = float(wage_base)
if working_wages < wage_base:
withholding = base + ((working_wages - prior_row_base) * rate / 100.0)
break
prior_row_base = wage_base
withholding += additional
return wage, -((withholding / wage) * 100.0)

View File

@@ -51,6 +51,19 @@ class HRContractUSPayrollConfig(models.Model):
fed_941_fit_w4_additional_withholding = fields.Float(string='Federal W4 Additional Withholding [4(c)]',
help='Form W4 (2020+) 4(c)')
ga_g4_sit_filing_status = fields.Selection([
('exempt', 'Exempt'),
('single', 'Single'),
('married filing joint, both spouses working', 'Married Filing Joint, both spouses working'),
('married filing joint, one spouse working', 'Married Filing Joint, one spouse working'),
('married filing separate', 'Married Filing Separate'),
('head of household', 'Head of Household'),
], string='Georgia G-4 Filing Status', help='G-4 3.')
ga_g4_sit_dependent_allowances = fields.Integer(string='Georgia G-4 Dependent Allowances',
help='G-4 4.')
ga_g4_sit_additional_allowances = fields.Integer(string='Georgia G-4 Additional Allowances',
help='G-4 5.')
mt_mw4_sit_exemptions = fields.Integer(string='Montana MW-4 Exemptions',
help='MW-4 Box G')
# Don't use the main state_income_tax_exempt because of special meaning and reporting

View File

@@ -7,6 +7,9 @@ from . import test_us_payslip_2020
from . import test_us_fl_florida_payslip_2019
from . import test_us_fl_florida_payslip_2020
from . import test_us_ga_georgia_payslip_2019
from . import test_us_ga_georgia_payslip_2020
from . import test_us_mt_montana_payslip_2019
from . import test_us_mt_montana_payslip_2020

View File

@@ -0,0 +1,135 @@
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
from .common import TestUsPayslip, process_payslip
class TestUsGAPayslip(TestUsPayslip):
# TAXES AND RATES
GA_UNEMP_MAX_WAGE = 9500.00
GA_UNEMP = -(2.70 / 100.0)
def test_taxes_weekly_single_with_additional_wh(self):
salary = 15000.00
schedule_pay = 'weekly'
allowances = 1
filing_status = 'single'
additional_wh = 12.50
# Hand Calculated Amount to Test
# Step 1 - Subtract standard deduction from wages. Std Deduct for single weekly is 88.50
# step1 = 15000.00 - 88.50 = 14911.5
# Step 2 - Subtract personal allowance from step1. Allowance for single weekly is 51.92
# step2 = step1 - 51.92 = 14859.58
# Step 3 - Subtract amount for dependents. Weekly dependent allowance is 57.50
# step3 = 14859.58 - 57.50 = 14802.08
# Step 4 -Determine wh amount from tables
# step4 = 4.42 + ((5.75 / 100.00) * (14802.08 - 135.00))
# Add additional_wh
# wh = 847.7771 + 12.50 = 860.2771
wh = -860.28
employee = self._createEmployee()
contract = self._createContract(employee,
wage=salary,
state_id=self.get_us_state('GA'),
ga_g4_sit_dependent_allowances=allowances,
ga_g4_sit_additional_allowances=0,
ga_g4_sit_filing_status=filing_status,
state_income_tax_additional_withholding=additional_wh,
schedule_pay=schedule_pay)
self.assertEqual(contract.schedule_pay, 'weekly')
self._log('2019 Georgia tax first payslip weekly:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['ER_US_SUTA'], self.GA_UNEMP_MAX_WAGE * self.GA_UNEMP)
self.assertPayrollEqual(cats['EE_US_SIT'], wh)
process_payslip(payslip)
remaining_GA_UNEMP_wages = 0.0 # We already reached max unemployment wages.
self._log('2019 Georgia tax second payslip weekly:')
payslip = self._createPayslip(employee, '2019-02-01', '2019-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['ER_US_SUTA'], remaining_GA_UNEMP_wages * self.GA_UNEMP)
def test_taxes_monthly_head_of_household(self):
salary = 25000.00
schedule_pay = 'monthly'
allowances = 2
filing_status = 'head of household'
additional_wh = 15.00
# Hand Calculated Amount to Test
# Step 1 - Subtract standard deduction from wages. Std Deduct for head of household monthly is 383.50
# step1 = 25000.00 - 383.50 = 24616.5
# Step 2 - Subtract personal allowance from step1. Allowance for head of household monthly is 225.00
# step2 = 24616.5 - 225.00 = 24391.5
# Step 3 - Subtract amount for dependents. Weekly dependent allowance is 250.00
# step3 = 24391.5 - (2 * 250.00) = 23891.5
# Step 4 - Determine wh amount from tables
# step4 = 28.33 + ((5.75 / 100.00) * (23891.5 - 833.00)) = 1354.19375
# Add additional_wh
# wh = 1354.19375 + 15.00 = 1369.19375
wh = -1369.19
employee = self._createEmployee()
contract = self._createContract(employee,
wage=salary,
state_id=self.get_us_state('GA'),
ga_g4_sit_dependent_allowances=allowances,
ga_g4_sit_additional_allowances=0,
ga_g4_sit_filing_status=filing_status,
state_income_tax_additional_withholding=additional_wh,
schedule_pay=schedule_pay)
self.assertEqual(contract.schedule_pay, 'monthly')
self._log('2019 Georgia tax first payslip monthly:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['ER_US_SUTA'], self.GA_UNEMP_MAX_WAGE * self.GA_UNEMP)
self.assertPayrollAlmostEqual(cats['EE_US_SIT'], wh)
process_payslip(payslip)
remaining_GA_UNEMP_wages = 0.0 # We already reached max unemployment wages.
self._log('2019 Georgia tax second payslip weekly:')
payslip = self._createPayslip(employee, '2019-02-01', '2019-02-28')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats['ER_US_SUTA'], remaining_GA_UNEMP_wages * self.GA_UNEMP)
def test_taxes_exempt(self):
salary = 25000.00
schedule_pay = 'monthly'
allowances = 2
filing_status = 'exempt'
additional_wh = 15.00
employee = self._createEmployee()
contract = self._createContract(employee,
wage=salary,
state_id=self.get_us_state('GA'),
ga_g4_sit_dependent_allowances=allowances,
ga_g4_sit_additional_allowances=0,
ga_g4_sit_filing_status=filing_status,
state_income_tax_additional_withholding=additional_wh,
schedule_pay=schedule_pay)
self._log('2019 Georgia tax first payslip exempt:')
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
self.assertPayrollEqual(cats.get('EE_US_SIT', 0), 0)

View File

@@ -0,0 +1,148 @@
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
from datetime import date
from .common import TestUsPayslip, process_payslip
class TestUsGAPayslip(TestUsPayslip):
# TAXES AND RATES
GA_UNEMP_MAX_WAGE = 9500.00
GA_UNEMP = 2.70
def _run_test_sit(self,
wage=0.0,
schedule_pay='monthly',
filing_status='single',
dependent_credit=0.0,
other_income=0.0,
deductions=0.0,
additional_withholding=0.0,
is_nonresident_alien=False,
state_income_tax_exempt=False,
state_income_tax_additional_withholding=0.0,
ga_g4_sit_dependent_allowances=0,
ga_g4_sit_additional_allowances=0,
ga_g4_sit_filing_status=None,
expected=0.0,
):
employee = self._createEmployee()
contract = self._createContract(employee,
wage=wage,
schedule_pay=schedule_pay,
fed_941_fit_w4_is_nonresident_alien=is_nonresident_alien,
fed_941_fit_w4_filing_status=filing_status,
fed_941_fit_w4_multiple_jobs_higher=False,
fed_941_fit_w4_dependent_credit=dependent_credit,
fed_941_fit_w4_other_income=other_income,
fed_941_fit_w4_deductions=deductions,
fed_941_fit_w4_additional_withholding=additional_withholding,
state_income_tax_exempt=state_income_tax_exempt,
state_income_tax_additional_withholding=state_income_tax_additional_withholding,
ga_g4_sit_dependent_allowances=ga_g4_sit_dependent_allowances,
ga_g4_sit_additional_allowances=ga_g4_sit_additional_allowances,
ga_g4_sit_filing_status=ga_g4_sit_filing_status,
state_id=self.get_us_state('GA'),
)
payslip = self._createPayslip(employee, '2020-01-01', '2020-01-31')
payslip.compute_sheet()
cats = self._getCategories(payslip)
# Instead of PayrollEqual after initial first round of testing.
self.assertPayrollAlmostEqual(cats.get('EE_US_SIT', 0.0), -expected)
return payslip
def test_taxes_weekly_single_with_additional_wh(self):
self._test_er_suta('GA', self.GA_UNEMP, date(2020, 1, 1), wage_base=self.GA_UNEMP_MAX_WAGE)
salary = 15000.00
schedule_pay = 'weekly'
allowances = 1
filing_status = 'single'
additional_wh = 12.50
# Hand Calculated Amount to Test
# Step 1 - Subtract standard deduction from wages. Std Deduct for single weekly is 88.50
# step1 = 15000.00 - 88.50 = 14911.5
# Step 2 - Subtract personal allowance from step1. Allowance for single weekly is 51.92
# step2 = step1 - 51.92 = 14859.58
# Step 3 - Subtract amount for dependents. Weekly dependent allowance is 57.50
# step3 = 14859.58 - 57.50 = 14802.08
# Step 4 -Determine wh amount from tables
# step4 = 4.42 + ((5.75 / 100.00) * (14802.08 - 135.00))
# Add additional_wh
# wh = 847.7771 + 12.50 = 860.2771
wh = 860.28
self._run_test_sit(wage=salary,
schedule_pay=schedule_pay,
state_income_tax_additional_withholding=additional_wh,
ga_g4_sit_dependent_allowances=allowances,
ga_g4_sit_additional_allowances=0,
ga_g4_sit_filing_status=filing_status,
expected=wh,
)
def test_taxes_monthly_head_of_household(self):
salary = 25000.00
schedule_pay = 'monthly'
allowances = 2
filing_status = 'head of household'
additional_wh = 15.00
# Hand Calculated Amount to Test
# Step 1 - Subtract standard deduction from wages. Std Deduct for head of household monthly is 383.50
# step1 = 25000.00 - 383.50 = 24616.5
# Step 2 - Subtract personal allowance from step1. Allowance for head of household monthly is 225.00
# step2 = 24616.5 - 225.00 = 24391.5
# Step 3 - Subtract amount for dependents. Weekly dependent allowance is 250.00
# step3 = 24391.5 - (2 * 250.00) = 23891.5
# Step 4 - Determine wh amount from tables
# step4 = 28.33 + ((5.75 / 100.00) * (23891.5 - 833.00)) = 1354.19375
# Add additional_wh
# wh = 1354.19375 + 15.00 = 1369.19375
wh = 1369.19
self._run_test_sit(wage=salary,
schedule_pay=schedule_pay,
state_income_tax_additional_withholding=additional_wh,
ga_g4_sit_dependent_allowances=allowances,
ga_g4_sit_additional_allowances=0,
ga_g4_sit_filing_status=filing_status,
expected=wh,
)
# additional from external calculator
self._run_test_sit(wage=425.0,
schedule_pay='weekly',
state_income_tax_additional_withholding=0.0,
ga_g4_sit_dependent_allowances=1,
ga_g4_sit_additional_allowances=0,
ga_g4_sit_filing_status='married filing separate',
expected=11.45,
)
self._run_test_sit(wage=3000.0,
schedule_pay='quarterly',
state_income_tax_additional_withholding=0.0,
ga_g4_sit_dependent_allowances=1,
ga_g4_sit_additional_allowances=1,
ga_g4_sit_filing_status='single',
expected=0.0,
)
# TODO 'married filing joint, both spouses working' returns lower than calculator
# TODO 'married filing joint, one spouse working' returns lower than calculator
def test_taxes_exempt(self):
salary = 25000.00
schedule_pay = 'monthly'
allowances = 2
filing_status = 'exempt'
additional_wh = 15.00
self._run_test_sit(wage=salary,
schedule_pay=schedule_pay,
state_income_tax_additional_withholding=additional_wh,
ga_g4_sit_dependent_allowances=allowances,
ga_g4_sit_additional_allowances=0,
ga_g4_sit_filing_status=filing_status,
expected=0.0,
)

View File

@@ -47,6 +47,14 @@
<group name="state_fl_florida" string="FL Florida" attrs="{'invisible':[('state_id', '!=', %(base.state_us_10)s)]}">
<p colspan="2"><h3>No additional fields.</h3></p>
</group>
<group name="state_ga_georgia" string="GA Georgia" attrs="{'invisible':[('state_id', '!=', %(base.state_us_11)s)]}">
<p colspan="2"><h3>Form G-4 - State Income Tax</h3></p>
<field name="ga_g4_sit_filing_status" string="Marital Status 3."/>
<field name="ga_g4_sit_dependent_allowances" string="Dependent Allowances 4."/>
<field name="ga_g4_sit_additional_allowances" string="Additional Allowances 5."/>
<field name="state_income_tax_additional_withholding" string="Additional Withholding 6."/>
<field name="state_income_tax_exempt" string="Exempt 8."/>
</group>
<group name="state_mt_montana" string="MT Montana" attrs="{'invisible':[('state_id', '!=', %(base.state_us_21)s)]}">
<p colspan="2"><h3>Form MT-4 - State Income Tax</h3></p>
<field name="mt_mw4_sit_exempt" string="Exempt"/>