From 9d8f5b9f5579a6a78a1ecd9a95e1a151404d8bd4 Mon Sep 17 00:00:00 2001
From: Jared Kipe
Date: Wed, 12 Aug 2020 10:51:40 -0700
Subject: [PATCH 1/3] IMP `l10n_us_hr_payroll` Add NY New York from 13.0
---
l10n_us_hr_payroll/__manifest__.py | 1 +
l10n_us_hr_payroll/data/final.xml | 5 +
l10n_us_hr_payroll/data/state/ny_new_york.xml | 270 ++++++++++++++++++
l10n_us_hr_payroll/models/hr_payslip.py | 2 +
.../models/state/ny_new_york.py | 54 ++++
.../models/us_payroll_config.py | 7 +
l10n_us_hr_payroll/tests/__init__.py | 3 +
.../tests/test_us_ny_new_york_payslip_2019.py | 106 +++++++
.../tests/test_us_ny_new_york_payslip_2020.py | 38 +++
.../views/us_payroll_config_views.xml | 6 +
10 files changed, 492 insertions(+)
create mode 100644 l10n_us_hr_payroll/data/state/ny_new_york.xml
create mode 100644 l10n_us_hr_payroll/models/state/ny_new_york.py
create mode 100644 l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
create mode 100644 l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py
index 564d9fa9..ec4a8428 100755
--- a/l10n_us_hr_payroll/__manifest__.py
+++ b/l10n_us_hr_payroll/__manifest__.py
@@ -51,6 +51,7 @@ USA Payroll Rules.
'data/state/nh_new_hampshire.xml',
'data/state/nj_newjersey.xml',
'data/state/nm_new_mexico.xml',
+ 'data/state/ny_new_york.xml',
'data/state/oh_ohio.xml',
'data/state/pa_pennsylvania.xml',
'data/state/tx_texas.xml',
diff --git a/l10n_us_hr_payroll/data/final.xml b/l10n_us_hr_payroll/data/final.xml
index 29046d56..b11f41da 100644
--- a/l10n_us_hr_payroll/data/final.xml
+++ b/l10n_us_hr_payroll/data/final.xml
@@ -93,6 +93,11 @@
ref('hr_payroll_rule_er_us_nm_suta'),
ref('hr_payroll_rule_ee_us_nm_sit'),
+ ref('hr_payroll_rule_er_us_ny_suta'),
+ ref('hr_payroll_rule_er_us_ny_suta_rsf'),
+ ref('hr_payroll_rule_er_us_ny_suta_mctmt'),
+ ref('hr_payroll_rule_ee_us_ny_sit'),
+
ref('hr_payroll_rule_er_us_oh_suta'),
ref('hr_payroll_rule_ee_us_oh_sit'),
diff --git a/l10n_us_hr_payroll/data/state/ny_new_york.xml b/l10n_us_hr_payroll/data/state/ny_new_york.xml
new file mode 100644
index 00000000..ad52594b
--- /dev/null
+++ b/l10n_us_hr_payroll/data/state/ny_new_york.xml
@@ -0,0 +1,270 @@
+
+
+
+
+
+ US NY New York SUTA Wage Base
+ us_ny_suta_wage_base
+ 14000.0
+
+
+
+ US NY New York SUTA Wage Base
+ us_ny_suta_wage_base
+ 14000.0
+
+
+
+
+
+
+
+ US NY New York SUTA Rate
+ us_ny_suta_rate
+ 1.09
+
+
+
+ US NY New York SUTA Rate
+ us_ny_suta_rate
+ 3.295
+
+
+
+
+
+
+ US NY New York SUTA RSF Rate
+ us_ny_suta_rsf_rate
+ 0.075
+
+
+
+ US NY New York SUTA RSF Rate
+ us_ny_suta_rsf_rate
+ 0.075
+
+
+
+
+
+
+ US NY New York SUTA MCTMT Rate
+ us_ny_suta_mctmt_rate
+ 0.0
+
+
+
+ US NY New York SUTA MCTMT Rate
+ us_ny_suta_mctmt_rate
+ 0.0
+
+
+
+
+
+
+ US NY New York SIT Tax Rate
+ us_ny_sit_tax_rate
+ {
+ 'single': {
+ 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0758, 112.58), (3032, 0.0808, 128.38), (4142, 0.0707, 206.08), (5104, 0.0856, 284.60), (20722, 0.0735, 366.90), (21684, 0.5208, 1514.85), ('inf', 0.0962, 2015.62)),
+ 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0758, 225.15), (6063, 0.0808, 256.77), (8285, 0.0707, 412.15), (10208, 0.0856, 569.19), (41444, 0.0735, 733.81), (43367, 0.5208, 3029.69), ('inf', 0.0962, 4021.23)),
+ 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0758, 243.92), (6569, 0.0808, 278.17), (8975, 0.0707, 446.50), (11058, 0.0856, 616.63), (44898, 0.0735, 794.96), (46981, 0.5208, 3282.17), ('inf', 0.0962, 4367.17)),
+ 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0758, 487.83), (13138, 0.0808, 556.33), (17950, 0.0707, 893.00), (22117, 0.0856, 1233.25), (89796, 0.0735, 1589.92), (93963, 0.5208, 6564.33), ('inf', 0.0962, 8734.33)),
+ 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0758, 5854.00), (157650, 0.0808, 6676.00), (215400, 0.0707, 10716.00), (265400, 0.0856, 14799.00), (1077550, 0.0735, 19079.00), (1127550, 0.5208, 78772.00), ('inf', 0.0962, 104812.00)),
+ },
+ 'married': {
+ 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0783, 112.58), (3032, 0.0833, 128.90), (4068, 0.0785, 209.00), (6215, 0.0707, 290.37), (7177, 0.0916, 442.17), (20722, 0.0735, 530.25), (41449, 0.0765, 1525.83), (42411, 0.9454, 3111.42), ('inf', 0.0962, 4020.46)),
+ 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0783, 225.15), (6063, 0.0833, 257.81), (8137, 0.0785, 418.00), (12431, 0.0707, 580.73), (14354, 0.0916, 884.35), (41444, 0.0735, 1060.50), (82898, 0.0765, 3051.65), (84821, 0.9454, 6222.85), ('inf', 0.0962, 8040.92)),
+ 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0783, 243.92), (6569, 0.0833, 279.29), (8815, 0.0785, 452.83), (13476, 0.0707, 629.13), (15550, 0.0916, 958.04), (44898, 0.0735, 1148.88), (89806, 0.0765, 3305.96), (91890, 0.9454, 6741.42), ('inf', 0.0962, 8711.00)),
+ 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0783, 487.83), (13138, 0.0833, 558.58), (17629, 0.0785, 905.67), (26933, 0.0707, 1258.25), (31100, 0.0916, 1916.08), (89796, 0.0735, 2297.75), (179613, 0.0765, 6611.92), (183779, 0.9454, 13482.83), ('inf', 0.0962, 17422.00)),
+ 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0783, 5854.00), (157650, 0.0833, 6703.00), (211550, 0.0785, 10868.00), (323200, 0.0707, 15099.00), (373200, 0.0916, 22993.00), (1077550, 0.0735, 27573.00), (2155350, 0.0765, 79343.00), (2205350, 0.9454, 161794.00), ('inf', 0.0962, 209064.00)),
+ }
+ }
+
+
+
+ US NY New York SIT Tax Rate
+ us_ny_sit_tax_rate
+ {
+ 'single': {
+ 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0758, 112.58), (3032, 0.0808, 128.38), (4142, 0.0707, 206.08), (5104, 0.0856, 284.60), (20722, 0.0735, 366.90), (21684, 0.5208, 1514.85), ('inf', 0.0962, 2015.62)),
+ 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0758, 225.15), (6063, 0.0808, 256.77), (8285, 0.0707, 412.15), (10208, 0.0856, 569.19), (41444, 0.0735, 733.81), (43367, 0.5208, 3029.69), ('inf', 0.0962, 4021.23)),
+ 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0758, 243.92), (6569, 0.0808, 278.17), (8975, 0.0707, 446.50), (11058, 0.0856, 616.63), (44898, 0.0735, 794.96), (46981, 0.5208, 3282.17), ('inf', 0.0962, 4367.17)),
+ 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0758, 487.83), (13138, 0.0808, 556.33), (17950, 0.0707, 893.00), (22117, 0.0856, 1233.25), (89796, 0.0735, 1589.92), (93963, 0.5208, 6564.33), ('inf', 0.0962, 8734.33)),
+ 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0758, 5854.00), (157650, 0.0808, 6676.00), (215400, 0.0707, 10716.00), (265400, 0.0856, 14799.00), (1077550, 0.0735, 19079.00), (1127550, 0.5208, 78772.00), ('inf', 0.0962, 104812.00)),
+ },
+ 'married': {
+ 'weekly': ((163, 0.0400, 0.0), (225, 0.0450, 6.54), (267, 0.0525, 9.31), (412, 0.0590, 11.54), (1551, 0.0633, 20.04), (1862, 0.0657, 92.17), (2070, 0.0783, 112.58), (3032, 0.0833, 128.90), (4068, 0.0785, 209.00), (6215, 0.0707, 290.37), (7177, 0.0916, 442.17), (20722, 0.0735, 530.25), (41449, 0.0765, 1525.83), (42411, 0.9454, 3111.42), ('inf', 0.0962, 4020.46)),
+ 'bi-weekly': ((327, 0.0400, 0.0), (450, 0.0450, 13.08), (535, 0.0525, 18.62), (823, 0.0590, 23.08), (3102, 0.0633, 40.08), (3723, 0.0657, 184.35), (4140, 0.0783, 225.15), (6063, 0.0833, 257.81), (8137, 0.0785, 418.00), (12431, 0.0707, 580.73), (14354, 0.0916, 884.35), (41444, 0.0735, 1060.50), (82898, 0.0765, 3051.65), (84821, 0.9454, 6222.85), ('inf', 0.0962, 8040.92)),
+ 'semi-monthly': ((354, 0.0400, 0.0), (488, 0.0450, 14.17), (579, 0.0525, 20.17), (892, 0.0590, 25.00), (3360, 0.0633, 43.42), (4033, 0.0657, 199.71), (4485, 0.0783, 243.92), (6569, 0.0833, 279.29), (8815, 0.0785, 452.83), (13476, 0.0707, 629.13), (15550, 0.0916, 958.04), (44898, 0.0735, 1148.88), (89806, 0.0765, 3305.96), (91890, 0.9454, 6741.42), ('inf', 0.0962, 8711.00)),
+ 'monthly': ((708, 0.0400, 0.0), (975, 0.0450, 28.33), (1158, 0.0525, 40.33), (1783, 0.0590, 50.00), (6721, 0.0633, 86.83), (8067, 0.0657, 399.42), (8971, 0.0783, 487.83), (13138, 0.0833, 558.58), (17629, 0.0785, 905.67), (26933, 0.0707, 1258.25), (31100, 0.0916, 1916.08), (89796, 0.0735, 2297.75), (179613, 0.0765, 6611.92), (183779, 0.9454, 13482.83), ('inf', 0.0962, 17422.00)),
+ 'annually': ((8500, 0.0400, 0.0), (11700, 0.0450, 340.00), (13900, 0.0525, 484.00), (21400, 0.0590, 600.00), (80650, 0.0633, 1042.00), (96800, 0.0657, 4793.00), (107650, 0.0783, 5854.00), (157650, 0.0833, 6703.00), (211550, 0.0785, 10868.00), (323200, 0.0707, 15099.00), (373200, 0.0916, 22993.00), (1077550, 0.0735, 27573.00), (2155350, 0.0765, 79343.00), (2205350, 0.9454, 161794.00), ('inf', 0.0962, 209064.00)),
+ }
+ }
+
+
+
+
+
+
+ US NY New York Over 10 Exemption Rate
+ us_ny_sit_over_10_exemption_rate
+ {
+ 'weekly': (142.30, 152.90, 19.25),
+ 'bi-weekly': (284.60, 305.80, 38.50),
+ 'semi-monthly': (308.35, 331.25, 41.65),
+ 'monthly': (616.70, 662.50, 83.30),
+ 'annual': (7400, 7950, 1000),
+ }
+
+
+
+ US NY New York Over 10 Exemption Rate
+ us_ny_sit_over_10_exemption_rate
+ {
+ 'weekly': (142.30, 152.90, 19.25),
+ 'bi-weekly': (284.60, 305.80, 38.50),
+ 'semi-monthly': (308.35, 331.25, 41.65),
+ 'monthly': (616.70, 662.50, 83.30),
+ 'annual': (7400, 7950, 1000),
+ }
+
+
+
+
+
+
+ US NY New York Deduction Exemption Rate
+ us_ny_sit_deduction_exemption_rate
+ {
+ 'single': {
+ 'weekly': (142.30, 161.55, 180.80, 200.05, 219.30, 238.55, 257.80, 277.05, 296.30, 315.55, 334.80),
+ 'bi-weekly': (284.60, 323.10, 361.60, 400.10, 438.60, 477.10, 515.60, 544.10, 592.60, 631.10, 669.60),
+ 'semi-monthly': (308.35, 350.0, 391.65, 433.30, 474.95, 516.60, 558.25, 599.90, 641.55, 683.20, 724.85),
+ 'monthly': (616.70, 700, 783.30, 866.60, 949.90, 1033.20, 1116.50, 1199.80, 1283.10, 1366.40, 1449.70),
+ 'annually': (7400, 8400, 9400, 10400, 11400, 12400, 13400, 14400, 15400, 16400, 17400),
+ },
+ 'married': {
+ 'weekly': (152.90, 172.15, 191.40, 210.65, 229.90, 249.15, 268.40, 287.65, 306.90, 326.15, 345.40),
+ 'bi-weekly': (305.80, 344.30, 382.80, 421.30, 459.80, 498.30, 536.80, 575.30, 613.80, 652.30, 690.80),
+ 'semi-monthly': (331.25, 372.90, 414.55, 456.20, 497.85, 539.50, 581.15, 622.80, 664.45, 706.10, 747.75),
+ 'monthly': (662.50, 745.80, 829.10, 912.40, 995.70, 1079.00, 1162.30, 1245.60, 1328.90, 1412.20, 1495.50),
+ 'annually': (7950, 8950, 9950, 10950, 11950, 12950, 13950, 14950, 15950, 16950, 17950),
+ },
+ }
+
+
+
+ US NY New York Deduction Exemption Rate
+ us_ny_sit_deduction_exemption_rate
+ {
+ 'single': {
+ 'weekly': (142.30, 161.55, 180.80, 200.05, 219.30, 238.55, 257.80, 277.05, 296.30, 315.55, 334.80),
+ 'bi-weekly': (284.60, 323.10, 361.60, 400.10, 438.60, 477.10, 515.60, 544.10, 592.60, 631.10, 669.60),
+ 'semi-monthly': (308.35, 350.0, 391.65, 433.30, 474.95, 516.60, 558.25, 599.90, 641.55, 683.20, 724.85),
+ 'monthly': (616.70, 700, 783.30, 866.60, 949.90, 1033.20, 1116.50, 1199.80, 1283.10, 1366.40, 1449.70),
+ 'annually': (7400, 8400, 9400, 10400, 11400, 12400, 13400, 14400, 15400, 16400, 17400),
+ },
+ 'married': {
+ 'weekly': (152.90, 172.15, 191.40, 210.65, 229.90, 249.15, 268.40, 287.65, 306.90, 326.15, 345.40),
+ 'bi-weekly': (305.80, 344.30, 382.80, 421.30, 459.80, 498.30, 536.80, 575.30, 613.80, 652.30, 690.80),
+ 'semi-monthly': (331.25, 372.90, 414.55, 456.20, 497.85, 539.50, 581.15, 622.80, 664.45, 706.10, 747.75),
+ 'monthly': (662.50, 745.80, 829.10, 912.40, 995.70, 1079.00, 1162.30, 1245.60, 1328.90, 1412.20, 1495.50),
+ 'annually': (7950, 8950, 9950, 10950, 11950, 12950, 13950, 14950, 15950, 16950, 17950),
+ },
+ }
+
+
+
+
+
+
+ US New York - Department of Taxation and Finance - Unemployment Tax
+
+
+ US New York - Department of Taxation and Finance - Unemployment Tax
+
+
+
+
+ US New York - Department of Taxation and Finance - Re-employment Service Fund
+
+
+ US New York - Department of Taxation and Finance - Re-employment Service Fund
+
+
+
+
+ US New York - Department of Taxation and Finance - Metropolitan Commuter Transportation Mobility Tax
+
+
+ US New York - Department of Taxation and Finance - Metropolitan Commuter Transportation Mobility Tax
+
+
+
+
+ US New York - Department of Taxation and Finance - Income Tax
+
+
+ US New York - Department of Taxation and Finance - Income Tax
+
+
+
+
+
+
+
+
+
+ ER: US NY New York State Unemployment
+ ER_US_NY_SUTA
+ python
+ result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_rate', state_code='NY')
+ code
+ result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_rate', state_code='NY')
+
+
+
+
+
+
+
+ ER: US NY New York State Re-employment Service Fund
+ ER_US_NY_SUTA_RSF
+ python
+ result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_rsf_rate', state_code='NY')
+ code
+ result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_rsf_rate', state_code='NY')
+
+
+
+
+
+
+
+ ER: US NY New York State Metropolitan Commuter Transportation Mobility Tax
+ ER_US_NY_SUTA_MCTMT
+ python
+ result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_mctmt_rate', state_code='NY')
+ code
+ result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ny_suta_wage_base', rate='us_ny_suta_mctmt_rate', state_code='NY')
+
+
+
+
+
+
+
+ EE: US NY New York State Income Tax Withholding
+ EE_US_NY_SIT
+ python
+ result, _ = ny_new_york_state_income_withholding(payslip, categories, worked_days, inputs)
+ code
+ result, result_rate = ny_new_york_state_income_withholding(payslip, categories, worked_days, inputs)
+
+
+
+
+
diff --git a/l10n_us_hr_payroll/models/hr_payslip.py b/l10n_us_hr_payroll/models/hr_payslip.py
index 5fa5cad8..ea4d4113 100644
--- a/l10n_us_hr_payroll/models/hr_payslip.py
+++ b/l10n_us_hr_payroll/models/hr_payslip.py
@@ -34,6 +34,7 @@ from .state.mt_montana import mt_montana_state_income_withholding
from .state.nc_northcarolina import nc_northcarolina_state_income_withholding
from .state.nj_newjersey import nj_newjersey_state_income_withholding
from .state.nm_new_mexico import nm_new_mexico_state_income_withholding
+from .state.ny_new_york import ny_new_york_state_income_withholding
from .state.oh_ohio import oh_ohio_state_income_withholding
from .state.va_virginia import va_virginia_state_income_withholding
from .state.wa_washington import wa_washington_fml_er, \
@@ -90,6 +91,7 @@ class HRPayslip(models.Model):
'nc_northcarolina_state_income_withholding': nc_northcarolina_state_income_withholding,
'nj_newjersey_state_income_withholding': nj_newjersey_state_income_withholding,
'nm_new_mexico_state_income_withholding': nm_new_mexico_state_income_withholding,
+ 'ny_new_york_state_income_withholding': ny_new_york_state_income_withholding,
'oh_ohio_state_income_withholding': oh_ohio_state_income_withholding,
'va_virginia_state_income_withholding': va_virginia_state_income_withholding,
'wa_washington_fml_er': wa_washington_fml_er,
diff --git a/l10n_us_hr_payroll/models/state/ny_new_york.py b/l10n_us_hr_payroll/models/state/ny_new_york.py
new file mode 100644
index 00000000..664507ef
--- /dev/null
+++ b/l10n_us_hr_payroll/models/state/ny_new_york.py
@@ -0,0 +1,54 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from .general import _state_applies, sit_wage
+
+
+def ny_new_york_state_income_withholding(payslip, categories, worked_days, inputs):
+ """
+ Returns SIT eligible wage and rate.
+
+ :return: result, result_rate (wage, percent)
+ """
+ state_code = 'NY'
+ if not _state_applies(payslip, state_code):
+ return 0.0, 0.0
+
+ # Determine Wage
+ wage = sit_wage(payslip, categories)
+ if not wage:
+ return 0.0, 0.0
+
+ filing_status = payslip.contract_id.us_payroll_config_value('ny_it2104_sit_filing_status')
+ if not filing_status:
+ return 0.0, 0.0
+
+ schedule_pay = payslip.contract_id.schedule_pay
+ additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding')
+ tax_table = payslip.dict.rule_parameter('us_ny_sit_tax_rate')[filing_status].get(schedule_pay)
+ allowances = payslip.contract_id.us_payroll_config_value('ny_it2104_sit_allowances')
+ over_10_deduction = payslip.dict.rule_parameter('us_ny_sit_over_10_exemption_rate')[schedule_pay]
+ deduction_exemption = payslip.dict.rule_parameter('us_ny_sit_deduction_exemption_rate')[filing_status].get(schedule_pay)
+
+ if allowances > 10:
+ if filing_status == 'single':
+ wage -= over_10_deduction[0] + over_10_deduction[2] * allowances
+ elif filing_status == 'married':
+ wage -= over_10_deduction[1] + over_10_deduction[2] * allowances
+
+ else:
+ if filing_status == 'single':
+ wage -= deduction_exemption[allowances]
+ elif filing_status == 'married':
+ wage -= deduction_exemption[allowances]
+ last = 0.0
+ withholding = 0.0
+ for row in tax_table:
+ amt, rate, flat_fee = row
+ if wage <= float(amt):
+ withholding = ((wage - last) * rate) + flat_fee
+ break
+ last = amt
+
+ withholding = max(withholding, 0.0)
+ withholding += additional
+ return wage, -((withholding / wage) * 100.0)
diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py
index cf13f188..4915b8d2 100644
--- a/l10n_us_hr_payroll/models/us_payroll_config.py
+++ b/l10n_us_hr_payroll/models/us_payroll_config.py
@@ -189,6 +189,13 @@ class HRContractUSPayrollConfig(models.Model):
('E', 'E')
], string='New Jersey Wage Chart Letter', help='NJ-W4. 3.')
+ ny_it2104_sit_filing_status = fields.Selection([
+ ('', 'Exempt'),
+ ('single', 'Single'),
+ ('married', 'Married'),
+ ], string='New York NY IT-2104 Filing Status', help='NY IT-2104')
+ ny_it2104_sit_allowances = fields.Integer(string="New York IT-2104 Allowances", help="NY IT-2104 1. 2.")
+
# Ohio will use generic SIT exempt and additional fields
oh_it4_sit_exemptions = fields.Integer(string='Ohio IT-4 Exemptions',
help='Line 4')
diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py
index d2b95c24..6068dd3c 100755
--- a/l10n_us_hr_payroll/tests/__init__.py
+++ b/l10n_us_hr_payroll/tests/__init__.py
@@ -72,6 +72,9 @@ from . import test_us_nj_newjersey_payslip_2020
from . import test_us_nm_new_mexico_payslip_2020
+from . import test_us_ny_new_york_payslip_2019
+from . import test_us_ny_new_york_payslip_2020
+
from . import test_us_oh_ohio_payslip_2019
from . import test_us_oh_ohio_payslip_2020
diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
new file mode 100644
index 00000000..d3e146de
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
@@ -0,0 +1,106 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from .common import TestUsPayslip, process_payslip
+
+
+class TestUsNYPayslip(TestUsPayslip):
+ ###
+ # Taxes and Rates
+ ###
+ NY_UNEMP_MAX_WAGE = 14000
+ NY_UNEMP = 3.295
+ NY_RSF = 0.075
+ NY_MCTMT = 0.0
+
+ def test_single_example1(self):
+ salary = 400
+ schedule_pay = 'weekly'
+ allowances = 3
+ additional_withholding = 0
+ filing_status = 'single'
+ additional = 0.0
+ wh = -8.20
+
+ employee = self._createEmployee()
+
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('NY'),
+ ny_it2104_sit_filing_status=filing_status,
+ state_income_tax_additional_withholding=additional,
+ ny_it2104_sit_allowances=allowances,
+ schedule_pay=schedule_pay)
+
+ self.assertEqual(contract.schedule_pay, 'weekly')
+ self._log('2018 New York tax first payslip:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+
+ payslip.compute_sheet()
+
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['NY_UNEMP'], cats['NY_UNEMP_WAGES'] * self.NY_UNEMP)
+ self.assertPayrollEqual(cats['NY_RSF'], cats['NY_UNEMP_WAGES'] * self.NY_RSF)
+ self.assertPayrollEqual(cats['NY_MCTMT'], cats['NY_UNEMP_WAGES'] * self.NY_MCTMT)
+ self.assertPayrollEqual(cats['EE_US_SIT'], wh)
+
+ process_payslip(payslip)
+
+ def test_married_example2(self):
+ salary = 5000
+ schedule_pay = 'semi-monthly'
+ allowances = 3
+ additional = 0
+ filing_status = 'married'
+ wh = -284.19
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('NY'),
+ ny_it2104_sit_filing_status=filing_status,
+ state_income_tax_additional_withholding=additional,
+ ny_it2104_sit_allowances=allowances,
+ schedule_pay=schedule_pay)
+
+ self._log('2019 New York tax first payslip:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+
+ payslip.compute_sheet()
+
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['NY_UNEMP'], cats['NY_UNEMP_WAGES'] * self.NY_UNEMP)
+ self.assertPayrollEqual(cats['NY_RSF'], cats['NY_UNEMP_WAGES'] * self.NY_RSF)
+ self.assertPayrollEqual(cats['NY_MCTMT'], cats['NY_UNEMP_WAGES'] * self.NY_MCTMT)
+ self.assertPayrollEqual(cats['EE_US_SIT'], wh)
+
+ process_payslip(payslip)
+
+ def test_single_example3(self):
+ salary = 50000
+ schedule_pay = 'monthly'
+ allowances = 3
+ additional = 0
+ filing_status = 'single'
+ wh = -3575.63
+
+ employee = self._createEmployee()
+
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('NY'),
+ ny_it2104_sit_filing_status=filing_status,
+ state_income_tax_additional_withholding=additional,
+ ny_it2104_sit_allowances=allowances,
+ schedule_pay=schedule_pay)
+
+ self._log('2019 New York tax first payslip:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+
+ payslip.compute_sheet()
+
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['EE_US_SIT'], wh)
+
diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
new file mode 100644
index 00000000..29fbc0cb
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
@@ -0,0 +1,38 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from datetime import date, timedelta
+from .common import TestUsPayslip
+
+
+class TestUsNYPayslip(TestUsPayslip):
+ ###
+ # 2020 Taxes and Rates
+ ###
+ NY_UNEMP_MAX_WAGE = 14000.0
+ NY_UNEMP = 3.295
+ NY_RSF = 0.075
+ NY_MCTMT = 0.0
+
+ def _test_sit(self, wage, filing_status, additional_withholding, allowances, schedule_pay, date_start, expected_withholding):
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=wage,
+ state_id=self.get_us_state('NY'),
+ ny_it2104_sit_filing_status=filing_status,
+ state_income_tax_additional_withholding=additional_withholding,
+ ny_it2104_sit_allowances=allowances,
+ schedule_pay=schedule_pay)
+ payslip = self._createPayslip(employee, date_start, date_start + timedelta(days=7))
+ payslip.compute_sheet()
+ cats = self._getCategories(payslip)
+
+ self._log('Computed period tax: ' + str(expected_withholding))
+ self.assertPayrollEqual(cats.get('EE_US_SIT', 0.0), -expected_withholding)
+
+ def test_2020_taxes_example(self):
+ combined_er_rate = self.NY_UNEMP + self.NY_RSF + self.NY_MCTMT
+ self._test_er_suta('NY', combined_er_rate, date(2020, 1, 1), wage_base=self.NY_UNEMP_MAX_WAGE, relaxed=True)
+ self._test_sit(400.0, 'single', 0.0, 3, 'weekly', date(2020, 1, 1), 8.20)
+ self._test_sit(50000.0, 'single', 0.0, 3, 'monthly', date(2020, 1, 1), 3575.63)
+ self._test_sit(50000.0, 'married', 0.0, 3, 'monthly', date(2020, 1, 1), 3619.82)
+ self._test_sit(50000.0, 'married', 10.0, 3, 'monthly', date(2020, 1, 1), 3629.83)
diff --git a/l10n_us_hr_payroll/views/us_payroll_config_views.xml b/l10n_us_hr_payroll/views/us_payroll_config_views.xml
index 8016d921..53ba7f4d 100644
--- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml
+++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml
@@ -169,6 +169,12 @@
Form NM W-4 - State Income Tax
+
+ Form NY IT-2104 - State Income Tax
+
+
+
+
Form IT-4 - State Income Tax
From 389128da0b9e1184e8baa849f86eb60dbee28b51 Mon Sep 17 00:00:00 2001
From: Bhoomi Vaishnani
Date: Tue, 11 Aug 2020 11:59:55 -0400
Subject: [PATCH 2/3] [IMP] l10n_us_hr_payroll: Changed wage base and suta rate
for NY New York 2019/2020. 4d704f1 Bhoomi Vaishnani
Aug 11, 2020 at 8:59 AM
---
l10n_us_hr_payroll/data/state/ny_new_york.xml | 8 ++++----
l10n_us_hr_payroll/models/us_payroll_config.py | 1 -
.../tests/test_us_ny_new_york_payslip_2019.py | 4 ++--
.../tests/test_us_ny_new_york_payslip_2020.py | 4 ++--
l10n_us_hr_payroll/views/us_payroll_config_views.xml | 2 +-
5 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/l10n_us_hr_payroll/data/state/ny_new_york.xml b/l10n_us_hr_payroll/data/state/ny_new_york.xml
index ad52594b..25aaa83f 100644
--- a/l10n_us_hr_payroll/data/state/ny_new_york.xml
+++ b/l10n_us_hr_payroll/data/state/ny_new_york.xml
@@ -5,13 +5,13 @@
US NY New York SUTA Wage Base
us_ny_suta_wage_base
- 14000.0
+ 11400.0
US NY New York SUTA Wage Base
us_ny_suta_wage_base
- 14000.0
+ 11600.0
@@ -21,13 +21,13 @@
US NY New York SUTA Rate
us_ny_suta_rate
- 1.09
+ 2.5
US NY New York SUTA Rate
us_ny_suta_rate
- 3.295
+ 2.5
diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py
index 4915b8d2..6f6b8e70 100644
--- a/l10n_us_hr_payroll/models/us_payroll_config.py
+++ b/l10n_us_hr_payroll/models/us_payroll_config.py
@@ -190,7 +190,6 @@ class HRContractUSPayrollConfig(models.Model):
], string='New Jersey Wage Chart Letter', help='NJ-W4. 3.')
ny_it2104_sit_filing_status = fields.Selection([
- ('', 'Exempt'),
('single', 'Single'),
('married', 'Married'),
], string='New York NY IT-2104 Filing Status', help='NY IT-2104')
diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
index d3e146de..973ea5ba 100644
--- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
+++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
@@ -7,8 +7,8 @@ class TestUsNYPayslip(TestUsPayslip):
###
# Taxes and Rates
###
- NY_UNEMP_MAX_WAGE = 14000
- NY_UNEMP = 3.295
+ NY_UNEMP_MAX_WAGE = 11400.0
+ NY_UNEMP = 2.5
NY_RSF = 0.075
NY_MCTMT = 0.0
diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
index 29fbc0cb..763bd67d 100644
--- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
+++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
@@ -8,8 +8,8 @@ class TestUsNYPayslip(TestUsPayslip):
###
# 2020 Taxes and Rates
###
- NY_UNEMP_MAX_WAGE = 14000.0
- NY_UNEMP = 3.295
+ NY_UNEMP_MAX_WAGE = 11600.0
+ NY_UNEMP = 2.5
NY_RSF = 0.075
NY_MCTMT = 0.0
diff --git a/l10n_us_hr_payroll/views/us_payroll_config_views.xml b/l10n_us_hr_payroll/views/us_payroll_config_views.xml
index 53ba7f4d..c464e524 100644
--- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml
+++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml
@@ -173,7 +173,7 @@
Form NY IT-2104 - State Income Tax
-
+
Form IT-4 - State Income Tax
From 6ebc37f5a6633a8dd83dcd1215353ab1943c193a Mon Sep 17 00:00:00 2001
From: Bhoomi Vaishnani
Date: Wed, 12 Aug 2020 13:25:15 -0400
Subject: [PATCH 3/3] [FIX] l10n_us_hr_payroll: Added exempt on filing status
for NY.
---
.../models/us_payroll_config.py | 1 +
.../tests/test_us_ny_new_york_payslip_2019.py | 27 +++++++++++++++++++
.../tests/test_us_ny_new_york_payslip_2020.py | 1 +
3 files changed, 29 insertions(+)
diff --git a/l10n_us_hr_payroll/models/us_payroll_config.py b/l10n_us_hr_payroll/models/us_payroll_config.py
index 6f6b8e70..4915b8d2 100644
--- a/l10n_us_hr_payroll/models/us_payroll_config.py
+++ b/l10n_us_hr_payroll/models/us_payroll_config.py
@@ -190,6 +190,7 @@ class HRContractUSPayrollConfig(models.Model):
], string='New Jersey Wage Chart Letter', help='NJ-W4. 3.')
ny_it2104_sit_filing_status = fields.Selection([
+ ('', 'Exempt'),
('single', 'Single'),
('married', 'Married'),
], string='New York NY IT-2104 Filing Status', help='NY IT-2104')
diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
index 973ea5ba..2c3b9306 100644
--- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
+++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2019.py
@@ -104,3 +104,30 @@ class TestUsNYPayslip(TestUsPayslip):
self.assertPayrollEqual(cats['EE_US_SIT'], wh)
+ def test_exempt_example3(self):
+ salary = 50000
+ schedule_pay = 'monthly'
+ allowances = 3
+ additional = 0
+ filing_status = ''
+ wh = 0.0
+
+ employee = self._createEmployee()
+
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('NY'),
+ ny_it2104_sit_filing_status=filing_status,
+ state_income_tax_additional_withholding=additional,
+ ny_it2104_sit_allowances=allowances,
+ schedule_pay=schedule_pay)
+
+ self._log('2019 New York tax first payslip:')
+ payslip = self._createPayslip(employee, '2019-01-01', '2019-01-31')
+
+ payslip.compute_sheet()
+
+ cats = self._getCategories(payslip)
+
+ self.assertPayrollEqual(cats['EE_US_SIT'], wh)
+
diff --git a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
index 763bd67d..b2b039b5 100644
--- a/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
+++ b/l10n_us_hr_payroll/tests/test_us_ny_new_york_payslip_2020.py
@@ -36,3 +36,4 @@ class TestUsNYPayslip(TestUsPayslip):
self._test_sit(50000.0, 'single', 0.0, 3, 'monthly', date(2020, 1, 1), 3575.63)
self._test_sit(50000.0, 'married', 0.0, 3, 'monthly', date(2020, 1, 1), 3619.82)
self._test_sit(50000.0, 'married', 10.0, 3, 'monthly', date(2020, 1, 1), 3629.83)
+ self._test_sit(50000.0, '', 0.0, 0, 'monthly', date(2020, 1, 1), 0.00)