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
coati_payroll/config.py
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
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 configuration for the payroll module."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
# <-------------------------------------------------------------------------> #
|
|
19
|
+
# Standard library
|
|
20
|
+
# <-------------------------------------------------------------------------> #
|
|
21
|
+
from os import environ, getcwd, path, sys
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
|
24
|
+
|
|
25
|
+
# <-------------------------------------------------------------------------> #
|
|
26
|
+
# Third party libraries
|
|
27
|
+
# <-------------------------------------------------------------------------> #
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# <-------------------------------------------------------------------------> #
|
|
31
|
+
# Local modules
|
|
32
|
+
# <-------------------------------------------------------------------------> #
|
|
33
|
+
from coati_payroll.log import log
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# ---------------------------------------------------------------------------------------
|
|
37
|
+
# Configuration file loading functionality
|
|
38
|
+
# ---------------------------------------------------------------------------------------
|
|
39
|
+
def load_config_from_file() -> dict:
|
|
40
|
+
"""
|
|
41
|
+
Busca y carga configuración desde archivo con ConfigObj.
|
|
42
|
+
|
|
43
|
+
Busca en las siguientes ubicaciones en orden:
|
|
44
|
+
1. /etc/coati-payroll/coati-payroll.conf
|
|
45
|
+
2. /etc/coati-payroll.conf
|
|
46
|
+
3. ~/.config/coati-payroll/coati-payroll.conf
|
|
47
|
+
3. ./coati-payroll.conf
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
dict: Diccionario de configuración, vacío si no se encuentra archivo
|
|
51
|
+
"""
|
|
52
|
+
try:
|
|
53
|
+
from configobj import ConfigObj
|
|
54
|
+
except ImportError:
|
|
55
|
+
log.debug("ConfigObj not available, skipping file-based configuration.")
|
|
56
|
+
return {}
|
|
57
|
+
|
|
58
|
+
search_paths = [
|
|
59
|
+
"/etc/coati-payroll/coati-payroll.conf",
|
|
60
|
+
"/etc/coati-payroll.conf",
|
|
61
|
+
path.expanduser("~/.config/coati-payroll/coati-payroll.conf"),
|
|
62
|
+
path.join(getcwd(), "coati-payroll.conf"),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
for config_path in search_paths:
|
|
66
|
+
if config_path and path.isfile(config_path):
|
|
67
|
+
try:
|
|
68
|
+
log.info(f"Loading configuration from file: {config_path}")
|
|
69
|
+
config_obj = ConfigObj(config_path, encoding="utf-8")
|
|
70
|
+
|
|
71
|
+
config_dict = dict(config_obj)
|
|
72
|
+
|
|
73
|
+
if "DATABASE_URL" in config_dict:
|
|
74
|
+
config_dict["SQLALCHEMY_DATABASE_URI"] = config_dict["DATABASE_URL"]
|
|
75
|
+
|
|
76
|
+
if "REDIS_URL" in config_dict:
|
|
77
|
+
config_dict["CACHE_REDIS_URL"] = config_dict["REDIS_URL"]
|
|
78
|
+
|
|
79
|
+
return config_dict
|
|
80
|
+
|
|
81
|
+
except Exception as e:
|
|
82
|
+
log.warning(f"Error loading configuration from {config_path}: {e}")
|
|
83
|
+
continue
|
|
84
|
+
|
|
85
|
+
log.trace("No configuration file found in search paths.")
|
|
86
|
+
return {}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
90
|
+
# Configuración central de la aplicación.
|
|
91
|
+
VALORES_TRUE = {*["1", "true", "yes", "on"], *["development", "dev"]}
|
|
92
|
+
DEBUG_VARS = ["DEBUG", "CI", "DEV", "DEVELOPMENT"]
|
|
93
|
+
FRAMEWORK_VARS = ["FLASK_ENV", "DJANGO_DEBUG", "NODE_ENV"]
|
|
94
|
+
GENERIC_VARS = ["ENV", "APP_ENV"]
|
|
95
|
+
|
|
96
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
97
|
+
# Gestión de variables de entorno.
|
|
98
|
+
DESARROLLO = any(
|
|
99
|
+
str(environ.get(var, "")).strip().lower() in VALORES_TRUE for var in [*DEBUG_VARS, *FRAMEWORK_VARS, *GENERIC_VARS]
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
103
|
+
# Directorios base de la aplicacion
|
|
104
|
+
DIRECTORIO_ACTUAL: Path = Path(path.abspath(path.dirname(__file__)))
|
|
105
|
+
DIRECTORIO_APP: Path = DIRECTORIO_ACTUAL.parent.absolute()
|
|
106
|
+
DIRECTORIO_DESARROLLO: Path = DIRECTORIO_APP
|
|
107
|
+
DIRECTORIO_PLANTILLAS_BASE: str = path.join(DIRECTORIO_ACTUAL, "templates")
|
|
108
|
+
DIRECTORIO_ARCHIVOS_BASE: str = path.join(DIRECTORIO_ACTUAL, "static")
|
|
109
|
+
|
|
110
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
111
|
+
# Directorios personalizados para la aplicación.
|
|
112
|
+
DIRECTORIO_ARCHIVOS = DIRECTORIO_ARCHIVOS_BASE
|
|
113
|
+
DIRECTORIO_PLANTILLAS = DIRECTORIO_PLANTILLAS_BASE
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
117
|
+
TESTING = (
|
|
118
|
+
"PYTEST_CURRENT_TEST" in environ
|
|
119
|
+
or "PYTEST_VERSION" in environ
|
|
120
|
+
or "TESTING" in environ
|
|
121
|
+
or hasattr(sys, "_called_from_test")
|
|
122
|
+
or environ.get("CI")
|
|
123
|
+
or "pytest" in sys.modules
|
|
124
|
+
or path.basename(sys.argv[0]) in ["pytest", "py.test"]
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
if TESTING:
|
|
128
|
+
# Use DB in memory for tests to avoid filesystem side-effects
|
|
129
|
+
SQLITE: str = "sqlite:///:memory:"
|
|
130
|
+
else:
|
|
131
|
+
# File-based sqlite in project root
|
|
132
|
+
sqlite_file = DIRECTORIO_DESARROLLO.joinpath("coati_payroll.db")
|
|
133
|
+
SQLITE = f"sqlite:///{sqlite_file.as_posix()}"
|
|
134
|
+
|
|
135
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
136
|
+
# Configuración de la aplicación:
|
|
137
|
+
# Se siguen las recomendaciones de "Twelve Factors App" y las opciones se leen del entorno.
|
|
138
|
+
CONFIGURACION: dict[str, str | bool | Path] = {}
|
|
139
|
+
CONFIGURACION["SECRET_KEY"] = environ.get("SECRET_KEY") or "dev" # nosec
|
|
140
|
+
CONFIGURACION["SQLALCHEMY_DATABASE_URI"] = environ.get("DATABASE_URL") or SQLITE # nosec
|
|
141
|
+
# Opciones comunes de configuración.
|
|
142
|
+
CONFIGURACION["PRESERVE_CONTEXT_ON_EXCEPTION"] = False
|
|
143
|
+
|
|
144
|
+
if DESARROLLO:
|
|
145
|
+
log.warning("Using default configuration.")
|
|
146
|
+
log.info("Default configuration is not recommended for use in production environments.")
|
|
147
|
+
CONFIGURACION["SQLALCHEMY_TRACK_MODIFICATIONS"] = "False"
|
|
148
|
+
CONFIGURACION["TEMPLATES_AUTO_RELOAD"] = True
|
|
149
|
+
|
|
150
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
151
|
+
# Corrige la URI de conexión a la base de datos si el usuario omite el driver apropiado.
|
|
152
|
+
|
|
153
|
+
if DATABASE_URL_BASE := CONFIGURACION.get("SQLALCHEMY_DATABASE_URI"):
|
|
154
|
+
|
|
155
|
+
DATABASE_URL_CORREGIDA = DATABASE_URL_BASE
|
|
156
|
+
|
|
157
|
+
prefix = DATABASE_URL_BASE.split(":", 1)[0] # Extraer prefijo: "postgres", "mysql", etc.
|
|
158
|
+
|
|
159
|
+
# Caso especial: Heroku + PostgreSQL
|
|
160
|
+
if environ.get("DYNO") and prefix in (
|
|
161
|
+
"postgres",
|
|
162
|
+
"postgresql",
|
|
163
|
+
): # type: ignore[operator]
|
|
164
|
+
parsed = urlparse(DATABASE_URL_BASE) # type: ignore[arg-type]
|
|
165
|
+
query = parse_qs(parsed.query)
|
|
166
|
+
query["sslmode"] = ["require"]
|
|
167
|
+
DATABASE_URL_CORREGIDA = urlunparse(parsed._replace(scheme="postgresql", query=urlencode(query, doseq=True)))
|
|
168
|
+
|
|
169
|
+
else:
|
|
170
|
+
# Corrige el esquema según el prefijo detectado
|
|
171
|
+
match prefix:
|
|
172
|
+
case "postgresql":
|
|
173
|
+
parsed = urlparse(DATABASE_URL_BASE)
|
|
174
|
+
query = parse_qs(parsed.query)
|
|
175
|
+
query.pop("sslmode", None)
|
|
176
|
+
new_query = urlencode(query, doseq=True) if query else ""
|
|
177
|
+
cleaned = urlunparse(parsed._replace(query=new_query))
|
|
178
|
+
DATABASE_URL_CORREGIDA = "postgresql+pg8000" + cleaned[10:]
|
|
179
|
+
case "postgres":
|
|
180
|
+
parsed = urlparse(DATABASE_URL_BASE)
|
|
181
|
+
query = parse_qs(parsed.query)
|
|
182
|
+
query.pop("sslmode", None)
|
|
183
|
+
new_query = urlencode(query, doseq=True) if query else ""
|
|
184
|
+
cleaned = urlunparse(parsed._replace(query=new_query))
|
|
185
|
+
DATABASE_URL_CORREGIDA = "postgresql+pg8000" + cleaned[8:]
|
|
186
|
+
case "mysql":
|
|
187
|
+
DATABASE_URL_CORREGIDA = "mysql+pymysql" + DATABASE_URL_BASE[5:]
|
|
188
|
+
case "mariadb":
|
|
189
|
+
DATABASE_URL_CORREGIDA = "mariadb+mariadbconnector" + DATABASE_URL_BASE[7:]
|
|
190
|
+
case _:
|
|
191
|
+
pass
|
|
192
|
+
|
|
193
|
+
# Actualizar configuración si hubo cambio
|
|
194
|
+
if DATABASE_URL_BASE != DATABASE_URL_CORREGIDA:
|
|
195
|
+
log.info(f"Database URI corrected: {DATABASE_URL_BASE} → {DATABASE_URL_CORREGIDA}")
|
|
196
|
+
CONFIGURACION["SQLALCHEMY_DATABASE_URI"] = DATABASE_URL_CORREGIDA
|
|
197
|
+
|
|
198
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
199
|
+
# Queue configuration for background job processing
|
|
200
|
+
# The system will automatically select between Dramatiq (Redis) and Huey (filesystem)
|
|
201
|
+
# based on REDIS_URL availability
|
|
202
|
+
CONFIGURACION["QUEUE_ENABLED"] = environ.get("QUEUE_ENABLED", "1") in [
|
|
203
|
+
"1",
|
|
204
|
+
"true",
|
|
205
|
+
"True",
|
|
206
|
+
"yes",
|
|
207
|
+
]
|
|
208
|
+
CONFIGURACION["QUEUE_STORAGE_PATH"] = environ.get("COATI_QUEUE_PATH") # For Huey filesystem
|
|
209
|
+
|
|
210
|
+
# Background payroll processing configuration
|
|
211
|
+
# Threshold for automatic background processing (number of employees)
|
|
212
|
+
# Payrolls with more employees than this threshold will be processed in background
|
|
213
|
+
# Default: 100 employees. Can be adjusted based on system performance:
|
|
214
|
+
# - For systems with complex formulas or slow performance: lower to 50 or 25
|
|
215
|
+
# - For high-performance systems: increase to 200 or 500
|
|
216
|
+
CONFIGURACION["BACKGROUND_PAYROLL_THRESHOLD"] = int(environ.get("BACKGROUND_PAYROLL_THRESHOLD", "100"))
|
|
217
|
+
|
|
218
|
+
# < --------------------------------------------------------------------------------------------- >
|
|
219
|
+
configuration = CONFIGURACION
|