150 lines
4.4 KiB
TypeScript
150 lines
4.4 KiB
TypeScript
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<PositionChange>,
|
||
@InjectRepository(Position)
|
||
private readonly positionRepository: Repository<Position>,
|
||
) {}
|
||
|
||
/**
|
||
* 分页查询单个持仓的所有变更记录
|
||
*/
|
||
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<PositionChange> {
|
||
// 验证持仓是否属于当前用户
|
||
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<PositionChange> {
|
||
// 查找变更记录
|
||
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);
|
||
}
|
||
}
|