add single endpoint
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -22,6 +22,6 @@ export class CreateRestaurantDto {
|
||||
|
||||
@ApiProperty({ example: 'sub_1234567890', description: 'شناسه اشتراک' })
|
||||
@IsString()
|
||||
subscriptionId!: string;
|
||||
userSubscriptionId!: string;
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { CreateRestaurantDto } from "./DTO/create-restaurant.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("admin/dmenu")
|
||||
@@ -112,7 +113,14 @@ export class DmenuController {
|
||||
|
||||
@Post('restaurants')
|
||||
@ApiOperation({ summary: "Create restaurant" })
|
||||
createRestaurant(@Body() dto: CreateRestaurantDto) {
|
||||
return this.restaurantService.createRestaurant(dto);
|
||||
createRestaurant(@Body() dto: CreateRestaurantDto, @UserDec("id") userId: string) {
|
||||
return this.restaurantService.createRestaurant(dto, userId);
|
||||
}
|
||||
|
||||
@Get('/super-admin/restaurants/subscription/:subscriptionId')
|
||||
@ApiOperation({ summary: "Get restaurant subscription by subscription ID" })
|
||||
@ApiParam({ name: "subscriptionId", required: true, type: String })
|
||||
getRestaurantSubscription(@Param("subscriptionId") subscriptionId: string) {
|
||||
return this.restaurantService.getRestaurantSubscription(subscriptionId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||
import dayjs from "dayjs";
|
||||
import Decimal from "decimal.js";
|
||||
|
||||
import { SubscriptionMessage } from "../../../common/enums/message.enum";
|
||||
import { InvoicesService } from "../../invoices/providers/invoices.service";
|
||||
import { UserSubscription } from "../../subscriptions/entities/user-subscription.entity";
|
||||
import { UserSubscriptionsRepository } from "../../subscriptions/repositories/user-subscriptions.repository";
|
||||
import { BuyPremiumPlanDto } from "../DTO/buy-premium-plan.dto";
|
||||
|
||||
@Injectable()
|
||||
export class PremiumService {
|
||||
constructor(
|
||||
private readonly userSubscriptionsRepository: UserSubscriptionsRepository,
|
||||
private readonly invoicesService: InvoicesService,
|
||||
) {}
|
||||
|
||||
async buyPremiumPlan(dto: BuyPremiumPlanDto, userId: string) {
|
||||
// Find the user's current subscription
|
||||
const userSubscription = await this.userSubscriptionsRepository.findOne({
|
||||
where: { id: dto.userSubscriptionId, user: { id: userId } },
|
||||
relations: {
|
||||
user: true,
|
||||
plan: { service: true },
|
||||
},
|
||||
});
|
||||
|
||||
if (!userSubscription) {
|
||||
throw new BadRequestException(SubscriptionMessage.NOT_FOUND);
|
||||
}
|
||||
|
||||
// Calculate remaining days
|
||||
const remainingDays = this.calculateRemainingDays(userSubscription);
|
||||
|
||||
// Extract duration from current plan and convert to months
|
||||
const planDurationInMonths = Math.round(userSubscription.plan.duration / 30);
|
||||
|
||||
// Get premium pricing based on extracted duration
|
||||
const premiumPrice = this.getPremiumPrice(planDurationInMonths);
|
||||
|
||||
// Create invoice items for premium purchase
|
||||
const invoiceItems = [{
|
||||
name: `Premium Plan - ${planDurationInMonths} Months`,
|
||||
count: 1,
|
||||
unitPrice: premiumPrice.toNumber(),
|
||||
discount: 0,
|
||||
}];
|
||||
|
||||
// Create invoice directly
|
||||
const createInvoiceDto = {
|
||||
userId: userSubscription.user.id,
|
||||
items: invoiceItems,
|
||||
isRecurring: false,
|
||||
};
|
||||
|
||||
const invoice = await this.invoicesService.createInvoiceAdmin(createInvoiceDto, {
|
||||
ip: '',
|
||||
headers: {},
|
||||
userId: userSubscription.user.id
|
||||
});
|
||||
|
||||
return {
|
||||
message: "Premium plan purchased successfully",
|
||||
userSubscription,
|
||||
invoice,
|
||||
remainingDays,
|
||||
premiumPrice: premiumPrice.toNumber(),
|
||||
};
|
||||
}
|
||||
|
||||
//************************************ */
|
||||
private calculateRemainingDays(userSubscription: UserSubscription): number {
|
||||
const now = dayjs();
|
||||
const endDate = dayjs(userSubscription.endDate);
|
||||
|
||||
if (endDate.isBefore(now)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return endDate.diff(now, 'day');
|
||||
}
|
||||
|
||||
//************************************ */
|
||||
private getPremiumPrice(durationInMonths: number): Decimal {
|
||||
switch (durationInMonths) {
|
||||
case 6:
|
||||
return new Decimal(5000000);
|
||||
case 12:
|
||||
return new Decimal(10000000);
|
||||
default:
|
||||
throw new BadRequestException("Invalid premium plan duration. Only 6 and 12 month plans are supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HttpService } from "@nestjs/axios";
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
|
||||
import { Inject } from "@nestjs/common";
|
||||
import { AxiosError } from "axios";
|
||||
import { catchError, firstValueFrom, throwError } from "rxjs";
|
||||
@@ -8,6 +8,9 @@ import { IDmenuConfig } from "../../../configs/icons.config";
|
||||
import { DMENU_CONFIG } from "../constants";
|
||||
import { FindRestaurantsDto } from "../DTO/find-restaurants.dto";
|
||||
import { CreateRestaurantDto } from "../DTO/create-restaurant.dto";
|
||||
import { PlanEnum } from "../interface/plan.interface";
|
||||
import { SubscriptionsService } from "../../subscriptions/providers/subscriptions.service";
|
||||
import { SubscriptionMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
@Injectable()
|
||||
export class RestaurantService {
|
||||
@@ -16,6 +19,7 @@ export class RestaurantService {
|
||||
constructor(
|
||||
@Inject(DMENU_CONFIG) private readonly config: IDmenuConfig,
|
||||
private readonly httpService: HttpService,
|
||||
private readonly subscriptionService: SubscriptionsService,
|
||||
) {}
|
||||
|
||||
private getHeaders(): Record<string, string> {
|
||||
@@ -67,11 +71,18 @@ export class RestaurantService {
|
||||
}
|
||||
}
|
||||
|
||||
async createRestaurant(dto: CreateRestaurantDto) {
|
||||
async createRestaurant(dto: CreateRestaurantDto, userId: string) {
|
||||
const { userSubscription } = await this.subscriptionService.getUserSubscriptionById(dto.userSubscriptionId, userId);
|
||||
if (!userSubscription) {
|
||||
throw new BadRequestException(SubscriptionMessage.USER_SUBS_NOT_FOUND);
|
||||
}
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.post(`${this.config.baseUrl}/super-admin/restaurants`, dto, {
|
||||
.post(`${this.config.baseUrl}/super-admin/restaurants`, {
|
||||
...dto,
|
||||
plan: PlanEnum.Base,
|
||||
}, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
.pipe(
|
||||
@@ -87,5 +98,20 @@ export class RestaurantService {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getRestaurantSubscription(subscriptionId: string) {
|
||||
// TODO: Implement the business logic to get restaurant subscription
|
||||
// This could involve querying the database, making external API calls, etc.
|
||||
|
||||
this.logger.log(`Getting restaurant subscription for ID: ${subscriptionId}`);
|
||||
|
||||
// For now, return a placeholder response
|
||||
// You should implement the actual logic based on your business requirements
|
||||
return {
|
||||
subscriptionId,
|
||||
message: "Restaurant subscription endpoint created successfully",
|
||||
// Add actual data structure based on your requirements
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Controller, Get, Param } from "@nestjs/common";
|
||||
import { ApiBearerAuth, ApiOperation, ApiParam, ApiTags } from "@nestjs/swagger";
|
||||
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { PermissionsDec } from "../../common/decorators/permission.decorator";
|
||||
import { PermissionEnum } from "../users/enums/permission.enum";
|
||||
import { RestaurantService } from "./providers/restaurant.service";
|
||||
|
||||
@ApiTags("super-admin")
|
||||
@Controller("super-admin")
|
||||
@AuthGuards()
|
||||
@PermissionsDec(PermissionEnum.DMENU)
|
||||
@ApiBearerAuth()
|
||||
export class SuperAdminController {
|
||||
constructor(
|
||||
private readonly restaurantService: RestaurantService,
|
||||
) {}
|
||||
|
||||
@Get('restaurants/subscription/:subscriptionId')
|
||||
@ApiOperation({ summary: "Get restaurant subscription by subscription ID" })
|
||||
@ApiParam({ name: "subscriptionId", required: true, type: String })
|
||||
getRestaurantSubscription(@Param("subscriptionId") subscriptionId: string) {
|
||||
return this.restaurantService.getRestaurantSubscription(subscriptionId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user