improvement: treatments UI/UX updated again to minimize clicking and scrolling.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Patch,
|
||||
@@ -92,6 +93,13 @@ export class CasesController {
|
||||
return this.casesService.startInternal(id, organizationId, req.user.id, req.user.language);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@ApiOperation({ summary: 'Delete an unstarted lab-origin draft (TAB_CASES_EDIT)' })
|
||||
deleteDraft(@Param('id') id: string, @Req() req) {
|
||||
const organizationId = this.casesService.getOrganizationIdFromUser(req.user);
|
||||
return this.casesService.deleteInternalDraft(id, organizationId, req.user.id);
|
||||
}
|
||||
|
||||
@Post(':id/lines/:lineClientKey/attachments')
|
||||
@ApiOperation({ summary: 'Upload attachments for a lab-origin draft line' })
|
||||
@ApiConsumes('multipart/form-data')
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { AppException, ErrorCode } from '../../common/errors';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { createReadStream, existsSync, mkdirSync } from 'fs';
|
||||
import { createReadStream, existsSync, mkdirSync, unlinkSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { CatalogEntityKind, LabCaseActivityType, LabCaseOrigin, LabTaskStatus, LinkStatus, Prisma, UserNotificationType } from '@prisma/client';
|
||||
import { PrismaService } from '../../../prisma/prisma.service';
|
||||
@@ -565,6 +565,56 @@ export class CasesService {
|
||||
return { success: true, data: await this.mapLabCaseDetail(refreshed, localeInput) };
|
||||
}
|
||||
|
||||
async deleteInternalDraft(
|
||||
labCaseId: string,
|
||||
labOrganizationId: string,
|
||||
actorUserId: string,
|
||||
) {
|
||||
await this.assertCanEditCases(actorUserId, labOrganizationId);
|
||||
const existing = await this.prisma.labCase.findFirst({
|
||||
where: {
|
||||
id: labCaseId,
|
||||
origin: LabCaseOrigin.LAB_INTERNAL,
|
||||
destinationOrganizationId: labOrganizationId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
startedAt: true,
|
||||
attachments: { include: { attachment: { select: { id: true, storagePath: true } } } },
|
||||
},
|
||||
});
|
||||
if (!existing) {
|
||||
throw new AppException(ErrorCode.CASE_NOT_FOUND, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
if (existing.startedAt) {
|
||||
throw new AppException(ErrorCode.LAB_CASE_ALREADY_STARTED, HttpStatus.CONFLICT);
|
||||
}
|
||||
|
||||
const orphanAttachments = existing.attachments.map((row) => row.attachment);
|
||||
const orphanIds = orphanAttachments.map((row) => row.id);
|
||||
|
||||
await this.prisma.$transaction(async (tx) => {
|
||||
await tx.labCase.delete({ where: { id: labCaseId } });
|
||||
if (orphanIds.length > 0) {
|
||||
await tx.treatmentDetailAttachment.deleteMany({
|
||||
where: { id: { in: orphanIds }, detailId: null },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
for (const attachment of orphanAttachments) {
|
||||
try {
|
||||
if (attachment.storagePath && existsSync(attachment.storagePath)) {
|
||||
unlinkSync(attachment.storagePath);
|
||||
}
|
||||
} catch {
|
||||
// Best-effort disk cleanup; the draft row is already gone.
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async uploadInternalAttachments(
|
||||
labCaseId: string,
|
||||
lineClientKey: string,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
ArrayMinSize,
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsDateString,
|
||||
@@ -61,7 +60,6 @@ export class SaveTreatmentDetailDto {
|
||||
|
||||
export class SaveTreatmentDraftDto {
|
||||
@IsArray()
|
||||
@ArrayMinSize(1)
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => SaveTreatmentDetailDto)
|
||||
details: SaveTreatmentDetailDto[];
|
||||
|
||||
Reference in New Issue
Block a user