feat(server): add membership CRUD methods to UserService

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
richarjiang
2026-04-07 09:42:42 +08:00
parent 867461f892
commit 0776bd8630

View File

@@ -2,6 +2,8 @@ import { Injectable, NotFoundException } from '@nestjs/common'
import { MembershipStatus, BookingStatus, UserRole, CardTypeCategory } from '@mp-pilates/shared'
import type { PaginatedData, UserProfileResponse, UserStatsResponse } from '@mp-pilates/shared'
import { PrismaService } from '../prisma/prisma.service'
import { Membership, CardType, Prisma } from '@prisma/client'
import { UpdateUserMembershipDto } from './dto/update-user-membership.dto'
const VALID_CARD_TYPES = new Set<string>(Object.values(CardTypeCategory))
@@ -226,4 +228,68 @@ export class UserService {
return { items, total, page, limit }
}
// ─── Membership management ────────────────────────────────────────────────
async getUserMembership(userId: string) {
const membership = await this.prisma.membership.findFirst({
where: { userId },
include: { cardType: true },
})
return membership ? { ...membership, cardType: { ...membership.cardType } } : null
}
async updateUserMembership(userId: string, dto: UpdateUserMembershipDto) {
const now = new Date()
const expireDate = new Date(dto.expireDate)
const remainingTimes = dto.remainingTimes ?? null
const isTimeBased = remainingTimes !== null
let status: MembershipStatus = MembershipStatus.ACTIVE
if (expireDate < now) {
status = MembershipStatus.EXPIRED
} else if (isTimeBased && remainingTimes <= 0) {
status = MembershipStatus.USED_UP
}
const existing = await this.prisma.membership.findFirst({ where: { userId } })
let membership: Membership & { cardType: CardType }
if (existing) {
const updated = await this.prisma.membership.update({
where: { id: existing.id },
data: {
cardTypeId: dto.cardTypeId,
remainingTimes: dto.remainingTimes ?? null,
startDate: new Date(dto.startDate),
expireDate: new Date(dto.expireDate),
status,
},
include: { cardType: true },
})
membership = { ...updated, cardType: { ...updated.cardType } }
} else {
const created = await this.prisma.membership.create({
data: {
userId,
cardTypeId: dto.cardTypeId,
remainingTimes: dto.remainingTimes ?? null,
startDate: new Date(dto.startDate),
expireDate: new Date(dto.expireDate),
status,
},
include: { cardType: true },
})
membership = { ...created, cardType: { ...created.cardType } }
}
return membership
}
async deleteUserMembership(userId: string): Promise<void> {
await this.prisma.membership.updateMany({
where: { userId },
data: { status: MembershipStatus.EXPIRED },
})
}
}