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,581 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: coati-payroll
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Requires-Python: >=3.11
|
|
5
|
+
Description-Content-Type: text/markdown
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Dist: argon2-cffi
|
|
8
|
+
Requires-Dist: babel
|
|
9
|
+
Requires-Dist: configobj
|
|
10
|
+
Requires-Dist: cryptography
|
|
11
|
+
Requires-Dist: dramatiq[redis]
|
|
12
|
+
Requires-Dist: email-validator
|
|
13
|
+
Requires-Dist: huey
|
|
14
|
+
Requires-Dist: flask
|
|
15
|
+
Requires-Dist: flask-babel
|
|
16
|
+
Requires-Dist: flask-caching
|
|
17
|
+
Requires-Dist: flask-limiter
|
|
18
|
+
Requires-Dist: flask-login
|
|
19
|
+
Requires-Dist: flask-mail
|
|
20
|
+
Requires-Dist: flask-reuploaded
|
|
21
|
+
Requires-Dist: flask-session
|
|
22
|
+
Requires-Dist: flask-sqlalchemy
|
|
23
|
+
Requires-Dist: flask-weasyprint
|
|
24
|
+
Requires-Dist: flask-wtf
|
|
25
|
+
Requires-Dist: mysql-connector-python
|
|
26
|
+
Requires-Dist: openpyxl
|
|
27
|
+
Requires-Dist: orjson
|
|
28
|
+
Requires-Dist: pg8000
|
|
29
|
+
Requires-Dist: python-dateutil
|
|
30
|
+
Requires-Dist: python-ulid
|
|
31
|
+
Requires-Dist: sqlalchemy
|
|
32
|
+
Requires-Dist: redis
|
|
33
|
+
Requires-Dist: waitress
|
|
34
|
+
Requires-Dist: weasyprint
|
|
35
|
+
Requires-Dist: wtforms
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
# Coati Payroll
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
[](https://github.com/williamjmorenor/coati-payroll/actions/workflows/python-package.yml)
|
|
43
|
+
[](https://codecov.io/github/bmosoluciones/coati-payroll)
|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
A jurisdiction-agnostic payroll calculation engine developed by BMO Soluciones, S.A.
|
|
47
|
+
|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
-----------
|
|
51
|
+
|
|
52
|
+
[](https://via.placeholder.com/800x600.png?text=Dashboard) [](https://via.placeholder.com/800x600.png?text=Employee+Management) [](https://via.placeholder.com/800x600.png?text=Payroll+Processing) [](https://via.placeholder.com/800x600.png?text=Reports)
|
|
53
|
+
|
|
54
|
+
-----------
|
|
55
|
+
|
|
56
|
+
**Coati Payroll** is a flexible and extensible payroll calculation engine, completely jurisdiction-agnostic. The system is designed so that organizations and implementers can define their own payroll rules through configuration, without the need to modify the source code.
|
|
57
|
+
|
|
58
|
+
The engine does not incorporate hardcoded legal rules. All earnings, deductions, benefits, taxes, and other payroll concepts exist only if the implementer configures them.
|
|
59
|
+
|
|
60
|
+
> **Important**: This project is governed by a [Social Contract](SOCIAL_CONTRACT.md) that clearly defines its scope, purpose, and limitations. Please read it before using the system in production.
|
|
61
|
+
|
|
62
|
+
## Key Features
|
|
63
|
+
|
|
64
|
+
- **Jurisdiction-Agnostic**: No hardcoded legal rules; all payroll logic is defined through configuration
|
|
65
|
+
- **Configurable Calculation Engine**: Payroll processing with fully configurable formulas and schemas
|
|
66
|
+
- **Flexible Calculation Rules**: Rule system that allows implementing any payroll logic through configuration
|
|
67
|
+
- **Multi-company**: Manage payrolls for multiple companies or entities from a single system
|
|
68
|
+
- **Employee Management**: Complete registration of personal, work, and salary information
|
|
69
|
+
- **Custom Fields**: Extend employee information with custom fields
|
|
70
|
+
- **Configurable Earnings**: Define any type of additional income (bonuses, commissions, overtime, etc.)
|
|
71
|
+
- **Priority-Based Deductions**: Configure deductions in priority order according to your needs
|
|
72
|
+
- **Employer Benefits**: Configure benefits and employer contributions as required
|
|
73
|
+
- **Loans and Advances**: Loan control with automatic installment deduction
|
|
74
|
+
- **Multi-currency**: Support for multiple currencies with exchange rates
|
|
75
|
+
- **Background Processing**: Queue system for large payrolls with Dramatiq/Huey
|
|
76
|
+
- **Vacation Management**: Complete module for vacation accrual, usage, and audit with configurable policies
|
|
77
|
+
- **Role-Based Access Control (RBAC)**: Permission system with Admin, HR, and Audit roles
|
|
78
|
+
- **Reporting System**: Custom reports with role-based permissions and execution audit
|
|
79
|
+
- **Internationalization**: Multi-language support with interface and content translation
|
|
80
|
+
|
|
81
|
+
## Quick Installation
|
|
82
|
+
|
|
83
|
+
### Requirements
|
|
84
|
+
|
|
85
|
+
- Python 3.11 or higher
|
|
86
|
+
- pip (Python package manager)
|
|
87
|
+
|
|
88
|
+
### Steps
|
|
89
|
+
|
|
90
|
+
1. **Clone the repository**
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/williamjmorenor/coati-payroll.git
|
|
94
|
+
cd coati-payroll
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
2. **Create and activate virtual environment**
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
python -m venv venv
|
|
101
|
+
source venv/bin/activate # Linux/macOS
|
|
102
|
+
# or
|
|
103
|
+
venv\Scripts\activate # Windows
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
3. **Install dependencies**
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install -r requirements.txt
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
4. **Run the application**
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
python app.py
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
5. **Access the system**
|
|
119
|
+
|
|
120
|
+
Open your browser at `http://localhost:5000`
|
|
121
|
+
|
|
122
|
+
**Default credentials:**
|
|
123
|
+
- User: `coati-admin`
|
|
124
|
+
- Password: `coati-admin`
|
|
125
|
+
|
|
126
|
+
> **Important**: Change the default credentials in production environments.
|
|
127
|
+
|
|
128
|
+
## Documentation
|
|
129
|
+
|
|
130
|
+
Complete documentation is available in the `docs/` directory and can be generated with MkDocs:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Install documentation dependencies
|
|
134
|
+
pip install -r docs.txt
|
|
135
|
+
|
|
136
|
+
# Serve documentation locally
|
|
137
|
+
mkdocs serve
|
|
138
|
+
|
|
139
|
+
# Generate static documentation
|
|
140
|
+
mkdocs build
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Documentation Contents
|
|
144
|
+
|
|
145
|
+
- **[Quick Start Guide](docs/guia/inicio-rapido.md)**: 15 minutes from installation to your first payroll - ideal for evaluating the system
|
|
146
|
+
- **Installation Guide**: Requirements, installation, and initial configuration
|
|
147
|
+
- **User Guide**: Users, companies, currencies, employees, custom fields, payroll concepts, calculation rules, loans, vacations, accounting configuration
|
|
148
|
+
- **Complete Tutorial**: Step by step to configure and run a payroll with all components
|
|
149
|
+
- **Advanced Features**:
|
|
150
|
+
- Queue system and background processing
|
|
151
|
+
- Database compatibility (SQLite, PostgreSQL, MySQL/MariaDB)
|
|
152
|
+
- Role-based access control (RBAC)
|
|
153
|
+
- Vacation management with configurable policies
|
|
154
|
+
- Custom reporting system
|
|
155
|
+
- Internationalization and translation
|
|
156
|
+
- **Reference**: Glossary, frequently asked questions, exchange rate import
|
|
157
|
+
|
|
158
|
+
## Architecture
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
coati/
|
|
162
|
+
├── app.py # Application entry point
|
|
163
|
+
├── coati_payroll/ # Main module
|
|
164
|
+
│ ├── __init__.py # Flask application factory
|
|
165
|
+
│ ├── model.py # Database models (SQLAlchemy)
|
|
166
|
+
│ ├── nomina_engine/ # Payroll calculation engine (refactored)
|
|
167
|
+
│ │ ├── __init__.py
|
|
168
|
+
│ │ ├── engine.py # Main orchestrator
|
|
169
|
+
│ │ ├── domain/ # Domain models
|
|
170
|
+
│ │ │ ├── payroll_context.py
|
|
171
|
+
│ │ │ ├── employee_calculation.py
|
|
172
|
+
│ │ │ └── calculation_items.py
|
|
173
|
+
│ │ ├── validators/ # Validations
|
|
174
|
+
│ │ │ ├── base_validator.py
|
|
175
|
+
│ │ │ ├── planilla_validator.py
|
|
176
|
+
│ │ │ ├── employee_validator.py
|
|
177
|
+
│ │ │ ├── period_validator.py
|
|
178
|
+
│ │ │ └── currency_validator.py
|
|
179
|
+
│ │ ├── calculators/ # Calculations
|
|
180
|
+
│ │ │ ├── salary_calculator.py
|
|
181
|
+
│ │ │ ├── concept_calculator.py
|
|
182
|
+
│ │ │ ├── perception_calculator.py
|
|
183
|
+
│ │ │ ├── deduction_calculator.py
|
|
184
|
+
│ │ │ ├── benefit_calculator.py
|
|
185
|
+
│ │ │ └── exchange_rate_calculator.py
|
|
186
|
+
│ │ ├── processors/ # Specific processors
|
|
187
|
+
│ │ │ ├── loan_processor.py
|
|
188
|
+
│ │ │ ├── accumulation_processor.py
|
|
189
|
+
│ │ │ ├── vacation_processor.py
|
|
190
|
+
│ │ │ ├── novelty_processor.py
|
|
191
|
+
│ │ │ └── accounting_processor.py
|
|
192
|
+
│ │ ├── repositories/ # Data access
|
|
193
|
+
│ │ │ ├── base_repository.py
|
|
194
|
+
│ │ │ ├── planilla_repository.py
|
|
195
|
+
│ │ │ ├── employee_repository.py
|
|
196
|
+
│ │ │ ├── acumulado_repository.py
|
|
197
|
+
│ │ │ ├── novelty_repository.py
|
|
198
|
+
│ │ │ ├── exchange_rate_repository.py
|
|
199
|
+
│ │ │ └── config_repository.py
|
|
200
|
+
│ │ ├── services/ # Business services
|
|
201
|
+
│ │ │ ├── payroll_execution_service.py
|
|
202
|
+
│ │ │ └── employee_processing_service.py
|
|
203
|
+
│ │ └── results/ # Results and DTOs
|
|
204
|
+
│ │ ├── payroll_result.py
|
|
205
|
+
│ │ ├── validation_result.py
|
|
206
|
+
│ │ └── error_result.py
|
|
207
|
+
│ ├── formula_engine/ # Formula engine (refactored)
|
|
208
|
+
│ │ ├── __init__.py
|
|
209
|
+
│ │ ├── engine.py # Main orchestrator
|
|
210
|
+
│ │ ├── exceptions.py # Custom exceptions
|
|
211
|
+
│ │ ├── data_sources.py # Available data sources
|
|
212
|
+
│ │ ├── novelty_codes.py # Novelty codes
|
|
213
|
+
│ │ ├── ast/ # Expression evaluation (Visitor pattern)
|
|
214
|
+
│ │ │ ├── ast_visitor.py
|
|
215
|
+
│ │ │ ├── expression_evaluator.py
|
|
216
|
+
│ │ │ ├── safe_operators.py
|
|
217
|
+
│ │ │ └── type_converter.py
|
|
218
|
+
│ │ ├── validation/ # Validations
|
|
219
|
+
│ │ │ ├── schema_validator.py
|
|
220
|
+
│ │ │ ├── tax_table_validator.py
|
|
221
|
+
│ │ │ └── security_validator.py
|
|
222
|
+
│ │ ├── steps/ # Step types (Strategy pattern)
|
|
223
|
+
│ │ │ ├── base_step.py
|
|
224
|
+
│ │ │ ├── calculation_step.py
|
|
225
|
+
│ │ │ ├── conditional_step.py
|
|
226
|
+
│ │ │ ├── tax_lookup_step.py
|
|
227
|
+
│ │ │ ├── assignment_step.py
|
|
228
|
+
│ │ │ └── step_factory.py
|
|
229
|
+
│ │ ├── tables/ # Tax tables
|
|
230
|
+
│ │ │ ├── tax_table.py
|
|
231
|
+
│ │ │ ├── bracket_calculator.py
|
|
232
|
+
│ │ │ └── table_lookup.py
|
|
233
|
+
│ │ ├── execution/ # Execution context
|
|
234
|
+
│ │ │ ├── execution_context.py
|
|
235
|
+
│ │ │ ├── step_executor.py
|
|
236
|
+
│ │ │ └── variable_store.py
|
|
237
|
+
│ │ └── results/ # Results
|
|
238
|
+
│ │ └── execution_result.py
|
|
239
|
+
│ ├── formula_engine_examples.py # Schema examples
|
|
240
|
+
│ ├── vacation_service.py # Vacation management service
|
|
241
|
+
│ ├── rbac.py # Role-based access control
|
|
242
|
+
│ ├── report_engine.py # Reporting engine
|
|
243
|
+
│ ├── forms.py # WTForms forms
|
|
244
|
+
│ ├── cli.py # Command-line interface (payrollctl)
|
|
245
|
+
│ ├── queue/ # Queue system (Dramatiq/Huey)
|
|
246
|
+
│ │ ├── driver.py
|
|
247
|
+
│ │ ├── selector.py
|
|
248
|
+
│ │ ├── tasks.py
|
|
249
|
+
│ │ └── drivers/
|
|
250
|
+
│ ├── vistas/ # Views/Controllers (Blueprints)
|
|
251
|
+
│ │ ├── planilla/ # Payroll module
|
|
252
|
+
│ │ └── [other modules]
|
|
253
|
+
│ ├── templates/ # HTML templates (Jinja2)
|
|
254
|
+
│ ├── translations/ # Translation files (i18n)
|
|
255
|
+
│ └── static/ # Static files
|
|
256
|
+
├── docs/ # MkDocs documentation
|
|
257
|
+
├── requirements.txt # Production dependencies
|
|
258
|
+
├── development.txt # Development dependencies
|
|
259
|
+
└── docs.txt # Documentation dependencies
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Configuration
|
|
263
|
+
|
|
264
|
+
### Command Line Interface (CLI)
|
|
265
|
+
|
|
266
|
+
The system includes the `payrollctl` tool for common administrative tasks. You can also use `flask` for built-in commands.
|
|
267
|
+
|
|
268
|
+
**System Operations:**
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# View system status
|
|
272
|
+
payrollctl system status
|
|
273
|
+
|
|
274
|
+
# Run system checks
|
|
275
|
+
payrollctl system check
|
|
276
|
+
|
|
277
|
+
# View system information
|
|
278
|
+
payrollctl system info
|
|
279
|
+
|
|
280
|
+
# View environment variables
|
|
281
|
+
payrollctl system env
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Database Management:**
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# View database status
|
|
288
|
+
payrollctl database status
|
|
289
|
+
|
|
290
|
+
# Initialize database and create admin user
|
|
291
|
+
payrollctl database init
|
|
292
|
+
|
|
293
|
+
# Load initial data (currencies, concepts, etc.)
|
|
294
|
+
payrollctl database seed
|
|
295
|
+
|
|
296
|
+
# Create database backup using native tools
|
|
297
|
+
# SQLite: Copy file | PostgreSQL: pg_dump | MySQL: mysqldump
|
|
298
|
+
payrollctl database backup -o backup_$(date +%Y%m%d).sql
|
|
299
|
+
|
|
300
|
+
# Restore database from backup
|
|
301
|
+
payrollctl database restore backup.db
|
|
302
|
+
|
|
303
|
+
# Database migration (requires flask-migrate)
|
|
304
|
+
payrollctl database migrate
|
|
305
|
+
payrollctl database upgrade
|
|
306
|
+
|
|
307
|
+
# Drop all tables (CAUTION!)
|
|
308
|
+
payrollctl database drop
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**User Management:**
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
# List all users
|
|
315
|
+
payrollctl users list
|
|
316
|
+
|
|
317
|
+
# Create a new user
|
|
318
|
+
payrollctl users create
|
|
319
|
+
|
|
320
|
+
# Disable a user
|
|
321
|
+
payrollctl users disable username
|
|
322
|
+
|
|
323
|
+
# Reset password
|
|
324
|
+
payrollctl users reset-password username
|
|
325
|
+
|
|
326
|
+
# Create or update admin user (disables other admins)
|
|
327
|
+
payrollctl users set-admin
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**Cache Management:**
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# Clear application caches
|
|
334
|
+
payrollctl cache clear
|
|
335
|
+
|
|
336
|
+
# Warm up caches
|
|
337
|
+
payrollctl cache warm
|
|
338
|
+
|
|
339
|
+
# View cache status
|
|
340
|
+
payrollctl cache status
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**Maintenance Tasks:**
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
# Clean up expired sessions
|
|
347
|
+
payrollctl maintenance cleanup-sessions
|
|
348
|
+
|
|
349
|
+
# Clean up temporary files
|
|
350
|
+
payrollctl maintenance cleanup-temp
|
|
351
|
+
|
|
352
|
+
# Run pending background jobs
|
|
353
|
+
payrollctl maintenance run-jobs
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Diagnostics and Debugging:**
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# View application configuration
|
|
360
|
+
payrollctl debug config
|
|
361
|
+
|
|
362
|
+
# List all application routes
|
|
363
|
+
payrollctl debug routes
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Note**: All commands also work with `flask` (e.g., `flask system status`).
|
|
367
|
+
|
|
368
|
+
**Automated Backups**: To configure automatic daily backups with systemd timers, see [Automated Backups Guide](docs/automated-backups.md).
|
|
369
|
+
|
|
370
|
+
### Environment Variables
|
|
371
|
+
|
|
372
|
+
| Variable | Description | Default Value |
|
|
373
|
+
|----------|-------------|---------------|
|
|
374
|
+
| `DATABASE_URL` | Database connection URI | Local SQLite |
|
|
375
|
+
| `SECRET_KEY` | Secret key for sessions | Auto-generated |
|
|
376
|
+
| `ADMIN_USER` | Initial admin user | `coati-admin` |
|
|
377
|
+
| `ADMIN_PASSWORD` | Admin password | `coati-admin` |
|
|
378
|
+
| `PORT` | Application port | `5000` |
|
|
379
|
+
| `SESSION_REDIS_URL` | Redis URL for sessions | None (uses SQLAlchemy) |
|
|
380
|
+
| `REDIS_URL` | Redis URL for queue system | None (uses Huey) |
|
|
381
|
+
| `QUEUE_ENABLED` | Enable queue system | `1` |
|
|
382
|
+
| `COATI_QUEUE_PATH` | Path for Huey storage | Auto-detected |
|
|
383
|
+
| `BACKGROUND_PAYROLL_THRESHOLD` | Employee threshold for background processing | `100` |
|
|
384
|
+
|
|
385
|
+
### Database
|
|
386
|
+
|
|
387
|
+
The system supports:
|
|
388
|
+
- **SQLite**: For development and testing (default)
|
|
389
|
+
- **PostgreSQL**: Recommended for production
|
|
390
|
+
- **MySQL/MariaDB**: Production alternative
|
|
391
|
+
|
|
392
|
+
The system is designed to be **database engine agnostic**. For more details on compatibility and configuration, see the [Database Compatibility Guide](docs/database-compatibility.md).
|
|
393
|
+
|
|
394
|
+
### Queue System
|
|
395
|
+
|
|
396
|
+
For long-running operations, the system includes a **background process queue system**:
|
|
397
|
+
|
|
398
|
+
- **Dramatiq + Redis**: For production environments with high scale
|
|
399
|
+
- **Huey + Filesystem**: For development or as automatic fallback
|
|
400
|
+
- **Automatic selection**: The system chooses the best available backend
|
|
401
|
+
- **Parallel processing**: Large payrolls are automatically processed in the background
|
|
402
|
+
- **Real-time feedback**: Task progress tracking
|
|
403
|
+
|
|
404
|
+
For more information, see the [Queue System Documentation](docs/queue_system.md) and [Background Payroll Processing](docs/background-payroll-processing.md).
|
|
405
|
+
|
|
406
|
+
## Workflow
|
|
407
|
+
|
|
408
|
+
```mermaid
|
|
409
|
+
graph LR
|
|
410
|
+
A[Configure Currencies] --> B[Create Earnings/Deductions/Benefits]
|
|
411
|
+
B --> C[Register Employees]
|
|
412
|
+
C --> D[Create Payroll]
|
|
413
|
+
D --> E[Assign Components]
|
|
414
|
+
E --> F[Execute Payroll]
|
|
415
|
+
F --> G[Review and Approve]
|
|
416
|
+
G --> H[Apply Payroll]
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Payroll Calculation
|
|
420
|
+
|
|
421
|
+
The payroll engine processes in this order:
|
|
422
|
+
|
|
423
|
+
1. **Base Salary**: Salary defined for the employee according to the payroll period
|
|
424
|
+
2. **Earnings**: Added to base salary → Gross Salary
|
|
425
|
+
3. **Deductions**: Subtracted in priority order → Net Salary
|
|
426
|
+
4. **Benefits**: Calculated as employer costs (do not affect net salary)
|
|
427
|
+
|
|
428
|
+
### Illustrative Calculation Example
|
|
429
|
+
|
|
430
|
+
> **Important Note**: This is an illustrative example with generic values and concepts. Concept names, percentages, and specific calculations **must be configured by the implementer** according to the laws and policies of their jurisdiction. The engine **does not include predefined legal rules**.
|
|
431
|
+
|
|
432
|
+
```
|
|
433
|
+
Base Salary: $ 10,000.00
|
|
434
|
+
+ Earning A: $ 500.00
|
|
435
|
+
+ Earning B: $ 300.00
|
|
436
|
+
= GROSS SALARY: $ 10,800.00
|
|
437
|
+
|
|
438
|
+
- Deduction A (X%): $ 756.00
|
|
439
|
+
- Deduction B (Y%): $ 540.00
|
|
440
|
+
- Deduction C: $ 200.00
|
|
441
|
+
= NET SALARY: $ 9,304.00
|
|
442
|
+
|
|
443
|
+
Employer Benefits (Company Costs):
|
|
444
|
+
+ Benefit A (W%): $ 2,160.00
|
|
445
|
+
+ Benefit B (Z%): $ 216.00
|
|
446
|
+
+ Benefit C (P%): $ 899.64
|
|
447
|
+
+ Benefit D (P%): $ 899.64
|
|
448
|
+
+ Benefit E (P%): $ 899.64
|
|
449
|
+
= TOTAL COMPANY COST: $ 15,178.92
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**How to configure these concepts?**
|
|
453
|
+
|
|
454
|
+
All concepts, percentages, and calculation rules are defined through:
|
|
455
|
+
- **Configurable earnings**: Define any type of additional income
|
|
456
|
+
- **Priority-based deductions**: Configure the order and formula for each deduction
|
|
457
|
+
- **Employer benefits**: Configure contributions according to your jurisdiction
|
|
458
|
+
- **Calculation rules**: Use the rule engine to implement complex logic (brackets, caps, exemptions, etc.)
|
|
459
|
+
|
|
460
|
+
See the [complete documentation](docs/) to learn how to configure your payroll system.
|
|
461
|
+
|
|
462
|
+
## Development
|
|
463
|
+
|
|
464
|
+
### Install development dependencies
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
pip install -r development.txt
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Database Structure
|
|
471
|
+
|
|
472
|
+
The main models are:
|
|
473
|
+
|
|
474
|
+
**System Configuration:**
|
|
475
|
+
- `Usuario`: System users with roles (Admin, HR, Audit)
|
|
476
|
+
- `Empresa`: Companies or entities that hire employees
|
|
477
|
+
- `Moneda`: System currencies
|
|
478
|
+
- `TipoCambio`: Exchange rates between currencies
|
|
479
|
+
- `ConfiguracionGlobal`: Global system configuration
|
|
480
|
+
|
|
481
|
+
**Personnel Management:**
|
|
482
|
+
- `Empleado`: Employee master record
|
|
483
|
+
- `CampoPersonalizado`: Custom fields for employees
|
|
484
|
+
- `HistorialSalario`: Salary change history
|
|
485
|
+
|
|
486
|
+
**Payroll:**
|
|
487
|
+
- `Percepcion`: Income concepts
|
|
488
|
+
- `Deduccion`: Deduction concepts
|
|
489
|
+
- `Prestacion`: Employer contributions
|
|
490
|
+
- `ReglaCalculo`: Calculation rules with configurable schemas
|
|
491
|
+
- `TipoPlanilla`: Payroll types (monthly, biweekly, etc.)
|
|
492
|
+
- `Planilla`: Payroll configuration
|
|
493
|
+
- `Nomina`: Payroll execution
|
|
494
|
+
- `NominaEmpleado`: Payroll detail per employee
|
|
495
|
+
- `NominaDetalle`: Detail lines (earnings, deductions)
|
|
496
|
+
- `NominaNovedad`: Payroll novelties
|
|
497
|
+
- `ComprobanteContable`: Accounting vouchers
|
|
498
|
+
|
|
499
|
+
**Loans:**
|
|
500
|
+
- `Adelanto`: Employee loans and advances
|
|
501
|
+
- `AdelantoAbono`: Loan payments
|
|
502
|
+
|
|
503
|
+
**Vacations:**
|
|
504
|
+
- `VacationPolicy`: Configurable vacation policies
|
|
505
|
+
- `VacationAccount`: Vacation accounts per employee
|
|
506
|
+
- `VacationLedger`: Vacation ledger (audit)
|
|
507
|
+
- `VacationNovelty`: Vacation requests and novelties
|
|
508
|
+
- `ConfiguracionVacaciones`: Vacation configuration (legacy)
|
|
509
|
+
- `VacacionEmpleado`: Employee vacations (legacy)
|
|
510
|
+
- `PrestacionAcumulada`: Accumulated benefits
|
|
511
|
+
- `CargaInicialPrestacion`: Initial benefit load
|
|
512
|
+
|
|
513
|
+
**Reports:**
|
|
514
|
+
- `Report`: Custom report definitions
|
|
515
|
+
- `ReportRole`: Report permissions by role
|
|
516
|
+
- `ReportExecution`: Report execution history
|
|
517
|
+
- `ReportAudit`: Report audit
|
|
518
|
+
|
|
519
|
+
## Social Contract and Responsibilities
|
|
520
|
+
|
|
521
|
+
This project is governed by a [Social Contract](SOCIAL_CONTRACT.md) that clearly establishes:
|
|
522
|
+
|
|
523
|
+
### Project Scope
|
|
524
|
+
|
|
525
|
+
- **Jurisdiction-agnostic engine**: Does not include and will not include hardcoded legal rules
|
|
526
|
+
- **Strict separation**: Between calculation engine, rule configuration, and payroll orchestration
|
|
527
|
+
- **Predictable and reproducible calculation**: Calculations are deterministic and auditable
|
|
528
|
+
- **Extensible by configuration**: Any legal change is implemented through configuration, not code
|
|
529
|
+
|
|
530
|
+
### Default Functionality
|
|
531
|
+
|
|
532
|
+
The engine, by default, **only** calculates:
|
|
533
|
+
1. Employee base salary according to the defined period
|
|
534
|
+
2. Salary advance installments when they exist
|
|
535
|
+
|
|
536
|
+
All other concepts (earnings, deductions, benefits, taxes, caps, brackets, exemptions) exist only if the implementer configures them.
|
|
537
|
+
|
|
538
|
+
### Implementer Responsibility
|
|
539
|
+
|
|
540
|
+
Correct use of the engine requires that the implementer:
|
|
541
|
+
- Has knowledge of how payroll is calculated in their jurisdiction
|
|
542
|
+
- Understands the applicable legal framework
|
|
543
|
+
- Is capable of manually calculating a complete payroll
|
|
544
|
+
- Compares manual results with system results
|
|
545
|
+
- Identifies and corrects configuration errors
|
|
546
|
+
|
|
547
|
+
### Warranties and Limitations
|
|
548
|
+
|
|
549
|
+
This software is distributed under the Apache 2.0 License **"AS IS"**:
|
|
550
|
+
- ✅ **Promises**: Predictable, reproducible, and auditable calculations
|
|
551
|
+
- ✅ **Promises**: Remain jurisdiction-agnostic
|
|
552
|
+
- ✅ **Promises**: Separation between engine and configuration
|
|
553
|
+
- ❌ **Does not guarantee**: Regulatory compliance in any jurisdiction
|
|
554
|
+
- ❌ **Does not guarantee**: Correct results without appropriate configuration
|
|
555
|
+
- ❌ **Does not replace**: Professional knowledge or legal advice
|
|
556
|
+
|
|
557
|
+
**For more details, read the complete [Social Contract](SOCIAL_CONTRACT.md) before using this system in production.**
|
|
558
|
+
|
|
559
|
+
## Support
|
|
560
|
+
|
|
561
|
+
To report issues or request features, please open an [Issue on GitHub](https://github.com/williamjmorenor/coati-payroll/issues).
|
|
562
|
+
|
|
563
|
+
## License
|
|
564
|
+
|
|
565
|
+
This project is licensed under the **Apache License 2.0** - a permissive open-source license that allows free use, modification, and distribution (including for commercial purposes), as long as copyright and license notices are preserved. It also includes a patent grant to protect users from patent claims but terminates rights if you file such claims. You may combine Apache-licensed code with proprietary software, but you cannot use Apache trademarks or logos without permission, and you must provide proper attribution to the original authors.
|
|
566
|
+
|
|
567
|
+
For more details, see the [LICENSE](LICENSE) file.
|
|
568
|
+
|
|
569
|
+
## Contributing
|
|
570
|
+
|
|
571
|
+
Contributions are welcome. Please:
|
|
572
|
+
|
|
573
|
+
1. Fork the repository
|
|
574
|
+
2. Create a branch for your feature (`git checkout -b feature/new-feature`)
|
|
575
|
+
3. Commit your changes (`git commit -am 'Add new feature'`)
|
|
576
|
+
4. Push to the branch (`git push origin feature/new-feature`)
|
|
577
|
+
5. Open a Pull Request
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
Made with ❤️ by [BMO Soluciones, S.A.](https://github.com/williamjmorenor)
|