#!/usr/bin/env bash # Pruebas del inventario por sitio (23-oct): arranca app.py con carpetas temporales. # Uso: bash tests-1023.sh [puerto] set -u REPO=${1:?ruta a hbox-docs}; PORT=${2:-8095} T=$(mktemp -d); export ACTAS_DIR=$T/actas PORT mkdir -p $ACTAS_DIR python3 $REPO/backend/app.py > $T/app.log 2>&1 & APP=$!; trap "kill $APP 2>/dev/null" EXIT; sleep 1.5 U="http://127.0.0.1:$PORT" LEO=(-s -H "X-Remote-User: leo" -H "Content-Type: application/json") ok=0; fail=0 check() { if [[ "$3" == *"$2"* ]]; then ok=$((ok+1)); echo " ✓ $1"; else fail=$((fail+1)); echo " ✕ $1 — esperaba «$2», obtuve: ${3:0:200}"; fi; } mov() { curl "${LEO[@]}" -X POST $U/api/inventario/movimiento -d "$1"; } inv() { curl "${LEO[@]}" $U/api/inventario; } py() { python3 -c "import sys,json; j=json.load(sys.stdin); $1"; } echo "## ítems y kit" check "alta GAB con kit 1" '"por_instalacion":1' "$(curl "${LEO[@]}" -X POST $U/api/inventario -d '{"codigo":"GAB-IP67","descripcion":"Gabinete IP67","categoria":"gabinete","por_instalacion":1}')" check "alta soporte (instalación) con stock inicial en LCT" '"ok":true' "$(curl "${LEO[@]}" -X POST $U/api/inventario -d '{"codigo":"SOP-RTG","descripcion":"Soporte para RTG","categoria":"instalacion","por_instalacion":1,"stock_inicial":2,"sitio":"lct"}')" check "categoría instalacion aceptada" '"instalacion"' "$(inv)" echo "## entrada, envío, recepción" check "entrada sin sitio = Querétaro" '"sitio":"qro"' "$(mov '{"item_id":"GAB-IP67","tipo":"entrada","cantidad":10,"motivo":"compra"}')" check "envío QRO → EIT" '"estado":"en-camino"' "$(mov '{"item_id":"GAB-IP67","tipo":"envio","cantidad":3,"sitio":"qro","destino":"Ensenada","motivo":"kit EIT","referencia":"guía 123"}')" R=$(inv) check "QRO baja a 7" "7" "$(echo "$R" | py 'print([i["por_sitio"].get("qro") for i in j["items"] if i["codigo"]=="GAB-IP67"][0])')" check "3 en camino a EIT" "3" "$(echo "$R" | py 'print([i["en_camino"].get("eit") for i in j["items"] if i["codigo"]=="GAB-IP67"][0])')" check "total sigue en 10" "10" "$(echo "$R" | py 'print([i["stock"] for i in j["items"] if i["codigo"]=="GAB-IP67"][0])')" check "lista de envíos abiertos" '"destino": "eit"' "$(echo "$R" | py 'print(json.dumps(j["envios"]))')" EID=$(echo "$R" | py 'print(j["envios"][0]["id"])') check "salida en EIT sin stock → 409" "hay 0" "$(mov '{"item_id":"GAB-IP67","tipo":"salida","cantidad":1,"sitio":"eit","motivo":"instalación"}')" check "recibir de más → 400" "no pueden llegar m" "$(mov '{"tipo":"recepcion","envio_id":"'$EID'","cantidad":5}')" check "recibir 2 de 3" '"sitio":"eit"' "$(mov '{"tipo":"recepcion","envio_id":"'$EID'","cantidad":2}')" R=$(inv) check "EIT tiene 2" "2" "$(echo "$R" | py 'print([i["por_sitio"].get("eit") for i in j["items"] if i["codigo"]=="GAB-IP67"][0])')" check "ya no va en camino" "{}" "$(echo "$R" | py 'print(json.dumps([i["en_camino"] for i in j["items"] if i["codigo"]=="GAB-IP67"][0]))')" check "el que no llegó baja del total (9)" "9" "$(echo "$R" | py 'print([i["stock"] for i in j["items"] if i["codigo"]=="GAB-IP67"][0])')" check "recibir otra vez → 409" "ya se recib" "$(mov '{"tipo":"recepcion","envio_id":"'$EID'"}')" check "salida en EIT con stock" '"en_sitio_despues":1' "$(mov '{"item_id":"GAB-IP67","tipo":"salida","cantidad":1,"sitio":"eit","motivo":"instalación","referencia":"HBOX5-E07-A010-R0006"}')" echo "## conteo físico por sitio" check "conteo en LCT = 4 (había 2 del alta)" '"en_sitio_despues":4' "$(mov '{"item_id":"SOP-RTG","tipo":"ajuste","cantidad":4,"sitio":"lzc","motivo":"conteo"}')" check "el total del soporte sube a 4" "4" "$(inv | py 'print([i["stock"] for i in j["items"] if i["codigo"]=="SOP-RTG"][0])')" echo "## errores" check "sitio inválido" "Sitio inv" "$(mov '{"item_id":"GAB-IP67","tipo":"entrada","cantidad":1,"sitio":"marte","motivo":"x"}')" check "envío al mismo sitio" "otro sitio" "$(mov '{"item_id":"GAB-IP67","tipo":"envio","cantidad":1,"sitio":"qro","destino":"qro","motivo":"x"}')" check "envío sin destino" "Elige a qu" "$(mov '{"item_id":"GAB-IP67","tipo":"envio","cantidad":1,"sitio":"qro","motivo":"x"}')" check "envío sin stock en el origen (sugiere «fuera»)" "fuera del inventario" "$(mov '{"item_id":"GAB-IP67","tipo":"envio","cantidad":50,"sitio":"qro","destino":"timsa","motivo":"x"}')" check "salida desde «fuera» no se acepta" "Sitio inv" "$(mov '{"item_id":"GAB-IP67","tipo":"salida","cantidad":1,"sitio":"fuera","motivo":"x"}')" echo "## envío de fuera del inventario (compra en camino, o material que salió antes de contarlo)" check "alta antena LTE con kit 2" '"por_instalacion":2' "$(curl "${LEO[@]}" -X POST $U/api/inventario -d '{"codigo":"ANT-LTE","descripcion":"Antena LTE","categoria":"antena","por_instalacion":2}')" check "envío desde fuera a EIT" '"sitio":"fuera"' "$(mov '{"item_id":"ANT-LTE","tipo":"envio","cantidad":4,"sitio":"proveedor","destino":"eit","motivo":"salió de Manzanillo antes del conteo","referencia":"guía 999"}')" R=$(inv) check "entra al total desde ya (4)" "4" "$(echo "$R" | py 'print([i["stock"] for i in j["items"] if i["codigo"]=="ANT-LTE"][0])')" check "no aparece en ningún sitio" "{}" "$(echo "$R" | py 'print(json.dumps([i["por_sitio"] for i in j["items"] if i["codigo"]=="ANT-LTE"][0]))')" check "va en camino a EIT" '{"eit": 4}' "$(echo "$R" | py 'print(json.dumps([i["en_camino"] for i in j["items"] if i["codigo"]=="ANT-LTE"][0]))')" EF=$(echo "$R" | py 'print([e["id"] for e in j["envios"] if e["codigo"]=="ANT-LTE"][0])') check "el envío abierto dice origen fuera" '"origen": "fuera"' "$(echo "$R" | py 'print(json.dumps([e for e in j["envios"] if e["codigo"]=="ANT-LTE"][0]))')" check "recibir las 4 en EIT" '"en_sitio_despues":4' "$(mov '{"tipo":"recepcion","envio_id":"'$EF'"}')" R=$(inv) check "EIT tiene 4 y el total sigue en 4" "4 4" "$(echo "$R" | py 'i=[i for i in j["items"] if i["codigo"]=="ANT-LTE"][0]; print(i["por_sitio"].get("eit"), i["stock"])')" echo "## consultas" check "movimientos de EIT (el envío y su recepción)" "recepcion" "$(curl "${LEO[@]}" "$U/api/inventario/movimientos?sitio=eit")" check "CSV con columna por sitio" "en_eit" "$(curl "${LEO[@]}" $U/api/inventario/export.csv | head -1)" check "CSV con la existencia en EIT" "GAB-IP67" "$(curl "${LEO[@]}" $U/api/inventario/export.csv)" echo echo "RESULTADO: $ok correctas · $fail fallidas · datos en $T"