mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-11-26 00:24:54 +00:00
feat: soft delete junior
This commit is contained in:
@ -0,0 +1,13 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class AddDeletedAtColumnToJunior1757915357218 implements MigrationInterface {
|
||||||
|
name = 'AddDeletedAtColumnToJunior1757915357218';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "juniors" ADD "deleted_at" TIMESTAMP WITH TIME ZONE`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "juniors" DROP COLUMN "deleted_at"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,3 +3,4 @@ export * from './1754915164809-create-neoleap-related-entities';
|
|||||||
export * from './1754915164810-seed-default-avatar';
|
export * from './1754915164810-seed-default-avatar';
|
||||||
export * from './1757349525708-create-money-requests-table';
|
export * from './1757349525708-create-money-requests-table';
|
||||||
export * from './1757433339849-add-reservation-amount-to-account-entity';
|
export * from './1757433339849-add-reservation-amount-to-account-entity';
|
||||||
|
export * from './1757915357218-add-deleted-at-column-to-junior';
|
||||||
|
|||||||
@ -68,7 +68,8 @@
|
|||||||
"CIVIL_ID_REQUIRED": "مطلوب بطاقة الهوية المدنية.",
|
"CIVIL_ID_REQUIRED": "مطلوب بطاقة الهوية المدنية.",
|
||||||
"CIVIL_ID_NOT_CREATED_BY_GUARDIAN": "تم تحميل بطاقة الهوية المدنية من قبل شخص آخر غير ولي الأمر.",
|
"CIVIL_ID_NOT_CREATED_BY_GUARDIAN": "تم تحميل بطاقة الهوية المدنية من قبل شخص آخر غير ولي الأمر.",
|
||||||
"CIVIL_ID_ALREADY_EXISTS": "بطاقة الهوية المدنية مستخدمة بالفعل من قبل طفل آخر.",
|
"CIVIL_ID_ALREADY_EXISTS": "بطاقة الهوية المدنية مستخدمة بالفعل من قبل طفل آخر.",
|
||||||
"CANNOT_UPDATE_REGISTERED_USER": "الطفل قد سجل بالفعل. لا يُسمح بتحديث البيانات."
|
"CANNOT_UPDATE_REGISTERED_USER": "الطفل قد سجل بالفعل. لا يُسمح بتحديث البيانات.",
|
||||||
|
"CANNOT_DELETE_REGISTERED_USER": "الطفل قد سجل بالفعل. لا يُسمح بحذف الطفل."
|
||||||
},
|
},
|
||||||
|
|
||||||
"MONEY_REQUEST": {
|
"MONEY_REQUEST": {
|
||||||
|
|||||||
@ -67,7 +67,8 @@
|
|||||||
"CIVIL_ID_REQUIRED": "Civil ID is required.",
|
"CIVIL_ID_REQUIRED": "Civil ID is required.",
|
||||||
"CIVIL_ID_NOT_CREATED_BY_GUARDIAN": "The civil ID document was not uploaded by the guardian.",
|
"CIVIL_ID_NOT_CREATED_BY_GUARDIAN": "The civil ID document was not uploaded by the guardian.",
|
||||||
"CIVIL_ID_ALREADY_EXISTS": "The civil ID is already used by another junior.",
|
"CIVIL_ID_ALREADY_EXISTS": "The civil ID is already used by another junior.",
|
||||||
"CANNOT_UPDATE_REGISTERED_USER": "The junior has already registered. Updating details is not allowed."
|
"CANNOT_UPDATE_REGISTERED_USER": "The junior has already registered. Updating details is not allowed.",
|
||||||
|
"CANNOT_DELETE_REGISTERED_USER": "The junior has already registered. Deleting the junior is not allowed."
|
||||||
},
|
},
|
||||||
|
|
||||||
"MONEY_REQUEST": {
|
"MONEY_REQUEST": {
|
||||||
|
|||||||
@ -1,4 +1,16 @@
|
|||||||
import { Body, Controller, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common';
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Delete,
|
||||||
|
Get,
|
||||||
|
HttpCode,
|
||||||
|
HttpStatus,
|
||||||
|
Param,
|
||||||
|
Patch,
|
||||||
|
Post,
|
||||||
|
Query,
|
||||||
|
UseGuards,
|
||||||
|
} from '@nestjs/common';
|
||||||
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||||
import { Roles } from '~/auth/enums';
|
import { Roles } from '~/auth/enums';
|
||||||
import { IJwtPayload } from '~/auth/interfaces';
|
import { IJwtPayload } from '~/auth/interfaces';
|
||||||
@ -83,6 +95,14 @@ export class JuniorController {
|
|||||||
return ResponseFactory.data(new JuniorResponseDto(junior));
|
return ResponseFactory.data(new JuniorResponseDto(junior));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Delete(':juniorId')
|
||||||
|
@UseGuards(RolesGuard)
|
||||||
|
@AllowedRoles(Roles.GUARDIAN)
|
||||||
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
|
async deleteJunior(@AuthenticatedUser() user: IJwtPayload, @Param('juniorId', CustomParseUUIDPipe) juniorId: string) {
|
||||||
|
await this.juniorService.deleteJunior(juniorId, user.sub);
|
||||||
|
}
|
||||||
|
|
||||||
@Post('set-theme')
|
@Post('set-theme')
|
||||||
@UseGuards(RolesGuard)
|
@UseGuards(RolesGuard)
|
||||||
@AllowedRoles(Roles.JUNIOR)
|
@AllowedRoles(Roles.JUNIOR)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import {
|
|||||||
BaseEntity,
|
BaseEntity,
|
||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
|
DeleteDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
JoinColumn,
|
JoinColumn,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
@ -49,4 +50,7 @@ export class Junior extends BaseEntity {
|
|||||||
|
|
||||||
@UpdateDateColumn({ name: 'updated_at', type: 'timestamp with time zone', default: () => 'CURRENT_TIMESTAMP' })
|
@UpdateDateColumn({ name: 'updated_at', type: 'timestamp with time zone', default: () => 'CURRENT_TIMESTAMP' })
|
||||||
updatedAt!: Date;
|
updatedAt!: Date;
|
||||||
|
|
||||||
|
@DeleteDateColumn({ name: 'deleted_at', type: 'timestamp with time zone', nullable: true })
|
||||||
|
deletedAt!: Date | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,4 +65,8 @@ export class JuniorRepository {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
softDelete(juniorId: string) {
|
||||||
|
return this.juniorRepository.softDelete({ id: juniorId });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { IsNull, Not } from 'typeorm';
|
||||||
import { Transactional } from 'typeorm-transactional';
|
import { Transactional } from 'typeorm-transactional';
|
||||||
import { Roles } from '~/auth/enums';
|
import { Roles } from '~/auth/enums';
|
||||||
import { CardService } from '~/card/services';
|
import { CardService } from '~/card/services';
|
||||||
@ -183,6 +184,31 @@ export class JuniorService {
|
|||||||
return this.cardService.transferToChild(juniorId, body.amount);
|
return this.cardService.transferToChild(juniorId, body.amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteJunior(juniorId: string, guardianId: string) {
|
||||||
|
const doesBelong = await this.doesJuniorBelongToGuardian(guardianId, juniorId);
|
||||||
|
|
||||||
|
if (!doesBelong) {
|
||||||
|
this.logger.error(`Junior ${juniorId} does not belong to guardian ${guardianId}`);
|
||||||
|
throw new BadRequestException('JUNIOR.NOT_BELONG_TO_GUARDIAN');
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasPassword = await this.userService.findUser({ id: juniorId, password: Not(IsNull()) });
|
||||||
|
|
||||||
|
if (hasPassword) {
|
||||||
|
this.logger.error(`Cannot delete junior ${juniorId} with registered user`);
|
||||||
|
throw new BadRequestException('JUNIOR.CANNOT_DELETE_REGISTERED_USER');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { affected } = await this.juniorRepository.softDelete(juniorId);
|
||||||
|
|
||||||
|
if (affected === 0) {
|
||||||
|
this.logger.error(`Junior ${juniorId} not found`);
|
||||||
|
throw new BadRequestException('JUNIOR.NOT_FOUND');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(`Junior ${juniorId} deleted successfully`);
|
||||||
|
}
|
||||||
|
|
||||||
private async prepareJuniorImages(juniors: Junior[]) {
|
private async prepareJuniorImages(juniors: Junior[]) {
|
||||||
this.logger.log(`Preparing junior images`);
|
this.logger.log(`Preparing junior images`);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
|
|||||||
Reference in New Issue
Block a user