Skip to content

Commit 9ef2d73

Browse files
committed
Refactor database seeding scripts and improve error handling
- Updated `gen_fix_seed.js` to maintain original positional insert for payroll_calculations and align disposal_vouchers and disposal_voucher_items mappings with legacy export order. - Modified `init-db-and-seed.sh` to allow fallback to legacy seed file if the primary seed file is missing, and added checks to prevent seeding with legacy mock patch markers. - Enhanced `reset-db-and-seed.sh` to enforce strict error handling during seeding, ensuring that legacy mock patch markers are not present in seed files, and improved logging for better traceability. - Removed legacy fallback logic and streamlined seeding strategy to focus on either fix-only or data-only approaches, ensuring critical tables are populated correctly.
1 parent 297cad5 commit 9ef2d73

File tree

7 files changed

+270
-195
lines changed

7 files changed

+270
-195
lines changed

.github/workflows/cd.yml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,17 +335,21 @@ jobs:
335335
PRODUCTS_COUNT="$(get_table_count products || echo 0)"
336336
VARIANTS_COUNT="$(get_table_count product_variants || echo 0)"
337337
STOCK_COUNT="$(get_table_count inventory_stock || echo 0)"
338+
SALE_ORDERS_COUNT="$(get_table_count sale_orders || echo 0)"
339+
SALE_ORDER_ITEMS_COUNT="$(get_table_count sale_order_items || echo 0)"
340+
TICKETS_COUNT="$(get_table_count tickets || echo 0)"
341+
LOYALTY_GIFTS_COUNT="$(get_table_count loyalty_gifts || echo 0)"
338342
refresh_integrity_metrics
339343
SEED_WAS_RUN=0
340344
341-
echo "Post-deploy counts: products=$PRODUCTS_COUNT, variants=$VARIANTS_COUNT, inventory_stock=$STOCK_COUNT"
345+
echo "Post-deploy counts: products=$PRODUCTS_COUNT, variants=$VARIANTS_COUNT, inventory_stock=$STOCK_COUNT, sale_orders=$SALE_ORDERS_COUNT, sale_order_items=$SALE_ORDER_ITEMS_COUNT, tickets=$TICKETS_COUNT, loyalty_gifts=$LOYALTY_GIFTS_COUNT"
342346
echo "Post-deploy integrity: joinable_variants=$JOINABLE_VARIANTS_COUNT, orphan_product_refs=$ORPHAN_PRODUCT_REFS, orphan_unit_refs=$ORPHAN_UNIT_REFS, stocked_variants=$STOCKED_VARIANTS_COUNT"
343347
344-
if [ "${PRODUCTS_COUNT:-0}" = "0" ] || [ "${VARIANTS_COUNT:-0}" = "0" ] || is_integrity_bad "$STOCK_COUNT"; then
348+
if [ "${PRODUCTS_COUNT:-0}" = "0" ] || [ "${VARIANTS_COUNT:-0}" = "0" ] || [ "${STOCK_COUNT:-0}" = "0" ] || [ "${SALE_ORDERS_COUNT:-0}" = "0" ] || [ "${SALE_ORDER_ITEMS_COUNT:-0}" = "0" ] || [ "${TICKETS_COUNT:-0}" = "0" ] || [ "${LOYALTY_GIFTS_COUNT:-0}" = "0" ] || is_integrity_bad "$STOCK_COUNT"; then
345349
echo "Detected empty or inconsistent critical product data. Running reset-db-and-seed.sh..."
346350
if [ -f "./deploy/scripts/reset-db-and-seed.sh" ]; then
347351
sudo chmod +x ./deploy/scripts/reset-db-and-seed.sh
348-
sudo DEPLOY_PATH="$DEPLOY_PATH" COMPOSE_FILE="$DEPLOY_PATH/docker-compose.prod.yml" ENV_FILE="$ENV_FILE" SEED_STRATEGY="fix-first" ENABLE_LEGACY_FALLBACK="false" bash ./deploy/scripts/reset-db-and-seed.sh
352+
sudo DEPLOY_PATH="$DEPLOY_PATH" COMPOSE_FILE="$DEPLOY_PATH/docker-compose.prod.yml" ENV_FILE="$ENV_FILE" SEED_STRATEGY="fix-only" bash ./deploy/scripts/reset-db-and-seed.sh
349353
SEED_WAS_RUN=1
350354
# Ensure services are up after seed
351355
compose_cmd up -d --remove-orphans
@@ -357,13 +361,17 @@ jobs:
357361
PRODUCTS_COUNT_FINAL="$(get_table_count products || echo 0)"
358362
VARIANTS_COUNT_FINAL="$(get_table_count product_variants || echo 0)"
359363
STOCK_COUNT_FINAL="$(get_table_count inventory_stock || echo 0)"
364+
SALE_ORDERS_COUNT_FINAL="$(get_table_count sale_orders || echo 0)"
365+
SALE_ORDER_ITEMS_COUNT_FINAL="$(get_table_count sale_order_items || echo 0)"
366+
TICKETS_COUNT_FINAL="$(get_table_count tickets || echo 0)"
367+
LOYALTY_GIFTS_COUNT_FINAL="$(get_table_count loyalty_gifts || echo 0)"
360368
refresh_integrity_metrics
361-
echo "Post-start final counts: products=$PRODUCTS_COUNT_FINAL, variants=$VARIANTS_COUNT_FINAL, inventory_stock=$STOCK_COUNT_FINAL"
369+
echo "Post-start final counts: products=$PRODUCTS_COUNT_FINAL, variants=$VARIANTS_COUNT_FINAL, inventory_stock=$STOCK_COUNT_FINAL, sale_orders=$SALE_ORDERS_COUNT_FINAL, sale_order_items=$SALE_ORDER_ITEMS_COUNT_FINAL, tickets=$TICKETS_COUNT_FINAL, loyalty_gifts=$LOYALTY_GIFTS_COUNT_FINAL"
362370
echo "Post-start final integrity: joinable_variants=$JOINABLE_VARIANTS_COUNT, orphan_product_refs=$ORPHAN_PRODUCT_REFS, orphan_unit_refs=$ORPHAN_UNIT_REFS, stocked_variants=$STOCKED_VARIANTS_COUNT"
363371
364-
if [ "${PRODUCTS_COUNT_FINAL:-0}" = "0" ] || [ "${VARIANTS_COUNT_FINAL:-0}" = "0" ] || is_integrity_bad "$STOCK_COUNT_FINAL"; then
365-
echo "ERROR: Critical product data is still inconsistent after deploy + seed."
366-
echo "Diagnostics: products=$PRODUCTS_COUNT_FINAL, variants=$VARIANTS_COUNT_FINAL, stock=$STOCK_COUNT_FINAL, joinable_variants=$JOINABLE_VARIANTS_COUNT, orphan_product_refs=$ORPHAN_PRODUCT_REFS, orphan_unit_refs=$ORPHAN_UNIT_REFS, stocked_variants=$STOCKED_VARIANTS_COUNT"
372+
if [ "${PRODUCTS_COUNT_FINAL:-0}" = "0" ] || [ "${VARIANTS_COUNT_FINAL:-0}" = "0" ] || [ "${STOCK_COUNT_FINAL:-0}" = "0" ] || [ "${SALE_ORDERS_COUNT_FINAL:-0}" = "0" ] || [ "${SALE_ORDER_ITEMS_COUNT_FINAL:-0}" = "0" ] || [ "${TICKETS_COUNT_FINAL:-0}" = "0" ] || [ "${LOYALTY_GIFTS_COUNT_FINAL:-0}" = "0" ] || is_integrity_bad "$STOCK_COUNT_FINAL"; then
373+
echo "ERROR: Critical seed data is still inconsistent after deploy + seed."
374+
echo "Diagnostics: products=$PRODUCTS_COUNT_FINAL, variants=$VARIANTS_COUNT_FINAL, stock=$STOCK_COUNT_FINAL, sale_orders=$SALE_ORDERS_COUNT_FINAL, sale_order_items=$SALE_ORDER_ITEMS_COUNT_FINAL, tickets=$TICKETS_COUNT_FINAL, loyalty_gifts=$LOYALTY_GIFTS_COUNT_FINAL, joinable_variants=$JOINABLE_VARIANTS_COUNT, orphan_product_refs=$ORPHAN_PRODUCT_REFS, orphan_unit_refs=$ORPHAN_UNIT_REFS, stocked_variants=$STOCKED_VARIANTS_COUNT"
367375
compose_cmd logs --tail=150 mysql backend || true
368376
exit 1
369377
fi

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,10 @@ File docker-compose.prod.yml dùng image:
100100
- docker.io/<IMAGE_NAMESPACE>/smalltrend-frontend:<IMAGE_TAG>
101101

