This commit is contained in:
mahyargdz
2025-09-14 15:15:03 +03:30
commit be82059172
534 changed files with 51310 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
import { BaseHttpController } from "inversify-express-utils";
import { HttpStatus } from "../enums/httpStatus.enum";
import { ResponseFactory } from "../factories/response.factory";
import { IPageFormat } from "../interfaces/PageFormatInterface";
import { IPaginateDataFormat } from "../interfaces/PaginateDataFormatInterface";
abstract class BaseController extends BaseHttpController {
private formatLink(page: number | boolean, limit: number): string | boolean {
const { protocol, hostname, path } = this.httpContext.request;
if (!page) return false;
return `${protocol}://${hostname}${path}?page=${page}&limit=${limit}`;
}
protected formatPage(page: number, limit: number, totalItems: number): IPageFormat {
const totalPages = Math.ceil(totalItems / limit);
const prevPage = page === 1 ? false : page - 1;
const nextPage = page >= totalPages ? false : page + 1;
return {
page,
limit,
totalItems,
totalPages,
prevPage: this.formatLink(prevPage, limit),
nextPage: this.formatLink(nextPage, limit),
};
}
protected paginate(count: number): IPaginateDataFormat {
const page = this.httpContext.request.query["page"] as string;
const limit = this.httpContext.request.query["limit"] as string;
const paginationInfo = this.formatPage(parseInt(page) || 1, parseInt(limit) || 10, count);
const results: IPaginateDataFormat = {
pager: paginationInfo,
};
return results;
}
protected response(data: Record<string, unknown>, status: HttpStatus = HttpStatus.Ok) {
const response = ResponseFactory.successResponse(status, data);
return this.json(response, status);
}
}
export { BaseController };
+23
View File
@@ -0,0 +1,23 @@
import { Model } from "mongoose";
abstract class BaseRepository<T> {
public model: Model<T>;
protected constructor(model: Model<T>) {
this.model = model;
}
async findById(id: string | number) {
return this.model.findById(id);
}
async findAll() {
return this.model.find().sort({ createdAt: -1 });
}
async delete(id: string) {
return this.model.findByIdAndDelete(id);
}
}
export { BaseRepository };
+19
View File
@@ -0,0 +1,19 @@
import { interfaces } from "inversify-express-utils";
const USER_KEY = "custom:user";
// Middleware to resolve parameters for custom decorators
export function resolveCustomDecorators(httpContext: interfaces.HttpContext, target: any, propertyKey: string | symbol, args: any[]) {
const metadata = Reflect.getMetadata(USER_KEY, target, propertyKey) || [];
for (const { parameterIndex, callback } of metadata) {
args[parameterIndex] = callback(httpContext);
}
}
export function createParamDecorator(callback: (httpContext: interfaces.HttpContext) => unknown): ParameterDecorator {
return (target, propertyKey, parameterIndex) => {
const existingMetadata = Reflect.getMetadata(USER_KEY, target, propertyKey as any) || [];
existingMetadata.push({ parameterIndex, callback });
Reflect.defineMetadata(USER_KEY, existingMetadata, target, propertyKey as any);
};
}
+91
View File
@@ -0,0 +1,91 @@
import "reflect-metadata";
// ApiOperation decorator
export function ApiOperation(summary: string): MethodDecorator {
return function (target, propertyKey) {
Reflect.defineMetadata("api:operation:summary", summary, target, propertyKey);
};
}
// ApiResponse decorator
export function ApiResponse(description: string, status: number = 200, example?: any): MethodDecorator {
return function (target, propertyKey) {
const existingResponses = Reflect.getMetadata("api:responses", target, propertyKey) || [];
existingResponses.push({ description, status, example });
Reflect.defineMetadata("api:responses", existingResponses, target, propertyKey);
};
}
// ApiTags decorator
export function ApiTags(...tags: string[]): ClassDecorator {
return function (target) {
Reflect.defineMetadata("api:tags", tags, target);
};
}
// ApiParam decorator
export function ApiParam(name: string, description: string, required: boolean = false): MethodDecorator {
return function (target, propertyKey) {
const existingParams = Reflect.getMetadata("api:params", target, propertyKey) || [];
existingParams.push({ name, description, required });
Reflect.defineMetadata("api:params", existingParams, target, propertyKey);
};
}
// ApiQuery decorator
export function ApiQuery(
name: string,
description: string,
required: boolean = false,
type: "string" | "array" = "string",
): MethodDecorator {
return function (target, propertyKey) {
const existingQueries = Reflect.getMetadata("api:queries", target, propertyKey) || [];
existingQueries.push({ name, description, required, type });
Reflect.defineMetadata("api:queries", existingQueries, target, propertyKey);
};
}
// ApiBody decorator
export function ApiBody(description: string): MethodDecorator {
return function (target, propertyKey) {
Reflect.defineMetadata("api:body", description, target, propertyKey);
};
}
export function ApiModel(dto: any): MethodDecorator {
return function (target, propertyKey) {
Reflect.defineMetadata("api:body:dto", dto, target, propertyKey);
};
}
export interface ApiPropertyOptions {
type: string;
description?: string;
example?: any;
required?: boolean;
}
export function ApiProperty(options: ApiPropertyOptions): PropertyDecorator {
return function (target, propertyKey) {
Reflect.defineMetadata("api:property", options, target, propertyKey);
};
}
export function ApiAuth(): MethodDecorator {
return function (target, propertyKey) {
Reflect.defineMetadata("api:auth", true, target, propertyKey);
};
}
export function ApiFile(description: string = "file", required: boolean = true, multiple: boolean = false): MethodDecorator {
return function (target, propertyKey) {
Reflect.defineMetadata("api:file", { description, required, multiple }, target, propertyKey);
};
}
export function AdminRoute(): MethodDecorator {
return function (target, propertyKey) {
Reflect.defineMetadata("api:isAdmin", true, target, propertyKey);
};
}
+9
View File
@@ -0,0 +1,9 @@
import "reflect-metadata";
import { HttpContext } from "inversify-express-utils";
import { createParamDecorator } from "./param.decorator";
// export function User(): ParameterDecorator {
// return createParamDecorator((httpContext: interfaces.HttpContext) => httpContext.user);
// }
export const User = () => createParamDecorator((ctx: HttpContext) => ctx.request.user);
@@ -0,0 +1,128 @@
import { ValidationArguments, ValidationOptions, registerDecorator } from "class-validator";
import moment from "jalali-moment";
import { Model, isValidObjectId } from "mongoose";
import { CommonMessage } from "../enums/message.enum";
// @ValidatorConstraint({ async: true })
// export class IsTypeValidConstraint implements ValidatorConstraintInterface {
// // eslint-disable-next-line no-unused-vars
// async validate(type: string, _args: ValidationArguments) {
// return type === process.env.USER_TYPE || type === process.env.SELLER_TYPE;
// }
// // eslint-disable-next-line no-unused-vars
// defaultMessage(_args: ValidationArguments) {
// return AuthMessage.TypeError;
// }
// }
// export function IsTypeValid(validationOptions?: ValidationOptions) {
// return function (object: object, propertyName: string) {
// registerDecorator({
// target: object.constructor,
// propertyName: propertyName,
// options: validationOptions,
// constraints: [],
// validator: IsTypeValidConstraint,
// });
// };
// }
// export function IsPhoneExists<T>(model: Model<T>, userId?: string, validationOptions?: ValidationOptions) {
// return function (object: object, propertyName: string) {
// registerDecorator({
// name: "IsPhoneExists",
// target: object.constructor,
// propertyName: propertyName,
// options: validationOptions,
// constraints: [userId],
// validator: {
// async validate(phoneNumber: string, args: ValidationArguments) {
// const [userId] = args.constraints;
// const user = await model.exists({ phoneNumber, _id: { $ne: userId } });
// return !user; // if user exists with a different ID, return false (validation fails)
// },
// // eslint-disable-next-line no-unused-vars
// defaultMessage(_args: ValidationArguments) {
// return AuthMessage.NumberExists;
// },
// },
// });
// };
// }
// export function IsEmailExists<T>(model: Model<T>, userId?: string, validationOptions?: ValidationOptions) {
// return function (object: object, propertyName: string) {
// registerDecorator({
// name: "IsEmailExists",
// target: object.constructor,
// propertyName: propertyName,
// options: validationOptions,
// constraints: [userId],
// validator: {
// async validate(email: string, args: ValidationArguments) {
// const [userId] = args.constraints;
// const user = await model.exists({ email, _id: { $ne: userId } });
// return !user; // if user exists with a different ID, return false (validation fails)
// },
// // eslint-disable-next-line no-unused-vars
// defaultMessage(_args: ValidationArguments) {
// return AuthMessage.EmailExists;
// },
// },
// });
// };
// }
export function IsValidId(model: Model<any> | Array<Model<any>>, validationOptions?: ValidationOptions) {
return function (object: object, propertyName: string) {
registerDecorator({
name: "IsValidId",
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [model],
validator: {
// eslint-disable-next-line no-unused-vars
async validate(id: string | number, _args: ValidationArguments) {
if (typeof id === "string") {
if (!isValidObjectId(id)) return false;
}
// Normalize to an array for uniform processing
const models = Array.isArray(model) ? model : [model];
// Check the ID in each model
for (const m of models) {
const existId = await m.exists({ _id: id });
if (existId) return true; // ID exists in one of the models
}
return false; // ID does not exist in any of the models
},
defaultMessage(args: ValidationArguments) {
return `${CommonMessage.NotValidId} ${args.property}`;
},
},
});
};
}
export function IsValidPersianDate(validationOptions?: ValidationOptions) {
return function (object: object, propertyName: string) {
registerDecorator({
name: "IsValidPersianDate",
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [],
validator: {
validate(date: string) {
return moment(date, "jYYYY/jMM/jDD", true).isValid();
},
defaultMessage() {
return "Invalid Persian date format. Expected format is YYYY/MM/DD.";
},
},
});
};
}
+19
View File
@@ -0,0 +1,19 @@
import { Expose } from "class-transformer";
import { IsInt, IsNotEmpty, IsOptional, Max, Min } from "class-validator";
export class PaginationDTO {
@Expose()
@IsOptional()
@IsNotEmpty()
@IsInt()
@Min(1)
page?: number;
@Expose()
@IsOptional()
@IsNotEmpty()
@IsInt()
@Min(1)
@Max(50)
limit?: number;
}
+11
View File
@@ -0,0 +1,11 @@
import { Expose } from "class-transformer";
import { IsMongoId, IsNotEmpty } from "class-validator";
import { CommonMessage } from "../enums/message.enum";
export class ParamDto {
@Expose()
@IsNotEmpty()
@IsMongoId({ message: CommonMessage.NotValidId })
id: string;
}
+14
View File
@@ -0,0 +1,14 @@
export enum CategoryThemeEnum {
Sized = "Size",
Colored = "Color",
Meterage = "Meterage",
No_color_No_sized = "noColor_noSize",
}
export enum categoryAttType {
Text = "text",
Select = "select",
Number = "number",
CheckBox = "checkbox",
// Input = "input",
}
+7
View File
@@ -0,0 +1,7 @@
export enum HttpMethod {
Post = "POST",
Get = "GET",
Patch = "PATCH",
Put = "PUT",
Delete = "DELETE",
}
+13
View File
@@ -0,0 +1,13 @@
export const enum HttpStatus {
Ok = 200,
Created = 201,
Accepted = 202,
NoContent = 204,
BadRequest = 400,
Unauthorized = 401,
Forbidden = 403,
NotFound = 404,
Conflict = 409,
PayloadTooLarge = 413,
InternalServerError = 500,
}
+9
View File
@@ -0,0 +1,9 @@
export enum DisplayLocations {
Mobile = "mobile",
Desktop = "desktop",
}
export enum MediaType {
Banner = "banner",
Slider = "slider",
}
+325
View File
@@ -0,0 +1,325 @@
export const enum AuthMessage {
//otp
OtpSentToNo = "کد به شماره موبایل شما ارسال شد",
OtpNotEmpty = "کد نباید خالی باشد",
OtpAlreadySentToNo = "کد به شماره موبایل شما ارسال شده است",
OtpAlreadySentToEmail = "کد به ایمیل شما ارسال شده است لطفا ایمیل خود را چک کنید یا بعد از چند دقیقه مجدد تلاش کنید",
OtpSentToEmail = "کد به ایمیل شما ارسال شد",
EmailSent = "ایمیل فعال سازی برای شما ارسال شد",
OtpIncorrect = "کد صحیح نمی باشد",
OtpCodeLength = "طول کد باید حداقل ۵ و حداکثر ۵ کاراکتر باشد",
//login/logout/auth
SuccessLogin = "با موفقیت وارد شدید",
PasswordChangedSuccessfully = "پسورد با موفقیت تغییر کرد",
EmailOrPasswordInc = "ایمیل یا پسورد اشتباه است",
ShopNotFound = "فروشگاه با این ایدی پیدا نشد",
IncorrectNumber = "فرمت موبایل اشتباه است",
UserIsLoggedIn = "شما قبلا وارد شدید",
LoggedOut = "شما از سیستم خارج شدید",
NeedLogin = "لطفا وارد حساب کاربری خود شوید",
EmailOrPhone = "یکی از ایمیل یا موبایل باید ارسال شود",
NumberNotEmpty = "شماره موبایل نباید خالی باشد",
TypeNotEmpty = "نوع کاربر نباید خالی باشد",
IncorrectEmail = "فرمت ایمیل اشتباه است",
EmailNotEmpty = "ایمیل نباید خالی باشد",
PasswordNotEmpty = "پسورد نباید خالی باشد",
NumberExists = "این شماره قبلا استفاده شده است",
EmailExists = "این ایمیل قبلا استفاده شده است",
TypeError = "تایپ اشتباه می باشد",
//token
TokenNotEmpty = "توکن نباید خالی باشد",
TokenNotFound = "توکن پیدا نشد",
TokenExpired = " توکن منقضی شده است لطفا دوباره وارد شوید",
TokenNotAssigned = " توکن به هیج کاربری متعلق نمی باشد دوباره وارد شوید",
AuthFailed = "کاربر احراز هویت نشده است",
InsufficientRole = "رول کاربر مجاز نیست",
InsufficientPermissions = "دسترسی‌های کاربر کافی نیست",
}
export const enum SellerMessage {
ShopUpdated = "اطلاعات فروشگاه با موفقیت آپدیت شد",
ShopIdIncorrect = "فرمت شناسه ملی شرکت اشتباه است باید 11 رقم و بدون علامت اضافی و به صورت رشته ارسال شود",
SellerNotFound = "فروشنده یافت نشد",
VideoWasWached = "قبلا این ویدیو را مشاهده کرده اید",
CardNumberIncorrect = "فرمت شماره کارت اشتباه است باید 16 رقم و بدون علامت اضافی و به صورت رشته ارسال شود",
CompanyDuplicate = "مشخصات شرکت تکراری می باشد",
RealSellerDuplicate = "مشخصات فروشنده تکراری می باشد",
SellerDocumentNotFound = "مدرک فروشنده یافت نشد",
DocumentTypeDuplicate = "نوع مدرک تکراری می باشد",
WholesaleRequestPending = "درخواست عمده فروشی شما در حال بررسی می باشد",
WholesaleRequestCreated = "درخواست عمده فروشی با موفقیت ثبت شد",
StatusNotFound = "وضعیت فروشنده یافت نشد",
WholesaleRequestNotFound = "درخواست عمده فروشی یافت نشد",
WholesaleRequestApproved = "درخواست عمده فروشی تایید شد",
InvalidBusinessType = "نوع فعالیت اشتباه است",
}
export const enum UserMessage {
UserUpdated = "اطلاعات کاربر با موفقیت آپدیت شد",
EmailNotExist = "ایمیل کاربر ثبت نشده است",
UserNotFound = "کاربری با این ایدی یافت نشد",
}
export const enum CommonMessage {
NotFoundBySlug = "با این اسلاگ پیدا نشد",
Created = "با موفقیت اضافه شد",
NameNotEmpty = "اسم نباید خالی باشد",
NationalCodeIncorrect = " فرمت کد ملی اشتباه است باید 10 رقم و بدون علامت اضافی و به صورت رشته ارسال شود",
PostalIncorrect = "فرمت شماره پستی اشتباه است باید 10 رقم و بدون علامت اضافی و به صورت رشته ارسال شود",
ShebaIncorrect = "فرمت شماره شبا اشتباه است باید 24 رقم و بدون علامت اضافی و به صورت رشته ارسال شود",
TelephoneNumberIncorrect = "فرمت شماره تلفن اشتباه است نباید شامل کاراکتر های خاص باشد",
NotFound = "کاربری با این ایدی پیدا نشد",
NotValid = "آیدی کاربر صحیح نمی باشد",
NotValidId = "آیدی صحیح نمی باشد",
NotEnoughVariant = "محصول تنوعی ندارد",
NotFoundById = "دیتا با این آیدی یافت نشد",
Deleted = "با موفقیت حذف شد",
Updated = "با موفقیت آپدیت شد",
DuplicateName = "نام تکراری می باشد",
SellerNotFound = "فروشنده یافت نشد",
SettingExists = "تنظیمات وجود دارد.در صورت نیاز آنرا ویرایش کنید.",
}
export const enum CategoryMessage {
Created = "دسته بندی با موفقیت ساخته شد",
Deleted = "دسته بندی با موفقیت حذف شد.",
Updated = "دسته بندی با موفقیت اپدیت شد.",
ParentNotExist = "کتگوری والد با این ایدی وجود ندارد",
description = "توضیحات را وارد کنید",
DuplicateTitle = "عنوان انگلیسی تکراری می باشد",
DuplicateSlug = "عنوان اسلاگ تکراری می باشد",
AlreadyExist = "تنوع قبلا ساخته شده است",
AttAlreadyExist = "ویژگی‌های این دسته بندی قبلا ساخته شده است",
VariantCreated = "تنوع‌های دسته بندی با موفقیت ساخته شدند",
AttributeCreated = "ویژگی‌های دسته بندی با موفقیت ساخته شدند",
NotValidId = "آیدی کتگوری صحیح نمی باشد",
MissingColors = "داده‌های رنگ برای تم انتخاب شده موجود نیست.",
MissingSizes = "داده‌های سایز برای تم انتخاب شده موجود نیست.",
MissingMeterages = "داده‌های متراژ برای تم انتخاب شده موجود نیست.",
InvalidTheme = "ویژگی‌های ارسال شده با تم انتخاب شده مطابقت ندارند یا ناقص هستند.",
NotFound = "کتگوری با این نام پیدا نشد",
ParentHasChild = "فرزند این دسته بندی قبلا ساخته شده است",
CanNotDelete = "دسته بندی نمیتواند حذف شود",
CategoryHasProduct = "این دسته بندی دارای محصول می باشد و قابل حذف نمی باشد",
CategoryIsParent = "این دسته بندی دارای زیر دسته می باشد و قابل حذف نمی باشد",
CategoryNotValidToChose = "کتگوری برای انتخاب مجاز نمی‌باشد",
AttributeDeleted = "ویژگی با موفقیت حذف شد",
}
export const enum BrandMessage {
NotFound = "برندی با این اسم یافت نشد",
Exist = "برند با این نام وجود دارد",
Created = "برند جدید با موفقیت ساخته شد",
}
export const enum ProductMessage {
Created = "کالا با موفقیت ساخته شد",
ProductRequested = "درخواست اضافه کردن کالا با موفقیت ثبت شد",
NotFound = "کالایی با این ایدی یافت نشد",
CreatedAttribute = "مشخصات کالا با موفقیت ساخته شد",
DuplicateName = "نام مدل تکراری می باشد",
ProductNotFound = "محصول با این ایدی یافت نشد",
ProductVariantNotFound = "تنوع محصول با این ایدی یافت نشد",
CanNotUpdate = "این کالا متعلق به فروشنده نمی باشد",
CanNotDeleteQuestion = "حذف پرسش با مشکل مواجه شد.",
CanNotDeleteComment = "حذف کامنت با مشکل مواجه شد.",
ProductReadyForRelease = "کالا ثبت شد و آماده‌ی انتشار می باشد",
ProductIsInNextStep = "کالا قبلا این مرحله را گذرانده است",
ProductIsInDraftStep = "کالا در حالت انتشار نمی‌باشد",
VariantCreated = "تنوع با موفقیت ساخته شد",
VariantUpdated = "تنوع با موفقیت آپدیت شد",
Deleted = "محصول و تمامی تنوع های آن با موفقیت حذف شدند.",
CanNotDelete = "محصول قابل حذف نمی باشد",
CanNotUpdateProduct = "محصول قابل اپدیت نمی باشد",
ProductMustBeInDraft = "کالا برای اپدیت باید در حالت پیش نویس باشد",
ProductUpdated = "محصول با موفقیت آپدیت شد",
ProductWithNoVariantCategoryTheme = "کالا‌هایی که دسته بندی آن ها بدون تنوع می باشد بیشتر از یک تنوع نمی توانند داشته باشند",
Cloned = "کالای مورد نظر کلون شد",
VariantAlreadyExists = "تنوع محصول قبلا ساخته شده است",
}
export const enum ProductRequestMessage {
RequestPhotoInvalid = "برای درج درخواست عکاسی باید تعداد عکس هم ارسال شود",
PhotoShouldSent = "درصورت دارا بودن عکس باید آن را ارسال کنید",
NotFound = "درخواستی برای این فروشنده با این ایدی یافت نشد",
}
export const enum WarrantyMessage {
Created = "گارانتی با موفقیت ساخته شد",
DuplicateName = "نام تکراری می باشد",
}
export const enum ContractMessage {
Created = "قرارداد با موفقیت ساخته شد",
NotFound = "قراردادی با این نام پیدا نشد",
AlreadyExist = "قرارداد قبلا ساخته شده است",
ContractNotFound = "قراردادی پیدا نشد",
ContractAlreadySigned = "قرارداد قبلا امضا شده است",
}
export const enum AttributeMessage {
AttributeNotFound = "ویژگی دسته‌بندی یافت نشد.",
AttributeIdIsIncorrect = "آیدی ویژگی صحیح نمی باشد.",
ColorNotAllowedForSizedTheme = "استفاده از ویژگی رنگ یا متراژ برای دسته‌بندی با تم سایز مجاز نیست.",
SizeNotAllowedForColoredTheme = "استفاده از ویژگی سایز یا متراژ برای دسته‌بندی با تم رنگ مجاز نیست.",
ColorRequiredForColoredTheme = "ویژگی رنگ برای دسته‌بندی با تم رنگ الزامی است.",
SizeRequiredForSizedTheme = "ویژگی سایز برای دسته‌بندی با تم سایز الزامی است.",
MeterageRequiredForMeterageTheme = "ویژگی متراژ برای دسته‌بندی با تم متراژ الزامی است.",
ColorOrSizeNotAllowedForMeterageTheme = "استفاده از ویژگی رنگ یا سایز برای دسته‌بندی با تم متراژ مجاز نیست.",
UnknownCategoryTheme = "تم دسته‌بندی نامشخص است.",
ThemeIsNoColorNoSize = "تم دسته‌بندی بدون رنگ و سایز می‌باشد.",
ThemeIsNoColorNoSizeNoMeterage = "تم دسته‌بندی بدون رنگ، سایز و متراژ می‌باشد.",
}
export const enum CartMessage {
StockNotEnough = "مقدار درخواستی از موجودی کالا بیشتر است",
CartNotFound = "سبد خرید برای این کاربر یافت نشد",
OrderLimitExceeded = "مقدار درخواستی از حد سفارش کالا بیشتر است",
CartIdInvalid = "سبد خرید با این آیدی یافت نشد",
ItemNotFound = "این کالا در سبد خرید موجود نیست",
ItemAdded = "کالا با موفقیت به سبد خرید اضافه شد",
ItemDeleted = "کالا با موفقیت از سبد خرید حذف شد",
CartUpdated = "سبد خرید با موفقیت بروز شد",
ProductNotBelongToVariant = "این تنوع مربوط به این کالا نیست",
CartShipmentItemsNotFound = "آیتم های سبد خرید یافت نشد",
InvalidCartShipmentItem = "آیتم سبد خرید معتبر نیست",
}
export const enum PaymentMessage {
PaymentNotFound = "پرداخت با این شناسه پیدا نشد",
PaymentMethodNotFound = "درگاه پرداخت با این شناسه پیدا نشد",
PaymentMethodsNotFound = "درگاه پرداختی پیدا نشد",
PaymentNotSuccessful = "پرداخت موفقیت آمیز نبوده‌ است",
PaymentSuccessful = "پرداخت آمیز با موفقیت انجام شد",
PRPaymentDesc = "پرداخت برای درخواست ثبت کالا",
CartPaymentDesc = "خرید کالا:",
PaymentNotBelongToUser = "پرداخت برای این کاربر نمی‌باشد",
PaymentRequestFailed = "درخواست پرداخت موفقیت آمیز نبود",
}
export const enum CouponMessage {
NotFound = "کد تخفیف اشتباه است یا غیرفعال شده است",
Expired = "کد تخفیف منقضی شده است",
AmountIsNotSatisfied = "مبلغ خرید برای اعمال کد تخفیف کافی نیست",
UsageLimit = "تعداد استفاده از کد تخفیف به اتمام رسیده است",
CouponUsedBefore = " شما قبلا از این کد تخفیف استفاده کرده‌اید",
CouponAdded = "کد تخفیف اعمال شد",
CouponAlreadyInCart = "کد تخفیف فقط یکبار می‌تواند در هر سبد خرید استفاده شود",
InvalidId = "آیدی کد تخفیف صحیح نمی باشد",
DiscountAmountOrPercentageRequired = "باید یکی از مقادیر مبلغ تخفیف یا درصد را وارد کنید",
BothDiscountOrPercentageShouldNotSend = "نباید هر دو مقدار مبلغ تخفیف و درصد را وارد کنید",
UserCouponUsageLimit = "تعداد استفاده شما از کد تخفیف به اتمام رسیده است",
InvalidProduct = "این کد تخفیف برای این کالا معتبر نمی‌باشد",
InvalidCategory = "این کد تخفیف برای این دسته بندی معتبر نمی‌باشد",
BothIncludedAndExcludedProductsShouldNotSend = "نباید هر دو مقدار محصولات شامل و محصولات مستثنی را وارد کنید",
}
export const enum MediaMessage {
MediaCreated = "مدیا ساخته شد",
SliderCreated = "اسلایدر ساخته شد",
BannerCreated = "بنر ساخته شد",
Activated = "مدیا فعال شد",
UploadLimitSize = "حجم فایل باید کمتر از 6 مگابایت باشد",
}
export const enum SetShipmentMessage {
CartNotFound = "سبد خرید یافت نشد",
InvalidShipmentInfoLength = "باید برای همه اقلام موجود در سبد خرید ارسال‌کننده مشخص کنید",
ProductVariantNotFound = "تنوع محصول یافت نشد",
ShipperNotAvailableForSeller = "این ارسال‌کننده برای این فروشنده موجود نیست",
ShipmentProviderNotFound = "ارائه‌دهنده خدمات ارسال یافت نشد",
CartItemNotFound = "کالای مربوط به این نوع محصول در سبد خرید یافت نشد",
InvalidShipmentItems = "برخی از تنوع‌های ارسال شده معتبر نیستند",
InvalidShipmentSellers = "برای این خرید همچین فروشنده‌ای وجود ندارد",
ShipmentOptionsUnavailable = "روش ارسال برای این کالا موجود نیست",
ShipmentMethodAlreadyActive = "این روش ارسال قبلا انتخاب شده است",
ShipmentMethodNotActive = "این روش ارسال انتخاب نشده است",
}
export const enum AdMessage {
NotFoundWithId = "تبلیغی با این پیدا نشد",
}
export const enum OrderMessage {
NotFound = "سفارشی با این آیدی پیدا نشد",
TrackingDetailInserted = "مشخصات مرسوله با موفقیت ثبت شد",
OrderItemsNotFound = "آیتم های این سفارش یافت نشد",
ShipmentItemNotFound = "آیتم های ارسالی سفارش یافت نشد",
ReturnOrderNotFound = "سفارش برگشتی با این آیدی پیدا نشد",
ReturnOrderItemsNotFound = "آیتم های سفارش برگشتی پیدا نشد",
ReturnApproved = "مرجوعی کالا تایید شد",
ReturnRejected = "مرجوعی کالا رد شد",
ReturnCompleted = "فرایند مرجوعی کامل شد",
ItemReceived = "وضعیت سفارش شما برای این فروشنده به دریافت شده تغییر پیدا کرد",
TrackingCodeNotFound = "برای سفارش شما کد پیگیری یافت نشد",
TrackingEmailSent = "ایمیل حاوی اطلاعات سفارس و کد رهگیری برای شما ارسال شد",
ItemAlreadyReceived = "سفارش شما قبلا تحویل گرفته شده است",
ItemNotShipped = "سفارش هنوز ارسال نشده است",
}
export const enum TicketMessage {
TicketNotBelongToSeller = "این تیکت متعلق به فروشنده نمی‌باشد",
TicketNotFound = "تیکتی با این آیدی پیدا نشد",
}
export const enum ChatMessage {
ChatNotFound = "چتی با این آیدی پیدا نشد",
}
export const enum WalletMessage {
WalletNotFound = "کیف پول فروشنده یافت نشد",
CreditedSuccessfully = "کیف پول با موفقیت شارژ شد",
InsufficientBalance = "موجودی کیف پول کافی نمی‌باشد",
InsufficientBalanceForWithdrawal = "موجودی کیف پول برای برداشت کافی نمی‌باشد",
DebitedSuccessfully = "برداشت از کیف پول با موفقیت انجام شد",
WithdrawalNotFound = "درخواست برداشتی با این آیدی یافت نشد",
WithdrawalFailed = "برداشت از کیف پول با مشکل مواجه شد",
WithdrawalSubmitted = "درخواست برداشت از کیف پول ثبت شد",
CreditFailed = "شارژ کیف پول ناموفق بود",
InvalidTransaction = "تراکنش نامعتبر است",
RejectWithdrawalRequest = "درخواست برداشت از کیف پول رد شد",
}
export const enum ShopMessage {
ShopNotFound = "فروشگاه برای این فروشنده یافت نشد",
ShopNotFoundById = "با این ایدی فروشگاه یافت نشد",
ShopNameExist = "نام فروشگاه تکراری می باشد",
NotFound = "فروشگاه یافت نشد",
}
export const enum AddressMessage {
Updated = "آدرس با موفقیت آپدیت شد",
NotFound = "آدرس کاربر یافت نشد",
UserShouldHaveAddress = "برای ثبت سفارش .کاربر ملزم به ثبت آدرس می‌باشد",
InvalidLocation = "مختصات جغرافیایی اشتباه می باشد",
SellerAddressNotFound = "برای ثبت قرار داد ابتدا آدرس خود در قسمت پروفابل ثبت کنید",
}
export const enum PricingMessage {
NotFound = "قیمت ها بافت نشد",
PhotographyFee = "هزینه عکاسی",
InsertFeeNotFound = "هزینه درج محصول یافت نشد",
UnboxingVideoFee = "هزینه ویدیو انباکسینگ یافت نشد",
ExpertReviewsFeeNotFound = "هزینه نقد و بررسی یافت نشد",
expertReviewsFee = "هزینه نقد و بررسی",
TypeIsExist = "این نوع قبلا ثبت شده است",
}
export const enum AdminMessage {
FullNameNotEmpty = "نام و نام خانوادگی نباید خالی باشد",
UserNameNotEmpty = "نام کاربری نباید خالی باشد",
RoleNotEmpty = "نقش کاربر نباید خالی باشد",
PasswordNotEmpty = "پسورد نباید خالی باشد",
AdminIsExist = "این نام کاربری قبلا ثبت شده است",
RoleNotFound = "نقش ادمین یافت نشد",
EmailNotEmpty = "ایمیل نباید خالی باشد",
PhoneNotEmpty = "شماره موبایل نباید خالی باشد",
DeletedSuccessfully = "حذف با موفقیت انجام شد",
NotFound = "ادمین یافت نشد",
}
export const enum RoleMessage {
RoleNotFound = "نقش یافت نشد",
RoleNameNotEmpty = "نام نقش نباید خالی باشد",
RoleNameDuplicate = "نام نقش تکراری می باشد",
PermissionsNotEmpty = "دسترسی‌ها نباید خالی باشد",
RoleExist = "این نقش قبلا ثبت شده است",
}
+22
View File
@@ -0,0 +1,22 @@
export enum PaymentStatus {
Pending = "Pending",
Cancelled = "Cancelled",
Completed = "Completed",
}
export enum OrdersStatus {
wait_payment = "wait_payment",
process_by_seller = "process_by_sellers",
cancelled_system = "cancelled_system",
Cancelled = "cancelled",
Delivered = "Delivered",
}
export enum OrderItemsStatus {
Processing = "Processing",
Shipped = "Shipped",
Delivered = "Delivered",
cancelled_shop = "cancelled_shop",
cancelled_system = "cancelled_system",
cancelled_user = "cancelled_user",
Returned = "Returned",
}
+9
View File
@@ -0,0 +1,9 @@
export enum PageEnum {
Faq = "Faq",
Seller = "Seller",
ProductTag = "ProductTag",
ProductDescription = "ProductDescription",
ProductBenefit = "ProductBenefit",
ShipmentProcess = "ShipmentProcess",
Policy = "Policy",
}
+10
View File
@@ -0,0 +1,10 @@
export enum GatewayProvider {
Zarinpal = "Zarinpal",
Asanpardakht = "asanPardakht",
}
export enum PaymentMethodType {
Online = "online",
POS = "pos",
Wallet = "wallet",
}
+28
View File
@@ -0,0 +1,28 @@
export enum ProductMarketStatus {
Out_of_stock = "out_of_stock",
Marketable = "Marketable",
stop_production = "stopProduction",
}
export enum ProductStatus {
Draft = "Draft",
Pending = "Pending",
Approved = "Approved",
Rejected = "Rejected",
}
export enum ProductSource {
LOCAL = "local",
IMPORT = "import",
}
export enum ProductDiscountType {
Fixed = "fixed",
Percent = "percent",
}
export enum CreateProductStep {
Detail = 1,
Attribute,
Image,
}
@@ -0,0 +1,5 @@
export enum Question_CommentStatus {
Pending = "pending",
Accepted = "accepted",
Rejected = "rejected",
}
+9
View File
@@ -0,0 +1,9 @@
export enum SellerType {
WHOLESALER = "WHOLESALER",
RETAILER = "RETAILER",
}
export enum SellerGender {
Male = "MALE",
Female = "FEMALE",
}
+6
View File
@@ -0,0 +1,6 @@
// Enum for Delivery Types
export enum DeliveryType {
SameDay = "SameDay", //(1) day
Express = "Express", //(1-2) days
Standard = "Standard", //(3-5) days
}
+6
View File
@@ -0,0 +1,6 @@
export enum StatusEnum {
Pending = "Pending",
Approved = "Approved",
Completed = "Completed",
Rejected = "Rejected",
}
+24
View File
@@ -0,0 +1,24 @@
import { HttpStatus } from "../enums/httpStatus.enum";
import { IErrorResponse, ISuccessResponse } from "../interfaces/IAppResponse";
export class ResponseFactory {
public static successResponse(status: HttpStatus, data: Record<string, unknown>): ISuccessResponse {
return {
status,
success: true,
results: {
...data,
},
};
}
public static errorResponse(status: HttpStatus, message: string, details: string[] = []): IErrorResponse {
return {
status,
success: false,
error: {
message,
details,
},
};
}
}
+8
View File
@@ -0,0 +1,8 @@
//interfaces
export { IAppOptions } from "./interfaces/IAppOptions";
export { IErrorResponse, ISuccessResponse } from "./interfaces/IAppResponse";
//enums
export { HttpStatus } from "./enums/httpStatus.enum";
export { HttpMethod } from "./enums/httpMethod.enum";
//factories
export { ResponseFactory } from "./factories/response.factory";
+7
View File
@@ -0,0 +1,7 @@
import { CorsOptions } from "cors";
import { Options } from "express-rate-limit";
export interface IAppOptions {
cors: CorsOptions;
rate: Partial<Options>;
}
+16
View File
@@ -0,0 +1,16 @@
import { HttpStatus } from "../enums/httpStatus.enum";
export interface IErrorResponse {
status: HttpStatus;
success: boolean;
error: {
message: string;
details: string[];
};
}
export interface ISuccessResponse {
status: HttpStatus;
success: boolean;
results: Record<string, unknown>;
}
@@ -0,0 +1,8 @@
export interface IPageFormat {
page: number;
limit: number;
totalItems: number;
totalPages: number;
prevPage: string | boolean;
nextPage: string | boolean;
}
@@ -0,0 +1,6 @@
import { IPageFormat } from "./PageFormatInterface";
export interface IPaginateDataFormat {
pager: IPageFormat;
// docs: Array<Record<string, unknown>>;
}
+61
View File
@@ -0,0 +1,61 @@
declare namespace NodeJS {
interface ProcessEnv {
PORT: string;
NODE_ENV: string;
MONGO_URI: string;
REDIS_URI: string;
REDIS_HOST: string;
REDIS_PORT: string;
REDIS_PASSWORD: string;
SMS_API_KEY: string;
SMS_SECRET: string;
SMS_NUMBER: string;
SMS_PATTERN_OTP: string;
SMS_PATTERN_USER_ORDER_PEND: string;
SMS_PATTERN_USER_ORDER_CREATE: string;
SMS_PATTERN_USER_ORDER_SHIPPED: string;
SMS_PATTERN_USER_ORDER_RETURNED: string;
SMS_PATTERN_SELLER_ORDER_CREATE: string;
SMS_PATTERN_SELLER_ORDER_CANCELLED: string;
SMTP_EMAIL: string;
SMTP_HOST: string;
SMTP_PORT: string;
SMTPS_PORT: string;
SMTP_SECURE: string;
SMTP_USER: string;
SMTP_PASSWORD: string;
JWT_SECRET: string;
JWT_EXPIRE_ACCESS: string;
JWT_EXPIRE_REFRESH: string;
BUCKET_ACCESS_KEY: string;
BUCKET_SECRET_KEY: string;
BUCKET_NAME: string;
BUCKET_URL: string;
DEFAULT_ADMIN_EMAIL: string;
DEFAULT_ADMIN_PASSWORD: string;
IPG_TYPE: string;
SITE_URL: string;
STORE_URL: string;
SELLER_URL: string;
ZARINPAL_MERCHANT_ID: string;
ASANPARDAKHT_MERCHANT_ID: string;
ASANPARDAKHT_MERCHANT_CONFIG_ID: string;
ASANPARDAKHT_USER: string;
ASANPARDAKHT_PASS: string;
MAP_API_KEY: string;
NESHAN_API_KEY: string;
LOGGER_LEVEL: string;
}
}
+9
View File
@@ -0,0 +1,9 @@
export type AuthTokenPayload = {
sub: string;
};
export type TokenType = "Access" | "Refresh";
export type AuthAdminToken = {
sub: string;
};
+42
View File
@@ -0,0 +1,42 @@
interface MetaData {
mobile?: string;
email?: string;
order_id?: string;
}
export interface ZarinPalPGNewArgs {
merchant_id: string;
amount: number;
description: string;
callback_url: string;
metadata?: MetaData;
currency?: "IRR" | "IRT";
}
interface PaymentRequestData {
code: number;
message: string;
authority: string;
fee_type: string;
fee: number;
}
export interface ZarinPalPGNewRequestData {
data: PaymentRequestData;
error: string[];
}
interface PaymentVerifyData {
code: number;
message: string;
card_hash: string;
card_pan: string;
ref_id: number;
fee_type: string;
fee: number;
}
export interface ZarinPalPGVerifyData {
data: PaymentVerifyData;
error: string[];
}
+102
View File
@@ -0,0 +1,102 @@
import { NotificationType } from "../../modules/notification/models/Abstraction/INotification";
export type CompareSearchQueries = {
limit: number;
page: number;
productId: number;
};
export type VariantQueries = {
page: number;
limit: number;
variantStatus: boolean;
shipmentMethod: number;
stock: boolean;
includeAd: boolean;
specialSale: boolean;
sort: string[];
q: string;
};
export type SellerProductQueries = {
page: number;
limit: number;
categoryId: string;
status: string;
q: string;
};
export type FilterByStatusProductsQueries = {
page: number;
limit: number;
status: string;
};
export type ProductsCommentsQueries = {
page: number;
limit: number;
productId: number;
status: string;
};
export type ProductsQuestionsQueries = {
page: number;
limit: number;
productId: number;
status: string;
};
export type SellerOrdersQueries = {
page: number;
limit: number;
shipperId: string;
status: string;
since: number;
maxPrice: number;
minPrice: number;
};
export type PaymentsQueries = {
page: number;
limit: number;
status: string;
since: number;
maxPrice: number;
minPrice: number;
};
export type AdminContactUsQueries = {
page: number;
limit: number;
email_phone: string;
};
export type AdminReturnsQueries = {
page: number;
limit: number;
};
export type AdminCancelsQueries = {
page: number;
limit: number;
};
export type SellerFinesQueries = {
page: number;
limit: number;
};
export type AdminFinesQueries = {
page: number;
limit: number;
};
export type NotificationQuery = {
page: number;
limit: number;
unread: boolean;
type: NotificationType;
since: number;
};
export type OrderStatusQuery = "Delivered" | "Processing" | "Cancelled";
+16
View File
@@ -0,0 +1,16 @@
// /* eslint-disable no-unused-vars */
// /* eslint-disable @typescript-eslint/no-unused-vars */
// import { ApiError } from "../../core/app/app.errors";
// // import express from "express";
// // import { Express } from "express";
// // import { Request } from "express";
// declare global {
// namespace Express {
// interface authError extends ApiError {}
// interface Request {
// authError?: authError;
// file?: Express.MulterS3.File;
// }
// }
// }