feat: add new form field components for company details and consumer management
- Implemented CompanyNameComponent, DescriptionComponent, DeviceIdComponent, EconomicCodeComponent, EmailComponent, FirstNameComponent, FiscalCodeComponent, GuildIdComponent, LastNameComponent, LegalNameComponent, LicenseStartsAtComponent, MobileComponent, MobileNumberComponent, ModelComponent, NameComponent, NationalCodeComponent, NationalIdComponent, PartnerTokenComponent, PosTypeComponent, PostalCodeComponent, ProviderIdComponent, QuantityComponent, RegistrationCodeComponent, RegistrationNumberComponent, SerialNumberComponent, SetOffComponent, SkuComponent, TerminalComponent, UnitPriceComponent, UsernameComponent. - Added field control configurations for new fields in the form. - Updated routing and branding configurations for TIS tenant. - Created consumer type models for handling individual and legal consumer data.
@@ -1,6 +1,9 @@
|
|||||||
# Build stage
|
# Build stage
|
||||||
FROM node:20 AS builder
|
FROM node:20 AS builder
|
||||||
|
|
||||||
|
ARG TENANT=tis
|
||||||
|
ARG DIST_DIR=tis
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# RUN npm config set registry "https://hub.megan.ir/npm/"
|
# RUN npm config set registry "https://hub.megan.ir/npm/"
|
||||||
@@ -11,14 +14,20 @@ RUN pnpm install
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN pnpm run build
|
RUN if [ "$TENANT" = "default" ]; then \
|
||||||
|
pnpm run build; \
|
||||||
|
else \
|
||||||
|
pnpm run build:$TENANT; \
|
||||||
|
fi
|
||||||
|
|
||||||
FROM nginx:alpine
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
ARG DIST_DIR=tis
|
||||||
|
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
|
||||||
COPY --from=builder /app/dist/pos.client/browser /usr/share/nginx/html
|
COPY --from=builder /app/dist/${DIST_DIR}/browser /usr/share/nginx/html
|
||||||
|
|
||||||
EXPOSE 4001
|
EXPOSE 5000
|
||||||
|
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
# WebView Bridge Contract
|
||||||
|
|
||||||
|
This document defines the Android WebView bridge contract used by tenant builds like `tis`.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
- The bridge is enabled per tenant via `environment.enableNativeBridge`.
|
||||||
|
- Current tenant config:
|
||||||
|
- `src/environments/environment.tis.ts` -> `enableNativeBridge: true`
|
||||||
|
- other environments -> `false`
|
||||||
|
|
||||||
|
## JavaScript host objects
|
||||||
|
|
||||||
|
The web app checks bridge methods on:
|
||||||
|
|
||||||
|
1. `window.AndroidBridge`
|
||||||
|
2. `window.Android` (fallback)
|
||||||
|
|
||||||
|
Your Android app can expose either one.
|
||||||
|
|
||||||
|
## Required native methods
|
||||||
|
|
||||||
|
Expose these synchronous methods through `@JavascriptInterface`:
|
||||||
|
|
||||||
|
- `pay(payloadJson: String): String`
|
||||||
|
- `print(payloadJson: String): String`
|
||||||
|
|
||||||
|
Both methods must return a JSON string.
|
||||||
|
|
||||||
|
## Return JSON format
|
||||||
|
|
||||||
|
Success:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Failure:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"error": "Reason message"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If a non-JSON string is returned, the app treats it as success with raw data.
|
||||||
|
|
||||||
|
## Payload schemas
|
||||||
|
|
||||||
|
### pay(payload)
|
||||||
|
|
||||||
|
Called before invoice submit when terminal amount is greater than zero.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"amount": 1200000,
|
||||||
|
"totalAmount": 3500000,
|
||||||
|
"invoiceDate": "2026-04-27T10:30:00.000Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
|
||||||
|
- `amount` number: terminal payment amount.
|
||||||
|
- `totalAmount` number: full invoice total.
|
||||||
|
- `invoiceDate` string: ISO date-time.
|
||||||
|
|
||||||
|
### print(payload)
|
||||||
|
|
||||||
|
Called after successful invoice creation (and from invoice view print action).
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"invoiceId": "a7e1f2...",
|
||||||
|
"code": "INV-1745730090000"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Fields are optional, but should be used when available.
|
||||||
|
|
||||||
|
## Web behavior summary
|
||||||
|
|
||||||
|
- On native pay failure:
|
||||||
|
- Invoice submit is stopped.
|
||||||
|
- User sees warning toast.
|
||||||
|
- On native print failure or missing bridge:
|
||||||
|
- In invoice page, app falls back to `window.print()`.
|
||||||
|
- In POS checkout flow, print failure does not block successful submit.
|
||||||
|
|
||||||
|
## Android integration example (Kotlin)
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
class AndroidBridge(
|
||||||
|
private val context: Context
|
||||||
|
) {
|
||||||
|
@JavascriptInterface
|
||||||
|
fun pay(payloadJson: String): String {
|
||||||
|
return try {
|
||||||
|
// TODO: parse payloadJson and run POS payment SDK synchronously
|
||||||
|
"""{"success":true,"data":{"txId":"12345"}}"""
|
||||||
|
} catch (e: Exception) {
|
||||||
|
"""{"success":false,"error":"${e.message ?: "Payment failed"}"}"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun print(payloadJson: String): String {
|
||||||
|
return try {
|
||||||
|
// TODO: parse payloadJson and print with printer SDK
|
||||||
|
"""{"success":true}"""
|
||||||
|
} catch (e: Exception) {
|
||||||
|
"""{"success":false,"error":"${e.message ?: "Print failed"}"}"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Attach to WebView:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
webView.settings.javaScriptEnabled = true
|
||||||
|
webView.addJavascriptInterface(AndroidBridge(this), "AndroidBridge")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- For production, use HTTPS for web app + API to avoid mixed-content issues.
|
||||||
|
- Keep method names and payload keys exactly as specified.
|
||||||
@@ -34,7 +34,9 @@
|
|||||||
"with": "src/environments/environment.prod.ts"
|
"with": "src/environments/environment.prod.ts"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"outputHashing": "all"
|
"outputHashing": "all",
|
||||||
|
"outputPath": "dist/pos.client",
|
||||||
|
"serviceWorker": "ngsw-config.json"
|
||||||
},
|
},
|
||||||
"staging": {
|
"staging": {
|
||||||
"extractLicenses": true,
|
"extractLicenses": true,
|
||||||
@@ -46,7 +48,45 @@
|
|||||||
],
|
],
|
||||||
"optimization": true,
|
"optimization": true,
|
||||||
"outputHashing": "all",
|
"outputHashing": "all",
|
||||||
|
"serviceWorker": "ngsw-config.json",
|
||||||
"sourceMap": false
|
"sourceMap": false
|
||||||
|
},
|
||||||
|
"tis": {
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "public-tis"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"maximumError": "3MB",
|
||||||
|
"maximumWarning": "2MB",
|
||||||
|
"type": "initial"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"maximumError": "8kB",
|
||||||
|
"maximumWarning": "4kB",
|
||||||
|
"type": "anyComponentStyle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "src/environments/environment.ts",
|
||||||
|
"with": "src/environments/environment.tis.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/app.routes.ts",
|
||||||
|
"with": "src/tenants/tis/app.routes.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"replace": "src/app/branding/branding.config.ts",
|
||||||
|
"with": "src/tenants/tis/branding.config.ts"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all",
|
||||||
|
"outputPath": "dist/tis",
|
||||||
|
"serviceWorker": "ngsw-config.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "production",
|
"defaultConfiguration": "production",
|
||||||
@@ -86,12 +126,14 @@
|
|||||||
},
|
},
|
||||||
"staging": {
|
"staging": {
|
||||||
"buildTarget": "pos.client:build:staging"
|
"buildTarget": "pos.client:build:staging"
|
||||||
|
},
|
||||||
|
"tis": {
|
||||||
|
"buildTarget": "pos.client:build:tis"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "development",
|
"defaultConfiguration": "development",
|
||||||
"options": {
|
"options": {
|
||||||
"port": 5000,
|
"port": 5000
|
||||||
"proxyConfig": "src/proxy.conf.js"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
TENANT: ${TENANT:-tis}
|
||||||
|
DIST_DIR: ${DIST_DIR:-tis}
|
||||||
container_name: psp_panel_prod
|
container_name: psp_panel_prod
|
||||||
ports:
|
ports:
|
||||||
- "5000:5000"
|
- "5000:5000"
|
||||||
@@ -14,7 +17,7 @@ services:
|
|||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/" ]
|
test: [ "CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:5000/" ]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|||||||
@@ -55,6 +55,17 @@ http {
|
|||||||
add_header Cache-Control "public, immutable";
|
add_header Cache-Control "public, immutable";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Service worker files should be revalidated on each request
|
||||||
|
location = /ngsw.json {
|
||||||
|
expires -1;
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /ngsw-worker.js {
|
||||||
|
expires -1;
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||||
|
}
|
||||||
|
|
||||||
# Angular routing - serve index.html for all routes
|
# Angular routing - serve index.html for all routes
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
||||||
|
"appData": {
|
||||||
|
"appVersion": "0.0.0",
|
||||||
|
"buildDate": "2026-04-27T06:02:22.249Z"
|
||||||
|
},
|
||||||
|
"assetGroups": [
|
||||||
|
{
|
||||||
|
"installMode": "prefetch",
|
||||||
|
"name": "app",
|
||||||
|
"resources": {
|
||||||
|
"files": [
|
||||||
|
"/favicon.ico",
|
||||||
|
"/index.html",
|
||||||
|
"/*.css",
|
||||||
|
"/*.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"updateMode": "prefetch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"installMode": "lazy",
|
||||||
|
"name": "assets",
|
||||||
|
"resources": {
|
||||||
|
"files": [
|
||||||
|
"/favicon/**",
|
||||||
|
"/assets/**",
|
||||||
|
"/**/*.svg",
|
||||||
|
"/**/*.png",
|
||||||
|
"/**/*.jpg",
|
||||||
|
"/**/*.jpeg",
|
||||||
|
"/**/*.webp",
|
||||||
|
"/**/*.gif",
|
||||||
|
"/**/*.woff",
|
||||||
|
"/**/*.woff2",
|
||||||
|
"/**/*.ttf",
|
||||||
|
"/**/*.otf"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"updateMode": "prefetch"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dataGroups": [
|
||||||
|
{
|
||||||
|
"cacheConfig": {
|
||||||
|
"maxAge": "1h",
|
||||||
|
"maxSize": 100,
|
||||||
|
"strategy": "freshness",
|
||||||
|
"timeout": "10s"
|
||||||
|
},
|
||||||
|
"name": "api-fresh",
|
||||||
|
"urls": [
|
||||||
|
"/api/**",
|
||||||
|
"https://*/api/**",
|
||||||
|
"http://*/api/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index": "/index.html",
|
||||||
|
"navigationUrls": [
|
||||||
|
"/**",
|
||||||
|
"!/**/*.*",
|
||||||
|
"!/**/*__*",
|
||||||
|
"!/**/*__*/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
"@angular/platform-browser": "^20.3.19",
|
"@angular/platform-browser": "^20.3.19",
|
||||||
"@angular/platform-browser-dynamic": "^20.3.19",
|
"@angular/platform-browser-dynamic": "^20.3.19",
|
||||||
"@angular/router": "^20.3.19",
|
"@angular/router": "^20.3.19",
|
||||||
|
"@angular/service-worker": "^20.3.19",
|
||||||
"@primeng/themes": "^20.4.0",
|
"@primeng/themes": "^20.4.0",
|
||||||
"@primeuix/themes": "^1.2.5",
|
"@primeuix/themes": "^1.2.5",
|
||||||
"@tailwindcss/postcss": "^4.2.3",
|
"@tailwindcss/postcss": "^4.2.3",
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
"karma-coverage": "~2.2.1",
|
"karma-coverage": "~2.2.1",
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "~2.1.0",
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
|
"madge": "^8.0.0",
|
||||||
"postcss": "^8.5.10",
|
"postcss": "^8.5.10",
|
||||||
"prettier": "^3.8.3",
|
"prettier": "^3.8.3",
|
||||||
"prettier-plugin-organize-imports": "^4.3.0",
|
"prettier-plugin-organize-imports": "^4.3.0",
|
||||||
@@ -66,9 +68,13 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
|
"build:tis": "ng build --configuration tis",
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
|
"prebuild": "node scripts/update-ngsw-appdata.js",
|
||||||
|
"prebuild:tis": "node scripts/update-ngsw-appdata.js",
|
||||||
"prestart": "node aspnetcore-https",
|
"prestart": "node aspnetcore-https",
|
||||||
"start": "run-script-os",
|
"start": "run-script-os",
|
||||||
|
"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: 524 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone",
|
||||||
|
"id": "/",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"purpose": "maskable",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"src": "/favicon/web-app-manifest-192x192.png",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purpose": "maskable",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"src": "/favicon/web-app-manifest-512x512.png",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "PSP A - مدیریت صورتحسابهای مالیاتی",
|
||||||
|
"short_name": "PSP A",
|
||||||
|
"start_url": "/",
|
||||||
|
"scope": "/",
|
||||||
|
"theme_color": "#ffffff"
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -5,17 +5,20 @@
|
|||||||
{
|
{
|
||||||
"purpose": "maskable",
|
"purpose": "maskable",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"src": "/web-app-manifest-192x192.png",
|
"src": "/favicon/web-app-manifest-192x192.png",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"purpose": "maskable",
|
"purpose": "maskable",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"src": "/web-app-manifest-512x512.png",
|
"src": "/favicon/web-app-manifest-512x512.png",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"id": "/",
|
||||||
"name": "مدیریت صورتحسابهای مالیاتی",
|
"name": "مدیریت صورتحسابهای مالیاتی",
|
||||||
|
"scope": "/",
|
||||||
"short_name": "مدیریت صورتحسابهای مالیاتی",
|
"short_name": "مدیریت صورتحسابهای مالیاتی",
|
||||||
|
"start_url": "/",
|
||||||
"theme_color": "#ffffff"
|
"theme_color": "#ffffff"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const root = path.resolve(__dirname, '..');
|
||||||
|
const packageJsonPath = path.join(root, 'package.json');
|
||||||
|
const ngswConfigPath = path.join(root, 'ngsw-config.json');
|
||||||
|
|
||||||
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||||||
|
const ngswConfig = JSON.parse(fs.readFileSync(ngswConfigPath, 'utf8'));
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const buildDate = process.env.BUILD_DATE || now.toISOString();
|
||||||
|
const appVersion = process.env.APP_VERSION || packageJson.version || '0.0.0';
|
||||||
|
|
||||||
|
ngswConfig.appData = {
|
||||||
|
...(ngswConfig.appData || {}),
|
||||||
|
appVersion,
|
||||||
|
buildDate,
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(ngswConfigPath, `${JSON.stringify(ngswConfig, null, 2)}\n`);
|
||||||
@@ -12,13 +12,14 @@ import {
|
|||||||
withInterceptors,
|
withInterceptors,
|
||||||
withInterceptorsFromDi,
|
withInterceptorsFromDi,
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
import { ApplicationConfig, provideZonelessChangeDetection } from '@angular/core';
|
import { ApplicationConfig, isDevMode, provideZonelessChangeDetection } from '@angular/core';
|
||||||
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
||||||
import {
|
import {
|
||||||
provideRouter,
|
provideRouter,
|
||||||
withEnabledBlockingInitialNavigation,
|
withEnabledBlockingInitialNavigation,
|
||||||
withInMemoryScrolling,
|
withInMemoryScrolling,
|
||||||
} from '@angular/router';
|
} from '@angular/router';
|
||||||
|
import { provideServiceWorker } from '@angular/service-worker';
|
||||||
// Use the consolidated preset that includes our custom variables
|
// Use the consolidated preset that includes our custom variables
|
||||||
import { ConfirmationService, MessageService } from 'primeng/api';
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||||
import { providePrimeNG } from 'primeng/config';
|
import { providePrimeNG } from 'primeng/config';
|
||||||
@@ -73,5 +74,9 @@ export const appConfig: ApplicationConfig = {
|
|||||||
withInterceptors([loggingInterceptor, authInterceptor, errorInterceptor, dedupInterceptor]),
|
withInterceptors([loggingInterceptor, authInterceptor, errorInterceptor, dedupInterceptor]),
|
||||||
withInterceptorsFromDi(),
|
withInterceptorsFromDi(),
|
||||||
),
|
),
|
||||||
|
provideServiceWorker('ngsw-worker.js', {
|
||||||
|
enabled: !isDevMode(),
|
||||||
|
registrationStrategy: 'registerWhenStable:30000',
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,40 +1 @@
|
|||||||
import { CONSUMER_ROUTES } from '@/domains/consumer/routes';
|
export { appRoutes } from './tenants/default/app.routes';
|
||||||
import { PARTNER_ROUTES } from '@/domains/partner/routes';
|
|
||||||
import { POS_ROUTES } from '@/domains/pos/routes';
|
|
||||||
import { PROVIDER_ROUTES } from '@/domains/provider/routes';
|
|
||||||
import { SUPER_ADMIN_ROUTES } from '@/domains/superAdmin/routes';
|
|
||||||
import { AuthComponent } from '@/modules/auth/pages/auth.component';
|
|
||||||
import { Notfound } from '@/pages/notfound/notfound.component';
|
|
||||||
import { Routes } from '@angular/router';
|
|
||||||
import { AppLayout } from './app/layout/default/app.layout.component';
|
|
||||||
import { Dashboard } from './app/pages/dashboard/dashboard';
|
|
||||||
import { Documentation } from './app/pages/documentation/documentation';
|
|
||||||
|
|
||||||
export const appRoutes: Routes = [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: AppLayout,
|
|
||||||
children: [
|
|
||||||
SUPER_ADMIN_ROUTES,
|
|
||||||
CONSUMER_ROUTES,
|
|
||||||
PROVIDER_ROUTES,
|
|
||||||
PARTNER_ROUTES,
|
|
||||||
{ path: 'ng', component: Dashboard },
|
|
||||||
{ path: 'uikit', loadChildren: () => import('./app/pages/uikit/uikit.routes') },
|
|
||||||
{ path: 'documentation', component: Documentation },
|
|
||||||
{ path: 'pages', loadChildren: () => import('./app/pages/pages.routes') },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
POS_ROUTES,
|
|
||||||
// {
|
|
||||||
// path: 'pos/:posId',
|
|
||||||
// component: POSComponent,
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
path: 'auth',
|
|
||||||
component: AuthComponent,
|
|
||||||
},
|
|
||||||
{ path: 'notfound', component: Notfound },
|
|
||||||
// { path: 'auth', loadChildren: () => import('./app/pages/auth/auth.routes') },
|
|
||||||
{ path: '**', redirectTo: '/notfound' },
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { brandingConfig } from '../../tenants/default/branding.config';
|
||||||
@@ -3,3 +3,4 @@ export { AuthService } from './auth.service';
|
|||||||
export { ErrorHandlerService } from './error-handler.service';
|
export { ErrorHandlerService } from './error-handler.service';
|
||||||
export { ConfigService } from './config.service';
|
export { ConfigService } from './config.service';
|
||||||
export * from './breadcrumb.service';
|
export * from './breadcrumb.service';
|
||||||
|
export * from './native-bridge.service';
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
|
||||||
|
interface INativeBridgeHost {
|
||||||
|
pay?: (payload: string) => unknown;
|
||||||
|
print?: (payload: string) => unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface INativePayRequest {
|
||||||
|
amount: number;
|
||||||
|
totalAmount: number;
|
||||||
|
invoiceDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface INativePrintRequest {
|
||||||
|
invoiceId?: string;
|
||||||
|
code?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface INativeBridgeResult<T = unknown> {
|
||||||
|
success: boolean;
|
||||||
|
data?: T;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class NativeBridgeService {
|
||||||
|
private get host(): INativeBridgeHost | undefined {
|
||||||
|
const globalWindow = window as unknown as {
|
||||||
|
AndroidBridge?: INativeBridgeHost;
|
||||||
|
Android?: INativeBridgeHost;
|
||||||
|
};
|
||||||
|
|
||||||
|
return globalWindow.AndroidBridge || globalWindow.Android;
|
||||||
|
}
|
||||||
|
|
||||||
|
isEnabled(): boolean {
|
||||||
|
return !!environment.enableNativeBridge;
|
||||||
|
}
|
||||||
|
|
||||||
|
canPay(): boolean {
|
||||||
|
return this.isEnabled() && typeof this.host?.pay === 'function';
|
||||||
|
}
|
||||||
|
|
||||||
|
canPrint(): boolean {
|
||||||
|
return this.isEnabled() && typeof this.host?.print === 'function';
|
||||||
|
}
|
||||||
|
|
||||||
|
pay(request: INativePayRequest): INativeBridgeResult {
|
||||||
|
return this.invoke('pay', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(request: INativePrintRequest): INativeBridgeResult {
|
||||||
|
return this.invoke('print', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private invoke(method: 'pay' | 'print', payload: object): INativeBridgeResult {
|
||||||
|
if (!this.isEnabled()) {
|
||||||
|
return { success: false, error: 'Native bridge is disabled for this tenant.' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn = this.host?.[method];
|
||||||
|
if (typeof fn !== 'function') {
|
||||||
|
return { success: false, error: `Native method "${method}" is not available.` };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const raw = fn(JSON.stringify(payload));
|
||||||
|
const parsed = this.tryParse(raw);
|
||||||
|
if (parsed && typeof parsed === 'object' && 'success' in parsed) {
|
||||||
|
return parsed as INativeBridgeResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true, data: parsed ?? raw };
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: (error as Error).message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private tryParse(value: unknown): unknown {
|
||||||
|
if (typeof value !== 'string') return value;
|
||||||
|
try {
|
||||||
|
return JSON.parse(value);
|
||||||
|
} catch {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { ValidatorFn } from '@angular/forms';
|
||||||
|
|
||||||
|
export function fiscalCodeValidator(): ValidatorFn {
|
||||||
|
return (control) => {
|
||||||
|
if (control.value === null || control.value === undefined || control.value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return control.value.length === 11 && /^[0-9]{11}$/.test(control.value)
|
||||||
|
? null
|
||||||
|
: { fiscalCode: 'معتبر نیست' };
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export * from './fiscal-code.validator';
|
||||||
export * from './iban.validator';
|
export * from './iban.validator';
|
||||||
export * from './mobile.validator';
|
export * from './mobile.validator';
|
||||||
export * from './must-match.validator';
|
export * from './must-match.validator';
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function mobileValidator(): ValidatorFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof v !== 'string') {
|
if (typeof v !== 'string') {
|
||||||
return { invalidMobile: true };
|
return { invalidMobile: 'معتبر نیست' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const trimmed = v.trim();
|
const trimmed = v.trim();
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ export function nationalIdValidator(): ValidatorFn {
|
|||||||
}
|
}
|
||||||
return control.value.length === 10 && /^[0-9]{10}$/.test(control.value)
|
return control.value.length === 10 && /^[0-9]{10}$/.test(control.value)
|
||||||
? null
|
? null
|
||||||
: { nationalId: true };
|
: { nationalId: 'معتبر نیست' };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ export function postalCodeValidator(): ValidatorFn {
|
|||||||
}
|
}
|
||||||
return control.value.length === 10 && /^[0-9]{10}$/.test(control.value)
|
return control.value.length === 10 && /^[0-9]{10}$/.test(control.value)
|
||||||
? null
|
? null
|
||||||
: { postalCode: true };
|
: { postalCode: 'معتبر نیست' };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Maybe } from '@/core';
|
import { Maybe } from '@/core';
|
||||||
|
import { NativeBridgeService } from '@/core/services';
|
||||||
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
||||||
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
|
import { PageLoadingComponent } from '@/shared/components/page-loading.component';
|
||||||
import {
|
import {
|
||||||
@@ -8,7 +9,7 @@ import {
|
|||||||
import { PriceMaskDirective } from '@/shared/directives';
|
import { PriceMaskDirective } from '@/shared/directives';
|
||||||
import { UikitEmptyStateComponent } from '@/uikit';
|
import { UikitEmptyStateComponent } from '@/uikit';
|
||||||
import { getGoodUnitTypeProperties } from '@/utils';
|
import { getGoodUnitTypeProperties } from '@/utils';
|
||||||
import { Component, EventEmitter, Input, Output, TemplateRef, ViewChild } from '@angular/core';
|
import { Component, EventEmitter, inject, Input, Output, TemplateRef, ViewChild } from '@angular/core';
|
||||||
import { Badge } from 'primeng/badge';
|
import { Badge } from 'primeng/badge';
|
||||||
import { ButtonDirective } from 'primeng/button';
|
import { ButtonDirective } from 'primeng/button';
|
||||||
import { Divider } from 'primeng/divider';
|
import { Divider } from 'primeng/divider';
|
||||||
@@ -34,6 +35,8 @@ export type TConsumerSaleInvoice = 'full' | 'customer' | 'pos';
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerSaleInvoiceSharedComponent {
|
export class ConsumerSaleInvoiceSharedComponent {
|
||||||
|
private readonly nativeBridge = inject(NativeBridgeService);
|
||||||
|
|
||||||
@Input({ required: true }) loading!: boolean;
|
@Input({ required: true }) loading!: boolean;
|
||||||
@Input() invoice?: Maybe<ISaleInvoiceFullResponse>;
|
@Input() invoice?: Maybe<ISaleInvoiceFullResponse>;
|
||||||
@Input() variant: TConsumerSaleInvoice = 'full';
|
@Input() variant: TConsumerSaleInvoice = 'full';
|
||||||
@@ -43,6 +46,14 @@ export class ConsumerSaleInvoiceSharedComponent {
|
|||||||
@ViewChild('totalAmount', { static: false }) totalAmount!: TemplateRef<any>;
|
@ViewChild('totalAmount', { static: false }) totalAmount!: TemplateRef<any>;
|
||||||
|
|
||||||
printInvoice = () => {
|
printInvoice = () => {
|
||||||
|
if (this.nativeBridge.isEnabled()) {
|
||||||
|
const result = this.nativeBridge.print({
|
||||||
|
invoiceId: this.invoice?.id,
|
||||||
|
code: this.invoice?.code,
|
||||||
|
});
|
||||||
|
if (result.success) return;
|
||||||
|
}
|
||||||
|
|
||||||
window.print();
|
window.print();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
header="اطلاعات لایسنس"
|
header="اطلاعات لایسنس"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -22,4 +22,4 @@
|
|||||||
<app-key-value label="ارایه شده توسط" [value]="license()?.partner?.name || 'برند نرمافزار'" />
|
<app-key-value label="ارایه شده توسط" [value]="license()?.partner?.name || 'برند نرمافزار'" />
|
||||||
</div>
|
</div>
|
||||||
} -->
|
} -->
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
import { KeyValueComponent } from '@/shared/components';
|
|
||||||
import { Component, inject } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { Message } from 'primeng/message';
|
|
||||||
import { ConsumerStore } from '../store/main.store';
|
import { ConsumerStore } from '../store/main.store';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-license-info-dialog',
|
selector: 'consumer-license-info-dialog',
|
||||||
templateUrl: './license-info-dialog.component.html',
|
templateUrl: './license-info-dialog.component.html',
|
||||||
imports: [Dialog, KeyValueComponent, Message],
|
imports: [SharedDialogComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerLicenseInfoDialogComponent extends AbstractDialog {
|
export class ConsumerLicenseInfoDialogComponent extends AbstractDialog {
|
||||||
private readonly store = inject(ConsumerStore);
|
private readonly store = inject(ConsumerStore);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
header="ویرایش گذرواژه"
|
header="ویرایش گذرواژه"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -14,4 +14,4 @@
|
|||||||
|
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import { SharedPasswordInputComponent } from '@/shared/components';
|
|||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
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';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IAccountRequest, IAccountResponse } from '../models';
|
import { IAccountRequest, IAccountResponse } from '../models';
|
||||||
import { AccountsService } from '../services/main.service';
|
import { AccountsService } from '../services/main.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'account-password-form',
|
selector: 'account-password-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [ReactiveFormsModule, Dialog, FormFooterActionsComponent, SharedPasswordInputComponent],
|
imports: [ReactiveFormsModule, SharedDialogComponent, FormFooterActionsComponent, SharedPasswordInputComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerAccountPasswordFormComponent extends AbstractFormDialog<
|
export class ConsumerAccountPasswordFormComponent extends AbstractFormDialog<
|
||||||
IAccountRequest,
|
IAccountRequest,
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export class ConsumerAccountPermissionListComponent {
|
|||||||
submit() {
|
submit() {
|
||||||
const dataToSet: IPermissionRequest = {};
|
const dataToSet: IPermissionRequest = {};
|
||||||
const posPermissions = this.permissions()
|
const posPermissions = this.permissions()
|
||||||
?.poses.filter((pos) => pos.hasAccess)
|
?.poses?.filter((pos) => pos.hasAccess)
|
||||||
.map((pos) => pos.id);
|
.map((pos) => pos.id);
|
||||||
const complexPermissions = this.permissions()
|
const complexPermissions = this.permissions()
|
||||||
?.complexes?.filter((complex) => complex.hasAccess)
|
?.complexes?.filter((complex) => complex.hasAccess)
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ export interface IAccountRawResponse {
|
|||||||
role: string;
|
role: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
account: Account;
|
account: Account;
|
||||||
pos: PosComplex;
|
pos: PosSummary;
|
||||||
}
|
}
|
||||||
export interface IAccountResponse extends IAccountRawResponse {}
|
export interface IAccountResponse extends IAccountRawResponse {}
|
||||||
|
|
||||||
export interface IAccountRequest {
|
export interface IAccountRequest {
|
||||||
name: string;
|
username?: string;
|
||||||
|
password?: string;
|
||||||
|
role?: string;
|
||||||
|
status?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAccountPasswordRequest {
|
export interface IAccountPasswordRequest {
|
||||||
@@ -20,6 +23,12 @@ interface Account {
|
|||||||
status: string;
|
status: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PosSummary {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
complex: PosComplex;
|
||||||
|
}
|
||||||
|
|
||||||
interface PosComplex {
|
interface PosComplex {
|
||||||
name: string;
|
name: string;
|
||||||
branch_code: string;
|
branch_code: string;
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import ISummary from '@/core/models/summary';
|
import ISummary from '@/core/models/summary';
|
||||||
|
|
||||||
export interface IPermissionRawResponse {
|
export interface IPermissionRawResponse {
|
||||||
poses: IPosPermissionResponse[];
|
poses?: IPosPermissionResponse[];
|
||||||
complexes: IComplexPermissionResponse[];
|
complexes?: IComplexPermissionResponse[];
|
||||||
business_activities: ICommonPermissionResponse[];
|
business_activities?: ICommonPermissionResponse[];
|
||||||
|
// Backend currently returns this key in camelCase for non-operator roles.
|
||||||
|
businessActivities?: ICommonPermissionResponse[];
|
||||||
}
|
}
|
||||||
export interface IPermissionResponse extends IPermissionRawResponse {}
|
export interface IPermissionResponse extends IPermissionRawResponse {}
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ interface ICommonPermissionResponse {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
hasAccess: boolean;
|
hasAccess: boolean;
|
||||||
|
role?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IComplexPermissionResponse extends ICommonPermissionResponse {
|
interface IComplexPermissionResponse extends ICommonPermissionResponse {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { CONSUMER_PERMISSIONS_API_ROUTES } from '../constants';
|
import { CONSUMER_PERMISSIONS_API_ROUTES } from '../constants';
|
||||||
import { IPermissionRawResponse, IPermissionRequest, IPermissionResponse } from '../models';
|
import { IPermissionRawResponse, IPermissionRequest, IPermissionResponse } from '../models';
|
||||||
@@ -11,7 +12,13 @@ export class PermissionsService {
|
|||||||
private apiRoutes = CONSUMER_PERMISSIONS_API_ROUTES;
|
private apiRoutes = CONSUMER_PERMISSIONS_API_ROUTES;
|
||||||
|
|
||||||
getAll(accountId: string): Observable<IPermissionResponse> {
|
getAll(accountId: string): Observable<IPermissionResponse> {
|
||||||
return this.http.get<IPermissionRawResponse>(this.apiRoutes.list(accountId));
|
return this.http.get<IPermissionRawResponse>(this.apiRoutes.list(accountId)).pipe(
|
||||||
|
map((res) => ({
|
||||||
|
poses: res.poses ?? [],
|
||||||
|
complexes: res.complexes ?? [],
|
||||||
|
business_activities: res.business_activities ?? res.businessActivities ?? [],
|
||||||
|
})),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(accountId: string, data: IPermissionRequest): Observable<IPermissionResponse> {
|
update(accountId: string, data: IPermissionRequest): Observable<IPermissionResponse> {
|
||||||
|
|||||||
@@ -8,11 +8,10 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
@if (selectedItemForEdit()) {
|
@if (selectedItemForEdit()) {
|
||||||
<account-password-form
|
<shared-change-password-form-dialog
|
||||||
[(visible)]="visibleForm"
|
[(visible)]="visibleForm"
|
||||||
[editMode]="editMode()"
|
[title]="selectedItemForEdit()?.account?.username || ''"
|
||||||
[accountId]="selectedItemForEdit()?.id!"
|
[loading]="passwordSubmitLoading()"
|
||||||
[initialValues]="selectedItemForEdit() || undefined"
|
(onSubmit)="updatePassword($event)"
|
||||||
(onSubmit)="refresh()"
|
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
|
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
|
||||||
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
|
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
|
||||||
|
import {
|
||||||
|
ChangePasswordFormDialogComponent,
|
||||||
|
IChangePasswordSubmitPayload,
|
||||||
|
} from '@/shared/components';
|
||||||
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
|
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
import { Component, inject } from '@angular/core';
|
import { Component, inject, signal } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { ConsumerAccountPasswordFormComponent } from '../components/form.component';
|
import { finalize } from 'rxjs';
|
||||||
import { consumerAccountsNamedRoutes } from '../constants';
|
import { consumerAccountsNamedRoutes } from '../constants';
|
||||||
import { IAccountResponse } from '../models';
|
import { IAccountResponse } from '../models';
|
||||||
import { AccountsService } from '../services/main.service';
|
import { AccountsService } from '../services/main.service';
|
||||||
@@ -11,11 +15,12 @@ import { AccountsService } from '../services/main.service';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-accounts',
|
selector: 'consumer-accounts',
|
||||||
templateUrl: './list.component.html',
|
templateUrl: './list.component.html',
|
||||||
imports: [PageDataListComponent, ConsumerAccountPasswordFormComponent],
|
imports: [PageDataListComponent, ChangePasswordFormDialogComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerAccountsComponent extends AbstractList<IAccountResponse> {
|
export class ConsumerAccountsComponent extends AbstractList<IAccountResponse> {
|
||||||
private readonly service = inject(AccountsService);
|
private readonly service = inject(AccountsService);
|
||||||
private readonly router = inject(Router);
|
private readonly router = inject(Router);
|
||||||
|
passwordSubmitLoading = signal(false);
|
||||||
|
|
||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
this.columns = [
|
this.columns = [
|
||||||
@@ -48,4 +53,17 @@ export class ConsumerAccountsComponent extends AbstractList<IAccountResponse> {
|
|||||||
toSinglePage(account: IAccountResponse) {
|
toSinglePage(account: IAccountResponse) {
|
||||||
this.router.navigateByUrl(consumerAccountsNamedRoutes.account.meta.pagePath!(account.id));
|
this.router.navigateByUrl(consumerAccountsNamedRoutes.account.meta.pagePath!(account.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePassword(payload: IChangePasswordSubmitPayload) {
|
||||||
|
if (!this.selectedItemForEdit()?.id) return;
|
||||||
|
|
||||||
|
this.passwordSubmitLoading.set(true);
|
||||||
|
this.service
|
||||||
|
.update(this.selectedItemForEdit()!.id, { password: payload.password })
|
||||||
|
.pipe(finalize(() => this.passwordSubmitLoading.set(false)))
|
||||||
|
.subscribe(() => {
|
||||||
|
this.visibleForm.set(false);
|
||||||
|
this.refresh();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ import { BreadcrumbService } from '@/core/services';
|
|||||||
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
import { AppCardComponent, KeyValueComponent } from '@/shared/components';
|
||||||
import { Component, computed, effect, inject, signal } from '@angular/core';
|
import { Component, computed, effect, inject, signal } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { ConsumerAccountPermissionListComponent } from '../components/permissions/list.component';
|
|
||||||
import { AccountStore } from '../store/account.store';
|
import { AccountStore } from '../store/account.store';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-account',
|
selector: 'consumer-account',
|
||||||
templateUrl: './single.component.html',
|
templateUrl: './single.component.html',
|
||||||
imports: [AppCardComponent, KeyValueComponent, ConsumerAccountPermissionListComponent],
|
imports: [AppCardComponent, KeyValueComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerAccountComponent {
|
export class ConsumerAccountComponent {
|
||||||
private readonly store = inject(AccountStore);
|
private readonly store = inject(AccountStore);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
[header]="preparedTitle"
|
[header]="preparedTitle"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -7,9 +7,9 @@
|
|||||||
(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.name" name="name" />
|
<field-name [control]="form.controls.name" />
|
||||||
<app-input label="کد شعبه" [control]="form.controls.branch_code" name="branch_code" />
|
<field-branch-code [control]="form.controls.branch_code" />
|
||||||
<app-input label="آدرس" [control]="form.controls.address" name="address" />
|
<field-address [control]="form.controls.address" />
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -1,17 +1,29 @@
|
|||||||
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
||||||
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
||||||
import { InputComponent } from '@/shared/components';
|
import {
|
||||||
|
NameComponent,
|
||||||
|
AddressComponent,
|
||||||
|
BranchCodeComponent,
|
||||||
|
} from '@/shared/components';
|
||||||
|
import { fieldControl } from '@/shared/constants/fields';
|
||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
import { Component, inject, Input } from '@angular/core';
|
import { Component, inject, Input } from '@angular/core';
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IComplexRequest, IComplexResponse } from '../../models';
|
import { IComplexRequest, IComplexResponse } from '../../models';
|
||||||
import { ConsumerComplexesService } from '../../services/complexes.service';
|
import { ConsumerComplexesService } from '../../services/complexes.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-complex-form',
|
selector: 'consumer-complex-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [ReactiveFormsModule, Dialog, InputComponent, FormFooterActionsComponent],
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
SharedDialogComponent,
|
||||||
|
NameComponent,
|
||||||
|
BranchCodeComponent,
|
||||||
|
AddressComponent,
|
||||||
|
FormFooterActionsComponent,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerComplexFormComponent extends AbstractFormDialog<
|
export class ConsumerComplexFormComponent extends AbstractFormDialog<
|
||||||
IComplexRequest,
|
IComplexRequest,
|
||||||
@@ -24,9 +36,9 @@ export class ConsumerComplexFormComponent extends AbstractFormDialog<
|
|||||||
|
|
||||||
initForm = () => {
|
initForm = () => {
|
||||||
return this.fb.group({
|
return this.fb.group({
|
||||||
name: [this.initialValues?.name || '', [Validators.required]],
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
branch_code: [this.initialValues?.branch_code || ''],
|
branch_code: fieldControl.branch_code(this.initialValues?.branch_code || ''),
|
||||||
address: [this.initialValues?.address || '', [Validators.required]],
|
address: fieldControl.address(this.initialValues?.address || ''),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
header="ویرایش فعالیت اقتصادی"
|
header="ویرایش فعالیت اقتصادی"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -7,7 +7,10 @@
|
|||||||
(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 [control]="form.controls.name" name="name" label="عنوان" />
|
<field-name [control]="form.controls.name" />
|
||||||
|
<field-economic-code [control]="form.controls.economic_code" />
|
||||||
|
<field-fiscal-code [control]="form.controls.fiscal_code" />
|
||||||
|
<field-partner-token [control]="form.controls.partner_token" />
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -1,16 +1,30 @@
|
|||||||
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
||||||
import { InputComponent } from '@/shared/components';
|
import {
|
||||||
|
EconomicCodeComponent,
|
||||||
|
FiscalCodeComponent,
|
||||||
|
NameComponent,
|
||||||
|
PartnerTokenComponent,
|
||||||
|
} from '@/shared/components';
|
||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
|
import { fieldControl } from '@/shared/constants/fields';
|
||||||
import { Component, inject, Input } from '@angular/core';
|
import { Component, inject, Input } from '@angular/core';
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IBusinessActivityRequest, IBusinessActivityResponse } from '../models';
|
import { IBusinessActivityRequest, IBusinessActivityResponse } from '../models';
|
||||||
import { BusinessActivitiesService } from '../services/main.service';
|
import { BusinessActivitiesService } from '../services/main.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-businessActivity-form',
|
selector: 'consumer-businessActivity-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [ReactiveFormsModule, Dialog, FormFooterActionsComponent, InputComponent],
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
SharedDialogComponent,
|
||||||
|
FormFooterActionsComponent,
|
||||||
|
NameComponent,
|
||||||
|
EconomicCodeComponent,
|
||||||
|
FiscalCodeComponent,
|
||||||
|
PartnerTokenComponent,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerBusinessActivityFormComponent extends AbstractFormDialog<
|
export class ConsumerBusinessActivityFormComponent extends AbstractFormDialog<
|
||||||
IBusinessActivityRequest,
|
IBusinessActivityRequest,
|
||||||
@@ -20,7 +34,10 @@ export class ConsumerBusinessActivityFormComponent extends AbstractFormDialog<
|
|||||||
private service = inject(BusinessActivitiesService);
|
private service = inject(BusinessActivitiesService);
|
||||||
|
|
||||||
form = this.fb.group({
|
form = this.fb.group({
|
||||||
name: [this.initialValues?.name, [Validators.required]],
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
|
economic_code: fieldControl.economic_code(this.initialValues?.economic_code || ''),
|
||||||
|
fiscal_code: fieldControl.fiscal_code(this.initialValues?.fiscal_code || ''),
|
||||||
|
partner_token: fieldControl.partner_token(this.initialValues?.partner_token || ''),
|
||||||
});
|
});
|
||||||
|
|
||||||
override submitForm(payload: IBusinessActivityRequest) {
|
override submitForm(payload: IBusinessActivityRequest) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog [header]="preparedTitle" [(visible)]="visible" [modal]="true" [style]="{ width: '500px' }" [closable]="true">
|
<shared-dialog [header]="preparedTitle" [(visible)]="visible" [modal]="true" [style]="{ width: '500px' }" [closable]="true">
|
||||||
<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.name" name="name" />
|
<app-input label="عنوان" [control]="form.controls.name" name="name" />
|
||||||
<app-input label="شناسه عمومی" [control]="form.controls.sku" name="sku" />
|
<app-input label="شناسه عمومی" [control]="form.controls.sku" name="sku" />
|
||||||
@@ -14,4 +14,4 @@
|
|||||||
|
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ 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 { 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';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
|
|
||||||
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
|
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
|
||||||
import { CatalogGuildGoodCategoriesSelectComponent } from '@/shared/catalog/guildGoodCategories';
|
import { CatalogGuildGoodCategoriesSelectComponent } from '@/shared/catalog/guildGoodCategories';
|
||||||
@@ -12,13 +11,14 @@ import {
|
|||||||
IConsumerBusinessActivityGoodResponse,
|
IConsumerBusinessActivityGoodResponse,
|
||||||
} from '../../models/goods_io';
|
} from '../../models/goods_io';
|
||||||
import { BusinessActivityGoodsService } from '../../services/goods.service';
|
import { BusinessActivityGoodsService } from '../../services/goods.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-businessActivity-good-form',
|
selector: 'consumer-businessActivity-good-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [
|
imports: [
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
Dialog,
|
SharedDialogComponent,
|
||||||
InputComponent,
|
InputComponent,
|
||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
EnumSelectComponent,
|
EnumSelectComponent,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
[header]="preparedTitle"
|
[header]="preparedTitle"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -7,19 +7,19 @@
|
|||||||
(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.name" name="name" />
|
<field-name [control]="form.controls.name" />
|
||||||
|
|
||||||
<app-enum-select [control]="form.controls.pos_type" type="posType" name="pos_type" />
|
<field-pos-type [control]="form.controls.pos_type" />
|
||||||
|
|
||||||
@if (form.controls.pos_type.value === "PSP") {
|
@if (form.controls.pos_type.value === "PSP") {
|
||||||
<app-input label="سریال دستگاه" [control]="form.controls.serial_number" name="serial_number" />
|
<field-serial-number [control]="form.controls.serial_number" />
|
||||||
<catalog-device-select [control]="form.controls.device_id" />
|
<field-device-id [control]="form.controls.device_id" />
|
||||||
<catalog-provider-select [control]="form.controls.provider_id" />
|
<field-provider-id [control]="form.controls.provider_id" />
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (!editMode) {
|
@if (!editMode) {
|
||||||
<p-divider align="center"> اطلاعات ورود </p-divider>
|
<p-divider align="center"> اطلاعات ورود </p-divider>
|
||||||
<app-input label="نام کاربری" [control]="form.controls.username" name="username" [isLtrInput]="true" />
|
<field-username [control]="form.controls.username" />
|
||||||
<shared-password-input
|
<shared-password-input
|
||||||
[passwordControl]="form.controls.password"
|
[passwordControl]="form.controls.password"
|
||||||
[confirmPasswordControl]="form.controls.confirmPassword"
|
[confirmPasswordControl]="form.controls.confirmPassword"
|
||||||
@@ -28,4 +28,4 @@
|
|||||||
|
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -1,29 +1,37 @@
|
|||||||
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
||||||
import { MustMatch } from '@/core/validators';
|
import { MustMatch } from '@/core/validators';
|
||||||
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
||||||
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
|
import {
|
||||||
import { CatalogProviderSelectComponent } from '@/shared/catalog';
|
NameComponent,
|
||||||
import { CatalogDeviceSelectComponent } from '@/shared/catalog/devices';
|
SharedPasswordInputComponent,
|
||||||
import { InputComponent, SharedPasswordInputComponent } from '@/shared/components';
|
DeviceIdComponent,
|
||||||
|
ProviderIdComponent,
|
||||||
|
SerialNumberComponent,
|
||||||
|
PosTypeComponent,
|
||||||
|
UsernameComponent,
|
||||||
|
} from '@/shared/components';
|
||||||
|
import { fieldControl } from '@/shared/constants/fields';
|
||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
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';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { Divider } from 'primeng/divider';
|
import { Divider } from 'primeng/divider';
|
||||||
import { IPosRequest, IPosResponse } from '../../models';
|
import { IPosRequest, IPosResponse } from '../../models';
|
||||||
import { ConsumerPosesService } from '../../services/poses.service';
|
import { ConsumerPosesService } from '../../services/poses.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-pos-form',
|
selector: 'consumer-pos-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [
|
imports: [
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
Dialog,
|
SharedDialogComponent,
|
||||||
InputComponent,
|
NameComponent,
|
||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
CatalogDeviceSelectComponent,
|
DeviceIdComponent,
|
||||||
CatalogProviderSelectComponent,
|
ProviderIdComponent,
|
||||||
EnumSelectComponent,
|
PosTypeComponent,
|
||||||
|
SerialNumberComponent,
|
||||||
|
UsernameComponent,
|
||||||
Divider,
|
Divider,
|
||||||
SharedPasswordInputComponent,
|
SharedPasswordInputComponent,
|
||||||
],
|
],
|
||||||
@@ -37,11 +45,11 @@ export class ConsumerPosFormComponent extends AbstractFormDialog<IPosRequest, IP
|
|||||||
|
|
||||||
initForm = () => {
|
initForm = () => {
|
||||||
const form = this.fb.group({
|
const form = this.fb.group({
|
||||||
name: [this.initialValues?.name || '', [Validators.required]],
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
pos_type: [this.initialValues?.pos_type || '', [Validators.required]],
|
pos_type: fieldControl.pos_type(this.initialValues?.pos_type || ''),
|
||||||
serial_number: [this.initialValues?.serial_number || ''],
|
serial_number: fieldControl.serial_number(this.initialValues?.serial_number || ''),
|
||||||
device_id: [this.initialValues?.device?.id || ''],
|
device_id: fieldControl.device_id(this.initialValues?.device?.id || ''),
|
||||||
provider_id: [this.initialValues?.provider?.id || ''],
|
provider_id: fieldControl.provider_id(this.initialValues?.provider?.id || ''),
|
||||||
username: [''],
|
username: [''],
|
||||||
password: [''],
|
password: [''],
|
||||||
confirmPassword: [''],
|
confirmPassword: [''],
|
||||||
@@ -82,13 +90,15 @@ export class ConsumerPosFormComponent extends AbstractFormDialog<IPosRequest, IP
|
|||||||
form.removeControl('confirmPassword');
|
form.removeControl('confirmPassword');
|
||||||
form.removeValidators([MustMatch('password', 'confirmPassword')]);
|
form.removeValidators([MustMatch('password', 'confirmPassword')]);
|
||||||
} else {
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
form.addControl(
|
form.addControl(
|
||||||
'username',
|
'username',
|
||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
nonNullable: true,
|
nonNullable: true,
|
||||||
validators: [Validators.required],
|
validators: fieldControl.username('')[1],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
// @ts-ignore
|
||||||
form.addControl(
|
form.addControl(
|
||||||
'password',
|
'password',
|
||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
@@ -96,6 +106,7 @@ export class ConsumerPosFormComponent extends AbstractFormDialog<IPosRequest, IP
|
|||||||
validators: [Validators.required],
|
validators: [Validators.required],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
// @ts-ignore
|
||||||
form.addControl(
|
form.addControl(
|
||||||
'confirmPassword',
|
'confirmPassword',
|
||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ export interface IBusinessActivityRawResponse {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
economic_code: string;
|
economic_code: string;
|
||||||
|
fiscal_code: string;
|
||||||
|
partner_token: string;
|
||||||
guild: ISummary;
|
guild: ISummary;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
license_info: LicenseInfo;
|
license_info: LicenseInfo;
|
||||||
@@ -12,6 +14,8 @@ export interface IBusinessActivityResponse extends IBusinessActivityRawResponse
|
|||||||
|
|
||||||
export interface IBusinessActivityRequest {
|
export interface IBusinessActivityRequest {
|
||||||
economic_code: string;
|
economic_code: string;
|
||||||
|
fiscal_code: string;
|
||||||
|
partner_token: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
header="ویرایش اطلاعات مشتری"
|
header="ویرایش اطلاعات مشتری"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -21,4 +21,4 @@
|
|||||||
(onClose)="close()"
|
(onClose)="close()"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { ICustomerResponse } from '../models';
|
import { ICustomerResponse } from '../models';
|
||||||
import { ConsumerCustomerIndividualFormComponent } from './form-individual.component';
|
import { ConsumerCustomerIndividualFormComponent } from './form-individual.component';
|
||||||
import { ConsumerCustomerLegalFormComponent } from './form-legal.component';
|
import { ConsumerCustomerLegalFormComponent } from './form-legal.component';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-customer-form-dialog',
|
selector: 'consumer-customer-form-dialog',
|
||||||
@@ -14,7 +14,7 @@ import { ConsumerCustomerLegalFormComponent } from './form-legal.component';
|
|||||||
ConsumerCustomerIndividualFormComponent,
|
ConsumerCustomerIndividualFormComponent,
|
||||||
ConsumerCustomerLegalFormComponent,
|
ConsumerCustomerLegalFormComponent,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
Dialog,
|
SharedDialogComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerBusinessActivityFormComponent extends AbstractDialog {
|
export class ConsumerBusinessActivityFormComponent extends AbstractDialog {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
||||||
<app-input [control]="form.controls.first_name" name="first_name" label="نام" />
|
<app-input [control]="form.controls.first_name" name="first_name" label="نام" />
|
||||||
<app-input [control]="form.controls.last_name" name="last_name" label="نام خانوادگی" />
|
<app-input [control]="form.controls.last_name" name="last_name" label="نام خانوادگی" />
|
||||||
<app-input [control]="form.controls.national_id" name="national_id" label="کد ملی" type="nationalId" />
|
<app-input [control]="form.controls.national_code" name="national_code" label="کد ملی" type="nationalId" />
|
||||||
<app-input [control]="form.controls.economic_code" name="economic_code" label="کد اقتصادی" maxlength="11" />
|
<app-input [control]="form.controls.economic_code" name="economic_code" label="کد اقتصادی" maxlength="11" />
|
||||||
<app-input [control]="form.controls.postal_code" name="postal_code" label="کد پستی" type="postalCode" />
|
<app-input [control]="form.controls.postal_code" name="postal_code" label="کد پستی" type="postalCode" />
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export class ConsumerCustomerIndividualFormComponent extends AbstractForm<
|
|||||||
return this.fb.group({
|
return this.fb.group({
|
||||||
first_name: [this.initialValues?.individual?.first_name || '', [Validators.required]],
|
first_name: [this.initialValues?.individual?.first_name || '', [Validators.required]],
|
||||||
last_name: [this.initialValues?.individual?.last_name || '', [Validators.required]],
|
last_name: [this.initialValues?.individual?.last_name || '', [Validators.required]],
|
||||||
national_id: [
|
national_code: [
|
||||||
this.initialValues?.individual?.national_id || '',
|
this.initialValues?.individual?.national_id || '',
|
||||||
[Validators.required, nationalIdValidator()],
|
[Validators.required, nationalIdValidator()],
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -12,12 +12,21 @@ export interface ICustomerResponse extends ICustomerRawResponse {}
|
|||||||
|
|
||||||
export interface ICustomerRequest {}
|
export interface ICustomerRequest {}
|
||||||
|
|
||||||
export interface ICustomerIndividualRequest extends CustomerIndividual {
|
export interface ICustomerIndividualRequest {
|
||||||
is_favorite: boolean;
|
first_name?: string;
|
||||||
|
last_name?: string;
|
||||||
|
national_code?: string;
|
||||||
|
postal_code?: string;
|
||||||
|
economic_code?: string;
|
||||||
|
is_favorite?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICustomerLegalRequest extends CustomerLegal {
|
export interface ICustomerLegalRequest {
|
||||||
is_favorite: boolean;
|
company_name?: string;
|
||||||
|
registration_number?: string;
|
||||||
|
postal_code?: string;
|
||||||
|
economic_code?: string;
|
||||||
|
is_favorite?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CustomerLegal {
|
interface CustomerLegal {
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import ISummary from '@/core/models/summary';
|
|||||||
export interface IStatisticsSaleInvoicesRawResponse {
|
export interface IStatisticsSaleInvoicesRawResponse {
|
||||||
id: string;
|
id: string;
|
||||||
code: string;
|
code: string;
|
||||||
created_date: string;
|
created_at: string;
|
||||||
|
created_date?: string;
|
||||||
total_amount: string;
|
total_amount: string;
|
||||||
pos: Pos;
|
pos: Pos;
|
||||||
consumer_account: ConsumerAccount;
|
consumer_account: ConsumerAccount;
|
||||||
created_at: string;
|
|
||||||
}
|
}
|
||||||
export interface IStatisticsSaleInvoicesResponse extends IStatisticsSaleInvoicesRawResponse {}
|
export interface IStatisticsSaleInvoicesResponse extends IStatisticsSaleInvoicesRawResponse {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
[header]="preparedTitle"
|
[header]="preparedTitle"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -10,4 +10,4 @@
|
|||||||
<app-input label="عنوان" [control]="form.controls.name" name="name" />
|
<app-input label="عنوان" [control]="form.controls.name" name="name" />
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ 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 { Component, inject, Input } from '@angular/core';
|
import { Component, inject, Input } from '@angular/core';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IPosRequest, IPosResponse } from '../models';
|
import { IPosRequest, IPosResponse } from '../models';
|
||||||
import { ConsumerPosesService } from '../services/main.service';
|
import { ConsumerPosesService } from '../services/main.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'consumer-pos-form',
|
selector: 'consumer-pos-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [ReactiveFormsModule, Dialog, InputComponent, FormFooterActionsComponent],
|
imports: [ReactiveFormsModule, SharedDialogComponent, InputComponent, FormFooterActionsComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerPosFormComponent extends AbstractFormDialog<IPosRequest, IPosResponse> {
|
export class ConsumerPosFormComponent extends AbstractFormDialog<IPosRequest, IPosResponse> {
|
||||||
private readonly service = inject(ConsumerPosesService);
|
private readonly service = inject(ConsumerPosesService);
|
||||||
|
|||||||
@@ -7,9 +7,13 @@ export interface IPosRawResponse {
|
|||||||
model?: string;
|
model?: string;
|
||||||
status: string;
|
status: string;
|
||||||
pos_type: string;
|
pos_type: string;
|
||||||
|
created_at?: string;
|
||||||
complex: ISummary;
|
complex: ISummary;
|
||||||
device?: ISummary;
|
device?: ISummary;
|
||||||
provider?: ISummary;
|
provider?: ISummary;
|
||||||
|
account?: {
|
||||||
|
username: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
export interface IPosResponse extends IPosRawResponse {}
|
export interface IPosResponse extends IPosRawResponse {}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,6 @@ interface Complex extends ISummary {
|
|||||||
|
|
||||||
interface Payments {
|
interface Payments {
|
||||||
amount: string;
|
amount: string;
|
||||||
paid_at: string;
|
paid_at?: string;
|
||||||
payment_method: string;
|
payment_method: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
header="ویرایش گذرواژه"
|
header="ویرایش گذرواژه"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -14,4 +14,4 @@
|
|||||||
|
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import { SharedPasswordInputComponent } from '@/shared/components';
|
|||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
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';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IAccountRequest, IAccountResponse } from '../models';
|
import { IAccountRequest, IAccountResponse } from '../models';
|
||||||
import { AccountsService } from '../services/main.service';
|
import { AccountsService } from '../services/main.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'account-password-form',
|
selector: 'account-password-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [ReactiveFormsModule, Dialog, FormFooterActionsComponent, SharedPasswordInputComponent],
|
imports: [ReactiveFormsModule, SharedDialogComponent, FormFooterActionsComponent, SharedPasswordInputComponent],
|
||||||
})
|
})
|
||||||
export class PartnerAccountPasswordFormComponent extends AbstractFormDialog<
|
export class PartnerAccountPasswordFormComponent extends AbstractFormDialog<
|
||||||
IAccountRequest,
|
IAccountRequest,
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ export interface IAccountRawResponse {
|
|||||||
export interface IAccountResponse extends IAccountRawResponse {}
|
export interface IAccountResponse extends IAccountRawResponse {}
|
||||||
|
|
||||||
export interface IAccountRequest {
|
export interface IAccountRequest {
|
||||||
name: string;
|
username?: string;
|
||||||
|
password?: string;
|
||||||
|
role?: string;
|
||||||
|
status?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAccountPasswordRequest {
|
export interface IAccountPasswordRequest {
|
||||||
|
|||||||
@@ -8,11 +8,10 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
@if (selectedItemForEdit()) {
|
@if (selectedItemForEdit()) {
|
||||||
<account-password-form
|
<shared-change-password-form-dialog
|
||||||
[(visible)]="visibleForm"
|
[(visible)]="visibleForm"
|
||||||
[editMode]="editMode()"
|
[title]="selectedItemForEdit()?.account?.username || ''"
|
||||||
[accountId]="selectedItemForEdit()?.id!"
|
[loading]="passwordSubmitLoading()"
|
||||||
[initialValues]="selectedItemForEdit() || undefined"
|
(onSubmit)="updatePassword($event)"
|
||||||
(onSubmit)="refresh()"
|
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
|
// import { CatalogRoleTagComponent } from '@/shared/catalog/roles';
|
||||||
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
|
import { AbstractList } from '@/shared/abstractClasses/abstract-list';
|
||||||
|
import {
|
||||||
|
ChangePasswordFormDialogComponent,
|
||||||
|
IChangePasswordSubmitPayload,
|
||||||
|
} from '@/shared/components';
|
||||||
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
|
import { PageDataListComponent } from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
import { Component, inject } from '@angular/core';
|
import { Component, inject, signal } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { PartnerAccountPasswordFormComponent } from '../components/form.component';
|
import { finalize } from 'rxjs';
|
||||||
import { partnerAccountsNamedRoutes } from '../constants';
|
import { partnerAccountsNamedRoutes } from '../constants';
|
||||||
import { IAccountResponse } from '../models';
|
import { IAccountResponse } from '../models';
|
||||||
import { AccountsService } from '../services/main.service';
|
import { AccountsService } from '../services/main.service';
|
||||||
@@ -11,11 +15,12 @@ import { AccountsService } from '../services/main.service';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-accounts',
|
selector: 'partner-accounts',
|
||||||
templateUrl: './list.component.html',
|
templateUrl: './list.component.html',
|
||||||
imports: [PageDataListComponent, PartnerAccountPasswordFormComponent],
|
imports: [PageDataListComponent, ChangePasswordFormDialogComponent],
|
||||||
})
|
})
|
||||||
export class PartnerAccountsComponent extends AbstractList<IAccountResponse> {
|
export class PartnerAccountsComponent extends AbstractList<IAccountResponse> {
|
||||||
private readonly service = inject(AccountsService);
|
private readonly service = inject(AccountsService);
|
||||||
private readonly router = inject(Router);
|
private readonly router = inject(Router);
|
||||||
|
passwordSubmitLoading = signal(false);
|
||||||
|
|
||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
this.columns = [
|
this.columns = [
|
||||||
@@ -48,4 +53,17 @@ export class PartnerAccountsComponent extends AbstractList<IAccountResponse> {
|
|||||||
toSinglePage(account: IAccountResponse) {
|
toSinglePage(account: IAccountResponse) {
|
||||||
this.router.navigateByUrl(partnerAccountsNamedRoutes.account.meta.pagePath!(account.id));
|
this.router.navigateByUrl(partnerAccountsNamedRoutes.account.meta.pagePath!(account.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePassword(payload: IChangePasswordSubmitPayload) {
|
||||||
|
if (!this.selectedItemForEdit()?.id) return;
|
||||||
|
|
||||||
|
this.passwordSubmitLoading.set(true);
|
||||||
|
this.service
|
||||||
|
.update(this.selectedItemForEdit()!.id, { password: payload.password })
|
||||||
|
.pipe(finalize(() => this.passwordSubmitLoading.set(false)))
|
||||||
|
.subscribe(() => {
|
||||||
|
this.visibleForm.set(false);
|
||||||
|
this.refresh();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
header="فرم کاربر"
|
header="فرم کاربر"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
(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.username" name="username" />
|
<field-username [control]="form.controls.username" />
|
||||||
<app-enum-select [control]="form.controls.role" name="role" type="consumerRole" />
|
<app-enum-select [control]="form.controls.role" name="role" type="consumerRole" />
|
||||||
<shared-password-input
|
<shared-password-input
|
||||||
[passwordControl]="form.controls.password"
|
[passwordControl]="form.controls.password"
|
||||||
@@ -15,4 +15,4 @@
|
|||||||
/>
|
/>
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -2,21 +2,22 @@ import { MustMatch, password } from '@/core/validators';
|
|||||||
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
||||||
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
||||||
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
|
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
|
||||||
import { InputComponent, SharedPasswordInputComponent } from '@/shared/components';
|
import { SharedPasswordInputComponent, UsernameComponent } from '@/shared/components';
|
||||||
|
import { fieldControl } from '@/shared/constants/fields';
|
||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
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';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IConsumerAccountRequest, IConsumerAccountResponse } from '../../models';
|
import { IConsumerAccountRequest, IConsumerAccountResponse } from '../../models';
|
||||||
import { PartnerConsumerAccountsService } from '../../services/accounts.service';
|
import { PartnerConsumerAccountsService } from '../../services/accounts.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-account-form',
|
selector: 'partner-consumer-account-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [
|
imports: [
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
Dialog,
|
SharedDialogComponent,
|
||||||
InputComponent,
|
UsernameComponent,
|
||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
SharedPasswordInputComponent,
|
SharedPasswordInputComponent,
|
||||||
EnumSelectComponent,
|
EnumSelectComponent,
|
||||||
@@ -35,7 +36,7 @@ export class ConsumerAccountFormComponent extends AbstractFormDialog<
|
|||||||
if (this.editMode) {
|
if (this.editMode) {
|
||||||
return this.fb.group(
|
return this.fb.group(
|
||||||
{
|
{
|
||||||
username: [this.initialValues?.account.username || '', [Validators.required]],
|
username: fieldControl.username(this.initialValues?.account.username || ''),
|
||||||
password: ['', [password()]],
|
password: ['', [password()]],
|
||||||
confirmPassword: [''],
|
confirmPassword: [''],
|
||||||
},
|
},
|
||||||
@@ -46,7 +47,7 @@ export class ConsumerAccountFormComponent extends AbstractFormDialog<
|
|||||||
}
|
}
|
||||||
return this.fb.group(
|
return this.fb.group(
|
||||||
{
|
{
|
||||||
username: [this.initialValues?.account.username || '', [Validators.required]],
|
username: fieldControl.username(this.initialValues?.account.username || ''),
|
||||||
role: ['', [Validators.required]],
|
role: ['', [Validators.required]],
|
||||||
password: ['', [Validators.required, password()]],
|
password: ['', [Validators.required, password()]],
|
||||||
confirmPassword: ['', [Validators.required]],
|
confirmPassword: ['', [Validators.required]],
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<shared-dialog
|
||||||
|
header="ایجاد فعالیت اقتصادی"
|
||||||
|
[(visible)]="visible"
|
||||||
|
[modal]="true"
|
||||||
|
[style]="{ width: '520px' }"
|
||||||
|
[closable]="true"
|
||||||
|
(onHide)="close()"
|
||||||
|
>
|
||||||
|
<p-stepper [value]="activeStep()" [linear]="true">
|
||||||
|
<p-step-list>
|
||||||
|
<p-step [value]="1">فعالیت اقتصادی</p-step>
|
||||||
|
<p-step [value]="2" [disabled]="!businessActivity()">فروشگاه</p-step>
|
||||||
|
<p-step [value]="3" [disabled]="!complex()">پایانهی فروشگاهی</p-step>
|
||||||
|
</p-step-list>
|
||||||
|
</p-stepper>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
@switch (activeStep()) {
|
||||||
|
@case (1) {
|
||||||
|
<partner-consumer-businessActivities-form-content
|
||||||
|
[consumerId]="consumerId"
|
||||||
|
(onSubmit)="onBusinessActivitySubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
@case (2) {
|
||||||
|
<partner-consumer-complex-form-content
|
||||||
|
[consumerId]="consumerId"
|
||||||
|
[businessActivityId]="businessActivity()?.id || ''"
|
||||||
|
(onSubmit)="onComplexSubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
@case (3) {
|
||||||
|
<partner-consumer-pos-form-content
|
||||||
|
[consumerId]="consumerId"
|
||||||
|
[businessActivityId]="businessActivity()?.id || ''"
|
||||||
|
[complexId]="complex()?.id || ''"
|
||||||
|
(onSubmit)="onPosSubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</shared-dialog>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
import { Component, effect, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||||
|
import { Step, StepList, Stepper } from 'primeng/stepper';
|
||||||
|
import { IBusinessActivityResponse, IComplexResponse, IPosResponse } from '../../../models';
|
||||||
|
import { ConsumerComplexFormContentComponent } from '../../complexes/form.component';
|
||||||
|
import { ConsumerPosFormContentComponent } from '../../poses/form.component';
|
||||||
|
import { ConsumerBusinessActivitiesFormComponent } from '../form.component';
|
||||||
|
|
||||||
|
export interface ICreateBusinessActivityStepperResult {
|
||||||
|
businessActivity: IBusinessActivityResponse;
|
||||||
|
complex: IComplexResponse;
|
||||||
|
pos: IPosResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'partner-consumer-businessActivities-create-wrapper',
|
||||||
|
templateUrl: './create-wrapper.component.html',
|
||||||
|
imports: [
|
||||||
|
SharedDialogComponent,
|
||||||
|
Stepper,
|
||||||
|
StepList,
|
||||||
|
Step,
|
||||||
|
ConsumerBusinessActivitiesFormComponent,
|
||||||
|
ConsumerComplexFormContentComponent,
|
||||||
|
ConsumerPosFormContentComponent,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class ConsumerBusinessActivitiesCreateWrapperComponent extends AbstractDialog {
|
||||||
|
@Input({ required: true }) consumerId!: string;
|
||||||
|
@Output() onSubmit = new EventEmitter<ICreateBusinessActivityStepperResult>();
|
||||||
|
|
||||||
|
activeStep = signal(1);
|
||||||
|
businessActivity = signal<IBusinessActivityResponse | null>(null);
|
||||||
|
complex = signal<IComplexResponse | null>(null);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
effect(() => {
|
||||||
|
if (this.visible) {
|
||||||
|
this.resetWizard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onBusinessActivitySubmit(response: IBusinessActivityResponse) {
|
||||||
|
this.businessActivity.set(response);
|
||||||
|
this.activeStep.set(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
onComplexSubmit(response: IComplexResponse) {
|
||||||
|
this.complex.set(response);
|
||||||
|
this.activeStep.set(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
onPosSubmit(response: IPosResponse) {
|
||||||
|
const businessActivity = this.businessActivity();
|
||||||
|
const complex = this.complex();
|
||||||
|
|
||||||
|
if (!businessActivity || !complex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onSubmit.emit({
|
||||||
|
businessActivity,
|
||||||
|
complex,
|
||||||
|
pos: response,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
override close() {
|
||||||
|
this.resetWizard();
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetWizard() {
|
||||||
|
this.activeStep.set(1);
|
||||||
|
this.businessActivity.set(null);
|
||||||
|
this.complex.set(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
[header]="preparedTitle"
|
[header]="preparedTitle"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -14,4 +14,4 @@
|
|||||||
(onSubmit)="onFormSubmit($event)"
|
(onSubmit)="onFormSubmit($event)"
|
||||||
(onClose)="close()"
|
(onClose)="close()"
|
||||||
/>
|
/>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IBusinessActivityResponse } from '../../models';
|
import { IBusinessActivityResponse } from '../../models';
|
||||||
import { ConsumerBusinessActivitiesFormComponent } from './form.component';
|
import { ConsumerBusinessActivitiesFormComponent } from './form.component';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-businessActivities-form',
|
selector: 'partner-consumer-businessActivities-form',
|
||||||
templateUrl: './form-dialog.component.html',
|
templateUrl: './form-dialog.component.html',
|
||||||
imports: [Dialog, ConsumerBusinessActivitiesFormComponent],
|
imports: [SharedDialogComponent, ConsumerBusinessActivitiesFormComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerBusinessActivitiesFormDialogComponent extends AbstractDialog {
|
export class ConsumerBusinessActivitiesFormDialogComponent extends AbstractDialog {
|
||||||
@Output() onSubmit = new EventEmitter<IBusinessActivityResponse>();
|
@Output() onSubmit = new EventEmitter<IBusinessActivityResponse>();
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
<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]="$any(form).controls.name" name="name" />
|
<field-name [control]="$any(form).controls.name" />
|
||||||
<app-input label="کد اقتصادی" [control]="$any(form).controls.economic_code" name="economic_code" />
|
<field-economic-code [control]="$any(form).controls.economic_code" />
|
||||||
<catalog-guild-select label="صنف" [control]="$any(form).controls.guild_id" name="guild_id" />
|
<field-fiscal-code [control]="$any(form).controls.fiscal_code" />
|
||||||
|
<field-partner-token [control]="$any(form).controls.partner_token" />
|
||||||
|
<field-guild-id [control]="$any(form).controls.guild_id" />
|
||||||
|
|
||||||
@if (!editMode) {
|
@if (!editMode) {
|
||||||
<p-divider align="center"> اطلاعات لایسنس </p-divider>
|
<p-divider align="center"> اطلاعات لایسنس </p-divider>
|
||||||
<uikit-datepicker
|
<field-license-starts-at
|
||||||
label="تاریخ شروع لایسنس"
|
|
||||||
[control]="$any(form).controls.license_starts_at"
|
[control]="$any(form).controls.license_starts_at"
|
||||||
name="license_starts_at"
|
|
||||||
hint="مدت زمان لایسنسها ۱ ساله هستند."
|
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import { AbstractForm } from '@/shared/abstractClasses';
|
import { AbstractForm } from '@/shared/abstractClasses';
|
||||||
import { CatalogGuildSelectComponent } from '@/shared/catalog/guild/components/select.component';
|
import {
|
||||||
import { InputComponent } from '@/shared/components';
|
EconomicCodeComponent,
|
||||||
|
FiscalCodeComponent,
|
||||||
|
GuildIdComponent,
|
||||||
|
LicenseStartsAtComponent,
|
||||||
|
NameComponent,
|
||||||
|
PartnerTokenComponent,
|
||||||
|
} 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 { fieldControl } from '@/shared/constants/fields';
|
||||||
import { Component, inject, Input } from '@angular/core';
|
import { Component, inject, Input } from '@angular/core';
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { Divider } from 'primeng/divider';
|
import { Divider } from 'primeng/divider';
|
||||||
import { IBusinessActivityRequest, IBusinessActivityResponse } from '../../models';
|
import { IBusinessActivityRequest, IBusinessActivityResponse } from '../../models';
|
||||||
import { PartnerConsumerBusinessActivitiesService } from '../../services/businessActivities.service';
|
import { PartnerConsumerBusinessActivitiesService } from '../../services/businessActivities.service';
|
||||||
@@ -14,11 +20,14 @@ import { PartnerConsumerBusinessActivitiesService } from '../../services/busines
|
|||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [
|
imports: [
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
InputComponent,
|
NameComponent,
|
||||||
|
EconomicCodeComponent,
|
||||||
|
FiscalCodeComponent,
|
||||||
|
PartnerTokenComponent,
|
||||||
|
GuildIdComponent,
|
||||||
|
LicenseStartsAtComponent,
|
||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
CatalogGuildSelectComponent,
|
|
||||||
Divider,
|
Divider,
|
||||||
UikitFlatpickrJalaliComponent,
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerBusinessActivitiesFormComponent extends AbstractForm<
|
export class ConsumerBusinessActivitiesFormComponent extends AbstractForm<
|
||||||
@@ -32,9 +41,11 @@ export class ConsumerBusinessActivitiesFormComponent extends AbstractForm<
|
|||||||
|
|
||||||
initForm = () => {
|
initForm = () => {
|
||||||
const form = this.fb.group({
|
const form = this.fb.group({
|
||||||
name: [this.initialValues?.name || '', [Validators.required]],
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
economic_code: [this.initialValues?.economic_code || '', [Validators.required]],
|
economic_code: fieldControl.economic_code(this.initialValues?.economic_code || ''),
|
||||||
guild_id: [this.initialValues?.guild?.id || '', [Validators.required]],
|
fiscal_code: fieldControl.fiscal_code(this.initialValues?.fiscal_code || ''),
|
||||||
|
partner_token: fieldControl.partner_token(this.initialValues?.partner_token || ''),
|
||||||
|
guild_id: fieldControl.guild_id(this.initialValues?.guild?.id || ''),
|
||||||
license_starts_at: [''],
|
license_starts_at: [''],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -46,7 +57,7 @@ export class ConsumerBusinessActivitiesFormComponent extends AbstractForm<
|
|||||||
'license_starts_at',
|
'license_starts_at',
|
||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
nonNullable: true,
|
nonNullable: true,
|
||||||
validators: [Validators.required],
|
validators: fieldControl.license_starts_at('')[1],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,14 @@
|
|||||||
(onRefresh)="refresh()"
|
(onRefresh)="refresh()"
|
||||||
>
|
>
|
||||||
</app-page-data-list>
|
</app-page-data-list>
|
||||||
|
<partner-consumer-businessActivities-create-wrapper
|
||||||
|
[(visible)]="visibleCreateForm"
|
||||||
|
[consumerId]="consumerId"
|
||||||
|
(onSubmit)="refresh()"
|
||||||
|
/>
|
||||||
<partner-consumer-businessActivities-form
|
<partner-consumer-businessActivities-form
|
||||||
[(visible)]="visibleForm"
|
[(visible)]="visibleForm"
|
||||||
[editMode]="editMode()"
|
[editMode]="true"
|
||||||
[consumerId]="consumerId"
|
[consumerId]="consumerId"
|
||||||
[businessActivityId]="selectedItemForEdit()?.id || ''"
|
[businessActivityId]="selectedItemForEdit()?.id || ''"
|
||||||
[initialValues]="selectedItemForEdit() || undefined"
|
[initialValues]="selectedItemForEdit() || undefined"
|
||||||
|
|||||||
@@ -4,17 +4,22 @@ import {
|
|||||||
IColumn,
|
IColumn,
|
||||||
PageDataListComponent,
|
PageDataListComponent,
|
||||||
} from '@/shared/components/pageDataList/page-data-list.component';
|
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
import { Component, inject, Input } from '@angular/core';
|
import { Component, inject, Input, signal } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { partnerConsumerBusinessActivitiesNamedRoutes } from '../../constants/routes/businessActivities';
|
import { partnerConsumerBusinessActivitiesNamedRoutes } from '../../constants/routes/businessActivities';
|
||||||
import { IBusinessActivityResponse } from '../../models';
|
import { IBusinessActivityResponse } from '../../models';
|
||||||
import { PartnerConsumerBusinessActivitiesService } from '../../services/businessActivities.service';
|
import { PartnerConsumerBusinessActivitiesService } from '../../services/businessActivities.service';
|
||||||
|
import { ConsumerBusinessActivitiesCreateWrapperComponent } from './create-wrapper/create-wrapper.component';
|
||||||
import { ConsumerBusinessActivitiesFormDialogComponent } from './form-dialog.component';
|
import { ConsumerBusinessActivitiesFormDialogComponent } from './form-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-businessActivities-list',
|
selector: 'partner-consumer-businessActivities-list',
|
||||||
templateUrl: './list.component.html',
|
templateUrl: './list.component.html',
|
||||||
imports: [PageDataListComponent, ConsumerBusinessActivitiesFormDialogComponent],
|
imports: [
|
||||||
|
PageDataListComponent,
|
||||||
|
ConsumerBusinessActivitiesFormDialogComponent,
|
||||||
|
ConsumerBusinessActivitiesCreateWrapperComponent,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerBusinessActivitiesComponent extends AbstractList<IBusinessActivityResponse> {
|
export class ConsumerBusinessActivitiesComponent extends AbstractList<IBusinessActivityResponse> {
|
||||||
@Input({ required: true }) consumerId!: string;
|
@Input({ required: true }) consumerId!: string;
|
||||||
@@ -50,6 +55,7 @@ export class ConsumerBusinessActivitiesComponent extends AbstractList<IBusinessA
|
|||||||
|
|
||||||
private readonly service = inject(PartnerConsumerBusinessActivitiesService);
|
private readonly service = inject(PartnerConsumerBusinessActivitiesService);
|
||||||
private readonly router = inject(Router);
|
private readonly router = inject(Router);
|
||||||
|
visibleCreateForm = signal(false);
|
||||||
|
|
||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
this.columns = this.header;
|
this.columns = this.header;
|
||||||
@@ -59,6 +65,10 @@ export class ConsumerBusinessActivitiesComponent extends AbstractList<IBusinessA
|
|||||||
return this.service.getAll(this.consumerId);
|
return this.service.getAll(this.consumerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override openAddForm() {
|
||||||
|
this.visibleCreateForm.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
toSinglePage(item: IBusinessActivityResponse) {
|
toSinglePage(item: IBusinessActivityResponse) {
|
||||||
this.router.navigateByUrl(
|
this.router.navigateByUrl(
|
||||||
partnerConsumerBusinessActivitiesNamedRoutes.businessActivity.meta.pagePath!(
|
partnerConsumerBusinessActivitiesNamedRoutes.businessActivity.meta.pagePath!(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
header="شارژ کاربر"
|
header="شارژ کاربر"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -10,4 +10,4 @@
|
|||||||
<app-input label="تعداد شارژ کاربران" [control]="form.controls.quantity" type="number" [min]="1" />
|
<app-input label="تعداد شارژ کاربران" [control]="form.controls.quantity" type="number" [min]="1" />
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -3,14 +3,19 @@ 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 { 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';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IPartnerChargeAccountRequest } from '../../models';
|
import { IPartnerChargeAccountRequest } from '../../models';
|
||||||
import { PartnerChargeAccountService } from '../../services/chargeAccount.service';
|
import { PartnerChargeAccountService } from '../../services/chargeAccount.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-charge-account-form-dialog',
|
selector: 'partner-charge-account-form-dialog',
|
||||||
templateUrl: './charge-account-form-dialog.component.html',
|
templateUrl: './charge-account-form-dialog.component.html',
|
||||||
imports: [Dialog, ReactiveFormsModule, InputComponent, FormFooterActionsComponent],
|
imports: [
|
||||||
|
SharedDialogComponent,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
InputComponent,
|
||||||
|
FormFooterActionsComponent,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class PartnerChargeAccountFormDialogComponent extends AbstractFormDialog<
|
export class PartnerChargeAccountFormDialogComponent extends AbstractFormDialog<
|
||||||
IPartnerChargeAccountRequest,
|
IPartnerChargeAccountRequest,
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<shared-dialog
|
||||||
|
header="ایجاد فروشگاه"
|
||||||
|
[(visible)]="visible"
|
||||||
|
[modal]="true"
|
||||||
|
[style]="{ width: '400px' }"
|
||||||
|
[closable]="true"
|
||||||
|
(onHide)="close()"
|
||||||
|
>
|
||||||
|
<p-stepper [value]="activeStep()" [linear]="true">
|
||||||
|
<p-step-list>
|
||||||
|
<p-step [value]="1">فروشگاه</p-step>
|
||||||
|
<p-step [value]="2" [disabled]="!complex()">پایانهی روشگاهی</p-step>
|
||||||
|
</p-step-list>
|
||||||
|
</p-stepper>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
@switch (activeStep()) {
|
||||||
|
@case (1) {
|
||||||
|
<partner-consumer-complex-form-content
|
||||||
|
[consumerId]="consumerId"
|
||||||
|
[businessActivityId]="businessActivityId"
|
||||||
|
(onSubmit)="onComplexSubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
@case (2) {
|
||||||
|
<partner-consumer-pos-form-content
|
||||||
|
[consumerId]="consumerId"
|
||||||
|
[businessActivityId]="businessActivityId"
|
||||||
|
[complexId]="complex()?.id || ''"
|
||||||
|
(onSubmit)="onPosSubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</shared-dialog>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
import { Component, effect, EventEmitter, Input, Output, signal } from '@angular/core';
|
||||||
|
import { Step, StepList, Stepper } from 'primeng/stepper';
|
||||||
|
import { IComplexResponse, IPosResponse } from '../../../models';
|
||||||
|
import { ConsumerPosFormContentComponent } from '../../poses/form.component';
|
||||||
|
import { ConsumerComplexFormContentComponent } from '../form.component';
|
||||||
|
|
||||||
|
export interface ICreateComplexStepperResult {
|
||||||
|
complex: IComplexResponse;
|
||||||
|
pos: IPosResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'partner-consumer-complexes-create-wrapper',
|
||||||
|
templateUrl: './create-wrapper.component.html',
|
||||||
|
imports: [
|
||||||
|
SharedDialogComponent,
|
||||||
|
Stepper,
|
||||||
|
StepList,
|
||||||
|
Step,
|
||||||
|
ConsumerComplexFormContentComponent,
|
||||||
|
ConsumerPosFormContentComponent,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class ConsumerComplexesCreateWrapperComponent extends AbstractDialog {
|
||||||
|
@Input({ required: true }) consumerId!: string;
|
||||||
|
@Input({ required: true }) businessActivityId!: string;
|
||||||
|
@Output() onSubmit = new EventEmitter<ICreateComplexStepperResult>();
|
||||||
|
|
||||||
|
activeStep = signal(1);
|
||||||
|
complex = signal<IComplexResponse | null>(null);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
effect(() => {
|
||||||
|
if (this.visible) {
|
||||||
|
this.resetWizard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onComplexSubmit(response: IComplexResponse) {
|
||||||
|
this.complex.set(response);
|
||||||
|
this.activeStep.set(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
onPosSubmit(response: IPosResponse) {
|
||||||
|
const complex = this.complex();
|
||||||
|
if (!complex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onSubmit.emit({
|
||||||
|
complex,
|
||||||
|
pos: response,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
override close() {
|
||||||
|
this.resetWizard();
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetWizard() {
|
||||||
|
this.activeStep.set(1);
|
||||||
|
this.complex.set(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
[header]="preparedTitle"
|
[header]="preparedTitle"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -15,4 +15,4 @@
|
|||||||
(onSubmit)="onFormSubmit($event)"
|
(onSubmit)="onFormSubmit($event)"
|
||||||
(onClose)="close()"
|
(onClose)="close()"
|
||||||
/>
|
/>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IComplexResponse } from '../../models';
|
import { IComplexResponse } from '../../models';
|
||||||
import { ConsumerComplexFormContentComponent } from './form.component';
|
import { ConsumerComplexFormContentComponent } from './form.component';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-complex-form',
|
selector: 'partner-consumer-complex-form',
|
||||||
templateUrl: './form-dialog.component.html',
|
templateUrl: './form-dialog.component.html',
|
||||||
imports: [Dialog, ConsumerComplexFormContentComponent],
|
imports: [SharedDialogComponent, ConsumerComplexFormContentComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerComplexFormDialogComponent extends AbstractDialog {
|
export class ConsumerComplexFormDialogComponent extends AbstractDialog {
|
||||||
@Output() onSubmit = new EventEmitter<IComplexResponse>();
|
@Output() onSubmit = new EventEmitter<IComplexResponse>();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<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.name" name="name" />
|
<field-name [control]="form.controls.name" />
|
||||||
<app-input label="کد شعبه" [control]="form.controls.branch_code" name="branch_code" />
|
<field-branch-code [control]="form.controls.branch_code" />
|
||||||
<app-input label="آدرس" [control]="form.controls.address" name="address" />
|
<field-address [control]="form.controls.address" />
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,16 +1,27 @@
|
|||||||
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
||||||
import { AbstractForm } from '@/shared/abstractClasses';
|
import { AbstractForm } from '@/shared/abstractClasses';
|
||||||
import { InputComponent } from '@/shared/components';
|
import {
|
||||||
|
NameComponent,
|
||||||
|
AddressComponent,
|
||||||
|
BranchCodeComponent,
|
||||||
|
} from '@/shared/components';
|
||||||
|
import { fieldControl } from '@/shared/constants/fields';
|
||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
import { Component, inject, Input } from '@angular/core';
|
import { Component, inject, Input } from '@angular/core';
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { IComplexRequest, IComplexResponse } from '../../models';
|
import { IComplexRequest, IComplexResponse } from '../../models';
|
||||||
import { PartnerComplexesService } from '../../services/complexes.service';
|
import { PartnerComplexesService } from '../../services/complexes.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-complex-form-content',
|
selector: 'partner-consumer-complex-form-content',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [ReactiveFormsModule, InputComponent, FormFooterActionsComponent],
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
NameComponent,
|
||||||
|
BranchCodeComponent,
|
||||||
|
AddressComponent,
|
||||||
|
FormFooterActionsComponent,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerComplexFormContentComponent extends AbstractForm<
|
export class ConsumerComplexFormContentComponent extends AbstractForm<
|
||||||
IComplexRequest,
|
IComplexRequest,
|
||||||
@@ -24,9 +35,9 @@ export class ConsumerComplexFormContentComponent extends AbstractForm<
|
|||||||
|
|
||||||
initForm = () => {
|
initForm = () => {
|
||||||
return this.fb.group({
|
return this.fb.group({
|
||||||
name: [this.initialValues?.name || '', [Validators.required]],
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
branch_code: [this.initialValues?.branch_code || ''],
|
branch_code: fieldControl.branch_code(this.initialValues?.branch_code || ''),
|
||||||
address: [this.initialValues?.address || '', [Validators.required]],
|
address: fieldControl.address(this.initialValues?.address || ''),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,15 @@
|
|||||||
(onRefresh)="refresh()"
|
(onRefresh)="refresh()"
|
||||||
>
|
>
|
||||||
</app-page-data-list>
|
</app-page-data-list>
|
||||||
|
<partner-consumer-complexes-create-wrapper
|
||||||
|
[(visible)]="visibleCreateForm"
|
||||||
|
[consumerId]="consumerId"
|
||||||
|
[businessActivityId]="businessId"
|
||||||
|
(onSubmit)="refresh()"
|
||||||
|
/>
|
||||||
<partner-consumer-complex-form
|
<partner-consumer-complex-form
|
||||||
[(visible)]="visibleForm"
|
[(visible)]="visibleForm"
|
||||||
[editMode]="editMode()"
|
[editMode]="true"
|
||||||
[consumerId]="consumerId"
|
[consumerId]="consumerId"
|
||||||
[businessActivityId]="businessId"
|
[businessActivityId]="businessId"
|
||||||
[complexId]="selectedItemForEdit()?.id || ''"
|
[complexId]="selectedItemForEdit()?.id || ''"
|
||||||
|
|||||||
@@ -4,17 +4,22 @@ import {
|
|||||||
IColumn,
|
IColumn,
|
||||||
PageDataListComponent,
|
PageDataListComponent,
|
||||||
} from '@/shared/components/pageDataList/page-data-list.component';
|
} from '@/shared/components/pageDataList/page-data-list.component';
|
||||||
import { Component, inject, Input } from '@angular/core';
|
import { Component, inject, Input, signal } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { partnerConsumerComplexesNamedRoutes } from '../../constants/routes/complexes';
|
import { partnerConsumerComplexesNamedRoutes } from '../../constants/routes/complexes';
|
||||||
import { IComplexResponse } from '../../models';
|
import { IComplexResponse } from '../../models';
|
||||||
import { PartnerComplexesService } from '../../services/complexes.service';
|
import { PartnerComplexesService } from '../../services/complexes.service';
|
||||||
|
import { ConsumerComplexesCreateWrapperComponent } from './create-wrapper/create-wrapper.component';
|
||||||
import { ConsumerComplexFormDialogComponent } from './form-dialog.component';
|
import { ConsumerComplexFormDialogComponent } from './form-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-complexes-list',
|
selector: 'partner-consumer-complexes-list',
|
||||||
templateUrl: './list.component.html',
|
templateUrl: './list.component.html',
|
||||||
imports: [PageDataListComponent, ConsumerComplexFormDialogComponent],
|
imports: [
|
||||||
|
PageDataListComponent,
|
||||||
|
ConsumerComplexFormDialogComponent,
|
||||||
|
ConsumerComplexesCreateWrapperComponent,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerComplexesComponent extends AbstractList<IComplexResponse> {
|
export class ConsumerComplexesComponent extends AbstractList<IComplexResponse> {
|
||||||
@Input() consumerId!: string;
|
@Input() consumerId!: string;
|
||||||
@@ -23,6 +28,8 @@ export class ConsumerComplexesComponent extends AbstractList<IComplexResponse> {
|
|||||||
@Input() header: IColumn[] = [
|
@Input() header: IColumn[] = [
|
||||||
{ field: 'id', header: 'شناسه', type: 'id' },
|
{ field: 'id', header: 'شناسه', type: 'id' },
|
||||||
{ field: 'name', header: 'عنوان' },
|
{ field: 'name', header: 'عنوان' },
|
||||||
|
{ field: 'branch_code', header: 'کد شعبه' },
|
||||||
|
{ field: 'pos_count', header: 'تعداد پایانهها' },
|
||||||
{
|
{
|
||||||
field: 'created_at',
|
field: 'created_at',
|
||||||
header: 'تاریخ ایجاد',
|
header: 'تاریخ ایجاد',
|
||||||
@@ -32,6 +39,7 @@ export class ConsumerComplexesComponent extends AbstractList<IComplexResponse> {
|
|||||||
|
|
||||||
private readonly service = inject(PartnerComplexesService);
|
private readonly service = inject(PartnerComplexesService);
|
||||||
private readonly router = inject(Router);
|
private readonly router = inject(Router);
|
||||||
|
visibleCreateForm = signal(false);
|
||||||
|
|
||||||
override setColumns(): void {
|
override setColumns(): void {
|
||||||
this.columns = this.header;
|
this.columns = this.header;
|
||||||
@@ -41,6 +49,10 @@ export class ConsumerComplexesComponent extends AbstractList<IComplexResponse> {
|
|||||||
return this.service.getAll(this.consumerId, this.businessId);
|
return this.service.getAll(this.consumerId, this.businessId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override openAddForm() {
|
||||||
|
this.visibleCreateForm.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
toSinglePage(item: IComplexResponse) {
|
toSinglePage(item: IComplexResponse) {
|
||||||
this.router.navigateByUrl(
|
this.router.navigateByUrl(
|
||||||
partnerConsumerComplexesNamedRoutes.complex.meta.pagePath!(
|
partnerConsumerComplexesNamedRoutes.complex.meta.pagePath!(
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<shared-dialog
|
||||||
|
header="ایجاد مشتری جدید"
|
||||||
|
[(visible)]="visible"
|
||||||
|
[modal]="true"
|
||||||
|
[style]="{ width: '640px' }"
|
||||||
|
[closable]="true"
|
||||||
|
(onHide)="close()"
|
||||||
|
>
|
||||||
|
<p-stepper [value]="activeStep()" [linear]="true">
|
||||||
|
<p-step-list>
|
||||||
|
<p-step [value]="1">اطلاعات اولیه</p-step>
|
||||||
|
<p-step [value]="2" [disabled]="!consumer()">فعالیت اقتصادی</p-step>
|
||||||
|
<p-step [value]="3" [disabled]="!businessActivity()">فروشگاه</p-step>
|
||||||
|
<p-step [value]="4" [disabled]="!complex()">پایانهی فروشگاهی</p-step>
|
||||||
|
</p-step-list>
|
||||||
|
</p-stepper>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
@switch (activeStep()) {
|
||||||
|
@case (1) {
|
||||||
|
<partner-consumer-form-content (onSubmit)="onConsumerSubmit($event)" (onClose)="close()" />
|
||||||
|
}
|
||||||
|
@case (2) {
|
||||||
|
<partner-consumer-businessActivities-form-content
|
||||||
|
[consumerId]="consumer()?.id || ''"
|
||||||
|
(onSubmit)="onBusinessActivitySubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
@case (3) {
|
||||||
|
<partner-consumer-complex-form-content
|
||||||
|
[consumerId]="consumer()?.id || ''"
|
||||||
|
[businessActivityId]="businessActivity()?.id || ''"
|
||||||
|
(onSubmit)="onComplexSubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
@case (4) {
|
||||||
|
<partner-consumer-pos-form-content
|
||||||
|
[consumerId]="consumer()?.id || ''"
|
||||||
|
[businessActivityId]="businessActivity()?.id || ''"
|
||||||
|
[complexId]="complex()?.id || ''"
|
||||||
|
(onSubmit)="onPosSubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</shared-dialog>
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
|
import { Component, effect, EventEmitter, Output, signal } from '@angular/core';
|
||||||
|
import { Step, StepList, Stepper } from 'primeng/stepper';
|
||||||
|
import {
|
||||||
|
IBusinessActivityResponse,
|
||||||
|
IComplexResponse,
|
||||||
|
IPartnerConsumerResponse,
|
||||||
|
IPosResponse,
|
||||||
|
} from '../../models';
|
||||||
|
import { ConsumerBusinessActivitiesFormComponent } from '../businessActivities/form.component';
|
||||||
|
import { ConsumerComplexFormContentComponent } from '../complexes/form.component';
|
||||||
|
import { ConsumerUserFormContentComponent } from '../form.component';
|
||||||
|
import { ConsumerPosFormContentComponent } from '../poses/form.component';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
|
export interface ICreateConsumerStepperResult {
|
||||||
|
consumer: IPartnerConsumerResponse;
|
||||||
|
businessActivity: IBusinessActivityResponse;
|
||||||
|
complex: IComplexResponse;
|
||||||
|
pos: IPosResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'partner-create-consumer-wrapper',
|
||||||
|
templateUrl: './create-consumer-wrapper.component.html',
|
||||||
|
imports: [
|
||||||
|
Stepper,
|
||||||
|
StepList,
|
||||||
|
Step,
|
||||||
|
ConsumerUserFormContentComponent,
|
||||||
|
ConsumerBusinessActivitiesFormComponent,
|
||||||
|
ConsumerComplexFormContentComponent,
|
||||||
|
ConsumerPosFormContentComponent,
|
||||||
|
SharedDialogComponent,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class CreateConsumerWrapperComponent extends AbstractDialog {
|
||||||
|
@Output() onSubmit = new EventEmitter<ICreateConsumerStepperResult>();
|
||||||
|
|
||||||
|
activeStep = signal(1);
|
||||||
|
consumer = signal<IPartnerConsumerResponse | null>(null);
|
||||||
|
businessActivity = signal<IBusinessActivityResponse | null>(null);
|
||||||
|
complex = signal<IComplexResponse | null>(null);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
effect(() => {
|
||||||
|
if (this.visible) {
|
||||||
|
this.resetWizard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onConsumerSubmit(response: IPartnerConsumerResponse) {
|
||||||
|
this.consumer.set(response);
|
||||||
|
this.activeStep.set(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBusinessActivitySubmit(response: IBusinessActivityResponse) {
|
||||||
|
this.businessActivity.set(response);
|
||||||
|
this.activeStep.set(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
onComplexSubmit(response: IComplexResponse) {
|
||||||
|
this.complex.set(response);
|
||||||
|
this.activeStep.set(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
onPosSubmit(response: IPosResponse) {
|
||||||
|
const consumer = this.consumer();
|
||||||
|
const businessActivity = this.businessActivity();
|
||||||
|
const complex = this.complex();
|
||||||
|
|
||||||
|
if (!consumer || !businessActivity || !complex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onSubmit.emit({
|
||||||
|
consumer,
|
||||||
|
businessActivity,
|
||||||
|
complex,
|
||||||
|
pos: response,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
override close() {
|
||||||
|
this.resetWizard();
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetWizard() {
|
||||||
|
this.activeStep.set(1);
|
||||||
|
this.consumer.set(null);
|
||||||
|
this.businessActivity.set(null);
|
||||||
|
this.complex.set(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<shared-dialog
|
||||||
|
[header]="preparedTitle"
|
||||||
|
[(visible)]="visible"
|
||||||
|
[modal]="true"
|
||||||
|
[style]="{ width: '500px' }"
|
||||||
|
[closable]="true"
|
||||||
|
(onHide)="close()"
|
||||||
|
>
|
||||||
|
<partner-consumer-form-content
|
||||||
|
[consumerId]="consumerId"
|
||||||
|
[initialValues]="initialValues"
|
||||||
|
[editMode]="editMode"
|
||||||
|
(onSubmit)="onFormSubmit($event)"
|
||||||
|
(onClose)="close()"
|
||||||
|
/>
|
||||||
|
</shared-dialog>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
import { IPartnerConsumerResponse } from '../models';
|
||||||
|
import { ConsumerUserFormContentComponent } from './form.component';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'partner-consumer-form',
|
||||||
|
templateUrl: './form-dialog.component.html',
|
||||||
|
imports: [SharedDialogComponent, ConsumerUserFormContentComponent],
|
||||||
|
})
|
||||||
|
export class ConsumerUserFormDialogComponent extends AbstractDialog {
|
||||||
|
@Output() onSubmit = new EventEmitter<IPartnerConsumerResponse>();
|
||||||
|
@Input() initialValues?: IPartnerConsumerResponse;
|
||||||
|
@Input() editMode?: boolean;
|
||||||
|
|
||||||
|
@Input() consumerId?: string;
|
||||||
|
|
||||||
|
get preparedTitle() {
|
||||||
|
return `${this.editMode ? 'ویرایش' : 'ایجاد'} مشتری`;
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormSubmit(response: IPartnerConsumerResponse) {
|
||||||
|
this.onSubmit.emit(response);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +1,32 @@
|
|||||||
<p-dialog
|
@if (!editMode) {
|
||||||
[header]="preparedTitle()"
|
<p-selectbutton
|
||||||
[(visible)]="visible"
|
[options]="consumerTypes"
|
||||||
[modal]="true"
|
[(ngModel)]="selectedType"
|
||||||
[style]="{ width: '500px' }"
|
optionValue="value"
|
||||||
[closable]="true"
|
optionLabel="name"
|
||||||
(onHide)="close()"
|
(onChange)="changeType($event.value)"
|
||||||
>
|
></p-selectbutton>
|
||||||
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4">
|
}
|
||||||
<app-input label="نام" [control]="form.controls.first_name" name="first_name" />
|
<form [formGroup]="form" (submit)="submit()" class="flex flex-col gap-4 mt-4">
|
||||||
<app-input label="نام خانوادگی" [control]="form.controls.last_name" name="last_name" />
|
@if (selectedType() === "INDIVIDUAL" && form.controls.individual) {
|
||||||
<app-input label="موبایل" [control]="form.controls.mobile_number" name="mobile_number" type="mobile" />
|
<field-first-name [control]="form.controls.individual.controls.first_name" />
|
||||||
<app-input label="کد ملی" [control]="form.controls.national_code" name="national_code" type="nationalId" />
|
<field-last-name [control]="form.controls.individual.controls.last_name" />
|
||||||
|
<field-mobile-number [control]="form.controls.individual.controls.mobile_number" />
|
||||||
|
<field-national-code [control]="form.controls.individual.controls.national_code" />
|
||||||
|
} @else if (form.controls.legal) {
|
||||||
|
<field-legal-name [control]="form.controls.legal.controls.name" />
|
||||||
|
<field-registration-code [control]="form.controls.legal.controls.registration_code" />
|
||||||
|
}
|
||||||
|
|
||||||
@if (!editMode) {
|
@if (!editMode) {
|
||||||
<p-divider align="center"> اطلاعات ورود </p-divider>
|
<p-divider align="center"> اطلاعات ورود </p-divider>
|
||||||
<!-- @ts-ignore -->
|
<!-- @ts-ignore -->
|
||||||
<app-input label="نام کاربری" [control]="form.controls.username" name="username" [isLtrInput]="true" />
|
<field-username [control]="form.controls.username" />
|
||||||
<shared-password-input
|
<shared-password-input
|
||||||
[passwordControl]="form.controls.password"
|
[passwordControl]="form.controls.password"
|
||||||
[confirmPasswordControl]="form.controls.confirmPassword"
|
[confirmPasswordControl]="form.controls.confirmPassword"
|
||||||
/>
|
/>
|
||||||
<p-divider align="center"> اطلاعات لایسنس </p-divider>
|
|
||||||
<uikit-datepicker
|
|
||||||
label="تاریخ شروع لایسنس"
|
|
||||||
[control]="form.controls.license_starts_at"
|
|
||||||
name="license_starts_at"
|
|
||||||
hint="مدت زمان لایسنسها ۱ ساله هستند."
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
|
||||||
|
|||||||
@@ -1,55 +1,88 @@
|
|||||||
import { mobileValidator, MustMatch } from '@/core/validators';
|
import { MustMatch } from '@/core/validators';
|
||||||
import { nationalIdValidator } from '@/core/validators/national-id.validator';
|
import { AbstractForm } from '@/shared/abstractClasses';
|
||||||
import { AbstractFormDialog } from '@/shared/abstractClasses';
|
import { fieldControl } from '@/shared/constants/fields';
|
||||||
import { InputComponent, SharedPasswordInputComponent } from '@/shared/components';
|
import {
|
||||||
|
FirstNameComponent,
|
||||||
|
LastNameComponent,
|
||||||
|
LegalNameComponent,
|
||||||
|
MobileNumberComponent,
|
||||||
|
NationalCodeComponent,
|
||||||
|
RegistrationCodeComponent,
|
||||||
|
SharedPasswordInputComponent,
|
||||||
|
UsernameComponent,
|
||||||
|
} 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 { Component, inject, Input, signal } from '@angular/core';
|
||||||
import { nowJalali } from '@/utils';
|
import { FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { Component, computed, inject, Input } from '@angular/core';
|
|
||||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { Divider } from 'primeng/divider';
|
import { Divider } from 'primeng/divider';
|
||||||
import { IConsumerRequest, IConsumerResponse } from '../models';
|
import { SelectButton } from 'primeng/selectbutton';
|
||||||
|
import { IPartnerConsumerRequest, IPartnerConsumerResponse } from '../models';
|
||||||
import { ConsumersService } from '../services/main.service';
|
import { ConsumersService } from '../services/main.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-form',
|
selector: 'partner-consumer-form-content',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [
|
imports: [
|
||||||
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
Dialog,
|
FirstNameComponent,
|
||||||
InputComponent,
|
LastNameComponent,
|
||||||
|
MobileNumberComponent,
|
||||||
|
NationalCodeComponent,
|
||||||
|
LegalNameComponent,
|
||||||
|
RegistrationCodeComponent,
|
||||||
|
UsernameComponent,
|
||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
Divider,
|
Divider,
|
||||||
UikitFlatpickrJalaliComponent,
|
|
||||||
SharedPasswordInputComponent,
|
SharedPasswordInputComponent,
|
||||||
|
SelectButton,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerUserFormComponent extends AbstractFormDialog<
|
export class ConsumerUserFormContentComponent extends AbstractForm<
|
||||||
IConsumerRequest,
|
IPartnerConsumerRequest,
|
||||||
IConsumerResponse
|
IPartnerConsumerResponse
|
||||||
> {
|
> {
|
||||||
@Input() consumerId?: string;
|
@Input() consumerId?: string;
|
||||||
private service = inject(ConsumersService);
|
private service = inject(ConsumersService);
|
||||||
|
|
||||||
preparedTitle = computed(() => `${this.editMode ? 'ویرایش' : 'ایجاد'} مشتری`);
|
consumerTypes = [
|
||||||
|
{
|
||||||
|
value: 'INDIVIDUAL',
|
||||||
|
name: 'حقیقی',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'LEGAL',
|
||||||
|
name: 'حقوقی',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedType = signal<string>(this.initialValues?.type || this.consumerTypes[0].value);
|
||||||
|
|
||||||
initForm = () => {
|
initForm = () => {
|
||||||
|
this.selectedType.set(this.initialValues?.type || this.consumerTypes[0].value);
|
||||||
|
const legal = this.fb.group({
|
||||||
|
name: fieldControl.legal_name(this.initialValues?.legal?.name || ''),
|
||||||
|
registration_code: fieldControl.registration_code(
|
||||||
|
this.initialValues?.legal?.registration_code || '',
|
||||||
|
),
|
||||||
|
});
|
||||||
|
const individual = this.fb.group({
|
||||||
|
first_name: fieldControl.first_name(this.initialValues?.individual?.first_name || ''),
|
||||||
|
last_name: fieldControl.last_name(this.initialValues?.individual?.last_name || ''),
|
||||||
|
mobile_number: fieldControl.mobile_number(
|
||||||
|
this.initialValues?.individual?.mobile_number || '',
|
||||||
|
),
|
||||||
|
national_code: fieldControl.national_code(
|
||||||
|
this.initialValues?.individual?.national_code || '',
|
||||||
|
),
|
||||||
|
});
|
||||||
const form = this.fb.group({
|
const form = this.fb.group({
|
||||||
first_name: [this.initialValues?.first_name || '', [Validators.required]],
|
type: [this.initialValues?.type || this.consumerTypes[0].value, [Validators.required]],
|
||||||
last_name: [this.initialValues?.last_name || '', [Validators.required]],
|
legal,
|
||||||
mobile_number: [
|
individual,
|
||||||
this.initialValues?.mobile_number || '',
|
|
||||||
[Validators.required, mobileValidator()],
|
|
||||||
],
|
|
||||||
national_code: [
|
|
||||||
this.initialValues?.national_code || '',
|
|
||||||
[Validators.required, nationalIdValidator()],
|
|
||||||
],
|
|
||||||
username: [''],
|
username: [''],
|
||||||
password: [''],
|
password: [''],
|
||||||
confirmPassword: [''],
|
confirmPassword: [''],
|
||||||
license_starts_at: [nowJalali(), [Validators.required]],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.editMode) {
|
if (this.editMode) {
|
||||||
@@ -59,15 +92,13 @@ export class ConsumerUserFormComponent extends AbstractFormDialog<
|
|||||||
form.removeControl('password');
|
form.removeControl('password');
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
form.removeControl('confirmPassword');
|
form.removeControl('confirmPassword');
|
||||||
// @ts-ignore
|
|
||||||
form.removeControl('license_starts_at');
|
|
||||||
form.removeValidators([MustMatch('password', 'confirmPassword')]);
|
form.removeValidators([MustMatch('password', 'confirmPassword')]);
|
||||||
} else {
|
} else {
|
||||||
form.addControl(
|
form.addControl(
|
||||||
'username',
|
'username',
|
||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
nonNullable: true,
|
nonNullable: true,
|
||||||
validators: [Validators.required],
|
validators: fieldControl.username('')[1],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
form.addControl(
|
form.addControl(
|
||||||
@@ -84,23 +115,43 @@ export class ConsumerUserFormComponent extends AbstractFormDialog<
|
|||||||
validators: [Validators.required],
|
validators: [Validators.required],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
form.addControl(
|
|
||||||
'license_starts_at',
|
|
||||||
this.fb.control<string>(nowJalali(), {
|
|
||||||
nonNullable: true,
|
|
||||||
validators: [Validators.required],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
form.addValidators([MustMatch('password', 'confirmPassword')]);
|
form.addValidators([MustMatch('password', 'confirmPassword')]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (form.controls.type.value === 'LEGAL') {
|
||||||
|
// @ts-ignore
|
||||||
|
form.addControl('legal', legal);
|
||||||
|
// @ts-ignore
|
||||||
|
form.removeControl('individual');
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
form.addControl('individual', individual);
|
||||||
|
// @ts-ignore
|
||||||
|
form.removeControl('legal');
|
||||||
|
}
|
||||||
|
|
||||||
|
form.controls.type.valueChanges.subscribe((type) => {
|
||||||
|
if (type === 'LEGAL') {
|
||||||
|
// @ts-ignore
|
||||||
|
form.addControl('legal', legal);
|
||||||
|
// @ts-ignore
|
||||||
|
form.removeControl('individual');
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
form.addControl('individual', individual);
|
||||||
|
// @ts-ignore
|
||||||
|
form.removeControl('legal');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return form;
|
return form;
|
||||||
};
|
};
|
||||||
|
|
||||||
form = this.initForm();
|
form = this.initForm();
|
||||||
|
|
||||||
override ngOnChanges() {
|
override ngOnChanges() {
|
||||||
this.form.patchValue(this.initialValues || {});
|
this.form.patchValue((this.initialValues as any) || {});
|
||||||
if (this.editMode && !this.consumerId) {
|
if (this.editMode && !this.consumerId) {
|
||||||
throw 'missing some arguments';
|
throw 'missing some arguments';
|
||||||
}
|
}
|
||||||
@@ -108,7 +159,7 @@ export class ConsumerUserFormComponent extends AbstractFormDialog<
|
|||||||
this.form = this.initForm();
|
this.form = this.initForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
override submitForm(payload: IConsumerRequest) {
|
override submitForm(payload: IPartnerConsumerRequest) {
|
||||||
if (this.editMode) {
|
if (this.editMode) {
|
||||||
return this.service.update(this.consumerId!, payload);
|
return this.service.update(this.consumerId!, payload);
|
||||||
}
|
}
|
||||||
@@ -116,4 +167,8 @@ export class ConsumerUserFormComponent extends AbstractFormDialog<
|
|||||||
const { confirmPassword, ...rest } = payload;
|
const { confirmPassword, ...rest } = payload;
|
||||||
return this.service.create(rest);
|
return this.service.create(rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeType(newType: string) {
|
||||||
|
this.form.controls.type.setValue(newType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
[header]="preparedTitle()"
|
[header]="preparedTitle()"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -16,4 +16,4 @@
|
|||||||
<!-- <uikit-datepicker label="تاریخ انقضای لایسنس" [control]="form.controls.expires_at" name="expires_at" /> -->
|
<!-- <uikit-datepicker label="تاریخ انقضای لایسنس" [control]="form.controls.expires_at" name="expires_at" /> -->
|
||||||
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
<app-form-footer-actions [submitLabel]="'ذخیره'" [loading]="submitLoading()" (onCancel)="close()" />
|
||||||
</form>
|
</form>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -3,14 +3,19 @@ import { FormFooterActionsComponent } from '@/shared/components/formFooterAction
|
|||||||
import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
import { UikitFlatpickrJalaliComponent } from '@/uikit';
|
||||||
import { Component, computed, inject, Input } from '@angular/core';
|
import { Component, computed, inject, Input } from '@angular/core';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { ILicenseRequest, ILicenseResponse } from '../../models';
|
import { ILicenseRequest, ILicenseResponse } from '../../models';
|
||||||
import { LicensesService } from '../../services/licenses.service';
|
import { LicensesService } from '../../services/licenses.service';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-license-form',
|
selector: 'partner-consumer-license-form',
|
||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [ReactiveFormsModule, Dialog, FormFooterActionsComponent, UikitFlatpickrJalaliComponent],
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
SharedDialogComponent,
|
||||||
|
FormFooterActionsComponent,
|
||||||
|
UikitFlatpickrJalaliComponent,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class ConsumerLicenseFormComponent extends AbstractFormDialog<
|
export class ConsumerLicenseFormComponent extends AbstractFormDialog<
|
||||||
ILicenseRequest,
|
ILicenseRequest,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<p-dialog
|
<shared-dialog
|
||||||
[header]="preparedTitle"
|
[header]="preparedTitle"
|
||||||
[(visible)]="visible"
|
[(visible)]="visible"
|
||||||
[modal]="true"
|
[modal]="true"
|
||||||
@@ -16,4 +16,4 @@
|
|||||||
(onSubmit)="onFormSubmit($event)"
|
(onSubmit)="onFormSubmit($event)"
|
||||||
(onClose)="close()"
|
(onClose)="close()"
|
||||||
/>
|
/>
|
||||||
</p-dialog>
|
</shared-dialog>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
import { AbstractDialog } from '@/shared/abstractClasses/abstract-dialog';
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { Dialog } from 'primeng/dialog';
|
|
||||||
import { IPosResponse } from '../../models';
|
import { IPosResponse } from '../../models';
|
||||||
import { ConsumerPosFormContentComponent } from './form.component';
|
import { ConsumerPosFormContentComponent } from './form.component';
|
||||||
|
import { SharedDialogComponent } from '@/shared/components/dialog/dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'partner-consumer-pos-form',
|
selector: 'partner-consumer-pos-form',
|
||||||
templateUrl: './form-dialog.component.html',
|
templateUrl: './form-dialog.component.html',
|
||||||
imports: [Dialog, ConsumerPosFormContentComponent],
|
imports: [SharedDialogComponent, ConsumerPosFormContentComponent],
|
||||||
})
|
})
|
||||||
export class ConsumerPosFormDialogComponent extends AbstractDialog {
|
export class ConsumerPosFormDialogComponent extends AbstractDialog {
|
||||||
@Output() onSubmit = new EventEmitter<IPosResponse>();
|
@Output() onSubmit = new EventEmitter<IPosResponse>();
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<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.name" name="name" />
|
<field-name [control]="form.controls.name" />
|
||||||
<app-enum-select [control]="form.controls.pos_type" type="posType" name="pos_type" />
|
<field-pos-type [control]="form.controls.pos_type" />
|
||||||
|
|
||||||
@if (form.controls.pos_type.value === "PSP") {
|
@if (form.controls.pos_type.value === "PSP") {
|
||||||
<app-input label="سریال دستگاه" [control]="form.controls.serial_number" name="serial_number" />
|
<field-serial-number [control]="form.controls.serial_number" />
|
||||||
<catalog-device-select [control]="form.controls.device_id" />
|
<field-device-id [control]="form.controls.device_id" />
|
||||||
<catalog-provider-select [control]="form.controls.provider_id" />
|
<field-provider-id [control]="form.controls.provider_id" />
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (!editMode) {
|
@if (!editMode) {
|
||||||
<p-divider align="center"> اطلاعات ورود </p-divider>
|
<p-divider align="center"> اطلاعات ورود </p-divider>
|
||||||
<app-input label="نام کاربری" [control]="form.controls.username" name="username" [isLtrInput]="true" />
|
<field-username [control]="form.controls.username" />
|
||||||
<shared-password-input
|
<shared-password-input
|
||||||
[passwordControl]="form.controls.password"
|
[passwordControl]="form.controls.password"
|
||||||
[confirmPasswordControl]="form.controls.confirmPassword"
|
[confirmPasswordControl]="form.controls.confirmPassword"
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
// import { CatalogRolesComponent } from '@/shared/catalog/roles';
|
||||||
import { MustMatch } from '@/core/validators';
|
import { MustMatch } from '@/core/validators';
|
||||||
import { AbstractForm } from '@/shared/abstractClasses';
|
import { AbstractForm } from '@/shared/abstractClasses';
|
||||||
import { EnumSelectComponent } from '@/shared/apiEnum/select.component';
|
import {
|
||||||
import { CatalogProviderSelectComponent } from '@/shared/catalog';
|
NameComponent,
|
||||||
import { CatalogDeviceSelectComponent } from '@/shared/catalog/devices';
|
SharedPasswordInputComponent,
|
||||||
import { InputComponent, SharedPasswordInputComponent } from '@/shared/components';
|
DeviceIdComponent,
|
||||||
|
ProviderIdComponent,
|
||||||
|
SerialNumberComponent,
|
||||||
|
PosTypeComponent,
|
||||||
|
UsernameComponent,
|
||||||
|
} from '@/shared/components';
|
||||||
|
import { fieldControl } from '@/shared/constants/fields';
|
||||||
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
import { FormFooterActionsComponent } from '@/shared/components/formFooterActions/form-footer-actions.component';
|
||||||
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,11 +23,13 @@ import { PartnerPosesService } from '../../services/poses.service';
|
|||||||
templateUrl: './form.component.html',
|
templateUrl: './form.component.html',
|
||||||
imports: [
|
imports: [
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
InputComponent,
|
NameComponent,
|
||||||
FormFooterActionsComponent,
|
FormFooterActionsComponent,
|
||||||
CatalogDeviceSelectComponent,
|
DeviceIdComponent,
|
||||||
CatalogProviderSelectComponent,
|
ProviderIdComponent,
|
||||||
EnumSelectComponent,
|
PosTypeComponent,
|
||||||
|
SerialNumberComponent,
|
||||||
|
UsernameComponent,
|
||||||
Divider,
|
Divider,
|
||||||
SharedPasswordInputComponent,
|
SharedPasswordInputComponent,
|
||||||
],
|
],
|
||||||
@@ -36,11 +44,11 @@ export class ConsumerPosFormContentComponent extends AbstractForm<IPosRequest, I
|
|||||||
|
|
||||||
initForm = () => {
|
initForm = () => {
|
||||||
const form = this.fb.group({
|
const form = this.fb.group({
|
||||||
name: [this.initialValues?.name || '', [Validators.required]],
|
name: fieldControl.name(this.initialValues?.name || ''),
|
||||||
pos_type: [this.initialValues?.pos_type || '', [Validators.required]],
|
pos_type: fieldControl.pos_type(this.initialValues?.pos_type || ''),
|
||||||
serial_number: [this.initialValues?.serial_number || ''],
|
serial_number: fieldControl.serial_number(this.initialValues?.serial_number || ''),
|
||||||
device_id: [this.initialValues?.device?.id || ''],
|
device_id: fieldControl.device_id(this.initialValues?.device?.id || ''),
|
||||||
provider_id: [this.initialValues?.provider?.id || ''],
|
provider_id: fieldControl.provider_id(this.initialValues?.provider?.id || ''),
|
||||||
username: [''],
|
username: [''],
|
||||||
password: [''],
|
password: [''],
|
||||||
confirmPassword: [''],
|
confirmPassword: [''],
|
||||||
@@ -81,13 +89,15 @@ export class ConsumerPosFormContentComponent extends AbstractForm<IPosRequest, I
|
|||||||
form.removeControl('confirmPassword');
|
form.removeControl('confirmPassword');
|
||||||
form.removeValidators([MustMatch('password', 'confirmPassword')]);
|
form.removeValidators([MustMatch('password', 'confirmPassword')]);
|
||||||
} else {
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
form.addControl(
|
form.addControl(
|
||||||
'username',
|
'username',
|
||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
nonNullable: true,
|
nonNullable: true,
|
||||||
validators: [Validators.required],
|
validators: fieldControl.username('')[1],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
// @ts-ignore
|
||||||
form.addControl(
|
form.addControl(
|
||||||
'password',
|
'password',
|
||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
@@ -95,6 +105,7 @@ export class ConsumerPosFormContentComponent extends AbstractForm<IPosRequest, I
|
|||||||
validators: [Validators.required],
|
validators: [Validators.required],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
// @ts-ignore
|
||||||
form.addControl(
|
form.addControl(
|
||||||
'confirmPassword',
|
'confirmPassword',
|
||||||
this.fb.control<string>('', {
|
this.fb.control<string>('', {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ export interface IBusinessActivityRawResponse {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
economic_code: string;
|
economic_code: string;
|
||||||
|
fiscal_code: string;
|
||||||
|
partner_token: string;
|
||||||
guild: ISummary;
|
guild: ISummary;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
license_info: LicenseInfo;
|
license_info: LicenseInfo;
|
||||||
@@ -13,9 +15,11 @@ export interface IBusinessActivityResponse extends IBusinessActivityRawResponse
|
|||||||
export interface IBusinessActivityRequest {
|
export interface IBusinessActivityRequest {
|
||||||
name: string;
|
name: string;
|
||||||
economic_code: string;
|
economic_code: string;
|
||||||
|
fiscal_code: string;
|
||||||
|
partner_token: string;
|
||||||
guild_id: string;
|
guild_id: string;
|
||||||
username?: string;
|
license_starts_at?: string;
|
||||||
password?: string;
|
expires_at?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LicenseInfo {
|
interface LicenseInfo {
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
export interface IPartnerChargeAccountRawResponse {
|
export interface IPartnerChargeAccountRawResponse {
|
||||||
id: string;
|
id: string;
|
||||||
|
credit_id: string;
|
||||||
|
license_activation_id: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
// tracking_code: string;
|
|
||||||
// activation_expires_at: string;
|
|
||||||
// charged_license_count: number;
|
|
||||||
// activated_license_count: number;
|
|
||||||
// remained_license_count: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPartnerChargeAccountResponse extends IPartnerChargeAccountRawResponse {}
|
export interface IPartnerChargeAccountResponse extends IPartnerChargeAccountRawResponse {}
|
||||||
|
|||||||