102102
## Lưu ý quan trọng về seed
103-
Đã chuẩn hóa nhiều đoạn INSERT trong backend/src/main/resources/data.sql theo kiểu có danh sách cột để tránh lỗi lệch thứ tự cột giữa các máy.
103+
Seed mặc định hiện tại dùng `deploy/fix_seed.sql` (được generate từ `backend/src/main/resources/data.sql` để map đúng cột cho các bảng dễ lệch schema).
104104
Nếu gặp lỗi seed sau khi pull code mới:
105-
1. Xóa và tạo lại DB nhỏ gọn
106-
2. Chạy lại run-seed.cmd
105+
1. Regenerate file seed chuẩn: `node deploy/gen_fix_seed.js`
106+
2. Chạy lại `backend/run-seed.cmd` (script sẽ tự verify các bảng trọng yếu như products, variants, tickets, loyalty_gifts, sale_orders)
107107

108108
## Tài liệu bổ sung
109109
- PRODUCTION_SETUP_STEPS.md

backend/run-seed.cmd

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@echo off
2-
setlocal
2+
setlocal EnableExtensions DisableDelayedExpansion
33
chcp 65001 >nul
44

55
echo ==============================================
@@ -33,13 +33,21 @@ if not defined DB_USERNAME set "DB_USERNAME=root"
3333
set "DB_PASSWORD=%DB_PASSWORD%"
3434
if not defined DB_PASSWORD set "DB_PASSWORD=1234"
3535

