meta_payroll_type: Refactor for more code reuse.

This commit is contained in:
Brett Smith 2020-12-23 17:27:30 -05:00
parent 9d41f79c52
commit 7c18bc221f
3 changed files with 79 additions and 44 deletions

View file

@ -67,7 +67,12 @@ class HookRegistry:
'.meta_repo_links': None,
'.meta_rt_links': ['MetaRTLinks'],
'.meta_tax_implication': None,
'.meta_payroll_type': None,
'.meta_payroll_type': [
'HealthInsuranceHook',
'OtherBenefitsHook',
'SalaryHook',
'TaxHook',
],
'.txn_date': ['TransactionDate'],
}

View file

@ -14,56 +14,86 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from . import core
import datetime
from . import core
from .. import ranges
from .. import data
from .. import errors as errormod
from ..beancount_types import (
Transaction,
)
class MetaPayrollType(core._PostingHook):
"""Verify payroll-type metadata, starting on 2020-03-01 (FY 2020), is provided for the accounts:
Expenses:Payroll:Salary, Expenses:Payroll:Taxes, Expenses:Payroll:Benefits:HealthInsurance, and
Expenses:Payroll:Benefits:Other.
Valid values for payroll-type are listed in the
_SALARY_TYPES, _TAX_TYPES, _HEALTH_INSURANCE_TYPES, and _OTHER_BENEFIT_TYPES
(respectively) in the class.
"""
METADATA_KEY = 'payroll-type'
HOOK_GROUPS = frozenset(['metadata', METADATA_KEY])
_TAX_TYPES = [ "CA:PP", "CA:EI",
"US:SocialSecurity", "US:Medicare",
"US:IL:Unemployment",
"US:MA:Unemployment", "US:MA:WorkTrain", "US:MA:Health",
"US:OR:Unemployment" ]
_SALARY_TYPES = [ "US:General", "US:PTO", "US:403b:Employee", "US:403b:Match",
"CA:General", "CA:PTO",
"CA:Taxes:Income", "CA:Taxes:EI", "CA:Taxes:PP",
"US:Taxes:Income", "US:Taxes:SocialSecurity", "US:Taxes:Medicare",
"US:IL:Taxes:Income",
"US:OR:Taxes:Income", "US:OR:Taxes:STT",
"US:MA:Taxes:Income", "US:MA:Disability:PML", "US:MA:Disability:PFL",
"US:NY:Taxes:Income", "US:NY:Disability:PFL", "US:NY:Disability", "US:NY:Taxes:NYC" ]
_HEALTH_INSURANCE_TYPES = [ "US:HRA:Fees", "US:HRA:Usage", "US:Premium:Main", "US:Premium:DentalVision" ]
_OTHER_BENEFIT_TYPES = [ "US:403b:Fees" ]
TXN_DATE_RANGE = ranges.DateRange(datetime.date(2020, 3, 1), core.DEFAULT_STOP_DATE)
METADATA_KEY = 'payroll-type'
class _PayrollTypeHook(core._NormalizePostingMetadataHook):
ACCOUNT: str
VALUES_ENUM = core.MetadataEnum(METADATA_KEY, [])
TXN_DATE_RANGE = ranges.DateRange(
datetime.date(2020, 3, 1),
core.DEFAULT_STOP_DATE,
)
def _run_on_post(self, txn: Transaction, post: data.Posting) -> bool:
if post.account.is_under('Expenses:Payroll:Salary') or post.account.is_under('Expenses:Payroll:Taxes') or \
post.account.is_under('Expenses:Payroll:Benefits:Other') or post.account.is_under('Expenses:Payroll:Benefits:HealthInsurance'):
return True
else:
return False
return post.account.is_under(self.ACCOUNT) is not None
def post_run(self, txn: Transaction, post: data.Posting) -> errormod.Iter:
value = post.meta.get(self.METADATA_KEY)
if value is None or \
(post.account.is_under('Expenses:Payroll:Salary') and (not value in self._SALARY_TYPES)) or \
(post.account.is_under('Expenses:Payroll:Taxes') and (not value in self._TAX_TYPES)) or \
(post.account.is_under('Expenses:Payroll:Benefits:HealthInsurance') and \
(not value in self._HEALTH_INSURANCE_TYPES)) or \
(post.account.is_under('Expenses:Payroll:Benefits:Other') and \
(not value in self._OTHER_BENEFIT_TYPES)):
yield errormod.InvalidMetadataError(txn, self.METADATA_KEY, value, post)
class HealthInsuranceHook(_PayrollTypeHook):
ACCOUNT = 'Expenses:Payroll:Benefits:HealthInsurance'
VALUES_ENUM = core.MetadataEnum(METADATA_KEY, [
'US:HRA:Fees',
'US:HRA:Usage',
'US:Premium:DentalVision',
'US:Premium:Main',
])
class OtherBenefitsHook(_PayrollTypeHook):
ACCOUNT = 'Expenses:Payroll:Benefits:Other'
VALUES_ENUM = core.MetadataEnum(METADATA_KEY, [
'US:403b:Fees',
])
class SalaryHook(_PayrollTypeHook):
ACCOUNT = 'Expenses:Payroll:Salary'
VALUES_ENUM = core.MetadataEnum(METADATA_KEY, [
'CA:General',
'CA:PTO',
'CA:Taxes:EI',
'CA:Taxes:Income',
'CA:Taxes:PP',
'US:403b:Employee',
'US:403b:Match',
'US:General',
'US:IL:Taxes:Income',
'US:MA:Disability:PFL',
'US:MA:Disability:PML',
'US:MA:Taxes:Income',
'US:NY:Disability',
'US:NY:Disability:PFL',
'US:NY:Taxes:Income',
'US:NY:Taxes:NYC',
'US:OR:Taxes:Income',
'US:OR:Taxes:STT',
'US:PTO',
'US:Taxes:Income',
'US:Taxes:Medicare',
'US:Taxes:SocialSecurity',
])
class TaxHook(_PayrollTypeHook):
ACCOUNT = 'Expenses:Payroll:Taxes'
VALUES_ENUM = core.MetadataEnum(METADATA_KEY, [
'CA:EI',
'CA:PP',
'US:IL:Unemployment',
'US:MA:Health',
'US:MA:Unemployment',
'US:MA:WorkTrain',
'US:Medicare',
'US:OR:Unemployment',
'US:SocialSecurity',
])

View file

@ -5,7 +5,7 @@ from setuptools import setup
setup(
name='conservancy_beancount',
description="Plugin, library, and reports for reading Conservancy's books",
version='1.13.1',
version='1.14.0',
author='Software Freedom Conservancy',
author_email='info@sfconservancy.org',
license='GNU AGPLv3+',