@furkot/export-expense-report 0.0.5 → 1.0.0
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 +44 -59
- 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,48 +21,35 @@ 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;
|
|
@@ -90,21 +71,23 @@ function* expenseReport(options) {
|
|
|
90
71
|
tags
|
|
91
72
|
} = steps[i];
|
|
92
73
|
const to = name || address;
|
|
93
|
-
const date =
|
|
74
|
+
const date = formatDate(new Date(arrival_time));
|
|
94
75
|
const inTripMode = mode === undefined || mode === tripMode;
|
|
95
76
|
const lines = [];
|
|
96
77
|
|
|
97
78
|
if (mileageRate && distance && inTripMode) {
|
|
98
79
|
const line = [];
|
|
99
80
|
|
|
100
|
-
line.push(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
81
|
+
line.push(
|
|
82
|
+
formatDescription(
|
|
83
|
+
[from, to].join(' - '),
|
|
84
|
+
dayLabel,
|
|
85
|
+
formatDistance(distance, 1, units, true),
|
|
86
|
+
formatAmount(mileageRate / 100, 3, currency)
|
|
87
|
+
)
|
|
88
|
+
);
|
|
106
89
|
line.push(date);
|
|
107
|
-
line.push(
|
|
90
|
+
line.push(formatDistance((distance * mileageRate) / 100, 2, units));
|
|
108
91
|
line.push(currency);
|
|
109
92
|
line.push('mileage');
|
|
110
93
|
|
|
@@ -113,9 +96,9 @@ function* expenseReport(options) {
|
|
|
113
96
|
if (costRoute) {
|
|
114
97
|
const line = [];
|
|
115
98
|
|
|
116
|
-
line.push(
|
|
99
|
+
line.push(formatDescription([from, to].join(' - '), dayLabel));
|
|
117
100
|
line.push(date);
|
|
118
|
-
line.push(
|
|
101
|
+
line.push(formatAmount(costRoute / 100, 2));
|
|
119
102
|
line.push(currency);
|
|
120
103
|
line.push(inTripMode ? 'tolls' : 'transportation');
|
|
121
104
|
|
|
@@ -124,14 +107,16 @@ function* expenseReport(options) {
|
|
|
124
107
|
if (cost) {
|
|
125
108
|
const line = [];
|
|
126
109
|
|
|
127
|
-
line.push(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
110
|
+
line.push(
|
|
111
|
+
formatDescription(
|
|
112
|
+
name || address,
|
|
113
|
+
tags,
|
|
114
|
+
dayLabel,
|
|
115
|
+
nights > 1 && [formatAmount(cost / 100, 2, currency), `${day + 1}/${nights}`]
|
|
116
|
+
)
|
|
117
|
+
);
|
|
133
118
|
line.push(date);
|
|
134
|
-
line.push(
|
|
119
|
+
line.push(formatAmount(cost / (nights || 1) / 100, 2));
|
|
135
120
|
line.push(currency);
|
|
136
121
|
line.push(getType(steps[i]));
|
|
137
122
|
line.push(notes);
|
|
@@ -141,9 +126,9 @@ function* expenseReport(options) {
|
|
|
141
126
|
if (per_diem) {
|
|
142
127
|
const line = [];
|
|
143
128
|
|
|
144
|
-
line.push(
|
|
129
|
+
line.push(formatDescription(address || name, tags, dayLabel));
|
|
145
130
|
line.push(date);
|
|
146
|
-
line.push(
|
|
131
|
+
line.push(formatAmount(per_diem / 100, 2));
|
|
147
132
|
line.push(currency);
|
|
148
133
|
line.push('per diem');
|
|
149
134
|
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": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Generate CSV expense report from Furkot trip data.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"export": "./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');
|