improvement: duedate added for shipped cases. cases and tasks ui and ux updated accordingly.

This commit is contained in:
2026-07-13 16:30:36 +03:30
parent a391eee15f
commit 08a1f34c4f
29 changed files with 502 additions and 30 deletions

View File

@@ -32,7 +32,8 @@ export type TaskSortField =
| 'patient'
| 'important'
| 'prosthesis'
| 'taskType';
| 'taskType'
| 'dueDate';
export class ListLabTasksDto {
@IsOptional()
@@ -87,8 +88,14 @@ export class ListLabTasksDto {
@IsBoolean()
assignedToMe?: boolean;
/** Past due date with at least one in-progress task on the case. */
@IsOptional()
@IsIn(['date', 'status', 'clinic', 'patient', 'important', 'prosthesis', 'taskType'])
@Transform(toBoolean)
@IsBoolean()
overdue?: boolean;
@IsOptional()
@IsIn(['date', 'status', 'clinic', 'patient', 'important', 'prosthesis', 'taskType', 'dueDate'])
sortBy?: TaskSortField;
@IsOptional()
@@ -159,8 +166,14 @@ export class LocateTaskPageDto {
@IsBoolean()
assignedToMe?: boolean;
/** Past due date with at least one in-progress task on the case. */
@IsOptional()
@IsIn(['date', 'status', 'clinic', 'patient', 'important', 'prosthesis', 'taskType'])
@Transform(toBoolean)
@IsBoolean()
overdue?: boolean;
@IsOptional()
@IsIn(['date', 'status', 'clinic', 'patient', 'important', 'prosthesis', 'taskType', 'dueDate'])
sortBy?: TaskSortField;
@IsOptional()

View File

@@ -12,6 +12,7 @@ import {
normalizeCatalogLocale,
} from '../catalog/catalog-label.service';
import { normalizeTaskTeeth } from '../cases/lab-case-task.util';
import { isLabCaseOverdue, startOfUtcDay } from '../../common/lab-case-due-date';
import { ListLabTasksDto, LocateTaskPageDto, UpdateLabTaskDto } from './dto/tasks.dto';
import { hasEffectivePermission } from '../../common/membership-permissions';
@@ -20,6 +21,7 @@ const taskListInclude = {
assignee: { select: { id: true, name: true } },
labCase: {
include: {
tasks: { select: { status: true } },
treatment: {
include: {
organization: { select: { id: true, name: true } },
@@ -310,7 +312,15 @@ export class TasksService {
const base: Prisma.LabCaseTaskWhereInput = {
...(query.labCaseId ? { labCaseId: query.labCaseId } : {}),
labCase: labCaseScope,
labCase: {
...labCaseScope,
...(query.overdue
? {
dueDate: { not: null, lt: startOfUtcDay() },
tasks: { some: { status: LabTaskStatus.IN_PROGRESS } },
}
: {}),
},
...(status !== undefined ? { status } : {}),
...(query.assignedToMe ? { assigneeUserId: actorUserId } : {}),
};
@@ -360,6 +370,7 @@ export class TasksService {
sentTo: query.sentTo,
stepCompleted: query.stepCompleted,
assignedToMe: query.assignedToMe,
overdue: query.overdue,
sortBy: query.sortBy,
sortDir: query.sortDir,
limit: query.limit,
@@ -501,6 +512,17 @@ export class TasksService {
...stepTiebreakers,
];
break;
case 'dueDate':
orderBy = [
{ labCase: { dueDate: dir } },
{ labCase: { sentAt: 'desc' } },
{ labCaseId: 'asc' },
{ treatmentDetailId: 'asc' },
{ prosthesisTypeCode: 'asc' },
{ stepOrder: 'asc' },
{ id: 'asc' },
];
break;
case 'date':
default:
orderBy = [
@@ -539,6 +561,8 @@ export class TasksService {
stepLabel: task.stepLabel,
status: task.status,
isImportant: task.labCase.isImportant,
caseDueDate: task.labCase.dueDate?.toISOString() ?? null,
isCaseOverdue: isLabCaseOverdue(task.labCase.dueDate, task.labCase.tasks),
assignee: task.assignee
? { id: task.assignee.id, name: task.assignee.name }
: null,