From 63694eccb165ac60e8b4941f410193c93ad74c96 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Thu, 4 Jun 2026 06:10:25 -0400 Subject: [PATCH] =?UTF-8?q?fix(scripts):=20verify=5Fservice=5Fbooking=20?= =?UTF-8?q?=E2=80=94=20general=20orphan-FK=20sweep=20+=20test=20port=20fix?= =?UTF-8?q?=20+=20scoped=20tags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardened after the first real clone-verify on odoo-westin: - Cleanup now generates an orphan-delete for EVERY single-column FK from PROD's pg_constraint and applies it to the clone (was tax-tables-only). westin-v19 also has deleted-company (payslip_tags_table, account_account_res_company_rel) and deleted-journal (account_payment_method_line) orphans that broke the clone -u. - run_odoo passes --http-port=0 --gevent-port=0 so --test-enable (which forces http_spawn even with --no-http in Odoo 19) doesn't die on 'Address already in use'. - TEST_TAGS scoped to this feature's classes (the broad tag also runs pre-existing dashboard/wizard tests that fail in this prod-config runner, unrelated to this work). Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/verify_service_booking.sh | 37 ++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/scripts/verify_service_booking.sh b/scripts/verify_service_booking.sh index 73f7415e..99ae0ec6 100755 --- a/scripts/verify_service_booking.sh +++ b/scripts/verify_service_booking.sh @@ -37,7 +37,11 @@ PGPW="${PGPW:-DevSecure2025!}" PGUSER="${PGUSER:-odoo}" MODULES="${MODULES:-fusion_tasks,fusion_claims}" # comma list for -u -TEST_TAGS="${TEST_TAGS:-/fusion_tasks,/fusion_claims}" +# Scope to THIS feature's test classes — the broad /fusion_claims tag also runs +# pre-existing dashboard/wizard tests that fail in this prod-config runner +# (CLAUDE.md fusion_repairs note: post_install trips on a pre-existing module), +# which is unrelated to this feature. Override TEST_TAGS to widen if desired. +TEST_TAGS="${TEST_TAGS:-/fusion_tasks:TestTaskTz,/fusion_claims:TestServiceRate,/fusion_claims:TestServiceBooking}" MOD_DIRS=(fusion_tasks fusion_claims) # dirs to stage/deploy BRANCH="${BRANCH:-claude/technician-service-booking}" @@ -91,17 +95,21 @@ dexec -e PGPASSWORD="$PGPW" "$DBC" sh -c \ >>"$LOG" 2>&1 ok "Cloned." -# ----------------------------- 2. ORPHAN-TAX-FK CLEANUP (clone only) --------- -# westin-v19 has ~3300 orphaned tax m2m rows under validated FKs; a plain -# pg_dump|psql clone can't rebuild the validating FK over them -> Odoo fails to -# load the registry. Safe to delete ON THE CLONE only. (CLAUDE.md gotcha.) -c "Orphaned-tax-FK cleanup (clone only)" -psql_clone -c "DELETE FROM product_taxes_rel WHERE tax_id NOT IN (SELECT id FROM account_tax);" >>"$LOG" 2>&1 || true -psql_clone -c "DELETE FROM product_supplier_taxes_rel WHERE tax_id NOT IN (SELECT id FROM account_tax);" >>"$LOG" 2>&1 || true -# sweep any other %_rel table carrying a tax_id column -psql_clone -t -A -c "SELECT table_name FROM information_schema.columns WHERE column_name='tax_id' AND table_name LIKE '%\\_rel';" 2>/dev/null \ - | while read -r t; do [[ -n "$t" ]] && psql_clone -c "DELETE FROM ${t} WHERE tax_id NOT IN (SELECT id FROM account_tax);" >>"$LOG" 2>&1 || true; done -ok "Orphan FKs cleared on clone." +# ----------------------------- 2. ORPHANED-FK CLEANUP (clone only) ----------- +# westin-v19 has orphaned rows under VALIDATED FKs (deleted taxes, companies, +# journals, ...). A plain pg_dump|psql clone cannot rebuild a validating FK over +# orphans, so the clone is MISSING those FKs; Odoo's check_foreign_keys then +# re-adds them and fails (e.g. payslip_tags_table.res_company_id=3, +# account_payment_method_line.journal_id=35). Generate an orphan-delete for EVERY +# single-column FK that exists on PROD (read-only SELECT on prod) and apply it to +# the clone. The clone is a throwaway; prod is never modified. +# (CLAUDE.md orphan-FK gotcha, generalised beyond the tax tables.) +c "Orphaned-FK cleanup (clone only) — general sweep from prod's FK definitions" +FKSQL="/tmp/svcbook_fkclean_${STAMP}.sql" +printf '%s\n' '\set ON_ERROR_STOP off' > "$FKSQL" +dexec -e PGPASSWORD="$PGPW" "$DBC" psql -U "$PGUSER" -d "$PROD_DB" -t -A -c "SELECT format('DELETE FROM %I a WHERE a.%I IS NOT NULL AND NOT EXISTS (SELECT 1 FROM %I b WHERE b.%I = a.%I);', src.relname, srcatt.attname, tgt.relname, tgtatt.attname, srcatt.attname) FROM pg_constraint con JOIN pg_class src ON src.oid=con.conrelid JOIN pg_namespace ns ON ns.oid=src.relnamespace AND ns.nspname='public' JOIN pg_class tgt ON tgt.oid=con.confrelid JOIN pg_attribute srcatt ON srcatt.attrelid=con.conrelid AND srcatt.attnum=con.conkey[1] JOIN pg_attribute tgtatt ON tgtatt.attrelid=con.confrelid AND tgtatt.attnum=con.confkey[1] WHERE con.contype='f' AND array_length(con.conkey,1)=1;" >> "$FKSQL" 2>>"$LOG" || true +dexec -i -e PGPASSWORD="$PGPW" "$DBC" psql -U "$PGUSER" -d "$CLONE_DB" < "$FKSQL" >>"$LOG" 2>&1 || true +ok "Orphan FKs cleared on clone (general sweep, $(grep -c '^DELETE' "$FKSQL" 2>/dev/null || echo 0) FK relations)." # ----------------------------- 3. STAGE MODULES (shadow) --------------------- c "Stage modules into $STAGE (shadows prod, prod files untouched)" @@ -114,9 +122,12 @@ ok "Staged: ${MOD_DIRS[*]}" # --test-enable SILENTLY SKIPS without --workers 0; log_level=warn hides test # output -> add --log-level=test. The EXIT CODE is authoritative. run_odoo() { # $1 = extra args + # --test-enable forces http_spawn() even with --no-http (Odoo 19), so the test + # run binds 8069 (held by the live app) and dies with "Address already in use". + # --http-port=0 --gevent-port=0 makes it pick ephemeral ports. (CLAUDE.md gotcha.) dexec "$APP" odoo -d "$CLONE_DB" \ --db_host db --db_port 5432 --db_user "$PGUSER" --db_password "$PGPW" \ - --addons-path="$ADDONS_PATH" --stop-after-init --no-http $1 + --addons-path="$ADDONS_PATH" --stop-after-init --no-http --http-port=0 --gevent-port=0 $1 } c "Install/upgrade on clone (catches install/render errors)"