From c760687d792e0aa99996957acea91d7b687f2215 Mon Sep 17 00:00:00 2001 From: Mathieu MARCHOIS Date: Sun, 30 May 2021 15:58:03 +0200 Subject: [PATCH] feat: shooting notice (#98) --- api/migrations/1622382189406-ShootingNotice.ts | 14 ++++++++++++++ .../Command/Shooting/CreateShootingCommand.ts | 3 ++- .../Shooting/CreateShootingCommandHandler.spec.ts | 4 +++- .../Shooting/CreateShootingCommandHandler.ts | 5 +++-- .../Command/Shooting/UpdateShootingCommand.ts | 1 + .../Shooting/UpdateShootingCommandHandler.spec.ts | 6 ++++-- .../Shooting/UpdateShootingCommandHandler.ts | 4 ++-- .../Shooting/GetShootingByIdQueryHandler.spec.ts | 4 +++- .../Query/Shooting/GetShootingByIdQueryHandler.ts | 3 ++- api/src/Application/School/View/ShootingView.ts | 1 + api/src/Domain/School/Shooting.entity.spec.ts | 8 ++++++-- api/src/Domain/School/Shooting.entity.ts | 13 ++++++++++++- .../School/Action/Shooting/CreateShootingAction.ts | 5 +++-- .../School/Action/Shooting/UpdateShootingAction.ts | 5 +++-- api/src/Infrastructure/School/DTO/ShootingDTO.ts | 8 ++++++-- .../School/Repository/ShootingRepository.ts | 1 + client/i18n/fr.json | 7 ++++--- .../[id]/shootings/[shootingId]/edit.svelte | 5 +++-- .../admin/schools/[id]/shootings/_Form.svelte | 8 +++++++- .../admin/schools/[id]/shootings/_Table.svelte | 3 --- 20 files changed, 80 insertions(+), 28 deletions(-) create mode 100644 api/migrations/1622382189406-ShootingNotice.ts diff --git a/api/migrations/1622382189406-ShootingNotice.ts b/api/migrations/1622382189406-ShootingNotice.ts new file mode 100644 index 0000000..c220800 --- /dev/null +++ b/api/migrations/1622382189406-ShootingNotice.ts @@ -0,0 +1,14 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ShootingNotice1622382189406 implements MigrationInterface { + name = 'ShootingNotice1622382189406' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "shooting" ADD "notice" character varying`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "shooting" DROP COLUMN "notice"`); + } + +} diff --git a/api/src/Application/School/Command/Shooting/CreateShootingCommand.ts b/api/src/Application/School/Command/Shooting/CreateShootingCommand.ts index 4956d31..6c3598d 100644 --- a/api/src/Application/School/Command/Shooting/CreateShootingCommand.ts +++ b/api/src/Application/School/Command/Shooting/CreateShootingCommand.ts @@ -5,6 +5,7 @@ export class CreateShootingCommand implements ICommand { public readonly name: string, public readonly shootingDate: Date, public readonly closingDate: Date, - public readonly schoolId: string + public readonly schoolId: string, + public readonly notice: string, ) {} } diff --git a/api/src/Application/School/Command/Shooting/CreateShootingCommandHandler.spec.ts b/api/src/Application/School/Command/Shooting/CreateShootingCommandHandler.spec.ts index 039e018..caf810e 100644 --- a/api/src/Application/School/Command/Shooting/CreateShootingCommandHandler.spec.ts +++ b/api/src/Application/School/Command/Shooting/CreateShootingCommandHandler.spec.ts @@ -14,13 +14,13 @@ describe('CreateShootingCommandHandler', () => { let createdShooting: Shooting; let handler: CreateShootingCommandHandler; - const product = mock(Product); const school = mock(School); const command = new CreateShootingCommand( 'Prise de vue début année', new Date('2021-04-18'), new Date('2021-09-01'), '553e2b3c-eb11-42b1-8f76-903add071ca7', + 'Message notice' ); beforeEach(() => { @@ -49,6 +49,7 @@ describe('CreateShootingCommandHandler', () => { new Date('2021-09-01'), ShootingStatus.DISABLED, instance(school), + 'Message notice' ) ) ) @@ -67,6 +68,7 @@ describe('CreateShootingCommandHandler', () => { new Date('2021-09-01'), ShootingStatus.DISABLED, instance(school), + 'Message notice' ) ) ) diff --git a/api/src/Application/School/Command/Shooting/CreateShootingCommandHandler.ts b/api/src/Application/School/Command/Shooting/CreateShootingCommandHandler.ts index 9447283..c2e3c05 100644 --- a/api/src/Application/School/Command/Shooting/CreateShootingCommandHandler.ts +++ b/api/src/Application/School/Command/Shooting/CreateShootingCommandHandler.ts @@ -16,7 +16,7 @@ export class CreateShootingCommandHandler { ) {} public async execute(command: CreateShootingCommand): Promise { - const { name, closingDate, schoolId, shootingDate } = command; + const { name, closingDate, schoolId, shootingDate, notice } = command; const school = await this.schoolRepository.findOneById(schoolId); if (!school) { @@ -29,7 +29,8 @@ export class CreateShootingCommandHandler { shootingDate, closingDate, ShootingStatus.DISABLED, - school + school, + notice ) ); diff --git a/api/src/Application/School/Command/Shooting/UpdateShootingCommand.ts b/api/src/Application/School/Command/Shooting/UpdateShootingCommand.ts index 1b00a10..2249fbb 100644 --- a/api/src/Application/School/Command/Shooting/UpdateShootingCommand.ts +++ b/api/src/Application/School/Command/Shooting/UpdateShootingCommand.ts @@ -6,5 +6,6 @@ export class UpdateShootingCommand implements ICommand { public readonly name: string, public readonly shootingDate: Date, public readonly closingDate: Date, + public readonly notice: string, ) { } } diff --git a/api/src/Application/School/Command/Shooting/UpdateShootingCommandHandler.spec.ts b/api/src/Application/School/Command/Shooting/UpdateShootingCommandHandler.spec.ts index aa82e74..4d370a3 100644 --- a/api/src/Application/School/Command/Shooting/UpdateShootingCommandHandler.spec.ts +++ b/api/src/Application/School/Command/Shooting/UpdateShootingCommandHandler.spec.ts @@ -15,6 +15,7 @@ describe('UpdateShootingCommandHandler', () => { 'Prise de vue début année', new Date('2021-04-18'), new Date('2021-09-01'), + 'Message notice' ); beforeEach(() => { @@ -47,8 +48,9 @@ describe('UpdateShootingCommandHandler', () => { verify(updatedShooting.update( 'Prise de vue début année', deepEqual(new Date('2021-04-18')), - deepEqual(new Date('2021-09-01'))) - ).once(); + deepEqual(new Date('2021-09-01')), + 'Message notice' + )).once(); verify(shootingRepository.findOneById('17efcbee-bd2f-410e-9e99-51684b592bad')).once(); }); diff --git a/api/src/Application/School/Command/Shooting/UpdateShootingCommandHandler.ts b/api/src/Application/School/Command/Shooting/UpdateShootingCommandHandler.ts index 2c43e40..c32a378 100644 --- a/api/src/Application/School/Command/Shooting/UpdateShootingCommandHandler.ts +++ b/api/src/Application/School/Command/Shooting/UpdateShootingCommandHandler.ts @@ -12,14 +12,14 @@ export class UpdateShootingCommandHandler { ) { } public async execute(command: UpdateShootingCommand): Promise { - const { name, closingDate, shootingDate, id } = command; + const { name, closingDate, shootingDate, notice, id } = command; const shooting = await this.shootingRepository.findOneById(id); if (!shooting) { throw new ShootingNotFoundException(); } - shooting.update(name, shootingDate, closingDate); + shooting.update(name, shootingDate, closingDate, notice); await this.shootingRepository.save(shooting); return shooting.getId(); diff --git a/api/src/Application/School/Query/Shooting/GetShootingByIdQueryHandler.spec.ts b/api/src/Application/School/Query/Shooting/GetShootingByIdQueryHandler.spec.ts index c00d116..837e9c6 100644 --- a/api/src/Application/School/Query/Shooting/GetShootingByIdQueryHandler.spec.ts +++ b/api/src/Application/School/Query/Shooting/GetShootingByIdQueryHandler.spec.ts @@ -17,7 +17,8 @@ describe('GetShootingByIdQueryHandler', () => { 'Prise de vue fin année', ShootingStatus.DISABLED, new Date('2021-04-18'), - new Date('2021-09-01') + new Date('2021-09-01'), + 'Notice' ); const shooting = mock(Shooting); @@ -25,6 +26,7 @@ describe('GetShootingByIdQueryHandler', () => { when(shooting.getName()).thenReturn('Prise de vue fin année'); when(shooting.getClosingDate()).thenReturn(new Date('2021-09-01')); when(shooting.getShootingDate()).thenReturn(new Date('2021-04-18')); + when(shooting.getNotice()).thenReturn('Notice'); when(shooting.getStatus()).thenReturn(ShootingStatus.DISABLED); when( shootingRepository.findOneById('eb9e1d9b-dce2-48a9-b64f-f0872f3157d2') diff --git a/api/src/Application/School/Query/Shooting/GetShootingByIdQueryHandler.ts b/api/src/Application/School/Query/Shooting/GetShootingByIdQueryHandler.ts index a6ff67c..4f45729 100644 --- a/api/src/Application/School/Query/Shooting/GetShootingByIdQueryHandler.ts +++ b/api/src/Application/School/Query/Shooting/GetShootingByIdQueryHandler.ts @@ -24,7 +24,8 @@ export class GetShootingByIdQueryHandler { shooting.getName(), shooting.getStatus(), shooting.getShootingDate(), - shooting.getClosingDate() + shooting.getClosingDate(), + shooting.getNotice() ); } } diff --git a/api/src/Application/School/View/ShootingView.ts b/api/src/Application/School/View/ShootingView.ts index 81d08b4..e59dcf3 100644 --- a/api/src/Application/School/View/ShootingView.ts +++ b/api/src/Application/School/View/ShootingView.ts @@ -7,5 +7,6 @@ export class ShootingView { public readonly status: ShootingStatus, public readonly shootingDate: Date, public readonly closingDate: Date, + public readonly notice?: string, ) {} } diff --git a/api/src/Domain/School/Shooting.entity.spec.ts b/api/src/Domain/School/Shooting.entity.spec.ts index 7d03312..0075b06 100644 --- a/api/src/Domain/School/Shooting.entity.spec.ts +++ b/api/src/Domain/School/Shooting.entity.spec.ts @@ -10,7 +10,8 @@ describe('Shooting', () => { new Date('2021-04-17'), new Date('2021-09-01'), ShootingStatus.DISABLED, - instance(school) + instance(school), + 'Fin des commandes le 10' ); expect(shooting.getId()).toBeUndefined(); expect(shooting.getName()).toBe('Prise de vue début année'); @@ -18,6 +19,7 @@ describe('Shooting', () => { expect(shooting.getClosingDate()).toMatchObject(new Date('2021-09-01T00:00:00.000Z')); expect(shooting.getStatus()).toBe(ShootingStatus.DISABLED); expect(shooting.getSchool()).toBe(instance(school)); + expect(shooting.getNotice()).toBe('Fin des commandes le 10'); }); it('testUpdate', () => { @@ -33,7 +35,8 @@ describe('Shooting', () => { shooting.update( 'Prise de vue fin année', new Date('2022-04-17'), - new Date('2022-09-01') + new Date('2022-09-01'), + 'Message notice' ); @@ -43,5 +46,6 @@ describe('Shooting', () => { expect(shooting.getClosingDate()).toMatchObject(new Date('2022-09-01T00:00:00.000Z')); expect(shooting.getStatus()).toBe(ShootingStatus.DISABLED); expect(shooting.getSchool()).toBe(instance(school)); + expect(shooting.getNotice()).toBe('Message notice'); }); }); diff --git a/api/src/Domain/School/Shooting.entity.ts b/api/src/Domain/School/Shooting.entity.ts index df04315..94ab407 100644 --- a/api/src/Domain/School/Shooting.entity.ts +++ b/api/src/Domain/School/Shooting.entity.ts @@ -20,6 +20,9 @@ export class Shooting { @Column({ type: 'date', nullable: false }) private closingDate: Date; + @Column({ type: 'varchar', nullable: true }) + private notice: string; + @Column('enum', { enum: ShootingStatus, nullable: false, default: ShootingStatus.DISABLED }) private status: ShootingStatus; @@ -31,13 +34,15 @@ export class Shooting { shootingDate: Date, closingDate: Date, status: ShootingStatus, - school: School + school: School, + notice?: string ) { this.name = name; this.shootingDate = shootingDate; this.closingDate = closingDate; this.status = status; this.school = school; + this.notice = notice; } public getId(): string { @@ -56,6 +61,10 @@ export class Shooting { return this.closingDate; } + public getNotice(): string { + return this.notice; + } + public getSchool(): School { return this.school; } @@ -68,9 +77,11 @@ export class Shooting { name: string, shootingDate: Date, closingDate: Date, + notice?: string, ): void { this.name = name; this.shootingDate = shootingDate; this.closingDate = closingDate; + this.notice = notice; } } diff --git a/api/src/Infrastructure/School/Action/Shooting/CreateShootingAction.ts b/api/src/Infrastructure/School/Action/Shooting/CreateShootingAction.ts index 5b7c8b8..7484e1c 100644 --- a/api/src/Infrastructure/School/Action/Shooting/CreateShootingAction.ts +++ b/api/src/Infrastructure/School/Action/Shooting/CreateShootingAction.ts @@ -31,7 +31,7 @@ export class CreateShootingAction { @Roles(UserRole.PHOTOGRAPHER) @ApiOperation({ summary: 'Create a shooting' }) public async index(@Param() idDto: IdDTO, @Body() dto: ShootingDTO) { - const { name, shootingDate, closingDate } = dto; + const { name, shootingDate, closingDate, notice } = dto; try { const id = await this.commandBus.execute( @@ -39,7 +39,8 @@ export class CreateShootingAction { name, new Date(shootingDate), new Date(closingDate), - idDto.id + idDto.id, + notice ) ); diff --git a/api/src/Infrastructure/School/Action/Shooting/UpdateShootingAction.ts b/api/src/Infrastructure/School/Action/Shooting/UpdateShootingAction.ts index b163bcd..c0384e0 100644 --- a/api/src/Infrastructure/School/Action/Shooting/UpdateShootingAction.ts +++ b/api/src/Infrastructure/School/Action/Shooting/UpdateShootingAction.ts @@ -32,13 +32,14 @@ export class UpdateShootingAction { @ApiOperation({ summary: 'Update shooting' }) public async index(@Param() idDto: IdDTO, @Body() dto: ShootingDTO) { try { - const { name, closingDate, shootingDate } = dto; + const { name, closingDate, shootingDate, notice } = dto; const id = await this.commandBus.execute( new UpdateShootingCommand( idDto.id, name, new Date(shootingDate), - new Date(closingDate) + new Date(closingDate), + notice ) ); diff --git a/api/src/Infrastructure/School/DTO/ShootingDTO.ts b/api/src/Infrastructure/School/DTO/ShootingDTO.ts index 49a86e5..4dcc1ec 100644 --- a/api/src/Infrastructure/School/DTO/ShootingDTO.ts +++ b/api/src/Infrastructure/School/DTO/ShootingDTO.ts @@ -1,5 +1,5 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsDateString, IsNotEmpty } from 'class-validator'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { IsDateString, IsNotEmpty, IsOptional } from 'class-validator'; import { DateGreaterOrEqualThan } from 'src/Infrastructure/Common/Validator/DateGreaterOrEqualThan'; export class ShootingDTO { @@ -7,6 +7,10 @@ export class ShootingDTO { @IsNotEmpty() public name: string; + @ApiPropertyOptional() + @IsOptional() + public notice: string; + @ApiProperty() @IsNotEmpty() @IsDateString() diff --git a/api/src/Infrastructure/School/Repository/ShootingRepository.ts b/api/src/Infrastructure/School/Repository/ShootingRepository.ts index 1a63634..6e167f6 100644 --- a/api/src/Infrastructure/School/Repository/ShootingRepository.ts +++ b/api/src/Infrastructure/School/Repository/ShootingRepository.ts @@ -37,6 +37,7 @@ export class ShootingRepository implements IShootingRepository { 'shooting.id', 'shooting.name', 'shooting.status', + 'shooting.notice', 'shooting.shootingDate', 'shooting.closingDate' ]) diff --git a/client/i18n/fr.json b/client/i18n/fr.json index 53d3393..d0853ce 100644 --- a/client/i18n/fr.json +++ b/client/i18n/fr.json @@ -286,8 +286,9 @@ }, "form": { "name": "Nom de la prise de vue", - "closing_date": "Date de la fermeture des commandes", - "shooting_date": "Date de la prise de vue" + "closing_date": "Date de la fermeture des commandes groupées", + "shooting_date": "Date de la prise de vue", + "notice": "Message d'information qui sera affiché au client" }, "status": { "enabled": "En ligne", @@ -295,7 +296,7 @@ }, "list": { "name": "Prise de vue", - "closing_date": "Fermeture commandes", + "closing_date": "Fermeture commandes groupées", "shooting_date": "Date", "status": "Etat", "class": "Nb classes", diff --git a/client/src/routes/admin/schools/[id]/shootings/[shootingId]/edit.svelte b/client/src/routes/admin/schools/[id]/shootings/[shootingId]/edit.svelte index 46d5f1f..e7c5a91 100644 --- a/client/src/routes/admin/schools/[id]/shootings/[shootingId]/edit.svelte +++ b/client/src/routes/admin/schools/[id]/shootings/[shootingId]/edit.svelte @@ -10,10 +10,10 @@ import { onMount } from 'svelte'; import { get, put } from 'utils/axios'; import Breadcrumb from 'components/Breadcrumb.svelte'; - import Form from '../_Form.svelte'; import { errorNormalizer } from 'normalizer/errors'; import ServerErrors from 'components/ServerErrors.svelte'; import H4Title from 'components/H4Title.svelte'; + import Form from '../_Form.svelte'; export let id; export let shootingId; @@ -21,7 +21,7 @@ let loading = false; let school; let shooting; - let title = $_('schools.shootings.edit.title'); + const title = $_('schools.shootings.edit.title'); let errors = []; onMount(async () => { @@ -70,5 +70,6 @@ name={shooting.name} closingDate={shooting.closingDate} shootingDate={shooting.shootingDate} + notice={shooting.notice} {loading} /> {/if} diff --git a/client/src/routes/admin/schools/[id]/shootings/_Form.svelte b/client/src/routes/admin/schools/[id]/shootings/_Form.svelte index ec30d9f..cf7828d 100644 --- a/client/src/routes/admin/schools/[id]/shootings/_Form.svelte +++ b/client/src/routes/admin/schools/[id]/shootings/_Form.svelte @@ -7,6 +7,7 @@ export let shootingDate = ''; export let closingDate = ''; export let name = ''; + export let notice = ''; export let loading; const dispatch = createEventDispatcher(); @@ -14,7 +15,8 @@ dispatch('save', { name, closingDate: new Date(closingDate), - shootingDate: new Date(shootingDate) + shootingDate: new Date(shootingDate), + notice }); }; @@ -33,6 +35,10 @@ type={'date'} label={$_('schools.shootings.form.closing_date')} bind:value={closingDate} /> +