From 24d990592db7623f15ef8c1d7a83b701b056ea41 Mon Sep 17 00:00:00 2001 From: Abdalhamid Alhamad Date: Thu, 12 Dec 2024 15:22:04 +0300 Subject: [PATCH] fix: fix tasks submission journey --- src/task/controllers/task.controller.ts | 1 + src/task/dtos/response/index.ts | 1 + .../task-submission-details.response.dto.ts | 18 ++++++++++++++++++ src/task/dtos/response/task.response.dto.ts | 10 +++++++--- src/task/repositories/task.repository.ts | 13 +++++++------ src/task/services/task.service.ts | 18 ++++++++++++++---- 6 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 src/task/dtos/response/task-submission-details.response.dto.ts diff --git a/src/task/controllers/task.controller.ts b/src/task/controllers/task.controller.ts index 715bf3c..5cac142 100644 --- a/src/task/controllers/task.controller.ts +++ b/src/task/controllers/task.controller.ts @@ -23,6 +23,7 @@ export class TaskController { @AllowedRoles(Roles.GUARDIAN) async createTask(@AuthenticatedUser() { sub }: IJwtPayload, @Body() body: CreateTaskRequestDto) { const task = await this.taskService.createTask(sub, body); + console.log(task.dueDate); return ResponseFactory.data(new TaskResponseDto(task)); } diff --git a/src/task/dtos/response/index.ts b/src/task/dtos/response/index.ts index 9eedc94..891389e 100644 --- a/src/task/dtos/response/index.ts +++ b/src/task/dtos/response/index.ts @@ -1 +1,2 @@ +export * from './task-submission-details.response.dto'; export * from './task.response.dto'; diff --git a/src/task/dtos/response/task-submission-details.response.dto.ts b/src/task/dtos/response/task-submission-details.response.dto.ts new file mode 100644 index 0000000..6ec3e93 --- /dev/null +++ b/src/task/dtos/response/task-submission-details.response.dto.ts @@ -0,0 +1,18 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { DocumentMetaResponseDto } from '~/document/dtos/response'; +import { TaskSubmission } from '~/task/entities/task-submissions.entity'; + +export class TaskSubmissionDetailsResponsetDto { + @ApiProperty() + submittedAt!: Date; + + @ApiProperty({ type: DocumentMetaResponseDto }) + proofOfCompletion!: DocumentMetaResponseDto | null; + + constructor(taskSubmission: TaskSubmission) { + this.submittedAt = taskSubmission.submittedAt; + this.proofOfCompletion = taskSubmission.proofOfCompletion + ? new DocumentMetaResponseDto(taskSubmission.proofOfCompletion) + : null; + } +} diff --git a/src/task/dtos/response/task.response.dto.ts b/src/task/dtos/response/task.response.dto.ts index 5135aeb..0fcb104 100644 --- a/src/task/dtos/response/task.response.dto.ts +++ b/src/task/dtos/response/task.response.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { DocumentMetaResponseDto } from '~/document/dtos/response'; import { JuniorResponseDto } from '~/junior/dtos/response'; import { Task } from '~/task/entities'; -import { TaskSubmission } from '~/task/entities/task-submissions.entity'; +import { TaskSubmissionDetailsResponsetDto } from './task-submission-details.response.dto'; export class TaskResponseDto { @ApiProperty() @@ -24,7 +24,10 @@ export class TaskResponseDto { rewardAmount!: number; @ApiProperty() - submission?: TaskSubmission; + isProofRequired!: boolean; + + @ApiProperty() + submission?: TaskSubmissionDetailsResponsetDto | null; @ApiProperty() junior!: JuniorResponseDto; @@ -45,7 +48,8 @@ export class TaskResponseDto { this.status = task.status; this.dueDate = task.dueDate; this.rewardAmount = task.rewardAmount; - this.submission = task.submission; + this.isProofRequired = task.isProofRequired; + this.submission = task.submission ? new TaskSubmissionDetailsResponsetDto(task.submission) : null; this.image = new DocumentMetaResponseDto(task.image); this.junior = new JuniorResponseDto(task.assignedTo); this.createdAt = task.createdAt; diff --git a/src/task/repositories/task.repository.ts b/src/task/repositories/task.repository.ts index e9be0c2..a80a102 100644 --- a/src/task/repositories/task.repository.ts +++ b/src/task/repositories/task.repository.ts @@ -36,9 +36,9 @@ export class TaskRepository { 'image', 'assignedTo', 'assignedTo.customer', - 'assignedTo.customer.user', - 'assignedTo.customer.user.profilePicture', + 'assignedTo.customer.profilePicture', 'submission', + 'submission.proofOfCompletion', ], }); } @@ -50,9 +50,9 @@ export class TaskRepository { .leftJoinAndSelect('task.image', 'image') .leftJoinAndSelect('task.assignedTo', 'assignedTo') .leftJoinAndSelect('assignedTo.customer', 'customer') - .leftJoinAndSelect('customer.user', 'user') - .leftJoinAndSelect('user.profilePicture', 'profilePicture') - .leftJoinAndSelect('task.submission', 'submission'); + .leftJoinAndSelect('customer.profilePicture', 'profilePicture') + .leftJoinAndSelect('task.submission', 'submission') + .leftJoinAndSelect('submission.proofOfCompletion', 'proofOfCompletion'); if (roles.includes(Roles.GUARDIAN)) { queryBuilder.where('task.assignedById = :userId', { userId }); @@ -90,11 +90,12 @@ export class TaskRepository { createSubmission(task: Task, body: TaskSubmissionRequestDto) { const submission = task.submission || new TaskSubmission(); - submission.status = SubmissionStatus.PENDING; + submission.status = task.isProofRequired ? SubmissionStatus.PENDING : SubmissionStatus.APPROVED; submission.submittedAt = new Date(); submission.taskId = task.id; submission.proofOfCompletionId = body.imageId; + task.submission = submission; return task.save(); } diff --git a/src/task/services/task.service.ts b/src/task/services/task.service.ts index d2caa1c..c9d2a45 100644 --- a/src/task/services/task.service.ts +++ b/src/task/services/task.service.ts @@ -1,4 +1,5 @@ import { BadRequestException, Injectable } from '@nestjs/common'; +import moment from 'moment'; import { FindOptionsWhere } from 'typeorm'; import { IJwtPayload } from '~/auth/interfaces'; import { OciService } from '~/document/services'; @@ -11,6 +12,13 @@ import { TaskRepository } from '../repositories'; export class TaskService { constructor(private readonly taskRepository: TaskRepository, private readonly ociService: OciService) {} async createTask(userId: string, body: CreateTaskRequestDto) { + if (moment(body.dueDate).isBefore(moment(body.startDate))) { + throw new BadRequestException('TASK.DUE_DATE_BEFORE_START_DATE'); + } + + if (moment(body.dueDate).isBefore(moment())) { + throw new BadRequestException('TASK.DUE_DATE_IN_PAST'); + } const task = await this.taskRepository.createTask(userId, body); return this.findTask({ id: task.id }); } @@ -22,12 +30,14 @@ export class TaskService { throw new BadRequestException('TASK.NOT_FOUND'); } + await this.prepareTasksPictures([task]); + return task; } async findTasks(user: IJwtPayload, query: TasksFilterOptions): Promise<[Task[], number]> { const [tasks, count] = await this.taskRepository.findTasks(user, query); - + console.log(tasks); await this.prepareTasksPictures(tasks); return [tasks, count]; @@ -53,7 +63,7 @@ export class TaskService { throw new BadRequestException('TASK.NO_SUBMISSION'); } - if (task.submission.status !== SubmissionStatus.PENDING) { + if (task.submission.status == SubmissionStatus.APPROVED) { throw new BadRequestException('TASK.SUBMISSION_ALREADY_REVIEWED'); } @@ -67,7 +77,7 @@ export class TaskService { throw new BadRequestException('TASK.NO_SUBMISSION'); } - if (task.submission.status !== SubmissionStatus.PENDING) { + if (task.submission.status == SubmissionStatus.REJECTED) { throw new BadRequestException('TASK.SUBMISSION_ALREADY_REVIEWED'); } @@ -85,7 +95,7 @@ export class TaskService { task.image.url = imageUrl; - if (task.submission) { + if (task.submission?.proofOfCompletion) { task.submission.proofOfCompletion.url = submissionUrl; }