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,76 @@
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>{{ _('Empleados') }}</h2>
10
+ <a href="{{ url_for('employee.new') }}" class="btn btn-primary">
11
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nuevo Empleado') }}
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>{{ _('Código') }}</th>
22
+ <th>{{ _('Identificación') }}</th>
23
+ <th>{{ _('Nombre Completo') }}</th>
24
+ <th>{{ _('Cargo') }}</th>
25
+ <th>{{ _('Área') }}</th>
26
+ <th>{{ _('Salario Base') }}</th>
27
+ <th>{{ _('Estado') }}</th>
28
+ <th>{{ _('Acciones') }}</th>
29
+ </tr>
30
+ </thead>
31
+ <tbody>
32
+ {% for employee in employees %}
33
+ <tr>
34
+ <td>{{ employee.codigo_empleado }}</td>
35
+ <td>{{ employee.identificacion_personal }}</td>
36
+ <td>{{ employee.primer_nombre }} {{ employee.segundo_nombre or '' }} {{ employee.primer_apellido }} {{ employee.segundo_apellido or '' }}</td>
37
+ <td>{{ employee.cargo or '-' }}</td>
38
+ <td>{{ employee.area or '-' }}</td>
39
+ <td>
40
+ {% if employee.moneda %}
41
+ {{ employee.moneda.simbolo or employee.moneda.codigo }} {{ employee.salario_base }}
42
+ {% else %}
43
+ {{ employee.salario_base }}
44
+ {% endif %}
45
+ </td>
46
+ <td>
47
+ {% if employee.activo %}
48
+ <span class="badge bg-success">{{ _('Activo') }}</span>
49
+ {% else %}
50
+ <span class="badge bg-warning">{{ _('Inactivo') }}</span>
51
+ {% endif %}
52
+ </td>
53
+ <td>
54
+ <a href="{{ url_for('employee.edit', id=employee.id) }}" class="btn btn-sm btn-outline-primary" title="{{ _('Editar') }}">
55
+ <i class="bi bi-pencil"></i>
56
+ </a>
57
+ <form action="{{ url_for('employee.delete', id=employee.id) }}" method="POST" class="d-inline" onsubmit="return confirm('{{ _('¿Está seguro de eliminar este empleado?') }}');">
58
+ <button type="submit" class="btn btn-sm btn-outline-danger" title="{{ _('Eliminar') }}">
59
+ <i class="bi bi-trash"></i>
60
+ </button>
61
+ </form>
62
+ </td>
63
+ </tr>
64
+ {% else %}
65
+ <tr>
66
+ <td colspan="8" class="text-center text-muted">{{ _('No hay empleados registrados.') }}</td>
67
+ </tr>
68
+ {% endfor %}
69
+ </tbody>
70
+ </table>
71
+ </div>
72
+ {{ render_pagination(pagination, 'employee.index') }}
73
+ </div>
74
+ </div>
75
+ </div>
76
+ {% endblock %}
@@ -0,0 +1,74 @@
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('empresa.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.codigo) }}
24
+ </div>
25
+ <div class="col-md-6">
26
+ {{ render_field(form.ruc) }}
27
+ </div>
28
+ </div>
29
+
30
+ <div class="row">
31
+ <div class="col-md-6">
32
+ {{ render_field(form.razon_social) }}
33
+ </div>
34
+ <div class="col-md-6">
35
+ {{ render_field(form.nombre_comercial) }}
36
+ </div>
37
+ </div>
38
+
39
+ <div class="row">
40
+ <div class="col-md-12">
41
+ {{ render_field(form.direccion) }}
42
+ </div>
43
+ </div>
44
+
45
+ <div class="row">
46
+ <div class="col-md-4">
47
+ {{ render_field(form.telefono) }}
48
+ </div>
49
+ <div class="col-md-4">
50
+ {{ render_field(form.correo) }}
51
+ </div>
52
+ <div class="col-md-4">
53
+ {{ render_field(form.sitio_web) }}
54
+ </div>
55
+ </div>
56
+
57
+ <div class="row">
58
+ <div class="col-md-6">
59
+ {{ render_field(form.representante_legal) }}
60
+ </div>
61
+ <div class="col-md-6">
62
+ {{ render_field(form.activo) }}
63
+ </div>
64
+ </div>
65
+
66
+ <div class="mt-4">
67
+ {{ form.submit(class="btn btn-primary") }}
68
+ <a href="{{ url_for('empresa.index') }}" class="btn btn-secondary">{{ _('Cancelar') }}</a>
69
+ </div>
70
+ </form>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ {% endblock %}
@@ -0,0 +1,71 @@
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>{{ _('Empresas') }}</h2>
10
+ <a href="{{ url_for('empresa.new') }}" class="btn btn-primary">
11
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nueva Empresa') }}
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>{{ _('Código') }}</th>
22
+ <th>{{ _('Razón Social') }}</th>
23
+ <th>{{ _('Nombre Comercial') }}</th>
24
+ <th>{{ _('RUC') }}</th>
25
+ <th>{{ _('Estado') }}</th>
26
+ <th>{{ _('Acciones') }}</th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ {% for empresa in empresas %}
31
+ <tr>
32
+ <td><strong>{{ empresa.codigo }}</strong></td>
33
+ <td>{{ empresa.razon_social }}</td>
34
+ <td>{{ empresa.nombre_comercial or '-' }}</td>
35
+ <td>{{ empresa.ruc }}</td>
36
+ <td>
37
+ {% if empresa.activo %}
38
+ <span class="badge bg-success">{{ _('Activa') }}</span>
39
+ {% else %}
40
+ <span class="badge bg-warning">{{ _('Inactiva') }}</span>
41
+ {% endif %}
42
+ </td>
43
+ <td>
44
+ <a href="{{ url_for('empresa.edit', empresa_id=empresa.id) }}" class="btn btn-sm btn-outline-primary" title="{{ _('Editar') }}">
45
+ <i class="bi bi-pencil"></i>
46
+ </a>
47
+ <form action="{{ url_for('empresa.toggle_active', empresa_id=empresa.id) }}" method="POST" class="d-inline">
48
+ <button type="submit" class="btn btn-sm btn-outline-secondary" title="{{ _('Activar/Desactivar') }}">
49
+ <i class="bi bi-toggle-on"></i>
50
+ </button>
51
+ </form>
52
+ <form action="{{ url_for('empresa.delete', empresa_id=empresa.id) }}" method="POST" class="d-inline" onsubmit="return confirm('{{ _('¿Está seguro de eliminar esta empresa?') }}');">
53
+ <button type="submit" class="btn btn-sm btn-outline-danger" title="{{ _('Eliminar') }}">
54
+ <i class="bi bi-trash"></i>
55
+ </button>
56
+ </form>
57
+ </td>
58
+ </tr>
59
+ {% else %}
60
+ <tr>
61
+ <td colspan="6" class="text-center text-muted">{{ _('No hay empresas registradas.') }}</td>
62
+ </tr>
63
+ {% endfor %}
64
+ </tbody>
65
+ </table>
66
+ </div>
67
+ {{ render_pagination(pagination, 'empresa.index') }}
68
+ </div>
69
+ </div>
70
+ </div>
71
+ {% endblock %}
@@ -0,0 +1,47 @@
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>{{ title }}</h2>
11
+ <a href="{{ url_for('exchange_rate.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.fecha) }}
24
+ </div>
25
+ <div class="col-md-6">
26
+ {{ render_field(form.tasa) }}
27
+ </div>
28
+ </div>
29
+
30
+ <div class="row">
31
+ <div class="col-md-6">
32
+ {{ render_field(form.moneda_origen_id) }}
33
+ </div>
34
+ <div class="col-md-6">
35
+ {{ render_field(form.moneda_destino_id) }}
36
+ </div>
37
+ </div>
38
+
39
+ <div class="mt-4">
40
+ {{ form.submit(class="btn btn-primary") }}
41
+ <a href="{{ url_for('exchange_rate.index') }}" class="btn btn-secondary">{{ _('Cancelar') }}</a>
42
+ </div>
43
+ </form>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ {% endblock %}
@@ -0,0 +1,93 @@
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>{{ _('Importar Tipos de Cambio desde Excel') }}</h2>
10
+ <a href="{{ url_for('exchange_rate.index') }}" class="btn btn-secondary">
11
+ <i class="bi bi-arrow-left me-1"></i>{{ _('Volver') }}
12
+ </a>
13
+ </div>
14
+
15
+ <div class="card">
16
+ <div class="card-body">
17
+ <h5 class="card-title">{{ _('Instrucciones') }}</h5>
18
+ <p>{{ _('El archivo Excel debe contener las siguientes columnas en el siguiente orden:') }}</p>
19
+ <ol>
20
+ <li><strong>{{ _('Fecha') }}</strong>: {{ _('Fecha del tipo de cambio (formato YYYY-MM-DD o DD/MM/YYYY)') }}</li>
21
+ <li><strong>{{ _('Moneda Base') }}</strong>: {{ _('Código de la moneda origen (ej: USD, NIO)') }}</li>
22
+ <li><strong>{{ _('Moneda Destino') }}</strong>: {{ _('Código de la moneda destino (ej: USD, NIO)') }}</li>
23
+ <li><strong>{{ _('Tipo de Cambio') }}</strong>: {{ _('Tasa de cambio (puede tener hasta 4 decimales)') }}</li>
24
+ </ol>
25
+ <div class="alert alert-info">
26
+ <i class="bi bi-info-circle me-1"></i>
27
+ {{ _('Nota: La primera fila del archivo debe contener los encabezados de las columnas y será ignorada durante la importación.') }}
28
+ </div>
29
+ <div class="alert alert-warning">
30
+ <i class="bi bi-exclamation-triangle me-1"></i>
31
+ {{ _('Si un tipo de cambio ya existe para la misma fecha y par de monedas, será actualizado con el nuevo valor.') }}
32
+ </div>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="card mt-3">
37
+ <div class="card-body">
38
+ <h5 class="card-title">{{ _('Seleccionar Archivo') }}</h5>
39
+ <form method="POST" action="{{ url_for('exchange_rate.import_excel') }}" enctype="multipart/form-data">
40
+ <div class="mb-3">
41
+ <label for="file" class="form-label">{{ _('Archivo Excel') }}</label>
42
+ <input type="file" class="form-control" id="file" name="file" accept=".xlsx,.xls" required>
43
+ <div class="form-text">{{ _('Formatos soportados: .xlsx, .xls') }}</div>
44
+ </div>
45
+ <button type="submit" class="btn btn-primary">
46
+ <i class="bi bi-upload me-1"></i>{{ _('Importar') }}
47
+ </button>
48
+ <a href="{{ url_for('exchange_rate.index') }}" class="btn btn-secondary">
49
+ {{ _('Cancelar') }}
50
+ </a>
51
+ </form>
52
+ </div>
53
+ </div>
54
+
55
+ <div class="card mt-3">
56
+ <div class="card-body">
57
+ <h5 class="card-title">{{ _('Ejemplo de Formato') }}</h5>
58
+ <div class="table-responsive">
59
+ <table class="table table-bordered">
60
+ <thead>
61
+ <tr>
62
+ <th>{{ _('Fecha') }}</th>
63
+ <th>{{ _('Moneda Base') }}</th>
64
+ <th>{{ _('Moneda Destino') }}</th>
65
+ <th>{{ _('Tipo de Cambio') }}</th>
66
+ </tr>
67
+ </thead>
68
+ <tbody>
69
+ <tr>
70
+ <td>2024-01-15</td>
71
+ <td>USD</td>
72
+ <td>NIO</td>
73
+ <td>36.5000</td>
74
+ </tr>
75
+ <tr>
76
+ <td>2024-01-16</td>
77
+ <td>USD</td>
78
+ <td>NIO</td>
79
+ <td>36.5500</td>
80
+ </tr>
81
+ <tr>
82
+ <td>2024-01-15</td>
83
+ <td>EUR</td>
84
+ <td>USD</td>
85
+ <td>1.0950</td>
86
+ </tr>
87
+ </tbody>
88
+ </table>
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ {% endblock %}
@@ -0,0 +1,114 @@
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>{{ _('Tipos de Cambio') }}</h2>
10
+ <div>
11
+ <a href="{{ url_for('exchange_rate.import_excel') }}" class="btn btn-success me-2">
12
+ <i class="bi bi-file-earmark-excel me-1"></i>{{ _('Importar desde Excel') }}
13
+ </a>
14
+ <a href="{{ url_for('exchange_rate.new') }}" class="btn btn-primary">
15
+ <i class="bi bi-plus-lg me-1"></i>{{ _('Nuevo Tipo de Cambio') }}
16
+ </a>
17
+ </div>
18
+ </div>
19
+
20
+ <!-- Filter Form -->
21
+ <div class="card mb-3">
22
+ <div class="card-header">
23
+ <h5 class="mb-0">
24
+ <i class="bi bi-funnel me-1"></i>{{ _('Filtros') }}
25
+ </h5>
26
+ </div>
27
+ <div class="card-body">
28
+ <form method="GET" action="{{ url_for('exchange_rate.index') }}">
29
+ <div class="row g-3">
30
+ <div class="col-md-3">
31
+ <label for="fecha_desde" class="form-label">{{ _('Fecha desde') }}</label>
32
+ <input type="date" class="form-control" id="fecha_desde" name="fecha_desde" value="{{ fecha_desde or '' }}">
33
+ </div>
34
+ <div class="col-md-3">
35
+ <label for="fecha_hasta" class="form-label">{{ _('Fecha hasta') }}</label>
36
+ <input type="date" class="form-control" id="fecha_hasta" name="fecha_hasta" value="{{ fecha_hasta or '' }}">
37
+ </div>
38
+ <div class="col-md-3">
39
+ <label for="moneda_origen_id" class="form-label">{{ _('Moneda origen') }}</label>
40
+ <select class="form-select" id="moneda_origen_id" name="moneda_origen_id">
41
+ <option value="">{{ _('Todas') }}</option>
42
+ {% for id, name in currencies %}
43
+ <option value="{{ id }}" {% if moneda_origen_id == id %}selected{% endif %}>{{ name }}</option>
44
+ {% endfor %}
45
+ </select>
46
+ </div>
47
+ <div class="col-md-3">
48
+ <label for="moneda_destino_id" class="form-label">{{ _('Moneda destino') }}</label>
49
+ <select class="form-select" id="moneda_destino_id" name="moneda_destino_id">
50
+ <option value="">{{ _('Todas') }}</option>
51
+ {% for id, name in currencies %}
52
+ <option value="{{ id }}" {% if moneda_destino_id == id %}selected{% endif %}>{{ name }}</option>
53
+ {% endfor %}
54
+ </select>
55
+ </div>
56
+ </div>
57
+ <div class="row mt-3">
58
+ <div class="col-12">
59
+ <button type="submit" class="btn btn-primary">
60
+ <i class="bi bi-search me-1"></i>{{ _('Buscar') }}
61
+ </button>
62
+ <a href="{{ url_for('exchange_rate.index') }}" class="btn btn-secondary">
63
+ <i class="bi bi-x-circle me-1"></i>{{ _('Limpiar') }}
64
+ </a>
65
+ </div>
66
+ </div>
67
+ </form>
68
+ </div>
69
+ </div>
70
+
71
+ <div class="card">
72
+ <div class="card-body">
73
+ <div class="table-responsive">
74
+ <table class="table table-hover">
75
+ <thead>
76
+ <tr>
77
+ <th>{{ _('Fecha') }}</th>
78
+ <th>{{ _('Moneda Origen') }}</th>
79
+ <th>{{ _('Moneda Destino') }}</th>
80
+ <th>{{ _('Tasa') }}</th>
81
+ <th>{{ _('Acciones') }}</th>
82
+ </tr>
83
+ </thead>
84
+ <tbody>
85
+ {% for rate in exchange_rates %}
86
+ <tr>
87
+ <td>{{ rate.fecha.strftime('%Y-%m-%d') }}</td>
88
+ <td>{{ rate.moneda_origen.codigo if rate.moneda_origen else '-' }}</td>
89
+ <td>{{ rate.moneda_destino.codigo if rate.moneda_destino else '-' }}</td>
90
+ <td>{{ rate.tasa }}</td>
91
+ <td>
92
+ <a href="{{ url_for('exchange_rate.edit', id=rate.id) }}" class="btn btn-sm btn-outline-primary" title="{{ _('Editar') }}">
93
+ <i class="bi bi-pencil"></i>
94
+ </a>
95
+ <form action="{{ url_for('exchange_rate.delete', id=rate.id) }}" method="POST" class="d-inline" onsubmit="return confirm('{{ _('¿Está seguro de eliminar este tipo de cambio?') }}');">
96
+ <button type="submit" class="btn btn-sm btn-outline-danger" title="{{ _('Eliminar') }}">
97
+ <i class="bi bi-trash"></i>
98
+ </button>
99
+ </form>
100
+ </td>
101
+ </tr>
102
+ {% else %}
103
+ <tr>
104
+ <td colspan="5" class="text-center text-muted">{{ _('No hay tipos de cambio registrados.') }}</td>
105
+ </tr>
106
+ {% endfor %}
107
+ </tbody>
108
+ </table>
109
+ </div>
110
+ {{ render_pagination(pagination, 'exchange_rate.index') }}
111
+ </div>
112
+ </div>
113
+ </div>
114
+ {% endblock %}
@@ -0,0 +1,58 @@
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><i class="bi bi-file-earmark-text me-2"></i>{{ _('Liquidaciones') }}</h2>
10
+ <a href="{{ url_for('liquidacion.nueva') }}" class="btn btn-primary">
11
+ <i class="bi bi-plus-circle me-1"></i>{{ _('Nueva') }}
12
+ </a>
13
+ </div>
14
+
15
+ <div class="card">
16
+ <div class="card-body">
17
+ {% if liquidaciones %}
18
+ <div class="table-responsive">
19
+ <table class="table table-striped">
20
+ <thead>
21
+ <tr>
22
+ <th>{{ _('Empleado') }}</th>
23
+ <th>{{ _('Fecha Cálculo') }}</th>
24
+ <th>{{ _('Días por Pagar') }}</th>
25
+ <th>{{ _('Total Neto') }}</th>
26
+ <th>{{ _('Estado') }}</th>
27
+ <th></th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ {% for l in liquidaciones %}
32
+ <tr>
33
+ <td>
34
+ {% if l.empleado %}
35
+ {{ l.empleado.primer_nombre }} {{ l.empleado.primer_apellido }}
36
+ {% else %}
37
+ {{ l.empleado_id }}
38
+ {% endif %}
39
+ </td>
40
+ <td>{{ l.fecha_calculo }}</td>
41
+ <td>{{ l.dias_por_pagar }}</td>
42
+ <td>{{ l.total_neto }}</td>
43
+ <td>{{ l.estado }}</td>
44
+ <td>
45
+ <a class="btn btn-sm btn-outline-primary" href="{{ url_for('liquidacion.ver', liquidacion_id=l.id) }}">{{ _('Ver') }}</a>
46
+ </td>
47
+ </tr>
48
+ {% endfor %}
49
+ </tbody>
50
+ </table>
51
+ </div>
52
+ {% else %}
53
+ <p class="text-muted mb-0">{{ _('No hay liquidaciones registradas.') }}</p>
54
+ {% endif %}
55
+ </div>
56
+ </div>
57
+ </div>
58
+ {% endblock %}
@@ -0,0 +1,51 @@
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><i class="bi bi-plus-circle me-2"></i>{{ _('Nueva Liquidación') }}</h2>
10
+ <a href="{{ url_for('liquidacion.index') }}" class="btn btn-outline-secondary">
11
+ <i class="bi bi-arrow-left me-1"></i>{{ _('Volver') }}
12
+ </a>
13
+ </div>
14
+
15
+ <div class="card">
16
+ <div class="card-body">
17
+ <form method="POST">
18
+ <div class="mb-3">
19
+ <label class="form-label" for="empleado_id">{{ _('Empleado') }}</label>
20
+ <select class="form-select" id="empleado_id" name="empleado_id" required>
21
+ <option value="">{{ _('-- Seleccionar --') }}</option>
22
+ {% for e in empleados %}
23
+ <option value="{{ e.id }}">{{ e.codigo_empleado }} - {{ e.primer_nombre }} {{ e.primer_apellido }}</option>
24
+ {% endfor %}
25
+ </select>
26
+ </div>
27
+
28
+ <div class="mb-3">
29
+ <label class="form-label" for="concepto_id">{{ _('Concepto') }}</label>
30
+ <select class="form-select" id="concepto_id" name="concepto_id">
31
+ <option value="">{{ _('-- Seleccionar --') }}</option>
32
+ {% for c in conceptos %}
33
+ <option value="{{ c.id }}">{{ c.nombre }}</option>
34
+ {% endfor %}
35
+ </select>
36
+ </div>
37
+
38
+ <div class="mb-3">
39
+ <label class="form-label" for="fecha_calculo">{{ _('Fecha de Cálculo') }}</label>
40
+ <input class="form-control" type="date" id="fecha_calculo" name="fecha_calculo" value="{{ fecha_calculo }}" />
41
+ </div>
42
+
43
+ <div class="d-flex gap-2">
44
+ <button type="submit" class="btn btn-primary">{{ _('Calcular') }}</button>
45
+ <a href="{{ url_for('liquidacion.index') }}" class="btn btn-secondary">{{ _('Cancelar') }}</a>
46
+ </div>
47
+ </form>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ {% endblock %}