refactor + macro fixes + theme system
This commit is contained in:
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Build rendiciones (F5)",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build-rendiciones"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"python-envs.defaultEnvManager": "ms-python.python:pyenv"
|
||||||
|
}
|
||||||
15
.vscode/tasks.json
vendored
Normal file
15
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "build-rendiciones",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker build -t rendiciones:latest .",
|
||||||
|
"group": "build",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "new"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|||||||
# Copy source code
|
# Copy source code
|
||||||
COPY app.py .
|
COPY app.py .
|
||||||
COPY templates/ ./templates/
|
COPY templates/ ./templates/
|
||||||
#COPY static/ ./static/
|
COPY static/ ./static/
|
||||||
#COPY .env .
|
#COPY .env .
|
||||||
|
|
||||||
# Create the folder structure for the volume mounts
|
# Create the folder structure for the volume mounts
|
||||||
|
|||||||
55
README.md
55
README.md
@@ -1,2 +1,57 @@
|
|||||||
# Rendiciones-App
|
# Rendiciones-App
|
||||||
|
|
||||||
|
## 🐳 Docker Deployment (Server)
|
||||||
|
|
||||||
|
Build and run the central inventory server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build the image
|
||||||
|
docker build -t rendiciones:latest .
|
||||||
|
|
||||||
|
# Run the container (Map port 5000 and persist the database/cache)
|
||||||
|
docker run -d \
|
||||||
|
-p 5000:5000 \
|
||||||
|
-v $(pwd)/rendiciones/db:/app/db \
|
||||||
|
-v $(pwd)/rendiciones/static/cache:/app/static/cache \
|
||||||
|
--name rendiciones-server \
|
||||||
|
--restart unless-stopped \
|
||||||
|
rendiciones:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use this stack:
|
||||||
|
```yml
|
||||||
|
name: rendiciones
|
||||||
|
services:
|
||||||
|
rendiciones:
|
||||||
|
ports:
|
||||||
|
- 5000:5000
|
||||||
|
volumes:
|
||||||
|
- YOUR_PATH/rendiciones/db:/app/db
|
||||||
|
- YOUR_PATH/serendicionesipos/static/cache:/app/static/cache
|
||||||
|
container_name: rendiciones-server
|
||||||
|
image: rendiciones:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
# TODO general:
|
||||||
|
- separar productos para tiendas
|
||||||
|
- limpiar requirements.txt
|
||||||
|
- hacer prompts mas bonitos y estandar
|
||||||
|
|
||||||
|
# TODO peppermint:
|
||||||
|
## formulario
|
||||||
|
- añadir total ventas (todos los medios de pago)
|
||||||
|
- total tarjetas + mp
|
||||||
|
- cantidad de boletas por metodod de pago
|
||||||
|
- añadir segunda persona a cargo
|
||||||
|
- verificar que todos los campos esten rellenos
|
||||||
|
- separar credito y debito
|
||||||
|
- permitir subir foto de total gastos (boleta/factura)
|
||||||
|
## otros
|
||||||
|
- bloquear turno para otra persona si ya fue subido por otra persona
|
||||||
|
- part time hora entrada y salida sin comisiones
|
||||||
|
- ocaciones especiales permiten comisiones (en panel admin)
|
||||||
|
|
||||||
|
# TODO happy candy:
|
||||||
|
- total vendido
|
||||||
|
- comision 2%
|
||||||
2
app.py
2
app.py
@@ -9,7 +9,7 @@ from datetime import date
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = "super_secret_dev_key"
|
app.secret_key = "super_secret_dev_key"
|
||||||
DB_NAME = "rendiciones.db"
|
DB_NAME = "db/rendiciones.db"
|
||||||
|
|
||||||
# --- Database & Helpers ---
|
# --- Database & Helpers ---
|
||||||
|
|
||||||
|
|||||||
2
db/.gitignore
vendored
Normal file
2
db/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
BIN
rendiciones.db
BIN
rendiciones.db
Binary file not shown.
2
static/cache/.gitignore
vendored
Normal file
2
static/cache/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
17
static/cookieStuff.js
Normal file
17
static/cookieStuff.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
function setCookie(name, value, days = 365) {
|
||||||
|
const d = new Date();
|
||||||
|
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||||
|
let expires = "expires=" + d.toUTCString();
|
||||||
|
document.cookie = name + "=" + value + ";" + expires + ";path=/;SameSite=Lax";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie(name) {
|
||||||
|
let nameEQ = name + "=";
|
||||||
|
let ca = document.cookie.split(';');
|
||||||
|
for (let i = 0; i < ca.length; i++) {
|
||||||
|
let c = ca[i];
|
||||||
|
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||||
|
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
BIN
static/favicon.png
Normal file
BIN
static/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
39
static/themeStuff.js
Normal file
39
static/themeStuff.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
function applyTheme(t) {
|
||||||
|
document.documentElement.setAttribute('data-bs-theme', t);
|
||||||
|
localStorage.setItem('theme', t);
|
||||||
|
|
||||||
|
const isDark = (t === 'dark');
|
||||||
|
const themeIcon = document.getElementById('theme-icon');
|
||||||
|
const themeLabel = document.getElementById('theme-label');
|
||||||
|
|
||||||
|
if (themeIcon) {
|
||||||
|
themeIcon.className = isDark ? 'bi bi-sun me-2' : 'bi bi-moon-stars me-2';
|
||||||
|
}
|
||||||
|
if (themeLabel) {
|
||||||
|
themeLabel.innerText = isDark ? 'Modo Claro' : 'Modo Oscuro';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleTheme() {
|
||||||
|
const current = document.documentElement.getAttribute('data-bs-theme');
|
||||||
|
applyTheme(current === 'dark' ? 'light' : 'dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
function initTheme() {
|
||||||
|
const savedTheme = localStorage.getItem('theme');
|
||||||
|
if (savedTheme) {
|
||||||
|
applyTheme(savedTheme);
|
||||||
|
} else {
|
||||||
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
applyTheme(prefersDark ? 'dark' : 'light');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for system theme changes only if the user hasn't set a manual override
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
|
||||||
|
if (!localStorage.getItem('theme')) {
|
||||||
|
applyTheme(e.matches ? 'dark' : 'light');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
initTheme();
|
||||||
@@ -1,4 +1,13 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Catálogo de Productos{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<!-- HEAD -->
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2 class="mb-4">Catálogo de Productos por Zona</h2>
|
<h2 class="mb-4">Catálogo de Productos por Zona</h2>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Detalle de Rendición{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<!-- HEAD -->
|
||||||
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Historial de Rendiciones{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<!-- HEAD -->
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2 class="mb-4">Historial de Rendiciones</h2>
|
<h2 class="mb-4">Historial de Rendiciones</h2>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Estructura Operativa{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<!-- HEAD -->
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2 class="mb-4">Estructura Operativa</h2>
|
<h2 class="mb-4">Estructura Operativa</h2>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Gestión de Trabajadores{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<!-- HEAD -->
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2 class="mb-4">Gestión de Trabajadores</h2>
|
<h2 class="mb-4">Gestión de Trabajadores</h2>
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="es" data-bs-theme="dark">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Sistema de Rendiciones</title>
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
{% include 'navbar.html' %}
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,4 +1,12 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Editar Producto{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<!-- HEAD -->
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Editar Trabajador{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<!-- HEAD -->
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Inicio de sesión{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row justify-content-center mt-5">
|
<div class="d-flex align-items-center justify-content-center vh-100">
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<div class="card shadow">
|
<div class="card shadow">
|
||||||
<div class="card-header bg-primary text-white text-center py-3">
|
<div class="card-header bg-primary text-white text-center py-3">
|
||||||
@@ -18,7 +21,13 @@
|
|||||||
<form method="POST">
|
<form method="POST">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">RUT</label>
|
<label class="form-label">RUT</label>
|
||||||
<input type="text" class="form-control" name="rut" id="rutInput" placeholder="12.345.678-9" required autofocus>
|
<input type="text"
|
||||||
|
class="form-control"
|
||||||
|
name="rut"
|
||||||
|
id="rutInput"
|
||||||
|
placeholder="12.345.678-9"
|
||||||
|
required
|
||||||
|
autofocus>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label class="form-label">Contraseña</label>
|
<label class="form-label">Contraseña</label>
|
||||||
@@ -30,7 +39,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('rutInput').addEventListener('input', function(e) {
|
document.getElementById('rutInput').addEventListener('input', function(e) {
|
||||||
let value = this.value.replace(/[^0-9kK]/g, '').toUpperCase();
|
let value = this.value.replace(/[^0-9kK]/g, '').toUpperCase();
|
||||||
|
|||||||
27
templates/macros/base.html
Normal file
27
templates/macros/base.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="es" data-bs-theme="dark">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Sistema de Rendiciones - {% block title %}{% endblock %}</title>
|
||||||
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.png') }}" type="image/x-icon">
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% if session.get('user_id') %}
|
||||||
|
{% include 'macros/navbar.html' %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<main class="container-fluid px-3">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="{{ url_for('static', filename='cookieStuff.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='themeStuff.js') }}"></script>
|
||||||
|
|
||||||
|
{% block scripts %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark border-bottom mb-4">
|
<nav class="navbar navbar-expand-lg border-bottom mb-4">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand" href="#">Rendiciones App</a>
|
<a class="navbar-brand" href="#">Rendiciones App</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
@@ -26,12 +26,26 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul class="navbar-nav">
|
<ul class="navbar-nav">
|
||||||
<li class="nav-item">
|
<li class="nav-item dropdown">
|
||||||
<span class="nav-link text-muted">RUT: {{ session.get('rut', 'Admin') }}</span>
|
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-person-circle me-1"></i> {{ session.get('rut', 'Admin') }}
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
|
||||||
|
<li>
|
||||||
|
<button class="dropdown-item d-flex align-items-center" onclick="toggleTheme()">
|
||||||
|
<i id="theme-icon" class="bi bi-sun me-2"></i>
|
||||||
|
<span id="theme-label">Modo Claro</span>
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li><hr class="dropdown-divider"></li>
|
||||||
<a class="nav-link text-danger" href="{{ url_for('logout') }}">Cerrar Sesión</a>
|
<li>
|
||||||
|
<a class="dropdown-item text-danger d-flex align-items-center" href="{{ url_for('logout') }}">
|
||||||
|
<i class="bi bi-box-arrow-right me-2"></i> Cerrar Sesión
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -1,4 +1,12 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "macros/base.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Rendición de Caja{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<!-- HEAD -->
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user