Files
tehran_tala/docs/GO-LIVE-PLAN.md
T
2026-10-04 20:11:09 +03:30

30 KiB
Raw Blame History

پلن رفتن به تولید — ارتقای پشته، جداسازی انتشار، جابه‌جایی از 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) —
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/<id> 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 روز جابه‌جایی ⬜