Default Vite base to /admin/ (ADMIN_PANEL_BASE) so Dokploy Path+/admin + Strip Path resolves assets instead of the user app root.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Rial wage and gram-debt arithmetic matched to the reference; order corrections keep debt in sync
- Document confirm/un-confirm is a compare-and-swap (no double-applied cache under concurrency)
- Settlement document and expert inputs validated (400 instead of 500)
- Expert: edit / activate-deactivate own customers, adjust raw weights only
- Made-to-order flow in the app, PreOrder.quantity migration
- Order grids: customer column, sort keys; panel select search; pre-order quantity save
- Rebuilt release artifacts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Drop the duplicate customer app from the monorepo and keep user-app-v2 as the only app; include order pricing, admin cart, OTP/SMS, and dashboard cache updates.
Co-authored-by: Cursor <cursoragent@cursor.com>
Rebuilds apps/api/release so the deployed image carries 5f3b004. The vendored
Prisma client changes are only its recorded build paths. No source change.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Experts (AdminUser) and customers (Customer) sign in to the same apps by mobile
but live in different tables, so the database cannot make the number unique
across them. A number could be given to an expert and to a customer, and the
login then silently merged the two (the customer row was adopted as the expert's
trading account), which left the expert on a customer session and the panel's
name edits unreachable.
The reference rejected a duplicate at entry (`unique:customers`, the agent being
a customers row too); this does the same where a number is typed in:
- customer create/update (wholesale, banker, walk-in): refused when an ACTIVE
expert holds the number;
- expert create/update: refused when a customer holds it (the expert's own
trading account excepted);
- the app's self sign-up: refused when an active expert holds it.
Only a number being created or CHANGED is checked, so existing duplicates keep
signing in and stay editable; the login's "expert wins" adoption is untouched.
Plain equality on the two unique columns, normalised with faToEn, so both
lookups are index hits.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- apps: the fixed «در حال مشاهده بهعنوان» strip (38px) sat over the fixed page
headers, which still sat at top: 0 (the old 30px body padding was shorter than
the strip too). The strip's height is now one variable, --aab-h, that the
fixed headers (PageBar, home, dashboard, toasts) use as their top.
- admin: the customer form offers only «مغازه دار اپلیکیشن» to anyone but the
super admin; bankers and walk-in shopkeepers are listed by super-admin-only
endpoints, so ordinary admins lost the customers they created under them.
- admin: the mobile slider rid (custom.config.statics.slider) was only under the
«سفارشی» branch, which the permission screen hides outside level 104. Same rid,
now listed under «مدیریت ثابت ها». Display only: the slider routes are still
gated by config.statics.
Rebuilds admin-panel, user-app and user-app-v2 dist.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
CustomerChoiceView, ChildOrdersView and ReportView bound their Drawer with
v-model:open, which only exists from ant-design-vue 4. Both apps ship 3.2.20,
so the drawer never opened: tapping a customer in «مشتریان من» did nothing and
the "ورود به حساب این مشتری" button inside it was unreachable.
Rebuilds user-app and user-app-v2 dist.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The "سفارش مشتریان" / "مشتریان من" entries are shown from session.isSalesExpert,
which was fetched from /expert/whoami only once, at sign-in. A slow or failed
request (silently swallowed) left the flag false until the next login, so an
expert saw a customer-only menu. The dashboard now asks again on mount and on
every re-activation, and keeps the current value when the request fails.
Rebuilds user-app and user-app-v2 dist.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Rebuilds apps/api/release and apps/admin-panel/dist so the deployed images
carry 0156a97 (X-Debug counts block on the wholesale lists, console output in
the panel). No source change.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sending X-Debug: 1 makes the five wholesale list endpoints return a counts-only
`debug` block next to the rows: the WHERE that actually ran, how many customers
the scope matches before the grid's own filters, how many customers exist per
kind/active/archived/step and how many are an expert's trading account. The
panel sends the header and console-logs the block when localStorage.debug === '1'.
Off by default; DIAG_LOG=false disables it server-side. No names or mobiles.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Prints aggregate counts only, prefixed [DIAG], right after migrations: customers
by kind/active/archived/step, what the omde list can show and how many rows are
sales-expert trading accounts (created vs adopted), experts' profile/trading
state, referral counts, the Admin table and the last applied migrations.
Read-only, no mobile/name/id is printed, each query isolated so a failure is
reported without stopping boot. Disable with DIAG_LOG=false; remove once the
empty-omde-list investigation is closed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The app shows a sales expert their own account through the linked trading
Customer row (/customer/me). That row was seeded from the expert once, at first
sign-in, and never updated again, so a name, mobile, credit-limit or wage-percent
change made in the panel never reached the app. In the reference the agent and
that account were one row, so an edit changed both.
Editing an expert now mirrors exactly the changed fields onto the trading row in
the same transaction: name parts, credit limit (gram_level), wage percent, and the
mobile when no other customer holds it. Existing drift heals on the next save.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PrismaExceptionFilter returned "Unique constraint failed on: mobile" in
English for a duplicate. It now answers in Persian, naming the field
(mobile, national code, member code, order number), with a safe generic
fallback. Covered by a unit test.
- The admin panel still shipped the old "NZ" favicon. favicon.png/.ico are now
generated from the project logo (the same one the user apps use), in both
public/ and dist/, and the links carry ?v=2 so browsers drop the cached icon.
- Rebuilt apps/api/release/app.js.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The reference (henza_server AdminController::getCustomer) lists type=2 AND
is_archive=0 with no verification or active filter. The develop-branch change
that hid inactive customers with a pending verification step from «عمده»
emptied the list for customers migrated in that state, while their numbers
stayed taken ("already exists"). Restore parity; the sales-expert trading
account exclusion is kept.
Includes the rebuilt release/app.js and a regression test.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
app.js, seed.js, the Prisma client in release/vendor and the new migration
20261026120000_split_admin_table, built with `pnpm build:release` (API only;
the admin panel and user apps are unchanged by this work).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AdminUser held both panel staff and sales experts, so one mobile could not be
both. Staff now live in "Admin" (panel only); sales experts stay in "AdminUser"
untouched. Uniqueness is per table.
- migration 20261026120000_split_admin_table: additive only. Creates "Admin",
copies non-expert rows with their ids, re-points the "who did this" foreign
keys (ledger, order status, sms, notification, upload, allocation, workshop,
admin session) to "Admin" without moving data. Never writes to "AdminUser".
- login, JWT, SSO, branch/workshop supervisors and the users grid use "Admin";
SALES_EXPERT create/edit still goes through admin/users into "AdminUser".
- an admin cannot be turned into an expert or the reverse (different tables).
- manual/: optional phase-2 script to drop the dormant admin copies from
"AdminUser", and a read-only expert-login diagnostic.
- docs/ADMIN-TABLE-SPLIT.md: what changed, deploy checklist, rollback.
Tested on a copy with 12,000 experts: expert rows byte-identical (md5) before
and after; full migration chain applies and matches schema.prisma.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Keep admin browser bootstrap from falling back to the customer app URL, and exclude activated customers from the pending-verification list so it no longer mirrors the main omde grid.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add paged orders API and infinite scroll, short order numbers, and align the guest invite card with the logged-in hero shell.
Co-authored-by: Cursor <cursoragent@cursor.com>
اپ۲: دکمهی «افزودن به سفارش» در صفحهی جزئیات محصول دیگر از پایین صفحه بیرون نمیافتد و همیشه دیده میشود.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
اپ۲: رنگ دکمهها، نوار نرخ طلا و خطهای جداکنندهی بالای صفحه از سرمهای به قرمز-شرابی برند تغییر کرد.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
اپ۲: رنگ سرمهای از پسزمینهی بالای برنامه و رنگ نوار مرورگر حذف شد؛ همهجا از رنگ صفحهی اصلی استفاده میشود.
پنل: فرم افزودن شخص با هر بار جابهجایی نوع شخص خالی باز میشود و اطلاعات نیمهکارهٔ قبلی دیگر نمایش داده نمیشود.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
پنل: بخشهای «تک فروشی» داشبورد (کارت، نمودار روند و تفکیک عمده/تک) فقط برای مدیر اصلی نمایش داده میشود.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
اپ: لوگوی تازهی برند در صفحهی اصلی، لودر و صفحهی ورود نمایش داده میشود.
پنل: لوگوی تازهی برند در ورود، منو و کامنتها نمایش داده میشود.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
اپ: نام برند در همهی صفحهها و پیامها یکسان شده و از یک تنظیم مرکزی خوانده میشود.
اپ: کارت حسابداری در صفحهی مشتری بازطراحی شد؛ ماندهها و وضعیت لینک واضحتر نمایش داده میشوند.
پنل: کارت حسابداری در پروندهی مشتری بازطراحی شد؛ ماندهها، آخرین ارسال و فرم لینک دستی واضحتر شدهاند.
پنل: ستون «کد» در جدولها بهطور پیشفرض پنهان است و از انتخاب ستونها قابل نمایش است.
پنل: تغییر نمایش ستونها در جدولها بلافاصله اعمال میشود.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Migrations were applied in plain name order, so 0002_admin_schema.sql ran
before 20260910113720_first and failed with relation "City" does not exist.
sortMigrations now always puts the baseline first; existing databases are
unaffected because their applied names are unchanged.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>