mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
IMP l10n_us_hr_payroll Port l10n_us_mt_hr_payroll MT Montana including migration.
This commit is contained in:
@@ -29,6 +29,7 @@ USA Payroll Rules.
|
||||
'data/federal/fed_941_fit_parameters.xml',
|
||||
'data/federal/fed_941_fit_rules.xml',
|
||||
'data/state/fl_florida.xml',
|
||||
'data/state/mt_montana.xml',
|
||||
'data/state/pa_pennsylvania.xml',
|
||||
'data/final.xml',
|
||||
'views/hr_contract_views.xml',
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
ref('hr_payroll_rule_ee_fed_941_fit'),
|
||||
|
||||
ref('hr_payroll_rule_er_us_fl_suta'),
|
||||
ref('hr_payroll_rule_er_us_mt_suta'),
|
||||
ref('hr_payroll_rule_er_us_mt_suta_aft'),
|
||||
ref('hr_payroll_rule_ee_us_mt_sit'),
|
||||
ref('hr_payroll_rule_er_us_pa_suta'),
|
||||
ref('hr_payroll_rule_ee_us_pa_suta'),
|
||||
ref('hr_payroll_rule_ee_us_pa_sit'),
|
||||
|
||||
166
l10n_us_hr_payroll/data/state/mt_montana.xml
Normal file
166
l10n_us_hr_payroll/data/state/mt_montana.xml
Normal file
@@ -0,0 +1,166 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<!-- Wage Base -->
|
||||
<data noupdate="1">
|
||||
<record id="rule_parameter_us_mt_suta_wage_base_2019" model="hr.payroll.rate">
|
||||
<field name="name">US MT Montana SUTA Wage Base</field>
|
||||
<field name="code">us_mt_suta_wage_base</field>
|
||||
<field name="parameter_value">33000.00</field>
|
||||
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
|
||||
</record>
|
||||
<record id="rule_parameter_us_mt_suta_wage_base_2020" model="hr.payroll.rate">
|
||||
<field name="name">US MT Montana SUTA Wage Base</field>
|
||||
<field name="code">us_mt_suta_wage_base</field>
|
||||
<field name="parameter_value">34100.00</field>
|
||||
<field name="date_from" eval="datetime(2020, 1, 1).date()"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<!-- Rate -->
|
||||
<data noupdate="1">
|
||||
<record id="rule_parameter_us_mt_suta_rate_2019" model="hr.payroll.rate">
|
||||
<field name="name">US MT Montana SUTA Rate (UI)</field>
|
||||
<field name="code">us_mt_suta_rate</field>
|
||||
<field name="parameter_value">1.18</field>
|
||||
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
|
||||
</record>
|
||||
<record id="rule_parameter_us_mt_suta_rate_2020" model="hr.payroll.rate">
|
||||
<field name="name">US MT Montana SUTA Rate (UI)</field>
|
||||
<field name="code">us_mt_suta_rate</field>
|
||||
<field name="parameter_value">1.18</field>
|
||||
<field name="date_from" eval="datetime(2020, 1, 1).date()"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<data noupdate="1">
|
||||
<record id="rule_parameter_us_mt_suta_aft_rate_2019" model="hr.payroll.rate">
|
||||
<field name="name">US MT Montana SUTA Administrative Fund Tax Rate</field>
|
||||
<field name="code">us_mt_suta_aft_rate</field>
|
||||
<field name="parameter_value">0.13</field>
|
||||
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
|
||||
</record>
|
||||
<record id="rule_parameter_us_mt_suta_aft_rate_2020" model="hr.payroll.rate">
|
||||
<field name="name">US MT Montana SUTA Administrative Fund Tax Rate</field>
|
||||
<field name="code">us_mt_suta_aft_rate</field>
|
||||
<field name="parameter_value">0.13</field>
|
||||
<field name="date_from" eval="datetime(2020, 1, 1).date()"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<data noupdate="1">
|
||||
<record id="rule_parameter_us_mt_sit_rate_2019" model="hr.payroll.rate">
|
||||
<field name="name">US MT Montana SIT Rate Table</field>
|
||||
<field name="code">us_mt_suta_sit_rate</field>
|
||||
<field name="parameter_value">{
|
||||
'weekly': [
|
||||
( 135.00, 0.0, 1.80),
|
||||
( 288.00, 2.0, 4.40),
|
||||
( 2308.00, 9.0, 6.00),
|
||||
( 'inf', 130.0, 6.60),
|
||||
],
|
||||
'bi-weekly': [
|
||||
( 269.00, 0.0, 1.80),
|
||||
( 577.00, 5.0, 4.40),
|
||||
( 4615.00, 18.0, 6.00),
|
||||
( 'inf', 261.0, 6.60),
|
||||
],
|
||||
'semi-monthly': [
|
||||
( 292.00, 0.0, 1.80),
|
||||
( 625.00, 5.0, 4.40),
|
||||
( 5000.00, 20.0, 6.00),
|
||||
( 'inf', 282.0, 6.60),
|
||||
],
|
||||
'monthly': [
|
||||
( 583.00, 0.0, 1.80),
|
||||
( 1250.00, 11.0, 4.40),
|
||||
( 10000.00, 40.0, 6.00),
|
||||
( 'inf', 565.0, 6.60),
|
||||
],
|
||||
'annually': [
|
||||
( 7000.00, 0.0, 1.80),
|
||||
( 15000.00, 126.0, 4.40),
|
||||
( 120000.00, 478.0, 6.00),
|
||||
( 'inf', 6778.0, 6.60),
|
||||
],
|
||||
}</field>
|
||||
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<data noupdate="1">
|
||||
<record id="rule_parameter_us_mt_sit_exemption_rate_2019" model="hr.payroll.rate">
|
||||
<field name="name">US MT Montana SIT Exemption Rate Table</field>
|
||||
<field name="code">us_mt_suta_sit_exemption_rate</field>
|
||||
<field name="parameter_value">{
|
||||
'weekly': 37.0,
|
||||
'bi-weekly': 73.0,
|
||||
'semi-monthly': 79.0,
|
||||
'monthly': 158.0,
|
||||
'annually': 1900.0,
|
||||
}</field>
|
||||
<field name="date_from" eval="datetime(2019, 1, 1).date()"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<!-- Partners and Contribution Registers -->
|
||||
<record id="res_partner_us_mt_dor" model="res.partner">
|
||||
<field name="name">US Montana - Department of Labor & Industries</field>
|
||||
</record>
|
||||
|
||||
<record id="contrib_register_us_mt_dor" model="hr.contribution.register">
|
||||
<field name="name">US Montana - Department of Labor & Industries</field>
|
||||
<field name="partner_id" ref="res_partner_us_mt_dor"/>
|
||||
</record>
|
||||
|
||||
<record id="res_partner_us_mt_dor_sit" model="res.partner">
|
||||
<field name="name">US Montana - Department of Revenue - Income Tax</field>
|
||||
</record>
|
||||
|
||||
<record id="contrib_register_us_mt_dor_sit" model="hr.contribution.register">
|
||||
<field name="name">US Montana - Department of Revenue - Income Tax</field>
|
||||
<field name="partner_id" ref="res_partner_us_mt_dor_sit"/>
|
||||
</record>
|
||||
|
||||
<!-- Categories -->
|
||||
|
||||
<!-- Rules -->
|
||||
<record id="hr_payroll_rule_er_us_mt_suta" model="hr.salary.rule">
|
||||
<field name="sequence" eval="450"/>
|
||||
<field name="category_id" ref="hr_payroll_category_er_us_suta"/>
|
||||
<field name="name">ER: US MT Montana State Unemployment (UI-5)</field>
|
||||
<field name="code">ER_US_MT_SUTA</field>
|
||||
<field name="condition_select">python</field>
|
||||
<field name="condition_python">result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_mt_suta_wage_base', rate='us_mt_suta_rate', state_code='MT')</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_mt_suta_wage_base', rate='us_mt_suta_rate', state_code='MT')</field>
|
||||
<field name="register_id" ref="contrib_register_us_mt_dor"/>
|
||||
<field name="appears_on_payslip" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_payroll_rule_er_us_mt_suta_aft" model="hr.salary.rule">
|
||||
<field name="sequence" eval="451"/>
|
||||
<field name="category_id" ref="hr_payroll_category_er_us_suta"/>
|
||||
<field name="name">ER: US MT Montana State Unemployment Administrative Fund Tax (AFT) (UI-5)</field>
|
||||
<field name="code">ER_US_MT_SUTA_AFT</field>
|
||||
<field name="condition_select">python</field>
|
||||
<field name="condition_python">result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_mt_suta_wage_base', rate='us_mt_suta_aft_rate', state_code='MT')</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_mt_suta_wage_base', rate='us_mt_suta_aft_rate', state_code='MT')</field>
|
||||
<field name="register_id" ref="contrib_register_us_mt_dor"/>
|
||||
<field name="appears_on_payslip" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_payroll_rule_ee_us_mt_sit" model="hr.salary.rule">
|
||||
<field name="sequence" eval="195"/>
|
||||
<field name="category_id" ref="hr_payroll_category_ee_us_sit"/>
|
||||
<field name="name">EE: US MT Montana State Income Tax Withholding (MW-3)</field>
|
||||
<field name="code">EE_US_MT_SIT</field>
|
||||
<field name="condition_select">python</field>
|
||||
<field name="condition_python">result, _ = mt_montana_state_income_withholding(payslip, categories, worked_days, inputs)</field>
|
||||
<field name="amount_select">code</field>
|
||||
<field name="amount_python_compute">result, result_rate = mt_montana_state_income_withholding(payslip, categories, worked_days, inputs)</field>
|
||||
<field name="register_id" ref="contrib_register_us_mt_dor_sit"/>
|
||||
<field name="appears_on_payslip" eval="True"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,6 +1,7 @@
|
||||
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.l10n_us_hr_payroll.migrations.data import FIELDS_CONTRACT_TO_US_PAYROLL_FORMS_2020
|
||||
from odoo.addons.l10n_us_hr_payroll.migrations.data import FIELDS_CONTRACT_TO_US_PAYROLL_FORMS_2020, \
|
||||
XMLIDS_COPY_ACCOUNTING_2020
|
||||
from odoo.addons.l10n_us_hr_payroll.migrations.helper import field_exists, \
|
||||
temp_field_exists, \
|
||||
remove_temp_field, \
|
||||
@@ -68,3 +69,17 @@ def migrate(cr, installed_version):
|
||||
|
||||
for field in fields_to_move:
|
||||
remove_temp_field(cr, 'hr_contract', field)
|
||||
|
||||
# Some added rules should have the same accounting side effects of other migrated rules
|
||||
# To ease the transition, we will copy the accounting fields from one to the other.
|
||||
for source, destinations in XMLIDS_COPY_ACCOUNTING_2020.items():
|
||||
source_rule = env.ref(source, raise_if_not_found=False)
|
||||
if source_rule:
|
||||
for destination in destinations:
|
||||
destination_rule = env.ref(destination, raise_if_not_found=False)
|
||||
if destination_rule:
|
||||
_logger.warn('Mirgrating accounting from rule: ' + source + ' to rule: ' + destination)
|
||||
destination_rule.write({
|
||||
'account_debit': source_rule.account_debit.id,
|
||||
'account_credit': source_rule.account_credit.id,
|
||||
})
|
||||
|
||||
@@ -9,6 +9,9 @@ FIELDS_CONTRACT_TO_US_PAYROLL_FORMS_2020 = {
|
||||
'fica_exempt': 'fed_941_fica_exempt',
|
||||
'futa_type': 'fed_940_type',
|
||||
# State
|
||||
'mt_mw4_additional_withholding': 'state_income_tax_additional_withholding',
|
||||
'mt_mw4_exemptions': 'mt_mw4_sit_exemptions',
|
||||
'mt_mw4_exempt': 'mt_mw4_sit_exempt',
|
||||
'pa_additional_withholding': 'state_income_tax_additional_withholding',
|
||||
}
|
||||
|
||||
@@ -32,6 +35,10 @@ XMLIDS_TO_REMOVE_2020 = [
|
||||
'l10n_us_fl_hr_payroll.hr_payroll_fl_unemp_wages',
|
||||
'l10n_us_fl_hr_payroll.hr_payroll_fl_unemp',
|
||||
'l10n_us_fl_hr_payroll.hr_payroll_rules_fl_unemp_wages_2018',
|
||||
'l10n_us_mt_hr_payroll.hr_payroll_mt_unemp_wages',
|
||||
'l10n_us_mt_hr_payroll.hr_payroll_mt_unemp',
|
||||
'l10n_us_mt_hr_payroll.hr_payroll_mt_income_withhold',
|
||||
'l10n_us_mt_hr_payroll.hr_payroll_rules_mt_unemp_wages',
|
||||
'l10n_us_pa_hr_payroll.res_partner_pador_unemp_employee',
|
||||
'l10n_us_pa_hr_payroll.contrib_register_pador_unemp_employee',
|
||||
'l10n_us_pa_hr_payroll.hr_payroll_pa_unemp_wages',
|
||||
@@ -59,6 +66,12 @@ XMLIDS_TO_RENAME_2020 = {
|
||||
'l10n_us_fl_hr_payroll.hr_payroll_rules_fl_unemp_2018': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_fl_suta',
|
||||
'l10n_us_fl_hr_payroll.res_partner_fldor': 'l10n_us_hr_payroll.res_partner_us_fl_dor',
|
||||
'l10n_us_fl_hr_payroll.contrib_register_fldor': 'l10n_us_hr_payroll.contrib_register_us_fl_dor',
|
||||
'l10n_us_mt_hr_payroll.res_partner_mtdor_unemp': 'l10n_us_hr_payroll.res_partner_us_mt_dor',
|
||||
'l10n_us_mt_hr_payroll.res_partner_mtdor_withhold': 'l10n_us_hr_payroll.res_partner_us_mt_dor_sit',
|
||||
'l10n_us_mt_hr_payroll.contrib_register_mtdor_unemp': 'l10n_us_hr_payroll.contrib_register_us_mt_dor',
|
||||
'l10n_us_mt_hr_payroll.contrib_register_mtdor_withhold': 'l10n_us_hr_payroll.contrib_register_us_mt_dor_sit',
|
||||
'l10n_us_mt_hr_payroll.hr_payroll_rules_mt_unemp': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_mt_suta',
|
||||
'l10n_us_mt_hr_payroll.hr_payroll_rules_mt_inc_withhold': 'l10n_us_hr_payroll.hr_payroll_rule_ee_us_mt_sit',
|
||||
'l10n_us_pa_hr_payroll.res_partner_pador_unemp_company': 'l10n_us_hr_payroll.res_partner_us_pa_dor',
|
||||
'l10n_us_pa_hr_payroll.res_partner_pador_withhold': 'l10n_us_hr_payroll.res_partner_us_pa_dor_sit',
|
||||
'l10n_us_pa_hr_payroll.contrib_register_pador_unemp_company': 'l10n_us_hr_payroll.contrib_register_us_pa_dor',
|
||||
@@ -66,4 +79,11 @@ XMLIDS_TO_RENAME_2020 = {
|
||||
'l10n_us_pa_hr_payroll.hr_payroll_rules_pa_unemp_employee_2018': 'l10n_us_hr_payroll.hr_payroll_rule_ee_us_pa_suta',
|
||||
'l10n_us_pa_hr_payroll.hr_payroll_rules_pa_unemp_company_2018': 'l10n_us_hr_payroll.hr_payroll_rule_er_us_pa_suta',
|
||||
'l10n_us_pa_hr_payroll.hr_payroll_rules_pa_inc_withhold_2018': 'l10n_us_hr_payroll.hr_payroll_rule_ee_us_pa_sit',
|
||||
|
||||
}
|
||||
|
||||
XMLIDS_COPY_ACCOUNTING_2020 = {
|
||||
'l10n_us_hr_payroll.hr_payroll_rule_er_us_mt_suta': [
|
||||
'l10n_us_hr_payroll.hr_payroll_rule_er_us_mt_suta_aft',
|
||||
],
|
||||
}
|
||||
|
||||
@@ -39,7 +39,12 @@ def temp_field_values(cr, table_name, id, field_names):
|
||||
values = cr.dictfetchone()
|
||||
if not values:
|
||||
return {}
|
||||
return {k.lstrip(TMP_PREFIX): v for k, v in values.items()}
|
||||
|
||||
def _remove_tmp_prefix(key):
|
||||
if key.startswith(TMP_PREFIX):
|
||||
return key[len(TMP_PREFIX):]
|
||||
return key
|
||||
return {_remove_tmp_prefix(k): v for k, v in values.items()}
|
||||
|
||||
|
||||
"""
|
||||
|
||||
@@ -11,6 +11,7 @@ from .federal.fed_941 import ee_us_941_fica_ss, \
|
||||
ee_us_941_fit
|
||||
from .state.general import general_state_unemployment, \
|
||||
general_state_income_withholding
|
||||
from .state.mt_montana import mt_montana_state_income_withholding
|
||||
|
||||
|
||||
class HRPayslip(models.Model):
|
||||
@@ -42,6 +43,7 @@ class HRPayslip(models.Model):
|
||||
'ee_us_941_fit': ee_us_941_fit,
|
||||
'general_state_unemployment': general_state_unemployment,
|
||||
'general_state_income_withholding': general_state_income_withholding,
|
||||
'mt_montana_state_income_withholding': mt_montana_state_income_withholding,
|
||||
}
|
||||
|
||||
def get_year(self):
|
||||
|
||||
@@ -96,7 +96,7 @@ def general_state_unemployment(payslip, categories, worked_days, inputs, wage_ba
|
||||
|
||||
def general_state_income_withholding(payslip, categories, worked_days, inputs, wage_base=None, wage_start=None, rate=None, state_code=None):
|
||||
"""
|
||||
Returns SUTA eligible wage and rate.
|
||||
Returns SIT eligible wage and rate.
|
||||
WAGE = GROSS - WAGE_US_941_FIT_EXEMPT
|
||||
|
||||
:return: result, result_rate (wage, percent)
|
||||
|
||||
41
l10n_us_hr_payroll/models/state/mt_montana.py
Normal file
41
l10n_us_hr_payroll/models/state/mt_montana.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from .general import _state_applies
|
||||
|
||||
|
||||
def mt_montana_state_income_withholding(payslip, categories, worked_days, inputs):
|
||||
#, wage_base = None, wage_start = None, rate = None, state_code = None
|
||||
"""
|
||||
Returns SIT eligible wage and rate.
|
||||
WAGE = GROSS - WAGE_US_941_FIT_EXEMPT
|
||||
|
||||
:return: result, result_rate (wage, percent)
|
||||
"""
|
||||
state_code = 'MT'
|
||||
if not _state_applies(payslip, state_code):
|
||||
return 0.0, 0.0
|
||||
|
||||
if payslip.dict.contract_id.us_payroll_config_value('mt_mw4_sit_exempt'):
|
||||
return 0.0, 0.0
|
||||
|
||||
# Determine Wage
|
||||
wage = categories.GROSS - categories.WAGE_US_941_FIT_EXEMPT
|
||||
schedule_pay = payslip.dict.contract_id.schedule_pay
|
||||
additional = payslip.dict.contract_id.us_payroll_config_value('state_income_tax_additional_withholding')
|
||||
exemptions = payslip.dict.contract_id.us_payroll_config_value('mt_mw4_sit_exemptions')
|
||||
exemption_rate = payslip.dict.rule_parameter('us_mt_suta_sit_exemption_rate').get(schedule_pay)
|
||||
withholding_rate = payslip.dict.rule_parameter('us_mt_suta_sit_rate').get(schedule_pay)
|
||||
if not exemption_rate or not withholding_rate or wage == 0.0:
|
||||
return 0.0, 0.0
|
||||
|
||||
adjusted_wage = wage - (exemption_rate * (exemptions or 0))
|
||||
withholding = 0.0
|
||||
if adjusted_wage > 0.0:
|
||||
prior_wage_cap = 0.0
|
||||
for row in withholding_rate:
|
||||
wage_cap, base, rate = row
|
||||
wage_cap = float(wage_cap) # e.g. 'inf'
|
||||
if adjusted_wage < wage_cap:
|
||||
withholding = round(base + ((rate / 100.0) * (adjusted_wage - prior_wage_cap)))
|
||||
break
|
||||
prior_wage_cap = wage_cap
|
||||
withholding += additional
|
||||
return wage, -((withholding / wage) * 100.0)
|
||||
@@ -46,3 +46,15 @@ class HRContractUSPayrollConfig(models.Model):
|
||||
help='Form W4 (2020+) 4(b)')
|
||||
fed_941_fit_w4_additional_withholding = fields.Float(string='Federal W4 Additional Withholding [4(c)]',
|
||||
help='Form W4 (2020+) 4(c)')
|
||||
|
||||
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
|
||||
# Use additional withholding but name it on the form 'MW-4 Box H'
|
||||
mt_mw4_sit_exempt = fields.Selection([
|
||||
('', 'Not Exempt'),
|
||||
('tribe', 'Registered Tribe'),
|
||||
('reserve', 'Reserve or National Guard'),
|
||||
('north_dakota', 'North Dakota'),
|
||||
('montana_for_marriage', 'Montana for Marriage'),
|
||||
], string='Montana MW-4 Exempt from Withholding', help='MW-4 Section 2')
|
||||
|
||||
@@ -6,5 +6,7 @@ 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_mt_montana_payslip_2019
|
||||
from . import test_us_mt_montana_payslip_2020
|
||||
from . import test_us_pa_pennsylvania_payslip_2019
|
||||
from . import test_us_pa_pennsylvania_payslip_2020
|
||||
|
||||
139
l10n_us_hr_payroll/tests/test_us_mt_montana_payslip_2019.py
Executable file
139
l10n_us_hr_payroll/tests/test_us_mt_montana_payslip_2019.py
Executable file
@@ -0,0 +1,139 @@
|
||||
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
||||
|
||||
from .common import TestUsPayslip, process_payslip
|
||||
|
||||
|
||||
class TestUsMtPayslip(TestUsPayslip):
|
||||
# Calculations from https://app.mt.gov/myrevenue/Endpoint/DownloadPdf?yearId=705
|
||||
MT_UNEMP = -1.18 / 100.0
|
||||
MT_UNEMP_AFT = -0.13 / 100.0
|
||||
|
||||
def test_2019_taxes_one(self):
|
||||
# Payroll Period Semi-Monthly example
|
||||
salary = 550
|
||||
mt_mw4_exemptions = 5
|
||||
|
||||
employee = self._createEmployee()
|
||||
contract = self._createContract(employee,
|
||||
wage=salary,
|
||||
state_id=self.get_us_state('MT'),
|
||||
mt_mw4_sit_exemptions=mt_mw4_exemptions,
|
||||
schedule_pay='semi-monthly')
|
||||
|
||||
self._log('2019 Montana tax single first payslip:')
|
||||
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
|
||||
|
||||
payslip.compute_sheet()
|
||||
|
||||
cats = self._getCategories(payslip)
|
||||
|
||||
self.assertPayrollEqual(cats['ER_US_SUTA'], salary * (self.MT_UNEMP + self.MT_UNEMP_AFT)) # New non-combined...
|
||||
|
||||
mt_taxable_income = salary - (79.0 * mt_mw4_exemptions)
|
||||
mt_withhold = round(0 + (0.018 * (mt_taxable_income - 0)))
|
||||
self.assertPayrollEqual(mt_taxable_income, 155.0)
|
||||
self.assertPayrollEqual(mt_withhold, 3.0)
|
||||
self.assertPayrollEqual(cats['EE_US_SIT'], -mt_withhold)
|
||||
|
||||
def test_2019_taxes_two(self):
|
||||
# Payroll Period Bi-Weekly example
|
||||
salary = 2950
|
||||
mt_mw4_exemptions = 2
|
||||
|
||||
employee = self._createEmployee()
|
||||
contract = self._createContract(employee,
|
||||
wage=salary,
|
||||
state_id=self.get_us_state('MT'),
|
||||
mt_mw4_sit_exemptions=mt_mw4_exemptions,
|
||||
schedule_pay='bi-weekly')
|
||||
|
||||
self._log('2019 Montana tax single first payslip:')
|
||||
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
|
||||
|
||||
payslip.compute_sheet()
|
||||
|
||||
cats = self._getCategories(payslip)
|
||||
|
||||
self.assertPayrollEqual(cats['ER_US_SUTA'], round(salary * (self.MT_UNEMP + self.MT_UNEMP_AFT), 2))
|
||||
|
||||
# Note!!
|
||||
# The example calculation uses A = 16 but the actual table describes this as A = 18
|
||||
mt_taxable_income = salary - (73.0 * mt_mw4_exemptions)
|
||||
mt_withhold = round(18 + (0.06 * (mt_taxable_income - 577)))
|
||||
self.assertPayrollEqual(mt_taxable_income, 2804.0)
|
||||
self.assertPayrollEqual(mt_withhold, 152.0)
|
||||
self.assertPayrollEqual(cats['EE_US_SIT'], -mt_withhold)
|
||||
|
||||
def test_2019_taxes_three(self):
|
||||
# Payroll Period Weekly example
|
||||
salary = 135
|
||||
mt_mw4_exemptions = 1
|
||||
|
||||
employee = self._createEmployee()
|
||||
contract = self._createContract(employee,
|
||||
wage=salary,
|
||||
state_id=self.get_us_state('MT'),
|
||||
mt_mw4_sit_exemptions=mt_mw4_exemptions,
|
||||
schedule_pay='weekly')
|
||||
|
||||
self._log('2019 Montana tax single first payslip:')
|
||||
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
|
||||
|
||||
payslip.compute_sheet()
|
||||
|
||||
cats = self._getCategories(payslip)
|
||||
|
||||
self.assertPayrollEqual(cats['ER_US_SUTA'], round(salary * (self.MT_UNEMP + self.MT_UNEMP_AFT), 2))
|
||||
|
||||
mt_taxable_income = salary - (37.0 * mt_mw4_exemptions)
|
||||
mt_withhold = round(0 + (0.018 * (mt_taxable_income - 0)))
|
||||
self.assertPayrollEqual(mt_taxable_income, 98.0)
|
||||
self.assertPayrollEqual(mt_withhold, 2.0)
|
||||
self.assertPayrollEqual(cats['EE_US_SIT'], -mt_withhold)
|
||||
|
||||
def test_2019_taxes_three_exempt(self):
|
||||
# Payroll Period Weekly example
|
||||
salary = 135
|
||||
mt_mw4_exemptions = 1
|
||||
|
||||
employee = self._createEmployee()
|
||||
contract = self._createContract(employee,
|
||||
wage=salary,
|
||||
state_id=self.get_us_state('MT'),
|
||||
mt_mw4_sit_exemptions=mt_mw4_exemptions,
|
||||
mt_mw4_sit_exempt='reserve',
|
||||
schedule_pay='weekly')
|
||||
|
||||
self._log('2019 Montana tax single first payslip:')
|
||||
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), 0.0)
|
||||
|
||||
def test_2019_taxes_three_additional(self):
|
||||
# Payroll Period Weekly example
|
||||
salary = 135
|
||||
mt_mw4_exemptions = 1
|
||||
mt_mw4_additional_withholding = 20.0
|
||||
|
||||
employee = self._createEmployee()
|
||||
contract = self._createContract(employee,
|
||||
wage=salary,
|
||||
state_id=self.get_us_state('MT'),
|
||||
mt_mw4_sit_exemptions=mt_mw4_exemptions,
|
||||
state_income_tax_additional_withholding=mt_mw4_additional_withholding,
|
||||
schedule_pay='weekly')
|
||||
|
||||
self._log('2019 Montana tax single first payslip:')
|
||||
payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
|
||||
|
||||
payslip.compute_sheet()
|
||||
cats = self._getCategories(payslip)
|
||||
|
||||
mt_taxable_income = salary - (37.0 * mt_mw4_exemptions)
|
||||
mt_withhold = round(0 + (0.018 * (mt_taxable_income - 0)))
|
||||
self.assertPayrollEqual(mt_taxable_income, 98.0)
|
||||
self.assertPayrollEqual(mt_withhold, 2.0)
|
||||
self.assertPayrollEqual(cats['EE_US_SIT'], -mt_withhold + -mt_mw4_additional_withholding)
|
||||
17
l10n_us_hr_payroll/tests/test_us_mt_montana_payslip_2020.py
Executable file
17
l10n_us_hr_payroll/tests/test_us_mt_montana_payslip_2020.py
Executable file
@@ -0,0 +1,17 @@
|
||||
# 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 TestUsMtPayslip(TestUsPayslip):
|
||||
# Calculations from https://app.mt.gov/myrevenue/Endpoint/DownloadPdf?yearId=705
|
||||
MT_UNEMP_WAGE_MAX = 34100.0
|
||||
MT_UNEMP = 1.18
|
||||
MT_UNEMP_AFT = 0.13
|
||||
|
||||
def test_2020_taxes_one(self):
|
||||
combined_rate = self.MT_UNEMP + self.MT_UNEMP_AFT # Combined for test as they both go to the same category and have the same cap
|
||||
self._test_er_suta('MT', combined_rate, date(2020, 1, 1), wage_base=self.MT_UNEMP_WAGE_MAX)
|
||||
|
||||
# TODO Montana Incometax rates for 2020 when released
|
||||
@@ -44,6 +44,12 @@
|
||||
<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_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"/>
|
||||
<field name="mt_mw4_sit_exemptions" string="Exemptions"/>
|
||||
<field name="state_income_tax_additional_withholding" string="Additional Withholding (Box H)"/>
|
||||
</group>
|
||||
<group name="state_pa_pennsylvania" string="PA Pennsylvania" attrs="{'invisible':[('state_id', '!=', %(base.state_us_39)s)]}">
|
||||
<field name="state_income_tax_exempt"/>
|
||||
<field name="state_income_tax_additional_withholding"/>
|
||||
|
||||
Reference in New Issue
Block a user