36-
set "SEED_FILE=src\main\resources\data.sql"
36+
set "SEED_FILE=..\deploy\fix_seed.sql"
37+
if not exist "%SEED_FILE%" set "SEED_FILE=src\main\resources\data.sql"
3738

3839
if not exist "%SEED_FILE%" (
3940
echo [ERROR] Seed file not found: %SEED_FILE%
4041
exit /b 1
4142
)
4243

44+
findstr /C:"DỮ LIỆU BÙ ĐẮP CHO CÁC BẢNG BỊ LỖI SCHEMA TRANSACTIONS" "%SEED_FILE%" >nul 2>nul
45+
if not errorlevel 1 (
46+
echo [ERROR] Seed file contains legacy mock patch block and is not allowed.
47+
echo [HINT] Regenerate deploy\fix_seed.sql using: node deploy\gen_fix_seed.js
48+
exit /b 1
49+
)
50+
4351
set "MYSQL_EXE=mysql"
4452
where mysql >nul 2>nul
4553
if errorlevel 1 (
@@ -60,6 +68,7 @@ if not defined MYSQL_EXE (
6068
)
6169

6270
echo [INFO] Target DB: %DB_NAME% at %DB_HOST%:%DB_PORT%
71+
echo [INFO] Seed file: %SEED_FILE%
6372

6473
set "MYSQL_PWD=%DB_PASSWORD%"
6574

@@ -70,15 +79,85 @@ if errorlevel 1 (
7079
exit /b 1
7180
)
7281

73-
"%MYSQL_EXE%" --default-character-set=utf8mb4 -h%DB_HOST% -P%DB_PORT% -u%DB_USERNAME% %DB_NAME% < "%SEED_FILE%" >nul
82+
"%MYSQL_EXE%" --default-character-set=utf8mb4 -h%DB_HOST% -P%DB_PORT% -u%DB_USERNAME% %DB_NAME% < "%SEED_FILE%"
7483
if errorlevel 1 (
7584
echo [ERROR] Failed to import seed file into %DB_NAME%.
7685
set "MYSQL_PWD="
7786
exit /b 1
7887
)
7988

89+
call :query_scalar "SELECT COUNT(*) FROM users;" USERS_COUNT
90+
call :query_scalar "SELECT COUNT(*) FROM products;" PRODUCTS_COUNT
91+
call :query_scalar "SELECT COUNT(*) FROM product_variants;" VARIANTS_COUNT
92+
call :query_scalar "SELECT COUNT(*) FROM inventory_stock;" STOCK_COUNT
93+
call :query_scalar "SELECT COUNT(*) FROM sale_orders;" SALE_ORDERS_COUNT
94+
call :query_scalar "SELECT COUNT(*) FROM sale_order_items;" SALE_ORDER_ITEMS_COUNT
95+
call :query_scalar "SELECT COUNT(*) FROM tickets;" TICKETS_COUNT
96+
call :query_scalar "SELECT COUNT(*) FROM loyalty_gifts;" LOYALTY_GIFTS_COUNT
97+
call :query_scalar "SELECT COUNT(*) FROM product_variants pv LEFT JOIN products p ON p.id = pv.product_id LEFT JOIN units u ON u.id = pv.unit_id WHERE p.id IS NOT NULL AND u.id IS NOT NULL;" JOINABLE_VARIANTS_COUNT
98+
call :query_scalar "SELECT COUNT(*) FROM product_variants pv LEFT JOIN products p ON p.id = pv.product_id WHERE p.id IS NULL;" ORPHAN_PRODUCT_REFS
99+
call :query_scalar "SELECT COUNT(*) FROM product_variants pv LEFT JOIN units u ON u.id = pv.unit_id WHERE u.id IS NULL;" ORPHAN_UNIT_REFS
100+
call :query_scalar "SELECT COUNT(DISTINCT variant_id) FROM inventory_stock WHERE COALESCE(quantity, 0) > 0;" STOCKED_VARIANTS_COUNT
101+
102+
if not defined USERS_COUNT set "USERS_COUNT=0"
103+
if not defined PRODUCTS_COUNT set "PRODUCTS_COUNT=0"
104+
if not defined VARIANTS_COUNT set "VARIANTS_COUNT=0"
105+
if not defined STOCK_COUNT set "STOCK_COUNT=0"
106+
if not defined SALE_ORDERS_COUNT set "SALE_ORDERS_COUNT=0"
107+
if not defined SALE_ORDER_ITEMS_COUNT set "SALE_ORDER_ITEMS_COUNT=0"
108+
if not defined TICKETS_COUNT set "TICKETS_COUNT=0"
109+
if not defined LOYALTY_GIFTS_COUNT set "LOYALTY_GIFTS_COUNT=0"
110+
if not defined JOINABLE_VARIANTS_COUNT set "JOINABLE_VARIANTS_COUNT=0"
111+
if not defined ORPHAN_PRODUCT_REFS set "ORPHAN_PRODUCT_REFS=0"
112+
if not defined ORPHAN_UNIT_REFS set "ORPHAN_UNIT_REFS=0"
113+
if not defined STOCKED_VARIANTS_COUNT set "STOCKED_VARIANTS_COUNT=0"
114+
115+
echo [INFO] Seed verification counts:
116+
echo users=%USERS_COUNT%, products=%PRODUCTS_COUNT%, variants=%VARIANTS_COUNT%, inventory_stock=%STOCK_COUNT%
117+
echo sale_orders=%SALE_ORDERS_COUNT%, sale_order_items=%SALE_ORDER_ITEMS_COUNT%, tickets=%TICKETS_COUNT%, loyalty_gifts=%LOYALTY_GIFTS_COUNT%
118+
echo joinable_variants=%JOINABLE_VARIANTS_COUNT%, orphan_product_refs=%ORPHAN_PRODUCT_REFS%, orphan_unit_refs=%ORPHAN_UNIT_REFS%, stocked_variants=%STOCKED_VARIANTS_COUNT%
119+
120+
if "%USERS_COUNT%"=="0" goto :seed_invalid
121+
if "%PRODUCTS_COUNT%"=="0" goto :seed_invalid
122+
if "%VARIANTS_COUNT%"=="0" goto :seed_invalid
123+
if "%STOCK_COUNT%"=="0" goto :seed_invalid
124+
if "%SALE_ORDERS_COUNT%"=="0" goto :seed_invalid
125+
if "%SALE_ORDER_ITEMS_COUNT%"=="0" goto :seed_invalid
126+
if "%TICKETS_COUNT%"=="0" goto :seed_invalid
127+
if "%LOYALTY_GIFTS_COUNT%"=="0" goto :seed_invalid
128+
if "%JOINABLE_VARIANTS_COUNT%"=="0" goto :seed_invalid
129+
if not "%ORPHAN_PRODUCT_REFS%"=="0" goto :seed_invalid
130+
if not "%ORPHAN_UNIT_REFS%"=="0" goto :seed_invalid
131+
if "%STOCKED_VARIANTS_COUNT%"=="0" goto :seed_invalid
132+
80133
set "MYSQL_PWD="
81134

82135
echo.
83136
echo [SUCCESS] Seed completed for database %DB_NAME%.
84137
exit /b 0
138+
139+
:query_scalar
140+
setlocal
141+
set "QUERY=%~1"
142+
set "OUT_VAR=%~2"
143+
set "TMP_FILE=%TEMP%\smalltrend_seed_%RANDOM%_%RANDOM%.tmp"
144+
145+
"%MYSQL_EXE%" --default-character-set=utf8mb4 -h%DB_HOST% -P%DB_PORT% -u%DB_USERNAME% -N -s %DB_NAME% -e "%QUERY%" > "%TMP_FILE%" 2>nul
146+
if errorlevel 1 (
147+
if exist "%TMP_FILE%" del "%TMP_FILE%" >nul 2>nul
148+
endlocal & set "%~2=0"
149+
goto :eof
150+
)
151+
152+
set "VALUE="
153+
if exist "%TMP_FILE%" set /p VALUE=<"%TMP_FILE%"
154+
if exist "%TMP_FILE%" del "%TMP_FILE%" >nul 2>nul
155+
if not defined VALUE set "VALUE=0"
156+
157+
endlocal & set "%~2=%VALUE%"
158+
goto :eof
159+
160+
:seed_invalid
161+
echo [ERROR] Seed completed but validation failed. Database is inconsistent.
162+
set "MYSQL_PWD="
163+
exit /b 1

0 commit comments

Comments
 (0)