import { Sum, HandlerSetter, ItemSelector } from 'interfaces'; import Operation from '../Operation'; import checkCondition from './checkCondition'; export default function getSumHandlers( parentEntityType: string, propKey: string, propValue: Sum ): {selfHandlerSetters: Array, childHandlerSetters: Array} { // ---------- selfHandler ---------- const selfHandlerSetter: HandlerSetter = { handlerHolder: 'SELF', // 'SELF' = parent onAdd: [{ updatingParentType: null, operationModifier: (parentOperation: Operation) => { // so, selfOperation = parentOperation parentOperation.modify({ [propKey]: 0 }); } }], onUpdate: [], onDelete: [] }; // ---------- childHandler ---------- const { childEntityType, childPropKey, conditions } = propValue; const checkNeedUpdatingParents = (childOperation: Operation, beforeParentItemSelectors: ItemSelector[], afterParentItemSelectors: ItemSelector[] ) => { let needUpdate: boolean = false; const deltas = {}; beforeParentItemSelectors.forEach(s => deltas[s.id] = 0); afterParentItemSelectors.forEach(s => deltas[s.id] = 0); const beforeChildNum = +childOperation.before[childPropKey] || 0; const isBeforeChildOnCondition = checkCondition(childOperation.before, conditions); if (isBeforeChildOnCondition) { beforeParentItemSelectors.forEach(s => deltas[s.id] -= beforeChildNum); } const afterChildNum = +childOperation.after[childPropKey] || 0; const isAfterChildOnCondition = checkCondition(childOperation.after, conditions); if (isAfterChildOnCondition) { afterParentItemSelectors.forEach(s => deltas[s.id] += afterChildNum); } Object.keys(deltas).forEach(parentId => { if (deltas[parentId] !== 0) needUpdate = true; }); return needUpdate; } const updateSumOfParentOperations = ( childOperation: Operation, beforeParentOperations: Array, afterParentOperations: Array ) => { const beforeChildNum = +childOperation.before[childPropKey] || 0; const isBeforeChildOnCondition = checkCondition(childOperation.before, conditions); if (isBeforeChildOnCondition) { beforeParentOperations.forEach((parentOperation) => { parentOperation.addNumToProp(propKey, -beforeChildNum); }); } const afterChildNum = +childOperation.after[childPropKey] || 0; const isAfterChildOnCondition = checkCondition(childOperation.after, conditions); if (isAfterChildOnCondition) { afterParentOperations.forEach((parentOperation) => { parentOperation.addNumToProp(propKey, afterChildNum); }); } }; const childHandlerSetter: HandlerSetter = { handlerHolder: childEntityType, onAdd: [{ checkNeedUpdatingParents, updatingParentType: parentEntityType, operationModifier: ( childOperation: Operation, beforeParentOperations: Array, afterParentOperations: Array ) => { updateSumOfParentOperations(childOperation, beforeParentOperations, afterParentOperations); } }], onUpdate: [{ checkNeedUpdatingParents, updatingParentType: parentEntityType, operationModifier: ( childOperation: Operation, beforeParentOperations: Array, afterParentOperations: Array ) => { updateSumOfParentOperations(childOperation, beforeParentOperations, afterParentOperations); } }], onDelete: [{ checkNeedUpdatingParents, updatingParentType: parentEntityType, operationModifier: ( childOperation: Operation, beforeParentOperations: Array, afterParentOperations: Array ) => { updateSumOfParentOperations(childOperation, beforeParentOperations, afterParentOperations); } }] }; return { selfHandlerSetters: [selfHandlerSetter], childHandlerSetters: [childHandlerSetter] }; }