feat: mask contact info for non-connected profiles and enable real-time Stripe subscription synchronization
This commit is contained in:
@@ -12,7 +12,7 @@ import {
|
|||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { UserRole } from '@prisma/client';
|
import { UserRole, SubscriptionStatus } from '@prisma/client';
|
||||||
import { StripeService } from './stripe.service';
|
import { StripeService } from './stripe.service';
|
||||||
import { SubscriptionService } from './subscription.service';
|
import { SubscriptionService } from './subscription.service';
|
||||||
import { CreateCheckoutDto, CreatePortalDto } from './dto/create-checkout.dto';
|
import { CreateCheckoutDto, CreatePortalDto } from './dto/create-checkout.dto';
|
||||||
@@ -94,28 +94,36 @@ export class StripeController {
|
|||||||
const subscription = await this.subscriptionService.getActivePlan(user.id);
|
const subscription = await this.subscriptionService.getActivePlan(user.id);
|
||||||
if (!subscription) return null;
|
if (!subscription) return null;
|
||||||
|
|
||||||
// Sync from Stripe if key fields are missing
|
// Always sync with Stripe to get latest state (cancel/uncancel, period changes)
|
||||||
if (
|
if (subscription.stripeSubscriptionId) {
|
||||||
subscription.stripeSubscriptionId &&
|
|
||||||
(!subscription.currentPeriodEnd ||
|
|
||||||
subscription.cancelAtPeriodEnd === null)
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
const stripeSub = await this.stripeService.getSubscription(
|
const stripeSub = await this.stripeService.getSubscription(
|
||||||
subscription.stripeSubscriptionId,
|
subscription.stripeSubscriptionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const statusMap: Record<string, SubscriptionStatus> = {
|
||||||
|
active: SubscriptionStatus.ACTIVE,
|
||||||
|
past_due: SubscriptionStatus.PAST_DUE,
|
||||||
|
canceled: SubscriptionStatus.CANCELED,
|
||||||
|
unpaid: SubscriptionStatus.UNPAID,
|
||||||
|
trialing: SubscriptionStatus.TRIALING,
|
||||||
|
incomplete: SubscriptionStatus.INCOMPLETE,
|
||||||
|
};
|
||||||
|
|
||||||
|
const stripeStatus = statusMap[stripeSub.status] || subscription.status;
|
||||||
|
const periodEnd = stripeSub.items?.data?.[0]?.current_period_end
|
||||||
|
|| (stripeSub as any).current_period_end;
|
||||||
|
|
||||||
const updated = await this.subscriptionService.updateSubscriptionStatus(
|
const updated = await this.subscriptionService.updateSubscriptionStatus(
|
||||||
subscription.stripeSubscriptionId,
|
subscription.stripeSubscriptionId,
|
||||||
subscription.status,
|
stripeStatus,
|
||||||
{
|
{
|
||||||
currentPeriodEnd: new Date(
|
currentPeriodEnd: new Date(periodEnd * 1000),
|
||||||
stripeSub.items.data[0].current_period_end * 1000,
|
|
||||||
),
|
|
||||||
cancelAtPeriodEnd: stripeSub.cancel_at_period_end,
|
cancelAtPeriodEnd: stripeSub.cancel_at_period_end,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return updated;
|
return updated;
|
||||||
} catch {
|
} catch (_err) {
|
||||||
// Fall through to return existing data
|
// Fall through to return existing data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user