@@ -353,27 +353,157 @@ export class GenericController {
353353 return Promise . all (
354354 records . map ( ( r ) => this . getById ( modelName , r . getDataValue ( "id" ) ) ) ,
355355 ) ;
356- /*
356+ }
357357
358- We need it to return like this
358+ /** Filter records dynamically based on provided query parameters */
359+ static async cascade_filter < T extends ModelKey > ( modelName : T , filters : any ) {
360+ console . log ( `Filtering ${ modelName } with filters:` , filters ) ;
359361
360- return records.map((paper) => {
361- const paperData = paper.get({ plain: true });
362+ const formattedName = this . formatModelName ( modelName ) ;
363+ const model = models [ formattedName ] ;
364+
365+ if ( ! model ) {
366+ return { error : `Invalid model name: ${ modelName } ` , status : 400 } ;
367+ }
368+
369+ // Prepare conditions for each model
370+ const whereConditions : Record < string , any > = { } ;
371+ const includeRelations : any [ ] = [ ] ;
372+
373+ // Extract filters for different models
374+ const modelFilters : Record < string , any > = {
375+ paper : { } ,
376+ parts : { } ,
377+ tids : { } ,
378+ sees : { } ,
379+ dds : { } ,
380+ } ;
381+
382+ for ( const key in filters ) {
383+ if ( ! filters [ key ] ) continue ;
384+
385+ if ( key . includes ( "." ) ) {
386+ const [ relation , field ] = key . split ( "." ) ;
387+ if ( modelFilters [ relation ] !== undefined ) {
388+ modelFilters [ relation ] [ field ] = filters [ key ] ;
389+ } else {
390+ console . warn ( `Invalid related model in filter: ${ relation } ` ) ;
391+ return { error : `Invalid relation '${ relation } '` , status : 400 } ;
392+ }
393+ } else {
394+ modelFilters . paper [ key ] = filters [ key ] ; // Direct paper filters
395+ }
396+ }
362397
398+ console . log ( "Parsed Filters:" , modelFilters ) ;
399+
400+ // Build Include Array Dynamically
401+ const buildInclude = ( modelKey : string , modelRef : any , alias : string ) => {
402+ if ( Object . keys ( modelFilters [ modelKey ] ) . length > 0 ) {
403+ return {
404+ model : modelRef ,
405+ as : alias ,
406+ required : true , // Enforce filtering at SQL level
407+ where : modelFilters [ modelKey ] ,
408+ attributes : {
409+ exclude : [ "createdAt" , "updatedAt" , "paperId" , "partId" ] ,
410+ } , // Exclude unwanted fields
411+ } ;
412+ }
363413 return {
364- ...paperData,
365- authors: Array.isArray(paperData.authors) ? paperData.authors : [],
366- parts: Array.isArray(paperData.parts)
367- ? paperData.parts.map((part: any) => ({
368- ...part,
369- tids: Array.isArray(part.tids) ? part.tids : [],
370- sees: Array.isArray(part.sees) ? part.sees : [],
371- dds: Array.isArray(part.dds) ? part.dds : [],
372- }))
373- : [],
414+ model : modelRef ,
415+ as : alias ,
416+ attributes : {
417+ exclude : [ "createdAt" , "updatedAt" , "paperId" , "partId" ] ,
418+ } , // Exclude unwanted fields
374419 } ;
420+ } ;
421+
422+ // Fetch filtered records
423+ const records = await models . Paper . findAll ( {
424+ where : modelFilters . paper ,
425+ include : [
426+ {
427+ model : models . Author ,
428+ as : "authors" ,
429+ attributes : { exclude : [ "createdAt" , "updatedAt" , "paper_author" ] } ,
430+ through : {
431+ attributes : [ ] , // This will exclude the 'paper_author' relationship table fields
432+ } ,
433+ } , // Exclude fields for authors
434+ buildInclude ( "parts" , models . Part , "parts" ) ,
435+ {
436+ model : models . Part ,
437+ as : "parts" ,
438+ required : Object . keys ( modelFilters . parts ) . length > 0 ,
439+ where : modelFilters . parts ,
440+ include : [
441+ buildInclude ( "tids" , models . Tid , "tids" ) ,
442+ buildInclude ( "sees" , models . See , "sees" ) ,
443+ buildInclude ( "dds" , models . Dd , "dds" ) ,
444+ ] ,
445+ attributes : { exclude : [ "createdAt" , "updatedAt" , "paper_part" ] } , // Exclude fields for parts
446+ through : {
447+ attributes : [ ] , // This will exclude the 'paper_author' relationship table fields
448+ } ,
449+ } ,
450+ ] ,
451+ attributes : { exclude : [ "createdAt" , "updatedAt" ] } , // Exclude fields for parts
452+ } ) ;
453+
454+ console . log ( "Found records:" , records . length ) ;
455+
456+ // Flatten Results & Remove Unfiltered Tests
457+ return records . flatMap ( ( paper ) => {
458+ const paperData = paper . get ( { plain : true } ) ;
459+ const { parts, ...paperWithoutParts } = paperData ;
460+
461+ return parts . flatMap ( ( part : any ) => {
462+ const { tids, sees, dds, ...partWithoutTests } = part ;
463+
464+ return [
465+ ...tids
466+ . filter (
467+ ( t : { [ x : string ] : any } ) =>
468+ Object . keys ( modelFilters . tids ) . length === 0 ||
469+ modelFilters . tids . some (
470+ ( f : string | number ) => t [ f ] === filters [ `tids.${ f } ` ] ,
471+ ) ,
472+ )
473+ . map ( ( tid : any ) => ( {
474+ paper : paperWithoutParts ,
475+ part : partWithoutTests ,
476+ tid,
477+ } ) ) ,
478+ ...sees
479+ . filter (
480+ ( s : { [ x : string ] : any } ) =>
481+ Object . keys ( modelFilters . sees ) . length === 0 ||
482+ modelFilters . sees . some (
483+ ( f : string | number ) => s [ f ] === filters [ `sees.${ f } ` ] ,
484+ ) ,
485+ )
486+ . map ( ( see : any ) => ( {
487+ paper : paperWithoutParts ,
488+ part : partWithoutTests ,
489+ see,
490+ } ) ) ,
491+ ...dds
492+ . filter (
493+ ( d : { [ x : string ] : any } ) =>
494+ Object . keys ( modelFilters . dds ) . length === 0 ||
495+ modelFilters . dds . some (
496+ ( f : string | number ) => d [ f ] === filters [ `dds.${ f } ` ] ,
497+ ) ,
498+ )
499+ . map ( ( dd : any ) => ( {
500+ paper : paperWithoutParts ,
501+ part : partWithoutTests ,
502+ dd,
503+ } ) ) ,
504+ ] ;
505+ } ) ;
375506 } ) ;
376- */
377507 }
378508
379509 /** Create full paper along with related entities */
0 commit comments