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 app.py .
|
||||
COPY templates/ ./templates/
|
||||
#COPY static/ ./static/
|
||||
COPY static/ ./static/
|
||||
#COPY .env .
|
||||
|
||||
# Create the folder structure for the volume mounts
|
||||
|
||||
55
README.md
55
README.md
@@ -1,2 +1,57 @@
|
||||
# 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.secret_key = "super_secret_dev_key"
|
||||
DB_NAME = "rendiciones.db"
|
||||
DB_NAME = "db/rendiciones.db"
|
||||
|
||||
# --- 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 %}
|
||||
<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 %}
|
||||
|
||||
<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 %}
|
||||
<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 %}
|
||||
<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 %}
|
||||
<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 %}
|
||||
<div class="row justify-content-center">
|
||||
<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 %}
|
||||
<div class="row justify-content-center">
|
||||
<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 %}
|
||||
<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="card shadow">
|
||||
<div class="card-header bg-primary text-white text-center py-3">
|
||||
@@ -18,7 +21,13 @@
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<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 class="mb-4">
|
||||
<label class="form-label">Contraseña</label>
|
||||
@@ -30,7 +39,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
document.getElementById('rutInput').addEventListener('input', function(e) {
|
||||
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">
|
||||
<a class="navbar-brand" href="#">Rendiciones App</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
@@ -26,12 +26,26 @@
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<span class="nav-link text-muted">RUT: {{ session.get('rut', 'Admin') }}</span>
|
||||
<li class="nav-item dropdown">
|
||||
<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 class="nav-item">
|
||||
<a class="nav-link text-danger" href="{{ url_for('logout') }}">Cerrar Sesión</a>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<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>
|
||||
</ul>
|
||||
{% 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 %}
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
|
||||
Reference in New Issue
Block a user