Files
tehran_taj/docs/parity/_inv-ref-admin.md
T
s.esmaeiliandClaude Opus 5 71192ba2ba parity(docs): Phase 0 inventory, mapping and draft PROTECTED list
Read-only inventory of all 7 projects (3 reference + 4 target) produced by
parallel subagents, every claim cited path:line. No source code changed.

- 00-INVENTORY.md  consolidated mapping: stack, backend, admin, user apps
- PROTECTED.md     draft protected list (awaiting user confirmation)
- ISSUES.md        26 logged issues (security, money/stock, validation, dead code)
- CHANGELOG.md     change log scaffold
- PROGRESS.md      resumable state + Q1-Q5 blocking Phase 1
- _inv-*.md        7 raw per-project inventories (8111 lines)

Key finding: the reference is a gold-jewellery B2B/B2C e-commerce system, not a
gold bank. Buy/sell, deposit/withdraw, transfer, KYC levels, payment callbacks,
cron and websockets do not exist in it, so they cannot be parity gaps.

[ref: henza_server, henza_admin, henza_pwa]

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 18:09:46 +03:30

127 KiB
Raw Blame History

Inventory — henza_admin (reference admin)

Read-only, evidence-based inventory. All path:line are relative to henza_admin/. Source read at: repo root E:\gold bank\henza_admin.


1. Stack & Versions

All from package.json.

Concern Package Version Line
Framework vue ^2.6.10 package.json:47
Router vue-router ^3.0.6 package.json:65
Store vuex ^3.1.1 package.json:77
UI lib (primary, tables/forms/modals) ant-design-vue ^1.6.0 package.json:8
UI lib (secondary, layout/theme/notify) vuesax 3.11.13 package.json:76
HTTP client axios ^0.19.0 package.json:11
Date (Jalali) moment-jalaali ^0.9.2 package.json:29
Date picker (Jalali) vue-persian-datetime-picker ^2.4.1 package.json:56
Charts apexcharts ^3.36.0 + vue-apexcharts ^1.6.2 package.json:7, 48
Charts (alt) chart.js ^2.8.0 + vue-chartjs ^3.4.2 package.json:12, 51
Charts (alt) echarts ^4.2.1 + vue-echarts ^4.0.3 package.json:15, 54
Grid (unused legacy) ag-grid-community / ag-grid-vue ^28.1.1 package.json:4-5
Validation (legacy) vee-validate ^2.2.8 package.json:46 — registered main.js:84-85; used only in views/auth/Login.vue. Business forms use ant-design v-decorator rules.
ACL vue-acl 4.0.7 package.json:49
Excel export xlsx ^0.15.0, file-saver 2.0.1 package.json:78, 16
i18n vue-i18n ^8.11.2 package.json:58
CSS tailwindcss ^1.0.1 + postcss-rtl 1.5.0 + sass package.json:84, 32
Firebase (legacy, auth store only) firebase ^9.6.7 package.json:17
Node node:^14--npm:6 package.json:3
App version 5.0.1 package.json:3

Build modes — vue.config.js:3-4: publicPath = /branch/ when NODE_ENV=='branch', else admin/; outputDir = branchDist/export vs dist/export. LESS modifyVars: primary-color:#1c2d56, secondary-color:#836447, third-color:#f5cb55, border-radius-base:6px (vue.config.js:15-20).


2. HTTP Layer

2.1 src/axios.js (primary instance — used everywhere)

Aspect Value Evidence
Base URL https://henzagold.com/oapi/admin/ (hard-coded, exported as baseURL) src/axios.js:5
Token storage key branch_token if isBranch() else token src/axios.js:6
Default headers Content-Type: application/json, Accept: application/json src/axios.js:7-11
Initial auth header Authorization: Bearer <localStorage[tokenName]> set at module load if token exists src/axios.js:13-17
Request interceptor Overwrites config.headers["Authorization"] = "Bearer " + localStorage.getItem(tokenName) on every request src/axios.js:24-32
Request error handler Promise.reject(error) — not returned (bug: interceptor returns undefined) src/axios.js:29-31
Response interceptor None on this instance src/axios.js (absent)
Exports default ax, named baseURL, token src/axios.js:5, 33-34
Registered as Vue.prototype.$http = axios src/main.js:19-20

