Una pestaña por sitio (ICAVE, TIMSA, EIT, LCT, Querétaro): lo que hay, lo que va en camino y lo que falta del kit para instalar. Movimientos con sitio, envío/recepción, origen «fuera». Lote 2026-10-23_inventario-sitios. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016X4CAujMuib2tDqt9JRg6X
67 lines
6.2 KiB
Bash
67 lines
6.2 KiB
Bash
#!/usr/bin/env bash
|
|
# Pruebas del inventario por sitio (23-oct): arranca app.py con carpetas temporales.
|
|
# Uso: bash tests-1023.sh <ruta-a-hbox-docs> [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"
|