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
435 lines (393 loc) • 13.9 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('../timeStream'),
streamForward = _require4.streamForward,
streamBackward = _require4.streamBackward;
var _require5 = require('../core/eventGeneration'),
redefineTimeStartAndTimeSpan = _require5.redefineTimeStartAndTimeSpan;
var _require6 = require('../core/dateUtility'),
getRelevantDateSegmentByFrequency = _require6.getRelevantDateSegmentByFrequency;
var _require7 = require('../constants'),
DATE_FORMAT_STRING = _require7.DATE_FORMAT_STRING,
WEEKLY = _require7.WEEKLY,
ONCE = _require7.ONCE,
EXECUTING_RULE_ADJUSTMENT = _require7.EXECUTING_RULE_ADJUSTMENT,
MODIFIED = _require7.MODIFIED,
EVENT_SOURCE = _require7.EVENT_SOURCE,
OBSERVER_SOURCE = _require7.OBSERVER_SOURCE,
BOTH = _require7.BOTH;
var reusableLogicForDateMovements = function reusableLogicForDateMovements(_ref) {
var danielSan = _ref.danielSan,
event = _ref.event,
specialAdjustment = _ref.specialAdjustment,
streamForwardOrBackWard = _ref.streamForwardOrBackWard,
date = _ref.date,
dateArray = _ref.dateArray,
frequency = _ref.frequency,
skipTimeTravel = _ref.skipTimeTravel;
var processPhase = EXECUTING_RULE_ADJUSTMENT;
if (dateArray) {
// note: timezone for "OBSERVER_SOURCE" is actually coming from the danielSan config.
// Because that will be the final assigned timezone for the event.
// even though the timezones for "EVENT_SOURCE" are coming from the event object,
// their below dates are calcluated via the rule timezone data (which is still the original data as it hasn't changed to the converted timezone yet)
var ruleContextLooperDate = date;
var ruleContextLooperDateString = getRelevantDateSegmentByFrequency({
frequency: frequency,
date: ruleContextLooperDate
}); // note: the following 2 variables would only be used in OBSERVER_SOURCE or BOTH
var observerContextLooperDate = convertTimeZone({
timeZone: danielSan.config.timeZone,
timeZoneType: danielSan.config.timeZoneType,
date: ruleContextLooperDate
});
var observerContextLooperDateString = getRelevantDateSegmentByFrequency({
frequency: frequency,
date: observerContextLooperDate.date
});
/* conditions: EVENT_SOURCE / OBSERVER_SOURCE / BOTH */
if (isUndefinedOrNull(specialAdjustment.context) || specialAdjustment.context === EVENT_SOURCE) {
while (dateArray.includes(ruleContextLooperDateString)) {
ruleContextLooperDate = streamForwardOrBackWard(ruleContextLooperDate);
event.dateStart = ruleContextLooperDate.format(DATE_FORMAT_STRING);
redefineTimeStartAndTimeSpan({
event: event,
skipTimeTravel: skipTimeTravel
});
processPhase = MODIFIED;
ruleContextLooperDate = createTimeZone({
timeZone: event.timeZone,
timeZoneType: event.timeZoneType,
dateString: event.dateStart,
timeString: event.timeStart
});
ruleContextLooperDateString = getRelevantDateSegmentByFrequency({
frequency: frequency,
date: ruleContextLooperDate
});
}
} else if (specialAdjustment.context === OBSERVER_SOURCE) {
while (dateArray.includes(observerContextLooperDateString)) {
ruleContextLooperDate = streamForwardOrBackWard(ruleContextLooperDate);
event.dateStart = ruleContextLooperDate.format(DATE_FORMAT_STRING);
processPhase = MODIFIED;
redefineTimeStartAndTimeSpan({
event: event,
skipTimeTravel: skipTimeTravel
});
ruleContextLooperDate = createTimeZone({
timeZone: event.timeZone,
timeZoneType: event.timeZoneType,
dateString: event.dateStart,
timeString: event.timeStart
});
observerContextLooperDate = convertTimeZone({
timeZone: danielSan.config.timeZone,
timeZoneType: danielSan.config.timeZoneType,
date: ruleContextLooperDate
});
observerContextLooperDateString = getRelevantDateSegmentByFrequency({
frequency: frequency,
date: observerContextLooperDate.date
});
}
} else if (specialAdjustment.context === BOTH) {
while (dateArray.includes(observerContextLooperDateString) || dateArray.includes(ruleContextLooperDateString)) {
ruleContextLooperDate = streamForwardOrBackWard(ruleContextLooperDate);
event.dateStart = ruleContextLooperDate.format(DATE_FORMAT_STRING);
processPhase = MODIFIED;
redefineTimeStartAndTimeSpan({
event: event,
skipTimeTravel: skipTimeTravel
});
ruleContextLooperDate = createTimeZone({
timeZone: event.timeZone,
timeZoneType: event.timeZoneType,
dateString: event.dateStart,
timeString: event.timeStart
});
ruleContextLooperDateString = getRelevantDateSegmentByFrequency({
frequency: frequency,
date: ruleContextLooperDate
});
observerContextLooperDate = convertTimeZone({
timeZone: danielSan.config.timeZone,
timeZoneType: danielSan.config.timeZoneType,
date: ruleContextLooperDate
});
observerContextLooperDateString = getRelevantDateSegmentByFrequency({
frequency: frequency,
date: observerContextLooperDate.date
});
}
}
}
return processPhase;
};
/*
specialAdjustments: [
{
type: MOVE_THIS_PROCESS_DATE_BEFORE_THESE_WEEKDAYS
weekdays: [SATURDAY, SUNDAY]
}
];
*/
var moveThisProcessDateBeforeTheseWeekdays = function moveThisProcessDateBeforeTheseWeekdays(_ref2) {
var danielSan = _ref2.danielSan,
event = _ref2.event,
specialAdjustment = _ref2.specialAdjustment,
date = _ref2.date,
skipTimeTravel = _ref2.skipTimeTravel;
var processPhase;
try {
processPhase = reusableLogicForDateMovements({
danielSan: danielSan,
event: event,
specialAdjustment: specialAdjustment,
streamForwardOrBackWard: streamBackward,
date: date,
dateArray: specialAdjustment.weekdays,
frequency: WEEKLY,
skipTimeTravel: skipTimeTravel
});
return processPhase;
} catch (err) {
throw errorDisc({
err: err,
data: {
specialAdjustment: specialAdjustment,
event: event,
processPhase: processPhase,
skipTimeTravel: skipTimeTravel
}
});
}
};
/*
specialAdjustments: [
{
type: MOVE_THIS_PROCESS_DATE_AFTER_THESE_WEEKDAYS
weekdays: [SATURDAY, SUNDAY]
}
];
*/
var moveThisProcessDateAfterTheseWeekdays = function moveThisProcessDateAfterTheseWeekdays(_ref3) {
var danielSan = _ref3.danielSan,
event = _ref3.event,
specialAdjustment = _ref3.specialAdjustment,
date = _ref3.date,
skipTimeTravel = _ref3.skipTimeTravel;
var processPhase;
try {
processPhase = reusableLogicForDateMovements({
danielSan: danielSan,
event: event,
specialAdjustment: specialAdjustment,
streamForwardOrBackWard: streamForward,
date: date,
dateArray: specialAdjustment.weekdays,
frequency: WEEKLY,
skipTimeTravel: skipTimeTravel
});
} catch (err) {
throw errorDisc({
err: err,
data: {
specialAdjustment: specialAdjustment,
event: event,
processPhase: processPhase,
skipTimeTravel: skipTimeTravel
}
});
}
};
/*
specialAdjustments: [
{
type: MOVE_THIS_PROCESS_DATE_BEFORE_THESE_DATES,
dates: ['2019-07-04', '2019-12-25'],
weekdays: [SATURDAY, SUNDAY] // weekdays are optional
}
]
*/
var moveThisProcessDateBeforeTheseDates = function moveThisProcessDateBeforeTheseDates(_ref4) {
var danielSan = _ref4.danielSan,
event = _ref4.event,
specialAdjustment = _ref4.specialAdjustment,
date = _ref4.date,
skipTimeTravel = _ref4.skipTimeTravel;
var processPhase;
try {
processPhase = EXECUTING_RULE_ADJUSTMENT;
if (specialAdjustment.dates) {
processPhase = reusableLogicForDateMovements({
danielSan: danielSan,
event: event,
specialAdjustment: specialAdjustment,
streamForwardOrBackWard: streamBackward,
date: date,
dateArray: specialAdjustment.dates,
frequency: ONCE,
skipTimeTravel: skipTimeTravel
});
}
if (specialAdjustment.weekdays) {
processPhase = moveThisProcessDateBeforeTheseWeekdays({
danielSan: danielSan,
event: event,
specialAdjustment: specialAdjustment,
date: date,
skipTimeTravel: skipTimeTravel
});
if (processPhase === MODIFIED) {
processPhase = moveThisProcessDateBeforeTheseDates({
danielSan: danielSan,
event: event,
specialAdjustment: specialAdjustment,
date: date,
skipTimeTravel: skipTimeTravel
});
}
}
return processPhase;
} catch (err) {
throw errorDisc({
err: err,
data: {
specialAdjustment: specialAdjustment,
event: event,
processPhase: processPhase,
skipTimeTravel: skipTimeTravel
}
});
}
};
/*
specialAdjustments: [
{
type: MOVE_THIS_PROCESS_DATE_AFTER_THESE_DATES,
dates: ['2019-07-04', '2019-12-25'],
weekdays: [SATURDAY, SUNDAY] // weekdays are optional
}
]
*/
var moveThisProcessDateAfterTheseDates = function moveThisProcessDateAfterTheseDates(_ref5) {
var danielSan = _ref5.danielSan,
event = _ref5.event,
specialAdjustment = _ref5.specialAdjustment,
date = _ref5.date,
skipTimeTravel = _ref5.skipTimeTravel;
var processPhase;
try {
processPhase = EXECUTING_RULE_ADJUSTMENT;
if (specialAdjustment.dates) {
processPhase = reusableLogicForDateMovements({
danielSan: danielSan,
event: event,
specialAdjustment: specialAdjustment,
streamForwardOrBackWard: streamForward,
date: date,
dateArray: specialAdjustment.dates,
frequency: ONCE,
skipTimeTravel: skipTimeTravel
});
}
if (specialAdjustment.weekdays) {
processPhase = moveThisProcessDateAfterTheseWeekdays({
danielSan: danielSan,
event: event,
specialAdjustment: specialAdjustment,
date: date,
skipTimeTravel: skipTimeTravel
});
if (processPhase === MODIFIED) {
processPhase = moveThisProcessDateAfterTheseDates({
danielSan: danielSan,
event: event,
specialAdjustment: specialAdjustment,
date: date,
skipTimeTravel: skipTimeTravel
});
}
}
return processPhase;
} catch (err) {
throw errorDisc({
err: err,
data: {
specialAdjustment: specialAdjustment,
event: event,
processPhase: processPhase,
skipTimeTravel: skipTimeTravel
}
});
}
};
/*
dates & amounts are parallel arrays
specialAdjustments: [
{
type: ADJUST_AMOUNT_ON_THESE_DATES,
dates: [
'2019-06-01',
'2019-09-01'
],
amounts: [
500000,
250000
]
}
]
*/
var adjustAmountOnTheseDates = function adjustAmountOnTheseDates(_ref6) {
var danielSan = _ref6.danielSan,
event = _ref6.event,
specialAdjustment = _ref6.specialAdjustment;
var processPhase = EXECUTING_RULE_ADJUSTMENT;
var ruleContextLooperDateTracker;
var looperDateIndexTracker;
try {
specialAdjustment.dates.forEach(function (ruleContextLooperDate, looperDateIndex) {
ruleContextLooperDateTracker = ruleContextLooperDate;
looperDateIndexTracker = looperDateIndex;
if (ruleContextLooperDate === event.dateStart) {
if (isUndefinedOrNull(specialAdjustment.context) || specialAdjustment.context === EVENT_SOURCE) {
event.amount += specialAdjustment.amounts[looperDateIndex];
} else if (specialAdjustment.context === OBSERVER_SOURCE) {
var adjustmentConverted = danielSan.config.currencySymbol && event.currencySymbol && danielSan.config.currencySymbol !== event.currencySymbol ? danielSan.config.currencyConversion({
amount: specialAdjustment.amounts[looperDateIndex],
inputSymbol: danielSan.config.currencySymbol,
outputSymbol: event.currencySymbol
}) : specialAdjustment.amounts[looperDateIndex];
event.amount += adjustmentConverted;
}
processPhase = MODIFIED;
}
});
return processPhase;
} catch (err) {
throw errorDisc({
err: err,
data: {
specialAdjustment: specialAdjustment,
event: event,
processPhase: processPhase,
ruleContextLooperDateTracker: ruleContextLooperDateTracker,
looperDateIndexTracker: looperDateIndexTracker
}
});
}
};
module.exports = {
moveThisProcessDateAfterTheseWeekdays: moveThisProcessDateAfterTheseWeekdays,
moveThisProcessDateAfterTheseDates: moveThisProcessDateAfterTheseDates,
moveThisProcessDateBeforeTheseWeekdays: moveThisProcessDateBeforeTheseWeekdays,
moveThisProcessDateBeforeTheseDates: moveThisProcessDateBeforeTheseDates,
adjustAmountOnTheseDates: adjustAmountOnTheseDates
};