@deveye/types 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/package.json +68 -0
  4. package/src/domain/audience.ts +549 -0
  5. package/src/domain/backup.ts +355 -0
  6. package/src/domain/credential.ts +55 -0
  7. package/src/domain/database.ts +467 -0
  8. package/src/domain/deploy.ts +231 -0
  9. package/src/domain/device.ts +172 -0
  10. package/src/domain/deviceFiles.ts +84 -0
  11. package/src/domain/deviceLogs.ts +82 -0
  12. package/src/domain/featureRegistry.ts +392 -0
  13. package/src/domain/finance.ts +477 -0
  14. package/src/domain/git.ts +419 -0
  15. package/src/domain/home.ts +314 -0
  16. package/src/domain/live.ts +272 -0
  17. package/src/domain/logs.ts +117 -0
  18. package/src/domain/mail.ts +394 -0
  19. package/src/domain/metrics.ts +127 -0
  20. package/src/domain/note.ts +202 -0
  21. package/src/domain/notifications.ts +268 -0
  22. package/src/domain/packages.ts +35 -0
  23. package/src/domain/password.ts +36 -0
  24. package/src/domain/presence.ts +21 -0
  25. package/src/domain/project.ts +168 -0
  26. package/src/domain/projectBoard.ts +130 -0
  27. package/src/domain/projectChat.ts +46 -0
  28. package/src/domain/projectHistory.ts +82 -0
  29. package/src/domain/projectLink.ts +87 -0
  30. package/src/domain/projectPlan.ts +68 -0
  31. package/src/domain/report.ts +492 -0
  32. package/src/domain/role.ts +8 -0
  33. package/src/domain/secrecy.ts +66 -0
  34. package/src/domain/sentinel.ts +623 -0
  35. package/src/domain/sharing.ts +186 -0
  36. package/src/domain/syncProtocol.ts +116 -0
  37. package/src/domain/twoFactor.ts +40 -0
  38. package/src/domain/uptime.ts +216 -0
  39. package/src/domain/user.ts +141 -0
  40. package/src/domain/workspace.ts +56 -0
  41. package/src/domain/workspaceRole.ts +251 -0
  42. package/src/features/admin.ts +112 -0
  43. package/src/features/audience.ts +275 -0
  44. package/src/features/backup.ts +230 -0
  45. package/src/features/database.ts +461 -0
  46. package/src/features/deploy.ts +245 -0
  47. package/src/features/device.ts +292 -0
  48. package/src/features/deviceFiles.ts +83 -0
  49. package/src/features/deviceLogs.ts +36 -0
  50. package/src/features/deviceTerminal.ts +57 -0
  51. package/src/features/finance.ts +360 -0
  52. package/src/features/git.ts +368 -0
  53. package/src/features/home.ts +32 -0
  54. package/src/features/live.ts +113 -0
  55. package/src/features/logs.ts +86 -0
  56. package/src/features/mail.ts +374 -0
  57. package/src/features/metrics.ts +185 -0
  58. package/src/features/note.ts +189 -0
  59. package/src/features/notify.ts +164 -0
  60. package/src/features/password.ts +67 -0
  61. package/src/features/project.ts +709 -0
  62. package/src/features/registry.ts +103 -0
  63. package/src/features/secrecy.ts +120 -0
  64. package/src/features/sentinel.ts +233 -0
  65. package/src/features/sharing.ts +79 -0
  66. package/src/features/twoFactor.ts +47 -0
  67. package/src/features/uptime.ts +186 -0
  68. package/src/features/user.ts +91 -0
  69. package/src/features/workspace.ts +200 -0
  70. package/src/http/auth.ts +94 -0
  71. package/src/http/device.ts +222 -0
  72. package/src/http/status.ts +45 -0
  73. package/src/index.ts +1700 -0
  74. package/src/protocol/agent.ts +1171 -0
  75. package/src/protocol/envelope.ts +46 -0
  76. package/src/protocol/error.ts +27 -0
  77. package/src/protocol/result.ts +17 -0
  78. package/src/protocol/version.ts +6 -0
  79. package/src/sdk/client-ambient.d.ts +238 -0
  80. package/src/sdk/client.ts +66 -0
  81. package/src/sdk/ids.ts +25 -0
  82. package/src/sdk/index.ts +11 -0
  83. package/src/sdk/manifest.ts +326 -0
  84. package/src/sdk/providers.ts +48 -0
  85. package/src/sdk/server.ts +378 -0
  86. package/src/sdk/testing.ts +179 -0
  87. package/src/utils/version.ts +28 -0
