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
- Whitelist
noneAuthUrl = ['/auth/login','/auth/forgot-password','/auth/register','/reg'] → next() (router.js:156-161, 185-187).
- Read token from
localStorage[isBranch()?'branch_token':'token'] (router.js:188).
- If no token →
router.push('/auth/login') (router.js:198).
- If token and module-level
roles is unset → await getPermission() (router.js:190-191).
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).
- 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 |
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).
| 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 |
| 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
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 |
| 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 |