@tasenor/common-plugins 1.17.13 → 1.17.14

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.
@@ -1,8 +1,8 @@
1
1
 
2
2
 
3
- > @tasenor/common-plugins@1.17.12 release /home/wigy/project/tasenor-qa/tasenor-bookkeeper/packages/tasenor-common-plugins
3
+ > @tasenor/common-plugins@1.17.13 release /home/wigy/project/tasenor-qa/tasenor-bookkeeper/packages/tasenor-common-plugins
4
4
  > pnpm version patch && pnpm publish --force --access public --no-git-checks
5
5
 
6
6
  npm warn Unknown env config "auto-install-peers". This will stop working in the next major version of npm.
7
- v1.17.13
7
+ v1.17.14
8
8
   WARN  using --force I sure hope you know what you are doing
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env -S npx tsx
2
+ import commonNode from '@tasenor/common-node'
3
+ const { readFile, saveText, trimCRLF } = commonNode.dataUtils
4
+
5
+ let tsv
6
+ tsv = trimCRLF(readFile('EstonianIncomeStatementReport - income-statement-fi.tsv'))
7
+ saveText('EstonianIncomeStatementReport', 'income-statement-fi.tsv', tsv)
8
+
9
+ tsv = trimCRLF(readFile('EstonianIncomeStatementReport - income-statement-detailed-fi.tsv'))
10
+ saveText('EstonianIncomeStatementReport', 'income-statement-detailed-fi.tsv', tsv)
@@ -0,0 +1,42 @@
1
+ # accounts title flags
2
+ 5000-5999 LIIKEVAIHTO DETAILS
3
+ BREAK
4
+ 5000-5999 LIIKEVAIHTO REQUIRED BOLD
5
+ 6000-6999 Liiketoiminnan muut tuotot HIDE_TOTAL BOLD
6
+ 6000-6999 _Liiketoiminnan muut tuotot DETAILS
7
+ 6000-6999 Liiketoiminnan muut tuotot yhteensä BOLD
8
+ BREAK
9
+ 7000-7099 Ostot ja alihankinta HIDE_TOTAL BOLD
10
+ 7000-7099 _Ostot ja alihankinta DETAILS
11
+ 7000-7099 Ostot ja alihankinta yhteensä BOLD
12
+ BREAK
13
+ 7100-7199 Henkilöstökulut HIDE_TOTAL BOLD
14
+ 7100-7199 _Henkilöstökulut DETAILS
15
+ 7100-7199 Henkilöstökulut yhteensä BOLD
16
+ BREAK
17
+ 7200-7299 Hallintokulut HIDE_TOTAL BOLD
18
+ 7200-7299 _Hallintokulut DETAILS
19
+ 7200-7299 Hallintokulut yhteensä BOLD
20
+ BREAK
21
+ 7300-7399 Markkinointi ja myynti HIDE_TOTAL BOLD
22
+ 7300-7399 _Markkinointi ja myynti DETAILS
23
+ 7300-7399 Markkinointi ja myynti yhteensä BOLD
24
+ BREAK
25
+ 7400-7499 Matkakulut HIDE_TOTAL BOLD
26
+ 7400-7499 _Matkakulut DETAILS
27
+ 7400-7499 Matkakulut yhteensä BOLD
28
+ BREAK
29
+ 7500-7599 Poistot ja arvonalentumiset HIDE_TOTAL BOLD
30
+ 7500-7599 _Poistot ja arvonalentumiset DETAILS
31
+ 7500-7599 Poistot ja arvonalentumiset yhteensä BOLD
32
+ BREAK
33
+ 7600-7699 Liiketoiminnan muut kulut HIDE_TOTAL BOLD
34
+ 7600-7699 _Liiketoiminnan muut kulut DETAILS
35
+ 7600-7699 Liiketoiminnan muut kulut yhteensä BOLD
36
+ BREAK
37
+ 5000-7999 VOITTO (TAPPIO) ENNEN VEROJA REQUIRED BOLD
38
+ 8000-8999 Verot HIDE_TOTAL BOLD
39
+ 8000-8999 _Verot DETAILS
40
+ 8000-8999 Verot yhteensä BOLD
41
+ BREAK
42
+ 5000-8999 TILIKAUDEN VOITTO (TAPPIO) REQUIRED BOLD
@@ -0,0 +1,13 @@
1
+ # accounts title flags
2
+ 5000-5999 LIIKEVAIHTO REQUIRED BOLD
3
+ 6000-6999 Liiketoiminnan muut tuotot
4
+ 7000-7099 Ostot ja alihankinta
5
+ 7100-7199 Henkilöstökulut
6
+ 7200-7299 Hallintokulut
7
+ 7300-7399 Markkinointi ja myynti
8
+ 7400-7499 Matkakulut
9
+ 7500-7599 Poistot ja arvonalentumiset
10
+ 7600-7699 Liiketoiminnan muut kulut
11
+ 5000-7999 VOITTO (TAPPIO) ENNEN VEROJA REQUIRED BOLD
12
+ 8000-8999 Verot yhteensä
13
+ 5000-8999 TILIKAUDEN VOITTO (TAPPIO) REQUIRED BOLD
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tasenor/common-plugins",
3
- "version": "1.17.13",
3
+ "version": "1.17.14",
4
4
  "description": "Shared common plugins of Tasenor project",
