apps/api/scripts/legacy-import/ reads the legacy MySQL (read only) and merges into the target Postgres. Every rule is from docs/DATA-MIGRATION-MAP.md, and each step cites its section. It covers cities, roles and permissions, branches, admin users, sales experts, workshops, customers, brands, categories, products, variants, product images, orders, the ledger, favourites, custom orders and a reconciliation report. Key rules: - Debt is rebuilt from legacy's own formula (updateRemain): delivered orders minus confirmed type 1-4 documents. Type 9 «سفارش» documents mirror orders and are skipped, or every order's debt would count twice. A balance the records cannot explain is carried as one ADJUSTMENT entry. In the 2026-10-04 dump that is only customer #125 (owner ruling). - Merge, not import: rows already in the target are matched by mobile or product code, and only their empty fields are filled. Never written: accounting* columns, ProductVariant.imageId, Accounting* tables. No ProductImage is ever deleted. - Roles map by title, not number. Legacy 86 is «حسابدار» but target 86 is «کارشناس فروش». An expert sharing a mobile with an admin never demotes the admin. - Soft-deleted variants and products that live order lines still point at (473 of 610 lines) come over inactive, so order history stays whole. - Owner rulings 2026-10-07: birthdays filtered (541 of 915), typed city kept plus exact-match cityId, the 7 legacy rejections get the sentinel reason, OTP-only accounts get OTP_ONLY_PASSWORD_HASH. - Tehran wall-clock timestamps are converted with ICU rules, including Iran's pre-2022 DST. Jalali receipt dates are converted with the jalaali-js arithmetic (truncating division; verified on 8 known dates). Safety: --target is required and never read from .env. Nothing is written without --yes, and a target not named *import*/*staging* also needs --confirm-db. The id map lives in its own schema, legacy_import, so a re-run updates instead of duplicating. Writes bypass the API services, so no SMS is sent and nothing is queued to accounting. Tested against goldbank_import_test, a clone of the dev DB, in three runs: - 1,503/1,503 created customers match legacy gold and rial balances (±0.0001 g / ±1 rial) - accounting data is byte-identical before and after - 0 imported variants have an imageId - runs 2 and 3 created zero duplicate rows - 6,196 image files copied, 3 missing in the legacy storage New devDependency: mysql2 ^3.24.5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
1.5 KiB
JSON
54 lines
1.5 KiB
JSON
{
|
|
"name": "api",
|
|
"version": "0.0.1",
|
|
"private": true,
|
|
"scripts": {
|
|
"dev": "nest start --watch",
|
|
"build": "nest build",
|
|
"build:release": "pnpm exec prisma generate && node scripts/clean-dist.cjs && nest build && node scripts/bundle-release.cjs",
|
|
"lint": "eslint \"src/**/*.ts\"",
|
|
"test": "jest",
|
|
"prisma:push": "prisma db push",
|
|
"prisma:migrate": "prisma migrate dev",
|
|
"prisma:seed": "prisma db seed",
|
|
"prisma:studio": "prisma studio"
|
|
},
|
|
"prisma": {
|
|
"seed": "ts-node --transpile-only prisma/seed.ts"
|
|
},
|
|
"dependencies": {
|
|
"@gold-bank/shared-types": "workspace:*",
|
|
"@nestjs/common": "^10.4.0",
|
|
"@nestjs/core": "^10.4.0",
|
|
"@nestjs/jwt": "^12.0.1",
|
|
"@nestjs/passport": "^10.0.3",
|
|
"@nestjs/platform-express": "^10.4.0",
|
|
"@prisma/client": "^5.19.0",
|
|
"bcryptjs": "^3.0.3",
|
|
"class-transformer": "^0.5.1",
|
|
"class-validator": "^0.14.1",
|
|
"passport": "^0.7.0",
|
|
"passport-jwt": "^4.0.1",
|
|
"reflect-metadata": "^0.2.2",
|
|
"rxjs": "^7.8.1"
|
|
},
|
|
"devDependencies": {
|
|
"@nestjs/cli": "^10.4.5",
|
|
"@nestjs/testing": "^10.4.22",
|
|
"@types/bcryptjs": "^3.0.0",
|
|
"@types/express": "^4.17.21",
|
|
"@types/jest": "^30.0.0",
|
|
"@types/node": "^20.14.0",
|
|
"@types/passport-jwt": "^4.0.1",
|
|
"@types/supertest": "^7.2.1",
|
|
"esbuild": "^0.25.0",
|
|
"jest": "^30.5.2",
|
|
"mysql2": "^3.24.5",
|
|
"prisma": "^5.19.0",
|
|
"supertest": "^7.2.2",
|
|
"ts-jest": "^29.4.12",
|
|
"ts-node": "^10.9.2",
|
|
"typescript": "^5.5.0"
|
|
}
|
|
}
|