tango-app-api-trax 3.9.57 → 3.9.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -2141,6 +2141,22 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
2141
2141
|
|
|
2142
2142
|
if ( requestData.submittype == 'submit' ) {
|
|
2143
2143
|
requestData.userComplianceCount = 0;
|
|
2144
|
+
|
|
2145
|
+
// Pull every "Matched/Not Matched" verdict out of a runAIData array, tolerating both shapes:
|
|
2146
|
+
// 1) [ { answerImage, results: [ { featureName, value } ] } ] (verdict nested under results)
|
|
2147
|
+
// 2) [ { featureName, value } ] (flat verdict)
|
|
2148
|
+
const extractMatchValues = ( runAIData ) => {
|
|
2149
|
+
if ( !Array.isArray( runAIData ) ) return [];
|
|
2150
|
+
const values = [];
|
|
2151
|
+
runAIData.forEach( ( entry ) => {
|
|
2152
|
+
const results = Array.isArray( entry?.results ) ? entry.results : [ entry ];
|
|
2153
|
+
results.forEach( ( r ) => {
|
|
2154
|
+
if ( r?.featureName === 'Matched/Not Matched' ) values.push( r?.value );
|
|
2155
|
+
} );
|
|
2156
|
+
} );
|
|
2157
|
+
return values;
|
|
2158
|
+
};
|
|
2159
|
+
|
|
2144
2160
|
for ( let section of sectionFormat ) {
|
|
2145
2161
|
for ( let question of section.questions ) {
|
|
2146
2162
|
let mustValidate = !question.linkType || ( question.linkType && question.linkquestionenabled );
|
|
@@ -2148,8 +2164,32 @@ export async function sopMobilechecklistMultiSectionFormatterv2( req, res, next
|
|
|
2148
2164
|
return res.sendError( 'Please Fill All Fields', 400 );
|
|
2149
2165
|
}
|
|
2150
2166
|
if ( question.compliance ) {
|
|
2151
|
-
|
|
2152
|
-
|
|
2167
|
+
let score = 0;
|
|
2168
|
+
|
|
2169
|
+
// image / image/video: when runAI verdicts are already present on the userAnswer,
|
|
2170
|
+
// derive compliance from them (every "Matched/Not Matched" must be True to count as
|
|
2171
|
+
// matched, else not matched), mirroring countUpdateRunAI.
|
|
2172
|
+
const aiAnswers = question.answerType === 'image/video' ?
|
|
2173
|
+
( question.userAnswer || [] ).filter( ( ua ) => ua?.answerType === 'image' ) :
|
|
2174
|
+
( question.userAnswer || [] );
|
|
2175
|
+
const hasRunAIData = [ 'image', 'image/video' ].includes( question.answerType ) &&
|
|
2176
|
+
aiAnswers.some( ( ua ) => Array.isArray( ua?.runAIData ) && ua.runAIData.length );
|
|
2177
|
+
|
|
2178
|
+
if ( hasRunAIData ) {
|
|
2179
|
+
const matchValues = aiAnswers.flatMap( ( ua ) => extractMatchValues( ua?.runAIData ) );
|
|
2180
|
+
const allMatched = matchValues.length > 0 && matchValues.every( ( v ) => v === 'True' || v === true );
|
|
2181
|
+
score = allMatched ?
|
|
2182
|
+
( question.answers?.[0]?.matchedCount ?? 0 ) :
|
|
2183
|
+
( question.answers?.[0]?.notMatchedCount ?? 0 );
|
|
2184
|
+
// Persist the derived score onto each userAnswer so PDF/dashboard reads stay consistent.
|
|
2185
|
+
( question.userAnswer || [] ).forEach( ( ua ) => {
|
|
2186
|
+
ua.complianceScore = score;
|
|
2187
|
+
} );
|
|
2188
|
+
} else {
|
|
2189
|
+
const scores = ( question.userAnswer || [] ).map( ( ua ) => ua?.complianceScore ?? 0 );
|
|
2190
|
+
score = scores.length ? Math.max( ...scores ) : 0;
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2153
2193
|
// Single-choice questions answered 'NA' / 'N/A' (case-insensitive) contribute 0;
|
|
2154
2194
|
// don't count the selected answer's compliance score for that question.
|
|
2155
2195
|
if ( question.answerType === 'multiplechoicesingle' ) {
|