@@ -0,0 +1,477 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Finances: le grand livre d'un espace, pour un particulier comme pour une PME.
5
+ *
6
+ * ## Les montants sont des entiers de centimes
7
+ *
8
+ * Jamais un flottant, nulle part: ni en base, ni sur le fil, ni dans le client.
9
+ * `0.1 + 0.2 !== 0.3` est une curiosité amusante partout sauf sur un solde, où
10
+ * l'écart s'accumule silencieusement à chaque écriture jusqu'à ce que la somme
11
+ * des opérations ne retombe plus sur le solde affiché. Le formatage en devise
12
+ * est la toute dernière étape, faite à l'affichage seul.
13
+ *
14
+ * ## Les dates sont des jours, pas des instants
15
+ *
16
+ * Une opération appartient à un jour civil (`AAAA-MM-JJ`), pas à un instant.
17
+ * Un horodatage epoch se décalerait d'un fuseau à l'autre et ferait basculer une
18
+ * dépense du 31 janvier au 1er février selon qui la regarde, ce qui déplacerait
19
+ * un mois comptable entier. La colonne SQL est un `DATE`, et la chaîne voyage
20
+ * telle quelle.
21
+ *
22
+ * ## Ce qui est chiffré, et ce qui ne peut pas l'être
23
+ *
24
+ * Le chiffrement de DevEye est non déterministe: rien de ce sur quoi on agrège
25
+ * ne peut le traverser. Un solde, un budget et une répartition par catégorie
26
+ * sont des `SUM(...) GROUP BY`, donc les **nombres, dates et rattachements**
27
+ * restent en clair, et le **texte libre** (intitulé, tiers, note, nom de compte,
28
+ * nom de catégorie) est chiffré. C'est le même partage que l'audience, et pour
29
+ * la même raison: sans lui, calculer un solde imposerait de télécharger toutes
30
+ * les opérations depuis le début dans le navigateur.
31
+ */
32
+
33
+ /** Plafond d'un montant, en centimes: mille milliards d'unités. */
34
+ export const FINANCE_AMOUNT_MAX = 100_000_000_000_000;
35
+
36
+ export const FINANCE_LABEL_MAX_LENGTH = 160;
37
+ export const FINANCE_NAME_MAX_LENGTH = 80;
38
+ export const FINANCE_NOTE_MAX_LENGTH = 2_000;
39
+ export const FINANCE_COUNTERPARTY_MAX_LENGTH = 120;
40
+
41
+ /**
42
+ * Un montant, en centimes, toujours **positif**. Le sens (entrée ou sortie) est
43
+ * porté par le `kind` de l'opération et non par le signe: un montant signé
44
+ * laisse exister « une dépense de -30 € », qui est une recette écrite de
45
+ * travers, et oblige chaque écran à se demander ce qu'il regarde.
46
+ */
47
+ export const financeAmountSchema = z.number().int().nonnegative().max(FINANCE_AMOUNT_MAX);
48
+
49
+ /** Un solde, lui, est signé: un compte peut être à découvert. */
50
+ export const financeBalanceSchema = z
51
+ .number()
52
+ .int()
53
+ .min(-FINANCE_AMOUNT_MAX)
54
+ .max(FINANCE_AMOUNT_MAX);
55
+
56
+ /** Un jour civil, `AAAA-MM-JJ`. */
57
+ export const financeDateSchema = z
58
+ .string()
59
+ .regex(/^\d{4}-\d{2}-\d{2}$/, 'Date attendue au format AAAA-MM-JJ');
60
+
61
+ /** Un mois civil, `AAAA-MM`, tel que le rendent les séries du tableau de bord. */
62
+ export const financeMonthSchema = z.string().regex(/^\d{4}-\d{2}$/);
63
+
64
+ /**
65
+ * Palette nommée des comptes et des catégories, adossée aux jetons de thème
66
+ * `--finance-<nom>`. Nommée plutôt que libre en hexadécimal: la valeur stockée
67
+ * reste liée au thème, donc elle suit ses réglages au lieu de jurer avec eux le
68
+ * jour où la palette est retouchée. Élargir cet enum ajoute une couleur.
69
+ */
70
+ export const financeColorSchema = z.enum([
71
+ 'red',
72
+ 'orange',
73
+ 'yellow',
74
+ 'green',
75
+ 'blue',
76
+ 'indigo',
77
+ 'purple',
78
+ 'pink'
79
+ ]);
80
+ export type FinanceColor = z.infer<typeof financeColorSchema>;
81
+
82
+ export const FINANCE_COLORS = financeColorSchema.options;
83
+
84
+ /**
85
+ * Devise de l'espace, code ISO 4217. Une seule par espace, et c'est délibéré:
86
+ * le multidevise n'est pas un champ de plus mais un taux de change daté par
87
+ * opération, sans quoi tout total additionnerait des euros et des dollars.
88
+ */
89
+ export const financeCurrencySchema = z.string().regex(/^[A-Z]{3}$/);
90
+
91
+ /**
92
+ * Réglages de la feature pour l'espace.
93
+ *
94
+ * `vatEnabled` est le seul commutateur entre l'usage particulier et l'usage
95
+ * PME: il fait apparaître la TVA sur les opérations et le récapitulatif
96
+ * collectée / déductible du tableau de bord. Rien d'autre ne change, parce que
97
+ * rien d'autre n'a besoin de changer: un livre de comptes est le même objet des
98
+ * deux côtés.
99
+ */
100
+ export const financeConfigSchema = z.object({
101
+ currency: financeCurrencySchema,
102
+ vatEnabled: z.boolean()
103
+ });
104
+ export type FinanceConfig = z.infer<typeof financeConfigSchema>;
105
+
106
+ /**
107
+ * Nature d'un compte. Sert à deux choses seulement: l'icône de la carte, et le
108
+ * fait qu'une **épargne** soit comptée à part du disponible sur le tableau de
109
+ * bord (avoir 8 000 € dont 7 000 bloqués sur un livret n'est pas la même
110
+ * situation que 8 000 € sur un compte courant).
111
+ */
112
+ export const financeAccountKindSchema = z.enum([
113
+ 'checking',
114
+ 'savings',
115
+ 'cash',
116
+ 'card',
117
+ 'business',
118
+ 'other'
119
+ ]);
120
+ export type FinanceAccountKind = z.infer<typeof financeAccountKindSchema>;
121
+
122
+ /**
123
+ * Un compte, tel que le client le reçoit.
124
+ *
125
+ * Les trois soldes répondent à trois questions distinctes, et les confondre est
126
+ * la source d'erreur la plus courante d'un livre de comptes:
127
+ * - `balance`: ce qu'il y a aujourd'hui, opérations datées d'aujourd'hui ou
128
+ * d'avant comprises. C'est le solde, sans autre qualificatif.
129
+ * - `projected`: le même en tenant compte des opérations déjà saisies à une
130
+ * date future (un loyer prélevé le 5, saisi le 2).
131
+ * - `cleared`: seulement ce qui a été **pointé**, c'est-à-dire vu sur le relevé
132
+ * de la banque. C'est celui-là que l'on compare au relevé, et lui seul.
133
+ */
134
+ export const financeAccountSchema = z.object({
135
+ id: z.number().int().positive(),
136
+ name: z.string().max(FINANCE_NAME_MAX_LENGTH),
137
+ kind: financeAccountKindSchema,
138
+ color: financeColorSchema,
139
+ /** Solde de départ, avant toute opération enregistrée dans DevEye. */
140
+ initialBalance: financeBalanceSchema,
141
+ balance: financeBalanceSchema,
142
+ projected: financeBalanceSchema,
143
+ cleared: financeBalanceSchema,
144
+ /** Nombre d'opérations rattachées, toutes dates confondues. */
145
+ transactionCount: z.number().int().nonnegative(),
146
+ /** Un compte archivé sort des totaux et des sélecteurs, sans rien perdre. */
147
+ archived: z.boolean(),
148
+ note: z.string().max(FINANCE_NOTE_MAX_LENGTH),
149
+ sortOrder: z.number().int().nonnegative(),
150
+ created: z.number().int().nonnegative()
151
+ });
152
+ export type FinanceAccount = z.infer<typeof financeAccountSchema>;
153
+
154
+ /**
155
+ * Sens d'une catégorie. Une catégorie ne sert qu'un sens: « Salaire » ne classe
156
+ * pas une dépense, et proposer les deux dans un seul sélecteur transforme le
157
+ * choix en fouille.
158
+ */
159
+ export const financeFlowSchema = z.enum(['expense', 'income']);
160
+ export type FinanceFlow = z.infer<typeof financeFlowSchema>;
161
+
162
+ export const financeCategorySchema = z.object({
163
+ id: z.number().int().positive(),
164
+ name: z.string().max(FINANCE_NAME_MAX_LENGTH),
165
+ flow: financeFlowSchema,
166
+ color: financeColorSchema,
167
+ /** Classe d'icône (`icons.css`), sans le préfixe `icon-`. */
168
+ icon: z.string().max(40),
169
+ sortOrder: z.number().int().nonnegative()
170
+ });
171
+ export type FinanceCategory = z.infer<typeof financeCategorySchema>;
172
+
173
+ /**
174
+ * Nature d'une opération.
175
+ *
176
+ * Un **virement** est une seule ligne et non deux: il porte son compte de
177
+ * départ (`accountId`) et son compte d'arrivée (`transferAccountId`), et les
178
+ * deux soldes en tiennent compte. Le représenter par une paire de lignes
179
+ * obligerait à les garder cohérentes à chaque modification, et une paire à
180
+ * moitié supprimée ferait apparaître de l'argent.
181
+ */
182
+ export const financeTransactionKindSchema = z.enum(['expense', 'income', 'transfer']);
183
+ export type FinanceTransactionKind = z.infer<typeof financeTransactionKindSchema>;
184
+
185
+ export const financeTransactionSchema = z.object({
186
+ id: z.number().int().positive(),
187
+ accountId: z.number().int().positive(),
188
+ kind: financeTransactionKindSchema,
189
+ amount: financeAmountSchema,
190
+ date: financeDateSchema,
191
+ label: z.string().max(FINANCE_LABEL_MAX_LENGTH),
192
+ categoryId: z.number().int().positive().nullable(),
193
+ /** Le compte crédité, pour un virement seulement. */
194
+ transferAccountId: z.number().int().positive().nullable(),
195
+ /** Qui a été payé, ou qui a payé. Texte libre, chiffré. */
196
+ counterparty: z.string().max(FINANCE_COUNTERPARTY_MAX_LENGTH),
197
+ note: z.string().max(FINANCE_NOTE_MAX_LENGTH),
198
+ /**
199
+ * Part de TVA du montant, en centimes, ou `null` quand la question ne se
200
+ * pose pas. Le **taux** n'est pas stocké: il se déduit, et le stocker
201
+ * ouvrirait la porte à un couple taux / montant incohérent, que rien ne
202
+ * pourrait ensuite départager.
203
+ */
204
+ vatAmount: financeAmountSchema.nullable(),
205
+ /** Vue sur le relevé de la banque. C'est ce que compte `cleared`. */
206
+ cleared: z.boolean(),
207
+ /** L'échéance qui l'a engendrée, quand elle vient d'une échéance. */
208
+ recurringId: z.number().int().positive().nullable(),
209
+ created: z.number().int().nonnegative(),
210
+ updated: z.number().int().nonnegative()
211
+ });
212
+ export type FinanceTransaction = z.infer<typeof financeTransactionSchema>;
213
+
214
+ /** Périodicité d'un budget. */
215
+ export const financeBudgetPeriodSchema = z.enum(['monthly', 'quarterly', 'yearly']);
216
+ export type FinanceBudgetPeriod = z.infer<typeof financeBudgetPeriodSchema>;
217
+
218
+ /**
219
+ * Une enveloppe posée sur une catégorie.
220
+ *
221
+ * `spent` et `remaining` sont calculés pour la période **en cours** au moment de
222
+ * la lecture, jamais stockés: un budget est une règle, pas un compteur, et
223
+ * mémoriser le compteur le ferait diverger dès qu'une opération passée est
224
+ * corrigée.
225
+ */
226
+ export const financeBudgetSchema = z.object({
227
+ id: z.number().int().positive(),
228
+ categoryId: z.number().int().positive(),
229
+ amount: financeAmountSchema,
230
+ period: financeBudgetPeriodSchema,
231
+ /** Consommé sur la période en cours. */
232
+ spent: financeAmountSchema,
233
+ /** Ce qu'il reste. Négatif quand l'enveloppe est dépassée. */
234
+ remaining: financeBalanceSchema,
235
+ /** Premier jour de la période en cours, pour situer le calcul. */
236
+ periodStart: financeDateSchema,
237
+ /** Premier jour de la période suivante (borne exclue). */
238
+ periodEnd: financeDateSchema
239
+ });
240
+ export type FinanceBudget = z.infer<typeof financeBudgetSchema>;
241
+
242
+ /** Cadence d'une échéance. Combinée à `interval`: « tous les 2 mois ». */
243
+ export const financeFrequencySchema = z.enum(['weekly', 'monthly', 'quarterly', 'yearly']);
244
+ export type FinanceFrequency = z.infer<typeof financeFrequencySchema>;
245
+
246
+ /**
247
+ * Une opération qui revient: loyer, salaire, abonnement, échéance de prêt.
248
+ *
249
+ * `automatic` décide de ce qui se passe quand la date arrive:
250
+ * - vrai: l'opération est écrite d'elle-même à la première lecture qui suit,
251
+ * parce qu'un salaire tombe qu'on regarde ou non;
252
+ * - faux: elle est proposée, et attend un clic. C'est ce qu'on veut d'une
253
+ * dépense dont le montant varie (électricité), qu'on ne veut pas voir
254
+ * apparaître à un montant faux.
255
+ *
256
+ * Voir `postDueRecurring` côté serveur pour le mécanisme, qui est une
257
+ * matérialisation paresseuse et non une tâche de fond.
258
+ */
259
+ export const financeRecurringSchema = z.object({
260
+ id: z.number().int().positive(),
261
+ accountId: z.number().int().positive(),
262
+ kind: financeTransactionKindSchema,
263
+ amount: financeAmountSchema,
264
+ label: z.string().max(FINANCE_LABEL_MAX_LENGTH),
265
+ categoryId: z.number().int().positive().nullable(),
266
+ transferAccountId: z.number().int().positive().nullable(),
267
+ counterparty: z.string().max(FINANCE_COUNTERPARTY_MAX_LENGTH),
268
+ note: z.string().max(FINANCE_NOTE_MAX_LENGTH),
269
+ vatAmount: financeAmountSchema.nullable(),
270
+ frequency: financeFrequencySchema,
271
+ /** « Tous les N » de la cadence. 1 = à chaque fois. */
272
+ interval: z.number().int().positive().max(60),
273
+ /** Prochaine occurrence attendue. */
274
+ nextDate: financeDateSchema,
275
+ /** Dernier jour couvert, ou `null` pour sans fin. */
276
+ endDate: financeDateSchema.nullable(),
277
+ automatic: z.boolean(),
278
+ /** Suspendue: plus rien n'est écrit ni proposé, sans rien perdre. */
279
+ active: z.boolean(),
280
+ /** Date de la dernière occurrence effectivement écrite. */
281
+ lastPostedDate: financeDateSchema.nullable(),
282
+ created: z.number().int().nonnegative()
283
+ });
284
+ export type FinanceRecurring = z.infer<typeof financeRecurringSchema>;
285
+
286
+ /** Fenêtre d'analyse du tableau de bord. */
287
+ export const financeRangeSchema = z.enum(['month', 'quarter', 'year']);
288
+ export type FinanceRange = z.infer<typeof financeRangeSchema>;
289
+
290
+ /** Un mois de la frise entrées / sorties. */
291
+ export const financeMonthPointSchema = z.object({
292
+ month: financeMonthSchema,
293
+ income: financeAmountSchema,
294
+ expense: financeAmountSchema,
295
+ /** Solde cumulé de tous les comptes actifs à la fin de ce mois. */
296
+ balance: financeBalanceSchema
297
+ });
298
+ export type FinanceMonthPoint = z.infer<typeof financeMonthPointSchema>;
299
+
300
+ /** Une part de la répartition par catégorie sur la fenêtre. */
301
+ export const financeCategoryShareSchema = z.object({
302
+ /** `null` = les opérations sans catégorie, rassemblées. */
303
+ categoryId: z.number().int().positive().nullable(),
304
+ flow: financeFlowSchema,
305
+ amount: financeAmountSchema,
306
+ count: z.number().int().nonnegative()
307
+ });
308
+ export type FinanceCategoryShare = z.infer<typeof financeCategoryShareSchema>;
309
+
310
+ /** Une occurrence attendue, telle que l'annonce le tableau de bord. */
311
+ export const financeUpcomingSchema = z.object({
312
+ recurringId: z.number().int().positive(),
313
+ date: financeDateSchema,
314
+ label: z.string(),
315
+ kind: financeTransactionKindSchema,
316
+ amount: financeAmountSchema,
317
+ accountId: z.number().int().positive(),
318
+ categoryId: z.number().int().positive().nullable(),
319
+ automatic: z.boolean(),
320
+ /** L'échéance est en retard: sa date est déjà passée. */
321
+ overdue: z.boolean()
322
+ });
323
+ export type FinanceUpcoming = z.infer<typeof financeUpcomingSchema>;
324
+
325
+ /**
326
+ * Tout ce que montre le tableau de bord, en une réponse.
327
+ *
328
+ * Une seule commande et non six: ces chiffres se lisent ensemble et doivent
329
+ * être cohérents entre eux. Six allers-retours indépendants laisseraient un
330
+ * écran où le solde vient d'avant une écriture et la répartition d'après.
331
+ */
332
+ export const financeOverviewSchema = z.object({
333
+ currency: financeCurrencySchema,
334
+ /** Bornes de la fenêtre analysée (`to` exclu). */
335
+ from: financeDateSchema,
336
+ to: financeDateSchema,
337
+ /** Somme des soldes du jour, comptes archivés exclus. */
338
+ netBalance: financeBalanceSchema,
339
+ /** La part de `netBalance` posée sur des comptes d'épargne. */
340
+ savings: financeBalanceSchema,
341
+ /** `netBalance` en tenant compte des opérations déjà datées plus tard. */
342
+ projected: financeBalanceSchema,
343
+ income: financeAmountSchema,
344
+ expense: financeAmountSchema,
345
+ /** Entrées moins sorties sur la fenêtre. Négatif quand on a puisé. */
346
+ net: financeBalanceSchema,
347
+ /** Même fenêtre, décalée d'une période en arrière, pour la comparaison. */
348
+ previousIncome: financeAmountSchema,
349
+ previousExpense: financeAmountSchema,
350
+ months: z.array(financeMonthPointSchema),
351
+ categories: z.array(financeCategoryShareSchema),
352
+ budgets: z.array(financeBudgetSchema),
353
+ upcoming: z.array(financeUpcomingSchema),
354
+ /** Récapitulatif TVA sur la fenêtre, ou `null` hors mode entreprise. */
355
+ vat: z
356
+ .object({
357
+ collected: financeAmountSchema,
358
+ deductible: financeAmountSchema,
359
+ /** Collectée moins déductible: ce qui est dû (positif) ou à récupérer. */
360
+ due: financeBalanceSchema
361
+ })
362
+ .nullable()
363
+ });
364
+ export type FinanceOverview = z.infer<typeof financeOverviewSchema>;
365
+
366
+ /** Ce que lit la carte de l'accueil. Volontairement minuscule. */
367
+ export const financeSummarySchema = z.object({
368
+ currency: financeCurrencySchema,
369
+ balance: financeBalanceSchema,
370
+ /** Entrées et sorties du mois civil en cours. */
371
+ income: financeAmountSchema,
372
+ expense: financeAmountSchema,
373
+ accountCount: z.number().int().nonnegative()
374
+ });
375
+ export type FinanceSummary = z.infer<typeof financeSummarySchema>;
376
+
377
+ /* ------------------------------------------------------------------ *
378
+ * Lignes SQL (serveur uniquement)
379
+ * ------------------------------------------------------------------ */
380
+
381
+ export interface FinanceConfigRow {
382
+ workspace_id: number;
383
+ currency: string;
384
+ vat_enabled: number;
385
+ }
386
+
387
+ export interface FinanceAccountRow {
388
+ id: number;
389
+ workspace_id: number;
390
+ kind: FinanceAccountKind;
391
+ color: FinanceColor;
392
+ initial_balance: number;
393
+ archived: number;
394
+ sort_order: number;
395
+ /** `{ name, note }` chiffré, étage ouvert. */
396
+ content: string;
397
+ created: number;
398
+ }
399
+
400
+ /** Une ligne de compte accompagnée de ses soldes calculés par la requête. */
401
+ export interface FinanceAccountBalanceRow extends FinanceAccountRow {
402
+ balance: number;
403
+ projected: number;
404
+ cleared: number;
405
+ transaction_count: number;
406
+ }
407
+
408
+ export interface FinanceCategoryRow {
409
+ id: number;
410
+ workspace_id: number;
411
+ flow: FinanceFlow;
412
+ color: FinanceColor;
413
+ icon: string;
414
+ sort_order: number;
415
+ /** `{ name }` chiffré, étage ouvert. */
416
+ content: string;
417
+ created: number;
418
+ }
419
+
420
+ export interface FinanceTransactionRow {
421
+ id: number;
422
+ workspace_id: number;
423
+ account_id: number;
424
+ transfer_account_id: number | null;
425
+ category_id: number | null;
426
+ recurring_id: number | null;
427
+ kind: FinanceTransactionKind;
428
+ amount: number;
429
+ vat_amount: number | null;
430
+ /**
431
+ * `AAAA-MM-JJ`. La colonne est un vrai `DATE`, dont le pilote rendrait un
432
+ * objet `Date`: le dépôt la projette systématiquement par `DATE_FORMAT`,
433
+ * pour qu'aucun fuseau ne s'interpose entre la base et l'écran.
434
+ */
435
+ date: string;
436
+ cleared: number;
437
+ /** `{ label, counterparty, note }` chiffré, étage ouvert. */
438
+ content: string;
439
+ created: number;
440
+ updated: number;
441
+ }
442
+
443
+ export interface FinanceBudgetRow {
444
+ id: number;
445
+ workspace_id: number;
446
+ category_id: number;
447
+ amount: number;
448
+ period: FinanceBudgetPeriod;
449
+ created: number;
450
+ }
451
+
452
+ export interface FinanceRecurringRow {
453
+ id: number;
454
+ workspace_id: number;
455
+ account_id: number;
456
+ transfer_account_id: number | null;
457
+ category_id: number | null;
458
+ kind: FinanceTransactionKind;
459
+ amount: number;
460
+ vat_amount: number | null;
461
+ frequency: FinanceFrequency;
462
+ interval_count: number;
463
+ next_date: string;
464
+ /**
465
+ * Jour du mois de la série (1 à 31), `null` pour une cadence hebdomadaire.
466
+ * Dérivé de `next_date` à l'écriture, jamais fourni par le client: c'est ce
467
+ * qui empêche une échéance au 31 de dériver au 28 après un février.
468
+ */
469
+ anchor_day: number | null;
470
+ end_date: string | null;
471
+ last_posted_date: string | null;
472
+ automatic: number;
473
+ active: number;
474
+ /** `{ label, counterparty, note }` chiffré, étage ouvert. */
475
+ content: string;
476
+ created: number;
477
+ }