actualizado 3-sept
This commit is contained in:
@@ -1,24 +1,34 @@
|
||||
import sqlite3
|
||||
import os
|
||||
import io
|
||||
from flask import Flask, render_template, session, request, redirect, url_for, g, flash, send_file, jsonify
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from functools import wraps
|
||||
from datetime import datetime, timedelta
|
||||
import unicodedata
|
||||
|
||||
from werkzeug.utils import secure_filename
|
||||
from werkzeug.exceptions import RequestEntityTooLarge
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = 'clave-secreta-navbar-app'
|
||||
# Límite máximo de subida: 5 MiB
|
||||
# app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
|
||||
|
||||
DATABASE = 'database/pyfleet.db'
|
||||
|
||||
PASSWORD_HASH = generate_password_hash('123')
|
||||
|
||||
|
||||
# Duración de inactividad máxima
|
||||
SESSION_TIMEOUT = timedelta(hours=4)
|
||||
|
||||
UPLOAD_FOLDER = 'uploads/documentos'
|
||||
ALLOWED_EXTENSIONS = {'pdf'}
|
||||
|
||||
|
||||
# ── Auth ─────────────────────────────────────────────────────
|
||||
|
||||
|
||||
def login_required(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
@@ -66,10 +76,30 @@ def logout():
|
||||
session.clear()
|
||||
return redirect(url_for('login'))
|
||||
|
||||
|
||||
# ── Funcion normalizar ───────────────────────────────────────────
|
||||
|
||||
def normalizar(texto):
|
||||
# if texto is None:
|
||||
# return ''
|
||||
texto = str(texto).strip().lower()
|
||||
|
||||
# Quitar tildes
|
||||
texto = unicodedata.normalize('NFD', texto)
|
||||
texto = ''.join(
|
||||
c for c in texto
|
||||
if unicodedata.category(c) != 'Mn'
|
||||
)
|
||||
|
||||
texto = ' '.join(texto.split()) # Convertir varios espacios seguidos en uno
|
||||
|
||||
return texto
|
||||
|
||||
# ── DB helpers ────────────────────────────────────────────────
|
||||
def get_db():
|
||||
if 'db' not in g:
|
||||
g.db = sqlite3.connect(DATABASE)
|
||||
g.db.create_function("NORM", 1, normalizar)
|
||||
g.db.row_factory = sqlite3.Row
|
||||
return g.db
|
||||
|
||||
@@ -80,63 +110,24 @@ def close_db(e=None):
|
||||
|
||||
def init_db():
|
||||
db = sqlite3.connect(DATABASE)
|
||||
|
||||
# ... tablas existentes ...
|
||||
db.create_function("NORM", 1, normalizar)
|
||||
# db.commit()
|
||||
# db.close()
|
||||
|
||||
# ... tablas existentes ...
|
||||
db.execute('''
|
||||
CREATE TABLE IF NOT EXISTS mensajes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
texto TEXT NOT NULL,
|
||||
autor TEXT,
|
||||
fecha DATETIME DEFAULT (datetime('now','localtime'))
|
||||
CREATE TABLE IF NOT EXISTS documentos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
vehiculo_id INTEGER NOT NULL REFERENCES vehiculos(id) ON DELETE CASCADE,
|
||||
nombre TEXT,
|
||||
filename TEXT NOT NULL,
|
||||
fecha DATETIME DEFAULT (datetime('now','localtime'))
|
||||
)
|
||||
''')
|
||||
|
||||
|
||||
db.execute('''
|
||||
CREATE TABLE IF NOT EXISTS vehiculos (
|
||||
"id" INTEGER,
|
||||
"m_oficial" TEXT,
|
||||
"m_civil" TEXT,
|
||||
"m_propia" TEXT,
|
||||
"VIN" TEXT,
|
||||
"poliza" TEXT,
|
||||
"viat" TEXT,
|
||||
"legajo" TEXT,
|
||||
"marca" TEXT,
|
||||
"modelo" TEXT,
|
||||
"tipo" TEXT,
|
||||
"denominacion" TEXT,
|
||||
"color" TEXT,
|
||||
"cilindrada" TEXT,
|
||||
"potencia" TEXT,
|
||||
"combustible" TEXT,
|
||||
"neumaticos" TEXT,
|
||||
"plazas" TEXT,
|
||||
"situacion" TEXT,
|
||||
"poblacion" TEXT,
|
||||
"unidad" TEXT,
|
||||
"grupo" TEXT,
|
||||
"int_grupo" TEXT,
|
||||
"int_juzgado" TEXT,
|
||||
"int_procedimiento" INTEGER,
|
||||
"f_destino_situacion" TEXT,
|
||||
"f_alta" TEXT,
|
||||
"f_baja" INTEGER,
|
||||
"km" TEXT,
|
||||
"km_1" TEXT,
|
||||
"itv_ultima" TEXT,
|
||||
"itv" TEXT,
|
||||
"observaciones" TEXT,
|
||||
"historial" TEXT,
|
||||
"notas" TEXT,
|
||||
PRIMARY KEY("id" AUTOINCREMENT)
|
||||
)
|
||||
|
||||
''')
|
||||
|
||||
db.commit()
|
||||
db.close()
|
||||
|
||||
|
||||
# ── Rutas generales ───────────────────────────────────────────
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@@ -217,53 +208,66 @@ def vehiculos_list():
|
||||
if 'incl_bajas' in request.args:
|
||||
incl_bajas = request.args.get('incl_bajas') == '1'
|
||||
session['incl_bajas'] = incl_bajas
|
||||
else:
|
||||
# Si no viene en la URL, recuperamos el último estado
|
||||
else: # Si no viene en la URL, recuperamos el último estado
|
||||
incl_bajas = session.get('incl_bajas', False)
|
||||
|
||||
|
||||
terminos = [t.strip() for t in q.split(',') if t.strip()] if q else []
|
||||
|
||||
# Filtro base de bajas
|
||||
filtro_bajas = '' if incl_bajas else "AND (situacion IS NULL OR UPPER(situacion) != 'BAJA')"
|
||||
|
||||
|
||||
|
||||
# OPCION 1. BAJAS SOLO MUESTRA BAJAS
|
||||
|
||||
if terminos:
|
||||
condiciones = []
|
||||
params = []
|
||||
|
||||
for t in terminos:
|
||||
like = f'%{t}%'
|
||||
t_norm = normalizar(t)
|
||||
|
||||
if t_norm == 'lanzadestellos':
|
||||
condiciones.append('lanzadestellos = 1')
|
||||
continue
|
||||
|
||||
like = f'%{t_norm}%'
|
||||
condiciones.append('''(
|
||||
m_oficial LIKE ? OR m_civil LIKE ? OR VIN LIKE ?
|
||||
OR marca LIKE ? OR modelo LIKE ? OR poblacion LIKE ?
|
||||
OR unidad LIKE ? OR grupo LIKE ? OR tipo LIKE ?
|
||||
OR situacion LIKE ? OR int_operacion LIKE ?
|
||||
NORM(m_oficial) LIKE ? OR
|
||||
NORM(m_reservada) LIKE ? OR
|
||||
NORM(VIN) LIKE ? OR
|
||||
NORM(marca) LIKE ? OR
|
||||
NORM(modelo) LIKE ? OR
|
||||
NORM(poblacion) LIKE ? OR
|
||||
NORM(unidad) LIKE ? OR
|
||||
NORM(denominacion) LIKE ? OR
|
||||
NORM(situacion) LIKE ?
|
||||
)''')
|
||||
|
||||
params.extend([like] * 11)
|
||||
params.extend([like] * 9)
|
||||
|
||||
where = ' AND '.join(condiciones)
|
||||
|
||||
rows = db.execute(
|
||||
f'SELECT id, m_oficial, m_civil, marca, modelo, poblacion, unidad, grupo, tipo, situacion FROM vehiculos WHERE {where} {filtro_bajas} ORDER BY id',
|
||||
f'''SELECT id, m_oficial, m_reservada, marca, modelo, poblacion, unidad,
|
||||
denominacion, tipo, situacion, lanzadestellos
|
||||
FROM vehiculos
|
||||
WHERE {where} {filtro_bajas}
|
||||
ORDER BY id''',
|
||||
params
|
||||
).fetchall()
|
||||
|
||||
else: # PARA QUE LA LISTA SALGA EN BLANCO INICIALMENTE
|
||||
rows = []
|
||||
# else:
|
||||
# rows = db.execute(
|
||||
# '''SELECT id, m_oficial, m_civil, marca, modelo, poblacion, unidad, tipo, tipo, situacion
|
||||
# FROM vehiculos
|
||||
# WHERE situacion IS NULL OR UPPER(situacion) != 'BAJA'
|
||||
# ORDER BY id'''
|
||||
# ).fetchall()
|
||||
|
||||
rows = []
|
||||
# else:
|
||||
# rows = db.execute(
|
||||
# '''SELECT id, m_oficial, m_reservada, marca, modelo, poblacion, unidad, tipo, tipo, situacion
|
||||
# FROM vehiculos
|
||||
# WHERE situacion IS NULL OR UPPER(situacion) != 'BAJA'
|
||||
# ORDER BY id'''
|
||||
# ).fetchall()
|
||||
|
||||
|
||||
if solo_filas:
|
||||
return render_template('vehiculos/rows.html', rows=rows, q=q, incl_bajas=incl_bajas)
|
||||
return render_template('vehiculos/list.html', page='vehiculos', rows=rows, q=q, incl_bajas=incl_bajas)
|
||||
|
||||
|
||||
|
||||
|
||||
@app.route('/vehiculos/nuevo', methods=['GET', 'POST'])
|
||||
@@ -282,15 +286,14 @@ def vehiculos_nuevo():
|
||||
|
||||
cursor = db.execute('''
|
||||
INSERT INTO vehiculos (
|
||||
m_oficial, m_civil, m_propia, VIN, poliza, viat, legajo, marca, modelo,
|
||||
tipo, color, cilindrada, potencia, combustible, neumaticos, plazas, lanzadestellos
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
m_oficial, m_reservada, m_propia, VIN, poliza, viat, legajo, marca, modelo,
|
||||
tipo, color, combustible, plazas, lanzadestellos
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
''', (
|
||||
f.get('m_oficial'), f.get('m_civil'), f.get('m_propia'), f.get('VIN'),
|
||||
f.get('m_oficial'), f.get('m_reservada'), f.get('m_propia'), f.get('VIN'),
|
||||
f.get('poliza'), f.get('viat'), f.get('legajo') or None,
|
||||
f.get('marca'), f.get('modelo'), f.get('tipo'), f.get('color'),
|
||||
f.get('cilindrada'), f.get('potencia') or None, f.get('combustible'),
|
||||
f.get('neumaticos'), f.get('plazas'), lanzadestellos
|
||||
f.get('combustible'), f.get('plazas'), lanzadestellos
|
||||
))
|
||||
# nuevo_id = cursor.lastrowid
|
||||
db.commit()
|
||||
@@ -347,15 +350,15 @@ def vehiculos_editar(id):
|
||||
|
||||
db.execute('''
|
||||
UPDATE vehiculos SET
|
||||
m_oficial=?, m_civil=?, m_propia=?, VIN=?, poliza=?, viat=?, legajo=?,
|
||||
marca=?, modelo=?, tipo=?, color=?, cilindrada=?, potencia=?, combustible=?, neumaticos=?, plazas=?, lanzadestellos=?,
|
||||
m_oficial=?, m_reservada=?, m_propia=?, VIN=?, poliza=?, viat=?, legajo=?,
|
||||
marca=?, modelo=?, tipo=?, color=?, combustible=?, plazas=?, lanzadestellos=?,
|
||||
situacion=?, poblacion=?, unidad=?,
|
||||
int_operacion=?, int_grupo=?, int_juzgado=?, int_procedimiento=?,
|
||||
km=?, km_1=?, itv_ultima=?, itv=?, notas=?
|
||||
WHERE id=?
|
||||
''', (
|
||||
f.get('m_oficial'), f.get('m_civil'), f.get('m_propia'), f.get('VIN'), f.get('poliza'), f.get('viat') or '', f.get('legajo') or None,
|
||||
f.get('marca'), f.get('modelo'), f.get('tipo'), f.get('color'), f.get('cilindrada'), f.get('potencia') or None, f.get('combustible'), f.get('neumaticos'), f.get('plazas'), lanzadestellos,
|
||||
f.get('m_oficial'), f.get('m_reservada'), f.get('m_propia'), f.get('VIN'), f.get('poliza'), f.get('viat') or '', f.get('legajo') or None,
|
||||
f.get('marca'), f.get('modelo'), f.get('tipo'), f.get('color'), f.get('combustible'), f.get('plazas'), lanzadestellos,
|
||||
f.get('situacion'), f.get('poblacion'), f.get('unidad'),
|
||||
f.get('int_operacion'), f.get('int_grupo'), f.get('int_juzgado'), f.get('int_procedimiento'),
|
||||
f.get('km') or None, f.get('km_1') or None, f.get('itv_ultima') or None, f.get('itv') or None,
|
||||
@@ -372,7 +375,12 @@ def vehiculos_editar(id):
|
||||
return redirect(f'/viat?q={q_viat}')
|
||||
return redirect(url_for('vehiculos_list', q=q) if q else url_for('vehiculos_list'))
|
||||
|
||||
matricula = vehiculo['m_oficial'] or vehiculo['m_civil'] or ''
|
||||
documentos = db.execute(
|
||||
'SELECT * FROM documentos WHERE vehiculo_id=? ORDER BY fecha DESC',
|
||||
(id,)
|
||||
).fetchall()
|
||||
|
||||
matricula = vehiculo['m_oficial'] or vehiculo['m_reservada'] or ''
|
||||
return render_template('vehiculos/form.html',
|
||||
page='vehiculos',
|
||||
vehiculo=vehiculo,
|
||||
@@ -386,7 +394,8 @@ def vehiculos_editar(id):
|
||||
hasta=hasta,
|
||||
q_itv=q_itv,
|
||||
origen=origen,
|
||||
q_viat=q_viat)
|
||||
q_viat=q_viat,
|
||||
documentos=documentos)
|
||||
|
||||
|
||||
@app.route('/vehiculos/<int:id>/eliminar', methods=['POST'])
|
||||
@@ -523,7 +532,6 @@ def historial_eliminar(vid, hid):
|
||||
|
||||
# 6. Si no queda ningún historial, limpiar el vehículo
|
||||
else:
|
||||
|
||||
db.execute('''
|
||||
UPDATE vehiculos
|
||||
SET
|
||||
@@ -563,33 +571,50 @@ def vehiculos_exportar():
|
||||
filtro_bajas = '' if incl_bajas else "AND (situacion IS NULL OR UPPER(situacion) != 'BAJA')"
|
||||
terminos = [t.strip() for t in q.split(',') if t.strip()] if q else []
|
||||
|
||||
|
||||
# terminos = [t.strip() for t in q.split(',') if t.strip()] if q else []
|
||||
|
||||
# Filtro base de bajas
|
||||
filtro_bajas = '' if incl_bajas else "AND (situacion IS NULL OR UPPER(situacion) != 'BAJA')"
|
||||
|
||||
if terminos:
|
||||
condiciones = []
|
||||
params = []
|
||||
|
||||
for t in terminos:
|
||||
like = f'%{t}%'
|
||||
t_norm = normalizar(t)
|
||||
|
||||
if t_norm == 'lanzadestellos':
|
||||
condiciones.append('lanzadestellos = 1')
|
||||
continue
|
||||
|
||||
like = f'%{t_norm}%'
|
||||
condiciones.append('''(
|
||||
m_oficial LIKE ? OR m_civil LIKE ? OR VIN LIKE ?
|
||||
OR marca LIKE ? OR modelo LIKE ? OR poblacion LIKE ?
|
||||
OR unidad LIKE ? OR grupo LIKE ? OR tipo LIKE ?
|
||||
OR situacion LIKE ? OR int_operacion LIKE ?
|
||||
|
||||
NORM(m_oficial) LIKE ? OR
|
||||
NORM(m_reservada) LIKE ? OR
|
||||
NORM(VIN) LIKE ? OR
|
||||
NORM(marca) LIKE ? OR
|
||||
NORM(modelo) LIKE ? OR
|
||||
NORM(poblacion) LIKE ? OR
|
||||
NORM(unidad) LIKE ? OR
|
||||
NORM(denominacion) LIKE ? OR
|
||||
NORM(situacion) LIKE ?
|
||||
)''')
|
||||
params.extend([like] * 9)
|
||||
|
||||
params.extend([like] * 11)
|
||||
where = ' AND '.join(condiciones)
|
||||
|
||||
# incluir_bajas = any(t.lower() == 'baja' for t in terminos)
|
||||
# if not incluir_bajas:
|
||||
# where = f"(situacion IS NULL OR UPPER(situacion) != 'BAJA') AND ({where})"
|
||||
|
||||
rows = db.execute(
|
||||
f'SELECT m_oficial, m_civil, marca, modelo, poblacion, unidad, grupo, tipo, situacion FROM vehiculos WHERE {where} {filtro_bajas} ORDER BY id',
|
||||
f'''SELECT id, m_oficial, m_reservada, marca, modelo, poblacion, unidad,
|
||||
denominacion, tipo, situacion, lanzadestellos
|
||||
FROM vehiculos
|
||||
WHERE {where} {filtro_bajas}
|
||||
ORDER BY id''',
|
||||
params
|
||||
).fetchall()
|
||||
else:
|
||||
rows = db.execute(
|
||||
'''SELECT m_oficial, m_civil, marca, modelo, poblacion, unidad, grupo, tipo, situacion
|
||||
'''SELECT m_oficial, m_reservada, marca, modelo, poblacion, unidad, grupo, tipo, situacion
|
||||
FROM vehiculos
|
||||
WHERE situacion IS NULL OR UPPER(situacion) != 'BAJA'
|
||||
ORDER BY id'''
|
||||
@@ -638,6 +663,202 @@ def vehiculos_exportar():
|
||||
|
||||
|
||||
|
||||
# UPLOADS FICHAS TECNICAS PDF
|
||||
def allowed_file(filename):
|
||||
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
||||
|
||||
|
||||
# @app.errorhandler(RequestEntityTooLarge)
|
||||
# def handle_file_too_large(e):
|
||||
# flash('Error: El archivo pdf no puede superar los 5 MB.', 'error')
|
||||
# return redirect(request.referrer or '/')
|
||||
|
||||
|
||||
@app.route('/vehiculos/<int:id>/documentos/upload', methods=['POST'])
|
||||
@login_required
|
||||
def documentos_upload(id):
|
||||
q = request.form.get('_q', '')
|
||||
incl_bajas = request.form.get('_incl_bajas', '0')
|
||||
desde = request.form.get('_desde', '')
|
||||
hasta = request.form.get('_hasta', '')
|
||||
q_itv = request.form.get('_q_itv', '')
|
||||
origen = request.form.get('_origen', '')
|
||||
q_viat = request.form.get('_q_viat', '')
|
||||
nombre = request.form.get('nombre_doc', '').strip()
|
||||
|
||||
if 'pdf' not in request.files:
|
||||
flash('No se seleccionó ningún archivo.', 'error')
|
||||
return redirect(f'/vehiculos/{id}/editar')
|
||||
|
||||
file = request.files['pdf']
|
||||
if file.filename == '' or not allowed_file(file.filename):
|
||||
flash('Solo se permiten archivos PDF.', 'error')
|
||||
return redirect(f'/vehiculos/{id}/editar')
|
||||
|
||||
# Comprobar tamaño máximo: 5 MiB
|
||||
MAX_FILE_SIZE = 5 * 1024 * 1024
|
||||
|
||||
file.seek(0, os.SEEK_END)
|
||||
file_size = file.tell()
|
||||
file.seek(0)
|
||||
|
||||
if file_size > MAX_FILE_SIZE:
|
||||
flash('El archivo PDF no puede superar los 5 MB.', 'error')
|
||||
return redirect(f'/vehiculos/{id}/editar?q={q}')
|
||||
|
||||
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||
|
||||
# Nombre único: vehiculo_id_timestamp.pdf
|
||||
import time
|
||||
filename = f'v{id}_{int(time.time())}.pdf'
|
||||
file.save(os.path.join(UPLOAD_FOLDER, filename))
|
||||
|
||||
# Si no puso nombre, usar el nombre original del archivo
|
||||
if not nombre:
|
||||
nombre = secure_filename(file.filename)
|
||||
|
||||
db = get_db()
|
||||
db.execute(
|
||||
'INSERT INTO documentos (vehiculo_id, nombre, filename) VALUES (?,?,?)',
|
||||
(id, nombre, filename)
|
||||
)
|
||||
db.commit()
|
||||
flash(f'Documento «{nombre}» subido correctamente.', 'ok')
|
||||
|
||||
url = f'/vehiculos/{id}/editar?q={q}'
|
||||
if origen == 'viat':
|
||||
url = f'/vehiculos/{id}/editar?origen=viat&q_viat={q_viat}'
|
||||
elif desde or hasta or q_itv:
|
||||
url = f'/vehiculos/{id}/editar?desde={desde}&hasta={hasta}&q_itv={q_itv}'
|
||||
return redirect(url)
|
||||
|
||||
|
||||
@app.route('/vehiculos/documentos/<int:doc_id>/ver')
|
||||
@login_required
|
||||
def documentos_ver(doc_id):
|
||||
from flask import send_from_directory
|
||||
db = get_db()
|
||||
doc = db.execute('SELECT * FROM documentos WHERE id=?', (doc_id,)).fetchone()
|
||||
if not doc:
|
||||
flash('Documento no encontrado.', 'error')
|
||||
return redirect(url_for('vehiculos_list'))
|
||||
return send_from_directory(UPLOAD_FOLDER, doc['filename'], as_attachment=False)
|
||||
|
||||
|
||||
@app.route('/vehiculos/documentos/<int:doc_id>/descargar')
|
||||
@login_required
|
||||
def documentos_descargar(doc_id):
|
||||
from flask import send_from_directory
|
||||
db = get_db()
|
||||
doc = db.execute('SELECT * FROM documentos WHERE id=?', (doc_id,)).fetchone()
|
||||
if not doc:
|
||||
flash('Documento no encontrado.', 'error')
|
||||
return redirect(url_for('vehiculos_list'))
|
||||
return send_from_directory(UPLOAD_FOLDER, doc['filename'],
|
||||
as_attachment=True,
|
||||
download_name=doc['nombre'])
|
||||
# download_name=doc['nombre'] + '.pdf')
|
||||
|
||||
@app.route('/vehiculos/documentos/<int:doc_id>/eliminar', methods=['POST'])
|
||||
@login_required
|
||||
def documentos_eliminar(doc_id):
|
||||
db = get_db()
|
||||
vid = request.form.get('vid', '')
|
||||
q = request.form.get('_q', '')
|
||||
incl_bajas = request.form.get('_incl_bajas', '0')
|
||||
|
||||
doc = db.execute('SELECT * FROM documentos WHERE id=?', (doc_id,)).fetchone()
|
||||
if doc:
|
||||
filepath = os.path.join(UPLOAD_FOLDER, doc['filename'])
|
||||
if os.path.exists(filepath):
|
||||
os.remove(filepath)
|
||||
db.execute('DELETE FROM documentos WHERE id=?', (doc_id,))
|
||||
db.commit()
|
||||
flash('Documento eliminado.', 'ok')
|
||||
|
||||
return redirect(f'/vehiculos/{vid}/editar?q={q}&incl_bajas={incl_bajas}')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# @app.route('/vehiculos/<int:id>/upload', methods=['POST'])
|
||||
# @login_required
|
||||
# def vehiculos_upload(id):
|
||||
# q = request.form.get('_q', '')
|
||||
# incl_bajas = request.form.get('_incl_bajas', '0')
|
||||
# desde = request.form.get('_desde', '')
|
||||
# hasta = request.form.get('_hasta', '')
|
||||
# q_itv = request.form.get('_q_itv', '')
|
||||
# origen = request.form.get('_origen', '')
|
||||
# q_viat = request.form.get('_q_viat', '')
|
||||
|
||||
# if 'pdf' not in request.files:
|
||||
# flash('No se seleccionó ningún archivo.', 'error')
|
||||
# return redirect(f'/vehiculos/{id}/editar?q={q}&incl_bajas={incl_bajas}')
|
||||
|
||||
# file = request.files['pdf']
|
||||
# if file.filename == '':
|
||||
# flash('No se seleccionó ningún archivo.', 'error')
|
||||
# return redirect(f'/vehiculos/{id}/editar?q={q}&incl_bajas={incl_bajas}')
|
||||
|
||||
# if file and allowed_file(file.filename):
|
||||
# # Guardar con nombre único basado en id del vehículo
|
||||
# os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||
# filename = f'ficha_tecnica_id_{id}.pdf'
|
||||
# filepath = os.path.join(UPLOAD_FOLDER, filename)
|
||||
# file.save(filepath)
|
||||
|
||||
# # Guardar referencia en BD
|
||||
# db = get_db()
|
||||
# db.execute('UPDATE vehiculos SET pdf=? WHERE id=?', (filename, id))
|
||||
# db.commit()
|
||||
# flash('Documento PDF subido correctamente.', 'ok')
|
||||
# else:
|
||||
# flash('Solo se permiten archivos PDF.', 'error')
|
||||
|
||||
# url = f'/vehiculos/{id}/editar?q={q}&incl_bajas={incl_bajas}'
|
||||
# if origen == 'viat':
|
||||
# url = f'/vehiculos/{id}/editar?origen=viat&q_viat={q_viat}'
|
||||
# elif desde or hasta or q_itv:
|
||||
# url = f'/vehiculos/{id}/editar?desde={desde}&hasta={hasta}&q_itv={q_itv}'
|
||||
# return redirect(url)
|
||||
|
||||
|
||||
# @app.route('/vehiculos/<int:id>/pdf')
|
||||
# @login_required
|
||||
# def vehiculos_pdf(id):
|
||||
# from flask import send_from_directory
|
||||
# db = get_db()
|
||||
# vehiculo = db.execute('SELECT pdf FROM vehiculos WHERE id=?', (id,)).fetchone()
|
||||
# if not vehiculo or not vehiculo['pdf']:
|
||||
# flash('No hay documento PDF para este vehículo.', 'error')
|
||||
# return redirect(f'/vehiculos/{id}/editar')
|
||||
# return send_from_directory(UPLOAD_FOLDER, vehiculo['pdf'], as_attachment=False)
|
||||
|
||||
|
||||
# @app.route('/vehiculos/<int:id>/pdf/eliminar', methods=['POST'])
|
||||
# @login_required
|
||||
# def vehiculos_pdf_eliminar(id):
|
||||
# q = request.form.get('_q', '')
|
||||
# incl_bajas = request.form.get('_incl_bajas', '0')
|
||||
# db = get_db()
|
||||
# vehiculo = db.execute('SELECT pdf FROM vehiculos WHERE id=?', (id,)).fetchone()
|
||||
# if vehiculo and vehiculo['pdf']:
|
||||
# filepath = os.path.join(UPLOAD_FOLDER, vehiculo['pdf'])
|
||||
# if os.path.exists(filepath):
|
||||
# os.remove(filepath)
|
||||
# db.execute('UPDATE vehiculos SET pdf=NULL WHERE id=?', (id,))
|
||||
# db.commit()
|
||||
# flash('Documento PDF eliminado.', 'ok')
|
||||
# return redirect(f'/vehiculos/{id}/editar?q={q}&incl_bajas={incl_bajas}')
|
||||
|
||||
|
||||
# Ruta API que devuelve unidades según población
|
||||
@app.route('/api/unidades/<int:poblacion_id>')
|
||||
@@ -683,7 +904,7 @@ def itv_list():
|
||||
params.extend([like] * 3)
|
||||
where_q = ' AND '.join(condiciones)
|
||||
rows = db.execute(f'''
|
||||
SELECT id, m_oficial, m_civil, marca, modelo, tipo,
|
||||
SELECT id, m_oficial, m_reservada, marca, modelo, tipo,
|
||||
tipo, unidad, poblacion, itv
|
||||
FROM vehiculos
|
||||
WHERE itv IS NOT NULL AND itv != ''
|
||||
@@ -693,7 +914,7 @@ def itv_list():
|
||||
''', params).fetchall()
|
||||
else:
|
||||
rows = db.execute('''
|
||||
SELECT id, m_oficial, m_civil, marca, modelo, tipo,
|
||||
SELECT id, m_oficial, m_reservada, marca, modelo, tipo,
|
||||
tipo, unidad, poblacion, itv
|
||||
FROM vehiculos
|
||||
WHERE itv IS NOT NULL AND itv != ''
|
||||
@@ -735,7 +956,7 @@ def itv_exportar():
|
||||
params.extend([like] * 3)
|
||||
where_q = ' AND '.join(condiciones)
|
||||
rows = db.execute(f'''
|
||||
SELECT m_oficial, m_civil, marca, modelo, tipo,
|
||||
SELECT m_oficial, m_reservada, marca, modelo, tipo,
|
||||
tipo, unidad, poblacion, itv
|
||||
FROM vehiculos
|
||||
WHERE itv IS NOT NULL AND itv != ''
|
||||
@@ -745,7 +966,7 @@ def itv_exportar():
|
||||
''', params).fetchall()
|
||||
else:
|
||||
rows = db.execute('''
|
||||
SELECT m_oficial, m_civil, marca, modelo, tipo,
|
||||
SELECT m_oficial, m_reservada, marca, modelo, tipo,
|
||||
tipo, unidad, poblacion, itv
|
||||
FROM vehiculos
|
||||
WHERE itv IS NOT NULL AND itv != ''
|
||||
@@ -941,6 +1162,104 @@ def editar_unidades():
|
||||
# return redirect(url_for('unidades_list'))
|
||||
|
||||
|
||||
############### API PARA USAR TABULATOR ######################################
|
||||
|
||||
# @app.route("/api/unidades/<int:unidad_id>", methods=["PATCH"])
|
||||
# @login_required
|
||||
# def actualizar_unidad(unidad_id):
|
||||
|
||||
# datos = request.get_json(silent=True) or {}
|
||||
|
||||
# campo = datos.get("campo")
|
||||
# valor = datos.get("valor")
|
||||
|
||||
# # Solo permitimos estos campos
|
||||
# if campo not in ("poblacion_id", "unidad"):
|
||||
# return jsonify({
|
||||
# "error": "Campo no permitido"
|
||||
# }), 400
|
||||
|
||||
# db = get_db()
|
||||
|
||||
# # Comprobar que existe la unidad
|
||||
# unidad_actual = db.execute(
|
||||
# "SELECT id FROM unidades WHERE id=?",
|
||||
# (unidad_id,)
|
||||
# ).fetchone()
|
||||
|
||||
# if unidad_actual is None:
|
||||
|
||||
# return jsonify({
|
||||
# "error": "La unidad no existe"
|
||||
# }), 404
|
||||
|
||||
# # CAMBIO DE POBLACIÓN
|
||||
# if campo == "poblacion_id":
|
||||
|
||||
# try:
|
||||
# poblacion_id = int(valor)
|
||||
# except (ValueError, TypeError):
|
||||
|
||||
# return jsonify({
|
||||
# "error": "Población no válida"
|
||||
# }), 400
|
||||
|
||||
|
||||
# poblacion = db.execute(
|
||||
# """ SELECT id, poblacion FROM poblaciones WHERE id=? """,
|
||||
# (poblacion_id,)
|
||||
# ).fetchone()
|
||||
|
||||
# if poblacion is None:
|
||||
|
||||
# return jsonify({
|
||||
# "error": "La población no existe"
|
||||
# }), 400
|
||||
|
||||
# valor = poblacion_id
|
||||
|
||||
# # CAMBIO DE UNIDAD
|
||||
# elif campo == "unidad":
|
||||
|
||||
# valor = str(valor or "").strip()
|
||||
|
||||
# if not valor:
|
||||
|
||||
# return jsonify({
|
||||
# "error": "El nombre de la unidad no puede estar vacío"
|
||||
# }), 400
|
||||
|
||||
# # UPDATE
|
||||
# db.execute(f""" UPDATE unidades SET {campo}=? WHERE id=?""",
|
||||
# (valor, unidad_id)
|
||||
# )
|
||||
|
||||
# db.commit()
|
||||
|
||||
# # DEVOLVER EL REGISTRO ACTUALIZADO
|
||||
# fila = db.execute(
|
||||
# """
|
||||
# SELECT
|
||||
# u.id,
|
||||
# u.poblacion_id,
|
||||
# u.unidad,
|
||||
# p.poblacion
|
||||
# FROM unidades u
|
||||
# LEFT JOIN poblaciones p
|
||||
# ON u.poblacion_id = p.id
|
||||
# WHERE u.id=? """,
|
||||
# (unidad_id,)
|
||||
# ).fetchone()
|
||||
|
||||
|
||||
# return jsonify({
|
||||
# "id": fila["id"],
|
||||
# "poblacion_id": fila["poblacion_id"],
|
||||
# "poblacion": fila["poblacion"],
|
||||
# "unidad": fila["unidad"]
|
||||
# })
|
||||
|
||||
|
||||
# ── CRUD tipo ─────────────────────────────────────────
|
||||
@app.route('/tipo')
|
||||
@login_required
|
||||
@@ -1023,7 +1342,7 @@ def viat_list():
|
||||
terminos = [t.strip() for t in q.split(',') if t.strip()] if q else []
|
||||
|
||||
sql = '''
|
||||
SELECT id, viat, m_oficial, m_civil, marca, modelo,
|
||||
SELECT id, viat, m_oficial, m_reservada, marca, modelo,
|
||||
poblacion, unidad, tipo
|
||||
FROM vehiculos
|
||||
WHERE viat IS NOT NULL
|
||||
@@ -1040,7 +1359,7 @@ def viat_list():
|
||||
(
|
||||
viat LIKE ?
|
||||
OR m_oficial LIKE ?
|
||||
OR m_civil LIKE ?
|
||||
OR m_reservada LIKE ?
|
||||
OR marca LIKE ?
|
||||
OR modelo LIKE ?
|
||||
OR poblacion LIKE ?
|
||||
@@ -1076,7 +1395,7 @@ def viat_exportar():
|
||||
terminos = [t.strip() for t in q.split(',') if t.strip()] if q else []
|
||||
|
||||
sql = '''
|
||||
SELECT id, viat, m_oficial, m_civil, marca, modelo,
|
||||
SELECT id, viat, m_oficial, m_reservada, marca, modelo,
|
||||
poblacion, unidad, tipo
|
||||
FROM vehiculos
|
||||
WHERE viat IS NOT NULL
|
||||
@@ -1093,7 +1412,7 @@ def viat_exportar():
|
||||
(
|
||||
viat LIKE ?
|
||||
OR m_oficial LIKE ?
|
||||
OR m_civil LIKE ?
|
||||
OR m_reservada LIKE ?
|
||||
OR marca LIKE ?
|
||||
OR modelo LIKE ?
|
||||
OR poblacion LIKE ?
|
||||
@@ -1126,7 +1445,7 @@ def viat_exportar():
|
||||
ws.row_dimensions[1].height = 22
|
||||
|
||||
for row in rows:
|
||||
ws.append([row['viat'], row['m_oficial'], row['m_civil'],
|
||||
ws.append([row['viat'], row['m_oficial'], row['m_reservada'],
|
||||
row['marca'], row['modelo'], row['poblacion'],
|
||||
row['unidad'], row['tipo']])
|
||||
|
||||
@@ -1284,10 +1603,36 @@ def fecha_es(valor):
|
||||
return valor
|
||||
|
||||
|
||||
|
||||
|
||||
# ------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
init_db()
|
||||
app.run(host="0.0.0.0", port=5000, debug=True)
|
||||
# app.run(debug=True)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# CODIGO PREVIO A INCLUIR NORMALIZACION
|
||||
# if terminos:
|
||||
# condiciones = []
|
||||
# params = []
|
||||
# for t in terminos:
|
||||
# like = f'%{t}%'
|
||||
# condiciones.append('''(
|
||||
# m_oficial LIKE ? OR m_reservada LIKE ? OR VIN LIKE ?
|
||||
# OR marca LIKE ? OR modelo LIKE ? OR poblacion LIKE ?
|
||||
# OR unidad LIKE ? OR grupo LIKE ? OR tipo LIKE ?
|
||||
# OR situacion LIKE ? OR int_operacion LIKE ?
|
||||
# )''')
|
||||
|
||||
# params.extend([like] * 11)
|
||||
# where = ' AND '.join(condiciones)
|
||||
|
||||
# rows = db.execute(
|
||||
# f'SELECT id, m_oficial, m_reservada, marca, modelo, poblacion, unidad, grupo, tipo, situacion FROM vehiculos WHERE {where} {filtro_bajas} ORDER BY id',
|
||||
# params
|
||||
# ).fetchall()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user