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,177 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
{% from "macros.html" import render_field, render_messages, render_form_errors %}
|
|
3
|
+
|
|
4
|
+
{% block content %}
|
|
5
|
+
{{ render_messages() }}
|
|
6
|
+
{{ render_form_errors(form) }}
|
|
7
|
+
|
|
8
|
+
<div class="content-header d-flex justify-content-between align-items-center mb-4">
|
|
9
|
+
<h3>
|
|
10
|
+
<i class="bi bi-{{ 'pencil' if is_edit else 'plus-circle' }}"></i>
|
|
11
|
+
{% if is_edit %}
|
|
12
|
+
{{ _('Editar Novedad') }}
|
|
13
|
+
{% else %}
|
|
14
|
+
{{ _('Nueva Novedad') }}
|
|
15
|
+
{% endif %}
|
|
16
|
+
</h3>
|
|
17
|
+
<a href="{{ url_for('planilla.listar_novedades', planilla_id=planilla.id, nomina_id=nomina.id) }}" class="btn btn-secondary">
|
|
18
|
+
<i class="bi bi-arrow-left"></i> {{ _('Volver') }}
|
|
19
|
+
</a>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div class="card mb-4">
|
|
23
|
+
<div class="card-header bg-light">
|
|
24
|
+
<div class="row">
|
|
25
|
+
<div class="col-md-4">
|
|
26
|
+
<strong>{{ _('Planilla:') }}</strong> {{ planilla.nombre }}
|
|
27
|
+
</div>
|
|
28
|
+
<div class="col-md-4">
|
|
29
|
+
<strong>{{ _('Período:') }}</strong> {{ nomina.periodo_inicio.strftime('%d/%m/%Y') }} - {{ nomina.periodo_fin.strftime('%d/%m/%Y') }}
|
|
30
|
+
</div>
|
|
31
|
+
<div class="col-md-4">
|
|
32
|
+
<strong>{{ _('Estado:') }}</strong>
|
|
33
|
+
{% if nomina.estado == 'generado' %}
|
|
34
|
+
<span class="badge bg-warning text-dark">{{ _('Generado') }}</span>
|
|
35
|
+
{% elif nomina.estado == 'aprobado' %}
|
|
36
|
+
<span class="badge bg-info">{{ _('Aprobado') }}</span>
|
|
37
|
+
{% endif %}
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div class="card">
|
|
44
|
+
<div class="card-header">
|
|
45
|
+
<h5 class="mb-0">{{ _('Datos de la Novedad') }}</h5>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="card-body">
|
|
48
|
+
<form method="post" novalidate>
|
|
49
|
+
{{ form.hidden_tag() }}
|
|
50
|
+
|
|
51
|
+
<div class="row">
|
|
52
|
+
<!-- Empleado -->
|
|
53
|
+
<div class="col-md-6">
|
|
54
|
+
{{ render_field(form.empleado_id) }}
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<!-- Tipo de Concepto -->
|
|
58
|
+
<div class="col-md-6">
|
|
59
|
+
{{ render_field(form.tipo_concepto) }}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div class="row">
|
|
64
|
+
<!-- Percepción (visible when tipo_concepto = percepcion) -->
|
|
65
|
+
<div class="col-md-6" id="percepcion-group">
|
|
66
|
+
{{ render_field(form.percepcion_id) }}
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<!-- Deducción (visible when tipo_concepto = deduccion) -->
|
|
70
|
+
<div class="col-md-6" id="deduccion-group">
|
|
71
|
+
{{ render_field(form.deduccion_id) }}
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="row">
|
|
76
|
+
<!-- Código del Concepto -->
|
|
77
|
+
<div class="col-md-6">
|
|
78
|
+
{{ render_field(form.codigo_concepto) }}
|
|
79
|
+
<small class="text-muted">
|
|
80
|
+
{{ _('Este código identifica el concepto en el sistema. Se actualizará automáticamente al seleccionar una percepción o deducción.') }}
|
|
81
|
+
</small>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<!-- Tipo de Valor -->
|
|
85
|
+
<div class="col-md-6">
|
|
86
|
+
{{ render_field(form.tipo_valor) }}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div class="row">
|
|
91
|
+
<!-- Valor / Cantidad -->
|
|
92
|
+
<div class="col-md-6">
|
|
93
|
+
{{ render_field(form.valor_cantidad) }}
|
|
94
|
+
<small class="text-muted">
|
|
95
|
+
{{ _('Ingrese el valor según el tipo seleccionado (ej: 5 para 5 horas, 1500 para un monto fijo).') }}
|
|
96
|
+
</small>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<!-- Fecha de la Novedad -->
|
|
100
|
+
<div class="col-md-6">
|
|
101
|
+
{{ render_field(form.fecha_novedad) }}
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<hr>
|
|
106
|
+
|
|
107
|
+
<div class="d-flex justify-content-between">
|
|
108
|
+
<a href="{{ url_for('planilla.listar_novedades', planilla_id=planilla.id, nomina_id=nomina.id) }}" class="btn btn-secondary">
|
|
109
|
+
<i class="bi bi-x-circle"></i> {{ _('Cancelar') }}
|
|
110
|
+
</a>
|
|
111
|
+
{{ form.submit(class="btn btn-primary") }}
|
|
112
|
+
</div>
|
|
113
|
+
</form>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<script>
|
|
118
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
119
|
+
const tipoConcepto = document.getElementById('tipo_concepto');
|
|
120
|
+
const percepcionGroup = document.getElementById('percepcion-group');
|
|
121
|
+
const deduccionGroup = document.getElementById('deduccion-group');
|
|
122
|
+
const percepcionSelect = document.getElementById('percepcion_id');
|
|
123
|
+
const deduccionSelect = document.getElementById('deduccion_id');
|
|
124
|
+
const codigoConcepto = document.getElementById('codigo_concepto');
|
|
125
|
+
|
|
126
|
+
// Early return if required elements are not found
|
|
127
|
+
if (!tipoConcepto || !percepcionGroup || !deduccionGroup) {
|
|
128
|
+
console.warn('Required form elements not found');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function updateVisibility() {
|
|
133
|
+
if (tipoConcepto.value === 'percepcion') {
|
|
134
|
+
percepcionGroup.style.display = 'block';
|
|
135
|
+
deduccionGroup.style.display = 'none';
|
|
136
|
+
} else {
|
|
137
|
+
percepcionGroup.style.display = 'none';
|
|
138
|
+
deduccionGroup.style.display = 'block';
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function updateCodigoFromPercepcion() {
|
|
143
|
+
if (!percepcionSelect || !codigoConcepto) return;
|
|
144
|
+
const selectedOption = percepcionSelect.options[percepcionSelect.selectedIndex];
|
|
145
|
+
if (selectedOption && selectedOption.value) {
|
|
146
|
+
// Extract codigo from the option text (format: "CODIGO - Nombre")
|
|
147
|
+
const text = selectedOption.text;
|
|
148
|
+
const codigo = text.split(' - ')[0];
|
|
149
|
+
if (codigo && codigo !== '--') {
|
|
150
|
+
codigoConcepto.value = codigo;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function updateCodigoFromDeduccion() {
|
|
156
|
+
if (!deduccionSelect || !codigoConcepto) return;
|
|
157
|
+
const selectedOption = deduccionSelect.options[deduccionSelect.selectedIndex];
|
|
158
|
+
if (selectedOption && selectedOption.value) {
|
|
159
|
+
// Extract codigo from the option text (format: "CODIGO - Nombre")
|
|
160
|
+
const text = selectedOption.text;
|
|
161
|
+
const codigo = text.split(' - ')[0];
|
|
162
|
+
if (codigo && codigo !== '--') {
|
|
163
|
+
codigoConcepto.value = codigo;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Initial visibility
|
|
169
|
+
updateVisibility();
|
|
170
|
+
|
|
171
|
+
// Event listeners
|
|
172
|
+
tipoConcepto.addEventListener('change', updateVisibility);
|
|
173
|
+
percepcionSelect.addEventListener('change', updateCodigoFromPercepcion);
|
|
174
|
+
deduccionSelect.addEventListener('change', updateCodigoFromDeduccion);
|
|
175
|
+
});
|
|
176
|
+
</script>
|
|
177
|
+
{% endblock %}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
{% from "macros.html" import render_messages %}
|
|
3
|
+
|
|
4
|
+
{% block content %}
|
|
5
|
+
{{ render_messages() }}
|
|
6
|
+
|
|
7
|
+
<div class="content-header d-flex justify-content-between align-items-center mb-4">
|
|
8
|
+
<h3>
|
|
9
|
+
<i class="bi bi-list-check"></i>
|
|
10
|
+
{{ _('Novedades de la Nómina') }}
|
|
11
|
+
</h3>
|
|
12
|
+
<div>
|
|
13
|
+
<a href="{{ url_for('planilla.ver_nomina', planilla_id=planilla.id, nomina_id=nomina.id) }}" class="btn btn-secondary">
|
|
14
|
+
<i class="bi bi-arrow-left"></i> {{ _('Volver a la Nómina') }}
|
|
15
|
+
</a>
|
|
16
|
+
{% if nomina.estado != 'aplicado' %}
|
|
17
|
+
<a href="{{ url_for('planilla.nueva_novedad', planilla_id=planilla.id, nomina_id=nomina.id) }}" class="btn btn-primary">
|
|
18
|
+
<i class="bi bi-plus-circle"></i> {{ _('Nueva Novedad') }}
|
|
19
|
+
</a>
|
|
20
|
+
{% endif %}
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="card mb-4">
|
|
25
|
+
<div class="card-header">
|
|
26
|
+
<div class="row">
|
|
27
|
+
<div class="col-md-4">
|
|
28
|
+
<strong>{{ _('Planilla:') }}</strong> {{ planilla.nombre }}
|
|
29
|
+
</div>
|
|
30
|
+
<div class="col-md-4">
|
|
31
|
+
<strong>{{ _('Período:') }}</strong> {{ nomina.periodo_inicio.strftime('%d/%m/%Y') }} - {{ nomina.periodo_fin.strftime('%d/%m/%Y') }}
|
|
32
|
+
</div>
|
|
33
|
+
<div class="col-md-4">
|
|
34
|
+
<strong>{{ _('Estado:') }}</strong>
|
|
35
|
+
{% if nomina.estado == 'generado' %}
|
|
36
|
+
<span class="badge bg-warning text-dark">{{ _('Generado') }}</span>
|
|
37
|
+
{% elif nomina.estado == 'aprobado' %}
|
|
38
|
+
<span class="badge bg-info">{{ _('Aprobado') }}</span>
|
|
39
|
+
{% elif nomina.estado == 'aplicado' %}
|
|
40
|
+
<span class="badge bg-success">{{ _('Aplicado') }}</span>
|
|
41
|
+
{% endif %}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
{% if nomina.estado == 'aplicado' %}
|
|
48
|
+
<div class="alert alert-info">
|
|
49
|
+
<i class="bi bi-info-circle"></i>
|
|
50
|
+
{{ _('Esta nómina ya ha sido aplicada. No se pueden agregar, editar o eliminar novedades.') }}
|
|
51
|
+
</div>
|
|
52
|
+
{% endif %}
|
|
53
|
+
|
|
54
|
+
<div class="card">
|
|
55
|
+
<div class="card-header">
|
|
56
|
+
<h5 class="mb-0">{{ _('Lista de Novedades') }} ({{ novedades|length }})</h5>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="card-body">
|
|
59
|
+
{% if novedades %}
|
|
60
|
+
<table class="table table-striped table-hover">
|
|
61
|
+
<thead>
|
|
62
|
+
<tr>
|
|
63
|
+
<th>{{ _('Empleado') }}</th>
|
|
64
|
+
<th>{{ _('Código Concepto') }}</th>
|
|
65
|
+
<th>{{ _('Tipo') }}</th>
|
|
66
|
+
<th>{{ _('Tipo Valor') }}</th>
|
|
67
|
+
<th class="text-end">{{ _('Valor') }}</th>
|
|
68
|
+
<th>{{ _('Fecha') }}</th>
|
|
69
|
+
<th>{{ _('Estado') }}</th>
|
|
70
|
+
<th>{{ _('Acciones') }}</th>
|
|
71
|
+
</tr>
|
|
72
|
+
</thead>
|
|
73
|
+
<tbody>
|
|
74
|
+
{% for novedad in novedades %}
|
|
75
|
+
<tr>
|
|
76
|
+
<td>
|
|
77
|
+
<strong>{{ novedad.empleado.primer_nombre }} {{ novedad.empleado.primer_apellido }}</strong>
|
|
78
|
+
<br>
|
|
79
|
+
<small class="text-muted">{{ novedad.empleado.codigo_empleado }}</small>
|
|
80
|
+
</td>
|
|
81
|
+
<td><code>{{ novedad.codigo_concepto }}</code></td>
|
|
82
|
+
<td>
|
|
83
|
+
{% if novedad.percepcion_id %}
|
|
84
|
+
<span class="badge bg-primary">{{ _('Percepción') }}</span>
|
|
85
|
+
{% elif novedad.deduccion_id %}
|
|
86
|
+
<span class="badge bg-danger">{{ _('Deducción') }}</span>
|
|
87
|
+
{% else %}
|
|
88
|
+
<span class="badge bg-secondary">{{ _('General') }}</span>
|
|
89
|
+
{% endif %}
|
|
90
|
+
</td>
|
|
91
|
+
<td>
|
|
92
|
+
{% if novedad.tipo_valor == 'monto' %}
|
|
93
|
+
{{ _('Monto Fijo') }}
|
|
94
|
+
{% elif novedad.tipo_valor == 'horas' %}
|
|
95
|
+
{{ _('Horas') }}
|
|
96
|
+
{% elif novedad.tipo_valor == 'dias' %}
|
|
97
|
+
{{ _('Días') }}
|
|
98
|
+
{% elif novedad.tipo_valor == 'cantidad' %}
|
|
99
|
+
{{ _('Cantidad') }}
|
|
100
|
+
{% elif novedad.tipo_valor == 'porcentaje' %}
|
|
101
|
+
{{ _('Porcentaje') }}
|
|
102
|
+
{% else %}
|
|
103
|
+
{{ novedad.tipo_valor or '-' }}
|
|
104
|
+
{% endif %}
|
|
105
|
+
</td>
|
|
106
|
+
<td class="text-end">{{ "{:,.2f}".format(novedad.valor_cantidad|float) }}</td>
|
|
107
|
+
<td>{{ novedad.fecha_novedad.strftime('%d/%m/%Y') if novedad.fecha_novedad else '-' }}</td>
|
|
108
|
+
<td>
|
|
109
|
+
{% if novedad.estado == 'ejecutada' %}
|
|
110
|
+
<span class="badge bg-success">{{ _('Ejecutada') }}</span>
|
|
111
|
+
{% else %}
|
|
112
|
+
<span class="badge bg-warning text-dark">{{ _('Pendiente') }}</span>
|
|
113
|
+
{% endif %}
|
|
114
|
+
</td>
|
|
115
|
+
<td>
|
|
116
|
+
{% if nomina.estado != 'aplicado' %}
|
|
117
|
+
<a href="{{ url_for('planilla.editar_novedad', planilla_id=planilla.id, nomina_id=nomina.id, novedad_id=novedad.id) }}"
|
|
118
|
+
class="btn btn-sm btn-outline-primary" title="{{ _('Editar') }}">
|
|
119
|
+
<i class="bi bi-pencil"></i>
|
|
120
|
+
</a>
|
|
121
|
+
<form action="{{ url_for('planilla.eliminar_novedad', planilla_id=planilla.id, nomina_id=nomina.id, novedad_id=novedad.id) }}"
|
|
122
|
+
method="post" style="display: inline;">
|
|
123
|
+
<button type="submit" class="btn btn-sm btn-outline-danger"
|
|
124
|
+
title="{{ _('Eliminar') }}"
|
|
125
|
+
onclick="return confirm('{{ _('¿Está seguro de eliminar esta novedad?') }}')">
|
|
126
|
+
<i class="bi bi-trash"></i>
|
|
127
|
+
</button>
|
|
128
|
+
</form>
|
|
129
|
+
{% else %}
|
|
130
|
+
<span class="text-muted">-</span>
|
|
131
|
+
{% endif %}
|
|
132
|
+
</td>
|
|
133
|
+
</tr>
|
|
134
|
+
{% endfor %}
|
|
135
|
+
</tbody>
|
|
136
|
+
</table>
|
|
137
|
+
{% else %}
|
|
138
|
+
<div class="text-center py-5">
|
|
139
|
+
<i class="bi bi-inbox display-4 text-muted"></i>
|
|
140
|
+
<p class="text-muted mt-3">{{ _('No hay novedades registradas para esta nómina.') }}</p>
|
|
141
|
+
{% if nomina.estado != 'aplicado' %}
|
|
142
|
+
<a href="{{ url_for('planilla.nueva_novedad', planilla_id=planilla.id, nomina_id=nomina.id) }}" class="btn btn-primary">
|
|
143
|
+
<i class="bi bi-plus-circle"></i> {{ _('Agregar Primera Novedad') }}
|
|
144
|
+
</a>
|
|
145
|
+
{% endif %}
|
|
146
|
+
</div>
|
|
147
|
+
{% endif %}
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
<div class="card mt-4">
|
|
152
|
+
<div class="card-header bg-light">
|
|
153
|
+
<h6 class="mb-0"><i class="bi bi-info-circle"></i> {{ _('¿Qué son las Novedades?') }}</h6>
|
|
154
|
+
</div>
|
|
155
|
+
<div class="card-body">
|
|
156
|
+
<p class="mb-2">
|
|
157
|
+
{{ _('Las novedades son eventos o ajustes que afectan la nómina de un empleado en un período específico. Pueden incluir:') }}
|
|
158
|
+
</p>
|
|
159
|
+
<ul class="mb-0">
|
|
160
|
+
<li><strong>{{ _('Percepciones (Ingresos):') }}</strong> {{ _('Horas extras, bonos, comisiones, etc.') }}</li>
|
|
161
|
+
<li><strong>{{ _('Deducciones (Egresos):') }}</strong> {{ _('Ausencias, descuentos, préstamos, etc.') }}</li>
|
|
162
|
+
</ul>
|
|
163
|
+
<p class="mt-2 mb-0 text-muted">
|
|
164
|
+
<small>
|
|
165
|
+
{{ _('Nota: Las novedades se aplican automáticamente a cualquier nómina cuyo período incluya la fecha de la novedad. Después de agregar novedades, use el botón "Recalcular" en la vista de la nómina para aplicar los cambios.') }}
|
|
166
|
+
</small>
|
|
167
|
+
</p>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
{% endblock %}
|