iobroker.time-tracker 0.2.1 → 0.2.3

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 CHANGED
@@ -305,6 +305,20 @@ local SQLite file, access is role-based, and every correction is written to an a
305
305
 
306
306
  ### **WORK IN PROGRESS**
307
307
 
308
+ ### 0.2.3 (2026-09-20)
309
+
310
+ - (Alex) fix: a corrected object definition really reaches existing installations now — `ensureObject` merges the
311
+ fields the adapter owns (`name`, `type`, `role`, `read`, `write`, `unit`) instead of only the name. An installation
312
+ created before 0.2.2 kept its old `role: "value"` on `commands.punchUserId`, so the object structure check still
313
+ reported `E1011`
314
+
315
+ ### 0.2.2 (2026-09-20)
316
+
317
+ - (Alex) object structure check: every object name carries all **eleven languages** now (`E6001`) and the employee-id
318
+ command uses the role **`level`** instead of `value` (`E1011`). The names live in one place
319
+ (`src/lib/adapter/stateNames.ts`), a unit test keeps them complete, and existing installations receive the new
320
+ names on the next start (`extendObject`)
321
+
308
322
  ### 0.2.1 (2026-09-20)
309
323
 
310
324
  - (Alex) `common.news` starts fresh after the rename: the new npm package `iobroker.time-tracker` only carries 0.2.0,
@@ -327,27 +341,6 @@ local SQLite file, access is role-based, and every correction is written to an a
327
341
  never reached npm (E2004, its pipeline was red). `npm run version:check` watches both rules from now on: it refuses
328
342
  `common.title` and every version in the news list has to exist on npm
329
343
 
330
- ### 0.1.8 (2026-09-19)
331
-
332
- - (Alex) fix: the pipeline of 0.1.7 failed in the ioBroker package test — `common.license` was added next to the
333
- existing `common.licenseInformation`, and the test refuses both together (“common.license should not exist together
334
- with common.licenseInformation”). The field is removed again, `npm run test:package` is part of the release checklist
335
- from now on, and `docs/entwicklung.md` records the rule
336
-
337
- ### 0.1.6 (2026-09-19)
338
-
339
- - (Alex) admin: the raw instance settings show a readable label now — in the language of the display — with the
340
- technical name in the small line below it, which is what the block promises. The labels are kept short enough that
341
- the fields do not cut them off
342
- - (Alex) admin: the block “All instance settings” is much shorter — three fields per line on a wide screen (two on a
343
- tablet, one on a phone) and the time zone on a line of its own, because its value is the longest
344
- - (Alex) **rules (automatic)**: the kind **“Clock in automatically”** joins them — an employee who is still missing at
345
- the configured time gets a punch in (the rule keeps quiet when somebody is clocked in already). Migration 18 rebuilds
346
- the rule table for the new kind and copies the run log first, because dropping the parent would take it with it
347
- - (Alex) **holidays**: the seeded days are shown in the language of the display — each one carries a stable key
348
- (`newYear`, `goodFriday`, …) and the app translates it; a day somebody added by hand keeps its own name
349
- - (Alex) admin: the two “first start” hints are easier to read — they are rendered as HTML with a larger font
350
-
351
344
  Older entries are kept in [`CHANGELOG_OLD.md`](CHANGELOG_OLD.md).
352
345
 
353
346
  ## Provenance
