Repository navigation
Expand file tree
/
Copy pathmain.js
More file actions
77 lines (62 loc) · 1.94 KB
/
Copy pathmain.js
File metadata and controls
77 lines (62 loc) · 1.94 KB
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
var helpers = require('./helpers.js');
exports.importInvoices = function(fileContent, profile) {
var rows = helpers.parseCSV(fileContent);
if (rows.length === 0) {
return [];
}
// Timemator has no VAT info, so use the profile’s default VAT rate.
var vatPercentage =
profile && typeof profile.vatPercentage === 'number'
? profile.vatPercentage
: 0;
// Rows without an hourly_rate fall back to the profile’s default hourly rate.
var fallbackRate =
profile && typeof profile.hourlyRate === 'number'
? profile.hourlyRate
: 0;
// Group rows by folder (one invoice each), then by task (one line item each).
var folders = {};
rows.forEach(function(row) {
var task = (row.task || '').trim();
var date = (row.date || '').trim();
if (!task || !date) return;
var folder = (row.folder || '').trim();
var duration = parseFloat(row.duration_decimal) || 0;
var hourlyRate = parseFloat(row.hourly_rate);
if (isNaN(hourlyRate)) hourlyRate = fallbackRate;
if (!folders[folder]) {
folders[folder] = { tasks: {}, dates: [] };
}
var group = folders[folder];
group.dates.push(date);
if (!group.tasks[task]) {
group.tasks[task] = { totalHours: 0, hourlyRate: hourlyRate };
}
group.tasks[task].totalHours += duration;
});
// One invoice per folder, line items sorted by task name.
return Object.keys(folders).sort().map(function(folder) {
var group = folders[folder];
group.dates.sort();
var items = Object.keys(group.tasks).sort().map(function(task) {
var t = group.tasks[task];
return {
description: task,
quantity: helpers.round2(t.totalHours),
unit: 'Hour',
unitPrice: t.hourlyRate,
vatPercentage: vatPercentage,
};
});
var patch = {
recipient: { name: folder },
serviceDateStart: group.dates[0],
items: items,
};
var lastDate = group.dates[group.dates.length - 1];
if (lastDate !== group.dates[0]) {
patch.serviceDateEnd = lastDate;
}
return patch;
});
};