Add SMS OTP, harden auth, and fix order/checkout server bugs.
Ship 4-digit OTP with rate-limit attempts, Tehran-safe expiry/rass math, larger JSON body limit for check images, and safer order pricing/status guards. Include rebuilt dist for prebuilt deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+14
-1
@@ -18,8 +18,21 @@ RUN_SEED=false
|
|||||||
|
|
||||||
JWT_SECRET=change-me-to-a-long-random-string
|
JWT_SECRET=change-me-to-a-long-random-string
|
||||||
JWT_EXPIRES_IN=7d
|
JWT_EXPIRES_IN=7d
|
||||||
MOCK_OTP_CODE=123456
|
MOCK_OTP_CODE=1234
|
||||||
OTP_TTL_MINUTES=5
|
OTP_TTL_MINUTES=5
|
||||||
|
|
||||||
|
# پیامک OTP (مثل آبشده خانگی — rayegansms / createsms)
|
||||||
|
SMS_ENABLED=true
|
||||||
|
SMS_API_URL=http://185.231.112.101/api/createsms
|
||||||
|
SMS_SECRET_KEY=your-sms-secret-key
|
||||||
|
SMS_PLATFORM=rayegansms
|
||||||
|
SMS_HOST=پارچه
|
||||||
|
SMS_APP_NAME=پارچه
|
||||||
|
|
||||||
|
# سقف حجم بدنه JSON (تصاویر چک و رسید base64 هستند)
|
||||||
|
BODY_LIMIT=25mb
|
||||||
|
TZ=Asia/Tehran
|
||||||
|
NODE_ENV=production
|
||||||
|
|
||||||
NPM_REGISTRY=https://registry.npmmirror.com
|
NPM_REGISTRY=https://registry.npmmirror.com
|
||||||
COMPOSE_BAKE=false
|
COMPOSE_BAKE=false
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ FROM node:22-bookworm
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
ENV TZ=Asia/Tehran
|
||||||
|
|
||||||
COPY deploy-bundle.tar.gz /tmp/deploy-bundle.tar.gz
|
COPY deploy-bundle.tar.gz /tmp/deploy-bundle.tar.gz
|
||||||
RUN tar -xzf /tmp/deploy-bundle.tar.gz -C /app \
|
RUN tar -xzf /tmp/deploy-bundle.tar.gz -C /app \
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ FROM node:22-alpine
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
ENV TZ=Asia/Tehran
|
||||||
|
|
||||||
COPY package.json package-lock.json ./
|
COPY package.json package-lock.json ./
|
||||||
COPY node_modules ./node_modules
|
COPY node_modules ./node_modules
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ RUN_SEED=true docker compose up -d
|
|||||||
| نقش | ورود | رمز / OTP |
|
| نقش | ورود | رمز / OTP |
|
||||||
|------|------|-----------|
|
|------|------|-----------|
|
||||||
| ادمین | `09121112222` | `admin123` |
|
| ادمین | `09121112222` | `admin123` |
|
||||||
| مشتری | `09121234567` | OTP: `123456` |
|
| مشتری | `09121234567` | OTP پیامکی (۴ رقم) — با `SMS_ENABLED=false` کد ثابت: `1234` |
|
||||||
|
|
||||||
## متغیرهای محیطی
|
## متغیرهای محیطی
|
||||||
|
|
||||||
@@ -71,8 +71,14 @@ DATABASE_URL=postgresql://fabric:fabric123@localhost:5432/fabric_trade?schema=pu
|
|||||||
JWT_SECRET=fabric-trade-dev-secret-change-me
|
JWT_SECRET=fabric-trade-dev-secret-change-me
|
||||||
JWT_EXPIRES_IN=7d
|
JWT_EXPIRES_IN=7d
|
||||||
PORT=3000
|
PORT=3000
|
||||||
MOCK_OTP_CODE=123456
|
MOCK_OTP_CODE=1234
|
||||||
OTP_TTL_MINUTES=5
|
OTP_TTL_MINUTES=5
|
||||||
|
SMS_ENABLED=true
|
||||||
|
SMS_API_URL=http://185.231.112.101/api/createsms
|
||||||
|
SMS_SECRET_KEY=...
|
||||||
|
SMS_PLATFORM=rayegansms
|
||||||
|
SMS_HOST=پارچه
|
||||||
|
SMS_APP_NAME=پارچه
|
||||||
```
|
```
|
||||||
|
|
||||||
## اسکریپتها
|
## اسکریپتها
|
||||||
|
|||||||
+4
-2
@@ -86,7 +86,8 @@ let AdminUsersService = class AdminUsersService {
|
|||||||
return this.map(user);
|
return this.map(user);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('شماره یا ایمیل تکراری است');
|
throw new common_1.ConflictException('شماره یا ایمیل تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -118,7 +119,8 @@ let AdminUsersService = class AdminUsersService {
|
|||||||
return this.map(user);
|
return this.map(user);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('شماره یا ایمیل تکراری است');
|
throw new common_1.ConflictException('شماره یا ایمیل تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"admin-users.service.js","sourceRoot":"","sources":["../../src/admin-users/admin-users.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAKwB;AACxB,2CAAmD;AACnD,iDAAmC;AACnC,6DAAyD;AAEzD,iDAI+B;AAE/B,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAG7B,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IACC;IAA7B,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAEtD,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;YACjD,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;SAC/B,CAAC,CAAC;QACH,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,0BAAiB,CAAC,sBAAsB,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAuB;QAClC,MAAM,KAAK,GAAG,IAAA,sBAAc,EAAC,IAAA,uBAAe,EAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,4BAAmB,CAAC,0BAA0B,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,IAAI,CACpC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,gBAAgB,EACxC,EAAE,CACH,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;gBAC9C,IAAI,EAAE;oBACJ,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE;oBAC7B,KAAK;oBACL,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;oBACrC,YAAY;oBACZ,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,kBAAS,CAAC,KAAK;oBACjC,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,IAAI;iBAC/B;aACF,CAAC,CAAC;YACH,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,eAAM,CAAC,6BAA6B,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5E,MAAM,IAAI,0BAAiB,CAAC,2BAA2B,CAAC,CAAC;YAC3D,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,GAAuB;QAC9C,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtB,MAAM,KAAK,GACT,GAAG,CAAC,KAAK,KAAK,SAAS;YACrB,CAAC,CAAC,IAAA,sBAAc,EAAC,IAAA,uBAAe,EAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC5C,CAAC,CAAC,SAAS,CAAC;QAChB,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,4BAAmB,CAAC,0BAA0B,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,GAAgC;YACxC,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE;YAC9B,KAAK;YACL,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE;YACtC,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAC;QACF,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;YACzB,IAAI,CAAC,YAAY,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;gBAC9C,KAAK,EAAE,EAAE,EAAE,EAAE;gBACb,IAAI;aACL,CAAC,CAAC;YACH,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,eAAM,CAAC,6BAA6B,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5E,MAAM,IAAI,0BAAiB,CAAC,2BAA2B,CAAC,CAAC;YAC3D,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAU,EAAE,QAAiB;QAC3C,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;YAC9C,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,IAAI,EAAE,EAAE,QAAQ,EAAE;SACnB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,EAAU;QAC7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,0BAAiB,CAAC,sBAAsB,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,GAAG,CAAC,IAUX;QACC,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,IAAI;YACpD,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;YACvC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;SACxC,CAAC;IACJ,CAAC;CACF,CAAA;AAvHY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAE0B,8BAAa;GADvC,iBAAiB,CAuH7B"}
|
{"version":3,"file":"admin-users.service.js","sourceRoot":"","sources":["../../src/admin-users/admin-users.service.ts"],"names":[],"mappings":"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"}
|
||||||
Vendored
+1
-1
@@ -9,10 +9,10 @@ export declare class AuthController {
|
|||||||
service: string;
|
service: string;
|
||||||
};
|
};
|
||||||
requestOtp(dto: RequestOtpDto): Promise<{
|
requestOtp(dto: RequestOtpDto): Promise<{
|
||||||
|
debugCode?: string | undefined;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
message: string;
|
message: string;
|
||||||
expiresAt: Date;
|
expiresAt: Date;
|
||||||
debugCode: string;
|
|
||||||
}>;
|
}>;
|
||||||
verifyOtp(dto: VerifyOtpDto): Promise<{
|
verifyOtp(dto: VerifyOtpDto): Promise<{
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
|
|||||||
Vendored
+4
-1
@@ -12,17 +12,20 @@ const jwt_1 = require("@nestjs/jwt");
|
|||||||
const config_1 = require("@nestjs/config");
|
const config_1 = require("@nestjs/config");
|
||||||
const auth_service_1 = require("./auth.service");
|
const auth_service_1 = require("./auth.service");
|
||||||
const auth_controller_1 = require("./auth.controller");
|
const auth_controller_1 = require("./auth.controller");
|
||||||
|
const sms_module_1 = require("../sms/sms.module");
|
||||||
|
const jwt_secret_1 = require("../common/utils/jwt-secret");
|
||||||
let AuthModule = class AuthModule {
|
let AuthModule = class AuthModule {
|
||||||
};
|
};
|
||||||
exports.AuthModule = AuthModule;
|
exports.AuthModule = AuthModule;
|
||||||
exports.AuthModule = AuthModule = __decorate([
|
exports.AuthModule = AuthModule = __decorate([
|
||||||
(0, common_1.Module)({
|
(0, common_1.Module)({
|
||||||
imports: [
|
imports: [
|
||||||
|
sms_module_1.SmsModule,
|
||||||
jwt_1.JwtModule.registerAsync({
|
jwt_1.JwtModule.registerAsync({
|
||||||
imports: [config_1.ConfigModule],
|
imports: [config_1.ConfigModule],
|
||||||
inject: [config_1.ConfigService],
|
inject: [config_1.ConfigService],
|
||||||
useFactory: (config) => ({
|
useFactory: (config) => ({
|
||||||
secret: config.get('JWT_SECRET', 'fabric-trade-dev-secret'),
|
secret: (0, jwt_secret_1.resolveJwtSecret)(config),
|
||||||
signOptions: {
|
signOptions: {
|
||||||
expiresIn: config.get('JWT_EXPIRES_IN', '7d'),
|
expiresIn: config.get('JWT_EXPIRES_IN', '7d'),
|
||||||
},
|
},
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,qCAAwC;AACxC,2CAA6D;AAC7D,iDAA6C;AAC7C,uDAAmD;AAmB5C,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IAjBtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,eAAS,CAAC,aAAa,CAAC;gBACtB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,MAAM,EAAE,CAAC,sBAAa,CAAC;gBACvB,UAAU,EAAE,CAAC,MAAqB,EAAE,EAAE,CAAC,CAAC;oBACtC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAS,YAAY,EAAE,yBAAyB,CAAC;oBACnE,WAAW,EAAE;wBACX,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAiB;qBAC9D;iBACF,CAAC;aACH,CAAC;SACH;QACD,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE,CAAC,0BAAW,CAAC;QACxB,OAAO,EAAE,CAAC,0BAAW,EAAE,eAAS,CAAC;KAClC,CAAC;GACW,UAAU,CAAG"}
|
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,qCAAwC;AACxC,2CAA6D;AAC7D,iDAA6C;AAC7C,uDAAmD;AACnD,kDAA8C;AAC9C,2DAA8D;AAoBvD,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IAlBtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,sBAAS;YACT,eAAS,CAAC,aAAa,CAAC;gBACtB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,MAAM,EAAE,CAAC,sBAAa,CAAC;gBACvB,UAAU,EAAE,CAAC,MAAqB,EAAE,EAAE,CAAC,CAAC;oBACtC,MAAM,EAAE,IAAA,6BAAgB,EAAC,MAAM,CAAC;oBAChC,WAAW,EAAE;wBACX,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC;qBAC9C;iBACF,CAAC;aACH,CAAC;SACH;QACD,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE,CAAC,0BAAW,CAAC;QACxB,OAAO,EAAE,CAAC,0BAAW,EAAE,eAAS,CAAC;KAClC,CAAC;GACW,UAAU,CAAG"}
|
||||||
Vendored
+5
-2
@@ -1,18 +1,21 @@
|
|||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { JwtService } from '@nestjs/jwt';
|
import { JwtService } from '@nestjs/jwt';
|
||||||
import { PrismaService } from '../prisma/prisma.service';
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
|
import { SmsService } from '../sms/sms.service';
|
||||||
import { AdminLoginDto, RequestOtpDto, UpdateProfileDto, VerifyOtpDto } from './dto/auth.dto';
|
import { AdminLoginDto, RequestOtpDto, UpdateProfileDto, VerifyOtpDto } from './dto/auth.dto';
|
||||||
export declare class AuthService {
|
export declare class AuthService {
|
||||||
private readonly prisma;
|
private readonly prisma;
|
||||||
private readonly jwt;
|
private readonly jwt;
|
||||||
private readonly config;
|
private readonly config;
|
||||||
constructor(prisma: PrismaService, jwt: JwtService, config: ConfigService);
|
private readonly sms;
|
||||||
|
constructor(prisma: PrismaService, jwt: JwtService, config: ConfigService, sms: SmsService);
|
||||||
requestOtp(dto: RequestOtpDto): Promise<{
|
requestOtp(dto: RequestOtpDto): Promise<{
|
||||||
|
debugCode?: string | undefined;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
message: string;
|
message: string;
|
||||||
expiresAt: Date;
|
expiresAt: Date;
|
||||||
debugCode: string;
|
|
||||||
}>;
|
}>;
|
||||||
|
private exposesDebugCode;
|
||||||
verifyOtp(dto: VerifyOtpDto): Promise<{
|
verifyOtp(dto: VerifyOtpDto): Promise<{
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
user: {
|
user: {
|
||||||
|
|||||||
Vendored
+62
-17
@@ -46,24 +46,31 @@ exports.AuthService = void 0;
|
|||||||
const common_1 = require("@nestjs/common");
|
const common_1 = require("@nestjs/common");
|
||||||
const config_1 = require("@nestjs/config");
|
const config_1 = require("@nestjs/config");
|
||||||
const jwt_1 = require("@nestjs/jwt");
|
const jwt_1 = require("@nestjs/jwt");
|
||||||
|
const node_crypto_1 = require("node:crypto");
|
||||||
const bcrypt = __importStar(require("bcryptjs"));
|
const bcrypt = __importStar(require("bcryptjs"));
|
||||||
const prisma_service_1 = require("../prisma/prisma.service");
|
const prisma_service_1 = require("../prisma/prisma.service");
|
||||||
|
const sms_service_1 = require("../sms/sms.service");
|
||||||
const phone_1 = require("../common/utils/phone");
|
const phone_1 = require("../common/utils/phone");
|
||||||
|
const MAX_OTP_ATTEMPTS = 5;
|
||||||
let AuthService = class AuthService {
|
let AuthService = class AuthService {
|
||||||
prisma;
|
prisma;
|
||||||
jwt;
|
jwt;
|
||||||
config;
|
config;
|
||||||
constructor(prisma, jwt, config) {
|
sms;
|
||||||
|
constructor(prisma, jwt, config, sms) {
|
||||||
this.prisma = prisma;
|
this.prisma = prisma;
|
||||||
this.jwt = jwt;
|
this.jwt = jwt;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.sms = sms;
|
||||||
}
|
}
|
||||||
async requestOtp(dto) {
|
async requestOtp(dto) {
|
||||||
const phone = (0, phone_1.normalizePhone)((0, phone_1.toEnglishDigits)(dto.phone));
|
const phone = (0, phone_1.normalizePhone)((0, phone_1.toEnglishDigits)(dto.phone));
|
||||||
if (!(0, phone_1.isValidPhone)(phone)) {
|
if (!(0, phone_1.isValidPhone)(phone)) {
|
||||||
throw new common_1.BadRequestException('شماره موبایل نامعتبر است');
|
throw new common_1.BadRequestException('شماره موبایل نامعتبر است');
|
||||||
}
|
}
|
||||||
const existing = await this.prisma.customer.findUnique({ where: { phone } });
|
const existing = await this.prisma.customer.findUnique({
|
||||||
|
where: { phone },
|
||||||
|
});
|
||||||
const isRegister = Boolean(dto.isRegister);
|
const isRegister = Boolean(dto.isRegister);
|
||||||
if (isRegister) {
|
if (isRegister) {
|
||||||
if (!dto.firstName?.trim() || !dto.lastName?.trim()) {
|
if (!dto.firstName?.trim() || !dto.lastName?.trim()) {
|
||||||
@@ -76,27 +83,49 @@ let AuthService = class AuthService {
|
|||||||
else if (!existing) {
|
else if (!existing) {
|
||||||
throw new common_1.BadRequestException('کاربری با این شماره یافت نشد');
|
throw new common_1.BadRequestException('کاربری با این شماره یافت نشد');
|
||||||
}
|
}
|
||||||
const code = this.config.get('MOCK_OTP_CODE', '123456');
|
else if (!existing.isActive) {
|
||||||
|
throw new common_1.UnauthorizedException('حساب کاربری شما غیرفعال است');
|
||||||
|
}
|
||||||
|
const smsEnabled = this.sms.isEnabled();
|
||||||
|
const code = smsEnabled
|
||||||
|
? String((0, node_crypto_1.randomInt)(1000, 10000))
|
||||||
|
: this.config.get('MOCK_OTP_CODE', '1234');
|
||||||
const ttl = Number(this.config.get('OTP_TTL_MINUTES', 5));
|
const ttl = Number(this.config.get('OTP_TTL_MINUTES', 5));
|
||||||
const expiresAt = new Date(Date.now() + ttl * 60_000);
|
const expiresAt = new Date(Date.now() + ttl * 60_000);
|
||||||
await this.prisma.otpChallenge.deleteMany({ where: { phone } });
|
const challenge = await this.prisma.$transaction(async (tx) => {
|
||||||
await this.prisma.otpChallenge.create({
|
await tx.otpChallenge.deleteMany({ where: { phone } });
|
||||||
data: {
|
return tx.otpChallenge.create({
|
||||||
phone,
|
data: {
|
||||||
code,
|
phone,
|
||||||
firstName: dto.firstName?.trim(),
|
code,
|
||||||
lastName: dto.lastName?.trim(),
|
firstName: dto.firstName?.trim(),
|
||||||
isRegister,
|
lastName: dto.lastName?.trim(),
|
||||||
expiresAt,
|
isRegister,
|
||||||
},
|
expiresAt,
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
if (smsEnabled) {
|
||||||
|
const sent = await this.sms.send(phone, this.sms.buildOtpMessage(code));
|
||||||
|
if (!sent.success) {
|
||||||
|
await this.prisma.otpChallenge.deleteMany({
|
||||||
|
where: { id: challenge.id },
|
||||||
|
});
|
||||||
|
throw new common_1.ServiceUnavailableException('ارسال پیامک با خطا مواجه شد؛ دوباره تلاش کنید');
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: 'کد تأیید ارسال شد',
|
message: 'کد تأیید ارسال شد',
|
||||||
expiresAt,
|
expiresAt,
|
||||||
debugCode: code,
|
...(this.exposesDebugCode(smsEnabled) ? { debugCode: code } : {}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
exposesDebugCode(smsEnabled) {
|
||||||
|
if (smsEnabled)
|
||||||
|
return false;
|
||||||
|
return this.config.get('NODE_ENV') !== 'production';
|
||||||
|
}
|
||||||
async verifyOtp(dto) {
|
async verifyOtp(dto) {
|
||||||
const phone = (0, phone_1.normalizePhone)((0, phone_1.toEnglishDigits)(dto.phone));
|
const phone = (0, phone_1.normalizePhone)((0, phone_1.toEnglishDigits)(dto.phone));
|
||||||
const code = (0, phone_1.toEnglishDigits)(dto.code).trim();
|
const code = (0, phone_1.toEnglishDigits)(dto.code).trim();
|
||||||
@@ -107,7 +136,15 @@ let AuthService = class AuthService {
|
|||||||
if (!challenge || challenge.expiresAt < new Date()) {
|
if (!challenge || challenge.expiresAt < new Date()) {
|
||||||
throw new common_1.UnauthorizedException('کد منقضی شده است');
|
throw new common_1.UnauthorizedException('کد منقضی شده است');
|
||||||
}
|
}
|
||||||
|
if (challenge.attempts >= MAX_OTP_ATTEMPTS) {
|
||||||
|
await this.prisma.otpChallenge.deleteMany({ where: { phone } });
|
||||||
|
throw new common_1.UnauthorizedException('تعداد تلاشهای نادرست زیاد است؛ کد جدید بگیرید');
|
||||||
|
}
|
||||||
if (challenge.code !== code) {
|
if (challenge.code !== code) {
|
||||||
|
await this.prisma.otpChallenge.update({
|
||||||
|
where: { id: challenge.id },
|
||||||
|
data: { attempts: { increment: 1 } },
|
||||||
|
});
|
||||||
throw new common_1.UnauthorizedException('کد تأیید نادرست است');
|
throw new common_1.UnauthorizedException('کد تأیید نادرست است');
|
||||||
}
|
}
|
||||||
let user = await this.prisma.customer.findUnique({ where: { phone } });
|
let user = await this.prisma.customer.findUnique({ where: { phone } });
|
||||||
@@ -126,6 +163,9 @@ let AuthService = class AuthService {
|
|||||||
else if (!user) {
|
else if (!user) {
|
||||||
throw new common_1.UnauthorizedException('کاربر یافت نشد');
|
throw new common_1.UnauthorizedException('کاربر یافت نشد');
|
||||||
}
|
}
|
||||||
|
else if (!user.isActive) {
|
||||||
|
throw new common_1.UnauthorizedException('حساب کاربری شما غیرفعال است');
|
||||||
|
}
|
||||||
await this.prisma.otpChallenge.deleteMany({ where: { phone } });
|
await this.prisma.otpChallenge.deleteMany({ where: { phone } });
|
||||||
const accessToken = await this.signCustomerToken(user.id, user.phone);
|
const accessToken = await this.signCustomerToken(user.id, user.phone);
|
||||||
return {
|
return {
|
||||||
@@ -166,7 +206,9 @@ let AuthService = class AuthService {
|
|||||||
}
|
}
|
||||||
async me(userId, type) {
|
async me(userId, type) {
|
||||||
if (type === 'admin') {
|
if (type === 'admin') {
|
||||||
const admin = await this.prisma.adminUser.findUnique({ where: { id: userId } });
|
const admin = await this.prisma.adminUser.findUnique({
|
||||||
|
where: { id: userId },
|
||||||
|
});
|
||||||
if (!admin)
|
if (!admin)
|
||||||
throw new common_1.UnauthorizedException();
|
throw new common_1.UnauthorizedException();
|
||||||
return {
|
return {
|
||||||
@@ -177,7 +219,9 @@ let AuthService = class AuthService {
|
|||||||
role: admin.role,
|
role: admin.role,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const user = await this.prisma.customer.findUnique({ where: { id: userId } });
|
const user = await this.prisma.customer.findUnique({
|
||||||
|
where: { id: userId },
|
||||||
|
});
|
||||||
if (!user)
|
if (!user)
|
||||||
throw new common_1.UnauthorizedException();
|
throw new common_1.UnauthorizedException();
|
||||||
return this.mapCustomer(user);
|
return this.mapCustomer(user);
|
||||||
@@ -216,6 +260,7 @@ exports.AuthService = AuthService = __decorate([
|
|||||||
(0, common_1.Injectable)(),
|
(0, common_1.Injectable)(),
|
||||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
|
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
|
||||||
jwt_1.JwtService,
|
jwt_1.JwtService,
|
||||||
config_1.ConfigService])
|
config_1.ConfigService,
|
||||||
|
sms_service_1.SmsService])
|
||||||
], AuthService);
|
], AuthService);
|
||||||
//# sourceMappingURL=auth.service.js.map
|
//# sourceMappingURL=auth.service.js.map
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -48,7 +48,7 @@ __decorate([
|
|||||||
], VerifyOtpDto.prototype, "phone", void 0);
|
], VerifyOtpDto.prototype, "phone", void 0);
|
||||||
__decorate([
|
__decorate([
|
||||||
(0, class_validator_1.IsString)(),
|
(0, class_validator_1.IsString)(),
|
||||||
(0, class_validator_1.MinLength)(4),
|
(0, class_validator_1.Length)(4, 4),
|
||||||
__metadata("design:type", String)
|
__metadata("design:type", String)
|
||||||
], VerifyOtpDto.prototype, "code", void 0);
|
], VerifyOtpDto.prototype, "code", void 0);
|
||||||
class AdminLoginDto {
|
class AdminLoginDto {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"auth.dto.js","sourceRoot":"","sources":["../../../src/auth/dto/auth.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA6E;AAE7E,MAAa,aAAa;IAExB,KAAK,CAAU;IAIf,SAAS,CAAU;IAInB,QAAQ,CAAU;IAIlB,UAAU,CAAW;CACtB;AAfD,sCAeC;AAbC;IADC,IAAA,0BAAQ,GAAE;;4CACI;AAIf;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;gDACQ;AAInB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;+CACO;AAIlB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,2BAAS,GAAE;;iDACS;AAGvB,MAAa,YAAY;IAEvB,KAAK,CAAU;IAIf,IAAI,CAAU;CACf;AAPD,oCAOC;AALC;IADC,IAAA,0BAAQ,GAAE;;2CACI;AAIf;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;;0CACC;AAGhB,MAAa,aAAa;IAExB,KAAK,CAAU;IAIf,QAAQ,CAAU;CACnB;AAPD,sCAOC;AALC;IADC,IAAA,0BAAQ,GAAE;;4CACI;AAIf;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;;+CACK;AAGpB,MAAa,gBAAgB;IAG3B,SAAS,CAAU;IAInB,QAAQ,CAAU;IAIlB,UAAU,CAAU;CACrB;AAZD,4CAYC;AATC;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;mDACQ;AAInB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;kDACO;AAIlB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;oDACS"}
|
{"version":3,"file":"auth.dto.js","sourceRoot":"","sources":["../../../src/auth/dto/auth.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAMyB;AAEzB,MAAa,aAAa;IAExB,KAAK,CAAU;IAIf,SAAS,CAAU;IAInB,QAAQ,CAAU;IAIlB,UAAU,CAAW;CACtB;AAfD,sCAeC;AAbC;IADC,IAAA,0BAAQ,GAAE;;4CACI;AAIf;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;gDACQ;AAInB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;+CACO;AAIlB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,2BAAS,GAAE;;iDACS;AAGvB,MAAa,YAAY;IAEvB,KAAK,CAAU;IAIf,IAAI,CAAU;CACf;AAPD,oCAOC;AALC;IADC,IAAA,0BAAQ,GAAE;;2CACI;AAIf;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,wBAAM,EAAC,CAAC,EAAE,CAAC,CAAC;;0CACC;AAGhB,MAAa,aAAa;IAExB,KAAK,CAAU;IAIf,QAAQ,CAAU;CACnB;AAPD,sCAOC;AALC;IADC,IAAA,0BAAQ,GAAE;;4CACI;AAIf;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;;+CACK;AAGpB,MAAa,gBAAgB;IAG3B,SAAS,CAAU;IAInB,QAAQ,CAAU;IAIlB,UAAU,CAAU;CACrB;AAZD,4CAYC;AATC;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;mDACQ;AAInB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;kDACO;AAIlB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;oDACS"}
|
||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"carts.controller.js","sourceRoot":"","sources":["../../src/carts/carts.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAQwB;AACxB,mDAA+C;AAC/C,0EAAgE;AAChE,wFAA0E;AAE1E,6CAIwB;AAIjB,IAAM,eAAe,GAArB,MAAM,eAAe;IACG;IAA7B,YAA6B,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAG3D,OAAO,CAAgB,IAAmB;QACxC,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC;IAGD,OAAO,CACU,IAAmB,EAC1B,GAAmB;QAE3B,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;IAGD,UAAU,CACO,IAAmB,EACjB,MAAc,EACvB,GAA8B;QAEtC,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5D,CAAC;IAGD,UAAU,CACO,IAAmB,EACjB,MAAc;QAE/B,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;IAGD,WAAW,CACM,IAAmB,EAC1B,GAAuB;QAE/B,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAGD,KAAK,CAAgB,IAAmB;QACtC,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;CACF,CAAA;AA7CY,0CAAe;AAI1B;IADC,IAAA,YAAG,GAAE;IACG,WAAA,IAAA,oCAAW,GAAE,CAAA;;;;8CAErB;AAGD;IADC,IAAA,aAAI,EAAC,OAAO,CAAC;IAEX,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,yBAAc;;8CAG5B;AAGD;IADC,IAAA,cAAK,EAAC,eAAe,CAAC;IAEpB,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,cAAK,EAAC,QAAQ,CAAC,CAAA;IACf,WAAA,IAAA,aAAI,GAAE,CAAA;;qDAAM,oCAAyB;;iDAGvC;AAGD;IADC,IAAA,eAAM,EAAC,eAAe,CAAC;IAErB,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,cAAK,EAAC,QAAQ,CAAC,CAAA;;;;iDAGjB;AAGD;IADC,IAAA,cAAK,EAAC,OAAO,CAAC;IAEZ,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,6BAAkB;;kDAGhC;AAGD;IADC,IAAA,eAAM,GAAE;IACF,WAAA,IAAA,oCAAW,GAAE,CAAA;;;;4CAEnB;0BA5CU,eAAe;IAF3B,IAAA,mBAAU,EAAC,OAAO,CAAC;IACnB,IAAA,0BAAQ,EAAC,UAAU,CAAC;qCAEwB,4BAAY;GAD5C,eAAe,CA6C3B"}
|
{"version":3,"file":"carts.controller.js","sourceRoot":"","sources":["../../src/carts/carts.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAQwB;AACxB,mDAA+C;AAC/C,0EAAgE;AAChE,wFAA0E;AAE1E,6CAIwB;AAIjB,IAAM,eAAe,GAArB,MAAM,eAAe;IACG;IAA7B,YAA6B,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAG3D,OAAO,CAAgB,IAAmB;QACxC,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC;IAGD,OAAO,CAAgB,IAAmB,EAAU,GAAmB;QACrE,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;IAGD,UAAU,CACO,IAAmB,EACjB,MAAc,EACvB,GAA8B;QAEtC,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5D,CAAC;IAGD,UAAU,CACO,IAAmB,EACjB,MAAc;QAE/B,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;IAGD,WAAW,CACM,IAAmB,EAC1B,GAAuB;QAE/B,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAGD,KAAK,CAAgB,IAAmB;QACtC,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;CACF,CAAA;AA1CY,0CAAe;AAI1B;IADC,IAAA,YAAG,GAAE;IACG,WAAA,IAAA,oCAAW,GAAE,CAAA;;;;8CAErB;AAGD;IADC,IAAA,aAAI,EAAC,OAAO,CAAC;IACL,WAAA,IAAA,oCAAW,GAAE,CAAA;IAAuB,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,yBAAc;;8CAEtE;AAGD;IADC,IAAA,cAAK,EAAC,eAAe,CAAC;IAEpB,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,cAAK,EAAC,QAAQ,CAAC,CAAA;IACf,WAAA,IAAA,aAAI,GAAE,CAAA;;qDAAM,oCAAyB;;iDAGvC;AAGD;IADC,IAAA,eAAM,EAAC,eAAe,CAAC;IAErB,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,cAAK,EAAC,QAAQ,CAAC,CAAA;;;;iDAGjB;AAGD;IADC,IAAA,cAAK,EAAC,OAAO,CAAC;IAEZ,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,6BAAkB;;kDAGhC;AAGD;IADC,IAAA,eAAM,GAAE;IACF,WAAA,IAAA,oCAAW,GAAE,CAAA;;;;4CAEnB;0BAzCU,eAAe;IAF3B,IAAA,mBAAU,EAAC,OAAO,CAAC;IACnB,IAAA,0BAAQ,EAAC,UAAU,CAAC;qCAEwB,4BAAY;GAD5C,eAAe,CA0C3B"}
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+15
@@ -14,6 +14,18 @@ const common_1 = require("@nestjs/common");
|
|||||||
const client_1 = require("@prisma/client");
|
const client_1 = require("@prisma/client");
|
||||||
const prisma_service_1 = require("../prisma/prisma.service");
|
const prisma_service_1 = require("../prisma/prisma.service");
|
||||||
const name_1 = require("../common/utils/name");
|
const name_1 = require("../common/utils/name");
|
||||||
|
const RECEIPT_SUBMITTABLE_STATUSES = [
|
||||||
|
client_1.OrderStatus.awaiting_review,
|
||||||
|
client_1.OrderStatus.pricing,
|
||||||
|
client_1.OrderStatus.needs_correction,
|
||||||
|
client_1.OrderStatus.awaiting_settlement,
|
||||||
|
client_1.OrderStatus.awaiting_settlement_fix,
|
||||||
|
client_1.OrderStatus.cash_in_progress,
|
||||||
|
client_1.OrderStatus.cash_invoice_issued,
|
||||||
|
client_1.OrderStatus.awaiting_cash_payment,
|
||||||
|
client_1.OrderStatus.cash_payment_submitted,
|
||||||
|
client_1.OrderStatus.awaiting_cash_confirmation,
|
||||||
|
];
|
||||||
let CashPaymentsService = class CashPaymentsService {
|
let CashPaymentsService = class CashPaymentsService {
|
||||||
prisma;
|
prisma;
|
||||||
constructor(prisma) {
|
constructor(prisma) {
|
||||||
@@ -32,6 +44,9 @@ let CashPaymentsService = class CashPaymentsService {
|
|||||||
if (order.settlementType !== client_1.SettlementType.cash) {
|
if (order.settlementType !== client_1.SettlementType.cash) {
|
||||||
throw new common_1.BadRequestException('این سفارش تسویه نقدی نیست');
|
throw new common_1.BadRequestException('این سفارش تسویه نقدی نیست');
|
||||||
}
|
}
|
||||||
|
if (!RECEIPT_SUBMITTABLE_STATUSES.includes(order.status)) {
|
||||||
|
throw new common_1.BadRequestException('در وضعیت فعلی سفارش امکان ثبت رسید وجود ندارد');
|
||||||
|
}
|
||||||
if (order.cashInvoiceExpiresAt &&
|
if (order.cashInvoiceExpiresAt &&
|
||||||
order.cashInvoiceExpiresAt.getTime() < Date.now()) {
|
order.cashInvoiceExpiresAt.getTime() < Date.now()) {
|
||||||
throw new common_1.BadRequestException('مهلت پرداخت فاکتور نقدی به پایان رسیده است');
|
throw new common_1.BadRequestException('مهلت پرداخت فاکتور نقدی به پایان رسیده است');
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+4
-2
@@ -68,7 +68,8 @@ let CatalogsService = class CatalogsService {
|
|||||||
return this.map(catalog);
|
return this.map(catalog);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('کد کاتالوگ در این شرکت تکراری است');
|
throw new common_1.ConflictException('کد کاتالوگ در این شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -96,7 +97,8 @@ let CatalogsService = class CatalogsService {
|
|||||||
return this.map(catalog);
|
return this.map(catalog);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('کد کاتالوگ در این شرکت تکراری است');
|
throw new common_1.ConflictException('کد کاتالوگ در این شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"catalogs.service.js","sourceRoot":"","sources":["../../src/catalogs/catalogs.service.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"catalogs.service.js","sourceRoot":"","sources":["../../src/catalogs/catalogs.service.ts"],"names":[],"mappings":"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"}
|
||||||
Vendored
+6
-2
@@ -19,7 +19,9 @@ let ChecksService = class ChecksService {
|
|||||||
this.prisma = prisma;
|
this.prisma = prisma;
|
||||||
}
|
}
|
||||||
async findByOrder(orderId) {
|
async findByOrder(orderId) {
|
||||||
const order = await this.prisma.order.findUnique({ where: { id: orderId } });
|
const order = await this.prisma.order.findUnique({
|
||||||
|
where: { id: orderId },
|
||||||
|
});
|
||||||
if (!order)
|
if (!order)
|
||||||
throw new common_1.NotFoundException('سفارش یافت نشد');
|
throw new common_1.NotFoundException('سفارش یافت نشد');
|
||||||
const checks = await this.prisma.check.findMany({
|
const checks = await this.prisma.check.findMany({
|
||||||
@@ -45,7 +47,9 @@ let ChecksService = class ChecksService {
|
|||||||
: check.notes,
|
: check.notes,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const siblings = await tx.check.findMany({ where: { orderId: check.orderId } });
|
const siblings = await tx.check.findMany({
|
||||||
|
where: { orderId: check.orderId },
|
||||||
|
});
|
||||||
const allApproved = siblings.every((c) => c.status === client_1.CheckStatus.approved);
|
const allApproved = siblings.every((c) => c.status === client_1.CheckStatus.approved);
|
||||||
const anyRejected = siblings.some((c) => c.status === client_1.CheckStatus.rejected);
|
const anyRejected = siblings.some((c) => c.status === client_1.CheckStatus.rejected);
|
||||||
let nextStatus = null;
|
let nextStatus = null;
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"checks.service.js","sourceRoot":"","sources":["../../src/checks/checks.service.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"checks.service.js","sourceRoot":"","sources":["../../src/checks/checks.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA+D;AAC/D,2CAA0D;AAC1D,6DAAyD;AAIlD,IAAM,aAAa,GAAnB,MAAM,aAAa;IACK;IAA7B,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAEtD,KAAK,CAAC,WAAW,CAAC,OAAe;QAC/B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;YAC/C,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,0BAAiB,CAAC,gBAAgB,CAAC,CAAC;QAE1D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YAC9C,KAAK,EAAE,EAAE,OAAO,EAAE;YAClB,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;SACxB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAU,EAAE,OAAe,EAAE,GAAyB;QACvE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;YAC/C,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;SAClD,CAAC,CAAC;QACH,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,0BAAiB,CAAC,aAAa,CAAC,CAAC;QAEvD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC1D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;gBACnC,KAAK,EAAE,EAAE,EAAE,EAAE;gBACb,IAAI,EAAE;oBACJ,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,KAAK,EAAE,GAAG,CAAC,IAAI;wBACb,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;wBACpD,CAAC,CAAC,KAAK,CAAC,KAAK;iBAChB;aACF,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;gBACvC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;aAClC,CAAC,CAAC;YACH,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,oBAAW,CAAC,QAAQ,CACzC,CAAC;YACF,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,oBAAW,CAAC,QAAQ,CACzC,CAAC;YAEF,IAAI,UAAU,GAAuB,IAAI,CAAC;YAC1C,IAAI,WAAW,EAAE,CAAC;gBAChB,UAAU,GAAG,oBAAW,CAAC,cAAc,CAAC;YAC1C,CAAC;iBAAM,IAAI,WAAW,EAAE,CAAC;gBACvB,UAAU,GAAG,oBAAW,CAAC,eAAe,CAAC;YAC3C,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM,KAAK,oBAAW,CAAC,QAAQ,EAAE,CAAC;gBAC/C,UAAU,GAAG,oBAAW,CAAC,eAAe,CAAC;YAC3C,CAAC;YAED,IAAI,UAAU,IAAI,UAAU,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACpD,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;oBACpB,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE;oBAC5B,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;iBAC7B,CAAC,CAAC;gBACH,MAAM,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC;oBACjC,IAAI,EAAE;wBACJ,OAAO,EAAE,KAAK,CAAC,OAAO;wBACtB,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;wBAC9B,QAAQ,EAAE,UAAU;wBACpB,SAAS,EAAE,SAAS,OAAO,EAAE;wBAC7B,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,eAAe,GAAG,CAAC,MAAM,YAAY;qBACxD;iBACF,CAAC,CAAC;YACL,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAEO,GAAG,CAAC,CAoBX;QACC,OAAO;YACL,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE;YAChC,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE;YACxB,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,SAAS;YACvC,eAAe,EAAE,CAAC,CAAC,eAAe,IAAI,SAAS;YAC/C,cAAc,EAAE,CAAC,CAAC,cAAc,IAAI,SAAS;YAC7C,aAAa,EAAE,CAAC,CAAC,aAAa,IAAI,SAAS;YAC3C,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;YAC1B,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,SAAS;YACrC,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,SAAS;YACrC,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,SAAS;YACnC,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,SAAS;YAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;YACpC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;SACrC,CAAC;IACJ,CAAC;CACF,CAAA;AAtHY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAE0B,8BAAa;GADvC,aAAa,CAsHzB"}
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"current-user.decorator.js","sourceRoot":"","sources":["../../../src/common/decorators/current-user.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AAS3D,QAAA,WAAW,GAAG,IAAA,6BAAoB,EAC7C,CAAC,KAAc,EAAE,GAAqB,EAAiB,EAAE;IACvD,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;IAChD,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC,CACF,CAAC"}
|
{"version":3,"file":"current-user.decorator.js","sourceRoot":"","sources":["../../../src/common/decorators/current-user.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AAS3D,QAAA,WAAW,GAAG,IAAA,6BAAoB,EAC7C,CAAC,KAAc,EAAE,GAAqB,EAAiB,EAAE;IACvD,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAA2B,CAAC;IACzE,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC,CACF,CAAC"}
|
||||||
Vendored
+2
-1
@@ -15,6 +15,7 @@ const core_1 = require("@nestjs/core");
|
|||||||
const jwt_1 = require("@nestjs/jwt");
|
const jwt_1 = require("@nestjs/jwt");
|
||||||
const config_1 = require("@nestjs/config");
|
const config_1 = require("@nestjs/config");
|
||||||
const auth_decorators_1 = require("../decorators/auth.decorators");
|
const auth_decorators_1 = require("../decorators/auth.decorators");
|
||||||
|
const jwt_secret_1 = require("../utils/jwt-secret");
|
||||||
let JwtAuthGuard = class JwtAuthGuard {
|
let JwtAuthGuard = class JwtAuthGuard {
|
||||||
reflector;
|
reflector;
|
||||||
jwtService;
|
jwtService;
|
||||||
@@ -40,7 +41,7 @@ let JwtAuthGuard = class JwtAuthGuard {
|
|||||||
let payload;
|
let payload;
|
||||||
try {
|
try {
|
||||||
payload = await this.jwtService.verifyAsync(token, {
|
payload = await this.jwtService.verifyAsync(token, {
|
||||||
secret: this.config.get('JWT_SECRET'),
|
secret: (0, jwt_secret_1.resolveJwtSecret)(this.config),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../../src/common/guards/jwt-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAMwB;AACxB,uCAAyC;AACzC,qCAAyC;AACzC,2CAA+C;AAC/C,mEAIuC;AAIhC,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEJ;IACA;IACA;IAHnB,YACmB,SAAoB,EACpB,UAAsB,EACtB,MAAqB;QAFrB,cAAS,GAAT,SAAS,CAAW;QACpB,eAAU,GAAV,UAAU,CAAY;QACtB,WAAM,GAAN,MAAM,CAAe;IACrC,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAU,+BAAa,EAAE;YACxE,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QACH,IAAI,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE1B,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAmC,CAAC;QACvE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,8BAAqB,CAAC,4BAA4B,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,OAAyC,CAAC;QAC9C,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE;gBACjD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAS,YAAY,CAAC;aAC9C,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,8BAAqB,CAAC,+BAA+B,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,IAAI,GAAkB;YAC1B,EAAE,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,EAAE;YAC7B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC;QACF,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAC/C,+BAAa,EACb,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAC3C,CAAC;QACF,IAAI,QAAQ,IAAI,QAAQ,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7D,MAAM,IAAI,2BAAkB,CAAC,kBAAkB,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAW,2BAAS,EAAE;YAClE,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,2BAAkB,CAAC,sBAAsB,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAxDY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;qCAGmB,gBAAS;QACR,gBAAU;QACd,sBAAa;GAJ7B,YAAY,CAwDxB"}
|
{"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../../src/common/guards/jwt-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAMwB;AACxB,uCAAyC;AACzC,qCAAyC;AACzC,2CAA+C;AAC/C,mEAIuC;AAEvC,oDAAuD;AAGhD,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEJ;IACA;IACA;IAHnB,YACmB,SAAoB,EACpB,UAAsB,EACtB,MAAqB;QAFrB,cAAS,GAAT,SAAS,CAAW;QACpB,eAAU,GAAV,UAAU,CAAY;QACtB,WAAM,GAAN,MAAM,CAAe;IACrC,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAU,+BAAa,EAAE;YACxE,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QACH,IAAI,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE1B,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAG7C,CAAC;QACL,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QACjD,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,8BAAqB,CAAC,4BAA4B,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,OAAyC,CAAC;QAC9C,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE;gBACjD,MAAM,EAAE,IAAA,6BAAgB,EAAC,IAAI,CAAC,MAAM,CAAC;aACtC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,8BAAqB,CAAC,+BAA+B,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,IAAI,GAAkB;YAC1B,EAAE,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,EAAE;YAC7B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC;QACF,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAE/C,+BAAa,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC7D,IAAI,QAAQ,IAAI,QAAQ,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7D,MAAM,IAAI,2BAAkB,CAAC,kBAAkB,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAW,2BAAS,EAAE;YAClE,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,2BAAkB,CAAC,sBAAsB,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AA1DY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;qCAGmB,gBAAS;QACR,gBAAU;QACd,sBAAa;GAJ7B,YAAY,CA0DxB"}
|
||||||
Vendored
+3
-3
@@ -1,14 +1,14 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.computeCashInvoiceExpiry = computeCashInvoiceExpiry;
|
exports.computeCashInvoiceExpiry = computeCashInvoiceExpiry;
|
||||||
|
const tehran_time_1 = require("./tehran-time");
|
||||||
function computeCashInvoiceExpiry(company) {
|
function computeCashInvoiceExpiry(company) {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
if (company.cashInvoiceValidUntilHour != null &&
|
if (company.cashInvoiceValidUntilHour != null &&
|
||||||
Number.isFinite(company.cashInvoiceValidUntilHour)) {
|
Number.isFinite(company.cashInvoiceValidUntilHour)) {
|
||||||
const expires = new Date(now);
|
const expires = (0, tehran_time_1.tehranAtHour)(now, company.cashInvoiceValidUntilHour);
|
||||||
expires.setHours(company.cashInvoiceValidUntilHour, 0, 0, 0);
|
|
||||||
if (expires.getTime() <= now.getTime()) {
|
if (expires.getTime() <= now.getTime()) {
|
||||||
expires.setDate(expires.getDate() + 1);
|
return (0, tehran_time_1.tehranAtHour)((0, tehran_time_1.addDays)(now, 1), company.cashInvoiceValidUntilHour);
|
||||||
}
|
}
|
||||||
return expires;
|
return expires;
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"cash-expiry.js","sourceRoot":"","sources":["../../../src/common/utils/cash-expiry.ts"],"names":[],"mappings":";;AAAA,4DAoBC;AApBD,SAAgB,wBAAwB,CAAC,OAGxC;IACC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,IACE,OAAO,CAAC,yBAAyB,IAAI,IAAI;QACzC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,yBAAyB,CAAC,EAClD,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7D,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;YACvC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,IAAI,IAAI,CACb,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,wBAAwB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAClE,CAAC;AACJ,CAAC"}
|
{"version":3,"file":"cash-expiry.js","sourceRoot":"","sources":["../../../src/common/utils/cash-expiry.ts"],"names":[],"mappings":";;AAEA,4DAmBC;AArBD,+CAAsD;AAEtD,SAAgB,wBAAwB,CAAC,OAGxC;IACC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,IACE,OAAO,CAAC,yBAAyB,IAAI,IAAI;QACzC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,yBAAyB,CAAC,EAClD,CAAC;QACD,MAAM,OAAO,GAAG,IAAA,0BAAY,EAAC,GAAG,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;QACrE,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;YACvC,OAAO,IAAA,0BAAY,EAAC,IAAA,qBAAO,EAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,IAAI,IAAI,CACb,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,wBAAwB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAClE,CAAC;AACJ,CAAC"}
|
||||||
Vendored
+5
-10
@@ -1,11 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.calculateCheckRass = calculateCheckRass;
|
exports.calculateCheckRass = calculateCheckRass;
|
||||||
function startOfDay(date) {
|
const tehran_time_1 = require("./tehran-time");
|
||||||
const d = new Date(date);
|
|
||||||
d.setHours(0, 0, 0, 0);
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
function calculateCheckRass(checks, baseDate = new Date()) {
|
function calculateCheckRass(checks, baseDate = new Date()) {
|
||||||
if (checks.length === 0) {
|
if (checks.length === 0) {
|
||||||
return {
|
return {
|
||||||
@@ -17,20 +13,19 @@ function calculateCheckRass(checks, baseDate = new Date()) {
|
|||||||
rassDate: null,
|
rassDate: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const base = startOfDay(baseDate);
|
const base = (0, tehran_time_1.tehranCalendarDay)(baseDate);
|
||||||
let totalAmount = 0;
|
let totalAmount = 0;
|
||||||
let weightedDays = 0;
|
let weightedDays = 0;
|
||||||
const dueDates = [];
|
const dueDates = [];
|
||||||
for (const check of checks) {
|
for (const check of checks) {
|
||||||
const due = startOfDay(new Date(check.dueDate));
|
const due = (0, tehran_time_1.calendarDayOf)(check.dueDate);
|
||||||
dueDates.push(due);
|
dueDates.push(due);
|
||||||
const days = Math.max(0, Math.round((due.getTime() - base.getTime()) / (1000 * 60 * 60 * 24)));
|
const days = Math.max(0, (0, tehran_time_1.diffInDays)(base, due));
|
||||||
totalAmount += check.amount;
|
totalAmount += check.amount;
|
||||||
weightedDays += check.amount * days;
|
weightedDays += check.amount * days;
|
||||||
}
|
}
|
||||||
const rassDays = totalAmount > 0 ? Math.round(weightedDays / totalAmount) : 0;
|
const rassDays = totalAmount > 0 ? Math.round(weightedDays / totalAmount) : 0;
|
||||||
const rassDate = new Date(base);
|
const rassDate = (0, tehran_time_1.addDays)(base, rassDays);
|
||||||
rassDate.setDate(rassDate.getDate() + rassDays);
|
|
||||||
dueDates.sort((a, b) => a.getTime() - b.getTime());
|
dueDates.sort((a, b) => a.getTime() - b.getTime());
|
||||||
return {
|
return {
|
||||||
checkCount: checks.length,
|
checkCount: checks.length,
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"check-rass.js","sourceRoot":"","sources":["../../../src/common/utils/check-rass.ts"],"names":[],"mappings":";;AAoBA,gDA4CC;AAlDD,SAAS,UAAU,CAAC,IAAU;IAC5B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAgB,kBAAkB,CAChC,MAAwB,EACxB,WAAiB,IAAI,IAAI,EAAE;IAE3B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,IAAI;YACpB,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,QAAQ,GAAW,EAAE,CAAC;IAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CACrE,CAAC;QACF,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC;QAC5B,YAAY,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IACtC,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAEnD,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,WAAW;QACX,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI;QAClD,eAAe,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI;QACrE,QAAQ;QACR,QAAQ,EAAE,QAAQ,CAAC,WAAW,EAAE;KACjC,CAAC;AACJ,CAAC"}
|
{"version":3,"file":"check-rass.js","sourceRoot":"","sources":["../../../src/common/utils/check-rass.ts"],"names":[],"mappings":";;AAqBA,gDAwCC;AA/CD,+CAKuB;AAEvB,SAAgB,kBAAkB,CAChC,MAAwB,EACxB,WAAiB,IAAI,IAAI,EAAE;IAE3B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,IAAI;YACpB,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,+BAAiB,EAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,QAAQ,GAAW,EAAE,CAAC;IAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAA,2BAAa,EAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAA,wBAAU,EAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAChD,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC;QAC5B,YAAY,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IACtC,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,MAAM,QAAQ,GAAG,IAAA,qBAAO,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAEnD,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,WAAW;QACX,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI;QAClD,eAAe,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI;QACrE,QAAQ;QACR,QAAQ,EAAE,QAAQ,CAAC,WAAW,EAAE;KACjC,CAAC;AACJ,CAAC"}
|
||||||
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
export declare function resolveJwtSecret(config: ConfigService): string;
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.resolveJwtSecret = resolveJwtSecret;
|
||||||
|
const DEV_FALLBACK = 'fabric-trade-dev-secret';
|
||||||
|
function resolveJwtSecret(config) {
|
||||||
|
const secret = config.get('JWT_SECRET')?.trim();
|
||||||
|
if (secret)
|
||||||
|
return secret;
|
||||||
|
if (config.get('NODE_ENV') === 'production') {
|
||||||
|
throw new Error('JWT_SECRET تنظیم نشده است');
|
||||||
|
}
|
||||||
|
return DEV_FALLBACK;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=jwt-secret.js.map
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"jwt-secret.js","sourceRoot":"","sources":["../../../src/common/utils/jwt-secret.ts"],"names":[],"mappings":";;AAOA,4CAQC;AAbD,MAAM,YAAY,GAAG,yBAAyB,CAAC;AAK/C,SAAgB,gBAAgB,CAAC,MAAqB;IACpD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAS,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,IAAI,MAAM,CAAC,GAAG,CAAS,UAAU,CAAC,KAAK,YAAY,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC"}
|
||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"name.js","sourceRoot":"","sources":["../../../src/common/utils/name.ts"],"names":[],"mappings":";;AAAA,sCAgBC;AAED,oCAEC;AApBD,SAAgB,aAAa,CAAC,IAAY;IAIxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAChD,CAAC;IACD,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,CAAC,CAAE;QACpB,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,SAAgB,YAAY,CAAC,SAAiB,EAAE,QAAgB;IAC9D,OAAO,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;AAC3C,CAAC"}
|
{"version":3,"file":"name.js","sourceRoot":"","sources":["../../../src/common/utils/name.ts"],"names":[],"mappings":";;AAAA,sCAgBC;AAED,oCAEC;AApBD,SAAgB,aAAa,CAAC,IAAY;IAIxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;QACnB,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,SAAgB,YAAY,CAAC,SAAiB,EAAE,QAAgB;IAC9D,OAAO,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;AAC3C,CAAC"}
|
||||||
Vendored
+28
-4
@@ -5,18 +5,40 @@ exports.resolveAdminStatusFilter = resolveAdminStatusFilter;
|
|||||||
exports.toAdminStatus = toAdminStatus;
|
exports.toAdminStatus = toAdminStatus;
|
||||||
const client_1 = require("@prisma/client");
|
const client_1 = require("@prisma/client");
|
||||||
exports.ADMIN_STATUS_MAP = {
|
exports.ADMIN_STATUS_MAP = {
|
||||||
pending_review: [client_1.OrderStatus.awaiting_review, client_1.OrderStatus.pricing],
|
pending_review: [
|
||||||
|
client_1.OrderStatus.cart,
|
||||||
|
client_1.OrderStatus.awaiting_settlement,
|
||||||
|
client_1.OrderStatus.cash_in_progress,
|
||||||
|
client_1.OrderStatus.check_in_progress,
|
||||||
|
client_1.OrderStatus.submitted,
|
||||||
|
client_1.OrderStatus.awaiting_review,
|
||||||
|
client_1.OrderStatus.pricing,
|
||||||
|
client_1.OrderStatus.cash_invoice_issued,
|
||||||
|
client_1.OrderStatus.awaiting_cash_payment,
|
||||||
|
client_1.OrderStatus.cash_payment_submitted,
|
||||||
|
client_1.OrderStatus.awaiting_cash_confirmation,
|
||||||
|
],
|
||||||
pending_check: [client_1.OrderStatus.awaiting_check_review],
|
pending_check: [client_1.OrderStatus.awaiting_check_review],
|
||||||
needs_correction: [client_1.OrderStatus.needs_correction],
|
needs_correction: [
|
||||||
check_correction: [client_1.OrderStatus.check_needs_fix],
|
client_1.OrderStatus.needs_correction,
|
||||||
|
client_1.OrderStatus.awaiting_settlement_fix,
|
||||||
|
],
|
||||||
|
check_correction: [client_1.OrderStatus.check_needs_fix, client_1.OrderStatus.check_rejected],
|
||||||
final_approval: [
|
final_approval: [
|
||||||
client_1.OrderStatus.final_approved,
|
client_1.OrderStatus.final_approved,
|
||||||
client_1.OrderStatus.checks_approved,
|
client_1.OrderStatus.checks_approved,
|
||||||
client_1.OrderStatus.cash_confirmed,
|
client_1.OrderStatus.cash_confirmed,
|
||||||
|
client_1.OrderStatus.preparing,
|
||||||
|
client_1.OrderStatus.ready_to_ship,
|
||||||
],
|
],
|
||||||
shipped: [client_1.OrderStatus.shipped],
|
shipped: [client_1.OrderStatus.shipped],
|
||||||
delivered: [client_1.OrderStatus.delivered],
|
delivered: [client_1.OrderStatus.delivered],
|
||||||
};
|
};
|
||||||
|
const TERMINAL_STATUSES = [
|
||||||
|
client_1.OrderStatus.cancelled,
|
||||||
|
client_1.OrderStatus.rejected,
|
||||||
|
client_1.OrderStatus.expired,
|
||||||
|
];
|
||||||
function resolveAdminStatusFilter(status) {
|
function resolveAdminStatusFilter(status) {
|
||||||
if (!status)
|
if (!status)
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -32,7 +54,9 @@ function toAdminStatus(status) {
|
|||||||
if (list.includes(status))
|
if (list.includes(status))
|
||||||
return admin;
|
return admin;
|
||||||
}
|
}
|
||||||
return status;
|
if (TERMINAL_STATUSES.includes(status))
|
||||||
|
return status;
|
||||||
|
return 'pending_review';
|
||||||
}
|
}
|
||||||
exports.ORDER_STATUS_LABELS = {
|
exports.ORDER_STATUS_LABELS = {
|
||||||
cart: 'سبد خرید',
|
cart: 'سبد خرید',
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"order-status.js","sourceRoot":"","sources":["../../../src/common/utils/order-status.ts"],"names":[],"mappings":";;;AAiBA,4DASC;AAED,sCAKC;AAjCD,2CAA6C;AAGhC,QAAA,gBAAgB,GAAkC;IAC7D,cAAc,EAAE,CAAC,oBAAW,CAAC,eAAe,EAAE,oBAAW,CAAC,OAAO,CAAC;IAClE,aAAa,EAAE,CAAC,oBAAW,CAAC,qBAAqB,CAAC;IAClD,gBAAgB,EAAE,CAAC,oBAAW,CAAC,gBAAgB,CAAC;IAChD,gBAAgB,EAAE,CAAC,oBAAW,CAAC,eAAe,CAAC;IAC/C,cAAc,EAAE;QACd,oBAAW,CAAC,cAAc;QAC1B,oBAAW,CAAC,eAAe;QAC3B,oBAAW,CAAC,cAAc;KAC3B;IACD,OAAO,EAAE,CAAC,oBAAW,CAAC,OAAO,CAAC;IAC9B,SAAS,EAAE,CAAC,oBAAW,CAAC,SAAS,CAAC;CACnC,CAAC;AAEF,SAAgB,wBAAwB,CACtC,MAAe;IAEf,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,wBAAgB,CAAC,MAAM,CAAC;QAAE,OAAO,wBAAgB,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,MAAM,CAAC,oBAAW,CAAC,CAAC,QAAQ,CAAC,MAAqB,CAAC,EAAE,CAAC;QAC/D,OAAO,CAAC,MAAqB,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,aAAa,CAAC,MAAmB;IAC/C,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,wBAAgB,CAAC,EAAE,CAAC;QAC7D,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;IAC1C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAEY,QAAA,mBAAmB,GAAgC;IAC9D,IAAI,EAAE,UAAU;IAChB,mBAAmB,EAAE,iBAAiB;IACtC,gBAAgB,EAAE,iBAAiB;IACnC,iBAAiB,EAAE,eAAe;IAClC,SAAS,EAAE,SAAS;IACpB,eAAe,EAAE,iBAAiB;IAClC,OAAO,EAAE,YAAY;IACrB,gBAAgB,EAAE,eAAe;IACjC,uBAAuB,EAAE,aAAa;IACtC,mBAAmB,EAAE,kBAAkB;IACvC,qBAAqB,EAAE,uBAAuB;IAC9C,sBAAsB,EAAE,qBAAqB;IAC7C,0BAA0B,EAAE,mBAAmB;IAC/C,cAAc,EAAE,sBAAsB;IACtC,qBAAqB,EAAE,UAAU;IACjC,eAAe,EAAE,UAAU;IAC3B,cAAc,EAAE,OAAO;IACvB,eAAe,EAAE,aAAa;IAC9B,cAAc,EAAE,aAAa;IAC7B,SAAS,EAAE,YAAY;IACvB,aAAa,EAAE,aAAa;IAC5B,OAAO,EAAE,WAAW;IACpB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,SAAS;IACpB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,OAAO;CACjB,CAAC"}
|
{"version":3,"file":"order-status.js","sourceRoot":"","sources":["../../../src/common/utils/order-status.ts"],"names":[],"mappings":"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"}
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
export declare function tehranCalendarDay(date: Date): Date;
|
||||||
|
export declare function calendarDayOf(date: Date | string): Date;
|
||||||
|
export declare function addDays(date: Date, days: number): Date;
|
||||||
|
export declare function diffInDays(from: Date, to: Date): number;
|
||||||
|
export declare function tehranAtHour(date: Date, hour: number): Date;
|
||||||
Vendored
+32
@@ -0,0 +1,32 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.tehranCalendarDay = tehranCalendarDay;
|
||||||
|
exports.calendarDayOf = calendarDayOf;
|
||||||
|
exports.addDays = addDays;
|
||||||
|
exports.diffInDays = diffInDays;
|
||||||
|
exports.tehranAtHour = tehranAtHour;
|
||||||
|
const TEHRAN_OFFSET_MS = (3 * 60 + 30) * 60 * 1000;
|
||||||
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
||||||
|
function utcStartOfDay(date) {
|
||||||
|
const d = new Date(date);
|
||||||
|
d.setUTCHours(0, 0, 0, 0);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
function tehranCalendarDay(date) {
|
||||||
|
return utcStartOfDay(new Date(date.getTime() + TEHRAN_OFFSET_MS));
|
||||||
|
}
|
||||||
|
function calendarDayOf(date) {
|
||||||
|
return utcStartOfDay(new Date(date));
|
||||||
|
}
|
||||||
|
function addDays(date, days) {
|
||||||
|
return new Date(date.getTime() + days * DAY_MS);
|
||||||
|
}
|
||||||
|
function diffInDays(from, to) {
|
||||||
|
return Math.round((to.getTime() - from.getTime()) / DAY_MS);
|
||||||
|
}
|
||||||
|
function tehranAtHour(date, hour) {
|
||||||
|
return new Date(tehranCalendarDay(date).getTime() +
|
||||||
|
hour * 60 * 60 * 1000 -
|
||||||
|
TEHRAN_OFFSET_MS);
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=tehran-time.js.map
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"tehran-time.js","sourceRoot":"","sources":["../../../src/common/utils/tehran-time.ts"],"names":[],"mappings":";;AAiBA,8CAEC;AAGD,sCAEC;AAED,0BAEC;AAED,gCAEC;AAGD,oCAMC;AArCD,MAAM,gBAAgB,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACnD,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnC,SAAS,aAAa,CAAC,IAAU;IAC/B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,OAAO,CAAC,CAAC;AACX,CAAC;AAMD,SAAgB,iBAAiB,CAAC,IAAU;IAC1C,OAAO,aAAa,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC;AACpE,CAAC;AAGD,SAAgB,aAAa,CAAC,IAAmB;IAC/C,OAAO,aAAa,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAgB,OAAO,CAAC,IAAU,EAAE,IAAY;IAC9C,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,SAAgB,UAAU,CAAC,IAAU,EAAE,EAAQ;IAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC;AAC9D,CAAC;AAGD,SAAgB,YAAY,CAAC,IAAU,EAAE,IAAY;IACnD,OAAO,IAAI,IAAI,CACb,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE;QAC/B,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;QACrB,gBAAgB,CACnB,CAAC;AACJ,CAAC"}
|
||||||
Vendored
+19
-7
@@ -23,7 +23,9 @@ let CompaniesService = class CompaniesService {
|
|||||||
where: activeOnly ? { isActive: true } : undefined,
|
where: activeOnly ? { isActive: true } : undefined,
|
||||||
orderBy: [{ displayOrder: 'asc' }, { name: 'asc' }],
|
orderBy: [{ displayOrder: 'asc' }, { name: 'asc' }],
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return companies.map((c) => this.mapCompany(c));
|
return companies.map((c) => this.mapCompany(c));
|
||||||
@@ -33,7 +35,9 @@ let CompaniesService = class CompaniesService {
|
|||||||
where: { id },
|
where: { id },
|
||||||
include: {
|
include: {
|
||||||
bankAccounts: { orderBy: { displayOrder: 'asc' } },
|
bankAccounts: { orderBy: { displayOrder: 'asc' } },
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!company)
|
if (!company)
|
||||||
@@ -58,13 +62,16 @@ let CompaniesService = class CompaniesService {
|
|||||||
isActive: dto.isActive ?? true,
|
isActive: dto.isActive ?? true,
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return this.mapCompany(company);
|
return this.mapCompany(company);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('اسلاگ شرکت تکراری است');
|
throw new common_1.ConflictException('اسلاگ شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -89,13 +96,16 @@ let CompaniesService = class CompaniesService {
|
|||||||
isActive: dto.isActive,
|
isActive: dto.isActive,
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return this.mapCompany(company);
|
return this.mapCompany(company);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('اسلاگ شرکت تکراری است');
|
throw new common_1.ConflictException('اسلاگ شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -107,7 +117,9 @@ let CompaniesService = class CompaniesService {
|
|||||||
where: { id },
|
where: { id },
|
||||||
data: { isActive },
|
data: { isActive },
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return this.mapCompany(company);
|
return this.mapCompany(company);
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+7
-3
@@ -84,7 +84,8 @@ let CustomersService = class CustomersService {
|
|||||||
return this.map(customer);
|
return this.map(customer);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('این شماره قبلاً ثبت شده است');
|
throw new common_1.ConflictException('این شماره قبلاً ثبت شده است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -100,7 +101,9 @@ let CustomersService = class CustomersService {
|
|||||||
}
|
}
|
||||||
let firstName;
|
let firstName;
|
||||||
let lastName;
|
let lastName;
|
||||||
if (dto.name !== undefined || dto.firstName !== undefined || dto.lastName !== undefined) {
|
if (dto.name !== undefined ||
|
||||||
|
dto.firstName !== undefined ||
|
||||||
|
dto.lastName !== undefined) {
|
||||||
const names = this.resolveNames(dto);
|
const names = this.resolveNames(dto);
|
||||||
firstName = names.firstName;
|
firstName = names.firstName;
|
||||||
lastName = names.lastName;
|
lastName = names.lastName;
|
||||||
@@ -127,7 +130,8 @@ let CustomersService = class CustomersService {
|
|||||||
return this.map(customer);
|
return this.map(customer);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('این شماره قبلاً ثبت شده است');
|
throw new common_1.ConflictException('این شماره قبلاً ثبت شده است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+6
-1
@@ -186,7 +186,12 @@ let DashboardService = class DashboardService {
|
|||||||
{ id: 'cd-today', label: 'امروز', tone: 'danger', days: 0 },
|
{ id: 'cd-today', label: 'امروز', tone: 'danger', days: 0 },
|
||||||
{ id: 'cd-3', label: '۳ روز آینده', tone: 'warning', days: 3 },
|
{ id: 'cd-3', label: '۳ روز آینده', tone: 'warning', days: 3 },
|
||||||
{ id: 'cd-7', label: '۷ روز آینده', tone: 'warning', days: 7 },
|
{ id: 'cd-7', label: '۷ روز آینده', tone: 'warning', days: 7 },
|
||||||
{ id: 'cd-30', label: '۳۰ روز آینده', tone: 'neutral', days: 30 },
|
{
|
||||||
|
id: 'cd-30',
|
||||||
|
label: '۳۰ روز آینده',
|
||||||
|
tone: 'neutral',
|
||||||
|
days: 30,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
return buckets.map((bucket) => {
|
return buckets.map((bucket) => {
|
||||||
const end = new Date(startOfToday);
|
const end = new Date(startOfToday);
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+5
-1
@@ -3,9 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const core_1 = require("@nestjs/core");
|
const core_1 = require("@nestjs/core");
|
||||||
const common_1 = require("@nestjs/common");
|
const common_1 = require("@nestjs/common");
|
||||||
const swagger_1 = require("@nestjs/swagger");
|
const swagger_1 = require("@nestjs/swagger");
|
||||||
|
const express_1 = require("express");
|
||||||
const app_module_1 = require("./app.module");
|
const app_module_1 = require("./app.module");
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await core_1.NestFactory.create(app_module_1.AppModule);
|
const app = await core_1.NestFactory.create(app_module_1.AppModule);
|
||||||
|
const bodyLimit = process.env.BODY_LIMIT || '25mb';
|
||||||
|
app.use((0, express_1.json)({ limit: bodyLimit }));
|
||||||
|
app.use((0, express_1.urlencoded)({ extended: true, limit: bodyLimit }));
|
||||||
const globalPrefix = process.env.GLOBAL_PREFIX || 'api';
|
const globalPrefix = process.env.GLOBAL_PREFIX || 'api';
|
||||||
app.setGlobalPrefix(globalPrefix);
|
app.setGlobalPrefix(globalPrefix);
|
||||||
app.enableCors({
|
app.enableCors({
|
||||||
@@ -31,5 +35,5 @@ async function bootstrap() {
|
|||||||
console.log(`Fabric Trade API listening on http://localhost:${port}/${globalPrefix}`);
|
console.log(`Fabric Trade API listening on http://localhost:${port}/${globalPrefix}`);
|
||||||
console.log(`Swagger docs at http://localhost:${port}/${globalPrefix}/docs`);
|
console.log(`Swagger docs at http://localhost:${port}/${globalPrefix}/docs`);
|
||||||
}
|
}
|
||||||
bootstrap();
|
void bootstrap();
|
||||||
//# sourceMappingURL=main.js.map
|
//# sourceMappingURL=main.js.map
|
||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,2CAAgD;AAChD,6CAAiE;AACjE,6CAAyC;AAEzC,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,CAAC,CAAC;IAGhD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,KAAK,CAAC;IACxD,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAClC,GAAG,CAAC,UAAU,CAAC;QACb,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IACH,GAAG,CAAC,cAAc,CAChB,IAAI,uBAAc,CAAC;QACjB,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,oBAAoB,EAAE,IAAI;QAC1B,gBAAgB,EAAE,EAAE,wBAAwB,EAAE,IAAI,EAAE;KACrD,CAAC,CACH,CAAC;IAEF,MAAM,aAAa,GAAG,IAAI,yBAAe,EAAE;SACxC,QAAQ,CAAC,kBAAkB,CAAC;SAC5B,cAAc,CAAC,sBAAsB,CAAC;SACtC,UAAU,CAAC,KAAK,CAAC;SACjB,aAAa,EAAE;SACf,KAAK,EAAE,CAAC;IACX,MAAM,QAAQ,GAAG,uBAAa,CAAC,cAAc,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAClE,uBAAa,CAAC,KAAK,CAAC,GAAG,YAAY,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IAE3D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;IACtC,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,kDAAkD,IAAI,IAAI,YAAY,EAAE,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,CAAC,oCAAoC,IAAI,IAAI,YAAY,OAAO,CAAC,CAAC;AAC/E,CAAC;AACD,SAAS,EAAE,CAAC"}
|
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,2CAAgD;AAChD,6CAAiE;AACjE,qCAA2C;AAC3C,6CAAyC;AAEzC,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,CAAC,CAAC;IAGhD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,CAAC;IACnD,GAAG,CAAC,GAAG,CAAC,IAAA,cAAI,EAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IACpC,GAAG,CAAC,GAAG,CAAC,IAAA,oBAAU,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAG1D,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,KAAK,CAAC;IACxD,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAClC,GAAG,CAAC,UAAU,CAAC;QACb,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IACH,GAAG,CAAC,cAAc,CAChB,IAAI,uBAAc,CAAC;QACjB,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,oBAAoB,EAAE,IAAI;QAC1B,gBAAgB,EAAE,EAAE,wBAAwB,EAAE,IAAI,EAAE;KACrD,CAAC,CACH,CAAC;IAEF,MAAM,aAAa,GAAG,IAAI,yBAAe,EAAE;SACxC,QAAQ,CAAC,kBAAkB,CAAC;SAC5B,cAAc,CAAC,sBAAsB,CAAC;SACtC,UAAU,CAAC,KAAK,CAAC;SACjB,aAAa,EAAE;SACf,KAAK,EAAE,CAAC;IACX,MAAM,QAAQ,GAAG,uBAAa,CAAC,cAAc,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAClE,uBAAa,CAAC,KAAK,CAAC,GAAG,YAAY,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IAE3D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;IACtC,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,CACT,kDAAkD,IAAI,IAAI,YAAY,EAAE,CACzE,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,oCAAoC,IAAI,IAAI,YAAY,OAAO,CAAC,CAAC;AAC/E,CAAC;AACD,KAAK,SAAS,EAAE,CAAC"}
|
||||||
Vendored
+2
@@ -2,6 +2,7 @@ import { CheckRegistrationMode, OrderStatus, SettlementType } from '@prisma/clie
|
|||||||
export declare class SubmitOrderItemDto {
|
export declare class SubmitOrderItemDto {
|
||||||
productId: string;
|
productId: string;
|
||||||
meterage: number;
|
meterage: number;
|
||||||
|
requestedMeterage?: number;
|
||||||
notes?: string;
|
notes?: string;
|
||||||
}
|
}
|
||||||
export declare class SubmitOrderCheckDto {
|
export declare class SubmitOrderCheckDto {
|
||||||
@@ -22,6 +23,7 @@ export declare class SubmitOrderCheckDto {
|
|||||||
export declare class SubmitOrderDto {
|
export declare class SubmitOrderDto {
|
||||||
companyId: string;
|
companyId: string;
|
||||||
settlementType: SettlementType;
|
settlementType: SettlementType;
|
||||||
|
settlementMethod?: SettlementType;
|
||||||
checkMode?: CheckRegistrationMode;
|
checkMode?: CheckRegistrationMode;
|
||||||
notes?: string;
|
notes?: string;
|
||||||
items: SubmitOrderItemDto[];
|
items: SubmitOrderItemDto[];
|
||||||
|
|||||||
Vendored
+13
@@ -16,6 +16,7 @@ const client_1 = require("@prisma/client");
|
|||||||
class SubmitOrderItemDto {
|
class SubmitOrderItemDto {
|
||||||
productId;
|
productId;
|
||||||
meterage;
|
meterage;
|
||||||
|
requestedMeterage;
|
||||||
notes;
|
notes;
|
||||||
}
|
}
|
||||||
exports.SubmitOrderItemDto = SubmitOrderItemDto;
|
exports.SubmitOrderItemDto = SubmitOrderItemDto;
|
||||||
@@ -29,6 +30,12 @@ __decorate([
|
|||||||
(0, class_validator_1.Min)(0.001),
|
(0, class_validator_1.Min)(0.001),
|
||||||
__metadata("design:type", Number)
|
__metadata("design:type", Number)
|
||||||
], SubmitOrderItemDto.prototype, "meterage", void 0);
|
], SubmitOrderItemDto.prototype, "meterage", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, class_validator_1.IsOptional)(),
|
||||||
|
(0, class_transformer_1.Type)(() => Number),
|
||||||
|
(0, class_validator_1.IsNumber)(),
|
||||||
|
__metadata("design:type", Number)
|
||||||
|
], SubmitOrderItemDto.prototype, "requestedMeterage", void 0);
|
||||||
__decorate([
|
__decorate([
|
||||||
(0, class_validator_1.IsOptional)(),
|
(0, class_validator_1.IsOptional)(),
|
||||||
(0, class_validator_1.IsString)(),
|
(0, class_validator_1.IsString)(),
|
||||||
@@ -118,6 +125,7 @@ __decorate([
|
|||||||
class SubmitOrderDto {
|
class SubmitOrderDto {
|
||||||
companyId;
|
companyId;
|
||||||
settlementType;
|
settlementType;
|
||||||
|
settlementMethod;
|
||||||
checkMode;
|
checkMode;
|
||||||
notes;
|
notes;
|
||||||
items;
|
items;
|
||||||
@@ -132,6 +140,11 @@ __decorate([
|
|||||||
(0, class_validator_1.IsEnum)(client_1.SettlementType),
|
(0, class_validator_1.IsEnum)(client_1.SettlementType),
|
||||||
__metadata("design:type", String)
|
__metadata("design:type", String)
|
||||||
], SubmitOrderDto.prototype, "settlementType", void 0);
|
], SubmitOrderDto.prototype, "settlementType", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, class_validator_1.IsOptional)(),
|
||||||
|
(0, class_validator_1.IsEnum)(client_1.SettlementType),
|
||||||
|
__metadata("design:type", String)
|
||||||
|
], SubmitOrderDto.prototype, "settlementMethod", void 0);
|
||||||
__decorate([
|
__decorate([
|
||||||
(0, class_validator_1.IsOptional)(),
|
(0, class_validator_1.IsOptional)(),
|
||||||
(0, class_validator_1.IsEnum)(client_1.CheckRegistrationMode),
|
(0, class_validator_1.IsEnum)(client_1.CheckRegistrationMode),
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"order.dto.js","sourceRoot":"","sources":["../../../src/orders/dto/order.dto.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"order.dto.js","sourceRoot":"","sources":["../../../src/orders/dto/order.dto.ts"],"names":[],"mappings":"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"}
|
||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"orders.controller.js","sourceRoot":"","sources":["../../src/orders/orders.controller.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"orders.controller.js","sourceRoot":"","sources":["../../src/orders/orders.controller.ts"],"names":[],"mappings":"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"}
|
||||||
Vendored
+1
@@ -938,6 +938,7 @@ export declare class OrdersService {
|
|||||||
}>;
|
}>;
|
||||||
private mapCheckCreate;
|
private mapCheckCreate;
|
||||||
private nextOrderNumber;
|
private nextOrderNumber;
|
||||||
|
private createWithUniqueOrderNumber;
|
||||||
private getOrder;
|
private getOrder;
|
||||||
mapOrder(order: OrderFull, adminView?: boolean): {
|
mapOrder(order: OrderFull, adminView?: boolean): {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
Vendored
+58
-20
@@ -28,6 +28,19 @@ const orderInclude = {
|
|||||||
user: true,
|
user: true,
|
||||||
company: true,
|
company: true,
|
||||||
};
|
};
|
||||||
|
function roundMoney(value) {
|
||||||
|
return Math.round(value * 100) / 100;
|
||||||
|
}
|
||||||
|
const CHECK_EDITABLE_STATUSES = [
|
||||||
|
client_1.OrderStatus.awaiting_review,
|
||||||
|
client_1.OrderStatus.pricing,
|
||||||
|
client_1.OrderStatus.needs_correction,
|
||||||
|
client_1.OrderStatus.awaiting_settlement_fix,
|
||||||
|
client_1.OrderStatus.check_in_progress,
|
||||||
|
client_1.OrderStatus.awaiting_check_review,
|
||||||
|
client_1.OrderStatus.check_needs_fix,
|
||||||
|
client_1.OrderStatus.check_rejected,
|
||||||
|
];
|
||||||
let OrdersService = class OrdersService {
|
let OrdersService = class OrdersService {
|
||||||
prisma;
|
prisma;
|
||||||
constructor(prisma) {
|
constructor(prisma) {
|
||||||
@@ -140,8 +153,7 @@ let OrdersService = class OrdersService {
|
|||||||
const cashInvoiceExpiresAt = settlementType === client_1.SettlementType.cash
|
const cashInvoiceExpiresAt = settlementType === client_1.SettlementType.cash
|
||||||
? (0, cash_expiry_1.computeCashInvoiceExpiry)(company)
|
? (0, cash_expiry_1.computeCashInvoiceExpiry)(company)
|
||||||
: null;
|
: null;
|
||||||
const orderNumber = await this.nextOrderNumber();
|
const order = await this.createWithUniqueOrderNumber((orderNumber) => this.prisma.$transaction(async (tx) => {
|
||||||
const order = await this.prisma.$transaction(async (tx) => {
|
|
||||||
const created = await tx.order.create({
|
const created = await tx.order.create({
|
||||||
data: {
|
data: {
|
||||||
orderNumber,
|
orderNumber,
|
||||||
@@ -188,7 +200,7 @@ let OrdersService = class OrdersService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return created;
|
return created;
|
||||||
});
|
}));
|
||||||
return this.mapOrder(order);
|
return this.mapOrder(order);
|
||||||
}
|
}
|
||||||
async adminCreate(adminId, dto) {
|
async adminCreate(adminId, dto) {
|
||||||
@@ -207,7 +219,9 @@ let OrdersService = class OrdersService {
|
|||||||
if (!(0, phone_1.isValidPhone)(phone)) {
|
if (!(0, phone_1.isValidPhone)(phone)) {
|
||||||
throw new common_1.BadRequestException('شماره موبایل نامعتبر است');
|
throw new common_1.BadRequestException('شماره موبایل نامعتبر است');
|
||||||
}
|
}
|
||||||
let customer = await this.prisma.customer.findUnique({ where: { phone } });
|
let customer = await this.prisma.customer.findUnique({
|
||||||
|
where: { phone },
|
||||||
|
});
|
||||||
if (!customer) {
|
if (!customer) {
|
||||||
const names = (0, name_1.splitFullName)(dto.customerName || 'مشتری جدید');
|
const names = (0, name_1.splitFullName)(dto.customerName || 'مشتری جدید');
|
||||||
customer = await this.prisma.customer.create({
|
customer = await this.prisma.customer.create({
|
||||||
@@ -223,12 +237,12 @@ let OrdersService = class OrdersService {
|
|||||||
if (!userId) {
|
if (!userId) {
|
||||||
throw new common_1.BadRequestException('شناسه یا شماره مشتری الزامی است');
|
throw new common_1.BadRequestException('شناسه یا شماره مشتری الزامی است');
|
||||||
}
|
}
|
||||||
const orderNumber = await this.nextOrderNumber();
|
|
||||||
const totalMeterage = dto.meterage ?? 0;
|
const totalMeterage = dto.meterage ?? 0;
|
||||||
const order = await this.prisma.order.create({
|
const ownerId = userId;
|
||||||
|
const order = await this.createWithUniqueOrderNumber((orderNumber) => this.prisma.order.create({
|
||||||
data: {
|
data: {
|
||||||
orderNumber,
|
orderNumber,
|
||||||
userId,
|
userId: ownerId,
|
||||||
companyId: company.id,
|
companyId: company.id,
|
||||||
companyName: company.name,
|
companyName: company.name,
|
||||||
settlementType,
|
settlementType,
|
||||||
@@ -245,33 +259,39 @@ let OrdersService = class OrdersService {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
include: orderInclude,
|
include: orderInclude,
|
||||||
});
|
}));
|
||||||
return this.mapOrder(order, true);
|
return this.mapOrder(order, true);
|
||||||
}
|
}
|
||||||
async updatePricing(id, adminId, dto) {
|
async updatePricing(id, adminId, dto) {
|
||||||
const order = await this.getOrder(id);
|
const order = await this.getOrder(id);
|
||||||
|
const unknown = dto.items.find((item) => !order.items.some((i) => i.id === item.id));
|
||||||
|
if (unknown) {
|
||||||
|
throw new common_1.BadRequestException(`آیتم ${unknown.id} یافت نشد`);
|
||||||
|
}
|
||||||
await this.prisma.$transaction(async (tx) => {
|
await this.prisma.$transaction(async (tx) => {
|
||||||
let totalAmount = 0;
|
let totalAmount = 0;
|
||||||
let totalMeterage = 0;
|
let totalMeterage = 0;
|
||||||
for (const item of dto.items) {
|
for (const existing of order.items) {
|
||||||
const existing = order.items.find((i) => i.id === item.id);
|
const item = dto.items.find((i) => i.id === existing.id);
|
||||||
if (!existing) {
|
const unitPrice = item?.unitPrice !== undefined
|
||||||
throw new common_1.BadRequestException(`آیتم ${item.id} یافت نشد`);
|
|
||||||
}
|
|
||||||
const unitPrice = item.unitPrice !== undefined
|
|
||||||
? item.unitPrice
|
? item.unitPrice
|
||||||
: item.supplyPrice !== undefined
|
: item?.supplyPrice !== undefined
|
||||||
? item.supplyPrice
|
? item.supplyPrice
|
||||||
: (existing.unitPrice ?? 0);
|
: (existing.unitPrice ?? 0);
|
||||||
const unitDiscount = item.unitDiscount ?? existing.unitDiscount ?? 0;
|
const unitDiscount = item?.unitDiscount ?? existing.unitDiscount ?? 0;
|
||||||
const confirmed = item.confirmedMeterage ??
|
if (unitDiscount > unitPrice) {
|
||||||
|
throw new common_1.BadRequestException('تخفیف واحد نمیتواند از قیمت واحد بیشتر باشد');
|
||||||
|
}
|
||||||
|
const confirmed = item?.confirmedMeterage ??
|
||||||
existing.confirmedMeterage ??
|
existing.confirmedMeterage ??
|
||||||
existing.requestedMeterage;
|
existing.requestedMeterage;
|
||||||
const lineTotal = Math.max(0, (unitPrice - unitDiscount) * confirmed);
|
const lineTotal = roundMoney(Math.max(0, (unitPrice - unitDiscount) * confirmed));
|
||||||
totalAmount += lineTotal;
|
totalAmount += lineTotal;
|
||||||
totalMeterage += confirmed;
|
totalMeterage += confirmed;
|
||||||
|
if (!item)
|
||||||
|
continue;
|
||||||
await tx.orderItem.update({
|
await tx.orderItem.update({
|
||||||
where: { id: item.id },
|
where: { id: existing.id },
|
||||||
data: {
|
data: {
|
||||||
confirmedMeterage: confirmed,
|
confirmedMeterage: confirmed,
|
||||||
unitPrice,
|
unitPrice,
|
||||||
@@ -280,9 +300,10 @@ let OrdersService = class OrdersService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
totalAmount = roundMoney(totalAmount);
|
||||||
const shippingCost = dto.shippingCost ?? order.shippingCost ?? 0;
|
const shippingCost = dto.shippingCost ?? order.shippingCost ?? 0;
|
||||||
const totalDiscount = dto.totalDiscount ?? order.totalDiscount ?? 0;
|
const totalDiscount = dto.totalDiscount ?? order.totalDiscount ?? 0;
|
||||||
const finalAmount = Math.max(0, totalAmount + shippingCost - totalDiscount);
|
const finalAmount = roundMoney(Math.max(0, totalAmount + shippingCost - totalDiscount));
|
||||||
const nextStatus = order.status === client_1.OrderStatus.awaiting_review ||
|
const nextStatus = order.status === client_1.OrderStatus.awaiting_review ||
|
||||||
order.status === client_1.OrderStatus.pricing
|
order.status === client_1.OrderStatus.pricing
|
||||||
? client_1.OrderStatus.pricing
|
? client_1.OrderStatus.pricing
|
||||||
@@ -354,6 +375,9 @@ let OrdersService = class OrdersService {
|
|||||||
if (order.settlementType !== client_1.SettlementType.check) {
|
if (order.settlementType !== client_1.SettlementType.check) {
|
||||||
throw new common_1.BadRequestException('این سفارش تسویه چکی نیست');
|
throw new common_1.BadRequestException('این سفارش تسویه چکی نیست');
|
||||||
}
|
}
|
||||||
|
if (!CHECK_EDITABLE_STATUSES.includes(order.status)) {
|
||||||
|
throw new common_1.BadRequestException('در وضعیت فعلی سفارش امکان ویرایش چکها وجود ندارد');
|
||||||
|
}
|
||||||
const checkMode = dto.checkMode ?? order.checkMode ?? client_1.CheckRegistrationMode.full;
|
const checkMode = dto.checkMode ?? order.checkMode ?? client_1.CheckRegistrationMode.full;
|
||||||
const rass = (0, check_rass_1.calculateCheckRass)(dto.checks.map((c) => ({ amount: c.amount, dueDate: c.dueDate })), order.createdAt);
|
const rass = (0, check_rass_1.calculateCheckRass)(dto.checks.map((c) => ({ amount: c.amount, dueDate: c.dueDate })), order.createdAt);
|
||||||
await this.prisma.$transaction(async (tx) => {
|
await this.prisma.$transaction(async (tx) => {
|
||||||
@@ -418,6 +442,20 @@ let OrdersService = class OrdersService {
|
|||||||
}
|
}
|
||||||
return `${(0, order_number_1.generateOrderNumber)()}-${Date.now().toString().slice(-3)}`;
|
return `${(0, order_number_1.generateOrderNumber)()}-${Date.now().toString().slice(-3)}`;
|
||||||
}
|
}
|
||||||
|
async createWithUniqueOrderNumber(create) {
|
||||||
|
for (let attempt = 0;; attempt++) {
|
||||||
|
const orderNumber = await this.nextOrderNumber();
|
||||||
|
try {
|
||||||
|
return await create(orderNumber);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
const isDuplicate = e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002';
|
||||||
|
if (!isDuplicate || attempt >= 4)
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
async getOrder(id) {
|
async getOrder(id) {
|
||||||
const order = await this.prisma.order.findUnique({
|
const order = await this.prisma.order.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+4
-2
@@ -83,7 +83,8 @@ let ProductsService = class ProductsService {
|
|||||||
return this.map(product);
|
return this.map(product);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('کد محصول در این شرکت تکراری است');
|
throw new common_1.ConflictException('کد محصول در این شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -131,7 +132,8 @@ let ProductsService = class ProductsService {
|
|||||||
return this.map(product);
|
return this.map(product);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (e instanceof client_1.Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002') {
|
||||||
throw new common_1.ConflictException('کد محصول در این شرکت تکراری است');
|
throw new common_1.ConflictException('کد محصول در این شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"shipments.controller.js","sourceRoot":"","sources":["../../src/shipments/shipments.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAQwB;AACxB,2CAAgD;AAChD,2DAAuD;AACvD,0EAAgE;AAChE,wFAA0E;AAE1E,qDAI4B;AAIrB,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IACD;IAA7B,YAA6B,gBAAkC;QAAlC,qBAAgB,GAAhB,gBAAgB,CAAkB;IAAG,CAAC;IAGnE,OAAO,CAAkB,MAAuB;QAC9C,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;IAGD,OAAO,CAAc,EAAU;QAC7B,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3C,CAAC;IAGD,MAAM,CACW,IAAmB,EAC1B,GAAsB;QAE9B,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACpD,CAAC;IAGD,MAAM,CAAc,EAAU,EAAU,GAAsB;QAC5D,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/C,CAAC;IAGD,aAAa,CACI,IAAmB,EACrB,EAAU,EACf,GAA6B;QAErC,OAAO,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;CACF,CAAA;AAlCY,kDAAmB;AAI9B;IADC,IAAA,YAAG,GAAE;IACG,WAAA,IAAA,cAAK,EAAC,QAAQ,CAAC,CAAA;;;;kDAEvB;AAGD;IADC,IAAA,YAAG,EAAC,KAAK,CAAC;IACF,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;;;;kDAEnB;AAGD;IADC,IAAA,aAAI,GAAE;IAEJ,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,gCAAiB;;iDAG/B;AAGD;IADC,IAAA,cAAK,EAAC,KAAK,CAAC;IACL,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;IAAc,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,gCAAiB;;iDAE7D;AAGD;IADC,IAAA,cAAK,EAAC,YAAY,CAAC;IAEjB,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;IACX,WAAA,IAAA,aAAI,GAAE,CAAA;;qDAAM,uCAAwB;;wDAGtC;8BAjCU,mBAAmB;IAF/B,IAAA,mBAAU,EAAC,iBAAiB,CAAC;IAC7B,IAAA,0BAAQ,EAAC,OAAO,CAAC;qCAE+B,oCAAgB;GADpD,mBAAmB,CAkC/B"}
|
{"version":3,"file":"shipments.controller.js","sourceRoot":"","sources":["../../src/shipments/shipments.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAQwB;AACxB,2CAAgD;AAChD,2DAAuD;AACvD,0EAAgE;AAChE,wFAA0E;AAE1E,qDAI4B;AAIrB,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IACD;IAA7B,YAA6B,gBAAkC;QAAlC,qBAAgB,GAAhB,gBAAgB,CAAkB;IAAG,CAAC;IAGnE,OAAO,CAAkB,MAAuB;QAC9C,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;IAGD,OAAO,CAAc,EAAU;QAC7B,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3C,CAAC;IAGD,MAAM,CAAgB,IAAmB,EAAU,GAAsB;QACvE,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACpD,CAAC;IAGD,MAAM,CAAc,EAAU,EAAU,GAAsB;QAC5D,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/C,CAAC;IAGD,aAAa,CACI,IAAmB,EACrB,EAAU,EACf,GAA6B;QAErC,OAAO,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/D,CAAC;CACF,CAAA;AA/BY,kDAAmB;AAI9B;IADC,IAAA,YAAG,GAAE;IACG,WAAA,IAAA,cAAK,EAAC,QAAQ,CAAC,CAAA;;;;kDAEvB;AAGD;IADC,IAAA,YAAG,EAAC,KAAK,CAAC;IACF,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;;;;kDAEnB;AAGD;IADC,IAAA,aAAI,GAAE;IACC,WAAA,IAAA,oCAAW,GAAE,CAAA;IAAuB,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,gCAAiB;;iDAExE;AAGD;IADC,IAAA,cAAK,EAAC,KAAK,CAAC;IACL,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;IAAc,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,gCAAiB;;iDAE7D;AAGD;IADC,IAAA,cAAK,EAAC,YAAY,CAAC;IAEjB,WAAA,IAAA,oCAAW,GAAE,CAAA;IACb,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;IACX,WAAA,IAAA,aAAI,GAAE,CAAA;;qDAAM,uCAAwB;;wDAGtC;8BA9BU,mBAAmB;IAF/B,IAAA,mBAAU,EAAC,iBAAiB,CAAC;IAC7B,IAAA,0BAAQ,EAAC,OAAO,CAAC;qCAE+B,oCAAgB;GADpD,mBAAmB,CA+B/B"}
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
export declare class SmsModule {
|
||||||
|
}
|
||||||
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
"use strict";
|
||||||
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||||
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||||
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||||
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||||
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.SmsModule = void 0;
|
||||||
|
const common_1 = require("@nestjs/common");
|
||||||
|
const sms_service_1 = require("./sms.service");
|
||||||
|
let SmsModule = class SmsModule {
|
||||||
|
};
|
||||||
|
exports.SmsModule = SmsModule;
|
||||||
|
exports.SmsModule = SmsModule = __decorate([
|
||||||
|
(0, common_1.Module)({
|
||||||
|
providers: [sms_service_1.SmsService],
|
||||||
|
exports: [sms_service_1.SmsService],
|
||||||
|
})
|
||||||
|
], SmsModule);
|
||||||
|
//# sourceMappingURL=sms.module.js.map
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"sms.module.js","sourceRoot":"","sources":["../../src/sms/sms.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,+CAA2C;AAMpC,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IAJrB,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,wBAAU,CAAC;QACvB,OAAO,EAAE,CAAC,wBAAU,CAAC;KACtB,CAAC;GACW,SAAS,CAAG"}
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
export type SmsSendResult = {
|
||||||
|
success: boolean;
|
||||||
|
raw: unknown;
|
||||||
|
};
|
||||||
|
export declare class SmsService {
|
||||||
|
private readonly config;
|
||||||
|
private readonly logger;
|
||||||
|
constructor(config: ConfigService);
|
||||||
|
isEnabled(): boolean;
|
||||||
|
send(to: string, message: string): Promise<SmsSendResult>;
|
||||||
|
buildOtpMessage(code: string): string;
|
||||||
|
private resolveHost;
|
||||||
|
}
|
||||||
Vendored
+104
@@ -0,0 +1,104 @@
|
|||||||
|
"use strict";
|
||||||
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||||
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||||
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||||
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||||
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||||
|
};
|
||||||
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||||
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||||
|
};
|
||||||
|
var SmsService_1;
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.SmsService = void 0;
|
||||||
|
const common_1 = require("@nestjs/common");
|
||||||
|
const config_1 = require("@nestjs/config");
|
||||||
|
function maskPhone(phone) {
|
||||||
|
return phone.length <= 4
|
||||||
|
? '****'
|
||||||
|
: `${phone.slice(0, 4)}****${phone.slice(-2)}`;
|
||||||
|
}
|
||||||
|
let SmsService = SmsService_1 = class SmsService {
|
||||||
|
config;
|
||||||
|
logger = new common_1.Logger(SmsService_1.name);
|
||||||
|
constructor(config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
isEnabled() {
|
||||||
|
const raw = (this.config.get('SMS_ENABLED', 'true') ?? 'true').toLowerCase();
|
||||||
|
return raw === '1' || raw === 'true' || raw === 'yes';
|
||||||
|
}
|
||||||
|
async send(to, message) {
|
||||||
|
const url = this.config.get('SMS_API_URL', 'http://185.231.112.101/api/createsms');
|
||||||
|
const secretKey = this.config.get('SMS_SECRET_KEY')?.trim();
|
||||||
|
if (!secretKey) {
|
||||||
|
this.logger.error('SMS_SECRET_KEY تنظیم نشده است');
|
||||||
|
return { success: false, raw: 'SMS_SECRET_KEY missing' };
|
||||||
|
}
|
||||||
|
const platform = this.config.get('SMS_PLATFORM', 'rayegansms');
|
||||||
|
const host = this.resolveHost();
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
secret_key: secretKey,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
phone: to,
|
||||||
|
host,
|
||||||
|
text: message.trim(),
|
||||||
|
platform,
|
||||||
|
}),
|
||||||
|
signal: AbortSignal.timeout(15_000),
|
||||||
|
});
|
||||||
|
const text = await response.text();
|
||||||
|
let body = text;
|
||||||
|
try {
|
||||||
|
body = text ? JSON.parse(text) : null;
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
let success = response.ok;
|
||||||
|
if (success && body && typeof body === 'object') {
|
||||||
|
const obj = body;
|
||||||
|
if ('success' in obj && obj.success === false)
|
||||||
|
success = false;
|
||||||
|
else if ('ok' in obj && obj.ok === false)
|
||||||
|
success = false;
|
||||||
|
else if (typeof obj.status === 'string' &&
|
||||||
|
['error', 'failed', 'fail'].includes(obj.status.toLowerCase())) {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
this.logger.warn(`SMS failed to ${maskPhone(to)}: ${JSON.stringify(body)}`);
|
||||||
|
}
|
||||||
|
return { success, raw: body };
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.logger.error(`SMS request error to ${maskPhone(to)}`, err instanceof Error ? err.stack : err);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
raw: err instanceof Error ? err.message : String(err),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildOtpMessage(code) {
|
||||||
|
const appName = this.config.get('SMS_APP_NAME', 'پارچه');
|
||||||
|
return `رمز عبور یکبار مصرف شما جهت ورود به اپلیکیشن ${appName} ${code} می باشد`;
|
||||||
|
}
|
||||||
|
resolveHost() {
|
||||||
|
const fromEnv = this.config.get('SMS_HOST')?.trim() ||
|
||||||
|
this.config.get('SMS_APP_NAME')?.trim();
|
||||||
|
if (fromEnv)
|
||||||
|
return fromEnv;
|
||||||
|
return 'fabric';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.SmsService = SmsService;
|
||||||
|
exports.SmsService = SmsService = SmsService_1 = __decorate([
|
||||||
|
(0, common_1.Injectable)(),
|
||||||
|
__metadata("design:paramtypes", [config_1.ConfigService])
|
||||||
|
], SmsService);
|
||||||
|
//# sourceMappingURL=sms.service.js.map
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"sms.service.js","sourceRoot":"","sources":["../../src/sms/sms.service.ts"],"names":[],"mappings":"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"}
|
||||||
@@ -28,11 +28,20 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql://${POSTGRES_USER:-fabric}:${POSTGRES_PASSWORD:-fabric123}@postgres:5432/${POSTGRES_DB:-fabric_trade}?schema=public
|
DATABASE_URL: postgresql://${POSTGRES_USER:-fabric}:${POSTGRES_PASSWORD:-fabric123}@postgres:5432/${POSTGRES_DB:-fabric_trade}?schema=public
|
||||||
JWT_SECRET: ${JWT_SECRET:-fabric-trade-dev-secret-change-me}
|
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required}
|
||||||
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d}
|
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d}
|
||||||
PORT: 3000
|
PORT: 3000
|
||||||
MOCK_OTP_CODE: ${MOCK_OTP_CODE:-123456}
|
MOCK_OTP_CODE: ${MOCK_OTP_CODE:-1234}
|
||||||
OTP_TTL_MINUTES: ${OTP_TTL_MINUTES:-5}
|
OTP_TTL_MINUTES: ${OTP_TTL_MINUTES:-5}
|
||||||
|
SMS_ENABLED: ${SMS_ENABLED:-true}
|
||||||
|
SMS_API_URL: ${SMS_API_URL:-http://185.231.112.101/api/createsms}
|
||||||
|
SMS_SECRET_KEY: ${SMS_SECRET_KEY:-}
|
||||||
|
SMS_PLATFORM: ${SMS_PLATFORM:-rayegansms}
|
||||||
|
SMS_HOST: ${SMS_HOST:-پارچه}
|
||||||
|
SMS_APP_NAME: ${SMS_APP_NAME:-پارچه}
|
||||||
|
BODY_LIMIT: ${BODY_LIMIT:-25mb}
|
||||||
|
TZ: ${TZ:-Asia/Tehran}
|
||||||
|
NODE_ENV: ${NODE_ENV:-production}
|
||||||
RUN_SEED: ${RUN_SEED:-false}
|
RUN_SEED: ${RUN_SEED:-false}
|
||||||
ports:
|
ports:
|
||||||
- '127.0.0.1:${API_PORT:-3000}:3000'
|
- '127.0.0.1:${API_PORT:-3000}:3000'
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql://${POSTGRES_USER:-fabric}:${POSTGRES_PASSWORD:-fabric123}@postgres:5432/${POSTGRES_DB:-fabric_trade}?schema=public
|
DATABASE_URL: postgresql://${POSTGRES_USER:-fabric}:${POSTGRES_PASSWORD:-fabric123}@postgres:5432/${POSTGRES_DB:-fabric_trade}?schema=public
|
||||||
PORT: ${PORT:-3000}
|
PORT: ${PORT:-3000}
|
||||||
|
TZ: ${TZ:-Asia/Tehran}
|
||||||
ports:
|
ports:
|
||||||
- '127.0.0.1:${API_PORT:-8585}:3000'
|
- '127.0.0.1:${API_PORT:-8585}:3000'
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"test:cov": "jest --coverage",
|
"test:cov": "jest --coverage",
|
||||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||||
|
"test:smoke": "node scripts/smoke-order-flow.mjs",
|
||||||
"prisma:generate": "prisma generate",
|
"prisma:generate": "prisma generate",
|
||||||
"prisma:migrate": "prisma migrate dev",
|
"prisma:migrate": "prisma migrate dev",
|
||||||
"prisma:deploy": "prisma migrate deploy",
|
"prisma:deploy": "prisma migrate deploy",
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- شمارنده تلاش ناموفق برای جلوگیری از حدسزدن کد ۴ رقمی
|
||||||
|
ALTER TABLE "OtpChallenge" ADD COLUMN "attempts" INTEGER NOT NULL DEFAULT 0;
|
||||||
@@ -210,6 +210,7 @@ model OtpChallenge {
|
|||||||
firstName String?
|
firstName String?
|
||||||
lastName String?
|
lastName String?
|
||||||
isRegister Boolean @default(false)
|
isRegister Boolean @default(false)
|
||||||
|
attempts Int @default(0)
|
||||||
expiresAt DateTime
|
expiresAt DateTime
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -636,7 +636,7 @@ async function main() {
|
|||||||
void order1;
|
void order1;
|
||||||
console.log('Seed completed successfully.');
|
console.log('Seed completed successfully.');
|
||||||
console.log('Admin login: 09121112222 / admin123');
|
console.log('Admin login: 09121112222 / admin123');
|
||||||
console.log('Customer OTP login: 09121234567 / code 123456');
|
console.log('Customer OTP login: 09121234567 / code 1234');
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -0,0 +1,335 @@
|
|||||||
|
/**
|
||||||
|
* تست دود جریان کامل سفارش: ورود مشتری، سبد، ثبت چکی و نقدی،
|
||||||
|
* قیمتگذاری ادمین، رسید نقدی و بررسی وضعیتها.
|
||||||
|
* اجرا: node scripts/smoke-order-flow.mjs
|
||||||
|
*/
|
||||||
|
const BASE = process.env.SMOKE_BASE_URL || 'http://127.0.0.1:3999/api';
|
||||||
|
const CUSTOMER_PHONE = '09121234567';
|
||||||
|
const ADMIN_PHONE = '09121112222';
|
||||||
|
const ADMIN_PASSWORD = 'admin123';
|
||||||
|
|
||||||
|
let passed = 0;
|
||||||
|
let failed = 0;
|
||||||
|
|
||||||
|
function check(name, condition, detail) {
|
||||||
|
if (condition) {
|
||||||
|
passed++;
|
||||||
|
console.log(` PASS ${name}`);
|
||||||
|
} else {
|
||||||
|
failed++;
|
||||||
|
console.log(` FAIL ${name}${detail ? ` → ${detail}` : ''}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function api(path, { method = 'GET', body, token } = {}) {
|
||||||
|
const res = await fetch(`${BASE}${path}`, {
|
||||||
|
method,
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
...(body ? { 'Content-Type': 'application/json' } : {}),
|
||||||
|
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||||
|
},
|
||||||
|
body: body ? JSON.stringify(body) : undefined,
|
||||||
|
});
|
||||||
|
const text = await res.text();
|
||||||
|
let data = null;
|
||||||
|
try {
|
||||||
|
data = text ? JSON.parse(text) : null;
|
||||||
|
} catch {
|
||||||
|
data = text;
|
||||||
|
}
|
||||||
|
return { status: res.status, data };
|
||||||
|
}
|
||||||
|
|
||||||
|
function jalaliIsoInDays(days) {
|
||||||
|
const d = new Date(Date.now() + days * 86400000);
|
||||||
|
return d.toISOString().slice(0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** تصویر base64 بزرگتر از سقف پیشفرض ۱۰۰KB اکسپرس */
|
||||||
|
function bigBase64(kb) {
|
||||||
|
return `data:image/jpeg;base64,${'A'.repeat(kb * 1024)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log(`\n== Smoke test @ ${BASE} ==\n`);
|
||||||
|
|
||||||
|
console.log('[1] احراز هویت');
|
||||||
|
const otp = await api('/auth/otp/request', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { phone: CUSTOMER_PHONE },
|
||||||
|
});
|
||||||
|
check('درخواست OTP', otp.status === 201 || otp.status === 200, `status=${otp.status}`);
|
||||||
|
const code = otp.data?.debugCode ?? '1234';
|
||||||
|
check('کد OTP چهار رقمی است', /^\d{4}$/.test(String(code)), `code=${code}`);
|
||||||
|
|
||||||
|
const badVerify = await api('/auth/otp/verify', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { phone: CUSTOMER_PHONE, code: '0000' === code ? '1111' : '0000' },
|
||||||
|
});
|
||||||
|
check('کد اشتباه رد میشود', badVerify.status === 401, `status=${badVerify.status}`);
|
||||||
|
|
||||||
|
const verify = await api('/auth/otp/verify', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { phone: CUSTOMER_PHONE, code: String(code) },
|
||||||
|
});
|
||||||
|
check('ورود مشتری', !!verify.data?.accessToken, JSON.stringify(verify.data).slice(0, 120));
|
||||||
|
const userToken = verify.data?.accessToken;
|
||||||
|
|
||||||
|
const adminLogin = await api('/admin/auth/login', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { phone: ADMIN_PHONE, password: ADMIN_PASSWORD },
|
||||||
|
});
|
||||||
|
check('ورود ادمین', !!adminLogin.data?.accessToken, JSON.stringify(adminLogin.data).slice(0, 120));
|
||||||
|
const adminToken = adminLogin.data?.accessToken;
|
||||||
|
|
||||||
|
console.log('\n[2] جداسازی دسترسی');
|
||||||
|
const crossAccess = await api('/admin/orders', { token: userToken });
|
||||||
|
check('توکن مشتری به مسیر ادمین دسترسی ندارد', crossAccess.status === 403, `status=${crossAccess.status}`);
|
||||||
|
const custWithAdmin = await api('/orders', { token: adminToken });
|
||||||
|
check('توکن ادمین به مسیر مشتری دسترسی ندارد', custWithAdmin.status === 403, `status=${custWithAdmin.status}`);
|
||||||
|
const noToken = await api('/orders');
|
||||||
|
check('بدون توکن ۴۰۱', noToken.status === 401, `status=${noToken.status}`);
|
||||||
|
|
||||||
|
console.log('\n[3] سبد خرید');
|
||||||
|
const companies = await api('/companies/public');
|
||||||
|
const company = companies.data?.[0];
|
||||||
|
check('لیست شرکتها', !!company, JSON.stringify(companies.data).slice(0, 120));
|
||||||
|
|
||||||
|
const products = await api(`/products?companyId=${company.id}`, { token: userToken });
|
||||||
|
const product = (Array.isArray(products.data) ? products.data : products.data?.items)?.find(
|
||||||
|
(p) => p.companyId === company.id,
|
||||||
|
);
|
||||||
|
check('لیست محصولات', !!product, JSON.stringify(products.data).slice(0, 160));
|
||||||
|
|
||||||
|
const meterage = Math.max(product.minMeterage ?? 1, product.orderMultiplier ?? 1);
|
||||||
|
await api('/carts', { method: 'DELETE', token: userToken });
|
||||||
|
const addItem = await api('/carts/items', {
|
||||||
|
method: 'POST',
|
||||||
|
token: userToken,
|
||||||
|
body: { productId: product.id, meterage },
|
||||||
|
});
|
||||||
|
check('افزودن به سبد', addItem.status < 300, `status=${addItem.status} ${JSON.stringify(addItem.data).slice(0, 120)}`);
|
||||||
|
|
||||||
|
console.log('\n[4] ثبت سفارش چکی با تصویر بزرگ');
|
||||||
|
const checkOrder = await api('/orders', {
|
||||||
|
method: 'POST',
|
||||||
|
token: userToken,
|
||||||
|
body: {
|
||||||
|
companyId: company.id,
|
||||||
|
settlementType: 'check',
|
||||||
|
checkMode: 'full',
|
||||||
|
items: [{ productId: product.id, meterage }],
|
||||||
|
checks: [
|
||||||
|
{
|
||||||
|
amount: 2000000,
|
||||||
|
dueDate: jalaliIsoInDays(30),
|
||||||
|
sayadId: '1234567890123456',
|
||||||
|
checkNumber: '123456',
|
||||||
|
ownerNationalId: '0012345678',
|
||||||
|
ownerFirstName: 'علی',
|
||||||
|
ownerLastName: 'رضایی',
|
||||||
|
bankName: 'ملی',
|
||||||
|
branchName: 'مرکزی',
|
||||||
|
frontImage: bigBase64(300),
|
||||||
|
backImage: bigBase64(300),
|
||||||
|
mode: 'full',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
check(
|
||||||
|
'ثبت سفارش چکی (بدنه ~۶۰۰KB)',
|
||||||
|
checkOrder.status < 300,
|
||||||
|
`status=${checkOrder.status} ${JSON.stringify(checkOrder.data).slice(0, 200)}`,
|
||||||
|
);
|
||||||
|
const checkOrderId = checkOrder.data?.id;
|
||||||
|
check('راس چک محاسبه شد', checkOrder.data?.checkRassDays === 30, `rass=${checkOrder.data?.checkRassDays}`);
|
||||||
|
|
||||||
|
console.log('\n[5] فیلدهای اضافه باید رد شوند');
|
||||||
|
const extraField = await api('/orders', {
|
||||||
|
method: 'POST',
|
||||||
|
token: userToken,
|
||||||
|
body: {
|
||||||
|
companyId: company.id,
|
||||||
|
settlementType: 'cash',
|
||||||
|
items: [{ productId: product.id, meterage }],
|
||||||
|
bogusField: 'x',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
check('فیلد ناشناخته ۴۰۰ میدهد', extraField.status === 400, `status=${extraField.status}`);
|
||||||
|
|
||||||
|
console.log('\n[6] ثبت سفارش نقدی');
|
||||||
|
await api('/carts/items', {
|
||||||
|
method: 'POST',
|
||||||
|
token: userToken,
|
||||||
|
body: { productId: product.id, meterage },
|
||||||
|
});
|
||||||
|
const cashOrder = await api('/orders', {
|
||||||
|
method: 'POST',
|
||||||
|
token: userToken,
|
||||||
|
body: {
|
||||||
|
companyId: company.id,
|
||||||
|
settlementType: 'cash',
|
||||||
|
items: [{ productId: product.id, meterage }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
check('ثبت سفارش نقدی', cashOrder.status < 300, `status=${cashOrder.status} ${JSON.stringify(cashOrder.data).slice(0, 200)}`);
|
||||||
|
const cashOrderId = cashOrder.data?.id;
|
||||||
|
const expiry = cashOrder.data?.cashInvoiceExpiresAt;
|
||||||
|
check('انقضای فاکتور در آینده است', !!expiry && new Date(expiry) > new Date(), `expiry=${expiry}`);
|
||||||
|
|
||||||
|
console.log('\n[7] سفارش در لیست مشتری دیده میشود');
|
||||||
|
const myOrders = await api('/orders', { token: userToken });
|
||||||
|
const ids = (myOrders.data ?? []).map((o) => o.id);
|
||||||
|
check('سفارش چکی در لیست', ids.includes(checkOrderId));
|
||||||
|
check('سفارش نقدی در لیست', ids.includes(cashOrderId));
|
||||||
|
|
||||||
|
console.log('\n[8] لیست و فیلتر ادمین');
|
||||||
|
const adminOrders = await api('/admin/orders', { token: adminToken });
|
||||||
|
const adminIds = (adminOrders.data ?? []).map((o) => o.id);
|
||||||
|
check('هر دو سفارش برای ادمین', adminIds.includes(checkOrderId) && adminIds.includes(cashOrderId));
|
||||||
|
const adminStatuses = new Set((adminOrders.data ?? []).map((o) => o.adminStatus));
|
||||||
|
const allowedTabs = new Set([
|
||||||
|
'pending_review',
|
||||||
|
'pending_check',
|
||||||
|
'needs_correction',
|
||||||
|
'check_correction',
|
||||||
|
'final_approval',
|
||||||
|
'shipped',
|
||||||
|
'delivered',
|
||||||
|
'cancelled',
|
||||||
|
'rejected',
|
||||||
|
'expired',
|
||||||
|
]);
|
||||||
|
const unknown = [...adminStatuses].filter((s) => !allowedTabs.has(s));
|
||||||
|
check('همه وضعیتها به تب معتبر نگاشت شدهاند', unknown.length === 0, `unknown=${unknown.join(',')}`);
|
||||||
|
|
||||||
|
const filtered = await api('/admin/orders?status=pending_review', { token: adminToken });
|
||||||
|
check(
|
||||||
|
'فیلتر «در انتظار بررسی» سفارشها را برمیگرداند',
|
||||||
|
(filtered.data ?? []).some((o) => o.id === cashOrderId),
|
||||||
|
`count=${(filtered.data ?? []).length}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('\n[9] قیمتگذاری ادمین');
|
||||||
|
const detail = await api(`/admin/orders/${cashOrderId}`, { token: adminToken });
|
||||||
|
const items = detail.data?.items ?? [];
|
||||||
|
check('سفارش آیتم دارد', items.length > 0);
|
||||||
|
const pricing = await api(`/admin/orders/${cashOrderId}/pricing`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
token: adminToken,
|
||||||
|
body: {
|
||||||
|
items: [{ id: items[0].id, confirmedMeterage: meterage, unitPrice: 100000, unitDiscount: 0 }],
|
||||||
|
shippingCost: 50000,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const expectedTotal = 100000 * meterage;
|
||||||
|
check('قیمتگذاری موفق', pricing.status < 300, `status=${pricing.status} ${JSON.stringify(pricing.data).slice(0, 150)}`);
|
||||||
|
check(
|
||||||
|
'جمع کل درست است',
|
||||||
|
Math.abs((pricing.data?.totalAmount ?? 0) - expectedTotal) < 0.01,
|
||||||
|
`total=${pricing.data?.totalAmount} expected=${expectedTotal}`,
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
'مبلغ نهایی = جمع + حمل',
|
||||||
|
Math.abs((pricing.data?.finalAmount ?? 0) - (expectedTotal + 50000)) < 0.01,
|
||||||
|
`final=${pricing.data?.finalAmount}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const badDiscount = await api(`/admin/orders/${cashOrderId}/pricing`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
token: adminToken,
|
||||||
|
body: { items: [{ id: items[0].id, unitPrice: 1000, unitDiscount: 5000 }] },
|
||||||
|
});
|
||||||
|
check('تخفیف بیشتر از قیمت رد میشود', badDiscount.status === 400, `status=${badDiscount.status}`);
|
||||||
|
|
||||||
|
console.log('\n[10] رسید پرداخت نقدی');
|
||||||
|
const accounts = await api(`/companies/${company.id}/bank-accounts`, { token: userToken });
|
||||||
|
const account = (accounts.data ?? [])[0];
|
||||||
|
check('حساب بانکی موجود', !!account, JSON.stringify(accounts.data).slice(0, 120));
|
||||||
|
|
||||||
|
const receipt = await api(`/orders/${cashOrderId}/cash-receipt`, {
|
||||||
|
method: 'POST',
|
||||||
|
token: userToken,
|
||||||
|
body: {
|
||||||
|
amount: expectedTotal + 50000,
|
||||||
|
transferDate: jalaliIsoInDays(0),
|
||||||
|
transferTime: '12:00',
|
||||||
|
trackingNumber: '987654321',
|
||||||
|
destinationAccountId: account.id,
|
||||||
|
receiptImage: bigBase64(400),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
check('ثبت رسید (تصویر ۴۰۰KB)', receipt.status < 300, `status=${receipt.status} ${JSON.stringify(receipt.data).slice(0, 200)}`);
|
||||||
|
|
||||||
|
const afterReceipt = await api(`/orders/${cashOrderId}`, { token: userToken });
|
||||||
|
check(
|
||||||
|
'وضعیت به تأیید پرداخت رفت',
|
||||||
|
afterReceipt.data?.status === 'awaiting_cash_confirmation',
|
||||||
|
`status=${afterReceipt.data?.status}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('\n[11] دسترسی متقاطع بین مشتریها');
|
||||||
|
const otherPhone = '09129999001';
|
||||||
|
await api('/auth/otp/request', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { phone: otherPhone, firstName: 'تست', lastName: 'دوم', isRegister: true },
|
||||||
|
});
|
||||||
|
const otherVerify = await api('/auth/otp/verify', {
|
||||||
|
method: 'POST',
|
||||||
|
body: { phone: otherPhone, code: String(code) },
|
||||||
|
});
|
||||||
|
const otherToken = otherVerify.data?.accessToken;
|
||||||
|
check('ثبتنام مشتری دوم', !!otherToken, JSON.stringify(otherVerify.data).slice(0, 120));
|
||||||
|
if (otherToken) {
|
||||||
|
const foreign = await api(`/orders/${cashOrderId}`, { token: otherToken });
|
||||||
|
check('سفارش دیگری قابل خواندن نیست', foreign.status === 403, `status=${foreign.status}`);
|
||||||
|
const foreignReceipt = await api(`/orders/${cashOrderId}/cash-receipt`, {
|
||||||
|
method: 'POST',
|
||||||
|
token: otherToken,
|
||||||
|
body: {
|
||||||
|
amount: 1000,
|
||||||
|
transferDate: jalaliIsoInDays(0),
|
||||||
|
transferTime: '12:00',
|
||||||
|
trackingNumber: '1',
|
||||||
|
destinationAccountId: account.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
check('رسید روی سفارش دیگری رد میشود', foreignReceipt.status === 403, `status=${foreignReceipt.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n[12] محافظت از ویرایش چک بعد از تأیید');
|
||||||
|
const approve = await api(`/admin/orders/${checkOrderId}/status`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
token: adminToken,
|
||||||
|
body: { status: 'delivered' },
|
||||||
|
});
|
||||||
|
check('تغییر وضعیت توسط ادمین', approve.status < 300, `status=${approve.status}`);
|
||||||
|
const lateEdit = await api(`/orders/${checkOrderId}/checks`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
token: userToken,
|
||||||
|
body: { checks: [{ amount: 1, dueDate: jalaliIsoInDays(10), mode: 'brief' }] },
|
||||||
|
});
|
||||||
|
check('ویرایش چک بعد از تحویل رد میشود', lateEdit.status === 400, `status=${lateEdit.status}`);
|
||||||
|
const lateReceipt = await api(`/orders/${checkOrderId}/cash-receipt`, {
|
||||||
|
method: 'POST',
|
||||||
|
token: userToken,
|
||||||
|
body: {
|
||||||
|
amount: 1000,
|
||||||
|
transferDate: jalaliIsoInDays(0),
|
||||||
|
transferTime: '12:00',
|
||||||
|
trackingNumber: '1',
|
||||||
|
destinationAccountId: account.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
check('رسید نقدی روی سفارش چکی رد میشود', lateReceipt.status === 400, `status=${lateReceipt.status}`);
|
||||||
|
|
||||||
|
console.log(`\n== نتیجه: ${passed} موفق، ${failed} ناموفق ==\n`);
|
||||||
|
process.exit(failed === 0 ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error('اجرای تست شکست خورد:', e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
@@ -35,4 +35,4 @@ echo " npm run start:dev"
|
|||||||
echo ""
|
echo ""
|
||||||
echo "Swagger: http://localhost:3000/api/docs"
|
echo "Swagger: http://localhost:3000/api/docs"
|
||||||
echo "Admin: 09121112222 / admin123"
|
echo "Admin: 09121112222 / admin123"
|
||||||
echo "OTP: 09121234567 / 123456"
|
echo "OTP: 09121234567 / 1234"
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ export class AdminUsersService {
|
|||||||
});
|
});
|
||||||
return this.map(user);
|
return this.map(user);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('شماره یا ایمیل تکراری است');
|
throw new ConflictException('شماره یا ایمیل تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -91,7 +94,10 @@ export class AdminUsersService {
|
|||||||
});
|
});
|
||||||
return this.map(user);
|
return this.map(user);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('شماره یا ایمیل تکراری است');
|
throw new ConflictException('شماره یا ایمیل تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -3,16 +3,19 @@ import { JwtModule } from '@nestjs/jwt';
|
|||||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service';
|
||||||
import { AuthController } from './auth.controller';
|
import { AuthController } from './auth.controller';
|
||||||
|
import { SmsModule } from '../sms/sms.module';
|
||||||
|
import { resolveJwtSecret } from '../common/utils/jwt-secret';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
SmsModule,
|
||||||
JwtModule.registerAsync({
|
JwtModule.registerAsync({
|
||||||
imports: [ConfigModule],
|
imports: [ConfigModule],
|
||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
useFactory: (config: ConfigService) => ({
|
useFactory: (config: ConfigService) => ({
|
||||||
secret: config.get<string>('JWT_SECRET', 'fabric-trade-dev-secret'),
|
secret: resolveJwtSecret(config),
|
||||||
signOptions: {
|
signOptions: {
|
||||||
expiresIn: config.get('JWT_EXPIRES_IN', '7d') as `${number}d`,
|
expiresIn: config.get('JWT_EXPIRES_IN', '7d'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|||||||
+70
-17
@@ -1,19 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
BadRequestException,
|
BadRequestException,
|
||||||
Injectable,
|
Injectable,
|
||||||
|
ServiceUnavailableException,
|
||||||
UnauthorizedException,
|
UnauthorizedException,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { JwtService } from '@nestjs/jwt';
|
import { JwtService } from '@nestjs/jwt';
|
||||||
|
import { randomInt } from 'node:crypto';
|
||||||
import * as bcrypt from 'bcryptjs';
|
import * as bcrypt from 'bcryptjs';
|
||||||
import { PrismaService } from '../prisma/prisma.service';
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
|
import { SmsService } from '../sms/sms.service';
|
||||||
import {
|
import {
|
||||||
AdminLoginDto,
|
AdminLoginDto,
|
||||||
RequestOtpDto,
|
RequestOtpDto,
|
||||||
UpdateProfileDto,
|
UpdateProfileDto,
|
||||||
VerifyOtpDto,
|
VerifyOtpDto,
|
||||||
} from './dto/auth.dto';
|
} from './dto/auth.dto';
|
||||||
import { isValidPhone, normalizePhone, toEnglishDigits } from '../common/utils/phone';
|
import {
|
||||||
|
isValidPhone,
|
||||||
|
normalizePhone,
|
||||||
|
toEnglishDigits,
|
||||||
|
} from '../common/utils/phone';
|
||||||
|
|
||||||
|
const MAX_OTP_ATTEMPTS = 5;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
@@ -21,6 +30,7 @@ export class AuthService {
|
|||||||
private readonly prisma: PrismaService,
|
private readonly prisma: PrismaService,
|
||||||
private readonly jwt: JwtService,
|
private readonly jwt: JwtService,
|
||||||
private readonly config: ConfigService,
|
private readonly config: ConfigService,
|
||||||
|
private readonly sms: SmsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async requestOtp(dto: RequestOtpDto) {
|
async requestOtp(dto: RequestOtpDto) {
|
||||||
@@ -29,7 +39,9 @@ export class AuthService {
|
|||||||
throw new BadRequestException('شماره موبایل نامعتبر است');
|
throw new BadRequestException('شماره موبایل نامعتبر است');
|
||||||
}
|
}
|
||||||
|
|
||||||
const existing = await this.prisma.customer.findUnique({ where: { phone } });
|
const existing = await this.prisma.customer.findUnique({
|
||||||
|
where: { phone },
|
||||||
|
});
|
||||||
const isRegister = Boolean(dto.isRegister);
|
const isRegister = Boolean(dto.isRegister);
|
||||||
|
|
||||||
if (isRegister) {
|
if (isRegister) {
|
||||||
@@ -41,33 +53,58 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
} else if (!existing) {
|
} else if (!existing) {
|
||||||
throw new BadRequestException('کاربری با این شماره یافت نشد');
|
throw new BadRequestException('کاربری با این شماره یافت نشد');
|
||||||
|
} else if (!existing.isActive) {
|
||||||
|
throw new UnauthorizedException('حساب کاربری شما غیرفعال است');
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = this.config.get<string>('MOCK_OTP_CODE', '123456');
|
const smsEnabled = this.sms.isEnabled();
|
||||||
|
const code = smsEnabled
|
||||||
|
? String(randomInt(1000, 10000))
|
||||||
|
: this.config.get<string>('MOCK_OTP_CODE', '1234');
|
||||||
const ttl = Number(this.config.get('OTP_TTL_MINUTES', 5));
|
const ttl = Number(this.config.get('OTP_TTL_MINUTES', 5));
|
||||||
const expiresAt = new Date(Date.now() + ttl * 60_000);
|
const expiresAt = new Date(Date.now() + ttl * 60_000);
|
||||||
|
|
||||||
await this.prisma.otpChallenge.deleteMany({ where: { phone } });
|
const challenge = await this.prisma.$transaction(async (tx) => {
|
||||||
await this.prisma.otpChallenge.create({
|
await tx.otpChallenge.deleteMany({ where: { phone } });
|
||||||
data: {
|
return tx.otpChallenge.create({
|
||||||
phone,
|
data: {
|
||||||
code,
|
phone,
|
||||||
firstName: dto.firstName?.trim(),
|
code,
|
||||||
lastName: dto.lastName?.trim(),
|
firstName: dto.firstName?.trim(),
|
||||||
isRegister,
|
lastName: dto.lastName?.trim(),
|
||||||
expiresAt,
|
isRegister,
|
||||||
},
|
expiresAt,
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (smsEnabled) {
|
||||||
|
const sent = await this.sms.send(phone, this.sms.buildOtpMessage(code));
|
||||||
|
if (!sent.success) {
|
||||||
|
// چالش ناموفق را پاک میکنیم تا کاربر با کدی که هرگز نرسیده گیر نکند
|
||||||
|
await this.prisma.otpChallenge.deleteMany({
|
||||||
|
where: { id: challenge.id },
|
||||||
|
});
|
||||||
|
throw new ServiceUnavailableException(
|
||||||
|
'ارسال پیامک با خطا مواجه شد؛ دوباره تلاش کنید',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: 'کد تأیید ارسال شد',
|
message: 'کد تأیید ارسال شد',
|
||||||
expiresAt,
|
expiresAt,
|
||||||
// فقط برای محیط توسعه
|
...(this.exposesDebugCode(smsEnabled) ? { debugCode: code } : {}),
|
||||||
debugCode: code,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** کد فقط در محیط توسعه و وقتی پیامک خاموش است برگردانده میشود. */
|
||||||
|
private exposesDebugCode(smsEnabled: boolean): boolean {
|
||||||
|
if (smsEnabled) return false;
|
||||||
|
return this.config.get<string>('NODE_ENV') !== 'production';
|
||||||
|
}
|
||||||
|
|
||||||
async verifyOtp(dto: VerifyOtpDto) {
|
async verifyOtp(dto: VerifyOtpDto) {
|
||||||
const phone = normalizePhone(toEnglishDigits(dto.phone));
|
const phone = normalizePhone(toEnglishDigits(dto.phone));
|
||||||
const code = toEnglishDigits(dto.code).trim();
|
const code = toEnglishDigits(dto.code).trim();
|
||||||
@@ -80,7 +117,17 @@ export class AuthService {
|
|||||||
if (!challenge || challenge.expiresAt < new Date()) {
|
if (!challenge || challenge.expiresAt < new Date()) {
|
||||||
throw new UnauthorizedException('کد منقضی شده است');
|
throw new UnauthorizedException('کد منقضی شده است');
|
||||||
}
|
}
|
||||||
|
if (challenge.attempts >= MAX_OTP_ATTEMPTS) {
|
||||||
|
await this.prisma.otpChallenge.deleteMany({ where: { phone } });
|
||||||
|
throw new UnauthorizedException(
|
||||||
|
'تعداد تلاشهای نادرست زیاد است؛ کد جدید بگیرید',
|
||||||
|
);
|
||||||
|
}
|
||||||
if (challenge.code !== code) {
|
if (challenge.code !== code) {
|
||||||
|
await this.prisma.otpChallenge.update({
|
||||||
|
where: { id: challenge.id },
|
||||||
|
data: { attempts: { increment: 1 } },
|
||||||
|
});
|
||||||
throw new UnauthorizedException('کد تأیید نادرست است');
|
throw new UnauthorizedException('کد تأیید نادرست است');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +145,8 @@ export class AuthService {
|
|||||||
});
|
});
|
||||||
} else if (!user) {
|
} else if (!user) {
|
||||||
throw new UnauthorizedException('کاربر یافت نشد');
|
throw new UnauthorizedException('کاربر یافت نشد');
|
||||||
|
} else if (!user.isActive) {
|
||||||
|
throw new UnauthorizedException('حساب کاربری شما غیرفعال است');
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.prisma.otpChallenge.deleteMany({ where: { phone } });
|
await this.prisma.otpChallenge.deleteMany({ where: { phone } });
|
||||||
@@ -147,7 +196,9 @@ export class AuthService {
|
|||||||
|
|
||||||
async me(userId: string, type: 'customer' | 'admin') {
|
async me(userId: string, type: 'customer' | 'admin') {
|
||||||
if (type === 'admin') {
|
if (type === 'admin') {
|
||||||
const admin = await this.prisma.adminUser.findUnique({ where: { id: userId } });
|
const admin = await this.prisma.adminUser.findUnique({
|
||||||
|
where: { id: userId },
|
||||||
|
});
|
||||||
if (!admin) throw new UnauthorizedException();
|
if (!admin) throw new UnauthorizedException();
|
||||||
return {
|
return {
|
||||||
id: admin.id,
|
id: admin.id,
|
||||||
@@ -158,7 +209,9 @@ export class AuthService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await this.prisma.customer.findUnique({ where: { id: userId } });
|
const user = await this.prisma.customer.findUnique({
|
||||||
|
where: { id: userId },
|
||||||
|
});
|
||||||
if (!user) throw new UnauthorizedException();
|
if (!user) throw new UnauthorizedException();
|
||||||
return this.mapCustomer(user);
|
return this.mapCustomer(user);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { IsBoolean, IsOptional, IsString, MinLength } from 'class-validator';
|
import {
|
||||||
|
IsBoolean,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
Length,
|
||||||
|
MinLength,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
export class RequestOtpDto {
|
export class RequestOtpDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@@ -22,7 +28,7 @@ export class VerifyOtpDto {
|
|||||||
phone!: string;
|
phone!: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@MinLength(4)
|
@Length(4, 4)
|
||||||
code!: string;
|
code!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,10 +28,7 @@ export class CartsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post('items')
|
@Post('items')
|
||||||
addItem(
|
addItem(@CurrentUser() user: AuthPrincipal, @Body() dto: AddCartItemDto) {
|
||||||
@CurrentUser() user: AuthPrincipal,
|
|
||||||
@Body() dto: AddCartItemDto,
|
|
||||||
) {
|
|
||||||
return this.cartsService.addItem(user.id, dto);
|
return this.cartsService.addItem(user.id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,8 +96,7 @@ export class CartsService {
|
|||||||
where: { id: itemId },
|
where: { id: itemId },
|
||||||
data: {
|
data: {
|
||||||
meterage: dto.meterage,
|
meterage: dto.meterage,
|
||||||
notes:
|
notes: dto.notes === undefined ? undefined : dto.notes?.trim() || null,
|
||||||
dto.notes === undefined ? undefined : dto.notes?.trim() || null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await this.prisma.cart.update({
|
await this.prisma.cart.update({
|
||||||
@@ -152,8 +151,7 @@ export class CartsService {
|
|||||||
`حداقل متراژ برای ${product.name} برابر ${product.minMeterage} است`,
|
`حداقل متراژ برای ${product.name} برابر ${product.minMeterage} است`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const rem =
|
const rem = Math.round((meterage / product.orderMultiplier) * 1000) / 1000;
|
||||||
Math.round((meterage / product.orderMultiplier) * 1000) / 1000;
|
|
||||||
if (Math.abs(rem - Math.round(rem)) > 1e-6) {
|
if (Math.abs(rem - Math.round(rem)) > 1e-6) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
`متراژ باید مضرب ${product.orderMultiplier} باشد`,
|
`متراژ باید مضرب ${product.orderMultiplier} باشد`,
|
||||||
|
|||||||
@@ -4,11 +4,7 @@ import {
|
|||||||
Injectable,
|
Injectable,
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import {
|
import { CashPaymentStatus, OrderStatus, SettlementType } from '@prisma/client';
|
||||||
CashPaymentStatus,
|
|
||||||
OrderStatus,
|
|
||||||
SettlementType,
|
|
||||||
} from '@prisma/client';
|
|
||||||
import { PrismaService } from '../prisma/prisma.service';
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
import {
|
import {
|
||||||
SubmitCashReceiptDto,
|
SubmitCashReceiptDto,
|
||||||
@@ -16,6 +12,20 @@ import {
|
|||||||
} from './dto/cash-payment.dto';
|
} from './dto/cash-payment.dto';
|
||||||
import { joinFullName } from '../common/utils/name';
|
import { joinFullName } from '../common/utils/name';
|
||||||
|
|
||||||
|
/** بعد از تأیید پرداخت یا ارسال، رسید جدید نباید وضعیت را به عقب برگرداند. */
|
||||||
|
const RECEIPT_SUBMITTABLE_STATUSES: OrderStatus[] = [
|
||||||
|
OrderStatus.awaiting_review,
|
||||||
|
OrderStatus.pricing,
|
||||||
|
OrderStatus.needs_correction,
|
||||||
|
OrderStatus.awaiting_settlement,
|
||||||
|
OrderStatus.awaiting_settlement_fix,
|
||||||
|
OrderStatus.cash_in_progress,
|
||||||
|
OrderStatus.cash_invoice_issued,
|
||||||
|
OrderStatus.awaiting_cash_payment,
|
||||||
|
OrderStatus.cash_payment_submitted,
|
||||||
|
OrderStatus.awaiting_cash_confirmation,
|
||||||
|
];
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CashPaymentsService {
|
export class CashPaymentsService {
|
||||||
constructor(private readonly prisma: PrismaService) {}
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
@@ -36,11 +46,18 @@ export class CashPaymentsService {
|
|||||||
if (order.settlementType !== SettlementType.cash) {
|
if (order.settlementType !== SettlementType.cash) {
|
||||||
throw new BadRequestException('این سفارش تسویه نقدی نیست');
|
throw new BadRequestException('این سفارش تسویه نقدی نیست');
|
||||||
}
|
}
|
||||||
|
if (!RECEIPT_SUBMITTABLE_STATUSES.includes(order.status)) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'در وضعیت فعلی سفارش امکان ثبت رسید وجود ندارد',
|
||||||
|
);
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
order.cashInvoiceExpiresAt &&
|
order.cashInvoiceExpiresAt &&
|
||||||
order.cashInvoiceExpiresAt.getTime() < Date.now()
|
order.cashInvoiceExpiresAt.getTime() < Date.now()
|
||||||
) {
|
) {
|
||||||
throw new BadRequestException('مهلت پرداخت فاکتور نقدی به پایان رسیده است');
|
throw new BadRequestException(
|
||||||
|
'مهلت پرداخت فاکتور نقدی به پایان رسیده است',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const account = await this.prisma.bankAccount.findFirst({
|
const account = await this.prisma.bankAccount.findFirst({
|
||||||
|
|||||||
@@ -61,7 +61,10 @@ export class CatalogsService {
|
|||||||
});
|
});
|
||||||
return this.map(catalog);
|
return this.map(catalog);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('کد کاتالوگ در این شرکت تکراری است');
|
throw new ConflictException('کد کاتالوگ در این شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -90,7 +93,10 @@ export class CatalogsService {
|
|||||||
});
|
});
|
||||||
return this.map(catalog);
|
return this.map(catalog);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('کد کاتالوگ در این شرکت تکراری است');
|
throw new ConflictException('کد کاتالوگ در این شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import {
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
Injectable,
|
import { CheckStatus, OrderStatus } from '@prisma/client';
|
||||||
NotFoundException,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import {
|
|
||||||
CheckStatus,
|
|
||||||
OrderStatus,
|
|
||||||
} from '@prisma/client';
|
|
||||||
import { PrismaService } from '../prisma/prisma.service';
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
import { UpdateCheckStatusDto } from './dto/check.dto';
|
import { UpdateCheckStatusDto } from './dto/check.dto';
|
||||||
|
|
||||||
@@ -14,7 +8,9 @@ export class ChecksService {
|
|||||||
constructor(private readonly prisma: PrismaService) {}
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
async findByOrder(orderId: string) {
|
async findByOrder(orderId: string) {
|
||||||
const order = await this.prisma.order.findUnique({ where: { id: orderId } });
|
const order = await this.prisma.order.findUnique({
|
||||||
|
where: { id: orderId },
|
||||||
|
});
|
||||||
if (!order) throw new NotFoundException('سفارش یافت نشد');
|
if (!order) throw new NotFoundException('سفارش یافت نشد');
|
||||||
|
|
||||||
const checks = await this.prisma.check.findMany({
|
const checks = await this.prisma.check.findMany({
|
||||||
@@ -24,11 +20,7 @@ export class ChecksService {
|
|||||||
return checks.map((c) => this.map(c));
|
return checks.map((c) => this.map(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateStatus(
|
async updateStatus(id: string, adminId: string, dto: UpdateCheckStatusDto) {
|
||||||
id: string,
|
|
||||||
adminId: string,
|
|
||||||
dto: UpdateCheckStatusDto,
|
|
||||||
) {
|
|
||||||
const check = await this.prisma.check.findUnique({
|
const check = await this.prisma.check.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: { order: { include: { checks: true } } },
|
include: { order: { include: { checks: true } } },
|
||||||
@@ -46,9 +38,15 @@ export class ChecksService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const siblings = await tx.check.findMany({ where: { orderId: check.orderId } });
|
const siblings = await tx.check.findMany({
|
||||||
const allApproved = siblings.every((c) => c.status === CheckStatus.approved);
|
where: { orderId: check.orderId },
|
||||||
const anyRejected = siblings.some((c) => c.status === CheckStatus.rejected);
|
});
|
||||||
|
const allApproved = siblings.every(
|
||||||
|
(c) => c.status === CheckStatus.approved,
|
||||||
|
);
|
||||||
|
const anyRejected = siblings.some(
|
||||||
|
(c) => c.status === CheckStatus.rejected,
|
||||||
|
);
|
||||||
|
|
||||||
let nextStatus: OrderStatus | null = null;
|
let nextStatus: OrderStatus | null = null;
|
||||||
if (anyRejected) {
|
if (anyRejected) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export interface AuthPrincipal {
|
|||||||
|
|
||||||
export const CurrentUser = createParamDecorator(
|
export const CurrentUser = createParamDecorator(
|
||||||
(_data: unknown, ctx: ExecutionContext): AuthPrincipal => {
|
(_data: unknown, ctx: ExecutionContext): AuthPrincipal => {
|
||||||
const request = ctx.switchToHttp().getRequest();
|
const request = ctx.switchToHttp().getRequest<{ user: AuthPrincipal }>();
|
||||||
return request.user;
|
return request.user;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
ROLES_KEY,
|
ROLES_KEY,
|
||||||
} from '../decorators/auth.decorators';
|
} from '../decorators/auth.decorators';
|
||||||
import { AuthPrincipal } from '../decorators/current-user.decorator';
|
import { AuthPrincipal } from '../decorators/current-user.decorator';
|
||||||
|
import { resolveJwtSecret } from '../utils/jwt-secret';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class JwtAuthGuard implements CanActivate {
|
export class JwtAuthGuard implements CanActivate {
|
||||||
@@ -30,8 +31,11 @@ export class JwtAuthGuard implements CanActivate {
|
|||||||
]);
|
]);
|
||||||
if (isPublic) return true;
|
if (isPublic) return true;
|
||||||
|
|
||||||
const request = context.switchToHttp().getRequest();
|
const request = context.switchToHttp().getRequest<{
|
||||||
const authHeader = request.headers.authorization as string | undefined;
|
headers: Record<string, string | undefined>;
|
||||||
|
user?: AuthPrincipal;
|
||||||
|
}>();
|
||||||
|
const authHeader = request.headers.authorization;
|
||||||
if (!authHeader?.startsWith('Bearer ')) {
|
if (!authHeader?.startsWith('Bearer ')) {
|
||||||
throw new UnauthorizedException('توکن احراز هویت الزامی است');
|
throw new UnauthorizedException('توکن احراز هویت الزامی است');
|
||||||
}
|
}
|
||||||
@@ -40,7 +44,7 @@ export class JwtAuthGuard implements CanActivate {
|
|||||||
let payload: AuthPrincipal & { sub?: string };
|
let payload: AuthPrincipal & { sub?: string };
|
||||||
try {
|
try {
|
||||||
payload = await this.jwtService.verifyAsync(token, {
|
payload = await this.jwtService.verifyAsync(token, {
|
||||||
secret: this.config.get<string>('JWT_SECRET'),
|
secret: resolveJwtSecret(this.config),
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
throw new UnauthorizedException('توکن نامعتبر یا منقضی شده است');
|
throw new UnauthorizedException('توکن نامعتبر یا منقضی شده است');
|
||||||
@@ -54,10 +58,9 @@ export class JwtAuthGuard implements CanActivate {
|
|||||||
};
|
};
|
||||||
request.user = user;
|
request.user = user;
|
||||||
|
|
||||||
const authType = this.reflector.getAllAndOverride<'customer' | 'admin' | 'any'>(
|
const authType = this.reflector.getAllAndOverride<
|
||||||
AUTH_TYPE_KEY,
|
'customer' | 'admin' | 'any'
|
||||||
[context.getHandler(), context.getClass()],
|
>(AUTH_TYPE_KEY, [context.getHandler(), context.getClass()]);
|
||||||
);
|
|
||||||
if (authType && authType !== 'any' && user.type !== authType) {
|
if (authType && authType !== 'any' && user.type !== authType) {
|
||||||
throw new ForbiddenException('دسترسی مجاز نیست');
|
throw new ForbiddenException('دسترسی مجاز نیست');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { addDays, tehranAtHour } from './tehran-time';
|
||||||
|
|
||||||
export function computeCashInvoiceExpiry(company: {
|
export function computeCashInvoiceExpiry(company: {
|
||||||
cashInvoiceValidUntilHour: number | null;
|
cashInvoiceValidUntilHour: number | null;
|
||||||
cashInvoiceValidityHours: number;
|
cashInvoiceValidityHours: number;
|
||||||
@@ -7,10 +9,9 @@ export function computeCashInvoiceExpiry(company: {
|
|||||||
company.cashInvoiceValidUntilHour != null &&
|
company.cashInvoiceValidUntilHour != null &&
|
||||||
Number.isFinite(company.cashInvoiceValidUntilHour)
|
Number.isFinite(company.cashInvoiceValidUntilHour)
|
||||||
) {
|
) {
|
||||||
const expires = new Date(now);
|
const expires = tehranAtHour(now, company.cashInvoiceValidUntilHour);
|
||||||
expires.setHours(company.cashInvoiceValidUntilHour, 0, 0, 0);
|
|
||||||
if (expires.getTime() <= now.getTime()) {
|
if (expires.getTime() <= now.getTime()) {
|
||||||
expires.setDate(expires.getDate() + 1);
|
return tehranAtHour(addDays(now, 1), company.cashInvoiceValidUntilHour);
|
||||||
}
|
}
|
||||||
return expires;
|
return expires;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ export type CheckRassResult = {
|
|||||||
rassDate: string | null;
|
rassDate: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
function startOfDay(date: Date): Date {
|
import {
|
||||||
const d = new Date(date);
|
addDays,
|
||||||
d.setHours(0, 0, 0, 0);
|
calendarDayOf,
|
||||||
return d;
|
diffInDays,
|
||||||
}
|
tehranCalendarDay,
|
||||||
|
} from './tehran-time';
|
||||||
|
|
||||||
export function calculateCheckRass(
|
export function calculateCheckRass(
|
||||||
checks: CheckRassInput[],
|
checks: CheckRassInput[],
|
||||||
@@ -33,25 +34,21 @@ export function calculateCheckRass(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const base = startOfDay(baseDate);
|
const base = tehranCalendarDay(baseDate);
|
||||||
let totalAmount = 0;
|
let totalAmount = 0;
|
||||||
let weightedDays = 0;
|
let weightedDays = 0;
|
||||||
const dueDates: Date[] = [];
|
const dueDates: Date[] = [];
|
||||||
|
|
||||||
for (const check of checks) {
|
for (const check of checks) {
|
||||||
const due = startOfDay(new Date(check.dueDate));
|
const due = calendarDayOf(check.dueDate);
|
||||||
dueDates.push(due);
|
dueDates.push(due);
|
||||||
const days = Math.max(
|
const days = Math.max(0, diffInDays(base, due));
|
||||||
0,
|
|
||||||
Math.round((due.getTime() - base.getTime()) / (1000 * 60 * 60 * 24)),
|
|
||||||
);
|
|
||||||
totalAmount += check.amount;
|
totalAmount += check.amount;
|
||||||
weightedDays += check.amount * days;
|
weightedDays += check.amount * days;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rassDays = totalAmount > 0 ? Math.round(weightedDays / totalAmount) : 0;
|
const rassDays = totalAmount > 0 ? Math.round(weightedDays / totalAmount) : 0;
|
||||||
const rassDate = new Date(base);
|
const rassDate = addDays(base, rassDays);
|
||||||
rassDate.setDate(rassDate.getDate() + rassDays);
|
|
||||||
dueDates.sort((a, b) => a.getTime() - b.getTime());
|
dueDates.sort((a, b) => a.getTime() - b.getTime());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
|
const DEV_FALLBACK = 'fabric-trade-dev-secret';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* امضا و اعتبارسنجی توکن باید از یک منبع بخوانند؛ در production نبود مقدار خطای راهاندازی است.
|
||||||
|
*/
|
||||||
|
export function resolveJwtSecret(config: ConfigService): string {
|
||||||
|
const secret = config.get<string>('JWT_SECRET')?.trim();
|
||||||
|
if (secret) return secret;
|
||||||
|
|
||||||
|
if (config.get<string>('NODE_ENV') === 'production') {
|
||||||
|
throw new Error('JWT_SECRET تنظیم نشده است');
|
||||||
|
}
|
||||||
|
return DEV_FALLBACK;
|
||||||
|
}
|
||||||
@@ -8,10 +8,10 @@ export function splitFullName(name: string): {
|
|||||||
}
|
}
|
||||||
const parts = trimmed.split(' ');
|
const parts = trimmed.split(' ');
|
||||||
if (parts.length === 1) {
|
if (parts.length === 1) {
|
||||||
return { firstName: parts[0]!, lastName: '' };
|
return { firstName: parts[0], lastName: '' };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
firstName: parts[0]!,
|
firstName: parts[0],
|
||||||
lastName: parts.slice(1).join(' '),
|
lastName: parts.slice(1).join(' '),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,43 @@ import { OrderStatus } from '@prisma/client';
|
|||||||
|
|
||||||
/** Admin UI simplified statuses → full Prisma OrderStatus values */
|
/** Admin UI simplified statuses → full Prisma OrderStatus values */
|
||||||
export const ADMIN_STATUS_MAP: Record<string, OrderStatus[]> = {
|
export const ADMIN_STATUS_MAP: Record<string, OrderStatus[]> = {
|
||||||
pending_review: [OrderStatus.awaiting_review, OrderStatus.pricing],
|
pending_review: [
|
||||||
|
OrderStatus.cart,
|
||||||
|
OrderStatus.awaiting_settlement,
|
||||||
|
OrderStatus.cash_in_progress,
|
||||||
|
OrderStatus.check_in_progress,
|
||||||
|
OrderStatus.submitted,
|
||||||
|
OrderStatus.awaiting_review,
|
||||||
|
OrderStatus.pricing,
|
||||||
|
OrderStatus.cash_invoice_issued,
|
||||||
|
OrderStatus.awaiting_cash_payment,
|
||||||
|
OrderStatus.cash_payment_submitted,
|
||||||
|
OrderStatus.awaiting_cash_confirmation,
|
||||||
|
],
|
||||||
pending_check: [OrderStatus.awaiting_check_review],
|
pending_check: [OrderStatus.awaiting_check_review],
|
||||||
needs_correction: [OrderStatus.needs_correction],
|
needs_correction: [
|
||||||
check_correction: [OrderStatus.check_needs_fix],
|
OrderStatus.needs_correction,
|
||||||
|
OrderStatus.awaiting_settlement_fix,
|
||||||
|
],
|
||||||
|
check_correction: [OrderStatus.check_needs_fix, OrderStatus.check_rejected],
|
||||||
final_approval: [
|
final_approval: [
|
||||||
OrderStatus.final_approved,
|
OrderStatus.final_approved,
|
||||||
OrderStatus.checks_approved,
|
OrderStatus.checks_approved,
|
||||||
OrderStatus.cash_confirmed,
|
OrderStatus.cash_confirmed,
|
||||||
|
OrderStatus.preparing,
|
||||||
|
OrderStatus.ready_to_ship,
|
||||||
],
|
],
|
||||||
shipped: [OrderStatus.shipped],
|
shipped: [OrderStatus.shipped],
|
||||||
delivered: [OrderStatus.delivered],
|
delivered: [OrderStatus.delivered],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** وضعیتهای پایانی عمداً در تبهای جریان کاری نمیآیند و با برچسب خودشان نمایش داده میشوند. */
|
||||||
|
const TERMINAL_STATUSES: OrderStatus[] = [
|
||||||
|
OrderStatus.cancelled,
|
||||||
|
OrderStatus.rejected,
|
||||||
|
OrderStatus.expired,
|
||||||
|
];
|
||||||
|
|
||||||
export function resolveAdminStatusFilter(
|
export function resolveAdminStatusFilter(
|
||||||
status?: string,
|
status?: string,
|
||||||
): OrderStatus[] | undefined {
|
): OrderStatus[] | undefined {
|
||||||
@@ -30,7 +54,8 @@ export function toAdminStatus(status: OrderStatus): string {
|
|||||||
for (const [admin, list] of Object.entries(ADMIN_STATUS_MAP)) {
|
for (const [admin, list] of Object.entries(ADMIN_STATUS_MAP)) {
|
||||||
if (list.includes(status)) return admin;
|
if (list.includes(status)) return admin;
|
||||||
}
|
}
|
||||||
return status;
|
if (TERMINAL_STATUSES.includes(status)) return status;
|
||||||
|
return 'pending_review';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ORDER_STATUS_LABELS: Record<OrderStatus, string> = {
|
export const ORDER_STATUS_LABELS: Record<OrderStatus, string> = {
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* محاسبات تقویمی باید مستقل از تایمزون سرور باشد؛ کانتینرها روی UTC اجرا میشوند.
|
||||||
|
* ایران از ۱۴۰۱ تغییر ساعت تابستانی ندارد، پس آفست ثابت +۰۳:۳۰ درست است.
|
||||||
|
*/
|
||||||
|
const TEHRAN_OFFSET_MS = (3 * 60 + 30) * 60 * 1000;
|
||||||
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
function utcStartOfDay(date: Date): Date {
|
||||||
|
const d = new Date(date);
|
||||||
|
d.setUTCHours(0, 0, 0, 0);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* روز تقویمی تهرانِ یک لحظه را بهصورت نیمهشب UTC همان روز برمیگرداند.
|
||||||
|
* خروجی برای اختلافگیری روزانه و سریالسازی `YYYY-MM-DD` امن است.
|
||||||
|
*/
|
||||||
|
export function tehranCalendarDay(date: Date): Date {
|
||||||
|
return utcStartOfDay(new Date(date.getTime() + TEHRAN_OFFSET_MS));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** تاریخ سررسید فقط-روز است و نیمهشب UTC ذخیره میشود. */
|
||||||
|
export function calendarDayOf(date: Date | string): Date {
|
||||||
|
return utcStartOfDay(new Date(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addDays(date: Date, days: number): Date {
|
||||||
|
return new Date(date.getTime() + days * DAY_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function diffInDays(from: Date, to: Date): number {
|
||||||
|
return Math.round((to.getTime() - from.getTime()) / DAY_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** لحظهای که در تهران ساعتِ دادهشده از همان روزِ تقویمی است. */
|
||||||
|
export function tehranAtHour(date: Date, hour: number): Date {
|
||||||
|
return new Date(
|
||||||
|
tehranCalendarDay(date).getTime() +
|
||||||
|
hour * 60 * 60 * 1000 -
|
||||||
|
TEHRAN_OFFSET_MS,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -21,7 +21,9 @@ export class CompaniesService {
|
|||||||
where: activeOnly ? { isActive: true } : undefined,
|
where: activeOnly ? { isActive: true } : undefined,
|
||||||
orderBy: [{ displayOrder: 'asc' }, { name: 'asc' }],
|
orderBy: [{ displayOrder: 'asc' }, { name: 'asc' }],
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return companies.map((c) => this.mapCompany(c));
|
return companies.map((c) => this.mapCompany(c));
|
||||||
@@ -32,7 +34,9 @@ export class CompaniesService {
|
|||||||
where: { id },
|
where: { id },
|
||||||
include: {
|
include: {
|
||||||
bankAccounts: { orderBy: { displayOrder: 'asc' } },
|
bankAccounts: { orderBy: { displayOrder: 'asc' } },
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!company) throw new NotFoundException('شرکت یافت نشد');
|
if (!company) throw new NotFoundException('شرکت یافت نشد');
|
||||||
@@ -57,12 +61,17 @@ export class CompaniesService {
|
|||||||
isActive: dto.isActive ?? true,
|
isActive: dto.isActive ?? true,
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return this.mapCompany(company);
|
return this.mapCompany(company);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('اسلاگ شرکت تکراری است');
|
throw new ConflictException('اسلاگ شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -90,12 +99,17 @@ export class CompaniesService {
|
|||||||
isActive: dto.isActive,
|
isActive: dto.isActive,
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return this.mapCompany(company);
|
return this.mapCompany(company);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('اسلاگ شرکت تکراری است');
|
throw new ConflictException('اسلاگ شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -108,7 +122,9 @@ export class CompaniesService {
|
|||||||
where: { id },
|
where: { id },
|
||||||
data: { isActive },
|
data: { isActive },
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { catalogs: true, products: true, bankAccounts: true } },
|
_count: {
|
||||||
|
select: { catalogs: true, products: true, bankAccounts: true },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return this.mapCompany(company);
|
return this.mapCompany(company);
|
||||||
@@ -151,8 +167,7 @@ export class CompaniesService {
|
|||||||
accountNumber: dto.accountNumber?.trim(),
|
accountNumber: dto.accountNumber?.trim(),
|
||||||
cardNumber: dto.cardNumber?.trim(),
|
cardNumber: dto.cardNumber?.trim(),
|
||||||
iban: dto.iban?.trim(),
|
iban: dto.iban?.trim(),
|
||||||
notes:
|
notes: dto.notes === undefined ? undefined : dto.notes?.trim() || null,
|
||||||
dto.notes === undefined ? undefined : dto.notes?.trim() || null,
|
|
||||||
displayOrder: dto.displayOrder,
|
displayOrder: dto.displayOrder,
|
||||||
isActive: dto.isActive,
|
isActive: dto.isActive,
|
||||||
},
|
},
|
||||||
@@ -181,23 +196,21 @@ export class CompaniesService {
|
|||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
private mapCompany(
|
private mapCompany(company: {
|
||||||
company: {
|
id: string;
|
||||||
id: string;
|
name: string;
|
||||||
name: string;
|
slug: string;
|
||||||
slug: string;
|
description: string | null;
|
||||||
description: string | null;
|
logoUrl: string | null;
|
||||||
logoUrl: string | null;
|
isActive: boolean;
|
||||||
isActive: boolean;
|
displayOrder: number;
|
||||||
displayOrder: number;
|
maxMeteragePerInvoice: number;
|
||||||
maxMeteragePerInvoice: number;
|
cashInvoiceValidityHours: number;
|
||||||
cashInvoiceValidityHours: number;
|
cashInvoiceValidUntilHour: number | null;
|
||||||
cashInvoiceValidUntilHour: number | null;
|
createdAt: Date;
|
||||||
createdAt: Date;
|
updatedAt: Date;
|
||||||
updatedAt: Date;
|
_count?: { catalogs: number; products: number; bankAccounts: number };
|
||||||
_count?: { catalogs: number; products: number; bankAccounts: number };
|
}) {
|
||||||
},
|
|
||||||
) {
|
|
||||||
return {
|
return {
|
||||||
id: company.id,
|
id: company.id,
|
||||||
name: company.name,
|
name: company.name,
|
||||||
|
|||||||
@@ -83,7 +83,10 @@ export class CustomersService {
|
|||||||
});
|
});
|
||||||
return this.map(customer);
|
return this.map(customer);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('این شماره قبلاً ثبت شده است');
|
throw new ConflictException('این شماره قبلاً ثبت شده است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -102,7 +105,11 @@ export class CustomersService {
|
|||||||
|
|
||||||
let firstName: string | undefined;
|
let firstName: string | undefined;
|
||||||
let lastName: string | undefined;
|
let lastName: string | undefined;
|
||||||
if (dto.name !== undefined || dto.firstName !== undefined || dto.lastName !== undefined) {
|
if (
|
||||||
|
dto.name !== undefined ||
|
||||||
|
dto.firstName !== undefined ||
|
||||||
|
dto.lastName !== undefined
|
||||||
|
) {
|
||||||
const names = this.resolveNames(dto);
|
const names = this.resolveNames(dto);
|
||||||
firstName = names.firstName;
|
firstName = names.firstName;
|
||||||
lastName = names.lastName;
|
lastName = names.lastName;
|
||||||
@@ -131,7 +138,10 @@ export class CustomersService {
|
|||||||
});
|
});
|
||||||
return this.map(customer);
|
return this.map(customer);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('این شماره قبلاً ثبت شده است');
|
throw new ConflictException('این شماره قبلاً ثبت شده است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -107,11 +107,7 @@ export class DashboardService {
|
|||||||
|
|
||||||
const sumAmounts = (
|
const sumAmounts = (
|
||||||
rows: { finalAmount: number | null; totalAmount: number | null }[],
|
rows: { finalAmount: number | null; totalAmount: number | null }[],
|
||||||
) =>
|
) => rows.reduce((s, o) => s + (o.finalAmount ?? o.totalAmount ?? 0), 0);
|
||||||
rows.reduce(
|
|
||||||
(s, o) => s + (o.finalAmount ?? o.totalAmount ?? 0),
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
|
|
||||||
const todaySales = sumAmounts(todayOrders);
|
const todaySales = sumAmounts(todayOrders);
|
||||||
const yesterdaySales = sumAmounts(yesterdayOrders);
|
const yesterdaySales = sumAmounts(yesterdayOrders);
|
||||||
@@ -130,7 +126,7 @@ export class DashboardService {
|
|||||||
(24 * 60 * 60 * 1000),
|
(24 * 60 * 60 * 1000),
|
||||||
);
|
);
|
||||||
if (dayIndex >= 0 && dayIndex < 28) {
|
if (dayIndex >= 0 && dayIndex < 28) {
|
||||||
salesByDay[dayIndex]! += order.finalAmount ?? order.totalAmount ?? 0;
|
salesByDay[dayIndex] += order.finalAmount ?? order.totalAmount ?? 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const maxSale = Math.max(...salesByDay, 1);
|
const maxSale = Math.max(...salesByDay, 1);
|
||||||
@@ -189,7 +185,12 @@ export class DashboardService {
|
|||||||
|
|
||||||
const byCompany = new Map<
|
const byCompany = new Map<
|
||||||
string,
|
string,
|
||||||
{ companyName: string; orderCount: number; totalAmount: number; meterage: number }
|
{
|
||||||
|
companyName: string;
|
||||||
|
orderCount: number;
|
||||||
|
totalAmount: number;
|
||||||
|
meterage: number;
|
||||||
|
}
|
||||||
>();
|
>();
|
||||||
const byStatus = new Map<string, number>();
|
const byStatus = new Map<string, number>();
|
||||||
|
|
||||||
@@ -228,7 +229,12 @@ export class DashboardService {
|
|||||||
{ id: 'cd-today', label: 'امروز', tone: 'danger' as const, days: 0 },
|
{ id: 'cd-today', label: 'امروز', tone: 'danger' as const, days: 0 },
|
||||||
{ id: 'cd-3', label: '۳ روز آینده', tone: 'warning' as const, days: 3 },
|
{ id: 'cd-3', label: '۳ روز آینده', tone: 'warning' as const, days: 3 },
|
||||||
{ id: 'cd-7', label: '۷ روز آینده', tone: 'warning' as const, days: 7 },
|
{ id: 'cd-7', label: '۷ روز آینده', tone: 'warning' as const, days: 7 },
|
||||||
{ id: 'cd-30', label: '۳۰ روز آینده', tone: 'neutral' as const, days: 30 },
|
{
|
||||||
|
id: 'cd-30',
|
||||||
|
label: '۳۰ روز آینده',
|
||||||
|
tone: 'neutral' as const,
|
||||||
|
days: 30,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return buckets.map((bucket) => {
|
return buckets.map((bucket) => {
|
||||||
|
|||||||
+10
-2
@@ -1,11 +1,17 @@
|
|||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { ValidationPipe } from '@nestjs/common';
|
import { ValidationPipe } from '@nestjs/common';
|
||||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||||
|
import { json, urlencoded } from 'express';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
|
|
||||||
|
// تصاویر چک و رسید بهصورت base64 داخل JSON میآیند و از سقف پیشفرض ۱۰۰KB رد میشوند
|
||||||
|
const bodyLimit = process.env.BODY_LIMIT || '25mb';
|
||||||
|
app.use(json({ limit: bodyLimit }));
|
||||||
|
app.use(urlencoded({ extended: true, limit: bodyLimit }));
|
||||||
|
|
||||||
// پشت LiteSpeed روی /server → GLOBAL_PREFIX=server/api
|
// پشت LiteSpeed روی /server → GLOBAL_PREFIX=server/api
|
||||||
const globalPrefix = process.env.GLOBAL_PREFIX || 'api';
|
const globalPrefix = process.env.GLOBAL_PREFIX || 'api';
|
||||||
app.setGlobalPrefix(globalPrefix);
|
app.setGlobalPrefix(globalPrefix);
|
||||||
@@ -33,7 +39,9 @@ async function bootstrap() {
|
|||||||
|
|
||||||
const port = process.env.PORT ?? 3000;
|
const port = process.env.PORT ?? 3000;
|
||||||
await app.listen(port);
|
await app.listen(port);
|
||||||
console.log(`Fabric Trade API listening on http://localhost:${port}/${globalPrefix}`);
|
console.log(
|
||||||
|
`Fabric Trade API listening on http://localhost:${port}/${globalPrefix}`,
|
||||||
|
);
|
||||||
console.log(`Swagger docs at http://localhost:${port}/${globalPrefix}/docs`);
|
console.log(`Swagger docs at http://localhost:${port}/${globalPrefix}/docs`);
|
||||||
}
|
}
|
||||||
bootstrap();
|
void bootstrap();
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ export class SubmitOrderItemDto {
|
|||||||
@Min(0.001)
|
@Min(0.001)
|
||||||
meterage!: number;
|
meterage!: number;
|
||||||
|
|
||||||
|
/** Alias پذیرفتهشده از کلاینتهای قدیمی؛ نادیده گرفته میشود */
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
requestedMeterage?: number;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
notes?: string;
|
notes?: string;
|
||||||
@@ -91,6 +97,11 @@ export class SubmitOrderDto {
|
|||||||
@IsEnum(SettlementType)
|
@IsEnum(SettlementType)
|
||||||
settlementType!: SettlementType;
|
settlementType!: SettlementType;
|
||||||
|
|
||||||
|
/** Alias پذیرفتهشده از کلاینتهای قدیمی؛ نادیده گرفته میشود */
|
||||||
|
@IsOptional()
|
||||||
|
@IsEnum(SettlementType)
|
||||||
|
settlementMethod?: SettlementType;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsEnum(CheckRegistrationMode)
|
@IsEnum(CheckRegistrationMode)
|
||||||
checkMode?: CheckRegistrationMode;
|
checkMode?: CheckRegistrationMode;
|
||||||
|
|||||||
@@ -31,19 +31,13 @@ export class CustomerOrdersController {
|
|||||||
|
|
||||||
@AuthType('customer')
|
@AuthType('customer')
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findOne(
|
findOne(@CurrentUser() user: AuthPrincipal, @Param('id') id: string) {
|
||||||
@CurrentUser() user: AuthPrincipal,
|
|
||||||
@Param('id') id: string,
|
|
||||||
) {
|
|
||||||
return this.ordersService.findMyOrder(user.id, id);
|
return this.ordersService.findMyOrder(user.id, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AuthType('customer')
|
@AuthType('customer')
|
||||||
@Post()
|
@Post()
|
||||||
submit(
|
submit(@CurrentUser() user: AuthPrincipal, @Body() dto: SubmitOrderDto) {
|
||||||
@CurrentUser() user: AuthPrincipal,
|
|
||||||
@Body() dto: SubmitOrderDto,
|
|
||||||
) {
|
|
||||||
return this.ordersService.submitOrder(user.id, dto);
|
return this.ordersService.submitOrder(user.id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,10 +68,7 @@ export class AdminOrdersController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
create(
|
create(@CurrentUser() user: AuthPrincipal, @Body() dto: AdminCreateOrderDto) {
|
||||||
@CurrentUser() user: AuthPrincipal,
|
|
||||||
@Body() dto: AdminCreateOrderDto,
|
|
||||||
) {
|
|
||||||
return this.ordersService.adminCreate(user.id, dto);
|
return this.ordersService.adminCreate(user.id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+150
-97
@@ -45,6 +45,23 @@ const orderInclude = {
|
|||||||
|
|
||||||
type OrderFull = Prisma.OrderGetPayload<{ include: typeof orderInclude }>;
|
type OrderFull = Prisma.OrderGetPayload<{ include: typeof orderInclude }>;
|
||||||
|
|
||||||
|
/** مبالغ ریالی روی Float ذخیره میشوند؛ گرد کردن از انباشت خطای اعشاری جلوگیری میکند. */
|
||||||
|
function roundMoney(value: number): number {
|
||||||
|
return Math.round(value * 100) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** بعد از تأیید چکها یا ارسال سفارش، مشتری نباید بتواند چکها را بازنویسی کند. */
|
||||||
|
const CHECK_EDITABLE_STATUSES: OrderStatus[] = [
|
||||||
|
OrderStatus.awaiting_review,
|
||||||
|
OrderStatus.pricing,
|
||||||
|
OrderStatus.needs_correction,
|
||||||
|
OrderStatus.awaiting_settlement_fix,
|
||||||
|
OrderStatus.check_in_progress,
|
||||||
|
OrderStatus.awaiting_check_review,
|
||||||
|
OrderStatus.check_needs_fix,
|
||||||
|
OrderStatus.check_rejected,
|
||||||
|
];
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OrdersService {
|
export class OrdersService {
|
||||||
constructor(private readonly prisma: PrismaService) {}
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
@@ -180,62 +197,62 @@ export class OrdersService {
|
|||||||
? computeCashInvoiceExpiry(company)
|
? computeCashInvoiceExpiry(company)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const orderNumber = await this.nextOrderNumber();
|
const order = await this.createWithUniqueOrderNumber((orderNumber) =>
|
||||||
|
this.prisma.$transaction(async (tx) => {
|
||||||
const order = await this.prisma.$transaction(async (tx) => {
|
const created = await tx.order.create({
|
||||||
const created = await tx.order.create({
|
data: {
|
||||||
data: {
|
orderNumber,
|
||||||
orderNumber,
|
userId,
|
||||||
userId,
|
companyId: company.id,
|
||||||
companyId: company.id,
|
companyName: company.name,
|
||||||
companyName: company.name,
|
settlementType,
|
||||||
settlementType,
|
checkMode,
|
||||||
checkMode,
|
status: OrderStatus.awaiting_review,
|
||||||
status: OrderStatus.awaiting_review,
|
totalMeterage,
|
||||||
totalMeterage,
|
notes: dto.notes?.trim() || null,
|
||||||
notes: dto.notes?.trim() || null,
|
checkRassDays: rass?.rassDays ?? null,
|
||||||
checkRassDays: rass?.rassDays ?? null,
|
checkRassDate: rass?.rassDate ? new Date(rass.rassDate) : null,
|
||||||
checkRassDate: rass?.rassDate ? new Date(rass.rassDate) : null,
|
cashInvoiceExpiresAt,
|
||||||
cashInvoiceExpiresAt,
|
items: { create: itemsData },
|
||||||
items: { create: itemsData },
|
checks:
|
||||||
checks:
|
settlementType === SettlementType.check && dto.checks
|
||||||
settlementType === SettlementType.check && dto.checks
|
? {
|
||||||
? {
|
create: dto.checks.map((c, index) =>
|
||||||
create: dto.checks.map((c, index) =>
|
this.mapCheckCreate(c, index + 1, checkMode!),
|
||||||
this.mapCheckCreate(c, index + 1, checkMode!),
|
),
|
||||||
),
|
}
|
||||||
}
|
: undefined,
|
||||||
: undefined,
|
statusHistory: {
|
||||||
statusHistory: {
|
create: [
|
||||||
create: [
|
{
|
||||||
{
|
fromStatus: null,
|
||||||
fromStatus: null,
|
toStatus: OrderStatus.submitted,
|
||||||
toStatus: OrderStatus.submitted,
|
changedBy: 'customer',
|
||||||
changedBy: 'customer',
|
note: 'سفارش ثبت شد',
|
||||||
note: 'سفارش ثبت شد',
|
},
|
||||||
},
|
{
|
||||||
{
|
fromStatus: OrderStatus.submitted,
|
||||||
fromStatus: OrderStatus.submitted,
|
toStatus: OrderStatus.awaiting_review,
|
||||||
toStatus: OrderStatus.awaiting_review,
|
changedBy: 'customer',
|
||||||
changedBy: 'customer',
|
note: 'ارسال برای بررسی مدیریت',
|
||||||
note: 'ارسال برای بررسی مدیریت',
|
},
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
},
|
},
|
||||||
},
|
include: orderInclude,
|
||||||
include: orderInclude,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear cart items for this company after successful submit
|
|
||||||
const cart = await tx.cart.findFirst({ where: { userId } });
|
|
||||||
if (cart) {
|
|
||||||
await tx.cartItem.deleteMany({
|
|
||||||
where: { cartId: cart.id, companyId: company.id },
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return created;
|
// Clear cart items for this company after successful submit
|
||||||
});
|
const cart = await tx.cart.findFirst({ where: { userId } });
|
||||||
|
if (cart) {
|
||||||
|
await tx.cartItem.deleteMany({
|
||||||
|
where: { cartId: cart.id, companyId: company.id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return created;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
return this.mapOrder(order);
|
return this.mapOrder(order);
|
||||||
}
|
}
|
||||||
@@ -257,7 +274,9 @@ export class OrdersService {
|
|||||||
if (!isValidPhone(phone)) {
|
if (!isValidPhone(phone)) {
|
||||||
throw new BadRequestException('شماره موبایل نامعتبر است');
|
throw new BadRequestException('شماره موبایل نامعتبر است');
|
||||||
}
|
}
|
||||||
let customer = await this.prisma.customer.findUnique({ where: { phone } });
|
let customer = await this.prisma.customer.findUnique({
|
||||||
|
where: { phone },
|
||||||
|
});
|
||||||
if (!customer) {
|
if (!customer) {
|
||||||
const names = splitFullName(dto.customerName || 'مشتری جدید');
|
const names = splitFullName(dto.customerName || 'مشتری جدید');
|
||||||
customer = await this.prisma.customer.create({
|
customer = await this.prisma.customer.create({
|
||||||
@@ -274,67 +293,79 @@ export class OrdersService {
|
|||||||
throw new BadRequestException('شناسه یا شماره مشتری الزامی است');
|
throw new BadRequestException('شناسه یا شماره مشتری الزامی است');
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderNumber = await this.nextOrderNumber();
|
|
||||||
const totalMeterage = dto.meterage ?? 0;
|
const totalMeterage = dto.meterage ?? 0;
|
||||||
|
const ownerId = userId;
|
||||||
|
|
||||||
const order = await this.prisma.order.create({
|
const order = await this.createWithUniqueOrderNumber((orderNumber) =>
|
||||||
data: {
|
this.prisma.order.create({
|
||||||
orderNumber,
|
data: {
|
||||||
userId,
|
orderNumber,
|
||||||
companyId: company.id,
|
userId: ownerId,
|
||||||
companyName: company.name,
|
companyId: company.id,
|
||||||
settlementType,
|
companyName: company.name,
|
||||||
status: OrderStatus.awaiting_review,
|
settlementType,
|
||||||
totalMeterage,
|
status: OrderStatus.awaiting_review,
|
||||||
notes: dto.notes?.trim() || null,
|
totalMeterage,
|
||||||
statusHistory: {
|
notes: dto.notes?.trim() || null,
|
||||||
create: {
|
statusHistory: {
|
||||||
fromStatus: null,
|
create: {
|
||||||
toStatus: OrderStatus.awaiting_review,
|
fromStatus: null,
|
||||||
changedBy: `admin:${adminId}`,
|
toStatus: OrderStatus.awaiting_review,
|
||||||
note: 'سفارش توسط ادمین ثبت شد',
|
changedBy: `admin:${adminId}`,
|
||||||
|
note: 'سفارش توسط ادمین ثبت شد',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
include: orderInclude,
|
||||||
include: orderInclude,
|
}),
|
||||||
});
|
);
|
||||||
|
|
||||||
return this.mapOrder(order, true);
|
return this.mapOrder(order, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updatePricing(
|
async updatePricing(id: string, adminId: string, dto: UpdateOrderPricingDto) {
|
||||||
id: string,
|
|
||||||
adminId: string,
|
|
||||||
dto: UpdateOrderPricingDto,
|
|
||||||
) {
|
|
||||||
const order = await this.getOrder(id);
|
const order = await this.getOrder(id);
|
||||||
|
|
||||||
|
const unknown = dto.items.find(
|
||||||
|
(item) => !order.items.some((i) => i.id === item.id),
|
||||||
|
);
|
||||||
|
if (unknown) {
|
||||||
|
throw new BadRequestException(`آیتم ${unknown.id} یافت نشد`);
|
||||||
|
}
|
||||||
|
|
||||||
await this.prisma.$transaction(async (tx) => {
|
await this.prisma.$transaction(async (tx) => {
|
||||||
let totalAmount = 0;
|
let totalAmount = 0;
|
||||||
let totalMeterage = 0;
|
let totalMeterage = 0;
|
||||||
|
|
||||||
for (const item of dto.items) {
|
// جمع کل باید روی همه آیتمهای سفارش حساب شود، نه فقط آیتمهای ارسالی
|
||||||
const existing = order.items.find((i) => i.id === item.id);
|
for (const existing of order.items) {
|
||||||
if (!existing) {
|
const item = dto.items.find((i) => i.id === existing.id);
|
||||||
throw new BadRequestException(`آیتم ${item.id} یافت نشد`);
|
|
||||||
}
|
|
||||||
const unitPrice =
|
const unitPrice =
|
||||||
item.unitPrice !== undefined
|
item?.unitPrice !== undefined
|
||||||
? item.unitPrice
|
? item.unitPrice
|
||||||
: item.supplyPrice !== undefined
|
: item?.supplyPrice !== undefined
|
||||||
? item.supplyPrice
|
? item.supplyPrice
|
||||||
: (existing.unitPrice ?? 0);
|
: (existing.unitPrice ?? 0);
|
||||||
const unitDiscount = item.unitDiscount ?? existing.unitDiscount ?? 0;
|
const unitDiscount = item?.unitDiscount ?? existing.unitDiscount ?? 0;
|
||||||
|
if (unitDiscount > unitPrice) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'تخفیف واحد نمیتواند از قیمت واحد بیشتر باشد',
|
||||||
|
);
|
||||||
|
}
|
||||||
const confirmed =
|
const confirmed =
|
||||||
item.confirmedMeterage ??
|
item?.confirmedMeterage ??
|
||||||
existing.confirmedMeterage ??
|
existing.confirmedMeterage ??
|
||||||
existing.requestedMeterage;
|
existing.requestedMeterage;
|
||||||
const lineTotal = Math.max(0, (unitPrice - unitDiscount) * confirmed);
|
const lineTotal = roundMoney(
|
||||||
|
Math.max(0, (unitPrice - unitDiscount) * confirmed),
|
||||||
|
);
|
||||||
totalAmount += lineTotal;
|
totalAmount += lineTotal;
|
||||||
totalMeterage += confirmed;
|
totalMeterage += confirmed;
|
||||||
|
|
||||||
|
if (!item) continue;
|
||||||
|
|
||||||
await tx.orderItem.update({
|
await tx.orderItem.update({
|
||||||
where: { id: item.id },
|
where: { id: existing.id },
|
||||||
data: {
|
data: {
|
||||||
confirmedMeterage: confirmed,
|
confirmedMeterage: confirmed,
|
||||||
unitPrice,
|
unitPrice,
|
||||||
@@ -343,10 +374,13 @@ export class OrdersService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
totalAmount = roundMoney(totalAmount);
|
||||||
|
|
||||||
const shippingCost = dto.shippingCost ?? order.shippingCost ?? 0;
|
const shippingCost = dto.shippingCost ?? order.shippingCost ?? 0;
|
||||||
const totalDiscount = dto.totalDiscount ?? order.totalDiscount ?? 0;
|
const totalDiscount = dto.totalDiscount ?? order.totalDiscount ?? 0;
|
||||||
const finalAmount = Math.max(0, totalAmount + shippingCost - totalDiscount);
|
const finalAmount = roundMoney(
|
||||||
|
Math.max(0, totalAmount + shippingCost - totalDiscount),
|
||||||
|
);
|
||||||
|
|
||||||
const nextStatus =
|
const nextStatus =
|
||||||
order.status === OrderStatus.awaiting_review ||
|
order.status === OrderStatus.awaiting_review ||
|
||||||
@@ -382,11 +416,7 @@ export class OrdersService {
|
|||||||
return this.findAdminOrder(id);
|
return this.findAdminOrder(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateStatus(
|
async updateStatus(id: string, adminId: string, dto: UpdateOrderStatusDto) {
|
||||||
id: string,
|
|
||||||
adminId: string,
|
|
||||||
dto: UpdateOrderStatusDto,
|
|
||||||
) {
|
|
||||||
const order = await this.getOrder(id);
|
const order = await this.getOrder(id);
|
||||||
if (order.status === dto.status) {
|
if (order.status === dto.status) {
|
||||||
return this.mapOrder(order, true);
|
return this.mapOrder(order, true);
|
||||||
@@ -435,8 +465,14 @@ export class OrdersService {
|
|||||||
if (order.settlementType !== SettlementType.check) {
|
if (order.settlementType !== SettlementType.check) {
|
||||||
throw new BadRequestException('این سفارش تسویه چکی نیست');
|
throw new BadRequestException('این سفارش تسویه چکی نیست');
|
||||||
}
|
}
|
||||||
|
if (!CHECK_EDITABLE_STATUSES.includes(order.status)) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'در وضعیت فعلی سفارش امکان ویرایش چکها وجود ندارد',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const checkMode = dto.checkMode ?? order.checkMode ?? CheckRegistrationMode.full;
|
const checkMode =
|
||||||
|
dto.checkMode ?? order.checkMode ?? CheckRegistrationMode.full;
|
||||||
const rass = calculateCheckRass(
|
const rass = calculateCheckRass(
|
||||||
dto.checks.map((c) => ({ amount: c.amount, dueDate: c.dueDate })),
|
dto.checks.map((c) => ({ amount: c.amount, dueDate: c.dueDate })),
|
||||||
order.createdAt,
|
order.createdAt,
|
||||||
@@ -512,6 +548,23 @@ export class OrdersService {
|
|||||||
return `${generateOrderNumber()}-${Date.now().toString().slice(-3)}`;
|
return `${generateOrderNumber()}-${Date.now().toString().slice(-3)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** بین انتخاب شماره و درج، امکان تصاحب شماره توسط درخواست همزمان هست. */
|
||||||
|
private async createWithUniqueOrderNumber<T>(
|
||||||
|
create: (orderNumber: string) => Promise<T>,
|
||||||
|
): Promise<T> {
|
||||||
|
for (let attempt = 0; ; attempt++) {
|
||||||
|
const orderNumber = await this.nextOrderNumber();
|
||||||
|
try {
|
||||||
|
return await create(orderNumber);
|
||||||
|
} catch (e) {
|
||||||
|
const isDuplicate =
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002';
|
||||||
|
if (!isDuplicate || attempt >= 4) throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async getOrder(id: string): Promise<OrderFull> {
|
private async getOrder(id: string): Promise<OrderFull> {
|
||||||
const order = await this.prisma.order.findUnique({
|
const order = await this.prisma.order.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
|
|||||||
@@ -81,7 +81,10 @@ export class ProductsService {
|
|||||||
});
|
});
|
||||||
return this.map(product);
|
return this.map(product);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('کد محصول در این شرکت تکراری است');
|
throw new ConflictException('کد محصول در این شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
@@ -135,7 +138,10 @@ export class ProductsService {
|
|||||||
});
|
});
|
||||||
return this.map(product);
|
return this.map(product);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
|
if (
|
||||||
|
e instanceof Prisma.PrismaClientKnownRequestError &&
|
||||||
|
e.code === 'P2002'
|
||||||
|
) {
|
||||||
throw new ConflictException('کد محصول در این شرکت تکراری است');
|
throw new ConflictException('کد محصول در این شرکت تکراری است');
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -34,10 +34,7 @@ export class ShipmentsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
create(
|
create(@CurrentUser() user: AuthPrincipal, @Body() dto: CreateShipmentDto) {
|
||||||
@CurrentUser() user: AuthPrincipal,
|
|
||||||
@Body() dto: CreateShipmentDto,
|
|
||||||
) {
|
|
||||||
return this.shipmentsService.create(user.id, dto);
|
return this.shipmentsService.create(user.id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ export class ShipmentsService {
|
|||||||
include: { order: { include: { user: true } } },
|
include: { order: { include: { user: true } } },
|
||||||
});
|
});
|
||||||
|
|
||||||
const nextOrderStatus = SHIPMENT_TO_ORDER[nextStatus!];
|
const nextOrderStatus = SHIPMENT_TO_ORDER[nextStatus];
|
||||||
if (shipment.order.status !== nextOrderStatus) {
|
if (shipment.order.status !== nextOrderStatus) {
|
||||||
await tx.order.update({
|
await tx.order.update({
|
||||||
where: { id: shipment.orderId },
|
where: { id: shipment.orderId },
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { SmsService } from './sms.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [SmsService],
|
||||||
|
exports: [SmsService],
|
||||||
|
})
|
||||||
|
export class SmsModule {}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
|
export type SmsSendResult = {
|
||||||
|
success: boolean;
|
||||||
|
raw: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
function maskPhone(phone: string): string {
|
||||||
|
return phone.length <= 4
|
||||||
|
? '****'
|
||||||
|
: `${phone.slice(0, 4)}****${phone.slice(-2)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SmsService {
|
||||||
|
private readonly logger = new Logger(SmsService.name);
|
||||||
|
|
||||||
|
constructor(private readonly config: ConfigService) {}
|
||||||
|
|
||||||
|
isEnabled(): boolean {
|
||||||
|
const raw = (
|
||||||
|
this.config.get<string>('SMS_ENABLED', 'true') ?? 'true'
|
||||||
|
).toLowerCase();
|
||||||
|
return raw === '1' || raw === 'true' || raw === 'yes';
|
||||||
|
}
|
||||||
|
|
||||||
|
async send(to: string, message: string): Promise<SmsSendResult> {
|
||||||
|
const url = this.config.get<string>(
|
||||||
|
'SMS_API_URL',
|
||||||
|
'http://185.231.112.101/api/createsms',
|
||||||
|
);
|
||||||
|
const secretKey = this.config.get<string>('SMS_SECRET_KEY')?.trim();
|
||||||
|
if (!secretKey) {
|
||||||
|
this.logger.error('SMS_SECRET_KEY تنظیم نشده است');
|
||||||
|
return { success: false, raw: 'SMS_SECRET_KEY missing' };
|
||||||
|
}
|
||||||
|
const platform = this.config.get<string>('SMS_PLATFORM', 'rayegansms');
|
||||||
|
const host = this.resolveHost();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
secret_key: secretKey,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
phone: to,
|
||||||
|
host,
|
||||||
|
text: message.trim(),
|
||||||
|
platform,
|
||||||
|
}),
|
||||||
|
signal: AbortSignal.timeout(15_000),
|
||||||
|
});
|
||||||
|
|
||||||
|
const text = await response.text();
|
||||||
|
let body: unknown = text;
|
||||||
|
try {
|
||||||
|
body = text ? JSON.parse(text) : null;
|
||||||
|
} catch {
|
||||||
|
/* keep raw text */
|
||||||
|
}
|
||||||
|
|
||||||
|
let success = response.ok;
|
||||||
|
if (success && body && typeof body === 'object') {
|
||||||
|
const obj = body as Record<string, unknown>;
|
||||||
|
if ('success' in obj && obj.success === false) success = false;
|
||||||
|
else if ('ok' in obj && obj.ok === false) success = false;
|
||||||
|
else if (
|
||||||
|
typeof obj.status === 'string' &&
|
||||||
|
['error', 'failed', 'fail'].includes(obj.status.toLowerCase())
|
||||||
|
) {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
this.logger.warn(
|
||||||
|
`SMS failed to ${maskPhone(to)}: ${JSON.stringify(body)}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success, raw: body };
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.error(
|
||||||
|
`SMS request error to ${maskPhone(to)}`,
|
||||||
|
err instanceof Error ? err.stack : err,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
raw: err instanceof Error ? err.message : String(err),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildOtpMessage(code: string): string {
|
||||||
|
const appName = this.config.get<string>('SMS_APP_NAME', 'پارچه');
|
||||||
|
return `رمز عبور یکبار مصرف شما جهت ورود به اپلیکیشن ${appName} ${code} می باشد`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private resolveHost(): string {
|
||||||
|
const fromEnv =
|
||||||
|
this.config.get<string>('SMS_HOST')?.trim() ||
|
||||||
|
this.config.get<string>('SMS_APP_NAME')?.trim();
|
||||||
|
if (fromEnv) return fromEnv;
|
||||||
|
return 'fabric';
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user