2.2 src/http/* (Vuexy template leftovers — DEAD CODE)

File Content Wired in?
src/http/axios/index.js:1-3 re-exports src/axios.js yes (by jwt module)
src/http/requests/index.js:1 import './auth' No — import './http/requests' is commented out at src/main.js:22-23
src/http/requests/auth/index.js:1 import './jwt/index.js' dead
src/http/requests/auth/jwt/index.js see below dead

src/http/requests/auth/jwt/index.js — never invoked (init() has no caller):

  • Response interceptor on 401 (src/http/requests/auth/jwt/index.js:26-43): single-flight refresh via isAlreadyFetchingAccessToken flag + subscribers queue (lines 5-14); dispatches auth/fetchAccessToken; retries original request with new bearer.
  • login(email,pwd) → POST /api/auth/login (line 48)
  • registerUser(name,email,pwd) → POST /api/auth/register (line 54)
  • refreshToken() → POST /api/auth/refresh-token with {accessToken: localStorage.accessToKen} (line 61 — note typo accessToKen)
  • store/auth/moduleAuthActions.js:357-361 fetchAccessToken wraps jwt.refreshToken() — also dead (real auth module is store/auth/moduleAuth.js).

Net effect: there is NO refresh-token flow and NO response interceptor in the live app. 401s bubble to each caller's try/catch.

2.3 Error handling / toasts

Two mechanisms coexist:

Mechanism Definition Usage
ant-design this.$message.* global via Vue.use(Antd) (src/main.js:3,16) e.g. this.$message.info('ویرایش موفق آمیز') / this.$message.error('خطا در ویرایش') — src/views/order/List.vue:262,265,273,276
Vuesax notify wrapper plugin src/notify.js (Vue.use(notify) at src/main.js:107-108) 5 prototype methods below

src/notify.js methods:

Method Title Default text Color Line
$ntSetError(msg) خطا در ثبت اطلاعات اطلاعات ثبت نگردید. danger notify.js:4-10
$ntSet(msg) اطلاعات ثبت شد. اطلاعات با موفقیت به ثبت رسید primary notify.js:12-18
$ntNoTitle(msg) — اطلاعات با موفقیت به ثبت رسید primary notify.js:19-24
$ntRemove(msg) اطلاعات با موفقیت حذف شد '' warning notify.js:27-33
$ntGetError(msg) خطا در ثبت اطلاعات در اطلاعات دریافت شده خطایی رخ داده danger notify.js:35-41

3. Router

src/router.js builds the tree; route arrays live in src/router/admin.js (admin build) and src/router/branch.js (branch build). src/router/{apps,category,customer,dashboard,full,manage,order,product,temp}.js exist but are not imported by src/router.js (only ./router/admin and ./router/branch are — src/router.js:6,8) → dead.

3.1 Router config

Item Value Line
mode history router.js:15
base process.env.BASE_URL router.js:16
scrollBehavior always {x:0,y:0} router.js:17-19
Main layout layouts/main/Main.vue, children = branchRoute or adminRoute per isBranch() router.js:25-28
Full-page layout layouts/full-page/FullPage.vue, children = fullPageBranchRoute/fullPageAdminRoute + 4 error pages router.js:32-138
catch-all * → redirect /pages/error-404 router.js:140-143
afterEach hides #loading-bg router.js:147-153

3.2 Guard (router.beforeEach) — src/router.js:184-199

  1. Whitelist noneAuthUrl = ['/auth/login','/auth/forgot-password','/auth/register','/reg'] → next() (router.js:156-161, 185-187).
  2. Read token from localStorage[isBranch()?'branch_token':'token'] (router.js:188).
  3. If no token → router.push('/auth/login') (router.js:198).
  4. If token and module-level roles is unset → await getPermission() (router.js:190-191).
  5. getPermission() (router.js:163-182): if store.state.auth.token && store.state.auth.user and no cached roles → GET users/show, dispatch users/getRoles(data.permission), delete permission+ut from payload, write localStorage[token|branch_token] = data.api_token and localStorage[user|branch_user] = JSON.stringify(data).
  6. If to.meta.role exists and !roles.includes(to.meta.role) → redirect to route name page-not-authorized (router.js:193-195).

Note: roles is a module-level variable cached for the page lifetime (router.js:162).

3.3 Admin routes — src/router/admin.js (adminRoute, main layout)

meta.rule is the vue-acl rule; meta.role is the real permission gate; meta.parent / meta.no_scroll are layout hints; meta.pageTitle + meta.breadcrumb drive the header.

path name component file meta.role meta.rule meta.pageTitle other meta line
/ dashboard (redirect → /my-data) — — — — admin.js:3-5
/dashboard/analytics — views/DashboardAnalytics.vue dashboard.tak editor — — admin.js:8-15
/my-data my-data views/user/myData.vue (none) editor — — admin.js:17-24
/dashboard/ecommerce — views/DashboardECommerce.vue dashboard.omde admin — — admin.js:26-33
/config/manage/const — views/manage/Const.vue config.statics editor مدیریت ثابت ها parent manage, no_scroll admin.js:34-54
/config/manage/wallet — views/manage/wallet.vue config.wallet editor مدیریت کیف پول parent manage, no_scroll admin.js:55-75
/config/manage/report — views/manage/report.vue config.report editor گزارش parent manage, no_scroll admin.js:76-96
/apps/product/ product (redirect → /apps/product/list) — — — — admin.js:98-102
/product/change/percent — views/apps/product/ChangePercent.vue product.percent editor — parent product, no_scroll admin.js:103-112
/apps/product/add — views/apps/product/AddProduct.vue product.create editor — parent product, no_scroll admin.js:113-122
/apps/product/edit/:id/:variant_id? product-edit views/apps/product/EditProduct.vue product.list.edit editor — parent product, no_scroll admin.js:123-133
/apps/product/list product-list views/apps/product/ProductList.vue product.list editor — parent product, no_scroll admin.js:134-144
/category category (redirect → /category/list) — — — — admin.js:146-150
/category/add/:id? category-add views/apps/category/Add.vue collection.create editor — parent category, no_scroll admin.js:151-161
/category/edit/:id category-edit views/apps/category/Edit.vue collection.list.edit editor — parent category, no_scroll admin.js:162-172
/category/list category-list views/apps/category/List.vue collection.list editor — parent category, no_scroll admin.js:173-183
/add/findoc — views/finical/addFinDoc document.create editor — — admin.js:185-192
/edit/findoc/:id — views/finical/addFinDoc document.list.edit editor — — admin.js:194-201
/order order (redirect → /order/list) — — — — admin.js:204-208
/order/list — views/order/List.vue order.list editor — parent order, no_scroll admin.js:209-218
/order/omde-list — views/order/OmdeList.vue order.omde editor — parent order, no_scroll admin.js:219-228
/order/make — views/order/MakeOrder.vue order.makeOrder editor — parent order, no_scroll admin.js:229-238
/order/create — views/order/create.vue order.create editor — parent order, no_scroll admin.js:239-248
/order/tamin-list — views/order/TaminList.vue order.tamin editor — parent order, no_scroll admin.js:249-258
major/promotion/list (relative → /major/promotion/list) — views/promotion/promotion_list offers.list editor — no_scroll admin.js:259-268
major/promotion/add — views/promotion/promotion_add_edit offers.create editor — no_scroll admin.js:269-278
major/promotion/edit/:id — views/promotion/promotion_add_edit offers.list.edit editor — no_scroll admin.js:279-288
major/promotion/tak/add — views/promotion/promotion_tak_add_edit offers.create.tak editor — no_scroll admin.js:289-298
major/promotion/tak/edit/:id — views/promotion/promotion_tak_add_edit offers.list.tak.edit editor — no_scroll admin.js:299-308
major/promotion/autopromotion — views/promotion/autopromotion offers.autopromotion editor — no_scroll admin.js:309-317
major/offersIgnore — views/offersIgnore/offersIgnore-add-edit.vue offersIgnore editor — — admin.js:319-326
/comments comments views/customer/Comments/Comments.vue comment editor دیدگاه ها breadcrumb admin.js:328-348
/sms/create create_sms views/sms/create.vue sms.create editor ارسال پیامک breadcrumb admin.js:350-370
/notify notify views/notify/user.vue notify.me editor لیست نوتیفیکیشن های ذریافتی breadcrumb admin.js:371-391
/notify/create create_notify views/notify/create.vue notify.create editor ارسال نوتیفیکیشن breadcrumb admin.js:392-412
/wallet wallet views/wallet/wallet.vue wallet editor لیست کیف پول های شارژ شده breadcrumb admin.js:413-433
/reagent/edit/:id reagent-edit views/apps/customer/EditReagent persons.list.sellers.edit editor — parent product, no_scroll admin.js:434-444
/bulkCustomer/edit/:id bulkCustomer-edit views/apps/customer/EditBulkCustomer persons.list.client.omde.edit editor — parent product, no_scroll admin.js:445-455
/bulkCustomer/view/:id bulkCustomer-view views/customer/omde/ViewOmdeCustomer persons.list.client.omde.view editor — parent product, no_scroll admin.js:456-466
/singleCustomer/edit/:id singleCustomer-edit views/apps/customer/EditSingleCustomer persons.list.client.single.edit editor — parent product, no_scroll admin.js:467-477
/singleCustomer/view/:id singleCustomer-view views/customer/single-customer/ViewSingleCustomer persons.list.client.single.view editor — parent product, no_scroll admin.js:478-488
/customer/omde-list omde-list-customer views/customer/omde/OmdeList.vue persons.list.client.omde editor مشتریان عمده breadcrumb admin.js:489-507
/customer/omde-non-verified-list omde-non-verified-list views/customer/omde/OmdeNonVerifiedList.vue persons.list.client.omde editor مشتریان در انتظار breadcrumb admin.js:509-527
/customer/banker-list banker-list views/customer/omde/BankerList.vue persons.list.client.omde editor لیست بنکداران breadcrumb admin.js:529-547
/customer/shopkeeper-list shopkeeper-list views/customer/omde/ShopkeeperList.vue persons.list.client.omde editor لیست مغازه داران حضوری breadcrumb admin.js:549-567
/customer/omde-archived-list omde-archived-list views/customer/omde/OmdeArchivedList.vue persons.list.client.omde editor مشتریان بایگانی breadcrumb admin.js:569-587
/customer/reagent-list raegentList views/customer/reagentList/ReagentList.vue persons.list.sellers editor کارشناسان فروش breadcrumb admin.js:589-607
/customer/add add-customer views/apps/customer/AddCustomer.vue persons.create editor افزودن مشتری breadcrumb admin.js:609-628
/customer/list list-customer views/customer/single-customer/SingleCustomer persons.list.client.single editor لیست مشتریان breadcrumb admin.js:630-645
/report/order_item report_order_item views/report/order_item report.order.item editor — — admin.js:647-659
/report/product report_product views/report/product report.product editor — — admin.js:661-669
/finical/list finical_list views/finical/list document.list editor — — admin.js:670-683
/user/list — views/user/ListUser.vue user.list editor لیست مدیران breadcrumb, no_scroll admin.js:685-704
/user/create — views/user/UserCreate.vue user.create editor افزودن کاربر breadcrumb, no_scroll admin.js:706-725
/user/edit/:id — views/user/UserEdit.vue user.list.edit editor ویرایش نوع کاربر breadcrumb, no_scroll admin.js:727-747
/permission — views/user/Permission.vue user.permission editor دسترسی ها breadcrumb, no_scroll admin.js:749-768
/city/create — views/city/createCity.vue cities.create editor افزودن شهر breadcrumb, no_scroll admin.js:770-789
/city/list — views/city/cityList.vue cities.list editor لیست شهر ها breadcrumb, no_scroll admin.js:791-811
/statics statics views/statics/index.vue statics editor آمار breadcrumb admin.js:813-832
/newsletters newsletters views/newsletters/newsletters.vue (commented out newsletters) editor خبرنامه breadcrumb admin.js:834-853
/branch/add add-branch views/branch/AddBranches.vue branch.create editor افزودن شعب breadcrumb admin.js:855-874
/branch/edit/:id edit-branch views/branch/EditBranches branch.create editor ویرایش شعب — admin.js:876-885
/branch/list list-branch views/branch/ListBranches.vue branch.list editor لیست شعب breadcrumb admin.js:886-906
/workshop/add add-workshop views/workshop/AddWorkshop.vue workshop.create editor افزودن کارگاه breadcrumb admin.js:908-927
/workshop/edit/:id edit-workshop views/workshop/EditWorkshop workshop.create editor ویرایش کارگاه — admin.js:929-938
/workshop/list list-workshop views/workshop/ListWorkshop.vue workshop.list editor لیست کارگاه ها breadcrumb admin.js:939-959
/invoice/add add-invoice views/invoice/AddInvoice.vue invoice.create editor افزودن فاکتور breadcrumb admin.js:961-980
/invoice/edit/:id edit-invoice views/invoice/EditInvoice.vue invoice.create editor ویرایش فاکتورها — admin.js:982-991
/invoice/list list-invoice views/invoice/ListInvoice.vue invoice.list editor لیست فاکتورها breadcrumb admin.js:992-1012

73 routes in adminRoute (incl. 4 redirect-only entries).

3.4 Admin full-page routes — fullPageAdminRoute (src/router/admin.js:1016-1033)

path name component meta line
/auth/login page-login views/auth/Login.vue rule editor admin.js:1017-1024
/reg reg views/reg.vue rule editor admin.js:1025-1032

3.5 Shared full-page error routes — src/router.js:104-135

path name component meta.rule
/pages/error-404 page-error-404 views/pages/Error404.vue editor (router.js:104-111)
/pages/error-500 page-error-500 views/pages/Error500.vue editor (router.js:112-119)
/pages/not-authorized page-not-authorized views/pages/NotAuthorized.vue editor (router.js:120-127)
/pages/maintenance page-maintenance views/pages/Maintenance.vue editor (router.js:128-135)
* — redirect /pages/error-404 router.js:140-143

3.6 Branch build routes — src/router/branch.js

path name component meta.role meta.rule line
/ main redirect → /dashboard — — branch.js:2-6
/dashboard dashboard views/branch/dashboard.vue dashboard.omde admin branch.js:7-15
/products product-list views/apps/product/ProductList.vue product.list editor branch.js:16-26
/order/list — views/order/List.vue order.list editor branch.js:32-41
/buy/order/list — views/branch/buyList.vue order.list editor branch.js:42-51
/order/create — views/branch/order/create.vue order.create editor branch.js:61-70
/singleCustomer/view/:id singleCustomer-view views/customer/single-customer/ViewSingleCustomer persons.list.client.single.view editor branch.js:82-92
/singleCustomer/edit/:id singleCustomer-edit views/apps/customer/EditSingleCustomer persons.list.client.single.edit editor branch.js:93-103
/customer/add add-customer views/branch/addCustomer.vue persons.create editor branch.js:104-112
/customer/list list-customer views/customer/single-customer/SingleCustomer persons.list.client.single editor branch.js:113-121
/auth/login (full-page) page-login views/branch/login.vue — editor branch.js:161-169

4. Menu / Navigation

Defined in src/layouts/components/vertical-nav-menu/navMenuItems.js; exports isBranch() ? branchMenu : adminMenu (navMenuItems.js:609-611). Consumed by VerticalNavMenu.vue (vertical layout) and HorizontalNavMenu.vue (branch/horizontal layout — themeConfig.js:23 sets mainLayoutType to horizontal for branch).

Gating: VerticalNavMenu.vue:322 — if ((item.permissionId && this.$hasPermission(item.permissionId)) || !item.permissionId). Additional server-driven removal at VerticalNavMenu.vue:187-220 (GET /roles/{ut} → removeItem list filters by permissionId).

4.1 Admin menu

Group (header / i18n) Item i18n url slug icon permissionId line
— پیشخوان null — HomeIcon dashboard 3-10
↳ آمار عمده فروشی /dashboard/ecommerce dashboard-ecommerce — dashboard.omde 12-18
↳ آمار تک فروشی /dashboard/analytics dashboard-ecommerce — dashboard.tak 19-25
Apps / کاربری (PackageIcon) اشخاص null — UserIcon persons 33-38
↳ اضافه کردن شخص /customer/add add-customer — persons.create 40-46
↳ لیست کارشناسان فروش /customer/reagent-list raegentList — persons.list.sellers 47-53
↳ لیست مشتریان عمده /customer/omde-list omde-customer-list — persons.list.client.omde 54-60
↳ لیست مشتریان در انتظار /customer/omde-non-verified-list omde-non-verified-list — persons.list.client.omde 61-67
↳ لیست مشتریان بایگانی /customer/omde-archived-list omde-archived-list — persons.list.client.omde 68-74
↳ لیست مشتریان تک /customer/list app-user-list — persons.list.client.single 75-81
↳ لیست بنکداران /customer/banker-list banker-list — none (commented) 82-88
↳ لیست مغازه داران حضوری /customer/Shopkeeper-list (capital S — route is /customer/shopkeeper-list) shopkeeper-list — none (commented) 89-95
شعب null — GridIcon branch 98-103
↳ افزودن شعب /branch/add add-branch — branch.create 105-111
↳ لیست شعب /branch/list branch-list — branch.list 112-118
کارگاه null — GridIcon workshop 122-127
↳ افزودن کارگاه /workshop/add add-workshop — workshop.create 129-135
↳ لیست کارگاه ها /workshop/list workshop-list — workshop.list 136-142
محصولات null — ShoppingBagIcon product 146-151
↳ افزودن محصول /apps/product/add add-product — product.create 153-159
↳ محصولات /apps/product/list product-list — product.list 160-166
↳ تغییر درصد محصولات /product/change/percent change-Percent — product.percent 167-173
سفارش ها null — BoxIcon order 176-181
↳ ثبت سفارش تک /order/create order-omde-list — order.create 183-189
↳ لیست سفارش های تک /order/list order-list — order.list 190-196
↳ سفارش های ساختنی /order/make order-makeOrder — order.makeOrder 197-203
↳ لیست سفارش های عمده /order/omde-list order-omde-list — order.omde 204-210
↳ لیست تامین /order/tamin-list order-tamin-list — order.tamin 211-217
مدیران null — UserIcon user 220-225
↳ دسترسی ها /permission user-permission — user.permission 227-233
↳ افزودن مدیر /user/create add-user — user.create 234-240
↳ لیست مدیران /user/list user-list — user.list 241-247
کیف پول null — CreditCardIcon wallet 250-255
↳ لیست کیف پول های شارژ شده /wallet wallet — wallet.list 257-263
دسته بندی ها null — ListIcon collection 266-271
↳ افزودن دسته بندی /category/add add-category — collection.create 273-279
↳ لیست دسته بندی ها /category/list list-category — collection.list 280-286
اسناد مالی null — DollarSignIcon document 289-294
↳ لیست اسناد /finical/list finical_list — document.list 296-302
↳ وارد کردن سند مالی مشتری /add/findoc findoc — document.create 303-309
تخفیفات null — GiftIcon offers 312-317
↳ تعریف تخفیف تک /major/promotion/tak/add major_promotion_add — offers.create.tak 319-325
↳ تخفیف اتوماتیک /major/promotion/autopromotion major_promotion_list — offers.autopromotion 326-332
↳ تعریف تخفیف عمده /major/promotion/add major_promotion_add — offers.create 333-339
↳ لیست تخفیفات /major/promotion/list major_promotion_list — offers.list 340-346
استثناعات تخفیف /major/offersIgnore offersIgnore SlashIcon offersIgnore 349-356
فاکتور انتقال null — BookIcon invoice 358-363
↳ افزودن فاکتور /invoice/add add-invoice — invoice.create 365-371
↳ لیست فاکتورها /invoice/list invoice-list — invoice.list 372-378
گزارشات null — FileTextIcon report 382-387
↳ گزارش تجمیعی سفارش و اسناد /report/order_item report_ordedr_item — report.order.item 389-395
↳ گزارش محصولات /report/product report_product — report.product 396-402
شهر ها null — PercentIcon cities 405-411
↳ افزودن شهر /city/create create_city — cities.create 413-419
↳ لیست شهر ها /city/list city_list — cities.list 420-426
دیدگاه ها /comments — MessageSquareIcon comment 429-436
پیامک null — MailIcon sms 437-442
↳ ارسال پیامک /sms/create create_sms — sms.create 444-450
نوتیفیکیشن null — BellIcon notify 453-458
↳ ارسال نوتیفیکیشن /notify/create create_notify — notify.create 460-466
آمار /statics — BarChartIcon statics 469-475
خبرنامه /newsletters — FileTextIcon newsletters.newsletters 476-482
UI / مدیریت (LayersIcon) پیکر بندی null — SettingsIcon config 490-495
↳ مدیریت ثابت ها /config/manage/const manage-const — config.statics 497-503
↳ گزارش /config/manage/report manage-report — config.report 504-510
↳ مدیریت کیف پول /config/manage/wallet manage-const — config.wallet 511-517

4.2 Branch menu — navMenuItems.js:524-607

i18n url icon permissionId line
پیشخوان /dashboard HomeIcon dashboard 525-532
اشخاص (group) null UserIcon persons 533-538
↳ اضافه کردن مشتری /customer/add UserPlusIcon persons.create 540-547
↳ لیست مشتریان /customer/list UsersIcon persons.list.client.single 548-555
محصولات /products ShoppingBagIcon product.list 558-565
فاکتور خرید /buy/order/list ShoppingBagIcon product.list 566-573
سفارش ها (group) null BoxIcon order 582-587
↳ ثبت سفارش /order/create InboxIcon order.create 589-596
↳ لیست سفارش /order/list ListIcon order.list 597-604

5. ACL / Permissions

5.1 Two independent systems

A. vue-acl (src/acl/acl.js) — mostly vestigial.

Item Value Line
Install Vue.use(AclInstaller) acl.js:5
initialRole 'admin', overridden by JSON.parse(localStorage.userInfo).userRole acl.js:7-10
notfound /pages/not-authorized acl.js:14
acceptLocalRules true acl.js:16
globalRules admin: AclRule('admin'); editor: AclRule('editor').or('admin') acl.js:17-20

Every route carries meta.rule of 'editor' (or 'admin' on the two dashboards) — see §3.3. Since the seeded role is admin and editor ORs admin, this never blocks anything in practice.

B. Real permission system ($hasPermission + meta.role) — the operative one.

Piece Definition
Check fn Vue.prototype.$hasPermission = (permission_id) => { const roles = store.state.users.roles; if(roles){ return roles.includes(permission_id) } } — src/main.js:142-148
Store of roles store.state.users.roles (undefined until loaded) — src/store/users/index.js:26
Loaded on login store/auth/moduleAuth.js:17 → dispatch('users/getRoles', data.roles.map(x=>x.rid)) from POST admin-login
Loaded on refresh src/router.js:170-172 → GET users/show → dispatch('users/getRoles', data.permission)
Parent expansion users/getRoles runs checkParent(roles) which, for each dotted key, adds every ancestor prefix — e.g. order.list.sts.remove implies order.list.sts, order.list, order — src/store/users/index.js:3-21, 64-66
Route gate to.meta.role checked in beforeEach — src/router.js:193-195
Menu gate item.permissionId — VerticalNavMenu.vue:322
Button gate v-if="$hasPermission('…')" in templates
Clear deleteRoles mutation — src/store/users/index.js:44-46, 67-69

5.2 Complete permission catalog — src/views/user/permissionConst.js

Tree used by the permission editor (views/user/Permission.vue) as a-tree data. 172 declared keys (a few key strings repeat with different titles, noted below).

key title (fa) line
dashboard پیشخوان 4
dashboard.omde آمار عمده فروشی 8
dashboard.tak آمار تک فروشی 12
persons اشخاص 18
persons.create اضافه کردن شخص 22
persons.create.seller افزودن کارشناس فروش 26
persons.create.client افزودن مشتری عمده 30
persons.create.single افزودن مشتری تک 34
persons.list.sellers لیست کارشناسان فروش 40
persons.list.sellers.edit ویرایش اطلاعات کارشناس فروش 44
persons.list.sellers.view.orders مشاهده سفارشات کارشناس فروش 48
persons.list.sellers.view.documents مشاهده اسناد مالی کارشناس فروش 52
persons.list.sellers.unable.order توقف سفارش کارشناس فروش 56
persons.list.sellers.able.order فعال سازی سفارش کارشناس فروش 60
persons.list.sellers.able فعال سازی حساب کاربری کارشناس فروش 64
persons.list.sellers.unable غیر فعال سازی حساب کاربری کارشناس فروش 68
persons.list.client.omde لیست مشتریان عمده 74
persons.list.client.omde.view مشاهده اطلاعات مشتریان عمده 78
persons.list.client.omde.edit ویرایش اطلاعات مشتری عمده 82
persons.list.client.omde.view.orders مشاهده سفارشات مشتری عمده 86
persons.list.client.omde.view.documents مشاهده اسناد مالی مشتری عمده 90
persons.list.client.omde.unable.order توقف سفارش مشتری عمده 94
persons.list.client.omde.able.order فعال سازی سفارش مشتری عمده 98
persons.list.client.omde.able فعال سازی مشتری عمده 102
persons.list.client.omde.unable غیر فعال سازی مشتری عمده 106
persons.list.client.single لیست مشتریان تک 112
persons.list.client.single.view مشاهده اطلاعات مشتریان تک (duplicate key at 124: «مشاهده اطلاعات مشتری تک») 116, 124
persons.list.client.single.edit ویرایش اطلاعات مشتری تک 120
branch شعب 132
branch.create افزودن شعب 137
branch.list لیست شعب 141
workshop کارگاه 147
workshop.create افزودن کارگاه 152
workshop.list لیست کارگاه ها 156
product محصولات 162
product.create افزودن محصول 167
product.list لیست محصولات 171
product.list.view مشاهده لیست محصولات (duplicate at 184: «مشاهده اطلاعات جامع محصول») 176, 184
product.list.edit ویرایش اطلاعات محصول 180
product.list.variants تنوع های محصول 188
product.list.variants.view مشاهده تنوع های محصول 193
product.list.variants.edit ویرایش تنوع محصول 197
product.list.variants.remove حذف تنوع محصول 201
product.list.variants.add افزودن تنوع محصول 205
product.list.remove حذف محصول 211
product.list.group.edit تغییر دسته ای 215
product.percent تغییر درصد محصولات 221
order سفارشات 227
order.list لیست سفارشات 232
order.list.view مشاهده لیست سفارشات (duplicate at 260: «مشاهده سفارش») 237, 260
order.list.sts وضعیت سفارش 241
order.list.sts.view مشاهده وضعیت سفارش 246
order.list.sts.remove حذف وضعیت 250
order.list.sts.submit ثبت وضعیت 254
order.list.view.edit ویرایش سفارش 264
order.list.pdf دریافت pdf 268
order.omde سفارشات عمده 274
order.omde.state وضعیت سفارش 279
order.omde.state.view مشاهده وضعیت سفارش 284
order.omde.state.submit ثبت وضعیت سفارش 288
order.omde.state.remove حذف وضعیت سفارش 292
order.omde.view مشاهده سفارش 298
order.omde.view.edit ویرایش سفارش 302
order.omde.view.remove حذف آیتم از سفارش 306
order.omde.remove حذف سفارش 310
order.omde.get دریافت pdf سفارش 314
order.makeOrder سفارشات ساختنی 320
order.makeOrder.state وضعیت سفارش 325
order.makeOrder.state.view مشاهده وضعیت سفارش 330
order.makeOrder.state.submit ثبت وضعیت سفارش 334
order.makeOrder.state.remove حذف وضعیت سفارش 338
order.makeOrder.view مشاهده سفارش 344
order.makeOrder.view.edit ویرایش سفارش 348
order.makeOrder.view.remove حذف آیتم از سفارش 352
order.makeOrder.remove حذف سفارش 356
order.makeOrder.get دریافت pdf سفارش 360
order.tamin لیست تامین 366
order.tamin.view مشاهده لیست تامین (duplicate at 394: «مشاهده سفارش») 371, 394
order.tamin.state وضعیت سفارش 375
order.tamin.state.view مشاهده وضعیت سفارش 380
order.tamin.state.submit ثبت وضعیت سفارش 384
order.tamin.state.remove حذف وضعیت سفارش 388
order.tamin.view.edit ویرایش سفارش 398
order.create ثبت سفارش تک 404
user مدیران 410
user.create افزودن مدیر 415
user.list لیست مدیران 419
user.list.view مشاهده لیست مدیران 424
user.list.edit ویرایش مدیر 428
user.list.remove حذف مدیر 432
user.list.create افزودن مدیر 436
user.permission دسترسی ها 442
user.permission.edit ویرایش دسترسی 447
user.permission.create افزودن دسترسی 451
collection دسته بندی ها 459
collection.create افزودن دسته بندی 464
collection.list لیست دسته بندی ها 468
collection.list.view مشاهده لیست دسته بندی ها 473
collection.list.edit ویرایش دسته 477
collection.list.remove حذف دسته 481
document اسناد مالی 489
document.list لیست اسناد مالی 494
document.list.view مشاهده لیست اسناد مالی 499
document.list.edit ویرایش سند مالی 503
document.list.remove حذف سند مالی 507
document.list.deny رد کردن سند مالی 511
document.list.confirm تأیید کردن سند مالی 515
document.list.get دریافت pdf سند مالی 519
document.create وارد کردن سند مالی مشتری 525
offersIgnore استثناعات تخفیف 531
offers تخفیفات 535
offers.list لیست تخفیفات 540
offers.list.view مشاهده لیست تخفیفات 545
offers.list.edit ویرایش تخفیف عمده 549
offers.list.tak.edit ویرایش تخفیف تک 553
offers.list.remove حذف تخفیف عمده 557
offers.list.tak.remove حذف تخفیف تک 561
offers.create تعریف تخفیف عمده 567
offers.create.tak تعریف تخفیف تک 571
offers.autopromotion تخفیف اتوماتیک 575
invoice فاکتور انتقال 581
invoice.create افزودن فاکتور 586
invoice.list لیست فاکتورها 590
report گزارشات 596
report.order.item گزارش تجمیعی سفارشات و اسناد مالی 601
report.product گزارش محصولات 605
cities شهرها 611
cities.create افزودن شهر 616
cities.list لیست شهرها 620
cities.list.view مشاهده لیست شهرها (duplicate at 633: «مشاهده شهر») 625, 633
cities.list.remove حذف شهر 629
cities.list.view.edit ویرایش شهر 637
comment دیدگاه ها 645
comment.view.all مشاهده لیست دیدگاه ها 649
comment.state تغییر وضعیت دیدگاه 653
comment.view مشاهده دیدگاه 657
comment.view.edit ویرایش دیدگاه 661
comment.remove حذف دیدگاه 665
sms پیامک 671
sms.create ارسال پیامک 676
sms.create.single ارسال برای یک شماره تلفن 681
sms.create.all ارسال برای همه کاربران 685
sms.create.reagent ارسال برای کارشناسان فروش 689
sms.create.omde ارسال برای مشتریان عمده 693
sms.create.multiple ارسال برای چند شماره تلفن 697
sms.list لیست پیامک های ارسال شده 703
wallet کیف پول 710
wallet.list لیست کیف پول های شارژ شده 715
wallet.charge شارژ کیف پول 719
wallet.percent تغییر درصد شارژ کیف پول 723
notify نوتیفیکیشن 729
notify.create ارسال نوتیفیکیشن 734
notify.create.multiple.reagent ارسال برای کارشناسان فروش 739
notify.create.single.customer ارسال برای یک مشتری 743
notify.create.multiple.omde ارسال برای مشتریان عمده 747
notify.create.multiple.customer ارسال برای همه مشتریان 751
notify.create.single.admin ارسال برای یک مدیر 755
notify.create.multiple.admin ارسال برای همه مدیران 759
notify.me لیست نوتیفیکیشن های دریافتی 765
config پیکربندی 771
config.statics مدیریت ثابت ها 775
config.statics.brand برند ها 780
config.statics.brand.create افزودن برند 785
config.statics.brand.edit ویرایش برند 789
config.statics.brand.remove حذف برند 793
config.statics.tags برچسب ها 799
config.statics.tags.create افزودن برچسب 804
config.statics.tags.edit ویرایش برچسب 808
config.statics.tags.remove حذف برچسب 812
config.wallet مدیریت کیف پول 820
config.report گزارش 824
statics آمار 830
newsletters.newsletters خبرنامه 834
custom سفارشی 838
custom.config.statics.slider اسلایدر موبایل 842
custom.config.statics.tags.banner.ids برچسب بنر اول سایت 846

Referenced in code but NOT in permissionConst.js (would never be grantable through the UI tree): persons.create.customer.tak (views/apps/customer/AddCustomer.vue:142), persons.list.sellers.view (views/customer/reagentList/ReagentList.vue:32).

5.3 Button-level permission checks — every $hasPermission(...) call site

Permission Call sites (file:line)
cities.list.remove views/city/cityList.vue:25
cities.list.view views/city/cityList.vue:18, 36
cities.list.view.edit views/user/ListUser.vue:108; views/city/cityList.vue:40, 47, 58, 66, 79, 90
collection.list.edit views/apps/category/List.vue:16
collection.list.remove views/apps/category/List.vue:24
comment.remove views/customer/Comments/Comments.vue:96
comment.state views/customer/Comments/Comments.vue:25
comment.view views/customer/Comments/Comments.vue:92, 104
comment.view.edit views/customer/Comments/Comments.vue:132, 155, 163
config.statics views/manage/Const.vue:3
config.statics.brand views/manage/Const.vue:8, 44
config.statics.brand.create views/manage/Const.vue:26, 36, 62, 72
config.statics.brand.edit views/manage/Const.vue:324, 342, 391, 411
config.statics.brand.remove views/manage/Const.vue:331
config.statics.tags views/manage/Const.vue:81
config.statics.tags.create views/manage/Const.vue:94, 104
config.statics.tags.edit views/manage/Const.vue:358, 375, 421
config.statics.tags.remove views/manage/Const.vue:365
config.wallet views/manage/wallet.vue:3
custom.config.statics.slider views/manage/Const.vue:122, 195
custom.config.statics.tags.banner.ids views/manage/Const.vue:110
document.list.confirm views/finical/list.vue:12
document.list.deny views/finical/list.vue:30
document.list.edit views/finical/list.vue:48
document.list.remove views/finical/list.vue:58
document.list.get views/finical/list.vue:76
notify layouts/components/navbar/TheNavbarVertical.vue:16
offers.list.edit / offers.list.tak.edit views/promotion/promotion_list.vue:53
offers.list.remove / offers.list.tak.remove views/promotion/promotion_list.vue:62
order.create views/invoice/EditInvoice.vue:3; views/invoice/AddInvoice.vue:3; views/order/create.vue:2
order.list.pdf views/order/List.vue:16
order.list.sts views/order/List.vue:41, 47; views/branch/buyList.vue:37, 43; views/workshop/buyList.vue:37, 43
order.list.sts.remove views/order/List.vue:60; views/branch/buyList.vue:56; views/workshop/buyList.vue:56
order.list.sts.submit views/order/List.vue:72; views/branch/buyList.vue:68; views/workshop/buyList.vue:68
order.list.view views/order/List.vue:13, 90
order.list.view.edit views/order/List.vue:135, 172, 182, 186, 205; views/invoice/ListInvoice.vue:125; views/branch/buyList.vue:98, 139; views/workshop/buyList.vue:98, 139
order.makeOrder.get views/order/MakeOrder.vue:21
order.makeOrder.remove views/order/MakeOrder.vue:18
order.makeOrder.state views/order/MakeOrder.vue:34, 42
order.makeOrder.state.remove views/order/MakeOrder.vue:54
order.makeOrder.state.submit views/order/MakeOrder.vue:65
order.makeOrder.view views/order/MakeOrder.vue:16, 82
order.makeOrder.view.edit views/order/MakeOrder.vue:108, 134, 139, 144, 149, 191
order.omde.get views/order/OmdeList.vue:21
order.omde.remove views/order/OmdeList.vue:18
order.omde.state views/order/OmdeList.vue:34, 42
order.omde.state.remove views/order/OmdeList.vue:54
order.omde.state.submit views/order/OmdeList.vue:65
order.omde.view views/order/OmdeList.vue:16, 82
order.omde.view.edit views/order/OmdeList.vue:107, 134, 139, 152, 159, 160
order.omde.view.remove views/order/OmdeList.vue:161
order.tamin.state views/order/TaminList.vue:23, 32
order.tamin.state.remove views/order/TaminList.vue:44
order.tamin.state.submit views/order/TaminList.vue:55
order.tamin.view views/order/TaminList.vue:12, 72
order.tamin.view.edit views/order/TaminList.vue:114, 129, 130
persons.create views/apps/customer/AddCustomer.vue:5
persons.create.client views/apps/customer/AddCustomer.vue:6
persons.create.seller views/apps/customer/AddCustomer.vue:137
persons.create.customer.tak views/apps/customer/AddCustomer.vue:142 (commented out — tab always shown, line 143)
persons.list.client.omde.able OmdeList.vue:50,119,170; OmdeNonVerifiedList.vue:50,119,168; OmdeArchivedList.vue:50,119,168; ShopkeeperList.vue:50,119,170; BankerList.vue:50,121,172
persons.list.client.omde.able.order OmdeList.vue:108,158; OmdeNonVerifiedList.vue:108,156; OmdeArchivedList.vue:108,156; ShopkeeperList.vue:108,158; BankerList.vue:109,160
persons.list.client.omde.edit OmdeList.vue:22,139; OmdeNonVerifiedList.vue:22,137; OmdeArchivedList.vue:22,137; ShopkeeperList.vue:22,139; BankerList.vue:22,141
persons.list.client.omde.unable OmdeList.vue:165; OmdeNonVerifiedList.vue:163; OmdeArchivedList.vue:163; ShopkeeperList.vue:165; BankerList.vue:167
persons.list.client.omde.unable.order OmdeList.vue:99,153; OmdeNonVerifiedList.vue:99,151; OmdeArchivedList.vue:99,151; ShopkeeperList.vue:99,153; BankerList.vue:99,155
persons.list.client.omde.view OmdeList.vue:29,142; OmdeNonVerifiedList.vue:29,140; OmdeArchivedList.vue:29,140; ShopkeeperList.vue:29,142; BankerList.vue:29,144
persons.list.client.omde.view.documents OmdeList.vue:43,148; OmdeNonVerifiedList.vue:43,146; OmdeArchivedList.vue:43,146; ShopkeeperList.vue:43,148; BankerList.vue:43,150
persons.list.client.omde.view.orders OmdeList.vue:36,145; OmdeNonVerifiedList.vue:36,143; OmdeArchivedList.vue:36,143; ShopkeeperList.vue:36,145; BankerList.vue:36,147
persons.list.sellers.able views/customer/reagentList/ReagentList.vue:61
persons.list.sellers.able.order ReagentList.vue:49
persons.list.sellers.edit ReagentList.vue:20, 29
persons.list.sellers.unable ReagentList.vue:54
persons.list.sellers.unable.order ReagentList.vue:44
persons.list.sellers.view ReagentList.vue:32
persons.list.sellers.view.documents ReagentList.vue:40
persons.list.sellers.view.orders ReagentList.vue:36
product.list.edit views/apps/product/ProductList.vue:24; views/report/product.vue:14
product.list.group.edit views/apps/product/ProductList.vue:108
product.list.remove views/apps/product/ProductList.vue:54
product.list.variants ProductList.vue:44, 181; AddProduct.vue:274
product.list.variants.add ProductList.vue:190; AddProduct.vue:282
product.list.variants.edit ProductList.vue:213; AddProduct.vue:297
product.list.variants.remove ProductList.vue:221; AddProduct.vue:306
product.list.view ProductList.vue:34; views/report/product.vue:23
sms.create views/sms/create.vue:57
sms.create.all views/sms/create.vue:18
sms.create.multiple views/sms/create.vue:27
sms.create.omde views/sms/create.vue:24
sms.create.reagent views/sms/create.vue:21
sms.create.single views/sms/create.vue:15
sms.list views/sms/create.vue:61, 64
user.list.create views/user/ListUser.vue:4
user.list.edit views/user/ListUser.vue:10, 41
user.list.remove views/user/ListUser.vue:20
user.permission.create views/user/Permission.vue:16, 36, 115
user.permission.edit views/user/Permission.vue:34
wallet.charge views/customer/single-customer/SingleCustomer.vue:18, 26, 37
wallet.list views/wallet/wallet.vue:3
wallet.percent views/wallet/wallet.vue:29

5.4 Permission checks inside table models (column visibility)

Model file Permission Effect
views/order/orderListModel.js:14-17 order.tamin.state adds sts_str + branch.name columns
views/order/OmdeListModel.js:20-32 order.omde.state adds sts column with the 7-value status filter
views/order/TaminListModel.js:14-16 order.tamin.state adds sts column
views/order/makeOrderModel.js:19-22 order.tamin.state adds sts_str_fa column
views/customer/Comments/CommentListModel.js:12-14 (role check) adds changeState column

6. Views

6.1 Full file listing under src/views (business + template)

Legend: [B] = business (reachable from a live route or embedded in one), [T] = Vuexy template demo / dead.

Root

File Purpose
views/Callback.vue [T] Auth0 callback stub (auth0 disabled at main.js:36-38).
views/DashboardAnalytics.vue [B] Single-retail (تک) dashboard; route /dashboard/analytics, role dashboard.tak.
views/DashboardECommerce.vue [B] Wholesale (عمده) dashboard; route /dashboard/ecommerce, role dashboard.omde.
views/Inp.vue [T] input scratch page, unrouted.
views/reg.vue [B] Public registration page; route /reg, full-page layout.

views/auth

File Purpose
views/auth/Login.vue [B] Admin login form (mobile + password).

views/user

File Purpose
views/user/ListUser.vue [B] Admin (مدیر) list + inline edit modal + delete.
views/user/UserCreate.vue [B] Create/edit admin form.
views/user/UserEdit.vue [B] 14-line wrapper that renders UserCreate in edit mode.
views/user/Permission.vue [B] Role (ut) ⇄ permission-tree editor.
views/user/myData.vue [B] 33-line "my profile" landing (default redirect target of /).
views/user/permissionConst.js [B] The 172-key permission tree (see §5.2).

views/customer

File Purpose
views/customer/omde/OmdeList.vue [B] Wholesale customer list (614 lines) — the richest list view.
views/customer/omde/OmdeNonVerifiedList.vue [B] Pending-verification wholesale customers (612 lines).
views/customer/omde/OmdeArchivedList.vue [B] Archived wholesale customers (612 lines).
views/customer/omde/BankerList.vue [B] Bankers (بنکدار) list (620 lines).
views/customer/omde/ShopkeeperList.vue [B] In-person shopkeepers list (614 lines).
views/customer/omde/ViewOmdeCustomer.vue [B] Wholesale customer 360° detail page (376 lines): orders/documents/sms/transactions tabs.
views/customer/omde/OmdeAdd.vue [B] Wholesale add form (215 lines, embedded).
views/customer/omde/{OmdeListModel,OmdeListNonVerifiedModel,OmdeArchiveListModel,BankerListModel,shopkeeperListModel}.js [B] XTbl column models for the five lists above.
views/customer/omde/{omdeCustomer,omdeOrder,omdeSms,omdeTransaction}.js [B] XTbl models used inside ViewOmdeCustomer tabs.
views/customer/single-customer/SingleCustomer.vue [B] Retail customer list (142 lines) + wallet-charge actions.
views/customer/single-customer/ViewSingleCustomer.vue [B] Retail customer detail (425 lines).
views/customer/single-customer/SingleCustomerList.js [B] XTbl model.
views/customer/single-customer/{singleOrder,singleSms,singleTransaction}.js [B] XTbl models for detail tabs.
views/customer/reagentList/ReagentList.vue [B] Sales-expert (کارشناس فروش) list.
views/customer/reagentList/ReagentListModel.js [B] XTbl model.
views/customer/Comments/Comments.vue [B] Product-comment moderation.
views/customer/Comments/CommentListModel.js [B] XTbl model.
views/customer/{List,CustomerEdit,CustomerEditTab*}.vue, views/customer/cell-renderer/* [T] ag-Grid-era leftovers, unrouted.

views/apps/customer

File Purpose
views/apps/customer/AddCustomer.vue [B] 3-tab person creation shell (wholesale / sales-expert / retail).
views/apps/customer/bulkCustomer.vue [B] Wholesale customer form (385 lines) — embedded + edit mode.
views/apps/customer/ReagentCustomer.vue [B] Sales-expert form (304 lines).
views/apps/customer/singleCustomer.vue [B] Retail customer form (131 lines).
views/apps/customer/EditBulkCustomer.vue [B] 19-line wrapper → bulkCustomer with :id.
views/apps/customer/EditReagent.vue [B] 19-line wrapper → ReagentCustomer with :id.
views/apps/customer/EditSingleCustomer.vue [B] 16-line wrapper → singleCustomer with :id.
views/apps/customer/{Edit,CustomerView}.vue, customer-edit/* [T] unrouted template leftovers.

views/apps/product

File Purpose
views/apps/product/AddProduct.vue [B] Product create form + inline variant manager (1044 lines — largest view).
views/apps/product/EditProduct.vue [B] 71-line wrapper → AddProduct with :id/:variant_id.
views/apps/product/ProductList.vue [B] Product list + variants drawer + bulk category change (694 lines).
views/apps/product/ChangePercent.vue [B] Bulk wage-percent change tool (254 lines).
views/apps/product/Varaint.vue [B] Variant editor component (396 lines) — embedded.
views/apps/product/EditVariant.vue [B] 15-line wrapper.
views/apps/product/comp/ProductUploader.vue, uploadMixin.js [B] Product image upload widget + mixin.

views/apps/category

File Purpose
views/apps/category/Add.vue [B] Category create/edit form (422 lines).
views/apps/category/Edit.vue [B] 12-line wrapper.
views/apps/category/List.vue [B] Category list (313 lines).
views/apps/category/CategoryTbl.js [B] XTbl model.

views/order

File Purpose
views/order/List.vue [B] Retail order list + status timeline modal + order-detail modal (322 lines).
views/order/OmdeList.vue [B] Wholesale order list (324 lines) — same structure + item removal.
views/order/TaminList.vue [B] Supply (تامین) list (241 lines).
views/order/MakeOrder.vue [B] Made-to-order (ساختنی) list (432 lines).
views/order/create.vue [B] Retail order creation with cart (451 lines).
views/order/Add.vue [T] 170-line older add form, unrouted.
views/order/{orderListModel,OmdeListModel,TaminListModel,makeOrderModel,product,workshopModel}.js [B] XTbl models.

views/finical

File Purpose
views/finical/addFinDoc.vue [B] Financial-document create/edit; 4 doc types (382 lines).
views/finical/list.vue [B] Financial-document list with confirm/deny/pdf (166 lines).
views/finical/list_model.js [B] XTbl model.

views/promotion & views/offersIgnore

File Purpose
views/promotion/promotion_list.vue [B] Promotion list (151 lines).
views/promotion/promotion_add_edit.vue [B] Wholesale promotion create/edit (415 lines).
views/promotion/promotion_tak_add_edit.vue [B] Retail promotion create/edit (388 lines).
views/promotion/autopromotion.vue [B] Automatic-discount config (92 lines).
views/offersIgnore/offersIgnore-add-edit.vue [B] Discount-exception editor (259 lines).

views/branch

File Purpose
views/branch/AddBranches.vue [B] Branch create (108 lines).
views/branch/EditBranches.vue [B] Branch edit (112 lines).
views/branch/ListBranches.vue [B] Branch list (88 lines).
views/branch/ListBranch.js [B] XTbl model.
views/branch/dashboard.vue [B] Branch-build dashboard (186 lines).
views/branch/login.vue [B] Branch-build login (82 lines).
views/branch/addCustomer.vue [B] 19-line branch customer wrapper.
views/branch/buyList.vue [B] Branch purchase-invoice list (262 lines).
views/branch/order/create.vue [B] Branch order creation.
views/branch/orderListModel.js [B] XTbl model.

views/workshop

File Purpose
views/workshop/AddWorkshop.vue [B] Workshop create (117 lines).
views/workshop/EditWorkshop.vue [B] Workshop edit (122 lines).
views/workshop/ListWorkshop.vue [B] Workshop list (88 lines).
views/workshop/ListWorkshop.js, orderListModel.js [B] XTbl models.
views/workshop/{addCustomer,buyList,login}.vue [B/T] copies of the branch equivalents; only reachable via the workshop feature.

views/invoice

File Purpose
views/invoice/AddInvoice.vue [B] Transfer-invoice create with product picker (322 lines).
views/invoice/EditInvoice.vue [B] Transfer-invoice edit (333 lines).
views/invoice/ListInvoice.vue [B] Transfer-invoice list (217 lines).
views/invoice/{AddInvoice,ListInvoice}.js [B] XTbl models.

views/city

File Purpose
views/city/createCity.vue [B] City create (166 lines).
views/city/cityList.vue [B] City list with inline edit + percent-aux modal (303 lines).
views/city/components/form.vue [B] Shared city form fields.
views/city/CityListModel.js [B] XTbl model.

views/manage, views/statics, views/report, views/wallet, views/sms, views/notify, views/newsletters

File Purpose
views/manage/Const.vue [B] Constants manager: brands, tags, mobile slider, site banner (977 lines).
views/manage/Const_new.vue [T] 256-line WIP rewrite, unrouted.
views/manage/wallet.vue [B] Wallet config: birthday credit + per-order charge percent (142 lines).
views/manage/report.vue [B] Metabase/dashboard-link embed (65 lines).
views/statics/index.vue [B] Product-view analytics by path/customer (207 lines).
views/report/order_item.vue [B] Consolidated order-item + document report (133 lines).
views/report/product.vue [B] Product/variant report (111 lines).
views/report/order_item_model.js [B] XTbl model.
views/wallet/wallet.vue [B] Charged-wallet list + percent config (103 lines).
views/wallet/walletTbl.js [B] XTbl model.
views/sms/create.vue [B] SMS blast composer (265 lines).
views/sms/list.vue [B] Sent-SMS list (115 lines) — not separately routed; used by create.vue.
views/notify/create.vue [B] Push-notification composer (156 lines).
views/notify/user.vue [B] Received-notification list (110 lines).
views/notify/notifyTbl.js [B] XTbl model.
views/newsletters/newsletters.vue [B] Newsletter subscriber list (59 lines).
views/newsletters/newsletter.js [B] XTbl model.

views/apps (template / partial)

File Purpose
views/apps/finance/{BagList,DebitList,FeeList,OrderList}.vue [T] earlier finance lists, unrouted.
views/apps/logs/{LogsList,Rules}.vue [T] unrouted.
views/apps/promotions/{AddPromotion,Editpromotion,PromotionList,VariantPromotion}.vue [T] superseded by views/promotion/*, unrouted.
views/apps/ticket/* (5 files) [T] unrouted.
views/apps/user/* (9 files) [T] Vuexy user-management demo, unrouted.
views/apps/{calendar,chat,email,todo,eCommerce}/* [T] Vuexy demo apps, unrouted.

Pure template demos (unrouted, not enumerated individually)

views/components/** (~120 files), views/charts-and-maps/** (~40), views/forms/** (~50), views/ui-elements/**, views/pages/{Error404,Error500,NotAuthorized,Maintenance}.vue (routed — see §3.5).

Business-view count: ~95 files (.vue + XTbl .js models) under the directories listed above.


6.2 Significant views in detail

views/order/List.vue — Retail order list (322 lines)

Aspect Detail
Table model views/order/orderListModel.js → POST https://henzagold.com/oapi/admin/single-order (orderListModel.js:4)
Title is_branch ? 'لیست سفارش' : 'لیست سفارش های تک فروشی' (List.vue:6, 238-240)
Columns id (شماره, filterNumber), customer.fname (نام مشتری, text), customer.lname (نام خانوادگی, text), total_price (جمع کل سفارش, text, slot total_price → `
Conditional columns if role order.tamin.state: sts_str (وضعیت) + branch.name (نام شعبه) — orderListModel.js:14-17
Row actions مشاهده سفارش (ListIcon, gate order.list.view, opens detail modal) — List.vue:13-15; دانلود pdf (FileIcon, gate order.list.pdf) → window.open('https://henzagold.com/oapi/admin/order/pdf/{id}','_blank') — List.vue:16-18, 295-297
Modal 1: status timeline gate order.list.sts; ATimeline over tempRow.activity; color green if item.proceed else gray (List.vue:246-248). Per step: submit → POST single/order-sts/edit with the item (gate order.list.sts.submit, List.vue:72-78, 258-267); remove → same endpoint with row.remove = true (gate order.list.sts.remove, index > 0 only, List.vue:60-68, 268-278). Both close the modal, $message.info('ویرایش موفق آمیز') / $message.error('خطا در ویرایش'), then this.$refs.tbl.fetch(). Confirmation uses APopconfirm with title «آیا مطمئن به حذف وضعیت مورد نظر هستید ؟», ok بله, cancel بی خیال. showSts is a no-op when row.branch_id is set (List.vue:249-254).
Modal 2: order detail gate order.list.view, width 80%. ADescriptions: مشتری, تلفن همراه, تاریخ ثبت, وضعیت, نام دریافت کننده محصول, تلفن همراه دریافت کننده, تلفن ثابت دریافت کننده (List.vue:93-115); آدرس ارسال block: استان, شهرستان, کد پستی, آدرس (List.vue:116-129). Items card: thumbnail via ZoomableImage (falls back to assets/images/no-image.png), نام محصول (ATag blue), عنوان تنوع, وزن نهایی (AInputNumber when editMode && order.list.view.edit, else red ATag), تعداد (editable likewise), توضیحات (List.vue:140-197). Footer: باشه + ویرایش سفارش (gate order.list.view.edit). editRow() has its axios.put('order/'+id, …) commented out (List.vue:279-289) — it only toggles state and refetches.
Export inherited from XTable toolbar (excel / json / print).

views/order/OmdeList.vue / TaminList.vue / MakeOrder.vue

Same three-part shape (list + status timeline + detail modal), differing in endpoint, permission family and status vocabulary:

View Table URL Permission family Status endpoint
OmdeList.vue POST .../major/order/table (OmdeListModel.js:7) order.omde.* POST major/order-sts/edit
TaminList.vue POST .../order-tamin (TaminListModel.js:3) order.tamin.* POST order-sts/edit
MakeOrder.vue POST .../get-custom-orders (makeOrderModel.js:4) order.makeOrder.* delete via DELETE custom-order/{id}, edit via PUT custom-order/{id}

OmdeList adds row-level delete (order.omde.remove), pdf (order.omde.get), and per-item removal inside the detail modal (order.omde.view.remove → DELETE major/order_item/).

Wholesale order status filter (OmdeListModel.js:21-32): 0: معلق, 1: ثبت سفارش, 2: تایید مدیر سیستم, 3: در حال تامین, 4: در حال آماده سازی , 5: تحویل مسئول فروش, 6: تحویل مشتری . Customer-confirmation filter (OmdeListModel.js:33-38, TaminListModel.js:17-22): 1: تایید شده, 2: در انتظار تایید.

MakeOrder columns (makeOrderModel.js:5-24): customer.id (شماره), customer.fname, customer.lname, color (رنگ محصول), size (سایز محصول), color_mina (رنگ مینا), color_stone (رنگ سنگ), sum (تعداد), time_creat_fa (تاریخ ثبت, filterDate), time_update_fa (hidden), customer.name (ثبت کننده), sts_str_fa (وضعیت, only with order.tamin.state), opt. Admin-confirm sets sts_str_fa = "تایید ادمین" (MakeOrder.vue:397).

views/order/create.vue — Retail order creation (451 lines)

Aspect Detail
Page gate $hasPermission('order.create') on the root element (create.vue:2)
Cart vuex cart module: cart/add (create.vue:229), cart/remove (create.vue:32), cart/updateItemQuantity (create.vue:44), cart/clear (create.vue:276), cart/init (create.vue:307, 399)
Qty control AInputNumber min 1, max variant.qty > 0 ? variant.qty : Infinity (create.vue:44)
Bootstrap calls GET /order/type → sale types (create.vue:395); POST /single-customer → rows as the customer dropdown (create.vue:397); cart/init (create.vue:399)
Fields (all ant v-decorator) customer_id — required, «مقدار را وارد نمایید», searchable select (create.vue:77); sts — required (create.vue:84); type — required (create.vue:91); shipping_address.reciver_fname, .reciver_lname, .province, .city, .zipcode, .reciver_phone, .reciver_fixed_phone — all optional, same message (create.vue:98-116); note textarea {minRows:3,maxRows:5} optional (create.vue:120); shipping_address.address textarea optional (create.vue:123); hidden app initialValue 'app' (create.vue:126); hidden reagent_id initialValue from data (create.vue:129)
sts enum (create.vue:158-165) 1: ثبت سفارش, 2: تایید مدیر سیستم, 3: در حال تامین, 4: در حال آماده سازی, 5: ارسال, 6: تحویل مشتری — note: no 0: معلق here, unlike the wholesale list filter
Inline variant creation POST add/variant with {...variant, title: variant.grams + ' گرم'} (create.vue:304) — the variant title is auto-derived from the weight
Product lookup GET product/show/{id} (create.vue:360); PUT product/update/{id} (create.vue:341)

views/apps/product/AddProduct.vue — Product create/edit (1044 lines)

Fields (a-form-item label → v-decorator key → rules):

Label Field Rules Line
کد محصول product_code required, «لطفا مقدار را وارد کنید» 11-14
نام محصول title required, same msg 16-19
نوع نمایش show_type (radio) required, initialValue 3 — 1: سایت, 2: اپلیکشن موبایل, 3: سایت و اپلیکشن موبایل 21-35
دسته بندی cats (multiple select) required, «وارد کردن دسته بندی الزامی است» 37-52
برند brand_id required 53-68
سینی ها ciny_ids rules commented out (optional) 69-99
برچسب ها tags optional, «وارد کردن برچسب الزامی است » 100-115
شرح محصول (موبایل) body_html none (quill editor) 116-121
شرح محصول (سایت) (separate editor) none 122-129
نوع تحویل delivery_type (radio) required, initialValue 1 — 1: کوتاه مدت, 2: بلند مدت 130-142
متن پیام نمایش به کاربر در بازه بلند مدت message_long_delivery none; disabled unless delivery_type == 2 143-149
نمایش محصول is_active (switch) initialValue true, valuePropName: 'checked' 150-152
پیشنهاد روز offer_day (switch) initialValue true 153-155
تضمین قیمت has_warranty (switch) initialValue true 156-158
موجود is_exist (switch) initialValue true 159-161

Variant sub-form (inside the same page, gated by product.list.variants, AddProduct.vue:274):

Label Field Rules Line
عنوان title required (empty msg) 345-352
تعداد qty required 353-363
وزن grams required 364-371
رنگ color required, «لطفا مقدار را وارد کنید»; options from GET /product/color (AddProduct.vue:857) 372-380
فعال is_active (switch) — 381-383
پیش سفارش is_pre_order (switch) — 384-386
اجرت ریالی rial_pay required 391-399
اجرت درصدی percentage_pay required 400-409
توضیح مختصر details none 411-413
توضیحات کامل description none 414-416
(hidden) product_id_id, id none 417-418

Variant actions gated: add product.list.variants.add (282), edit product.list.variants.edit (297), remove product.list.variants.remove (306).

API calls: POST product/create (660); PUT product/update/{id} (698); GET product/show/{id} (718); GET /product/color (857); POST category (976); GET brand?text_search=% (986); GET /const/__list__tags (989); GET https://henzagold.com/oapi/admin/ciny (991).

views/apps/product/ProductList.vue (694 lines)

Aspect Detail
Model src/table/product.js:20 → POST .../products, title «لیست محصولات»
Columns id (کد, filterNumber), ProductImage (تصویر محصول, slot image, noSort), title (نام محصول, text), brand.title (برند, text), category.collection.title (دسته بندی, text), product_code (کد محصول, text), show_type (نوع نمایش, filterSelect), action (عملیات, slot op, noSort) — table/product.js:21-32
Row actions ویرایش (product.list.edit, line 24) → window.open('/admin/apps/product/edit/{id}','_blank') (648); مشاهده (product.list.view, 34); تنوع ها (product.list.variants, 44) → POST get/variants {id} (631); حذف (product.list.remove, 54) → POST delete/product/{id} then $refs.tblProducts.fetch() (670-672)
Variant drawer actions add → window.open('/admin/apps/product/{id}/variant/add','_blank') (546); toggles → GET product/warranty/{id} (556), GET product/exist/{id} (558); offer toggle → GET /product/offer/{id} (570); variant reload → GET product/{product_id}/variant (665)
Bulk edit multi-select rows → card «تغییر دسته ای» (gate product.list.group.edit, line 108-114) with confirm «آیا مطمئن به تغییر {n} محصول هستید ؟» → POST /change/all (582)

views/apps/customer/* — person forms

All three tabs share the ant v-decorator pattern; every rule is required: false — validation is effectively server-side only.

bulkCustomer.vue (wholesale, 385 lines) fields: fname (نام, 17), lname (نام خانوادگی, 24), ncode (کد ملی, 31), password (رمز عبور, 40), mobile (شماره تلفن همراه, 48) with pattern /^(?:0|98|\+98|\+980|0098|098|00980)?(9\d{9})$/ msg «تلفن وارد شده نامعتبر است», type (نوع کاربری, 61), store_name (نام مغازه, 71), phone (تلفن, 78), pasazh_name (نام پاساژ, 85), city_id (شهر, 94, msg «شهر را انتخاب نمایید»), mcode (کد مشتری ته حساب, 106), a Jalali date field (116, msg «تاریخ دریافت را وارد نمایید»), image uploads عکس جواز کسب / عکس سردر مغازه / عکس پروفایل (119-143), address (آدرس, 147), reagent_id (کارشناس فروش, 164/182, msg «کارشناس فروش را انتخاب نمایید»), percent (درصد روی محصول, 197, msg «درصد روی محصول را وارد نمایید»), gram_level (سقف اعتبار, 204, msg «سقف اعتبار را وارد نمایید»). Calls: GET cities/get-percent-aux/{city_id} on city change (265); dispatch('customer/omdeSave', values) (296); GET query/reagent (315); POST cities/list (321); GET customer/{id} in edit mode (330).

ReagentCustomer.vue (304 lines) — same field set minus wholesale-only fields; mobile pattern differs: /^09(0[1-2]|1[0-9]|3[0-9]|2[0-1])-?[0-9]{3}-?[0-9]{4}$/ (line 52). Calls GET cities/get-percent-aux/{v} (221), dispatch('customer/omdeSave') (245), POST cities/list (265), GET customer/{id} (274).

singleCustomer.vue (retail, 131 lines) fields: fname (9), lname (16), phone (24), Jalali date (34), city_id (40). Calls: PUT single/{id} on edit (90), POST single on create (92), POST cities/list (110), GET single/{id} (119).

views/finical/addFinDoc.vue — Financial documents (382 lines)

Document type (type, initialValue 2, addFinDoc.vue:18-32):

value label
1 آب شده (melted gold)
2 حواله (transfer)
3 چک (cheque)
4 پولی (cash)

Fields shown conditionally on form.getFieldValue('type'):

Label Field Rule Applies to Line
نوع سند type optional, initial 2 all 18
مشتری customer_id required all 39/46
توضیحات note optional all 53
وزن (گرم) original_value required آب شده 70
عیار ayar required آب شده 76
نام آزمایشگاه lab optional آب شده 89
انگ ang optional آب شده 95
وزن (گرم) value required حواله 110
حواله به to optional, initialValue 'حواله کوثر'; options = 'حواله کوثر' + havale_list حواله 121
مبلغ چک price required چک 138
وزن (گرم) value optional چک 144
نام صاحب حساب account_name optional چک 151
نام بانک bank_name optional چک 157
میزان پول price required پولی 174
مظنه price_per_gram required پولی 180

views/finical/list.vue row actions: تایید (document.list.confirm, line 12), رد (document.list.deny, 30), ویرایش (document.list.edit, 48), حذف (document.list.remove, 58), pdf (document.list.get, 76). List columns (views/finical/list_model.js, POST .../cash/table): id (شماره سفارش, number), type_str (نوع سند, text), price (پول), value (وزن نهایی (گرم)), to (به, hidden), customer.name (نام و نام خانوادگی مشتری), note (توضیحات), ayar (عیار, number), lab (آزمایشگاه), recive_date (تاریخ دریافت, date), account_name (hidden), bank_name (hidden), caj (تاریخ ثبت, date), uaj (hidden), confirmed (وضعیت تایید سند, filterSelect {0:'تایید نشده', 1:'تایید شده'}, list_model.js:19-22), price_per_gram (مظنه, hidden), original_value (وزن طلای داده شده, hidden), ang (انگ, hidden), opt.

views/user/UserCreate.vue + views/user/ListUser.vue — Admin CRUD

Shared field rules (UserCreate.vue:7-60, mirrored in ListUser.vue:48-100 edit modal):

Label Field Rules
نام fname required «لطفا مقدار را وارد کنید»; pattern /^([\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C ])+$/ msg «فیلد نام باید شامل حروف فارسی باشد.»
نام خانوادگی lname same as fname
شماره موبایل mobile required; pattern /(\+98|0|98|0098)?([ ]|-|[()]){0,2}9[0-9]([ ]|-|[()]){0,2}(?:[0-9]([ ]|-|[()]){0,2}){8}/ msg «فرمت شماره موبایل نادرست است.»; min: 11 msg «شماره موبایل باید 11 رقم باشد »
نوع کاربری ut required «وارد کردن مقدار الزامی است»; options from GET const/__list__ut (UserCreate.vue:169)
رمز عبور password required (multi-rule block, UserCreate.vue:43-50)
تأیید رمز عبور password_confirmation required + match check (UserCreate.vue:55-62)

Calls: create POST /users (UserCreate.vue:108); update PUT /users/{route.params.id} (UserCreate.vue:104) and PUT /users/{tempRow.id} from the list modal (ListUser.vue:162); delete DELETE users/{id} (ListUser.vue:224) followed by $refs.tbl.fetch(). List model src/table/userTbl.js:2: GET/POST /users/list; columns id (کد مدیر, noFilter), fname (نام, text), lname (نام خانوادگی, text), mobile (موبایل, text), ut (نوع کاربر, number, slot ut), op (عملیات, slot, noSort).

views/user/Permission.vue — Role/permission editor (175 lines)

Field Rule Line
سطح کاربر (ut) required, «لطفاسطح دسترسی را انتخاب کنید» 9
نام سطح دسترسی (user) required: newUT (only when creating a new role) 19
نقش ها a-tree over permissionConst.js 23

Flow: load role list GET /const/__list__ut (113); load a role's grants GET /roles/{id} (136); create a new role POST const {key:"__list__ut", val: values.user} (77) then POST roles/create {ut: newUtId, roles: rid} (80); when editing, each removed key is deleted individually with a 500 ms stagger — DELETE /roles/{ut}/{x} inside setTimeout(…, 500) (86) — then POST roles/create {ut, roles: rid} (93).

views/sms/create.vue — SMS blast (265 lines)

type select (required, plus {type:'number', message:'مقدار انتخاب شده نا معتبر است'} — create.vue:13), options each gated:

value label gate
-1 یک شماره تلفن sms.create.single
0 همه کاربران sms.create.all
1 کارشناسان فروش sms.create.reagent
2 مشتریان عمده sms.create.omde
9 چند شماره تلفن sms.create.multiple

Other fields: mobile (shown when type === -1) required + pattern /^(\+98|0098|98|0)?9\d{9}$/g msg «فرمت شماره موبایل نادرست است.» (35); mobiles (multi) required (43); text (متن پیامک) required (52). Calls: sent-list POST /sms/table (168); test send POST https://henzagold.com/oapi/api/sms/batch/test (195); real send POST https://henzagold.com/oapi/api/sms/batch (216, 231). Note these two hit /oapi/api/…, not the /oapi/admin/ base.

views/notify/create.vue — Push notification (156 lines)

Field Rule Line
عنوان (title) required «لطفا مقدار را وارد کنید» 7
نوع کاربر (type_send) required 13
کاربر (customer_id) required, shown when type_send ∈ {3, 5} 31
متن پیام (note) required «مقدار را وارد نمایید» 55

type_send enum (create.vue:83-90): 1: کارشناسان فروش, 2: مشتریان عمده, 3: یک مشتری, 4: همه مشتریان, 5: یک مدیر, 6: همه مدیران. Calls: POST /notify (112); admin picker POST /users/list (128); customer picker POST /notify/customer (139). Received list (views/notify/user.vue + notifyTbl.js:3): POST /notify/table, columns id (شماره), title (عنوان), note (متن), opt; tbl.noFilters() (notifyTbl.js:9). Mark-read GET /notify/read/{id}; detail GET /notify/{id}.

views/manage/wallet.vue — Wallet config (142 lines)

Section Field Rule Line
Birthday credit birthday_expire (انقضا (روز)) required 13
Birthday credit birthday_credit (میزان (تومان)) required 18
Per-order charge expire (انقضا (روز)) required 34
Per-order charge percent (درصد) required 42

Calls: GET /wallet/config (77), GET /wallet/birthday/config (91), POST /wallet/config (109, 126). Page gated by config.wallet (wallet.vue:3).

views/wallet/wallet.vue — Charged-wallet list (103 lines)

Page gated by wallet.list (line 3); percent control gated by wallet.percent (line 29). Model walletTbl.js:3 → POST /wallet/table; columns id (شماره), customer.name (نام مشتری, text), order.id (شماره سفارش, text), value (میزان شارژ, slot value), expire_at (تاریخ انقضا, slot time, noSort); tbl.noFilters() (walletTbl.js:10).

views/statics/index.vue — Product-view analytics (207 lines)

mode select (index.vue:6-17): title (عنوان مسیر), customer/all (تمام مشتریان), customer/id (یک مشتری — reveals a searchable customer select). Calls: POST log/{mode} or POST log/customer/{customer} with {start_at, end_at} (index.vue:146-147); POST fallback (171); GET log/ago/{customer} (174); customer list GET /log/list/customer (188). Columns for the customer/* modes nest customer.id (شناسه), customer.name (نام), customer.mobile (موبایل) under «مشتری», then time (زمان) and title (نام محصول) (index.vue:105-136).

Customer list views (OmdeList / OmdeNonVerifiedList / OmdeArchivedList / BankerList / ShopkeeperList)

Five near-identical 612–620-line views. Shared column model (differing only in URL):

key title filter flags
id کد number
fname نام text hidden
lname نام خانوادگی text hidden
name نام و نام خانوادگی text
mobile موبایل text hidden, noSort
city_id شهر select(store.state.users.cityFilters), filterKey('city_id') hidden, slot city
reagent.name کارشناس فروش text noSort
gram_level سطح اعتبار number noSort
percent درصد number noSort
remain بدهی گرمی number noSort
rial_remain بدهی ریالی number noSort
caj تاریخ ثبت date noSort
uaj بروزرسانی date hidden, noSort
sts_str وضعیت ثبت سفارش — slot sts, noSort
active وضعیت حساب کاربری select slot active, noSort
phone تلفن text hidden, noSort
address آدرس text hidden, noSort
store_name نام مغازه text hidden, noSort
zone منطقه text hidden, noSort
pasazh_name نام پاساژ text hidden, noSort
opt عملیات — slot opt, noSort

(OmdeListModel.js:8-42 and the four siblings, identical line numbering.)

View Table URL
OmdeList POST .../customer (OmdeListModel.js:7)
OmdeNonVerifiedList POST .../major/verify/table (OmdeListNonVerifiedModel.js:7)
OmdeArchivedList POST .../major/archive/table (OmdeArchiveListModel.js:7)
BankerList POST .../banker (BankerListModel.js:7)
ShopkeeperList POST .../shopkeeper (shopkeeperListModel.js:7)

Row actions (all five, gates listed in §5.3): ویرایش, مشاهده, مشاهده سفارشات, مشاهده اسناد مالی, توقف سفارش / فعال سازی سفارش, فعال سازی / غیر فعال سازی حساب. Endpoints used: POST customer/toggle-active, POST customer/toggle-sts, POST major/verify, GET major/archive/{id}, GET major/dashboard/{id}.

ReagentList.vue uses POST .../reagent (ReagentListModel.js:7) with grams_sell (میزان فروش) added and the shop/zone columns removed (ReagentListModel.js:21).

SingleCustomer.vue (SingleCustomerList.js:3 → POST .../single-customer): id (کد, number), fname (نام, text), lname (نام خانوادگی, text, noSort), phone (تلفن تماس, text, noSort), email (ایمیل, text, noSort), branch.name (نام شعبه, text, noSort), op (عملیات). Wallet-charge actions gated by wallet.charge (SingleCustomer.vue:18, 26, 37).

Detail pages (ViewOmdeCustomer.vue, ViewSingleCustomer.vue)

Tabbed 360° views built from four XTbl models each:

Tab Wholesale model → URL Retail model → URL
Customers omdeCustomer.js:4 → .../major/customer —
Orders omdeOrder.js:4 → .../major/order singleOrder.js:4 → .../single/order
SMS omdeSms.js:3 → .../major/sms singleSms.js:3 → .../single/sms
Transactions omdeTransaction.js:3 → .../major/cash singleTransaction.js:3 → .../single/transaction

Transaction columns (omdeTransaction.js:4-7): id (شماره), order.id (شماره سفارش, text, setDefaultValue('-')), value (میزان شارژ, slot), expire_at (تاریخ انقضا, noSort, setDefaultFilter('jdate'), setDefaultValue('-')). SMS columns (omdeSms.js:4-8): id, massage (متن پیامک, text), mobile (شماره تلفن, slot value), created_at (تاریخ انقضا, setDefaultFilter('jdate'), setDefaultValue('-')), sts (وضعیت, slot). Other calls: GET single/{id}, GET single/order/{id}, GET single/report/{id}, GET single/wallet/{id}, GET log/ago/{id}.

views/report/*

order_item.vue model (order_item_model.js:3 → POST .../report/order_item) columns: id (کد آیتم), product_title (نام محصول), variant_title (عنوان تنوع), original_rash_weight (وزن خام), rash_weight (وزن نهایی), qty (تعداد), percent (درصد), rial_pay (اجرت ریالی), note (توضیحات), order_id (شماره سفارش), order.caj (تاریخ ثبت شفارش), order.cashe.id (شماره سند), order.cashe.type_str (نوع سند), order.cashe.value (جمع کل سند), order.customer.fname, order.customer.lname, order.customer.name, order.parent.name (کارشناس فروش) — order_item_model.js:4-21.

product.vue model (src/table/variant.js:3 → POST /product/report) columns: id (کد تنوع), product_id_id (کد محصول, hidden), product.title (نام محصول, filterKey('product')), title (نام تنوع), qty (تعداد), grams (وزن), color_str (رنگ, slot color), rial_pay (اجرت ریالی), percentage_pay (اجرت درصدی), op (عملیات). Edit action → window.open('/admin/apps/product/edit/{product.id}/{row.id}','_blank') (product.vue:101), gate product.list.edit (line 14).

Other list models

View Model file:line URL Columns
Branch list views/branch/ListBranch.js:3 POST .../branch/table name (نام, text), address (آدرس, text), phone (شماره تلفن, number), user.name (مدیر شعبه, number), op (slot actions)
Branch buy list views/branch/orderListModel.js:4 POST .../branch/product/table id (شماره, number), count_item (تعداد آیتم ها), sum_weight (جمع وزن), caj (تاریخ ثبت, date), uaj (hidden), sts_str (وضعیت, conditional), note (توضیحات), opt
Workshop list views/workshop/ListWorkshop.js:3 POST .../workshop/table name, address, phone (number), op (slot actions); _noDownload = true (line 10)
Workshop buy list views/workshop/orderListModel.js:4 POST .../workshop/product/table id, count_item, sum_weight, caj, uaj (hidden), opt
Invoice list views/invoice/ListInvoice.js:4 POST .../branch/product/table id (ردیف, number), name (نام مشتری, text), sum_weight (جمع کل سفارش, number, noSort), count_item (تعداد آیتم ها, number, noSort), caj (تاریخ ثبت, date, noSort), allocator_user.name (ثبت کننده, slot user, noSort), note (توضیحات, text, noSort), op (slot actions)
Invoice product picker views/invoice/AddInvoice.js:3 POST .../products id, ProductImage (slot image), title, min_gram (وزن, number), brand.title, category.collection.title, product_code, max_gram (حداکثر وزن, hidden), op; _noDownload = true (line 16)
Order product picker views/order/product.js:3 POST .../products id, ProductImage, title, brand.title, category.collection.title, product_code, min_gram (hidden), max_gram (hidden), op; _noDownload = true
Category list views/apps/category/CategoryTbl.js:3 POST .../category id (شماره, number), image (تصویر, slot, noSort), type_str (نوع نمایش), title (عنوان دسته), parent.title (پدر دسته), …, opt
Promotion list src/table/list_model.js:3 POST .../major/promotion/table id (شماره تخفیف, number), title (عنوان), description (توضیحات), type_str (نوع تخفیف), start_atj (تاریخ شروع), end_atj (تاریخ پایان), type_customer (نوع مشتری, slot), opt
Comments views/customer/Comments/CommentListModel.js:4 POST .../comment/table product_id (hidden, number), product.title (نام محصول, slot productName), customer.id (hidden), customer (نام نویسنده, slot), reply (پاسخ, slot, noSort), sts (وضعیت, slot, noSort), changeState (conditional), opt
City list views/city/CityListModel.js:3 POST .../cities/list (model constructed with no .add() calls — columns built in the view)
Brand list src/table/brand.js:3 POST .../brand id (کد, number), title (نام برند, text)
Newsletter views/newsletters/newsletter.js:3 POST .../fashion/table name (نام, text), mobile (شماره موبایل, number), op (slot actions); _noDownload = true
Wholesale customer (alt) src/table/major_customer.js:3 POST .../major/table id, lname (hidden), name ×2, mobile (hidden), gram_level, percent, remain, rial_remain, grams_sell, caj, uaj (hidden)

7. Store

src/store/store.js — root with state/getters/mutations/actions + 11 namespaced modules (store.js:39-60). strict: process.env.NODE_ENV !== 'production' (store.js:59).

Module key File Purpose
cart store/cart/cart.js Retail order cart
invoiceCart store/invoiceCart/invoiceCart.js Transfer-invoice cart (near-identical copy of cart)
auth store/auth/moduleAuth.js Live auth (login, token/user persistence)
category store/category/index.js Category CRUD
variant store/variant/index.js Product variants
product store/product/index.js Product CRUD
promotion store/promotion/index.js Variant promotions
order store/order/index.js Order CRUD
customer store/customer/index.js Customer CRUD
eCommerce store/eCommerce/moduleECommerce.js Vuexy template demo
variantpromotion store/variantpromotion/index.js Per-variant promotion rows
users store/users/index.js Roles/permissions + city filter cache

Registered but commented out (store.js:21-24): todo, calendar, chat, email. manage/const.js is imported as moduleConst but not registered (store.js:29, 48 — line 48 is commented). Directories present and unused: store/data-list/, store/user-management/, store/manage/index.js (empty file).

Root state — src/store/state.js:73-91

AppActiveUser (merged localStorage.userInfo over defaults, state.js:18-46), bodyOverlay, isVerticalNavMenuActive, is_touch_device, mainLayoutType (from themeConfig), navbarSearchAndPinList, reduceButton, verticalNavMenuWidth, verticalNavMenuItemsMin, scrollY, starredPages, theme, themePrimaryColor, windowWidth, orderCount (state.js:90). Root mutations of note: setOrderCount (mutations.js:20-22), UPDATE_USER_INFO (mutations.js:100-121, also writes localStorage.userInfo), layout/theme toggles (mutations.js:23-92).

auth — src/store/auth/moduleAuth.js

Item Detail
state.user function reading localStorage[isBranch()?'branch_user':'user'] (moduleAuth.js:5-7) — a function, not a value; router.js:164 truth-tests it, so it is always truthy
state.token function reading localStorage[isBranch()?'branch_token':'token'] (moduleAuth.js:8-10) — same caveat
state.userPermission [] (moduleAuth.js:11) — unused
action login(payload) POST admin-login → dispatch('users/getRoles', data.roles.map(x=>x.rid), {root:true}), then delete data.roles; delete data.ut, commit('INJECT', data); rethrows on error (moduleAuth.js:14-24)
mutation INJECT writes `localStorage[token

Dead siblings: moduleAuthActions.js (firebase + jwt flows, 362 lines), moduleAuthState.js (firebase isUserLoggedIn), moduleAuthMutations.js (SET_BEARER), moduleAuthGetters.js (empty).

users — src/store/users/index.js

State: cityFilters: {}, userInfo: undefined, roles: undefined (index.js:23-27).

Action Endpoint / behavior
getCities POST cities/list → commit('setCities', res.data.rows) which maps {[x.id]: x.title} (index.js:51-57, 30-34)
setUserInfo / deleteUserInfo local only (index.js:58-63)
getRoles(roles) commit('getRoles', checkParent(roles)) — expands every dotted key to all ancestor prefixes (index.js:64-66, 3-21)
deleteRoles clears state.roles (index.js:67-69)

CRUD modules — endpoints per action

Module Action HTTP Endpoint Line
order remove(id) DELETE order/{id} then dispatch('order/fetch') order/index.js:42-43
order save(payload) PUT / POST order/{id} if payload.id else order/ order/index.js:54, 57
order fetch GET order/ params {page: state.page, text_search: state.searchQuery} order/index.js:69
product init GET config/statics product/index.js:46
product remove(id) POST delete/product/{id} then fetch product/index.js:58-59
product save POST product product/index.js:78
product (2nd save) PUT / POST product/{id} else product product/index.js:91, 94
product fetch GET product/ params {page, text_search} product/index.js:106
product (variant) PUT product/variant/{id} product/index.js:115
customer remove(id) DELETE user/profile/{id} then fetch customer/index.js:44-45
customer save PUT / POST user/profile/{id} else user/profile/ customer/index.js:56, 59
customer omdeSave POST customer/create customer/index.js:71
customer fetch GET user/profile params {page, text_search} customer/index.js:82
customer getEditData({id}) GET user/profile/{id} customer/index.js:94
category remove(id) DELETE category/{id} then fetch category/index.js:39-40
category save PUT / POST category/{id} else category/ category/index.js:52, 55
category fetch GET category/ params {page, text_search} category/index.js:67
variant init GET config/statics variant/index.js:38
variant save POST add/variant (both create and "update" paths) variant/index.js:51, 54
variant remove(row) DELETE /product/variant/{row.id} variant/index.js:66
promotion init GET config/statics promotion/index.js:46
promotion remove(id) DELETE product/variant/promotion/{id} then fetch promotion/index.js:58-60
promotion save PUT / POST product/variant/promotion/{id} else product/variant/promotion promotion/index.js:70, 73
promotion fetch GET product/variant/promotion params {page, text_search} promotion/index.js:85
variantpromotion remove(id) DELETE product/variant/promotion/variant-promotion/{id} variantpromotion/index.js:58
variantpromotion save PUT / POST product/variant/promotion/variant-promotion/{id}/ else product/variant/promotion/variant-promotion variantpromotion/index.js:71, 75
variantpromotion fetch(id) GET /product/variant/promotion/{id}/variant-promotion variantpromotion/index.js:88
cart / invoiceCart init POST product/variant body {products_id: ids} cart/cart.js:73; invoiceCart.js:68

Shared list-module state shape (order, customer, category, product, promotion, variantpromotion): {model, rows, count, page, loading, searchQuery} with mutations ADD_ITEM, LOADING, SET_PAGE/PAGE_SET, SEARCH_QUERY_SET, FETCH, INJECT_LIST, EDIT_ROW (e.g. order/index.js:3-36).

cart / invoiceCart business rules

Rule Evidence
Identity key is the pair (pid, vid) cart/cart.js:11
An item is only addable if variant && !(!variant.is_pre_order && variant.qty === 0) — i.e. out-of-stock is allowed only when the variant is pre-order cart/cart.js:15; invoiceCart.js:15
Re-hydration (init) re-applies the same stock rule against variants_all[0] and drops items that fail cart/cart.js:79; invoiceCart.js:74
Each rebuilt item carries {vid, pid, product, qty, promotion_id: product.promotion?.id ?? null} cart/cart.js:80-86
INIT is committed after every mutation (persistence hook) cart/cart.js:52-68

8. Shared utils / filters / mixins

src/utils/index.js

Export Behavior Line
isBranch() process.env.NODE_ENV == 'branch' (also console.logs the env) utils/index.js:1-4

This single flag drives: token/user localStorage key (axios.js:6, moduleAuth.js:6/9, router.js:173/174/188), route table (router.js:27, 39), menu (navMenuItems.js:609), layout type (themeConfig.js:23), page titles (order/List.vue:6).

src/filters/filters.js — Vue global filters

Filter Signature Behavior Line
capitalize (value) Title-cases each space-separated word 4-14
title (value, replacer='_') Splits on replacer, capitalizes, re-joins with space 16-27
truncate (value, limit) value.substring(0, limit) 29-31
tailing (value, tail) value + tail 33-35
time (value, is24HrFormat=false) H:MM (24h) or h:MM بعد از ظهر / قبل از ظهر (12h) 41-53
date (value, fullDate=false) Slices a JS Date string: DD MMM or DD MMM YYYY 55-63
month (val, showYear=true) Regex-extracts month (+ year) from a Date string 65-75
csv (value) value.join(', ') 77-79
filter_tags (value) Strips HTML tags via `/</?[^>]+(> $)/g`
k_formatter (num) num > 999 ? (num/1000).toFixed(1)+'هزار' : num 85-87
price (val) Thousand separators: val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); returns val unchanged when falsy (so 0 passes through) 92-97
priceUnit (val) Same as price + ' تومان ' suffix 99-104
jdateTime (val) moment(val).format('jYYYY/jMM/jDD - hh:mm:ss') — note 12-hour hh with no am/pm marker 107-112
jdate (val) moment(val).format('jYYYY/jMM/jDD') 114-119
dynamicFilter (value, name, ...args) Vue.filter(name)(value, ...args) — used by XTbl setDefaultFilter 120-122
none val => val Identity — the default for setDefaultFilter 123

Notable absences: there is no gram/weight formatter, no Persian↔English digit-conversion utility, and no price-input mask anywhere in the codebase. Weights are rendered raw ({{item.grams}}, order/List.vue:173) and entered through plain a-input-number. Prices are formatted only on read via price/priceUnit.

src/mixins/citiesModel.js

Method Behavior Line
normalizeCityId(data) Clones data; if city_id is null and city is set, resolves it — from city.id when city is an object, or by title match against this.cities when it's a string; finally coerces city_id to Number mixins/citiesModel.js:3-18
recursiveFunction(obj, level) Builds an ant a-cascader/a-tree-select node tree from the flat this.cities array using level/parent; disabled: level === 0 (provinces not selectable); emits {value:Number(id), label:title, key:Number(id), disabled, children?} mixins/citiesModel.js:19-46

src/views/apps/product/uploadMixin.js — product image upload helpers. src/components/input/mixins.js — shared form-input mixin (see §9).

Constants / enums (exact values)

Domain Values Source
Wholesale order status (filter) 0: معلق, 1: ثبت سفارش, 2: تایید مدیر سیستم, 3: در حال تامین, 4: در حال آماده سازی , 5: تحویل مسئول فروش, 6: تحویل مشتری views/order/OmdeListModel.js:23-29
Retail order status (create form) 1: ثبت سفارش, 2: تایید مدیر سیستم, 3: در حال تامین, 4: در حال آماده سازی, 5: ارسال, 6: تحویل مشتری views/order/create.vue:158-165
Customer confirmation 1: تایید شده, 2: در انتظار تایید views/order/OmdeListModel.js:35-36; TaminListModel.js:19-20
Financial document type 1: آب شده, 2: حواله, 3: چک, 4: پولی views/finical/addFinDoc.vue:19-31
Document confirmation 0: تایید نشده, 1: تایید شده views/finical/list_model.js:20-21
Product display type 1: سایت, 2: اپلیکشن موبایل, 3: سایت و اپلیکشن موبایل (default 3) views/apps/product/AddProduct.vue:23-33
Delivery type 1: کوتاه مدت, 2: بلند مدت (default 1) views/apps/product/AddProduct.vue:132-141
SMS audience -1: یک شماره تلفن, 0: همه کاربران, 1: کارشناسان فروش, 2: مشتریان عمده, 9: چند شماره تلفن views/sms/create.vue:15-29
Notification audience 1: کارشناسان فروش, 2: مشتریان عمده, 3: یک مشتری, 4: همه مشتریان, 5: یک مدیر, 6: همه مدیران views/notify/create.vue:83-90
Statics mode title (عنوان مسیر), customer/all (تمام مشتریان), customer/id (یک مشتری) views/statics/index.vue:7-16
Default transfer target 'حواله کوثر' + server havale_list views/finical/addFinDoc.vue:121-127
Const-manager keys {id:'brand', title:'برند ها', icon:'icon-user', iconPack:'feather'} (ut/status entries commented out) store/manage/const.js:6-25
Theme colors primary:#1c2d56, secondary:#836447, third:#f5cb55, success:#28C76F, danger:#EA5455, warning:#FF9F43, dark:#1E1E1E themeConfig.js:5-14

9. Components

9.1 Table system — src/components/x-table/

The workhorse. Four near-duplicate copies exist: x-table/ (canonical), x-table_select/, custom-xtable-select/, backup-table/. Only x-table is imported by business views.

model/XTbl.js — fluent table builder:

Member Purpose Line
constructor(url, title) sets the POST endpoint and the report title XTbl.js:10-13
add(col) appends an Xtc XTbl.js:15-20
addDefaultFilter(filter) pre-applied filter XTbl.js:22-28
addOpt(...) appends an «عملیات» column with noSort() XTbl.js:31-38
hidePagination() / hideSearch() / addExtraBtn() all set _hidePageination = true (the latter two are copy-paste bugs) XTbl.js:41-59
getSortFields() cols where __sorter is truthy XTbl.js:47-49
noSearch() / noSettings() / noFilters() set _noSearch / _noSettings / _noFilters XTbl.js:61-74

model/Xtc.js — column builder. Defaults: dataIndex = key, show = true, __sorter = true (Xtc.js:4-12).

Method Effect Line
filterKey(key) overrides the server-side filter field (__fkey/master) Xtc.js:33-37
renderSlot(name) sets scopedSlots.customRender Xtc.js:39-48
filterText() filterType = 'default' Xtc.js:59-63
filterSwitch() filterType = 'switch' Xtc.js:65-70
filterQuery(action) filterType = 'query' + filterAction Xtc.js:73-78
filterDate() filterType = 'date' Xtc.js:80-84
filterSelect(items) filterType = 'select' + filterItems Xtc.js:86-91
filterNumber() filterType = 'number' Xtc.js:93-97
noSort() __sorter = false Xtc.js:99-102
hidden() show = false (still toggleable in the column selector) Xtc.js:104-107
setDefaultValue(v) / setDefaultFilter(v) delegate to sedmedghAddon/XtcModel mixins — setDefaultFilter names a Vue filter applied via dynamicFilter Xtc.js:109-115

XTable.vue — the rendering component (ant a-table based):

Aspect Detail Line
Query shape {search, filters: [], limit: 10, page: 1, order} XTable.vue:316-320
Default page size 10; selectable ['5','10','20'] XTable.vue:255-256, 319
Sort encoding +field (asc) / -field (desc) from the sort + sortDirection controls XTable.vue:340-343
Header-click sort `this.query.order = ['{- +}{columnKey}']— **inverted vs. the dropdown**:ascendmaps to-`
Request body {...query, select: visibleCols.map(c=>c.key), titles: {key: title}, report_title: model.title} (+ op when exporting) XTable.vue:466-491
Filter pruning drops filters with no value unless op ∈ {'null','nn'} or value == 0 XTable.vue:469
Page reset if the filter+search hash changed since the last request → query.page = 1 XTable.vue:472-481
Fetch await axios.post(this.model.url, this.requestData(op)); on op ∈ {'excel','json','print'} → window.open(data.url) and return XTable.vue:494-512
Export buttons json (line 96), excel (107), print (118) XTable.vue:96-118
Search a-input-search → sets query.search, refetches XTable.vue:10-15, 519-523
Filter UI dynamic rows via XFilterRow; add row pushes {id: rand} (XTable.vue:410-412); clear all disabled when empty (171) XTable.vue:131-175
Column selector visibleCols = cols.filter(c => c.show) XTable.vue:377-381
Fullscreen openFullscreen/closeFullscreen from x-table/fullscreen.js XTable.vue:456-465
Lifecycle mounted() → fetch() XTable.vue:384

Filter widgets (x-table/components/): TextXTableFilter.vue, NumberXTableFilter.vue, DateXTableFilter.vue (Jalali), SelectOptionXTableFilter.vue, SwitchXTableFilter.vue, QuerySelectTableFilter.vue, XFilterRow.vue.

9.2 Form inputs — src/components/input/

mixins.js — shared by all input components:

Prop Purpose
field the v-decorator key
items, form, formClass, label, help, show_help presentation
initialValue merged into _options.initialValue (mixins.js:43-45)
required when truthy, auto-generates rules: [{required: true, message: \وارد کردن ${label} الزامی است`}]` (mixins.js:46-53)
options raw ant decorator options, merged first (mixins.js:39-42)

Computed status proxies $refs.fi.getValidateStatus() (mixins.js:29-34).

DateInput.vue (name: 'JalaliInput') — Jalali date picker:

Aspect Detail Line
Widget vue-persian-datetime-picker, color="#1c2d56", clearable, auto-submit DateInput.vue:9-15
Bound value hidden <input v-decorator="[field, _options]"> — the picker writes into the ant form imperatively DateInput.vue:7
Default format jYYYY/jMM/jDD when no format prop DateInput.vue:49
Props format, displayFormat DateInput.vue:29-32
Clear null → sets the field to null via $refs.fi.FormContext.form.setFieldsValue DateInput.vue:44-47
Sync updated() re-reads the field value back into the picker DateInput.vue:57-59

Uploaders:

Component Upload target Notes
input/UploadInput.vue baseURL + 'file/create' (UploadInput.vue:72) multi-file; a second definition in the same file uses themeConfig.home('cu/file/create') (line 215) — dead branch
input/SingleUploadInput.vue `${baseURL}file/create` (SingleUploadInput.vue:52) single file + preview modal
input/SingleUploadInputPropList.vue same pattern prop-driven list variant
input/PodcastUploadInput.vue same pattern audio
x-upload/XUpload.vue props.url; axios.post(url, formData, {'Content-Type':'multipart/form-data'}) XUpload.vue:41-42, 69
components/MyUpload.vue, views/components/MyUpload.vue image cropper wrapper
excel/ImportExcel.vue client-side xlsx import

query-selector/QuerySelector.vue — debounced remote-search select:

Aspect Detail Line
Props vDecorator, url QuerySelector.vue:42-45
Debounce 300 ms setTimeout (cancelled on each keystroke) QuerySelector.vue:27-38
Request axios.get(url, {params: {text_search: value}}) QuerySelector.vue:34
Option shape <a-select-option :key="d.id">{{ d.title }}</a-select-option> QuerySelector.vue:15-19
Config show-search, :filter-option="false" (server-side filtering), :not-found-content="null", :show-arrow="false", placeholder جستجو QuerySelector.vue:2-14

9.3 Other components

Component Purpose
tooltip-btn/TooltipBtn.vue Icon button + tooltip + optional pop-title confirm — the standard row-action control
ZoomableImage.vue Click-to-zoom thumbnail (used in order/product detail modals)
vx-card/VxCard.vue Page card wrapper — globally registered (globalComponents.js:3, 10)
vx-list/VxList.vue, vx-input-group/VxInputGroup.vue, FeatherIcon.vue globally registered (globalComponents.js:11-14)
vx-auto-suggest/VxAutoSuggest.vue Autocomplete (template)
vx-table/VxTable.vue Legacy table (template)
goldPrice.vue Live gold-price widget
Moshtarian.vue Customer picker widget
statistics-cards/ + chartConfigs.js Dashboard stat cards
timeline/VxTimeline.vue Timeline (template)
icon/index.vue + icons.json Icon browser
ChangeTimeDurationDropdown.vue Dashboard date-range picker
VxTour.vue Product tour (disabled — themeConfig.disableThemeTour = true, themeConfig.js:20)
vue-select registered globally with custom Deselect/OpenIndicator (globalComponents.js:18-40)

10. Env / Config

auth_config.json

{ "domain": "YOUR_DOMAIN", "clientId": "YOUR_CLIENT_ID" }

Unfilled Auth0 placeholders. src/plugins/auth.js and src/auth/authService.js reference it, but AuthPlugin is commented out at src/main.js:36-38. Dead config.

themeConfig.js

Key Value Line
colors.primary #1c2d56 themeConfig.js:6
colors.secondary #836447 themeConfig.js:7
colors.third #f5cb55 themeConfig.js:8
colors.success / danger / warning / dark #28C76F / #EA5455 / #FF9F43 / #1E1E1E themeConfig.js:10-13
disableCustomizer false themeConfig.js:19
disableThemeTour true themeConfig.js:20
footerType 'hidden' themeConfig.js:21
hideScrollToTop false themeConfig.js:22
mainLayoutType isBranch() ? 'horizontal' : 'vertical' themeConfig.js:23
navbarColor '#fff' themeConfig.js:24
navbarType 'floating' themeConfig.js:25
routerTransition 'zoom-fade' themeConfig.js:26
rtl true themeConfig.js:27
sidebarCollapsed false themeConfig.js:28
theme 'light' themeConfig.js:29
userInfoLocalStorageKey 'userInfo' themeConfig.js:31

Side effect: Vue.use(Vuesax, {theme:{colors}, rtl: themeConfig.rtl}) at themeConfig.js:34.

Environment variables

File Content
.env.branch NODE_ENV="branch" (the only env file in the repo)

process.env reads across the codebase:

Reference Location
process.env.NODE_ENV == 'branch' src/utils/index.js:3 (the isBranch() switch)
process.env.BASE_URL src/router.js:16 (router base)
process.env.NODE_ENV src/store/store.js:59 (strict mode)
process.env.NODE_ENV == 'branch' vue.config.js:3-4 (publicPath / outputDir)

No VUE_APP_* variables exist. The API base URL is hard-coded at src/axios.js:5, and several table models and views re-hard-code the absolute https://henzagold.com/oapi/admin/... prefix rather than relying on baseURL.

Other config files

File Notes
babel.config.js preset @vue/app
postcss.config.js tailwind + autoprefixer + postcss-rtl
tailwind.config.js (28 600 B) / tailwind-v0.js (26 430 B) Tailwind theme; the -v0 file is an unused backup
.browserslistrc, .editorconfig, .eslintrc.js, .eslintignore tooling
src/firebase/firebaseConfig.js imported only from a commented line (main.js:32-33) — dead
src/i18n/i18n.js, i18nData.js vue-i18n set up (main.js:64-65); menu labels use a literal i18n field of Persian text rather than translation keys
src/fake-db/* axios-mock-adapter fixtures; disabled (main.js:25-26)

Appendix A — Complete API endpoint index (as called from views / tables / components)

Relative paths resolve against https://henzagold.com/oapi/admin/ (src/axios.js:5).

Auth / user / roles

Method Endpoint Caller
POST admin-login store/auth/moduleAuth.js:16
GET users/show src/router.js:170
POST /users views/user/UserCreate.vue:108
POST /users/list views/notify/create.vue:128; src/table/userTbl.js:2
PUT /users/{id} views/user/UserCreate.vue:104; views/user/ListUser.vue:162
DELETE users/{id} views/user/ListUser.vue:224
GET /user/list (listed in grep index)
GET /roles/{id} views/user/Permission.vue:136; VerticalNavMenu.vue:191
POST roles/create views/user/Permission.vue:80, 93
DELETE /roles/{ut}/{key} views/user/Permission.vue:86

Products / variants / categories / brands

Method Endpoint Caller
POST .../products table/product.js:20; views/order/product.js:3; views/invoice/AddInvoice.js:3; table/promotion_product.js:20
POST product/create views/apps/product/AddProduct.vue:660
PUT product/update/{id} AddProduct.vue:698; order/create.vue:341
GET product/show/{id} AddProduct.vue:718; order/create.vue:360
POST delete/product/{id} ProductList.vue:670; store/product/index.js:58
POST get/variants ProductList.vue:631
GET get/variant (grep index)
GET product/{id}/variant ProductList.vue:665
POST add/variant order/create.vue:304; store/variant/index.js:51,54
PUT product/variant/{id} store/product/index.js:115; store/promotion/index.js:94
DELETE /product/variant/{id} store/variant/index.js:66
POST product/variant store/cart/cart.js:73; store/invoiceCart/invoiceCart.js:68
GET /product/color AddProduct.vue:857
GET product/warranty/{id} ProductList.vue:556
GET product/exist/{id} ProductList.vue:558
GET /product/offer/{id} ProductList.vue:570
POST /change/all ProductList.vue:582
POST /change/percent/count views/apps/product/ChangePercent.vue
POST /product/report table/variant.js:3
POST/GET category AddProduct.vue:976; CategoryTbl.js:3; store/category/*
DELETE category/{id} store/category/index.js:39
PUT category/{id} store/category/index.js:52
GET brand AddProduct.vue:986; table/brand.js:3
POST /brand/create views/manage/Const.vue
PUT /brand/ views/manage/Const.vue
DELETE /brand/ views/manage/Const.vue
GET .../ciny AddProduct.vue:991
POST/PUT/DELETE /ciny, /ciny/ views/manage/Const.vue

Orders

Method Endpoint Caller
POST .../single-order views/order/orderListModel.js:4
POST .../major/order/table views/order/OmdeListModel.js:7
POST .../order-tamin views/order/TaminListModel.js:3
POST .../get-custom-orders views/order/makeOrderModel.js:4
GET .../major/order views/customer/omde/omdeOrder.js:4
GET .../single/order views/customer/single-customer/singleOrder.js:4
PUT/POST order/, order/{id} store/order/index.js:54,57
GET order/ store/order/index.js:69
DELETE order/{id} store/order/index.js:42
GET /order/type views/order/create.vue:395
POST single/order-sts/edit views/order/List.vue:260, 271
POST order-sts/edit views/order/TaminList.vue
POST major/order-sts/edit views/order/OmdeList.vue
POST order-item/edit views/order/OmdeList.vue
DELETE major/order_item/ views/order/OmdeList.vue
PUT custom-order/{id} views/order/MakeOrder.vue
DELETE custom-order/{id} views/order/MakeOrder.vue
POST delete-order views/order/*
(window.open) .../order/pdf/{id} views/order/List.vue:296

Customers

Method Endpoint Caller
POST .../customer views/customer/omde/OmdeListModel.js:7
POST .../major/verify/table OmdeListNonVerifiedModel.js:7
POST .../major/archive/table OmdeArchiveListModel.js:7
POST .../banker BankerListModel.js:7
POST .../shopkeeper shopkeeperListModel.js:7
POST .../reagent ReagentListModel.js:7
POST .../single-customer SingleCustomerList.js:3; views/order/create.vue:397
POST .../major/table table/major_customer.js:3
GET .../major/customer omdeCustomer.js:4
POST customer/create store/customer/index.js:71
GET customer/{id} bulkCustomer.vue:330; ReagentCustomer.vue:274
POST customer/toggle-active omde list views
POST customer/toggle-sts omde list views
POST major/verify OmdeNonVerifiedList.vue
GET major/archive/{id} OmdeArchivedList.vue
GET major/dashboard/{id} ViewOmdeCustomer.vue
POST single singleCustomer.vue:92
PUT single/{id} singleCustomer.vue:90
GET single/{id} singleCustomer.vue:119
GET single/order/{id} / single/report/{id} / single/wallet/{id} ViewSingleCustomer.vue
GET query/reagent bulkCustomer.vue:315
GET/PUT/DELETE/POST user/profile[/{id}] store/customer/index.js:44,56,59,82,94
GET user/profile/address/1 (grep index)

Finance / documents / wallet / invoices

Method Endpoint Caller
POST .../cash/table views/finical/list_model.js:3
GET .../major/cash omdeTransaction.js:3
GET .../single/transaction singleTransaction.js:3
POST /wallet/table views/wallet/walletTbl.js:3
GET /wallet/config views/manage/wallet.vue:77
GET /wallet/birthday/config views/manage/wallet.vue:91
POST /wallet/config views/manage/wallet.vue:109, 126
POST .../branch/product/table views/invoice/ListInvoice.js:4; views/branch/orderListModel.js:4
POST /branch/product views/invoice/AddInvoice.vue
GET branch/product/{id} views/invoice/EditInvoice.vue
DELETE branch/product/{id} views/invoice/ListInvoice.vue

Branches / workshops / cities

Method Endpoint Caller
POST .../branch/table views/branch/ListBranch.js:3
POST /branch views/branch/AddBranches.vue
PUT /branch/{id} views/branch/EditBranches.vue
GET /branch/{id} views/branch/EditBranches.vue
GET /branch/list (grep index)
GET /branch/active/{id} views/branch/ListBranches.vue
POST workshop/table views/workshop/ListWorkshop.js:3; views/order/workshopModel.js:3
POST .../workshop/product/table views/workshop/orderListModel.js:4
POST /workshop views/workshop/AddWorkshop.vue
PUT /workshop/{id} views/workshop/EditWorkshop.vue
GET /workshop/{id} views/workshop/EditWorkshop.vue
GET /workshop/active/{id} views/workshop/ListWorkshop.vue
POST cities/list store/users/index.js:52; bulkCustomer.vue:321; CityListModel.js:3
POST cities views/city/createCity.vue
PUT cities/{id} views/city/cityList.vue
DELETE cities/{id} views/city/cityList.vue
GET cities/get-percent/{id} views/city/cityList.vue
GET cities/get-percent-aux/{id} views/city/cityList.vue; bulkCustomer.vue:265; ReagentCustomer.vue:221

Promotions / offers

Method Endpoint Caller
POST .../major/promotion/table src/table/list_model.js:3
GET /product/variant/promotion/{id} views/promotion/*
POST/PUT/DELETE product/variant/promotion[/{id}] store/promotion/index.js:58,70,73,85
POST/PUT/DELETE product/variant/promotion/variant-promotion[/{id}] store/variantpromotion/index.js:58,71,75,88
GET /autopromotion views/promotion/autopromotion.vue
PUT /autopromotion views/promotion/autopromotion.vue
GET /ignore views/offersIgnore/offersIgnore-add-edit.vue
POST /ignore views/offersIgnore/offersIgnore-add-edit.vue
DELETE /ignore/ views/offersIgnore/offersIgnore-add-edit.vue

Comments / SMS / notifications / newsletter / reports / config

Method Endpoint Caller
POST .../comment/table views/customer/Comments/CommentListModel.js:4
POST comment Comments.vue
POST comment/sts Comments.vue
DELETE comment/{id} Comments.vue
POST /sms/table views/sms/create.vue:168
POST https://henzagold.com/oapi/api/sms/batch views/sms/create.vue:216, 231
POST https://henzagold.com/oapi/api/sms/batch/test views/sms/create.vue:195
GET .../major/sms omdeSms.js:3
GET .../single/sms singleSms.js:3
POST /notify views/notify/create.vue:112
POST /notify/table views/notify/notifyTbl.js:3
POST /notify/customer views/notify/create.vue:139
GET /notify/{id} views/notify/user.vue
GET /notify/read/{id} views/notify/user.vue
POST .../fashion/table views/newsletters/newsletter.js:3
POST .../report/order_item views/report/order_item_model.js:3
GET get-analytics views/DashboardECommerce.vue
GET get-analytics-tak views/DashboardAnalytics.vue
GET /dashboard/link views/manage/report.vue:52
POST log/{mode}, log/customer/{id} views/statics/index.vue:147
GET log/ago/{id} views/statics/index.vue:174
GET /log/list/customer views/statics/index.vue:188
GET config/statics store/{product,variant,promotion,variantpromotion,manage}/*.js
GET /const/__list__ut views/user/Permission.vue:113; UserCreate.vue:169; ListUser.vue:257
GET /const/__list__tags AddProduct.vue:989
GET /const/mobile_main_slider, /const/site views/manage/Const.vue
POST const, /const views/user/Permission.vue:77; views/manage/Const.vue
PUT /const/, /const/49, /const/54, /const/site_test views/manage/Const.vue
DELETE /const/by-id/ views/manage/Const.vue
GET price components/goldPrice.vue
PUT file/update/ upload components
POST {baseURL}file/create input/UploadInput.vue:72; input/SingleUploadInput.vue:52
GET /te/query, POST /ddf scratch/debug endpoints

Appendix B — Known defects / oddities found while reading

# Issue Evidence
1 No response interceptor and no token-refresh in the live app; the whole src/http/requests/** refresh machinery is unreachable src/axios.js (no response interceptor); src/main.js:22-23 (import commented)
2 Request-error interceptor does not return the rejection src/axios.js:29-31
3 store.state.auth.user / .token are functions, so isLogin in the guard is always truthy store/auth/moduleAuth.js:5-10 vs router.js:164
4 Header-click sorting inverts direction relative to the sort dropdown (ascend → -) XTable.vue:449 vs XTable.vue:342
5 XTbl.hideSearch() and addExtraBtn() both set _hidePageination (copy-paste) XTbl.js:51-59
6 Menu URL /customer/Shopkeeper-list does not match route /customer/shopkeeper-list (case) navMenuItems.js:90 vs admin.js:550
7 order/List.vue "ویرایش سفارش" persists nothing — the axios.put is commented out views/order/List.vue:281
8 Retail order-status enum lacks 0: معلق present in the wholesale filter create.vue:158 vs OmdeListModel.js:23
9 Banker / Shopkeeper menu entries have no permissionId, so they render for everyone navMenuItems.js:86-87, 93-94
10 Permission keys persons.create.customer.tak and persons.list.sellers.view are referenced in views but absent from permissionConst.js AddCustomer.vue:142; ReagentList.vue:32
11 /newsletters route has its role commented out → reachable by any authenticated admin admin.js:851
12 Jalali datetime filter uses 12-hour hh with no am/pm marker filters.js:109
13 Base URL is hard-coded in src/axios.js and again as absolute strings in ~30 table models axios.js:5; e.g. orderListModel.js:4
14 SMS send bypasses the admin base and posts to /oapi/api/sms/batch views/sms/create.vue:216
15 Refresh-token payload reads localStorage.getItem('accessToKen') (capital K typo) http/requests/auth/jwt/index.js:61
16 auth_config.json still holds Auth0 placeholders and is never used auth_config.json; main.js:36-38
17 No gram/weight formatter, no Persian↔English digit conversion, no price input mask anywhere absent from src/filters, src/utils, src/components/input
18 Permission deletion in the role editor fires N staggered setTimeout(…, 500) deletes — racy for large diffs views/user/Permission.vue:86