fix : extend and upgrade user subscription

This commit is contained in:
2026-02-01 11:54:51 +03:30
parent 3a80ce021d
commit 0ba027d4e3
7 changed files with 110 additions and 56 deletions
@@ -29,6 +29,7 @@ import { SubscriptionStatus } from "../enums/subscription-status.enum";
import { IBusinessProvisioningJob } from "../interfaces/IProvisioning-job-data";
import { SubscriptionsPlanRepository } from "../repositories/subscriptions.repository";
import { UserSubscriptionsRepository } from "../repositories/user-subscriptions.repository";
import { InvoicePurpose } from "../../invoices/interfaces/external-invoice.interface";
@Injectable()
export class SubscriptionsService {
@@ -308,7 +309,7 @@ export class SubscriptionsService {
await queryRunner.manager.save(UserSubscription, userSubscription);
const invoiceDueDate = dayjs(userSubscription.startDate).add(INVOICE.DUEDATE, "day").toDate();
const invoice = await this.invoicesService.createInvoiceForSubscription(user, plan, userSubscription, invoiceDueDate, queryRunner);
const invoice = await this.invoicesService.createInvoiceForSubscription(user, plan, userSubscription, invoiceDueDate, queryRunner,InvoicePurpose.NEW);
userSubscription.status = SubscriptionStatus.INACTIVE;
await queryRunner.manager.save(UserSubscription, userSubscription);
@@ -334,7 +335,7 @@ export class SubscriptionsService {
}
//************************************ */
async extendSubscribeToPlan(userSubscriptionId: string, dto: ExtendUSerSubscribeServiceDto, userId: string) {
async renewUserSubscription(userSubscriptionId: string, dto: ExtendUSerSubscribeServiceDto, userId: string) {
const queryRunner = this.dataSource.createQueryRunner();
try {
@@ -366,11 +367,11 @@ export class SubscriptionsService {
const invoiceDueDate = dayjs().add(INVOICE.DUEDATE, "day").toDate();
const invoice = await this.invoicesService.createInvoiceForSubscription(user, plan, userSubscription, invoiceDueDate, queryRunner);
const invoice = await this.invoicesService.createInvoiceForSubscription(user, plan, userSubscription, invoiceDueDate, queryRunner,InvoicePurpose.RENEW);
userSubscription.plan = plan;
// userSubscription.plan = plan;
await queryRunner.manager.save(userSubscription);
// await queryRunner.manager.save(userSubscription);
await this.addProvisioningJob(userSubscription, plan, user);
@@ -415,28 +416,28 @@ export class SubscriptionsService {
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);
}
// Validate that new plan is more expensive than current plan
if (new Decimal(newPlan.price).lessThanOrEqualTo(userSubscription.plan.price)) {
if (new Decimal(newPlan.price).lessThan(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'));
const currentPlanRemainingDays = 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')})`);
console.log(`📅 Remaining days: ${currentPlanRemainingDays} (endDate: ${endDate.format('YYYY-MM-DD')}, today: ${today.format('YYYY-MM-DD')})`);
if (remainingDays <= 0) {
if (currentPlanRemainingDays <= 0) {
throw new BadRequestException(SubscriptionMessage.SUBSCRIPTION_EXPIRED_CANNOT_UPGRADE);
}
const remainingDays = newPlan.duration - currentPlanRemainingDays
// Calculate daily rates
const currentPlanDuration = userSubscription.plan.duration;
const newPlanDuration = newPlan.duration;
@@ -451,13 +452,13 @@ export class SubscriptionsService {
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`);
const proratedUpgradeCost = dailyPriceDifference.mul(currentPlanRemainingDays).add(newDailyRate.mul(remainingDays))
console.log(`🧮 Prorated upgrade cost: ${dailyPriceDifference.toNumber()} IRR/day × ${currentPlanRemainingDays} 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 finalUpgradeCost = + Decimal.max(proratedUpgradeCost, minimumCharge).toNumber().toFixed(0)
console.log(`✅ Final upgrade cost: max(${proratedUpgradeCost.toNumber()} IRR, ${minimumCharge.toNumber()} IRR minimum) = ${finalUpgradeCost} IRR`);
const user = await this.usersService.findOneByIdWithQueryRunner(userSubscription.user.id, queryRunner);
@@ -473,8 +474,8 @@ export class SubscriptionsService {
);
// Update the subscription to the new plan
userSubscription.plan = newPlan;
await queryRunner.manager.save(UserSubscription, userSubscription);
// userSubscription.plan = newPlan;
// await queryRunner.manager.save(UserSubscription, userSubscription);
// Add provisioning job for the new plan
await this.addProvisioningJob(userSubscription, newPlan, user);
@@ -485,10 +486,10 @@ export class SubscriptionsService {
userSubscription,
invoice,
upgradeDetails: {
remainingDays,
remainingDays: currentPlanRemainingDays,
currentPlanPrice: userSubscription.plan.price,
newPlanPrice: newPlan.price,
proratedUpgradeCost: finalUpgradeCost.toNumber(),
proratedUpgradeCost: finalUpgradeCost,
},
};
} catch (error) {
@@ -639,7 +640,7 @@ export class SubscriptionsService {
.leftJoinAndSelect("userSubscription.user", "user")
.leftJoinAndSelect("userSubscription.plan", "plan")
.leftJoin("plan.service", "service")
.addSelect(["service.name", "service.title"]);
.addSelect(["service.name", "service.title"]);
if (queryDto.q) {
queryBuilder.andWhere(