@@ -0,0 +1,520 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var stateNames_exports = {};
20
+ __export(stateNames_exports, {
21
+ STATE_NAMES: () => STATE_NAMES
22
+ });
23
+ module.exports = __toCommonJS(stateNames_exports);
24
+ const STATE_NAMES = {
25
+ /** Channel holding the employees */
26
+ usersChannel: {
27
+ en: "Employees",
28
+ de: "Mitarbeiter",
29
+ ru: "\u0421\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u0438",
30
+ pt: "Funcion\xE1rios",
31
+ nl: "Medewerkers",
32
+ fr: "Employ\xE9s",
33
+ it: "Dipendenti",
34
+ es: "Empleados",
35
+ pl: "Pracownicy",
36
+ uk: "\u0421\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A\u0438",
37
+ "zh-cn": "\u5458\u5DE5"
38
+ },
39
+ /** Channel of one employee */
40
+ employeeChannel: {
41
+ en: "Employee",
42
+ de: "Mitarbeiter",
43
+ ru: "\u0421\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A",
44
+ pt: "Funcion\xE1rio",
45
+ nl: "Medewerker",
46
+ fr: "Employ\xE9",
47
+ it: "Dipendente",
48
+ es: "Empleado",
49
+ pl: "Pracownik",
50
+ uk: "\u0421\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A",
51
+ "zh-cn": "\u5458\u5DE5"
52
+ },
53
+ /** Channel of the writable commands */
54
+ commandsChannel: {
55
+ en: "Commands",
56
+ de: "Befehle",
57
+ ru: "\u041A\u043E\u043C\u0430\u043D\u0434\u044B",
58
+ pt: "Comandos",
59
+ nl: "Opdrachten",
60
+ fr: "Commandes",
61
+ it: "Comandi",
62
+ es: "Comandos",
63
+ pl: "Polecenia",
64
+ uk: "\u041A\u043E\u043C\u0430\u043D\u0434\u0438",
65
+ "zh-cn": "\u547D\u4EE4"
66
+ },
67
+ /** Channel with the figures of the instance */
68
+ infoChannel: {
69
+ en: "Information",
70
+ de: "Information",
71
+ ru: "\u0418\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F",
72
+ pt: "Informa\xE7\xE3o",
73
+ nl: "Informatie",
74
+ fr: "Informations",
75
+ it: "Informazioni",
76
+ es: "Informaci\xF3n",
77
+ pl: "Informacje",
78
+ uk: "\u0406\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044F",
79
+ "zh-cn": "\u4FE1\u606F"
80
+ },
81
+ /** Channel with the figures of the whole company */
82
+ companyChannel: {
83
+ en: "Company",
84
+ de: "Firma",
85
+ ru: "\u041A\u043E\u043C\u043F\u0430\u043D\u0438\u044F",
86
+ pt: "Empresa",
87
+ nl: "Bedrijf",
88
+ fr: "Entreprise",
89
+ it: "Azienda",
90
+ es: "Empresa",
91
+ pl: "Firma",
92
+ uk: "\u041A\u043E\u043C\u043F\u0430\u043D\u0456\u044F",
93
+ "zh-cn": "\u516C\u53F8"
94
+ },
95
+ /** Channel with the newest event of the instance */
96
+ eventsChannel: {
97
+ en: "Events",
98
+ de: "Ereignisse",
99
+ ru: "\u0421\u043E\u0431\u044B\u0442\u0438\u044F",
100
+ pt: "Eventos",
101
+ nl: "Gebeurtenissen",
102
+ fr: "\xC9v\xE9nements",
103
+ it: "Eventi",
104
+ es: "Eventos",
105
+ pl: "Zdarzenia",
106
+ uk: "\u041F\u043E\u0434\u0456\u0457",
107
+ "zh-cn": "\u4E8B\u4EF6"
108
+ },
109
+ /** Shown name of the employee */
110
+ displayName: {
111
+ en: "Name",
112
+ de: "Name",
113
+ ru: "\u0418\u043C\u044F",
114
+ pt: "Nome",
115
+ nl: "Naam",
116
+ fr: "Nom",
117
+ it: "Nome",
118
+ es: "Nombre",
119
+ pl: "Nazwa",
120
+ uk: "\u0406\u043C'\u044F",
121
+ "zh-cn": "\u59D3\u540D"
122
+ },
123
+ /** Writable presence of the employee (working time runs) */
124
+ userPresent: {
125
+ en: "Present (working time is running)",
126
+ de: "Anwesenheit (Arbeitszeit l\xE4uft)",
127
+ ru: "\u041F\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 (\u0440\u0430\u0431\u043E\u0447\u0435\u0435 \u0432\u0440\u0435\u043C\u044F \u0438\u0434\u0451\u0442)",
128
+ pt: "Presente (o tempo de trabalho corre)",
129
+ nl: "Aanwezig (werktijd loopt)",
130
+ fr: "Pr\xE9sent (temps de travail en cours)",
131
+ it: "Presente (tempo di lavoro in corso)",
132
+ es: "Presente (tiempo de trabajo en curso)",
133
+ pl: "Obecno\u015B\u0107 (czas pracy trwa)",
134
+ uk: "\u041F\u0440\u0438\u0441\u0443\u0442\u043D\u0456\u0441\u0442\u044C (\u0440\u043E\u0431\u043E\u0447\u0438\u0439 \u0447\u0430\u0441 \u0456\u0434\u0435)",
135
+ "zh-cn": "\u5728\u5C97\uFF08\u5DE5\u4F5C\u65F6\u95F4\u8BA1\u65F6\u4E2D\uFF09"
136
+ },
137
+ /** True while the last punch of the day has no counterpart */
138
+ hasOpenEntry: {
139
+ en: "Punched in",
140
+ de: "Eingestempelt",
141
+ ru: "\u041F\u0440\u0438\u0445\u043E\u0434 \u043E\u0442\u043C\u0435\u0447\u0435\u043D",
142
+ pt: "Entrada registada",
143
+ nl: "Ingeklokt",
144
+ fr: "Pointage d'arriv\xE9e",
145
+ it: "Entrata registrata",
146
+ es: "Entrada registrada",
147
+ pl: "Zarejestrowane wej\u015Bcie",
148
+ uk: "\u0412\u0456\u0434\u043C\u0456\u0447\u0435\u043D\u043E \u043F\u0440\u0438\u0445\u0456\u0434",
149
+ "zh-cn": "\u5DF2\u7B7E\u5230"
150
+ },
151
+ /** Instant of the last punch */
152
+ lastPunch: {
153
+ en: "Last punch",
154
+ de: "Letzte Buchung",
155
+ ru: "\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u043E\u0442\u043C\u0435\u0442\u043A\u0430",
156
+ pt: "\xDAltimo registo",
157
+ nl: "Laatste stempeling",
158
+ fr: "Dernier pointage",
159
+ it: "Ultima timbratura",
160
+ es: "\xDAltimo registro",
161
+ pl: "Ostatni wpis",
162
+ uk: "\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0432\u0456\u0434\u043C\u0456\u0442\u043A\u0430",
163
+ "zh-cn": "\u6700\u540E\u6253\u5361"
164
+ },
165
+ /** Net working time of today */
166
+ todayWorkedMinutes: {
167
+ en: "Worked today",
168
+ de: "Heute gearbeitet",
169
+ ru: "\u041E\u0442\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u043E \u0441\u0435\u0433\u043E\u0434\u043D\u044F",
170
+ pt: "Trabalhado hoje",
171
+ nl: "Vandaag gewerkt",
172
+ fr: "Travaill\xE9 aujourd'hui",
173
+ it: "Lavorato oggi",
174
+ es: "Trabajado hoy",
175
+ pl: "Przepracowane dzi\u015B",
176
+ uk: "\u0412\u0456\u0434\u043F\u0440\u0430\u0446\u044C\u043E\u0432\u0430\u043D\u043E \u0441\u044C\u043E\u0433\u043E\u0434\u043D\u0456",
177
+ "zh-cn": "\u4ECA\u65E5\u5DF2\u5DE5\u4F5C"
178
+ },
179
+ /** Balance of today */
180
+ todayBalanceMinutes: {
181
+ en: "Balance today",
182
+ de: "Saldo heute",
183
+ ru: "\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0441\u0435\u0433\u043E\u0434\u043D\u044F",
184
+ pt: "Saldo de hoje",
185
+ nl: "Saldo vandaag",
186
+ fr: "Solde du jour",
187
+ it: "Saldo di oggi",
188
+ es: "Saldo de hoy",
189
+ pl: "Saldo dzisiaj",
190
+ uk: "\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0441\u044C\u043E\u0433\u043E\u0434\u043D\u0456",
191
+ "zh-cn": "\u4ECA\u65E5\u4F59\u989D"
192
+ },
193
+ /** Net working time of the current month */
194
+ monthWorkedMinutes: {
195
+ en: "Worked this month",
196
+ de: "Diesen Monat gearbeitet",
197
+ ru: "\u041E\u0442\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u043E \u0437\u0430 \u043C\u0435\u0441\u044F\u0446",
198
+ pt: "Trabalhado este m\xEAs",
199
+ nl: "Deze maand gewerkt",
200
+ fr: "Travaill\xE9 ce mois",
201
+ it: "Lavorato questo mese",
202
+ es: "Trabajado este mes",
203
+ pl: "Przepracowane w tym miesi\u0105cu",
204
+ uk: "\u0412\u0456\u0434\u043F\u0440\u0430\u0446\u044C\u043E\u0432\u0430\u043D\u043E \u0446\u044C\u043E\u0433\u043E \u043C\u0456\u0441\u044F\u0446\u044F",
205
+ "zh-cn": "\u672C\u6708\u5DF2\u5DE5\u4F5C"
206
+ },
207
+ /** Balance of the current month */
208
+ monthBalanceMinutes: {
209
+ en: "Balance this month",
210
+ de: "Saldo diesen Monat",
211
+ ru: "\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u043C\u0435\u0441\u044F\u0446",
212
+ pt: "Saldo deste m\xEAs",
213
+ nl: "Saldo deze maand",
214
+ fr: "Solde du mois",
215
+ it: "Saldo di questo mese",
216
+ es: "Saldo de este mes",
217
+ pl: "Saldo w tym miesi\u0105cu",
218
+ uk: "\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0446\u0435\u0439 \u043C\u0456\u0441\u044F\u0446\u044C",
219
+ "zh-cn": "\u672C\u6708\u4F59\u989D"
220
+ },
221
+ /** Balance of the current year */
222
+ yearBalanceMinutes: {
223
+ en: "Balance this year",
224
+ de: "Saldo dieses Jahr",
225
+ ru: "\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0433\u043E\u0434",
226
+ pt: "Saldo deste ano",
227
+ nl: "Saldo dit jaar",
228
+ fr: "Solde de l'ann\xE9e",
229
+ it: "Saldo di quest'anno",
230
+ es: "Saldo de este a\xF1o",
231
+ pl: "Saldo w tym roku",
232
+ uk: "\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0446\u0435\u0439 \u0440\u0456\u043A",
233
+ "zh-cn": "\u672C\u5E74\u4F59\u989D"
234
+ },
235
+ /** Punches waiting for a decision */
236
+ openConflicts: {
237
+ en: "Open conflicts",
238
+ de: "Offene Konflikte",
239
+ ru: "\u041E\u0442\u043A\u0440\u044B\u0442\u044B\u0435 \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u044B",
240
+ pt: "Conflitos em aberto",
241
+ nl: "Openstaande conflicten",
242
+ fr: "Conflits en attente",
243
+ it: "Conflitti aperti",
244
+ es: "Conflictos abiertos",
245
+ pl: "Otwarte konflikty",
246
+ uk: "\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0456 \u043A\u043E\u043D\u0444\u043B\u0456\u043A\u0442\u0438",
247
+ "zh-cn": "\u672A\u89E3\u51B3\u7684\u51B2\u7A81"
248
+ },
249
+ /** Employee the punch commands apply to */
250
+ punchUserId: {
251
+ en: "Employee id for punch commands",
252
+ de: "Mitarbeiter-Id f\xFCr Stempelbefehle",
253
+ ru: "\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0441\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u0430 \u0434\u043B\u044F \u043A\u043E\u043C\u0430\u043D\u0434",
254
+ pt: "ID do funcion\xE1rio para comandos",
255
+ nl: "Medewerker-id voor opdrachten",
256
+ fr: "Identifiant de l'employ\xE9 pour les commandes",
257
+ it: "ID del dipendente per i comandi",
258
+ es: "ID del empleado para comandos",
259
+ pl: "Identyfikator pracownika dla polece\u0144",
260
+ uk: "\u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0441\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A\u0430 \u0434\u043B\u044F \u043A\u043E\u043C\u0430\u043D\u0434",
261
+ "zh-cn": "\u6253\u5361\u547D\u4EE4\u7684\u5458\u5DE5 ID"
262
+ },
263
+ /** Button: punch in or out */
264
+ punch: {
265
+ en: "Punch in or out",
266
+ de: "Ein- oder ausstempeln",
267
+ ru: "\u041E\u0442\u043C\u0435\u0442\u0438\u0442\u044C\u0441\u044F (\u043F\u0440\u0438\u0445\u043E\u0434 \u0438\u043B\u0438 \u0443\u0445\u043E\u0434)",
268
+ pt: "Marcar entrada ou sa\xEDda",
269
+ nl: "In- of uitklokken",
270
+ fr: "Pointer l'arriv\xE9e ou le d\xE9part",
271
+ it: "Timbrare entrata o uscita",
272
+ es: "Fichar entrada o salida",
273
+ pl: "Zarejestruj wej\u015Bcie lub wyj\u015Bcie",
274
+ uk: "\u0412\u0456\u0434\u043C\u0456\u0442\u0438\u0442\u0438 \u043F\u0440\u0438\u0445\u0456\u0434 \u0430\u0431\u043E \u0432\u0438\u0445\u0456\u0434",
275
+ "zh-cn": "\u4E0A\u73ED\u6216\u4E0B\u73ED\u6253\u5361"
276
+ },
277
+ /** Button: punch and round the time */
278
+ quickPunch: {
279
+ en: "Punch with quick rounding",
280
+ de: "Stempeln mit Schnellrundung",
281
+ ru: "\u041E\u0442\u043C\u0435\u0442\u0438\u0442\u044C\u0441\u044F \u0441 \u0431\u044B\u0441\u0442\u0440\u044B\u043C \u043E\u043A\u0440\u0443\u0433\u043B\u0435\u043D\u0438\u0435\u043C",
282
+ pt: "Marcar com arredondamento r\xE1pido",
283
+ nl: "Klokken met snelle afronding",
284
+ fr: "Pointer avec arrondi rapide",
285
+ it: "Timbrare con arrotondamento rapido",
286
+ es: "Fichar con redondeo r\xE1pido",
287
+ pl: "Zarejestruj z szybkim zaokr\u0105gleniem",
288
+ uk: "\u0412\u0456\u0434\u043C\u0456\u0442\u0438\u0442\u0438 \u0437\u0456 \u0448\u0432\u0438\u0434\u043A\u0438\u043C \u043E\u043A\u0440\u0443\u0433\u043B\u0435\u043D\u043D\u044F\u043C",
289
+ "zh-cn": "\u5FEB\u901F\u53D6\u6574\u6253\u5361"
290
+ },
291
+ /** Month to close */
292
+ closeMonth: {
293
+ en: "Close month (YYYY-MM)",
294
+ de: "Monat abschlie\xDFen (JJJJ-MM)",
295
+ ru: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u0441\u044F\u0446 (\u0413\u0413\u0413\u0413-\u041C\u041C)",
296
+ pt: "Fechar m\xEAs (AAAA-MM)",
297
+ nl: "Maand afsluiten (JJJJ-MM)",
298
+ fr: "Cl\xF4turer le mois (AAAA-MM)",
299
+ it: "Chiudere il mese (AAAA-MM)",
300
+ es: "Cerrar mes (AAAA-MM)",
301
+ pl: "Zamknij miesi\u0105c (RRRR-MM)",
302
+ uk: "\u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u043C\u0456\u0441\u044F\u0446\u044C (\u0420\u0420\u0420\u0420-\u041C\u041C)",
303
+ "zh-cn": "\u5173\u95ED\u6708\u4EFD\uFF08YYYY-MM\uFF09"
304
+ },
305
+ /** Period to recalculate */
306
+ recalc: {
307
+ en: "Recalculate period (YYYY-MM or YYYY)",
308
+ de: "Zeitraum neu berechnen (JJJJ-MM oder JJJJ)",
309
+ ru: "\u041F\u0435\u0440\u0435\u0441\u0447\u0438\u0442\u0430\u0442\u044C \u043F\u0435\u0440\u0438\u043E\u0434 (\u0413\u0413\u0413\u0413-\u041C\u041C \u0438\u043B\u0438 \u0413\u0413\u0413\u0413)",
310
+ pt: "Recalcular per\xEDodo (AAAA-MM ou AAAA)",
311
+ nl: "Periode opnieuw berekenen (JJJJ-MM of JJJJ)",
312
+ fr: "Recalculer la p\xE9riode (AAAA-MM ou AAAA)",
313
+ it: "Ricalcolare il periodo (AAAA-MM o AAAA)",
314
+ es: "Recalcular periodo (AAAA-MM o AAAA)",
315
+ pl: "Przelicz okres (RRRR-MM lub RRRR)",
316
+ uk: "\u041F\u0435\u0440\u0435\u0440\u0430\u0445\u0443\u0432\u0430\u0442\u0438 \u043F\u0435\u0440\u0456\u043E\u0434 (\u0420\u0420\u0420\u0420-\u041C\u041C \u0430\u0431\u043E \u0420\u0420\u0420\u0420)",
317
+ "zh-cn": "\u91CD\u65B0\u8BA1\u7B97\u671F\u95F4\uFF08YYYY-MM \u6216 YYYY\uFF09"
318
+ },
319
+ /** Button: write a database backup */
320
+ backupCommand: {
321
+ en: "Write a database backup",
322
+ de: "Datenbank-Sicherung schreiben",
323
+ ru: "\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u0443\u044E \u043A\u043E\u043F\u0438\u044E \u0431\u0430\u0437\u044B",
324
+ pt: "Criar c\xF3pia de seguran\xE7a da base de dados",
325
+ nl: "Databasback-up maken",
326
+ fr: "Cr\xE9er une sauvegarde de la base",
327
+ it: "Creare un backup del database",
328
+ es: "Crear copia de seguridad de la base",
329
+ pl: "Utw\xF3rz kopi\u0119 zapasow\u0105 bazy",
330
+ uk: "\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u0443 \u043A\u043E\u043F\u0456\u044E \u0431\u0430\u0437\u0438",
331
+ "zh-cn": "\u5199\u5165\u6570\u636E\u5E93\u5907\u4EFD"
332
+ },
333
+ /** Version of the adapter */
334
+ version: {
335
+ en: "Adapter version",
336
+ de: "Adapter-Version",
337
+ ru: "\u0412\u0435\u0440\u0441\u0438\u044F \u0430\u0434\u0430\u043F\u0442\u0435\u0440\u0430",
338
+ pt: "Vers\xE3o do adaptador",
339
+ nl: "Adapterversie",
340
+ fr: "Version de l'adaptateur",
341
+ it: "Versione dell'adattatore",
342
+ es: "Versi\xF3n del adaptador",
343
+ pl: "Wersja adaptera",
344
+ uk: "\u0412\u0435\u0440\u0441\u0456\u044F \u0430\u0434\u0430\u043F\u0442\u0435\u0440\u0430",
345
+ "zh-cn": "\u9002\u914D\u5668\u7248\u672C"
346
+ },
347
+ /** Version of the database schema */
348
+ schemaVersion: {
349
+ en: "Database schema version",
350
+ de: "Datenbank-Schemaversion",
351
+ ru: "\u0412\u0435\u0440\u0441\u0438\u044F \u0441\u0445\u0435\u043C\u044B \u0431\u0430\u0437\u044B \u0434\u0430\u043D\u043D\u044B\u0445",
352
+ pt: "Vers\xE3o do esquema da base de dados",
353
+ nl: "Schemaversie van de database",
354
+ fr: "Version du sch\xE9ma de la base",
355
+ it: "Versione dello schema del database",
356
+ es: "Versi\xF3n del esquema de la base",
357
+ pl: "Wersja schematu bazy",
358
+ uk: "\u0412\u0435\u0440\u0441\u0456\u044F \u0441\u0445\u0435\u043C\u0438 \u0431\u0430\u0437\u0438 \u0434\u0430\u043D\u0438\u0445",
359
+ "zh-cn": "\u6570\u636E\u5E93\u67B6\u6784\u7248\u672C"
360
+ },
361
+ /** Size of the database file */
362
+ dbSizeBytes: {
363
+ en: "Database size",
364
+ de: "Datenbank-Gr\xF6\xDFe",
365
+ ru: "\u0420\u0430\u0437\u043C\u0435\u0440 \u0431\u0430\u0437\u044B \u0434\u0430\u043D\u043D\u044B\u0445",
366
+ pt: "Tamanho da base de dados",
367
+ nl: "Grootte van de database",
368
+ fr: "Taille de la base",
369
+ it: "Dimensione del database",
370
+ es: "Tama\xF1o de la base",
371
+ pl: "Rozmiar bazy",
372
+ uk: "\u0420\u043E\u0437\u043C\u0456\u0440 \u0431\u0430\u0437\u0438 \u0434\u0430\u043D\u0438\u0445",
373
+ "zh-cn": "\u6570\u636E\u5E93\u5927\u5C0F"
374
+ },
375
+ /** Last error of the instance */
376
+ lastError: {
377
+ en: "Last error",
378
+ de: "Letzter Fehler",
379
+ ru: "\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u043E\u0448\u0438\u0431\u043A\u0430",
380
+ pt: "\xDAltimo erro",
381
+ nl: "Laatste fout",
382
+ fr: "Derni\xE8re erreur",
383
+ it: "Ultimo errore",
384
+ es: "\xDAltimo error",
385
+ pl: "Ostatni b\u0142\u0105d",
386
+ uk: "\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u043F\u043E\u043C\u0438\u043B\u043A\u0430",
387
+ "zh-cn": "\u6700\u540E\u7684\u9519\u8BEF"
388
+ },
389
+ /** Instant of the last backup */
390
+ lastBackup: {
391
+ en: "Last backup",
392
+ de: "Letzte Sicherung",
393
+ ru: "\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u0430\u044F \u043A\u043E\u043F\u0438\u044F",
394
+ pt: "\xDAltima c\xF3pia de seguran\xE7a",
395
+ nl: "Laatste back-up",
396
+ fr: "Derni\xE8re sauvegarde",
397
+ it: "Ultimo backup",
398
+ es: "\xDAltima copia de seguridad",
399
+ pl: "Ostatnia kopia zapasowa",
400
+ uk: "\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u0430 \u043A\u043E\u043F\u0456\u044F",
401
+ "zh-cn": "\u6700\u540E\u7684\u5907\u4EFD"
402
+ },
403
+ /** Number of employees that are present */
404
+ companyPresentCount: {
405
+ en: "Present employees",
406
+ de: "Anwesende Mitarbeiter",
407
+ ru: "\u041F\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0435 \u0441\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u0438",
408
+ pt: "Funcion\xE1rios presentes",
409
+ nl: "Aanwezige medewerkers",
410
+ fr: "Employ\xE9s pr\xE9sents",
411
+ it: "Dipendenti presenti",
412
+ es: "Empleados presentes",
413
+ pl: "Obecni pracownicy",
414
+ uk: "\u041F\u0440\u0438\u0441\u0443\u0442\u043D\u0456 \u0441\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A\u0438",
415
+ "zh-cn": "\u5728\u5C97\u5458\u5DE5"
416
+ },
417
+ /** Names of the employees that are present */
418
+ companyPresent: {
419
+ en: "Who is present",
420
+ de: "Wer ist anwesend",
421
+ ru: "\u041A\u0442\u043E \u043F\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442",
422
+ pt: "Quem est\xE1 presente",
423
+ nl: "Wie is aanwezig",
424
+ fr: "Qui est pr\xE9sent",
425
+ it: "Chi \xE8 presente",
426
+ es: "Qui\xE9n est\xE1 presente",
427
+ pl: "Kto jest obecny",
428
+ uk: "\u0425\u0442\u043E \u043F\u0440\u0438\u0441\u0443\u0442\u043D\u0456\u0439",
429
+ "zh-cn": "\u8C01\u5728\u5C97"
430
+ },
431
+ /** Instant of the newest punch of the company */
432
+ companyLastPunch: {
433
+ en: "Last punch",
434
+ de: "Letzte Buchung",
435
+ ru: "\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u043E\u0442\u043C\u0435\u0442\u043A\u0430",
436
+ pt: "\xDAltimo registo",
437
+ nl: "Laatste stempeling",
438
+ fr: "Dernier pointage",
439
+ it: "Ultima timbratura",
440
+ es: "\xDAltimo registro",
441
+ pl: "Ostatni wpis",
442
+ uk: "\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0432\u0456\u0434\u043C\u0456\u0442\u043A\u0430",
443
+ "zh-cn": "\u6700\u540E\u6253\u5361"
444
+ },
445
+ /** Instant of the newest event */
446
+ lastAt: {
447
+ en: "Last event at",
448
+ de: "Letztes Ereignis um",
449
+ ru: "\u0412\u0440\u0435\u043C\u044F \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F",
450
+ pt: "Hora do \xFAltimo evento",
451
+ nl: "Tijdstip laatste gebeurtenis",
452
+ fr: "Heure du dernier \xE9v\xE9nement",
453
+ it: "Ora dell'ultimo evento",
454
+ es: "Hora del \xFAltimo evento",
455
+ pl: "Czas ostatniego zdarzenia",
456
+ uk: "\u0427\u0430\u0441 \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u043F\u043E\u0434\u0456\u0457",
457
+ "zh-cn": "\u6700\u540E\u4E8B\u4EF6\u65F6\u95F4"
458
+ },
459
+ /** Kind of the newest event */
460
+ lastType: {
461
+ en: "Kind of the last event",
462
+ de: "Art des letzten Ereignisses",
463
+ ru: "\u0422\u0438\u043F \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F",
464
+ pt: "Tipo do \xFAltimo evento",
465
+ nl: "Soort laatste gebeurtenis",
466
+ fr: "Type du dernier \xE9v\xE9nement",
467
+ it: "Tipo dell'ultimo evento",
468
+ es: "Tipo del \xFAltimo evento",
469
+ pl: "Rodzaj ostatniego zdarzenia",
470
+ uk: "\u0422\u0438\u043F \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u043F\u043E\u0434\u0456\u0457",
471
+ "zh-cn": "\u6700\u540E\u4E8B\u4EF6\u7C7B\u578B"
472
+ },
473
+ /** Employee of the newest event */
474
+ lastUser: {
475
+ en: "Employee of the last event",
476
+ de: "Mitarbeiter des letzten Ereignisses",
477
+ ru: "\u0421\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F",
478
+ pt: "Funcion\xE1rio do \xFAltimo evento",
479
+ nl: "Medewerker van de laatste gebeurtenis",
480
+ fr: "Employ\xE9 du dernier \xE9v\xE9nement",
481
+ it: "Dipendente dell'ultimo evento",
482
+ es: "Empleado del \xFAltimo evento",
483
+ pl: "Pracownik ostatniego zdarzenia",
484
+ uk: "\u0421\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u043F\u043E\u0434\u0456\u0457",
485
+ "zh-cn": "\u6700\u540E\u4E8B\u4EF6\u7684\u5458\u5DE5"
486
+ },
487
+ /** Direction of the newest punch */
488
+ lastDirection: {
489
+ en: "Direction of the last punch",
490
+ de: "Richtung der letzten Buchung",
491
+ ru: "\u041D\u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0439 \u043E\u0442\u043C\u0435\u0442\u043A\u0438",
492
+ pt: "Dire\xE7\xE3o do \xFAltimo registo",
493
+ nl: "Richting van de laatste stempeling",
494
+ fr: "Sens du dernier pointage",
495
+ it: "Direzione dell'ultima timbratura",
496
+ es: "Direcci\xF3n del \xFAltimo registro",
497
+ pl: "Kierunek ostatniego wpisu",
498
+ uk: "\u041D\u0430\u043F\u0440\u044F\u043C\u043E\u043A \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u0432\u0456\u0434\u043C\u0456\u0442\u043A\u0438",
499
+ "zh-cn": "\u6700\u540E\u6253\u5361\u7684\u65B9\u5411"
500
+ },
501
+ /** Source of the newest event */
502
+ lastSource: {
503
+ en: "Source of the last event",
504
+ de: "Quelle des letzten Ereignisses",
505
+ ru: "\u0418\u0441\u0442\u043E\u0447\u043D\u0438\u043A \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F",
506
+ pt: "Origem do \xFAltimo evento",
507
+ nl: "Bron van de laatste gebeurtenis",
508
+ fr: "Source du dernier \xE9v\xE9nement",
509
+ it: "Origine dell'ultimo evento",
510
+ es: "Origen del \xFAltimo evento",
511
+ pl: "\u0179r\xF3d\u0142o ostatniego zdarzenia",
512
+ uk: "\u0414\u0436\u0435\u0440\u0435\u043B\u043E \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u043F\u043E\u0434\u0456\u0457",
513
+ "zh-cn": "\u6700\u540E\u4E8B\u4EF6\u7684\u6765\u6E90"
514
+ }
515
+ };
516
+ // Annotate the CommonJS export names for ESM import in node:
517
+ 0 && (module.exports = {
518
+ STATE_NAMES
519
+ });
520
+ //# sourceMappingURL=stateNames.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/adapter/stateNames.ts"],
4
+ "sourcesContent": ["/**\n * Names of the adapter's objects, in the eleven languages ioBroker recommends (checker `E6001`).\n *\n * `states.ts` creates the tree; this module is the single place that carries the texts, so every name has the same\n * set of languages. `states.test.ts` walks the whole tree and fails when a name misses one of the eleven keys \u2014\n * that is how the recommendation stays satisfied without anyone remembering it.\n */\n\n/** One object name: the eleven languages the ioBroker checker recommends. */\nexport interface StateName {\n\t/** English */\n\ten: string;\n\t/** German */\n\tde: string;\n\t/** Russian */\n\tru: string;\n\t/** Portuguese */\n\tpt: string;\n\t/** Dutch */\n\tnl: string;\n\t/** French */\n\tfr: string;\n\t/** Italian */\n\tit: string;\n\t/** Spanish */\n\tes: string;\n\t/** Polish */\n\tpl: string;\n\t/** Ukrainian */\n\tuk: string;\n\t/** Chinese (simplified) */\n\t\"zh-cn\": string;\n}\n\n/** Object names of the adapter, grouped like the state tree. */\nexport const STATE_NAMES = {\n\t/** Channel holding the employees */\n\tusersChannel: {\n\t\ten: \"Employees\",\n\t\tde: \"Mitarbeiter\",\n\t\tru: \"\u0421\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u0438\",\n\t\tpt: \"Funcion\u00E1rios\",\n\t\tnl: \"Medewerkers\",\n\t\tfr: \"Employ\u00E9s\",\n\t\tit: \"Dipendenti\",\n\t\tes: \"Empleados\",\n\t\tpl: \"Pracownicy\",\n\t\tuk: \"\u0421\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A\u0438\",\n\t\t\"zh-cn\": \"\u5458\u5DE5\",\n\t},\n\t/** Channel of one employee */\n\temployeeChannel: {\n\t\ten: \"Employee\",\n\t\tde: \"Mitarbeiter\",\n\t\tru: \"\u0421\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\",\n\t\tpt: \"Funcion\u00E1rio\",\n\t\tnl: \"Medewerker\",\n\t\tfr: \"Employ\u00E9\",\n\t\tit: \"Dipendente\",\n\t\tes: \"Empleado\",\n\t\tpl: \"Pracownik\",\n\t\tuk: \"\u0421\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A\",\n\t\t\"zh-cn\": \"\u5458\u5DE5\",\n\t},\n\t/** Channel of the writable commands */\n\tcommandsChannel: {\n\t\ten: \"Commands\",\n\t\tde: \"Befehle\",\n\t\tru: \"\u041A\u043E\u043C\u0430\u043D\u0434\u044B\",\n\t\tpt: \"Comandos\",\n\t\tnl: \"Opdrachten\",\n\t\tfr: \"Commandes\",\n\t\tit: \"Comandi\",\n\t\tes: \"Comandos\",\n\t\tpl: \"Polecenia\",\n\t\tuk: \"\u041A\u043E\u043C\u0430\u043D\u0434\u0438\",\n\t\t\"zh-cn\": \"\u547D\u4EE4\",\n\t},\n\t/** Channel with the figures of the instance */\n\tinfoChannel: {\n\t\ten: \"Information\",\n\t\tde: \"Information\",\n\t\tru: \"\u0418\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F\",\n\t\tpt: \"Informa\u00E7\u00E3o\",\n\t\tnl: \"Informatie\",\n\t\tfr: \"Informations\",\n\t\tit: \"Informazioni\",\n\t\tes: \"Informaci\u00F3n\",\n\t\tpl: \"Informacje\",\n\t\tuk: \"\u0406\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044F\",\n\t\t\"zh-cn\": \"\u4FE1\u606F\",\n\t},\n\t/** Channel with the figures of the whole company */\n\tcompanyChannel: {\n\t\ten: \"Company\",\n\t\tde: \"Firma\",\n\t\tru: \"\u041A\u043E\u043C\u043F\u0430\u043D\u0438\u044F\",\n\t\tpt: \"Empresa\",\n\t\tnl: \"Bedrijf\",\n\t\tfr: \"Entreprise\",\n\t\tit: \"Azienda\",\n\t\tes: \"Empresa\",\n\t\tpl: \"Firma\",\n\t\tuk: \"\u041A\u043E\u043C\u043F\u0430\u043D\u0456\u044F\",\n\t\t\"zh-cn\": \"\u516C\u53F8\",\n\t},\n\t/** Channel with the newest event of the instance */\n\teventsChannel: {\n\t\ten: \"Events\",\n\t\tde: \"Ereignisse\",\n\t\tru: \"\u0421\u043E\u0431\u044B\u0442\u0438\u044F\",\n\t\tpt: \"Eventos\",\n\t\tnl: \"Gebeurtenissen\",\n\t\tfr: \"\u00C9v\u00E9nements\",\n\t\tit: \"Eventi\",\n\t\tes: \"Eventos\",\n\t\tpl: \"Zdarzenia\",\n\t\tuk: \"\u041F\u043E\u0434\u0456\u0457\",\n\t\t\"zh-cn\": \"\u4E8B\u4EF6\",\n\t},\n\t/** Shown name of the employee */\n\tdisplayName: {\n\t\ten: \"Name\",\n\t\tde: \"Name\",\n\t\tru: \"\u0418\u043C\u044F\",\n\t\tpt: \"Nome\",\n\t\tnl: \"Naam\",\n\t\tfr: \"Nom\",\n\t\tit: \"Nome\",\n\t\tes: \"Nombre\",\n\t\tpl: \"Nazwa\",\n\t\tuk: \"\u0406\u043C'\u044F\",\n\t\t\"zh-cn\": \"\u59D3\u540D\",\n\t},\n\t/** Writable presence of the employee (working time runs) */\n\tuserPresent: {\n\t\ten: \"Present (working time is running)\",\n\t\tde: \"Anwesenheit (Arbeitszeit l\u00E4uft)\",\n\t\tru: \"\u041F\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 (\u0440\u0430\u0431\u043E\u0447\u0435\u0435 \u0432\u0440\u0435\u043C\u044F \u0438\u0434\u0451\u0442)\",\n\t\tpt: \"Presente (o tempo de trabalho corre)\",\n\t\tnl: \"Aanwezig (werktijd loopt)\",\n\t\tfr: \"Pr\u00E9sent (temps de travail en cours)\",\n\t\tit: \"Presente (tempo di lavoro in corso)\",\n\t\tes: \"Presente (tiempo de trabajo en curso)\",\n\t\tpl: \"Obecno\u015B\u0107 (czas pracy trwa)\",\n\t\tuk: \"\u041F\u0440\u0438\u0441\u0443\u0442\u043D\u0456\u0441\u0442\u044C (\u0440\u043E\u0431\u043E\u0447\u0438\u0439 \u0447\u0430\u0441 \u0456\u0434\u0435)\",\n\t\t\"zh-cn\": \"\u5728\u5C97\uFF08\u5DE5\u4F5C\u65F6\u95F4\u8BA1\u65F6\u4E2D\uFF09\",\n\t},\n\t/** True while the last punch of the day has no counterpart */\n\thasOpenEntry: {\n\t\ten: \"Punched in\",\n\t\tde: \"Eingestempelt\",\n\t\tru: \"\u041F\u0440\u0438\u0445\u043E\u0434 \u043E\u0442\u043C\u0435\u0447\u0435\u043D\",\n\t\tpt: \"Entrada registada\",\n\t\tnl: \"Ingeklokt\",\n\t\tfr: \"Pointage d'arriv\u00E9e\",\n\t\tit: \"Entrata registrata\",\n\t\tes: \"Entrada registrada\",\n\t\tpl: \"Zarejestrowane wej\u015Bcie\",\n\t\tuk: \"\u0412\u0456\u0434\u043C\u0456\u0447\u0435\u043D\u043E \u043F\u0440\u0438\u0445\u0456\u0434\",\n\t\t\"zh-cn\": \"\u5DF2\u7B7E\u5230\",\n\t},\n\t/** Instant of the last punch */\n\tlastPunch: {\n\t\ten: \"Last punch\",\n\t\tde: \"Letzte Buchung\",\n\t\tru: \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u043E\u0442\u043C\u0435\u0442\u043A\u0430\",\n\t\tpt: \"\u00DAltimo registo\",\n\t\tnl: \"Laatste stempeling\",\n\t\tfr: \"Dernier pointage\",\n\t\tit: \"Ultima timbratura\",\n\t\tes: \"\u00DAltimo registro\",\n\t\tpl: \"Ostatni wpis\",\n\t\tuk: \"\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0432\u0456\u0434\u043C\u0456\u0442\u043A\u0430\",\n\t\t\"zh-cn\": \"\u6700\u540E\u6253\u5361\",\n\t},\n\t/** Net working time of today */\n\ttodayWorkedMinutes: {\n\t\ten: \"Worked today\",\n\t\tde: \"Heute gearbeitet\",\n\t\tru: \"\u041E\u0442\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u043E \u0441\u0435\u0433\u043E\u0434\u043D\u044F\",\n\t\tpt: \"Trabalhado hoje\",\n\t\tnl: \"Vandaag gewerkt\",\n\t\tfr: \"Travaill\u00E9 aujourd'hui\",\n\t\tit: \"Lavorato oggi\",\n\t\tes: \"Trabajado hoy\",\n\t\tpl: \"Przepracowane dzi\u015B\",\n\t\tuk: \"\u0412\u0456\u0434\u043F\u0440\u0430\u0446\u044C\u043E\u0432\u0430\u043D\u043E \u0441\u044C\u043E\u0433\u043E\u0434\u043D\u0456\",\n\t\t\"zh-cn\": \"\u4ECA\u65E5\u5DF2\u5DE5\u4F5C\",\n\t},\n\t/** Balance of today */\n\ttodayBalanceMinutes: {\n\t\ten: \"Balance today\",\n\t\tde: \"Saldo heute\",\n\t\tru: \"\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0441\u0435\u0433\u043E\u0434\u043D\u044F\",\n\t\tpt: \"Saldo de hoje\",\n\t\tnl: \"Saldo vandaag\",\n\t\tfr: \"Solde du jour\",\n\t\tit: \"Saldo di oggi\",\n\t\tes: \"Saldo de hoy\",\n\t\tpl: \"Saldo dzisiaj\",\n\t\tuk: \"\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0441\u044C\u043E\u0433\u043E\u0434\u043D\u0456\",\n\t\t\"zh-cn\": \"\u4ECA\u65E5\u4F59\u989D\",\n\t},\n\t/** Net working time of the current month */\n\tmonthWorkedMinutes: {\n\t\ten: \"Worked this month\",\n\t\tde: \"Diesen Monat gearbeitet\",\n\t\tru: \"\u041E\u0442\u0440\u0430\u0431\u043E\u0442\u0430\u043D\u043E \u0437\u0430 \u043C\u0435\u0441\u044F\u0446\",\n\t\tpt: \"Trabalhado este m\u00EAs\",\n\t\tnl: \"Deze maand gewerkt\",\n\t\tfr: \"Travaill\u00E9 ce mois\",\n\t\tit: \"Lavorato questo mese\",\n\t\tes: \"Trabajado este mes\",\n\t\tpl: \"Przepracowane w tym miesi\u0105cu\",\n\t\tuk: \"\u0412\u0456\u0434\u043F\u0440\u0430\u0446\u044C\u043E\u0432\u0430\u043D\u043E \u0446\u044C\u043E\u0433\u043E \u043C\u0456\u0441\u044F\u0446\u044F\",\n\t\t\"zh-cn\": \"\u672C\u6708\u5DF2\u5DE5\u4F5C\",\n\t},\n\t/** Balance of the current month */\n\tmonthBalanceMinutes: {\n\t\ten: \"Balance this month\",\n\t\tde: \"Saldo diesen Monat\",\n\t\tru: \"\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u043C\u0435\u0441\u044F\u0446\",\n\t\tpt: \"Saldo deste m\u00EAs\",\n\t\tnl: \"Saldo deze maand\",\n\t\tfr: \"Solde du mois\",\n\t\tit: \"Saldo di questo mese\",\n\t\tes: \"Saldo de este mes\",\n\t\tpl: \"Saldo w tym miesi\u0105cu\",\n\t\tuk: \"\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0446\u0435\u0439 \u043C\u0456\u0441\u044F\u0446\u044C\",\n\t\t\"zh-cn\": \"\u672C\u6708\u4F59\u989D\",\n\t},\n\t/** Balance of the current year */\n\tyearBalanceMinutes: {\n\t\ten: \"Balance this year\",\n\t\tde: \"Saldo dieses Jahr\",\n\t\tru: \"\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0433\u043E\u0434\",\n\t\tpt: \"Saldo deste ano\",\n\t\tnl: \"Saldo dit jaar\",\n\t\tfr: \"Solde de l'ann\u00E9e\",\n\t\tit: \"Saldo di quest'anno\",\n\t\tes: \"Saldo de este a\u00F1o\",\n\t\tpl: \"Saldo w tym roku\",\n\t\tuk: \"\u0411\u0430\u043B\u0430\u043D\u0441 \u0437\u0430 \u0446\u0435\u0439 \u0440\u0456\u043A\",\n\t\t\"zh-cn\": \"\u672C\u5E74\u4F59\u989D\",\n\t},\n\t/** Punches waiting for a decision */\n\topenConflicts: {\n\t\ten: \"Open conflicts\",\n\t\tde: \"Offene Konflikte\",\n\t\tru: \"\u041E\u0442\u043A\u0440\u044B\u0442\u044B\u0435 \u043A\u043E\u043D\u0444\u043B\u0438\u043A\u0442\u044B\",\n\t\tpt: \"Conflitos em aberto\",\n\t\tnl: \"Openstaande conflicten\",\n\t\tfr: \"Conflits en attente\",\n\t\tit: \"Conflitti aperti\",\n\t\tes: \"Conflictos abiertos\",\n\t\tpl: \"Otwarte konflikty\",\n\t\tuk: \"\u0412\u0456\u0434\u043A\u0440\u0438\u0442\u0456 \u043A\u043E\u043D\u0444\u043B\u0456\u043A\u0442\u0438\",\n\t\t\"zh-cn\": \"\u672A\u89E3\u51B3\u7684\u51B2\u7A81\",\n\t},\n\t/** Employee the punch commands apply to */\n\tpunchUserId: {\n\t\ten: \"Employee id for punch commands\",\n\t\tde: \"Mitarbeiter-Id f\u00FCr Stempelbefehle\",\n\t\tru: \"\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0441\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u0430 \u0434\u043B\u044F \u043A\u043E\u043C\u0430\u043D\u0434\",\n\t\tpt: \"ID do funcion\u00E1rio para comandos\",\n\t\tnl: \"Medewerker-id voor opdrachten\",\n\t\tfr: \"Identifiant de l'employ\u00E9 pour les commandes\",\n\t\tit: \"ID del dipendente per i comandi\",\n\t\tes: \"ID del empleado para comandos\",\n\t\tpl: \"Identyfikator pracownika dla polece\u0144\",\n\t\tuk: \"\u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0441\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A\u0430 \u0434\u043B\u044F \u043A\u043E\u043C\u0430\u043D\u0434\",\n\t\t\"zh-cn\": \"\u6253\u5361\u547D\u4EE4\u7684\u5458\u5DE5 ID\",\n\t},\n\t/** Button: punch in or out */\n\tpunch: {\n\t\ten: \"Punch in or out\",\n\t\tde: \"Ein- oder ausstempeln\",\n\t\tru: \"\u041E\u0442\u043C\u0435\u0442\u0438\u0442\u044C\u0441\u044F (\u043F\u0440\u0438\u0445\u043E\u0434 \u0438\u043B\u0438 \u0443\u0445\u043E\u0434)\",\n\t\tpt: \"Marcar entrada ou sa\u00EDda\",\n\t\tnl: \"In- of uitklokken\",\n\t\tfr: \"Pointer l'arriv\u00E9e ou le d\u00E9part\",\n\t\tit: \"Timbrare entrata o uscita\",\n\t\tes: \"Fichar entrada o salida\",\n\t\tpl: \"Zarejestruj wej\u015Bcie lub wyj\u015Bcie\",\n\t\tuk: \"\u0412\u0456\u0434\u043C\u0456\u0442\u0438\u0442\u0438 \u043F\u0440\u0438\u0445\u0456\u0434 \u0430\u0431\u043E \u0432\u0438\u0445\u0456\u0434\",\n\t\t\"zh-cn\": \"\u4E0A\u73ED\u6216\u4E0B\u73ED\u6253\u5361\",\n\t},\n\t/** Button: punch and round the time */\n\tquickPunch: {\n\t\ten: \"Punch with quick rounding\",\n\t\tde: \"Stempeln mit Schnellrundung\",\n\t\tru: \"\u041E\u0442\u043C\u0435\u0442\u0438\u0442\u044C\u0441\u044F \u0441 \u0431\u044B\u0441\u0442\u0440\u044B\u043C \u043E\u043A\u0440\u0443\u0433\u043B\u0435\u043D\u0438\u0435\u043C\",\n\t\tpt: \"Marcar com arredondamento r\u00E1pido\",\n\t\tnl: \"Klokken met snelle afronding\",\n\t\tfr: \"Pointer avec arrondi rapide\",\n\t\tit: \"Timbrare con arrotondamento rapido\",\n\t\tes: \"Fichar con redondeo r\u00E1pido\",\n\t\tpl: \"Zarejestruj z szybkim zaokr\u0105gleniem\",\n\t\tuk: \"\u0412\u0456\u0434\u043C\u0456\u0442\u0438\u0442\u0438 \u0437\u0456 \u0448\u0432\u0438\u0434\u043A\u0438\u043C \u043E\u043A\u0440\u0443\u0433\u043B\u0435\u043D\u043D\u044F\u043C\",\n\t\t\"zh-cn\": \"\u5FEB\u901F\u53D6\u6574\u6253\u5361\",\n\t},\n\t/** Month to close */\n\tcloseMonth: {\n\t\ten: \"Close month (YYYY-MM)\",\n\t\tde: \"Monat abschlie\u00DFen (JJJJ-MM)\",\n\t\tru: \"\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u0441\u044F\u0446 (\u0413\u0413\u0413\u0413-\u041C\u041C)\",\n\t\tpt: \"Fechar m\u00EAs (AAAA-MM)\",\n\t\tnl: \"Maand afsluiten (JJJJ-MM)\",\n\t\tfr: \"Cl\u00F4turer le mois (AAAA-MM)\",\n\t\tit: \"Chiudere il mese (AAAA-MM)\",\n\t\tes: \"Cerrar mes (AAAA-MM)\",\n\t\tpl: \"Zamknij miesi\u0105c (RRRR-MM)\",\n\t\tuk: \"\u0417\u0430\u043A\u0440\u0438\u0442\u0438 \u043C\u0456\u0441\u044F\u0446\u044C (\u0420\u0420\u0420\u0420-\u041C\u041C)\",\n\t\t\"zh-cn\": \"\u5173\u95ED\u6708\u4EFD\uFF08YYYY-MM\uFF09\",\n\t},\n\t/** Period to recalculate */\n\trecalc: {\n\t\ten: \"Recalculate period (YYYY-MM or YYYY)\",\n\t\tde: \"Zeitraum neu berechnen (JJJJ-MM oder JJJJ)\",\n\t\tru: \"\u041F\u0435\u0440\u0435\u0441\u0447\u0438\u0442\u0430\u0442\u044C \u043F\u0435\u0440\u0438\u043E\u0434 (\u0413\u0413\u0413\u0413-\u041C\u041C \u0438\u043B\u0438 \u0413\u0413\u0413\u0413)\",\n\t\tpt: \"Recalcular per\u00EDodo (AAAA-MM ou AAAA)\",\n\t\tnl: \"Periode opnieuw berekenen (JJJJ-MM of JJJJ)\",\n\t\tfr: \"Recalculer la p\u00E9riode (AAAA-MM ou AAAA)\",\n\t\tit: \"Ricalcolare il periodo (AAAA-MM o AAAA)\",\n\t\tes: \"Recalcular periodo (AAAA-MM o AAAA)\",\n\t\tpl: \"Przelicz okres (RRRR-MM lub RRRR)\",\n\t\tuk: \"\u041F\u0435\u0440\u0435\u0440\u0430\u0445\u0443\u0432\u0430\u0442\u0438 \u043F\u0435\u0440\u0456\u043E\u0434 (\u0420\u0420\u0420\u0420-\u041C\u041C \u0430\u0431\u043E \u0420\u0420\u0420\u0420)\",\n\t\t\"zh-cn\": \"\u91CD\u65B0\u8BA1\u7B97\u671F\u95F4\uFF08YYYY-MM \u6216 YYYY\uFF09\",\n\t},\n\t/** Button: write a database backup */\n\tbackupCommand: {\n\t\ten: \"Write a database backup\",\n\t\tde: \"Datenbank-Sicherung schreiben\",\n\t\tru: \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u0443\u044E \u043A\u043E\u043F\u0438\u044E \u0431\u0430\u0437\u044B\",\n\t\tpt: \"Criar c\u00F3pia de seguran\u00E7a da base de dados\",\n\t\tnl: \"Databasback-up maken\",\n\t\tfr: \"Cr\u00E9er une sauvegarde de la base\",\n\t\tit: \"Creare un backup del database\",\n\t\tes: \"Crear copia de seguridad de la base\",\n\t\tpl: \"Utw\u00F3rz kopi\u0119 zapasow\u0105 bazy\",\n\t\tuk: \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u0443 \u043A\u043E\u043F\u0456\u044E \u0431\u0430\u0437\u0438\",\n\t\t\"zh-cn\": \"\u5199\u5165\u6570\u636E\u5E93\u5907\u4EFD\",\n\t},\n\t/** Version of the adapter */\n\tversion: {\n\t\ten: \"Adapter version\",\n\t\tde: \"Adapter-Version\",\n\t\tru: \"\u0412\u0435\u0440\u0441\u0438\u044F \u0430\u0434\u0430\u043F\u0442\u0435\u0440\u0430\",\n\t\tpt: \"Vers\u00E3o do adaptador\",\n\t\tnl: \"Adapterversie\",\n\t\tfr: \"Version de l'adaptateur\",\n\t\tit: \"Versione dell'adattatore\",\n\t\tes: \"Versi\u00F3n del adaptador\",\n\t\tpl: \"Wersja adaptera\",\n\t\tuk: \"\u0412\u0435\u0440\u0441\u0456\u044F \u0430\u0434\u0430\u043F\u0442\u0435\u0440\u0430\",\n\t\t\"zh-cn\": \"\u9002\u914D\u5668\u7248\u672C\",\n\t},\n\t/** Version of the database schema */\n\tschemaVersion: {\n\t\ten: \"Database schema version\",\n\t\tde: \"Datenbank-Schemaversion\",\n\t\tru: \"\u0412\u0435\u0440\u0441\u0438\u044F \u0441\u0445\u0435\u043C\u044B \u0431\u0430\u0437\u044B \u0434\u0430\u043D\u043D\u044B\u0445\",\n\t\tpt: \"Vers\u00E3o do esquema da base de dados\",\n\t\tnl: \"Schemaversie van de database\",\n\t\tfr: \"Version du sch\u00E9ma de la base\",\n\t\tit: \"Versione dello schema del database\",\n\t\tes: \"Versi\u00F3n del esquema de la base\",\n\t\tpl: \"Wersja schematu bazy\",\n\t\tuk: \"\u0412\u0435\u0440\u0441\u0456\u044F \u0441\u0445\u0435\u043C\u0438 \u0431\u0430\u0437\u0438 \u0434\u0430\u043D\u0438\u0445\",\n\t\t\"zh-cn\": \"\u6570\u636E\u5E93\u67B6\u6784\u7248\u672C\",\n\t},\n\t/** Size of the database file */\n\tdbSizeBytes: {\n\t\ten: \"Database size\",\n\t\tde: \"Datenbank-Gr\u00F6\u00DFe\",\n\t\tru: \"\u0420\u0430\u0437\u043C\u0435\u0440 \u0431\u0430\u0437\u044B \u0434\u0430\u043D\u043D\u044B\u0445\",\n\t\tpt: \"Tamanho da base de dados\",\n\t\tnl: \"Grootte van de database\",\n\t\tfr: \"Taille de la base\",\n\t\tit: \"Dimensione del database\",\n\t\tes: \"Tama\u00F1o de la base\",\n\t\tpl: \"Rozmiar bazy\",\n\t\tuk: \"\u0420\u043E\u0437\u043C\u0456\u0440 \u0431\u0430\u0437\u0438 \u0434\u0430\u043D\u0438\u0445\",\n\t\t\"zh-cn\": \"\u6570\u636E\u5E93\u5927\u5C0F\",\n\t},\n\t/** Last error of the instance */\n\tlastError: {\n\t\ten: \"Last error\",\n\t\tde: \"Letzter Fehler\",\n\t\tru: \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u043E\u0448\u0438\u0431\u043A\u0430\",\n\t\tpt: \"\u00DAltimo erro\",\n\t\tnl: \"Laatste fout\",\n\t\tfr: \"Derni\u00E8re erreur\",\n\t\tit: \"Ultimo errore\",\n\t\tes: \"\u00DAltimo error\",\n\t\tpl: \"Ostatni b\u0142\u0105d\",\n\t\tuk: \"\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u043F\u043E\u043C\u0438\u043B\u043A\u0430\",\n\t\t\"zh-cn\": \"\u6700\u540E\u7684\u9519\u8BEF\",\n\t},\n\t/** Instant of the last backup */\n\tlastBackup: {\n\t\ten: \"Last backup\",\n\t\tde: \"Letzte Sicherung\",\n\t\tru: \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u0430\u044F \u043A\u043E\u043F\u0438\u044F\",\n\t\tpt: \"\u00DAltima c\u00F3pia de seguran\u00E7a\",\n\t\tnl: \"Laatste back-up\",\n\t\tfr: \"Derni\u00E8re sauvegarde\",\n\t\tit: \"Ultimo backup\",\n\t\tes: \"\u00DAltima copia de seguridad\",\n\t\tpl: \"Ostatnia kopia zapasowa\",\n\t\tuk: \"\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0440\u0435\u0437\u0435\u0440\u0432\u043D\u0430 \u043A\u043E\u043F\u0456\u044F\",\n\t\t\"zh-cn\": \"\u6700\u540E\u7684\u5907\u4EFD\",\n\t},\n\t/** Number of employees that are present */\n\tcompanyPresentCount: {\n\t\ten: \"Present employees\",\n\t\tde: \"Anwesende Mitarbeiter\",\n\t\tru: \"\u041F\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0435 \u0441\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A\u0438\",\n\t\tpt: \"Funcion\u00E1rios presentes\",\n\t\tnl: \"Aanwezige medewerkers\",\n\t\tfr: \"Employ\u00E9s pr\u00E9sents\",\n\t\tit: \"Dipendenti presenti\",\n\t\tes: \"Empleados presentes\",\n\t\tpl: \"Obecni pracownicy\",\n\t\tuk: \"\u041F\u0440\u0438\u0441\u0443\u0442\u043D\u0456 \u0441\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A\u0438\",\n\t\t\"zh-cn\": \"\u5728\u5C97\u5458\u5DE5\",\n\t},\n\t/** Names of the employees that are present */\n\tcompanyPresent: {\n\t\ten: \"Who is present\",\n\t\tde: \"Wer ist anwesend\",\n\t\tru: \"\u041A\u0442\u043E \u043F\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442\",\n\t\tpt: \"Quem est\u00E1 presente\",\n\t\tnl: \"Wie is aanwezig\",\n\t\tfr: \"Qui est pr\u00E9sent\",\n\t\tit: \"Chi \u00E8 presente\",\n\t\tes: \"Qui\u00E9n est\u00E1 presente\",\n\t\tpl: \"Kto jest obecny\",\n\t\tuk: \"\u0425\u0442\u043E \u043F\u0440\u0438\u0441\u0443\u0442\u043D\u0456\u0439\",\n\t\t\"zh-cn\": \"\u8C01\u5728\u5C97\",\n\t},\n\t/** Instant of the newest punch of the company */\n\tcompanyLastPunch: {\n\t\ten: \"Last punch\",\n\t\tde: \"Letzte Buchung\",\n\t\tru: \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u044F\u044F \u043E\u0442\u043C\u0435\u0442\u043A\u0430\",\n\t\tpt: \"\u00DAltimo registo\",\n\t\tnl: \"Laatste stempeling\",\n\t\tfr: \"Dernier pointage\",\n\t\tit: \"Ultima timbratura\",\n\t\tes: \"\u00DAltimo registro\",\n\t\tpl: \"Ostatni wpis\",\n\t\tuk: \"\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0432\u0456\u0434\u043C\u0456\u0442\u043A\u0430\",\n\t\t\"zh-cn\": \"\u6700\u540E\u6253\u5361\",\n\t},\n\t/** Instant of the newest event */\n\tlastAt: {\n\t\ten: \"Last event at\",\n\t\tde: \"Letztes Ereignis um\",\n\t\tru: \"\u0412\u0440\u0435\u043C\u044F \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F\",\n\t\tpt: \"Hora do \u00FAltimo evento\",\n\t\tnl: \"Tijdstip laatste gebeurtenis\",\n\t\tfr: \"Heure du dernier \u00E9v\u00E9nement\",\n\t\tit: \"Ora dell'ultimo evento\",\n\t\tes: \"Hora del \u00FAltimo evento\",\n\t\tpl: \"Czas ostatniego zdarzenia\",\n\t\tuk: \"\u0427\u0430\u0441 \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u043F\u043E\u0434\u0456\u0457\",\n\t\t\"zh-cn\": \"\u6700\u540E\u4E8B\u4EF6\u65F6\u95F4\",\n\t},\n\t/** Kind of the newest event */\n\tlastType: {\n\t\ten: \"Kind of the last event\",\n\t\tde: \"Art des letzten Ereignisses\",\n\t\tru: \"\u0422\u0438\u043F \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F\",\n\t\tpt: \"Tipo do \u00FAltimo evento\",\n\t\tnl: \"Soort laatste gebeurtenis\",\n\t\tfr: \"Type du dernier \u00E9v\u00E9nement\",\n\t\tit: \"Tipo dell'ultimo evento\",\n\t\tes: \"Tipo del \u00FAltimo evento\",\n\t\tpl: \"Rodzaj ostatniego zdarzenia\",\n\t\tuk: \"\u0422\u0438\u043F \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u043F\u043E\u0434\u0456\u0457\",\n\t\t\"zh-cn\": \"\u6700\u540E\u4E8B\u4EF6\u7C7B\u578B\",\n\t},\n\t/** Employee of the newest event */\n\tlastUser: {\n\t\ten: \"Employee of the last event\",\n\t\tde: \"Mitarbeiter des letzten Ereignisses\",\n\t\tru: \"\u0421\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F\",\n\t\tpt: \"Funcion\u00E1rio do \u00FAltimo evento\",\n\t\tnl: \"Medewerker van de laatste gebeurtenis\",\n\t\tfr: \"Employ\u00E9 du dernier \u00E9v\u00E9nement\",\n\t\tit: \"Dipendente dell'ultimo evento\",\n\t\tes: \"Empleado del \u00FAltimo evento\",\n\t\tpl: \"Pracownik ostatniego zdarzenia\",\n\t\tuk: \"\u0421\u043F\u0456\u0432\u0440\u043E\u0431\u0456\u0442\u043D\u0438\u043A \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u043F\u043E\u0434\u0456\u0457\",\n\t\t\"zh-cn\": \"\u6700\u540E\u4E8B\u4EF6\u7684\u5458\u5DE5\",\n\t},\n\t/** Direction of the newest punch */\n\tlastDirection: {\n\t\ten: \"Direction of the last punch\",\n\t\tde: \"Richtung der letzten Buchung\",\n\t\tru: \"\u041D\u0430\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0439 \u043E\u0442\u043C\u0435\u0442\u043A\u0438\",\n\t\tpt: \"Dire\u00E7\u00E3o do \u00FAltimo registo\",\n\t\tnl: \"Richting van de laatste stempeling\",\n\t\tfr: \"Sens du dernier pointage\",\n\t\tit: \"Direzione dell'ultima timbratura\",\n\t\tes: \"Direcci\u00F3n del \u00FAltimo registro\",\n\t\tpl: \"Kierunek ostatniego wpisu\",\n\t\tuk: \"\u041D\u0430\u043F\u0440\u044F\u043C\u043E\u043A \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u0432\u0456\u0434\u043C\u0456\u0442\u043A\u0438\",\n\t\t\"zh-cn\": \"\u6700\u540E\u6253\u5361\u7684\u65B9\u5411\",\n\t},\n\t/** Source of the newest event */\n\tlastSource: {\n\t\ten: \"Source of the last event\",\n\t\tde: \"Quelle des letzten Ereignisses\",\n\t\tru: \"\u0418\u0441\u0442\u043E\u0447\u043D\u0438\u043A \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F\",\n\t\tpt: \"Origem do \u00FAltimo evento\",\n\t\tnl: \"Bron van de laatste gebeurtenis\",\n\t\tfr: \"Source du dernier \u00E9v\u00E9nement\",\n\t\tit: \"Origine dell'ultimo evento\",\n\t\tes: \"Origen del \u00FAltimo evento\",\n\t\tpl: \"\u0179r\u00F3d\u0142o ostatniego zdarzenia\",\n\t\tuk: \"\u0414\u0436\u0435\u0440\u0435\u043B\u043E \u043E\u0441\u0442\u0430\u043D\u043D\u044C\u043E\u0457 \u043F\u043E\u0434\u0456\u0457\",\n\t\t\"zh-cn\": \"\u6700\u540E\u4E8B\u4EF6\u7684\u6765\u6E90\",\n\t},\n} satisfies Record<string, StateName>;\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -32,6 +32,7 @@ __export(states_exports, {
32
32
  readUserSnapshot: () => readUserSnapshot
33
33
  });
