501 lines
18 KiB
TypeScript
501 lines
18 KiB
TypeScript
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 { IDmenuConfig } from "../../../configs/icons.config";
|
|
import { DMENU_CONFIG } from "../constants";
|
|
import { FindRestaurantsDto } from "../DTO/find-restaurants.dto";
|
|
import { SetupRestaurantDto } from "../DTO/create-restaurant.dto";
|
|
import { UpdateRestaurantDto } from "../DTO/update-restaurant.dto";
|
|
import { CreateMyRestaurantAdminDto } from "../DTO/create-restaurant-admin.dto";
|
|
import { PlanEnum, ISetupRestaurant, 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";
|
|
|
|
|
|
@Injectable()
|
|
export class RestaurantService {
|
|
private readonly logger = new Logger(RestaurantService.name);
|
|
|
|
constructor(
|
|
@Inject(DMENU_CONFIG) private readonly config: IDmenuConfig,
|
|
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: FindRestaurantsDto) {
|
|
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;
|
|
}
|
|
|
|
if (queryDto.plan) {
|
|
params.plan = queryDto.plan;
|
|
}
|
|
|
|
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 getRestaurantById(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: SetupRestaurantDto, userId: string) {
|
|
const { userSubscription } = await this.subscriptionService.getUserSubscriptionById(dto.userSubscriptionId, userId);
|
|
if (!userSubscription) {
|
|
throw new BadRequestException(SubscriptionMessage.USER_SUBS_NOT_FOUND);
|
|
}
|
|
const plan = userSubscription.plan.name.includes("دلیوری") ? PlanEnum.Premium : PlanEnum.Base;
|
|
|
|
const user = await this.usersService.findOneById(userId)
|
|
|
|
if (!user) {
|
|
throw new BadRequestException("User Not found");
|
|
}
|
|
|
|
const setupRestaurantDto: ISetupRestaurant = {
|
|
name: userSubscription.businessName,
|
|
slug: dto.slug,
|
|
establishedYear: 1400,
|
|
phone: user.user.phone,
|
|
plan,
|
|
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: UpdateRestaurantDto) {
|
|
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 },
|
|
headers: this.getHeaders()
|
|
})
|
|
.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: CreateMyRestaurantAdminDto) {
|
|
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 hardDeleteRestaurant(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;
|
|
}
|
|
}
|
|
}
|