import { Injectable, NotFoundException, ForbiddenException, Logger, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { PositionChange } from './position-change.entity'; import { CreatePositionChangeDto } from './dto/create-position-change.dto'; import { UpdatePositionChangeDto } from './dto/update-position-change.dto'; import { QueryPositionChangeDto } from './dto/query-position-change.dto'; import { PaginationInfo } from '@/common/dto/pagination.dto'; import { Position } from '../position/position.entity'; @Injectable() export class PositionChangeService { private readonly logger = new Logger(PositionChangeService.name); constructor( @InjectRepository(PositionChange) private readonly positionChangeRepository: Repository, @InjectRepository(Position) private readonly positionRepository: Repository, ) {} /** * 分页查询单个持仓的所有变更记录 */ async findAllByPositionId( positionId: number, userId: number, queryDto: QueryPositionChangeDto, ): Promise<{ list: PositionChange[]; pagination: PaginationInfo; }> { // 验证持仓是否属于当前用户 const position = await this.positionRepository.findOne({ where: { positionId, userId }, }); if (!position) { throw new NotFoundException(`持仓不存在:ID ${positionId}`); } // 分页参数 const page = queryDto.page || 1; const limit = queryDto.limit || 10; const skip = (page - 1) * limit; // 查询总数 const total = await this.positionChangeRepository.count({ where: { positionId }, }); // 查询分页数据(按变更日期和创建时间倒序) const list = await this.positionChangeRepository.find({ where: { positionId }, order: { changeDate: 'DESC', createdAt: 'DESC', }, skip, take: limit, }); // 计算总页数 const total_page = Math.ceil(total / limit); return { list, pagination: { total, total_page, page_size: limit, current_page: page, }, }; } /** * 创建持仓变更记录 */ async create( userId: number, createPositionChangeDto: CreatePositionChangeDto, ): Promise { // 验证持仓是否属于当前用户 const position = await this.positionRepository.findOne({ where: { positionId: createPositionChangeDto.positionId, userId, }, }); if (!position) { throw new NotFoundException( `持仓不存在:ID ${createPositionChangeDto.positionId}`, ); } // 创建变更记录 const positionChange = this.positionChangeRepository.create({ ...createPositionChangeDto, changeDate: new Date(createPositionChangeDto.changeDate), }); return this.positionChangeRepository.save(positionChange); } /** * 更新持仓变更记录的备注/思考 */ async update( changeId: number, userId: number, updatePositionChangeDto: UpdatePositionChangeDto, ): Promise { // 查找变更记录 const positionChange = await this.positionChangeRepository.findOne({ where: { changeId }, relations: [], // 不加载关联,后面手动验证 }); if (!positionChange) { throw new NotFoundException(`变更记录不存在:ID ${changeId}`); } // 验证持仓是否属于当前用户 const position = await this.positionRepository.findOne({ where: { positionId: positionChange.positionId, userId, }, }); if (!position) { throw new ForbiddenException('无权访问该持仓的变更记录'); } // 只更新备注字段 if (updatePositionChangeDto.notes !== undefined) { positionChange.notes = updatePositionChangeDto.notes; } return this.positionChangeRepository.save(positionChange); } }