34
34
  module.exports = __toCommonJS(states_exports);
35
+ var import_stateNames = require("./stateNames");
35
36
  var import_time = require("../util/time");
36
37
  const COMMAND_IDS = {
37
38
  /** Employee the commands apply to */
@@ -64,6 +65,13 @@ function stateObject(name, type, role, options = {}) {
64
65
  function channelObject(name) {
65
66
  return { type: "channel", common: { name }, native: {} };
66
67
  }
68
+ async function ensureObject(port, id, object) {
69
+ var _a;
70
+ await port.setObjectNotExists(id, object);
71
+ const common = { ...(_a = object.common) != null ? _a : {} };
72
+ delete common.custom;
73
+ await port.extendObject(id, { common });
74
+ }
67
75
  function readUserSnapshot(args) {
68
76
  var _a, _b, _c;
69
77
  const user = args.users.findById(args.userId);
@@ -125,143 +133,108 @@ async function publishAllUserStates(args) {
125
133
  }
126
134
  async function createUserChannel(port, userId) {
127
135
  const id = `users.${userId}`;
128
- await port.setObjectNotExists("users", channelObject({ en: "Employees", de: "Mitarbeiter" }));
129
- await port.setObjectNotExists(id, channelObject({ en: "Employee", de: "Mitarbeiter" }));
130
- await port.setObjectNotExists(`${id}.displayName`, stateObject({ en: "Name", de: "Name" }, "string", "info.name"));
131
- await port.setObjectNotExists(
136
+ await ensureObject(port, "users", channelObject(import_stateNames.STATE_NAMES.usersChannel));
137
+ await ensureObject(port, id, channelObject(import_stateNames.STATE_NAMES.employeeChannel));
138
+ await ensureObject(port, `${id}.displayName`, stateObject(import_stateNames.STATE_NAMES.displayName, "string", "info.name"));
139
+ await ensureObject(
140
+ port,
132
141
  `${id}.present`,
133
- stateObject(
134
- { en: "Present (working time is running)", de: "Anwesenheit (Arbeitszeit l\xE4uft)" },
135
- "boolean",
136
- "switch",
137
- { write: true }
138
- )
142
+ stateObject(import_stateNames.STATE_NAMES.userPresent, "boolean", "switch", { write: true })
139
143
  );
140
- await port.setObjectNotExists(
144
+ await ensureObject(
145
+ port,
141
146
  `${id}.hasOpenEntry`,
142
- stateObject({ en: "Punched in", de: "Eingestempelt" }, "boolean", "indicator.working")
147
+ stateObject(import_stateNames.STATE_NAMES.hasOpenEntry, "boolean", "indicator.working")
143
148
  );
144
- await port.setObjectNotExists(
145
- `${id}.lastPunch`,
146
- stateObject({ en: "Last punch", de: "Letzte Buchung" }, "number", "value.time")
147
- );
148
- await port.setObjectNotExists(
149
+ await ensureObject(port, `${id}.lastPunch`, stateObject(import_stateNames.STATE_NAMES.lastPunch, "number", "value.time"));
150
+ await ensureObject(
151
+ port,
149
152
  `${id}.todayWorkedMinutes`,
150
- stateObject({ en: "Worked today", de: "Heute gearbeitet" }, "number", "value", { unit: "min" })
153
+ stateObject(import_stateNames.STATE_NAMES.todayWorkedMinutes, "number", "value", { unit: "min" })
151
154
  );
152
- await port.setObjectNotExists(
155
+ await ensureObject(
156
+ port,
153
157
  `${id}.todayBalanceMinutes`,
154
- stateObject({ en: "Balance today", de: "Saldo heute" }, "number", "value", { unit: "min" })
158
+ stateObject(import_stateNames.STATE_NAMES.todayBalanceMinutes, "number", "value", { unit: "min" })
155
159
  );
156
- await port.setObjectNotExists(
160
+ await ensureObject(
161
+ port,
157
162
  `${id}.monthWorkedMinutes`,
158
- stateObject({ en: "Worked this month", de: "Diesen Monat gearbeitet" }, "number", "value", { unit: "min" })
163
+ stateObject(import_stateNames.STATE_NAMES.monthWorkedMinutes, "number", "value", { unit: "min" })
159
164
  );
160
- await port.setObjectNotExists(
165
+ await ensureObject(
166
+ port,
161
167
  `${id}.monthBalanceMinutes`,
162
- stateObject({ en: "Balance this month", de: "Saldo diesen Monat" }, "number", "value", { unit: "min" })
168
+ stateObject(import_stateNames.STATE_NAMES.monthBalanceMinutes, "number", "value", { unit: "min" })
163
169
  );
164
- await port.setObjectNotExists(
170
+ await ensureObject(
171
+ port,
165
172
  `${id}.yearBalanceMinutes`,
166
- stateObject({ en: "Balance this year", de: "Saldo dieses Jahr" }, "number", "value", { unit: "min" })
167
- );
168
- await port.setObjectNotExists(
169
- `${id}.openConflicts`,
170
- stateObject({ en: "Open conflicts", de: "Offene Konflikte" }, "number", "value")
173
+ stateObject(import_stateNames.STATE_NAMES.yearBalanceMinutes, "number", "value", { unit: "min" })
171
174
  );
175
+ await ensureObject(port, `${id}.openConflicts`, stateObject(import_stateNames.STATE_NAMES.openConflicts, "number", "value"));
172
176
  return id;
173
177
  }
174
178
  async function createCommandStates(port) {
175
- await port.setObjectNotExists("commands", channelObject({ en: "Commands", de: "Befehle" }));
176
- await port.setObjectNotExists(
179
+ await ensureObject(port, "commands", channelObject(import_stateNames.STATE_NAMES.commandsChannel));
180
+ await ensureObject(
181
+ port,
177
182
  COMMAND_IDS.punchUserId,
178
- stateObject(
179
- { en: "Employee id for punch commands", de: "Mitarbeiter-Id f\xFCr Stempelbefehle" },
180
- "number",
181
- "value",
182
- {
183
- write: true
184
- }
185
- )
183
+ stateObject(import_stateNames.STATE_NAMES.punchUserId, "number", "level", {
184
+ write: true
185
+ })
186
186
  );
187
- await port.setObjectNotExists(
187
+ await ensureObject(
188
+ port,
188
189
  COMMAND_IDS.punch,
189
- stateObject({ en: "Punch in or out", de: "Ein- oder ausstempeln" }, "boolean", "button", {
190
+ stateObject(import_stateNames.STATE_NAMES.punch, "boolean", "button", {
190
191
  read: false,
191
192
  write: true
192
193
  })
193
194
  );
194
- await port.setObjectNotExists(
195
+ await ensureObject(
196
+ port,
195
197
  COMMAND_IDS.quickPunch,
196
- stateObject({ en: "Punch with quick rounding", de: "Stempeln mit Schnellrundung" }, "boolean", "button", {
198
+ stateObject(import_stateNames.STATE_NAMES.quickPunch, "boolean", "button", {
197
199
  read: false,
198
200
  write: true
199
201
  })
200
202
  );
201
- await port.setObjectNotExists(
203
+ await ensureObject(
204
+ port,
202
205
  COMMAND_IDS.closeMonth,
203
- stateObject({ en: "Close month (YYYY-MM)", de: "Monat abschlie\xDFen (JJJJ-MM)" }, "string", "text", {
206
+ stateObject(import_stateNames.STATE_NAMES.closeMonth, "string", "text", {
204
207
  write: true
205
208
  })
206
209
  );
207
- await port.setObjectNotExists(
208
- COMMAND_IDS.recalc,
209
- stateObject(
210
- { en: "Recalculate period (YYYY-MM or YYYY)", de: "Zeitraum neu berechnen (JJJJ-MM oder JJJJ)" },
211
- "string",
212
- "text",
213
- { write: true }
214
- )
215
- );
216
- await port.setObjectNotExists(
210
+ await ensureObject(port, COMMAND_IDS.recalc, stateObject(import_stateNames.STATE_NAMES.recalc, "string", "text", { write: true }));
211
+ await ensureObject(
212
+ port,
217
213
  COMMAND_IDS.backup,
218
- stateObject({ en: "Write a database backup", de: "Datenbank-Sicherung schreiben" }, "boolean", "button", {
214
+ stateObject(import_stateNames.STATE_NAMES.backupCommand, "boolean", "button", {
219
215
  read: false,
220
216
  write: true
221
217
  })
222
218
  );
223
219
  }
224
220
  async function createInfoStates(port) {
225
- await port.setObjectNotExists("info", channelObject({ en: "Information", de: "Information" }));
226
- await port.setObjectNotExists(
227
- "info.version",
228
- stateObject({ en: "Adapter version", de: "Adapter-Version" }, "string", "text")
229
- );
230
- await port.setObjectNotExists(
231
- "info.schemaVersion",
232
- stateObject({ en: "Database schema version", de: "Datenbank-Schemaversion" }, "string", "text")
233
- );
234
- await port.setObjectNotExists(
221
+ await ensureObject(port, "info", channelObject(import_stateNames.STATE_NAMES.infoChannel));
222
+ await ensureObject(port, "info.version", stateObject(import_stateNames.STATE_NAMES.version, "string", "text"));
223
+ await ensureObject(port, "info.schemaVersion", stateObject(import_stateNames.STATE_NAMES.schemaVersion, "string", "text"));
224
+ await ensureObject(
225
+ port,
235
226
  "info.dbSizeBytes",
236
- stateObject({ en: "Database size", de: "Datenbank-Gr\xF6\xDFe" }, "number", "value", { unit: "bytes" })
237
- );
238
- await port.setObjectNotExists(
239
- "info.lastError",
240
- stateObject({ en: "Last error", de: "Letzter Fehler" }, "string", "text")
241
- );
242
- await port.setObjectNotExists(
243
- "info.lastBackup",
244
- stateObject({ en: "Last backup", de: "Letzte Sicherung" }, "number", "value.time")
227
+ stateObject(import_stateNames.STATE_NAMES.dbSizeBytes, "number", "value", { unit: "bytes" })
245
228
  );
229
+ await ensureObject(port, "info.lastError", stateObject(import_stateNames.STATE_NAMES.lastError, "string", "text"));
230
+ await ensureObject(port, "info.lastBackup", stateObject(import_stateNames.STATE_NAMES.lastBackup, "number", "value.time"));
246
231
  }
247
232
  async function createCompanyStates(port) {
248
- await port.setObjectNotExists("company", channelObject({ en: "Company", de: "Firma" }));
249
- await port.setObjectNotExists(
250
- "company.presentCount",
251
- stateObject({ en: "Present employees", de: "Anwesende Mitarbeiter" }, "number", "value")
252
- );
253
- await port.setObjectNotExists(
254
- "company.present",
255
- stateObject({ en: "Who is present", de: "Wer ist anwesend" }, "string", "text")
256
- );
257
- await port.setObjectNotExists(
258
- "company.openConflicts",
259
- stateObject({ en: "Open conflicts", de: "Offene Konflikte" }, "number", "value")
260
- );
261
- await port.setObjectNotExists(
262
- "company.lastPunch",
263
- stateObject({ en: "Last punch", de: "Letzte Buchung" }, "number", "value.time")
264
- );
233
+ await ensureObject(port, "company", channelObject(import_stateNames.STATE_NAMES.companyChannel));
234
+ await ensureObject(port, "company.presentCount", stateObject(import_stateNames.STATE_NAMES.companyPresentCount, "number", "value"));
235
+ await ensureObject(port, "company.present", stateObject(import_stateNames.STATE_NAMES.companyPresent, "string", "text"));
236
+ await ensureObject(port, "company.openConflicts", stateObject(import_stateNames.STATE_NAMES.openConflicts, "number", "value"));
237
+ await ensureObject(port, "company.lastPunch", stateObject(import_stateNames.STATE_NAMES.companyLastPunch, "number", "value.time"));
265
238
  }
266
239
  function readCompanySnapshot(snapshots) {
267
240
  const present = snapshots.filter((snapshot) => snapshot.hasOpenEntry);
@@ -283,27 +256,12 @@ async function publishCompanySnapshot(port, snapshot) {
283
256
  await port.setState("company.lastPunch", (_a = snapshot.lastPunchUtc) != null ? _a : 0, true);
284
257
  }
285
258
  async function createEventStates(port) {
286
- await port.setObjectNotExists("events", channelObject({ en: "Events", de: "Ereignisse" }));
287
- await port.setObjectNotExists(
288
- "events.lastAt",
289
- stateObject({ en: "Last event at", de: "Letztes Ereignis um" }, "number", "value.time")
290
- );
291
- await port.setObjectNotExists(
292
- "events.lastType",
293
- stateObject({ en: "Kind of the last event", de: "Art des letzten Ereignisses" }, "string", "text")
294
- );
295
- await port.setObjectNotExists(
296
- "events.lastUser",
297
- stateObject({ en: "Employee of the last event", de: "Mitarbeiter des letzten Ereignisses" }, "string", "text")
298
- );
299
- await port.setObjectNotExists(
300
- "events.lastDirection",
301
- stateObject({ en: "Direction of the last punch", de: "Richtung der letzten Buchung" }, "string", "text")
302
- );
303
- await port.setObjectNotExists(
304
- "events.lastSource",
305
- stateObject({ en: "Source of the last event", de: "Quelle des letzten Ereignisses" }, "string", "text")
306
- );
259
+ await ensureObject(port, "events", channelObject(import_stateNames.STATE_NAMES.eventsChannel));
260
+ await ensureObject(port, "events.lastAt", stateObject(import_stateNames.STATE_NAMES.lastAt, "number", "value.time"));
261
+ await ensureObject(port, "events.lastType", stateObject(import_stateNames.STATE_NAMES.lastType, "string", "text"));
262
+ await ensureObject(port, "events.lastUser", stateObject(import_stateNames.STATE_NAMES.lastUser, "string", "text"));
263
+ await ensureObject(port, "events.lastDirection", stateObject(import_stateNames.STATE_NAMES.lastDirection, "string", "text"));
264
+ await ensureObject(port, "events.lastSource", stateObject(import_stateNames.STATE_NAMES.lastSource, "string", "text"));
307
265
  }
308
266
  async function publishEventSnapshot(port, snapshot) {
309
267
  await port.setState("events.lastAt", snapshot.atUtc, true);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/adapter/states.ts"],
4
- "sourcesContent": ["/**\n * States published by the adapter.\n *\n * The adapter exposes a small, stable state tree so that other adapters (and the user's dashboards) can show\n * and trigger time tracking without speaking to the REST API:\n *\n * ```\n * users.<userId>.displayName / present / hasOpenEntry / lastPunch / todayWorkedMinutes / todayBalanceMinutes\n * users.<userId>.openConflicts\n * commands.punchUserId / punch / quickPunch / closeMonth / recalc\n * ```\n *\n * All objects are created with `setObjectNotExists`, so existing instances keep their settings. The logic works\n * on a tiny port interface (`StatePort`) \u2014 the adapter instance in production, a recorder in the tests.\n */\n\nimport type { UsersRepository } from \"../db/repositories/users\";\nimport type { AggregationService } from \"../services/aggregation\";\nimport type { SyncService } from \"../services/sync\";\nimport { localDate as resolveLocalDate } from \"../util/time\";\n\n/** Subset of the adapter API the state layer needs. */\nexport interface StatePort {\n\t/**\n\t * Creates an object when it does not exist yet.\n\t *\n\t * @param id - full state id (including the instance prefix)\n\t * @param object - object definition\n\t */\n\tsetObjectNotExists(id: string, object: ioBroker.SettableObject): Promise<unknown> | void;\n\t/**\n\t * Writes a state value.\n\t *\n\t * @param id - full state id (including the instance prefix)\n\t * @param value - value to write\n\t * @param ack - true for confirmed values\n\t */\n\tsetState(id: string, value: ioBroker.StateValue, ack?: boolean): Promise<unknown> | void;\n}\n\n/** Figures of one employee shown in the state tree. */\nexport interface UserSnapshot {\n\t/** Database id of the employee */\n\tuserId: number;\n\t/** Shown name */\n\tdisplayName: string;\n\t/** True when the last punch of today has no counterpart */\n\thasOpenEntry: boolean;\n\t/** Instant of the last punch of the day, `null` when there is none */\n\tlastPunchUtc: number | null;\n\t/** Net working time of today in minutes */\n\tworkedMinutes: number;\n\t/** Balance of today in minutes */\n\tbalanceMinutes: number;\n\t/** Punches waiting for a decision */\n\topenConflicts: number;\n\t/** Net working time of the current month in minutes */\n\tmonthWorkedMinutes: number;\n\t/** Balance of the current month in minutes */\n\tmonthBalanceMinutes: number;\n\t/** Balance of the current year in minutes */\n\tyearBalanceMinutes: number;\n}\n\n/** Figures of the whole company, published next to the employees. */\nexport interface CompanySnapshot {\n\t/** Employees that are clocked in right now */\n\tpresentCount: number;\n\t/** Names of those employees, separated by a comma (empty when nobody is present) */\n\tpresent: string;\n\t/** Punches of all employees waiting for a decision */\n\topenConflicts: number;\n\t/** Instant of the newest punch of today, `null` when nobody punched */\n\tlastPunchUtc: number | null;\n}\n\n/** Newest event of the instance, mirrored into the state tree. */\nexport interface EventSnapshot {\n\t/** Kind of the event, e.g. `punch` */\n\ttype: string;\n\t/** Instant the event belongs to */\n\tatUtc: number;\n\t/** Name of the employee the event belongs to, empty for instance wide events */\n\tuserName: string;\n\t/** Direction of a punch (`in`/`out`), empty for other events */\n\tdirection: string;\n\t/** Where the change came from, e.g. `web` or `terminal`, empty when unknown */\n\tsource: string;\n}\n\n/** Names of the writable command states. */\nexport const COMMAND_IDS = {\n\t/** Employee the commands apply to */\n\tpunchUserId: \"commands.punchUserId\",\n\t/** Punch in or out for `punchUserId` */\n\tpunch: \"commands.punch\",\n\t/** Punch in or out with the configured quick rounding */\n\tquickPunch: \"commands.quickPunch\",\n\t/** Close a month, value `YYYY-MM` */\n\tcloseMonth: \"commands.closeMonth\",\n\t/** Recalculate a period, value `YYYY-MM` or `YYYY` */\n\trecalc: \"commands.recalc\",\n\t/** Write a backup of the database */\n\tbackup: \"commands.backup\",\n} as const;\n\n/**\n * Builds a state object definition.\n *\n * @param name - name in English and German\n * @param name.en - English name\n * @param name.de - German name\n * @param type - state type\n * @param role - state role\n * @param options - additional flags\n * @param options.read - value can be read (default true)\n * @param options.write - value can be written (default false)\n * @param options.unit - unit of the value\n * @returns object definition\n */\nfunction stateObject(\n\tname: { en: string; de: string },\n\ttype: ioBroker.CommonType,\n\trole: string,\n\toptions: { read?: boolean; write?: boolean; unit?: string } = {},\n): ioBroker.SettableObject {\n\treturn {\n\t\ttype: \"state\",\n\t\tcommon: {\n\t\t\tname,\n\t\t\ttype,\n\t\t\trole,\n\t\t\tread: options.read !== false,\n\t\t\twrite: options.write === true,\n\t\t\t...(options.unit ? { unit: options.unit } : {}),\n\t\t},\n\t\tnative: {},\n\t};\n}\n\n/**\n * Builds a channel object definition.\n *\n * @param name - name in English and German\n * @param name.en - English name\n * @param name.de - German name\n * @returns object definition\n */\nfunction channelObject(name: { en: string; de: string }): ioBroker.SettableObject {\n\treturn { type: \"channel\", common: { name }, native: {} };\n}\n\n/**\n * Reads the figures of an employee for the state tree.\n *\n * @param args - data sources and employee\n * @param args.aggregation - aggregation service\n * @param args.users - user storage\n * @param args.sync - synchronisation service (open conflicts)\n * @param args.userId - database id of the employee\n * @param args.now - instant of the snapshot\n * @returns snapshot of the figures\n */\nexport function readUserSnapshot(args: {\n\taggregation: AggregationService;\n\tusers: UsersRepository;\n\tsync: SyncService;\n\tuserId: number;\n\tnow?: number;\n}): UserSnapshot | null {\n\tconst user = args.users.findById(args.userId);\n\tif (!user) {\n\t\treturn null;\n\t}\n\n\tconst timestamp = args.now ?? Math.floor(Date.now() / 1000);\n\tconst today = resolveLocalDate(timestamp, user.timezone);\n\tconst day = args.aggregation.recalculateDay(user.id, today, { now: timestamp });\n\t// the month is recalculated like the month view does it; the year is read, so the publishing stays cheap\n\tconst year = Number(today.slice(0, 4));\n\tconst month = Number(today.slice(5, 7));\n\tconst monthAggregate = args.aggregation.recalculateMonth(user.id, year, month, { now: timestamp });\n\tconst yearAggregate = args.aggregation.year(user.id, year);\n\n\treturn {\n\t\tuserId: user.id,\n\t\tdisplayName: user.displayName,\n\t\thasOpenEntry: day.hasOpenEntry,\n\t\tlastPunchUtc: Math.max(day.firstInUtc ?? 0, day.lastOutUtc ?? 0) || null,\n\t\tworkedMinutes: day.workedMin,\n\t\tbalanceMinutes: day.balanceMin,\n\t\topenConflicts: args.sync.conflicts(user.id).length,\n\t\tmonthWorkedMinutes: monthAggregate.workedMin,\n\t\tmonthBalanceMinutes: monthAggregate.balanceMin,\n\t\tyearBalanceMinutes: yearAggregate ? yearAggregate.workedMin - yearAggregate.targetMin : 0,\n\t};\n}\n\n/**\n * Publishes the figures of one employee.\n *\n * @param port - state port\n * @param snapshot - figures to publish\n */\nexport async function publishUserSnapshot(port: StatePort, snapshot: UserSnapshot): Promise<void> {\n\tconst id = `users.${snapshot.userId}`;\n\tawait port.setState(`${id}.displayName`, snapshot.displayName, true);\n\tawait port.setState(`${id}.present`, snapshot.hasOpenEntry, true);\n\tawait port.setState(`${id}.hasOpenEntry`, snapshot.hasOpenEntry, true);\n\tawait port.setState(`${id}.lastPunch`, snapshot.lastPunchUtc ?? 0, true);\n\tawait port.setState(`${id}.todayWorkedMinutes`, snapshot.workedMinutes, true);\n\tawait port.setState(`${id}.todayBalanceMinutes`, snapshot.balanceMinutes, true);\n\tawait port.setState(`${id}.monthWorkedMinutes`, snapshot.monthWorkedMinutes, true);\n\tawait port.setState(`${id}.monthBalanceMinutes`, snapshot.monthBalanceMinutes, true);\n\tawait port.setState(`${id}.yearBalanceMinutes`, snapshot.yearBalanceMinutes, true);\n\tawait port.setState(`${id}.openConflicts`, snapshot.openConflicts, true);\n}\n\n/**\n * Creates the channels of all employees and publishes their current figures.\n *\n * @param args - state port and data sources\n * @param args.port - state port\n * @param args.aggregation - aggregation service\n * @param args.users - user storage\n * @param args.sync - synchronisation service\n * @param args.now - instant of the snapshot\n * @returns the published snapshots\n */\nexport async function publishAllUserStates(args: {\n\tport: StatePort;\n\taggregation: AggregationService;\n\tusers: UsersRepository;\n\tsync: SyncService;\n\tnow?: number;\n}): Promise<UserSnapshot[]> {\n\tconst snapshots: UserSnapshot[] = [];\n\tfor (const user of args.users.list({ includeInactive: true })) {\n\t\tawait createUserChannel(args.port, user.id);\n\t\tconst snapshot = readUserSnapshot({\n\t\t\taggregation: args.aggregation,\n\t\t\tusers: args.users,\n\t\t\tsync: args.sync,\n\t\t\tuserId: user.id,\n\t\t\tnow: args.now,\n\t\t});\n\t\tif (!snapshot) {\n\t\t\tcontinue;\n\t\t}\n\t\tawait publishUserSnapshot(args.port, snapshot);\n\t\tsnapshots.push(snapshot);\n\t}\n\treturn snapshots;\n}\n\n/**\n * Creates the channel of one employee, including the shared parent channel `users`.\n *\n * The parent channel matters: the ioBroker object structure check (`E3009`) requires every state to have its\n * parents, so `users.<userId>.*` below a missing `users` produced 126 findings in the repository check\n * (PR #6697). `setObjectNotExists` keeps the call idempotent.\n *\n * @param port - state port\n * @param userId - database id of the employee\n * @returns the channel id\n */\nexport async function createUserChannel(port: StatePort, userId: number): Promise<string> {\n\tconst id = `users.${userId}`;\n\tawait port.setObjectNotExists(\"users\", channelObject({ en: \"Employees\", de: \"Mitarbeiter\" }));\n\tawait port.setObjectNotExists(id, channelObject({ en: \"Employee\", de: \"Mitarbeiter\" }));\n\tawait port.setObjectNotExists(`${id}.displayName`, stateObject({ en: \"Name\", de: \"Name\" }, \"string\", \"info.name\"));\n\t// the writable twin of `hasOpenEntry`: a script, a fingerprint reader or a dashboard writes it to say that\n\t// somebody arrived (`true`) or left (`false`) \u2014 see `presence.ts` for what the adapter does with it\n\tawait port.setObjectNotExists(\n\t\t`${id}.present`,\n\t\tstateObject(\n\t\t\t{ en: \"Present (working time is running)\", de: \"Anwesenheit (Arbeitszeit l\u00E4uft)\" },\n\t\t\t\"boolean\",\n\t\t\t\"switch\",\n\t\t\t{ write: true },\n\t\t),\n\t);\n\tawait port.setObjectNotExists(\n\t\t`${id}.hasOpenEntry`,\n\t\tstateObject({ en: \"Punched in\", de: \"Eingestempelt\" }, \"boolean\", \"indicator.working\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t`${id}.lastPunch`,\n\t\tstateObject({ en: \"Last punch\", de: \"Letzte Buchung\" }, \"number\", \"value.time\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t`${id}.todayWorkedMinutes`,\n\t\tstateObject({ en: \"Worked today\", de: \"Heute gearbeitet\" }, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait port.setObjectNotExists(\n\t\t`${id}.todayBalanceMinutes`,\n\t\tstateObject({ en: \"Balance today\", de: \"Saldo heute\" }, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait port.setObjectNotExists(\n\t\t`${id}.monthWorkedMinutes`,\n\t\tstateObject({ en: \"Worked this month\", de: \"Diesen Monat gearbeitet\" }, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait port.setObjectNotExists(\n\t\t`${id}.monthBalanceMinutes`,\n\t\tstateObject({ en: \"Balance this month\", de: \"Saldo diesen Monat\" }, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait port.setObjectNotExists(\n\t\t`${id}.yearBalanceMinutes`,\n\t\tstateObject({ en: \"Balance this year\", de: \"Saldo dieses Jahr\" }, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait port.setObjectNotExists(\n\t\t`${id}.openConflicts`,\n\t\tstateObject({ en: \"Open conflicts\", de: \"Offene Konflikte\" }, \"number\", \"value\"),\n\t);\n\treturn id;\n}\n\n/**\n * Creates the writable command states.\n *\n * @param port - state port\n */\nexport async function createCommandStates(port: StatePort): Promise<void> {\n\tawait port.setObjectNotExists(\"commands\", channelObject({ en: \"Commands\", de: \"Befehle\" }));\n\tawait port.setObjectNotExists(\n\t\tCOMMAND_IDS.punchUserId,\n\t\tstateObject(\n\t\t\t{ en: \"Employee id for punch commands\", de: \"Mitarbeiter-Id f\u00FCr Stempelbefehle\" },\n\t\t\t\"number\",\n\t\t\t\"value\",\n\t\t\t{\n\t\t\t\twrite: true,\n\t\t\t},\n\t\t),\n\t);\n\tawait port.setObjectNotExists(\n\t\tCOMMAND_IDS.punch,\n\t\tstateObject({ en: \"Punch in or out\", de: \"Ein- oder ausstempeln\" }, \"boolean\", \"button\", {\n\t\t\tread: false,\n\t\t\twrite: true,\n\t\t}),\n\t);\n\tawait port.setObjectNotExists(\n\t\tCOMMAND_IDS.quickPunch,\n\t\tstateObject({ en: \"Punch with quick rounding\", de: \"Stempeln mit Schnellrundung\" }, \"boolean\", \"button\", {\n\t\t\tread: false,\n\t\t\twrite: true,\n\t\t}),\n\t);\n\tawait port.setObjectNotExists(\n\t\tCOMMAND_IDS.closeMonth,\n\t\tstateObject({ en: \"Close month (YYYY-MM)\", de: \"Monat abschlie\u00DFen (JJJJ-MM)\" }, \"string\", \"text\", {\n\t\t\twrite: true,\n\t\t}),\n\t);\n\tawait port.setObjectNotExists(\n\t\tCOMMAND_IDS.recalc,\n\t\tstateObject(\n\t\t\t{ en: \"Recalculate period (YYYY-MM or YYYY)\", de: \"Zeitraum neu berechnen (JJJJ-MM oder JJJJ)\" },\n\t\t\t\"string\",\n\t\t\t\"text\",\n\t\t\t{ write: true },\n\t\t),\n\t);\n\tawait port.setObjectNotExists(\n\t\tCOMMAND_IDS.backup,\n\t\tstateObject({ en: \"Write a database backup\", de: \"Datenbank-Sicherung schreiben\" }, \"boolean\", \"button\", {\n\t\t\tread: false,\n\t\t\twrite: true,\n\t\t}),\n\t);\n}\n\n/**\n * Creates the informational states of the instance.\n *\n * @param port - state port\n */\nexport async function createInfoStates(port: StatePort): Promise<void> {\n\tawait port.setObjectNotExists(\"info\", channelObject({ en: \"Information\", de: \"Information\" }));\n\tawait port.setObjectNotExists(\n\t\t\"info.version\",\n\t\tstateObject({ en: \"Adapter version\", de: \"Adapter-Version\" }, \"string\", \"text\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"info.schemaVersion\",\n\t\tstateObject({ en: \"Database schema version\", de: \"Datenbank-Schemaversion\" }, \"string\", \"text\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"info.dbSizeBytes\",\n\t\tstateObject({ en: \"Database size\", de: \"Datenbank-Gr\u00F6\u00DFe\" }, \"number\", \"value\", { unit: \"bytes\" }),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"info.lastError\",\n\t\tstateObject({ en: \"Last error\", de: \"Letzter Fehler\" }, \"string\", \"text\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"info.lastBackup\",\n\t\tstateObject({ en: \"Last backup\", de: \"Letzte Sicherung\" }, \"number\", \"value.time\"),\n\t);\n}\n\n/**\n * Creates the states of the company.\n *\n * @param port - state port\n */\nexport async function createCompanyStates(port: StatePort): Promise<void> {\n\tawait port.setObjectNotExists(\"company\", channelObject({ en: \"Company\", de: \"Firma\" }));\n\tawait port.setObjectNotExists(\n\t\t\"company.presentCount\",\n\t\tstateObject({ en: \"Present employees\", de: \"Anwesende Mitarbeiter\" }, \"number\", \"value\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"company.present\",\n\t\tstateObject({ en: \"Who is present\", de: \"Wer ist anwesend\" }, \"string\", \"text\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"company.openConflicts\",\n\t\tstateObject({ en: \"Open conflicts\", de: \"Offene Konflikte\" }, \"number\", \"value\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"company.lastPunch\",\n\t\tstateObject({ en: \"Last punch\", de: \"Letzte Buchung\" }, \"number\", \"value.time\"),\n\t);\n}\n\n/**\n * Reads the company figures out of the figures of the employees.\n *\n * @param snapshots - figures of all employees\n * @returns the company figures\n */\nexport function readCompanySnapshot(snapshots: UserSnapshot[]): CompanySnapshot {\n\tconst present = snapshots.filter(snapshot => snapshot.hasOpenEntry);\n\treturn {\n\t\tpresentCount: present.length,\n\t\tpresent: present.map(snapshot => snapshot.displayName).join(\", \"),\n\t\topenConflicts: snapshots.reduce((sum, snapshot) => sum + snapshot.openConflicts, 0),\n\t\tlastPunchUtc: snapshots.reduce<number | null>(\n\t\t\t(newest, snapshot) =>\n\t\t\t\tsnapshot.lastPunchUtc !== null && (newest === null || snapshot.lastPunchUtc > newest)\n\t\t\t\t\t? snapshot.lastPunchUtc\n\t\t\t\t\t: newest,\n\t\t\tnull,\n\t\t),\n\t};\n}\n\n/**\n * Publishes the company figures.\n *\n * @param port - state port\n * @param snapshot - figures to publish\n */\nexport async function publishCompanySnapshot(port: StatePort, snapshot: CompanySnapshot): Promise<void> {\n\tawait port.setState(\"company.presentCount\", snapshot.presentCount, true);\n\tawait port.setState(\"company.present\", snapshot.present, true);\n\tawait port.setState(\"company.openConflicts\", snapshot.openConflicts, true);\n\tawait port.setState(\"company.lastPunch\", snapshot.lastPunchUtc ?? 0, true);\n}\n\n/**\n * Creates the event states.\n *\n * @param port - state port\n */\nexport async function createEventStates(port: StatePort): Promise<void> {\n\tawait port.setObjectNotExists(\"events\", channelObject({ en: \"Events\", de: \"Ereignisse\" }));\n\tawait port.setObjectNotExists(\n\t\t\"events.lastAt\",\n\t\tstateObject({ en: \"Last event at\", de: \"Letztes Ereignis um\" }, \"number\", \"value.time\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"events.lastType\",\n\t\tstateObject({ en: \"Kind of the last event\", de: \"Art des letzten Ereignisses\" }, \"string\", \"text\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"events.lastUser\",\n\t\tstateObject({ en: \"Employee of the last event\", de: \"Mitarbeiter des letzten Ereignisses\" }, \"string\", \"text\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"events.lastDirection\",\n\t\tstateObject({ en: \"Direction of the last punch\", de: \"Richtung der letzten Buchung\" }, \"string\", \"text\"),\n\t);\n\tawait port.setObjectNotExists(\n\t\t\"events.lastSource\",\n\t\tstateObject({ en: \"Source of the last event\", de: \"Quelle des letzten Ereignisses\" }, \"string\", \"text\"),\n\t);\n}\n\n/**\n * Publishes the newest event.\n *\n * @param port - state port\n * @param snapshot - event to publish\n */\nexport async function publishEventSnapshot(port: StatePort, snapshot: EventSnapshot): Promise<void> {\n\tawait port.setState(\"events.lastAt\", snapshot.atUtc, true);\n\tawait port.setState(\"events.lastType\", snapshot.type, true);\n\tawait port.setState(\"events.lastUser\", snapshot.userName, true);\n\tawait port.setState(\"events.lastDirection\", snapshot.direction, true);\n\tawait port.setState(\"events.lastSource\", snapshot.source, true);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * States published by the adapter.\n *\n * The adapter exposes a small, stable state tree so that other adapters (and the user's dashboards) can show\n * and trigger time tracking without speaking to the REST API:\n *\n * ```\n * users.<userId>.displayName / present / hasOpenEntry / lastPunch / todayWorkedMinutes / todayBalanceMinutes\n * users.<userId>.openConflicts\n * commands.punchUserId / punch / quickPunch / closeMonth / recalc\n * ```\n *\n * All objects are created with `setObjectNotExists`, so existing instances keep their settings. The logic works\n * on a tiny port interface (`StatePort`) \u2014 the adapter instance in production, a recorder in the tests.\n */\n\nimport type { UsersRepository } from \"../db/repositories/users\";\nimport type { AggregationService } from \"../services/aggregation\";\nimport type { SyncService } from \"../services/sync\";\nimport { STATE_NAMES, type StateName } from \"./stateNames\";\nimport { localDate as resolveLocalDate } from \"../util/time\";\n\n/** Subset of the adapter API the state layer needs. */\nexport interface StatePort {\n\t/**\n\t * Creates an object when it does not exist yet.\n\t *\n\t * @param id - full state id (including the instance prefix)\n\t * @param object - object definition\n\t */\n\tsetObjectNotExists(id: string, object: ioBroker.SettableObject): Promise<unknown> | void;\n\t/**\n\t * Merges fields into an object that already exists.\n\t *\n\t * @param id - full state id (including the instance prefix)\n\t * @param object - fields to merge\n\t */\n\textendObject(id: string, object: ioBroker.PartialObject): Promise<unknown> | void;\n\t/**\n\t * Writes a state value.\n\t *\n\t * @param id - full state id (including the instance prefix)\n\t * @param value - value to write\n\t * @param ack - true for confirmed values\n\t */\n\tsetState(id: string, value: ioBroker.StateValue, ack?: boolean): Promise<unknown> | void;\n}\n\n/** Figures of one employee shown in the state tree. */\nexport interface UserSnapshot {\n\t/** Database id of the employee */\n\tuserId: number;\n\t/** Shown name */\n\tdisplayName: string;\n\t/** True when the last punch of today has no counterpart */\n\thasOpenEntry: boolean;\n\t/** Instant of the last punch of the day, `null` when there is none */\n\tlastPunchUtc: number | null;\n\t/** Net working time of today in minutes */\n\tworkedMinutes: number;\n\t/** Balance of today in minutes */\n\tbalanceMinutes: number;\n\t/** Punches waiting for a decision */\n\topenConflicts: number;\n\t/** Net working time of the current month in minutes */\n\tmonthWorkedMinutes: number;\n\t/** Balance of the current month in minutes */\n\tmonthBalanceMinutes: number;\n\t/** Balance of the current year in minutes */\n\tyearBalanceMinutes: number;\n}\n\n/** Figures of the whole company, published next to the employees. */\nexport interface CompanySnapshot {\n\t/** Employees that are clocked in right now */\n\tpresentCount: number;\n\t/** Names of those employees, separated by a comma (empty when nobody is present) */\n\tpresent: string;\n\t/** Punches of all employees waiting for a decision */\n\topenConflicts: number;\n\t/** Instant of the newest punch of today, `null` when nobody punched */\n\tlastPunchUtc: number | null;\n}\n\n/** Newest event of the instance, mirrored into the state tree. */\nexport interface EventSnapshot {\n\t/** Kind of the event, e.g. `punch` */\n\ttype: string;\n\t/** Instant the event belongs to */\n\tatUtc: number;\n\t/** Name of the employee the event belongs to, empty for instance wide events */\n\tuserName: string;\n\t/** Direction of a punch (`in`/`out`), empty for other events */\n\tdirection: string;\n\t/** Where the change came from, e.g. `web` or `terminal`, empty when unknown */\n\tsource: string;\n}\n\n/** Names of the writable command states. */\nexport const COMMAND_IDS = {\n\t/** Employee the commands apply to */\n\tpunchUserId: \"commands.punchUserId\",\n\t/** Punch in or out for `punchUserId` */\n\tpunch: \"commands.punch\",\n\t/** Punch in or out with the configured quick rounding */\n\tquickPunch: \"commands.quickPunch\",\n\t/** Close a month, value `YYYY-MM` */\n\tcloseMonth: \"commands.closeMonth\",\n\t/** Recalculate a period, value `YYYY-MM` or `YYYY` */\n\trecalc: \"commands.recalc\",\n\t/** Write a backup of the database */\n\tbackup: \"commands.backup\",\n} as const;\n\n/**\n * Builds a state object definition.\n *\n * @param name - name in English and German\n * @param name.en - English name\n * @param name.de - German name\n * @param type - state type\n * @param role - state role\n * @param options - additional flags\n * @param options.read - value can be read (default true)\n * @param options.write - value can be written (default false)\n * @param options.unit - unit of the value\n * @returns object definition\n */\nfunction stateObject(\n\tname: StateName,\n\ttype: ioBroker.CommonType,\n\trole: string,\n\toptions: { read?: boolean; write?: boolean; unit?: string } = {},\n): ioBroker.SettableObject {\n\treturn {\n\t\ttype: \"state\",\n\t\tcommon: {\n\t\t\tname,\n\t\t\ttype,\n\t\t\trole,\n\t\t\tread: options.read !== false,\n\t\t\twrite: options.write === true,\n\t\t\t...(options.unit ? { unit: options.unit } : {}),\n\t\t},\n\t\tnative: {},\n\t};\n}\n\n/**\n * Builds a channel object definition.\n *\n * @param name - name in English and German\n * @param name.en - English name\n * @param name.de - German name\n * @returns object definition\n */\nfunction channelObject(name: StateName): ioBroker.SettableObject {\n\treturn { type: \"channel\", common: { name }, native: {} };\n}\n\n/**\n * Creates an object when it is missing and keeps the definition of an existing one current.\n *\n * `setObjectNotExists` alone would leave existing installations on the definition they were created with \u2014 a later\n * correction (for example the role of `commands.punchUserId`, checker `E1011`) would never arrive. So the fields the\n * adapter owns are merged on every start; `common.custom` is left out, that is where the user configures `history`\n * and similar integrations.\n *\n * @param port - state port\n * @param id - full state id (including the instance prefix)\n * @param object - object definition\n */\nasync function ensureObject(port: StatePort, id: string, object: ioBroker.SettableObject): Promise<void> {\n\tawait port.setObjectNotExists(id, object);\n\tconst common: Record<string, unknown> = { ...(object.common ?? {}) };\n\tdelete common.custom;\n\tawait port.extendObject(id, { common });\n}\n\n/**\n * Reads the figures of an employee for the state tree.\n *\n * @param args - data sources and employee\n * @param args.aggregation - aggregation service\n * @param args.users - user storage\n * @param args.sync - synchronisation service (open conflicts)\n * @param args.userId - database id of the employee\n * @param args.now - instant of the snapshot\n * @returns snapshot of the figures\n */\nexport function readUserSnapshot(args: {\n\taggregation: AggregationService;\n\tusers: UsersRepository;\n\tsync: SyncService;\n\tuserId: number;\n\tnow?: number;\n}): UserSnapshot | null {\n\tconst user = args.users.findById(args.userId);\n\tif (!user) {\n\t\treturn null;\n\t}\n\n\tconst timestamp = args.now ?? Math.floor(Date.now() / 1000);\n\tconst today = resolveLocalDate(timestamp, user.timezone);\n\tconst day = args.aggregation.recalculateDay(user.id, today, { now: timestamp });\n\t// the month is recalculated like the month view does it; the year is read, so the publishing stays cheap\n\tconst year = Number(today.slice(0, 4));\n\tconst month = Number(today.slice(5, 7));\n\tconst monthAggregate = args.aggregation.recalculateMonth(user.id, year, month, { now: timestamp });\n\tconst yearAggregate = args.aggregation.year(user.id, year);\n\n\treturn {\n\t\tuserId: user.id,\n\t\tdisplayName: user.displayName,\n\t\thasOpenEntry: day.hasOpenEntry,\n\t\tlastPunchUtc: Math.max(day.firstInUtc ?? 0, day.lastOutUtc ?? 0) || null,\n\t\tworkedMinutes: day.workedMin,\n\t\tbalanceMinutes: day.balanceMin,\n\t\topenConflicts: args.sync.conflicts(user.id).length,\n\t\tmonthWorkedMinutes: monthAggregate.workedMin,\n\t\tmonthBalanceMinutes: monthAggregate.balanceMin,\n\t\tyearBalanceMinutes: yearAggregate ? yearAggregate.workedMin - yearAggregate.targetMin : 0,\n\t};\n}\n\n/**\n * Publishes the figures of one employee.\n *\n * @param port - state port\n * @param snapshot - figures to publish\n */\nexport async function publishUserSnapshot(port: StatePort, snapshot: UserSnapshot): Promise<void> {\n\tconst id = `users.${snapshot.userId}`;\n\tawait port.setState(`${id}.displayName`, snapshot.displayName, true);\n\tawait port.setState(`${id}.present`, snapshot.hasOpenEntry, true);\n\tawait port.setState(`${id}.hasOpenEntry`, snapshot.hasOpenEntry, true);\n\tawait port.setState(`${id}.lastPunch`, snapshot.lastPunchUtc ?? 0, true);\n\tawait port.setState(`${id}.todayWorkedMinutes`, snapshot.workedMinutes, true);\n\tawait port.setState(`${id}.todayBalanceMinutes`, snapshot.balanceMinutes, true);\n\tawait port.setState(`${id}.monthWorkedMinutes`, snapshot.monthWorkedMinutes, true);\n\tawait port.setState(`${id}.monthBalanceMinutes`, snapshot.monthBalanceMinutes, true);\n\tawait port.setState(`${id}.yearBalanceMinutes`, snapshot.yearBalanceMinutes, true);\n\tawait port.setState(`${id}.openConflicts`, snapshot.openConflicts, true);\n}\n\n/**\n * Creates the channels of all employees and publishes their current figures.\n *\n * @param args - state port and data sources\n * @param args.port - state port\n * @param args.aggregation - aggregation service\n * @param args.users - user storage\n * @param args.sync - synchronisation service\n * @param args.now - instant of the snapshot\n * @returns the published snapshots\n */\nexport async function publishAllUserStates(args: {\n\tport: StatePort;\n\taggregation: AggregationService;\n\tusers: UsersRepository;\n\tsync: SyncService;\n\tnow?: number;\n}): Promise<UserSnapshot[]> {\n\tconst snapshots: UserSnapshot[] = [];\n\tfor (const user of args.users.list({ includeInactive: true })) {\n\t\tawait createUserChannel(args.port, user.id);\n\t\tconst snapshot = readUserSnapshot({\n\t\t\taggregation: args.aggregation,\n\t\t\tusers: args.users,\n\t\t\tsync: args.sync,\n\t\t\tuserId: user.id,\n\t\t\tnow: args.now,\n\t\t});\n\t\tif (!snapshot) {\n\t\t\tcontinue;\n\t\t}\n\t\tawait publishUserSnapshot(args.port, snapshot);\n\t\tsnapshots.push(snapshot);\n\t}\n\treturn snapshots;\n}\n\n/**\n * Creates the channel of one employee, including the shared parent channel `users`.\n *\n * The parent channel matters: the ioBroker object structure check (`E3009`) requires every state to have its\n * parents, so `users.<userId>.*` below a missing `users` produced 126 findings in the repository check\n * (PR #6697). `setObjectNotExists` keeps the call idempotent.\n *\n * @param port - state port\n * @param userId - database id of the employee\n * @returns the channel id\n */\nexport async function createUserChannel(port: StatePort, userId: number): Promise<string> {\n\tconst id = `users.${userId}`;\n\tawait ensureObject(port, \"users\", channelObject(STATE_NAMES.usersChannel));\n\tawait ensureObject(port, id, channelObject(STATE_NAMES.employeeChannel));\n\tawait ensureObject(port, `${id}.displayName`, stateObject(STATE_NAMES.displayName, \"string\", \"info.name\"));\n\t// the writable twin of `hasOpenEntry`: a script, a fingerprint reader or a dashboard writes it to say that\n\t// somebody arrived (`true`) or left (`false`) \u2014 see `presence.ts` for what the adapter does with it\n\tawait ensureObject(\n\t\tport,\n\t\t`${id}.present`,\n\t\tstateObject(STATE_NAMES.userPresent, \"boolean\", \"switch\", { write: true }),\n\t);\n\tawait ensureObject(\n\t\tport,\n\t\t`${id}.hasOpenEntry`,\n\t\tstateObject(STATE_NAMES.hasOpenEntry, \"boolean\", \"indicator.working\"),\n\t);\n\tawait ensureObject(port, `${id}.lastPunch`, stateObject(STATE_NAMES.lastPunch, \"number\", \"value.time\"));\n\tawait ensureObject(\n\t\tport,\n\t\t`${id}.todayWorkedMinutes`,\n\t\tstateObject(STATE_NAMES.todayWorkedMinutes, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait ensureObject(\n\t\tport,\n\t\t`${id}.todayBalanceMinutes`,\n\t\tstateObject(STATE_NAMES.todayBalanceMinutes, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait ensureObject(\n\t\tport,\n\t\t`${id}.monthWorkedMinutes`,\n\t\tstateObject(STATE_NAMES.monthWorkedMinutes, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait ensureObject(\n\t\tport,\n\t\t`${id}.monthBalanceMinutes`,\n\t\tstateObject(STATE_NAMES.monthBalanceMinutes, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait ensureObject(\n\t\tport,\n\t\t`${id}.yearBalanceMinutes`,\n\t\tstateObject(STATE_NAMES.yearBalanceMinutes, \"number\", \"value\", { unit: \"min\" }),\n\t);\n\tawait ensureObject(port, `${id}.openConflicts`, stateObject(STATE_NAMES.openConflicts, \"number\", \"value\"));\n\treturn id;\n}\n\n/**\n * Creates the writable command states.\n *\n * @param port - state port\n */\nexport async function createCommandStates(port: StatePort): Promise<void> {\n\tawait ensureObject(port, \"commands\", channelObject(STATE_NAMES.commandsChannel));\n\tawait ensureObject(\n\t\tport,\n\t\tCOMMAND_IDS.punchUserId,\n\t\tstateObject(STATE_NAMES.punchUserId, \"number\", \"level\", {\n\t\t\twrite: true,\n\t\t}),\n\t);\n\tawait ensureObject(\n\t\tport,\n\t\tCOMMAND_IDS.punch,\n\t\tstateObject(STATE_NAMES.punch, \"boolean\", \"button\", {\n\t\t\tread: false,\n\t\t\twrite: true,\n\t\t}),\n\t);\n\tawait ensureObject(\n\t\tport,\n\t\tCOMMAND_IDS.quickPunch,\n\t\tstateObject(STATE_NAMES.quickPunch, \"boolean\", \"button\", {\n\t\t\tread: false,\n\t\t\twrite: true,\n\t\t}),\n\t);\n\tawait ensureObject(\n\t\tport,\n\t\tCOMMAND_IDS.closeMonth,\n\t\tstateObject(STATE_NAMES.closeMonth, \"string\", \"text\", {\n\t\t\twrite: true,\n\t\t}),\n\t);\n\tawait ensureObject(port, COMMAND_IDS.recalc, stateObject(STATE_NAMES.recalc, \"string\", \"text\", { write: true }));\n\tawait ensureObject(\n\t\tport,\n\t\tCOMMAND_IDS.backup,\n\t\tstateObject(STATE_NAMES.backupCommand, \"boolean\", \"button\", {\n\t\t\tread: false,\n\t\t\twrite: true,\n\t\t}),\n\t);\n}\n\n/**\n * Creates the informational states of the instance.\n *\n * @param port - state port\n */\nexport async function createInfoStates(port: StatePort): Promise<void> {\n\tawait ensureObject(port, \"info\", channelObject(STATE_NAMES.infoChannel));\n\tawait ensureObject(port, \"info.version\", stateObject(STATE_NAMES.version, \"string\", \"text\"));\n\tawait ensureObject(port, \"info.schemaVersion\", stateObject(STATE_NAMES.schemaVersion, \"string\", \"text\"));\n\tawait ensureObject(\n\t\tport,\n\t\t\"info.dbSizeBytes\",\n\t\tstateObject(STATE_NAMES.dbSizeBytes, \"number\", \"value\", { unit: \"bytes\" }),\n\t);\n\tawait ensureObject(port, \"info.lastError\", stateObject(STATE_NAMES.lastError, \"string\", \"text\"));\n\tawait ensureObject(port, \"info.lastBackup\", stateObject(STATE_NAMES.lastBackup, \"number\", \"value.time\"));\n}\n\n/**\n * Creates the states of the company.\n *\n * @param port - state port\n */\nexport async function createCompanyStates(port: StatePort): Promise<void> {\n\tawait ensureObject(port, \"company\", channelObject(STATE_NAMES.companyChannel));\n\tawait ensureObject(port, \"company.presentCount\", stateObject(STATE_NAMES.companyPresentCount, \"number\", \"value\"));\n\tawait ensureObject(port, \"company.present\", stateObject(STATE_NAMES.companyPresent, \"string\", \"text\"));\n\tawait ensureObject(port, \"company.openConflicts\", stateObject(STATE_NAMES.openConflicts, \"number\", \"value\"));\n\tawait ensureObject(port, \"company.lastPunch\", stateObject(STATE_NAMES.companyLastPunch, \"number\", \"value.time\"));\n}\n\n/**\n * Reads the company figures out of the figures of the employees.\n *\n * @param snapshots - figures of all employees\n * @returns the company figures\n */\nexport function readCompanySnapshot(snapshots: UserSnapshot[]): CompanySnapshot {\n\tconst present = snapshots.filter(snapshot => snapshot.hasOpenEntry);\n\treturn {\n\t\tpresentCount: present.length,\n\t\tpresent: present.map(snapshot => snapshot.displayName).join(\", \"),\n\t\topenConflicts: snapshots.reduce((sum, snapshot) => sum + snapshot.openConflicts, 0),\n\t\tlastPunchUtc: snapshots.reduce<number | null>(\n\t\t\t(newest, snapshot) =>\n\t\t\t\tsnapshot.lastPunchUtc !== null && (newest === null || snapshot.lastPunchUtc > newest)\n\t\t\t\t\t? snapshot.lastPunchUtc\n\t\t\t\t\t: newest,\n\t\t\tnull,\n\t\t),\n\t};\n}\n\n/**\n * Publishes the company figures.\n *\n * @param port - state port\n * @param snapshot - figures to publish\n */\nexport async function publishCompanySnapshot(port: StatePort, snapshot: CompanySnapshot): Promise<void> {\n\tawait port.setState(\"company.presentCount\", snapshot.presentCount, true);\n\tawait port.setState(\"company.present\", snapshot.present, true);\n\tawait port.setState(\"company.openConflicts\", snapshot.openConflicts, true);\n\tawait port.setState(\"company.lastPunch\", snapshot.lastPunchUtc ?? 0, true);\n}\n\n/**\n * Creates the event states.\n *\n * @param port - state port\n */\nexport async function createEventStates(port: StatePort): Promise<void> {\n\tawait ensureObject(port, \"events\", channelObject(STATE_NAMES.eventsChannel));\n\tawait ensureObject(port, \"events.lastAt\", stateObject(STATE_NAMES.lastAt, \"number\", \"value.time\"));\n\tawait ensureObject(port, \"events.lastType\", stateObject(STATE_NAMES.lastType, \"string\", \"text\"));\n\tawait ensureObject(port, \"events.lastUser\", stateObject(STATE_NAMES.lastUser, \"string\", \"text\"));\n\tawait ensureObject(port, \"events.lastDirection\", stateObject(STATE_NAMES.lastDirection, \"string\", \"text\"));\n\tawait ensureObject(port, \"events.lastSource\", stateObject(STATE_NAMES.lastSource, \"string\", \"text\"));\n}\n\n/**\n * Publishes the newest event.\n *\n * @param port - state port\n * @param snapshot - event to publish\n */\nexport async function publishEventSnapshot(port: StatePort, snapshot: EventSnapshot): Promise<void> {\n\tawait port.setState(\"events.lastAt\", snapshot.atUtc, true);\n\tawait port.setState(\"events.lastType\", snapshot.type, true);\n\tawait port.setState(\"events.lastUser\", snapshot.userName, true);\n\tawait port.setState(\"events.lastDirection\", snapshot.direction, true);\n\tawait port.setState(\"events.lastSource\", snapshot.source, true);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBA,wBAA4C;AAC5C,kBAA8C;AA+EvC,MAAM,cAAc;AAAA;AAAA,EAE1B,aAAa;AAAA;AAAA,EAEb,OAAO;AAAA;AAAA,EAEP,YAAY;AAAA;AAAA,EAEZ,YAAY;AAAA;AAAA,EAEZ,QAAQ;AAAA;AAAA,EAER,QAAQ;AACT;AAgBA,SAAS,YACR,MACA,MACA,MACA,UAA8D,CAAC,GACrC;AAC1B,SAAO;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,QAAQ,SAAS;AAAA,MACvB,OAAO,QAAQ,UAAU;AAAA,MACzB,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC9C;AAAA,IACA,QAAQ,CAAC;AAAA,EACV;AACD;AAUA,SAAS,cAAc,MAA0C;AAChE,SAAO,EAAE,MAAM,WAAW,QAAQ,EAAE,KAAK,GAAG,QAAQ,CAAC,EAAE;AACxD;AAcA,eAAe,aAAa,MAAiB,IAAY,QAAgD;AA5KzG;AA6KC,QAAM,KAAK,mBAAmB,IAAI,MAAM;AACxC,QAAM,SAAkC,EAAE,IAAI,YAAO,WAAP,YAAiB,CAAC,EAAG;AACnE,SAAO,OAAO;AACd,QAAM,KAAK,aAAa,IAAI,EAAE,OAAO,CAAC;AACvC;AAaO,SAAS,iBAAiB,MAMT;AApMxB;AAqMC,QAAM,OAAO,KAAK,MAAM,SAAS,KAAK,MAAM;AAC5C,MAAI,CAAC,MAAM;AACV,WAAO;AAAA,EACR;AAEA,QAAM,aAAY,UAAK,QAAL,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC1D,QAAM,YAAQ,YAAAA,WAAiB,WAAW,KAAK,QAAQ;AACvD,QAAM,MAAM,KAAK,YAAY,eAAe,KAAK,IAAI,OAAO,EAAE,KAAK,UAAU,CAAC;AAE9E,QAAM,OAAO,OAAO,MAAM,MAAM,GAAG,CAAC,CAAC;AACrC,QAAM,QAAQ,OAAO,MAAM,MAAM,GAAG,CAAC,CAAC;AACtC,QAAM,iBAAiB,KAAK,YAAY,iBAAiB,KAAK,IAAI,MAAM,OAAO,EAAE,KAAK,UAAU,CAAC;AACjG,QAAM,gBAAgB,KAAK,YAAY,KAAK,KAAK,IAAI,IAAI;AAEzD,SAAO;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,aAAa,KAAK;AAAA,IAClB,cAAc,IAAI;AAAA,IAClB,cAAc,KAAK,KAAI,SAAI,eAAJ,YAAkB,IAAG,SAAI,eAAJ,YAAkB,CAAC,KAAK;AAAA,IACpE,eAAe,IAAI;AAAA,IACnB,gBAAgB,IAAI;AAAA,IACpB,eAAe,KAAK,KAAK,UAAU,KAAK,EAAE,EAAE;AAAA,IAC5C,oBAAoB,eAAe;AAAA,IACnC,qBAAqB,eAAe;AAAA,IACpC,oBAAoB,gBAAgB,cAAc,YAAY,cAAc,YAAY;AAAA,EACzF;AACD;AAQA,eAAsB,oBAAoB,MAAiB,UAAuC;AAvOlG;AAwOC,QAAM,KAAK,SAAS,SAAS,MAAM;AACnC,QAAM,KAAK,SAAS,GAAG,EAAE,gBAAgB,SAAS,aAAa,IAAI;AACnE,QAAM,KAAK,SAAS,GAAG,EAAE,YAAY,SAAS,cAAc,IAAI;AAChE,QAAM,KAAK,SAAS,GAAG,EAAE,iBAAiB,SAAS,cAAc,IAAI;AACrE,QAAM,KAAK,SAAS,GAAG,EAAE,eAAc,cAAS,iBAAT,YAAyB,GAAG,IAAI;AACvE,QAAM,KAAK,SAAS,GAAG,EAAE,uBAAuB,SAAS,eAAe,IAAI;AAC5E,QAAM,KAAK,SAAS,GAAG,EAAE,wBAAwB,SAAS,gBAAgB,IAAI;AAC9E,QAAM,KAAK,SAAS,GAAG,EAAE,uBAAuB,SAAS,oBAAoB,IAAI;AACjF,QAAM,KAAK,SAAS,GAAG,EAAE,wBAAwB,SAAS,qBAAqB,IAAI;AACnF,QAAM,KAAK,SAAS,GAAG,EAAE,uBAAuB,SAAS,oBAAoB,IAAI;AACjF,QAAM,KAAK,SAAS,GAAG,EAAE,kBAAkB,SAAS,eAAe,IAAI;AACxE;AAaA,eAAsB,qBAAqB,MAMf;AAC3B,QAAM,YAA4B,CAAC;AACnC,aAAW,QAAQ,KAAK,MAAM,KAAK,EAAE,iBAAiB,KAAK,CAAC,GAAG;AAC9D,UAAM,kBAAkB,KAAK,MAAM,KAAK,EAAE;AAC1C,UAAM,WAAW,iBAAiB;AAAA,MACjC,aAAa,KAAK;AAAA,MAClB,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,KAAK,KAAK;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAU;AACd;AAAA,IACD;AACA,UAAM,oBAAoB,KAAK,MAAM,QAAQ;AAC7C,cAAU,KAAK,QAAQ;AAAA,EACxB;AACA,SAAO;AACR;AAaA,eAAsB,kBAAkB,MAAiB,QAAiC;AACzF,QAAM,KAAK,SAAS,MAAM;AAC1B,QAAM,aAAa,MAAM,SAAS,cAAc,8BAAY,YAAY,CAAC;AACzE,QAAM,aAAa,MAAM,IAAI,cAAc,8BAAY,eAAe,CAAC;AACvE,QAAM,aAAa,MAAM,GAAG,EAAE,gBAAgB,YAAY,8BAAY,aAAa,UAAU,WAAW,CAAC;AAGzG,QAAM;AAAA,IACL;AAAA,IACA,GAAG,EAAE;AAAA,IACL,YAAY,8BAAY,aAAa,WAAW,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,EAC1E;AACA,QAAM;AAAA,IACL;AAAA,IACA,GAAG,EAAE;AAAA,IACL,YAAY,8BAAY,cAAc,WAAW,mBAAmB;AAAA,EACrE;AACA,QAAM,aAAa,MAAM,GAAG,EAAE,cAAc,YAAY,8BAAY,WAAW,UAAU,YAAY,CAAC;AACtG,QAAM;AAAA,IACL;AAAA,IACA,GAAG,EAAE;AAAA,IACL,YAAY,8BAAY,oBAAoB,UAAU,SAAS,EAAE,MAAM,MAAM,CAAC;AAAA,EAC/E;AACA,QAAM;AAAA,IACL;AAAA,IACA,GAAG,EAAE;AAAA,IACL,YAAY,8BAAY,qBAAqB,UAAU,SAAS,EAAE,MAAM,MAAM,CAAC;AAAA,EAChF;AACA,QAAM;AAAA,IACL;AAAA,IACA,GAAG,EAAE;AAAA,IACL,YAAY,8BAAY,oBAAoB,UAAU,SAAS,EAAE,MAAM,MAAM,CAAC;AAAA,EAC/E;AACA,QAAM;AAAA,IACL;AAAA,IACA,GAAG,EAAE;AAAA,IACL,YAAY,8BAAY,qBAAqB,UAAU,SAAS,EAAE,MAAM,MAAM,CAAC;AAAA,EAChF;AACA,QAAM;AAAA,IACL;AAAA,IACA,GAAG,EAAE;AAAA,IACL,YAAY,8BAAY,oBAAoB,UAAU,SAAS,EAAE,MAAM,MAAM,CAAC;AAAA,EAC/E;AACA,QAAM,aAAa,MAAM,GAAG,EAAE,kBAAkB,YAAY,8BAAY,eAAe,UAAU,OAAO,CAAC;AACzG,SAAO;AACR;AAOA,eAAsB,oBAAoB,MAAgC;AACzE,QAAM,aAAa,MAAM,YAAY,cAAc,8BAAY,eAAe,CAAC;AAC/E,QAAM;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,YAAY,8BAAY,aAAa,UAAU,SAAS;AAAA,MACvD,OAAO;AAAA,IACR,CAAC;AAAA,EACF;AACA,QAAM;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,YAAY,8BAAY,OAAO,WAAW,UAAU;AAAA,MACnD,MAAM;AAAA,MACN,OAAO;AAAA,IACR,CAAC;AAAA,EACF;AACA,QAAM;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,YAAY,8BAAY,YAAY,WAAW,UAAU;AAAA,MACxD,MAAM;AAAA,MACN,OAAO;AAAA,IACR,CAAC;AAAA,EACF;AACA,QAAM;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,YAAY,8BAAY,YAAY,UAAU,QAAQ;AAAA,MACrD,OAAO;AAAA,IACR,CAAC;AAAA,EACF;AACA,QAAM,aAAa,MAAM,YAAY,QAAQ,YAAY,8BAAY,QAAQ,UAAU,QAAQ,EAAE,OAAO,KAAK,CAAC,CAAC;AAC/G,QAAM;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,YAAY,8BAAY,eAAe,WAAW,UAAU;AAAA,MAC3D,MAAM;AAAA,MACN,OAAO;AAAA,IACR,CAAC;AAAA,EACF;AACD;AAOA,eAAsB,iBAAiB,MAAgC;AACtE,QAAM,aAAa,MAAM,QAAQ,cAAc,8BAAY,WAAW,CAAC;AACvE,QAAM,aAAa,MAAM,gBAAgB,YAAY,8BAAY,SAAS,UAAU,MAAM,CAAC;AAC3F,QAAM,aAAa,MAAM,sBAAsB,YAAY,8BAAY,eAAe,UAAU,MAAM,CAAC;AACvG,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,8BAAY,aAAa,UAAU,SAAS,EAAE,MAAM,QAAQ,CAAC;AAAA,EAC1E;AACA,QAAM,aAAa,MAAM,kBAAkB,YAAY,8BAAY,WAAW,UAAU,MAAM,CAAC;AAC/F,QAAM,aAAa,MAAM,mBAAmB,YAAY,8BAAY,YAAY,UAAU,YAAY,CAAC;AACxG;AAOA,eAAsB,oBAAoB,MAAgC;AACzE,QAAM,aAAa,MAAM,WAAW,cAAc,8BAAY,cAAc,CAAC;AAC7E,QAAM,aAAa,MAAM,wBAAwB,YAAY,8BAAY,qBAAqB,UAAU,OAAO,CAAC;AAChH,QAAM,aAAa,MAAM,mBAAmB,YAAY,8BAAY,gBAAgB,UAAU,MAAM,CAAC;AACrG,QAAM,aAAa,MAAM,yBAAyB,YAAY,8BAAY,eAAe,UAAU,OAAO,CAAC;AAC3G,QAAM,aAAa,MAAM,qBAAqB,YAAY,8BAAY,kBAAkB,UAAU,YAAY,CAAC;AAChH;AAQO,SAAS,oBAAoB,WAA4C;AAC/E,QAAM,UAAU,UAAU,OAAO,cAAY,SAAS,YAAY;AAClE,SAAO;AAAA,IACN,cAAc,QAAQ;AAAA,IACtB,SAAS,QAAQ,IAAI,cAAY,SAAS,WAAW,EAAE,KAAK,IAAI;AAAA,IAChE,eAAe,UAAU,OAAO,CAAC,KAAK,aAAa,MAAM,SAAS,eAAe,CAAC;AAAA,IAClF,cAAc,UAAU;AAAA,MACvB,CAAC,QAAQ,aACR,SAAS,iBAAiB,SAAS,WAAW,QAAQ,SAAS,eAAe,UAC3E,SAAS,eACT;AAAA,MACJ;AAAA,IACD;AAAA,EACD;AACD;AAQA,eAAsB,uBAAuB,MAAiB,UAA0C;AA/bxG;AAgcC,QAAM,KAAK,SAAS,wBAAwB,SAAS,cAAc,IAAI;AACvE,QAAM,KAAK,SAAS,mBAAmB,SAAS,SAAS,IAAI;AAC7D,QAAM,KAAK,SAAS,yBAAyB,SAAS,eAAe,IAAI;AACzE,QAAM,KAAK,SAAS,sBAAqB,cAAS,iBAAT,YAAyB,GAAG,IAAI;AAC1E;AAOA,eAAsB,kBAAkB,MAAgC;AACvE,QAAM,aAAa,MAAM,UAAU,cAAc,8BAAY,aAAa,CAAC;AAC3E,QAAM,aAAa,MAAM,iBAAiB,YAAY,8BAAY,QAAQ,UAAU,YAAY,CAAC;AACjG,QAAM,aAAa,MAAM,mBAAmB,YAAY,8BAAY,UAAU,UAAU,MAAM,CAAC;AAC/F,QAAM,aAAa,MAAM,mBAAmB,YAAY,8BAAY,UAAU,UAAU,MAAM,CAAC;AAC/F,QAAM,aAAa,MAAM,wBAAwB,YAAY,8BAAY,eAAe,UAAU,MAAM,CAAC;AACzG,QAAM,aAAa,MAAM,qBAAqB,YAAY,8BAAY,YAAY,UAAU,MAAM,CAAC;AACpG;AAQA,eAAsB,qBAAqB,MAAiB,UAAwC;AACnG,QAAM,KAAK,SAAS,iBAAiB,SAAS,OAAO,IAAI;AACzD,QAAM,KAAK,SAAS,mBAAmB,SAAS,MAAM,IAAI;AAC1D,QAAM,KAAK,SAAS,mBAAmB,SAAS,UAAU,IAAI;AAC9D,QAAM,KAAK,SAAS,wBAAwB,SAAS,WAAW,IAAI;AACpE,QAAM,KAAK,SAAS,qBAAqB,SAAS,QAAQ,IAAI;AAC/D;",
6
6
  "names": ["resolveLocalDate"]
7
7
  }
package/io-package.json CHANGED
@@ -1,9 +1,35 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "time-tracker",
4
- "version": "0.2.1",
4
+ "version": "0.2.3",
5
5
  "nogit": true,
6
6
  "news": {
7
+ "0.2.3": {
8
+ "en": "fix: a corrected object definition reaches existing installations now — `ensureObject` merges the fields the adapter owns (`name`, `type`, `role`, `read`, `write`, `unit`) instead of only the name, so `commands.punchUserId` receives the role `level` on the next start (checker `E1011`)",
9
+ "de": "fix: eine korrigierte Objektdefinition erreicht jetzt auch bestehende Installationen — `ensureObject` mischt die adapter-eigenen Felder (`name`, `type`, `role`, `read`, `write`, `unit`) statt nur den Namen zusammen, deshalb erhält `commands.punchUserId` beim nächsten Start die Rolle `level` (Checker `E1011`)",
10
+ "ru": "исправление: исправленное определение объекта теперь доходит и до существующих установок — `ensureObject` объединяет поля, которыми владеет адаптер (`name`, `type`, `role`, `read`, `write`, `unit`), а не только имя, поэтому `commands.punchUserId` получит роль `level` при следующем запуске (проверка `E1011`)",
11
+ "pt": "correção: uma definição de objeto corrigida chega agora também às instalações existentes — `ensureObject` junta os campos do adaptador (`name`, `type`, `role`, `read`, `write`, `unit`) em vez de apenas o nome, por isso `commands.punchUserId` recebe a função `level` no próximo arranque (verificação `E1011`)",
12
+ "nl": "fix: een gecorrigeerde objectdefinitie bereikt nu ook bestaande installaties — `ensureObject` voegt de velden van de adapter samen (`name`, `type`, `role`, `read`, `write`, `unit`) in plaats van alleen de naam, daarom krijgt `commands.punchUserId` bij de volgende start de rol `level` (controle `E1011`)",
13
+ "fr": "correctif : une définition d'objet corrigée parvient désormais aussi aux installations existantes — `ensureObject` fusionne les champs propres à l'adaptateur (`name`, `type`, `role`, `read`, `write`, `unit`) au lieu du seul nom, `commands.punchUserId` reçoit donc le rôle `level` au prochain démarrage (contrôle `E1011`)",
14
+ "it": "correzione: una definizione di oggetto corretta raggiunge ora anche le installazioni esistenti — `ensureObject` unisce i campi dell'adattatore (`name`, `type`, `role`, `read`, `write`, `unit`) invece del solo nome, quindi `commands.punchUserId` riceve il ruolo `level` al prossimo avvio (controllo `E1011`)",
15
+ "es": "corrección: una definición de objeto corregida llega ahora también a las instalaciones existentes — `ensureObject` combina los campos propios del adaptador (`name`, `type`, `role`, `read`, `write`, `unit`) en lugar de solo el nombre, por eso `commands.punchUserId` recibe el rol `level` en el próximo arranque (comprobación `E1011`)",
16
+ "pl": "poprawka: skorygowana definicja obiektu dociera teraz także do istniejących instalacji — `ensureObject` scala pola należące do adaptera (`name`, `type`, `role`, `read`, `write`, `unit`), a nie tylko nazwę, dlatego `commands.punchUserId` otrzyma rolę `level` przy następnym starcie (kontrola `E1011`)",
17
+ "uk": "виправлення: виправлене визначення об'єкта тепер доходить і до наявних установок — `ensureObject` об'єднує поля, якими володіє адаптер (`name`, `type`, `role`, `read`, `write`, `unit`), а не лише назву, тому `commands.punchUserId` отримає роль `level` під час наступного запуску (перевірка `E1011`)",
18
+ "zh-cn": "修复:修正后的对象定义现在也会到达已有安装 —— `ensureObject` 合并适配器拥有的字段(`name`、`type`、`role`、`read`、`write`、`unit`),而不仅是名称,因此 `commands.punchUserId` 会在下次启动时获得角色 `level`(检查 `E1011`)"
19
+ },
20
+ "0.2.2": {
21
+ "en": "the object structure check is satisfied: every object name carries all eleven languages (`E6001`) and the employee-id command uses the role `level` instead of `value` (`E1011`). The names live in one place and existing installations receive them on the next start",
22
+ "de": "die Objektstruktur-Prüfung ist erfüllt: jeder Objektname trägt jetzt alle elf Sprachen (`E6001`) und der Mitarbeiter-Id-Befehl nutzt die Rolle `level` statt `value` (`E1011`). Die Namen liegen an einer Stelle, bestehende Installationen erhalten sie beim nächsten Start",
23
+ "ru": "проверка структуры объектов пройдена: каждое имя объекта теперь содержит все одиннадцать языков (`E6001`), а команда с идентификатором сотрудника использует роль `level` вместо `value` (`E1011`). Имена хранятся в одном месте, существующие установки получат их при следующем запуске",
24
+ "pt": "a verificação da estrutura dos objetos está satisfeita: cada nome de objeto passa a ter os onze idiomas (`E6001`) e o comando do ID do funcionário usa a função `level` em vez de `value` (`E1011`). Os nomes ficam num único lugar e as instalações existentes recebem-nos no próximo arranque",
25
+ "nl": "de objectstructuurcontrole is voldaan: elke objectnaam heeft nu alle elf talen (`E6001`) en de opdracht met het medewerker-id gebruikt de rol `level` in plaats van `value` (`E1011`). De namen staan op één plek en bestaande installaties krijgen ze bij de volgende start",
26
+ "fr": "le contrôle de la structure des objets est satisfait : chaque nom d'objet porte désormais les onze langues (`E6001`) et la commande d'identifiant d'employé utilise le rôle `level` au lieu de `value` (`E1011`). Les noms sont au même endroit et les installations existantes les reçoivent au prochain démarrage",
27
+ "it": "il controllo della struttura degli oggetti è soddisfatto: ogni nome di oggetto ora porta tutte e undici le lingue (`E6001`) e il comando con l'ID del dipendente usa il ruolo `level` invece di `value` (`E1011`). I nomi stanno in un unico posto e le installazioni esistenti li ricevono al prossimo avvio",
28
+ "es": "la comprobación de la estructura de objetos está satisfecha: cada nombre de objeto lleva ahora los once idiomas (`E6001`) y el comando del ID del empleado usa el rol `level` en lugar de `value` (`E1011`). Los nombres están en un solo lugar y las instalaciones existentes los reciben en el próximo arranque",
29
+ "pl": "kontrola struktury obiektów jest spełniona: każda nazwa obiektu ma teraz wszystkie jedenaście języków (`E6001`), a polecenie z identyfikatorem pracownika używa roli `level` zamiast `value` (`E1011`). Nazwy są w jednym miejscu, a istniejące instalacje otrzymają je przy następnym starcie",
30
+ "uk": "перевірку структури об'єктів пройдено: кожна назва об'єкта тепер містить усі одинадцять мов (`E6001`), а команда з ідентифікатором співробітника використовує роль `level` замість `value` (`E1011`). Назви лежать в одному місці, наявні установки отримають їх під час наступного запуску",
31
+ "zh-cn": "对象结构检查已满足:每个对象名称现在都包含全部十一种语言(`E6001`),员工 ID 命令使用角色 `level` 而不是 `value`(`E1011`)。名称集中在一个地方,现有安装会在下次启动时获得它们"
32
+ },
7
33
  "0.2.1": {
8
34
  "en": "`common.news` starts fresh after the rename: the new npm package `iobroker.time-tracker` only carries 0.2.0, so the entries of 0.1.3 to 0.1.9 are removed again — the repository checker reported them as `E2004` (“do not exist at NPM”). The release notes of those versions stay in the changelog",
9
35
  "de": "`common.news` beginnt nach der Umbenennung neu: das neue npm-Paket `iobroker.time-tracker` führt nur die 0.2.0, deshalb sind die Einträge 0.1.3 bis 0.1.9 wieder entfernt — der Repository-Checker meldete sie als `E2004` („do not exist at NPM“). Die Release-Notizen dieser Versionen bleiben im Changelog",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.time-tracker",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Time tracking (clock-in/out) for ioBroker with web app, badge terminal and reports",
5
5
  "author": {
6
6
  "name": "Alex",
package/www/sw.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sw.js","sources":["../../../../../../tmp/8426b5182483896588e7e821c3d0cc22/sw.js"],"sourcesContent":["import {clientsClaim as workbox_core_clientsClaim} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {registerRoute as workbox_routing_registerRoute} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-routing/registerRoute.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\nself.skipWaiting();\nworkbox_core_clientsClaim();\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"person.png\",\n \"revision\": \"771d3283ece4739e203e02aac535855e\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"45c88f7faf80a0e4c5539908dc6b94f2\"\n },\n {\n \"url\": \"icon-512.png\",\n \"revision\": \"d8e3715779f4cd7e67e1f82f215a2f22\"\n },\n {\n \"url\": \"icon-192.png\",\n \"revision\": \"940ef37caef09c52272ddab844b9ea9b\"\n },\n {\n \"url\": \"favicon.svg\",\n \"revision\": \"309e9efece69d60920618512ab9d57bf\"\n },\n {\n \"url\": \"assets/workbox-window.prod.es5-Bd17z0YL.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-QI3wrEvW.js\",\n \"revision\": null\n },\n {\n \"url\": \"icon-192.png\",\n \"revision\": \"940ef37caef09c52272ddab844b9ea9b\"\n },\n {\n \"url\": \"icon-512.png\",\n \"revision\": \"d8e3715779f4cd7e67e1f82f215a2f22\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"6f40f1ce0ce138d5af307fb0dbb1e6f9\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();workbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"index.html\"), {\n allowlist: [/^\\/$/], denylist: [/^\\/api\\//],}));\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL","allowlist","denylist"],"mappings":"inBAoBAA,KAAKC,cACLC,EAAAA,eAMAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,MAEd,CACED,IAAO,2BACPC,SAAY,MAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,qCAEb,CAAA,GACHC,EAAAA,wBAA2CC,EAAAA,cAA8B,IAAIC,EAAAA,gBAAgCC,0BAA2C,cAAe,CACrKC,UAAW,CAAC,QAAUC,SAAU,CAAC"}
1
+ {"version":3,"file":"sw.js","sources":["../../../../../../tmp/39b73fa92f9c5a66a2b842640534a590/sw.js"],"sourcesContent":["import {clientsClaim as workbox_core_clientsClaim} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {registerRoute as workbox_routing_registerRoute} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-routing/registerRoute.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/home/runner/work/ioBroker.time-tracker/ioBroker.time-tracker/src-pwa/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\nself.skipWaiting();\nworkbox_core_clientsClaim();\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"person.png\",\n \"revision\": \"771d3283ece4739e203e02aac535855e\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"45c88f7faf80a0e4c5539908dc6b94f2\"\n },\n {\n \"url\": \"icon-512.png\",\n \"revision\": \"d8e3715779f4cd7e67e1f82f215a2f22\"\n },\n {\n \"url\": \"icon-192.png\",\n \"revision\": \"940ef37caef09c52272ddab844b9ea9b\"\n },\n {\n \"url\": \"favicon.svg\",\n \"revision\": \"309e9efece69d60920618512ab9d57bf\"\n },\n {\n \"url\": \"assets/workbox-window.prod.es5-Bd17z0YL.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-QI3wrEvW.js\",\n \"revision\": null\n },\n {\n \"url\": \"icon-192.png\",\n \"revision\": \"940ef37caef09c52272ddab844b9ea9b\"\n },\n {\n \"url\": \"icon-512.png\",\n \"revision\": \"d8e3715779f4cd7e67e1f82f215a2f22\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"6f40f1ce0ce138d5af307fb0dbb1e6f9\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();workbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"index.html\"), {\n allowlist: [/^\\/$/], denylist: [/^\\/api\\//],}));\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL","allowlist","denylist"],"mappings":"inBAoBAA,KAAKC,cACLC,EAAAA,eAMAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,MAEd,CACED,IAAO,2BACPC,SAAY,MAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,qCAEb,CAAA,GACHC,EAAAA,wBAA2CC,EAAAA,cAA8B,IAAIC,EAAAA,gBAAgCC,0BAA2C,cAAe,CACrKC,UAAW,CAAC,QAAUC,SAAU,CAAC"}