@@ -3,6 +3,9 @@ import { InjectRepository } from "@mikro-orm/nestjs";
3
3
import { Injectable , UnprocessableEntityException } from "@nestjs/common" ;
4
4
import { QuestionnaireCreationDto , QuestionnaireMutationDto } from "./questionnaire.dto" ;
5
5
import { 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" ;
6
9
7
10
@Injectable ( )
8
11
export class QuestionnairesService {
@@ -16,6 +19,25 @@ export class QuestionnairesService {
16
19
const questionnaire = new Questionnaire ( ) ;
17
20
questionnaire . assign ( questionnaireCreationDto , { em : this . em } ) ;
18
21
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
+
19
41
try {
20
42
await this . em . persist ( questionnaire ) . flush ( ) ;
21
43
} catch ( e ) {
@@ -42,12 +64,21 @@ export class QuestionnairesService {
42
64
return ( await this . questionnaireRepository . findOneOrFail ( filter ) ) . toObject ( ) ;
43
65
}
44
66
67
+ async findLatestByParticipant ( participantId : number ) {
68
+ return this . questionnaireRepository . findOne ( { participant : participantId } , { orderBy : { endedAt : "desc" } } ) ;
69
+ }
70
+
45
71
async update ( id : number , questionnaireMutationDto : QuestionnaireMutationDto ) {
46
72
const questionnaire = await this . questionnaireRepository . findOneOrFail ( id , {
47
73
populate : [ "entries" , "entries.carer" , "entries.entryLanguages.language" ] ,
48
74
} ) ;
49
75
questionnaire . assign ( questionnaireMutationDto ) ;
50
76
77
+ const prevQuestionnaire = await this . findLatestByParticipant ( questionnaire . participant ! . id ) ;
78
+ if ( prevQuestionnaire ?. id !== id ) {
79
+ this . validateStartDate ( questionnaire , prevQuestionnaire ) ;
80
+ }
81
+
51
82
await this . em . persist ( questionnaire ) . flush ( ) ;
52
83
53
84
return questionnaire . toObject ( ) ;
@@ -56,4 +87,10 @@ export class QuestionnairesService {
56
87
remove ( id : number ) {
57
88
return this . em . remove ( this . questionnaireRepository . getReference ( id ) ) . flush ( ) ;
58
89
}
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
+ }
59
96
}
0 commit comments