api-server/src/modules/users/users.service.ts

95 lines
3.3 KiB
TypeScript
Raw Normal View History

import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common';
import { UsersRepository } from './users.repository';
import { PrismaService } from '../../infrastructure/database/prisma.service';
const DELETION_COOLING_DAYS = 7;
@Injectable()
export class UsersService {
constructor(
private readonly usersRepository: UsersRepository,
private readonly prisma: PrismaService,
) {}
async getProfile(userId: string) { return this.usersRepository.findProfileByUserId(userId); }
async updateProfile(userId: string, dto: any) { return this.usersRepository.updateProfile(userId, dto); }
async getProfileDetail(userId: string) { return this.usersRepository.findUserProfile(userId); }
async updateProfileDetail(userId: string, dto: any) { return this.usersRepository.upsertUserProfile(userId, dto); }
async updatePreferences(userId: string, dto: any) { return this.usersRepository.updatePreferences(userId, dto); }
// ── Membership ──
async getMembership(userId: string) {
return this.prisma.userMembership.findFirst({
where: { userId, active: true },
include: { plan: true },
orderBy: { createdAt: 'desc' },
});
}
// ── Account Deletion ──
async requestDeletion(userId: string) {
const existing = await this.prisma.accountDeletionRequest.findFirst({
where: { userId, status: 'pending' },
});
if (existing) throw new BadRequestException('已有进行中的注销申请');
const coolingEndsAt = new Date(Date.now() + DELETION_COOLING_DAYS * 86400000);
return this.prisma.accountDeletionRequest.create({
data: { userId, coolingEndsAt },
});
}
async cancelDeletion(userId: string) {
const req = await this.prisma.accountDeletionRequest.findFirst({
where: { userId, status: 'pending' },
});
if (!req) throw new NotFoundException('未找到进行中的注销申请');
return this.prisma.accountDeletionRequest.update({
where: { id: req.id },
data: { status: 'cancelled', cancelledAt: new Date() },
});
}
// ── Device Management ──
async getDevices(userId: string) {
return this.prisma.userDevice.findMany({
where: { userId },
orderBy: { lastSeenAt: 'desc' },
});
}
async removeDevice(userId: string, deviceId: string) {
await this.prisma.userDevice.deleteMany({
where: { userId, deviceId },
});
return { success: true };
}
// ── Storage ──
async getStorage(userId: string) {
const files = await this.prisma.uploadedFile.findMany({
where: { userId },
select: { sizeBytes: true, mimeType: true },
});
const usedBytes = files.reduce((sum, f) => sum + Number(f.sizeBytes), 0);
const totalBytes = 1024 * 1024 * 1024; // 1GB hardcoded for now
return { totalBytes, usedBytes, fileCount: files.length };
}
// ── Assets Summary ──
async getAssetsSummary(userId: string) {
const [kbCount, itemCount, cardCount] = await Promise.all([
this.prisma.knowledgeBase.count({ where: { userId, deletedAt: null } }),
this.prisma.knowledgeItem.count({ where: { userId, deletedAt: null } }),
this.prisma.reviewCard.count({ where: { userId } }),
]);
return { knowledgeBaseCount: kbCount, knowledgeItemCount: itemCount, reviewCardCount: cardCount };
}
}