coati-payroll 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of coati-payroll might be problematic. Click here for more details.
- coati_payroll/__init__.py +415 -0
- coati_payroll/app.py +95 -0
- coati_payroll/audit_helpers.py +904 -0
- coati_payroll/auth.py +123 -0
- coati_payroll/cli.py +1318 -0
- coati_payroll/config.py +219 -0
- coati_payroll/demo_data.py +813 -0
- coati_payroll/enums.py +278 -0
- coati_payroll/forms.py +1769 -0
- coati_payroll/formula_engine/__init__.py +81 -0
- coati_payroll/formula_engine/ast/__init__.py +110 -0
- coati_payroll/formula_engine/ast/ast_visitor.py +259 -0
- coati_payroll/formula_engine/ast/expression_evaluator.py +228 -0
- coati_payroll/formula_engine/ast/safe_operators.py +131 -0
- coati_payroll/formula_engine/ast/type_converter.py +172 -0
- coati_payroll/formula_engine/data_sources.py +752 -0
- coati_payroll/formula_engine/engine.py +247 -0
- coati_payroll/formula_engine/exceptions.py +52 -0
- coati_payroll/formula_engine/execution/__init__.py +24 -0
- coati_payroll/formula_engine/execution/execution_context.py +52 -0
- coati_payroll/formula_engine/execution/step_executor.py +62 -0
- coati_payroll/formula_engine/execution/variable_store.py +59 -0
- coati_payroll/formula_engine/novelty_codes.py +206 -0
- coati_payroll/formula_engine/results/__init__.py +20 -0
- coati_payroll/formula_engine/results/execution_result.py +59 -0
- coati_payroll/formula_engine/steps/__init__.py +30 -0
- coati_payroll/formula_engine/steps/assignment_step.py +71 -0
- coati_payroll/formula_engine/steps/base_step.py +48 -0
- coati_payroll/formula_engine/steps/calculation_step.py +42 -0
- coati_payroll/formula_engine/steps/conditional_step.py +122 -0
- coati_payroll/formula_engine/steps/step_factory.py +58 -0
- coati_payroll/formula_engine/steps/tax_lookup_step.py +45 -0
- coati_payroll/formula_engine/tables/__init__.py +24 -0
- coati_payroll/formula_engine/tables/bracket_calculator.py +51 -0
- coati_payroll/formula_engine/tables/table_lookup.py +161 -0
- coati_payroll/formula_engine/tables/tax_table.py +32 -0
- coati_payroll/formula_engine/validation/__init__.py +24 -0
- coati_payroll/formula_engine/validation/schema_validator.py +37 -0
- coati_payroll/formula_engine/validation/security_validator.py +52 -0
- coati_payroll/formula_engine/validation/tax_table_validator.py +205 -0
- coati_payroll/formula_engine_examples.py +153 -0
- coati_payroll/i18n.py +54 -0
- coati_payroll/initial_data.py +613 -0
- coati_payroll/interes_engine.py +450 -0
- coati_payroll/liquidacion_engine/__init__.py +25 -0
- coati_payroll/liquidacion_engine/engine.py +267 -0
- coati_payroll/locale_config.py +165 -0
- coati_payroll/log.py +138 -0
- coati_payroll/model.py +2410 -0
- coati_payroll/nomina_engine/__init__.py +87 -0
- coati_payroll/nomina_engine/calculators/__init__.py +30 -0
- coati_payroll/nomina_engine/calculators/benefit_calculator.py +79 -0
- coati_payroll/nomina_engine/calculators/concept_calculator.py +254 -0
- coati_payroll/nomina_engine/calculators/deduction_calculator.py +105 -0
- coati_payroll/nomina_engine/calculators/exchange_rate_calculator.py +51 -0
- coati_payroll/nomina_engine/calculators/perception_calculator.py +75 -0
- coati_payroll/nomina_engine/calculators/salary_calculator.py +86 -0
- coati_payroll/nomina_engine/domain/__init__.py +27 -0
- coati_payroll/nomina_engine/domain/calculation_items.py +52 -0
- coati_payroll/nomina_engine/domain/employee_calculation.py +53 -0
- coati_payroll/nomina_engine/domain/payroll_context.py +44 -0
- coati_payroll/nomina_engine/engine.py +188 -0
- coati_payroll/nomina_engine/processors/__init__.py +28 -0
- coati_payroll/nomina_engine/processors/accounting_processor.py +171 -0
- coati_payroll/nomina_engine/processors/accumulation_processor.py +90 -0
- coati_payroll/nomina_engine/processors/loan_processor.py +227 -0
- coati_payroll/nomina_engine/processors/novelty_processor.py +42 -0
- coati_payroll/nomina_engine/processors/vacation_processor.py +67 -0
- coati_payroll/nomina_engine/repositories/__init__.py +32 -0
- coati_payroll/nomina_engine/repositories/acumulado_repository.py +83 -0
- coati_payroll/nomina_engine/repositories/base_repository.py +40 -0
- coati_payroll/nomina_engine/repositories/config_repository.py +102 -0
- coati_payroll/nomina_engine/repositories/employee_repository.py +34 -0
- coati_payroll/nomina_engine/repositories/exchange_rate_repository.py +58 -0
- coati_payroll/nomina_engine/repositories/novelty_repository.py +54 -0
- coati_payroll/nomina_engine/repositories/planilla_repository.py +52 -0
- coati_payroll/nomina_engine/results/__init__.py +24 -0
- coati_payroll/nomina_engine/results/error_result.py +28 -0
- coati_payroll/nomina_engine/results/payroll_result.py +53 -0
- coati_payroll/nomina_engine/results/validation_result.py +39 -0
- coati_payroll/nomina_engine/services/__init__.py +22 -0
- coati_payroll/nomina_engine/services/accounting_voucher_service.py +708 -0
- coati_payroll/nomina_engine/services/employee_processing_service.py +173 -0
- coati_payroll/nomina_engine/services/payroll_execution_service.py +374 -0
- coati_payroll/nomina_engine/services/snapshot_service.py +295 -0
- coati_payroll/nomina_engine/validators/__init__.py +31 -0
- coati_payroll/nomina_engine/validators/base_validator.py +48 -0
- coati_payroll/nomina_engine/validators/currency_validator.py +50 -0
- coati_payroll/nomina_engine/validators/employee_validator.py +87 -0
- coati_payroll/nomina_engine/validators/period_validator.py +44 -0
- coati_payroll/nomina_engine/validators/planilla_validator.py +136 -0
- coati_payroll/plugin_manager.py +176 -0
- coati_payroll/queue/__init__.py +33 -0
- coati_payroll/queue/driver.py +127 -0
- coati_payroll/queue/drivers/__init__.py +22 -0
- coati_payroll/queue/drivers/dramatiq_driver.py +268 -0
- coati_payroll/queue/drivers/huey_driver.py +390 -0
- coati_payroll/queue/drivers/noop_driver.py +54 -0
- coati_payroll/queue/selector.py +121 -0
- coati_payroll/queue/tasks.py +764 -0
- coati_payroll/rate_limiting.py +83 -0
- coati_payroll/rbac.py +183 -0
- coati_payroll/report_engine.py +512 -0
- coati_payroll/report_export.py +208 -0
- coati_payroll/schema_validator.py +167 -0
- coati_payroll/security.py +77 -0
- coati_payroll/static/styles.css +1044 -0
- coati_payroll/system_reports.py +573 -0
- coati_payroll/templates/auth/login.html +189 -0
- coati_payroll/templates/base.html +283 -0
- coati_payroll/templates/index.html +227 -0
- coati_payroll/templates/macros.html +146 -0
- coati_payroll/templates/modules/calculation_rule/form.html +78 -0
- coati_payroll/templates/modules/calculation_rule/index.html +102 -0
- coati_payroll/templates/modules/calculation_rule/schema_editor.html +1159 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/form.html +170 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/index.html +170 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/reporte.html +193 -0
- coati_payroll/templates/modules/config_calculos/index.html +44 -0
- coati_payroll/templates/modules/configuracion/index.html +90 -0
- coati_payroll/templates/modules/currency/form.html +47 -0
- coati_payroll/templates/modules/currency/index.html +64 -0
- coati_payroll/templates/modules/custom_field/form.html +62 -0
- coati_payroll/templates/modules/custom_field/index.html +78 -0
- coati_payroll/templates/modules/deduccion/form.html +1 -0
- coati_payroll/templates/modules/deduccion/index.html +1 -0
- coati_payroll/templates/modules/employee/form.html +254 -0
- coati_payroll/templates/modules/employee/index.html +76 -0
- coati_payroll/templates/modules/empresa/form.html +74 -0
- coati_payroll/templates/modules/empresa/index.html +71 -0
- coati_payroll/templates/modules/exchange_rate/form.html +47 -0
- coati_payroll/templates/modules/exchange_rate/import.html +93 -0
- coati_payroll/templates/modules/exchange_rate/index.html +114 -0
- coati_payroll/templates/modules/liquidacion/index.html +58 -0
- coati_payroll/templates/modules/liquidacion/nueva.html +51 -0
- coati_payroll/templates/modules/liquidacion/ver.html +91 -0
- coati_payroll/templates/modules/payroll_concepts/audit_log.html +146 -0
- coati_payroll/templates/modules/percepcion/form.html +1 -0
- coati_payroll/templates/modules/percepcion/index.html +1 -0
- coati_payroll/templates/modules/planilla/config.html +190 -0
- coati_payroll/templates/modules/planilla/config_deducciones.html +129 -0
- coati_payroll/templates/modules/planilla/config_empleados.html +116 -0
- coati_payroll/templates/modules/planilla/config_percepciones.html +113 -0
- coati_payroll/templates/modules/planilla/config_prestaciones.html +118 -0
- coati_payroll/templates/modules/planilla/config_reglas.html +120 -0
- coati_payroll/templates/modules/planilla/ejecutar_nomina.html +106 -0
- coati_payroll/templates/modules/planilla/form.html +197 -0
- coati_payroll/templates/modules/planilla/index.html +144 -0
- coati_payroll/templates/modules/planilla/listar_nominas.html +91 -0
- coati_payroll/templates/modules/planilla/log_nomina.html +135 -0
- coati_payroll/templates/modules/planilla/novedades/form.html +177 -0
- coati_payroll/templates/modules/planilla/novedades/index.html +170 -0
- coati_payroll/templates/modules/planilla/ver_nomina.html +477 -0
- coati_payroll/templates/modules/planilla/ver_nomina_empleado.html +231 -0
- coati_payroll/templates/modules/plugins/index.html +71 -0
- coati_payroll/templates/modules/prestacion/form.html +1 -0
- coati_payroll/templates/modules/prestacion/index.html +1 -0
- coati_payroll/templates/modules/prestacion_management/dashboard.html +150 -0
- coati_payroll/templates/modules/prestacion_management/initial_balance_bulk.html +195 -0
- coati_payroll/templates/modules/prestamo/approve.html +156 -0
- coati_payroll/templates/modules/prestamo/condonacion.html +249 -0
- coati_payroll/templates/modules/prestamo/detail.html +443 -0
- coati_payroll/templates/modules/prestamo/form.html +203 -0
- coati_payroll/templates/modules/prestamo/index.html +150 -0
- coati_payroll/templates/modules/prestamo/pago_extraordinario.html +211 -0
- coati_payroll/templates/modules/prestamo/tabla_pago_pdf.html +181 -0
- coati_payroll/templates/modules/report/admin_index.html +125 -0
- coati_payroll/templates/modules/report/detail.html +129 -0
- coati_payroll/templates/modules/report/execute.html +266 -0
- coati_payroll/templates/modules/report/index.html +95 -0
- coati_payroll/templates/modules/report/permissions.html +64 -0
- coati_payroll/templates/modules/settings/index.html +274 -0
- coati_payroll/templates/modules/shared/concept_form.html +201 -0
- coati_payroll/templates/modules/shared/concept_index.html +145 -0
- coati_payroll/templates/modules/tipo_planilla/form.html +70 -0
- coati_payroll/templates/modules/tipo_planilla/index.html +68 -0
- coati_payroll/templates/modules/user/form.html +65 -0
- coati_payroll/templates/modules/user/index.html +76 -0
- coati_payroll/templates/modules/user/profile.html +81 -0
- coati_payroll/templates/modules/vacation/account_detail.html +149 -0
- coati_payroll/templates/modules/vacation/account_form.html +52 -0
- coati_payroll/templates/modules/vacation/account_index.html +68 -0
- coati_payroll/templates/modules/vacation/dashboard.html +156 -0
- coati_payroll/templates/modules/vacation/initial_balance_bulk.html +149 -0
- coati_payroll/templates/modules/vacation/initial_balance_form.html +93 -0
- coati_payroll/templates/modules/vacation/leave_request_detail.html +158 -0
- coati_payroll/templates/modules/vacation/leave_request_form.html +61 -0
- coati_payroll/templates/modules/vacation/leave_request_index.html +98 -0
- coati_payroll/templates/modules/vacation/policy_detail.html +176 -0
- coati_payroll/templates/modules/vacation/policy_form.html +152 -0
- coati_payroll/templates/modules/vacation/policy_index.html +79 -0
- coati_payroll/templates/modules/vacation/register_taken_form.html +178 -0
- coati_payroll/translations/en/LC_MESSAGES/messages.mo +0 -0
- coati_payroll/translations/en/LC_MESSAGES/messages.po +7283 -0
- coati_payroll/translations/es/LC_MESSAGES/messages.mo +0 -0
- coati_payroll/translations/es/LC_MESSAGES/messages.po +7374 -0
- coati_payroll/vacation_service.py +451 -0
- coati_payroll/version.py +18 -0
- coati_payroll/vistas/__init__.py +64 -0
- coati_payroll/vistas/calculation_rule.py +307 -0
- coati_payroll/vistas/carga_inicial_prestacion.py +423 -0
- coati_payroll/vistas/config_calculos.py +72 -0
- coati_payroll/vistas/configuracion.py +87 -0
- coati_payroll/vistas/constants.py +17 -0
- coati_payroll/vistas/currency.py +112 -0
- coati_payroll/vistas/custom_field.py +120 -0
- coati_payroll/vistas/employee.py +305 -0
- coati_payroll/vistas/empresa.py +153 -0
- coati_payroll/vistas/exchange_rate.py +341 -0
- coati_payroll/vistas/liquidacion.py +205 -0
- coati_payroll/vistas/payroll_concepts.py +580 -0
- coati_payroll/vistas/planilla/__init__.py +38 -0
- coati_payroll/vistas/planilla/association_routes.py +238 -0
- coati_payroll/vistas/planilla/config_routes.py +158 -0
- coati_payroll/vistas/planilla/export_routes.py +175 -0
- coati_payroll/vistas/planilla/helpers/__init__.py +34 -0
- coati_payroll/vistas/planilla/helpers/association_helpers.py +161 -0
- coati_payroll/vistas/planilla/helpers/excel_helpers.py +29 -0
- coati_payroll/vistas/planilla/helpers/form_helpers.py +97 -0
- coati_payroll/vistas/planilla/nomina_routes.py +488 -0
- coati_payroll/vistas/planilla/novedad_routes.py +227 -0
- coati_payroll/vistas/planilla/routes.py +145 -0
- coati_payroll/vistas/planilla/services/__init__.py +26 -0
- coati_payroll/vistas/planilla/services/export_service.py +687 -0
- coati_payroll/vistas/planilla/services/nomina_service.py +233 -0
- coati_payroll/vistas/planilla/services/novedad_service.py +126 -0
- coati_payroll/vistas/planilla/services/planilla_service.py +34 -0
- coati_payroll/vistas/planilla/validators/__init__.py +18 -0
- coati_payroll/vistas/planilla/validators/planilla_validators.py +40 -0
- coati_payroll/vistas/plugins.py +45 -0
- coati_payroll/vistas/prestacion.py +272 -0
- coati_payroll/vistas/prestamo.py +808 -0
- coati_payroll/vistas/report.py +432 -0
- coati_payroll/vistas/settings.py +29 -0
- coati_payroll/vistas/tipo_planilla.py +134 -0
- coati_payroll/vistas/user.py +172 -0
- coati_payroll/vistas/vacation.py +1045 -0
- coati_payroll-0.0.2.dist-info/LICENSE +201 -0
- coati_payroll-0.0.2.dist-info/METADATA +581 -0
- coati_payroll-0.0.2.dist-info/RECORD +243 -0
- coati_payroll-0.0.2.dist-info/WHEEL +5 -0
- coati_payroll-0.0.2.dist-info/entry_points.txt +2 -0
- coati_payroll-0.0.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="es">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
7
|
+
<title>{{ _('Iniciar sesión') }} - Coati Payroll</title>
|
|
8
|
+
|
|
9
|
+
<!-- Google Fonts - Enterprise Typography -->
|
|
10
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
11
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
12
|
+
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
13
|
+
|
|
14
|
+
<!-- Bootstrap (mismo CDN que base) -->
|
|
15
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
16
|
+
|
|
17
|
+
<!-- Bootstrap Icons -->
|
|
18
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
19
|
+
|
|
20
|
+
<!-- App styles -->
|
|
21
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
|
22
|
+
</head>
|
|
23
|
+
|
|
24
|
+
<body class="login-page">
|
|
25
|
+
<div class="login-container">
|
|
26
|
+
<!-- Left side - Branding -->
|
|
27
|
+
<div class="login-branding">
|
|
28
|
+
<div class="branding-content">
|
|
29
|
+
<div class="logo-container">
|
|
30
|
+
<span class="logo-placeholder logo-large"><i class="bi bi-flower1"></i></span>
|
|
31
|
+
</div>
|
|
32
|
+
<div>
|
|
33
|
+
<h1 class="brand-name">Coati <span>Payroll</span></h1>
|
|
34
|
+
<p class="brand-tagline">
|
|
35
|
+
{{ _('Sistema de gestión de nóminas') }}<br>
|
|
36
|
+
{{ _('Agiliza y simplifica el pago de sueldos en su compañía.') }}
|
|
37
|
+
</p>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="brand-features">
|
|
40
|
+
<div class="feature-item">
|
|
41
|
+
<i class="bi bi-building-fill-add"></i>
|
|
42
|
+
<span>{{ _('Multiempresa') }}</span>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="feature-item">
|
|
45
|
+
<i class="bi bi-currency-exchange"></i>
|
|
46
|
+
<span>{{ _('Multimoneda') }}</span>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="feature-item">
|
|
49
|
+
<i class="bi bi-shield-check"></i>
|
|
50
|
+
<span>{{ _('Seguro y confiable') }}</span>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="feature-item">
|
|
53
|
+
<i class="bi bi-speedometer2"></i>
|
|
54
|
+
<span>{{ _('Rápido y eficiente') }}</span>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="feature-item">
|
|
57
|
+
<i class="bi bi-gear-fill"></i>
|
|
58
|
+
<span>{{ _('Configurable') }}</span>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="feature-item">
|
|
61
|
+
<i class="bi bi-shuffle"></i>
|
|
62
|
+
<span>{{ _('Flexible') }}</span>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<!-- Right side - Login Form -->
|
|
69
|
+
<div class="login-form-container">
|
|
70
|
+
<div class="login-form-wrapper">
|
|
71
|
+
<div class="login-header">
|
|
72
|
+
<h2 id="loginTitle">{{ _('Iniciar sesión') }}</h2>
|
|
73
|
+
<p class="login-subtitle">{{ _('Introduce tus credenciales para acceder a tu cuenta.') }}</p>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{%- set flashed = get_flashed_messages(with_categories=true) -%}
|
|
77
|
+
{% if flashed %}
|
|
78
|
+
<div id="errorMsg" class="alert alert-warning" role="alert" aria-live="polite">
|
|
79
|
+
<i class="bi bi-exclamation-triangle me-2"></i>
|
|
80
|
+
{{ flashed[0][1] }}
|
|
81
|
+
</div>
|
|
82
|
+
{% endif %}
|
|
83
|
+
|
|
84
|
+
<form id="loginForm" method="post" action="{{ url_for('auth.login') }}">
|
|
85
|
+
{{ form.hidden_tag() }}
|
|
86
|
+
|
|
87
|
+
<div class="mb-4">
|
|
88
|
+
<label for="{{ form.email.id }}" class="form-label">
|
|
89
|
+
<i class="bi bi-person me-1"></i>
|
|
90
|
+
{{ _('Usuario o correo electrónico') }}
|
|
91
|
+
</label>
|
|
92
|
+
{{ form.email(id='email', class_='form-control form-control-lg', autocomplete='username', placeholder=_('usuario o correo')) }}
|
|
93
|
+
{% if form.email.errors %}
|
|
94
|
+
<div class="form-text text-danger">{{ form.email.errors[0] }}</div>
|
|
95
|
+
{% else %}
|
|
96
|
+
<div class="form-text">
|
|
97
|
+
{{ _('Usa el correo o el nombre de usuario asociado a tu cuenta.') }}</div>
|
|
98
|
+
{% endif %}
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div class="mb-4">
|
|
102
|
+
<label for="{{ form.password.id }}" class="form-label">
|
|
103
|
+
<i class="bi bi-lock me-1"></i>
|
|
104
|
+
{{ _('Contraseña') }}
|
|
105
|
+
</label>
|
|
106
|
+
<div class="input-group">
|
|
107
|
+
{{ form.password(id='password', class_='form-control form-control-lg', autocomplete='current-password', placeholder='••••••••') }}
|
|
108
|
+
<button type="button" id="togglePwd" class="btn btn-outline-secondary"
|
|
109
|
+
aria-label="{{ _('Mostrar u ocultar contraseña') }}" aria-pressed="false">
|
|
110
|
+
<i class="bi bi-eye" id="toggleIcon" aria-hidden="true"></i>
|
|
111
|
+
</button>
|
|
112
|
+
</div>
|
|
113
|
+
{% if form.password.errors %}
|
|
114
|
+
<div class="form-text text-danger">{{ form.password.errors[0] }}</div>
|
|
115
|
+
{% endif %}
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div class="d-grid mb-3">
|
|
119
|
+
{{ form.submit(class_='btn btn-primary btn-lg') }}
|
|
120
|
+
</div>
|
|
121
|
+
</form>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<script>
|
|
127
|
+
// Textos de JS marcados para que Flask-Babel pueda extraerlos
|
|
128
|
+
const TXT_SHOW = "{{ _('Mostrar') }}";
|
|
129
|
+
const TXT_HIDE = "{{ _('Ocultar') }}";
|
|
130
|
+
const ERR_EMAIL = "{{ _('Por favor introduce tu correo.') }}";
|
|
131
|
+
const ERR_PASS = "{{ _('La contraseña debe tener al menos 6 caracteres.') }}";
|
|
132
|
+
const ERR_CONN = "{{ _('No se pudo conectar al servidor.') }}";
|
|
133
|
+
const ERR_LOGIN = "{{ _('Error al iniciar sesión') }}";
|
|
134
|
+
|
|
135
|
+
(function () {
|
|
136
|
+
const pwd = document.getElementById('password');
|
|
137
|
+
const toggle = document.getElementById('togglePwd');
|
|
138
|
+
const toggleIcon = document.getElementById('toggleIcon');
|
|
139
|
+
const form = document.getElementById('loginForm');
|
|
140
|
+
const errorMsg = document.getElementById('errorMsg');
|
|
141
|
+
|
|
142
|
+
toggle.addEventListener('click', () => {
|
|
143
|
+
if (pwd.type === 'password') {
|
|
144
|
+
pwd.type = 'text';
|
|
145
|
+
toggleIcon.classList.remove('bi-eye');
|
|
146
|
+
toggleIcon.classList.add('bi-eye-slash');
|
|
147
|
+
toggle.setAttribute('aria-pressed', 'true');
|
|
148
|
+
} else {
|
|
149
|
+
pwd.type = 'password';
|
|
150
|
+
toggleIcon.classList.remove('bi-eye-slash');
|
|
151
|
+
toggleIcon.classList.add('bi-eye');
|
|
152
|
+
toggle.setAttribute('aria-pressed', 'false');
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
form.addEventListener('submit', (e) => {
|
|
157
|
+
if (errorMsg) {
|
|
158
|
+
errorMsg.style.display = 'none';
|
|
159
|
+
errorMsg.textContent = '';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const email = document.getElementById('email').value.trim();
|
|
163
|
+
const password = pwd.value;
|
|
164
|
+
|
|
165
|
+
if (!email) {
|
|
166
|
+
e.preventDefault();
|
|
167
|
+
showError(ERR_EMAIL);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (password.length < 6) {
|
|
171
|
+
e.preventDefault();
|
|
172
|
+
showError(ERR_PASS);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
function showError(text) {
|
|
178
|
+
if (errorMsg) {
|
|
179
|
+
errorMsg.innerHTML = '<i class="bi bi-exclamation-triangle me-2"></i>' + text;
|
|
180
|
+
errorMsg.style.display = 'block';
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
document.getElementById('email').focus();
|
|
185
|
+
})();
|
|
186
|
+
</script>
|
|
187
|
+
</body>
|
|
188
|
+
|
|
189
|
+
</html>
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="es">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>{{ _('Coaty - Sistema de Planillas') }}</title>
|
|
7
|
+
|
|
8
|
+
<!-- Google Fonts - Enterprise Typography -->
|
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
11
|
+
<link
|
|
12
|
+
href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;600;700&display=swap"
|
|
13
|
+
rel="stylesheet"
|
|
14
|
+
/>
|
|
15
|
+
|
|
16
|
+
<!-- Bootstrap 5 -->
|
|
17
|
+
<link
|
|
18
|
+
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
|
19
|
+
rel="stylesheet"
|
|
20
|
+
/>
|
|
21
|
+
|
|
22
|
+
<!-- Bootstrap Icons -->
|
|
23
|
+
<link
|
|
24
|
+
rel="stylesheet"
|
|
25
|
+
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
|
|
26
|
+
/>
|
|
27
|
+
|
|
28
|
+
<!-- Custom styles -->
|
|
29
|
+
<link
|
|
30
|
+
rel="stylesheet"
|
|
31
|
+
href="{{ url_for('static', filename='styles.css') }}"
|
|
32
|
+
/>
|
|
33
|
+
</head>
|
|
34
|
+
|
|
35
|
+
<body>
|
|
36
|
+
<!-- ======================= NAVBAR SUPERIOR ======================= -->
|
|
37
|
+
<nav class="navbar navbar-expand-lg navbar-dark bg-coaty-dark px-3">
|
|
38
|
+
<!-- Botón hamburguesa para abrir sidebar en pantallas pequeñas -->
|
|
39
|
+
<button
|
|
40
|
+
class="btn sidebar-toggle-btn d-lg-none me-2"
|
|
41
|
+
id="sidebarToggleMobile"
|
|
42
|
+
aria-label="Toggle sidebar"
|
|
43
|
+
>
|
|
44
|
+
<span class="navbar-toggler-icon"></span>
|
|
45
|
+
</button>
|
|
46
|
+
|
|
47
|
+
<a
|
|
48
|
+
class="navbar-brand fw-bold text-uppercase"
|
|
49
|
+
href="{{ url_for('app.index') }}"
|
|
50
|
+
>
|
|
51
|
+
<!-- Logo placeholder - reemplazar con logo real posteriormente -->
|
|
52
|
+
<span class="logo-placeholder"
|
|
53
|
+
><i class="bi bi-flower1"></i
|
|
54
|
+
></span>
|
|
55
|
+
<span
|
|
56
|
+
>{{ _('Coati') }}
|
|
57
|
+
<span class="fw-normal">Payroll</span></span
|
|
58
|
+
>
|
|
59
|
+
</a>
|
|
60
|
+
|
|
61
|
+
<!-- Navbar items - visible en pantallas grandes -->
|
|
62
|
+
<div
|
|
63
|
+
class="navbar-collapse justify-content-end d-none d-lg-flex"
|
|
64
|
+
id="topNav"
|
|
65
|
+
>
|
|
66
|
+
<ul class="navbar-nav flex-row gap-2 mb-0">
|
|
67
|
+
<li class="nav-item">
|
|
68
|
+
<a
|
|
69
|
+
class="nav-link"
|
|
70
|
+
href="{{ url_for('user.profile') }}"
|
|
71
|
+
>
|
|
72
|
+
<i class="bi bi-person-circle"></i>
|
|
73
|
+
{{ _('Mi Perfil') }}
|
|
74
|
+
</a>
|
|
75
|
+
</li>
|
|
76
|
+
<li class="nav-item">
|
|
77
|
+
<a class="nav-link" href="{{ url_for('auth.logout') }}">
|
|
78
|
+
<i class="bi bi-box-arrow-right"></i>
|
|
79
|
+
{{ _('Cerrar Sesión') }}
|
|
80
|
+
</a>
|
|
81
|
+
</li>
|
|
82
|
+
</ul>
|
|
83
|
+
</div>
|
|
84
|
+
</nav>
|
|
85
|
+
|
|
86
|
+
<!-- ======================= LAYOUT PRINCIPAL ======================= -->
|
|
87
|
+
<div class="d-flex">
|
|
88
|
+
<!-- ======================= SIDEBAR ======================= -->
|
|
89
|
+
<aside id="sidebar" class="sidebar bg-coaty-light">
|
|
90
|
+
<!-- Sidebar header with logo -->
|
|
91
|
+
<div class="sidebar-header">
|
|
92
|
+
<div class="brand-title">
|
|
93
|
+
<span class="logo-placeholder"
|
|
94
|
+
><i class="bi bi-flower1"></i
|
|
95
|
+
></span>
|
|
96
|
+
{{ _('Coati Payroll') }}
|
|
97
|
+
</div>
|
|
98
|
+
<div class="brand-subtitle">
|
|
99
|
+
{{ _('Sistema de Planillas') }}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<ul class="nav flex-column">
|
|
104
|
+
<!-- Inicio -->
|
|
105
|
+
<li class="nav-item">
|
|
106
|
+
<a
|
|
107
|
+
class="nav-link d-flex align-items-center"
|
|
108
|
+
href="{{ url_for('app.index') }}"
|
|
109
|
+
>
|
|
110
|
+
<i class="bi bi-house me-2"></i
|
|
111
|
+
><span><span>{{ _('Inicio') }}</span></span>
|
|
112
|
+
</a>
|
|
113
|
+
</li>
|
|
114
|
+
|
|
115
|
+
<!-- Empresas -->
|
|
116
|
+
<li class="nav-item">
|
|
117
|
+
<a
|
|
118
|
+
class="nav-link d-flex align-items-center"
|
|
119
|
+
href="{{ url_for('empresa.index') }}"
|
|
120
|
+
>
|
|
121
|
+
<i class="bi bi-building-fill"></i
|
|
122
|
+
><span><span>{{ _('Empresas') }}</span></span>
|
|
123
|
+
</a>
|
|
124
|
+
</li>
|
|
125
|
+
|
|
126
|
+
<!-- Planillas -->
|
|
127
|
+
<li class="nav-item">
|
|
128
|
+
<a
|
|
129
|
+
class="nav-link d-flex align-items-center"
|
|
130
|
+
href="{{ url_for('planilla.index') }}"
|
|
131
|
+
>
|
|
132
|
+
<i class="bi bi-calculator me-2"></i
|
|
133
|
+
><span><span>{{ _('Planillas') }}</span></span>
|
|
134
|
+
</a>
|
|
135
|
+
</li>
|
|
136
|
+
|
|
137
|
+
<li class="nav-item">
|
|
138
|
+
<a class="nav-link d-flex align-items-center" href="{{ url_for('liquidacion.index') }}">
|
|
139
|
+
<i class="bi bi-file-earmark-text me-2"></i
|
|
140
|
+
><span><span>{{ _('Liquidaciones') }}</span></span>
|
|
141
|
+
</a>
|
|
142
|
+
</li>
|
|
143
|
+
|
|
144
|
+
<!-- Empleados -->
|
|
145
|
+
<li class="nav-item">
|
|
146
|
+
<a
|
|
147
|
+
class="nav-link d-flex align-items-center"
|
|
148
|
+
href="{{ url_for('employee.index') }}"
|
|
149
|
+
>
|
|
150
|
+
<i class="bi bi-people me-2"></i
|
|
151
|
+
><span><span>{{ _('Empleados') }}</span></span>
|
|
152
|
+
</a>
|
|
153
|
+
</li>
|
|
154
|
+
|
|
155
|
+
<!-- Vacaciones -->
|
|
156
|
+
<li class="nav-item">
|
|
157
|
+
<a
|
|
158
|
+
class="nav-link d-flex align-items-center"
|
|
159
|
+
href="{{ url_for('vacation.dashboard') }}"
|
|
160
|
+
>
|
|
161
|
+
<i class="bi bi-calendar-check me-2"></i
|
|
162
|
+
><span><span>{{ _('Vacaciones') }}</span></span>
|
|
163
|
+
</a>
|
|
164
|
+
</li>
|
|
165
|
+
|
|
166
|
+
<!-- Prestaciones -->
|
|
167
|
+
<li class="nav-item">
|
|
168
|
+
<a
|
|
169
|
+
class="nav-link d-flex align-items-center"
|
|
170
|
+
href="{{ url_for('prestacion_management.dashboard') }}"
|
|
171
|
+
>
|
|
172
|
+
<i class="bi bi-gift me-2"></i
|
|
173
|
+
><span><span>{{ _('Prestaciones') }}</span></span>
|
|
174
|
+
</a>
|
|
175
|
+
</li>
|
|
176
|
+
|
|
177
|
+
<!-- Préstamos -->
|
|
178
|
+
<li class="nav-item">
|
|
179
|
+
<a
|
|
180
|
+
class="nav-link d-flex align-items-center"
|
|
181
|
+
href="{{ url_for('prestamo.index') }}"
|
|
182
|
+
>
|
|
183
|
+
<i class="bi bi-cash-coin me-2"></i
|
|
184
|
+
><span><span>{{ _('Préstamos') }}</span></span>
|
|
185
|
+
</a>
|
|
186
|
+
</li>
|
|
187
|
+
|
|
188
|
+
<!-- Usuarios -->
|
|
189
|
+
<li class="nav-item">
|
|
190
|
+
<a
|
|
191
|
+
class="nav-link d-flex align-items-center"
|
|
192
|
+
href="{{ url_for('user.index') }}"
|
|
193
|
+
>
|
|
194
|
+
<i class="bi bi-person-gear me-2"></i
|
|
195
|
+
><span><span>{{ _('Usuarios') }}</span></span>
|
|
196
|
+
</a>
|
|
197
|
+
</li>
|
|
198
|
+
|
|
199
|
+
{% for active_plugin in plugin_actives %}
|
|
200
|
+
<li class="nav-item">
|
|
201
|
+
<a class="nav-link d-flex align-items-center" href="{{ active_plugin.url }}">
|
|
202
|
+
<i class="{{ active_plugin.icon or 'bi bi-puzzle' }} me-2"></i
|
|
203
|
+
><span><span>{{ active_plugin.label }}</span></span>
|
|
204
|
+
</a>
|
|
205
|
+
</li>
|
|
206
|
+
{% endfor %}
|
|
207
|
+
|
|
208
|
+
<!-- Configuración -->
|
|
209
|
+
<li class="nav-item">
|
|
210
|
+
<a
|
|
211
|
+
class="nav-link d-flex align-items-center"
|
|
212
|
+
href="{{ url_for('settings.index') }}"
|
|
213
|
+
>
|
|
214
|
+
<i class="bi bi-gear me-2"></i
|
|
215
|
+
><span><span>{{ _('Configuración') }}</span></span>
|
|
216
|
+
</a>
|
|
217
|
+
</li>
|
|
218
|
+
</ul>
|
|
219
|
+
|
|
220
|
+
<!-- Mobile-only links: Profile and Logout (shown only on small screens) -->
|
|
221
|
+
<div class="mobile-only-links">
|
|
222
|
+
<ul class="nav flex-column">
|
|
223
|
+
<li class="nav-item">
|
|
224
|
+
<a
|
|
225
|
+
class="nav-link d-flex align-items-center"
|
|
226
|
+
href="{{ url_for('user.profile') }}"
|
|
227
|
+
>
|
|
228
|
+
<i class="bi bi-person-circle me-2"></i>
|
|
229
|
+
<span>{{ _('Mi Perfil') }}</span>
|
|
230
|
+
</a>
|
|
231
|
+
</li>
|
|
232
|
+
<li class="nav-item">
|
|
233
|
+
<a
|
|
234
|
+
class="nav-link d-flex align-items-center"
|
|
235
|
+
href="{{ url_for('auth.logout') }}"
|
|
236
|
+
>
|
|
237
|
+
<i class="bi bi-box-arrow-right me-2"></i>
|
|
238
|
+
<span>{{ _('Cerrar Sesión') }}</span>
|
|
239
|
+
</a>
|
|
240
|
+
</li>
|
|
241
|
+
</ul>
|
|
242
|
+
</div>
|
|
243
|
+
</aside>
|
|
244
|
+
|
|
245
|
+
<!-- ======================= CONTENIDO DINÁMICO ======================= -->
|
|
246
|
+
<main class="flex-grow-1 p-4">
|
|
247
|
+
{% block content %}
|
|
248
|
+
<h2>{{ _('Bienvenido a Coaty') }}</h2>
|
|
249
|
+
<p>{{ _('Sistema de Planillas (Payroll)') }}</p>
|
|
250
|
+
{% endblock %}
|
|
251
|
+
</main>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<!-- Bootstrap JS -->
|
|
255
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
256
|
+
|
|
257
|
+
<!-- Sidebar Toggle Script -->
|
|
258
|
+
<script>
|
|
259
|
+
document
|
|
260
|
+
.getElementById("sidebarToggleMobile")
|
|
261
|
+
.addEventListener("click", function () {
|
|
262
|
+
document.getElementById("sidebar").classList.toggle("open");
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Close sidebar when clicking outside of it on mobile
|
|
266
|
+
document.addEventListener("click", function (event) {
|
|
267
|
+
const sidebar = document.getElementById("sidebar");
|
|
268
|
+
const toggleBtn = document.getElementById(
|
|
269
|
+
"sidebarToggleMobile",
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
if (
|
|
273
|
+
window.innerWidth < 992 &&
|
|
274
|
+
sidebar.classList.contains("open") &&
|
|
275
|
+
!sidebar.contains(event.target) &&
|
|
276
|
+
!toggleBtn.contains(event.target)
|
|
277
|
+
) {
|
|
278
|
+
sidebar.classList.remove("open");
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
</script>
|
|
282
|
+
</body>
|
|
283
|
+
</html>
|