coati-payroll 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of coati-payroll might be problematic. Click here for more details.
- coati_payroll/__init__.py +415 -0
- coati_payroll/app.py +95 -0
- coati_payroll/audit_helpers.py +904 -0
- coati_payroll/auth.py +123 -0
- coati_payroll/cli.py +1318 -0
- coati_payroll/config.py +219 -0
- coati_payroll/demo_data.py +813 -0
- coati_payroll/enums.py +278 -0
- coati_payroll/forms.py +1769 -0
- coati_payroll/formula_engine/__init__.py +81 -0
- coati_payroll/formula_engine/ast/__init__.py +110 -0
- coati_payroll/formula_engine/ast/ast_visitor.py +259 -0
- coati_payroll/formula_engine/ast/expression_evaluator.py +228 -0
- coati_payroll/formula_engine/ast/safe_operators.py +131 -0
- coati_payroll/formula_engine/ast/type_converter.py +172 -0
- coati_payroll/formula_engine/data_sources.py +752 -0
- coati_payroll/formula_engine/engine.py +247 -0
- coati_payroll/formula_engine/exceptions.py +52 -0
- coati_payroll/formula_engine/execution/__init__.py +24 -0
- coati_payroll/formula_engine/execution/execution_context.py +52 -0
- coati_payroll/formula_engine/execution/step_executor.py +62 -0
- coati_payroll/formula_engine/execution/variable_store.py +59 -0
- coati_payroll/formula_engine/novelty_codes.py +206 -0
- coati_payroll/formula_engine/results/__init__.py +20 -0
- coati_payroll/formula_engine/results/execution_result.py +59 -0
- coati_payroll/formula_engine/steps/__init__.py +30 -0
- coati_payroll/formula_engine/steps/assignment_step.py +71 -0
- coati_payroll/formula_engine/steps/base_step.py +48 -0
- coati_payroll/formula_engine/steps/calculation_step.py +42 -0
- coati_payroll/formula_engine/steps/conditional_step.py +122 -0
- coati_payroll/formula_engine/steps/step_factory.py +58 -0
- coati_payroll/formula_engine/steps/tax_lookup_step.py +45 -0
- coati_payroll/formula_engine/tables/__init__.py +24 -0
- coati_payroll/formula_engine/tables/bracket_calculator.py +51 -0
- coati_payroll/formula_engine/tables/table_lookup.py +161 -0
- coati_payroll/formula_engine/tables/tax_table.py +32 -0
- coati_payroll/formula_engine/validation/__init__.py +24 -0
- coati_payroll/formula_engine/validation/schema_validator.py +37 -0
- coati_payroll/formula_engine/validation/security_validator.py +52 -0
- coati_payroll/formula_engine/validation/tax_table_validator.py +205 -0
- coati_payroll/formula_engine_examples.py +153 -0
- coati_payroll/i18n.py +54 -0
- coati_payroll/initial_data.py +613 -0
- coati_payroll/interes_engine.py +450 -0
- coati_payroll/liquidacion_engine/__init__.py +25 -0
- coati_payroll/liquidacion_engine/engine.py +267 -0
- coati_payroll/locale_config.py +165 -0
- coati_payroll/log.py +138 -0
- coati_payroll/model.py +2410 -0
- coati_payroll/nomina_engine/__init__.py +87 -0
- coati_payroll/nomina_engine/calculators/__init__.py +30 -0
- coati_payroll/nomina_engine/calculators/benefit_calculator.py +79 -0
- coati_payroll/nomina_engine/calculators/concept_calculator.py +254 -0
- coati_payroll/nomina_engine/calculators/deduction_calculator.py +105 -0
- coati_payroll/nomina_engine/calculators/exchange_rate_calculator.py +51 -0
- coati_payroll/nomina_engine/calculators/perception_calculator.py +75 -0
- coati_payroll/nomina_engine/calculators/salary_calculator.py +86 -0
- coati_payroll/nomina_engine/domain/__init__.py +27 -0
- coati_payroll/nomina_engine/domain/calculation_items.py +52 -0
- coati_payroll/nomina_engine/domain/employee_calculation.py +53 -0
- coati_payroll/nomina_engine/domain/payroll_context.py +44 -0
- coati_payroll/nomina_engine/engine.py +188 -0
- coati_payroll/nomina_engine/processors/__init__.py +28 -0
- coati_payroll/nomina_engine/processors/accounting_processor.py +171 -0
- coati_payroll/nomina_engine/processors/accumulation_processor.py +90 -0
- coati_payroll/nomina_engine/processors/loan_processor.py +227 -0
- coati_payroll/nomina_engine/processors/novelty_processor.py +42 -0
- coati_payroll/nomina_engine/processors/vacation_processor.py +67 -0
- coati_payroll/nomina_engine/repositories/__init__.py +32 -0
- coati_payroll/nomina_engine/repositories/acumulado_repository.py +83 -0
- coati_payroll/nomina_engine/repositories/base_repository.py +40 -0
- coati_payroll/nomina_engine/repositories/config_repository.py +102 -0
- coati_payroll/nomina_engine/repositories/employee_repository.py +34 -0
- coati_payroll/nomina_engine/repositories/exchange_rate_repository.py +58 -0
- coati_payroll/nomina_engine/repositories/novelty_repository.py +54 -0
- coati_payroll/nomina_engine/repositories/planilla_repository.py +52 -0
- coati_payroll/nomina_engine/results/__init__.py +24 -0
- coati_payroll/nomina_engine/results/error_result.py +28 -0
- coati_payroll/nomina_engine/results/payroll_result.py +53 -0
- coati_payroll/nomina_engine/results/validation_result.py +39 -0
- coati_payroll/nomina_engine/services/__init__.py +22 -0
- coati_payroll/nomina_engine/services/accounting_voucher_service.py +708 -0
- coati_payroll/nomina_engine/services/employee_processing_service.py +173 -0
- coati_payroll/nomina_engine/services/payroll_execution_service.py +374 -0
- coati_payroll/nomina_engine/services/snapshot_service.py +295 -0
- coati_payroll/nomina_engine/validators/__init__.py +31 -0
- coati_payroll/nomina_engine/validators/base_validator.py +48 -0
- coati_payroll/nomina_engine/validators/currency_validator.py +50 -0
- coati_payroll/nomina_engine/validators/employee_validator.py +87 -0
- coati_payroll/nomina_engine/validators/period_validator.py +44 -0
- coati_payroll/nomina_engine/validators/planilla_validator.py +136 -0
- coati_payroll/plugin_manager.py +176 -0
- coati_payroll/queue/__init__.py +33 -0
- coati_payroll/queue/driver.py +127 -0
- coati_payroll/queue/drivers/__init__.py +22 -0
- coati_payroll/queue/drivers/dramatiq_driver.py +268 -0
- coati_payroll/queue/drivers/huey_driver.py +390 -0
- coati_payroll/queue/drivers/noop_driver.py +54 -0
- coati_payroll/queue/selector.py +121 -0
- coati_payroll/queue/tasks.py +764 -0
- coati_payroll/rate_limiting.py +83 -0
- coati_payroll/rbac.py +183 -0
- coati_payroll/report_engine.py +512 -0
- coati_payroll/report_export.py +208 -0
- coati_payroll/schema_validator.py +167 -0
- coati_payroll/security.py +77 -0
- coati_payroll/static/styles.css +1044 -0
- coati_payroll/system_reports.py +573 -0
- coati_payroll/templates/auth/login.html +189 -0
- coati_payroll/templates/base.html +283 -0
- coati_payroll/templates/index.html +227 -0
- coati_payroll/templates/macros.html +146 -0
- coati_payroll/templates/modules/calculation_rule/form.html +78 -0
- coati_payroll/templates/modules/calculation_rule/index.html +102 -0
- coati_payroll/templates/modules/calculation_rule/schema_editor.html +1159 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/form.html +170 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/index.html +170 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/reporte.html +193 -0
- coati_payroll/templates/modules/config_calculos/index.html +44 -0
- coati_payroll/templates/modules/configuracion/index.html +90 -0
- coati_payroll/templates/modules/currency/form.html +47 -0
- coati_payroll/templates/modules/currency/index.html +64 -0
- coati_payroll/templates/modules/custom_field/form.html +62 -0
- coati_payroll/templates/modules/custom_field/index.html +78 -0
- coati_payroll/templates/modules/deduccion/form.html +1 -0
- coati_payroll/templates/modules/deduccion/index.html +1 -0
- coati_payroll/templates/modules/employee/form.html +254 -0
- coati_payroll/templates/modules/employee/index.html +76 -0
- coati_payroll/templates/modules/empresa/form.html +74 -0
- coati_payroll/templates/modules/empresa/index.html +71 -0
- coati_payroll/templates/modules/exchange_rate/form.html +47 -0
- coati_payroll/templates/modules/exchange_rate/import.html +93 -0
- coati_payroll/templates/modules/exchange_rate/index.html +114 -0
- coati_payroll/templates/modules/liquidacion/index.html +58 -0
- coati_payroll/templates/modules/liquidacion/nueva.html +51 -0
- coati_payroll/templates/modules/liquidacion/ver.html +91 -0
- coati_payroll/templates/modules/payroll_concepts/audit_log.html +146 -0
- coati_payroll/templates/modules/percepcion/form.html +1 -0
- coati_payroll/templates/modules/percepcion/index.html +1 -0
- coati_payroll/templates/modules/planilla/config.html +190 -0
- coati_payroll/templates/modules/planilla/config_deducciones.html +129 -0
- coati_payroll/templates/modules/planilla/config_empleados.html +116 -0
- coati_payroll/templates/modules/planilla/config_percepciones.html +113 -0
- coati_payroll/templates/modules/planilla/config_prestaciones.html +118 -0
- coati_payroll/templates/modules/planilla/config_reglas.html +120 -0
- coati_payroll/templates/modules/planilla/ejecutar_nomina.html +106 -0
- coati_payroll/templates/modules/planilla/form.html +197 -0
- coati_payroll/templates/modules/planilla/index.html +144 -0
- coati_payroll/templates/modules/planilla/listar_nominas.html +91 -0
- coati_payroll/templates/modules/planilla/log_nomina.html +135 -0
- coati_payroll/templates/modules/planilla/novedades/form.html +177 -0
- coati_payroll/templates/modules/planilla/novedades/index.html +170 -0
- coati_payroll/templates/modules/planilla/ver_nomina.html +477 -0
- coati_payroll/templates/modules/planilla/ver_nomina_empleado.html +231 -0
- coati_payroll/templates/modules/plugins/index.html +71 -0
- coati_payroll/templates/modules/prestacion/form.html +1 -0
- coati_payroll/templates/modules/prestacion/index.html +1 -0
- coati_payroll/templates/modules/prestacion_management/dashboard.html +150 -0
- coati_payroll/templates/modules/prestacion_management/initial_balance_bulk.html +195 -0
- coati_payroll/templates/modules/prestamo/approve.html +156 -0
- coati_payroll/templates/modules/prestamo/condonacion.html +249 -0
- coati_payroll/templates/modules/prestamo/detail.html +443 -0
- coati_payroll/templates/modules/prestamo/form.html +203 -0
- coati_payroll/templates/modules/prestamo/index.html +150 -0
- coati_payroll/templates/modules/prestamo/pago_extraordinario.html +211 -0
- coati_payroll/templates/modules/prestamo/tabla_pago_pdf.html +181 -0
- coati_payroll/templates/modules/report/admin_index.html +125 -0
- coati_payroll/templates/modules/report/detail.html +129 -0
- coati_payroll/templates/modules/report/execute.html +266 -0
- coati_payroll/templates/modules/report/index.html +95 -0
- coati_payroll/templates/modules/report/permissions.html +64 -0
- coati_payroll/templates/modules/settings/index.html +274 -0
- coati_payroll/templates/modules/shared/concept_form.html +201 -0
- coati_payroll/templates/modules/shared/concept_index.html +145 -0
- coati_payroll/templates/modules/tipo_planilla/form.html +70 -0
- coati_payroll/templates/modules/tipo_planilla/index.html +68 -0
- coati_payroll/templates/modules/user/form.html +65 -0
- coati_payroll/templates/modules/user/index.html +76 -0
- coati_payroll/templates/modules/user/profile.html +81 -0
- coati_payroll/templates/modules/vacation/account_detail.html +149 -0
- coati_payroll/templates/modules/vacation/account_form.html +52 -0
- coati_payroll/templates/modules/vacation/account_index.html +68 -0
- coati_payroll/templates/modules/vacation/dashboard.html +156 -0
- coati_payroll/templates/modules/vacation/initial_balance_bulk.html +149 -0
- coati_payroll/templates/modules/vacation/initial_balance_form.html +93 -0
- coati_payroll/templates/modules/vacation/leave_request_detail.html +158 -0
- coati_payroll/templates/modules/vacation/leave_request_form.html +61 -0
- coati_payroll/templates/modules/vacation/leave_request_index.html +98 -0
- coati_payroll/templates/modules/vacation/policy_detail.html +176 -0
- coati_payroll/templates/modules/vacation/policy_form.html +152 -0
- coati_payroll/templates/modules/vacation/policy_index.html +79 -0
- coati_payroll/templates/modules/vacation/register_taken_form.html +178 -0
- coati_payroll/translations/en/LC_MESSAGES/messages.mo +0 -0
- coati_payroll/translations/en/LC_MESSAGES/messages.po +7283 -0
- coati_payroll/translations/es/LC_MESSAGES/messages.mo +0 -0
- coati_payroll/translations/es/LC_MESSAGES/messages.po +7374 -0
- coati_payroll/vacation_service.py +451 -0
- coati_payroll/version.py +18 -0
- coati_payroll/vistas/__init__.py +64 -0
- coati_payroll/vistas/calculation_rule.py +307 -0
- coati_payroll/vistas/carga_inicial_prestacion.py +423 -0
- coati_payroll/vistas/config_calculos.py +72 -0
- coati_payroll/vistas/configuracion.py +87 -0
- coati_payroll/vistas/constants.py +17 -0
- coati_payroll/vistas/currency.py +112 -0
- coati_payroll/vistas/custom_field.py +120 -0
- coati_payroll/vistas/employee.py +305 -0
- coati_payroll/vistas/empresa.py +153 -0
- coati_payroll/vistas/exchange_rate.py +341 -0
- coati_payroll/vistas/liquidacion.py +205 -0
- coati_payroll/vistas/payroll_concepts.py +580 -0
- coati_payroll/vistas/planilla/__init__.py +38 -0
- coati_payroll/vistas/planilla/association_routes.py +238 -0
- coati_payroll/vistas/planilla/config_routes.py +158 -0
- coati_payroll/vistas/planilla/export_routes.py +175 -0
- coati_payroll/vistas/planilla/helpers/__init__.py +34 -0
- coati_payroll/vistas/planilla/helpers/association_helpers.py +161 -0
- coati_payroll/vistas/planilla/helpers/excel_helpers.py +29 -0
- coati_payroll/vistas/planilla/helpers/form_helpers.py +97 -0
- coati_payroll/vistas/planilla/nomina_routes.py +488 -0
- coati_payroll/vistas/planilla/novedad_routes.py +227 -0
- coati_payroll/vistas/planilla/routes.py +145 -0
- coati_payroll/vistas/planilla/services/__init__.py +26 -0
- coati_payroll/vistas/planilla/services/export_service.py +687 -0
- coati_payroll/vistas/planilla/services/nomina_service.py +233 -0
- coati_payroll/vistas/planilla/services/novedad_service.py +126 -0
- coati_payroll/vistas/planilla/services/planilla_service.py +34 -0
- coati_payroll/vistas/planilla/validators/__init__.py +18 -0
- coati_payroll/vistas/planilla/validators/planilla_validators.py +40 -0
- coati_payroll/vistas/plugins.py +45 -0
- coati_payroll/vistas/prestacion.py +272 -0
- coati_payroll/vistas/prestamo.py +808 -0
- coati_payroll/vistas/report.py +432 -0
- coati_payroll/vistas/settings.py +29 -0
- coati_payroll/vistas/tipo_planilla.py +134 -0
- coati_payroll/vistas/user.py +172 -0
- coati_payroll/vistas/vacation.py +1045 -0
- coati_payroll-0.0.2.dist-info/LICENSE +201 -0
- coati_payroll-0.0.2.dist-info/METADATA +581 -0
- coati_payroll-0.0.2.dist-info/RECORD +243 -0
- coati_payroll-0.0.2.dist-info/WHEEL +5 -0
- coati_payroll-0.0.2.dist-info/entry_points.txt +2 -0
- coati_payroll-0.0.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Mapping of novelty codes to their calculation behavior.
|
|
15
|
+
|
|
16
|
+
This module defines the mapping between novelty codes and their
|
|
17
|
+
calculation behavior (perception/deduction, gravable, etc.).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
NOVELTY_CODES = {
|
|
21
|
+
"HORAS_EXTRA": {
|
|
22
|
+
"tipo": "percepcion",
|
|
23
|
+
"gravable": True,
|
|
24
|
+
"descripcion": "Horas extra trabajadas",
|
|
25
|
+
},
|
|
26
|
+
"HORAS_EXTRA_DOBLES": {
|
|
27
|
+
"tipo": "percepcion",
|
|
28
|
+
"gravable": True,
|
|
29
|
+
"descripcion": "Horas extra dobles (feriados/domingos)",
|
|
30
|
+
},
|
|
31
|
+
"AUSENCIA": {
|
|
32
|
+
"tipo": "deduccion",
|
|
33
|
+
"gravable": False,
|
|
34
|
+
"descripcion": "Ausencia no justificada",
|
|
35
|
+
},
|
|
36
|
+
"INCAPACIDAD": {
|
|
37
|
+
"tipo": "deduccion",
|
|
38
|
+
"gravable": False,
|
|
39
|
+
"descripcion": "Incapacidad médica",
|
|
40
|
+
},
|
|
41
|
+
"COMISION": {
|
|
42
|
+
"tipo": "percepcion",
|
|
43
|
+
"gravable": True,
|
|
44
|
+
"descripcion": "Comisiones por ventas",
|
|
45
|
+
},
|
|
46
|
+
"BONIFICACION": {
|
|
47
|
+
"tipo": "percepcion",
|
|
48
|
+
"gravable": True,
|
|
49
|
+
"descripcion": "Bonificación",
|
|
50
|
+
},
|
|
51
|
+
"VIATICO": {
|
|
52
|
+
"tipo": "percepcion",
|
|
53
|
+
"gravable": False,
|
|
54
|
+
"descripcion": "Viáticos",
|
|
55
|
+
},
|
|
56
|
+
"VACACIONES": {
|
|
57
|
+
"tipo": "percepcion",
|
|
58
|
+
"gravable": True,
|
|
59
|
+
"descripcion": "Pago de vacaciones",
|
|
60
|
+
},
|
|
61
|
+
"ADELANTO": {
|
|
62
|
+
"tipo": "deduccion",
|
|
63
|
+
"gravable": False,
|
|
64
|
+
"descripcion": "Adelanto de salario",
|
|
65
|
+
},
|
|
66
|
+
"PRESTAMO": {
|
|
67
|
+
"tipo": "deduccion",
|
|
68
|
+
"gravable": False,
|
|
69
|
+
"descripcion": "Cuota de préstamo",
|
|
70
|
+
},
|
|
71
|
+
# A. Compensación Base y Directa
|
|
72
|
+
"BONO_OBJETIVOS": {
|
|
73
|
+
"tipo": "percepcion",
|
|
74
|
+
"gravable": True,
|
|
75
|
+
"descripcion": "Bono por cumplimiento de objetivos",
|
|
76
|
+
},
|
|
77
|
+
"BONO_ANUAL": {
|
|
78
|
+
"tipo": "percepcion",
|
|
79
|
+
"gravable": True,
|
|
80
|
+
"descripcion": "Bono anual o trimestral",
|
|
81
|
+
},
|
|
82
|
+
"PLUS_PELIGROSIDAD": {
|
|
83
|
+
"tipo": "percepcion",
|
|
84
|
+
"gravable": True,
|
|
85
|
+
"descripcion": "Plus por peligrosidad o toxicidad",
|
|
86
|
+
},
|
|
87
|
+
"PLUS_NOCTURNO": {
|
|
88
|
+
"tipo": "percepcion",
|
|
89
|
+
"gravable": True,
|
|
90
|
+
"descripcion": "Plus por trabajo nocturno",
|
|
91
|
+
},
|
|
92
|
+
"PLUS_ANTIGUEDAD": {
|
|
93
|
+
"tipo": "percepcion",
|
|
94
|
+
"gravable": True,
|
|
95
|
+
"descripcion": "Plus por antigüedad",
|
|
96
|
+
},
|
|
97
|
+
# B. Compensaciones en Especie y Beneficios
|
|
98
|
+
"USO_VEHICULO": {
|
|
99
|
+
"tipo": "percepcion",
|
|
100
|
+
"gravable": True,
|
|
101
|
+
"descripcion": "Uso de vehículo de empresa",
|
|
102
|
+
},
|
|
103
|
+
"SEGURO_SALUD": {
|
|
104
|
+
"tipo": "percepcion",
|
|
105
|
+
"gravable": False,
|
|
106
|
+
"descripcion": "Seguro de salud privado",
|
|
107
|
+
},
|
|
108
|
+
"APORTE_PENSION": {
|
|
109
|
+
"tipo": "percepcion",
|
|
110
|
+
"gravable": False,
|
|
111
|
+
"descripcion": "Aporte patronal a pensión/retiro",
|
|
112
|
+
},
|
|
113
|
+
"STOCK_OPTIONS": {
|
|
114
|
+
"tipo": "percepcion",
|
|
115
|
+
"gravable": True,
|
|
116
|
+
"descripcion": "Opciones de compra de acciones",
|
|
117
|
+
},
|
|
118
|
+
"SUBSIDIO_ALIMENTACION": {
|
|
119
|
+
"tipo": "percepcion",
|
|
120
|
+
"gravable": False,
|
|
121
|
+
"descripcion": "Subsidio de alimentación",
|
|
122
|
+
},
|
|
123
|
+
"SUBSIDIO_TRANSPORTE": {
|
|
124
|
+
"tipo": "percepcion",
|
|
125
|
+
"gravable": False,
|
|
126
|
+
"descripcion": "Subsidio de transporte",
|
|
127
|
+
},
|
|
128
|
+
"SUBSIDIO_GUARDERIA": {
|
|
129
|
+
"tipo": "percepcion",
|
|
130
|
+
"gravable": False,
|
|
131
|
+
"descripcion": "Subsidio de guardería",
|
|
132
|
+
},
|
|
133
|
+
# C. Compensaciones por Tiempo y Bienestar
|
|
134
|
+
"PAGO_FESTIVOS": {
|
|
135
|
+
"tipo": "percepcion",
|
|
136
|
+
"gravable": True,
|
|
137
|
+
"descripcion": "Pago por días festivos trabajados",
|
|
138
|
+
},
|
|
139
|
+
"THIRTEENTH_SALARY": {
|
|
140
|
+
"tipo": "percepcion",
|
|
141
|
+
"gravable": True,
|
|
142
|
+
"descripcion": "Aguinaldo o gratificación anual",
|
|
143
|
+
},
|
|
144
|
+
"UTILIDADES": {
|
|
145
|
+
"tipo": "percepcion",
|
|
146
|
+
"gravable": True,
|
|
147
|
+
"descripcion": "Participación en utilidades",
|
|
148
|
+
},
|
|
149
|
+
"PERMISO_PAGADO": {
|
|
150
|
+
"tipo": "percepcion",
|
|
151
|
+
"gravable": True,
|
|
152
|
+
"descripcion": "Permisos pagados (enfermedad, maternidad, etc.)",
|
|
153
|
+
},
|
|
154
|
+
"FONDO_AHORRO_EMPRESA": {
|
|
155
|
+
"tipo": "percepcion",
|
|
156
|
+
"gravable": False,
|
|
157
|
+
"descripcion": "Aporte empresa a fondo de ahorro",
|
|
158
|
+
},
|
|
159
|
+
"FONDO_AHORRO_EMPLEADO": {
|
|
160
|
+
"tipo": "deduccion",
|
|
161
|
+
"gravable": False,
|
|
162
|
+
"descripcion": "Aporte empleado a fondo de ahorro",
|
|
163
|
+
},
|
|
164
|
+
# D. Reembolsos y Dietas
|
|
165
|
+
"GASTOS_REPRESENTACION": {
|
|
166
|
+
"tipo": "percepcion",
|
|
167
|
+
"gravable": False,
|
|
168
|
+
"descripcion": "Gastos de representación",
|
|
169
|
+
},
|
|
170
|
+
"REEMBOLSO_FORMACION": {
|
|
171
|
+
"tipo": "percepcion",
|
|
172
|
+
"gravable": False,
|
|
173
|
+
"descripcion": "Reembolso de gastos de formación",
|
|
174
|
+
},
|
|
175
|
+
"REEMBOLSO_MEDICO": {
|
|
176
|
+
"tipo": "percepcion",
|
|
177
|
+
"gravable": False,
|
|
178
|
+
"descripcion": "Reembolso de gastos médicos",
|
|
179
|
+
},
|
|
180
|
+
# E. Pagos por Eventos Específicos
|
|
181
|
+
"INDEMNIZACION": {
|
|
182
|
+
"tipo": "percepcion",
|
|
183
|
+
"gravable": True,
|
|
184
|
+
"descripcion": "Indemnización por despido",
|
|
185
|
+
},
|
|
186
|
+
"COMPENSACION_REUBICACION": {
|
|
187
|
+
"tipo": "percepcion",
|
|
188
|
+
"gravable": False,
|
|
189
|
+
"descripcion": "Compensación por reubicación",
|
|
190
|
+
},
|
|
191
|
+
"PREMIO_PUNTUALIDAD": {
|
|
192
|
+
"tipo": "percepcion",
|
|
193
|
+
"gravable": True,
|
|
194
|
+
"descripcion": "Premio por puntualidad/asistencia",
|
|
195
|
+
},
|
|
196
|
+
"PREMIO_INNOVACION": {
|
|
197
|
+
"tipo": "percepcion",
|
|
198
|
+
"gravable": True,
|
|
199
|
+
"descripcion": "Premio por ideas innovadoras",
|
|
200
|
+
},
|
|
201
|
+
"AYUDA_FALLECIMIENTO": {
|
|
202
|
+
"tipo": "percepcion",
|
|
203
|
+
"gravable": False,
|
|
204
|
+
"descripcion": "Ayuda por fallecimiento de familiar",
|
|
205
|
+
},
|
|
206
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Result DTOs for formula engine execution."""
|
|
15
|
+
|
|
16
|
+
from .execution_result import ExecutionResult
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"ExecutionResult",
|
|
20
|
+
]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Execution result DTO."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from decimal import Decimal
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ExecutionResult:
|
|
23
|
+
"""Result of formula execution."""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
variables: dict[str, Decimal],
|
|
28
|
+
step_results: dict[str, Any],
|
|
29
|
+
final_output: Decimal,
|
|
30
|
+
):
|
|
31
|
+
"""Initialize execution result.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
variables: All variables after execution
|
|
35
|
+
step_results: Results from each step
|
|
36
|
+
final_output: Final output value
|
|
37
|
+
"""
|
|
38
|
+
self.variables = variables
|
|
39
|
+
self.step_results = step_results
|
|
40
|
+
self.final_output = final_output
|
|
41
|
+
|
|
42
|
+
def to_dict(self) -> dict[str, Any]:
|
|
43
|
+
"""Convert result to dictionary format.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Dictionary representation of result
|
|
47
|
+
"""
|
|
48
|
+
return {
|
|
49
|
+
"variables": {k: float(v) for k, v in self.variables.items()},
|
|
50
|
+
"results": {
|
|
51
|
+
k: (
|
|
52
|
+
float(v)
|
|
53
|
+
if isinstance(v, Decimal)
|
|
54
|
+
else ({kk: float(vv) for kk, vv in v.items()} if isinstance(v, dict) else v)
|
|
55
|
+
)
|
|
56
|
+
for k, v in self.step_results.items()
|
|
57
|
+
},
|
|
58
|
+
"output": float(self.final_output),
|
|
59
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Step execution modules using Strategy pattern."""
|
|
15
|
+
|
|
16
|
+
from .base_step import Step
|
|
17
|
+
from .calculation_step import CalculationStep
|
|
18
|
+
from .conditional_step import ConditionalStep
|
|
19
|
+
from .tax_lookup_step import TaxLookupStep
|
|
20
|
+
from .assignment_step import AssignmentStep
|
|
21
|
+
from .step_factory import StepFactory
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"Step",
|
|
25
|
+
"CalculationStep",
|
|
26
|
+
"ConditionalStep",
|
|
27
|
+
"TaxLookupStep",
|
|
28
|
+
"AssignmentStep",
|
|
29
|
+
"StepFactory",
|
|
30
|
+
]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Assignment step implementation."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from decimal import Decimal
|
|
19
|
+
from typing import TYPE_CHECKING, Any
|
|
20
|
+
|
|
21
|
+
from ..ast.type_converter import to_decimal
|
|
22
|
+
from .base_step import Step
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from ..execution.execution_context import ExecutionContext
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class AssignmentStep(Step):
|
|
29
|
+
"""Step for assigning values to variables."""
|
|
30
|
+
|
|
31
|
+
def execute(self, context: "ExecutionContext") -> Decimal:
|
|
32
|
+
"""Execute assignment step.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
context: Execution context
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Assigned value as Decimal
|
|
39
|
+
"""
|
|
40
|
+
value = self.config.get("value")
|
|
41
|
+
result = self._resolve_value(value, context)
|
|
42
|
+
return result
|
|
43
|
+
|
|
44
|
+
def _resolve_value(self, value: Any, context: "ExecutionContext") -> Decimal:
|
|
45
|
+
"""Resolve a value that might be a variable reference.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
value: Value or variable name to resolve
|
|
49
|
+
context: Execution context
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Decimal value
|
|
53
|
+
"""
|
|
54
|
+
if isinstance(value, str) and value in context.variables:
|
|
55
|
+
resolved = context.variables[value]
|
|
56
|
+
if context.trace_callback:
|
|
57
|
+
from coati_payroll.i18n import _
|
|
58
|
+
|
|
59
|
+
context.trace_callback(
|
|
60
|
+
_("Resolviendo variable '%(name)s' => %(value)s") % {"name": value, "value": resolved}
|
|
61
|
+
)
|
|
62
|
+
return resolved
|
|
63
|
+
|
|
64
|
+
resolved_literal = to_decimal(value)
|
|
65
|
+
if context.trace_callback:
|
|
66
|
+
from coati_payroll.i18n import _
|
|
67
|
+
|
|
68
|
+
context.trace_callback(
|
|
69
|
+
_("Resolviendo valor literal '%(raw)s' => %(value)s") % {"raw": value, "value": resolved_literal}
|
|
70
|
+
)
|
|
71
|
+
return resolved_literal
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Base step interface for Strategy pattern."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from abc import ABC, abstractmethod
|
|
19
|
+
from typing import Any, TYPE_CHECKING
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from ..execution.execution_context import ExecutionContext
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Step(ABC):
|
|
26
|
+
"""Base interface for all step types."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, name: str, config: dict[str, Any]):
|
|
29
|
+
"""Initialize step.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
name: Step name
|
|
33
|
+
config: Step configuration dictionary
|
|
34
|
+
"""
|
|
35
|
+
self.name = name
|
|
36
|
+
self.config = config
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def execute(self, context: "ExecutionContext") -> Any:
|
|
40
|
+
"""Execute the step and return result.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
context: Execution context with variables and tax tables
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Step execution result
|
|
47
|
+
"""
|
|
48
|
+
pass
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Calculation step implementation."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from decimal import Decimal
|
|
19
|
+
from typing import TYPE_CHECKING
|
|
20
|
+
|
|
21
|
+
from ..ast.expression_evaluator import ExpressionEvaluator
|
|
22
|
+
from .base_step import Step
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from ..execution.execution_context import ExecutionContext
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CalculationStep(Step):
|
|
29
|
+
"""Step for executing mathematical calculations."""
|
|
30
|
+
|
|
31
|
+
def execute(self, context: "ExecutionContext") -> Decimal:
|
|
32
|
+
"""Execute calculation step.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
context: Execution context
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Calculated result as Decimal
|
|
39
|
+
"""
|
|
40
|
+
formula = self.config.get("formula", "")
|
|
41
|
+
evaluator = ExpressionEvaluator(variables=context.variables, trace_callback=context.trace_callback)
|
|
42
|
+
return evaluator.evaluate(formula)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Conditional step implementation."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from decimal import Decimal
|
|
19
|
+
from typing import TYPE_CHECKING, Any
|
|
20
|
+
|
|
21
|
+
from ..ast.expression_evaluator import ExpressionEvaluator
|
|
22
|
+
from ..ast.safe_operators import COMPARISON_OPERATORS
|
|
23
|
+
from ..ast.type_converter import to_decimal
|
|
24
|
+
from ..exceptions import CalculationError
|
|
25
|
+
from .base_step import Step
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from ..execution.execution_context import ExecutionContext
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ConditionalStep(Step):
|
|
32
|
+
"""Step for conditional logic (if/else)."""
|
|
33
|
+
|
|
34
|
+
def execute(self, context: "ExecutionContext") -> Decimal:
|
|
35
|
+
"""Execute conditional step.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
context: Execution context
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Result of selected branch as Decimal
|
|
42
|
+
"""
|
|
43
|
+
condition = self.config.get("condition", {})
|
|
44
|
+
if_true = self.config.get("if_true", "0")
|
|
45
|
+
if_false = self.config.get("if_false", "0")
|
|
46
|
+
|
|
47
|
+
# Evaluate condition
|
|
48
|
+
condition_result = self._evaluate_condition(condition, context)
|
|
49
|
+
|
|
50
|
+
# Select expression based on condition
|
|
51
|
+
selected_value = if_true if condition_result else if_false
|
|
52
|
+
|
|
53
|
+
# Evaluate selected expression
|
|
54
|
+
evaluator = ExpressionEvaluator(variables=context.variables, trace_callback=context.trace_callback)
|
|
55
|
+
return evaluator.evaluate(str(selected_value))
|
|
56
|
+
|
|
57
|
+
def _evaluate_condition(self, condition: dict[str, Any], context: "ExecutionContext") -> bool:
|
|
58
|
+
"""Evaluate a conditional expression.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
condition: Dictionary with 'left', 'operator', 'right' keys
|
|
62
|
+
context: Execution context
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Boolean result of the condition
|
|
66
|
+
|
|
67
|
+
Raises:
|
|
68
|
+
CalculationError: If condition is invalid
|
|
69
|
+
"""
|
|
70
|
+
if not isinstance(condition, dict):
|
|
71
|
+
raise CalculationError("Condition must be a dictionary")
|
|
72
|
+
|
|
73
|
+
left = condition.get("left")
|
|
74
|
+
op = condition.get("operator")
|
|
75
|
+
right = condition.get("right")
|
|
76
|
+
|
|
77
|
+
if op not in COMPARISON_OPERATORS:
|
|
78
|
+
raise CalculationError(f"Invalid comparison operator: {op}")
|
|
79
|
+
|
|
80
|
+
# Resolve variable references
|
|
81
|
+
left_val = self._resolve_value(left, context)
|
|
82
|
+
right_val = self._resolve_value(right, context)
|
|
83
|
+
result = COMPARISON_OPERATORS[op](left_val, right_val)
|
|
84
|
+
|
|
85
|
+
if context.trace_callback:
|
|
86
|
+
from coati_payroll.i18n import _
|
|
87
|
+
|
|
88
|
+
context.trace_callback(
|
|
89
|
+
_("Condición evaluada: %(left)s %(op)s %(right)s -> %(res)s")
|
|
90
|
+
% {"left": left_val, "op": op, "right": right_val, "res": result}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
return result
|
|
94
|
+
|
|
95
|
+
def _resolve_value(self, value: Any, context: "ExecutionContext") -> Decimal:
|
|
96
|
+
"""Resolve a value that might be a variable reference.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
value: Value or variable name to resolve
|
|
100
|
+
context: Execution context
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Decimal value
|
|
104
|
+
"""
|
|
105
|
+
if isinstance(value, str) and value in context.variables:
|
|
106
|
+
resolved = context.variables[value]
|
|
107
|
+
if context.trace_callback:
|
|
108
|
+
from coati_payroll.i18n import _
|
|
109
|
+
|
|
110
|
+
context.trace_callback(
|
|
111
|
+
_("Resolviendo variable '%(name)s' => %(value)s") % {"name": value, "value": resolved}
|
|
112
|
+
)
|
|
113
|
+
return resolved
|
|
114
|
+
|
|
115
|
+
resolved_literal = to_decimal(value)
|
|
116
|
+
if context.trace_callback:
|
|
117
|
+
from coati_payroll.i18n import _
|
|
118
|
+
|
|
119
|
+
context.trace_callback(
|
|
120
|
+
_("Resolviendo valor literal '%(raw)s' => %(value)s") % {"raw": value, "value": resolved_literal}
|
|
121
|
+
)
|
|
122
|
+
return resolved_literal
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Factory for creating step instances."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from coati_payroll.enums import StepType
|
|
21
|
+
|
|
22
|
+
from ..exceptions import CalculationError
|
|
23
|
+
from .assignment_step import AssignmentStep
|
|
24
|
+
from .base_step import Step
|
|
25
|
+
from .calculation_step import CalculationStep
|
|
26
|
+
from .conditional_step import ConditionalStep
|
|
27
|
+
from .tax_lookup_step import TaxLookupStep
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class StepFactory:
|
|
31
|
+
"""Factory for creating step instances."""
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def create_step(step_config: dict[str, Any]) -> Step:
|
|
35
|
+
"""Create a step instance from configuration.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
step_config: Step configuration dictionary
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Step instance
|
|
42
|
+
|
|
43
|
+
Raises:
|
|
44
|
+
CalculationError: If step type is unknown
|
|
45
|
+
"""
|
|
46
|
+
step_type = step_config.get("type")
|
|
47
|
+
step_name = step_config.get("name", "unnamed_step")
|
|
48
|
+
|
|
49
|
+
if step_type == StepType.CALCULATION:
|
|
50
|
+
return CalculationStep(step_name, step_config)
|
|
51
|
+
elif step_type == StepType.CONDITIONAL:
|
|
52
|
+
return ConditionalStep(step_name, step_config)
|
|
53
|
+
elif step_type == StepType.TAX_LOOKUP:
|
|
54
|
+
return TaxLookupStep(step_name, step_config)
|
|
55
|
+
elif step_type == StepType.ASSIGNMENT:
|
|
56
|
+
return AssignmentStep(step_name, step_config)
|
|
57
|
+
else:
|
|
58
|
+
raise CalculationError(f"Unknown step type: {step_type}")
|