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,150 @@
1
+ {% extends 'base.html' %}
2
+ {% from 'macros.html' import render_messages %}
3
+
4
+ {% block content %}
5
+ <div class="container-fluid">
6
+ {{ render_messages() }}
7
+
8
+ <div class="d-flex justify-content-between align-items-center mb-4">
9
+ <h2><i class="bi bi-cash-coin me-2"></i>{{ _('Préstamos y Adelantos') }}</h2>
10
+ <a href="{{ url_for('prestamo.new') }}" class="btn btn-primary">
11
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nuevo Préstamo/Adelanto') }}
12
+ </a>
13
+ </div>
14
+
15
+ <!-- Filters -->
16
+ <div class="card mb-3">
17
+ <div class="card-body">
18
+ <form method="GET" action="{{ url_for('prestamo.index') }}" class="row g-3">
19
+ <div class="col-md-4">
20
+ <label for="empleado_id" class="form-label">{{ _('Empleado') }}</label>
21
+ <select name="empleado_id" id="empleado_id" class="form-select">
22
+ <option value="">{{ _('-- Todos los empleados --') }}</option>
23
+ {% for emp in empleados %}
24
+ <option value="{{ emp.id }}" {% if filtro_empleado == emp.id %}selected{% endif %}>
25
+ {{ emp.primer_nombre }} {{ emp.primer_apellido }} - {{ emp.codigo_empleado }}
26
+ </option>
27
+ {% endfor %}
28
+ </select>
29
+ </div>
30
+ <div class="col-md-3">
31
+ <label for="tipo" class="form-label">{{ _('Tipo') }}</label>
32
+ <select name="tipo" id="tipo" class="form-select">
33
+ <option value="">{{ _('-- Todos --') }}</option>
34
+ <option value="adelanto" {% if filtro_tipo == 'adelanto' %}selected{% endif %}>{{ _('Adelanto') }}</option>
35
+ <option value="prestamo" {% if filtro_tipo == 'prestamo' %}selected{% endif %}>{{ _('Préstamo') }}</option>
36
+ </select>
37
+ </div>
38
+ <div class="col-md-3">
39
+ <label for="estado" class="form-label">{{ _('Estado') }}</label>
40
+ <select name="estado" id="estado" class="form-select">
41
+ <option value="">{{ _('-- Todos --') }}</option>
42
+ <option value="borrador" {% if filtro_estado == 'borrador' %}selected{% endif %}>{{ _('Borrador') }}</option>
43
+ <option value="pendiente" {% if filtro_estado == 'pendiente' %}selected{% endif %}>{{ _('Pendiente') }}</option>
44
+ <option value="aprobado" {% if filtro_estado == 'aprobado' %}selected{% endif %}>{{ _('Aprobado') }}</option>
45
+ <option value="aplicado" {% if filtro_estado == 'aplicado' %}selected{% endif %}>{{ _('Aplicado') }}</option>
46
+ <option value="pagado" {% if filtro_estado == 'pagado' %}selected{% endif %}>{{ _('Pagado') }}</option>
47
+ <option value="rechazado" {% if filtro_estado == 'rechazado' %}selected{% endif %}>{{ _('Rechazado') }}</option>
48
+ <option value="cancelado" {% if filtro_estado == 'cancelado' %}selected{% endif %}>{{ _('Cancelado') }}</option>
49
+ </select>
50
+ </div>
51
+ <div class="col-md-2 d-flex align-items-end">
52
+ <button type="submit" class="btn btn-secondary w-100">
53
+ <i class="bi bi-funnel me-1"></i>{{ _('Filtrar') }}
54
+ </button>
55
+ </div>
56
+ </form>
57
+ </div>
58
+ </div>
59
+
60
+ <!-- Loans Table -->
61
+ <div class="card">
62
+ <div class="card-body">
63
+ <div class="table-responsive">
64
+ <table class="table table-hover">
65
+ <thead>
66
+ <tr>
67
+ <th>{{ _('Empleado') }}</th>
68
+ <th>{{ _('Tipo') }}</th>
69
+ <th>{{ _('Fecha Solicitud') }}</th>
70
+ <th>{{ _('Monto') }}</th>
71
+ <th>{{ _('Cuotas') }}</th>
72
+ <th>{{ _('Saldo Pendiente') }}</th>
73
+ <th>{{ _('Estado') }}</th>
74
+ <th>{{ _('Acciones') }}</th>
75
+ </tr>
76
+ </thead>
77
+ <tbody>
78
+ {% for prestamo in prestamos %}
79
+ <tr>
80
+ <td>
81
+ {{ prestamo.empleado.primer_nombre }} {{ prestamo.empleado.primer_apellido }}<br>
82
+ <small class="text-muted">{{ prestamo.empleado.codigo_empleado }}</small>
83
+ </td>
84
+ <td>
85
+ {% if prestamo.tipo == 'adelanto' %}
86
+ <span class="badge bg-info">{{ _('Adelanto') }}</span>
87
+ {% else %}
88
+ <span class="badge bg-primary">{{ _('Préstamo') }}</span>
89
+ {% endif %}
90
+ </td>
91
+ <td>{{ prestamo.fecha_solicitud.strftime('%d/%m/%Y') }}</td>
92
+ <td>
93
+ {% if prestamo.moneda %}
94
+ {{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}
95
+ {% endif %}
96
+ {{ prestamo.monto_aprobado or prestamo.monto_solicitado }}
97
+ </td>
98
+ <td>{{ prestamo.cuotas_pactadas }}</td>
99
+ <td>
100
+ {% if prestamo.moneda %}
101
+ {{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}
102
+ {% endif %}
103
+ {{ prestamo.saldo_pendiente }}
104
+ </td>
105
+ <td>
106
+ {% if prestamo.estado == 'borrador' %}
107
+ <span class="badge bg-secondary">{{ _('Borrador') }}</span>
108
+ {% elif prestamo.estado == 'pendiente' %}
109
+ <span class="badge bg-warning text-dark">{{ _('Pendiente') }}</span>
110
+ {% elif prestamo.estado == 'aprobado' %}
111
+ <span class="badge bg-success">{{ _('Aprobado') }}</span>
112
+ {% elif prestamo.estado == 'aplicado' %}
113
+ <span class="badge bg-success">{{ _('Aplicado') }}</span>
114
+ {% elif prestamo.estado == 'pagado' %}
115
+ <span class="badge bg-dark">{{ _('Pagado') }}</span>
116
+ {% elif prestamo.estado == 'rechazado' %}
117
+ <span class="badge bg-danger">{{ _('Rechazado') }}</span>
118
+ {% elif prestamo.estado == 'cancelado' %}
119
+ <span class="badge bg-secondary">{{ _('Cancelado') }}</span>
120
+ {% endif %}
121
+ </td>
122
+ <td>
123
+ <a href="{{ url_for('prestamo.detail', prestamo_id=prestamo.id) }}"
124
+ class="btn btn-sm btn-outline-primary"
125
+ title="{{ _('Ver Detalle') }}">
126
+ <i class="bi bi-eye"></i>
127
+ </a>
128
+ {% if prestamo.estado in ['borrador', 'pendiente'] %}
129
+ <a href="{{ url_for('prestamo.edit', prestamo_id=prestamo.id) }}"
130
+ class="btn btn-sm btn-outline-secondary"
131
+ title="{{ _('Editar') }}">
132
+ <i class="bi bi-pencil"></i>
133
+ </a>
134
+ {% endif %}
135
+ </td>
136
+ </tr>
137
+ {% else %}
138
+ <tr>
139
+ <td colspan="8" class="text-center text-muted py-4">
140
+ {{ _('No hay préstamos o adelantos registrados.') }}
141
+ </td>
142
+ </tr>
143
+ {% endfor %}
144
+ </tbody>
145
+ </table>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ </div>
150
+ {% endblock %}
@@ -0,0 +1,211 @@
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>
10
+ <i class="bi bi-cash-stack me-2"></i>
11
+ {{ _('Registrar Pago Extraordinario') }}
12
+ </h2>
13
+ <a href="{{ url_for('prestamo.detail', prestamo_id=prestamo.id) }}" class="btn btn-outline-secondary">
14
+ <i class="bi bi-arrow-left me-1"></i>{{ _('Volver') }}
15
+ </a>
16
+ </div>
17
+
18
+ <!-- Loan Summary -->
19
+ <div class="card mb-4">
20
+ <div class="card-header bg-info text-white">
21
+ <h5 class="mb-0">{{ _('Información del Préstamo') }}</h5>
22
+ </div>
23
+ <div class="card-body">
24
+ <div class="row">
25
+ <div class="col-md-4">
26
+ <p><strong>{{ _('Empleado:') }}</strong> {{ prestamo.empleado.primer_nombre }} {{ prestamo.empleado.primer_apellido }}</p>
27
+ <p><strong>{{ _('Código:') }}</strong> {{ prestamo.empleado.codigo_empleado }}</p>
28
+ </div>
29
+ <div class="col-md-4">
30
+ <p><strong>{{ _('Saldo Pendiente:') }}</strong>
31
+ <span class="text-danger fs-5">
32
+ {% if prestamo.moneda %}
33
+ {{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}
34
+ {% endif %}
35
+ {{ "{:,.2f}".format(prestamo.saldo_pendiente) }}
36
+ </span>
37
+ </p>
38
+ </div>
39
+ <div class="col-md-4">
40
+ <p><strong>{{ _('Monto por Cuota:') }}</strong>
41
+ {% if prestamo.moneda %}
42
+ {{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}
43
+ {% endif %}
44
+ {{ "{:,.2f}".format(prestamo.monto_por_cuota or 0) }}
45
+ </p>
46
+ <p><strong>{{ _('Cuotas Pactadas:') }}</strong> {{ prestamo.cuotas_pactadas }}</p>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </div>
51
+
52
+ <!-- Payment Form -->
53
+ <div class="card">
54
+ <div class="card-header bg-primary text-white">
55
+ <h5 class="mb-0">{{ _('Datos del Pago Extraordinario') }}</h5>
56
+ </div>
57
+ <div class="card-body">
58
+ <form method="POST" novalidate>
59
+ {{ form.hidden_tag() }}
60
+
61
+ <div class="alert alert-info">
62
+ <i class="bi bi-info-circle me-2"></i>
63
+ <strong>{{ _('Nota:') }}</strong> {{ _('Los pagos extraordinarios permiten al empleado adelantar el pago de su préstamo. Debe indicar cómo desea aplicar este pago según la legislación laboral.') }}
64
+ </div>
65
+
66
+ <div class="row mb-3">
67
+ <div class="col-md-6">
68
+ <label for="{{ form.fecha_abono.id }}" class="form-label">
69
+ {{ form.fecha_abono.label.text }} <span class="text-danger">*</span>
70
+ </label>
71
+ {{ form.fecha_abono(class="form-control" + (" is-invalid" if form.fecha_abono.errors else "")) }}
72
+ {% if form.fecha_abono.errors %}
73
+ <div class="invalid-feedback">{{ form.fecha_abono.errors[0] }}</div>
74
+ {% endif %}
75
+ </div>
76
+
77
+ <div class="col-md-6">
78
+ <label for="{{ form.monto_abonado.id }}" class="form-label">
79
+ {{ form.monto_abonado.label.text }} <span class="text-danger">*</span>
80
+ </label>
81
+ <div class="input-group">
82
+ {% if prestamo.moneda %}
83
+ <span class="input-group-text">{{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}</span>
84
+ {% endif %}
85
+ {{ form.monto_abonado(class="form-control" + (" is-invalid" if form.monto_abonado.errors else "")) }}
86
+ {% if form.monto_abonado.errors %}
87
+ <div class="invalid-feedback">{{ form.monto_abonado.errors[0] }}</div>
88
+ {% endif %}
89
+ </div>
90
+ {% if form.monto_abonado.description %}
91
+ <div class="form-text">{{ form.monto_abonado.description }}</div>
92
+ {% endif %}
93
+ </div>
94
+ </div>
95
+
96
+ <div class="row mb-3">
97
+ <div class="col-12">
98
+ <label for="{{ form.tipo_aplicacion.id }}" class="form-label">
99
+ {{ form.tipo_aplicacion.label.text }} <span class="text-danger">*</span>
100
+ </label>
101
+ {{ form.tipo_aplicacion(class="form-select" + (" is-invalid" if form.tipo_aplicacion.errors else "")) }}
102
+ {% if form.tipo_aplicacion.errors %}
103
+ <div class="invalid-feedback">{{ form.tipo_aplicacion.errors[0] }}</div>
104
+ {% endif %}
105
+ {% if form.tipo_aplicacion.description %}
106
+ <div class="form-text">{{ form.tipo_aplicacion.description }}</div>
107
+ {% endif %}
108
+ </div>
109
+ </div>
110
+
111
+ <hr class="my-4">
112
+ <h6 class="mb-3">{{ _('Documentación de Auditoría') }}</h6>
113
+
114
+ <div class="row mb-3">
115
+ <div class="col-md-6">
116
+ <label for="{{ form.tipo_comprobante.id }}" class="form-label">
117
+ {{ form.tipo_comprobante.label.text }} <span class="text-danger">*</span>
118
+ </label>
119
+ {{ form.tipo_comprobante(class="form-select" + (" is-invalid" if form.tipo_comprobante.errors else "")) }}
120
+ {% if form.tipo_comprobante.errors %}
121
+ <div class="invalid-feedback">{{ form.tipo_comprobante.errors[0] }}</div>
122
+ {% endif %}
123
+ {% if form.tipo_comprobante.description %}
124
+ <div class="form-text">{{ form.tipo_comprobante.description }}</div>
125
+ {% endif %}
126
+ </div>
127
+
128
+ <div class="col-md-6">
129
+ <label for="{{ form.numero_comprobante.id }}" class="form-label">
130
+ {{ form.numero_comprobante.label.text }} <span class="text-danger">*</span>
131
+ </label>
132
+ {{ form.numero_comprobante(class="form-control" + (" is-invalid" if form.numero_comprobante.errors else "")) }}
133
+ {% if form.numero_comprobante.errors %}
134
+ <div class="invalid-feedback">{{ form.numero_comprobante.errors[0] }}</div>
135
+ {% endif %}
136
+ {% if form.numero_comprobante.description %}
137
+ <div class="form-text">{{ form.numero_comprobante.description }}</div>
138
+ {% endif %}
139
+ </div>
140
+ </div>
141
+
142
+ <div class="row mb-3">
143
+ <div class="col-md-6">
144
+ <label for="{{ form.referencia_bancaria.id }}" class="form-label">
145
+ {{ form.referencia_bancaria.label.text }}
146
+ </label>
147
+ {{ form.referencia_bancaria(class="form-control" + (" is-invalid" if form.referencia_bancaria.errors else "")) }}
148
+ {% if form.referencia_bancaria.errors %}
149
+ <div class="invalid-feedback">{{ form.referencia_bancaria.errors[0] }}</div>
150
+ {% endif %}
151
+ {% if form.referencia_bancaria.description %}
152
+ <div class="form-text">{{ form.referencia_bancaria.description }}</div>
153
+ {% endif %}
154
+ </div>
155
+
156
+ <div class="col-md-6">
157
+ <label for="{{ form.observaciones.id }}" class="form-label">
158
+ {{ form.observaciones.label.text }}
159
+ </label>
160
+ {{ form.observaciones(class="form-control" + (" is-invalid" if form.observaciones.errors else "")) }}
161
+ {% if form.observaciones.errors %}
162
+ <div class="invalid-feedback">{{ form.observaciones.errors[0] }}</div>
163
+ {% endif %}
164
+ {% if form.observaciones.description %}
165
+ <div class="form-text">{{ form.observaciones.description }}</div>
166
+ {% endif %}
167
+ </div>
168
+ </div>
169
+
170
+ <hr class="my-4">
171
+ <h6 class="mb-3">{{ _('Información Contable (Opcional)') }}</h6>
172
+
173
+ <div class="row mb-3">
174
+ <div class="col-md-6">
175
+ <label for="{{ form.cuenta_debe.id }}" class="form-label">
176
+ {{ form.cuenta_debe.label.text }}
177
+ </label>
178
+ {{ form.cuenta_debe(class="form-control" + (" is-invalid" if form.cuenta_debe.errors else "")) }}
179
+ {% if form.cuenta_debe.errors %}
180
+ <div class="invalid-feedback">{{ form.cuenta_debe.errors[0] }}</div>
181
+ {% endif %}
182
+ {% if form.cuenta_debe.description %}
183
+ <div class="form-text">{{ form.cuenta_debe.description }}</div>
184
+ {% endif %}
185
+ </div>
186
+
187
+ <div class="col-md-6">
188
+ <label for="{{ form.cuenta_haber.id }}" class="form-label">
189
+ {{ form.cuenta_haber.label.text }}
190
+ </label>
191
+ {{ form.cuenta_haber(class="form-control" + (" is-invalid" if form.cuenta_haber.errors else "")) }}
192
+ {% if form.cuenta_haber.errors %}
193
+ <div class="invalid-feedback">{{ form.cuenta_haber.errors[0] }}</div>
194
+ {% endif %}
195
+ {% if form.cuenta_haber.description %}
196
+ <div class="form-text">{{ form.cuenta_haber.description }}</div>
197
+ {% endif %}
198
+ </div>
199
+ </div>
200
+
201
+ <div class="d-flex justify-content-end gap-2 mt-4">
202
+ <a href="{{ url_for('prestamo.detail', prestamo_id=prestamo.id) }}" class="btn btn-secondary">
203
+ {{ _('Cancelar') }}
204
+ </a>
205
+ {{ form.submit(class="btn btn-primary") }}
206
+ </div>
207
+ </form>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ {% endblock %}
@@ -0,0 +1,181 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Tabla de Pagos - Préstamo/Adelanto</title>
6
+ <style>
7
+ @page {
8
+ size: letter;
9
+ margin: 2cm;
10
+ }
11
+ body {
12
+ font-family: Arial, sans-serif;
13
+ font-size: 11pt;
14
+ }
15
+ .header {
16
+ text-align: center;
17
+ margin-bottom: 30px;
18
+ }
19
+ .header h1 {
20
+ margin: 0;
21
+ font-size: 18pt;
22
+ }
23
+ .info-section {
24
+ margin-bottom: 20px;
25
+ }
26
+ .info-row {
27
+ margin-bottom: 5px;
28
+ }
29
+ .info-label {
30
+ font-weight: bold;
31
+ display: inline-block;
32
+ width: 150px;
33
+ }
34
+ table {
35
+ width: 100%;
36
+ border-collapse: collapse;
37
+ margin-top: 20px;
38
+ }
39
+ th, td {
40
+ border: 1px solid #ddd;
41
+ padding: 8px;
42
+ text-align: left;
43
+ }
44
+ th {
45
+ background-color: #366092;
46
+ color: white;
47
+ font-weight: bold;
48
+ }
49
+ .text-right {
50
+ text-align: right;
51
+ }
52
+ .text-center {
53
+ text-align: center;
54
+ }
55
+ .footer {
56
+ margin-top: 50px;
57
+ border-top: 1px solid #000;
58
+ padding-top: 10px;
59
+ }
60
+ .signature-section {
61
+ margin-top: 80px;
62
+ display: flex;
63
+ justify-content: space-between;
64
+ }
65
+ .signature-line {
66
+ width: 45%;
67
+ border-top: 1px solid #000;
68
+ text-align: center;
69
+ padding-top: 5px;
70
+ }
71
+ </style>
72
+ </head>
73
+ <body>
74
+ <div class="header">
75
+ <h1>TABLA DE PAGOS</h1>
76
+ <p>Préstamo / Adelanto de Salario</p>
77
+ </div>
78
+
79
+ <div class="info-section">
80
+ <div class="info-row">
81
+ <span class="info-label">Empleado:</span>
82
+ <span>{{ prestamo.empleado.primer_nombre }} {{ prestamo.empleado.primer_apellido }}</span>
83
+ </div>
84
+ <div class="info-row">
85
+ <span class="info-label">Código Empleado:</span>
86
+ <span>{{ prestamo.empleado.codigo_empleado }}</span>
87
+ </div>
88
+ <div class="info-row">
89
+ <span class="info-label">Tipo:</span>
90
+ <span>{% if prestamo.tipo == 'adelanto' %}Adelanto de Salario{% else %}Préstamo{% endif %}</span>
91
+ </div>
92
+ <div class="info-row">
93
+ <span class="info-label">Monto Aprobado:</span>
94
+ <span>
95
+ {% if prestamo.moneda %}{{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}{% endif %}
96
+ {{ "{:,.2f}".format(prestamo.monto_aprobado or prestamo.monto_solicitado) }}
97
+ </span>
98
+ </div>
99
+ <div class="info-row">
100
+ <span class="info-label">Número de Cuotas:</span>
101
+ <span>{{ prestamo.cuotas_pactadas }}</span>
102
+ </div>
103
+ <div class="info-row">
104
+ <span class="info-label">Monto por Cuota:</span>
105
+ <span>
106
+ {% if prestamo.moneda %}{{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}{% endif %}
107
+ {{ "{:,.2f}".format(prestamo.monto_por_cuota or 0) }}
108
+ </span>
109
+ </div>
110
+ <div class="info-row">
111
+ <span class="info-label">Fecha de Solicitud:</span>
112
+ <span>{{ prestamo.fecha_solicitud.strftime('%d/%m/%Y') }}</span>
113
+ </div>
114
+ {% if prestamo.fecha_aprobacion %}
115
+ <div class="info-row">
116
+ <span class="info-label">Fecha de Aprobación:</span>
117
+ <span>{{ prestamo.fecha_aprobacion.strftime('%d/%m/%Y') }}</span>
118
+ </div>
119
+ {% endif %}
120
+ </div>
121
+
122
+ <table>
123
+ <thead>
124
+ <tr>
125
+ <th class="text-center">#</th>
126
+ <th>Fecha Estimada</th>
127
+ <th class="text-right">Cuota</th>
128
+ <th class="text-right">Interés</th>
129
+ <th class="text-right">Capital</th>
130
+ <th class="text-right">Saldo</th>
131
+ </tr>
132
+ </thead>
133
+ <tbody>
134
+ {% for item in tabla_pago %}
135
+ <tr>
136
+ <td class="text-center">{{ item.numero }}</td>
137
+ <td>
138
+ {% if item.fecha_estimada %}
139
+ {{ item.fecha_estimada.strftime('%d/%m/%Y') }}
140
+ {% else %}
141
+ -
142
+ {% endif %}
143
+ </td>
144
+ <td class="text-right">
145
+ {% if prestamo.moneda %}{{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}{% endif %}
146
+ {{ "{:,.2f}".format(item.cuota) }}
147
+ </td>
148
+ <td class="text-right">
149
+ {% if prestamo.moneda %}{{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}{% endif %}
150
+ {{ "{:,.2f}".format(item.interes) }}
151
+ </td>
152
+ <td class="text-right">
153
+ {% if prestamo.moneda %}{{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}{% endif %}
154
+ {{ "{:,.2f}".format(item.capital) }}
155
+ </td>
156
+ <td class="text-right">
157
+ {% if prestamo.moneda %}{{ prestamo.moneda.simbolo or prestamo.moneda.codigo }}{% endif %}
158
+ {{ "{:,.2f}".format(item.saldo) }}
159
+ </td>
160
+ </tr>
161
+ {% endfor %}
162
+ </tbody>
163
+ </table>
164
+
165
+ <div class="signature-section">
166
+ <div class="signature-line">
167
+ <p>Firma del Empleado</p>
168
+ </div>
169
+ <div class="signature-line">
170
+ <p>Firma Autorizada</p>
171
+ </div>
172
+ </div>
173
+
174
+ <div class="footer">
175
+ <p style="font-size: 9pt; text-align: center;">
176
+ Este documento constituye el compromiso de pago del préstamo/adelanto arriba detallado.
177
+ El empleado se compromete a pagar las cuotas según lo establecido.
178
+ </p>
179
+ </div>
180
+ </body>
181
+ </html>