feat: v3.4.12 ticket iteration
Refund rollback, winery T+3, multi withdraw, mini-user store detail, dev plan batch edit and WeCom dispatch, support ticket edit/attachments/batch status, package imageUrl. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -30,6 +30,7 @@ import {
|
||||
UpdateDevPlanSettingsDto,
|
||||
UpdateDevPlanTaskDto,
|
||||
UpdateDevPlanVersionDto,
|
||||
DevPlanTaskBatchUpdateDto,
|
||||
} from './dto/dev-plan.dto';
|
||||
|
||||
@Controller('admin/dev-plan')
|
||||
@@ -91,6 +92,12 @@ export class AdminDevPlanController {
|
||||
return this.service.dispatchTasks(body, account.id);
|
||||
}
|
||||
|
||||
@Post('tasks/batch-update')
|
||||
@HqOperation({ action: HqOperationAction.DEV_PLAN_TASK_UPDATE, refType: 'DEV_PLAN_TASK', includeBody: true, batch: true })
|
||||
batchUpdateTasks(@Body() body: DevPlanTaskBatchUpdateDto) {
|
||||
return this.service.batchUpdateTasks(body);
|
||||
}
|
||||
|
||||
@Get('versions')
|
||||
listVersions(
|
||||
@Query('status') status?: string,
|
||||
|
||||
@@ -48,6 +48,8 @@ import type {
|
||||
|
||||
DevPlanTaskDispatchDto,
|
||||
|
||||
DevPlanTaskBatchUpdateDto,
|
||||
|
||||
DevPlanTaskListQueryDto,
|
||||
|
||||
UpdateDevPlanSettingsDto,
|
||||
@@ -1009,6 +1011,100 @@ export class DevPlanService {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async appendVersionTasks(versionId: bigint, taskIds: string[]) {
|
||||
|
||||
const version = await this.prisma.devPlanVersion.findUnique({ where: { id: versionId } });
|
||||
|
||||
if (!version) throw new NotFoundException('版本不存在');
|
||||
|
||||
|
||||
|
||||
const ids = taskIds.map(BigInt);
|
||||
|
||||
const existing = await this.prisma.devPlanVersionTask.findMany({
|
||||
|
||||
where: { versionId, taskId: { in: ids } },
|
||||
|
||||
select: { taskId: true },
|
||||
|
||||
});
|
||||
|
||||
const linked = new Set(existing.map((row) => row.taskId.toString()));
|
||||
|
||||
const toAdd = ids.filter((id) => !linked.has(id.toString()));
|
||||
|
||||
if (!toAdd.length) return;
|
||||
|
||||
|
||||
|
||||
const maxSort = await this.prisma.devPlanVersionTask.aggregate({
|
||||
|
||||
where: { versionId },
|
||||
|
||||
_max: { sortOrder: true },
|
||||
|
||||
});
|
||||
|
||||
let sort = (maxSort._max.sortOrder ?? -1) + 1;
|
||||
|
||||
|
||||
|
||||
await this.prisma.devPlanVersionTask.createMany({
|
||||
|
||||
data: toAdd.map((taskId, index) => ({ versionId, taskId, sortOrder: sort + index })),
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
async batchUpdateTasks(dto: DevPlanTaskBatchUpdateDto) {
|
||||
|
||||
if (!dto.taskIds.length) throw new BadRequestException('请至少选择 1 条任务');
|
||||
|
||||
if (!dto.status && !dto.versionId) {
|
||||
|
||||
throw new BadRequestException('请至少指定状态或关联版本');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const taskIds = dto.taskIds.map(BigInt);
|
||||
|
||||
const tasks = await this.prisma.devPlanTask.findMany({ where: { id: { in: taskIds } } });
|
||||
|
||||
if (tasks.length !== taskIds.length) throw new BadRequestException('部分任务不存在');
|
||||
|
||||
|
||||
|
||||
if (dto.status) {
|
||||
|
||||
for (const task of tasks) {
|
||||
|
||||
await this.updateTask(task.id, { status: dto.status });
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (dto.versionId) {
|
||||
|
||||
await this.appendVersionTasks(BigInt(dto.versionId), dto.taskIds);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return { updated: taskIds.length };
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
import {
|
||||
ArrayMinSize,
|
||||
IsArray,
|
||||
IsIn,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateIf,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import { ArrayMinSize, IsArray, IsBoolean, IsIn, IsNotEmpty, IsOptional, IsString, ValidateIf, ValidateNested } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
DEV_PLAN_TASK_STATUSES,
|
||||
@@ -161,6 +152,29 @@ export class ReviewSupportTicketDto {
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => DevPlanTaskFromTicketDto)
|
||||
tasks?: DevPlanTaskFromTicketDto[];
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
dispatchToWecom?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
dispatchSupplement?: string;
|
||||
}
|
||||
|
||||
export class DevPlanTaskBatchUpdateDto {
|
||||
@IsArray()
|
||||
@ArrayMinSize(1)
|
||||
@IsString({ each: true })
|
||||
taskIds!: string[];
|
||||
|
||||
@IsOptional()
|
||||
@IsIn(DEV_PLAN_TASK_STATUSES)
|
||||
status?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
versionId?: string | null;
|
||||
}
|
||||
|
||||
export class BatchReviewPreviewDto {
|
||||
|
||||
Reference in New Issue
Block a user