#!/usr/bin/env bash set -Eeuo pipefail ROOT="${ROOT:-/var/www/dhv2.korexlabs.com}" cd "$ROOT" API_URL="${API_URL:-http://127.0.0.1:3101/api/v3}" DB_SERVICE="${DB_SERVICE:-db}" psql_app() { docker compose exec -T "$DB_SERVICE" sh -lc \ 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -At -v ON_ERROR_STOP=1 -v app_user="$APP_DB_USER"' <<<"$1" } echo "========== D5.3.5.1 · VERSIONES ==========" API_VERSION="$(node -p "require('./api-v3/package.json').version")" WEB_VERSION="$(node -p "require('./web-v2/package.json').version")" [[ "$API_VERSION" == "0.19.3-5.1" ]] [[ "$WEB_VERSION" == "0.19.3-5.1" ]] echo "API: $API_VERSION" echo "WEB: $WEB_VERSION" echo echo "========== D5.3.5.1 · MIGRACIONES ==========" MIGRATION_OUTPUT="$(docker compose --profile tools run --rm migrate npm run migration:show 2>&1)" echo "$MIGRATION_OUTPUT" grep -q "Pending migrations: no" <<<"$MIGRATION_OUTPUT" echo echo "========== D5.3.5.1 · HEALTH ==========" HEALTH="$(curl -fsS "$API_URL/health")" echo "$HEALTH" grep -q '"version":"0.19.3-5.1"' <<<"$HEALTH" grep -q '"phase":"D5.3.5.1"' <<<"$HEALTH" echo echo "========== D5.3.5.1 · RUTAS PROTEGIDAS ==========" CODE="$(curl -sS -o /tmp/dhv2-d535-imports.txt -w '%{http_code}' "$API_URL/asset-imports")" [[ "$CODE" == "401" ]] echo "/asset-imports sin sesión: 401 OK" CODE="$(curl -sS -o /tmp/dhv2-d535-tree.txt -w '%{http_code}' "$API_URL/assets/tree-children")" [[ "$CODE" == "401" ]] echo "/assets/tree-children sin sesión: 401 OK" echo echo "========== D5.3.5.1 · MODELO DE IMPORTACIÓN ==========" grep -q 'export interface ImportBatchRow' api-v3/src/asset-imports/asset-imports.service.ts echo "Contrato público ImportBatchRow: OK" [[ "$(psql_app "SELECT COUNT(*) FROM information_schema.tables WHERE table_name IN ('asset_import_batches','asset_import_rows');")" == "2" ]] [[ "$(psql_app "SELECT COUNT(*) FROM pg_type WHERE typname IN ('asset_import_batch_status','asset_import_row_status','asset_import_suggested_action');")" == "3" ]] [[ "$(psql_app "SELECT COUNT(*) FROM permissions WHERE code IN ('asset_imports.read','asset_imports.manage');")" == "2" ]] [[ "$(psql_app "SELECT COUNT(*) FROM pg_indexes WHERE indexname IN ('idx_assets_code_trgm','idx_assets_name_trgm','idx_asset_external_identifiers_value_trgm','idx_asset_attribute_values_text_trgm');")" == "4" ]] [[ "$(psql_app "SELECT COUNT(*) FROM pg_extension WHERE extname='pg_trgm';")" == "1" ]] [[ "$(psql_app "SELECT has_table_privilege(:'app_user','asset_import_batches','SELECT') AND has_table_privilege(:'app_user','asset_import_batches','INSERT') AND has_table_privilege(:'app_user','asset_import_batches','UPDATE');")" == "t" ]] [[ "$(psql_app "SELECT has_table_privilege(:'app_user','asset_import_batches','DELETE');")" == "f" ]] [[ "$(psql_app "SELECT COUNT(*) FROM typeorm_migrations WHERE name='PhaseD535ImportCenterScalability1787594400000';")" == "1" ]] echo "Staging, permisos, pg_trgm y protección contra DELETE: OK" echo echo "========== D5.3.5.1 · PARSER XLSX ==========" docker compose exec -T api sh -lc 'command -v unzip >/dev/null && unzip -v >/dev/null' grep -q 'MAX_ASSET_IMPORT_BYTES' api-v3/src/asset-imports/asset-import-parser.ts grep -q 'MENDOZA_INVENTORY_V1' api-v3/src/asset-imports/asset-import-profiles.ts grep -q 'MENDOZA_YACIMIENTOS_V1' api-v3/src/asset-imports/asset-import-profiles.ts grep -q 'INVENTORY_ID_MULTIPLE_LOCATIONS' api-v3/src/asset-imports/asset-import-profiles.ts echo "Parser XLSX/CSV, perfiles y conflictos: OK" echo echo "========== D5.3.5.1 · NO MODIFICA EL MAESTRO ==========" grep -q 'INSERT INTO asset_import_batches' api-v3/src/asset-imports/asset-imports.service.ts ! grep -Eq 'INSERT INTO assets[[:space:]]*\\(' api-v3/src/asset-imports/asset-imports.service.ts ! grep -Eq 'UPDATE assets[[:space:]]+SET' api-v3/src/asset-imports/asset-imports.service.ts echo "El Centro de Importaciones sólo analiza/stagea: OK" echo echo "========== D5.3.5.1 · ASSET CENTER ESCALABLE ==========" grep -q "@Get('tree-children')" api-v3/src/asset-master/assets.controller.ts grep -q 'listAssetTreeChildren' web-v2/src/features/assets/AssetHierarchyView.tsx ! grep -q 'listAssetTree(' web-v2/src/features/assets/AssetHierarchyView.tsx grep -q 'Los hijos se cargan recién al expandir' web-v2/src/features/assets/AssetHierarchyView.tsx echo "Jerarquía lazy-loading: OK" echo echo "========== D5.3.5.1 · DASHBOARD ==========" grep -q 'Centro de importaciones' web-v2/src/pages/AssetImportsPage.tsx grep -q 'No crea ni modifica activos' web-v2/src/pages/AssetImportsPage.tsx grep -q "path=\"/importaciones\"" web-v2/src/app/App.tsx grep -q "label: 'Importaciones'" web-v2/src/layout/AppLayout.tsx grep -q '0.19.3-5.1' web-v2/src/config/version.ts echo "Centro de Importaciones y navegación: OK" echo echo "========== D5.3.5.1 · CONTENEDORES ==========" docker compose ps -a echo echo "ACEPTACIÓN DE FASE D5.3.5.1: OK"