improvement: task assignment flow added. cases and tasks feature updated accordingly.

This commit is contained in:
2026-07-13 15:47:32 +03:30
parent 0d073f1ec0
commit a391eee15f
21 changed files with 357 additions and 35 deletions

View File

@@ -81,6 +81,12 @@ export class ListLabTasksDto {
@IsUUID()
labCaseId?: string;
/** When true, only tasks assigned to the current user. */
@IsOptional()
@Transform(toBoolean)
@IsBoolean()
assignedToMe?: boolean;
@IsOptional()
@IsIn(['date', 'status', 'clinic', 'patient', 'important', 'prosthesis', 'taskType'])
sortBy?: TaskSortField;
@@ -147,6 +153,12 @@ export class LocateTaskPageDto {
@IsString()
stepCompleted?: string;
/** When true, only tasks assigned to the current user. */
@IsOptional()
@Transform(toBoolean)
@IsBoolean()
assignedToMe?: boolean;
@IsOptional()
@IsIn(['date', 'status', 'clinic', 'patient', 'important', 'prosthesis', 'taskType'])
sortBy?: TaskSortField;

View File

@@ -17,6 +17,7 @@ import { hasEffectivePermission } from '../../common/membership-permissions';
const taskListInclude = {
lastStatusChangedBy: { select: { id: true, name: true } },
assignee: { select: { id: true, name: true } },
labCase: {
include: {
treatment: {
@@ -55,7 +56,7 @@ export class TasksService {
const limit = Math.min(Math.max(query.limit ?? 50, 1), 100);
const skip = (page - 1) * limit;
const where = await this.buildListWhere(labOrganizationId, query);
const where = await this.buildListWhere(labOrganizationId, actorUserId, query);
const [items, total] = await Promise.all([
this.prisma.labCaseTask.findMany({
@@ -117,7 +118,7 @@ export class TasksService {
throw new NotFoundException('Task not found');
}
const where = await this.buildListWhere(labOrganizationId, listQuery);
const where = await this.buildListWhere(labOrganizationId, actorUserId, listQuery);
const inFilteredSet = await this.prisma.labCaseTask.count({
where: { AND: [where, { id: query.taskId }] },
});
@@ -176,6 +177,10 @@ export class TasksService {
throw new NotFoundException('Task not found');
}
if (task.assigneeUserId && task.assigneeUserId !== actorUserId) {
throw new ForbiddenException('This task is assigned to another staff member');
}
const updated = await this.prisma.$transaction(async (tx) => {
const result = await tx.labCaseTask.update({
where: { id: taskId },
@@ -263,6 +268,7 @@ export class TasksService {
private async buildListWhere(
labOrganizationId: string,
actorUserId: string,
query: ListLabTasksDto,
): Promise<Prisma.LabCaseTaskWhereInput> {
const sentAtFilter: Prisma.DateTimeNullableFilter = { not: null };
@@ -306,6 +312,7 @@ export class TasksService {
...(query.labCaseId ? { labCaseId: query.labCaseId } : {}),
labCase: labCaseScope,
...(status !== undefined ? { status } : {}),
...(query.assignedToMe ? { assigneeUserId: actorUserId } : {}),
};
const stepCompleted = query.stepCompleted?.trim();
@@ -327,12 +334,16 @@ export class TasksService {
}
return {
...base,
OR: completedGroups.map((group) => ({
labCaseId: group.labCaseId,
treatmentDetailId: group.treatmentDetailId,
prosthesisTypeCode: group.prosthesisTypeCode,
})),
AND: [
base,
{
OR: completedGroups.map((group) => ({
labCaseId: group.labCaseId,
treatmentDetailId: group.treatmentDetailId,
prosthesisTypeCode: group.prosthesisTypeCode,
})),
},
],
};
}
@@ -348,6 +359,7 @@ export class TasksService {
sentFrom: query.sentFrom,
sentTo: query.sentTo,
stepCompleted: query.stepCompleted,
assignedToMe: query.assignedToMe,
sortBy: query.sortBy,
sortDir: query.sortDir,
limit: query.limit,
@@ -527,6 +539,10 @@ export class TasksService {
stepLabel: task.stepLabel,
status: task.status,
isImportant: task.labCase.isImportant,
assignee: task.assignee
? { id: task.assignee.id, name: task.assignee.name }
: null,
assignedAt: task.assignedAt?.toISOString() ?? null,
lastStatusChangedAt: task.lastStatusChangedAt?.toISOString() ?? null,
lastStatusChangedBy: task.lastStatusChangedBy
? { id: task.lastStatusChangedBy.id, name: task.lastStatusChangedBy.name }