actualizado 3-sept

This commit is contained in:
2026-09-03 19:40:44 +02:00
parent 89992823b4
commit 5d2912f789
4338 changed files with 350157 additions and 386 deletions
+457 -112
View File
@@ -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()