upgrade plan
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class AddPlanToInvoiceItem1767508304292 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "invoice_item"
|
||||
ADD COLUMN "planId" uuid
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "invoice_item"
|
||||
ADD CONSTRAINT "FK_invoice_item_plan"
|
||||
FOREIGN KEY ("planId") REFERENCES "subscription_plan"("id")
|
||||
ON DELETE RESTRICT ON UPDATE NO ACTION
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX "IDX_invoice_item_plan" ON "invoice_item" ("planId")
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "invoice_item"
|
||||
DROP CONSTRAINT "FK_invoice_item_plan"
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
DROP INDEX "IDX_invoice_item_plan"
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "invoice_item"
|
||||
DROP COLUMN "planId"
|
||||
`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -524,6 +524,9 @@ export const enum SubscriptionMessage {
|
||||
FREE_PLAN_LIMIT_EXCEEDED = "شما در یک ماه گذشته از پلن رایگان استفاده کردهاید و نمیتوانید مجدداً استفاده کنید",
|
||||
FREE_PLAN_NOT_ALLOWED = "انتخاب پلن رایگان در تمدید سرویس امکان پدیر نیست",
|
||||
USER_DOES_NOT_HAVE_ACCESS = "شما دسترسی به این سرویس ندارید",
|
||||
SERVICE_MISMATCH = "سرویس پلن فعلی با سرویس پلن جدید متفاوت است",
|
||||
UPGRADE_TO_LOWER_OR_EQUAL_PLAN_NOT_ALLOWED = "ارتقا به پلن با قیمت کمتر یا برابر مجاز نیست",
|
||||
SUBSCRIPTION_EXPIRED_CANNOT_UPGRADE = "اشتراک منقضی شده و قابل ارتقا نیست",
|
||||
}
|
||||
|
||||
export const enum InvoiceMessage {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { forwardRef, Module } from "@nestjs/common";
|
||||
|
||||
import { DMENU_CONFIG } from "./constants";
|
||||
import { DmenuController } from "./dmenu.controller";
|
||||
@@ -9,7 +9,7 @@ import { dmenuConfig } from "../../configs/icons.config";
|
||||
import { SubscriptionsModule } from "../subscriptions/subscriptions.module";
|
||||
|
||||
@Module({
|
||||
imports: [SubscriptionsModule],
|
||||
imports: [forwardRef(() => SubscriptionsModule)],
|
||||
controllers: [DmenuController],
|
||||
providers: [
|
||||
IconsService,
|
||||
@@ -21,5 +21,6 @@ import { SubscriptionsModule } from "../subscriptions/subscriptions.module";
|
||||
inject: dmenuConfig().inject,
|
||||
},
|
||||
],
|
||||
})
|
||||
exports: [RestaurantService],
|
||||
})
|
||||
export class DmenuModule {}
|
||||
|
||||
@@ -14,3 +14,15 @@ export interface ISetupRestaurant {
|
||||
subscriptionEndDate: string|Date;
|
||||
subscriptionStartDate: string|Date;
|
||||
}
|
||||
|
||||
export interface IExternalApiPaginationMeta {
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
totalPages: number;
|
||||
}
|
||||
|
||||
export interface IExternalApiResponse<T> {
|
||||
data: T;
|
||||
meta: IExternalApiPaginationMeta;
|
||||
}
|
||||
@@ -10,7 +10,7 @@ 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 } from "../interface/plan.interface";
|
||||
import { PlanEnum, ISetupRestaurant, IExternalApiResponse } from "../interface/plan.interface";
|
||||
import { SubscriptionsService } from "../../subscriptions/providers/subscriptions.service";
|
||||
import { SubscriptionMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
@@ -55,7 +55,7 @@ export class RestaurantService {
|
||||
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.get(`${this.config.baseUrl}/super-admin/restaurants`, {
|
||||
.get<IExternalApiResponse<any[]>>(`${this.config.baseUrl}/super-admin/restaurants`, {
|
||||
params,
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
@@ -66,7 +66,11 @@ export class RestaurantService {
|
||||
}),
|
||||
),
|
||||
);
|
||||
return data;
|
||||
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);
|
||||
@@ -331,4 +335,36 @@ export class RestaurantService {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async upgradeSubscription(subscriptionId: string, newPlan: string, subscriptionEndDate: string) {
|
||||
try {
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.patch(`${this.config.baseUrl}/super-admin/restaurants/subscription/${subscriptionId}/upgrade`, {
|
||||
plan: 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import Decimal from "decimal.js";
|
||||
import { Column, Entity, ManyToOne } from "typeorm";
|
||||
import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
|
||||
|
||||
import { Invoice } from "./invoice.entity";
|
||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||
import { DecimalTransformer } from "../../../common/transformers/decimal.transformer";
|
||||
import { UserSubscription } from "../../subscriptions/entities/user-subscription.entity";
|
||||
import { SubscriptionPlan } from "../../subscriptions/entities/subscription.entity";
|
||||
import { UserSupportPlan } from "../../support-plans/entities/user-support-plan.entity";
|
||||
@Entity()
|
||||
export class InvoiceItem extends BaseEntity {
|
||||
@@ -29,6 +30,13 @@ export class InvoiceItem extends BaseEntity {
|
||||
@ManyToOne(() => UserSubscription, { nullable: true, onDelete: "RESTRICT" })
|
||||
subscriptionPlan: UserSubscription | null;
|
||||
|
||||
@ManyToOne(() => SubscriptionPlan, { nullable: true, onDelete: "RESTRICT" })
|
||||
@JoinColumn({ name: "planId" })
|
||||
plan: SubscriptionPlan | null;
|
||||
|
||||
@ManyToOne(() => UserSupportPlan, { nullable: true, onDelete: "RESTRICT" })
|
||||
supportPlan: UserSupportPlan | null;
|
||||
|
||||
@Column({ type: "uuid", nullable: true })
|
||||
planId: string | null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BullModule } from "@nestjs/bullmq";
|
||||
import { Module } from "@nestjs/common";
|
||||
import { forwardRef, Module } from "@nestjs/common";
|
||||
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||
|
||||
import { INVOICE } from "./constants";
|
||||
@@ -11,6 +11,7 @@ import { InvoiceProcessor } from "./queue/invoice.processor";
|
||||
import { InvoiceItemsRepository } from "./repositories/invoice-items.repository";
|
||||
import { InvoicesRepository } from "./repositories/invoices.repository";
|
||||
import { AccessLogsModule } from "../access-logs/access-logs.module";
|
||||
import { DmenuModule } from "../dmenu/dmenu.module";
|
||||
import { Discount } from "../discounts/entities/discount.entity";
|
||||
import { UsageDiscount } from "../discounts/entities/usage-discount.entity";
|
||||
import { DiscountRepository } from "../discounts/repositories/discounts.repository";
|
||||
@@ -46,6 +47,7 @@ import { WalletsModule } from "../wallets/wallets.module";
|
||||
NotificationModule,
|
||||
PaymentsModule,
|
||||
AccessLogsModule,
|
||||
forwardRef(() => DmenuModule),
|
||||
],
|
||||
providers: [InvoicesService, InvoicesRepository, InvoiceItemsRepository, DiscountRepository, UsageDiscountRepository, InvoiceProcessor],
|
||||
controllers: [InvoicesController],
|
||||
|
||||
@@ -11,6 +11,7 @@ import { OperationType } from "../../access-logs/enums/operation-type.enum";
|
||||
import { UserType } from "../../access-logs/enums/user-type.enum";
|
||||
import { AccessLogService } from "../../access-logs/providers/access-log.service";
|
||||
import { VerifyOtpWithUserId } from "../../auth/DTO/verify-otp.dto";
|
||||
import { RestaurantService } from "../../dmenu/providers/restaurant.service";
|
||||
import { Discount } from "../../discounts/entities/discount.entity";
|
||||
import { DiscountType } from "../../discounts/enums/discount-type.enum";
|
||||
import { NotificationQueue } from "../../notifications/queue/notification.queue";
|
||||
@@ -53,6 +54,7 @@ export class InvoicesService {
|
||||
private readonly smsService: SmsService,
|
||||
private readonly dataSource: DataSource,
|
||||
private readonly accessLogService: AccessLogService,
|
||||
private readonly restaurantService: RestaurantService,
|
||||
) {}
|
||||
|
||||
///********************************** */
|
||||
@@ -498,6 +500,7 @@ export class InvoicesService {
|
||||
unitPrice: originalPrice,
|
||||
discount: discount ? new Decimal(originalPrice).sub(finalPrice).toNumber() : 0,
|
||||
subscriptionPlan: userSub,
|
||||
plan: plan,
|
||||
totalPrice: finalPrice,
|
||||
};
|
||||
|
||||
@@ -540,6 +543,63 @@ export class InvoicesService {
|
||||
|
||||
return invoice;
|
||||
}
|
||||
|
||||
//********************************** */
|
||||
async createInvoiceForSubscriptionUpgrade(user: User, plan: SubscriptionPlan, userSub: UserSubscription, dueDate: Date, qryRnr: QueryRunner, upgradeCost?: Decimal) {
|
||||
const discount = plan.directDiscount;
|
||||
const originalPrice = upgradeCost || (plan.originalPrice || plan.price);
|
||||
const finalPrice = upgradeCost || plan.price;
|
||||
|
||||
const invoiceItem = {
|
||||
name: `${plan.service.name} - Upgrade`,
|
||||
count: 1,
|
||||
unitPrice: originalPrice,
|
||||
discount: discount ? new Decimal(originalPrice).sub(finalPrice).toNumber() : 0,
|
||||
subscriptionPlan: userSub,
|
||||
plan: plan,
|
||||
totalPrice: finalPrice,
|
||||
};
|
||||
|
||||
const taxAmount = new Decimal(finalPrice).mul(0.1);
|
||||
const totalPrice = new Decimal(finalPrice).add(taxAmount);
|
||||
|
||||
const invoice = qryRnr.manager.create(Invoice, {
|
||||
user,
|
||||
totalPrice: totalPrice,
|
||||
originalPrice: new Decimal(originalPrice).add(new Decimal(originalPrice).mul(0.1)),
|
||||
tax: taxAmount.toNumber(),
|
||||
status: InvoiceStatus.WAIT_PAYMENT,
|
||||
dueDate,
|
||||
items: [invoiceItem],
|
||||
discount: discount || undefined,
|
||||
});
|
||||
|
||||
await qryRnr.manager.save(Invoice, invoice);
|
||||
|
||||
await this.notificationQueue.addInvoiceCreationNotification(user.id, {
|
||||
invoiceId: invoice.numericId.toString(),
|
||||
dueDate: invoice.dueDate,
|
||||
createDate: invoice.createdAt,
|
||||
price: totalPrice.toNumber(),
|
||||
userPhone: user.phone,
|
||||
userEmail: user.email,
|
||||
items: plan.service.name,
|
||||
});
|
||||
|
||||
await this.invoiceQueue.add(
|
||||
INVOICE.REMINDER_JOB_NAME,
|
||||
{ invoiceId: invoice.id },
|
||||
{
|
||||
delay: dayjs(invoice.dueDate).subtract(INVOICE.DAYS_BEFORE_OVERDUE, "day").diff(dayjs()),
|
||||
attempts: INVOICE.REMINDER_JOB_ATTEMPTS,
|
||||
backoff: { type: "exponential", delay: INVOICE.REMINDER_JOB_BACKOFF },
|
||||
priority: INVOICE.REMINDER_JOB_PRIORITY,
|
||||
},
|
||||
);
|
||||
|
||||
return invoice;
|
||||
}
|
||||
|
||||
//********************************** */
|
||||
async createInvoiceForSupportPlan(
|
||||
user: User,
|
||||
@@ -735,7 +795,39 @@ export class InvoicesService {
|
||||
|
||||
if (invoice.items[0]?.subscriptionPlan && !invoice.isExternal) {
|
||||
const userSubscription = invoice.items[0].subscriptionPlan;
|
||||
const invoiceItem = invoice.items[0];
|
||||
|
||||
// Check if this is an upgrade (subscription is ACTIVE and plan in invoice differs from current plan)
|
||||
const isUpgrade = userSubscription.status === SubscriptionStatus.ACTIVE &&
|
||||
invoiceItem.plan &&
|
||||
invoiceItem.plan.id !== userSubscription.plan.id;
|
||||
|
||||
if (isUpgrade) {
|
||||
// This is an upgrade - update subscription with the new plan
|
||||
const upgradePlan = invoiceItem.plan!;
|
||||
|
||||
userSubscription.plan = upgradePlan;
|
||||
this.logger.log(`Subscription ${userSubscription.id} upgraded to plan ${upgradePlan.name}`);
|
||||
await this.scheduleNextRenewalJob(userSubscription);
|
||||
|
||||
// Call external API for dmenu service upgrades
|
||||
if (upgradePlan.service.name.toLowerCase().includes('dmenu') || upgradePlan.service.slug?.toLowerCase().includes('dmenu')) {
|
||||
try {
|
||||
this.logger.log(`Calling external API for dmenu upgrade: subscription ${userSubscription.id}`);
|
||||
const dmenuPlan = upgradePlan.name.includes("دلیوری") ? "premium" : "base";
|
||||
await this.restaurantService.upgradeSubscription(
|
||||
userSubscription.id,
|
||||
dmenuPlan,
|
||||
userSubscription.endDate.toISOString()
|
||||
);
|
||||
this.logger.log(`External API call completed for dmenu upgrade: subscription ${userSubscription.id}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to call external API for dmenu upgrade: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
// Don't fail the transaction if external API call fails
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Regular subscription logic (renewal or activation)
|
||||
const isRenewal = userSubscription.status === SubscriptionStatus.ACTIVE;
|
||||
|
||||
if (isRenewal) {
|
||||
@@ -748,6 +840,7 @@ export class InvoicesService {
|
||||
userSubscription.status = SubscriptionStatus.ACTIVE;
|
||||
await this.scheduleNextRenewalJob(userSubscription);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
await queryRunner.manager.save(UserSubscription, userSubscription);
|
||||
@@ -849,6 +942,7 @@ export class InvoicesService {
|
||||
subscriptionPlan: {
|
||||
plan: true,
|
||||
},
|
||||
plan: true,
|
||||
supportPlan: {
|
||||
supportPlan: true,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsString } from "class-validator";
|
||||
|
||||
export class UpgradeSubscriptionDto {
|
||||
@ApiProperty({
|
||||
description: "The ID of the new plan to upgrade to",
|
||||
example: "plan-uuid-123"
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
planId: string;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { InjectQueue } from "@nestjs/bullmq";
|
||||
import { BadRequestException, ForbiddenException, Injectable, Logger } from "@nestjs/common";
|
||||
import { ModuleRef } from "@nestjs/core";
|
||||
import { Queue } from "bullmq";
|
||||
import dayjs from "dayjs";
|
||||
import Decimal from "decimal.js";
|
||||
@@ -35,11 +36,15 @@ export class SubscriptionsService {
|
||||
@InjectQueue(SUBSCRIPTIONS.PROVISIONING_QUEUE_NAME) private readonly provisioningQueue: Queue,
|
||||
private readonly subscriptionsPlanRepository: SubscriptionsPlanRepository,
|
||||
private readonly userSubscriptionsRepository: UserSubscriptionsRepository,
|
||||
private readonly invoicesService: InvoicesService,
|
||||
private readonly moduleRef: ModuleRef,
|
||||
private readonly usersService: UsersService,
|
||||
private readonly danakServices: DanakServicesService,
|
||||
private readonly dataSource: DataSource,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
private get invoicesService(): InvoicesService {
|
||||
return this.moduleRef.get(InvoicesService, { strict: false });
|
||||
}
|
||||
|
||||
//************************************ */
|
||||
async createSubscriptionsPlan(createDto: AddSubscriptionsToServiceDto) {
|
||||
@@ -361,6 +366,98 @@ export class SubscriptionsService {
|
||||
}
|
||||
}
|
||||
|
||||
//************************************ */
|
||||
async upgradeSubscription(userSubscriptionId: string, planId: string, userId: string) {
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
|
||||
try {
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
const userSubscription = await queryRunner.manager.findOne(UserSubscription, {
|
||||
where: { id: userSubscriptionId, user: { id: userId } },
|
||||
relations: { plan: true }
|
||||
});
|
||||
if (!userSubscription) throw new BadRequestException(SubscriptionMessage.USER_SUBS_NOT_FOUND);
|
||||
|
||||
const newPlan = await this.subscriptionsPlanRepository.findOneBy({ id: planId });
|
||||
if (!newPlan) throw new BadRequestException(SubscriptionMessage.PLAN_NOT_FOUND);
|
||||
|
||||
if (userSubscription.plan.service.id !== newPlan.service.id) {
|
||||
throw new BadRequestException(SubscriptionMessage.SERVICE_MISMATCH);
|
||||
}
|
||||
|
||||
// Validate that new plan is more expensive than current plan
|
||||
if (new Decimal(newPlan.price).lessThanOrEqualTo(userSubscription.plan.price)) {
|
||||
throw new BadRequestException(SubscriptionMessage.UPGRADE_TO_LOWER_OR_EQUAL_PLAN_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
// Calculate remaining days in current subscription
|
||||
const today = dayjs();
|
||||
const endDate = dayjs(userSubscription.endDate);
|
||||
const remainingDays = Math.max(0, endDate.diff(today, 'day'));
|
||||
|
||||
if (remainingDays <= 0) {
|
||||
throw new BadRequestException(SubscriptionMessage.SUBSCRIPTION_EXPIRED_CANNOT_UPGRADE);
|
||||
}
|
||||
|
||||
// Calculate daily rates
|
||||
const currentPlanDuration = userSubscription.plan.duration;
|
||||
const newPlanDuration = newPlan.duration;
|
||||
|
||||
const currentDailyRate = new Decimal(userSubscription.plan.price).div(currentPlanDuration);
|
||||
const newDailyRate = new Decimal(newPlan.price).div(newPlanDuration);
|
||||
|
||||
// Calculate price difference per day
|
||||
const dailyPriceDifference = newDailyRate.sub(currentDailyRate);
|
||||
|
||||
// Calculate prorated upgrade cost for remaining days
|
||||
const proratedUpgradeCost = dailyPriceDifference.mul(remainingDays);
|
||||
|
||||
// Ensure minimum charge amount
|
||||
const minimumCharge = new Decimal(1000); // 1000 IRR minimum
|
||||
const finalUpgradeCost = Decimal.max(proratedUpgradeCost, minimumCharge);
|
||||
|
||||
const user = await this.usersService.findOneByIdWithQueryRunner(userSubscription.user.id, queryRunner);
|
||||
|
||||
const invoiceDueDate = dayjs().add(INVOICE.DUEDATE, "day").toDate();
|
||||
|
||||
const invoice = await this.invoicesService.createInvoiceForSubscriptionUpgrade(
|
||||
user,
|
||||
newPlan,
|
||||
userSubscription,
|
||||
invoiceDueDate,
|
||||
queryRunner,
|
||||
finalUpgradeCost
|
||||
);
|
||||
|
||||
// Update the subscription to the new plan
|
||||
userSubscription.plan = newPlan;
|
||||
await queryRunner.manager.save(UserSubscription, userSubscription);
|
||||
|
||||
// Add provisioning job for the new plan
|
||||
await this.addProvisioningJob(userSubscription, newPlan, user);
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
return {
|
||||
message: SubscriptionMessage.INVOICE_CREATED_SUCCESSFULLY,
|
||||
userSubscription,
|
||||
invoice,
|
||||
upgradeDetails: {
|
||||
remainingDays,
|
||||
currentPlanPrice: userSubscription.plan.price,
|
||||
newPlanPrice: newPlan.price,
|
||||
proratedUpgradeCost: finalUpgradeCost.toNumber(),
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
//************************************ */
|
||||
async getServiceSubscriptions(serviceId: string, queryDto: ServiceSubsQueryDto) {
|
||||
const service = await this.danakServices.findServiceById(serviceId);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { ServiceSubsQueryDto } from "./DTO/service-subs-query.dto";
|
||||
import { ExtendUSerSubscribeServiceDto, SubscribeServiceDto } from "./DTO/subscribe-service.dto";
|
||||
import { SubscriptionAccessDto } from "./DTO/subscription-access-dto";
|
||||
import { UpdateSubscriptionPlanDto } from "./DTO/update-subscription.dto";
|
||||
import { UpgradeSubscriptionDto } from "./DTO/upgrade-subscription.dto";
|
||||
import { UserSubscriptionIdParamDto } from "./DTO/user-subscription-id.param.dto";
|
||||
import { SubscriptionsService } from "./providers/subscriptions.service";
|
||||
import { UserQuickAccessService } from "./providers/users-quick-access.service";
|
||||
@@ -90,6 +91,16 @@ export class SubscriptionsController {
|
||||
return this.subscriptionService.extendSubscribeToPlan(paramDto.userSubscriptionId, subscribeDto, userId);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Upgrade subscription plan ==> user route" })
|
||||
@Put(":userSubscriptionId/upgrade")
|
||||
upgradeSubscription(
|
||||
@Param() paramDto: UserSubscriptionIdParamDto,
|
||||
@Body() upgradeDto: UpgradeSubscriptionDto,
|
||||
@UserDec("id") userId: string,
|
||||
) {
|
||||
return this.subscriptionService.upgradeSubscription(paramDto.userSubscriptionId, upgradeDto.planId, userId);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "add quick access a service ==> user route" })
|
||||
@Post(":id/add-quick-access")
|
||||
addQuickAccess(@Param() paramDto: ParamDto, @UserDec("id") userId: string) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BullModule } from "@nestjs/bullmq";
|
||||
import { Module } from "@nestjs/common";
|
||||
import { forwardRef, Module } from "@nestjs/common";
|
||||
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||
|
||||
import { SUBSCRIPTIONS } from "./constants";
|
||||
@@ -24,10 +24,10 @@ import { UserQuickAccessRepository } from "./repositories/users-quick-access.rep
|
||||
name: SUBSCRIPTIONS.PROVISIONING_QUEUE_NAME,
|
||||
prefix: SUBSCRIPTIONS.PROVISIONING_QUEUE_PREFIX,
|
||||
}),
|
||||
forwardRef(() => InvoicesModule),
|
||||
DanakServicesModule,
|
||||
UsersModule,
|
||||
WalletsModule,
|
||||
InvoicesModule,
|
||||
],
|
||||
providers: [
|
||||
SubscriptionsService,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import * as request from "supertest";
|
||||
import request from "supertest";
|
||||
|
||||
import { AppModule } from "./../src/app.module";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user