diff --git a/package-lock.json b/package-lock.json index 7890633..508df3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,6 +65,7 @@ "@types/nodemailer": "^6.4.16", "@types/passport-jwt": "^4.0.1", "@types/supertest": "^6.0.0", + "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^5.59.2", "@typescript-eslint/parser": "^5.59.2", "eslint": "^8.39.0", @@ -3121,6 +3122,13 @@ "@types/superagent": "^8.1.0" } }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/validator": { "version": "13.12.2", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.2.tgz", diff --git a/package.json b/package.json index e41907c..688dd70 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@types/nodemailer": "^6.4.16", "@types/passport-jwt": "^4.0.1", "@types/supertest": "^6.0.0", + "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^5.59.2", "@typescript-eslint/parser": "^5.59.2", "eslint": "^8.39.0", diff --git a/src/app.module.ts b/src/app.module.ts index ebee151..d459e4d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,6 +18,7 @@ import { DocumentModule } from './document/document.module'; import { GuardianModule } from './guardian/guardian.module'; import { HealthModule } from './health/health.module'; import { JuniorModule } from './junior/junior.module'; +import { LookupModule } from './common/modules/lookup/lookup.module'; @Module({ controllers: [], imports: [ @@ -51,6 +52,7 @@ import { JuniorModule } from './junior/junior.module'; OtpModule, DocumentModule, HealthModule, + LookupModule, ], providers: [ // Global Pipes diff --git a/src/common/modules/lookup/controllers/index.ts b/src/common/modules/lookup/controllers/index.ts new file mode 100644 index 0000000..3064974 --- /dev/null +++ b/src/common/modules/lookup/controllers/index.ts @@ -0,0 +1 @@ +export * from './lookup.controller'; diff --git a/src/common/modules/lookup/controllers/lookup.controller.ts b/src/common/modules/lookup/controllers/lookup.controller.ts new file mode 100644 index 0000000..2916ab2 --- /dev/null +++ b/src/common/modules/lookup/controllers/lookup.controller.ts @@ -0,0 +1,23 @@ +import { Controller, Get, UseGuards } from '@nestjs/common'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { AccessTokenGuard } from '~/common/guards'; +import { ApiDataArrayResponse } from '~/core/decorators'; +import { ResponseFactory } from '~/core/utils'; +import { DocumentMetaResponseDto } from '~/document/dtos/response'; +import { LookupService } from '../services'; + +@Controller('lookup') +@ApiTags('Lookups') +@ApiBearerAuth() +export class LookupController { + constructor(private readonly lookupService: LookupService) {} + + @UseGuards(AccessTokenGuard) + @Get('default-avatars') + @ApiDataArrayResponse(DocumentMetaResponseDto) + async findDefaultAvatars() { + const avatars = await this.lookupService.findDefaultAvatar(); + + return ResponseFactory.dataArray(avatars.map((avatar) => new DocumentMetaResponseDto(avatar))); + } +} diff --git a/src/common/modules/lookup/lookup.module.ts b/src/common/modules/lookup/lookup.module.ts new file mode 100644 index 0000000..df7aacc --- /dev/null +++ b/src/common/modules/lookup/lookup.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { DocumentModule } from '~/document/document.module'; +import { LookupController } from './controllers'; +import { LookupService } from './services'; + +@Module({ + controllers: [LookupController], + providers: [LookupService], + imports: [DocumentModule], +}) +export class LookupModule {} diff --git a/src/common/modules/lookup/services/index.ts b/src/common/modules/lookup/services/index.ts new file mode 100644 index 0000000..e9b5545 --- /dev/null +++ b/src/common/modules/lookup/services/index.ts @@ -0,0 +1 @@ +export * from './lookup.service'; diff --git a/src/common/modules/lookup/services/lookup.service.ts b/src/common/modules/lookup/services/lookup.service.ts new file mode 100644 index 0000000..4ed48d0 --- /dev/null +++ b/src/common/modules/lookup/services/lookup.service.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common'; +import { DocumentType } from '~/document/enums'; +import { DocumentService } from '~/document/services'; + +@Injectable() +export class LookupService { + constructor(private readonly documentService: DocumentService) {} + findDefaultAvatar() { + return this.documentService.findDocuments({ documentType: DocumentType.DEFAULT_AVATAR }); + } +} diff --git a/src/db/migrations/1733748083604-create-theme-entity.ts b/src/db/migrations/1733748083604-create-theme-entity.ts new file mode 100644 index 0000000..e43ab7a --- /dev/null +++ b/src/db/migrations/1733748083604-create-theme-entity.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class CreateThemeEntity1733748083604 implements MigrationInterface { + name = 'CreateThemeEntity1733748083604'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "themes" + ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), + "color" character varying(255) NOT NULL, + "avatar_id" uuid, "junior_id" uuid NOT NULL, + CONSTRAINT "REL_73fcb76399a308cdd2d431a8f2" UNIQUE ("junior_id"), + CONSTRAINT "PK_ddbeaab913c18682e5c88155592" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `ALTER TABLE "themes" ADD CONSTRAINT "FK_169b672cc28cc757e1f4464864d" FOREIGN KEY ("avatar_id") REFERENCES "documents"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "themes" ADD CONSTRAINT "FK_73fcb76399a308cdd2d431a8f2e" FOREIGN KEY ("junior_id") REFERENCES "juniors"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "themes" DROP CONSTRAINT "FK_73fcb76399a308cdd2d431a8f2e"`); + await queryRunner.query(`ALTER TABLE "themes" DROP CONSTRAINT "FK_169b672cc28cc757e1f4464864d"`); + await queryRunner.query(`DROP TABLE "themes"`); + } +} diff --git a/src/db/migrations/1733750228289-seed-default-avatar.ts b/src/db/migrations/1733750228289-seed-default-avatar.ts new file mode 100644 index 0000000..0983ccb --- /dev/null +++ b/src/db/migrations/1733750228289-seed-default-avatar.ts @@ -0,0 +1,73 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; +import { v4 as uuid } from 'uuid'; +import { Document } from '../../document/entities'; +import { DocumentType } from '../../document/enums'; +const DEFAULT_AVATARS = [ + { + id: uuid(), + name: 'vacation', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, + { + id: uuid(), + name: 'colors', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, + { + id: uuid(), + name: 'astronaut', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, + { + id: uuid(), + name: 'pet', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, + { + id: uuid(), + name: 'disney', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, + { + id: uuid(), + name: 'clothes', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, + { + id: uuid(), + name: 'playstation', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, + { + id: uuid(), + name: 'football', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, + { + id: uuid(), + name: 'cars', + extension: '.jpg', + documentType: DocumentType.DEFAULT_AVATAR, + }, +]; +export class SeedDefaultAvatar1733750228289 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.manager.getRepository(Document).save(DEFAULT_AVATARS); + } + + public async down(queryRunner: QueryRunner): Promise { + await DEFAULT_AVATARS.forEach(async (avatar) => { + await queryRunner.manager + .getRepository(Document) + .delete({ name: avatar.name, documentType: avatar.documentType }); + }); + } +} diff --git a/src/db/migrations/index.ts b/src/db/migrations/index.ts index b8656e5..9eb83d9 100644 --- a/src/db/migrations/index.ts +++ b/src/db/migrations/index.ts @@ -6,3 +6,5 @@ export * from './1733298524771-create-customer-entity'; export * from './1733314952318-create-device-entity'; export * from './1733731507261-create-junior-entity'; export * from './1733732021622-create-guardian-entity'; +export * from './1733748083604-create-theme-entity'; +export * from './1733750228289-seed-default-avatar'; diff --git a/src/document/constants/buckets.constant.ts b/src/document/constants/buckets.constant.ts index eb95616..e8540ae 100644 --- a/src/document/constants/buckets.constant.ts +++ b/src/document/constants/buckets.constant.ts @@ -3,4 +3,5 @@ import { DocumentType } from '../enums'; export const BUCKETS: Record = { [DocumentType.PROFILE_PICTURE]: 'profile-pictures', [DocumentType.PASSPORT]: 'passports', + [DocumentType.DEFAULT_AVATAR]: 'avatars', }; diff --git a/src/document/document.module.ts b/src/document/document.module.ts index 22a7853..c4d2807 100644 --- a/src/document/document.module.ts +++ b/src/document/document.module.ts @@ -9,5 +9,6 @@ import { DocumentService, OciService } from './services'; imports: [TypeOrmModule.forFeature([Document])], controllers: [DocumentController], providers: [DocumentService, OciService, DocumentRepository], + exports: [DocumentService], }) export class DocumentModule {} diff --git a/src/document/entities/document.entity.ts b/src/document/entities/document.entity.ts index 2a0dc5d..da8793d 100644 --- a/src/document/entities/document.entity.ts +++ b/src/document/entities/document.entity.ts @@ -1,6 +1,6 @@ -import { Column, Entity, OneToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; +import { Column, Entity, OneToMany, OneToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; import { User } from '~/auth/entities'; -import { Junior } from '~/junior/entities'; +import { Junior, Theme } from '~/junior/entities'; import { DocumentType } from '../enums'; @Entity('documents') @@ -18,13 +18,16 @@ export class Document { documentType!: DocumentType; @OneToOne(() => User, (user) => user.profilePicture, { onDelete: 'CASCADE' }) - user!: User; + user?: User; @OneToOne(() => Junior, (junior) => junior.civilIdFront, { onDelete: 'CASCADE' }) - juniorCivilIdFront!: User; + juniorCivilIdFront?: User; @OneToOne(() => Junior, (junior) => junior.civilIdBack, { onDelete: 'CASCADE' }) - juniorCivilIdBack!: User; + juniorCivilIdBack?: User; + + @OneToMany(() => Theme, (theme) => theme.avatar) + themes?: Theme[]; @UpdateDateColumn({ name: 'updated_at', type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) updatedAt!: Date; diff --git a/src/document/enums/document-type.enum.ts b/src/document/enums/document-type.enum.ts index 12dbc49..e7e8e33 100644 --- a/src/document/enums/document-type.enum.ts +++ b/src/document/enums/document-type.enum.ts @@ -1,4 +1,5 @@ export enum DocumentType { PROFILE_PICTURE = 'PROFILE_PICTURE', PASSPORT = 'PASSPORT', + DEFAULT_AVATAR = 'DEFAULT_AVATAR', } diff --git a/src/document/repositories/document.repository.ts b/src/document/repositories/document.repository.ts index dc4b7e6..e76eadd 100644 --- a/src/document/repositories/document.repository.ts +++ b/src/document/repositories/document.repository.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; +import { FindOptionsWhere, Repository } from 'typeorm'; import { UploadResponseDto } from '../dtos/response'; import { Document } from '../entities'; @@ -17,4 +17,8 @@ export class DocumentRepository { }), ); } + + findDocuments(where: FindOptionsWhere) { + return this.documentRepository.find({ where }); + } } diff --git a/src/document/services/document.service.ts b/src/document/services/document.service.ts index 3b1d6db..3d0c39e 100644 --- a/src/document/services/document.service.ts +++ b/src/document/services/document.service.ts @@ -1,5 +1,7 @@ import { Injectable } from '@nestjs/common'; +import { FindOptionsWhere } from 'typeorm'; import { UploadDocumentRequestDto } from '../dtos/request'; +import { Document } from '../entities'; import { DocumentRepository } from '../repositories'; import { OciService } from './oci.service'; @@ -10,4 +12,8 @@ export class DocumentService { const uploadedFile = await this.ociService.uploadFile(file, uploadedDocumentRequest); return this.documentRepository.createDocument(uploadedFile); } + + findDocuments(where: FindOptionsWhere) { + return this.documentRepository.findDocuments(where); + } } diff --git a/src/junior/controllers/junior.controller.ts b/src/junior/controllers/junior.controller.ts index 32eecf3..e63b18e 100644 --- a/src/junior/controllers/junior.controller.ts +++ b/src/junior/controllers/junior.controller.ts @@ -7,8 +7,8 @@ import { ApiDataPageResponse, ApiDataResponse } from '~/core/decorators'; import { PageOptionsRequestDto } from '~/core/dtos'; import { CustomParseUUIDPipe } from '~/core/pipes'; import { ResponseFactory } from '~/core/utils'; -import { CreateJuniorRequestDto } from '../dtos/request'; -import { JuniorResponseDto } from '../dtos/response'; +import { CreateJuniorRequestDto, SetThemeRequestDto } from '../dtos/request'; +import { JuniorResponseDto, ThemeResponseDto } from '../dtos/response'; import { JuniorService } from '../services'; @Controller('juniors') @@ -53,4 +53,12 @@ export class JuniorController { return ResponseFactory.data(new JuniorResponseDto(junior)); } + + @Post('set-theme') + @UseGuards(AccessTokenGuard) + @ApiDataResponse(JuniorResponseDto) + async setTheme(@Body() body: SetThemeRequestDto, @AuthenticatedUser() user: IJwtPayload) { + const theme = await this.juniorService.setTheme(body, user.sub); + return ResponseFactory.data(new ThemeResponseDto(theme)); + } } diff --git a/src/junior/dtos/request/index.ts b/src/junior/dtos/request/index.ts index cfba4cb..128c82e 100644 --- a/src/junior/dtos/request/index.ts +++ b/src/junior/dtos/request/index.ts @@ -1,2 +1,3 @@ export * from './create-junior-user.request.dto'; export * from './create-junior.request.dto'; +export * from './set-theme.request.dto'; diff --git a/src/junior/dtos/request/set-theme.request.dto.ts b/src/junior/dtos/request/set-theme.request.dto.ts new file mode 100644 index 0000000..5aadb8c --- /dev/null +++ b/src/junior/dtos/request/set-theme.request.dto.ts @@ -0,0 +1,13 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsEnum, IsUUID } from 'class-validator'; +import { ThemeColor } from '~/junior/enums'; + +export class SetThemeRequestDto { + @ApiProperty({ example: ThemeColor.VIOLET }) + @IsEnum(ThemeColor) + color!: ThemeColor; + + @ApiProperty({ example: 'fbfre-4f4f-4f4f-4f4f' }) + @IsUUID() + avatarId!: string; +} diff --git a/src/junior/dtos/response/index.ts b/src/junior/dtos/response/index.ts index ea31220..e1b955b 100644 --- a/src/junior/dtos/response/index.ts +++ b/src/junior/dtos/response/index.ts @@ -1 +1,2 @@ export * from './junior.response.dto'; +export * from './theme.response.dto'; diff --git a/src/junior/dtos/response/theme.response.dto.ts b/src/junior/dtos/response/theme.response.dto.ts new file mode 100644 index 0000000..0d64526 --- /dev/null +++ b/src/junior/dtos/response/theme.response.dto.ts @@ -0,0 +1,26 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Theme } from '~/junior/entities'; +import { ThemeColor } from '~/junior/enums'; + +export class ThemeResponseDto { + @ApiProperty({ example: '645fds-4f5s4f-4f5s4f-4f5s4f' }) + id!: string; + + @ApiProperty({ example: ThemeColor.BLUE }) + color!: string; + + @ApiProperty({ example: '645fds-4f5s4f-4f5s4f-4f5s4f' }) + avatarId!: string; + + @ApiProperty({ example: '645fds-4f5s4f-4f5s4f-4f5s4f' }) + juniorId!: string; + + constructor(theme: Theme | null) { + if (theme) { + this.id = theme.id; + this.color = theme.color; + this.avatarId = theme.avatarId; + this.juniorId = theme.juniorId; + } + } +} diff --git a/src/junior/entities/index.ts b/src/junior/entities/index.ts index c565d22..ff1006a 100644 --- a/src/junior/entities/index.ts +++ b/src/junior/entities/index.ts @@ -1 +1,2 @@ export * from './junior.entity'; +export * from './theme.entity'; diff --git a/src/junior/entities/junior.entity.ts b/src/junior/entities/junior.entity.ts index 7e5e8d6..db98b1f 100644 --- a/src/junior/entities/junior.entity.ts +++ b/src/junior/entities/junior.entity.ts @@ -13,6 +13,7 @@ import { Customer } from '~/customer/entities'; import { Document } from '~/document/entities'; import { Guardian } from '~/guardian/entities/guradian.entity'; import { Relationship } from '../enums'; +import { Theme } from './theme.entity'; @Entity('juniors') export class Junior extends BaseEntity { @@ -46,6 +47,9 @@ export class Junior extends BaseEntity { @JoinColumn({ name: 'customer_id' }) customer!: Customer; + @OneToOne(() => Theme, (theme) => theme.junior, { cascade: true, nullable: true }) + theme!: Theme; + @ManyToOne(() => Guardian, (guardian) => guardian.juniors) @JoinColumn({ name: 'guardian_id' }) guardian!: Guardian; diff --git a/src/junior/entities/theme.entity.ts b/src/junior/entities/theme.entity.ts new file mode 100644 index 0000000..cf347fb --- /dev/null +++ b/src/junior/entities/theme.entity.ts @@ -0,0 +1,26 @@ +import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, OneToOne, PrimaryGeneratedColumn } from 'typeorm'; +import { Document } from '~/document/entities'; +import { Junior } from './junior.entity'; + +@Entity('themes') +export class Theme extends BaseEntity { + @PrimaryGeneratedColumn('uuid') + id!: string; + + @Column('varchar', { length: 255, name: 'color' }) + color!: string; + + @Column('uuid', { name: 'avatar_id', nullable: true }) + avatarId!: string; + + @ManyToOne(() => Document, (document) => document.themes, { cascade: true, nullable: true }) + @JoinColumn({ name: 'avatar_id' }) + avatar!: Document; + + @Column('uuid', { name: 'junior_id' }) + juniorId!: string; + + @OneToOne(() => Junior, (junior) => junior.theme, { onDelete: 'CASCADE' }) + @JoinColumn({ name: 'junior_id' }) + junior!: Junior; +} diff --git a/src/junior/enums/index.ts b/src/junior/enums/index.ts index f9194f0..a139128 100644 --- a/src/junior/enums/index.ts +++ b/src/junior/enums/index.ts @@ -1 +1,2 @@ export * from './relationship.enum'; +export * from './theme-color.enum'; diff --git a/src/junior/enums/theme-color.enum.ts b/src/junior/enums/theme-color.enum.ts new file mode 100644 index 0000000..1719b92 --- /dev/null +++ b/src/junior/enums/theme-color.enum.ts @@ -0,0 +1,5 @@ +export enum ThemeColor { + BLUE = 'BLUE', + GREEN = 'GREEN', + VIOLET = 'VIOLET', +} diff --git a/src/junior/junior.module.ts b/src/junior/junior.module.ts index 7ad6c64..21e5816 100644 --- a/src/junior/junior.module.ts +++ b/src/junior/junior.module.ts @@ -3,13 +3,13 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { AuthModule } from '~/auth/auth.module'; import { CustomerModule } from '~/customer/customer.module'; import { JuniorController } from './controllers'; -import { Junior } from './entities'; +import { Junior, Theme } from './entities'; import { JuniorRepository } from './repositories'; import { JuniorService } from './services'; @Module({ controllers: [JuniorController], providers: [JuniorService, JuniorRepository], - imports: [TypeOrmModule.forFeature([Junior]), AuthModule, CustomerModule], + imports: [TypeOrmModule.forFeature([Junior, Theme]), AuthModule, CustomerModule], }) export class JuniorModule {} diff --git a/src/junior/repositories/junior.repository.ts b/src/junior/repositories/junior.repository.ts index da5291d..524dbc6 100644 --- a/src/junior/repositories/junior.repository.ts +++ b/src/junior/repositories/junior.repository.ts @@ -2,6 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { PageOptionsRequestDto } from '~/core/dtos'; +import { SetThemeRequestDto } from '../dtos/request'; +import { Theme } from '../entities'; import { Junior } from '../entities/junior.entity'; const FIRST_PAGE = 1; @Injectable() @@ -17,10 +19,23 @@ export class JuniorRepository { }); } - findJuniorById(juniorId: string, guardianId: string) { + findJuniorById(juniorId: string, guardianId?: string) { return this.juniorRepository.findOne({ where: { id: juniorId, guardianId }, - relations: ['customer', 'customer.user'], + relations: ['customer', 'customer.user', 'theme'], }); } + + setTheme(body: SetThemeRequestDto, junior: Junior) { + junior.theme = Theme.create({ ...body, junior }); + return this.juniorRepository.save(junior); + } + + removeTheme(theme: Theme) { + return this.juniorRepository.manager.remove(theme); + } + + findThemeForJunior(juniorId: string) { + return this.juniorRepository.manager.findOne(Theme, { where: { juniorId }, relations: ['avatar'] }); + } } diff --git a/src/junior/services/junior.service.ts b/src/junior/services/junior.service.ts index 25caea6..a8788a8 100644 --- a/src/junior/services/junior.service.ts +++ b/src/junior/services/junior.service.ts @@ -4,7 +4,7 @@ import { Roles } from '~/auth/enums'; import { UserService } from '~/auth/services'; import { PageOptionsRequestDto } from '~/core/dtos'; import { CustomerService } from '~/customer/services'; -import { CreateJuniorRequestDto } from '../dtos/request'; +import { CreateJuniorRequestDto, SetThemeRequestDto } from '../dtos/request'; import { Junior } from '../entities'; import { JuniorRepository } from '../repositories'; @@ -50,7 +50,7 @@ export class JuniorService { return this.findJuniorById(user.id, guardianId); } - async findJuniorById(juniorId: string, guardianId: string) { + async findJuniorById(juniorId: string, guardianId?: string) { const junior = await this.juniorRepository.findJuniorById(juniorId, guardianId); if (!junior) { @@ -59,6 +59,16 @@ export class JuniorService { return junior; } + @Transactional() + async setTheme(body: SetThemeRequestDto, juniorId: string) { + const junior = await this.findJuniorById(juniorId); + if (junior.theme) { + await this.juniorRepository.removeTheme(junior.theme); + } + await this.juniorRepository.setTheme(body, junior); + return this.juniorRepository.findThemeForJunior(juniorId); + } + findJuniorsByGuardianId(guardianId: string, pageOptions: PageOptionsRequestDto) { return this.juniorRepository.findJuniorsByGuardianId(guardianId, pageOptions); }