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
246 lines (212 loc) • 8.39 kB
JavaScript
"use strict";
var _require = require('../utility/errorHandling'),
errorDisc = _require.errorDisc;
var _require2 = require('../utility/validation'),
isUndefinedOrNull = _require2.isUndefinedOrNull;
var _require3 = require('../timeZone'),
createTimeZone = _require3.createTimeZone,
convertTimeZone = _require3.convertTimeZone;
var _require4 = require('./dateUtility'),
getRelevantDateSegmentByFrequency = _require4.getRelevantDateSegmentByFrequency;
var _require5 = require('../analytics'),
findIrrelevantRules = _require5.findIrrelevantRules;
var _require6 = require('../constants'),
EVENT_SOURCE = _require6.EVENT_SOURCE,
OBSERVER_SOURCE = _require6.OBSERVER_SOURCE,
BOTH = _require6.BOTH,
DATE_FORMAT_STRING = _require6.DATE_FORMAT_STRING,
EXECUTION_REJECTED = _require6.EXECUTION_REJECTED,
ONCE = _require6.ONCE; // flags a rule that is no longer relevant for active budget-projection calculations
var flagRuleForRetirement = function flagRuleForRetirement(_ref) {
var danielSan = _ref.danielSan,
rule = _ref.rule,
date = _ref.date,
index = _ref.index;
try {
// if effectiveDateEnd has been reached, flag the rule for retirement
var dateString = date.format(DATE_FORMAT_STRING);
if (!isUndefinedOrNull(rule.effectiveDateEnd) && dateString >= rule.effectiveDateEnd || rule.frequency === ONCE && typeof rule.processDate === 'string' && dateString >= rule.processDate) {
danielSan.retiredRuleIndices.push(index);
}
} catch (err) {
throw errorDisc({
err: err,
data: {
rule: rule,
date: date,
index: index
}
});
}
}; // retires rules that were flagged in flagRuleForRetirement()
var retireRules = function retireRules(danielSan) {
var looper;
try {
// retire obsolete rules
if (danielSan.retiredRuleIndices.length > 0) {
// optimize later - but this works
var newRules = [];
danielSan.rules.forEach(function (rule, index) {
if (!danielSan.retiredRuleIndices.includes(index)) {
newRules.push(rule);
}
});
danielSan.rules = [].concat(newRules);
danielSan.retiredRuleIndices = []; // reset retiredRuleIndices
}
} catch (err) {
throw errorDisc({
err: err,
data: {
retiredRuleIndices: danielSan.retiredRuleIndices,
looper: looper
}
});
}
}; // returns/removes rules that have no chance ot being included into a projected event
var seekAndDestroyIrrelevantRules = function seekAndDestroyIrrelevantRules(danielSan) {
var _findIrrelevantRules = findIrrelevantRules(danielSan),
relevantRules = _findIrrelevantRules.relevantRules,
irrelevantRules = _findIrrelevantRules.irrelevantRules;
danielSan.rules = relevantRules; // remove irrelevantRules from the danielSan reference
return irrelevantRules; // return irrelevantRules if needed
};
var deleteIrrelevantRules = function deleteIrrelevantRules(danielSan) {
try {
var irrelevantRules = seekAndDestroyIrrelevantRules(danielSan);
danielSan.irrelevantRules = irrelevantRules;
} catch (err) {
throw errorDisc({
err: err
});
}
};
var discardEventsOutsideDateRange = function discardEventsOutsideDateRange(danielSan) {
var _danielSan$config = danielSan.config,
effectiveDateStart = _danielSan$config.effectiveDateStart,
timeStart = _danielSan$config.timeStart,
effectiveDateEnd = _danielSan$config.effectiveDateEnd,
timeEnd = _danielSan$config.timeEnd,
timeZone = _danielSan$config.timeZone,
timeZoneType = _danielSan$config.timeZoneType;
var eventsToDiscard = [];
var newEventList = [];
danielSan.events.forEach(function (event) {
var dateToStart = createTimeZone({
timeZone: timeZone,
timeZoneType: timeZoneType,
dateString: effectiveDateStart,
timeString: timeStart
});
var eventDateStart = createTimeZone({
timeZone: timeZone,
timeZoneType: timeZoneType,
dateString: event.dateStart,
timeString: event.timeStart
});
var dateToEnd = createTimeZone({
timeZone: timeZone,
timeZoneType: timeZoneType,
dateString: effectiveDateEnd,
timeString: timeEnd || timeStart
});
if (eventDateStart.isBefore(dateToStart) || eventDateStart.isAfter(dateToEnd)) {
eventsToDiscard.push(event);
} else {
newEventList.push(event);
}
});
danielSan.discardedEvents = eventsToDiscard; // we only need to re-reference danielSan.events if we are discarding anything
if (eventsToDiscard.length > 0) {
danielSan.events = newEventList;
}
};
/*
exclusions: {
weekdays: [SATURDAY, SUNDAY],
dates: ['2019-07-04', '2019-09-17', '2019-10-31']
}
*/
var exclusionsPhase = function exclusionsPhase(_ref2) {
var danielSan = _ref2.danielSan,
rule = _ref2.rule,
date = _ref2.date,
processPhase = _ref2.processPhase;
var transientProcessPhase;
try {
transientProcessPhase = processPhase || '';
if (rule.exclusions) {
// eslint-disable-next-line no-unused-vars
var relevantDateSegmentForExclusion;
var dynamicDateSegmentForExclusion;
var anyMatch = false;
if (rule.exclusions.weekdays) {
if (isUndefinedOrNull(rule.exclusions.context) || rule.exclusions.context === EVENT_SOURCE || rule.exclusions.context === BOTH) {
relevantDateSegmentForExclusion = date.day();
anyMatch = rule.exclusions.weekdays.some(function (eventDate) {
dynamicDateSegmentForExclusion = eventDate; // eslint-disable-next-line eqeqeq
return dynamicDateSegmentForExclusion === relevantDateSegmentForExclusion;
});
} else if (rule.exclusions.context === OBSERVER_SOURCE || rule.exclusions.context === BOTH) {
var convertedDate = convertTimeZone({
timeZone: danielSan.config.timeZone,
timeZoneType: danielSan.config.timeZoneType,
date: date
});
relevantDateSegmentForExclusion = convertedDate.day();
anyMatch = rule.exclusions.weekdays.some(function (eventDate) {
dynamicDateSegmentForExclusion = eventDate; // eslint-disable-next-line eqeqeq
return dynamicDateSegmentForExclusion === relevantDateSegmentForExclusion;
});
}
if (anyMatch) transientProcessPhase = EXECUTION_REJECTED;
}
if (rule.exclusions.dates && transientProcessPhase !== EXECUTION_REJECTED) {
if (isUndefinedOrNull(rule.exclusions.context) || rule.exclusions.context === EVENT_SOURCE || rule.exclusions.context === BOTH) {
relevantDateSegmentForExclusion = getRelevantDateSegmentByFrequency({
frequency: ONCE,
date: date
});
anyMatch = rule.exclusions.dates.some(function (eventDate) {
dynamicDateSegmentForExclusion = eventDate;
return dynamicDateSegmentForExclusion === relevantDateSegmentForExclusion;
});
} else if (rule.exclusions.context === OBSERVER_SOURCE || rule.exclusions.context === BOTH) {
var _convertedDate = convertTimeZone({
timeZone: danielSan.config.timeZone,
timeZoneType: danielSan.config.timeZoneType,
date: date
});
relevantDateSegmentForExclusion = getRelevantDateSegmentByFrequency({
frequency: ONCE,
date: _convertedDate
});
anyMatch = rule.exclusions.dates.some(function (eventDate) {
dynamicDateSegmentForExclusion = eventDate;
return dynamicDateSegmentForExclusion === relevantDateSegmentForExclusion;
});
}
if (anyMatch) transientProcessPhase = EXECUTION_REJECTED;
}
}
return transientProcessPhase;
} catch (err) {
throw errorDisc({
err: err,
data: {
rule: rule,
date: date,
processPhase: processPhase,
transientProcessPhase: transientProcessPhase
}
});
}
};
module.exports = {
flagRuleForRetirement: flagRuleForRetirement,
retireRules: retireRules,
seekAndDestroyIrrelevantRules: seekAndDestroyIrrelevantRules,
deleteIrrelevantRules: deleteIrrelevantRules,
discardEventsOutsideDateRange: discardEventsOutsideDateRange,
exclusionsPhase: exclusionsPhase
};