|
30 | 30 |
|
31 | 31 | /** |
32 | 32 | * Export strategy for PNEU (Invasive Pneumococcal Infection) disease exports. |
33 | | - * PNEU follows the EpiPulse metadata specification exactly with 49 fixed columns (no repeatable fields). |
| 33 | + * PNEU follows the EpiPulse metadata specification with 56 total columns (28 common + 28 PNEU-specific). |
34 | 34 | * <p> |
35 | | - * Metadata specification: |
36 | | - * - 13 common demographic fields |
37 | | - * - 5 clinical/diagnostic fields (including DateOfDiagnosis, ClinicalCriteria) |
38 | | - * - 2 laboratory fields (PathogenDetectionMethod, Serotype) |
39 | | - * - 23 vaccination fields (detailed PCV1-4 and PPV tracking) |
40 | | - * - 9 AST fields (antimicrobial susceptibility for CTX/CFX, ERY, PEN) |
| 35 | + * Column breakdown: |
| 36 | + * - 28 common fields (demographic, case identification, hospitalization, outcome) |
| 37 | + * - 28 PNEU-specific fields: |
| 38 | + * - 1 NRL field (NRLData) |
| 39 | + * - 5 clinical/diagnostic fields (DateOfDiagnosis, meningitis, septicaemia, pneumonia -> ClinicalCriteria) |
| 40 | + * - 2 laboratory fields (PathogenDetectionMethod, Serotype) |
| 41 | + * - 11 PCV vaccination fields (DatePCV1-4, BrandPCV1-4, DosePCV1-4 derived, PcvDoses) |
| 42 | + * - 2 PPV vaccination fields (DatePPV, PpvDoses) |
| 43 | + * - 10 AST fields (AstMethod, MicSign/MicValue/SIR for CTX_CFX, ERY, PEN) |
41 | 44 | */ |
42 | 45 | @Stateless |
43 | 46 | @LocalBean |
@@ -65,15 +68,15 @@ protected String buildDiseaseExportQuery() { |
65 | 68 | // Note: AST data not currently stored in SORMAS for PNEU - fields will be NULL |
66 | 69 | // query.append(buildPneuAstDataCte()); |
67 | 70 |
|
68 | | - // Main SELECT clause with all 49 PNEU fields |
| 71 | + // Main SELECT clause with all 56 columns (28 common + 28 PNEU-specific) |
69 | 72 | query.append(buildPneuSelectClause()); |
70 | 73 |
|
71 | 74 | return query.toString(); |
72 | 75 | } |
73 | 76 |
|
74 | 77 | /** |
75 | | - * Maps all 21 PNEU-specific fields from SQL result row to DTO |
76 | | - * (Common fields already mapped by parent class - 28 fields) |
| 78 | + * Maps all 28 PNEU-specific fields from SQL result row to DTO. |
| 79 | + * Common fields (28) are already mapped by parent class, giving 56 total columns. |
77 | 80 | */ |
78 | 81 | @Override |
79 | 82 | protected void mapDiseaseSpecificFields(EpipulseDiseaseExportEntryDto dto, Object[] row, int startIndex) { |
@@ -206,8 +209,7 @@ protected void mapDiseaseSpecificFields(EpipulseDiseaseExportEntryDto dto, Objec |
206 | 209 |
|
207 | 210 | @Override |
208 | 211 | protected void calculateDiseaseSpecificMaxCounts(List<EpipulseDiseaseExportEntryDto> entries, EpipulseDiseaseExportResult result) { |
209 | | - // PNEU has no repeatable fields according to metadata specification |
210 | | - // All 49 columns are fixed - no dynamic column generation needed |
| 212 | + // PNEU has no repeatable fields - all 56 columns are fixed (no dynamic column generation needed) |
211 | 213 | // Common repeatable fields (pathogenTests, immunizations) are handled by parent class |
212 | 214 | } |
213 | 215 |
|
@@ -269,36 +271,39 @@ private String buildPneuClinicalCriteriaCte() { |
269 | 271 | */ |
270 | 272 | private String buildPneuVaccinationDetailsCte() { |
271 | 273 | //@formatter:off |
272 | | - return "pneu_vaccination_details AS (" + |
273 | | - " SELECT c.id as case_id," + |
274 | | - " MAX(CASE WHEN is_pcv AND pcv_row_num = 1 THEN v.vaccinationdate END) as date_pcv1," + |
275 | | - " MAX(CASE WHEN is_pcv AND pcv_row_num = 1 THEN CAST(v.vaccinename AS text) END) as brand_pcv1," + |
276 | | - " MAX(CASE WHEN is_pcv AND pcv_row_num = 2 THEN v.vaccinationdate END) as date_pcv2," + |
277 | | - " MAX(CASE WHEN is_pcv AND pcv_row_num = 2 THEN CAST(v.vaccinename AS text) END) as brand_pcv2," + |
278 | | - " MAX(CASE WHEN is_pcv AND pcv_row_num = 3 THEN v.vaccinationdate END) as date_pcv3," + |
279 | | - " MAX(CASE WHEN is_pcv AND pcv_row_num = 3 THEN CAST(v.vaccinename AS text) END) as brand_pcv3," + |
280 | | - " MAX(CASE WHEN is_pcv AND pcv_row_num = 4 THEN v.vaccinationdate END) as date_pcv4," + |
281 | | - " MAX(CASE WHEN is_pcv AND pcv_row_num = 4 THEN CAST(v.vaccinename AS text) END) as brand_pcv4," + |
282 | | - " SUM(CASE WHEN is_pcv THEN 1 ELSE 0 END) as pcv_doses," + |
283 | | - " MAX(CASE WHEN is_ppv AND ppv_row_num = 1 THEN v.vaccinationdate END) as date_ppv," + |
284 | | - " SUM(CASE WHEN is_ppv THEN 1 ELSE 0 END) as ppv_doses " + |
285 | | - " FROM filtered_cases c " + |
286 | | - " LEFT JOIN vaccination v ON v.immunization_id IN (SELECT i.id FROM immunization i WHERE i.person_id = c.person_id AND i.disease = 'INVASIVE_PNEUMOCOCCAL_INFECTION') " + |
287 | | - " LEFT JOIN LATERAL (" + |
288 | | - " SELECT CASE " + |
289 | | - " WHEN CAST(v.vaccinename AS text) LIKE '%PCV%' OR CAST(v.vaccinename AS text) LIKE '%CONJUGATE%' THEN true " + |
290 | | - " ELSE false " + |
291 | | - " END as is_pcv," + |
292 | | - " CASE " + |
293 | | - " WHEN CAST(v.vaccinename AS text) LIKE '%PPV%' OR CAST(v.vaccinename AS text) LIKE '%POLYSACCHARIDE%' THEN true " + |
294 | | - " ELSE false " + |
295 | | - " END as is_ppv," + |
296 | | - " SUM(CASE WHEN CAST(v.vaccinename AS text) LIKE '%PCV%' OR CAST(v.vaccinename AS text) LIKE '%CONJUGATE%' THEN 1 ELSE 0 END) " + |
297 | | - " OVER (PARTITION BY c.id ORDER BY v.vaccinationdate) as pcv_row_num," + |
298 | | - " SUM(CASE WHEN CAST(v.vaccinename AS text) LIKE '%PPV%' OR CAST(v.vaccinename AS text) LIKE '%POLYSACCHARIDE%' THEN 1 ELSE 0 END) " + |
299 | | - " OVER (PARTITION BY c.id ORDER BY v.vaccinationdate) as ppv_row_num " + |
300 | | - " ) vax_info ON true " + |
301 | | - " GROUP BY c.id) "; |
| 274 | + return "pneu_vaccination_details AS (" + |
| 275 | + " SELECT vax.case_id," + |
| 276 | + " MAX(CASE WHEN vax.is_pcv AND vax.pcv_row_num = 1 THEN vax.vaccinationdate END) as date_pcv1," + |
| 277 | + " MAX(CASE WHEN vax.is_pcv AND vax.pcv_row_num = 1 THEN CAST(vax.vaccinename AS text) END) as brand_pcv1," + |
| 278 | + " MAX(CASE WHEN vax.is_pcv AND vax.pcv_row_num = 2 THEN vax.vaccinationdate END) as date_pcv2," + |
| 279 | + " MAX(CASE WHEN vax.is_pcv AND vax.pcv_row_num = 2 THEN CAST(vax.vaccinename AS text) END) as brand_pcv2," + |
| 280 | + " MAX(CASE WHEN vax.is_pcv AND vax.pcv_row_num = 3 THEN vax.vaccinationdate END) as date_pcv3," + |
| 281 | + " MAX(CASE WHEN vax.is_pcv AND vax.pcv_row_num = 3 THEN CAST(vax.vaccinename AS text) END) as brand_pcv3," + |
| 282 | + " MAX(CASE WHEN vax.is_pcv AND vax.pcv_row_num = 4 THEN vax.vaccinationdate END) as date_pcv4," + |
| 283 | + " MAX(CASE WHEN vax.is_pcv AND vax.pcv_row_num = 4 THEN CAST(vax.vaccinename AS text) END) as brand_pcv4," + |
| 284 | + " SUM(CASE WHEN vax.is_pcv THEN 1 ELSE 0 END) as pcv_doses," + |
| 285 | + " MAX(CASE WHEN vax.is_ppv AND vax.ppv_row_num = 1 THEN vax.vaccinationdate END) as date_ppv," + |
| 286 | + " SUM(CASE WHEN vax.is_ppv THEN 1 ELSE 0 END) as ppv_doses " + |
| 287 | + " FROM (" + |
| 288 | + " SELECT c.id as case_id," + |
| 289 | + " v.vaccinationdate," + |
| 290 | + " v.vaccinename," + |
| 291 | + " CASE " + |
| 292 | + " WHEN CAST(v.vaccinename AS text) LIKE '%PCV%' OR CAST(v.vaccinename AS text) LIKE '%CONJUGATE%' THEN true " + |
| 293 | + " ELSE false " + |
| 294 | + " END as is_pcv," + |
| 295 | + " CASE " + |
| 296 | + " WHEN CAST(v.vaccinename AS text) LIKE '%PPV%' OR CAST(v.vaccinename AS text) LIKE '%POLYSACCHARIDE%' THEN true " + |
| 297 | + " ELSE false " + |
| 298 | + " END as is_ppv," + |
| 299 | + " SUM(CASE WHEN CAST(v.vaccinename AS text) LIKE '%PCV%' OR CAST(v.vaccinename AS text) LIKE '%CONJUGATE%' THEN 1 ELSE 0 END) " + |
| 300 | + " OVER (PARTITION BY c.id ORDER BY v.vaccinationdate) as pcv_row_num," + |
| 301 | + " SUM(CASE WHEN CAST(v.vaccinename AS text) LIKE '%PPV%' OR CAST(v.vaccinename AS text) LIKE '%POLYSACCHARIDE%' THEN 1 ELSE 0 END) " + |
| 302 | + " OVER (PARTITION BY c.id ORDER BY v.vaccinationdate) as ppv_row_num " + |
| 303 | + " FROM filtered_cases c " + |
| 304 | + " LEFT JOIN vaccination v ON v.immunization_id IN (SELECT i.id FROM immunization i WHERE i.person_id = c.person_id AND i.disease = 'INVASIVE_PNEUMOCOCCAL_INFECTION') " + |
| 305 | + " ) vax " + |
| 306 | + " GROUP BY vax.case_id) "; |
302 | 307 | //@formatter:on |
303 | 308 | } |
304 | 309 |
|
@@ -331,12 +336,12 @@ private String buildPneuAstDataCte() { |
331 | 336 | } |
332 | 337 |
|
333 | 338 | /** |
334 | | - * Builds SELECT clause with all 49 PNEU fields following metadata specification |
| 339 | + * Builds SELECT clause with all 56 columns (28 common + 28 PNEU-specific). |
335 | 340 | */ |
336 | 341 | private String buildPneuSelectClause() { |
337 | 342 | StringBuilder select = new StringBuilder(); |
338 | 343 | //@formatter:off |
339 | | - // Use common SELECT fields (28 fields) and append PNEU-specific fields (21 fields) |
| 344 | + // Use common SELECT fields (28 fields) and append PNEU-specific fields (28 fields) |
340 | 345 | select.append("SELECT ") |
341 | 346 | .append(sqlCteBuilder.buildCommonSelectFields()) |
342 | 347 | .append(",") |
|
0 commit comments