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.

Files changed (243) hide show
  1. coati_payroll/__init__.py +415 -0
  2. coati_payroll/app.py +95 -0
  3. coati_payroll/audit_helpers.py +904 -0
  4. coati_payroll/auth.py +123 -0
  5. coati_payroll/cli.py +1318 -0
  6. coati_payroll/config.py +219 -0
  7. coati_payroll/demo_data.py +813 -0
  8. coati_payroll/enums.py +278 -0
  9. coati_payroll/forms.py +1769 -0
  10. coati_payroll/formula_engine/__init__.py +81 -0
  11. coati_payroll/formula_engine/ast/__init__.py +110 -0
  12. coati_payroll/formula_engine/ast/ast_visitor.py +259 -0
  13. coati_payroll/formula_engine/ast/expression_evaluator.py +228 -0
  14. coati_payroll/formula_engine/ast/safe_operators.py +131 -0
  15. coati_payroll/formula_engine/ast/type_converter.py +172 -0
  16. coati_payroll/formula_engine/data_sources.py +752 -0
  17. coati_payroll/formula_engine/engine.py +247 -0
  18. coati_payroll/formula_engine/exceptions.py +52 -0
  19. coati_payroll/formula_engine/execution/__init__.py +24 -0
  20. coati_payroll/formula_engine/execution/execution_context.py +52 -0
  21. coati_payroll/formula_engine/execution/step_executor.py +62 -0
  22. coati_payroll/formula_engine/execution/variable_store.py +59 -0
  23. coati_payroll/formula_engine/novelty_codes.py +206 -0
  24. coati_payroll/formula_engine/results/__init__.py +20 -0
  25. coati_payroll/formula_engine/results/execution_result.py +59 -0
  26. coati_payroll/formula_engine/steps/__init__.py +30 -0
  27. coati_payroll/formula_engine/steps/assignment_step.py +71 -0
  28. coati_payroll/formula_engine/steps/base_step.py +48 -0
  29. coati_payroll/formula_engine/steps/calculation_step.py +42 -0
  30. coati_payroll/formula_engine/steps/conditional_step.py +122 -0
  31. coati_payroll/formula_engine/steps/step_factory.py +58 -0
  32. coati_payroll/formula_engine/steps/tax_lookup_step.py +45 -0
  33. coati_payroll/formula_engine/tables/__init__.py +24 -0
  34. coati_payroll/formula_engine/tables/bracket_calculator.py +51 -0
  35. coati_payroll/formula_engine/tables/table_lookup.py +161 -0
  36. coati_payroll/formula_engine/tables/tax_table.py +32 -0
  37. coati_payroll/formula_engine/validation/__init__.py +24 -0
  38. coati_payroll/formula_engine/validation/schema_validator.py +37 -0
  39. coati_payroll/formula_engine/validation/security_validator.py +52 -0
  40. coati_payroll/formula_engine/validation/tax_table_validator.py +205 -0
  41. coati_payroll/formula_engine_examples.py +153 -0
  42. coati_payroll/i18n.py +54 -0
  43. coati_payroll/initial_data.py +613 -0
  44. coati_payroll/interes_engine.py +450 -0
  45. coati_payroll/liquidacion_engine/__init__.py +25 -0
  46. coati_payroll/liquidacion_engine/engine.py +267 -0
  47. coati_payroll/locale_config.py +165 -0
  48. coati_payroll/log.py +138 -0
  49. coati_payroll/model.py +2410 -0
  50. coati_payroll/nomina_engine/__init__.py +87 -0
  51. coati_payroll/nomina_engine/calculators/__init__.py +30 -0
  52. coati_payroll/nomina_engine/calculators/benefit_calculator.py +79 -0
  53. coati_payroll/nomina_engine/calculators/concept_calculator.py +254 -0
  54. coati_payroll/nomina_engine/calculators/deduction_calculator.py +105 -0
  55. coati_payroll/nomina_engine/calculators/exchange_rate_calculator.py +51 -0
  56. coati_payroll/nomina_engine/calculators/perception_calculator.py +75 -0
  57. coati_payroll/nomina_engine/calculators/salary_calculator.py +86 -0
  58. coati_payroll/nomina_engine/domain/__init__.py +27 -0
  59. coati_payroll/nomina_engine/domain/calculation_items.py +52 -0
  60. coati_payroll/nomina_engine/domain/employee_calculation.py +53 -0
  61. coati_payroll/nomina_engine/domain/payroll_context.py +44 -0
  62. coati_payroll/nomina_engine/engine.py +188 -0
  63. coati_payroll/nomina_engine/processors/__init__.py +28 -0
  64. coati_payroll/nomina_engine/processors/accounting_processor.py +171 -0
  65. coati_payroll/nomina_engine/processors/accumulation_processor.py +90 -0
  66. coati_payroll/nomina_engine/processors/loan_processor.py +227 -0
  67. coati_payroll/nomina_engine/processors/novelty_processor.py +42 -0
  68. coati_payroll/nomina_engine/processors/vacation_processor.py +67 -0
  69. coati_payroll/nomina_engine/repositories/__init__.py +32 -0
  70. coati_payroll/nomina_engine/repositories/acumulado_repository.py +83 -0
  71. coati_payroll/nomina_engine/repositories/base_repository.py +40 -0
  72. coati_payroll/nomina_engine/repositories/config_repository.py +102 -0
  73. coati_payroll/nomina_engine/repositories/employee_repository.py +34 -0
  74. coati_payroll/nomina_engine/repositories/exchange_rate_repository.py +58 -0
  75. coati_payroll/nomina_engine/repositories/novelty_repository.py +54 -0
  76. coati_payroll/nomina_engine/repositories/planilla_repository.py +52 -0
  77. coati_payroll/nomina_engine/results/__init__.py +24 -0
  78. coati_payroll/nomina_engine/results/error_result.py +28 -0
  79. coati_payroll/nomina_engine/results/payroll_result.py +53 -0
  80. coati_payroll/nomina_engine/results/validation_result.py +39 -0
  81. coati_payroll/nomina_engine/services/__init__.py +22 -0
  82. coati_payroll/nomina_engine/services/accounting_voucher_service.py +708 -0
  83. coati_payroll/nomina_engine/services/employee_processing_service.py +173 -0
  84. coati_payroll/nomina_engine/services/payroll_execution_service.py +374 -0
  85. coati_payroll/nomina_engine/services/snapshot_service.py +295 -0
  86. coati_payroll/nomina_engine/validators/__init__.py +31 -0
  87. coati_payroll/nomina_engine/validators/base_validator.py +48 -0
  88. coati_payroll/nomina_engine/validators/currency_validator.py +50 -0
  89. coati_payroll/nomina_engine/validators/employee_validator.py +87 -0
  90. coati_payroll/nomina_engine/validators/period_validator.py +44 -0
  91. coati_payroll/nomina_engine/validators/planilla_validator.py +136 -0
  92. coati_payroll/plugin_manager.py +176 -0
  93. coati_payroll/queue/__init__.py +33 -0
  94. coati_payroll/queue/driver.py +127 -0
  95. coati_payroll/queue/drivers/__init__.py +22 -0
  96. coati_payroll/queue/drivers/dramatiq_driver.py +268 -0
  97. coati_payroll/queue/drivers/huey_driver.py +390 -0
  98. coati_payroll/queue/drivers/noop_driver.py +54 -0
  99. coati_payroll/queue/selector.py +121 -0
  100. coati_payroll/queue/tasks.py +764 -0
  101. coati_payroll/rate_limiting.py +83 -0
  102. coati_payroll/rbac.py +183 -0
  103. coati_payroll/report_engine.py +512 -0
  104. coati_payroll/report_export.py +208 -0
  105. coati_payroll/schema_validator.py +167 -0
  106. coati_payroll/security.py +77 -0
  107. coati_payroll/static/styles.css +1044 -0
  108. coati_payroll/system_reports.py +573 -0
  109. coati_payroll/templates/auth/login.html +189 -0
  110. coati_payroll/templates/base.html +283 -0
  111. coati_payroll/templates/index.html +227 -0
  112. coati_payroll/templates/macros.html +146 -0
  113. coati_payroll/templates/modules/calculation_rule/form.html +78 -0
  114. coati_payroll/templates/modules/calculation_rule/index.html +102 -0
  115. coati_payroll/templates/modules/calculation_rule/schema_editor.html +1159 -0
  116. coati_payroll/templates/modules/carga_inicial_prestacion/form.html +170 -0
  117. coati_payroll/templates/modules/carga_inicial_prestacion/index.html +170 -0
  118. coati_payroll/templates/modules/carga_inicial_prestacion/reporte.html +193 -0
  119. coati_payroll/templates/modules/config_calculos/index.html +44 -0
  120. coati_payroll/templates/modules/configuracion/index.html +90 -0
  121. coati_payroll/templates/modules/currency/form.html +47 -0
  122. coati_payroll/templates/modules/currency/index.html +64 -0
  123. coati_payroll/templates/modules/custom_field/form.html +62 -0
  124. coati_payroll/templates/modules/custom_field/index.html +78 -0
  125. coati_payroll/templates/modules/deduccion/form.html +1 -0
  126. coati_payroll/templates/modules/deduccion/index.html +1 -0
  127. coati_payroll/templates/modules/employee/form.html +254 -0
  128. coati_payroll/templates/modules/employee/index.html +76 -0
  129. coati_payroll/templates/modules/empresa/form.html +74 -0
  130. coati_payroll/templates/modules/empresa/index.html +71 -0
  131. coati_payroll/templates/modules/exchange_rate/form.html +47 -0
  132. coati_payroll/templates/modules/exchange_rate/import.html +93 -0
  133. coati_payroll/templates/modules/exchange_rate/index.html +114 -0
  134. coati_payroll/templates/modules/liquidacion/index.html +58 -0
  135. coati_payroll/templates/modules/liquidacion/nueva.html +51 -0
  136. coati_payroll/templates/modules/liquidacion/ver.html +91 -0
  137. coati_payroll/templates/modules/payroll_concepts/audit_log.html +146 -0
  138. coati_payroll/templates/modules/percepcion/form.html +1 -0
  139. coati_payroll/templates/modules/percepcion/index.html +1 -0
  140. coati_payroll/templates/modules/planilla/config.html +190 -0
  141. coati_payroll/templates/modules/planilla/config_deducciones.html +129 -0
  142. coati_payroll/templates/modules/planilla/config_empleados.html +116 -0
  143. coati_payroll/templates/modules/planilla/config_percepciones.html +113 -0
  144. coati_payroll/templates/modules/planilla/config_prestaciones.html +118 -0
  145. coati_payroll/templates/modules/planilla/config_reglas.html +120 -0
  146. coati_payroll/templates/modules/planilla/ejecutar_nomina.html +106 -0
  147. coati_payroll/templates/modules/planilla/form.html +197 -0
  148. coati_payroll/templates/modules/planilla/index.html +144 -0
  149. coati_payroll/templates/modules/planilla/listar_nominas.html +91 -0
  150. coati_payroll/templates/modules/planilla/log_nomina.html +135 -0
  151. coati_payroll/templates/modules/planilla/novedades/form.html +177 -0
  152. coati_payroll/templates/modules/planilla/novedades/index.html +170 -0
  153. coati_payroll/templates/modules/planilla/ver_nomina.html +477 -0
  154. coati_payroll/templates/modules/planilla/ver_nomina_empleado.html +231 -0
  155. coati_payroll/templates/modules/plugins/index.html +71 -0
  156. coati_payroll/templates/modules/prestacion/form.html +1 -0
  157. coati_payroll/templates/modules/prestacion/index.html +1 -0
  158. coati_payroll/templates/modules/prestacion_management/dashboard.html +150 -0
  159. coati_payroll/templates/modules/prestacion_management/initial_balance_bulk.html +195 -0
  160. coati_payroll/templates/modules/prestamo/approve.html +156 -0
  161. coati_payroll/templates/modules/prestamo/condonacion.html +249 -0
  162. coati_payroll/templates/modules/prestamo/detail.html +443 -0
  163. coati_payroll/templates/modules/prestamo/form.html +203 -0
  164. coati_payroll/templates/modules/prestamo/index.html +150 -0
  165. coati_payroll/templates/modules/prestamo/pago_extraordinario.html +211 -0
  166. coati_payroll/templates/modules/prestamo/tabla_pago_pdf.html +181 -0
  167. coati_payroll/templates/modules/report/admin_index.html +125 -0
  168. coati_payroll/templates/modules/report/detail.html +129 -0
  169. coati_payroll/templates/modules/report/execute.html +266 -0
  170. coati_payroll/templates/modules/report/index.html +95 -0
  171. coati_payroll/templates/modules/report/permissions.html +64 -0
  172. coati_payroll/templates/modules/settings/index.html +274 -0
  173. coati_payroll/templates/modules/shared/concept_form.html +201 -0
  174. coati_payroll/templates/modules/shared/concept_index.html +145 -0
  175. coati_payroll/templates/modules/tipo_planilla/form.html +70 -0
  176. coati_payroll/templates/modules/tipo_planilla/index.html +68 -0
  177. coati_payroll/templates/modules/user/form.html +65 -0
  178. coati_payroll/templates/modules/user/index.html +76 -0
  179. coati_payroll/templates/modules/user/profile.html +81 -0
  180. coati_payroll/templates/modules/vacation/account_detail.html +149 -0
  181. coati_payroll/templates/modules/vacation/account_form.html +52 -0
  182. coati_payroll/templates/modules/vacation/account_index.html +68 -0
  183. coati_payroll/templates/modules/vacation/dashboard.html +156 -0
  184. coati_payroll/templates/modules/vacation/initial_balance_bulk.html +149 -0
  185. coati_payroll/templates/modules/vacation/initial_balance_form.html +93 -0
  186. coati_payroll/templates/modules/vacation/leave_request_detail.html +158 -0
  187. coati_payroll/templates/modules/vacation/leave_request_form.html +61 -0
  188. coati_payroll/templates/modules/vacation/leave_request_index.html +98 -0
  189. coati_payroll/templates/modules/vacation/policy_detail.html +176 -0
  190. coati_payroll/templates/modules/vacation/policy_form.html +152 -0
  191. coati_payroll/templates/modules/vacation/policy_index.html +79 -0
  192. coati_payroll/templates/modules/vacation/register_taken_form.html +178 -0
  193. coati_payroll/translations/en/LC_MESSAGES/messages.mo +0 -0
  194. coati_payroll/translations/en/LC_MESSAGES/messages.po +7283 -0
  195. coati_payroll/translations/es/LC_MESSAGES/messages.mo +0 -0
  196. coati_payroll/translations/es/LC_MESSAGES/messages.po +7374 -0
  197. coati_payroll/vacation_service.py +451 -0
  198. coati_payroll/version.py +18 -0
  199. coati_payroll/vistas/__init__.py +64 -0
  200. coati_payroll/vistas/calculation_rule.py +307 -0
  201. coati_payroll/vistas/carga_inicial_prestacion.py +423 -0
  202. coati_payroll/vistas/config_calculos.py +72 -0
  203. coati_payroll/vistas/configuracion.py +87 -0
  204. coati_payroll/vistas/constants.py +17 -0
  205. coati_payroll/vistas/currency.py +112 -0
  206. coati_payroll/vistas/custom_field.py +120 -0
  207. coati_payroll/vistas/employee.py +305 -0
  208. coati_payroll/vistas/empresa.py +153 -0
  209. coati_payroll/vistas/exchange_rate.py +341 -0
  210. coati_payroll/vistas/liquidacion.py +205 -0
  211. coati_payroll/vistas/payroll_concepts.py +580 -0
  212. coati_payroll/vistas/planilla/__init__.py +38 -0
  213. coati_payroll/vistas/planilla/association_routes.py +238 -0
  214. coati_payroll/vistas/planilla/config_routes.py +158 -0
  215. coati_payroll/vistas/planilla/export_routes.py +175 -0
  216. coati_payroll/vistas/planilla/helpers/__init__.py +34 -0
  217. coati_payroll/vistas/planilla/helpers/association_helpers.py +161 -0
  218. coati_payroll/vistas/planilla/helpers/excel_helpers.py +29 -0
  219. coati_payroll/vistas/planilla/helpers/form_helpers.py +97 -0
  220. coati_payroll/vistas/planilla/nomina_routes.py +488 -0
  221. coati_payroll/vistas/planilla/novedad_routes.py +227 -0
  222. coati_payroll/vistas/planilla/routes.py +145 -0
  223. coati_payroll/vistas/planilla/services/__init__.py +26 -0
  224. coati_payroll/vistas/planilla/services/export_service.py +687 -0
  225. coati_payroll/vistas/planilla/services/nomina_service.py +233 -0
  226. coati_payroll/vistas/planilla/services/novedad_service.py +126 -0
  227. coati_payroll/vistas/planilla/services/planilla_service.py +34 -0
  228. coati_payroll/vistas/planilla/validators/__init__.py +18 -0
  229. coati_payroll/vistas/planilla/validators/planilla_validators.py +40 -0
  230. coati_payroll/vistas/plugins.py +45 -0
  231. coati_payroll/vistas/prestacion.py +272 -0
  232. coati_payroll/vistas/prestamo.py +808 -0
  233. coati_payroll/vistas/report.py +432 -0
  234. coati_payroll/vistas/settings.py +29 -0
  235. coati_payroll/vistas/tipo_planilla.py +134 -0
  236. coati_payroll/vistas/user.py +172 -0
  237. coati_payroll/vistas/vacation.py +1045 -0
  238. coati_payroll-0.0.2.dist-info/LICENSE +201 -0
  239. coati_payroll-0.0.2.dist-info/METADATA +581 -0
  240. coati_payroll-0.0.2.dist-info/RECORD +243 -0
  241. coati_payroll-0.0.2.dist-info/WHEEL +5 -0
  242. coati_payroll-0.0.2.dist-info/entry_points.txt +2 -0
  243. coati_payroll-0.0.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,231 @@
