dkala module
This commit is contained in:
@@ -42,6 +42,7 @@ import { TicketsModule } from "./modules/tickets/tickets.module";
|
||||
import { UploaderModule } from "./modules/uploader/uploader.module";
|
||||
import { UsersModule } from "./modules/users/users.module";
|
||||
import { WalletsModule } from "./modules/wallets/wallets.module";
|
||||
import { DkalaModule } from "./modules/dkala/dmenu.module";
|
||||
@Module({
|
||||
imports: [
|
||||
// TelegrafModule.forRootAsync(telegrafConfig()),
|
||||
@@ -87,6 +88,7 @@ import { WalletsModule } from "./modules/wallets/wallets.module";
|
||||
SupportPlansModule,
|
||||
AccessLogsModule,
|
||||
DmenuModule,
|
||||
DkalaModule
|
||||
],
|
||||
controllers: [],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
|
||||
export function dkalaConfig() {
|
||||
return {
|
||||
inject: [ConfigService],
|
||||
useFactory: async (configService: ConfigService) => {
|
||||
return {
|
||||
baseUrl: configService.get<string>("DKALA_BACKEND_URL")??'https://dkala-api.danakcorp.com',
|
||||
username: configService.get<string>("DKALA_USERNAME")??'danak@dsc.com',
|
||||
password: configService.get<string>("DKALA_PASSWORD")??'DsCdAnAk?@ABC',
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export interface IDkalaConfig {
|
||||
baseUrl: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsUUID } from "class-validator";
|
||||
|
||||
import { SubscriptionMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
export class BuyPremiumPlanDto {
|
||||
@IsNotEmpty({ message: SubscriptionMessage.PLAN_ID_REQUIRED })
|
||||
@IsUUID(4, { message: SubscriptionMessage.PLAN_ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "The restaurant subscription ID to upgrade", example: "f7b3b3b3-7b3b-4b3b-8b3b-3b3b3b3b3b3b" })
|
||||
userSubscriptionId: string;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsString } from "class-validator";
|
||||
|
||||
export class CreateGroupDto {
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@ApiProperty({ description: "Group name", example: "Navigation Icons" })
|
||||
name: string;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsOptional, IsString, IsUrl } from "class-validator";
|
||||
|
||||
export class CreateIconDto {
|
||||
@IsNotEmpty()
|
||||
@IsUrl({ protocols: ["http", "https"], require_protocol: true })
|
||||
@ApiProperty({ description: "Icon URL", example: "https://example.com/icons/home.svg" })
|
||||
url: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({ description: "Icon group ID", example: "group-123", required: false })
|
||||
groupId?: string;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
export class CreateMyShopAdminDto {
|
||||
@ApiProperty({ description: 'Mobile phone number' })
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
phone!: string;
|
||||
|
||||
@ApiProperty({ description: 'First name', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
firstName?: string;
|
||||
|
||||
@ApiProperty({ description: 'Last name', required: false })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
lastName?: string;
|
||||
|
||||
@ApiProperty({ description: 'Role id for the admin' })
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
roleId!: string;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class SetupShopDto {
|
||||
|
||||
@ApiProperty({ example: 'zhivan', description: 'شناسه (slug) رستوران، لاتین و بدون فاصله' })
|
||||
@IsString()
|
||||
slug!: string;
|
||||
|
||||
|
||||
@ApiProperty({ example: 'sub_1234567890', description: 'شناسه اشتراک' })
|
||||
@IsString()
|
||||
userSubscriptionId!: string;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import {
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsNumber,
|
||||
Min,
|
||||
IsIn,
|
||||
IsBoolean,
|
||||
} from 'class-validator';
|
||||
import { Type, Transform } from 'class-transformer';
|
||||
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||
|
||||
const sortOrderOptions = ['asc', 'desc'] as const;
|
||||
type SortOrder = (typeof sortOrderOptions)[number];
|
||||
|
||||
export class FindShopsDto {
|
||||
@ApiPropertyOptional({ default: 1, minimum: 1 })
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
page: number = 1;
|
||||
|
||||
@ApiPropertyOptional({ default: 10, minimum: 1 })
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
limit: number = 10;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Search by name, slug, domain, or address',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
search?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Filter by active status',
|
||||
type: Boolean,
|
||||
})
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => {
|
||||
if (value === 'true') return true;
|
||||
if (value === 'false') return false;
|
||||
return value;
|
||||
})
|
||||
@IsBoolean()
|
||||
isActive?: boolean;
|
||||
|
||||
|
||||
@ApiPropertyOptional({ default: 'createdAt' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
orderBy: string = 'createdAt';
|
||||
|
||||
@ApiPropertyOptional({
|
||||
enum: sortOrderOptions,
|
||||
default: 'desc',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(sortOrderOptions)
|
||||
order: SortOrder = 'desc';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { PartialType } from "@nestjs/swagger";
|
||||
|
||||
import { CreateGroupDto } from "./create-group.dto";
|
||||
|
||||
export class UpdateGroupDto extends PartialType(CreateGroupDto) {}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { PartialType } from "@nestjs/swagger";
|
||||
|
||||
import { CreateIconDto } from "./create-icon.dto";
|
||||
|
||||
export class UpdateIconDto extends PartialType(CreateIconDto) {}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { IsString, IsOptional, IsNumber, IsDate, IsBoolean } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
export class UpdateShopDto {
|
||||
@ApiPropertyOptional({ example: 'کافه ژیوان', description: 'نام رستوران' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
name?: string;
|
||||
|
||||
@ApiPropertyOptional({ example: 'zhivan', description: 'شناسه (slug) رستوران، لاتین و بدون فاصله' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
slug?: string;
|
||||
|
||||
@ApiPropertyOptional({ example: 2020, description: 'سال تأسیس' })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
establishedYear?: number;
|
||||
|
||||
@ApiPropertyOptional({ example: '09123456789', description: 'شماره تلفن' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
phone?: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
isActive?: boolean;
|
||||
|
||||
|
||||
@ApiPropertyOptional({ example: 'sub_1234567890', description: 'شناسه اشتراک' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
subscriptionId?: string;
|
||||
|
||||
@ApiPropertyOptional({ example: '2025-12-26', description: 'تاریخ انقضای اشتراک' })
|
||||
@IsOptional()
|
||||
@Type(() => Date)
|
||||
@IsDate()
|
||||
subscriptionEndDate?: Date;
|
||||
|
||||
@ApiPropertyOptional({ example: '2025-12-26', description: 'تاریخ شروع اشتراک' })
|
||||
@IsOptional()
|
||||
@Type(() => Date)
|
||||
@IsDate()
|
||||
subscriptionStartDate?: Date;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export const DKALA_CONFIG = "DKALA_CONFIG";
|
||||
@@ -0,0 +1,219 @@
|
||||
import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from "@nestjs/common";
|
||||
import { ApiBearerAuth, ApiOperation, ApiParam, ApiQuery, ApiTags } from "@nestjs/swagger";
|
||||
|
||||
import { DContactService } from "./providers/contact.service";
|
||||
import { DkalaIconsService } from "./providers/icons.service";
|
||||
import { ShopService } from "./providers/shop.service";
|
||||
import { CreateIconDto } from "./DTO/create-icon.dto";
|
||||
import { UpdateIconDto } from "./DTO/update-icon.dto";
|
||||
import { CreateGroupDto } from "./DTO/create-group.dto";
|
||||
import { UpdateGroupDto } from "./DTO/update-group.dto";
|
||||
import { FindShopsDto } from "./DTO/find-shops.dto";
|
||||
import { SetupShopDto } from "./DTO/create-shop.dto";
|
||||
import { UpdateShopDto } from "./DTO/update-shop.dto";
|
||||
import { CreateMyShopAdminDto } from "./DTO/create-shop-admin.dto";
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { PermissionsDec } from "../../common/decorators/permission.decorator";
|
||||
import { PermissionEnum } from "../users/enums/permission.enum";
|
||||
import { UserDec } from "../../common/decorators/user.decorator";
|
||||
|
||||
@ApiTags("d-menu")
|
||||
@Controller()
|
||||
@AuthGuards()
|
||||
|
||||
@ApiBearerAuth()
|
||||
export class DkalaController {
|
||||
constructor(
|
||||
private readonly iconsService: DkalaIconsService,
|
||||
private readonly contactService: DContactService,
|
||||
private readonly shopService: ShopService,
|
||||
) { }
|
||||
|
||||
// Icon endpoints
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Post('admin/dkala/icons')
|
||||
@ApiOperation({ summary: "Create icon" })
|
||||
createIcon(@Body() dto: CreateIconDto) {
|
||||
return this.iconsService.createIcon(dto);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get('admin/dkala/icons')
|
||||
@ApiOperation({ summary: "Get all icons" })
|
||||
findAllIcons() {
|
||||
return this.iconsService.findAllIcons();
|
||||
}
|
||||
// Group endpoints: place BEFORE `icons/:id` routes to avoid route conflicts
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Post("admin/dkala/icons/groups")
|
||||
@ApiOperation({ summary: "Create icon group" })
|
||||
createGroup(@Body() dto: CreateGroupDto) {
|
||||
return this.iconsService.createGroup(dto);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get("admin/dkala/icons/groups")
|
||||
@ApiOperation({ summary: "Get all icon groups" })
|
||||
findAllGroups() {
|
||||
return this.iconsService.findAllGroups();
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get("admin/dkala/icons/groups/:id")
|
||||
@ApiOperation({ summary: "Get icon group by id" })
|
||||
@ApiParam({ name: "id", required: true, type: String })
|
||||
findOneGroup(@Param("id") id: string) {
|
||||
return this.iconsService.findOneGroup(id);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Patch("admin/dkala/icons/groups/:id")
|
||||
@ApiOperation({ summary: "Update icon group" })
|
||||
@ApiParam({ name: "id" })
|
||||
updateGroup(@Param("id") id: string, @Body() dto: UpdateGroupDto) {
|
||||
return this.iconsService.updateGroup(id, dto);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Delete("admin/dkala/icons/groups/:id")
|
||||
@ApiOperation({ summary: "Delete icon group" })
|
||||
@ApiParam({ name: "id" })
|
||||
removeGroup(@Param("id") id: string) {
|
||||
return this.iconsService.removeGroup(id);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get("admin/dkala/icons/:id")
|
||||
@ApiOperation({ summary: "Get icon by id" })
|
||||
@ApiParam({ name: "id", required: true, type: String })
|
||||
findOneIcon(@Param("id") id: string) {
|
||||
return this.iconsService.findOneIcon(id);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Patch("admin/dkala/icons/:id")
|
||||
@ApiOperation({ summary: "Update icon" })
|
||||
@ApiParam({ name: "id" })
|
||||
updateIcon(@Param("id") id: string, @Body() dto: UpdateIconDto) {
|
||||
return this.iconsService.updateIcon(id, dto);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Delete("admin/dkala/icons/:id")
|
||||
@ApiOperation({ summary: "Delete icon" })
|
||||
@ApiParam({ name: "id" })
|
||||
removeIcon(@Param("id") id: string) {
|
||||
return this.iconsService.removeIcon(id);
|
||||
}
|
||||
// contacts
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get('admin/dkala/contacts')
|
||||
findAll() {
|
||||
return this.contactService.findAll();
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get("admin/dkala/contacts/:id")
|
||||
findOne(@Param("id") id: string) {
|
||||
return this.contactService.findOne(+id);
|
||||
}
|
||||
|
||||
// restaurant
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get('admin/dkala/shops')
|
||||
@ApiOperation({ summary: "Get all restaurants" })
|
||||
findAllRestaurant(@Query() queryDto: FindShopsDto) {
|
||||
return this.shopService.findAll(queryDto);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get('admin/dkala/shops/:id')
|
||||
@ApiOperation({ summary: "Get restaurant by ID" })
|
||||
@ApiParam({ name: "id", required: true, type: String })
|
||||
getRestaurantById(@Param("id") id: string) {
|
||||
return this.shopService.getShopById(id);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@Get('admin/dkala/shops/sms-count')
|
||||
@ApiOperation({ summary: 'Get SMS count for each restaurant with pagination' })
|
||||
@ApiQuery({ name: 'page', required: false, type: Number, description: 'Page number (default: 1)', minimum: 1 })
|
||||
@ApiQuery({ name: 'limit', required: false, type: Number, description: 'Items per page (default: 10)', minimum: 1 })
|
||||
async getSmsCount(
|
||||
@Query('page') page?: number,
|
||||
@Query('limit') limit?: number,
|
||||
) {
|
||||
const parsedPage = page ? parseInt(page.toString(), 10) : 1;
|
||||
const parsedLimit = limit ? parseInt(limit.toString(), 10) : 10;
|
||||
return await this.shopService.getSmsCountByRestaurant(parsedPage, parsedLimit);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Patch('admin/dkala/shops/:id')
|
||||
@ApiOperation({ summary: "Update restaurant" })
|
||||
@ApiParam({ name: "id", required: true, type: String })
|
||||
updateRestaurant(@Param("id") id: string, @Body() dto: UpdateShopDto) {
|
||||
return this.shopService.updateRestaurant(id, dto);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Delete('admin/dkala/shops/:id/hard-delete')
|
||||
@ApiOperation({ summary: "Hard delete restaurant" })
|
||||
@ApiParam({ name: "id", required: true, type: String })
|
||||
hardDeleteRestaurant(@Param("id") id: string) {
|
||||
return this.shopService.hardDeleteShop(id);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get('admin/dkala/system-roles')
|
||||
@ApiOperation({ summary: "Get system roles" })
|
||||
getSystemRoles() {
|
||||
return this.shopService.getSystemRoles();
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Get('admin/dkala/shops/:restaurantId/admins')
|
||||
@ApiOperation({ summary: "Get restaurant admins" })
|
||||
@ApiParam({ name: "restaurantId", required: true, type: String })
|
||||
getRestaurantAdmins(@Param("restaurantId") restaurantId: string) {
|
||||
return this.shopService.getRestaurantAdmins(restaurantId);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Post('admin/dkala/shops/:restaurantId/admins')
|
||||
@ApiOperation({ summary: "Assign admin to restaurant" })
|
||||
@ApiParam({ name: "restaurantId", required: true, type: String })
|
||||
assignRestaurantAdmin(@Param("restaurantId") restaurantId: string, @Body() dto: CreateMyShopAdminDto) {
|
||||
return this.shopService.assignRestaurantAdmin(restaurantId, dto);
|
||||
}
|
||||
|
||||
@PermissionsDec(PermissionEnum.DKALA)
|
||||
@Delete('admin/dkala/shops/:restaurantId/admins/:adminId')
|
||||
@ApiOperation({ summary: "Revoke admin from restaurant" })
|
||||
@ApiParam({ name: "restaurantId", required: true, type: String })
|
||||
@ApiParam({ name: "adminId", required: true, type: String })
|
||||
revokeRestaurantAdmin(@Param("restaurantId") restaurantId: string, @Param("adminId") adminId: string) {
|
||||
return this.shopService.revokeRestaurantAdmin(restaurantId, adminId);
|
||||
}
|
||||
|
||||
//***User Endpoints***
|
||||
@Post('dkala/shops')
|
||||
@ApiOperation({ summary: "Create restaurant" })
|
||||
createRestaurant(@Body() dto: SetupShopDto, @UserDec("id") userId: string) {
|
||||
return this.shopService.createRestaurant(dto, userId);
|
||||
}
|
||||
|
||||
@Get('dkala/shops/subscription/:subscriptionId')
|
||||
@ApiOperation({ summary: "Get restaurant subscription by subscription ID" })
|
||||
@ApiParam({ name: "subscriptionId", required: true, type: String })
|
||||
getRestaurantSubscription(@Param("subscriptionId") subscriptionId: string) {
|
||||
return this.shopService.getRestaurantSubscription(subscriptionId);
|
||||
}
|
||||
|
||||
@Post('dkala/auth/direct-login/:userSubscriptionId')
|
||||
@ApiOperation({ summary: "Direct login with user subscription ID" })
|
||||
@ApiParam({ name: "userSubscriptionId", required: true, type: String })
|
||||
directLogin(@Param("userSubscriptionId") userSubscriptionId: string, @UserDec("id") userId: string) {
|
||||
return this.shopService.directLogin(userSubscriptionId, userId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { forwardRef, Module } from "@nestjs/common";
|
||||
|
||||
import { DKALA_CONFIG } from "./constants";
|
||||
import { DkalaController } from "./dmenu.controller";
|
||||
import { DContactService } from "./providers/contact.service";
|
||||
import { DkalaIconsService } from "./providers/icons.service";
|
||||
import { ShopService } from "./providers/shop.service";
|
||||
import { SubscriptionsModule } from "../subscriptions/subscriptions.module";
|
||||
import { UsersModule } from "../users/users.module";
|
||||
import { dkalaConfig } from "../../configs/dkala.config";
|
||||
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
forwardRef(() => SubscriptionsModule),
|
||||
UsersModule
|
||||
],
|
||||
controllers: [DkalaController],
|
||||
providers: [
|
||||
DkalaIconsService,
|
||||
DContactService,
|
||||
ShopService,
|
||||
{
|
||||
provide: DKALA_CONFIG,
|
||||
useFactory: dkalaConfig().useFactory,
|
||||
inject: dkalaConfig().inject,
|
||||
},
|
||||
],
|
||||
exports: [ShopService],
|
||||
})
|
||||
export class DkalaModule {}
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
export interface ISetupShop {
|
||||
name: string;
|
||||
slug: string;
|
||||
establishedYear: number;
|
||||
phone: string;
|
||||
subscriptionId: string;
|
||||
subscriptionEndDate: string | Date;
|
||||
subscriptionStartDate: string | Date;
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
export interface IExternalApiPaginationMeta {
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
totalPages: number;
|
||||
}
|
||||
|
||||
export interface IExternalApiResponse<T> {
|
||||
data: T;
|
||||
meta: IExternalApiPaginationMeta;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { HttpService } from "@nestjs/axios";
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import { Inject } from "@nestjs/common";
|
||||
import { AxiosError } from "axios";
|
||||
import { catchError, firstValueFrom, throwError } from "rxjs";
|
||||
|
||||
import { DKALA_CONFIG } from "../constants";
|
||||
import { IDkalaConfig } from "../../../configs/dkala.config";
|
||||
|
||||
@Injectable()
|
||||
export class DContactService {
|
||||
private readonly logger = new Logger(DContactService.name);
|
||||
|
||||
constructor(
|
||||
@Inject(DKALA_CONFIG) private readonly config: IDkalaConfig,
|
||||
private readonly httpService: HttpService,
|
||||
) {}
|
||||
|
||||
private getHeaders(): Record<string, string> {
|
||||
const credentials = Buffer.from(`${this.config.username}:${this.config.password}`).toString("base64");
|
||||
return {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Basic ${credentials}`,
|
||||
};
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.get(`${this.config.baseUrl}/super-admin/contact`, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to fetch contacts: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error fetching contacts: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(id: number) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.get(`${this.config.baseUrl}/super-admin/contact/${id}`, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to fetch contact: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error fetching contact: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
import { HttpService } from "@nestjs/axios";
|
||||
import { Inject, Injectable, Logger } from "@nestjs/common";
|
||||
import { AxiosError } from "axios";
|
||||
import { catchError, firstValueFrom, throwError } from "rxjs";
|
||||
|
||||
import { IDmenuConfig } from "../../../configs/icons.config";
|
||||
import { DKALA_CONFIG } from "../constants";
|
||||
import { CreateGroupDto } from "../DTO/create-group.dto";
|
||||
import { CreateIconDto } from "../DTO/create-icon.dto";
|
||||
import { UpdateGroupDto } from "../DTO/update-group.dto";
|
||||
import { UpdateIconDto } from "../DTO/update-icon.dto";
|
||||
|
||||
@Injectable()
|
||||
export class DkalaIconsService {
|
||||
private readonly logger = new Logger(DkalaIconsService.name);
|
||||
|
||||
constructor(
|
||||
@Inject(DKALA_CONFIG) private readonly config: IDmenuConfig,
|
||||
private readonly httpService: HttpService,
|
||||
) {}
|
||||
|
||||
private getHeaders(): Record<string, string> {
|
||||
const credentials = Buffer.from(`${this.config.username}:${this.config.password}`).toString("base64");
|
||||
return {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Basic ${credentials}`,
|
||||
};
|
||||
}
|
||||
|
||||
// Icon methods
|
||||
async createIcon(dto: CreateIconDto) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.post(`${this.config.baseUrl}/super-admin/icons`, dto, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to create icon: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error creating icon: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async findAllIcons() {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.get(`${this.config.baseUrl}/super-admin/icons`, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to fetch icons: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error fetching icons: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async findOneIcon(id: string) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.get(`${this.config.baseUrl}/super-admin/icons/${id}`, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to fetch icon: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error fetching icon: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateIcon(id: string, dto: UpdateIconDto) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.patch(`${this.config.baseUrl}/super-admin/icons/${id}`, dto, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to update icon: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error updating icon: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async removeIcon(id: string) {
|
||||
try {
|
||||
const response = await firstValueFrom(
|
||||
this.httpService.delete(`${this.config.baseUrl}/super-admin/icons/${id}`, { headers: this.getHeaders(), data: {} }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to delete icon: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return response.data ?? { message: "Icon deleted successfully" };
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error deleting icon: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Group methods
|
||||
async createGroup(dto: CreateGroupDto) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.post(`${this.config.baseUrl}/super-admin/icons/groups`, dto, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to create group: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error creating group: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async findAllGroups() {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.get(`${this.config.baseUrl}/super-admin/icons/groups`, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to fetch groups: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error fetching groups: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async findOneGroup(id: string) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.get(`${this.config.baseUrl}/super-admin/icons/groups/${id}`, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to fetch group: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error fetching group: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateGroup(id: string, dto: UpdateGroupDto) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService.patch(`${this.config.baseUrl}/super-admin/icons/groups/${id}`, dto, { headers: this.getHeaders() }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to update group: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error updating group: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async removeGroup(id: string) {
|
||||
try {
|
||||
const response = await firstValueFrom(
|
||||
this.httpService.delete(`${this.config.baseUrl}/super-admin/icons/groups/${id}`, { headers: this.getHeaders(), data: {} }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to delete group: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return response.data ?? { message: "Group deleted successfully" };
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Error deleting group: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,494 @@
|
||||
import { HttpService } from "@nestjs/axios";
|
||||
import { BadRequestException, HttpException, Injectable, Logger } from "@nestjs/common";
|
||||
import { Inject } from "@nestjs/common";
|
||||
import { AxiosError } from "axios";
|
||||
import { catchError, firstValueFrom, throwError } from "rxjs";
|
||||
|
||||
import { DKALA_CONFIG } from "../constants";
|
||||
import { FindShopsDto } from "../DTO/find-shops.dto";
|
||||
import { SetupShopDto } from "../DTO/create-shop.dto";
|
||||
import { UpdateShopDto } from "../DTO/update-shop.dto";
|
||||
import { CreateMyShopAdminDto } from "../DTO/create-shop-admin.dto";
|
||||
import { ISetupShop, IExternalApiResponse } from "../interface/plan.interface";
|
||||
import { SubscriptionsService } from "../../subscriptions/providers/subscriptions.service";
|
||||
import { UsersService } from "../../users/providers/users.service";
|
||||
import { SubscriptionMessage } from "../../../common/enums/message.enum";
|
||||
import { IDkalaConfig } from "../../../configs/dkala.config";
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ShopService {
|
||||
private readonly logger = new Logger(ShopService.name);
|
||||
|
||||
constructor(
|
||||
@Inject(DKALA_CONFIG) private readonly config: IDkalaConfig,
|
||||
private readonly httpService: HttpService,
|
||||
private readonly subscriptionService: SubscriptionsService,
|
||||
private readonly usersService: UsersService,
|
||||
) { }
|
||||
|
||||
private getHeaders(): Record<string, string> {
|
||||
const credentials = Buffer.from(`${this.config.username}:${this.config.password}`).toString("base64");
|
||||
return {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Basic ${credentials}`,
|
||||
};
|
||||
}
|
||||
|
||||
async findAll(queryDto: FindShopsDto) {
|
||||
try {
|
||||
const params: Record<string, any> = {
|
||||
page: queryDto.page || 1,
|
||||
limit: queryDto.limit || 10,
|
||||
orderBy: queryDto.orderBy || "createdAt",
|
||||
order: queryDto.order || "desc",
|
||||
};
|
||||
|
||||
if (queryDto.search) {
|
||||
params.search = queryDto.search;
|
||||
}
|
||||
|
||||
if (queryDto.isActive !== undefined) {
|
||||
params.isActive = queryDto.isActive;
|
||||
}
|
||||
|
||||
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.get<IExternalApiResponse<any[]>>(`${this.config.baseUrl}/super-admin/restaurants`, {
|
||||
params,
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to fetch restaurants: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return {
|
||||
restaurants: data.data,
|
||||
count: data.meta.total,
|
||||
paginate: true,
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error fetching restaurants: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getShopById(id: string) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.get(`${this.config.baseUrl}/super-admin/restaurants/${id}`, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to get restaurant by ID: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error getting restaurant by ID: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async createRestaurant(dto: SetupShopDto, userId: string) {
|
||||
const { userSubscription } = await this.subscriptionService.getUserSubscriptionById(dto.userSubscriptionId, userId);
|
||||
if (!userSubscription) {
|
||||
throw new BadRequestException(SubscriptionMessage.USER_SUBS_NOT_FOUND);
|
||||
}
|
||||
|
||||
const user = await this.usersService.findOneById(userId)
|
||||
|
||||
if (!user) {
|
||||
throw new BadRequestException("User Not found");
|
||||
}
|
||||
|
||||
const setupRestaurantDto: ISetupShop = {
|
||||
name: userSubscription.businessName,
|
||||
slug: dto.slug,
|
||||
establishedYear: 1400,
|
||||
phone: user.user.phone,
|
||||
subscriptionId: dto.userSubscriptionId,
|
||||
subscriptionEndDate: userSubscription.endDate.toISOString(),
|
||||
subscriptionStartDate: userSubscription.startDate.toISOString(),
|
||||
isActive: true
|
||||
};
|
||||
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.post(`${this.config.baseUrl}/super-admin/restaurants`, setupRestaurantDto, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to create restaurant: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error creating restaurant: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateRestaurant(id: string, dto: UpdateShopDto) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.patch(`${this.config.baseUrl}/super-admin/restaurants/${id}`, dto, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to update restaurant: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error updating restaurant: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getRestaurantSubscription(subscriptionId: string) {
|
||||
try {
|
||||
console.log('subscriptionId', subscriptionId)
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.get(`${this.config.baseUrl}/super-admin/restaurants/subscription/${subscriptionId}`, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to get restaurant subscription: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
console.log('data', data)
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error getting restaurant subscription: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getSmsCountByRestaurant(page: number, limit: number) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.get(this.config.baseUrl + "/super-admin/notifications/sms-count", {
|
||||
params: { page, limit },
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error("error in getting SMS count by restaurant", err);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error("error in getSmsCountByRestaurant", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getSystemRoles() {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.get(`${this.config.baseUrl}/super-admin/system-roles`, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to get system roles: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error getting system roles: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getRestaurantAdmins(restaurantId: string) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.get(`${this.config.baseUrl}/super-admin/restaurants/${restaurantId}/admins`, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to get restaurant admins: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error getting restaurant admins: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async revokeRestaurantAdmin(restaurantId: string, adminId: string) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.delete(`${this.config.baseUrl}/super-admin/restaurants/${restaurantId}/admins/${adminId}`, {
|
||||
headers: this.getHeaders(),
|
||||
data: {},
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to revoke restaurant admin: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error revoking restaurant admin: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async assignRestaurantAdmin(restaurantId: string, dto: CreateMyShopAdminDto) {
|
||||
try {
|
||||
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.post(`${this.config.baseUrl}/super-admin/restaurants/${restaurantId}/admins`, dto, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to assign restaurant admin: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
...data,
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error assigning restaurant admin: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async upgradeSubscription(subscriptionId: string, newPlan: 'base' | 'premium', subscriptionEndDate: Date) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.patch(`${this.config.baseUrl}/super-admin/restaurants/subscription/${subscriptionId}/upgrade`, {
|
||||
newPlan,
|
||||
subscriptionEndDate
|
||||
}, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to upgrade restaurant subscription: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error upgrading restaurant subscription: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async hardDeleteShop(id: string) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.delete(`${this.config.baseUrl}/super-admin/restaurants/${id}/hard-delete`, {
|
||||
headers: this.getHeaders(),
|
||||
data: {},
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to hard delete restaurant: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error hard deleting restaurant: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async directLogin(userSubscriptionId: string, userId: string) {
|
||||
try {
|
||||
// 1. Get userSubscription by id
|
||||
const user = await this.usersService.findOneById(userId)
|
||||
|
||||
if (!user) {
|
||||
throw new BadRequestException("User Not found");
|
||||
}
|
||||
// 2. Get phone from userSubscription
|
||||
const phone = user.user.phone
|
||||
if (!phone) {
|
||||
throw new BadRequestException("Phone number not found in user subscription");
|
||||
}
|
||||
|
||||
// 3. Get restaurant by subscription id
|
||||
const restaurant = await this.getRestaurantSubscription(userSubscriptionId);
|
||||
|
||||
// 4. Get slug from restaurant
|
||||
const slug = restaurant.data.slug;
|
||||
if (!slug) {
|
||||
throw new BadRequestException("Restaurant slug not found");
|
||||
}
|
||||
|
||||
// 5. Login with phone and slug
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.post(`${this.config.baseUrl}/super-admin/auth/direct-login`, {
|
||||
phone,
|
||||
slug,
|
||||
}, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(`Failed to perform direct login: ${err.message}`, err.stack);
|
||||
return throwError(() => err);
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError && error.response) {
|
||||
this.logger.error(`External API error response:`, error.response.data);
|
||||
const errorResponse = {
|
||||
...error.response.data,
|
||||
message: error.response.data.error?.message || error.message,
|
||||
};
|
||||
throw new HttpException(errorResponse, error.response.status);
|
||||
}
|
||||
this.logger.error(`Error performing direct login: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,5 @@ export enum PermissionEnum {
|
||||
MANAGE_SSO_CLIENTS = "manage_sso_clients",
|
||||
SUPPORT_PLAN = "support_plan",
|
||||
DMENU = "dmenu",
|
||||
DKALA = "dkala",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user