@furkot/export-expense-report 0.0.4 → 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 +45 -58
- 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;
|
|
@@ -80,6 +61,7 @@ function* expenseReport(options) {
|
|
|
80
61
|
cost,
|
|
81
62
|
costRoute,
|
|
82
63
|
day,
|
|
64
|
+
dayLabel,
|
|
83
65
|
distance,
|
|
84
66
|
mode,
|
|
85
67
|
name,
|
|
@@ -89,20 +71,23 @@ function* expenseReport(options) {
|
|
|
89
71
|
tags
|
|
90
72
|
} = steps[i];
|
|
91
73
|
const to = name || address;
|
|
92
|
-
const date =
|
|
74
|
+
const date = formatDate(new Date(arrival_time));
|
|
93
75
|
const inTripMode = mode === undefined || mode === tripMode;
|
|
94
76
|
const lines = [];
|
|
95
77
|
|
|
96
78
|
if (mileageRate && distance && inTripMode) {
|
|
97
79
|
const line = [];
|
|
98
80
|
|
|
99
|
-
line.push(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
+
);
|
|
104
89
|
line.push(date);
|
|
105
|
-
line.push(
|
|
90
|
+
line.push(formatDistance((distance * mileageRate) / 100, 2, units));
|
|
106
91
|
line.push(currency);
|
|
107
92
|
line.push('mileage');
|
|
108
93
|
|
|
@@ -111,9 +96,9 @@ function* expenseReport(options) {
|
|
|
111
96
|
if (costRoute) {
|
|
112
97
|
const line = [];
|
|
113
98
|
|
|
114
|
-
line.push(
|
|
99
|
+
line.push(formatDescription([from, to].join(' - '), dayLabel));
|
|
115
100
|
line.push(date);
|
|
116
|
-
line.push(
|
|
101
|
+
line.push(formatAmount(costRoute / 100, 2));
|
|
117
102
|
line.push(currency);
|
|
118
103
|
line.push(inTripMode ? 'tolls' : 'transportation');
|
|
119
104
|
|
|
@@ -122,14 +107,16 @@ function* expenseReport(options) {
|
|
|
122
107
|
if (cost) {
|
|
123
108
|
const line = [];
|
|
124
109
|
|
|
125
|
-
line.push(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
+
);
|
|
131
118
|
line.push(date);
|
|
132
|
-
line.push(
|
|
119
|
+
line.push(formatAmount(cost / (nights || 1) / 100, 2));
|
|
133
120
|
line.push(currency);
|
|
134
121
|
line.push(getType(steps[i]));
|
|
135
122
|
line.push(notes);
|
|
@@ -139,9 +126,9 @@ function* expenseReport(options) {
|
|
|
139
126
|
if (per_diem) {
|
|
140
127
|
const line = [];
|
|
141
128
|
|
|
142
|
-
line.push(
|
|
129
|
+
line.push(formatDescription(address || name, tags, dayLabel));
|
|
143
130
|
line.push(date);
|
|
144
|
-
line.push(
|
|
131
|
+
line.push(formatAmount(per_diem / 100, 2));
|
|
145
132
|
line.push(currency);
|
|
146
133
|
line.push('per diem');
|
|
147
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');
|