daniel-san
Version:
a node-based budget-projection engine that helps your routines and finances find balance. The program features aggregates, terminal and file-based reporting output, multi-currency conversion capability and multi-frequency accounting triggers, including: o
911 lines (789 loc) • 31.9 kB
JavaScript
"use strict";
var moment = require('moment');
var _require = require('../utility/errorHandling'),
errorDisc = _require.errorDisc;
var _require2 = require('../utility/validation'),
isUndefinedOrNull = _require2.isUndefinedOrNull;
var _require3 = require('../utility/dataStructures'),
deepCopy = _require3.deepCopy;
var _require4 = require('../timeZone'),
initializeTimeZoneData = _require4.initializeTimeZoneData,
createTimeZone = _require4.createTimeZone,
convertTimeZone = _require4.convertTimeZone;
var _require5 = require('../timeStream'),
TimeStream = _require5.TimeStream;
var _require6 = require('../constants'),
DATE_FORMAT_STRING = _require6.DATE_FORMAT_STRING,
ONCE = _require6.ONCE,
SUNDAY = _require6.SUNDAY,
MONDAY = _require6.MONDAY,
TUESDAY = _require6.TUESDAY,
WEDNESDAY = _require6.WEDNESDAY,
THURSDAY = _require6.THURSDAY,
FRIDAY = _require6.FRIDAY,
SATURDAY = _require6.SATURDAY,
POSITIVE = _require6.POSITIVE,
NEGATIVE = _require6.NEGATIVE,
BOTH = _require6.BOTH,
ANY = _require6.ANY,
UNION = _require6.UNION,
INTERSECTION = _require6.INTERSECTION,
DEFAULT = _require6.DEFAULT,
ASCENDING = _require6.ASCENDING,
DESCENDING = _require6.DESCENDING,
SUM = _require6.SUM,
AVERAGE = _require6.AVERAGE,
MEDIANS = _require6.MEDIANS,
MODES = _require6.MODES,
MIN = _require6.MIN,
MAX = _require6.MAX,
DEFAULT_SELECTION_LIMIT = _require6.DEFAULT_SELECTION_LIMIT;
var dropEventsWithDuplicateKey = function dropEventsWithDuplicateKey(_ref) {
var events = _ref.events,
uniqueKey = _ref.key;
if (isUndefinedOrNull(uniqueKey)) {
return events;
} else {
var set = new Set();
var newEvents = [];
events.forEach(function (event) {
if (!set.has(event[uniqueKey])) {
set.add(event[uniqueKey]);
newEvents.push(event);
}
});
return newEvents;
}
};
var sortEventsForReports = function sortEventsForReports(_ref2) {
var _ref2$sortKey = _ref2.sortKey,
sortKey = _ref2$sortKey === void 0 ? null : _ref2$sortKey,
_ref2$sortDirection = _ref2.sortDirection,
sortDirection = _ref2$sortDirection === void 0 ? ASCENDING : _ref2$sortDirection,
_ref2$selectionLimit = _ref2.selectionLimit,
selectionLimit = _ref2$selectionLimit === void 0 ? null : _ref2$selectionLimit,
_ref2$uniqueKey = _ref2.uniqueKey,
uniqueKey = _ref2$uniqueKey === void 0 ? null : _ref2$uniqueKey,
events = _ref2.events;
var eventsWithUniqueKeyCheck = dropEventsWithDuplicateKey({
events: events,
key: uniqueKey
}); // if uniqueKey was defined on reporting rule, then remove duplicates
if (isUndefinedOrNull(sortKey) || sortKey === DEFAULT || sortDirection === DEFAULT) {
var finalResult = eventsWithUniqueKeyCheck.slice(0, !isUndefinedOrNull(selectionLimit) && selectionLimit <= eventsWithUniqueKeyCheck.length ? selectionLimit : eventsWithUniqueKeyCheck.length);
return finalResult; // eslint-disable-next-line no-else-return
} else {
var sortingDirection = sortDirection === DESCENDING ? -1 : 1;
var sortedEvents = deepCopy(eventsWithUniqueKeyCheck).sort(function (aObj, bObj) {
var a = aObj[sortKey];
var b = bObj[sortKey];
if (a > b) {
return 1 * sortingDirection;
} else if (a < b) {
return -1 * sortingDirection; // eslint-disable-next-line no-else-return
} else {
return 0;
}
});
var finalCollection = sortedEvents.slice(0, !isUndefinedOrNull(selectionLimit) && selectionLimit <= sortedEvents.length ? selectionLimit : sortedEvents.length);
return finalCollection;
}
};
var sortAggregates = function sortAggregates(_ref3) {
var aggregateConfig = _ref3.aggregateConfig,
aggregates = _ref3.aggregates;
var newAggregates;
var configSortKey = aggregateConfig.sortKey;
var sortKey;
var sortDirection;
if (isUndefinedOrNull(aggregateConfig.sortKey)) {
configSortKey = DEFAULT;
}
if (configSortKey === DEFAULT || aggregateConfig.sortDirection === DEFAULT) {
return aggregates;
}
if (isUndefinedOrNull(aggregateConfig.sortDirection)) {
sortDirection = 1; // defaults to ASCENDING order
} else {
sortDirection = aggregateConfig.sortDirection === DESCENDING ? -1 : 1;
}
switch (configSortKey) {
case SUM:
sortKey = 'sum';
break;
case AVERAGE:
sortKey = 'average';
break;
case MEDIANS:
sortKey = 'medians';
break;
case MODES:
sortKey = 'modes';
break;
case MIN:
sortKey = 'min';
break;
case MAX:
sortKey = 'max';
break;
case DEFAULT:
return aggregates;
default:
sortKey = aggregateConfig.sortKey;
}
if (sortKey === 'medians' || sortKey === 'modes') {
newAggregates = deepCopy(aggregates).sort(function (aObj, bObj) {
var aList = aObj[sortKey];
var bList = bObj[sortKey];
var sortResult = -1;
aList.some(function (a) {
return bList.some(function (b) {
if (a > b) {
sortResult = 1 * sortDirection;
if (sortDirection === ASCENDING) return true;
} else if (a < b) {
sortResult = -1 * sortDirection;
if (sortDirection === DESCENDING) return true; // eslint-disable-next-line no-else-return
} else {
sortResult = 0;
}
});
});
return sortResult;
});
} else {
newAggregates = deepCopy(aggregates).sort(function (aObj, bObj) {
var a = aObj[sortKey];
var b = bObj[sortKey];
if (a > b) {
return 1 * sortDirection;
} else if (a < b) {
return -1 * sortDirection; // eslint-disable-next-line no-else-return
} else {
return 0;
}
});
}
var finalCollection = newAggregates.slice(0, !isUndefinedOrNull(aggregateConfig.selectionLimit) && aggregateConfig.selectionLimit <= newAggregates.length ? aggregateConfig.selectionLimit : newAggregates.length);
return finalCollection;
};
var isThisWithinXPercentOfThat = function isThisWithinXPercentOfThat(_ref4) {
var value = _ref4.value,
_ref4$xPercentRange = _ref4.xPercentRange,
xPercentRange = _ref4$xPercentRange === void 0 ? 0 : _ref4$xPercentRange,
xPercentTarget = _ref4.xPercentTarget;
// const difference = value - xPercentTarget;
var xPercentOfValue = Math.abs(xPercentRange * xPercentTarget);
var lowValue = xPercentTarget - xPercentOfValue;
var highValue = xPercentTarget + xPercentOfValue;
if (value >= lowValue && value <= highValue) {
return true; // eslint-disable-next-line no-else-return
} else {
return false;
}
}; // TODO: delete
// const isThisWithinXPercentOfThat = ({ value, xPercentRange = 0, xPercentTarget }) => {
// // const difference = value - xPercentTarget;
// const xPercentOfValue = Math.abs(xPercentRange * xPercentTarget);
// const lowValue = value - xPercentOfValue;
// const highValue = value + xPercentOfValue;
// if (xPercentTarget >= lowValue && xPercentTarget <= highValue) {
// return true;
// // eslint-disable-next-line no-else-return
// } else {
// return false;
// }
// };
var findEventsWithinXPercentOfValue = function findEventsWithinXPercentOfValue(_ref5) {
var events = _ref5.events,
_ref5$propertyKey = _ref5.propertyKey,
propertyKey = _ref5$propertyKey === void 0 ? 'balanceEnding' : _ref5$propertyKey,
_ref5$xPercentRange = _ref5.xPercentRange,
xPercentRange = _ref5$xPercentRange === void 0 ? 0 : _ref5$xPercentRange,
xPercentTarget = _ref5.xPercentTarget;
var newEvents = events.filter(function (event) {
return isThisWithinXPercentOfThat({
value: event[propertyKey],
xPercentRange: xPercentRange,
xPercentTarget: xPercentTarget
});
});
return newEvents || [];
};
var getWeekdayNumFromString = function getWeekdayNumFromString(weekdayString) {
var weekdayNum;
switch (weekdayString) {
case 'sunday':
weekdayNum = SUNDAY;
break;
case 'monday':
weekdayNum = MONDAY;
break;
case 'tuesday':
weekdayNum = TUESDAY;
break;
case 'wednesday':
weekdayNum = WEDNESDAY;
break;
case 'thursday':
weekdayNum = THURSDAY;
break;
case 'friday':
weekdayNum = FRIDAY;
break;
case 'saturday':
weekdayNum = SATURDAY;
break;
default:
weekdayNum = MONDAY;
break;
}
return weekdayNum;
};
var defaultStringComparator = function defaultStringComparator(filterKey, filterValue) {
return filterKey === filterValue;
};
var filterEventsByKeysAndValues = function filterEventsByKeysAndValues(_ref6) {
var events = _ref6.events,
_ref6$filterKeys = _ref6.filterKeys,
filterKeys = _ref6$filterKeys === void 0 ? [] : _ref6$filterKeys,
_ref6$filterValues = _ref6.filterValues,
filterValues = _ref6$filterValues === void 0 ? [] : _ref6$filterValues,
_ref6$filterType = _ref6.filterType,
filterType = _ref6$filterType === void 0 ? UNION : _ref6$filterType,
_ref6$filterComparato = _ref6.filterComparator,
filterComparator = _ref6$filterComparato === void 0 ? defaultStringComparator : _ref6$filterComparato;
if (isUndefinedOrNull(filterComparator)) {
filterComparator = defaultStringComparator;
}
if (isUndefinedOrNull(filterType)) {
filterType = UNION;
}
var transientEvent; // for errorDisc
try {
var newEvents = events; // default value
if (filterKeys && filterKeys.length > 0 && filterValues && filterValues.length === filterKeys.length) {
var duplicateEvents = deepCopy(events);
newEvents = duplicateEvents.filter(function (event) {
transientEvent = event;
var includeEvent = false;
for (var looper = 0; looper < filterKeys.length; looper++) {
if (!isUndefinedOrNull(event[filterKeys[looper]]) && (filterValues[looper] === ANY || filterComparator(event[filterKeys[looper]], filterValues[looper]))) {
includeEvent = true;
if (isUndefinedOrNull(filterType) || filterType === UNION) {
break;
}
} else {
includeEvent = false;
if (filterType === INTERSECTION) {
break;
}
}
}
return includeEvent;
});
}
return newEvents;
} catch (err) {
throw errorDisc({
err: err,
data: {
event: transientEvent,
filterKeys: filterKeys,
filterValues: filterValues,
filterType: filterType
}
});
}
}; // you should probably run the validation functions in core/validation.js prior to using this
// finds rules with end dates that are less than the beginning date range of the budget projection
var findRulesToRetire = function findRulesToRetire(danielSan) {
var effectiveDateStart = danielSan.config.effectiveDateStart;
var newRulesToRetire = []; // eslint-disable-next-line array-callback-return
danielSan.rules.forEach(function (rule, index) {
var dateToStartConfig = initializeTimeZoneData(danielSan);
var dateToStart = createTimeZone({
timeZone: dateToStartConfig.timeZone,
timeZoneType: dateToStartConfig.timeZoneType,
dateString: effectiveDateStart
});
var convertedDateToStartConfig = initializeTimeZoneData(rule);
var convertedDateToStart = convertTimeZone({
timeZone: convertedDateToStartConfig.timeZone,
timeZoneType: convertedDateToStartConfig.timeZoneType,
date: dateToStart
}).date;
var convertedDateStartString = convertedDateToStart.format(DATE_FORMAT_STRING);
if (!isUndefinedOrNull(rule.effectiveDateEnd) && rule.effectiveDateEnd < convertedDateStartString) {
rule.ruleIndex = index;
newRulesToRetire.push(rule);
} else if (rule.frequency === ONCE && typeof rule.processDate === 'string' && rule.processDate < convertedDateStartString) {
rule.ruleIndex = index;
newRulesToRetire.push(rule);
}
}); // TODO: below - couldn't we simply return newToRetire?
if (newRulesToRetire.length > 0) {
return newRulesToRetire; // eslint-disable-next-line no-else-return
} else {
return [];
} // eslint-disable-next-line no-unreachable
return []; // this line satisfies another linting error
}; // you should probably run the validation functions in core/validation.js prior to using this
// finds rules that have no chance of being triggered via the current configuration
var findIrrelevantRules = function findIrrelevantRules(danielSan) {
var rules = danielSan.rules,
_danielSan$config = danielSan.config,
effectiveDateStart = _danielSan$config.effectiveDateStart,
effectiveDateEnd = _danielSan$config.effectiveDateEnd,
timeZone = _danielSan$config.timeZone,
timeZoneType = _danielSan$config.timeZoneType;
var relevantRules = [];
var irrelevantRules = [];
rules.forEach(function (rule, index) {
var dateToStart = createTimeZone({
timeZone: timeZone,
timeZoneType: timeZoneType,
dateString: effectiveDateStart
});
var convertedDateToStart = convertTimeZone({
timeZone: rule.timeZone,
timeZoneType: rule.timeZoneType,
date: dateToStart
}).date;
var convertedDateToStartString = convertedDateToStart.format(DATE_FORMAT_STRING);
var dateToEnd = createTimeZone({
timeZone: timeZone,
timeZoneType: timeZoneType,
dateString: effectiveDateEnd
});
var convertedDateToEnd = convertTimeZone({
timeZone: rule.timeZone,
timeZoneType: rule.timeZoneType,
date: dateToEnd
}).date;
var convertedDateToEndString = convertedDateToEnd.format(DATE_FORMAT_STRING);
var allowToLive = true;
if (!isUndefinedOrNull(rule.effectiveDateEnd) && rule.effectiveDateEnd < convertedDateToStartString || !isUndefinedOrNull(rule.effectiveDateStart) && rule.effectiveDateStart > convertedDateToEndString) {
// exclude
allowToLive = false; // eslint-disable-next-line no-else-return
} else if (rule.frequency === ONCE && typeof rule.EventProcessDate === 'string' && rule.EventProcessDate < convertedDateToStartString) {
// exclude:
allowToLive = false;
} else if (isUndefinedOrNull(rule.effectiveDateEnd)) {
// include
allowToLive = true;
} else {
// include
allowToLive = true;
}
if (allowToLive) {
relevantRules.push(rule);
} else {
rule.ruleIndex = index;
irrelevantRules.push(rule);
}
});
return {
relevantRules: relevantRules,
irrelevantRules: irrelevantRules
};
};
var findEventsWithProperty = function findEventsWithProperty(_ref7) {
var events = _ref7.events,
propertyKey = _ref7.propertyKey;
// eslint-disable-next-line array-callback-return
var eventsFound = events.filter(function (event) {
// eslint-disable-line consistent-return
if (!isUndefinedOrNull(event[propertyKey])) {
return event; // eslint-disable-next-line no-else-return
} else {
return false;
}
});
if (eventsFound.length > 0) {
return eventsFound; // eslint-disable-next-line no-else-return
} else {
return null;
} // eslint-disable-next-line no-unreachable
return null; // this line satisfies another linting error
};
var findEventsByPropertyKeyAndValues = function findEventsByPropertyKeyAndValues(_ref8) {
var events = _ref8.events,
propertyKey = _ref8.propertyKey,
searchValues = _ref8.searchValues;
if (events && propertyKey && searchValues && Array.isArray(searchValues) && searchValues.length > 0) {
var eventsFound = [];
events.forEach(function (event) {
searchValues.forEach(function (searchCriteriaValue) {
var eventProperty = event[propertyKey];
if (!isUndefinedOrNull(eventProperty) && typeof eventProperty === 'string') {
eventProperty = eventProperty.toLowerCase();
}
var newSearchCriteriaValue = typeof searchCriteriaValue === 'string' ? searchCriteriaValue.toLowerCase() : searchCriteriaValue;
if (!isUndefinedOrNull(eventProperty) && eventProperty === newSearchCriteriaValue) {
eventsFound.push(event);
}
});
});
if (eventsFound && eventsFound.length > 0) {
return eventsFound; // eslint-disable-next-line no-else-return
} else {
return null;
} // eslint-disable-next-line no-else-return
} else {
return null;
}
};
var findEventsWithPropertyKeyContainingSubstring = function findEventsWithPropertyKeyContainingSubstring(_ref9) {
var events = _ref9.events,
propertyKey = _ref9.propertyKey,
substring = _ref9.substring;
var substrings;
if (typeof substring === 'string') {
substrings = [];
substrings.push(substring);
} else {
substrings = substring;
} // eslint-disable-next-line array-callback-return
var eventsFound = events.filter(function (event) {
// eslint-disable-next-line consistent-return
return substrings.some(function (string) {
// eslint-disable-line array-callback-return
// eslint-disable-line consistent-return
if (!isUndefinedOrNull(event[propertyKey]) && event[propertyKey].includes(string)) {
return true;
}
});
});
if (eventsFound.length > 0) {
return eventsFound; // eslint-disable-next-line no-else-return
} else {
return null;
} // eslint-disable-next-line no-unreachable
return null; // this line satisfies another linting error
};
var findCriticalSnapshots = function findCriticalSnapshots(_ref10) {
var _ref10$events = _ref10.events,
events = _ref10$events === void 0 ? [] : _ref10$events,
_ref10$criticalThresh = _ref10.criticalThreshold,
criticalThreshold = _ref10$criticalThresh === void 0 ? 0 : _ref10$criticalThresh,
_ref10$propertyKey = _ref10.propertyKey,
propertyKey = _ref10$propertyKey === void 0 ? 'balanceEnding' : _ref10$propertyKey;
var criticalSnapshots = [];
if (!isUndefinedOrNull(criticalThreshold)) {
criticalSnapshots = events.filter(function (event) {
if (!isUndefinedOrNull(event[propertyKey])) {
return event[propertyKey] < criticalThreshold; // eslint-disable-next-line no-else-return
} else {
return false;
}
});
}
return criticalSnapshots;
};
var findSnapshotsGreaterThanSupport = function findSnapshotsGreaterThanSupport(_ref11) {
var _ref11$events = _ref11.events,
events = _ref11$events === void 0 ? [] : _ref11$events,
_ref11$amount = _ref11.amount,
amount = _ref11$amount === void 0 ? 0 : _ref11$amount,
_ref11$propertyKey = _ref11.propertyKey,
propertyKey = _ref11$propertyKey === void 0 ? 'balanceEnding' : _ref11$propertyKey;
var newCollection = events.filter(function (element) {
if (!isUndefinedOrNull(element[propertyKey]) && element[propertyKey] > amount) {
return element; // eslint-disable-next-line no-else-return
} else {
return false;
}
});
return newCollection;
};
var findSnapshotsLessThanResistance = function findSnapshotsLessThanResistance(_ref12) {
var _ref12$events = _ref12.events,
events = _ref12$events === void 0 ? [] : _ref12$events,
_ref12$amount = _ref12.amount,
amount = _ref12$amount === void 0 ? 0 : _ref12$amount,
_ref12$propertyKey = _ref12.propertyKey,
propertyKey = _ref12$propertyKey === void 0 ? 'balanceEnding' : _ref12$propertyKey;
var newCollection = events.filter(function (element) {
if (!isUndefinedOrNull(element[propertyKey]) && element[propertyKey] < amount) {
return element; // eslint-disable-next-line no-else-return
} else {
return false;
}
});
return newCollection;
};
var findPositiveSnapshotsGreaterThanSupport = function findPositiveSnapshotsGreaterThanSupport(_ref13) {
var _ref13$events = _ref13.events,
events = _ref13$events === void 0 ? [] : _ref13$events,
_ref13$amount = _ref13.amount,
amount = _ref13$amount === void 0 ? 0 : _ref13$amount,
_ref13$propertyKey = _ref13.propertyKey,
propertyKey = _ref13$propertyKey === void 0 ? 'balanceEnding' : _ref13$propertyKey;
var newCollection = events.filter(function (element) {
if (!isUndefinedOrNull(element[propertyKey]) && element[propertyKey] > 0 && element[propertyKey] > amount) {
return element; // eslint-disable-next-line no-else-return
} else {
return false;
}
});
return newCollection;
};
var findPositiveSnapshotsLessThanResistance = function findPositiveSnapshotsLessThanResistance(_ref14) {
var _ref14$events = _ref14.events,
events = _ref14$events === void 0 ? [] : _ref14$events,
_ref14$amount = _ref14.amount,
amount = _ref14$amount === void 0 ? 0 : _ref14$amount,
_ref14$propertyKey = _ref14.propertyKey,
propertyKey = _ref14$propertyKey === void 0 ? 'balanceEnding' : _ref14$propertyKey;
var newCollection = events.filter(function (element) {
if (!isUndefinedOrNull(element[propertyKey]) && element[propertyKey] > 0 && element[propertyKey] < amount) {
return element; // eslint-disable-next-line no-else-return
} else {
return false;
}
});
return newCollection;
};
var findNegativeSnapshotsGreaterThanSupport = function findNegativeSnapshotsGreaterThanSupport(_ref15) {
var _ref15$events = _ref15.events,
events = _ref15$events === void 0 ? [] : _ref15$events,
_ref15$amount = _ref15.amount,
amount = _ref15$amount === void 0 ? 0 : _ref15$amount,
_ref15$propertyKey = _ref15.propertyKey,
propertyKey = _ref15$propertyKey === void 0 ? 'balanceEnding' : _ref15$propertyKey;
var newCollection = events.filter(function (element) {
if (!isUndefinedOrNull(element[propertyKey]) && element[propertyKey] < 0 && Math.abs(element[propertyKey]) > Math.abs(amount)) {
return element; // eslint-disable-next-line no-else-return
} else {
return false;
}
});
return newCollection;
};
var findNegativeSnapshotsLessThanResistance = function findNegativeSnapshotsLessThanResistance(_ref16) {
var _ref16$events = _ref16.events,
events = _ref16$events === void 0 ? [] : _ref16$events,
_ref16$amount = _ref16.amount,
amount = _ref16$amount === void 0 ? 0 : _ref16$amount,
_ref16$propertyKey = _ref16.propertyKey,
propertyKey = _ref16$propertyKey === void 0 ? 'balanceEnding' : _ref16$propertyKey;
var newCollection = events.filter(function (element) {
if (!isUndefinedOrNull(element[propertyKey]) && element[propertyKey] < 0 && Math.abs(element[propertyKey]) < Math.abs(amount)) {
return element; // eslint-disable-next-line no-else-return
} else {
return false;
}
});
return newCollection;
};
var isVal1GreaterThanVal2 = function isVal1GreaterThanVal2(val1, val2) {
return val1 > val2;
};
var isAbsVal1GreaterThanAbsVal2 = function isAbsVal1GreaterThanAbsVal2(val1, val2) {
return Math.abs(val1) > Math.abs(val2);
};
var isVal1LessThanVal2 = function isVal1LessThanVal2(val1, val2) {
return val1 < val2;
};
var isAbsVal1LessThanAbsVal2 = function isAbsVal1LessThanAbsVal2(val1, val2) {
return Math.abs(val1) < Math.abs(val2);
};
var filterEventsByFlowDirection = function filterEventsByFlowDirection(_ref17) {
var events = _ref17.events,
_ref17$propertyKey = _ref17.propertyKey,
propertyKey = _ref17$propertyKey === void 0 ? 'balanceEnding' : _ref17$propertyKey,
flowDirection = _ref17.flowDirection;
var deepCopyOfEvents = deepCopy(events);
var newEvents;
switch (flowDirection) {
case POSITIVE:
newEvents = deepCopyOfEvents.filter(function (event) {
return event[propertyKey] > 0;
});
break;
case NEGATIVE:
newEvents = deepCopyOfEvents.filter(function (event) {
return event[propertyKey] < 0;
});
break;
case BOTH:
newEvents = deepCopyOfEvents;
break;
default:
newEvents = deepCopyOfEvents;
break;
}
return newEvents;
}; // TODO: performance could be increased by making a separete function for findLeastValueSnapshots
// TODO cont: instead of passing reverse as a parameter and reverse the sort
var findGreatestValueSnapshots = function findGreatestValueSnapshots(_ref18) {
var _ref18$events = _ref18.events,
events = _ref18$events === void 0 ? [] : _ref18$events,
_ref18$propertyKey = _ref18.propertyKey,
propertyKey = _ref18$propertyKey === void 0 ? 'balanceEnding' : _ref18$propertyKey,
_ref18$selectionLimit = _ref18.selectionLimit,
selectionLimit = _ref18$selectionLimit === void 0 ? DEFAULT_SELECTION_LIMIT : _ref18$selectionLimit,
_ref18$flowDirection = _ref18.flowDirection,
flowDirection = _ref18$flowDirection === void 0 ? BOTH : _ref18$flowDirection,
_ref18$reverse = _ref18.reverse,
reverse = _ref18$reverse === void 0 ? false : _ref18$reverse,
_ref18$alreadyFiltere = _ref18.alreadyFiltered,
alreadyFiltered = _ref18$alreadyFiltere === void 0 ? false : _ref18$alreadyFiltere;
var sortedCollection = [];
var newEvents = deepCopy(events); // TODO: should refactor to only send this function pre-filtered events: for eg. with filterEventsByFlowDirection, whatever you do make sure you test it a lot!
var greaterThanComparator;
var lessThanComparator;
switch (flowDirection) {
case POSITIVE:
greaterThanComparator = isVal1GreaterThanVal2;
lessThanComparator = isVal1LessThanVal2;
break;
case NEGATIVE:
greaterThanComparator = isAbsVal1GreaterThanAbsVal2;
lessThanComparator = isAbsVal1LessThanAbsVal2;
break;
case BOTH:
greaterThanComparator = isVal1GreaterThanVal2;
lessThanComparator = isVal1LessThanVal2;
break;
default:
greaterThanComparator = isVal1GreaterThanVal2;
lessThanComparator = isVal1LessThanVal2;
break;
}
sortedCollection = newEvents.sort(function (a, b) {
if (isUndefinedOrNull(a) && !isUndefinedOrNull(b)) {
return -1;
} else if (!isUndefinedOrNull(a) && isUndefinedOrNull(b)) {
return 1;
} else if (isUndefinedOrNull(a) && isUndefinedOrNull(b)) {
return 0;
} else if (greaterThanComparator(a[propertyKey], b[propertyKey])) {
return -1;
} else if (lessThanComparator(a[propertyKey], b[propertyKey])) {
return 1; // eslint-disable-next-line no-else-return
} else {
return 0;
}
});
if (reverse) {
sortedCollection = sortedCollection.reverse();
}
return sortedCollection;
};
var findGreatestPositiveValueSnapshots = function findGreatestPositiveValueSnapshots(_ref19) {
var _ref19$events = _ref19.events,
events = _ref19$events === void 0 ? [] : _ref19$events,
_ref19$propertyKey = _ref19.propertyKey,
propertyKey = _ref19$propertyKey === void 0 ? 'balanceEnding' : _ref19$propertyKey,
_ref19$selectionLimit = _ref19.selectionLimit,
selectionLimit = _ref19$selectionLimit === void 0 ? DEFAULT_SELECTION_LIMIT : _ref19$selectionLimit,
_ref19$reverse = _ref19.reverse,
reverse = _ref19$reverse === void 0 ? false : _ref19$reverse;
var newEvents = deepCopy(events);
var sortedCollection = newEvents.filter(function (e) {
return e[propertyKey] > 0;
}).sort(function (a, b) {
if (isUndefinedOrNull(a) && !isUndefinedOrNull(b)) {
return -1;
} else if (!isUndefinedOrNull(a) && isUndefinedOrNull(b)) {
return 1;
} else if (isUndefinedOrNull(a) && isUndefinedOrNull(b)) {
return 0;
} else if (a[propertyKey] > b[propertyKey]) {
return -1;
} else if (a[propertyKey] < b[propertyKey]) {
return 1; // eslint-disable-next-line no-else-return
} else {
return 0;
}
});
if (reverse) {
sortedCollection = sortedCollection.reverse();
}
return sortedCollection;
};
var findGreatestNegativeValueSnapshots = function findGreatestNegativeValueSnapshots(_ref20) {
var _ref20$events = _ref20.events,
events = _ref20$events === void 0 ? [] : _ref20$events,
_ref20$propertyKey = _ref20.propertyKey,
propertyKey = _ref20$propertyKey === void 0 ? 'balanceEnding' : _ref20$propertyKey,
_ref20$selectionLimit = _ref20.selectionLimit,
selectionLimit = _ref20$selectionLimit === void 0 ? DEFAULT_SELECTION_LIMIT : _ref20$selectionLimit,
_ref20$reverse = _ref20.reverse,
reverse = _ref20$reverse === void 0 ? false : _ref20$reverse;
var newEvents = deepCopy(events);
var sortedCollection = newEvents.filter(function (e) {
return e[propertyKey] < 0;
}).sort(function (a, b) {
if (isUndefinedOrNull(a) && !isUndefinedOrNull(b)) {
return -1;
} else if (!isUndefinedOrNull(a) && isUndefinedOrNull(b)) {
return 1;
} else if (isUndefinedOrNull(a) && isUndefinedOrNull(b)) {
return 0;
} else if (Math.abs(a[propertyKey]) > Math.abs(b[propertyKey])) {
return -1;
} else if (Math.abs(a[propertyKey]) < Math.abs(b[propertyKey])) {
return 1; // eslint-disable-next-line no-else-return
} else {
return 0;
}
});
if (reverse) {
sortedCollection = sortedCollection.reverse();
}
return sortedCollection;
};
var sumAllPositiveEventAmounts = function sumAllPositiveEventAmounts(events) {
var sum = 0;
events.forEach(function (event) {
var amount = event.amount;
if (!isUndefinedOrNull(amount) && amount > 0) {
// routine/reminder types like STANDARD_EVENT_ROUTINE do not require an amount field
// we first check to make sure it had an amount field so that it satisfies our required context
// however, we are actually only interested in the multi-currency converted amount
sum += amount;
}
});
return sum;
};
var sumAllNegativeEventAmounts = function sumAllNegativeEventAmounts(events) {
var sum = 0;
events.forEach(function (event) {
var amount = event.amount;
if (!isUndefinedOrNull(amount) && amount < 0) {
// routine/reminder types like STANDARD_EVENT_ROUTINE do not require an amount field
// we first check to make sure it had an amount field so that it satisfies our required context
// however, we are actually only interested in the multi-currency converted amount
sum += amount;
}
});
return sum;
};
module.exports = {
sortEventsForReports: sortEventsForReports,
sortAggregates: sortAggregates,
isThisWithinXPercentOfThat: isThisWithinXPercentOfThat,
findEventsWithinXPercentOfValue: findEventsWithinXPercentOfValue,
filterEventsByKeysAndValues: filterEventsByKeysAndValues,
filterEventsByFlowDirection: filterEventsByFlowDirection,
findSnapshotsGreaterThanSupport: findSnapshotsGreaterThanSupport,
findSnapshotsLessThanResistance: findSnapshotsLessThanResistance,
findPositiveSnapshotsGreaterThanSupport: findPositiveSnapshotsGreaterThanSupport,
findPositiveSnapshotsLessThanResistance: findPositiveSnapshotsLessThanResistance,
findNegativeSnapshotsGreaterThanSupport: findNegativeSnapshotsGreaterThanSupport,
findNegativeSnapshotsLessThanResistance: findNegativeSnapshotsLessThanResistance,
findGreatestValueSnapshots: findGreatestValueSnapshots,
findGreatestPositiveValueSnapshots: findGreatestPositiveValueSnapshots,
findGreatestNegativeValueSnapshots: findGreatestNegativeValueSnapshots,
findCriticalSnapshots: findCriticalSnapshots,
findRulesToRetire: findRulesToRetire,
findIrrelevantRules: findIrrelevantRules,
findEventsWithProperty: findEventsWithProperty,
findEventsByPropertyKeyAndValues: findEventsByPropertyKeyAndValues,
findEventsWithPropertyKeyContainingSubstring: findEventsWithPropertyKeyContainingSubstring,
sumAllPositiveEventAmounts: sumAllPositiveEventAmounts,
sumAllNegativeEventAmounts: sumAllNegativeEventAmounts
};