@@ -3,6 +3,9 @@ import { InjectRepository } from "@mikro-orm/nestjs";
33import { Injectable , UnprocessableEntityException } from "@nestjs/common" ;
44import { QuestionnaireCreationDto , QuestionnaireMutationDto } from "./questionnaire.dto" ;
55import { Questionnaire } from "./questionnaire.entity" ;
6+ import { Entry } from "../entries/entry.entity" ;
7+ import { EntryLanguage } from "../entry-languages/entry-language.entity" ;
8+ import { addDays , isSameDay } from "date-fns" ;
69
710@Injectable ( )
811export class QuestionnairesService {
@@ -16,6 +19,25 @@ export class QuestionnairesService {
1619 const questionnaire = new Questionnaire ( ) ;
1720 questionnaire . assign ( questionnaireCreationDto , { em : this . em } ) ;
1821
22+ const prevQuestionnaire = await this . findLatestByParticipant ( questionnaire . participant ! . id ) ;
23+ this . validateStartDate ( questionnaire , prevQuestionnaire ) ;
24+
25+ await prevQuestionnaire ?. populate ( [ "entries.entryLanguages" ] ) ;
26+
27+ const clonedEntries = prevQuestionnaire ?. entries . map ( ( entry ) => {
28+ const { id : _id , entryLanguages : _entryLanguages , questionnaire : _questionnaire , ...rest } = entry . toPOJO ( ) ;
29+ const newEntry = this . em . create ( Entry , { ...rest , questionnaire } ) ;
30+
31+ entry . entryLanguages . map ( ( entryLanguage ) => {
32+ const { id : _id , entry : _entry , ...rest } = entryLanguage . toPOJO ( ) ;
33+ return this . em . create ( EntryLanguage , { ...rest , entry : newEntry } ) ;
34+ } ) ;
35+
36+ return newEntry ;
37+ } ) ;
38+
39+ questionnaire . assign ( { entries : clonedEntries ?? [ ] } ) ;
40+
1941 try {
2042 await this . em . persist ( questionnaire ) . flush ( ) ;
2143 } catch ( e ) {
@@ -42,12 +64,21 @@ export class QuestionnairesService {
4264 return ( await this . questionnaireRepository . findOneOrFail ( filter ) ) . toObject ( ) ;
4365 }
4466
67+ async findLatestByParticipant ( participantId : number ) {
68+ return this . questionnaireRepository . findOne ( { participant : participantId } , { orderBy : { endedAt : "desc" } } ) ;
69+ }
70+
4571 async update ( id : number , questionnaireMutationDto : QuestionnaireMutationDto ) {
4672 const questionnaire = await this . questionnaireRepository . findOneOrFail ( id , {
4773 populate : [ "entries" , "entries.carer" , "entries.entryLanguages.language" ] ,
4874 } ) ;
4975 questionnaire . assign ( questionnaireMutationDto ) ;
5076
77+ const prevQuestionnaire = await this . findLatestByParticipant ( questionnaire . participant ! . id ) ;
78+ if ( prevQuestionnaire ?. id !== id ) {
79+ this . validateStartDate ( questionnaire , prevQuestionnaire ) ;
80+ }
81+
5182 await this . em . persist ( questionnaire ) . flush ( ) ;
5283
5384 return questionnaire . toObject ( ) ;
@@ -56,4 +87,10 @@ export class QuestionnairesService {
5687 remove ( id : number ) {
5788 return this . em . remove ( this . questionnaireRepository . getReference ( id ) ) . flush ( ) ;
5889 }
90+
91+ private validateStartDate ( questionnaire : Questionnaire , prevQuestionnaire : Questionnaire | null ) {
92+ if ( prevQuestionnaire && ! isSameDay ( addDays ( prevQuestionnaire . endedAt ! , 1 ) , questionnaire . startedAt ! ) ) {
93+ throw new UnprocessableEntityException ( "Start of the new questionnaire must match with the end of the previous" ) ;
94+ }
95+ }
5996}
0 commit comments