-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathget-file-contents.js
93 lines (70 loc) · 3.35 KB
/
get-file-contents.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
'use strict';
const parse = require('csv-parse/lib/sync');
const fs = require('fs');
const path = require('path');
const _ = require('lodash');
const assert = require('assert');
const config = require('config');
const REDMINE_ACTIVITIES = config.activities;
let accumulatedTimeByDateMap = {};
let lastDate = null;
const validateAndUpdateRow = (row, i) => {
const index = i + 1;
assert(isValidNumber(row.ticket), `Ticket must be a number. Error in row: ${index}`);
assert(isValidNumber(row.hours), `Hours must be a number. Error in row: ${index}`);
assert(!_.isEmpty(row.comment), `Comment must not be empty. Error in row: ${index}`);
assert(_.includes(REDMINE_ACTIVITIES, row.activity), `Invalid Redmine Activity '${row.activity}' in row: ${index} | Value must be one of: ${REDMINE_ACTIVITIES}`);
const inputDate = row.date || lastDate;
lastDate = inputDate;
row.date = getFullDate(inputDate, index);
validateAccumulatedValue(row.date, row.hours, index);
return row;
};
const isValidNumber = num => !isNaN(num) && String(num) !== '0';
const SUNDAY = 0;
const SATURDAY = 6;
const A_DAY = 1000 * 60 * 60 * 24;
const THIRTY_DAYS = A_DAY * 30;
const getFullDate = (rawDate, index) => {
const partialDateRegex = /^\d{2}-\d{2}$/;
const fullDateRegex = /^(\d{4})-(\d{2})-(\d{2})$/;
const date = partialDateRegex.test(rawDate)
? new Date().getFullYear() + '-' + rawDate
: rawDate;
assert(fullDateRegex.test(date), `Invalid date '${date}' in row: ${index} | The date must be in the following format: YYYY-MM-DD`);
assert(isValidDate(new Date(date)), `Invalid date '${date}' in row: ${index} | Invalid Date`);
const dateNowInstance = new Date();
dateNowInstance.setHours(0);
dateNowInstance.setMinutes(0);
dateNowInstance.setSeconds(0);
const dateParts = date.match(fullDateRegex);
const dateRowInstance = new Date(dateParts[1], Number(dateParts[2]) - 1, dateParts[3]);
dateRowInstance.setHours(0);
dateRowInstance.setMinutes(0);
dateRowInstance.setSeconds(0);
const dayOfTheWeek = dateRowInstance.getDay();
assert(dateRowInstance <= dateNowInstance, `Invalid date ${date} in row: ${index} | The date must be today or in the past`);
assert(dateNowInstance - dateRowInstance < THIRTY_DAYS, `Invalid date ${date} in row: ${index} | The date cannot be more than 30 days into the past`);
assert(dayOfTheWeek !== SUNDAY && dayOfTheWeek !== SATURDAY, `Invalid date ${date} in row: ${index} | Cannot add a time entry on weekend`);
return formatDate(date);
};
const formatDate = date => {
const parts = date.split('-');
return `${parts[1]}/${parts[2]}/${parts[0]}`
};
const isValidDate = date =>
Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date.getTime());
const validateAccumulatedValue = (date, hours, index) => {
if (!accumulatedTimeByDateMap[date]) {
accumulatedTimeByDateMap[date] = 0;
}
accumulatedTimeByDateMap[date] += Number(hours);
assert(accumulatedTimeByDateMap[date] <= 8, `Your total of hours for ${date} is greater than 8 in the row: ${index} | Current accumulated value is ${accumulatedTimeByDateMap[date]}`)
};
module.exports = () => {
const rawContent = parse(fs.readFileSync(path.join(__dirname, './entries.csv')), {columns: true, trim: true, skip_empty_lines: true});
// TODO encapsulate this
accumulatedTimeByDateMap = {};
lastDate = null;
return _.map(rawContent, validateAndUpdateRow);
};