5
5
  "repository": "git@github.com:dataplugoy/tasenor-bookkeeper.git",
6
6
  "author": "Tommi Ronkainen <tommi.ronkainen@gmail.com>",
@@ -13,9 +13,9 @@
13
13
  "dayjs": "1.10.8",
14
14
  "sprintf-js": "^1.1.2",
15
15
  "tsx": "^4.7.0",
16
- "@tasenor/common": "1.17.13",
17
- "@tasenor/common-ui": "1.17.13",
18
- "@tasenor/common-node": "1.17.13"
16
+ "@tasenor/common-node": "1.17.14",
17
+ "@tasenor/common-ui": "1.17.14",
18
+ "@tasenor/common": "1.17.14"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@mui/icons-material": "^5.14.1",
@@ -31,7 +31,7 @@
31
31
  "react-i18next": "^14.0.5",
32
32
  "react-router-dom": "^6.14.1",
33
33
  "typescript": "^5.1.6",
34
- "@tasenor/config": "1.17.13",
34
+ "@tasenor/config": "1.17.14",
35
35
  "eslint-config-tasenor": "0.0.0"
36
36
  },
37
37
  "peerDependencies": {
@@ -0,0 +1,42 @@
1
+ # accounts title flags
2
+ 5000-5999 LIIKEVAIHTO DETAILS
3
+ BREAK
4
+ 5000-5999 LIIKEVAIHTO REQUIRED BOLD
5
+ 6000-6999 Liiketoiminnan muut tuotot HIDE_TOTAL BOLD
6
+ 6000-6999 _Liiketoiminnan muut tuotot DETAILS
7
+ 6000-6999 Liiketoiminnan muut tuotot yhteensä BOLD
8
+ BREAK
9
+ 7000-7099 Ostot ja alihankinta HIDE_TOTAL BOLD
10
+ 7000-7099 _Ostot ja alihankinta DETAILS
11
+ 7000-7099 Ostot ja alihankinta yhteensä BOLD
12
+ BREAK
13
+ 7100-7199 Henkilöstökulut HIDE_TOTAL BOLD
14
+ 7100-7199 _Henkilöstökulut DETAILS
15
+ 7100-7199 Henkilöstökulut yhteensä BOLD
16
+ BREAK
17
+ 7200-7299 Hallintokulut HIDE_TOTAL BOLD
18
+ 7200-7299 _Hallintokulut DETAILS
19
+ 7200-7299 Hallintokulut yhteensä BOLD
20
+ BREAK
21
+ 7300-7399 Markkinointi ja myynti HIDE_TOTAL BOLD
22
+ 7300-7399 _Markkinointi ja myynti DETAILS
23
+ 7300-7399 Markkinointi ja myynti yhteensä BOLD
24
+ BREAK
25
+ 7400-7499 Matkakulut HIDE_TOTAL BOLD
26
+ 7400-7499 _Matkakulut DETAILS
27
+ 7400-7499 Matkakulut yhteensä BOLD
28
+ BREAK
29
+ 7500-7599 Poistot ja arvonalentumiset HIDE_TOTAL BOLD
30
+ 7500-7599 _Poistot ja arvonalentumiset DETAILS
31
+ 7500-7599 Poistot ja arvonalentumiset yhteensä BOLD
32
+ BREAK
33
+ 7600-7699 Liiketoiminnan muut kulut HIDE_TOTAL BOLD
34
+ 7600-7699 _Liiketoiminnan muut kulut DETAILS
35
+ 7600-7699 Liiketoiminnan muut kulut yhteensä BOLD
36
+ BREAK
37
+ 5000-7999 VOITTO (TAPPIO) ENNEN VEROJA REQUIRED BOLD
38
+ 8000-8999 Verot HIDE_TOTAL BOLD
39
+ 8000-8999 _Verot DETAILS
40
+ 8000-8999 Verot yhteensä BOLD
41
+ BREAK
42
+ 5000-8999 TILIKAUDEN VOITTO (TAPPIO) REQUIRED BOLD
@@ -0,0 +1,13 @@
1
+ # accounts title flags
2
+ 5000-5999 LIIKEVAIHTO REQUIRED BOLD
3
+ 6000-6999 Liiketoiminnan muut tuotot
4
+ 7000-7099 Ostot ja alihankinta
5
+ 7100-7199 Henkilöstökulut
6
+ 7200-7299 Hallintokulut
7
+ 7300-7399 Markkinointi ja myynti
8
+ 7400-7499 Matkakulut
9
+ 7500-7599 Poistot ja arvonalentumiset
10
+ 7600-7699 Liiketoiminnan muut kulut
11
+ 5000-7999 VOITTO (TAPPIO) ENNEN VEROJA REQUIRED BOLD
12
+ 8000-8999 Verot yhteensä
13
+ 5000-8999 TILIKAUDEN VOITTO (TAPPIO) REQUIRED BOLD
@@ -0,0 +1,235 @@
1
+ import { AccountNumber, Language, PluginCode, ReportID, ReportOptions, Version } from '@tasenor/common'
2
+ import { ReportPlugin } from '@tasenor/common-node'
3
+ import dayjs from 'dayjs'
4
+ import quarterOfYear from 'dayjs/plugin/quarterOfYear'
5
+ dayjs.extend(quarterOfYear)
6
+
7
+ class EstonianIncomeStatementReport extends ReportPlugin {
8
+
9
+ constructor() {
10
+ super('income-statement-detailed' as ReportID, 'income-statement' as ReportID)
11
+
12
+ this.schemes = new Set(['EstonianLimitedCompanyLite'])
13
+
14
+ this.code = 'EstonianIncomeStatementReport' as PluginCode
15
+ this.title = 'Income Statement Report (Estonian)'
16
+ this.version = '1.0.18' as Version
17
+ this.icon = '<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><g><path d="M14,5H5v14h14v-9h-5V5z M8,17c-0.55,0-1-0.45-1-1s0.45-1,1-1s1,0.45,1,1S8.55,17,8,17z M8,13 c-0.55,0-1-0.45-1-1s0.45-1,1-1s1,0.45,1,1S8.55,13,8,13z M8,9C7.45,9,7,8.55,7,8s0.45-1,1-1s1,0.45,1,1S8.55,9,8,9z" opacity=".3"/><circle cx="8" cy="8" r="1"/><path d="M15,3H5C3.9,3,3.01,3.9,3.01,5L3,19c0,1.1,0.89,2,1.99,2H19c1.1,0,2-0.9,2-2V9L15,3z M19,19H5V5h9v5h5V19z"/><circle cx="8" cy="12" r="1"/><circle cx="8" cy="16" r="1"/></g></g></svg>'
18
+ this.releaseDate = '2023-03-14'
19
+ this.use = 'backend'
20
+ this.type = 'report'
21
+ this.description = 'Income statement report translated in Finnish and English.'
22
+
23
+ this.languages = {
24
+ en: {
25
+ 'report-income-statement-detailed': 'Detailed income statement',
26
+ 'report-income-statement': 'Income statement'
27
+ },
28
+ fi: {
29
+ 'report-income-statement-detailed': 'Tuloslaskelma tilierittelyin',
30
+ 'report-income-statement': 'Tuloslaskelma'
31
+ }
32
+ }
33
+ }
34
+
35
+ forceOptions(options) {
36
+ return {
37
+ negateAssetAndProfit: true,
38
+ addPreviousPeriod: !options.byTags
39
+ }
40
+ }
41
+
42
+ getLanguages(): Language[] {
43
+ return ['fi']
44
+ }
45
+
46
+ getReportOptions(): ReportOptions {
47
+ return {
48
+ month1: 'radio:1',
49
+ month2: 'radio:1',
50
+ quarter1: 'radio:1',
51
+ month4: 'radio:1',
52
+ month5: 'radio:1',
53
+ quarter2: 'radio:1',
54
+ month7: 'radio:1',
55
+ month8: 'radio:1',
56
+ quarter3: 'radio:1',
57
+ month10: 'radio:1',
58
+ month11: 'radio:1',
59
+ full: 'radio:1:default',
60
+ byTags: 'boolean'
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Construct column title for period.
66
+ * @param formatName
67
+ * @param period
68
+ * @param settings
69
+ */
70
+ columnTitle(id, period, options) {
71
+ const start = this.time2str(period.start_date)
72
+ const year = dayjs(period.start_date).year()
73
+ let end
74
+
75
+ if (options.month1) {
76
+ end = `{${dayjs(`${year}-02-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
77
+ } else if (options.month2) {
78
+ end = `{${dayjs(`${year}-03-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
79
+ } else if (options.month4) {
80
+ end = `{${dayjs(`${year}-05-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
81
+ } else if (options.month5) {
82
+ end = `{${dayjs(`${year}-06-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
83
+ } else if (options.month7) {
84
+ end = `{${dayjs(`${year}-08-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
85
+ } else if (options.month8) {
86
+ end = `{${dayjs(`${year}-09-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
87
+ } else if (options.month10) {
88
+ end = `{${dayjs(`${year}-11-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
89
+ } else if (options.month11) {
90
+ end = `{${dayjs(`${year}-12-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
91
+ } else if (options.quarter1) {
92
+ end = `{${dayjs(`${year}-04-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
93
+ } else if (options.quarter2) {
94
+ end = `{${dayjs(`${year}-07-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
95
+ } else if (options.quarter3) {
96
+ end = `{${dayjs(`${year}-10-01`).subtract(1, 'day').format('YYYY-MM-DD')}}`
97
+ } else {
98
+ end = `{${this.time2str(period.end_date)}}`
99
+ }
100
+
101
+ return '{' + start + '} — {' + end + '}'
102
+ }
103
+
104
+ async getColumns(id, entries, options, settings) {
105
+ // Construct columns for each tag and extra column for non-tagged.
106
+ if (options.byTags) {
107
+ const columns = settings.tags.map((tag) => ({
108
+ type: 'currency',
109
+ name: `tag-${tag.tag}`,
110
+ title: tag.name
111
+ }))
112
+ columns.push({
113
+ type: 'currency',
114
+ name: 'other',
115
+ title: '{Other}'
116
+ })
117
+ columns.unshift({
118
+ name: 'title',
119
+ title: '',
120
+ type: 'name'
121
+ })
122
+ return columns
123
+ }
124
+
125
+ return super.getColumns(id, entries, options, settings)
126
+ }
127
+
128
+ preProcessByTags(id, entries, options, settings, columns) {
129
+ // Prepapre.
130
+ const columnNames = columns.map((col) => col.name)
131
+ const tagSet = new Set(settings.tags.map(t => t.tag))
132
+
133
+ // Summarize all totals from the entries.
134
+ const totals: Record<string, Record<string, number>> = {}
135
+ columnNames.forEach((column) => (totals[column] = {}))
136
+ const accountNames = {}
137
+ const accountNumbers = new Set<AccountNumber>()
138
+ const regex = /^((\[\w+\])+)/
139
+ entries.forEach((entry) => {
140
+ let shares: string[] = []
141
+ const r = regex.exec(entry.description)
142
+ if (r) {
143
+ shares = r[1].substr(1, r[1].length - 2).split('][').filter(t => tagSet.has(t))
144
+ }
145
+ let amount = entry.amount
146
+ if (shares.length) {
147
+ // Share the amount so that rounding errors are split.
148
+ const piece = amount < 0 ? Math.ceil(amount / shares.length) : Math.floor(amount / shares.length)
149
+ shares.forEach((tag) => {
150
+ const column = `tag-${tag}`
151
+ totals[column][entry.number] = totals[column][entry.number] || 0
152
+ totals[column][entry.number] += piece
153
+ amount -= piece
154
+ })
155
+ if (amount) {
156
+ // Make semi-random starting point and distribute cents.
157
+ let i = (entry.periodId) % shares.length
158
+ const delta = amount < 0 ? -1 : 1
159
+ for (let count = Math.abs(amount); count > 0; count--) {
160
+ const column = `tag-${shares[i]}`
161
+ totals[column][entry.number] += delta
162
+ amount -= delta
163
+ i = (i + 1) % shares.length
164
+ }
165
+ }
166
+ }
167
+
168
+ if (amount) {
169
+ totals.other[entry.number] = totals.other[entry.number] || 0
170
+ totals.other[entry.number] += amount
171
+ }
172
+
173
+ accountNames[entry.number] = entry.name
174
+ accountNumbers.add(entry.number)
175
+ })
176
+
177
+ return this.parseAndCombineReport([...accountNumbers], accountNames, columns, options.format, totals)
178
+ }
179
+
180
+ async preProcess(id, entries, options, settings, columns) {
181
+ if (options.byTags) {
182
+ return this.preProcessByTags(id, entries, options, settings, columns)
183
+ }
184
+
185
+ const columnNames = columns.map((col) => col.name)
186
+
187
+ // Summarize all totals from the entries.
188
+ const totals = {}
189
+ columnNames.forEach((column) => (totals[column] = {}))
190
+ const accountNames = {}
191
+ const accountNumbers = new Set<AccountNumber>()
192
+ entries.forEach((entry) => {
193
+ const column = 'period' + entry.periodId
194
+ totals[column][entry.number] = totals[column][entry.number] || 0
195
+ totals[column][entry.number] += entry.amount
196
+ accountNames[entry.number] = entry.name
197
+ accountNumbers.add(entry.number)
198
+ })
199
+
200
+ return this.parseAndCombineReport([...accountNumbers], accountNames, columns, options.format, totals)
201
+ }
202
+
203
+ /**
204
+ * Remove empty columns if report made by tags.
205
+ */
206
+ async postProcess(id, data, options, settings, columns) {
207
+ if (!options.byTags) {
208
+ return data
209
+ }
210
+
211
+ // Find empty columns.
212
+ const found = new Set()
213
+ for (const line of data) {
214
+ if (!line.values) {
215
+ continue
216
+ }
217
+ for (const [k, v] of Object.entries(line.values)) {
218
+ if (v !== null && !isNaN(v as number)) {
219
+ found.add(k)
220
+ }
221
+ }
222
+ }
223
+
224
+ // Remove empty columns.
225
+ for (let i = 0; i < columns.length; i++) {
226
+ if ((columns[i].type === 'currency' || columns[i].type === 'numeric') && !found.has(columns[i].name)) {
227
+ columns.splice(i, 1)
228
+ i--
229
+ }
230
+ }
231
+ return data
232
+ }
233
+ }
234
+
235
+ export default EstonianIncomeStatementReport