feat: excluir contratos del envío TNS
- Columna excluir en tabla contratos (migración automática) - 25 contratos nuevos sembrados con excluir=1 (laboratorios externos, clínicas, médicos particulares) - load_excluded_set() en contratos.py para consultar el set en runtime - preview: marca items excluidos y los reporta en el conteo - send/send-one/send-direct: bloquea envío si contrato está excluido - automation preview+run: filtra excluidos antes del loop, reporta count - UI /contratos: columna Envío TNS con toggle Activo/Excluido, fila en rojo si excluida Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
3baa6e5f75
commit
200a3f550b
@@ -31,9 +31,14 @@ def _migrate(conn):
|
|||||||
nit_empresa TEXT NOT NULL DEFAULT '',
|
nit_empresa TEXT NOT NULL DEFAULT '',
|
||||||
tipo_usuario TEXT NOT NULL,
|
tipo_usuario TEXT NOT NULL,
|
||||||
descripcion TEXT NOT NULL DEFAULT '',
|
descripcion TEXT NOT NULL DEFAULT '',
|
||||||
|
excluir INTEGER NOT NULL DEFAULT 0,
|
||||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
else:
|
||||||
|
contrato_cols = {r[1] for r in conn.execute("PRAGMA table_info(contratos)")}
|
||||||
|
if "excluir" not in contrato_cols:
|
||||||
|
conn.execute("ALTER TABLE contratos ADD COLUMN excluir INTEGER NOT NULL DEFAULT 0")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from app.services.json_generator import (
|
|||||||
)
|
)
|
||||||
from app.services.api_client import get_tns_token, TNS_BASE
|
from app.services.api_client import get_tns_token, TNS_BASE
|
||||||
from app.services.whatsapp_sync import sync_paciente, sync_todos, guardar_sync_log
|
from app.services.whatsapp_sync import sync_paciente, sync_todos, guardar_sync_log
|
||||||
from app.routes.contratos import load_contrato_map
|
from app.routes.contratos import load_contrato_map, load_excluded_set
|
||||||
|
|
||||||
router = APIRouter(prefix="/automation", tags=["automation"])
|
router = APIRouter(prefix="/automation", tags=["automation"])
|
||||||
|
|
||||||
@@ -137,7 +137,11 @@ async def preview_automation(
|
|||||||
if not ok2:
|
if not ok2:
|
||||||
return JSONResponse({"success": False, "message": f"Error BD RDA: {err2}"})
|
return JSONResponse({"success": False, "message": f"Error BD RDA: {err2}"})
|
||||||
|
|
||||||
grupos = agrupar_por_recepcion(rows_rda)
|
grupos_all = agrupar_por_recepcion(rows_rda)
|
||||||
|
excluded = load_excluded_set()
|
||||||
|
grupos = {k: v for k, v in grupos_all.items()
|
||||||
|
if str(v[0].get("CODCONTRATO") or "").strip() not in excluded}
|
||||||
|
excluidos_count = len(grupos_all) - len(grupos)
|
||||||
total_examenes = sum(len(v) for v in grupos.values())
|
total_examenes = sum(len(v) for v in grupos.values())
|
||||||
|
|
||||||
# Agrupar RDA por COD_PACIENTE
|
# Agrupar RDA por COD_PACIENTE
|
||||||
@@ -172,6 +176,7 @@ async def preview_automation(
|
|||||||
"pacientes": len(rows_pac),
|
"pacientes": len(rows_pac),
|
||||||
"recepciones": len(grupos),
|
"recepciones": len(grupos),
|
||||||
"examenes": total_examenes,
|
"examenes": total_examenes,
|
||||||
|
"excluidos": excluidos_count,
|
||||||
"pacientes_preview": pacientes_preview,
|
"pacientes_preview": pacientes_preview,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -273,7 +278,12 @@ async def run_automation(
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# ── PASO 2: Enviar RDA Paciente ───────────────────────────────────────────
|
# ── PASO 2: Enviar RDA Paciente ───────────────────────────────────────────
|
||||||
grupos = agrupar_por_recepcion(rows_rda)
|
excluded = load_excluded_set()
|
||||||
|
grupos_all = agrupar_por_recepcion(rows_rda)
|
||||||
|
grupos = {k: v for k, v in grupos_all.items()
|
||||||
|
if str(v[0].get("CODCONTRATO") or "").strip() not in excluded}
|
||||||
|
resultado["paso2_rda"]["excluidos"] = len(grupos_all) - len(grupos)
|
||||||
|
|
||||||
endpoint = f"{TNS_BASE}/v2/rda/RdaPaciente/Insertar?codigosucursal={api_sucursal or '00'}"
|
endpoint = f"{TNS_BASE}/v2/rda/RdaPaciente/Insertar?codigosucursal={api_sucursal or '00'}"
|
||||||
prof_def = configs.get("profesional_default", "")
|
prof_def = configs.get("profesional_default", "")
|
||||||
esp_def = configs.get("especialidad_default", "")
|
esp_def = configs.get("especialidad_default", "")
|
||||||
|
|||||||
+82
-24
@@ -5,37 +5,66 @@ from app.auth import get_current_user
|
|||||||
|
|
||||||
router = APIRouter(prefix="/contratos", tags=["contratos"])
|
router = APIRouter(prefix="/contratos", tags=["contratos"])
|
||||||
|
|
||||||
|
# (numero_contrato, nit_empresa, tipo_usuario, descripcion, excluir)
|
||||||
_SEED = [
|
_SEED = [
|
||||||
("001", "860078828", "11", "EPS SANITAS"),
|
("001", "860078828", "11", "EPS SANITAS", 0),
|
||||||
("002", "830054904", "11", "EPS COMPENSAR"),
|
("002", "830054904", "11", "EPS COMPENSAR", 0),
|
||||||
("003", "900278729", "12", "PARTICULAR"),
|
("003", "900278729", "12", "PARTICULAR", 0),
|
||||||
("004", "800106339", "11", "EPS NUEVA EPS"),
|
("004", "800106339", "11", "EPS NUEVA EPS", 0),
|
||||||
("005", "800153424", "11", "EPS SURA"),
|
("005", "800153424", "11", "EPS SURA", 0),
|
||||||
("006", "805009741", "11", "EPS COOMEVA"),
|
("006", "805009741", "11", "EPS COOMEVA", 0),
|
||||||
("007", "860002183", "11", "EPS FAMISANAR"),
|
("007", "860002183", "11", "EPS FAMISANAR", 0),
|
||||||
("008", "860002503", "11", "EPS CRUZ BLANCA"),
|
("008", "860002503", "11", "EPS CRUZ BLANCA", 0),
|
||||||
("009", "860027404", "11", "EPS COLSANITAS"),
|
("009", "860027404", "11", "EPS COLSANITAS", 0),
|
||||||
("010", "860039988", "11", "EPS SALUD TOTAL"),
|
("010", "860039988", "11", "EPS SALUD TOTAL", 0),
|
||||||
("011", "890903790", "11", "EPS SAVIA SALUD"),
|
("011", "890903790", "11", "EPS SAVIA SALUD", 0),
|
||||||
("012", "900178724", "11", "EPS MUTUAL SER"),
|
("012", "900178724", "11", "EPS MUTUAL SER", 0),
|
||||||
("034", "860078828", "11", "EPS SANITAS (alt)"),
|
("034", "860078828", "11", "EPS SANITAS (alt)", 0),
|
||||||
("035", "860078828", "11", "EPS SANITAS (alt)"),
|
("035", "860078828", "11", "EPS SANITAS (alt)", 0),
|
||||||
("036", "860078828", "11", "EPS SANITAS (alt)"),
|
("036", "860078828", "11", "EPS SANITAS (alt)", 0),
|
||||||
("20062026", "800182856", "01", "SUBSIDIADO"),
|
("20062026", "800182856", "01", "SUBSIDIADO", 0),
|
||||||
("CW225489", "899999068", "07", "POLIZA / SEGURO"),
|
("CW225489", "899999068", "07", "POLIZA / SEGURO", 0),
|
||||||
|
# Contratos excluidos del envío TNS
|
||||||
|
("013", "", "11", "MEDILAVORO S.A.S", 1),
|
||||||
|
("014", "", "11", "LABORATORIO UROCLINICO",1),
|
||||||
|
("015", "", "11", "ANDRES AFANADOR VILLAMIZAR", 1),
|
||||||
|
("016", "", "11", "OMAR FERNANDO RIBERO GOMEZ", 1),
|
||||||
|
("017", "", "11", "CLAUDIA BELEN JULIO SEPULVEDA", 1),
|
||||||
|
("018", "", "11", "LABORATORIO MICROBIOLOGICO - MARGIE OJEDA", 1),
|
||||||
|
("019", "", "11", "LABORATORIO TOXICOLOGICO - MARTHA MORALES", 1),
|
||||||
|
("020", "", "11", "MARTHA LUCIA GALLARDO", 1),
|
||||||
|
("021", "", "11", "LABORATORIO VILMA OROZCO AYALA", 1),
|
||||||
|
("022", "", "11", "CLINICA SAN JOSE DE CUCUTA", 1),
|
||||||
|
("023", "", "11", "URONORTE S.A", 1),
|
||||||
|
("024", "", "11", "LABORATORIO CLINICO BIOLAB S.A.S", 1),
|
||||||
|
("025", "", "11", "JOEL LEONARDO CARRILLO CORREDOR", 1),
|
||||||
|
("026", "", "11", "ROLANDO IVAN PENARANDA DEVIA", 1),
|
||||||
|
("027", "", "11", "JOSE WILMER GARCIA CALDERON", 1),
|
||||||
|
("028", "", "11", "ONCOMEDICAL IPS S.A.S", 1),
|
||||||
|
("029", "", "11", "GENETIX S.A.S", 1),
|
||||||
|
("030", "", "11", "NORFETUS S.A.S", 1),
|
||||||
|
("031", "", "11", "TBTB GLOBAL LAB S.A.S", 1),
|
||||||
|
("032", "", "11", "COLGENES S.A.S", 1),
|
||||||
|
("033", "", "11", "IPS FIGURAS SPA CUCUTA S.A.S", 1),
|
||||||
|
("037", "", "11", "CLINICA URGENCIAS LA MERCED", 1),
|
||||||
|
("038", "", "11", "CLINICA COLSANITAS S.A.", 1),
|
||||||
|
("039", "", "11", "GOMEZ GIL JOSE JESUS", 1),
|
||||||
|
("040", "", "11", "MARTHA LILIANA SALGAR GALLEGO", 1),
|
||||||
|
("041", "", "11", "GENCELL PHARMA S.A.S", 1),
|
||||||
|
("042", "", "07", "AXA COLPATRIA HYC", 1),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def ensure_defaults():
|
def ensure_defaults():
|
||||||
conn = get_connection()
|
conn = get_connection()
|
||||||
for nc, nit, tu, desc in _SEED:
|
for nc, nit, tu, desc, excluir in _SEED:
|
||||||
exists = conn.execute(
|
exists = conn.execute(
|
||||||
"SELECT id FROM contratos WHERE numero_contrato = ?", (nc,)
|
"SELECT id FROM contratos WHERE numero_contrato = ?", (nc,)
|
||||||
).fetchone()
|
).fetchone()
|
||||||
if not exists:
|
if not exists:
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT INTO contratos (numero_contrato, nit_empresa, tipo_usuario, descripcion) VALUES (?,?,?,?)",
|
"INSERT INTO contratos (numero_contrato, nit_empresa, tipo_usuario, descripcion, excluir) VALUES (?,?,?,?,?)",
|
||||||
(nc, nit, tu, desc),
|
(nc, nit, tu, desc, excluir),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
@@ -57,6 +86,21 @@ def load_contrato_map() -> dict:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def load_excluded_set() -> set:
|
||||||
|
"""Devuelve set de numero_contrato (raw + sin ceros) marcados como excluir=1."""
|
||||||
|
conn = get_connection()
|
||||||
|
rows = conn.execute("SELECT numero_contrato FROM contratos WHERE excluir=1").fetchall()
|
||||||
|
conn.close()
|
||||||
|
result = set()
|
||||||
|
for r in rows:
|
||||||
|
nc = r["numero_contrato"].strip()
|
||||||
|
result.add(nc)
|
||||||
|
nc_s = nc.lstrip("0") or nc
|
||||||
|
if nc_s != nc:
|
||||||
|
result.add(nc_s)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@router.get("")
|
@router.get("")
|
||||||
async def contratos_page(request: Request, user: dict = Depends(get_current_user)):
|
async def contratos_page(request: Request, user: dict = Depends(get_current_user)):
|
||||||
conn = get_connection()
|
conn = get_connection()
|
||||||
@@ -75,12 +119,13 @@ async def contrato_create(
|
|||||||
nit_empresa: str = Form(""),
|
nit_empresa: str = Form(""),
|
||||||
tipo_usuario: str = Form(...),
|
tipo_usuario: str = Form(...),
|
||||||
descripcion: str = Form(""),
|
descripcion: str = Form(""),
|
||||||
|
excluir: str = Form("0"),
|
||||||
):
|
):
|
||||||
conn = get_connection()
|
conn = get_connection()
|
||||||
try:
|
try:
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT INTO contratos (numero_contrato, nit_empresa, tipo_usuario, descripcion) VALUES (?,?,?,?)",
|
"INSERT INTO contratos (numero_contrato, nit_empresa, tipo_usuario, descripcion, excluir) VALUES (?,?,?,?,?)",
|
||||||
(numero_contrato.strip(), nit_empresa.strip(), tipo_usuario.strip(), descripcion.strip()),
|
(numero_contrato.strip(), nit_empresa.strip(), tipo_usuario.strip(), descripcion.strip(), int(excluir)),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -97,11 +142,24 @@ async def contrato_update(
|
|||||||
nit_empresa: str = Form(""),
|
nit_empresa: str = Form(""),
|
||||||
tipo_usuario: str = Form(...),
|
tipo_usuario: str = Form(...),
|
||||||
descripcion: str = Form(""),
|
descripcion: str = Form(""),
|
||||||
|
excluir: str = Form("0"),
|
||||||
):
|
):
|
||||||
conn = get_connection()
|
conn = get_connection()
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"UPDATE contratos SET numero_contrato=?, nit_empresa=?, tipo_usuario=?, descripcion=? WHERE id=?",
|
"UPDATE contratos SET numero_contrato=?, nit_empresa=?, tipo_usuario=?, descripcion=?, excluir=? WHERE id=?",
|
||||||
(numero_contrato.strip(), nit_empresa.strip(), tipo_usuario.strip(), descripcion.strip(), contrato_id),
|
(numero_contrato.strip(), nit_empresa.strip(), tipo_usuario.strip(), descripcion.strip(), int(excluir), contrato_id),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return RedirectResponse("/contratos", status_code=302)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/toggle-excluir/{contrato_id}")
|
||||||
|
async def toggle_excluir(contrato_id: int, user: dict = Depends(get_current_user)):
|
||||||
|
conn = get_connection()
|
||||||
|
conn.execute(
|
||||||
|
"UPDATE contratos SET excluir = CASE WHEN excluir=1 THEN 0 ELSE 1 END WHERE id=?",
|
||||||
|
(contrato_id,)
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from app.auth import get_current_user
|
|||||||
from app.services.firebird_service import get_firebird_from_config
|
from app.services.firebird_service import get_firebird_from_config
|
||||||
from app.services.json_generator import generar_rda_paciente, agrupar_por_recepcion
|
from app.services.json_generator import generar_rda_paciente, agrupar_por_recepcion
|
||||||
from app.services.api_client import get_tns_token, TNS_BASE
|
from app.services.api_client import get_tns_token, TNS_BASE
|
||||||
from app.routes.contratos import load_contrato_map
|
from app.routes.contratos import load_contrato_map, load_excluded_set
|
||||||
|
|
||||||
router = APIRouter(prefix="/transaccion", tags=["transaccion"])
|
router = APIRouter(prefix="/transaccion", tags=["transaccion"])
|
||||||
|
|
||||||
@@ -98,10 +98,13 @@ async def preview_transaccion(
|
|||||||
remis_def = cfg.get("remisionante_default", "00")
|
remis_def = cfg.get("remisionante_default", "00")
|
||||||
prefijo_def = cfg.get("prefijo_tns_default", "00")
|
prefijo_def = cfg.get("prefijo_tns_default", "00")
|
||||||
contrato_map = load_contrato_map()
|
contrato_map = load_contrato_map()
|
||||||
|
excluded = load_excluded_set()
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
for id_rec, grupo_rows in grupos.items():
|
for id_rec, grupo_rows in grupos.items():
|
||||||
enviado = _is_sent(id_rec)
|
enviado = _is_sent(id_rec)
|
||||||
|
cod_c = str(grupo_rows[0].get("CODCONTRATO") or "").strip()
|
||||||
|
is_excluded = cod_c in excluded
|
||||||
rda = generar_rda_paciente(grupo_rows, prof_def, esp_def, remis_def, prefijo_def, contrato_map=contrato_map)
|
rda = generar_rda_paciente(grupo_rows, prof_def, esp_def, remis_def, prefijo_def, contrato_map=contrato_map)
|
||||||
items.append({
|
items.append({
|
||||||
"idrecepcion": id_rec,
|
"idrecepcion": id_rec,
|
||||||
@@ -111,12 +114,14 @@ async def preview_transaccion(
|
|||||||
"examenes": [r.get("COD_EXAMEN", "") for r in grupo_rows],
|
"examenes": [r.get("COD_EXAMEN", "") for r in grupo_rows],
|
||||||
"valor": float(grupo_rows[0].get("VALORTOTAL") or 0),
|
"valor": float(grupo_rows[0].get("VALORTOTAL") or 0),
|
||||||
"enviado": enviado,
|
"enviado": enviado,
|
||||||
|
"excluido": is_excluded,
|
||||||
"json": rda,
|
"json": rda,
|
||||||
})
|
})
|
||||||
|
|
||||||
pendientes = sum(1 for i in items if not i["enviado"])
|
pendientes = sum(1 for i in items if not i["enviado"] and not i["excluido"])
|
||||||
enviados_ok = sum(1 for i in items if i["enviado"] and i["enviado"]["status"] == "success")
|
enviados_ok = sum(1 for i in items if i["enviado"] and i["enviado"]["status"] == "success")
|
||||||
enviados_err = sum(1 for i in items if i["enviado"] and i["enviado"]["status"] == "error")
|
enviados_err = sum(1 for i in items if i["enviado"] and i["enviado"]["status"] == "error")
|
||||||
|
excluidos = sum(1 for i in items if i["excluido"])
|
||||||
|
|
||||||
return JSONResponse({
|
return JSONResponse({
|
||||||
"success": True,
|
"success": True,
|
||||||
@@ -124,6 +129,7 @@ async def preview_transaccion(
|
|||||||
"pendientes": pendientes,
|
"pendientes": pendientes,
|
||||||
"enviados_ok": enviados_ok,
|
"enviados_ok": enviados_ok,
|
||||||
"enviados_err": enviados_err,
|
"enviados_err": enviados_err,
|
||||||
|
"excluidos": excluidos,
|
||||||
"items": items,
|
"items": items,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -149,6 +155,10 @@ async def send_one(
|
|||||||
if not grupo_rows:
|
if not grupo_rows:
|
||||||
return JSONResponse({"success": False, "message": f"IDRECEPCION {idrecepcion} no encontrado"})
|
return JSONResponse({"success": False, "message": f"IDRECEPCION {idrecepcion} no encontrado"})
|
||||||
|
|
||||||
|
cod_c = str(grupo_rows[0].get("CODCONTRATO") or "").strip()
|
||||||
|
if cod_c in load_excluded_set():
|
||||||
|
return JSONResponse({"success": False, "message": f"Contrato {cod_c} está excluido del envío TNS"})
|
||||||
|
|
||||||
token, token_err = await get_tns_token(
|
token, token_err = await get_tns_token(
|
||||||
cfg.get("tns_empresa", ""), cfg.get("tns_usuario", ""), cfg.get("tns_password", "")
|
cfg.get("tns_empresa", ""), cfg.get("tns_usuario", ""), cfg.get("tns_password", "")
|
||||||
)
|
)
|
||||||
@@ -237,6 +247,12 @@ async def send_transaccion(
|
|||||||
if solo_pendientes == "1":
|
if solo_pendientes == "1":
|
||||||
grupos = {k: v for k, v in grupos.items() if not _is_sent(k)}
|
grupos = {k: v for k, v in grupos.items() if not _is_sent(k)}
|
||||||
|
|
||||||
|
excluded = load_excluded_set()
|
||||||
|
grupos_enviar = {k: v for k, v in grupos.items()
|
||||||
|
if str(v[0].get("CODCONTRATO") or "").strip() not in excluded}
|
||||||
|
excluidos_count = len(grupos) - len(grupos_enviar)
|
||||||
|
grupos = grupos_enviar
|
||||||
|
|
||||||
contrato_map = load_contrato_map()
|
contrato_map = load_contrato_map()
|
||||||
|
|
||||||
token, token_err = await get_tns_token(
|
token, token_err = await get_tns_token(
|
||||||
@@ -306,6 +322,7 @@ async def send_transaccion(
|
|||||||
"success": err_count == 0,
|
"success": err_count == 0,
|
||||||
"total_enviados": ok_count,
|
"total_enviados": ok_count,
|
||||||
"total_errores": err_count,
|
"total_errores": err_count,
|
||||||
|
"total_excluidos": excluidos_count,
|
||||||
"resultados": resultados,
|
"resultados": resultados,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -340,6 +357,12 @@ async def send_direct(
|
|||||||
if not grupos:
|
if not grupos:
|
||||||
return JSONResponse({"success": False, "message": "Sin datos agrupables"})
|
return JSONResponse({"success": False, "message": "Sin datos agrupables"})
|
||||||
|
|
||||||
|
# Rechazar si todos los grupos pertenecen a contratos excluidos
|
||||||
|
excluded = load_excluded_set()
|
||||||
|
primer_contrato = str(list(grupos.values())[0][0].get("CODCONTRATO") or "").strip()
|
||||||
|
if primer_contrato in excluded:
|
||||||
|
return JSONResponse({"success": False, "message": f"Contrato {primer_contrato} está excluido del envío TNS"})
|
||||||
|
|
||||||
token, token_err = await get_tns_token(
|
token, token_err = await get_tns_token(
|
||||||
cfg.get("tns_empresa", ""), cfg.get("tns_usuario", ""), cfg.get("tns_password", "")
|
cfg.get("tns_empresa", ""), cfg.get("tns_usuario", ""), cfg.get("tns_password", "")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{% block title %}Contratos{% endblock %}
|
{% block title %}Contratos{% endblock %}
|
||||||
{% block header %}Contratos{% endblock %}
|
{% block header %}Contratos{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="max-w-4xl space-y-6">
|
<div class="max-w-5xl space-y-6">
|
||||||
|
|
||||||
<!-- Agregar contrato -->
|
<!-- Agregar contrato -->
|
||||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
|
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<h3 class="font-semibold text-gray-800"><i class="fas fa-plus-circle mr-2 text-blue-500"></i>Agregar Contrato</h3>
|
<h3 class="font-semibold text-gray-800"><i class="fas fa-plus-circle mr-2 text-blue-500"></i>Agregar Contrato</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
<form method="POST" action="/contratos/create" class="grid grid-cols-4 gap-3 items-end">
|
<form method="POST" action="/contratos/create" class="grid grid-cols-5 gap-3 items-end">
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-xs font-medium text-gray-600 mb-1">N° Contrato</label>
|
<label class="block text-xs font-medium text-gray-600 mb-1">N° Contrato</label>
|
||||||
<input type="text" name="numero_contrato" required placeholder="Ej: 001"
|
<input type="text" name="numero_contrato" required placeholder="Ej: 001"
|
||||||
@@ -36,7 +36,11 @@
|
|||||||
<input type="text" name="descripcion" placeholder="Ej: EPS SANITAS"
|
<input type="text" name="descripcion" placeholder="Ej: EPS SANITAS"
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-4 flex justify-end">
|
<div class="flex items-end gap-3">
|
||||||
|
<label class="flex items-center gap-1.5 text-xs text-gray-600 mb-2 cursor-pointer">
|
||||||
|
<input type="checkbox" name="excluir" value="1" class="rounded">
|
||||||
|
Excluir TNS
|
||||||
|
</label>
|
||||||
<button type="submit"
|
<button type="submit"
|
||||||
class="px-5 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition-colors">
|
class="px-5 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-lg transition-colors">
|
||||||
<i class="fas fa-plus mr-1"></i> Agregar
|
<i class="fas fa-plus mr-1"></i> Agregar
|
||||||
@@ -63,13 +67,14 @@
|
|||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">NIT Empresa</th>
|
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">NIT Empresa</th>
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">Tipo Usuario</th>
|
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">Tipo Usuario</th>
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">Descripción</th>
|
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">Descripción</th>
|
||||||
|
<th class="px-4 py-3 text-center text-xs font-semibold text-gray-500 uppercase">Envío TNS</th>
|
||||||
<th class="px-4 py-3 text-center text-xs font-semibold text-gray-500 uppercase">Acciones</th>
|
<th class="px-4 py-3 text-center text-xs font-semibold text-gray-500 uppercase">Acciones</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-gray-100">
|
<tbody class="divide-y divide-gray-100">
|
||||||
{% for c in contratos %}
|
{% for c in contratos %}
|
||||||
<tr class="hover:bg-gray-50" id="row-{{ c.id }}">
|
<tr class="hover:bg-gray-50 {% if c.excluir %}bg-red-50{% endif %}" id="row-{{ c.id }}">
|
||||||
<td class="px-4 py-3 font-mono font-semibold text-gray-800">{{ c.numero_contrato }}</td>
|
<td class="px-4 py-3 font-mono font-semibold {% if c.excluir %}text-red-500{% else %}text-gray-800{% endif %}">{{ c.numero_contrato }}</td>
|
||||||
<td class="px-4 py-3 text-gray-600">{{ c.nit_empresa }}</td>
|
<td class="px-4 py-3 text-gray-600">{{ c.nit_empresa }}</td>
|
||||||
<td class="px-4 py-3">
|
<td class="px-4 py-3">
|
||||||
{% set tu = c.tipo_usuario %}
|
{% set tu = c.tipo_usuario %}
|
||||||
@@ -87,7 +92,20 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-3 text-gray-500">{{ c.descripcion }}</td>
|
<td class="px-4 py-3 text-gray-500">{{ c.descripcion }}</td>
|
||||||
<td class="px-4 py-3 text-center">
|
<td class="px-4 py-3 text-center">
|
||||||
<button onclick="openEdit({{ c.id }}, '{{ c.numero_contrato }}', '{{ c.nit_empresa }}', '{{ c.tipo_usuario }}', '{{ c.descripcion }}')"
|
<form method="POST" action="/contratos/toggle-excluir/{{ c.id }}" class="inline">
|
||||||
|
{% if c.excluir %}
|
||||||
|
<button type="submit" class="inline-flex items-center gap-1 px-2.5 py-1 bg-red-100 text-red-700 hover:bg-red-200 rounded-full text-xs font-medium transition-colors">
|
||||||
|
<i class="fas fa-ban text-xs"></i> Excluido
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="submit" class="inline-flex items-center gap-1 px-2.5 py-1 bg-green-100 text-green-700 hover:bg-green-200 rounded-full text-xs font-medium transition-colors">
|
||||||
|
<i class="fas fa-check text-xs"></i> Activo
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-3 text-center">
|
||||||
|
<button onclick="openEdit({{ c.id }}, '{{ c.numero_contrato }}', '{{ c.nit_empresa }}', '{{ c.tipo_usuario }}', '{{ c.descripcion }}', {{ c.excluir }})"
|
||||||
class="text-blue-600 hover:text-blue-800 mr-3 text-xs">
|
class="text-blue-600 hover:text-blue-800 mr-3 text-xs">
|
||||||
<i class="fas fa-edit"></i> Editar
|
<i class="fas fa-edit"></i> Editar
|
||||||
</button>
|
</button>
|
||||||
@@ -100,7 +118,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr><td colspan="5" class="px-4 py-8 text-center text-gray-400">No hay contratos registrados</td></tr>
|
<tr><td colspan="6" class="px-4 py-8 text-center text-gray-400">No hay contratos registrados</td></tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -143,6 +161,10 @@
|
|||||||
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<input type="checkbox" name="excluir" id="edit-excluir" value="1" class="rounded">
|
||||||
|
<label for="edit-excluir" class="text-sm text-gray-700">Excluir del envío TNS</label>
|
||||||
|
</div>
|
||||||
<div class="flex justify-end space-x-3 pt-2">
|
<div class="flex justify-end space-x-3 pt-2">
|
||||||
<button type="button" onclick="closeEdit()"
|
<button type="button" onclick="closeEdit()"
|
||||||
class="px-4 py-2 text-sm text-gray-600 hover:text-gray-800 border border-gray-300 rounded-lg">
|
class="px-4 py-2 text-sm text-gray-600 hover:text-gray-800 border border-gray-300 rounded-lg">
|
||||||
@@ -158,12 +180,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function openEdit(id, nc, nit, tu, desc) {
|
function openEdit(id, nc, nit, tu, desc, excluir) {
|
||||||
document.getElementById('edit-form').action = '/contratos/update/' + id;
|
document.getElementById('edit-form').action = '/contratos/update/' + id;
|
||||||
document.getElementById('edit-nc').value = nc;
|
document.getElementById('edit-nc').value = nc;
|
||||||
document.getElementById('edit-nit').value = nit;
|
document.getElementById('edit-nit').value = nit;
|
||||||
document.getElementById('edit-tu').value = tu;
|
document.getElementById('edit-tu').value = tu;
|
||||||
document.getElementById('edit-desc').value = desc;
|
document.getElementById('edit-desc').value = desc;
|
||||||
|
document.getElementById('edit-excluir').checked = excluir === 1;
|
||||||
document.getElementById('edit-modal').classList.remove('hidden');
|
document.getElementById('edit-modal').classList.remove('hidden');
|
||||||
}
|
}
|
||||||
function closeEdit() {
|
function closeEdit() {
|
||||||
|
|||||||
Reference in New Issue
Block a user