fix: fix tasks submission journey

This commit is contained in:
Abdalhamid Alhamad
2024-12-12 15:22:04 +03:00
parent 5b7b7ff689
commit 24d990592d
6 changed files with 48 additions and 13 deletions

View File

@ -23,6 +23,7 @@ export class TaskController {
@AllowedRoles(Roles.GUARDIAN) @AllowedRoles(Roles.GUARDIAN)
async createTask(@AuthenticatedUser() { sub }: IJwtPayload, @Body() body: CreateTaskRequestDto) { async createTask(@AuthenticatedUser() { sub }: IJwtPayload, @Body() body: CreateTaskRequestDto) {
const task = await this.taskService.createTask(sub, body); const task = await this.taskService.createTask(sub, body);
console.log(task.dueDate);
return ResponseFactory.data(new TaskResponseDto(task)); return ResponseFactory.data(new TaskResponseDto(task));
} }

View File

@ -1 +1,2 @@
export * from './task-submission-details.response.dto';
export * from './task.response.dto'; export * from './task.response.dto';

View File

@ -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;
}
}

View File

@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger';
import { DocumentMetaResponseDto } from '~/document/dtos/response'; import { DocumentMetaResponseDto } from '~/document/dtos/response';
import { JuniorResponseDto } from '~/junior/dtos/response'; import { JuniorResponseDto } from '~/junior/dtos/response';
import { Task } from '~/task/entities'; import { Task } from '~/task/entities';
import { TaskSubmission } from '~/task/entities/task-submissions.entity'; import { TaskSubmissionDetailsResponsetDto } from './task-submission-details.response.dto';
export class TaskResponseDto { export class TaskResponseDto {
@ApiProperty() @ApiProperty()
@ -24,7 +24,10 @@ export class TaskResponseDto {
rewardAmount!: number; rewardAmount!: number;
@ApiProperty() @ApiProperty()
submission?: TaskSubmission; isProofRequired!: boolean;
@ApiProperty()
submission?: TaskSubmissionDetailsResponsetDto | null;
@ApiProperty() @ApiProperty()
junior!: JuniorResponseDto; junior!: JuniorResponseDto;
@ -45,7 +48,8 @@ export class TaskResponseDto {
this.status = task.status; this.status = task.status;
this.dueDate = task.dueDate; this.dueDate = task.dueDate;
this.rewardAmount = task.rewardAmount; 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.image = new DocumentMetaResponseDto(task.image);
this.junior = new JuniorResponseDto(task.assignedTo); this.junior = new JuniorResponseDto(task.assignedTo);
this.createdAt = task.createdAt; this.createdAt = task.createdAt;

View File

@ -36,9 +36,9 @@ export class TaskRepository {
'image', 'image',
'assignedTo', 'assignedTo',
'assignedTo.customer', 'assignedTo.customer',
'assignedTo.customer.user', 'assignedTo.customer.profilePicture',
'assignedTo.customer.user.profilePicture',
'submission', 'submission',
'submission.proofOfCompletion',
], ],
}); });
} }
@ -50,9 +50,9 @@ export class TaskRepository {
.leftJoinAndSelect('task.image', 'image') .leftJoinAndSelect('task.image', 'image')
.leftJoinAndSelect('task.assignedTo', 'assignedTo') .leftJoinAndSelect('task.assignedTo', 'assignedTo')
.leftJoinAndSelect('assignedTo.customer', 'customer') .leftJoinAndSelect('assignedTo.customer', 'customer')
.leftJoinAndSelect('customer.user', 'user') .leftJoinAndSelect('customer.profilePicture', 'profilePicture')
.leftJoinAndSelect('user.profilePicture', 'profilePicture') .leftJoinAndSelect('task.submission', 'submission')
.leftJoinAndSelect('task.submission', 'submission'); .leftJoinAndSelect('submission.proofOfCompletion', 'proofOfCompletion');
if (roles.includes(Roles.GUARDIAN)) { if (roles.includes(Roles.GUARDIAN)) {
queryBuilder.where('task.assignedById = :userId', { userId }); queryBuilder.where('task.assignedById = :userId', { userId });
@ -90,11 +90,12 @@ export class TaskRepository {
createSubmission(task: Task, body: TaskSubmissionRequestDto) { createSubmission(task: Task, body: TaskSubmissionRequestDto) {
const submission = task.submission || new TaskSubmission(); const submission = task.submission || new TaskSubmission();
submission.status = SubmissionStatus.PENDING; submission.status = task.isProofRequired ? SubmissionStatus.PENDING : SubmissionStatus.APPROVED;
submission.submittedAt = new Date(); submission.submittedAt = new Date();
submission.taskId = task.id; submission.taskId = task.id;
submission.proofOfCompletionId = body.imageId; submission.proofOfCompletionId = body.imageId;
task.submission = submission;
return task.save(); return task.save();
} }

View File

@ -1,4 +1,5 @@
import { BadRequestException, Injectable } from '@nestjs/common'; import { BadRequestException, Injectable } from '@nestjs/common';
import moment from 'moment';
import { FindOptionsWhere } from 'typeorm'; import { FindOptionsWhere } from 'typeorm';
import { IJwtPayload } from '~/auth/interfaces'; import { IJwtPayload } from '~/auth/interfaces';
import { OciService } from '~/document/services'; import { OciService } from '~/document/services';
@ -11,6 +12,13 @@ import { TaskRepository } from '../repositories';
export class TaskService { export class TaskService {
constructor(private readonly taskRepository: TaskRepository, private readonly ociService: OciService) {} constructor(private readonly taskRepository: TaskRepository, private readonly ociService: OciService) {}
async createTask(userId: string, body: CreateTaskRequestDto) { 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); const task = await this.taskRepository.createTask(userId, body);
return this.findTask({ id: task.id }); return this.findTask({ id: task.id });
} }
@ -22,12 +30,14 @@ export class TaskService {
throw new BadRequestException('TASK.NOT_FOUND'); throw new BadRequestException('TASK.NOT_FOUND');
} }
await this.prepareTasksPictures([task]);
return task; return task;
} }
async findTasks(user: IJwtPayload, query: TasksFilterOptions): Promise<[Task[], number]> { async findTasks(user: IJwtPayload, query: TasksFilterOptions): Promise<[Task[], number]> {
const [tasks, count] = await this.taskRepository.findTasks(user, query); const [tasks, count] = await this.taskRepository.findTasks(user, query);
console.log(tasks);
await this.prepareTasksPictures(tasks); await this.prepareTasksPictures(tasks);
return [tasks, count]; return [tasks, count];
@ -53,7 +63,7 @@ export class TaskService {
throw new BadRequestException('TASK.NO_SUBMISSION'); 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'); throw new BadRequestException('TASK.SUBMISSION_ALREADY_REVIEWED');
} }
@ -67,7 +77,7 @@ export class TaskService {
throw new BadRequestException('TASK.NO_SUBMISSION'); 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'); throw new BadRequestException('TASK.SUBMISSION_ALREADY_REVIEWED');
} }
@ -85,7 +95,7 @@ export class TaskService {
task.image.url = imageUrl; task.image.url = imageUrl;
if (task.submission) { if (task.submission?.proofOfCompletion) {
task.submission.proofOfCompletion.url = submissionUrl; task.submission.proofOfCompletion.url = submissionUrl;
} }