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,52 @@
1
+ {% extends 'base.html' %}
2
+ {% from 'macros.html' import render_field, render_messages, render_form_errors %}
3
+
4
+ {% block content %}
5
+ <div class="container">
6
+ {{ render_messages() }}
7
+ {{ render_form_errors(form) }}
8
+
9
+ <div class="d-flex justify-content-between align-items-center mb-4">
10
+ <h2>{{ titulo }}</h2>
11
+ <a href="{{ url_for('vacation.account_index') }}" class="btn btn-secondary">
12
+ <i class="bi bi-arrow-left me-1"></i>{{ _('Volver') }}
13
+ </a>
14
+ </div>
15
+
16
+ <div class="card">
17
+ <div class="card-body">
18
+ <form method="POST" action="">
19
+ {{ form.hidden_tag() }}
20
+
21
+ <div class="row">
22
+ <div class="col-md-6">
23
+ {{ render_field(form.empleado_id) }}
24
+ </div>
25
+ <div class="col-md-6">
26
+ {{ render_field(form.policy_id) }}
27
+ </div>
28
+ </div>
29
+
30
+ <div class="row">
31
+ <div class="col-md-6">
32
+ {{ render_field(form.current_balance) }}
33
+ </div>
34
+ <div class="col-md-6">
35
+ {{ render_field(form.activo) }}
36
+ </div>
37
+ </div>
38
+
39
+ <div class="alert alert-info">
40
+ <i class="bi bi-info-circle me-2"></i>
41
+ {{ _('El balance inicial será registrado como una entrada en el libro mayor de vacaciones.') }}
42
+ </div>
43
+
44
+ <div class="mt-4">
45
+ {{ form.submit(class="btn btn-primary") }}
46
+ <a href="{{ url_for('vacation.account_index') }}" class="btn btn-secondary">{{ _('Cancelar') }}</a>
47
+ </div>
48
+ </form>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ {% endblock %}
@@ -0,0 +1,68 @@
1
+ {% extends 'base.html' %}
2
+ {% from 'macros.html' import render_messages, render_pagination %}
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>{{ _('Cuentas de Vacaciones') }}</h2>
10
+ <a href="{{ url_for('vacation.account_new') }}" class="btn btn-primary">
11
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nueva Cuenta') }}
12
+ </a>
13
+ </div>
14
+
15
+ <div class="card">
16
+ <div class="card-body">
17
+ <div class="table-responsive">
18
+ <table class="table table-hover">
19
+ <thead>
20
+ <tr>
21
+ <th>{{ _('Empleado') }}</th>
22
+ <th>{{ _('Código') }}</th>
23
+ <th>{{ _('Política') }}</th>
24
+ <th>{{ _('Balance Actual') }}</th>
25
+ <th>{{ _('Unidad') }}</th>
26
+ <th>{{ _('Última Acumulación') }}</th>
27
+ <th>{{ _('Estado') }}</th>
28
+ <th>{{ _('Acciones') }}</th>
29
+ </tr>
30
+ </thead>
31
+ <tbody>
32
+ {% for account in accounts %}
33
+ <tr>
34
+ <td>{{ account.empleado.primer_nombre }} {{ account.empleado.primer_apellido }}</td>
35
+ <td><strong>{{ account.empleado.codigo_empleado }}</strong></td>
36
+ <td>{{ account.policy.nombre }}</td>
37
+ <td>
38
+ <span class="badge bg-primary">{{ account.current_balance }}</span>
39
+ </td>
40
+ <td>{{ account.policy.unit_type }}</td>
41
+ <td>{{ account.last_accrual_date.strftime('%Y-%m-%d') if account.last_accrual_date else '-' }}</td>
42
+ <td>
43
+ {% if account.activo %}
44
+ <span class="badge bg-success">{{ _('Activa') }}</span>
45
+ {% else %}
46
+ <span class="badge bg-warning">{{ _('Inactiva') }}</span>
47
+ {% endif %}
48
+ </td>
49
+ <td>
50
+ <a href="{{ url_for('vacation.account_detail', account_id=account.id) }}"
51
+ class="btn btn-sm btn-outline-info" title="{{ _('Ver Detalles') }}">
52
+ <i class="bi bi-eye"></i>
53
+ </a>
54
+ </td>
55
+ </tr>
56
+ {% else %}
57
+ <tr>
58
+ <td colspan="8" class="text-center text-muted">{{ _('No hay cuentas registradas.') }}</td>
59
+ </tr>
60
+ {% endfor %}
61
+ </tbody>
62
+ </table>
63
+ </div>
64
+ {{ render_pagination(pagination, 'vacation.account_index') }}
65
+ </div>
66
+ </div>
67
+ </div>
68
+ {% endblock %}
@@ -0,0 +1,156 @@
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 Vacaciones') }}</h2>
10
+ <p class="text-muted">{{ _('Sistema robusto y flexible para el control de vacaciones') }}</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">{{ _('Políticas Activas') }}</h5>
19
+ <p class="display-4">{{ total_policies }}</p>
20
+ <a href="{{ url_for('vacation.policy_index') }}" class="btn btn-sm btn-primary">
21
+ {{ _('Ver Políticas') }}
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">{{ _('Cuentas Activas') }}</h5>
30
+ <p class="display-4">{{ total_accounts }}</p>
31
+ <a href="{{ url_for('vacation.account_index') }}" class="btn btn-sm btn-primary">
32
+ {{ _('Ver Cuentas') }}
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">{{ _('Solicitudes Pendientes') }}</h5>
41
+ <p class="display-4">{{ pending_requests }}</p>
42
+ <a href="{{ url_for('vacation.leave_request_index', estado='pendiente') }}" class="btn btn-sm btn-primary">
43
+ {{ _('Ver Solicitudes') }}
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('vacation.policy_new') }}" class="btn btn-outline-primary">
56
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nueva Política') }}
57
+ </a>
58
+ <a href="{{ url_for('vacation.account_new') }}" class="btn btn-outline-primary">
59
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nueva Cuenta') }}
60
+ </a>
61
+ <a href="{{ url_for('vacation.leave_request_new') }}" class="btn btn-outline-primary">
62
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nueva Solicitud') }}
63
+ </a>
64
+ <a href="{{ url_for('vacation.register_vacation_taken') }}" class="btn btn-success">
65
+ <i class="bi bi-calendar-check me-1"></i>{{ _('Registrar Vacaciones Descansadas') }}
66
+ </a>
67
+ </div>
68
+ </div>
69
+ </div>
70
+
71
+ <!-- Initial Balance Loading (Implementation Phase) -->
72
+ <div class="row mb-4">
73
+ <div class="col-12">
74
+ <div class="card border-info">
75
+ <div class="card-header bg-info text-white">
76
+ <h5 class="mb-0">
77
+ <i class="bi bi-cloud-upload me-2"></i>{{ _('Carga de Saldos Iniciales') }}
78
+ <small class="float-end badge bg-light text-dark">{{ _('Implementación') }}</small>
79
+ </h5>
80
+ </div>
81
+ <div class="card-body">
82
+ <p class="mb-3">
83
+ {{ _('Durante la implementación del sistema, cargue los saldos iniciales de vacaciones de sus empleados:') }}
84
+ </p>
85
+ <div class="btn-group" role="group">
86
+ <a href="{{ url_for('vacation.initial_balance_form') }}" class="btn btn-outline-info">
87
+ <i class="bi bi-person-plus me-1"></i>{{ _('Carga Individual') }}
88
+ </a>
89
+ <a href="{{ url_for('vacation.initial_balance_bulk') }}" class="btn btn-outline-info">
90
+ <i class="bi bi-file-earmark-excel me-1"></i>{{ _('Carga Masiva (Excel)') }}
91
+ </a>
92
+ </div>
93
+ <small class="text-muted d-block mt-2">
94
+ <i class="bi bi-info-circle"></i>
95
+ {{ _('Solo para cuentas sin movimientos previos. Use la carga masiva para empresas con muchos empleados.') }}
96
+ </small>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ </div>
101
+
102
+ <!-- Recent Activity -->
103
+ <div class="card">
104
+ <div class="card-header">
105
+ <h5 class="mb-0">{{ _('Actividad Reciente') }}</h5>
106
+ </div>
107
+ <div class="card-body">
108
+ <div class="table-responsive">
109
+ <table class="table table-hover">
110
+ <thead>
111
+ <tr>
112
+ <th>{{ _('Empleado') }}</th>
113
+ <th>{{ _('Tipo') }}</th>
114
+ <th>{{ _('Fechas') }}</th>
115
+ <th>{{ _('Unidades') }}</th>
116
+ <th>{{ _('Estado') }}</th>
117
+ <th>{{ _('Acciones') }}</th>
118
+ </tr>
119
+ </thead>
120
+ <tbody>
121
+ {% for request in recent_requests %}
122
+ <tr>
123
+ <td>{{ request.empleado.primer_nombre }} {{ request.empleado.primer_apellido }}</td>
124
+ <td>{{ _('Solicitud de Vacaciones') }}</td>
125
+ <td>{{ request.start_date.strftime('%Y-%m-%d') }} - {{ request.end_date.strftime('%Y-%m-%d') }}</td>
126
+ <td>{{ request.units }}</td>
127
+ <td>
128
+ {% if request.estado == 'pendiente' %}
129
+ <span class="badge bg-warning">{{ _('Pendiente') }}</span>
130
+ {% elif request.estado == 'aprobado' %}
131
+ <span class="badge bg-success">{{ _('Aprobado') }}</span>
132
+ {% elif request.estado == 'rechazado' %}
133
+ <span class="badge bg-danger">{{ _('Rechazado') }}</span>
134
+ {% elif request.estado == 'disfrutado' %}
135
+ <span class="badge bg-info">{{ _('Disfrutado') }}</span>
136
+ {% endif %}
137
+ </td>
138
+ <td>
139
+ <a href="{{ url_for('vacation.leave_request_detail', request_id=request.id) }}"
140
+ class="btn btn-sm btn-outline-primary" title="{{ _('Ver Detalles') }}">
141
+ <i class="bi bi-eye"></i>
142
+ </a>
143
+ </td>
144
+ </tr>
145
+ {% else %}
146
+ <tr>
147
+ <td colspan="6" class="text-center text-muted">{{ _('No hay actividad reciente.') }}</td>
148
+ </tr>
149
+ {% endfor %}
150
+ </tbody>
151
+ </table>
152
+ </div>
153
+ </div>
154
+ </div>
155
+ </div>
156
+ {% endblock %}
@@ -0,0 +1,149 @@
1
+ {% extends "base.html" %}
2
+ {% block title %}{{ _('Carga Masiva de Saldos Iniciales de Vacaciones') }}{% endblock %}
3
+
4
+ {% block content %}
5
+ <div class="container-fluid">
6
+ <div class="row">
7
+ <div class="col-md-10 offset-md-1">
8
+ <div class="card">
9
+ <div class="card-header bg-primary text-white">
10
+ <h4 class="mb-0">
11
+ <i class="fas fa-file-excel"></i> {{ _('Carga Masiva de Saldos Iniciales desde Excel') }}
12
+ </h4>
13
+ </div>
14
+ <div class="card-body">
15
+ <div class="alert alert-info">
16
+ <i class="fas fa-info-circle"></i>
17
+ <strong>{{ _('Uso:') }}</strong>
18
+ {{ _('Use esta función para cargar los saldos iniciales de vacaciones de múltiples empleados desde un archivo Excel durante la implementación del sistema.') }}
19
+ </div>
20
+
21
+ <div class="card mb-4">
22
+ <div class="card-header bg-light">
23
+ <h5 class="mb-0">{{ _('Formato del Archivo Excel') }}</h5>
24
+ </div>
25
+ <div class="card-body">
26
+ <p>{{ _('El archivo Excel debe tener las siguientes columnas (sin encabezados):') }}</p>
27
+ <table class="table table-bordered table-sm">
28
+ <thead class="thead-light">
29
+ <tr>
30
+ <th>{{ _('Columna') }}</th>
31
+ <th>{{ _('Campo') }}</th>
32
+ <th>{{ _('Tipo') }}</th>
33
+ <th>{{ _('Requerido') }}</th>
34
+ <th>{{ _('Ejemplo') }}</th>
35
+ </tr>
36
+ </thead>
37
+ <tbody>
38
+ <tr>
39
+ <td><strong>A</strong></td>
40
+ <td>{{ _('Código de Empleado') }}</td>
41
+ <td>{{ _('Texto') }}</td>
42
+ <td><span class="badge badge-danger">{{ _('Sí') }}</span></td>
43
+ <td>EMP001</td>
44
+ </tr>
45
+ <tr>
46
+ <td><strong>B</strong></td>
47
+ <td>{{ _('Saldo Inicial') }}</td>
48
+ <td>{{ _('Número') }}</td>
49
+ <td><span class="badge badge-danger">{{ _('Sí') }}</span></td>
50
+ <td>15.5</td>
51
+ </tr>
52
+ <tr>
53
+ <td><strong>C</strong></td>
54
+ <td>{{ _('Fecha de Corte') }}</td>
55
+ <td>{{ _('Fecha (DD/MM/YYYY)') }}</td>
56
+ <td><span class="badge badge-danger">{{ _('Sí') }}</span></td>
57
+ <td>31/12/2024</td>
58
+ </tr>
59
+ <tr>
60
+ <td><strong>D</strong></td>
61
+ <td>{{ _('Observaciones') }}</td>
62
+ <td>{{ _('Texto') }}</td>
63
+ <td><span class="badge badge-secondary">{{ _('No') }}</span></td>
64
+ <td>{{ _('Saldo al inicio del sistema') }}</td>
65
+ </tr>
66
+ </tbody>
67
+ </table>
68
+
69
+ <div class="alert alert-warning mt-3">
70
+ <strong>{{ _('Requisitos:') }}</strong>
71
+ <ul class="mb-0">
72
+ <li>{{ _('Los empleados deben existir en el sistema y estar activos.') }}</li>
73
+ <li>{{ _('Cada empleado debe tener una cuenta de vacaciones activa creada previamente.') }}</li>
74
+ <li>{{ _('Las cuentas de vacaciones no deben tener movimientos previos.') }}</li>
75
+ <li><strong>{{ _('IMPORTANTE: El archivo Excel NO debe tener encabezados. Los datos comienzan en la fila 1.') }}</strong></li>
76
+ </ul>
77
+ </div>
78
+
79
+ <div class="alert alert-success">
80
+ <strong>{{ _('Ejemplo de archivo Excel:') }}</strong>
81
+ <table class="table table-sm table-bordered mt-2 bg-white">
82
+ <tbody>
83
+ <tr>
84
+ <td>EMP001</td>
85
+ <td>15.5</td>
86
+ <td>31/12/2024</td>
87
+ <td>{{ _('Saldo inicial 2024') }}</td>
88
+ </tr>
89
+ <tr>
90
+ <td>EMP002</td>
91
+ <td>20.0</td>
92
+ <td>31/12/2024</td>
93
+ <td>{{ _('Vacaciones acumuladas') }}</td>
94
+ </tr>
95
+ <tr>
96
+ <td>EMP003</td>
97
+ <td>8.75</td>
98
+ <td>31/12/2024</td>
99
+ <td></td>
100
+ </tr>
101
+ </tbody>
102
+ </table>
103
+ </div>
104
+ </div>
105
+ </div>
106
+
107
+ <div class="card">
108
+ <div class="card-header bg-light">
109
+ <h5 class="mb-0">{{ _('Subir Archivo') }}</h5>
110
+ </div>
111
+ <div class="card-body">
112
+ <form method="POST" enctype="multipart/form-data">
113
+ <div class="form-group">
114
+ <label for="file" class="form-label required">{{ _('Archivo Excel') }}</label>
115
+ <input type="file"
116
+ class="form-control"
117
+ id="file"
118
+ name="file"
119
+ accept=".xlsx,.xls"
120
+ required>
121
+ <small class="form-text text-muted">
122
+ {{ _('Formatos aceptados: .xlsx, .xls') }}
123
+ </small>
124
+ </div>
125
+
126
+ <div class="form-group mt-4">
127
+ <button type="submit" class="btn btn-primary btn-lg">
128
+ <i class="fas fa-upload"></i> {{ _('Cargar Saldos Iniciales') }}
129
+ </button>
130
+ <a href="{{ url_for('vacation.dashboard') }}" class="btn btn-secondary">
131
+ {{ _('Cancelar') }}
132
+ </a>
133
+ </div>
134
+ </form>
135
+ </div>
136
+ </div>
137
+
138
+ <div class="alert alert-primary mt-4">
139
+ <i class="fas fa-lightbulb"></i>
140
+ <strong>{{ _('Consejo:') }}</strong>
141
+ {{ _('Para cargar un solo empleado o hacer correcciones, use el') }}
142
+ <a href="{{ url_for('vacation.initial_balance_form') }}">{{ _('formulario individual') }}</a>.
143
+ </div>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ {% endblock %}
@@ -0,0 +1,93 @@
1
+ {% extends "base.html" %}
2
+ {% block title %}{{ _('Cargar Saldo Inicial de Vacaciones') }}{% endblock %}
3
+
4
+ {% block content %}
5
+ <div class="container-fluid">
6
+ <div class="row">
7
+ <div class="col-md-8 offset-md-2">
8
+ <div class="card">
9
+ <div class="card-header bg-primary text-white">
10
+ <h4 class="mb-0">
11
+ <i class="fas fa-upload"></i> {{ _('Cargar Saldo Inicial de Vacaciones') }}
12
+ </h4>
13
+ </div>
14
+ <div class="card-body">
15
+ <div class="alert alert-info">
16
+ <i class="fas fa-info-circle"></i>
17
+ <strong>{{ _('Uso:') }}</strong>
18
+ {{ _('Use este formulario para cargar el saldo inicial de vacaciones de un empleado al momento de implementar el sistema.') }}
19
+ <br><br>
20
+ <strong>{{ _('Importante:') }}</strong>
21
+ <ul class="mb-0">
22
+ <li>{{ _('El empleado debe tener una cuenta de vacaciones activa.') }}</li>
23
+ <li>{{ _('Solo puede cargar saldo inicial en cuentas sin movimientos previos.') }}</li>
24
+ <li>{{ _('Para cargar múltiples empleados, use la opción de') }} <a href="{{ url_for('vacation.initial_balance_bulk') }}">{{ _('carga masiva desde Excel') }}</a>.</li>
25
+ </ul>
26
+ </div>
27
+
28
+ <form method="POST" novalidate>
29
+ {{ form.hidden_tag() }}
30
+
31
+ <div class="form-group">
32
+ {{ form.empleado_id.label(class="form-label required") }}
33
+ {{ form.empleado_id(class="form-control" + (' is-invalid' if form.empleado_id.errors else '')) }}
34
+ {% if form.empleado_id.description %}
35
+ <small class="form-text text-muted">{{ form.empleado_id.description }}</small>
36
+ {% endif %}
37
+ {% if form.empleado_id.errors %}
38
+ <div class="invalid-feedback d-block">
39
+ {{ form.empleado_id.errors[0] }}
40
+ </div>
41
+ {% endif %}
42
+ </div>
43
+
44
+ <div class="form-group">
45
+ {{ form.saldo_inicial.label(class="form-label required") }}
46
+ {{ form.saldo_inicial(class="form-control" + (' is-invalid' if form.saldo_inicial.errors else ''), placeholder="0.00") }}
47
+ {% if form.saldo_inicial.description %}
48
+ <small class="form-text text-muted">{{ form.saldo_inicial.description }}</small>
49
+ {% endif %}
50
+ {% if form.saldo_inicial.errors %}
51
+ <div class="invalid-feedback d-block">
52
+ {{ form.saldo_inicial.errors[0] }}
53
+ </div>
54
+ {% endif %}
55
+ </div>
56
+
57
+ <div class="form-group">
58
+ {{ form.fecha_corte.label(class="form-label required") }}
59
+ {{ form.fecha_corte(class="form-control" + (' is-invalid' if form.fecha_corte.errors else '')) }}
60
+ {% if form.fecha_corte.description %}
61
+ <small class="form-text text-muted">{{ form.fecha_corte.description }}</small>
62
+ {% endif %}
63
+ {% if form.fecha_corte.errors %}
64
+ <div class="invalid-feedback d-block">
65
+ {{ form.fecha_corte.errors[0] }}
66
+ </div>
67
+ {% endif %}
68
+ </div>
69
+
70
+ <div class="form-group">
71
+ {{ form.observaciones.label(class="form-label") }}
72
+ {{ form.observaciones(class="form-control" + (' is-invalid' if form.observaciones.errors else ''), rows=3) }}
73
+ {% if form.observaciones.description %}
74
+ <small class="form-text text-muted">{{ form.observaciones.description }}</small>
75
+ {% endif %}
76
+ {% if form.observaciones.errors %}
77
+ <div class="invalid-feedback d-block">
78
+ {{ form.observaciones.errors[0] }}
79
+ </div>
80
+ {% endif %}
81
+ </div>
82
+
83
+ <div class="form-group mt-4">
84
+ {{ form.submit(class="btn btn-primary btn-lg") }}
85
+ <a href="{{ url_for('vacation.dashboard') }}" class="btn btn-secondary">{{ _('Cancelar') }}</a>
86
+ </div>
87
+ </form>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ {% endblock %}