1
+ {% extends "base.html" %}
2
+ {% block content %}
3
+ <div class="content-header">
4
+ <h3>
5
+ Detalle de Nómina: {{ nomina_empleado.empleado.primer_nombre }} {{ nomina_empleado.empleado.primer_apellido }}
6
+ </h3>
7
+ <a href="{{ url_for('planilla.ver_nomina', planilla_id=planilla.id, nomina_id=nomina.id) }}" class="btn btn-secondary">
8
+ <i class="fas fa-arrow-left"></i> Volver a la Nómina
9
+ </a>
10
+ </div>
11
+
12
+ <div class="card mb-4">
13
+ <div class="card-header">
14
+ <h5 class="mb-0">Información del Empleado</h5>
15
+ </div>
16
+ <div class="card-body">
17
+ <div class="row">
18
+ <div class="col-md-4">
19
+ <strong>Nombre Completo:</strong><br>
20
+ {{ nomina_empleado.empleado.primer_nombre }}
21
+ {% if nomina_empleado.empleado.segundo_nombre %}{{ nomina_empleado.empleado.segundo_nombre }}{% endif %}
22
+ {{ nomina_empleado.empleado.primer_apellido }}
23
+ {% if nomina_empleado.empleado.segundo_apellido %}{{ nomina_empleado.empleado.segundo_apellido }}{% endif %}
24
+ </div>
25
+ <div class="col-md-2">
26
+ <strong>Identificación:</strong><br>
27
+ {{ nomina_empleado.empleado.identificacion_personal }}
28
+ </div>
29
+ <div class="col-md-3">
30
+ <strong>Cargo:</strong><br>
31
+ {{ nomina_empleado.cargo_snapshot or nomina_empleado.empleado.cargo or 'N/A' }}
32
+ </div>
33
+ <div class="col-md-3">
34
+ <strong>Área:</strong><br>
35
+ {{ nomina_empleado.area_snapshot or nomina_empleado.empleado.area or 'N/A' }}
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+
41
+ <div class="row">
42
+ <!-- Resumen -->
43
+ <div class="col-md-4">
44
+ <div class="card mb-4">
45
+ <div class="card-header bg-info text-white">
46
+ <h6 class="mb-0">Resumen</h6>
47
+ </div>
48
+ <div class="card-body">
49
+ <table class="table table-sm mb-0">
50
+ <tr>
51
+ <td>Salario Base:</td>
52
+ <td class="text-right">{{ "{:,.2f}".format(nomina_empleado.sueldo_base_historico|float) }}</td>
53
+ </tr>
54
+ <tr>
55
+ <td>Total Ingresos:</td>
56
+ <td class="text-right text-primary">+{{ "{:,.2f}".format(nomina_empleado.total_ingresos|float) }}</td>
57
+ </tr>
58
+ <tr class="table-light">
59
+ <td><strong>Salario Bruto:</strong></td>
60
+ <td class="text-right"><strong>{{ "{:,.2f}".format(nomina_empleado.salario_bruto|float) }}</strong></td>
61
+ </tr>
62
+ <tr>
63
+ <td>Total Deducciones:</td>
64
+ <td class="text-right text-danger">-{{ "{:,.2f}".format(nomina_empleado.total_deducciones|float) }}</td>
65
+ </tr>
66
+ <tr class="table-success">
67
+ <td><strong>Salario Neto:</strong></td>
68
+ <td class="text-right"><strong>{{ "{:,.2f}".format(nomina_empleado.salario_neto|float) }}</strong></td>
69
+ </tr>
70
+ {% if nomina_empleado.tipo_cambio_aplicado and nomina_empleado.tipo_cambio_aplicado != 1 %}
71
+ <tr>
72
+ <td>Tipo de Cambio:</td>
73
+ <td class="text-right">{{ "{:.4f}".format(nomina_empleado.tipo_cambio_aplicado|float) }}</td>
74
+ </tr>
75
+ {% endif %}
76
+ </table>
77
+ </div>
78
+ </div>
79
+ </div>
80
+
81
+ <!-- Percepciones -->
82
+ <div class="col-md-4">
83
+ <div class="card mb-4">
84
+ <div class="card-header bg-primary text-white">
85
+ <h6 class="mb-0">Percepciones (Ingresos)</h6>
86
+ </div>
87
+ <div class="card-body p-0">
88
+ {% if percepciones %}
89
+ <table class="table table-sm mb-0">
90
+ <thead class="table-light">
91
+ <tr>
92
+ <th>Concepto</th>
93
+ <th class="text-right">Monto</th>
94
+ </tr>
95
+ </thead>
96
+ <tbody>
97
+ {% for p in percepciones %}
98
+ <tr>
99
+ <td>
100
+ <small class="text-muted">[{{ p.codigo }}]</small><br>
101
+ {{ p.descripcion }}
102
+ </td>
103
+ <td class="text-right">{{ "{:,.2f}".format(p.monto|float) }}</td>
104
+ </tr>
105
+ {% endfor %}
106
+ </tbody>
107
+ <tfoot class="table-primary">
108
+ <tr>
109
+ <th>Total Percepciones</th>
110
+ <th class="text-right">{{ "{:,.2f}".format(nomina_empleado.total_ingresos|float) }}</th>
111
+ </tr>
112
+ </tfoot>
113
+ </table>
114
+ {% else %}
115
+ <div class="p-3 text-muted">
116
+ <em>Sin percepciones adicionales</em>
117
+ </div>
118
+ {% endif %}
119
+ </div>
120
+ </div>
121
+ </div>
122
+
123
+ <!-- Deducciones -->
124
+ <div class="col-md-4">
125
+ <div class="card mb-4">
126
+ <div class="card-header bg-danger text-white">
127
+ <h6 class="mb-0">Deducciones</h6>
128
+ </div>
129
+ <div class="card-body p-0">
130
+ {% if deducciones %}
131
+ <table class="table table-sm mb-0">
132
+ <thead class="table-light">
133
+ <tr>
134
+ <th>Concepto</th>
135
+ <th class="text-right">Monto</th>
136
+ </tr>
137
+ </thead>
138
+ <tbody>
139
+ {% for d in deducciones %}
140
+ <tr>
141
+ <td>
142
+ <small class="text-muted">[{{ d.codigo }}]</small><br>
143
+ {{ d.descripcion }}
144
+ </td>
145
+ <td class="text-right">{{ "{:,.2f}".format(d.monto|float) }}</td>
146
+ </tr>
147
+ {% endfor %}
148
+ </tbody>
149
+ <tfoot class="table-danger">
150
+ <tr>
151
+ <th>Total Deducciones</th>
152
+ <th class="text-right">{{ "{:,.2f}".format(nomina_empleado.total_deducciones|float) }}</th>
153
+ </tr>
154
+ </tfoot>
155
+ </table>
156
+ {% else %}
157
+ <div class="p-3 text-muted">
158
+ <em>Sin deducciones</em>
159
+ </div>
160
+ {% endif %}
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </div>
165
+
166
+ <!-- Prestaciones (Costo Empleador) -->
167
+ {% if prestaciones %}
168
+ <div class="card mb-4">
169
+ <div class="card-header bg-warning">
170
+ <h6 class="mb-0">Prestaciones (Costo Empleador - No afecta salario neto)</h6>
171
+ </div>
172
+ <div class="card-body">
173
+ <table class="table table-sm">
174
+ <thead>
175
+ <tr>
176
+ <th>Código</th>
177
+ <th>Concepto</th>
178
+ <th class="text-right">Monto</th>
179
+ </tr>
180
+ </thead>
181
+ <tbody>
182
+ {% for p in prestaciones %}
183
+ <tr>
184
+ <td><code>{{ p.codigo }}</code></td>
185
+ <td>{{ p.descripcion }}</td>
186
+ <td class="text-right">{{ "{:,.2f}".format(p.monto|float) }}</td>
187
+ </tr>
188
+ {% endfor %}
189
+ </tbody>
190
+ <tfoot class="table-warning">
191
+ <tr>
192
+ <th colspan="2">Total Prestaciones (Costo Empleador)</th>
193
+ <th class="text-right">
194
+ {% set total_prestaciones = prestaciones|map(attribute='monto')|sum %}
195
+ {{ "{:,.2f}".format(total_prestaciones|float) }}
196
+ </th>
197
+ </tr>
198
+ </tfoot>
199
+ </table>
200
+ </div>
201
+ </div>
202
+ {% endif %}
203
+
204
+ <div class="card">
205
+ <div class="card-header">
206
+ <h6 class="mb-0">Período de Nómina</h6>
207
+ </div>
208
+ <div class="card-body">
209
+ <div class="row">
210
+ <div class="col-md-4">
211
+ <strong>Período:</strong><br>
212
+ {{ nomina.periodo_inicio.strftime('%d/%m/%Y') }} - {{ nomina.periodo_fin.strftime('%d/%m/%Y') }}
213
+ </div>
214
+ <div class="col-md-4">
215
+ <strong>Fecha de Generación:</strong><br>
216
+ {{ nomina.fecha_generacion.strftime('%d/%m/%Y %H:%M') }}
217
+ </div>
218
+ <div class="col-md-4">
219
+ <strong>Estado:</strong><br>
220
+ {% if nomina.estado == 'generado' %}
221
+ <span class="badge badge-warning">Generado</span>
222
+ {% elif nomina.estado == 'aprobado' %}
223
+ <span class="badge badge-info">Aprobado</span>
224
+ {% elif nomina.estado == 'aplicado' %}
225
+ <span class="badge badge-success">Aplicado</span>
226
+ {% endif %}
227
+ </div>
228
+ </div>
229
+ </div>
230
+ </div>
231
+ {% endblock %}
@@ -0,0 +1,71 @@
1
+ {% extends 'base.html' %}
2
+ {% from 'macros.html' import render_messages %}
3
+
4
+ {% block content %}
5
+ <div class="container">
6
+ {{ render_messages() }}
7
+
8
+ <div class="d-flex justify-content-between align-items-center mb-4">
9
+ <h2>{{ _('Plugins') }}</h2>
10
+ </div>
11
+
12
+ <div class="card">
13
+ <div class="card-body">
14
+ <div class="table-responsive">
15
+ <table class="table table-hover">
16
+ <thead>
17
+ <tr>
18
+ <th>{{ _('Paquete') }}</th>
19
+ <th>{{ _('Versión') }}</th>
20
+ <th>{{ _('Instalado') }}</th>
21
+ <th>{{ _('Estado') }}</th>
22
+ <th>{{ _('Acciones') }}</th>
23
+ </tr>
24
+ </thead>
25
+ <tbody>
26
+ {% for plugin in plugins %}
27
+ <tr>
28
+ <td><strong>{{ plugin.distribution_name }}</strong></td>
29
+ <td>{{ plugin.version or '-' }}</td>
30
+ <td>
31
+ {% if plugin.installed %}
32
+ <span class="badge bg-success">{{ _('Sí') }}</span>
33
+ {% else %}
34
+ <span class="badge bg-secondary">{{ _('No') }}</span>
35
+ {% endif %}
36
+ </td>
37
+ <td>
38
+ {% if plugin.active %}
39
+ <span class="badge bg-success">{{ _('Activo') }}</span>
40
+ {% else %}
41
+ <span class="badge bg-warning">{{ _('Inactivo') }}</span>
42
+ {% endif %}
43
+ </td>
44
+ <td>
45
+ <form action="{{ url_for('plugins.toggle', plugin_id=plugin.id) }}" method="POST" class="d-inline">
46
+ {% if plugin.active %}
47
+ <button type="submit" class="btn btn-sm btn-outline-warning">
48
+ <i class="bi bi-toggle-off"></i>
49
+ {{ _('Desactivar') }}
50
+ </button>
51
+ {% else %}
52
+ <button type="submit" class="btn btn-sm btn-outline-success" {% if not plugin.installed %}disabled{% endif %}>
53
+ <i class="bi bi-toggle-on"></i>
54
+ {{ _('Activar') }}
55
+ </button>
56
+ {% endif %}
57
+ </form>
58
+ </td>
59
+ </tr>
60
+ {% else %}
61
+ <tr>
62
+ <td colspan="5" class="text-center text-muted">{{ _('No se encontraron plugins.') }}</td>
63
+ </tr>
64
+ {% endfor %}
65
+ </tbody>
66
+ </table>
67
+ </div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ {% endblock %}
@@ -0,0 +1 @@
1
+ {% extends "modules/shared/concept_form.html" %}
@@ -0,0 +1 @@
1
+ {% extends "modules/shared/concept_index.html" %}
@@ -0,0 +1,150 @@
1
+ {% extends 'base.html' %}
2
+ {% from 'macros.html' import render_messages %}
3
+
4
+ {% block content %}
5
+ <div class="container">
6
+ {{ render_messages() }}
7
+
8
+ <div class="mb-4">
9
+ <h2>{{ _('Gestión de Prestaciones') }}</h2>
10
+ <p class="text-muted">{{ _('Sistema robusto y flexible para el control de prestaciones laborales') }}</p>
11
+ </div>
12
+
13
+ <!-- Statistics Cards -->
14
+ <div class="row mb-4">
15
+ <div class="col-md-4">
16
+ <div class="card text-center">
17
+ <div class="card-body">
18
+ <h5 class="card-title">{{ _('Prestaciones Activas') }}</h5>
19
+ <p class="display-4">{{ total_prestaciones }}</p>
20
+ <a href="{{ url_for('prestacion.prestacion_index') }}" class="btn btn-sm btn-primary">
21
+ {{ _('Ver Prestaciones') }}
22
+ </a>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ <div class="col-md-4">
27
+ <div class="card text-center">
28
+ <div class="card-body">
29
+ <h5 class="card-title">{{ _('Empleados con Saldo') }}</h5>
30
+ <p class="display-4">{{ total_accounts }}</p>
31
+ <a href="{{ url_for('carga_inicial_prestacion.reporte') }}" class="btn btn-sm btn-primary">
32
+ {{ _('Ver Reporte') }}
33
+ </a>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ <div class="col-md-4">
38
+ <div class="card text-center">
39
+ <div class="card-body">
40
+ <h5 class="card-title">{{ _('Cargas Pendientes') }}</h5>
41
+ <p class="display-4">{{ pending_loads }}</p>
42
+ <a href="{{ url_for('carga_inicial_prestacion.index', estado='borrador') }}" class="btn btn-sm btn-primary">
43
+ {{ _('Ver Pendientes') }}
44
+ </a>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+
50
+ <!-- Quick Actions -->
51
+ <div class="row mb-4">
52
+ <div class="col-12">
53
+ <h4>{{ _('Acciones Rápidas') }}</h4>
54
+ <div class="btn-group" role="group">
55
+ <a href="{{ url_for('prestacion.prestacion_new') }}" class="btn btn-outline-primary">
56
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nueva Prestación') }}
57
+ </a>
58
+ <a href="{{ url_for('carga_inicial_prestacion.nueva') }}" class="btn btn-outline-primary">
59
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Carga Individual') }}
60
+ </a>
61
+ <a href="{{ url_for('carga_inicial_prestacion.reporte') }}" class="btn btn-success">
62
+ <i class="bi bi-file-earmark-text me-1"></i>{{ _('Ver Reporte de Acumulados') }}
63
+ </a>
64
+ </div>
65
+ </div>
66
+ </div>
67
+
68
+ <!-- Initial Balance Loading (Implementation Phase) -->
69
+ <div class="row mb-4">
70
+ <div class="col-12">
71
+ <div class="card border-info">
72
+ <div class="card-header bg-info text-white">
73
+ <h5 class="mb-0">
74
+ <i class="bi bi-cloud-upload me-2"></i>{{ _('Carga de Saldos Iniciales') }}
75
+ <small class="float-end badge bg-light text-dark">{{ _('Implementación') }}</small>
76
+ </h5>
77
+ </div>
78
+ <div class="card-body">
79
+ <p class="mb-3">
80
+ {{ _('Durante la implementación del sistema, cargue los saldos iniciales de prestaciones de sus empleados:') }}
81
+ </p>
82
+ <div class="btn-group" role="group">
83
+ <a href="{{ url_for('carga_inicial_prestacion.nueva') }}" class="btn btn-outline-info">
84
+ <i class="bi bi-person-plus me-1"></i>{{ _('Carga Individual') }}
85
+ </a>
86
+ <a href="{{ url_for('prestacion_management.initial_balance_bulk') }}" class="btn btn-outline-info">
87
+ <i class="bi bi-file-earmark-excel me-1"></i>{{ _('Carga Masiva (Excel)') }}
88
+ </a>
89
+ </div>
90
+ <small class="text-muted d-block mt-2">
91
+ <i class="bi bi-info-circle"></i>
92
+ {{ _('Use la carga masiva para empresas con muchos empleados. Los registros se crean en estado borrador y deben aplicarse individualmente.') }}
93
+ </small>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </div>
98
+
99
+ <!-- Recent Activity -->
100
+ <div class="card">
101
+ <div class="card-header">
102
+ <h5 class="mb-0">{{ _('Actividad Reciente') }}</h5>
103
+ </div>
104
+ <div class="card-body">
105
+ <div class="table-responsive">
106
+ <table class="table table-hover">
107
+ <thead>
108
+ <tr>
109
+ <th>{{ _('Fecha') }}</th>
110
+ <th>{{ _('Empleado') }}</th>
111
+ <th>{{ _('Prestación') }}</th>
112
+ <th>{{ _('Tipo Transacción') }}</th>
113
+ <th>{{ _('Monto') }}</th>
114
+ <th>{{ _('Saldo') }}</th>
115
+ </tr>
116
+ </thead>
117
+ <tbody>
118
+ {% for trans in recent_transactions %}
119
+ <tr>
120
+ <td>{{ trans.fecha_transaccion.strftime('%Y-%m-%d') }}</td>
121
+ <td>{{ trans.empleado.primer_nombre }} {{ trans.empleado.primer_apellido }}</td>
122
+ <td>{{ trans.prestacion.codigo }} - {{ trans.prestacion.nombre }}</td>
123
+ <td>
124
+ {% if trans.tipo_transaccion == 'saldo_inicial' %}
125
+ <span class="badge bg-info">{{ _('Saldo Inicial') }}</span>
126
+ {% elif trans.tipo_transaccion == 'acumulacion' %}
127
+ <span class="badge bg-success">{{ _('Acumulación') }}</span>
128
+ {% elif trans.tipo_transaccion == 'pago' %}
129
+ <span class="badge bg-warning">{{ _('Pago') }}</span>
130
+ {% elif trans.tipo_transaccion == 'ajuste' %}
131
+ <span class="badge bg-secondary">{{ _('Ajuste') }}</span>
132
+ {% else %}
133
+ <span class="badge bg-light text-dark">{{ trans.tipo_transaccion }}</span>
134
+ {% endif %}
135
+ </td>
136
+ <td>{{ trans.moneda.codigo }} {{ "{:,.2f}".format(trans.monto_transaccion) }}</td>
137
+ <td>{{ trans.moneda.codigo }} {{ "{:,.2f}".format(trans.saldo_nuevo) }}</td>
138
+ </tr>
139
+ {% else %}
140
+ <tr>
141
+ <td colspan="6" class="text-center text-muted">{{ _('No hay actividad reciente.') }}</td>
142
+ </tr>
143
+ {% endfor %}
144
+ </tbody>
145
+ </table>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ </div>
150
+ {% endblock %}
@@ -0,0 +1,195 @@
1
+ {% extends "base.html" %}
2
+ {% from 'macros.html' import render_messages %}
3
+
4
+ {% block title %}{{ _('Carga Masiva de Saldos Iniciales de Prestaciones') }}{% endblock %}
5
+
6
+ {% block content %}
7
+ <div class="container-fluid">
8
+ {{ render_messages() }}
9
+
10
+ <div class="row">
11
+ <div class="col-md-10 offset-md-1">
12
+ <div class="card">
13
+ <div class="card-header bg-primary text-white">
14
+ <h4 class="mb-0">
15
+ <i class="bi bi-file-earmark-excel"></i> {{ _('Carga Masiva de Saldos Iniciales desde Excel') }}
16
+ </h4>
17
+ </div>
18
+ <div class="card-body">
19
+ <div class="alert alert-info">
20
+ <i class="bi bi-info-circle"></i>
21
+ <strong>{{ _('Uso:') }}</strong>
22
+ {{ _('Use esta función para cargar los saldos iniciales de prestaciones de múltiples empleados desde un archivo Excel durante la implementación del sistema.') }}
23
+ </div>
24
+
25
+ <div class="card mb-4">
26
+ <div class="card-header bg-light">
27
+ <h5 class="mb-0">{{ _('Formato del Archivo Excel') }}</h5>
28
+ </div>
29
+ <div class="card-body">
30
+ <p>{{ _('El archivo Excel debe tener las siguientes columnas (sin encabezados):') }}</p>
31
+ <table class="table table-bordered table-sm">
32
+ <thead class="thead-light">
33
+ <tr>
34
+ <th>{{ _('Columna') }}</th>
35
+ <th>{{ _('Campo') }}</th>
36
+ <th>{{ _('Tipo') }}</th>
37
+ <th>{{ _('Requerido') }}</th>
38
+ <th>{{ _('Ejemplo') }}</th>
39
+ </tr>
40
+ </thead>
41
+ <tbody>
42
+ <tr>
43
+ <td><strong>A</strong></td>
44
+ <td>{{ _('Código de Empleado') }}</td>
45
+ <td>{{ _('Texto') }}</td>
46
+ <td><span class="badge bg-danger">{{ _('Sí') }}</span></td>
47
+ <td>EMP001</td>
48
+ </tr>
49
+ <tr>
50
+ <td><strong>B</strong></td>
51
+ <td>{{ _('Código de Prestación') }}</td>
52
+ <td>{{ _('Texto') }}</td>
53
+ <td><span class="badge bg-danger">{{ _('Sí') }}</span></td>
54
+ <td>AGUINALDO</td>
55
+ </tr>
56
+ <tr>
57
+ <td><strong>C</strong></td>
58
+ <td>{{ _('Año de Corte') }}</td>
59
+ <td>{{ _('Número') }}</td>
60
+ <td><span class="badge bg-danger">{{ _('Sí') }}</span></td>
61
+ <td>2024</td>
62
+ </tr>
63
+ <tr>
64
+ <td><strong>D</strong></td>
65
+ <td>{{ _('Mes de Corte') }}</td>
66
+ <td>{{ _('Número (1-12)') }}</td>
67
+ <td><span class="badge bg-danger">{{ _('Sí') }}</span></td>
68
+ <td>12</td>
69
+ </tr>
70
+ <tr>
71
+ <td><strong>E</strong></td>
72
+ <td>{{ _('Código de Moneda') }}</td>
73
+ <td>{{ _('Texto') }}</td>
74
+ <td><span class="badge bg-danger">{{ _('Sí') }}</span></td>
75
+ <td>NIO</td>
76
+ </tr>
77
+ <tr>
78
+ <td><strong>F</strong></td>
79
+ <td>{{ _('Saldo Acumulado') }}</td>
80
+ <td>{{ _('Número') }}</td>
81
+ <td><span class="badge bg-danger">{{ _('Sí') }}</span></td>
82
+ <td>15000.50</td>
83
+ </tr>
84
+ <tr>
85
+ <td><strong>G</strong></td>
86
+ <td>{{ _('Tipo de Cambio') }}</td>
87
+ <td>{{ _('Número') }}</td>
88
+ <td><span class="badge bg-secondary">{{ _('No') }}</span></td>
89
+ <td>1.0</td>
90
+ </tr>
91
+ <tr>
92
+ <td><strong>H</strong></td>
93
+ <td>{{ _('Observaciones') }}</td>
94
+ <td>{{ _('Texto') }}</td>
95
+ <td><span class="badge bg-secondary">{{ _('No') }}</span></td>
96
+ <td>{{ _('Saldo al inicio del sistema') }}</td>
97
+ </tr>
98
+ </tbody>
99
+ </table>
100
+
101
+ <div class="alert alert-warning mt-3">
102
+ <strong>{{ _('Requisitos:') }}</strong>
103
+ <ul class="mb-0">
104
+ <li>{{ _('Los empleados deben existir en el sistema y estar activos.') }}</li>
105
+ <li>{{ _('Las prestaciones deben existir en el sistema y estar activas.') }}</li>
106
+ <li>{{ _('Las monedas deben existir en el sistema y estar activas.') }}</li>
107
+ <li>{{ _('Los registros se crean en estado "borrador" y deben aplicarse individualmente desde la lista de cargas.') }}</li>
108
+ <li><strong>{{ _('IMPORTANTE: El archivo Excel NO debe tener encabezados. Los datos comienzan en la fila 1.') }}</strong></li>
109
+ </ul>
110
+ </div>
111
+
112
+ <div class="alert alert-success">
113
+ <strong>{{ _('Ejemplo de archivo Excel:') }}</strong>
114
+ <table class="table table-sm table-bordered mt-2 bg-white">
115
+ <tbody>
116
+ <tr>
117
+ <td>EMP001</td>
118
+ <td>AGUINALDO</td>
119
+ <td>2024</td>
120
+ <td>12</td>
121
+ <td>NIO</td>
122
+ <td>15000.50</td>
123
+ <td>1.0</td>
124
+ <td>{{ _('Saldo inicial 2024') }}</td>
125
+ </tr>
126
+ <tr>
127
+ <td>EMP002</td>
128
+ <td>VACACIONES</td>
129
+ <td>2024</td>
130
+ <td>12</td>
131
+ <td>NIO</td>
132
+ <td>8500.00</td>
133
+ <td>1.0</td>
134
+ <td>{{ _('Prestaciones acumuladas') }}</td>
135
+ </tr>
136
+ <tr>
137
+ <td>EMP003</td>
138
+ <td>INDEMNIZACION</td>
139
+ <td>2024</td>
140
+ <td>12</td>
141
+ <td>USD</td>
142
+ <td>500.00</td>
143
+ <td>36.50</td>
144
+ <td></td>
145
+ </tr>
146
+ </tbody>
147
+ </table>
148
+ </div>
149
+ </div>
150
+ </div>
151
+
152
+ <div class="card">
153
+ <div class="card-header bg-light">
154
+ <h5 class="mb-0">{{ _('Subir Archivo') }}</h5>
155
+ </div>
156
+ <div class="card-body">
157
+ <form method="POST" enctype="multipart/form-data">
158
+ <div class="form-group mb-3">
159
+ <label for="file" class="form-label required">{{ _('Archivo Excel') }}</label>
160
+ <input type="file"
161
+ class="form-control"
162
+ id="file"
163
+ name="file"
164
+ accept=".xlsx,.xls"
165
+ required>
166
+ <small class="form-text text-muted">
167
+ {{ _('Formatos aceptados: .xlsx, .xls') }}
168
+ </small>
169
+ </div>
170
+
171
+ <div class="form-group mt-4">
172
+ <button type="submit" class="btn btn-primary btn-lg">
173
+ <i class="bi bi-upload"></i> {{ _('Cargar Saldos Iniciales') }}
174
+ </button>
175
+ <a href="{{ url_for('prestacion_management.dashboard') }}" class="btn btn-secondary">
176
+ {{ _('Cancelar') }}
177
+ </a>
178
+ </div>
179
+ </form>
180
+ </div>
181
+ </div>
182
+
183
+ <div class="alert alert-primary mt-4">
184
+ <i class="bi bi-lightbulb"></i>
185
+ <strong>{{ _('Consejo:') }}</strong>
186
+ {{ _('Después de cargar el archivo, los registros estarán en estado "borrador". Revise la') }}
187
+ <a href="{{ url_for('carga_inicial_prestacion.index') }}">{{ _('lista de cargas') }}</a>
188
+ {{ _('y aplique cada registro individualmente para crear las transacciones en el sistema.') }}
189
+ </div>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ </div>
194
+ </div>
195
+ {% endblock %}