# پلن رفتن به تولید — ارتقای پشته، جداسازی انتشار، جابه‌جایی از henza سند برنامه‌ریزی، نوشته‌شده در ۲۰۲۶-۱۰-۰۴. **هیچ قدمی هنوز اجرا نشده.** > این سند طوری نوشته شده که **روی سیستم دیگری، بدون گفتگوی قبلی، قابل ادامه باشد.** از §۰ شروع کنید. > > نسخه‌ها و تاریخ‌های این سند مال روز نوشتن‌اند. قبل از اجرای هر قدم، با > `node scripts/check-majors.mjs` دوباره بسنجید. --- ## خلاصه - **هدف:** سیستم زنده‌ی henza که الان زیر بار است، روی پشته‌ی جدید برود — **با همان ظاهر برای کاربر**، سریع‌تر و امن‌تر. - **تصمیم مخزن:** پروژه‌ی جدید ساخته نمی‌شود. همین مونوریپو «نسخه‌ی بعدی تولید» است و امنیت تولید با **جداسازی انتشار** تأمین می‌شود (§۱). - **سرعت از بک‌اند می‌آید، نه از بازنویسی ظاهر.** اپ کاربر قدیم همین حالا Vue 3 است (§۲). - **بزرگ‌ترین ریسک داده است، نه کد.** ابزار انتقال داده از دیتابیس henza به Postgres هنوز وجود ندارد (§۷). ### ترتیب اجرا | # | قدم | بخش | وابسته به | |---|---|---|---| | 1 | راه‌اندازی روی هر سیستم + commit و push اسناد | §۰ | — | | 2 | اندازه‌گیری مبنا روی سیستم زنده | §۳ | — | | 3 | ارتقای پشته | §۵ | — | | 4 | جداسازی انتشار | §۶ | — | | 5 | پورت اپ کلاسیک | `docs/PWA-PORT-PLAN.md` | تصمیم‌های مالک در آن سند | | 6 | ابزار مهاجرت داده و تطبیق | §۷ | — (موازی با ۵ قابل انجام است) | | 7 | اجرای موازی روی staging | §۸ | ۵ و ۶ | | 8 | بستن مسدودکننده‌ها | §۹ | — | | 9 | روز جابه‌جایی | §۱۰ | همه | --- ## §۰ — ادامه روی سیستم دیگر ### چه چیزی با git منتقل می‌شود و چه چیزی نه | چیز | در git مونوریپو؟ | روی سیستم جدید | |---|---|---| | کد مونوریپو و `docs/` | بله، **بعد از commit و push** | clone از `http://get.feep.ir/s.esmaeili/gold-bank.git` | | همین سند، `docs/PWA-PORT-PLAN.md` و `scripts/check-majors.mjs` | **امروز نه** — هنوز commit نشده‌اند | قبل از ترک این سیستم، commit و push | | `henza_pwa`، `henza_server`، `henza_admin` | **نه** — هر کدام مخزن git جدای خودش است و مونوریپو آن‌ها را track نمی‌کند | جدا clone و روی commit پین‌شده checkout (جدول بعد) | | `.env` | نه — ignore شده، و باید همین‌طور بماند | از `.env.example` بسازید؛ secret ها را از جای امن بیاورید | | `CLAUDE.md` | نه — در ریشه‌ی workspace قبلی (`E:\gold bank`) بوده و اسناد parity به §2، §3، §4 و §6 آن ارجاع می‌دهند | اگر نسخه‌اش را دارید به مخزن اضافه کنید؛ بازسازی قواعدش در `docs/PWA-PORT-PLAN.md` آمده | | skill `reference-parity-audit` | نه — روی ماشین قبلی | اگر دارید منتقل کنید؛ وگرنه D12 و همین اسناد روش را می‌گویند | | حافظه‌ی Claude | نه — محلی است | همین اسناد جایش را می‌گیرند | ### مخزن‌های مرجع — commit های پین‌شده | مخزن | remote | commit | نکته | |---|---|---|---| | `henza_pwa` | `http://get.feep.ir/henzagold/henza_pwa.git` | `b171fff` (2026-09-02) | مرجع پورت کلاسیک | | `henza_server` | `http://get.feep.ir/henzagold/henza_server.git` | `37c7d7a` (2026-09-17) | روی سیستم فعلی سه فایل حذف‌شده‌ی commit‌نشده دارد (`resources/js/app.js`، `resources/js/bootstrap.js`، `webpack.mix.js`). این‌ها اسکلت Laravel Mix‌اند و به API ربطی ندارند؛ clone تازه آن‌ها را دارد و در parity فرقی ایجاد نمی‌کند | | `henza_admin` | `http://get.feep.ir/henzagold/henza_admin.git` | `1b67448` (2026-08-11) | — | ```bash git clone http://get.feep.ir/s.esmaeili/gold-bank.git cd gold-bank git checkout release/delivery # یا هر شاخه‌ای که این اسناد رویش commit شده‌اند git clone http://get.feep.ir/henzagold/henza_pwa.git && git -C henza_pwa checkout b171fff git clone http://get.feep.ir/henzagold/henza_server.git && git -C henza_server checkout 37c7d7a git clone http://get.feep.ir/henzagold/henza_admin.git && git -C henza_admin checkout 1b67448 cp .env.example .env # بعد secret ها را پر کنید pnpm install --frozen-lockfile ``` ### دو تله 1. **پوشه‌های `henza_*` در `.gitignore` نیستند.** یک `git add .` یا `git add -A` آن‌ها را به‌صورت «embedded repository» اضافه می‌کند، و clone روی سیستم دیگر به‌جایشان پوشه‌ی خالی می‌گیرد. یا این سه نام به `.gitignore` اضافه شوند، یا همیشه فایل‌ها با نام add شوند. 2. **remote ها `http://` هستند، نه `https://`.** نام کاربری و رمز git بدون رمزنگاری منتقل می‌شوند. ### ابزار روی سیستم جدید - **Node 24.** سیستم فعلی 24.21 دارد؛ `engines` در `package.json` می‌گوید `>=20`؛ ایمیج Docker API روی 20 است (§۵.۱). - **pnpm 9** (`packageManager: pnpm@9.0.0`). - **build روی خود ماشین انجام می‌شود، نه داخل Docker** (DEPLOY-03). Dockerfile ها فقط خروجی ساخته‌شده (`release/` و `dist/`) را کپی می‌کنند، پس Node و سیستم‌عامل ماشین build روی خروجی اثر دارند. قبل از `docker compose build` همیشه `pnpm build:release` اجرا شود. - **ترتیب خواندن:** همین سند ← `docs/parity/PROGRESS.md` ← `docs/parity/DECISIONS.md` ← `docs/PWA-PORT-PLAN.md`. --- ## §۱ — تصمیم مخزن: پروژه‌ی جدید نه **وضعیت:** پیشنهاد (۲۰۲۶-۱۰-۰۴)؛ مالک خواست نوشته شود. 1. **اپ‌ها و API با هم تکامل پیدا می‌کنند.** اپ کلاسیک برای ۱۸ endpoint تازه به `apps/api` وابسته است، و ادمین و اپ‌ها یک دیتابیس و یک schema دارند. جدا کردن اپ و API در دو مخزن یعنی هر تغییر دو PR، و ناهمخوانی نسخه‌ی کلاینت و سرور. 2. **امنیت تولید از جداسازی انتشار می‌آید، نه جداسازی مخزن.** هر اپ همین حالا Dockerfile و سرویس جدا دارد. فقط `build:release` همه را با هم می‌سازد، پس خرابی یک اپ آزمایشی انتشار تولید را هم می‌خواباند. راه‌حل در §۶. 3. **تاریخچه و قواعد اینجاست.** تاریخچه‌ی git و کل `docs/parity` (تصمیم‌ها، PROTECTED، ISSUES) در همین مخزن است؛ مخزن تازه یا گمشان می‌کند یا دو نسخه می‌سازد. **چه وقت پروژه‌ی جدید درست است:** اگر `user-app` و `user-app-v2` قرار است محصول، برند یا تیم دیگری شوند. اگر قرار است هرگز منتشر نشوند، بایگانی‌شان کنید (یک tag، و خروج از انتشار) — باز هم بدون مخزن جدید. حذفشان طبق D18 و `PROTECTED.md` تأیید صریح مالک می‌خواهد. --- ## §۲ — واقعیت درباره‌ی «سرعت» | بخش | در تولید امروز | وضعیت | جایگزین در مونوریپو | |---|---|---|---| | سرور | Laravel 8 + PHP `^7.3` (`henza_server/composer.json`) | پشتیبانی امنیتی Laravel 8 در ژانویه‌ی ۲۰۲۳ و PHP 7.x در ۲۰۲۲ تمام شده | `apps/api` — NestJS + Prisma + Postgres | | ادمین | Vue 2.6 + Vuex 3 + Vuesax + Tailwind 1 + vue-cli 3 (`henza_admin/package.json`) | Vue 2 پایان ۲۰۲۳ تمام شد | `apps/admin-panel` — Vue 3 | | اپ کاربر | Vue 3 + Vite + Tailwind 3 — lockfile آن Vue 3.5.40 دارد و هر ۲۳ route آن lazy است | **پشته به‌روز است** | `apps/user-app-classic` (`docs/PWA-PORT-PLAN.md`) | پس بردن اپ کاربر روی «Vue 3، Tailwind، Pinia» به‌خودی‌خود سریعش نمی‌کند. اهرم‌های واقعی سرعت در آن: 1. **کل CSS ant-design** با `import 'ant-design-vue/dist/antd.less'` (`henza_pwa/src/main.ts:7`) → فقط استایل کامپوننت‌های استفاده‌شده. 2. **کل CSS vant، دو بار:** `vant/lib/index.css` هم در `main.ts:10` و هم در `main.ts:11`. 3. **درخواست‌های تکراری:** `/price` از دو مسیر جدا (`store/store.ts:114` و `Dashboard.vue:634`)؛ `/front` دو بار (`home/index.vue:184` و `Mixins/getProducts.ts:46`). 4. **بدون صفحه‌بندی:** `/get-orders` و `/get-my-findoc` کل داده را برمی‌گردانند. 5. **گزارش حساب** از یک سیستم حسابداری بیرونی proxy می‌شد (D24)؛ در هدف از دفتر داخلی خوانده می‌شود. همه‌ی این‌ها زیر کاپوت‌اند و ظاهر را عوض نمی‌کنند، پس با قرارداد «دقیقاً مثل مرجع» در `docs/PWA-PORT-PLAN.md` سازگارند. --- ## §۳ — اندازه‌گیری مبنا (قدم ۲) بدون عدد «قبل»، معلوم نیست کندی کجاست و بعداً هم نمی‌شود نشان داد سریع‌تر شده. **روی تولید آزمون بار (load test) اجرا نشود.** | لایه | ابزار | چه چیزی ثبت شود | |---|---|---| | اپ — مهمان | `npx lighthouse https://app.henzagold.com/home --only-categories=performance --output=json --output-path=baseline-home.json` (پیش‌فرض Lighthouse شبیه‌سازی موبایل است)؛ همین برای `/search` و یک `/product/` | LCP، TBT، حجم JS و CSS منتقل‌شده، تعداد درخواست‌ها | | اپ — واردشده | Chrome DevTools ← Performance و Network، روی یک گوشی متوسط واقعی | زمان تا نمایش میز کار؛ تعداد و زمان درخواست‌های شروع | | سرور | لاگ nginx با `$request_time` یا لاگ Laravel، در یک روز کاری | p50 و p95 برای `/front`، `/get-products`، `/me-data`، `/get-orders`، `/get-my-findoc`، `/price`، `/fin_tahesab/*`، `/set-order` | | دیتابیس | slow query log (مثلاً بالای 0.5 ثانیه)، یک روز | ده کوئری کندتر | | سنجه | مبنا (henza) | بعد از جابه‌جایی | |---|---|---| | LCP خانه (موبایل) | | | | حجم JS + CSS خانه | | | | تعداد درخواست تا میز کار | | | | p95 `/front` | | | | p95 `/get-products` | | | | p95 `/set-order` | | | --- ## §۴ — استاندارد نسخه‌ها «دو نسخه عقب‌تر» به‌عنوان قاعده‌ی ثابت جواب نمی‌دهد: دو نسخه قبل از vue-router فعلی، router مخصوص Vue 2 است که مرده؛ و دو نسخه قبل از NestJS فعلی، همان نسخه‌ای است که الان دارید و از ژانویه patch نگرفته. **قاعده:** جدیدترین major که حدود ۶ ماه از انتشارش گذشته، هنوز patch می‌گیرد و وابستگی‌ها پشتیبانی‌اش می‌کنند. **دو استثنا:** - **ابزارهای زمان build** (TypeScript، vue-tsc، Vite) روی سرور اجرا نمی‌شوند؛ patch نگرفتنشان ریسک امنیتی زمان اجرا ندارد. - **کتابخانه‌هایی که ظاهر را می‌سازند** مستقل از سنشان ثابت می‌مانند (جدول دوم). داده‌ی npm در ۲۰۲۶-۱۰-۰۴ — با `node scripts/check-majors.mjs` تازه کنید: | بسته | جدیدترین | پیشنهاد | الان در مونوریپو | خط فعلی آخرین بار کی patch شد | نوع | |---|---|---|---|---|---| | Node | 26 (هنوز LTS نیست) | **24 LTS** | Docker API: **20** | Node 20 از ۲۰۲۶-۰۴-۳۰ پشتیبانی ندارد | زمان اجرا | | NestJS | 12.1.2 (یک‌ماهه) | **11.x** — فعال | `^10.4.0` | 10.4.22 در ۲۰۲۶-۰۱-۱۰ | زمان اجرا | | Prisma | 8 (RC) / 7.10.0 | **6.19.x** حالا؛ 7 بعد از تولید | `^5.19.0` | 5.22.0 در ۲۰۲۴-۱۱-۰۵ | زمان اجرا | | ایمیج nginx | `latest` | **tag ثابت** | `latest` | — | زمان اجرا | | Vue | 3.5.43 | **3.5.x** | `^3.5.0` | فعال | کلاینت | | vue-router | 5.3.1 | **4.6.4** (آخرین 4.x) | `^4.4.0` | 4.6.4 در ۲۰۲۵-۱۲-۱۱ | کلاینت | | Pinia | 4.0.3 (سه‌ماهه) | **2.3.1** (آخرین 2.x) | `^2.2.0` | 2.3.1 در ۲۰۲۵-۰۱-۲۰ | کلاینت | | Vite | 8.3.2 | **7.3.x** | `^5.4.0` | 5.4.21 در ۲۰۲۵-۱۰-۲۰ | build | | @vitejs/plugin-vue | 6.0.9 | **6.0.x** | `^5.1.0` | 5.2.4 در ۲۰۲۵-۰۵-۰۹ | build | | vite-plugin-pwa | 2.0.0 (یک‌روزه) | **1.3.x** | `^0.20.5` | 0.21.2 در ۲۰۲۵-۰۳-۲۱ | build | | TypeScript | 7.0.2 (سه‌ماهه، کامپایلر تازه) | **5.9.3** | `^5.5.0` | 5.9.3 در ۲۰۲۵-۰۹-۳۰ | build | | vue-tsc | 3.3.12 | **3.x** | `^2.1.0` | 2.2.12 در ۲۰۲۵-۰۷-۰۲ | build | **چرا Pinia 3 نه:** خط 3 هم ۳۳۳ روز است release نداشته، و برای پروژه‌ی Vue 3 چیزی بیشتر از 2 نمی‌دهد. تنها خط فعال 4 است که هنوز سه ماه بیشتر عمر ندارد — بعداً. **چرا Prisma 6 با اینکه ۱۸۶ روز release نداشته:** پله‌ی کوچک‌تر و کم‌ریسک‌تر از 5 است (§۵.۷)؛ مقصد بلندمدت 7 است که بعد از تولید می‌آید. سازگاری این ترکیب بررسی شد: `@vitejs/plugin-vue@6` با Vite 5 تا 8، `vite-plugin-pwa@1.3` با Vite 3 تا 8، `vue-tsc@3` با TypeScript ≥ 5.0، Vite 7 با Node ≥ 20.19، و NestJS 11 با Node ≥ 20 جور است. ### کتابخانه‌هایی که به‌خاطر ظاهر ثابت می‌مانند | بسته | نسخه | چرا | |---|---|---| | `ant-design-vue` | 3.2.20 برای اپ‌های کاربر؛ 4.2.6 برای ادمین | v4 استایل را به CSS-in-JS برده. **هیچ‌کدام از دو خط از نوامبر ۲۰۲۴ release نداشته‌اند** — ریسک بلندمدتی که به‌خاطر ظاهر پذیرفته می‌شود | | `tailwindcss` | 3.0.18 | Tailwind 4 بازنویسی است و پیش‌فرض‌هایش ظاهر را عوض می‌کند | | `vant` | 4.10.x (اپ کلاسیک دقیقاً 4.10.0) | — | | `swiper` | 7.4.1 | — | | `@vueuse/core` | 9.13.0 | مرجع با همین نسخه است؛ ارتقا رفتار `useTransition` و `useInfiniteScroll` را عوض می‌کند و تست جدا می‌خواهد | **پین:** نسخه‌ها بدون `^` و `~`، lockfile commit‌شده، و `pnpm install --frozen-lockfile` روی ماشین build. --- ## §۵ — قدم‌های ارتقا (قدم ۳) **قواعد همه‌ی زیرقدم‌ها:** - هر زیرقدم یک commit یا PR جدا روی شاخه‌ی خودش (`chore/upgrade-*`)، با تست کامل، **بدون کار فیچر قاطی**. - `admin-panel`، `user-app` و `user-app-v2` در `PROTECTED.md` هستند: ارتقای ابزارشان **تأیید صریح مالک** و اسکرین‌شات قبل و بعد از صفحه‌های اصلی می‌خواهد. هیچ تغییر ظاهری یا رفتاری مجاز نیست. - برای دیتابیس، روند D14 و D15 برقرار است: هرگز `migrate reset` و هرگز دست زدن به `_prisma_migrations`. ترتیب از کم‌ریسک به پرریسک است، به‌جز Node که اول می‌آید چون Vite 7 به Node ≥ 20.19 نیاز دارد و Node 20 تمام شده. ### ۵.۱ — Node 24 - **تغییر:** `apps/api/Dockerfile` از `node:20-bookworm` به `node:24-bookworm`؛ `engines.node` به `">=24 <25"`؛ فایل `.nvmrc` با مقدار `24`. - **ممکن است بشکند:** ریسک پایین — `apps/api/package.json` هیچ وابستگی native ندارد (بررسی شد). - **سنجش:** `pnpm build:release`؛ بالا آمدن API در Docker؛ `apps/api/scripts/auth-smoke.sh` (۴۶ assertion)؛ `pnpm test` در api. ### ۵.۲ — پین ایمیج nginx - **تغییر:** نسخه‌ی واقعی `latest` فعلی را پیدا کنید (`docker run --rm docker.arvancloud.ir/nginx:latest nginx -v`) و در سه Dockerfile همان tag را بنویسید. - **رفتار:** بی‌تغییر؛ فقط از این به بعد هر build همان nginx را می‌گیرد. ### ۵.۳ — پین دقیق و patch های داخل همان خط - **تغییر:** حذف `^` و `~` از وابستگی‌های همه‌ی `package.json` ها؛ بالا بردن به آخرین patch در همان major: Vue 3.5.43، vue-router 4.6.4، Pinia 2.3.1، TypeScript 5.9.3؛ `pnpm install --frozen-lockfile` روی ماشین build و در CI. - **سنجش:** روی یک clone تازه، `pnpm install --frozen-lockfile` بدون تغییر lockfile تمام شود؛ typecheck و build همه‌ی اپ‌ها. ### ۵.۴ — vue-tsc 3 - **ممکن است بشکند:** vue-tsc 3 خطاهای تایپی تازه در template ها پیدا می‌کند. همه درست شوند، نه خاموش. - **سنجش:** typecheck تمیز در `admin-panel`، `user-app` و `user-app-v2`. ### ۵.۵ — Vite 7، plugin-vue 6، vite-plugin-pwa 1.3 - **مهم‌ترین تله:** طبق راهنمای مهاجرت Vite 7، پیش‌فرض `build.target` از `'modules'` به `'baseline-widely-available'` عوض شده — یعنی مرورگرهای جدیدتر (حدود Chrome 107 و Safari 16). **هیچ‌کدام از `vite.config.ts` ها `build.target` ندارند** (بررسی شد)، پس گوشی‌های قدیمی‌تر کاربران بی‌صدا از کار می‌افتند. ← `build.target` صریحاً روی مقدار قبلی، `['es2020', 'edge88', 'firefox78', 'chrome87', 'safari14']`، گذاشته شود، مگر مالک بر اساس آمار گوشی‌های کاربران تصمیم دیگری بگیرد. قبل از اجرا با راهنمای رسمی تطبیق داده شود. - `vite-plugin-pwa@1.3` به `workbox-build` و `workbox-window` ^7.4.1 نیاز دارد. - **سنجش:** build هر سه اپ؛ سناریوی دود (ورود، کاتالوگ، سبد)؛ نصب PWA و جریان به‌روزرسانی؛ اسکرین‌شات قبل و بعد. ### ۵.۶ — NestJS 11 (همه‌ی بسته‌های `@nestjs/*` با هم) - **ممکن است بشکند:** NestJS 11 روی Express 5 است. route با wildcard یا `forRoutes('*')` در کد نیست (بررسی شد) — رایج‌ترین شکست صدق نمی‌کند. ولی parser پیش‌فرض query در Express 5 «simple» شده؛ هر endpoint که query تودرتو می‌خواند باید چک شود. با راهنمای مهاجرت رسمی تطبیق داده شود. - **سنجش:** jest کامل؛ `auth-smoke.sh`؛ تست‌های توکن متقابل (T1). ### ۵.۷ — Prisma 6.19 - **ممکن است بشکند:** مهم‌ترین شکست‌های Prisma 6 اینجا صدق نمی‌کنند (بررسی شد): در migration ها رابطه‌ی many-to-many ضمنی نیست، و فیلد `Bytes` و `NotFoundError` استفاده نشده‌اند. - **سنجش:** بعد از ارتقا، `prisma migrate diff --from-schema-datasource --to-schema-datamodel --script` باید «empty migration» بدهد؛ `prisma migrate status`؛ jest؛ دود. ### ۵.۸ — بعداً، نه قبل از تولید Prisma 7، Pinia 4، vue-router 5، Vite 8، TypeScript 6 و 7، NestJS 12 — هر کدام وقتی پخته شد، جدا و با تست. **Tailwind 4 و ant-design-vue 4 هرگز برای اپ‌های کاربر**، چون ظاهر عوض می‌شود. --- ## §۶ — جداسازی انتشار (قدم ۴) - **مجموعه‌ی تولید:** `apps/api`، `apps/admin-panel`، و `apps/user-app-classic` وقتی آماده شد. **آزمایشی:** `apps/user-app`، `apps/user-app-v2`. - **اسکریپت تازه‌ی `build:prod`** فقط برای مجموعه‌ی تولید. `build:release` فعلی دست نمی‌خورد، چون `DELIVERY.md` به آن تکیه دارد. - **`docker-compose.yml`:** سرویس‌های آزمایشی زیر `profiles: ["experimental"]` بروند، تا `docker compose up` فقط تولید را بالا بیاورد و آزمایشی‌ها با `--profile experimental` بیایند. `DELIVERY.md` هم‌زمان به‌روز شود. - **شاخه‌ها:** `main` همیشه آماده‌ی تولید؛ کار روی شاخه‌های `chore/upgrade-*` و `feature/classic-*`؛ شاخه‌ی انتشار از `main` بریده شود. امروز همه‌چیز روی `release/delivery` است. - **DEPLOY-03 — build داخل Docker با multi-stage:** حالا که کار ممکن است بین ماشین‌ها جابه‌جا شود، اولویتش بالاتر است. خروجی نباید به Node و سیستم‌عامل ماشین build وابسته باشد. --- ## §۷ — مهاجرت داده و تطبیق (قدم ۶) — بزرگ‌ترین شکاف **واقعیت:** ابزار انتقال داده از دیتابیس henza به Postgres نه در مخزن هست و نه در اسناد (جست‌وجوی ۲۰۲۶-۱۰-۰۴). موتور دیتابیس henza هم از مخزن معلوم نیست — `config/database.php` پیش‌فرض `'localhost'` دارد و `.env.example` تنظیم DB ندارد. احتمالاً MySQL است؛ از سرور تولید تأیید شود. **ویژگی‌های اجباری ابزار:** - تکرارپذیر و idempotent؛ همیشه روی **کپی** داده‌ی تولید. - برای هر موجودیت یک جدول نگاشت `legacyId ← id جدید` نگه دارد. لازم است برای: - تطبیق؛ - ترتیب ۹ دسته‌ی خانه که با id عددی هاردکد شده (Q5 در `docs/PWA-PORT-PLAN.md`)؛ - لینک‌های قدیمی محصول (`/product/123`) که کاربران فرستاده‌اند — بدون نگاشت، به خانه redirect می‌شوند؛ - سبدهای باز `appCart` روی گوشی‌ها. - یک گزارش تطبیق بسازد (جدول دوم). | henza | مقصد | نکته | |---|---|---| | مشتری (`customers`) | `Customer` | نام ← `firstName`/`lastName` (D0)؛ `type` ← `CustomerKind`؛ `percent` ← `makingChargeOffsetPercent` (D9)؛ `gram_level` ← `goldCreditLimitGrams`؛ `remain` ← `goldDebtGrams`؛ `rial_remain` ← `fiatDebtRial` **با بررسی واحد** (نقص #19 در `docs/PWA-PORT-PLAN.md`) | | کارشناس فروش (`customers.type = 1`) | `AdminUser` با نقش `SALES_EXPERT` + `SalesExpertProfile` | D17 و D21 | | مشتری تک (`SingleCustomer`/`login`) | `Customer` با `kind = RETAIL` | D13 — داده حفظ شود، حتی اگر خارج از کار است | | کاربران ادمین (`users`) و `permission` | `AdminUser` + `UserType` + `Permission` | — | | محصول، تنوع، تصویر، دسته، برند، کالکشن | مدل‌های هم‌نام | **فایل‌های تصویر هم کپی شوند** (`UPLOAD_DIR`) | | سفارش‌ها — عمده و تک، دو جدول جدا در henza | `Order` + `OrderItem` + `OrderStatusEvent` | `sts` عددی ← `OrderStatus` | | سفارش ساخت | `PreOrder` | — | | اسناد مالی (`cash`) | `LedgerEntry` | فقط تأییدشده‌ها در موجودی حساب می‌شوند (D24) | | کیف پول و cashback | مدل‌های موجود | D13 — حفظ، بدون کار | | علاقه‌مندی، تخفیف و استثنا، اعلان، شهر، تنظیمات | مدل‌های موجود یا تازه | علاقه‌مندی جدول تازه می‌خواهد (`docs/PWA-PORT-PLAN.md`) | | بررسی تطبیق | آستانه | |---|---| | تعداد مشتری، کارشناس و کاربر ادمین | دقیقاً برابر | | بدهی طلای هر مشتری (`remain` ↔ `goldDebtGrams`) | **صفر اختلاف** | | بدهی ریالی هر مشتری | **صفر اختلاف**، بعد از تبدیل واحد | | سقف اعتبار و آفست اجرت هر مشتری | صفر اختلاف | | تعداد سفارش به تفکیک وضعیت؛ جمع وزن سفارش‌های باز | برابر | | تعداد و جمع اسناد تأییدشده و تأییدنشده | برابر | | تعداد محصول، تنوع و تصویر؛ فایل تصویر گم‌شده | برابر؛ صفر | **شماره‌ی تکراری بین مشتری و کارشناس** قبل از مهاجرت فهرست شود. یکتایی شماره بین `Customer` و `AdminUser` امروز اجرا نمی‌شود — هر چهار بررسی تداخل فقط `adminUser` را کوئری می‌کنند — و در `ISSUES.md` هم ثبت نشده. قاعده‌ی مالک در D21: «کارشناس برنده است». --- ## §۸ — اجرای موازی روی staging (قدم ۷) - یک دامنه‌ی staging؛ هر شب داده‌ی تولید با ابزار §۷ منتقل و تطبیق شود. - **پیامک در staging خاموش، یا فقط به شماره‌ی تست.** داده‌ی واقعی یعنی شماره‌ی واقعی مشتری‌ها. - کاربران داخلی جریان‌های واقعی را روی staging امتحان کنند. - **معیار آمادگی:** مثلاً سه شب پیاپی تطبیق تمیز، و هیچ باگ مسدودکننده‌ی باز. --- ## §۹ — مسدودکننده‌های قبل از تولید (قدم ۸) | مورد | منبع | |---|---| | مقدار جدا برای `JWT_CUSTOMER_SECRET` (REL-03) | `DELIVERY.md` §A1 | | حذف `OTP_MASTER_CODE` (REL-01) | §A2 | | `JWT_SECRET` واقعی | §A3 | | اعتبارنامه‌ی SMS (REL-02) | §A4 | | چرخاندن اعتبارنامه‌های نشت‌کرده: پنل SMS (SEC-12)، توکن‌های PayPing و Tahesab و pepper کیف پول (SEC-06). **هم‌زمان با سیستم قدیم**، چون همان حساب‌های زنده‌اند؛ چرخاندن یک‌طرفه پیامک سیستم قدیم را قطع می‌کند | §B | | MON-08 — سرور اجرت و تخفیف را از کلاینت نپذیرد. وضعیت فعلی چک شود | `docs/parity/ISSUES.md` | | MON-05 — اجرای `canPlaceOrders` و `verificationStep` | `docs/parity/ISSUES.md` | | یکتایی شماره بین `Customer` و `AdminUser` | §۷ | --- ## §۱۰ — روز جابه‌جایی (قدم ۹) ### شرط‌های go/no-go - همه‌ی موارد §۹ بسته‌اند. - معیار آمادگی §۸ برقرار است. - برگشت (rollback) یک بار تمرین شده. - به کاربران اطلاع داده شده: زمان قطعی؛ یک بار ورود دوباره با OTP، چون توکن‌های قدیمی باطل می‌شوند؛ خالی شدن سبدهای باز، مگر با نگاشت §۷ منتقل شوند. ### گام‌ها 1. سیستم قدیم در حالت نگهداری؛ نوشتن قفل. 2. مهاجرت نهایی و گزارش تطبیق ← **تصمیم go/no-go.** 3. سوئیچ مسیرها روی **همان دامنه‌ها**: - service worker جدید در همان مسیر `/sw.js`، تا جای قبلی را بگیرد. - نسخه‌ی اپ کلاسیک بالاتر از `1.0.7` باشد، تا دیالوگ مرجع «نسخه جدید هنزا منتشر شد!» یک بار برای همه بیاید و اپ تازه شود (`henza_pwa/src/App.vue:56-74`). 4. اولین باز شدن بعد از سوئیچ ممکن است پوسته‌ی کش‌شده‌ی قدیمی را نشان دهد که به API قدیم (`henzagold.com/oapi/api/`) درخواست می‌فرستد. آن مسیر تا مدتی پاسخ تمیز (مثلاً 503) بدهد، نه timeout. 5. آزمون دود: ورود با OTP؛ موجودی میز کار برابر گزارش تطبیق؛ ثبت سفارش روی یک مشتری تست؛ ورود ادمین و دیدن همان سفارش؛ رسیدن پیامک. 6. باز کردن برای همه. ### برگشت - سیستم قدیم چند روز (مثلاً ۱۴ روز) فقط‌خواندنی بماند؛ پشتیبان کامل از هر دو دیتابیس. - **مهلت تصمیم برگشت از قبل تعیین شود** (مثلاً ۲ ساعت بعد از باز کردن). بعد از آن، سفارش‌ها و اسناد تازه فقط در سیستم جدیدند و برگشت یعنی انتقال دستی آن‌ها به دیتابیس قدیم. - **برگشت سمت گوشی‌ها فوری نیست:** service worker جدید روی گوشی‌ها کش شده. برای برگرداندن، نسخه‌ی قدیم باید با شماره‌ی نسخه‌ی بالاتر دوباره منتشر شود. --- ## §۱۱ — بعد از جابه‌جایی - مقایسه با مبنای §۳ و ثبت نتیجه در جدول همان بخش. - پایش خطا و زمان پاسخ در هفته‌ی اول. - بعد: ارتقاهای §۵.۸؛ وصل کردن `user-app` و `user-app-v2` به قابلیت‌های تازه‌ی بک‌اند (تنش ۱ در `docs/PWA-PORT-PLAN.md`). --- # وضعیت اجرا | # | قدم | وضعیت | |---|---|---| | 1 | راه‌اندازی روی هر سیستم + commit و push اسناد | ⬜ | | 2 | اندازه‌گیری مبنا | ⬜ | | 3 | ارتقای پشته (۵.۱ تا ۵.۷) | ⬜ | | 4 | جداسازی انتشار | ⬜ | | 5 | پورت اپ کلاسیک | ⬜ منتظر تصمیم‌های مالک در `docs/PWA-PORT-PLAN.md` | | 6 | ابزار مهاجرت داده و تطبیق | ⬜ | | 7 | اجرای موازی روی staging | ⬜ | | 8 | بستن مسدودکننده‌ها | ⬜ | | 9 | روز جابه‌جایی | ⬜ |