messages
This commit is contained in:
@@ -58,6 +58,10 @@ export const enum AuthMessage {
|
|||||||
NATIONAL_CODE_INVALID = 'کد ملی نامعتبر است',
|
NATIONAL_CODE_INVALID = 'کد ملی نامعتبر است',
|
||||||
INVALID_REFRESH_TOKEN = 'توکن رفرش نامعتبر است',
|
INVALID_REFRESH_TOKEN = 'توکن رفرش نامعتبر است',
|
||||||
REFRESH_TOKEN_EXPIRED = 'توکن رفرش منقضی شده است',
|
REFRESH_TOKEN_EXPIRED = 'توکن رفرش منقضی شده است',
|
||||||
|
REFRESH_TOKEN_MUST_BE_STRING = 'توکن رفرش باید یک رشته باشد',
|
||||||
|
REFRESH_TOKEN_REQUIRED = 'توکن رفرش الزامی است',
|
||||||
|
FAILED_TO_REFRESH_TOKEN = 'تمدید توکن با خطا مواجه شد',
|
||||||
|
OTP_EXPIRED_OR_NOT_FOUND = 'کد منقضی شده یا یافت نشد',
|
||||||
LOGOUT_SUCCESS = 'خروج با موفقیت انجام شد',
|
LOGOUT_SUCCESS = 'خروج با موفقیت انجام شد',
|
||||||
CURRENT_PASSWORD_INVALID = 'رمز عبور فعلی نامعتبر است',
|
CURRENT_PASSWORD_INVALID = 'رمز عبور فعلی نامعتبر است',
|
||||||
TOKEN_EXPIRED_OR_INVALID = 'توکن منقضی شده یا نامعتبر است',
|
TOKEN_EXPIRED_OR_INVALID = 'توکن منقضی شده یا نامعتبر است',
|
||||||
@@ -73,6 +77,11 @@ export const enum AuthMessage {
|
|||||||
}
|
}
|
||||||
export const enum ProductMessage {
|
export const enum ProductMessage {
|
||||||
NOT_FOUND = 'محصولی با این مشخصات یافت نشد',
|
NOT_FOUND = 'محصولی با این مشخصات یافت نشد',
|
||||||
|
ATTRIBUTE_REQUIRED_FOR_VARIANTS = 'برای محصولات با چند نوع، ویژگی الزامی است',
|
||||||
|
VARIANT_NOT_FOUND = 'نوع محصول یافت نشد',
|
||||||
|
PRODUCT_NOT_BELONGS_TO_SHOP = 'محصول به فروشگاه شما تعلق ندارد',
|
||||||
|
FAVORITE_REMOVED = 'محصول از علاقهمندیها حذف شد',
|
||||||
|
FAVORITE_ADDED = 'محصول به علاقهمندیها اضافه شد',
|
||||||
}
|
}
|
||||||
export const enum CategoryMessage {
|
export const enum CategoryMessage {
|
||||||
NOT_FOUND = 'دستهبندی مورد نظر یافت نشد',
|
NOT_FOUND = 'دستهبندی مورد نظر یافت نشد',
|
||||||
@@ -129,6 +138,11 @@ export const enum UserMessage {
|
|||||||
PUSH_TOKEN_ADDED_SUCCESSFULLY = 'توکن پوش با موفقیت اضافه شد',
|
PUSH_TOKEN_ADDED_SUCCESSFULLY = 'توکن پوش با موفقیت اضافه شد',
|
||||||
NO_PUSH_TOKENS_FOUND = 'توکن پوشی برای این کاربر یافت نشد',
|
NO_PUSH_TOKENS_FOUND = 'توکن پوشی برای این کاربر یافت نشد',
|
||||||
PUSH_TOKEN_REMOVED_SUCCESSFULLY = 'توکن پوش با موفقیت حذف شد',
|
PUSH_TOKEN_REMOVED_SUCCESSFULLY = 'توکن پوش با موفقیت حذف شد',
|
||||||
|
ADDRESS_NOT_FOUND = 'آدرس یافت نشد',
|
||||||
|
POINTS_MUST_BE_GREATER_THAN_ZERO = 'امتیاز تبدیل باید بیشتر از صفر باشد',
|
||||||
|
SHOP_SCORE_NOT_FOUND = 'امتیاز فروشگاه یافت نشد',
|
||||||
|
SHOP_PURCHASE_SCORE_NOT_FOUND = 'امتیاز خرید فروشگاه یافت نشد',
|
||||||
|
SHOP_PURCHASE_AMOUNT_NOT_FOUND = 'مبلغ خرید فروشگاه یافت نشد',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum CommonMessage {
|
export const enum CommonMessage {
|
||||||
@@ -291,7 +305,7 @@ export const enum EmailMessage {
|
|||||||
MESSAGE_MARKED_AS_UNSEEN_SUCCESSFULLY = 'پیام با موفقیت به عنوان خوانده نشده علامت گذاری شد',
|
MESSAGE_MARKED_AS_UNSEEN_SUCCESSFULLY = 'پیام با موفقیت به عنوان خوانده نشده علامت گذاری شد',
|
||||||
MESSAGE_MARK_AS_UNSEEN_FAILED = 'علامت گذاری پیام به عنوان خوانده نشده با خطا مواجه شد',
|
MESSAGE_MARK_AS_UNSEEN_FAILED = 'علامت گذاری پیام به عنوان خوانده نشده با خطا مواجه شد',
|
||||||
ATTACHMENT_ID_MUST_BE_STRING = 'شناسه پیوست باید یک رشته باشد',
|
ATTACHMENT_ID_MUST_BE_STRING = 'شناسه پیوست باید یک رشته باشد',
|
||||||
IS_FORWARD_MUST_BE_BOOLEAN = 'IS_FORWARD_MUST_BE_BOOLEAN',
|
IS_FORWARD_MUST_BE_BOOLEAN = 'وضعیت فوروارد باید بولین باشد',
|
||||||
|
|
||||||
// Favorite/Star messages (Gmail-like behavior)
|
// Favorite/Star messages (Gmail-like behavior)
|
||||||
MESSAGE_MARKED_AS_FAVORITE_SUCCESSFULLY = 'پیام با موفقیت به عنوان مورد علاقه علامت گذاری شد',
|
MESSAGE_MARKED_AS_FAVORITE_SUCCESSFULLY = 'پیام با موفقیت به عنوان مورد علاقه علامت گذاری شد',
|
||||||
@@ -300,7 +314,7 @@ export const enum EmailMessage {
|
|||||||
SPAM_EMPTYED_SUCCESSFULLY = 'همه پیام های اسپم با موفقیت حذف شدند',
|
SPAM_EMPTYED_SUCCESSFULLY = 'همه پیام های اسپم با موفقیت حذف شدند',
|
||||||
SAVE_DRAFT_SUCCESS = 'پیش نویس با موفقیت ذخیره شد',
|
SAVE_DRAFT_SUCCESS = 'پیش نویس با موفقیت ذخیره شد',
|
||||||
HTML_CONTENT_REQUIRED = 'محتوای HTML مورد نیاز است',
|
HTML_CONTENT_REQUIRED = 'محتوای HTML مورد نیاز است',
|
||||||
TEXT_CONTENT_REQUIRED = 'TEXT_CONTENT_REQUIRED',
|
TEXT_CONTENT_REQUIRED = 'محتوای متنی الزامی است',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum WebSocketMessage {
|
export const enum WebSocketMessage {
|
||||||
@@ -318,6 +332,8 @@ export const enum WebSocketMessage {
|
|||||||
LEFT_ROOM_SUCCESS = 'با موفقیت از اتاق خارج شدید',
|
LEFT_ROOM_SUCCESS = 'با موفقیت از اتاق خارج شدید',
|
||||||
ROOM_NOT_FOUND = 'اتاق یافت نشد',
|
ROOM_NOT_FOUND = 'اتاق یافت نشد',
|
||||||
UNAUTHORIZED_ROOM_ACCESS = 'دسترسی غیرمجاز به اتاق',
|
UNAUTHORIZED_ROOM_ACCESS = 'دسترسی غیرمجاز به اتاق',
|
||||||
|
ADMIN_LEFT_ROOM = 'ادمین با موفقیت از اتاق خارج شد',
|
||||||
|
ADMIN_JOINED_ROOM = 'ادمین با موفقیت به اتاق متصل شد',
|
||||||
|
|
||||||
// Session Management Messages
|
// Session Management Messages
|
||||||
WS_SESSION_CREATED = 'جلسه وب سوکت ایجاد شد',
|
WS_SESSION_CREATED = 'جلسه وب سوکت ایجاد شد',
|
||||||
@@ -347,6 +363,7 @@ export const enum WebSocketMessage {
|
|||||||
|
|
||||||
// Authentication errors
|
// Authentication errors
|
||||||
AUTHENTICATION_REQUIRED = 'احراز هویت ضروری است',
|
AUTHENTICATION_REQUIRED = 'احراز هویت ضروری است',
|
||||||
|
INVALID_TOKEN_PAYLOAD = 'محتویات توکن نامعتبر است',
|
||||||
INVALID_TOKEN = 'توکن احراز هویت نامعتبر است',
|
INVALID_TOKEN = 'توکن احراز هویت نامعتبر است',
|
||||||
TOKEN_EXPIRED = 'توکن منقضی شده است',
|
TOKEN_EXPIRED = 'توکن منقضی شده است',
|
||||||
UNAUTHORIZED_ACCESS = 'دسترسی غیرمجاز',
|
UNAUTHORIZED_ACCESS = 'دسترسی غیرمجاز',
|
||||||
@@ -398,8 +415,19 @@ export const enum SmsMessage {
|
|||||||
SEND_SMS_ERROR = 'خطا در ارسال پیامک',
|
SEND_SMS_ERROR = 'خطا در ارسال پیامک',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const enum AdminMessage {
|
||||||
|
ROLE_NOT_FOUND = 'نقش یافت نشد',
|
||||||
|
ROLE_NOT_BELONGS_TO_SHOP = 'نقش به این فروشگاه تعلق ندارد',
|
||||||
|
SHOP_NOT_FOUND = 'فروشگاه یافت نشد',
|
||||||
|
ADMIN_NOT_FOUND = 'ادمین یافت نشد',
|
||||||
|
PHONE_ALREADY_TAKEN = 'این شماره قبلا توسط ادمین دیگری استفاده شده است',
|
||||||
|
ADMIN_ROLE_NOT_FOUND = 'نقش ادمین یافت نشد',
|
||||||
|
}
|
||||||
|
|
||||||
export const enum RestMessage {
|
export const enum RestMessage {
|
||||||
NOT_FOUND = 'کسب و کار یافت نشد',
|
NOT_FOUND = 'کسب و کار یافت نشد',
|
||||||
|
DUPLICATE_SUBSCRIPTION_ID = 'شناسه اشتراک تکراری است',
|
||||||
|
SYSTEM_ROLE_NOT_FOUND = 'نقش سیستمی یافت نشد',
|
||||||
BUSINESS_ID_REQUIRED = 'شناسه کسب و کار مورد نیاز است',
|
BUSINESS_ID_REQUIRED = 'شناسه کسب و کار مورد نیاز است',
|
||||||
SLUG_REQUIRED = 'اسلاگ مورد نیاز است',
|
SLUG_REQUIRED = 'اسلاگ مورد نیاز است',
|
||||||
SLUG_MUST_BE_STRING = 'اسلاگ باید یک رشته باشد',
|
SLUG_MUST_BE_STRING = 'اسلاگ باید یک رشته باشد',
|
||||||
@@ -522,6 +550,9 @@ export const enum DnsRecordMessage {
|
|||||||
|
|
||||||
export const enum RoleMessage {
|
export const enum RoleMessage {
|
||||||
NOT_FOUND = 'نقش یافت نشد',
|
NOT_FOUND = 'نقش یافت نشد',
|
||||||
|
ROLE_ALREADY_EXISTS_FOR_SHOP = 'نقشی با این نام قبلا برای این فروشگاه ثبت شده است',
|
||||||
|
ONE_OR_MORE_PERMISSIONS_NOT_FOUND = 'یک یا چند دسترسی یافت نشد',
|
||||||
|
ROLE_HAS_ADMINS = 'این نقش دارای ادمین است و نمیتوان حذف کرد',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum SignatureMessage {
|
export const enum SignatureMessage {
|
||||||
@@ -584,6 +615,7 @@ export const enum NotificationMessage {
|
|||||||
CHANGE_PASSWORD_MESSAGE = 'رمز عبور شما با موفقیت تغییر کرد',
|
CHANGE_PASSWORD_MESSAGE = 'رمز عبور شما با موفقیت تغییر کرد',
|
||||||
CHANGE_PASSWORD = 'تغییر رمز عبور',
|
CHANGE_PASSWORD = 'تغییر رمز عبور',
|
||||||
NOT_FOUND = 'اعلان یافت نشد',
|
NOT_FOUND = 'اعلان یافت نشد',
|
||||||
|
NOTIFICATION_PREFERENCE_NOT_FOUND = 'تنظیمات اعلان یافت نشد',
|
||||||
READ_SUCCESS = 'اعلان با موفقیت خوانده شد',
|
READ_SUCCESS = 'اعلان با موفقیت خوانده شد',
|
||||||
ORDER_CREATED = 'سفارش جدید ایجاد شد',
|
ORDER_CREATED = 'سفارش جدید ایجاد شد',
|
||||||
ORDER_STATUS_CHANGED = 'وضعیت سفارش تغییر کرد',
|
ORDER_STATUS_CHANGED = 'وضعیت سفارش تغییر کرد',
|
||||||
@@ -659,6 +691,9 @@ export const enum ReviewMessage {
|
|||||||
COMMENT_CREATED = 'نظر با موفقیت ثبت شد',
|
COMMENT_CREATED = 'نظر با موفقیت ثبت شد',
|
||||||
COMMENT_UPDATED = 'نظر با موفقیت بهروزرسانی شد',
|
COMMENT_UPDATED = 'نظر با موفقیت بهروزرسانی شد',
|
||||||
COMMENT_DELETED = 'نظر با موفقیت حذف شد',
|
COMMENT_DELETED = 'نظر با موفقیت حذف شد',
|
||||||
|
PRODUCT_NOT_IN_ORDER = 'محصول در سفارش مشخص شده وجود ندارد',
|
||||||
|
CREATE_REVIEW_FAILED = 'ثبت نظر با خطا مواجه شد',
|
||||||
|
ONLY_ADMIN_CAN_CHANGE_STATUS = 'فقط ادمین میتواند وضعیت نظر را تغییر دهد',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum IconMessage {
|
export const enum IconMessage {
|
||||||
@@ -677,6 +712,7 @@ export const enum GroupMessage {
|
|||||||
|
|
||||||
export const enum OrderMessage {
|
export const enum OrderMessage {
|
||||||
NOT_FOUND = 'سفارش یافت نشد',
|
NOT_FOUND = 'سفارش یافت نشد',
|
||||||
|
ORDER_NOT_FOUND_OR_NOT_OWNED = 'سفارش یافت نشد یا به کاربر فعلی تعلق ندارد',
|
||||||
PAYMENT_METHOD_MISSING = 'روش پرداخت سفارش مشخص نشده است',
|
PAYMENT_METHOD_MISSING = 'روش پرداخت سفارش مشخص نشده است',
|
||||||
INVALID_STATUS_TRANSITION = 'انتقال وضعیت نامعتبر است',
|
INVALID_STATUS_TRANSITION = 'انتقال وضعیت نامعتبر است',
|
||||||
CART_EMPTY = 'سبد خرید خالی است. لطفا قبل از ایجاد سفارش، آیتمهایی به سبد اضافه کنید',
|
CART_EMPTY = 'سبد خرید خالی است. لطفا قبل از ایجاد سفارش، آیتمهایی به سبد اضافه کنید',
|
||||||
@@ -696,6 +732,7 @@ export const enum OrderMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const enum CartMessage {
|
export const enum CartMessage {
|
||||||
|
AT_LEAST_ONE_ITEM_REQUIRED = 'حداقل یک آیتم الزامی است',
|
||||||
TABLE_NUMBER_REQUIRED = 'شماره میز برای سفارش در محل الزامی است',
|
TABLE_NUMBER_REQUIRED = 'شماره میز برای سفارش در محل الزامی است',
|
||||||
CAR_ADDRESS_REQUIRED = 'آدرس خودرو برای تحویل به خودرو الزامی است',
|
CAR_ADDRESS_REQUIRED = 'آدرس خودرو برای تحویل به خودرو الزامی است',
|
||||||
ADDRESS_REQUIRED = 'آدرس برای تحویل پیک الزامی است',
|
ADDRESS_REQUIRED = 'آدرس برای تحویل پیک الزامی است',
|
||||||
@@ -744,6 +781,7 @@ export const enum PaymentMessage {
|
|||||||
PAYMENT_METHOD_NOT_CASH = 'روش پرداخت نقدی نیست',
|
PAYMENT_METHOD_NOT_CASH = 'روش پرداخت نقدی نیست',
|
||||||
PAYMENT_ALREADY_PAID = 'پرداخت قبلا انجام شده است',
|
PAYMENT_ALREADY_PAID = 'پرداخت قبلا انجام شده است',
|
||||||
EXISTING_PENDING_PAYMENT_MISMATCH = 'پرداخت در انتظار موجود با روش پرداخت سفارش مطابقت ندارد',
|
EXISTING_PENDING_PAYMENT_MISMATCH = 'پرداخت در انتظار موجود با روش پرداخت سفارش مطابقت ندارد',
|
||||||
|
INVALID_TRANSACTION_TYPE = 'نوع تراکنش نامعتبر است',
|
||||||
ZARINPAL_INVALID_RESPONSE = 'پاسخ نامعتبر از API زرینپال',
|
ZARINPAL_INVALID_RESPONSE = 'پاسخ نامعتبر از API زرینپال',
|
||||||
ZARINPAL_PAYMENT_REQUEST_ERROR = 'خطا در درخواست پرداخت زرینپال',
|
ZARINPAL_PAYMENT_REQUEST_ERROR = 'خطا در درخواست پرداخت زرینپال',
|
||||||
ZARINPAL_VERIFY_ERROR = 'خطا در تایید پرداخت زرینپال',
|
ZARINPAL_VERIFY_ERROR = 'خطا در تایید پرداخت زرینپال',
|
||||||
|
|||||||
@@ -43,6 +43,6 @@ export class HttpExceptionFilter implements ExceptionFilter {
|
|||||||
return Array.isArray(response.message) ? response.message : [response.message];
|
return Array.isArray(response.message) ? response.message : [response.message];
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'something wrong';
|
return 'مشکلی پیش آمده است';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { UpdateAdminDto } from '../dto/update-admin.dto';
|
|||||||
import { AdminRole } from '../entities/adminRole.entity';
|
import { AdminRole } from '../entities/adminRole.entity';
|
||||||
import { normalizePhone } from '../../utils/phone.util';
|
import { normalizePhone } from '../../utils/phone.util';
|
||||||
import { AdminRepository } from '../repositories/admin.repository';
|
import { AdminRepository } from '../repositories/admin.repository';
|
||||||
|
import { AdminMessage, RoleMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdminService {
|
export class AdminService {
|
||||||
@@ -55,15 +56,15 @@ export class AdminService {
|
|||||||
await this.em.persistAndFlush(admin);
|
await this.em.persistAndFlush(admin);
|
||||||
}
|
}
|
||||||
const role = await this.em.findOne(Role, { id: roleId, isSystem: false });
|
const role = await this.em.findOne(Role, { id: roleId, isSystem: false });
|
||||||
if (!role) throw new NotFoundException('Role not found');
|
if (!role) throw new NotFoundException(AdminMessage.ROLE_NOT_FOUND);
|
||||||
|
|
||||||
// Validate that role belongs to the shop or is general (shop: null)
|
// Validate that role belongs to the shop or is general (shop: null)
|
||||||
if (role.shop && role.shop.id !== shopId) {
|
if (role.shop && role.shop.id !== shopId) {
|
||||||
throw new BadRequestException('Role does not belong to this shop');
|
throw new BadRequestException(AdminMessage.ROLE_NOT_BELONGS_TO_SHOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
const shop = await this.em.findOne(Shop, { id: shopId });
|
const shop = await this.em.findOne(Shop, { id: shopId });
|
||||||
if (!shop) throw new NotFoundException('Shop not found');
|
if (!shop) throw new NotFoundException(AdminMessage.SHOP_NOT_FOUND);
|
||||||
|
|
||||||
let adminRole = await this.adminRoleRepository.findOne({
|
let adminRole = await this.adminRoleRepository.findOne({
|
||||||
admin: admin,
|
admin: admin,
|
||||||
@@ -105,7 +106,7 @@ export class AdminService {
|
|||||||
|
|
||||||
|
|
||||||
const shop = await this.em.findOne(Shop, { id: shopId });
|
const shop = await this.em.findOne(Shop, { id: shopId });
|
||||||
if (!shop) throw new NotFoundException('Shop not found');
|
if (!shop) throw new NotFoundException(AdminMessage.SHOP_NOT_FOUND);
|
||||||
|
|
||||||
let adminRole = await this.adminRoleRepository.findOne({
|
let adminRole = await this.adminRoleRepository.findOne({
|
||||||
admin: admin,
|
admin: admin,
|
||||||
@@ -128,7 +129,7 @@ export class AdminService {
|
|||||||
|
|
||||||
async getShopAdminsBySuperAdmin(shopId: string): Promise<Admin[]> {
|
async getShopAdminsBySuperAdmin(shopId: string): Promise<Admin[]> {
|
||||||
const shop = await this.em.findOne(Shop, { id: shopId });
|
const shop = await this.em.findOne(Shop, { id: shopId });
|
||||||
if (!shop) throw new NotFoundException('Shop not found');
|
if (!shop) throw new NotFoundException(AdminMessage.SHOP_NOT_FOUND);
|
||||||
|
|
||||||
return this.adminRepository.find({ roles: { shop: shop } }, { populate: ['roles', 'roles.role'] });
|
return this.adminRepository.find({ roles: { shop: shop } }, { populate: ['roles', 'roles.role'] });
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,7 @@ export class AdminService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!admin) {
|
if (!admin) {
|
||||||
throw new NotFoundException('Admin not found');
|
throw new NotFoundException(AdminMessage.ADMIN_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { roleId, ...rest } = dto;
|
const { roleId, ...rest } = dto;
|
||||||
@@ -159,7 +160,7 @@ export class AdminService {
|
|||||||
id: { $ne: adminId }, // Exclude current admin from duplicate check
|
id: { $ne: adminId }, // Exclude current admin from duplicate check
|
||||||
});
|
});
|
||||||
if (exists) {
|
if (exists) {
|
||||||
throw new ConflictException('This Phone Number is already taken');
|
throw new ConflictException(AdminMessage.PHONE_ALREADY_TAKEN);
|
||||||
}
|
}
|
||||||
admin.phone = normalizedPhone;
|
admin.phone = normalizedPhone;
|
||||||
}
|
}
|
||||||
@@ -168,12 +169,12 @@ export class AdminService {
|
|||||||
if (roleId) {
|
if (roleId) {
|
||||||
const role = await this.em.findOne(Role, { id: roleId, isSystem: false }, { populate: ['shop'] });
|
const role = await this.em.findOne(Role, { id: roleId, isSystem: false }, { populate: ['shop'] });
|
||||||
if (!role) {
|
if (!role) {
|
||||||
throw new NotFoundException('Role not found');
|
throw new NotFoundException(AdminMessage.ROLE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that role belongs to the shop or is general (shop: null)
|
// Validate that role belongs to the shop or is general (shop: null)
|
||||||
if (role.shop && role.shop.id !== shopId) {
|
if (role.shop && role.shop.id !== shopId) {
|
||||||
throw new BadRequestException('Role does not belong to this shop');
|
throw new BadRequestException(AdminMessage.ROLE_NOT_BELONGS_TO_SHOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find existing AdminRole for this admin and shop
|
// Find existing AdminRole for this admin and shop
|
||||||
@@ -187,7 +188,7 @@ export class AdminService {
|
|||||||
existingAdminRole.role = role;
|
existingAdminRole.role = role;
|
||||||
} else {
|
} else {
|
||||||
const shop = await this.em.findOne(Shop, { id: shopId });
|
const shop = await this.em.findOne(Shop, { id: shopId });
|
||||||
if (!shop) throw new NotFoundException('Shop not found');
|
if (!shop) throw new NotFoundException(AdminMessage.SHOP_NOT_FOUND);
|
||||||
// Create new AdminRole using repository for consistency
|
// Create new AdminRole using repository for consistency
|
||||||
const newAdminRole = this.adminRoleRepository.create({
|
const newAdminRole = this.adminRoleRepository.create({
|
||||||
admin,
|
admin,
|
||||||
@@ -205,7 +206,7 @@ export class AdminService {
|
|||||||
async remove(adminId: string, shopId: string): Promise<void> {
|
async remove(adminId: string, shopId: string): Promise<void> {
|
||||||
const adminRole = await this.adminRoleRepository.findOne({ admin: { id: adminId }, shop: { id: shopId } });
|
const adminRole = await this.adminRoleRepository.findOne({ admin: { id: adminId }, shop: { id: shopId } });
|
||||||
if (!adminRole) {
|
if (!adminRole) {
|
||||||
throw new NotFoundException('Admin role not found');
|
throw new NotFoundException(AdminMessage.ADMIN_ROLE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
return this.em.removeAndFlush(adminRole);
|
return this.em.removeAndFlush(adminRole);
|
||||||
}
|
}
|
||||||
@@ -226,7 +227,7 @@ export class AdminService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!admin) {
|
if (!admin) {
|
||||||
throw new BadRequestException('Admin not found');
|
throw new BadRequestException(AdminMessage.ADMIN_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure all roles are populated
|
// Ensure all roles are populated
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
import { AuthMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
export class RefreshTokenDto {
|
export class RefreshTokenDto {
|
||||||
@ApiProperty({ description: 'Refresh token' })
|
@ApiProperty({ description: 'Refresh token' })
|
||||||
@IsString({ message: 'Refresh token must be a string' })
|
@IsString({ message: AuthMessage.REFRESH_TOKEN_MUST_BE_STRING })
|
||||||
@IsNotEmpty({ message: 'Refresh token is required' })
|
@IsNotEmpty({ message: AuthMessage.REFRESH_TOKEN_REQUIRED })
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ export class AuthService {
|
|||||||
const normalizedPhone = normalizePhone(phone);
|
const normalizedPhone = normalizePhone(phone);
|
||||||
const key = this.userOtpKey(slug, normalizedPhone);
|
const key = this.userOtpKey(slug, normalizedPhone);
|
||||||
const cachedCode = await this.cacheService.get(key);
|
const cachedCode = await this.cacheService.get(key);
|
||||||
if (!cachedCode) throw new BadRequestException('OTP expired or not found');
|
if (!cachedCode) throw new BadRequestException(AuthMessage.OTP_EXPIRED_OR_NOT_FOUND);
|
||||||
if (cachedCode !== code) throw new BadRequestException('Invalid OTP');
|
if (cachedCode !== code) throw new BadRequestException(AuthMessage.INVALID_OTP);
|
||||||
|
|
||||||
await this.cacheService.del(key);
|
await this.cacheService.del(key);
|
||||||
|
|
||||||
@@ -80,9 +80,9 @@ export class AuthService {
|
|||||||
const key = this.adminOtpKey(slug, normalizedPhone);
|
const key = this.adminOtpKey(slug, normalizedPhone);
|
||||||
const cachedCode = await this.cacheService.get(key);
|
const cachedCode = await this.cacheService.get(key);
|
||||||
|
|
||||||
if (!cachedCode) throw new BadRequestException('OTP expired or not found');
|
if (!cachedCode) throw new BadRequestException(AuthMessage.OTP_EXPIRED_OR_NOT_FOUND);
|
||||||
|
|
||||||
if (cachedCode !== code) throw new BadRequestException('Invalid OTP');
|
if (cachedCode !== code) throw new BadRequestException(AuthMessage.INVALID_OTP);
|
||||||
await this.cacheService.del(key);
|
await this.cacheService.del(key);
|
||||||
|
|
||||||
const admin = await this.adminService.findByPhoneAndShopSlug(normalizedPhone, slug);
|
const admin = await this.adminService.findByPhoneAndShopSlug(normalizedPhone, slug);
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ export class TokensService {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('Failed to generate new tokens after refresh', error);
|
this.logger.error('Failed to generate new tokens after refresh', error);
|
||||||
// Transaction will rollback automatically, preserving the old token
|
// Transaction will rollback automatically, preserving the old token
|
||||||
throw new UnauthorizedException('Failed to refresh token');
|
throw new UnauthorizedException(AuthMessage.FAILED_TO_REFRESH_TOKEN);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsNotEmpty, IsArray, ValidateNested, ArrayMinSize, IsInt, Min, IsString } from 'class-validator';
|
import { IsNotEmpty, IsArray, ValidateNested, ArrayMinSize, IsInt, Min, IsString } from 'class-validator';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
|
import { CartMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
class AddItemToCartDto {
|
class AddItemToCartDto {
|
||||||
@ApiProperty({ description: 'Quantity of the product item', example: 1, minimum: 1 })
|
@ApiProperty({ description: 'Quantity of the product item', example: 1, minimum: 1 })
|
||||||
@@ -27,7 +28,7 @@ export class BulkAddItemsToCartDto {
|
|||||||
})
|
})
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@ArrayMinSize(1, { message: 'At least one item is required' })
|
@ArrayMinSize(1, { message: CartMessage.AT_LEAST_ONE_ITEM_REQUIRED })
|
||||||
@ValidateNested({ each: true })
|
@ValidateNested({ each: true })
|
||||||
@Type(() => AddItemToCartDto)
|
@Type(() => AddItemToCartDto)
|
||||||
items!: AddItemToCartDto[];
|
items!: AddItemToCartDto[];
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Socket } from 'socket.io';
|
|||||||
import { JwtService } from '@nestjs/jwt';
|
import { JwtService } from '@nestjs/jwt';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { IAdminTokenPayload } from '../../auth/interfaces/IToken-payload';
|
import { IAdminTokenPayload } from '../../auth/interfaces/IToken-payload';
|
||||||
|
import { WebSocketMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
export interface AuthenticatedSocket extends Socket {
|
export interface AuthenticatedSocket extends Socket {
|
||||||
adminId?: string;
|
adminId?: string;
|
||||||
@@ -33,7 +34,7 @@ export class WsAdminAuthGuard implements CanActivate {
|
|||||||
auth: client.handshake.auth,
|
auth: client.handshake.auth,
|
||||||
query: client.handshake.query,
|
query: client.handshake.query,
|
||||||
});
|
});
|
||||||
throw new WsException('Authentication required');
|
throw new WsException(WebSocketMessage.AUTHENTICATION_REQUIRED);
|
||||||
}
|
}
|
||||||
|
|
||||||
const secret = this.configService.getOrThrow<string>('JWT_SECRET');
|
const secret = this.configService.getOrThrow<string>('JWT_SECRET');
|
||||||
@@ -43,7 +44,7 @@ export class WsAdminAuthGuard implements CanActivate {
|
|||||||
|
|
||||||
if (!payload.adminId || !payload.shopId) {
|
if (!payload.adminId || !payload.shopId) {
|
||||||
this.logger.error('Invalid token payload structure', payload);
|
this.logger.error('Invalid token payload structure', payload);
|
||||||
throw new WsException('Invalid token payload');
|
throw new WsException(WebSocketMessage.INVALID_TOKEN_PAYLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach admin info to socket
|
// Attach admin info to socket
|
||||||
@@ -61,7 +62,7 @@ export class WsAdminAuthGuard implements CanActivate {
|
|||||||
error: error instanceof Error ? error.message : 'Unknown error',
|
error: error instanceof Error ? error.message : 'Unknown error',
|
||||||
socketId: client.id,
|
socketId: client.id,
|
||||||
});
|
});
|
||||||
throw new WsException('Authentication failed');
|
throw new WsException(WebSocketMessage.WS_AUTHENTICATION_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { WsAdminAuthGuard, type AuthenticatedSocket } from './guards/ws-admin-au
|
|||||||
import { ModuleRef } from '@nestjs/core';
|
import { ModuleRef } from '@nestjs/core';
|
||||||
import { ExecutionContext } from '@nestjs/common';
|
import { ExecutionContext } from '@nestjs/common';
|
||||||
import { IInAppNotificationPayload } from './interfaces/notification.interface';
|
import { IInAppNotificationPayload } from './interfaces/notification.interface';
|
||||||
|
import { WebSocketMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
@WebSocketGateway({
|
@WebSocketGateway({
|
||||||
cors: {
|
cors: {
|
||||||
@@ -53,7 +54,7 @@ export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisco
|
|||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Connection authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
`Connection authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||||
);
|
);
|
||||||
void client.emit('error', { message: 'Authentication failed' });
|
void client.emit('error', { message: WebSocketMessage.WS_AUTHENTICATION_FAILED });
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,14 +90,14 @@ export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisco
|
|||||||
const room = this.getRoom(client.adminId!, client.shopId!);
|
const room = this.getRoom(client.adminId!, client.shopId!);
|
||||||
void client.leave(room);
|
void client.leave(room);
|
||||||
this.logger.log(`Admin ${client.adminId} (Client ${client.id}) left room: ${room}`);
|
this.logger.log(`Admin ${client.adminId} (Client ${client.id}) left room: ${room}`);
|
||||||
void client.emit('left', { room, message: 'Successfully Admin left room' });
|
void client.emit('left', { room, message: WebSocketMessage.ADMIN_LEFT_ROOM });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleJoinRoom(client: AuthenticatedSocket) {
|
handleJoinRoom(client: AuthenticatedSocket) {
|
||||||
const room = this.getRoom(client.adminId!, client.shopId!);
|
const room = this.getRoom(client.adminId!, client.shopId!);
|
||||||
void client.join(room);
|
void client.join(room);
|
||||||
this.logger.log(`Admin ${client.adminId} (Client ${client.id}) joined room: ${room}`);
|
this.logger.log(`Admin ${client.adminId} (Client ${client.id}) joined room: ${room}`);
|
||||||
void client.emit('joined', { room, message: 'Successfully Admin joined room' });
|
void client.emit('joined', { room, message: WebSocketMessage.ADMIN_JOINED_ROOM });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async authenticateConnection(client: Socket): Promise<void> {
|
private async authenticateConnection(client: Socket): Promise<void> {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Shop } from '../../shops/entities/shop.entity';
|
|||||||
import { CreatePreferenceDto } from '../dto/create-preference.dto';
|
import { CreatePreferenceDto } from '../dto/create-preference.dto';
|
||||||
import { UpdatePreferenceDto } from '../dto/update-preference.dto';
|
import { UpdatePreferenceDto } from '../dto/update-preference.dto';
|
||||||
import { NotifTitleEnum } from '../interfaces/notification.interface';
|
import { NotifTitleEnum } from '../interfaces/notification.interface';
|
||||||
|
import { NotificationMessage, RestMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NotificationPreferenceService {
|
export class NotificationPreferenceService {
|
||||||
@@ -13,7 +14,7 @@ export class NotificationPreferenceService {
|
|||||||
async create(shopId: string, dto: CreatePreferenceDto): Promise<NotificationPreference> {
|
async create(shopId: string, dto: CreatePreferenceDto): Promise<NotificationPreference> {
|
||||||
const shop = await this.em.findOne(Shop, { id: shopId });
|
const shop = await this.em.findOne(Shop, { id: shopId });
|
||||||
if (!shop) {
|
if (!shop) {
|
||||||
throw new NotFoundException('Shop not found');
|
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const preference = this.em.create(NotificationPreference, {
|
const preference = this.em.create(NotificationPreference, {
|
||||||
@@ -46,7 +47,7 @@ export class NotificationPreferenceService {
|
|||||||
// ): Promise<NotificationPreference> {
|
// ): Promise<NotificationPreference> {
|
||||||
// const preference = await this.findByRestaurantAndType(shopId, notificationType);
|
// const preference = await this.findByRestaurantAndType(shopId, notificationType);
|
||||||
// if (!preference) {
|
// if (!preference) {
|
||||||
// throw new NotFoundException('Notification preference not found');
|
// throw new NotFoundException(NotificationMessage.NOTIFICATION_PREFERENCE_NOT_FOUND);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// preference.enabled = enabled;
|
// preference.enabled = enabled;
|
||||||
@@ -64,7 +65,7 @@ export class NotificationPreferenceService {
|
|||||||
shop: { id: shopId },
|
shop: { id: shopId },
|
||||||
});
|
});
|
||||||
if (!preference) {
|
if (!preference) {
|
||||||
throw new NotFoundException('Notification preference not found');
|
throw new NotFoundException(NotificationMessage.NOTIFICATION_PREFERENCE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.em.assign(preference, dto);
|
this.em.assign(preference, dto);
|
||||||
@@ -78,7 +79,7 @@ export class NotificationPreferenceService {
|
|||||||
id: preferenceId,
|
id: preferenceId,
|
||||||
});
|
});
|
||||||
if (!preference) {
|
if (!preference) {
|
||||||
throw new NotFoundException('Notification preference not found');
|
throw new NotFoundException(NotificationMessage.NOTIFICATION_PREFERENCE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
await this.em.removeAndFlush(preference);
|
await this.em.removeAndFlush(preference);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { NotificationsGateway } from '../notifications.gateway';
|
|||||||
import { NotifChannelEnum, NotifRequest, NotifTitleEnum } from '../interfaces/notification.interface';
|
import { NotifChannelEnum, NotifRequest, NotifTitleEnum } from '../interfaces/notification.interface';
|
||||||
import { SmsLogRepository } from '../repositories/sms-log.repository';
|
import { SmsLogRepository } from '../repositories/sms-log.repository';
|
||||||
import { PaginatedResult } from '../../../common/interfaces/pagination.interface';
|
import { PaginatedResult } from '../../../common/interfaces/pagination.interface';
|
||||||
|
import { NotificationMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NotificationService {
|
export class NotificationService {
|
||||||
@@ -96,7 +97,7 @@ export class NotificationService {
|
|||||||
async findOne(id: string): Promise<Notification> {
|
async findOne(id: string): Promise<Notification> {
|
||||||
const notification = await this.em.findOne(Notification, { id }, { populate: ['shop', 'user'] });
|
const notification = await this.em.findOne(Notification, { id }, { populate: ['shop', 'user'] });
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
throw new NotFoundException('Notification not found');
|
throw new NotFoundException(NotificationMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
return notification;
|
return notification;
|
||||||
}
|
}
|
||||||
@@ -188,7 +189,7 @@ export class NotificationService {
|
|||||||
shop: { id: shopId },
|
shop: { id: shopId },
|
||||||
});
|
});
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
throw new NotFoundException('Notification not found');
|
throw new NotFoundException(NotificationMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
notification.seenAt = new Date();
|
notification.seenAt = new Date();
|
||||||
await this.em.persistAndFlush(notification);
|
await this.em.persistAndFlush(notification);
|
||||||
@@ -200,7 +201,7 @@ export class NotificationService {
|
|||||||
shop: { id: shopId },
|
shop: { id: shopId },
|
||||||
});
|
});
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
throw new NotFoundException('Notification not found');
|
throw new NotFoundException(NotificationMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
notification.seenAt = new Date();
|
notification.seenAt = new Date();
|
||||||
await this.em.persistAndFlush(notification);
|
await this.em.persistAndFlush(notification);
|
||||||
|
|||||||
@@ -113,11 +113,11 @@ export class PaymentsService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!walletTransaction) {
|
if (!walletTransaction) {
|
||||||
throw new NotFoundException('User wallet not found');
|
throw new NotFoundException(PaymentMessage.WALLET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (walletTransaction.balance < ctx.amount) {
|
if (walletTransaction.balance < ctx.amount) {
|
||||||
throw new BadRequestException('Insufficient wallet balance');
|
throw new BadRequestException(PaymentMessage.INSUFFICIENT_WALLET_BALANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newBalance = walletTransaction.balance - ctx.amount;
|
const newBalance = walletTransaction.balance - ctx.amount;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { CategoryRepository } from '../repositories/category.repository';
|
|||||||
import { EntityManager } from '@mikro-orm/postgresql';
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
import { RequiredEntityData } from '@mikro-orm/core';
|
import { RequiredEntityData } from '@mikro-orm/core';
|
||||||
import { Product } from '../entities/product.entity';
|
import { Product } from '../entities/product.entity';
|
||||||
import { CategoryMessage, ProductMessage } from 'src/common/enums/message.enum';
|
import { CategoryMessage, ProductMessage, UserMessage } from 'src/common/enums/message.enum';
|
||||||
import { Favorite } from '../entities/favorite.entity';
|
import { Favorite } from '../entities/favorite.entity';
|
||||||
import { Variant } from '../entities/variant.entity';
|
import { Variant } from '../entities/variant.entity';
|
||||||
import { ShopService } from 'src/modules/shops/providers/shops.service';
|
import { ShopService } from 'src/modules/shops/providers/shops.service';
|
||||||
@@ -24,7 +24,6 @@ export class ProductService {
|
|||||||
private readonly favoriteRepository: FavoriteRepository,
|
private readonly favoriteRepository: FavoriteRepository,
|
||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
) { }
|
) { }
|
||||||
// TODO : Messages must be in persian
|
|
||||||
async create(shopId: string, dto: CreateProductDto) {
|
async create(shopId: string, dto: CreateProductDto) {
|
||||||
const { categoryId, variants, ...rest } = dto;
|
const { categoryId, variants, ...rest } = dto;
|
||||||
const shop = await this.shopService.findOrFail(shopId);
|
const shop = await this.shopService.findOrFail(shopId);
|
||||||
@@ -32,7 +31,7 @@ export class ProductService {
|
|||||||
const category = await this.categoryService.findOrFail(categoryId)
|
const category = await this.categoryService.findOrFail(categoryId)
|
||||||
|
|
||||||
if (variants.length > 1 && !dto.attribute) {
|
if (variants.length > 1 && !dto.attribute) {
|
||||||
throw new BadRequestException('Attribute is required for multiple variants');
|
throw new BadRequestException(ProductMessage.ATTRIBUTE_REQUIRED_FOR_VARIANTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
const product = await this.em.transactional(async em => {
|
const product = await this.em.transactional(async em => {
|
||||||
@@ -144,7 +143,7 @@ export class ProductService {
|
|||||||
// Update existing variant
|
// Update existing variant
|
||||||
const existingVariant = existingVariantsMap.get(id);
|
const existingVariant = existingVariantsMap.get(id);
|
||||||
if (!existingVariant) {
|
if (!existingVariant) {
|
||||||
throw new NotFoundException('Variant not found');
|
throw new NotFoundException(ProductMessage.VARIANT_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the variant fields
|
// Update the variant fields
|
||||||
@@ -183,7 +182,7 @@ export class ProductService {
|
|||||||
const product = await this.findOrFail(id)
|
const product = await this.findOrFail(id)
|
||||||
|
|
||||||
if (product.shop.id !== shopId) {
|
if (product.shop.id !== shopId) {
|
||||||
throw new BadRequestException("Product doesnt belongs to your shop")
|
throw new BadRequestException(ProductMessage.PRODUCT_NOT_BELONGS_TO_SHOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
product.deletedAt = new Date();
|
product.deletedAt = new Date();
|
||||||
@@ -198,7 +197,7 @@ export class ProductService {
|
|||||||
const product = await this.em.findOne(Product, productId);
|
const product = await this.em.findOne(Product, productId);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new NotFoundException('User not found');
|
throw new NotFoundException(UserMessage.USER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (!product) {
|
if (!product) {
|
||||||
throw new NotFoundException(ProductMessage.NOT_FOUND);
|
throw new NotFoundException(ProductMessage.NOT_FOUND);
|
||||||
@@ -211,12 +210,12 @@ export class ProductService {
|
|||||||
|
|
||||||
if (favorite) {
|
if (favorite) {
|
||||||
await this.em.removeAndFlush(favorite);
|
await this.em.removeAndFlush(favorite);
|
||||||
return { message: 'Favorite removed successfully' };
|
return { message: ProductMessage.FAVORITE_REMOVED };
|
||||||
}
|
}
|
||||||
|
|
||||||
const newFavorite = this.em.create(Favorite, { user, product });
|
const newFavorite = this.em.create(Favorite, { user, product });
|
||||||
await this.em.persistAndFlush(newFavorite);
|
await this.em.persistAndFlush(newFavorite);
|
||||||
return { message: 'Favorite added successfully' };
|
return { message: ProductMessage.FAVORITE_ADDED };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -245,7 +244,7 @@ export class ProductService {
|
|||||||
populate: ['product', 'product.shop', 'product.variants'],
|
populate: ['product', 'product.shop', 'product.variants'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!variant) throw new NotFoundException('Variant not found');
|
if (!variant) throw new NotFoundException(ProductMessage.VARIANT_NOT_FOUND);
|
||||||
|
|
||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { UserRepository } from '../../users/repositories/user.repository';
|
|||||||
import { EntityManager } from '@mikro-orm/postgresql';
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
import { RequiredEntityData } from '@mikro-orm/core';
|
import { RequiredEntityData } from '@mikro-orm/core';
|
||||||
import { Review } from '../entities/review.entity';
|
import { Review } from '../entities/review.entity';
|
||||||
import { ProductMessage, UserMessage, ReviewMessage } from 'src/common/enums/message.enum';
|
import { OrderMessage, ProductMessage, RestMessage, UserMessage, ReviewMessage } from 'src/common/enums/message.enum';
|
||||||
import { Order } from '../../orders/entities/order.entity';
|
import { Order } from '../../orders/entities/order.entity';
|
||||||
import { OrderItem } from '../../orders/entities/order-item.entity';
|
import { OrderItem } from '../../orders/entities/order-item.entity';
|
||||||
import { Shop } from '../../shops/entities/shop.entity';
|
import { Shop } from '../../shops/entities/shop.entity';
|
||||||
@@ -43,7 +43,7 @@ export class ReviewService {
|
|||||||
// Find order and verify it belongs to the user, populate shop to get shopId
|
// Find order and verify it belongs to the user, populate shop to get shopId
|
||||||
const order = await this.em.findOne(Order, { id: orderId, user: { id: userId } }, { populate: ['shop'] });
|
const order = await this.em.findOne(Order, { id: orderId, user: { id: userId } }, { populate: ['shop'] });
|
||||||
if (!order) {
|
if (!order) {
|
||||||
throw new NotFoundException('Order not found or does not belong to the current user');
|
throw new NotFoundException(OrderMessage.ORDER_NOT_FOUND_OR_NOT_OWNED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the product is in the order (check through variant.product)
|
// Verify the product is in the order (check through variant.product)
|
||||||
@@ -54,7 +54,7 @@ export class ReviewService {
|
|||||||
populate: ['variant', 'variant.product'],
|
populate: ['variant', 'variant.product'],
|
||||||
});
|
});
|
||||||
if (!orderItem) {
|
if (!orderItem) {
|
||||||
throw new BadRequestException('Product is not in the specified order');
|
throw new BadRequestException(ReviewMessage.PRODUCT_NOT_IN_ORDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user already commented on this product for this order
|
// Check if user already commented on this product for this order
|
||||||
@@ -81,7 +81,7 @@ export class ReviewService {
|
|||||||
|
|
||||||
const review = this.reviewRepository.create(data);
|
const review = this.reviewRepository.create(data);
|
||||||
if (!review) {
|
if (!review) {
|
||||||
throw new BadRequestException('Failed to create review entity');
|
throw new BadRequestException(ReviewMessage.CREATE_REVIEW_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.em.persistAndFlush(review);
|
await this.em.persistAndFlush(review);
|
||||||
@@ -115,7 +115,7 @@ export class ReviewService {
|
|||||||
const { shopSlug: restuarantSlug, ...restDto } = dto;
|
const { shopSlug: restuarantSlug, ...restDto } = dto;
|
||||||
const shop = await this.em.findOne(Shop, { slug: restuarantSlug });
|
const shop = await this.em.findOne(Shop, { slug: restuarantSlug });
|
||||||
if (!shop) {
|
if (!shop) {
|
||||||
throw new NotFoundException('RestaurantMessage.NOT_FOUND');
|
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
return this.reviewRepository.findAllPaginated({ ...restDto, shopId: shop.id });
|
return this.reviewRepository.findAllPaginated({ ...restDto, shopId: shop.id });
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ export class ReviewService {
|
|||||||
|
|
||||||
// Users can only update rating and comment, not status
|
// Users can only update rating and comment, not status
|
||||||
if (!isAdmin && dto.status !== undefined) {
|
if (!isAdmin && dto.status !== undefined) {
|
||||||
throw new BadRequestException('Only admins can change review status');
|
throw new BadRequestException(ReviewMessage.ONLY_ADMIN_CAN_CHANGE_STATUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldRating = review.rating;
|
const oldRating = review.rating;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { EntityManager } from '@mikro-orm/postgresql';
|
|||||||
import { CreateRoleDto } from '../dto/create-role.dto';
|
import { CreateRoleDto } from '../dto/create-role.dto';
|
||||||
import { UpdateRoleDto } from '../dto/update-role.dto';
|
import { UpdateRoleDto } from '../dto/update-role.dto';
|
||||||
import { RolePermission } from '../entities/rolePermission.entity';
|
import { RolePermission } from '../entities/rolePermission.entity';
|
||||||
|
import { RestMessage, RoleMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RolesService {
|
export class RolesService {
|
||||||
@@ -25,14 +26,14 @@ export class RolesService {
|
|||||||
// Check if role already exists
|
// Check if role already exists
|
||||||
const existing = await this.roleRepository.findOne({ name, shop: shopId ? { id: shopId } : null });
|
const existing = await this.roleRepository.findOne({ name, shop: shopId ? { id: shopId } : null });
|
||||||
if (existing) {
|
if (existing) {
|
||||||
throw new BadRequestException('Role with this name already exists for the shop');
|
throw new BadRequestException(RoleMessage.ROLE_ALREADY_EXISTS_FOR_SHOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
let shop: Shop | null = null;
|
let shop: Shop | null = null;
|
||||||
if (shopId) {
|
if (shopId) {
|
||||||
shop = await this.em.findOne(Shop, { id: shopId });
|
shop = await this.em.findOne(Shop, { id: shopId });
|
||||||
if (!shop) {
|
if (!shop) {
|
||||||
throw new NotFoundException('Shop not found');
|
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ export class RolesService {
|
|||||||
if (permissionIds && permissionIds.length > 0) {
|
if (permissionIds && permissionIds.length > 0) {
|
||||||
const permissions = await this.permissionRepository.find({ id: { $in: permissionIds } });
|
const permissions = await this.permissionRepository.find({ id: { $in: permissionIds } });
|
||||||
if (permissions.length !== permissionIds.length) {
|
if (permissions.length !== permissionIds.length) {
|
||||||
throw new BadRequestException('One or more permissions not found');
|
throw new BadRequestException(RoleMessage.ONE_OR_MORE_PERMISSIONS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
permissions.forEach(p => role.permissions.add(p));
|
permissions.forEach(p => role.permissions.add(p));
|
||||||
}
|
}
|
||||||
@@ -72,7 +73,7 @@ export class RolesService {
|
|||||||
{ populate: ['permissions', 'shop'] },
|
{ populate: ['permissions', 'shop'] },
|
||||||
);
|
);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
throw new NotFoundException('Role not found');
|
throw new NotFoundException(RoleMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
@@ -83,7 +84,7 @@ export class RolesService {
|
|||||||
{ populate: ['permissions', 'shop'] },
|
{ populate: ['permissions', 'shop'] },
|
||||||
);
|
);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
throw new NotFoundException('Role not found');
|
throw new NotFoundException(RoleMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dto.name) {
|
if (dto.name) {
|
||||||
@@ -95,7 +96,7 @@ export class RolesService {
|
|||||||
role.permissions.removeAll();
|
role.permissions.removeAll();
|
||||||
const permissions = await this.permissionRepository.find({ id: { $in: dto.permissionIds } });
|
const permissions = await this.permissionRepository.find({ id: { $in: dto.permissionIds } });
|
||||||
if (permissions.length !== dto.permissionIds.length) {
|
if (permissions.length !== dto.permissionIds.length) {
|
||||||
throw new BadRequestException('One or more permissions not found');
|
throw new BadRequestException(RoleMessage.ONE_OR_MORE_PERMISSIONS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
permissions.forEach(p => role.permissions.add(p));
|
permissions.forEach(p => role.permissions.add(p));
|
||||||
}
|
}
|
||||||
@@ -122,10 +123,10 @@ export class RolesService {
|
|||||||
{ populate: ['permissions', 'shop'] },
|
{ populate: ['permissions', 'shop'] },
|
||||||
);
|
);
|
||||||
if (!role) {
|
if (!role) {
|
||||||
throw new NotFoundException('Role not found');
|
throw new NotFoundException(RoleMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (!role.admins.isEmpty()) {
|
if (!role.admins.isEmpty()) {
|
||||||
throw new BadRequestException('Role has admins');
|
throw new BadRequestException(RoleMessage.ROLE_HAS_ADMINS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hard delete pivot table entries (role_permissions) before soft deleting the role
|
// Hard delete pivot table entries (role_permissions) before soft deleting the role
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export class ShopService {
|
|||||||
|
|
||||||
const validateSubscriptionId = await em.findOne(Shop, { subscriptionId: dto.subscriptionId })
|
const validateSubscriptionId = await em.findOne(Shop, { subscriptionId: dto.subscriptionId })
|
||||||
if (validateSubscriptionId) {
|
if (validateSubscriptionId) {
|
||||||
throw new BadRequestException("Duplicate subscriptionId: " + dto.subscriptionId)
|
throw new BadRequestException(RestMessage.DUPLICATE_SUBSCRIPTION_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create shop
|
// Create shop
|
||||||
@@ -64,7 +64,7 @@ export class ShopService {
|
|||||||
|
|
||||||
const role = await em.findOne(Role, { isSystem: true });
|
const role = await em.findOne(Role, { isSystem: true });
|
||||||
if (!role) {
|
if (!role) {
|
||||||
throw new BadRequestException(`System role not found`);
|
throw new BadRequestException(RestMessage.SYSTEM_ROLE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizedPhone = normalizePhone(dto.phone);
|
const normalizedPhone = normalizePhone(dto.phone);
|
||||||
@@ -116,7 +116,7 @@ export class ShopService {
|
|||||||
const shop = await this.em.findOne(Shop, { slug });
|
const shop = await this.em.findOne(Shop, { slug });
|
||||||
|
|
||||||
if (!shop) {
|
if (!shop) {
|
||||||
throw new NotFoundException(`Shop with slug "${slug}" not found`);
|
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return shop;
|
return shop;
|
||||||
@@ -235,7 +235,7 @@ export class ShopService {
|
|||||||
async findOrFail(shopId: string) {
|
async findOrFail(shopId: string) {
|
||||||
const shop = await this.shopRepository.findOne({ id: shopId }, { populate: ['deliveries'] })
|
const shop = await this.shopRepository.findOne({ id: shopId }, { populate: ['deliveries'] })
|
||||||
if (!shop) {
|
if (!shop) {
|
||||||
throw new BadRequestException("Shop not found")
|
throw new BadRequestException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
return shop
|
return shop
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ export class ShopService {
|
|||||||
async findOrFailBySlug(shopSlug: string) {
|
async findOrFailBySlug(shopSlug: string) {
|
||||||
const shop = await this.shopRepository.findOne({ slug: shopSlug }, { populate: ['deliveries'] })
|
const shop = await this.shopRepository.findOne({ slug: shopSlug }, { populate: ['deliveries'] })
|
||||||
if (!shop) {
|
if (!shop) {
|
||||||
throw new BadRequestException("Shop not found")
|
throw new BadRequestException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
return shop
|
return shop
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { WalletTransactionRepository } from '../repositories/wallet-transaction.
|
|||||||
import { WalletService } from './wallet.service';
|
import { WalletService } from './wallet.service';
|
||||||
import { WalletTransactionReason, WalletTransactionType } from '../interface/wallet';
|
import { WalletTransactionReason, WalletTransactionType } from '../interface/wallet';
|
||||||
import { WalletTransaction } from '../entities/wallet-transaction.entity';
|
import { WalletTransaction } from '../entities/wallet-transaction.entity';
|
||||||
|
import { RestMessage, UserMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserService {
|
export class UserService {
|
||||||
@@ -56,7 +57,7 @@ export class UserService {
|
|||||||
|
|
||||||
// async updateUser(userId: string, dto: UpdateUserDto): Promise<User> {
|
// async updateUser(userId: string, dto: UpdateUserDto): Promise<User> {
|
||||||
// const user = await this.em.findOneOrFail(User, userId, {}).catch(() => {
|
// const user = await this.em.findOneOrFail(User, userId, {}).catch(() => {
|
||||||
// throw new NotFoundException(`User with ID ${userId} not found.`);
|
// throw new NotFoundException(UserMessage.USER_NOT_FOUND);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// this.em.assign(user, { ...dto });
|
// this.em.assign(user, { ...dto });
|
||||||
@@ -86,7 +87,7 @@ export class UserService {
|
|||||||
// get registerscore from shop
|
// get registerscore from shop
|
||||||
const shop = await this.restaurantRepository.findOne({ id: shopId });
|
const shop = await this.restaurantRepository.findOne({ id: shopId });
|
||||||
if (!shop) {
|
if (!shop) {
|
||||||
throw new NotFoundException(`Shop not found.`);
|
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
const points = Number(shop.score?.registerScore || 0);
|
const points = Number(shop.score?.registerScore || 0);
|
||||||
const createData = _raw as unknown as RequiredEntityData<User>;
|
const createData = _raw as unknown as RequiredEntityData<User>;
|
||||||
@@ -107,7 +108,7 @@ export class UserService {
|
|||||||
async updateUser(userId: string, shopId: string, dto: UpdateUserDto): Promise<User> {
|
async updateUser(userId: string, shopId: string, dto: UpdateUserDto): Promise<User> {
|
||||||
const user = await this.userRepository.findOne({ id: userId });
|
const user = await this.userRepository.findOne({ id: userId });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new NotFoundException(`User with ID ${userId} not found.`);
|
throw new NotFoundException(UserMessage.USER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize date strings into Date objects if provided
|
// Normalize date strings into Date objects if provided
|
||||||
@@ -180,7 +181,7 @@ export class UserService {
|
|||||||
async getUserAddresses(userId: string): Promise<UserAddress[]> {
|
async getUserAddresses(userId: string): Promise<UserAddress[]> {
|
||||||
const user = await this.userRepository.findOne({ id: userId }, { populate: ['addresses'] });
|
const user = await this.userRepository.findOne({ id: userId }, { populate: ['addresses'] });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new NotFoundException(`User with ID ${userId} not found.`);
|
throw new NotFoundException(UserMessage.USER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load addresses if not already loaded
|
// Load addresses if not already loaded
|
||||||
@@ -191,7 +192,7 @@ export class UserService {
|
|||||||
async createUserAddress(userId: string, dto: CreateUserAddressDto): Promise<UserAddress> {
|
async createUserAddress(userId: string, dto: CreateUserAddressDto): Promise<UserAddress> {
|
||||||
const user = await this.userRepository.findOne({ id: userId });
|
const user = await this.userRepository.findOne({ id: userId });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new NotFoundException(`User with ID ${userId} not found.`);
|
throw new NotFoundException(UserMessage.USER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If setting as default, unset other default addresses
|
// If setting as default, unset other default addresses
|
||||||
@@ -228,7 +229,7 @@ export class UserService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!address) {
|
if (!address) {
|
||||||
throw new NotFoundException(`Address with ID ${addressId} not found for user ${userId}.`);
|
throw new NotFoundException(UserMessage.ADDRESS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
@@ -241,7 +242,7 @@ export class UserService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!address) {
|
if (!address) {
|
||||||
throw new NotFoundException(`Address with ID ${addressId} not found for user ${userId}.`);
|
throw new NotFoundException(UserMessage.ADDRESS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If setting as default, unset other default addresses
|
// If setting as default, unset other default addresses
|
||||||
@@ -271,7 +272,7 @@ export class UserService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!address) {
|
if (!address) {
|
||||||
throw new NotFoundException(`Address with ID ${addressId} not found for user ${userId}.`);
|
throw new NotFoundException(UserMessage.ADDRESS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Soft delete the address
|
// Soft delete the address
|
||||||
@@ -286,7 +287,7 @@ export class UserService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!address) {
|
if (!address) {
|
||||||
throw new NotFoundException(`Address with ID ${addressId} not found for user ${userId}.`);
|
throw new NotFoundException(UserMessage.ADDRESS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unset all other default addresses
|
// Unset all other default addresses
|
||||||
@@ -310,11 +311,11 @@ export class UserService {
|
|||||||
return this.em.transactional(async em => {
|
return this.em.transactional(async em => {
|
||||||
const user = await em.findOne(User, { id: userId });
|
const user = await em.findOne(User, { id: userId });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new NotFoundException(`User with ID ${userId} not found.`);
|
throw new NotFoundException(UserMessage.USER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
const shop = await em.findOne(Shop, { id: shopId });
|
const shop = await em.findOne(Shop, { id: shopId });
|
||||||
if (!shop) {
|
if (!shop) {
|
||||||
throw new NotFoundException(`Shop with ID ${shopId} not found.`);
|
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
let walletTransaction = await em.findOne(WalletTransaction, { user: { id: userId }, shop: { id: shopId } },
|
let walletTransaction = await em.findOne(WalletTransaction, { user: { id: userId }, shop: { id: shopId } },
|
||||||
{ orderBy: { createdAt: 'DESC' } });
|
{ orderBy: { createdAt: 'DESC' } });
|
||||||
@@ -336,17 +337,17 @@ export class UserService {
|
|||||||
|
|
||||||
// Validate points to convert
|
// Validate points to convert
|
||||||
if (pointsToConvert <= 0) {
|
if (pointsToConvert <= 0) {
|
||||||
throw new BadRequestException('Points to convert must be greater than 0.');
|
throw new BadRequestException(UserMessage.POINTS_MUST_BE_GREATER_THAN_ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shop.score) {
|
if (!shop.score) {
|
||||||
throw new BadRequestException('Shop score not found.');
|
throw new BadRequestException(UserMessage.SHOP_SCORE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (!shop.score.purchaseScore) {
|
if (!shop.score.purchaseScore) {
|
||||||
throw new BadRequestException('Shop purchase score not found.');
|
throw new BadRequestException(UserMessage.SHOP_PURCHASE_SCORE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
if (!shop.score.purchaseAmount) {
|
if (!shop.score.purchaseAmount) {
|
||||||
throw new BadRequestException('Shop purchase amount not found.');
|
throw new BadRequestException(UserMessage.SHOP_PURCHASE_AMOUNT_NOT_FOUND);
|
||||||
}
|
}
|
||||||
const walletIncreaseAmount =
|
const walletIncreaseAmount =
|
||||||
(Number(pointsToConvert) * Number(shop.score.purchaseAmount)) / Number(shop.score.purchaseScore);
|
(Number(pointsToConvert) * Number(shop.score.purchaseAmount)) / Number(shop.score.purchaseScore);
|
||||||
@@ -388,7 +389,7 @@ export class UserService {
|
|||||||
async findOneOrFail(userId: string): Promise<User> {
|
async findOneOrFail(userId: string): Promise<User> {
|
||||||
const user = await this.userRepository.findOne({ id: userId });
|
const user = await this.userRepository.findOne({ id: userId });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new NotFoundException(`User with ID ${userId} not found.`);
|
throw new NotFoundException(UserMessage.USER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
@@ -396,7 +397,7 @@ export class UserService {
|
|||||||
async getUserAddressOrFail(addressId: string): Promise<UserAddress> {
|
async getUserAddressOrFail(addressId: string): Promise<UserAddress> {
|
||||||
const address = await this.em.findOne(UserAddress, { id: addressId }, { populate: ['user'] });
|
const address = await this.em.findOne(UserAddress, { id: addressId }, { populate: ['user'] });
|
||||||
if (!address) {
|
if (!address) {
|
||||||
throw new NotFoundException("User address not found.");
|
throw new NotFoundException(UserMessage.ADDRESS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { CreateWalletTransactionDto } from '../dto/create-wallet-transaction.dto
|
|||||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||||
import { WalletTransactionType } from '../interface/wallet';
|
import { WalletTransactionType } from '../interface/wallet';
|
||||||
import { PointTransactionRepository } from '../repositories/point-transaction.repository';
|
import { PointTransactionRepository } from '../repositories/point-transaction.repository';
|
||||||
|
import { PaymentMessage } from 'src/common/enums/message.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WalletService {
|
export class WalletService {
|
||||||
@@ -44,7 +45,7 @@ export class WalletService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!walletTransaction) {
|
if (!walletTransaction) {
|
||||||
throw new NotFoundException(`User wallet not found for user ${userId} and shop ${shopId}.`);
|
throw new NotFoundException(PaymentMessage.WALLET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the 'where' filter query
|
// Build the 'where' filter query
|
||||||
@@ -127,7 +128,7 @@ export class WalletService {
|
|||||||
|
|
||||||
// Validate amount
|
// Validate amount
|
||||||
if (amount <= 0) {
|
if (amount <= 0) {
|
||||||
throw new BadRequestException('Transaction amount must be greater than 0.');
|
throw new BadRequestException(PaymentMessage.AMOUNT_MUST_BE_GREATER_THAN_ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the user's wallet for this shop
|
// Find the user's wallet for this shop
|
||||||
@@ -137,7 +138,7 @@ export class WalletService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!walletTransaction) {
|
if (!walletTransaction) {
|
||||||
throw new NotFoundException(`User wallet not found for user ${userId} and shop ${shopId}.`);
|
throw new NotFoundException(PaymentMessage.WALLET_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate new balance
|
// Calculate new balance
|
||||||
@@ -148,11 +149,11 @@ export class WalletService {
|
|||||||
newBalance = currentBalance + amount;
|
newBalance = currentBalance + amount;
|
||||||
} else if (type === WalletTransactionType.DEBIT) {
|
} else if (type === WalletTransactionType.DEBIT) {
|
||||||
if (currentBalance < amount) {
|
if (currentBalance < amount) {
|
||||||
throw new BadRequestException(`Insufficient wallet balance. Current: ${currentBalance}, Required: ${amount}.`);
|
throw new BadRequestException(PaymentMessage.INSUFFICIENT_WALLET_BALANCE);
|
||||||
}
|
}
|
||||||
newBalance = currentBalance - amount;
|
newBalance = currentBalance - amount;
|
||||||
} else {
|
} else {
|
||||||
throw new BadRequestException(`Invalid transaction type: ${type}`);
|
throw new BadRequestException(PaymentMessage.INVALID_TRANSACTION_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update wallet balance
|
// Update wallet balance
|
||||||
|
|||||||
Reference in New Issue
Block a user