@@ -25,6 +25,16 @@ import {
2525} from '../../utils/xls' ;
2626import { updateNilVerificationBodyAsEmptyString } from '../../utils/helpers.js' ;
2727
28+ const buildAssociationIncludes = ( ModelClass ) =>
29+ ModelClass . getAssociatedModels ( ) . map ( ( association ) => {
30+ return {
31+ model : association . model ,
32+ as : formatModelAssociationName ( association ) ,
33+ } ;
34+ } ) ;
35+
36+ const dedupe = ( values ) => _ . uniq ( values . filter ( Boolean ) ) ;
37+
2838class Staging extends Model {
2939 static changes = new rxjs . Subject ( ) ;
3040
@@ -316,100 +326,141 @@ class Staging extends Model {
316326 } ;
317327
318328 static getDiffObject = async ( uuid , table , action , data ) => {
319- const diff = { } ;
320- if ( action === 'INSERT' ) {
321- diff . original = { } ;
322- diff . change = JSON . parse ( data ) ;
323- }
329+ const [ diff ] = await Staging . getDiffObjects ( [ { uuid, table, action, data } ] ) ;
330+ return diff ;
331+ } ;
324332
325- if ( action === 'UPDATE' ) {
326- diff . change = JSON . parse ( data ) ;
327-
328- let original ;
329-
330- if ( table === 'Projects' ) {
331- original = await Project . findOne ( {
332- where : { warehouseProjectId : uuid } ,
333- include : Project . getAssociatedModels ( ) . map ( ( association ) => {
334- return {
335- model : association . model ,
336- as : formatModelAssociationName ( association ) ,
337- } ;
338- } ) ,
339- } ) ;
340-
341- // Show the issuance data if its being reused
342- // this is just for view purposes onlys
343- await Promise . all (
344- diff . change . map ( async ( record ) => {
345- if ( record . issuanceId ) {
346- const issuance = await Issuance . findOne ( {
347- where : { id : record . issuanceId } ,
348- } ) ;
349-
350- record . issuance = issuance . dataValues ;
351- }
352- } ) ,
353- ) ;
354- } else if ( table === 'Units' ) {
355- original = await Unit . findOne ( {
356- where : { warehouseUnitId : uuid } ,
357- include : Unit . getAssociatedModels ( ) . map ( ( association ) => {
358- return {
359- model : association . model ,
360- as : formatModelAssociationName ( association ) ,
361- } ;
362- } ) ,
363- } ) ;
364-
365- // Show the issuance data if its being reused,
366- // this is just for view purposes onlys
367- await Promise . all (
368- diff . change . map ( async ( record ) => {
369- if ( record . issuanceId ) {
370- const issuance = await Issuance . findOne ( {
371- where : { id : record . issuanceId } ,
372- } ) ;
373-
374- record . issuance = issuance . dataValues ;
375- }
376- } ) ,
377- ) ;
333+ static getDiffObjects = async ( stagingRecords ) => {
334+ const normalizedRecords = stagingRecords . map ( ( record ) => {
335+ if ( ! record ) {
336+ return record ;
378337 }
379338
380- diff . original = original ;
381- }
339+ return record . dataValues ? record . dataValues : record ;
340+ } ) ;
382341
383- if ( action === 'DELETE' ) {
384- let original ;
385-
386- if ( table === 'Projects' ) {
387- original = await Project . findOne ( {
388- where : { warehouseProjectId : uuid } ,
389- include : Project . getAssociatedModels ( ) . map ( ( association ) => {
390- return {
391- model : association . model ,
392- as : formatModelAssociationName ( association ) ,
393- } ;
394- } ) ,
395- } ) ;
396- } else if ( table === 'Units' ) {
397- original = await Unit . findOne ( {
398- where : { warehouseUnitId : uuid } ,
399- include : Unit . getAssociatedModels ( ) . map ( ( association ) => {
400- return {
401- model : association . model ,
402- as : formatModelAssociationName ( association ) ,
403- } ;
404- } ) ,
405- } ) ;
342+ const parsedChanges = normalizedRecords . map ( ( record ) => {
343+ if ( ! record || record . action !== 'UPDATE' ) {
344+ return null ;
406345 }
407346
408- diff . original = original ;
409- diff . change = { } ;
410- }
347+ return JSON . parse ( record . data ) ;
348+ } ) ;
411349
412- return diff ;
350+ const unitIds = dedupe (
351+ normalizedRecords
352+ . filter (
353+ ( record ) =>
354+ record &&
355+ record . table === 'Units' &&
356+ [ 'UPDATE' , 'DELETE' ] . includes ( record . action ) ,
357+ )
358+ . map ( ( record ) => record . uuid ) ,
359+ ) ;
360+ const projectIds = dedupe (
361+ normalizedRecords
362+ . filter (
363+ ( record ) =>
364+ record &&
365+ record . table === 'Projects' &&
366+ [ 'UPDATE' , 'DELETE' ] . includes ( record . action ) ,
367+ )
368+ . map ( ( record ) => record . uuid ) ,
369+ ) ;
370+ const issuanceIds = dedupe (
371+ normalizedRecords . flatMap ( ( record , index ) => {
372+ if (
373+ ! record ||
374+ record . action !== 'UPDATE' ||
375+ ! [ 'Projects' , 'Units' ] . includes ( record . table )
376+ ) {
377+ return [ ] ;
378+ }
379+
380+ return ( parsedChanges [ index ] || [ ] ) . map ( ( changeRecord ) => changeRecord . issuanceId ) ;
381+ } ) ,
382+ ) ;
383+
384+ const [ units , projects , issuances ] = await Promise . all ( [
385+ unitIds . length
386+ ? Unit . findAll ( {
387+ where : { warehouseUnitId : { [ Op . in ] : unitIds } } ,
388+ include : buildAssociationIncludes ( Unit ) ,
389+ } )
390+ : [ ] ,
391+ projectIds . length
392+ ? Project . findAll ( {
393+ where : { warehouseProjectId : { [ Op . in ] : projectIds } } ,
394+ include : buildAssociationIncludes ( Project ) ,
395+ } )
396+ : [ ] ,
397+ issuanceIds . length
398+ ? Issuance . findAll ( {
399+ where : { id : { [ Op . in ] : issuanceIds } } ,
400+ } )
401+ : [ ] ,
402+ ] ) ;
403+
404+ const unitsById = new Map (
405+ units . map ( ( record ) => [ record . warehouseUnitId , record ] ) ,
406+ ) ;
407+ const projectsById = new Map (
408+ projects . map ( ( record ) => [ record . warehouseProjectId , record ] ) ,
409+ ) ;
410+ const issuancesById = new Map (
411+ issuances . map ( ( record ) => [ record . id , record . dataValues ] ) ,
412+ ) ;
413+
414+ return normalizedRecords . map ( ( record , index ) => {
415+ const diff = { } ;
416+
417+ if ( record . action === 'INSERT' ) {
418+ diff . original = { } ;
419+ diff . change = JSON . parse ( record . data ) ;
420+ return diff ;
421+ }
422+
423+ if ( record . action === 'UPDATE' ) {
424+ diff . change = parsedChanges [ index ] ;
425+
426+ if ( [ 'Projects' , 'Units' ] . includes ( record . table ) ) {
427+ diff . change . forEach ( ( changeRecord ) => {
428+ if ( changeRecord . issuanceId ) {
429+ if ( ! issuancesById . has ( changeRecord . issuanceId ) ) {
430+ logger . warn (
431+ `[v1][staging:getDiffObjects] Missing issuance '${ changeRecord . issuanceId } ' for staged ${ record . table } record '${ record . uuid } '` ,
432+ ) ;
433+ throw new Error (
434+ `Could not find issuance '${ changeRecord . issuanceId } ' for staged ${ record . table } record '${ record . uuid } '` ,
435+ ) ;
436+ }
437+
438+ changeRecord . issuance = issuancesById . get ( changeRecord . issuanceId ) ;
439+ }
440+ } ) ;
441+ }
442+
443+ diff . original =
444+ record . table === 'Projects'
445+ ? projectsById . get ( record . uuid ) ?? null
446+ : record . table === 'Units'
447+ ? unitsById . get ( record . uuid ) ?? null
448+ : undefined ;
449+ return diff ;
450+ }
451+
452+ if ( record . action === 'DELETE' ) {
453+ diff . original =
454+ record . table === 'Projects'
455+ ? projectsById . get ( record . uuid ) ?? null
456+ : record . table === 'Units'
457+ ? unitsById . get ( record . uuid ) ?? null
458+ : undefined ;
459+ diff . change = { } ;
460+ }
461+
462+ return diff ;
463+ } ) ;
413464 } ;
414465
415466 static seperateStagingDataIntoActionGroups = ( stagedData , table ) => {
0 commit comments