@@ -5,6 +5,7 @@ import { linearRegression } from '@douglasneuroinformatics/libstats';
55import { BadRequestException , Injectable , NotFoundException , UnprocessableEntityException } from '@nestjs/common' ;
66import type { Json , ScalarInstrument } from '@opendatacapture/runtime-core' ;
77import { DEFAULT_GROUP_NAME } from '@opendatacapture/schemas/core' ;
8+ import { $RecordArrayFieldValue } from '@opendatacapture/schemas/instrument' ;
89import type {
910 CreateInstrumentRecordData ,
1011 InstrumentRecord ,
@@ -26,6 +27,17 @@ import { SubjectsService } from '@/subjects/subjects.service';
2627
2728import { InstrumentMeasuresService } from './instrument-measures.service' ;
2829
30+ type ExpandDataType =
31+ | {
32+ measure : string ;
33+ measureValue : boolean | Date | number | string | undefined ;
34+ success : true ;
35+ }
36+ | {
37+ message : string ;
38+ success : false ;
39+ } ;
40+
2941@Injectable ( )
3042export class InstrumentRecordsService {
3143 constructor (
@@ -153,26 +165,53 @@ export class InstrumentRecordsService {
153165 instrument = ( await this . instrumentsService . findById ( record . instrumentId ) ) as ScalarInstrument ;
154166 instruments . set ( record . instrumentId , instrument ) ;
155167 }
156-
157168 for ( const [ measureKey , measureValue ] of Object . entries ( record . computedMeasures ) ) {
158- data . push ( {
159- instrumentEdition : instrument . internal . edition ,
160- instrumentName : instrument . internal . name ,
161- measure : measureKey ,
162- sessionDate : record . session . date . toISOString ( ) ,
163- sessionId : record . session . id ,
164- sessionType : record . session . type ,
165- subjectAge : record . subject . dateOfBirth ? yearsPassed ( record . subject . dateOfBirth ) : null ,
166- // eslint-disable-next-line perfectionist/sort-objects
167- groupId : record . subject . groupIds [ 0 ] ?? DEFAULT_GROUP_NAME ,
168- subjectId : record . subject . id ,
169- subjectSex : record . subject . sex ,
170- timestamp : record . date . toISOString ( ) ,
171- value : measureValue
172- } ) ;
169+ if ( measureValue == null ) {
170+ continue ;
171+ }
172+
173+ if ( ! Array . isArray ( measureValue ) ) {
174+ data . push ( {
175+ groupId : record . subject . groupIds [ 0 ] ?? DEFAULT_GROUP_NAME ,
176+ instrumentEdition : instrument . internal . edition ,
177+ instrumentName : instrument . internal . name ,
178+ measure : measureKey ,
179+ sessionDate : record . session . date . toISOString ( ) ,
180+ sessionId : record . session . id ,
181+ sessionType : record . session . type ,
182+ subjectAge : record . subject . dateOfBirth ? yearsPassed ( record . subject . dateOfBirth ) : null ,
183+ subjectId : record . subject . id ,
184+ subjectSex : record . subject . sex ,
185+ timestamp : record . date . toISOString ( ) ,
186+ value : measureValue
187+ } ) ;
188+ }
189+
190+ if ( Array . isArray ( measureValue ) && measureValue . length < 1 ) continue ;
191+
192+ if ( Array . isArray ( measureValue ) && measureValue . length >= 1 ) {
193+ const arrayResult = this . expandData ( measureValue ) ;
194+ arrayResult . forEach ( ( arrayEntry : ExpandDataType ) => {
195+ if ( ! arrayEntry . success )
196+ throw new Error ( `exportRecords: ${ instrument . internal . name } .${ measureKey } — ${ arrayEntry . message } ` ) ;
197+ data . push ( {
198+ groupId : record . subject . groupIds [ 0 ] ?? DEFAULT_GROUP_NAME ,
199+ instrumentEdition : instrument . internal . edition ,
200+ instrumentName : instrument . internal . name ,
201+ measure : `${ measureKey } - ${ arrayEntry . measure } ` ,
202+ sessionDate : record . session . date . toISOString ( ) ,
203+ sessionId : record . session . id ,
204+ sessionType : record . session . type ,
205+ subjectAge : record . subject . dateOfBirth ? yearsPassed ( record . subject . dateOfBirth ) : null ,
206+ subjectId : record . subject . id ,
207+ subjectSex : record . subject . sex ,
208+ timestamp : record . date . toISOString ( ) ,
209+ value : arrayEntry . measureValue
210+ } ) ;
211+ } ) ;
212+ }
173213 }
174214 }
175-
176215 return data ;
177216 }
178217
@@ -378,6 +417,30 @@ export class InstrumentRecordsService {
378417 }
379418 }
380419
420+ private expandData ( listEntry : any [ ] ) : ExpandDataType [ ] {
421+ const validRecordArrayList : ExpandDataType [ ] = [ ] ;
422+ if ( listEntry . length < 1 ) {
423+ throw new Error ( 'Record Array is Empty' ) ;
424+ }
425+ for ( const objectEntry of Object . values ( listEntry ) ) {
426+ for ( const [ dataKey , dataValue ] of Object . entries ( objectEntry as { [ key : string ] : any } ) ) {
427+ const parseResult = $RecordArrayFieldValue . safeParse ( dataValue ) ;
428+ if ( ! parseResult . success ) {
429+ validRecordArrayList . push ( {
430+ message : `Error interpreting value ${ dataValue } and record array key ${ dataKey } ` ,
431+ success : false
432+ } ) ;
433+ }
434+ validRecordArrayList . push ( {
435+ measure : dataKey ,
436+ measureValue : parseResult . data ,
437+ success : true
438+ } ) ;
439+ }
440+ }
441+ return validRecordArrayList ;
442+ }
443+
381444 private getInstrumentById ( instrumentId : string ) {
382445 return this . instrumentsService
383446 . findById ( instrumentId )
0 commit comments