Compare commits
11 Commits
5ee03cf761
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 93ebc80da3 | |||
| 4e4cc08224 | |||
| e5f53c2265 | |||
| b57d6b4e4b | |||
| ea458c7b72 | |||
| 151eff2f7c | |||
| 1a0c40ecde | |||
| d1dd67aee7 | |||
| f7f8a91a85 | |||
| 2c90f8091e | |||
| d6aa165592 |
@@ -51,6 +51,54 @@
|
|||||||
"optimization": false,
|
"optimization": false,
|
||||||
"sourceMap": true
|
"sourceMap": true
|
||||||
},
|
},
|
||||||
|
"novin": {
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "public-novin"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"maximumError": "3MB",
|
||||||
|
"maximumWarning": "2MB",
|
||||||
|
"type": "initial"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maximumError": "8kB",
|
||||||
|
"maximumWarning": "4kB",
|
||||||
|
"type": "anyComponentStyle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "src/config.ts",
|
||||||
|
"with": "src/tenants/novin/config.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/assets/images/brandingAssets.ts",
|
||||||
|
"with": "src/tenants/novin/brandingAssets.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/environments/environment.ts",
|
||||||
|
"with": "src/environments/environment.novin.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/app.routes.ts",
|
||||||
|
"with": "src/tenants/novin/app.routes.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/app/branding/branding.config.ts",
|
||||||
|
"with": "src/tenants/novin/branding.config.ts"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all",
|
||||||
|
"outputPath": "dist/novin",
|
||||||
|
"styles": [
|
||||||
|
"src/assets/styles.scss",
|
||||||
|
"src/assets/psp.scss"
|
||||||
|
]
|
||||||
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"budgets": [
|
"budgets": [
|
||||||
{
|
{
|
||||||
@@ -81,6 +129,54 @@
|
|||||||
"outputHashing": "all",
|
"outputHashing": "all",
|
||||||
"outputPath": "dist/production"
|
"outputPath": "dist/production"
|
||||||
},
|
},
|
||||||
|
"sepehr": {
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "public-sepehr"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"maximumError": "3MB",
|
||||||
|
"maximumWarning": "2MB",
|
||||||
|
"type": "initial"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maximumError": "8kB",
|
||||||
|
"maximumWarning": "4kB",
|
||||||
|
"type": "anyComponentStyle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "src/config.ts",
|
||||||
|
"with": "src/tenants/sepehr/config.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/assets/images/brandingAssets.ts",
|
||||||
|
"with": "src/tenants/sepehr/brandingAssets.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/environments/environment.ts",
|
||||||
|
"with": "src/environments/environment.sepehr.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/app.routes.ts",
|
||||||
|
"with": "src/tenants/sepehr/app.routes.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/app/branding/branding.config.ts",
|
||||||
|
"with": "src/tenants/sepehr/branding.config.ts"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all",
|
||||||
|
"outputPath": "dist/sepehr",
|
||||||
|
"styles": [
|
||||||
|
"src/assets/styles.scss",
|
||||||
|
"src/assets/psp.scss"
|
||||||
|
]
|
||||||
|
},
|
||||||
"staging": {
|
"staging": {
|
||||||
"extractLicenses": true,
|
"extractLicenses": true,
|
||||||
"fileReplacements": [
|
"fileReplacements": [
|
||||||
@@ -100,10 +196,6 @@
|
|||||||
"input": "public-tis"
|
"input": "public-tis"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"styles": [
|
|
||||||
"src/assets/styles.scss",
|
|
||||||
"src/assets/psp.scss"
|
|
||||||
],
|
|
||||||
"budgets": [
|
"budgets": [
|
||||||
{
|
{
|
||||||
"maximumError": "3MB",
|
"maximumError": "3MB",
|
||||||
@@ -139,7 +231,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"outputHashing": "all",
|
"outputHashing": "all",
|
||||||
"outputPath": "dist/tis"
|
"outputPath": "dist/tis",
|
||||||
|
"styles": [
|
||||||
|
"src/assets/styles.scss",
|
||||||
|
"src/assets/psp.scss"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"tis-development": {
|
"tis-development": {
|
||||||
"assets": [
|
"assets": [
|
||||||
@@ -148,10 +244,6 @@
|
|||||||
"input": "public-tis"
|
"input": "public-tis"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"styles": [
|
|
||||||
"src/assets/styles.scss",
|
|
||||||
"src/assets/psp.scss"
|
|
||||||
],
|
|
||||||
"budgets": [
|
"budgets": [
|
||||||
{
|
{
|
||||||
"maximumError": "2.5MB",
|
"maximumError": "2.5MB",
|
||||||
@@ -190,7 +282,11 @@
|
|||||||
"optimization": false,
|
"optimization": false,
|
||||||
"outputHashing": "all",
|
"outputHashing": "all",
|
||||||
"outputPath": "dist/tis",
|
"outputPath": "dist/tis",
|
||||||
"sourceMap": true
|
"sourceMap": true,
|
||||||
|
"styles": [
|
||||||
|
"src/assets/styles.scss",
|
||||||
|
"src/assets/psp.scss"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "production",
|
"defaultConfiguration": "production",
|
||||||
@@ -230,9 +326,15 @@
|
|||||||
"development": {
|
"development": {
|
||||||
"buildTarget": "pos.client:build:development"
|
"buildTarget": "pos.client:build:development"
|
||||||
},
|
},
|
||||||
|
"novin": {
|
||||||
|
"buildTarget": "pos.client:build:novin"
|
||||||
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"buildTarget": "pos.client:build:production"
|
"buildTarget": "pos.client:build:production"
|
||||||
},
|
},
|
||||||
|
"sepehr": {
|
||||||
|
"buildTarget": "pos.client:build:sepehr"
|
||||||
|
},
|
||||||
"staging": {
|
"staging": {
|
||||||
"buildTarget": "pos.client:build:staging"
|
"buildTarget": "pos.client:build:staging"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,6 +13,29 @@ services:
|
|||||||
- "8091:8090"
|
- "8091:8090"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
|
app_novin:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
TENANT: novin
|
||||||
|
DIST_DIR: novin
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "8093:8090"
|
||||||
|
restart: unless-stopped
|
||||||
|
# app_sepehr:
|
||||||
|
# build:
|
||||||
|
# context: .
|
||||||
|
# dockerfile: Dockerfile
|
||||||
|
# args:
|
||||||
|
# TENANT: sepehr
|
||||||
|
# DIST_DIR: sepehr
|
||||||
|
|
||||||
|
# ports:
|
||||||
|
# - "8092:8090"
|
||||||
|
# restart: unless-stopped
|
||||||
|
|
||||||
app_default:
|
app_default:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
|
|||||||
@@ -56,10 +56,14 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
|
"build:novin": "ng build --configuration novin",
|
||||||
|
"build:sepehr": "ng build --configuration sepehr",
|
||||||
"build:tis": "ng build --configuration tis",
|
"build:tis": "ng build --configuration tis",
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"prestart": "node aspnetcore-https",
|
"prestart": "node aspnetcore-https",
|
||||||
"start": "run-script-os",
|
"start": "run-script-os",
|
||||||
|
"start:novin": " ng serve --configuration novin",
|
||||||
|
"start:sepehr": " ng serve --configuration sepehr",
|
||||||
"start:tis": " ng serve --configuration tis",
|
"start:tis": " ng serve --configuration tis",
|
||||||
"test": "ng test",
|
"test": "ng test",
|
||||||
"watch": "ng build --watch --configuration development"
|
"watch": "ng build --watch --configuration development"
|
||||||
|
|||||||
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 94 KiB |
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"purpose": "any",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"src": "/favicon/web-app-manifest-192x192.png",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purpose": "maskable",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"src": "/favicon/web-app-manifest-192x192.png",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purpose": "any",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"src": "/favicon/web-app-manifest-512x512.png",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purpose": "maskable",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"src": "/favicon/web-app-manifest-512x512.png",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "/",
|
||||||
|
"name": "پرداخت نوین - مدیریت صورتحسابهای مالیاتی",
|
||||||
|
"scope": "/",
|
||||||
|
"short_name": "پرداخت نوین",
|
||||||
|
"start_url": "/",
|
||||||
|
"theme_color": "#ffffff"
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 187 KiB |
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "پرداخت الکترونیک سپهر",
|
||||||
|
"short_name": "پرداخت الکترونیک سپهر",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/web-app-manifest-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/web-app-manifest-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"purpose": "any",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"src": "/favicon/web-app-manifest-192x192.png",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purpose": "maskable",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"src": "/favicon/web-app-manifest-192x192.png",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purpose": "any",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"src": "/favicon/web-app-manifest-512x512.png",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purpose": "maskable",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"src": "/favicon/web-app-manifest-512x512.png",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "/",
|
||||||
|
"name": "پرداخت الکترونیک سپهر",
|
||||||
|
"scope": "/",
|
||||||
|
"short_name": "سپهر",
|
||||||
|
"start_url": "/",
|
||||||
|
"theme_color": "#ffffff"
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 4.5 KiB |
@@ -28,9 +28,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"id": "/",
|
"id": "/",
|
||||||
"name": "نرم افزار صورتحسابهای مالیاتی پاژن",
|
"name": "نرم افزار صورتحسابهای مالیاتی سپاس",
|
||||||
"scope": "/",
|
"scope": "/",
|
||||||
"short_name": "پاژن",
|
"short_name": "سپاس",
|
||||||
"start_url": "/",
|
"start_url": "/",
|
||||||
"theme_color": "#ffffff"
|
"theme_color": "#ffffff"
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 19 KiB |
@@ -73,14 +73,14 @@ export class NativeBridgeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pay(request: INativePayRequest): any {
|
pay(request: INativePayRequest): any {
|
||||||
if (request.amount <= 10_000) {
|
// if (request.amount <= 1_000) {
|
||||||
const errorMessage = 'برای مقادیر زیر ۱۰۰ هزار ریال، پرداخت ممکن نیست.';
|
// const errorMessage = 'برای مقادیر زیر ۱۰ هزار ریال، پرداخت ممکن نیست.';
|
||||||
this.toastService.warn({ text: errorMessage, life: 3000 });
|
// this.toastService.warn({ text: errorMessage, life: 3000 });
|
||||||
return {
|
// return {
|
||||||
success: false,
|
// success: false,
|
||||||
error: errorMessage,
|
// error: errorMessage,
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
this.toastService.info({ text: 'در حال پردازش پرداخت...' });
|
this.toastService.info({ text: 'در حال پردازش پرداخت...' });
|
||||||
try {
|
try {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { inject, Injectable } from '@angular/core';
|
import { inject, Injectable } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import config from 'src/config';
|
||||||
import { AuthService } from '../../services/auth.service';
|
import { AuthService } from '../../services/auth.service';
|
||||||
import { BaseState, BaseStore } from '../base-store';
|
import { BaseState, BaseStore } from '../base-store';
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@ export class GlobalStore extends BaseStore<GlobalState> {
|
|||||||
readonly isOnline = this.computed((state) => state.isOnline);
|
readonly isOnline = this.computed((state) => state.isOnline);
|
||||||
readonly notifications = this.computed((state) => state.notifications);
|
readonly notifications = this.computed((state) => state.notifications);
|
||||||
readonly unreadNotifications = this.computed((state) =>
|
readonly unreadNotifications = this.computed((state) =>
|
||||||
state.notifications.filter((n) => !n.read),
|
state.notifications.filter((n) => !n.read)
|
||||||
);
|
);
|
||||||
readonly breadcrumbs = this.computed((state) => state.breadcrumbs);
|
readonly breadcrumbs = this.computed((state) => state.breadcrumbs);
|
||||||
readonly preferences = this.computed((state) => state.preferences);
|
readonly preferences = this.computed((state) => state.preferences);
|
||||||
@@ -144,7 +145,11 @@ export class GlobalStore extends BaseStore<GlobalState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load theme from localStorage
|
// Load theme from localStorage
|
||||||
const savedTheme = localStorage.getItem('app_theme') as 'light' | 'dark';
|
const savedTheme = config.isPosApplication
|
||||||
|
? 'light'
|
||||||
|
: (localStorage.getItem('app_theme') as 'light' | 'dark');
|
||||||
|
console.log('savedTheme', savedTheme);
|
||||||
|
|
||||||
if (savedTheme) {
|
if (savedTheme) {
|
||||||
this.patchState({ theme: savedTheme });
|
this.patchState({ theme: savedTheme });
|
||||||
}
|
}
|
||||||
@@ -250,7 +255,7 @@ export class GlobalStore extends BaseStore<GlobalState> {
|
|||||||
*/
|
*/
|
||||||
markNotificationRead(id: string): void {
|
markNotificationRead(id: string): void {
|
||||||
const notifications = this._state().notifications.map((n) =>
|
const notifications = this._state().notifications.map((n) =>
|
||||||
n.id === id ? { ...n, read: true } : n,
|
n.id === id ? { ...n, read: true } : n
|
||||||
);
|
);
|
||||||
this.patchState({ notifications });
|
this.patchState({ notifications });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const columns: IColumn[] = [
|
|||||||
{ field: 'device', header: 'دستگاه', type: 'nested', nestedOption: { path: 'device.name' } },
|
{ field: 'device', header: 'دستگاه', type: 'nested', nestedOption: { path: 'device.name' } },
|
||||||
{
|
{
|
||||||
field: 'provider',
|
field: 'provider',
|
||||||
header: 'ارایهدهنده',
|
header: 'PSP',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedOption: { path: 'provider.name' },
|
nestedOption: { path: 'provider.name' },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ export const CONSUMER_MENU_ITEMS = [
|
|||||||
routerLink: ['/consumer/poses'],
|
routerLink: ['/consumer/poses'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'صورتحسابها',
|
label: 'صورتحساب',
|
||||||
icon: 'pi pi-fw pi-receipt',
|
icon: 'pi pi-fw pi-receipt',
|
||||||
routerLink: ['/consumer/sale_invoices'],
|
routerLink: ['/consumer/sale_invoices'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'مشتریها',
|
label: 'مشتری',
|
||||||
icon: 'pi pi-fw pi-users',
|
icon: 'pi pi-fw pi-users',
|
||||||
routerLink: ['/consumer/customers'],
|
routerLink: ['/consumer/customers'],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<app-key-value label="شماره سریال" [value]="pos()?.serial_number" />
|
<app-key-value label="شماره سریال" [value]="pos()?.serial_number" />
|
||||||
<app-key-value label="نوع دستگاه" [value]="pos()?.device?.name" />
|
<app-key-value label="نوع دستگاه" [value]="pos()?.device?.name" />
|
||||||
<app-key-value label="مدل دستگاه" [value]="pos()?.model" />
|
<app-key-value label="مدل دستگاه" [value]="pos()?.model" />
|
||||||
<app-key-value label="ارایهدهنده" [value]="pos()?.provider?.name" />
|
<app-key-value label="PSP" [value]="pos()?.provider?.name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</app-card-data>
|
</app-card-data>
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ export class ConsumerCustomerSaleInvoiceComponent {
|
|||||||
constructor() {
|
constructor() {
|
||||||
effect(() => {
|
effect(() => {
|
||||||
if (this.invoice()?.id) {
|
if (this.invoice()?.id) {
|
||||||
console.log('inja');
|
|
||||||
|
|
||||||
this.setBreadcrumb();
|
this.setBreadcrumb();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,7 +28,17 @@ export class ConsumerStatisticsLatestInvoicesComponent extends AbstractList<ISta
|
|||||||
readonly invoicesPageRoute = consumerSaleInvoicesNamedRoutes.saleInvoices.meta.pagePath!();
|
readonly invoicesPageRoute = consumerSaleInvoicesNamedRoutes.saleInvoices.meta.pagePath!();
|
||||||
|
|
||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
this.columns = saleInvoiceListConfig.columns.filter((column) => column.field !== 'created_at');
|
this.columns = saleInvoiceListConfig.columns
|
||||||
|
.filter((column) => column.field !== 'created_at')
|
||||||
|
.map((header) => {
|
||||||
|
if (header.field === 'status') {
|
||||||
|
return {
|
||||||
|
...header,
|
||||||
|
customDataModel: this.status,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return header;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDataRequest() {
|
override getDataRequest() {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<app-key-value label="شماره سریال" [value]="pos()?.serial_number" />
|
<app-key-value label="شماره سریال" [value]="pos()?.serial_number" />
|
||||||
<app-key-value label="نوع دستگاه" [value]="pos()?.device?.name" />
|
<app-key-value label="نوع دستگاه" [value]="pos()?.device?.name" />
|
||||||
<app-key-value label="مدل دستگاه" [value]="pos()?.model" />
|
<app-key-value label="مدل دستگاه" [value]="pos()?.model" />
|
||||||
<app-key-value label="ارایهدهنده" [value]="pos()?.provider?.name" />
|
<app-key-value label="PSP" [value]="pos()?.provider?.name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</app-card-data>
|
</app-card-data>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export class ConsumerSaleInvoiceStore extends EntityStore<
|
|||||||
routerLink: consumerSaleInvoicesNamedRoutes.saleInvoices.meta.pagePath!(),
|
routerLink: consumerSaleInvoicesNamedRoutes.saleInvoices.meta.pagePath!(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.entity()?.code,
|
title: `صورتحساب ${this.entity()?.invoice_number}`,
|
||||||
routerLink: consumerSaleInvoicesNamedRoutes.saleInvoice.meta.pagePath!(invoiceId),
|
routerLink: consumerSaleInvoicesNamedRoutes.saleInvoice.meta.pagePath!(invoiceId),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -53,7 +53,7 @@ export class ConsumerSaleInvoiceStore extends EntityStore<
|
|||||||
catchError((error) => {
|
catchError((error) => {
|
||||||
this.setError(error);
|
this.setError(error);
|
||||||
throw error;
|
throw error;
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
.subscribe((entity) => {
|
.subscribe((entity) => {
|
||||||
this.patchState({ entity });
|
this.patchState({ entity });
|
||||||
|
|||||||
@@ -8,20 +8,21 @@ export const PARTNER_MENU_ITEMS = [
|
|||||||
routerLink: ['/partner'],
|
routerLink: ['/partner'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'حسابهای کاربری',
|
label: 'مودی',
|
||||||
icon: 'pi pi-fw pi-user',
|
|
||||||
routerLink: ['/partner/accounts'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'مشتریها',
|
|
||||||
icon: 'pi pi-fw pi-users',
|
icon: 'pi pi-fw pi-users',
|
||||||
routerLink: ['/partner/consumers'],
|
routerLink: ['/partner/consumers'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'لایسنسها',
|
label: 'لایسنس',
|
||||||
icon: 'pi pi-fw pi-key',
|
icon: 'pi pi-fw pi-key',
|
||||||
routerLink: ['/partner/licenses'],
|
routerLink: ['/partner/licenses'],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
label: 'حسابهای کاربری',
|
||||||
|
icon: 'pi pi-fw pi-user',
|
||||||
|
routerLink: ['/partner/accounts'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
] as MenuItem[];
|
] as MenuItem[];
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
<shared-dialog
|
<shared-dialog
|
||||||
header="افزودن مشتری"
|
header="افزودن مودی"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
[style]="{ width: '640px' }"
|
[style]="{ width: '640px' }"
|
||||||
[closable]="true"
|
[closable]="true"
|
||||||
(onHide)="close()"
|
(onHide)="close()">
|
||||||
>
|
|
||||||
<p-stepper [value]="activeStep()" [linear]="true">
|
<p-stepper [value]="activeStep()" [linear]="true">
|
||||||
<p-step-list>
|
<p-step-list>
|
||||||
<p-step [value]="1">اطلاعات اولیه</p-step>
|
<p-step [value]="1">اطلاعات اولیه</p-step>
|
||||||
@@ -24,16 +23,14 @@
|
|||||||
<partner-consumer-businessActivities-form-content
|
<partner-consumer-businessActivities-form-content
|
||||||
[consumerId]="consumer()?.id || ''"
|
[consumerId]="consumer()?.id || ''"
|
||||||
(onSubmit)="onBusinessActivitySubmit($event)"
|
(onSubmit)="onBusinessActivitySubmit($event)"
|
||||||
(onClose)="close()"
|
(onClose)="close()" />
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
@case (3) {
|
@case (3) {
|
||||||
<partner-consumer-complex-form-content
|
<partner-consumer-complex-form-content
|
||||||
[consumerId]="consumer()?.id || ''"
|
[consumerId]="consumer()?.id || ''"
|
||||||
[businessActivityId]="businessActivity()?.id || ''"
|
[businessActivityId]="businessActivity()?.id || ''"
|
||||||
(onSubmit)="onComplexSubmit($event)"
|
(onSubmit)="onComplexSubmit($event)"
|
||||||
(onClose)="close()"
|
(onClose)="close()" />
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
@case (4) {
|
@case (4) {
|
||||||
<partner-consumer-pos-form-content
|
<partner-consumer-pos-form-content
|
||||||
@@ -41,8 +38,7 @@
|
|||||||
[businessActivityId]="businessActivity()?.id || ''"
|
[businessActivityId]="businessActivity()?.id || ''"
|
||||||
[complexId]="complex()?.id || ''"
|
[complexId]="complex()?.id || ''"
|
||||||
(onSubmit)="onPosSubmit($event)"
|
(onSubmit)="onPosSubmit($event)"
|
||||||
(onClose)="close()"
|
(onClose)="close()" />
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class ConsumerUserFormDialogComponent extends AbstractDialog {
|
|||||||
@Input() consumerId?: string;
|
@Input() consumerId?: string;
|
||||||
|
|
||||||
get preparedTitle() {
|
get preparedTitle() {
|
||||||
return `${this.editMode ? 'ویرایش' : 'افزودن'} مشتری`;
|
return `${this.editMode ? 'ویرایش' : 'افزودن'} مودی`;
|
||||||
}
|
}
|
||||||
|
|
||||||
onFormSubmit(response: IPartnerConsumerResponse) {
|
onFormSubmit(response: IPartnerConsumerResponse) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const partnerConsumersNamedRoutes: NamedRoutes<TConsumersRouteNames> = {
|
|||||||
path: 'consumers',
|
path: 'consumers',
|
||||||
loadComponent: () => import('../../views/list.component').then((m) => m.ConsumersComponent),
|
loadComponent: () => import('../../views/list.component').then((m) => m.ConsumersComponent),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'مشتریها',
|
title: 'مودیان',
|
||||||
pagePath: () => '/partner/consumers',
|
pagePath: () => '/partner/consumers',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -18,7 +18,7 @@ export const partnerConsumersNamedRoutes: NamedRoutes<TConsumersRouteNames> = {
|
|||||||
path: 'consumers/:consumerId',
|
path: 'consumers/:consumerId',
|
||||||
loadComponent: () => import('../../views/single.component').then((m) => m.ConsumerComponent),
|
loadComponent: () => import('../../views/single.component').then((m) => m.ConsumerComponent),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'مشتری',
|
title: 'مودی',
|
||||||
pagePath: (guildId: string) => `/partner/consumers/${guildId}`,
|
pagePath: (guildId: string) => `/partner/consumers/${guildId}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<app-page-data-list
|
<app-page-data-list
|
||||||
pageTitle="مشتریها"
|
pageTitle="مودیان"
|
||||||
[addNewCtaLabel]="'افزودن مشتری'"
|
[addNewCtaLabel]="'افزودن مودی'"
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[showAdd]="true"
|
[showAdd]="true"
|
||||||
emptyPlaceholderTitle="مشتری یافت نشد"
|
emptyPlaceholderTitle="مودی یافت نشد"
|
||||||
emptyPlaceholderDescription="برای افزودن مشتری، روی دکمهٔ بالا کلیک کنید."
|
emptyPlaceholderDescription="برای افزودن مودی، روی دکمهٔ بالا کلیک کنید."
|
||||||
[items]="items()"
|
[items]="items()"
|
||||||
[loading]="loading()"
|
[loading]="loading()"
|
||||||
[showDetails]="true"
|
[showDetails]="true"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<app-card-data cardTitle="اطلاعات مشتری" [editable]="true" [(editMode)]="editMode">
|
<app-card-data cardTitle="اطلاعات مودی" [editable]="true" [(editMode)]="editMode">
|
||||||
<ng-template #moreActions> </ng-template>
|
<ng-template #moreActions> </ng-template>
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="listKeyValue">
|
<div class="listKeyValue">
|
||||||
<app-key-value label="نام مشتری" [value]="consumer()?.name" />
|
<app-key-value label="نام" [value]="consumer()?.name" />
|
||||||
<app-key-value label="نوع مشتری" [value]="consumer()?.type?.translate" />
|
<app-key-value label="نوع" [value]="consumer()?.type?.translate" />
|
||||||
@if (consumer()?.type?.value === 'LEGAL') {
|
@if (consumer()?.type?.value === 'LEGAL') {
|
||||||
<app-key-value label="شناسه ملی" [value]="consumer()?.legal?.registration_code" />
|
<app-key-value label="شناسه ملی" [value]="consumer()?.legal?.registration_code" />
|
||||||
} @else {
|
} @else {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="flex flex-col gap-4 w-full">
|
<div class="flex w-full flex-col gap-4">
|
||||||
<uikit-field label="بر اساس نام مشتری" name="search" class="w-full">
|
<uikit-field label="بر اساس نام مودی" name="search" class="w-full">
|
||||||
<p-inputgroup class="w-full">
|
<p-inputgroup class="w-full">
|
||||||
<input pInputText [(ngModel)]="search" placeholder="جستجوی نام مشتری" (ngModelChange)="onFilterChange($event)" />
|
<input pInputText [(ngModel)]="search" placeholder="جستجوی نام مودی" (ngModelChange)="onFilterChange($event)" />
|
||||||
<p-inputgroup-addon>
|
<p-inputgroup-addon>
|
||||||
<p-button icon="pi pi-times" severity="secondary" (onClick)="clearSearch()"></p-button>
|
<p-button icon="pi pi-times" severity="secondary" (onClick)="clearSearch()"></p-button>
|
||||||
</p-inputgroup-addon>
|
</p-inputgroup-addon>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export class PartnerLicenseListComponent extends AbstractList<ILicenseResponse>
|
|||||||
// { field: 'id', header: 'شناسه', type: 'id' },
|
// { field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{
|
{
|
||||||
field: 'business_activity',
|
field: 'business_activity',
|
||||||
header: 'عنوان مشتری',
|
header: 'مودی',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedOption: {
|
nestedOption: {
|
||||||
path: 'business_activity.consumer.name',
|
path: 'business_activity.consumer.name',
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<app-card-data cardTitle="تغییر رمز عبور" [editable]="false">
|
|
||||||
<form [formGroup]="form" (submit)="submit()" class="mx-auto max-w-lg">
|
|
||||||
<shared-password-input
|
|
||||||
[passwordControl]="form.controls.password"
|
|
||||||
[confirmPasswordControl]="form.controls.confirmPassword" />
|
|
||||||
<button type="submit" pButton [disabled]="form.invalid || loading()" class="mx-auto w-full max-w-xs">
|
|
||||||
تغییر رمز عبور
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</app-card-data>
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import { ToastService } from '@/core/services/toast.service';
|
|
||||||
import { MustMatch } from '@/core/validators';
|
|
||||||
import { AppCardComponent, SharedPasswordInputComponent } from '@/shared/components';
|
|
||||||
import { fieldControl } from '@/shared/constants';
|
|
||||||
import { Component, inject, signal } from '@angular/core';
|
|
||||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
|
||||||
import { ButtonDirective } from 'primeng/button';
|
|
||||||
import { finalize } from 'rxjs';
|
|
||||||
import { ProfileService } from '../services/main.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'partner-reset-password-card',
|
|
||||||
templateUrl: './reset-password-card.component.html',
|
|
||||||
imports: [ReactiveFormsModule, AppCardComponent, SharedPasswordInputComponent, ButtonDirective],
|
|
||||||
})
|
|
||||||
export class PartnerResetPasswordCardComponent {
|
|
||||||
private readonly service = inject(ProfileService);
|
|
||||||
private readonly fb = inject(FormBuilder);
|
|
||||||
private readonly toastService = inject(ToastService);
|
|
||||||
|
|
||||||
readonly loading = signal(false);
|
|
||||||
|
|
||||||
form = this.fb.group(
|
|
||||||
{
|
|
||||||
password: fieldControl.password(),
|
|
||||||
confirmPassword: fieldControl.confirmPassword(),
|
|
||||||
},
|
|
||||||
{ validators: [MustMatch('password', 'confirmPassword')] }
|
|
||||||
);
|
|
||||||
|
|
||||||
submit() {
|
|
||||||
if (this.form.invalid) {
|
|
||||||
this.form.markAllAsTouched();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading.set(true);
|
|
||||||
this.service
|
|
||||||
.resetPassword({ password: this.form.value.password as string })
|
|
||||||
.pipe(finalize(() => this.loading.set(false)))
|
|
||||||
.subscribe(() => {
|
|
||||||
this.form.reset();
|
|
||||||
this.toastService.success({ text: 'رمز عبور با موفقیت بهروز شد.' });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,5 +12,6 @@ export interface IProfileRequestPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IResetPasswordRequest {
|
export interface IResetPasswordRequest {
|
||||||
|
currentPassword: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<app-card-data cardTitle="اطلاعات پروفایل" [editable]="true" [(editMode)]="editing">
|
<app-card-data cardTitle="اطلاعات پروفایل" [editable]="true" [(editMode)]="editing">
|
||||||
|
<ng-template #moreActions>
|
||||||
|
<p-button type="button" variant="outlined" size="small" (onClick)="openResetPasswordDialog()">
|
||||||
|
تغییر گذرواژه
|
||||||
|
</p-button>
|
||||||
|
</ng-template>
|
||||||
<div class="listKeyValue">
|
<div class="listKeyValue">
|
||||||
<app-key-value label="تصویر" [value]="profile()?.logo_url" type="thumbnail" />
|
<app-key-value label="تصویر" [value]="profile()?.logo_url" type="thumbnail" />
|
||||||
<app-key-value label="عنوان" [value]="profile()?.name" />
|
<app-key-value label="عنوان" [value]="profile()?.name" />
|
||||||
@@ -7,9 +12,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</app-card-data>
|
</app-card-data>
|
||||||
|
|
||||||
<partner-reset-password-card />
|
|
||||||
|
|
||||||
@if (editing()) {
|
@if (editing()) {
|
||||||
<partner-profile-form [(visible)]="editing" [initialValues]="profile()!" (onSubmit)="onEditSuccess()" />
|
<partner-profile-form [(visible)]="editing" [initialValues]="profile()!" (onSubmit)="onEditSuccess()" />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<shared-change-password-form-dialog
|
||||||
|
[(visible)]="resetPasswordDialog"
|
||||||
|
[showCurrentPasswordField]="true"
|
||||||
|
[loading]="resetPasswordLoading()"
|
||||||
|
(onSubmit)="resetPassword($event)" />
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
|
import { ToastService } from '@/core/services/toast.service';
|
||||||
import { PartnerStore } from '@/domains/partner/store/main.store';
|
import { PartnerStore } from '@/domains/partner/store/main.store';
|
||||||
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
import {
|
||||||
|
AppCardComponent,
|
||||||
|
ChangePasswordFormDialogComponent,
|
||||||
|
KeyValueComponent,
|
||||||
|
} from '@/shared/components';
|
||||||
import { Component, computed, inject, signal } from '@angular/core';
|
import { Component, computed, inject, signal } from '@angular/core';
|
||||||
|
import { Button } from 'primeng/button';
|
||||||
|
import { finalize } from 'rxjs';
|
||||||
import { PartnerProfileFormComponent } from '../components/form.component';
|
import { PartnerProfileFormComponent } from '../components/form.component';
|
||||||
import { PartnerResetPasswordCardComponent } from '../components/reset-password-card.component';
|
import { IResetPasswordRequest } from '../models';
|
||||||
|
import { ProfileService } from '../services/main.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-profile',
|
selector: 'partner-profile',
|
||||||
@@ -10,17 +18,22 @@ import { PartnerResetPasswordCardComponent } from '../components/reset-password-
|
|||||||
imports: [
|
imports: [
|
||||||
AppCardComponent,
|
AppCardComponent,
|
||||||
KeyValueComponent,
|
KeyValueComponent,
|
||||||
PartnerResetPasswordCardComponent,
|
|
||||||
PartnerProfileFormComponent,
|
PartnerProfileFormComponent,
|
||||||
|
Button,
|
||||||
|
ChangePasswordFormDialogComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PartnerProfileComponent {
|
export class PartnerProfileComponent {
|
||||||
private readonly store = inject(PartnerStore);
|
private readonly store = inject(PartnerStore);
|
||||||
|
private readonly service = inject(ProfileService);
|
||||||
|
private readonly toastService = inject(ToastService);
|
||||||
|
|
||||||
|
readonly resetPasswordLoading = signal(false);
|
||||||
|
editing = signal(false);
|
||||||
|
resetPasswordDialog = signal(false);
|
||||||
|
|
||||||
readonly profile = computed(() => this.store.entity());
|
readonly profile = computed(() => this.store.entity());
|
||||||
|
|
||||||
editing = signal(false);
|
|
||||||
|
|
||||||
edit() {
|
edit() {
|
||||||
this.editing.set(true);
|
this.editing.set(true);
|
||||||
}
|
}
|
||||||
@@ -28,4 +41,21 @@ export class PartnerProfileComponent {
|
|||||||
onEditSuccess() {
|
onEditSuccess() {
|
||||||
this.store.getData();
|
this.store.getData();
|
||||||
}
|
}
|
||||||
|
openResetPasswordDialog() {
|
||||||
|
this.resetPasswordDialog.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPassword(payload: IResetPasswordRequest) {
|
||||||
|
this.resetPasswordLoading.set(true);
|
||||||
|
|
||||||
|
this.service
|
||||||
|
.resetPassword(payload)
|
||||||
|
.pipe(finalize(() => this.resetPasswordLoading.set(false)))
|
||||||
|
.subscribe(() => {
|
||||||
|
this.toastService.success({
|
||||||
|
text: 'تغییر رمز عبور با موفقیت انجام شد.',
|
||||||
|
});
|
||||||
|
this.resetPasswordDialog.set(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<ng-template #topbarCenter>
|
<ng-template #topbarCenter>
|
||||||
@if (posInfo()) {
|
@if (posInfo()) {
|
||||||
<a [routerLink]="homeRouteLink" class="flex flex-col items-center justify-center gap-2">
|
<a [routerLink]="homeRouteLink" class="flex flex-col items-center justify-center gap-2">
|
||||||
<div class="h-8 w-8">
|
<div class="h-8 max-w-20">
|
||||||
<img
|
<img
|
||||||
[src]="posInfo()?.partner?.logo_url ?? placeholderLogo"
|
[src]="posInfo()?.partner?.logo_url ?? placeholderLogo"
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import {
|
|||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class PosConfigSendToFiscalActivationService {
|
export class PosConfigSendToFiscalActivationService {
|
||||||
get(): IPosConfigSendToFiscalActivationResponse {
|
get(): IPosConfigSendToFiscalActivationResponse {
|
||||||
const defaultPrice = Boolean(
|
const sendToFiscalActivation = Boolean(
|
||||||
window.localStorage.getItem(LOCAL_STORAGE_KEYS.POS_CONFIG_SEND_TO_FISCAL_ACTIVATION) ===
|
window.localStorage.getItem(LOCAL_STORAGE_KEYS.POS_CONFIG_SEND_TO_FISCAL_ACTIVATION) ===
|
||||||
'true'
|
'true'
|
||||||
);
|
);
|
||||||
|
|
||||||
this.submit(defaultPrice);
|
this.submit(sendToFiscalActivation);
|
||||||
return defaultPrice;
|
return sendToFiscalActivation;
|
||||||
}
|
}
|
||||||
|
|
||||||
submit(data: IPosConfigSendToFiscalActivationPayload) {
|
submit(data: IPosConfigSendToFiscalActivationPayload) {
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
<app-inner-pages-header [pageTitle]="preparedPageTitle()" [backRoute]="backRoute" />
|
<app-inner-pages-header [pageTitle]="preparedPageTitle()" [backRoute]="backRoute" />
|
||||||
<hr class="mt-0!" />
|
<hr class="mt-0!" />
|
||||||
<div class="flex w-full flex-col flex-wrap gap-3 p-4">
|
<div class="flex w-full flex-col flex-wrap gap-3 p-4">
|
||||||
<shared-good-form [guildId]="guildId()" [createFn]="createFn" (onSubmit)="onSubmit()" (onClose)="onPrev()" />
|
<shared-good-form
|
||||||
|
[guildId]="guildId()"
|
||||||
|
[createFn]="createFn"
|
||||||
|
class="block w-full"
|
||||||
|
(onSubmit)="onSubmit()"
|
||||||
|
(onClose)="onPrev()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
[initialValues]="item()!"
|
[initialValues]="item()!"
|
||||||
[updateFn]="updateFn"
|
[updateFn]="updateFn"
|
||||||
[editMode]="true"
|
[editMode]="true"
|
||||||
|
class="block w-full"
|
||||||
(onSubmit)="onSubmit()"
|
(onSubmit)="onSubmit()"
|
||||||
(onClose)="onPrev()" />
|
(onClose)="onPrev()" />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
import { IPosOrderItem } from '../../shop/models';
|
import { ICorrectionRequest } from '@/shared/components/invoices/models';
|
||||||
|
|
||||||
export interface IPosCorrectionRequest {
|
export interface IPosCorrectionRequest extends ICorrectionRequest {}
|
||||||
total_amount: number;
|
|
||||||
discount_amount: number;
|
|
||||||
tax_amount: number;
|
|
||||||
invoice_date: string;
|
|
||||||
items: IPosOrderItem[];
|
|
||||||
notes?: string;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { TspProviderResponseStatus } from '@/shared/catalog';
|
import { TspProviderResponseStatus } from '@/shared/catalog';
|
||||||
|
import { IPosSaleInvoicesSummaryResponse } from './io';
|
||||||
|
|
||||||
export interface IPosSaleInvoiceFiscalActionResponse {
|
export interface IPosSaleInvoiceFiscalActionResponse {
|
||||||
|
invoice: IPosSaleInvoicesSummaryResponse;
|
||||||
message?: string;
|
message?: string;
|
||||||
status: TspProviderResponseStatus;
|
status: TspProviderResponseStatus;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { IPosOrderItem } from '../../shop/models';
|
|
||||||
|
|
||||||
export interface IPosReturnFromSaleRequest {
|
export interface IPosReturnFromSaleRequest {
|
||||||
total_amount: number;
|
|
||||||
discount_amount: number;
|
|
||||||
tax_amount: number;
|
|
||||||
invoice_date: string;
|
invoice_date: string;
|
||||||
items: IPosOrderItem[];
|
items: IPosReturnFromSaleItem[];
|
||||||
notes?: string;
|
}
|
||||||
|
|
||||||
|
export interface IPosReturnFromSaleItem {
|
||||||
|
good_id: string;
|
||||||
|
quantity: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
IPosSaleInvoicesSummaryRawResponse,
|
IPosSaleInvoicesSummaryRawResponse,
|
||||||
IPosSaleInvoicesSummaryResponse,
|
IPosSaleInvoicesSummaryResponse,
|
||||||
} from '../models';
|
} from '../models';
|
||||||
|
import { IPosReturnFromSaleRequest } from '../models/returnFromSale';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class PosSaleInvoicesService {
|
export class PosSaleInvoicesService {
|
||||||
@@ -65,7 +66,10 @@ export class PosSaleInvoicesService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
returnFromSale(data: any, invoiceId: string): Observable<IPosSaleInvoiceFiscalActionResponse> {
|
returnFromSale(
|
||||||
|
data: IPosReturnFromSaleRequest,
|
||||||
|
invoiceId: string
|
||||||
|
): Observable<IPosSaleInvoiceFiscalActionResponse> {
|
||||||
return this.http.post<IPosSaleInvoiceFiscalActionResponse>(
|
return this.http.post<IPosSaleInvoiceFiscalActionResponse>(
|
||||||
this.apiRoutes.tsp.returnFromSale(invoiceId),
|
this.apiRoutes.tsp.returnFromSale(invoiceId),
|
||||||
data
|
data
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
[sendToTspLoading]="sendToTspLoading()"
|
[sendToTspLoading]="sendToTspLoading()"
|
||||||
[inquiryLoading]="inquiryLoading()"
|
[inquiryLoading]="inquiryLoading()"
|
||||||
[resendToTspLoading]="resendToTspLoading()"
|
[resendToTspLoading]="resendToTspLoading()"
|
||||||
|
[correctionLoading]="correctionLoading()"
|
||||||
|
[returnFromSaleLoading]="backFromSaleLoading()"
|
||||||
(onSendToTsp)="sendToTsp()"
|
(onSendToTsp)="sendToTsp()"
|
||||||
(onResendToTsp)="resendToTsp()"
|
(onResendToTsp)="resendToTsp()"
|
||||||
(onInquiry)="inquiry()"
|
(onInquiry)="inquiry()"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { ToastService } from '@/core/services/toast.service';
|
import { ToastService } from '@/core/services/toast.service';
|
||||||
import taxProviderStatusTranslatorUtil from '@/shared/catalog/taxProviderStatus/tax-provider-status-translator.util';
|
import taxProviderStatusTranslatorUtil from '@/shared/catalog/taxProviderStatus/tax-provider-status-translator.util';
|
||||||
import { SharedSaleInvoiceSingleViewComponent } from '@/shared/components/invoices/sale-invoice-single-view.component';
|
import { SharedSaleInvoiceSingleViewComponent } from '@/shared/components/invoices/sale-invoice-single-view.component';
|
||||||
import pageParamsUtils from '@/utils/page-params.utils';
|
|
||||||
import { Component, computed, inject, signal } from '@angular/core';
|
import { Component, computed, inject, signal } from '@angular/core';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { finalize } from 'rxjs';
|
import { distinctUntilChanged, finalize, map } from 'rxjs';
|
||||||
import { posSaleInvoicesNamedRoutes } from '../constants';
|
import { posSaleInvoicesNamedRoutes } from '../constants';
|
||||||
import { IPosCorrectionRequest } from '../models/correction';
|
import { IPosCorrectionRequest } from '../models/correction';
|
||||||
import { IPosReturnFromSaleRequest } from '../models/returnFromSale';
|
import { IPosReturnFromSaleRequest } from '../models/returnFromSale';
|
||||||
@@ -20,8 +20,20 @@ export class PosSaleInvoiceComponent {
|
|||||||
private readonly store = inject(PosSaleInvoiceStore);
|
private readonly store = inject(PosSaleInvoiceStore);
|
||||||
private readonly toastService = inject(ToastService);
|
private readonly toastService = inject(ToastService);
|
||||||
|
|
||||||
pageParams = computed(() => pageParamsUtils(this.route));
|
invoiceId = signal<string>('');
|
||||||
invoiceId = signal<string>(this.pageParams()['invoiceId']);
|
|
||||||
|
constructor() {
|
||||||
|
this.route.paramMap
|
||||||
|
.pipe(
|
||||||
|
map((params) => params.get('invoiceId') ?? ''),
|
||||||
|
distinctUntilChanged(),
|
||||||
|
takeUntilDestroyed()
|
||||||
|
)
|
||||||
|
.subscribe((invoiceId) => {
|
||||||
|
this.invoiceId.set(invoiceId);
|
||||||
|
this.store.getData(invoiceId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
inquiryLoading = signal(false);
|
inquiryLoading = signal(false);
|
||||||
sendToTspLoading = signal(false);
|
sendToTspLoading = signal(false);
|
||||||
@@ -94,7 +106,12 @@ export class PosSaleInvoiceComponent {
|
|||||||
this.correctionLoading.set(false);
|
this.correctionLoading.set(false);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe((res) => {
|
||||||
|
this.toastService.success({
|
||||||
|
text: `اصلاحیهی صورتحساب با شمارهی ${res.invoice?.invoice_number} با موفقیت ایجاد شد.`,
|
||||||
|
});
|
||||||
|
this.store.updateStatus(res.status);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
returnFromSale(data: IPosReturnFromSaleRequest) {
|
returnFromSale(data: IPosReturnFromSaleRequest) {
|
||||||
this.backFromSaleLoading.set(true);
|
this.backFromSaleLoading.set(true);
|
||||||
@@ -105,7 +122,12 @@ export class PosSaleInvoiceComponent {
|
|||||||
this.backFromSaleLoading.set(false);
|
this.backFromSaleLoading.set(false);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe((res) => {
|
||||||
|
this.toastService.success({
|
||||||
|
text: `برگشت از فروش با شمارهی ${res.invoice?.invoice_number} با موفقیت ایجاد شد.`,
|
||||||
|
});
|
||||||
|
this.store.updateStatus(res.status);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
revoke() {
|
revoke() {
|
||||||
this.revokeLoading.set(true);
|
this.revokeLoading.set(true);
|
||||||
@@ -116,10 +138,11 @@ export class PosSaleInvoiceComponent {
|
|||||||
this.revokeLoading.set(false);
|
this.revokeLoading.set(false);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe((res) => {
|
||||||
}
|
this.toastService.success({
|
||||||
|
text: `صورتحساب شمارهی ${res.invoice?.invoice_number} با موفقیت ابطال شد.`,
|
||||||
ngOnInit() {
|
});
|
||||||
this.store.getData(this.invoiceId());
|
this.store.updateStatus(res.status);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<form [formGroup]="form" (submit)="submit()">
|
<form [formGroup]="form" (submit)="submit()">
|
||||||
<app-input [control]="form.controls.name" name="name" label="نام مشتری" />
|
<app-input [control]="form.controls.name" name="name" label="نام مشتری" />
|
||||||
<app-input [control]="form.controls.national_id" name="national_id" label="شماره ملی" type="nationalId" />
|
<app-input [control]="form.controls.economic_code" name="economic_code" label="کد اقتصادی" />
|
||||||
<app-form-footer-actions submitLabel="ثبت مشتری و ادامه" (onCancel)="close()" />
|
<app-form-footer-actions submitLabel="ثبت مشتری و ادامه" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { nationalIdValidator } from '@/core/validators/national-id.validator';
|
|
||||||
import { AbstractForm } from '@/shared/abstractClasses';
|
import { AbstractForm } from '@/shared/abstractClasses';
|
||||||
import { InputComponent } from '@/shared/components';
|
import { InputComponent } from '@/shared/components';
|
||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
@@ -19,10 +18,7 @@ export class CustomerUnknownFormComponent extends AbstractForm<IUnknownCustomer,
|
|||||||
|
|
||||||
override showSuccessMessage = false;
|
override showSuccessMessage = false;
|
||||||
form = this.fb.group({
|
form = this.fb.group({
|
||||||
national_id: [
|
economic_code: [this.store?.customer().info?.customer_unknown?.economic_code || ''],
|
||||||
this.store?.customer().info?.customer_unknown?.national_id || '',
|
|
||||||
[nationalIdValidator()],
|
|
||||||
],
|
|
||||||
name: [this.store?.customer().info?.customer_unknown?.name || ''],
|
name: [this.store?.customer().info?.customer_unknown?.name || ''],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ export class PosOrderSectionComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
submitAndPay() {
|
submitAndPay() {
|
||||||
console.log('submitAndPay');
|
|
||||||
|
|
||||||
this.onSubmit.emit();
|
this.onSubmit.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export interface ILegalCustomer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IUnknownCustomer {
|
export interface IUnknownCustomer {
|
||||||
national_id: string;
|
economic_code?: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,14 @@ export class PosService {
|
|||||||
|
|
||||||
getGoodCategories(): Observable<IListingResponse<IGoodCategoryResponse>> {
|
getGoodCategories(): Observable<IListingResponse<IGoodCategoryResponse>> {
|
||||||
return this.http.get<IListingResponse<IGoodCategoryRawResponse>>(
|
return this.http.get<IListingResponse<IGoodCategoryRawResponse>>(
|
||||||
this.apiRoutes.goodCategories(),
|
this.apiRoutes.goodCategories()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
submitOrder(payload: IPosOrderRequest): Observable<IPosOrderResponse> {
|
submitOrder(payload: IPosOrderRequest, send_to_tsp: boolean): Observable<IPosOrderResponse> {
|
||||||
return this.http.post<IPosOrderRawResponse>(this.apiRoutes.submitOrder(), payload);
|
return this.http.post<IPosOrderRawResponse>(this.apiRoutes.submitOrder(), {
|
||||||
|
...payload,
|
||||||
|
send_to_tsp,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ import { PosPaymentResult } from '../models';
|
|||||||
|
|
||||||
export abstract class PosPaymentBridgeAbstract {
|
export abstract class PosPaymentBridgeAbstract {
|
||||||
abstract registerPaymentResultListener(handler: (payload: PosPaymentResult) => void): () => void;
|
abstract registerPaymentResultListener(handler: (payload: PosPaymentResult) => void): () => void;
|
||||||
abstract emitPaymentResultForTest(payload: unknown): void;
|
abstract emitPaymentResultForTest(payload: PosPaymentResult): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,25 +11,9 @@ export class PosPaymentBridgeService extends PosPaymentBridgeAbstract {
|
|||||||
window.WebV = {
|
window.WebV = {
|
||||||
onPaymentResult: (payload: PosPaymentResult) => {
|
onPaymentResult: (payload: PosPaymentResult) => {
|
||||||
try {
|
try {
|
||||||
// const parsedPayload: PosPaymentResult = JSON.parse(payload);
|
|
||||||
// this.toastServices.info({ text: payload.data?.customerCardNO || '', life: 10000 });
|
|
||||||
// this.toastServices.info({
|
|
||||||
// text: payload.data?.responseCode || 'No response code',
|
|
||||||
// life: 10000,
|
|
||||||
// });
|
|
||||||
// this.toastServices.info({ text: payload.data?.rrn || 'No response code', life: 10000 });
|
|
||||||
// this.toastServices.info({ text: payload.data?.stan || 'No response code', life: 10000 });
|
|
||||||
// this.toastServices.info({
|
|
||||||
// text: payload.data?.terminalId || 'No response code',
|
|
||||||
// life: 10000,
|
|
||||||
// });
|
|
||||||
// this.toastServices.info({
|
|
||||||
// text: payload.data?.transactionDateTime || 'No response code',
|
|
||||||
// life: 10000,
|
|
||||||
// });
|
|
||||||
handler(payload);
|
handler(payload);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.toastServices.error({ text: 'Failed to parse payment result', life: 10000 });
|
// this.toastServices.error({ text: 'Failed to parse payment result', life: 10000 });
|
||||||
this.toastServices.error({
|
this.toastServices.error({
|
||||||
text: e instanceof Error ? e.message : String(e),
|
text: e instanceof Error ? e.message : String(e),
|
||||||
life: 10000,
|
life: 10000,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
import { computed, inject, Injectable, signal } from '@angular/core';
|
import { computed, inject, Injectable, signal } from '@angular/core';
|
||||||
import { catchError, finalize, firstValueFrom, map, throwError } from 'rxjs';
|
import { catchError, finalize, firstValueFrom, map, throwError } from 'rxjs';
|
||||||
|
import { PosConfigSendToFiscalActivationService } from '../../configs/components/sendToFiscalActivation/services/main.service';
|
||||||
import { ICustomer, IPayment, IPosOrderRequest, IPosOrderResponse } from '../models';
|
import { ICustomer, IPayment, IPosOrderRequest, IPosOrderResponse } from '../models';
|
||||||
import { IPosInOrderGood, IPosOrderItem } from '../models/types';
|
import { IPosInOrderGood, IPosOrderItem } from '../models/types';
|
||||||
import { PosService } from '../services/main.service';
|
import { PosService } from '../services/main.service';
|
||||||
@@ -64,6 +65,9 @@ export const INITIAL_POS_STATE: IPosLandingState = {
|
|||||||
@Injectable({ providedIn: 'any' })
|
@Injectable({ providedIn: 'any' })
|
||||||
export class PosLandingStore {
|
export class PosLandingStore {
|
||||||
private readonly service = inject(PosService);
|
private readonly service = inject(PosService);
|
||||||
|
private readonly posConfigSendToFiscalActivationService = inject(
|
||||||
|
PosConfigSendToFiscalActivationService
|
||||||
|
);
|
||||||
|
|
||||||
private state$ = signal<IPosLandingState>({ ...INITIAL_POS_STATE });
|
private state$ = signal<IPosLandingState>({ ...INITIAL_POS_STATE });
|
||||||
|
|
||||||
@@ -295,31 +299,33 @@ export class PosLandingStore {
|
|||||||
|
|
||||||
let res: Maybe<IPosOrderResponse> = null;
|
let res: Maybe<IPosOrderResponse> = null;
|
||||||
|
|
||||||
return this.service.submitOrder(orderPayload).pipe(
|
return this.service
|
||||||
finalize(() => {
|
.submitOrder(orderPayload, this.posConfigSendToFiscalActivationService.get())
|
||||||
this.setState({ submitOrderLoading: false });
|
.pipe(
|
||||||
}),
|
finalize(() => {
|
||||||
catchError((error) => throwError(() => error)),
|
this.setState({ submitOrderLoading: false });
|
||||||
|
}),
|
||||||
|
catchError((error) => throwError(() => error)),
|
||||||
|
|
||||||
map((_res) => {
|
map((_res) => {
|
||||||
if (_res) {
|
if (_res) {
|
||||||
this.setState({
|
this.setState({
|
||||||
inOrderGoods: [],
|
inOrderGoods: [],
|
||||||
customerDetails: {
|
customerDetails: {
|
||||||
type: CustomerType.UNKNOWN,
|
type: CustomerType.UNKNOWN,
|
||||||
},
|
},
|
||||||
invoiceDate: _res.invoice_date,
|
invoiceDate: _res.invoice_date,
|
||||||
payments: {
|
payments: {
|
||||||
cash: 0,
|
cash: 0,
|
||||||
set_off: 0,
|
set_off: 0,
|
||||||
terminals: [],
|
terminals: [],
|
||||||
},
|
},
|
||||||
orderNote: '',
|
orderNote: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return _res;
|
return _res;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,13 @@
|
|||||||
(onSubmit)="submitOrder()" />
|
(onSubmit)="submitOrder()" />
|
||||||
}
|
}
|
||||||
@if (isVisiblePaymentForm()) {
|
@if (isVisiblePaymentForm()) {
|
||||||
<pos-payment-form-dialog [(visible)]="isVisiblePaymentForm" (onSubmit)="submitPayment($event)" />
|
<shared-invoice-payment-form-dialog
|
||||||
|
[(visible)]="isVisiblePaymentForm"
|
||||||
|
[totalAmount]="priceInfo().totalAmount"
|
||||||
|
[submitOrderLoading]="submitOrderLoading()"
|
||||||
|
[isGoldGuild]="isGoldGuild()"
|
||||||
|
[isUnknownCustomer]="isUnknownCustomer()"
|
||||||
|
(onSubmitPayment)="submitPayment($event)" />
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (responseInvoice()) {
|
@if (responseInvoice()) {
|
||||||
|
|||||||
@@ -2,16 +2,17 @@
|
|||||||
import { Maybe } from '@/core';
|
import { Maybe } from '@/core';
|
||||||
import { PosInfoStore } from '@/domains/pos/store/pos.store';
|
import { PosInfoStore } from '@/domains/pos/store/pos.store';
|
||||||
import { AbstractIsMobileComponent } from '@/shared/abstractClasses/abstract-is-mobile';
|
import { AbstractIsMobileComponent } from '@/shared/abstractClasses/abstract-is-mobile';
|
||||||
|
import { PosPaymentFormDialogComponent } from '@/shared/components/invoices/payment';
|
||||||
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
|
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
|
||||||
import { PriceMaskDirective } from '@/shared/directives';
|
import { PriceMaskDirective } from '@/shared/directives';
|
||||||
import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
|
import { finalize } from 'rxjs';
|
||||||
import { PosOrderSectionDialogComponent } from '../components/order/order-section-dialog.component';
|
import { PosOrderSectionDialogComponent } from '../components/order/order-section-dialog.component';
|
||||||
import { PosOrderSectionComponent } from '../components/order/order-section.component';
|
import { PosOrderSectionComponent } from '../components/order/order-section.component';
|
||||||
import { PosOrderSubmittedDialogComponent } from '../components/order/order-submitted-dialog.component';
|
import { PosOrderSubmittedDialogComponent } from '../components/order/order-submitted-dialog.component';
|
||||||
import { PosPaymentFormDialogComponent } from '../components/payment/form-dialog.component';
|
|
||||||
import { PosGoodsComponent } from '../components/views/goods.component';
|
import { PosGoodsComponent } from '../components/views/goods.component';
|
||||||
import { IPosOrderResponse } from '../models';
|
import { IPayment, IPosOrderResponse } from '../models';
|
||||||
import { PosLandingStore } from '../store/main.store';
|
import { PosLandingStore } from '../store/main.store';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -45,6 +46,11 @@ export class PosShopComponent extends AbstractIsMobileComponent {
|
|||||||
readonly error = computed(() => this.infoStore.error());
|
readonly error = computed(() => this.infoStore.error());
|
||||||
readonly inOrderGoods = computed(() => this.landingStore.inOrderGoods());
|
readonly inOrderGoods = computed(() => this.landingStore.inOrderGoods());
|
||||||
readonly priceInfo = computed(() => this.landingStore.orderPricingInfo());
|
readonly priceInfo = computed(() => this.landingStore.orderPricingInfo());
|
||||||
|
readonly submitOrderLoading = computed(() => this.landingStore.submitOrderLoading());
|
||||||
|
readonly isGoldGuild = computed(
|
||||||
|
() => this.infoStore.entity()?.guild.code.toLowerCase() === 'gold'
|
||||||
|
);
|
||||||
|
readonly isUnknownCustomer = computed(() => this.landingStore.customer().type === 'UNKNOWN');
|
||||||
|
|
||||||
// getData() {
|
// getData() {
|
||||||
// this.infoStore.getData().subscribe();
|
// this.infoStore.getData().subscribe();
|
||||||
@@ -66,10 +72,25 @@ export class PosShopComponent extends AbstractIsMobileComponent {
|
|||||||
this.isVisiblePaymentForm.set(true);
|
this.isVisiblePaymentForm.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
submitPayment(invoice: IPosOrderResponse) {
|
submitPayment(event: {
|
||||||
this.closeInvoiceBottomSheet();
|
payment: IPayment;
|
||||||
this.responseInvoice.set(invoice);
|
settlementType: 'CASH' | 'CREDIT' | 'MIXED';
|
||||||
this.isVisibleSuccessDialog.set(true);
|
}) {
|
||||||
|
this.landingStore.setSettlementType(event.settlementType);
|
||||||
|
this.landingStore.setPayment(event.payment);
|
||||||
|
|
||||||
|
this.landingStore
|
||||||
|
.submitOrder()
|
||||||
|
.pipe(
|
||||||
|
finalize(() => {
|
||||||
|
this.isVisiblePaymentForm.set(false);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe((invoice) => {
|
||||||
|
this.closeInvoiceBottomSheet();
|
||||||
|
this.responseInvoice.set(invoice as IPosOrderResponse);
|
||||||
|
this.isVisibleSuccessDialog.set(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
closeSuccessDialog() {
|
closeSuccessDialog() {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<div class="flex items-center justify-center h-svh w-svw">
|
<div class="flex h-svh w-svw items-center justify-center">
|
||||||
<span class="text-center"> به پنل ارایهدهنده خوش آمدید </span>
|
<span class="text-center"> به پنل PSP خوش آمدید </span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ export const SUPER_ADMIN_MENU_ITEMS = [
|
|||||||
icon: 'pi pi-fw pi-home',
|
icon: 'pi pi-fw pi-home',
|
||||||
routerLink: ['/'],
|
routerLink: ['/'],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
label: 'مشتری',
|
// label: 'مودی',
|
||||||
icon: 'pi pi-fw pi-id-card',
|
// icon: 'pi pi-fw pi-id-card',
|
||||||
routerLink: ['/super_admin/consumers'],
|
// routerLink: ['/super_admin/consumers'],
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
label: 'شریک تجاری',
|
label: 'شریک تجاری',
|
||||||
@@ -19,7 +19,7 @@ export const SUPER_ADMIN_MENU_ITEMS = [
|
|||||||
routerLink: ['/super_admin/partners'],
|
routerLink: ['/super_admin/partners'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'ارایهدهنده',
|
label: 'PSP',
|
||||||
icon: 'pi pi-fw pi-building-columns',
|
icon: 'pi pi-fw pi-building-columns',
|
||||||
routerLink: ['/super_admin/providers'],
|
routerLink: ['/super_admin/providers'],
|
||||||
},
|
},
|
||||||
@@ -40,11 +40,11 @@ export const SUPER_ADMIN_MENU_ITEMS = [
|
|||||||
// icon: 'pi pi-fw pi-barcode',
|
// icon: 'pi pi-fw pi-barcode',
|
||||||
// routerLink: [stockKeepingUnitsNamedRoutes.stockKeepingUnits.meta.pagePath!()],
|
// routerLink: [stockKeepingUnitsNamedRoutes.stockKeepingUnits.meta.pagePath!()],
|
||||||
// },
|
// },
|
||||||
{
|
// {
|
||||||
label: 'لایسنس',
|
// label: 'لایسنس',
|
||||||
icon: 'pi pi-fw pi-key',
|
// icon: 'pi pi-fw pi-key',
|
||||||
routerLink: ['/super_admin/licenses'],
|
// routerLink: ['/super_admin/licenses'],
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
label: 'برند دستگاه',
|
label: 'برند دستگاه',
|
||||||
icon: 'pi pi-fw pi-receipt',
|
icon: 'pi pi-fw pi-receipt',
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class ConsumerUserFormComponent extends AbstractFormDialog<
|
|||||||
@Input() consumerId?: string;
|
@Input() consumerId?: string;
|
||||||
private service = inject(ConsumersService);
|
private service = inject(ConsumersService);
|
||||||
|
|
||||||
preparedTitle = computed(() => `${this.editMode ? 'ویرایش' : 'افزودن'} مشتری`);
|
preparedTitle = computed(() => `${this.editMode ? 'ویرایش' : 'افزودن'} مودی`);
|
||||||
|
|
||||||
initForm = () => {
|
initForm = () => {
|
||||||
const form = this.fb.group({
|
const form = this.fb.group({
|
||||||
@@ -63,7 +63,7 @@ export class ConsumerUserFormComponent extends AbstractFormDialog<
|
|||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
nonNullable: true,
|
nonNullable: true,
|
||||||
validators: fieldControl.username('')[1],
|
validators: fieldControl.username('')[1],
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
form.addControl(
|
form.addControl(
|
||||||
@@ -71,7 +71,7 @@ export class ConsumerUserFormComponent extends AbstractFormDialog<
|
|||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
nonNullable: true,
|
nonNullable: true,
|
||||||
validators: [Validators.required],
|
validators: [Validators.required],
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
form.addControl(
|
form.addControl(
|
||||||
@@ -79,7 +79,7 @@ export class ConsumerUserFormComponent extends AbstractFormDialog<
|
|||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
nonNullable: true,
|
nonNullable: true,
|
||||||
validators: [Validators.required],
|
validators: [Validators.required],
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
form.addValidators([MustMatch('password', 'confirmPassword')]);
|
form.addValidators([MustMatch('password', 'confirmPassword')]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class ConsumerPosesComponent extends AbstractList<IPosResponse> {
|
|||||||
{ field: 'pos_type', header: 'نوع دستگاه' },
|
{ field: 'pos_type', header: 'نوع دستگاه' },
|
||||||
{
|
{
|
||||||
field: 'provider',
|
field: 'provider',
|
||||||
header: 'ارایهدهنده',
|
header: 'PSP',
|
||||||
type: 'nested',
|
type: 'nested',
|
||||||
nestedOption: { path: 'provider.name' },
|
nestedOption: { path: 'provider.name' },
|
||||||
},
|
},
|
||||||
@@ -58,8 +58,8 @@ export class ConsumerPosesComponent extends AbstractList<IPosResponse> {
|
|||||||
this.consumerId,
|
this.consumerId,
|
||||||
this.businessId,
|
this.businessId,
|
||||||
this.complexId,
|
this.complexId,
|
||||||
item.id,
|
item.id
|
||||||
),
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const superAdminConsumersNamedRoutes: NamedRoutes<TConsumersRouteNames> =
|
|||||||
path: 'consumers',
|
path: 'consumers',
|
||||||
loadComponent: () => import('../../views/list.component').then((m) => m.ConsumersComponent),
|
loadComponent: () => import('../../views/list.component').then((m) => m.ConsumersComponent),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'مشتریها',
|
title: 'مودیان',
|
||||||
pagePath: () => '/super_admin/consumers',
|
pagePath: () => '/super_admin/consumers',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -18,7 +18,7 @@ export const superAdminConsumersNamedRoutes: NamedRoutes<TConsumersRouteNames> =
|
|||||||
path: 'consumers/:consumerId',
|
path: 'consumers/:consumerId',
|
||||||
loadComponent: () => import('../../views/single.component').then((m) => m.ConsumerComponent),
|
loadComponent: () => import('../../views/single.component').then((m) => m.ConsumerComponent),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'مشتری',
|
title: 'مودی',
|
||||||
pagePath: (guildId: string) => `/super_admin/consumers/${guildId}`,
|
pagePath: (guildId: string) => `/super_admin/consumers/${guildId}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
<app-page-data-list
|
<app-page-data-list
|
||||||
pageTitle="مدیریت مشتریها"
|
pageTitle="مدیریت مودیان"
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
emptyPlaceholderTitle="مشتری یافت نشد"
|
emptyPlaceholderTitle="مودی یافت نشد"
|
||||||
[items]="items()"
|
[items]="items()"
|
||||||
[loading]="loading()"
|
[loading]="loading()"
|
||||||
[showDetails]="true"
|
[showDetails]="true"
|
||||||
(onAdd)="openAddForm()"
|
(onAdd)="openAddForm()"
|
||||||
(onDetails)="toSinglePage($event)"
|
(onDetails)="toSinglePage($event)"
|
||||||
(onEdit)="onEditClick($event)"
|
(onEdit)="onEditClick($event)"
|
||||||
(onRefresh)="refresh()"
|
(onRefresh)="refresh()" />
|
||||||
/>
|
|
||||||
<superAdmin-consumer-form
|
<superAdmin-consumer-form
|
||||||
[(visible)]="visibleForm"
|
[(visible)]="visibleForm"
|
||||||
[editMode]="editMode()"
|
[editMode]="editMode()"
|
||||||
[consumerId]="selectedItemForEdit()?.id"
|
[consumerId]="selectedItemForEdit()?.id"
|
||||||
[initialValues]="selectedItemForEdit() || undefined"
|
[initialValues]="selectedItemForEdit() || undefined"
|
||||||
(onSubmit)="refresh()"
|
(onSubmit)="refresh()" />
|
||||||
/>
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<app-card-data cardTitle="اطلاعات مشتری" [(editMode)]="editMode">
|
<app-card-data cardTitle="اطلاعات مودی" [(editMode)]="editMode">
|
||||||
<ng-template #moreActions> </ng-template>
|
<ng-template #moreActions> </ng-template>
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="listKeyValue">
|
<div class="listKeyValue">
|
||||||
<app-key-value label="نام مشتری" [value]="consumer()?.name" />
|
<app-key-value label="نام" [value]="consumer()?.name" />
|
||||||
<app-key-value label="نوع مشتری" [value]="consumer()?.type?.translate" />
|
<app-key-value label="نوع" [value]="consumer()?.type?.translate" />
|
||||||
@if (consumer()?.type?.value === 'LEGAL') {
|
@if (consumer()?.type?.value === 'LEGAL') {
|
||||||
<app-key-value label="شناسه ملی" [value]="consumer()?.legal?.registration_code" />
|
<app-key-value label="شناسه ملی" [value]="consumer()?.legal?.registration_code" />
|
||||||
} @else {
|
} @else {
|
||||||
|
|||||||
@@ -3,13 +3,12 @@
|
|||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
[style]="{ width: '500px' }"
|
[style]="{ width: '500px' }"
|
||||||
[closable]="true"
|
[closable]="true">
|
||||||
>
|
|
||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||||
<field-code [control]="form.controls.code" />
|
<field-code [control]="form.controls.code" />
|
||||||
<field-name [control]="form.controls.name" />
|
<field-name [control]="form.controls.name" />
|
||||||
<field-vat [control]="form.controls.VAT" />
|
<field-vat [control]="form.controls.VAT" />
|
||||||
<field-sku-type [control]="form.controls.type" />
|
<!-- <field-sku-type [control]="form.controls.type" /> -->
|
||||||
|
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -9,16 +9,15 @@
|
|||||||
[fullHeight]="fullHeight"
|
[fullHeight]="fullHeight"
|
||||||
[showAdd]="true"
|
[showAdd]="true"
|
||||||
[showEdit]="true"
|
[showEdit]="true"
|
||||||
|
[showAll]="showAllBtn"
|
||||||
[allItemsPageRoute]="allItemsPageRoute()"
|
[allItemsPageRoute]="allItemsPageRoute()"
|
||||||
(onEdit)="onEditClick($event)"
|
(onEdit)="onEditClick($event)"
|
||||||
(onAdd)="openAddForm()"
|
(onAdd)="openAddForm()"
|
||||||
(onRefresh)="refresh()"
|
(onRefresh)="refresh()" />
|
||||||
/>
|
|
||||||
|
|
||||||
<stock-keeping-unit-form
|
<stock-keeping-unit-form
|
||||||
[(visible)]="visibleForm"
|
[(visible)]="visibleForm"
|
||||||
[initialValues]="selectedItemForEdit() || undefined"
|
[initialValues]="selectedItemForEdit() || undefined"
|
||||||
[guildId]="guildId"
|
[guildId]="guildId"
|
||||||
[editMode]="editMode()"
|
[editMode]="editMode()"
|
||||||
(onSubmit)="refresh()"
|
(onSubmit)="refresh()" />
|
||||||
/>
|
|
||||||
|
|||||||
@@ -19,13 +19,14 @@ import { StockKeepingUnitFormComponent } from './form.component';
|
|||||||
export class GuildStockKeepingUnitsListComponent extends AbstractList<IStockKeepingUnitResponse> {
|
export class GuildStockKeepingUnitsListComponent extends AbstractList<IStockKeepingUnitResponse> {
|
||||||
@Input() guildId!: string;
|
@Input() guildId!: string;
|
||||||
@Input() fullHeight?: boolean;
|
@Input() fullHeight?: boolean;
|
||||||
|
@Input() showAllBtn?: boolean;
|
||||||
@Input() header: IColumn[] = skuListConfig.columns;
|
@Input() header: IColumn[] = skuListConfig.columns;
|
||||||
|
|
||||||
listConfig = skuListConfig;
|
listConfig = skuListConfig;
|
||||||
service = inject(StockKeepingUnitsService);
|
service = inject(StockKeepingUnitsService);
|
||||||
|
|
||||||
allItemsPageRoute = computed(() =>
|
allItemsPageRoute = computed(() =>
|
||||||
stockKeepingUnitsNamedRoutes.stockKeepingUnits.meta.pagePath!(this.guildId),
|
stockKeepingUnitsNamedRoutes.stockKeepingUnits.meta.pagePath!(this.guildId)
|
||||||
);
|
);
|
||||||
|
|
||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ export const stockKeepingUnitsNamedRoutes: NamedRoutes<TStockKeepingUnitsRouteNa
|
|||||||
path: 'stock-keeping-units',
|
path: 'stock-keeping-units',
|
||||||
loadComponent: () =>
|
loadComponent: () =>
|
||||||
import('../../views/stockKeepingUnits/list.component').then(
|
import('../../views/stockKeepingUnits/list.component').then(
|
||||||
(m) => m.GuildStockKeepingUnitsComponent,
|
(m) => m.GuildStockKeepingUnitsComponent
|
||||||
),
|
),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'شناسه کالاها',
|
title: 'شناسه کالاها',
|
||||||
pagePath: () => '/super_admin/guilds/:guildId/stock-keeping-units',
|
pagePath: (guildId: string) => `/super_admin/guilds/${guildId}/stock-keeping-units`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<admin-guild-goods-list [guildId]="guildId()" [showAllBtn]="true" class="w-full" />
|
<admin-guild-goods-list [guildId]="guildId()" [showAllBtn]="true" class="w-full" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex max-h-125">
|
<div class="flex max-h-125">
|
||||||
<admin-guild-stock-keeping-units-list [guildId]="guildId()" class="w-full" />
|
<admin-guild-stock-keeping-units-list [guildId]="guildId()" [showAllBtn]="true" class="w-full" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<admin-guild-form
|
<admin-guild-form
|
||||||
|
|||||||
@@ -7,12 +7,11 @@
|
|||||||
(onHide)="close()">
|
(onHide)="close()">
|
||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||||
<app-input label="تعداد شارژ" [control]="form.controls.quantity" type="number" />
|
<app-input label="تعداد شارژ" [control]="form.controls.quantity" type="number" />
|
||||||
<!-- <uikit-datepicker
|
<app-datepicker
|
||||||
label="انقضای فروش"
|
label="انقضای فروش"
|
||||||
[control]="form.controls.activated_expires_at"
|
[control]="form.controls.activated_expires_at"
|
||||||
name="activated_expires_at"
|
name="activated_expires_at"
|
||||||
[minDate]="minDate"
|
[min]="minDate" />
|
||||||
/> -->
|
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</shared-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { InputComponent } from '@/shared/components';
|
|||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
// import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
// import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
||||||
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
import { DatepickerComponent } from '@/uikit';
|
||||||
import { nowJalali } from '@/utils';
|
import { nowJalali } from '@/utils';
|
||||||
import { Component, inject, Input } from '@angular/core';
|
import { Component, inject, Input } from '@angular/core';
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
@@ -17,7 +18,7 @@ import { AdminPartnerChargeLicenseTransactionsService } from '../services/charge
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
InputComponent,
|
InputComponent,
|
||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
// UikitFlatpickrJalaliComponent,
|
DatepickerComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PartnerChargeLicenseFormDialogComponent extends AbstractFormDialog<
|
export class PartnerChargeLicenseFormDialogComponent extends AbstractFormDialog<
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class AdminPartnerLicensesComponent extends AbstractList<IPartnerActivate
|
|||||||
// { field: 'id', header: 'شناسه', type: 'id' },
|
// { field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{
|
{
|
||||||
field: 'consumer',
|
field: 'consumer',
|
||||||
header: 'مشتری',
|
header: 'مودی',
|
||||||
customDataModel(item: IPartnerActivatedLicenseResponse) {
|
customDataModel(item: IPartnerActivatedLicenseResponse) {
|
||||||
return `${item.business_activity.consumer_name} (${item.business_activity.name})`;
|
return `${item.business_activity.consumer_name} (${item.business_activity.name})`;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,8 +13,7 @@
|
|||||||
(onAdd)="openAddForm()"
|
(onAdd)="openAddForm()"
|
||||||
(onDetails)="toSinglePage($event)"
|
(onDetails)="toSinglePage($event)"
|
||||||
(onEdit)="onEditClick($event)"
|
(onEdit)="onEditClick($event)"
|
||||||
(onRefresh)="refresh()"
|
(onRefresh)="refresh()">
|
||||||
>
|
|
||||||
<ng-template #name let-item>
|
<ng-template #name let-item>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<p-avatar
|
<p-avatar
|
||||||
@@ -22,8 +21,7 @@
|
|||||||
[title]="item.name"
|
[title]="item.name"
|
||||||
[label]="item.logo_url ? '' : item.name.slice(0, 2)"
|
[label]="item.logo_url ? '' : item.name.slice(0, 2)"
|
||||||
shape="square"
|
shape="square"
|
||||||
size="large"
|
size="large"></p-avatar>
|
||||||
></p-avatar>
|
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@@ -51,5 +49,4 @@
|
|||||||
[editMode]="editMode()"
|
[editMode]="editMode()"
|
||||||
[partnerId]="selectedItemForEdit()?.id"
|
[partnerId]="selectedItemForEdit()?.id"
|
||||||
[initialValues]="selectedItemForEdit() || undefined"
|
[initialValues]="selectedItemForEdit() || undefined"
|
||||||
(onSubmit)="refresh()"
|
(onSubmit)="refresh()" />
|
||||||
/>
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export class ProviderFormComponent extends AbstractFormDialog<IProviderRequest,
|
|||||||
|
|
||||||
form = this.initForm();
|
form = this.initForm();
|
||||||
|
|
||||||
preparedTitle = computed(() => `${this.editMode ? 'ویرایش' : 'افزودن'} ارایهدهنده`);
|
preparedTitle = computed(() => `${this.editMode ? 'ویرایش' : 'افزودن'} PSP`);
|
||||||
|
|
||||||
override ngOnChanges() {
|
override ngOnChanges() {
|
||||||
this.form.patchValue(this.initialValues ?? {});
|
this.form.patchValue(this.initialValues ?? {});
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const providersNamedRoutes: NamedRoutes<TProvidersRouteNames> = {
|
|||||||
path: 'providers/:providerId',
|
path: 'providers/:providerId',
|
||||||
loadComponent: () => import('../../views/single.component').then((m) => m.ProviderComponent),
|
loadComponent: () => import('../../views/single.component').then((m) => m.ProviderComponent),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'ارایهدهنده',
|
title: 'PSP',
|
||||||
pagePath: () => '/super_admin/providers/:providerId',
|
pagePath: () => '/super_admin/providers/:providerId',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,24 +4,22 @@
|
|||||||
[options]="items()"
|
[options]="items()"
|
||||||
optionLabel="name"
|
optionLabel="name"
|
||||||
[optionValue]="selectOptionValue"
|
[optionValue]="selectOptionValue"
|
||||||
placeholder="انتخاب ارایهدهنده"
|
placeholder="انتخاب PSP"
|
||||||
[formControl]="control"
|
[formControl]="control"
|
||||||
[showClear]="showClear"
|
[showClear]="showClear"
|
||||||
[filter]="true"
|
[filter]="true"
|
||||||
appendTo="body"
|
appendTo="body">
|
||||||
>
|
|
||||||
@if (canInsert) {
|
@if (canInsert) {
|
||||||
<ng-template #footer>
|
<ng-template #footer>
|
||||||
<div class="p-3">
|
<div class="p-3">
|
||||||
<p-button
|
<p-button
|
||||||
label="افزودن ارایهدهنده"
|
label="افزودن PSP"
|
||||||
fluid
|
fluid
|
||||||
severity="secondary"
|
severity="secondary"
|
||||||
text
|
text
|
||||||
size="small"
|
size="small"
|
||||||
icon="pi pi-plus"
|
icon="pi pi-plus"
|
||||||
(onClick)="onOpenForm()"
|
(onClick)="onOpenForm()" />
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
<app-page-data-list
|
<app-page-data-list
|
||||||
[pageTitle]="'مدیریت ارایهدهندهگان'"
|
[pageTitle]="'مدیریت PSP'"
|
||||||
[addNewCtaLabel]="'افزودن ارایهدهنده'"
|
[addNewCtaLabel]="'افزودن PSP'"
|
||||||
[columns]="columns"
|
[columns]="columns"
|
||||||
[showAdd]="true"
|
[showAdd]="true"
|
||||||
emptyPlaceholderTitle="ارایهدهندهی یافت نشد"
|
emptyPlaceholderTitle="PSPی یافت نشد"
|
||||||
emptyPlaceholderDescription="برای افزودن ارایهدهندهی، روی دکمهٔ بالا کلیک کنید."
|
emptyPlaceholderDescription="برای افزودن PSPی، روی دکمهٔ بالا کلیک کنید."
|
||||||
[items]="items()"
|
[items]="items()"
|
||||||
[loading]="loading()"
|
[loading]="loading()"
|
||||||
[showDetails]="true"
|
[showDetails]="true"
|
||||||
[showAdd]="true"
|
[showAdd]="true"
|
||||||
(onAdd)="openAddForm()"
|
(onAdd)="openAddForm()"
|
||||||
(onRefresh)="refresh()"
|
(onRefresh)="refresh()" />
|
||||||
/>
|
|
||||||
<provider-form
|
<provider-form
|
||||||
[(visible)]="visibleForm"
|
[(visible)]="visibleForm"
|
||||||
[editMode]="editMode()"
|
[editMode]="editMode()"
|
||||||
[providerId]="selectedItemForEdit()?.id"
|
[providerId]="selectedItemForEdit()?.id"
|
||||||
[initialValues]="selectedItemForEdit() || undefined"
|
[initialValues]="selectedItemForEdit() || undefined"
|
||||||
(onSubmit)="refresh()"
|
(onSubmit)="refresh()" />
|
||||||
/>
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export class AppLayout {
|
|||||||
constructor(
|
constructor(
|
||||||
public layoutService: LayoutService,
|
public layoutService: LayoutService,
|
||||||
public renderer: Renderer2,
|
public renderer: Renderer2,
|
||||||
public router: Router,
|
public router: Router
|
||||||
) {
|
) {
|
||||||
this.layoutService.headerSlot$.subscribe((tpl) => (this.topBarMoreAction = tpl));
|
this.layoutService.headerSlot$.subscribe((tpl) => (this.topBarMoreAction = tpl));
|
||||||
this.layoutService.topbarStartSlot$.subscribe((tpl) => (this.topBarStartAction = tpl));
|
this.layoutService.topbarStartSlot$.subscribe((tpl) => (this.topBarStartAction = tpl));
|
||||||
@@ -105,7 +105,7 @@ export class AppLayout {
|
|||||||
} else {
|
} else {
|
||||||
document.body.className = document.body.className.replace(
|
document.body.className = document.body.className.replace(
|
||||||
new RegExp('(^|\\b)' + 'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'),
|
new RegExp('(^|\\b)' + 'blocked-scroll'.split(' ').join('|') + '(\\b|$)', 'gi'),
|
||||||
' ',
|
' '
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,6 +169,10 @@ export class AppLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges() {
|
||||||
|
console.log('layout changed');
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
if (this.overlayMenuOpenSubscription) {
|
if (this.overlayMenuOpenSubscription) {
|
||||||
this.overlayMenuOpenSubscription.unsubscribe();
|
this.overlayMenuOpenSubscription.unsubscribe();
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<div class="h-10 w-10">
|
<div class="h-10 w-10">
|
||||||
<img [src]="logo" alt="Logo" class="object-contain" />
|
<img [src]="logo" alt="Logo" class="object-contain" />
|
||||||
</div>
|
</div>
|
||||||
<span class="text-muted-color text-sm font-medium">مدیریت صورتحسابهای مالیاتی پاژن</span>
|
<span class="text-muted-color text-sm font-medium">مدیریت صورتحسابهای مالیاتی سپاس</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,13 +9,12 @@
|
|||||||
size="large"
|
size="large"
|
||||||
icon="pi pi-bars"
|
icon="pi pi-bars"
|
||||||
class="layout-menu-button layout-topbar-action"
|
class="layout-menu-button layout-topbar-action"
|
||||||
(click)="layoutService.onMenuToggle()"
|
(click)="layoutService.onMenuToggle()"></p-button>
|
||||||
></p-button>
|
|
||||||
}
|
}
|
||||||
<div class="flex items-center gap-2">
|
<a href="/" class="flex items-center gap-2">
|
||||||
<img [src]="logo" width="32" />
|
<img [src]="logo" width="32" />
|
||||||
<span class="text-xl">{{ panelTitle() }}</span>
|
<span class="text-xl">{{ panelTitle() }}</span>
|
||||||
</div>
|
</a>
|
||||||
}
|
}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #center>
|
<ng-template #center>
|
||||||
@@ -34,13 +33,12 @@
|
|||||||
[icon]="`pi ${layoutService.isDarkTheme() ? 'pi-moon' : 'pi-sun'}`"
|
[icon]="`pi ${layoutService.isDarkTheme() ? 'pi-moon' : 'pi-sun'}`"
|
||||||
text
|
text
|
||||||
size="large"
|
size="large"
|
||||||
(click)="toggleDarkMode()"
|
(click)="toggleDarkMode()">
|
||||||
>
|
|
||||||
<i [ngClass]="{}"></i>
|
<i [ngClass]="{}"></i>
|
||||||
</p-button>
|
</p-button>
|
||||||
|
|
||||||
<div class="">
|
<div class="">
|
||||||
<p-menu #menu [model]="profileMenuItems()" [popup]="true" />
|
<p-menu #menu appendTo="body" [model]="profileMenuItems()" [popup]="true" />
|
||||||
<p-button (click)="menu.toggle($event)" icon="pi pi-user" text severity="contrast" size="large" />
|
<p-button (click)="menu.toggle($event)" icon="pi pi-user" text severity="contrast" size="large" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { computed, effect, Injectable, signal, TemplateRef } from '@angular/core';
|
import { computed, effect, Injectable, signal, TemplateRef } from '@angular/core';
|
||||||
import { MenuItem } from 'primeng/api';
|
import { MenuItem } from 'primeng/api';
|
||||||
import { BehaviorSubject, Subject } from 'rxjs';
|
import { BehaviorSubject, Subject } from 'rxjs';
|
||||||
|
import config from 'src/config';
|
||||||
|
|
||||||
export interface layoutConfig {
|
export interface layoutConfig {
|
||||||
preset?: string;
|
preset?: string;
|
||||||
@@ -39,7 +40,7 @@ export class LayoutService {
|
|||||||
preset: 'Aura',
|
preset: 'Aura',
|
||||||
primary: 'surface',
|
primary: 'surface',
|
||||||
surface: null,
|
surface: null,
|
||||||
darkTheme: localStorage.getItem('isDarkTheme') === 'true',
|
darkTheme: config.isPosApplication ? false : localStorage.getItem('isDarkTheme') === 'true',
|
||||||
menuMode: 'static',
|
menuMode: 'static',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -81,10 +82,12 @@ export class LayoutService {
|
|||||||
|
|
||||||
overlayOpen$ = this.overlayOpen.asObservable();
|
overlayOpen$ = this.overlayOpen.asObservable();
|
||||||
|
|
||||||
theme = computed(() => (this.layoutConfig()?.darkTheme ? 'light' : 'dark'));
|
theme = computed(() =>
|
||||||
|
config.isPosApplication ? 'light' : this.layoutConfig()?.darkTheme ? 'light' : 'dark'
|
||||||
|
);
|
||||||
|
|
||||||
isSidebarActive = computed(
|
isSidebarActive = computed(
|
||||||
() => this.layoutState().overlayMenuActive || this.layoutState().staticMenuMobileActive,
|
() => this.layoutState().overlayMenuActive || this.layoutState().staticMenuMobileActive
|
||||||
);
|
);
|
||||||
|
|
||||||
isDarkTheme = computed(() => this.layoutConfig().darkTheme);
|
isDarkTheme = computed(() => this.layoutConfig().darkTheme);
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
<div class="bg-white h-svh relative">
|
<div class="relative h-svh bg-white">
|
||||||
<div class="absolute inset-0 opacity-30 blur-xs flex items-center justify-center">
|
<div class="absolute inset-0 flex items-center justify-center opacity-30 blur-xs">
|
||||||
<img [src]="authVector" alt="background image" class="w-full bg-cover bg-no-repeat" />
|
<img [src]="authVector" alt="background image" class="w-full bg-cover bg-no-repeat" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center items-center relative z-10 h-svh mx-auto bg-gray-800/80">
|
<div class="relative z-10 mx-auto flex h-svh items-center justify-center bg-gray-800/80">
|
||||||
<div
|
<div
|
||||||
class="flex flex-col items-center justify-center px-12 py-10 h-auto bg-surface-card border border-surface-border rounded-lg shadow w-full max-w-md"
|
class="bg-surface-card border-surface-border flex h-auto w-full max-w-md flex-col items-center justify-center rounded-lg border px-12 py-10 shadow">
|
||||||
>
|
<div class="mb-10 flex flex-col items-center justify-center gap-4 text-center">
|
||||||
<div class="flex flex-col gap-4 text-center mb-10 items-center justify-center">
|
<img [src]="logo" alt="مدیریت صورتحسابهای مالیاتی" class="h-auto w-20" />
|
||||||
<img [src]="logo" alt="مدیریت صورتحسابهای مالیاتی" class="w-20 h-auto" />
|
<span class="text-lg font-bold"> {{ authTitle }}</span>
|
||||||
<span class="text-lg font-bold"> به پنل مدیریت صورتحسابهای مالیاتی پاژن خوش آمدید. </span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- @if (activeStep() === "login") { -->
|
<!-- @if (activeStep() === "login") { -->
|
||||||
@@ -18,8 +17,7 @@
|
|||||||
[defaultRole]="role"
|
[defaultRole]="role"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
(onSuccessfullySubmit)="onLoggedIn($event)"
|
(onSuccessfullySubmit)="onLoggedIn($event)"
|
||||||
(onToSignup)="toSignUp()"
|
(onToSignup)="toSignUp()" />
|
||||||
/>
|
|
||||||
<!-- } @else if (activeStep() === "signup") {
|
<!-- } @else if (activeStep() === "signup") {
|
||||||
<auth-signup role="TEACHER" class="w-full" />
|
<auth-signup role="TEACHER" class="w-full" />
|
||||||
} @else if (activeStep() === "otp") {
|
} @else if (activeStep() === "otp") {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { brandingConfig } from '@/branding/branding.config';
|
||||||
import { IAuthResponse, TRoles } from '@/core';
|
import { IAuthResponse, TRoles } from '@/core';
|
||||||
import { AuthService } from '@/core/services/auth.service';
|
import { AuthService } from '@/core/services/auth.service';
|
||||||
import { ToastService } from '@/core/services/toast.service';
|
import { ToastService } from '@/core/services/toast.service';
|
||||||
@@ -34,6 +35,8 @@ export class AuthComponent {
|
|||||||
selectedRole = signal<TRoles | undefined>(this.role);
|
selectedRole = signal<TRoles | undefined>(this.role);
|
||||||
accountRole = signal<string>('');
|
accountRole = signal<string>('');
|
||||||
|
|
||||||
|
authTitle = `به پنل مدیریت صورتحسابهای مالیاتی ${brandingConfig.title} خوش آمدید.`;
|
||||||
|
|
||||||
toSignUp = () => {
|
toSignUp = () => {
|
||||||
this.activeStep.set('signup');
|
this.activeStep.set('signup');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ export class CatalogInvoiceTypeTagComponent {
|
|||||||
return 'success';
|
return 'success';
|
||||||
case 'CORRECTION':
|
case 'CORRECTION':
|
||||||
return 'warn';
|
return 'warn';
|
||||||
|
case 'RETURN':
|
||||||
|
return 'warn';
|
||||||
case 'REVOKE':
|
case 'REVOKE':
|
||||||
return 'danger';
|
return 'danger';
|
||||||
}
|
}
|
||||||
@@ -28,6 +30,8 @@ export class CatalogInvoiceTypeTagComponent {
|
|||||||
return 'اصلی';
|
return 'اصلی';
|
||||||
case 'CORRECTION':
|
case 'CORRECTION':
|
||||||
return 'اصلاحی';
|
return 'اصلاحی';
|
||||||
|
case 'RETURN':
|
||||||
|
return 'برگشت از فروش';
|
||||||
case 'REVOKE':
|
case 'REVOKE':
|
||||||
return 'ابطالی';
|
return 'ابطالی';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export const InvoiceTypes = {
|
export const InvoiceTypes = {
|
||||||
ORIGINAL: 'ORIGINAL',
|
ORIGINAL: 'ORIGINAL',
|
||||||
CORRECTION: 'CORRECTION',
|
CORRECTION: 'CORRECTION',
|
||||||
|
RETURN: 'RETURN',
|
||||||
REVOKE: 'REVOKE',
|
REVOKE: 'REVOKE',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|||||||