@furkot/export-expense-report 0.0.5 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +1 -1
- package/lib/expense-report.js +54 -60
- package/lib/format.js +6 -23
- package/package.json +9 -7
- package/index.js +0 -1
package/Readme.md
CHANGED
package/lib/expense-report.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { formatAmount, formatDate, formatDescription, formatDistance } from './format.js';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports.extension = 'csv';
|
|
7
|
-
exports.encoding = 'utf8';
|
|
3
|
+
expenseReport.contentType = 'text/csv';
|
|
4
|
+
expenseReport.extension = 'csv';
|
|
5
|
+
expenseReport.encoding = 'utf8';
|
|
8
6
|
|
|
9
7
|
const types = init(
|
|
10
8
|
[98, 161],
|
|
@@ -12,11 +10,7 @@ const types = init(
|
|
|
12
10
|
init(
|
|
13
11
|
[10, 25, 178, 179],
|
|
14
12
|
'fuel',
|
|
15
|
-
init(
|
|
16
|
-
[9, 24, 27, 28, 30, 31, 32, 90, 139, 143, 156, 158, 159, 172],
|
|
17
|
-
'meal',
|
|
18
|
-
Object.create(null)
|
|
19
|
-
)
|
|
13
|
+
init([9, 24, 27, 28, 30, 31, 32, 90, 139, 143, 156, 158, 159, 172], 'meal', Object.create(null))
|
|
20
14
|
)
|
|
21
15
|
);
|
|
22
16
|
|
|
@@ -27,51 +21,39 @@ function init(arr, tp, r) {
|
|
|
27
21
|
}, r);
|
|
28
22
|
}
|
|
29
23
|
function prepare(line) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
const items = line.map(item => {
|
|
25
|
+
switch (typeof item) {
|
|
26
|
+
case 'number':
|
|
27
|
+
return item.toString();
|
|
28
|
+
case 'string':
|
|
29
|
+
// quote strings
|
|
30
|
+
return `"${item.replace(/"/g, '""')}"`;
|
|
31
|
+
default:
|
|
32
|
+
// empty string for everything else
|
|
33
|
+
return '';
|
|
37
34
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}).join(',') + '\n';
|
|
35
|
+
});
|
|
36
|
+
return `${items.join(',')}\n`;
|
|
41
37
|
}
|
|
42
38
|
|
|
43
|
-
function getType({
|
|
44
|
-
nights,
|
|
45
|
-
sym
|
|
46
|
-
}) {
|
|
39
|
+
function getType({ nights, sym }) {
|
|
47
40
|
if (nights) {
|
|
48
41
|
return 'lodging';
|
|
49
42
|
}
|
|
50
43
|
return types[sym] || '';
|
|
51
44
|
}
|
|
52
45
|
|
|
53
|
-
function* expenseReport(options) {
|
|
46
|
+
export default function* expenseReport(options) {
|
|
54
47
|
const {
|
|
55
|
-
metadata: {
|
|
56
|
-
currency,
|
|
57
|
-
units,
|
|
58
|
-
mileageRate,
|
|
59
|
-
mode: tripMode
|
|
60
|
-
},
|
|
48
|
+
metadata: { currency, units, mileageRate, mode: tripMode },
|
|
61
49
|
routes
|
|
62
50
|
} = options;
|
|
63
51
|
|
|
64
|
-
const header = [
|
|
65
|
-
'Description',
|
|
66
|
-
'Date',
|
|
67
|
-
'Amount',
|
|
68
|
-
'Currency',
|
|
69
|
-
'Type',
|
|
70
|
-
'Notes'
|
|
71
|
-
];
|
|
52
|
+
const header = ['Description', 'Date', 'Amount', 'Currency', 'Type', 'Notes'];
|
|
72
53
|
|
|
73
54
|
const steps = routes[0].points;
|
|
74
55
|
let from;
|
|
56
|
+
let passthruDistance = 0;
|
|
75
57
|
|
|
76
58
|
function getLines(i) {
|
|
77
59
|
const {
|
|
@@ -86,25 +68,35 @@ function* expenseReport(options) {
|
|
|
86
68
|
name,
|
|
87
69
|
nights,
|
|
88
70
|
notes,
|
|
71
|
+
passthru,
|
|
89
72
|
per_diem,
|
|
90
73
|
tags
|
|
91
74
|
} = steps[i];
|
|
75
|
+
|
|
76
|
+
if (passthru) {
|
|
77
|
+
passthruDistance += distance;
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
const stepDistance = (distance ?? 0) + passthruDistance;
|
|
81
|
+
passthruDistance = 0;
|
|
92
82
|
const to = name || address;
|
|
93
|
-
const date =
|
|
83
|
+
const date = formatDate(new Date(arrival_time));
|
|
94
84
|
const inTripMode = mode === undefined || mode === tripMode;
|
|
95
85
|
const lines = [];
|
|
96
86
|
|
|
97
|
-
if (mileageRate &&
|
|
87
|
+
if (mileageRate && stepDistance && inTripMode) {
|
|
98
88
|
const line = [];
|
|
99
89
|
|
|
100
|
-
line.push(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
90
|
+
line.push(
|
|
91
|
+
formatDescription(
|
|
92
|
+
[from, to].join(' - '),
|
|
93
|
+
dayLabel,
|
|
94
|
+
formatDistance(stepDistance, 1, units, true),
|
|
95
|
+
formatAmount(mileageRate / 100, 3, currency)
|
|
96
|
+
)
|
|
97
|
+
);
|
|
106
98
|
line.push(date);
|
|
107
|
-
line.push(
|
|
99
|
+
line.push(formatDistance((stepDistance * mileageRate) / 100, 2, units));
|
|
108
100
|
line.push(currency);
|
|
109
101
|
line.push('mileage');
|
|
110
102
|
|
|
@@ -113,9 +105,9 @@ function* expenseReport(options) {
|
|
|
113
105
|
if (costRoute) {
|
|
114
106
|
const line = [];
|
|
115
107
|
|
|
116
|
-
line.push(
|
|
108
|
+
line.push(formatDescription([from, to].join(' - '), dayLabel));
|
|
117
109
|
line.push(date);
|
|
118
|
-
line.push(
|
|
110
|
+
line.push(formatAmount(costRoute / 100, 2));
|
|
119
111
|
line.push(currency);
|
|
120
112
|
line.push(inTripMode ? 'tolls' : 'transportation');
|
|
121
113
|
|
|
@@ -124,14 +116,16 @@ function* expenseReport(options) {
|
|
|
124
116
|
if (cost) {
|
|
125
117
|
const line = [];
|
|
126
118
|
|
|
127
|
-
line.push(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
119
|
+
line.push(
|
|
120
|
+
formatDescription(
|
|
121
|
+
name || address,
|
|
122
|
+
tags,
|
|
123
|
+
dayLabel,
|
|
124
|
+
nights > 1 && [formatAmount(cost / 100, 2, currency), `${day + 1}/${nights}`]
|
|
125
|
+
)
|
|
126
|
+
);
|
|
133
127
|
line.push(date);
|
|
134
|
-
line.push(
|
|
128
|
+
line.push(formatAmount(cost / (nights || 1) / 100, 2));
|
|
135
129
|
line.push(currency);
|
|
136
130
|
line.push(getType(steps[i]));
|
|
137
131
|
line.push(notes);
|
|
@@ -141,9 +135,9 @@ function* expenseReport(options) {
|
|
|
141
135
|
if (per_diem) {
|
|
142
136
|
const line = [];
|
|
143
137
|
|
|
144
|
-
line.push(
|
|
138
|
+
line.push(formatDescription(address || name, tags, dayLabel));
|
|
145
139
|
line.push(date);
|
|
146
|
-
line.push(
|
|
140
|
+
line.push(formatAmount(per_diem / 100, 2));
|
|
147
141
|
line.push(currency);
|
|
148
142
|
line.push('per diem');
|
|
149
143
|
line.push(notes);
|
package/lib/format.js
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
amount,
|
|
3
|
-
date,
|
|
4
|
-
description,
|
|
5
|
-
distance
|
|
6
|
-
};
|
|
7
|
-
|
|
8
1
|
function pad(n) {
|
|
9
|
-
return n < 10 ?
|
|
2
|
+
return n < 10 ? `0${n}` : n;
|
|
10
3
|
}
|
|
11
4
|
|
|
12
|
-
function
|
|
5
|
+
export function formatAmount(amt, precision, currency) {
|
|
13
6
|
precision = precision || 0;
|
|
14
7
|
const result = amt.toFixed(precision);
|
|
15
8
|
if (currency) {
|
|
@@ -18,25 +11,15 @@ function amount(amt, precision, currency) {
|
|
|
18
11
|
return result;
|
|
19
12
|
}
|
|
20
13
|
|
|
21
|
-
function
|
|
14
|
+
export function formatDate(d) {
|
|
22
15
|
return [d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate()].map(pad).join('-');
|
|
23
16
|
}
|
|
24
17
|
|
|
25
|
-
function
|
|
26
|
-
return
|
|
27
|
-
if (v) {
|
|
28
|
-
if (Array.isArray(v)) {
|
|
29
|
-
r.push(...v);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
r.push(v);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return r;
|
|
36
|
-
}, []).join(' / ');
|
|
18
|
+
export function formatDescription(...args) {
|
|
19
|
+
return args.filter(Boolean).flat().join(' / ');
|
|
37
20
|
}
|
|
38
21
|
|
|
39
|
-
function
|
|
22
|
+
export function formatDistance(dist, precision, units, withUnits) {
|
|
40
23
|
const div = units === 'km' ? 1000 : 1609.344;
|
|
41
24
|
precision = precision || 0;
|
|
42
25
|
const result = (dist / div).toFixed(precision);
|
package/package.json
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@furkot/export-expense-report",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Generate CSV expense report from Furkot trip data.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": "./lib/expense-report.js",
|
|
5
7
|
"author": {
|
|
6
8
|
"name": "Natalia Kowalczyk",
|
|
7
9
|
"email": "melitele@code42day.com",
|
|
8
10
|
"url": "https://melitele.me"
|
|
9
11
|
},
|
|
10
|
-
"repository":
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/furkot/export-expense-report.git"
|
|
15
|
+
},
|
|
11
16
|
"license": "MIT",
|
|
12
17
|
"keywords": [
|
|
13
18
|
"expense-report",
|
|
@@ -17,16 +22,13 @@
|
|
|
17
22
|
"planner",
|
|
18
23
|
"CSV"
|
|
19
24
|
],
|
|
20
|
-
"dependencies": {},
|
|
21
25
|
"devDependencies": {
|
|
22
|
-
"@
|
|
23
|
-
"should": "~13"
|
|
26
|
+
"@biomejs/biome": "^1.9.4"
|
|
24
27
|
},
|
|
25
28
|
"scripts": {
|
|
26
29
|
"test": "make check"
|
|
27
30
|
},
|
|
28
31
|
"files": [
|
|
29
|
-
"index.js",
|
|
30
32
|
"lib"
|
|
31
33
|
]
|
|
32
|
-
}
|
|
34
|
+
}
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('./lib/expense-report');
|