From 757b03195ddbb99ca9fd266305db25e02217e9e8 Mon Sep 17 00:00:00 2001
From: Bhoomi Vaishnani
Date: Fri, 21 Feb 2020 17:05:11 -0500
Subject: [PATCH] IMP `l10n_us_hr_payroll` Port `l10n_us_ct_hr_payroll` CT
Connecticut including migration
---
l10n_us_hr_payroll/__manifest__.py | 1 +
.../data/state/ct_connecticut.xml | 1227 +++++++++++++++++
l10n_us_hr_payroll/models/hr_payslip.py | 2 +
.../models/state/ct_connecticut.py | 76 +
.../models/us_payroll_config.py | 8 +
l10n_us_hr_payroll/tests/__init__.py | 3 +
.../test_us_ct_connecticut_payslip_2019.py | 121 ++
.../test_us_ct_connecticut_payslip_2020.py | 34 +
.../views/us_payroll_config_views.xml | 5 +
9 files changed, 1477 insertions(+)
create mode 100644 l10n_us_hr_payroll/data/state/ct_connecticut.xml
create mode 100644 l10n_us_hr_payroll/models/state/ct_connecticut.py
create mode 100644 l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2019.py
create mode 100644 l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2020.py
diff --git a/l10n_us_hr_payroll/__manifest__.py b/l10n_us_hr_payroll/__manifest__.py
index 3f26f989..d9aa37e5 100644
--- a/l10n_us_hr_payroll/__manifest__.py
+++ b/l10n_us_hr_payroll/__manifest__.py
@@ -29,6 +29,7 @@ United States of America - Payroll Rules.
'data/state/al_alabama.xml',
'data/state/ar_arkansas.xml',
'data/state/az_arizona.xml',
+ 'data/state/ct_connecticut.xml',
'data/state/fl_florida.xml',
'data/state/ga_georgia.xml',
'data/state/il_illinois.xml',
diff --git a/l10n_us_hr_payroll/data/state/ct_connecticut.xml b/l10n_us_hr_payroll/data/state/ct_connecticut.xml
new file mode 100644
index 00000000..646b9373
--- /dev/null
+++ b/l10n_us_hr_payroll/data/state/ct_connecticut.xml
@@ -0,0 +1,1227 @@
+
+
+
+
+ US CT Connecticut SUTA Wage Base
+ us_ct_suta_wage_base
+
+
+
+
+ 15000.0
+
+
+
+
+ 15000.0
+
+
+
+
+
+
+
+ US CT Connecticut SUTA Rate
+ us_ct_suta_rate
+
+
+
+
+ 3.4
+
+
+
+
+ 3.2
+
+
+
+
+
+
+ US CT Connecticut SIT Initial Tax Rate
+ us_ct_sit_initial_tax_rate
+
+
+
+
+ {
+ 'a': [
+ ( 10000, 0, 3.00),
+ ( 50000, 300, 5.00),
+ (100000, 2300, 5.50),
+ (200000, 5050, 6.00),
+ (250000, 11050, 6.50),
+ (500000, 14300, 6.90),
+ ( 'inf', 31550, 6.99),
+ ],
+ 'b': [
+ ( 16000, 0, 3.00),
+ ( 80000, 480, 5.00),
+ (160000, 3680, 5.50),
+ (320000, 8080, 6.00),
+ (400000, 17680, 6.50),
+ (800000, 22880, 6.90),
+ ( 'inf', 50480, 6.99),
+ ],
+ 'c': [
+ ( 20000, 0, 3.00),
+ ( 100000, 600, 5.00),
+ ( 200000, 4600, 5.50),
+ ( 400000, 10100, 6.00),
+ ( 500000, 22100, 6.50),
+ (1000000, 28600, 6.90),
+ ( 'inf', 63100, 6.99),
+ ],
+ 'd': [
+ ( 10000, 0, 3.00),
+ ( 50000, 300, 5.00),
+ (100000, 2300, 5.50),
+ (200000, 5050, 6.00),
+ (250000, 11050, 6.50),
+ (500000, 14300, 6.90),
+ ( 'inf', 31550, 6.99),
+ ],
+ 'f': [
+ ( 10000, 0, 3.00),
+ ( 50000, 300, 5.00),
+ (100000, 2300, 5.50),
+ (200000, 5050, 6.00),
+ (250000, 11050, 6.50),
+ (500000, 14300, 6.90),
+ ( 'inf', 31550, 6.99),
+ ],
+ }
+
+
+
+
+ {
+ 'a': [
+ ( 10000, 0, 3.00),
+ ( 50000, 300, 5.00),
+ (100000, 2300, 5.50),
+ (200000, 5050, 6.00),
+ (250000, 11050, 6.50),
+ (500000, 14300, 6.90),
+ ( 'inf', 31550, 6.99),
+ ],
+ 'b': [
+ ( 16000, 0, 3.00),
+ ( 80000, 480, 5.00),
+ (160000, 3680, 5.50),
+ (320000, 8080, 6.00),
+ (400000, 17680, 6.50),
+ (800000, 22880, 6.90),
+ ( 'inf', 50480, 6.99),
+ ],
+ 'c': [
+ ( 20000, 0, 3.00),
+ ( 100000, 600, 5.00),
+ ( 200000, 4600, 5.50),
+ ( 400000, 10100, 6.00),
+ ( 500000, 22100, 6.50),
+ (1000000, 28600, 6.90),
+ ( 'inf', 63100, 6.99),
+ ],
+ 'd': [
+ ( 10000, 0, 3.00),
+ ( 50000, 300, 5.00),
+ (100000, 2300, 5.50),
+ (200000, 5050, 6.00),
+ (250000, 11050, 6.50),
+ (500000, 14300, 6.90),
+ ( 'inf', 31550, 6.99),
+ ],
+ 'f': [
+ ( 10000, 0, 3.00),
+ ( 50000, 300, 5.00),
+ (100000, 2300, 5.50),
+ (200000, 5050, 6.00),
+ (250000, 11050, 6.50),
+ (500000, 14300, 6.90),
+ ( 'inf', 31550, 6.99),
+ ],
+ }
+
+
+
+
+
+
+ US CT Connecticut Tax Rate
+ us_ct_sit_tax_rate
+
+
+
+
+ {
+ 'a': [
+ (50250, 0),
+ (52750, 20),
+ (55250, 40),
+ (57750, 60),
+ (60250, 80),
+ (62750, 100),
+ (65250, 120),
+ (67750, 140),
+ (70250, 160),
+ (72750, 180),
+ ('inf', 200),
+ ],
+ 'b': [
+ ( 78500, 0),
+ ( 82500, 32),
+ ( 86500, 64),
+ ( 90500, 96),
+ ( 94500, 128),
+ ( 98500, 160),
+ (102500, 192),
+ (106500, 224),
+ (110500, 256),
+ (114500, 288),
+ ( 'inf', 320),
+ ],
+ 'c': [
+ (100500, 0),
+ (105500, 40),
+ (110500, 80),
+ (115500, 120),
+ (120500, 160),
+ (125500, 200),
+ (130500, 240),
+ (135500, 280),
+ (140500, 320),
+ (145500, 360),
+ ( 'inf', 400),
+
+ ],
+ 'd': [
+ (50250, 0),
+ (52750, 20),
+ (55250, 40),
+ (57750, 60),
+ (60250, 80),
+ (62750, 100),
+ (65250, 120),
+ (67750, 140),
+ (70250, 160),
+ (72750, 180),
+ ('inf', 200),
+ ],
+ 'f': [
+ ( 56500, 0),
+ ( 61500, 20),
+ ( 66500, 40),
+ ( 71500, 60),
+ ( 76500, 80),
+ ( 81500, 100),
+ ( 86500, 120),
+ ( 91500, 140),
+ ( 96500, 160),
+ (101500, 180),
+ ( 'inf', 200),
+ ],
+ }
+
+
+
+
+ {
+ 'a': [
+ (50250, 0),
+ (52750, 20),
+ (55250, 40),
+ (57750, 60),
+ (60250, 80),
+ (62750, 100),
+ (65250, 120),
+ (67750, 140),
+ (70250, 160),
+ (72750, 180),
+ ('inf', 200),
+ ],
+ 'b': [
+ ( 78500, 0),
+ ( 82500, 32),
+ ( 86500, 64),
+ ( 90500, 96),
+ ( 94500, 128),
+ ( 98500, 160),
+ (102500, 192),
+ (106500, 224),
+ (110500, 256),
+ (114500, 288),
+ ( 'inf', 320),
+ ],
+ 'c': [
+ (100500, 0),
+ (105500, 40),
+ (110500, 80),
+ (115500, 120),
+ (120500, 160),
+ (125500, 200),
+ (130500, 240),
+ (135500, 280),
+ (140500, 320),
+ (145500, 360),
+ ( 'inf', 400),
+
+ ],
+ 'd': [
+ (50250, 0),
+ (52750, 20),
+ (55250, 40),
+ (57750, 60),
+ (60250, 80),
+ (62750, 100),
+ (65250, 120),
+ (67750, 140),
+ (70250, 160),
+ (72750, 180),
+ ('inf', 200),
+ ],
+ 'f': [
+ ( 56500, 0),
+ ( 61500, 20),
+ ( 66500, 40),
+ ( 71500, 60),
+ ( 76500, 80),
+ ( 81500, 100),
+ ( 86500, 120),
+ ( 91500, 140),
+ ( 96500, 160),
+ (101500, 180),
+ ( 'inf', 200),
+ ],
+ }
+
+
+
+
+
+
+ US CT Connecticut Decimal Rate
+ us_ct_sit_decimal_rate
+
+
+
+
+ {
+ 'a': [
+ (15000, 0.75),
+ (15500, 0.70),
+ (16000, 0.65),
+ (16500, 0.60),
+ (17000, 0.55),
+ (17500, 0.50),
+ (18000, 0.45),
+ (18500, 0.40),
+ (20000, 0.35),
+ (20500, 0.30),
+ (21000, 0.25),
+ (21500, 0.20),
+ (25000, 0.15),
+ (25500, 0.14),
+ (26000, 0.13),
+ (26500, 0.12),
+ (27000, 0.11),
+ (48000, 0.10),
+ (48500, 0.09),
+ (49000, 0.08),
+ (49500, 0.08),
+ (50000, 0.06),
+ (50500, 0.05),
+ (51000, 0.03),
+ (51500, 0.03),
+ (52000, 0.02),
+ (52500, 0.01),
+ ('inf', 0.00),
+ ],
+ 'b': [
+ (24000, 0.75),
+ (24500, 0.70),
+ (25000, 0.65),
+ (25500, 0.60),
+ (26000, 0.55),
+ (26500, 0.50),
+ (27000, 0.45),
+ (27500, 0.40),
+ (34000, 0.35),
+ (34500, 0.30),
+ (35000, 0.25),
+ (35500, 0.20),
+ (44000, 0.15),
+ (44500, 0.14),
+ (45000, 0.13),
+ (45500, 0.12),
+ (46000, 0.11),
+ (74000, 0.10),
+ (74500, 0.09),
+ (75000, 0.08),
+ (75500, 0.08),
+ (76000, 0.06),
+ (76500, 0.05),
+ (77000, 0.03),
+ (77500, 0.03),
+ (78000, 0.02),
+ (78500, 0.01),
+ ('inf', 0.00),
+ ],
+ 'c': [
+ (30000, 0.75),
+ (30500, 0.70),
+ (31000, 0.65),
+ (31500, 0.60),
+ (32000, 0.55),
+ (32500, 0.50),
+ (33000, 0.45),
+ (33500, 0.40),
+ (40000, 0.35),
+ (40500, 0.30),
+ (41000, 0.25),
+ (41500, 0.20),
+ (50000, 0.15),
+ (50500, 0.14),
+ (51000, 0.13),
+ (51500, 0.12),
+ (52000, 0.11),
+ (96000, 0.10),
+ (96500, 0.09),
+ (97000, 0.08),
+ (97500, 0.08),
+ (98000, 0.06),
+ (98500, 0.05),
+ (99000, 0.03),
+ (99500, 0.03),
+ (100000, 0.02),
+ (100500, 0.01),
+ ('inf', 0.00),
+ ],
+ 'f': [
+ (18800, 0.75),
+ (19300, 0.70),
+ (19800, 0.65),
+ (20300, 0.60),
+ (20800, 0.55),
+ (21300, 0.50),
+ (21800, 0.45),
+ (22300, 0.40),
+ (25000, 0.35),
+ (25500, 0.30),
+ (26000, 0.25),
+ (26500, 0.20),
+ (31300, 0.15),
+ (31800, 0.14),
+ (32300, 0.13),
+ (32800, 0.12),
+ (33300, 0.11),
+ (60000, 0.10),
+ (60500, 0.09),
+ (61000, 0.08),
+ (61500, 0.08),
+ (62000, 0.06),
+ (62500, 0.05),
+ (63000, 0.03),
+ (63500, 0.03),
+ (64000, 0.02),
+ (64500, 0.01),
+ ('inf', 0.00),
+ ],
+ }
+
+
+
+
+ {
+ 'a': [
+ (15000, 0.75),
+ (15500, 0.70),
+ (16000, 0.65),
+ (16500, 0.60),
+ (17000, 0.55),
+ (17500, 0.50),
+ (18000, 0.45),
+ (18500, 0.40),
+ (20000, 0.35),
+ (20500, 0.30),
+ (21000, 0.25),
+ (21500, 0.20),
+ (25000, 0.15),
+ (25500, 0.14),
+ (26000, 0.13),
+ (26500, 0.12),
+ (27000, 0.11),
+ (48000, 0.10),
+ (48500, 0.09),
+ (49000, 0.08),
+ (49500, 0.08),
+ (50000, 0.06),
+ (50500, 0.05),
+ (51000, 0.03),
+ (51500, 0.03),
+ (52000, 0.02),
+ (52500, 0.01),
+ ('inf', 0.00),
+ ],
+ 'b': [
+ (24000, 0.75),
+ (24500, 0.70),
+ (25000, 0.65),
+ (25500, 0.60),
+ (26000, 0.55),
+ (26500, 0.50),
+ (27000, 0.45),
+ (27500, 0.40),
+ (34000, 0.35),
+ (34500, 0.30),
+ (35000, 0.25),
+ (35500, 0.20),
+ (44000, 0.15),
+ (44500, 0.14),
+ (45000, 0.13),
+ (45500, 0.12),
+ (46000, 0.11),
+ (74000, 0.10),
+ (74500, 0.09),
+ (75000, 0.08),
+ (75500, 0.08),
+ (76000, 0.06),
+ (76500, 0.05),
+ (77000, 0.03),
+ (77500, 0.03),
+ (78000, 0.02),
+ (78500, 0.01),
+ ('inf', 0.00),
+ ],
+ 'c': [
+ (30000, 0.75),
+ (30500, 0.70),
+ (31000, 0.65),
+ (31500, 0.60),
+ (32000, 0.55),
+ (32500, 0.50),
+ (33000, 0.45),
+ (33500, 0.40),
+ (40000, 0.35),
+ (40500, 0.30),
+ (41000, 0.25),
+ (41500, 0.20),
+ (50000, 0.15),
+ (50500, 0.14),
+ (51000, 0.13),
+ (51500, 0.12),
+ (52000, 0.11),
+ (96000, 0.10),
+ (96500, 0.09),
+ (97000, 0.08),
+ (97500, 0.08),
+ (98000, 0.06),
+ (98500, 0.05),
+ (99000, 0.03),
+ (99500, 0.03),
+ (100000, 0.02),
+ (100500, 0.01),
+ ('inf', 0.00),
+ ],
+ 'f': [
+ (18800, 0.75),
+ (19300, 0.70),
+ (19800, 0.65),
+ (20300, 0.60),
+ (20800, 0.55),
+ (21300, 0.50),
+ (21800, 0.45),
+ (22300, 0.40),
+ (25000, 0.35),
+ (25500, 0.30),
+ (26000, 0.25),
+ (26500, 0.20),
+ (31300, 0.15),
+ (31800, 0.14),
+ (32300, 0.13),
+ (32800, 0.12),
+ (33300, 0.11),
+ (60000, 0.10),
+ (60500, 0.09),
+ (61000, 0.08),
+ (61500, 0.08),
+ (62000, 0.06),
+ (62500, 0.05),
+ (63000, 0.03),
+ (63500, 0.03),
+ (64000, 0.02),
+ (64500, 0.01),
+ ('inf', 0.00),
+ ],
+ }
+
+
+
+
+
+
+ US CT Connecticut Recapture Rate
+ us_ct_sit_recapture_rate
+
+
+
+
+ {
+ 'a': [
+ (200000, 0),
+ (205000, 90),
+ (210000, 180),
+ (215000, 270),
+ (220000, 360),
+ (225000, 450),
+ (230000, 540),
+ (235000, 630),
+ (240000, 720),
+ (245000, 810),
+ (250000, 900),
+ (255000, 990),
+ (260000, 1080),
+ (265000, 1170),
+ (270000, 1260),
+ (275000, 1350),
+ (280000, 1440),
+ (285000, 1530),
+ (290000, 1620),
+ (295000, 1710),
+ (300000, 1800),
+ (305000, 1890),
+ (310000, 1980),
+ (315000, 2070),
+ (320000, 2160),
+ (325000, 2250),
+ (330000, 2340),
+ (335000, 2430),
+ (340000, 2520),
+ (345000, 2610),
+ (500000, 2700),
+ (505000, 2750),
+ (510000, 2800),
+ (515000, 2850),
+ (520000, 2900),
+ (525000, 2950),
+ (530000, 3000),
+ (535000, 3050),
+ (540000, 3100),
+ ( 'inf', 200),
+ ],
+ 'b': [
+ (320000, 0),
+ (328000, 140),
+ (336000, 280),
+ (344000, 420),
+ (352000, 560),
+ (360000, 700),
+ (368000, 840),
+ (376000, 980),
+ (384000, 1120),
+ (392000, 1260),
+ (400000, 1400),
+ (408000, 1540),
+ (416000, 1680),
+ (424000, 1820),
+ (432000, 1960),
+ (440000, 2100),
+ (448000, 2240),
+ (456000, 2380),
+ (464000, 2520),
+ (472000, 2660),
+ (480000, 2800),
+ (488000, 2940),
+ (496000, 3080),
+ (504000, 3220),
+ (512000, 3360),
+ (520000, 3500),
+ (528000, 3640),
+ (536000, 3780),
+ (544000, 3920),
+ (552000, 4060),
+ (800000, 4200),
+ (808000, 4280),
+ (816000, 4360),
+ (824000, 4440),
+ (832000, 4520),
+ (840000, 4600),
+ (848000, 4680),
+ (856000, 4760),
+ (864000, 4840),
+ ( 'inf', 4920),
+ ],
+ 'c': [
+ ( 400000, 0),
+ ( 410000, 180),
+ ( 420000, 360),
+ ( 430000, 540),
+ ( 440000, 720),
+ ( 450000, 900),
+ ( 460000, 1080),
+ ( 470000, 1260),
+ ( 480000, 1440),
+ ( 490000, 1620),
+ ( 500000, 1800),
+ ( 510000, 1980),
+ ( 520000, 2160),
+ ( 530000, 2340),
+ ( 540000, 2520),
+ ( 550000, 2700),
+ ( 560000, 2880),
+ ( 570000, 3060),
+ ( 580000, 3240),
+ ( 590000, 3420),
+ ( 600000, 3600),
+ ( 610000, 3780),
+ ( 620000, 3960),
+ ( 630000, 4140),
+ ( 640000, 4320),
+ ( 650000, 4500),
+ ( 660000, 4680),
+ ( 670000, 4860),
+ ( 680000, 5040),
+ ( 690000, 5220),
+ (1000000, 5400),
+ (1010000, 5500),
+ (1020000, 5600),
+ (1030000, 5700),
+ (1040000, 5800),
+ (1050000, 5900),
+ (1060000, 6000),
+ (1070000, 6100),
+ (1080000, 6200),
+ ( 'inf', 6300),
+ ],
+ 'd': [
+ (200000, 0),
+ (205000, 90),
+ (210000, 180),
+ (215000, 270),
+ (220000, 360),
+ (225000, 450),
+ (230000, 540),
+ (235000, 630),
+ (240000, 720),
+ (245000, 810),
+ (250000, 900),
+ (255000, 990),
+ (260000, 1080),
+ (265000, 1170),
+ (270000, 1260),
+ (275000, 1350),
+ (280000, 1440),
+ (285000, 1530),
+ (290000, 1620),
+ (295000, 1710),
+ (300000, 1800),
+ (305000, 1890),
+ (310000, 1980),
+ (315000, 2070),
+ (320000, 2160),
+ (325000, 2250),
+ (330000, 2340),
+ (335000, 2430),
+ (340000, 2520),
+ (345000, 2610),
+ (500000, 2700),
+ (505000, 2750),
+ (510000, 2800),
+ (515000, 2850),
+ (520000, 2900),
+ (525000, 2950),
+ (530000, 3000),
+ (535000, 3050),
+ (540000, 3100),
+ ( 'inf', 200),
+ ],
+ 'f': [
+ (200000, 0),
+ (205000, 90),
+ (210000, 180),
+ (215000, 270),
+ (220000, 360),
+ (225000, 450),
+ (230000, 540),
+ (235000, 630),
+ (240000, 720),
+ (245000, 810),
+ (250000, 900),
+ (255000, 990),
+ (260000, 1080),
+ (265000, 1170),
+ (270000, 1260),
+ (275000, 1350),
+ (280000, 1440),
+ (285000, 1530),
+ (290000, 1620),
+ (295000, 1710),
+ (300000, 1800),
+ (305000, 1890),
+ (310000, 1980),
+ (315000, 2070),
+ (320000, 2160),
+ (325000, 2250),
+ (330000, 2340),
+ (335000, 2430),
+ (340000, 2520),
+ (345000, 2610),
+ (500000, 2700),
+ (505000, 2750),
+ (510000, 2800),
+ (515000, 2850),
+ (520000, 2900),
+ (525000, 2950),
+ (530000, 3000),
+ (535000, 3050),
+ (540000, 3100),
+ ( 'inf', 200),
+ ],
+ }
+
+
+
+
+ {
+ 'a': [
+ (200000, 0),
+ (205000, 90),
+ (210000, 180),
+ (215000, 270),
+ (220000, 360),
+ (225000, 450),
+ (230000, 540),
+ (235000, 630),
+ (240000, 720),
+ (245000, 810),
+ (250000, 900),
+ (255000, 990),
+ (260000, 1080),
+ (265000, 1170),
+ (270000, 1260),
+ (275000, 1350),
+ (280000, 1440),
+ (285000, 1530),
+ (290000, 1620),
+ (295000, 1710),
+ (300000, 1800),
+ (305000, 1890),
+ (310000, 1980),
+ (315000, 2070),
+ (320000, 2160),
+ (325000, 2250),
+ (330000, 2340),
+ (335000, 2430),
+ (340000, 2520),
+ (345000, 2610),
+ (500000, 2700),
+ (505000, 2750),
+ (510000, 2800),
+ (515000, 2850),
+ (520000, 2900),
+ (525000, 2950),
+ (530000, 3000),
+ (535000, 3050),
+ (540000, 3100),
+ ( 'inf', 200),
+ ],
+ 'b': [
+ (320000, 0),
+ (328000, 140),
+ (336000, 280),
+ (344000, 420),
+ (352000, 560),
+ (360000, 700),
+ (368000, 840),
+ (376000, 980),
+ (384000, 1120),
+ (392000, 1260),
+ (400000, 1400),
+ (408000, 1540),
+ (416000, 1680),
+ (424000, 1820),
+ (432000, 1960),
+ (440000, 2100),
+ (448000, 2240),
+ (456000, 2380),
+ (464000, 2520),
+ (472000, 2660),
+ (480000, 2800),
+ (488000, 2940),
+ (496000, 3080),
+ (504000, 3220),
+ (512000, 3360),
+ (520000, 3500),
+ (528000, 3640),
+ (536000, 3780),
+ (544000, 3920),
+ (552000, 4060),
+ (800000, 4200),
+ (808000, 4280),
+ (816000, 4360),
+ (824000, 4440),
+ (832000, 4520),
+ (840000, 4600),
+ (848000, 4680),
+ (856000, 4760),
+ (864000, 4840),
+ ( 'inf', 4920),
+ ],
+ 'c': [
+ ( 400000, 0),
+ ( 410000, 180),
+ ( 420000, 360),
+ ( 430000, 540),
+ ( 440000, 720),
+ ( 450000, 900),
+ ( 460000, 1080),
+ ( 470000, 1260),
+ ( 480000, 1440),
+ ( 490000, 1620),
+ ( 500000, 1800),
+ ( 510000, 1980),
+ ( 520000, 2160),
+ ( 530000, 2340),
+ ( 540000, 2520),
+ ( 550000, 2700),
+ ( 560000, 2880),
+ ( 570000, 3060),
+ ( 580000, 3240),
+ ( 590000, 3420),
+ ( 600000, 3600),
+ ( 610000, 3780),
+ ( 620000, 3960),
+ ( 630000, 4140),
+ ( 640000, 4320),
+ ( 650000, 4500),
+ ( 660000, 4680),
+ ( 670000, 4860),
+ ( 680000, 5040),
+ ( 690000, 5220),
+ (1000000, 5400),
+ (1010000, 5500),
+ (1020000, 5600),
+ (1030000, 5700),
+ (1040000, 5800),
+ (1050000, 5900),
+ (1060000, 6000),
+ (1070000, 6100),
+ (1080000, 6200),
+ ( 'inf', 6300),
+ ],
+ 'd': [
+ (200000, 0),
+ (205000, 90),
+ (210000, 180),
+ (215000, 270),
+ (220000, 360),
+ (225000, 450),
+ (230000, 540),
+ (235000, 630),
+ (240000, 720),
+ (245000, 810),
+ (250000, 900),
+ (255000, 990),
+ (260000, 1080),
+ (265000, 1170),
+ (270000, 1260),
+ (275000, 1350),
+ (280000, 1440),
+ (285000, 1530),
+ (290000, 1620),
+ (295000, 1710),
+ (300000, 1800),
+ (305000, 1890),
+ (310000, 1980),
+ (315000, 2070),
+ (320000, 2160),
+ (325000, 2250),
+ (330000, 2340),
+ (335000, 2430),
+ (340000, 2520),
+ (345000, 2610),
+ (500000, 2700),
+ (505000, 2750),
+ (510000, 2800),
+ (515000, 2850),
+ (520000, 2900),
+ (525000, 2950),
+ (530000, 3000),
+ (535000, 3050),
+ (540000, 3100),
+ ( 'inf', 200),
+ ],
+ 'f': [
+ (200000, 0),
+ (205000, 90),
+ (210000, 180),
+ (215000, 270),
+ (220000, 360),
+ (225000, 450),
+ (230000, 540),
+ (235000, 630),
+ (240000, 720),
+ (245000, 810),
+ (250000, 900),
+ (255000, 990),
+ (260000, 1080),
+ (265000, 1170),
+ (270000, 1260),
+ (275000, 1350),
+ (280000, 1440),
+ (285000, 1530),
+ (290000, 1620),
+ (295000, 1710),
+ (300000, 1800),
+ (305000, 1890),
+ (310000, 1980),
+ (315000, 2070),
+ (320000, 2160),
+ (325000, 2250),
+ (330000, 2340),
+ (335000, 2430),
+ (340000, 2520),
+ (345000, 2610),
+ (500000, 2700),
+ (505000, 2750),
+ (510000, 2800),
+ (515000, 2850),
+ (520000, 2900),
+ (525000, 2950),
+ (530000, 3000),
+ (535000, 3050),
+ (540000, 3100),
+ ( 'inf', 200),
+ ],
+ }
+
+
+
+
+
+
+ US CT Connecticut Personal Exemption Rate
+ us_ct_sit_personal_exemption_rate
+
+
+
+
+ {
+ 'a' : [
+ (24000, 12000),
+ (25000, 11000),
+ (26000, 10000),
+ (27000, 9000),
+ (28000, 8000),
+ (29000, 7000),
+ (30000, 6000),
+ (31000, 5000),
+ (32000, 4000),
+ (33000, 3000),
+ (34000, 2000),
+ (35000, 1000),
+ ('inf', 0),
+ ],
+ 'b' : [
+ (38000, 19000),
+ (39000, 18000),
+ (40000, 17000),
+ (41000, 16000),
+ (42000, 15000),
+ (43000, 14000),
+ (44000, 13000),
+ (45000, 12000),
+ (46000, 11000),
+ (47000, 10000),
+ (48000, 9000),
+ (49000, 8000),
+ (50000, 7000),
+ (51000, 6000),
+ (52000, 5000),
+ (53000, 4000),
+ (54000, 3000),
+ (55000, 2000),
+ (56000, 1000),
+ ('inf', 0),
+ ],
+ 'c': [
+ (48000, 24000),
+ (49000, 23000),
+ (50000, 22000),
+ (51000, 21000),
+ (52000, 20000),
+ (53000, 19000),
+ (54000, 18000),
+ (55000, 17000),
+ (56000, 16000),
+ (57000, 15000),
+ (58000, 14000),
+ (59000, 13000),
+ (60000, 12000),
+ (61000, 11000),
+ (62000, 10000),
+ (63000, 9000),
+ (64000, 8000),
+ (65000, 7000),
+ (66000, 6000),
+ (67000, 5000),
+ (68000, 4000),
+ (69000, 3000),
+ (70000, 2000),
+ (71000, 1000),
+ ('inf', 0),
+ ],
+ 'f' : [
+ (30000, 15000),
+ (31000, 14000),
+ (22000, 13000),
+ (33000, 12000),
+ (34000, 11000),
+ (35000, 10000),
+ (36000, 9000),
+ (37000, 8000),
+ (38000, 7000),
+ (39000, 6000),
+ (40000, 5000),
+ (41000, 4000),
+ (42000, 3000),
+ (43000, 2000),
+ (44000, 1000),
+ ('inf', 0),
+ ],
+ }
+
+
+
+
+ {
+ 'a' : [
+ (24000, 12000),
+ (25000, 11000),
+ (26000, 10000),
+ (27000, 9000),
+ (28000, 8000),
+ (29000, 7000),
+ (30000, 6000),
+ (31000, 5000),
+ (32000, 4000),
+ (33000, 3000),
+ (34000, 2000),
+ (35000, 1000),
+ ('inf', 0),
+ ],
+ 'b' : [
+ (38000, 19000),
+ (39000, 18000),
+ (40000, 17000),
+ (41000, 16000),
+ (42000, 15000),
+ (43000, 14000),
+ (44000, 13000),
+ (45000, 12000),
+ (46000, 11000),
+ (47000, 10000),
+ (48000, 9000),
+ (49000, 8000),
+ (50000, 7000),
+ (51000, 6000),
+ (52000, 5000),
+ (53000, 4000),
+ (54000, 3000),
+ (55000, 2000),
+ (56000, 1000),
+ ('inf', 0),
+ ],
+ 'c': [
+ (48000, 24000),
+ (49000, 23000),
+ (50000, 22000),
+ (51000, 21000),
+ (52000, 20000),
+ (53000, 19000),
+ (54000, 18000),
+ (55000, 17000),
+ (56000, 16000),
+ (57000, 15000),
+ (58000, 14000),
+ (59000, 13000),
+ (60000, 12000),
+ (61000, 11000),
+ (62000, 10000),
+ (63000, 9000),
+ (64000, 8000),
+ (65000, 7000),
+ (66000, 6000),
+ (67000, 5000),
+ (68000, 4000),
+ (69000, 3000),
+ (70000, 2000),
+ (71000, 1000),
+ ('inf', 0),
+ ],
+ 'f' : [
+ (30000, 15000),
+ (31000, 14000),
+ (22000, 13000),
+ (33000, 12000),
+ (34000, 11000),
+ (35000, 10000),
+ (36000, 9000),
+ (37000, 8000),
+ (38000, 7000),
+ (39000, 6000),
+ (40000, 5000),
+ (41000, 4000),
+ (42000, 3000),
+ (43000, 2000),
+ (44000, 1000),
+ ('inf', 0),
+ ],
+ }
+
+
+
+
+
+
+
+ US Connecticut - Department of Labor (CDOL) - Unemployment Tax
+
+
+
+ US Connecticut - Department of Revenue Services (CDRS) - Income Tax
+
+
+
+
+
+
+
+
+
+ ER: US CT Connecticut State Unemployment
+ ER_US_CT_SUTA
+ python
+ result, _ = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ct_suta_wage_base', rate='us_ct_suta_rate', state_code='CT')
+ code
+ result, result_rate = general_state_unemployment(payslip, categories, worked_days, inputs, wage_base='us_ct_suta_wage_base', rate='us_ct_suta_rate', state_code='CT')
+
+
+
+
+
+
+
+
+ EE: US CT Connecticut State Income Tax Withholding
+ EE_US_CT_SIT
+ python
+ result, _ = ct_connecticut_state_income_withholding(payslip, categories, worked_days, inputs)
+ code
+ result, result_rate = ct_connecticut_state_income_withholding(payslip, categories, worked_days, inputs)
+
+
+
+
+
\ No newline at end of file
diff --git a/l10n_us_hr_payroll/models/hr_payslip.py b/l10n_us_hr_payroll/models/hr_payslip.py
index 3d52d04c..330ae93e 100644
--- a/l10n_us_hr_payroll/models/hr_payslip.py
+++ b/l10n_us_hr_payroll/models/hr_payslip.py
@@ -15,6 +15,7 @@ from .state.general import general_state_unemployment, \
from .state.al_alabama import al_alabama_state_income_withholding
from .state.ar_arkansas import ar_arkansas_state_income_withholding
from .state.az_arizona import az_arizona_state_income_withholding
+from .state.ct_connecticut import ct_connecticut_state_income_withholding
from .state.ga_georgia import ga_georgia_state_income_withholding
from .state.il_illinois import il_illinois_state_income_withholding
from .state.mi_michigan import mi_michigan_state_income_withholding
@@ -62,6 +63,7 @@ class HRPayslip(models.Model):
'al_alabama_state_income_withholding': al_alabama_state_income_withholding,
'ar_arkansas_state_income_withholding': ar_arkansas_state_income_withholding,
'az_arizona_state_income_withholding': az_arizona_state_income_withholding,
+ 'ct_connecticut_state_income_withholding': ct_connecticut_state_income_withholding,
'ga_georgia_state_income_withholding': ga_georgia_state_income_withholding,
'il_illinois_state_income_withholding': il_illinois_state_income_withholding,
'mi_michigan_state_income_withholding': mi_michigan_state_income_withholding,
diff --git a/l10n_us_hr_payroll/models/state/ct_connecticut.py b/l10n_us_hr_payroll/models/state/ct_connecticut.py
new file mode 100644
index 00000000..344dc9c8
--- /dev/null
+++ b/l10n_us_hr_payroll/models/state/ct_connecticut.py
@@ -0,0 +1,76 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from .general import _state_applies, sit_wage
+
+
+def ct_connecticut_state_income_withholding(payslip, categories, worked_days, inputs):
+ """
+ Returns SIT eligible wage and rate.
+
+ :return: result, result_rate (wage, percent)
+ """
+ state_code = 'CT'
+ 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
+
+ pay_periods = payslip.dict.get_pay_periods_in_year()
+ additional = payslip.contract_id.us_payroll_config_value('state_income_tax_additional_withholding')
+ withholding_code = payslip.contract_id.us_payroll_config_value('ct_w4na_sit_code')
+ exemption_table = payslip.rule_parameter('us_ct_sit_personal_exemption_rate').get(withholding_code, [('inf', 0.0)])
+ initial_tax_tbl = payslip.rule_parameter('us_ct_sit_initial_tax_rate').get(withholding_code, [('inf', 0.0, 0.0)])
+ tax_table = payslip.rule_parameter('us_ct_sit_tax_rate').get(withholding_code, [('inf', 0.0)])
+ recapture_table = payslip.rule_parameter('us_ct_sit_recapture_rate').get(withholding_code, [('inf', 0.0)])
+ decimal_table = payslip.rule_parameter('us_ct_sit_decimal_rate').get(withholding_code, [('inf', 0.0)])
+
+ annual_wages = wage * pay_periods
+ personal_exemption = 0.0
+ for bracket in exemption_table:
+ if annual_wages <= float(bracket[0]):
+ personal_exemption = bracket[1]
+ break
+
+ withholding = 0.0
+ taxable_income = annual_wages - personal_exemption
+ if taxable_income < 0.0:
+ taxable_income = 0.0
+
+ if taxable_income:
+ initial_tax = 0.0
+ last = 0.0
+ for bracket in initial_tax_tbl:
+ if taxable_income <= float(bracket[0]):
+ initial_tax = bracket[1] + ((bracket[2] / 100.0) * (taxable_income - last))
+ break
+ last = bracket[0]
+
+ tax_add_back = 0.0
+ for bracket in tax_table:
+ if annual_wages <= float(bracket[0]):
+ tax_add_back = bracket[1]
+ break
+
+ recapture_amount = 0.0
+ for bracket in recapture_table:
+ if annual_wages <= float(bracket[0]):
+ recapture_amount = bracket[1]
+ break
+
+ withholding = initial_tax + tax_add_back + recapture_amount
+ decimal_amount = 1.0
+ for bracket in decimal_table:
+ if annual_wages <= float(bracket[0]):
+ decimal_amount= bracket[1]
+ break
+
+ withholding = withholding * (1.00 - decimal_amount)
+ if withholding < 0.0:
+ withholding = 0.0
+ withholding /= pay_periods
+
+ 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 69dc69c2..c038396c 100644
--- a/l10n_us_hr_payroll/models/us_payroll_config.py
+++ b/l10n_us_hr_payroll/models/us_payroll_config.py
@@ -66,6 +66,14 @@ class HRContractUSPayrollConfig(models.Model):
string='Arizona A-4 Withholding Percentage',
help='A-4 1. (0.8 or 1.3 or 1.8 or 2.7 or 3.6 or 4.2 or 5.1 or 0 for exempt.')
+ ct_w4na_sit_code = fields.Selection([
+ ('a', 'A'),
+ ('b', 'B'),
+ ('c', 'C'),
+ ('d', 'D'),
+ ('f', 'F'),
+ ], string='Connecticut CT-W4 Withholding Code', help='CT-W4 1.')
+
ga_g4_sit_filing_status = fields.Selection([
('exempt', 'Exempt'),
('single', 'Single'),
diff --git a/l10n_us_hr_payroll/tests/__init__.py b/l10n_us_hr_payroll/tests/__init__.py
index 1ded7fb4..92176b7f 100755
--- a/l10n_us_hr_payroll/tests/__init__.py
+++ b/l10n_us_hr_payroll/tests/__init__.py
@@ -16,6 +16,9 @@ from . import test_us_ar_arkansas_payslip_2020
from . import test_us_az_arizona_payslip_2019
from . import test_us_az_arizona_payslip_2020
+from . import test_us_ct_connecticut_payslip_2019
+from . import test_us_ct_connecticut_payslip_2020
+
from . import test_us_fl_florida_payslip_2019
from . import test_us_fl_florida_payslip_2020
diff --git a/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2019.py b/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2019.py
new file mode 100644
index 00000000..ab423131
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2019.py
@@ -0,0 +1,121 @@
+# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
+
+from .common import TestUsPayslip, process_payslip
+
+
+class TestUsCTPayslip(TestUsPayslip):
+ # TAXES AND RATES
+ CT_UNEMP_MAX_WAGE = 15000.00
+ CT_UNEMP = -(3.40 / 100.0)
+
+ def test_taxes_weekly_with_additional_wh(self):
+
+ # Tax tables can be found here:
+ # https://portal.ct.gov/-/media/DRS/Publications/pubsip/2019/IP-2019(1).pdf?la=en
+ # Step 1 - Wages per period -> 10000.00
+ salary = 10000.00
+ # Step 2 and 3 - Annual wages -> 10000.00 * 52.0 -> 520000.0
+ schedule_pay = 'weekly'
+ # Step 4 Employee Withholding Code -> A
+ wh_code = 'a'
+ # Step 5 - Use annual wages and withholding code with table for exemption amount.
+ # exemption_amt = 0 since highest bracket.
+ # Step 6 - Subtract 5 from 3 for taxable income.
+ # taxable income = 520000.00 since we do not have an exemption.
+ # Step 7 - Determine initial amount from table
+ # initial = 31550 + ((6.99 / 100) * (520000.00 - 500000.00))
+ # 32948.0
+ # Step 8 - Determine the tax rate phase out add back from table.
+ # phase_out = 200
+ # Step 9 - Determine the recapture amount from table.
+ # Close to top, but not top. -> 2900
+ # Step 10 - Add Step 7, 8, 9
+ # 32948.0 + 200 + 2900.00 - > 36048.0
+ # Step 11 - Determine decimal amount from personal tax credits.
+ # We get no tax credit.
+ # Step 12 - Multiple Step 10 by 1.00 - Step 11
+ # 36048.0 * 1.00 = 36048.0
+ # Step 13 - Divide by the number of pay periods.
+ # 36048.0 / 52.0 = 693.23
+ # Step 14 & 15 & 16- Add / Subtract the additional or under withholding amount. Then Add this to the amount
+ # for withholding per period.
+ additional_wh = 12.50
+ # 693.23 + 12.50 ->
+ wh = -705.73
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('CT'),
+ ct_w4na_sit_code=wh_code,
+ state_income_tax_additional_withholding=additional_wh,
+ schedule_pay=schedule_pay)
+
+ self._log('2019 Connecticut 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'], salary * self.CT_UNEMP)
+ self.assertPayrollEqual(cats['EE_US_SIT'], wh)
+
+ process_payslip(payslip)
+
+ remaining_CT_UNEMP_wages = 5000.00 # We already reached the maximum wage for unemployment insurance.
+ self._log('2019 Connecticut 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_CT_UNEMP_wages * self.CT_UNEMP)
+
+ def test_taxes_weekly_with_different_code(self):
+
+ # Tax tables can be found here:
+ # https://portal.ct.gov/-/media/DRS/Publications/pubsip/2019/IP-2019(1).pdf?la=en
+ # Step 1 - Wages per period -> 15000.00
+ salary = 15000.00
+ # Step 2 and 3 - Annual wages -> 15000.00 * 12.0 -> 180000.0
+ schedule_pay = 'monthly'
+ # Step 4 Employee Withholding Code -> B
+ wh_code = 'b'
+ # Step 5 - Use annual wages and withholding code with table for exemption amount.
+ # exemption_amt = 0 since highest bracket.
+ # Step 6 - Subtract 5 from 3 for taxable income.
+ # taxable income = 180000.0 since we do not have an exemption.
+ # Step 7 - Determine initial amount from table
+ # initial = 8080 + ((6.00 / 100) * (180000.0 - 160000))
+ # 9280.0
+ # Step 8 - Determine the tax rate phase out add back from table.
+ # phase_out = 320
+ # Step 9 - Determine the recapture amount from table.
+ # Bottom -> 0
+ # Step 10 - Add Step 7, 8, 9
+ # 9280.0 + 320 + 0 - > 9600.0
+ # Step 11 - Determine decimal amount from personal tax credits.
+ # We get no tax credit.
+ # Step 12 - Multiple Step 10 by 1.00 - Step 11
+ # 9600.0 * 1.00 = 9600.0
+ # Step 13 - Divide by the number of pay periods.
+ # 9600.0 / 12.0 = 800.0
+ # Step 14 & 15 & 16- Add / Subtract the additional or under withholding amount. Then Add this to the amount
+ # for withholding per period.
+ additional_wh = 15.00
+ # 800.0 + 15.00 ->
+ wh = -815.0
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=salary,
+ state_id=self.get_us_state('CT'),
+ ct_w4na_sit_code=wh_code,
+ state_income_tax_additional_withholding=additional_wh,
+ schedule_pay=schedule_pay)
+
+ self._log('2019 Connecticut 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.CT_UNEMP_MAX_WAGE * self.CT_UNEMP)
+ self.assertPayrollEqual(cats['EE_US_SIT'], wh)
diff --git a/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2020.py b/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2020.py
new file mode 100644
index 00000000..a5db79a6
--- /dev/null
+++ b/l10n_us_hr_payroll/tests/test_us_ct_connecticut_payslip_2020.py
@@ -0,0 +1,34 @@
+# 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 TestUsCTPayslip(TestUsPayslip):
+ # Taxes and Rates
+ CT_UNEMP_MAX_WAGE = 15000.0
+ CT_UNEMP = 3.2
+
+ def _test_sit(self, wage, withholding_code, additional_withholding, schedule_pay, date_start, expected_withholding):
+
+ employee = self._createEmployee()
+ contract = self._createContract(employee,
+ wage=wage,
+ state_id=self.get_us_state('CT'),
+ ct_w4na_sit_code=withholding_code,
+ state_income_tax_additional_withholding=additional_withholding,
+ 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):
+ self._test_er_suta('CT', self.CT_UNEMP, date(2020, 1, 1), wage_base=self.CT_UNEMP_MAX_WAGE)
+ self._test_sit(10000.0, 'a', 0.0, 'weekly', date(2020, 1, 1), 693.23)
+ self._test_sit(12000.0, 'b', 15.0, 'bi-weekly', date(2020, 1, 1), 688.85)
+ self._test_sit(5000.0, 'f', 15.0, 'monthly', date(2020, 1, 1), 230.25)
+ self._test_sit(15000.0, 'c', 0.0, 'monthly', date(2020, 1, 1), 783.33)
+ self._test_sit(18000.0, 'b', 0.0, 'weekly', date(2020, 1, 1), 1254.35)
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 082aedcb..a59bf54f 100644
--- a/l10n_us_hr_payroll/views/us_payroll_config_views.xml
+++ b/l10n_us_hr_payroll/views/us_payroll_config_views.xml
@@ -62,6 +62,11 @@
+
+ Form CT-W4 - State Income Tax
+
+
+
No additional fields.