From 6732de80662c690a67e640a96d67175f0b2f2e2c Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Tue, 6 Jan 2026 08:53:13 +0330 Subject: [PATCH] subscription:upgrade --- .../providers/subscriptions.service.ts | 62 +++++++++++++++---- .../repositories/subscriptions.repository.ts | 7 +++ .../subscriptions/subscriptions.module.ts | 2 + 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/modules/subscriptions/providers/subscriptions.service.ts b/src/modules/subscriptions/providers/subscriptions.service.ts index e7c9b0f..40cf017 100755 --- a/src/modules/subscriptions/providers/subscriptions.service.ts +++ b/src/modules/subscriptions/providers/subscriptions.service.ts @@ -9,6 +9,7 @@ import { DataSource, In, Not, QueryRunner } from "typeorm"; import { ServiceMessage, SubscriptionMessage } from "../../../common/enums/message.enum"; import { DanakServicesService } from "../../danak-services/providers/danak-services.service"; +import { RestaurantService } from "../../dmenu/providers/restaurant.service"; import { INVOICE } from "../../invoices/constants"; import { InvoicesService } from "../../invoices/providers/invoices.service"; import { User } from "../../users/entities/user.entity"; @@ -47,18 +48,31 @@ export class SubscriptionsService { return this.moduleRef.get(InvoicesService, { strict: false }); } + private get restaurantService(): RestaurantService { + return this.moduleRef.get(RestaurantService, { strict: false }); + } + //************************************ */ async createSubscriptionsPlan(createDto: AddSubscriptionsToServiceDto) { const danakService = await this.danakServices.findServiceById(createDto.serviceId); if (!danakService) throw new BadRequestException(ServiceMessage.SERVICE_NOT_FOUND_BY_ID); - const subscriptions = createDto.subs.map((sub) => ({ - ...sub, - service: { id: createDto.serviceId }, - price: sub.price < 100_000 ? new Decimal(0) : new Decimal(sub.price), - originalPrice: sub.price < 100_000 ? new Decimal(0) : new Decimal(sub.price), - isFree: sub.price < 100_000, - })); + const subscriptions = createDto.subs.map((sub) => { + const adjustedPrice = sub.price < 100_000 ? new Decimal(0) : new Decimal(sub.price); + const isFree = sub.price < 100_000; + if (isFree) { + console.log(`🎁 Plan "${sub.name}" marked as FREE (price ${sub.price} < 100,000 IRR)`); + } else { + console.log(`💰 Plan "${sub.name}" price: ${adjustedPrice.toNumber()} IRR`); + } + return { + ...sub, + service: { id: createDto.serviceId }, + price: adjustedPrice, + originalPrice: adjustedPrice, + isFree, + }; + }); const subscriptionNames = createDto.subs.map((sub) => sub.name); const existingSubscriptions = await this.subscriptionsPlanRepository.find({ @@ -143,8 +157,15 @@ export class SubscriptionsService { if (updateDto.duration) subscription.duration = updateDto.duration; if (updateDto.price) { - subscription.price = updateDto.price < 100_000 ? new Decimal(0) : new Decimal(updateDto.price); - subscription.originalPrice = updateDto.price < 100_000 ? new Decimal(0) : new Decimal(updateDto.price); + const adjustedPrice = updateDto.price < 100_000 ? new Decimal(0) : new Decimal(updateDto.price); + const isFree = updateDto.price < 100_000; + if (isFree) { + console.log(`🎁 Plan "${subscription.name}" updated to FREE (price ${updateDto.price} < 100,000 IRR)`); + } else { + console.log(`💰 Plan "${subscription.name}" price updated to: ${adjustedPrice.toNumber()} IRR`); + } + subscription.price = adjustedPrice; + subscription.originalPrice = adjustedPrice; } await this.subscriptionsPlanRepository.save({ @@ -377,13 +398,25 @@ export class SubscriptionsService { const userSubscription = await queryRunner.manager.findOne(UserSubscription, { where: { id: userSubscriptionId, user: { id: userId } }, - relations: { plan: true } + relations: { plan: { service: true }, user: true } }); if (!userSubscription) throw new BadRequestException(SubscriptionMessage.USER_SUBS_NOT_FOUND); - const newPlan = await this.subscriptionsPlanRepository.findOneBy({ id: planId }); + // Check if restaurant exists for dmenu service + if (userSubscription.plan.service.name.includes('دی منو')) { + try { + const rest = await this.restaurantService.getRestaurantSubscription(userSubscriptionId); + console.log('rest', rest) + } catch (error) { + throw new BadRequestException('Restaurant* not found for this subscription'); + } + } + + const newPlan = await this.subscriptionsPlanRepository.findById(planId); if (!newPlan) throw new BadRequestException(SubscriptionMessage.PLAN_NOT_FOUND); + console.log('new plan', newPlan.service.id) + console.log('userSubscription.plan.service.id',userSubscription.plan.service.id) if (userSubscription.plan.service.id !== newPlan.service.id) { throw new BadRequestException(SubscriptionMessage.SERVICE_MISMATCH); } @@ -397,6 +430,8 @@ export class SubscriptionsService { const today = dayjs(); const endDate = dayjs(userSubscription.endDate); const remainingDays = Math.max(0, endDate.diff(today, 'day')); + console.log('🔢 CALCULATION LOGS:'); + console.log(`📅 Remaining days: ${remainingDays} (endDate: ${endDate.format('YYYY-MM-DD')}, today: ${today.format('YYYY-MM-DD')})`); if (remainingDays <= 0) { throw new BadRequestException(SubscriptionMessage.SUBSCRIPTION_EXPIRED_CANNOT_UPGRADE); @@ -408,16 +443,21 @@ export class SubscriptionsService { const currentDailyRate = new Decimal(userSubscription.plan.price).div(currentPlanDuration); const newDailyRate = new Decimal(newPlan.price).div(newPlanDuration); + console.log(`💰 Current plan: ${userSubscription.plan.price} IRR for ${currentPlanDuration} days = ${currentDailyRate.toNumber()} IRR/day`); + console.log(`💰 New plan: ${newPlan.price} IRR for ${newPlanDuration} days = ${newDailyRate.toNumber()} IRR/day`); // Calculate price difference per day const dailyPriceDifference = newDailyRate.sub(currentDailyRate); + console.log(`📈 Daily price difference: ${dailyPriceDifference.toNumber()} IRR/day`); // Calculate prorated upgrade cost for remaining days const proratedUpgradeCost = dailyPriceDifference.mul(remainingDays); + console.log(`🧮 Prorated upgrade cost: ${dailyPriceDifference.toNumber()} IRR/day × ${remainingDays} days = ${proratedUpgradeCost.toNumber()} IRR`); // Ensure minimum charge amount const minimumCharge = new Decimal(1000); // 1000 IRR minimum const finalUpgradeCost = Decimal.max(proratedUpgradeCost, minimumCharge); + console.log(`✅ Final upgrade cost: max(${proratedUpgradeCost.toNumber()} IRR, ${minimumCharge.toNumber()} IRR minimum) = ${finalUpgradeCost.toNumber()} IRR`); const user = await this.usersService.findOneByIdWithQueryRunner(userSubscription.user.id, queryRunner); diff --git a/src/modules/subscriptions/repositories/subscriptions.repository.ts b/src/modules/subscriptions/repositories/subscriptions.repository.ts index 26972ec..5ce794b 100755 --- a/src/modules/subscriptions/repositories/subscriptions.repository.ts +++ b/src/modules/subscriptions/repositories/subscriptions.repository.ts @@ -13,4 +13,11 @@ export class SubscriptionsPlanRepository extends Repository { async findOneByName(name: string, id?: string): Promise { return this.findOneBy({ name, ...(id && { id: Not(id) }) }); } + + async findById(id: string): Promise { + return this.findOne({ + where: { id }, + relations: { service: true } + }); + } } diff --git a/src/modules/subscriptions/subscriptions.module.ts b/src/modules/subscriptions/subscriptions.module.ts index 2894805..95bd6e5 100755 --- a/src/modules/subscriptions/subscriptions.module.ts +++ b/src/modules/subscriptions/subscriptions.module.ts @@ -10,6 +10,7 @@ import { SubscriptionsPlanRepository } from "./repositories/subscriptions.reposi import { UserSubscriptionsRepository } from "./repositories/user-subscriptions.repository"; import { SubscriptionsController } from "./subscriptions.controller"; import { DanakServicesModule } from "../danak-services/danak-services.module"; +import { DmenuModule } from "../dmenu/dmenu.module"; import { InvoicesModule } from "../invoices/invoices.module"; import { UsersModule } from "../users/users.module"; import { WalletsModule } from "../wallets/wallets.module"; @@ -26,6 +27,7 @@ import { UserQuickAccessRepository } from "./repositories/users-quick-access.rep }), forwardRef(() => InvoicesModule), DanakServicesModule, + forwardRef(() => DmenuModule), UsersModule, WalletsModule, ],