@opencxh/domain 1.275.0 → 1.277.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 (49) hide show
  1. package/dist/entities/activity/types.d.ts +5 -1
  2. package/dist/entities/ai-account/modality.d.ts +0 -2
  3. package/dist/entities/ai-account/vendors.d.ts +2 -7
  4. package/dist/entities/ai-message/types.d.ts +2 -0
  5. package/dist/entities/approval/decide-each.d.ts +16 -0
  6. package/dist/entities/approval/decide-each.test.d.ts +1 -0
  7. package/dist/entities/approval/index.d.ts +1 -0
  8. package/dist/entities/business-entity/types.d.ts +16 -7
  9. package/dist/entities/catalog/pricing.d.ts +12 -1
  10. package/dist/entities/catalog/types.d.ts +5 -0
  11. package/dist/entities/custom-field-def/types.d.ts +3 -3
  12. package/dist/entities/playbook/actor.d.ts +1 -12
  13. package/dist/entities/playbook/approval.d.ts +14 -0
  14. package/dist/entities/playbook/approval.test.d.ts +1 -0
  15. package/dist/entities/playbook/autonomy.d.ts +25 -0
  16. package/dist/entities/playbook/autonomy.test.d.ts +1 -0
  17. package/dist/entities/playbook/index.d.ts +2 -0
  18. package/dist/entities/playbook/labels.d.ts +1 -3
  19. package/dist/entities/playbook/types.d.ts +30 -38
  20. package/dist/entities/reaction/types.d.ts +6 -1
  21. package/dist/entities/rule/bind.d.ts +20 -5
  22. package/dist/entities/rule/outcome.d.ts +2 -0
  23. package/dist/entities/rule/trigger-source.d.ts +4 -4
  24. package/dist/entities/rule/types.d.ts +47 -4
  25. package/dist/entities/saved-view/index.d.ts +1 -0
  26. package/dist/entities/saved-view/types.d.ts +30 -0
  27. package/dist/entities/scope/actor.d.ts +0 -5
  28. package/dist/entities/sla/types.d.ts +1 -1
  29. package/dist/entities/transaction/convert.d.ts +16 -0
  30. package/dist/entities/transaction/document.d.ts +2 -0
  31. package/dist/entities/transaction/keys.d.ts +15 -0
  32. package/dist/entities/transaction/kinds.d.ts +25 -4
  33. package/dist/entities/transaction/payment-term.d.ts +0 -8
  34. package/dist/entities/transaction/types.d.ts +21 -1
  35. package/dist/entities/webhook/types.d.ts +7 -1
  36. package/dist/entities/work/index.d.ts +2 -0
  37. package/dist/entities/work/ladder.d.ts +3 -0
  38. package/dist/entities/work/recurrence.d.ts +26 -0
  39. package/dist/entities/work/recurrence.test.d.ts +1 -0
  40. package/dist/entities/work/types.d.ts +27 -7
  41. package/dist/entities/work/view.d.ts +27 -0
  42. package/dist/index.cjs +19 -19
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.js +1796 -1488
  45. package/dist/platform/ai-tools.d.ts +34 -15
  46. package/dist/platform/permission.d.ts +2 -2
  47. package/dist/platform/resource-source.d.ts +14 -0
  48. package/dist/platform/tool-verdict.d.ts +22 -9
  49. package/package.json +1 -1
@@ -13,8 +13,24 @@ export declare function isFrozen(transaction: Pick<Transaction, "issuedAt">): bo
13
13
  * Everything else is a `BadRequestError`. Whoever wants to change a sent quote gets v2.
14
14
  */
15
15
  export declare const FROZEN_WRITABLE_FIELDS: readonly (keyof Transaction)[];
16
+ /**
17
+ * What a save may set on a draft. `status` is not here: it moves through `issue` and the status
18
+ * route, which check the transition and announce it.
19
+ */
20
+ export declare const DRAFT_FIELDS: readonly ["companyId", "contactId", "dealItemId", "title", "reference", "currency", "taxOverrideKey", "introText", "termsText", "expiresAt", "deliveredAt", "periodFrom", "periodTo", "paymentTerm", "lines"];
21
+ /**
22
+ * The draft fields a save may empty, named in `clear`. A list and not `null` in the body:
23
+ * `invoke` strips `null`, so "empty this" never reaches the server any other way.
24
+ */
25
+ export declare const CLEARABLE_FIELDS: readonly ["contactId", "dealItemId", "title", "reference", "taxOverrideKey", "introText", "termsText", "expiresAt", "deliveredAt", "periodFrom", "periodTo"];
26
+ export type ClearableField = (typeof CLEARABLE_FIELDS)[number];
16
27
  /** The fields a draft carries over; the server owns id, organisation and author. */
17
28
  export type TransactionDraft = Omit<Transaction, "id" | "organizationId" | "createdBy" | "createdAt" | "updatedAt">;
29
+ /**
30
+ * Whether `source` may become a `kindKey`: offered, a step the source's kind allows, and for a
31
+ * correcting kind (a credit note) only from the issued document it corrects.
32
+ */
33
+ export declare function canConvert(source: Pick<Transaction, "kindKey" | "issuedAt">, kindKey: string): boolean;
18
34
  /**
19
35
  * The conversion: quote -> order -> invoice -> credit note, as one function.
20
36
  *
@@ -24,6 +24,8 @@ export interface TransactionContextSources {
24
24
  organizationName?: string;
25
25
  /** Who the recipient reads; drives which template row is picked. */
26
26
  locale?: string;
27
+ /** The number of the document a credit note corrects. */
28
+ creditedNumber?: string;
27
29
  }
28
30
  /**
29
31
  * The tokens: `{customer.name}`, `{quote.number}`, `{totals.gross}`.
@@ -12,6 +12,21 @@ export declare const PRODUCT_SCOPE_KIND = "product";
12
12
  /** `invoice:412`. The kind of a transaction *is* its kind key — no mapping table. */
13
13
  export declare function transactionScopeKey(kindKey: string, id: string): string;
14
14
  export declare function productScopeKey(id: string): string;
15
+ /**
16
+ * The shell path of a document, under the administration it belongs to.
17
+ *
18
+ * `fallbackEntityId` is for a row that predates administrations (`""` = the default one); without
19
+ * either there is no screen to point at, and no link beats a dead one.
20
+ */
21
+ export declare function transactionHref(row: {
22
+ id: string;
23
+ kindKey: string;
24
+ businessEntityId?: string;
25
+ }, fallbackEntityId?: string): string | undefined;
26
+ export declare function productHref(row: {
27
+ id: string;
28
+ businessEntityId?: string;
29
+ }, fallbackEntityId?: string): string | undefined;
15
30
  /** Is this scopeKey one of ours, and which id does it point at? */
16
31
  export declare function transactionIdFromScope(scopeKey: string): string | undefined;
17
32
  /**
@@ -13,8 +13,12 @@ import { TransactionStatus } from './types';
13
13
  */
14
14
  export interface TransactionKind {
15
15
  key: string;
16
- /** i18n key, not text. */
16
+ /** i18n key, not text. For a screen that has `t()`. */
17
17
  label: string;
18
+ /** Dutch, for what the server writes itself: an approval title, a related row, a card. */
19
+ name: string;
20
+ /** What the seeded template row is called, when the paper has another name than the kind. */
21
+ paperName?: string;
18
22
  /** Gets a number from a series when issued. */
19
23
  numbered: boolean;
20
24
  /** Invert amounts: a credit note is an invoice with a minus sign. */
@@ -35,6 +39,19 @@ export interface TransactionKind {
35
39
  * invoice or a credit note.
36
40
  */
37
41
  issuedStatus: TransactionStatus;
42
+ /**
43
+ * The answers a person may give after issuing, per status. `draft -> issuedStatus` is not in
44
+ * here: that move is `issue`, with its gate and its number. Walking back one step is allowed —
45
+ * a mis-click on "accepted" must not need a new version.
46
+ */
47
+ transitions: Partial<Record<TransactionStatus, readonly TransactionStatus[]>>;
48
+ /** What this kind may become through `convert`. A revision of the same kind is `version`. */
49
+ convertsTo: readonly string[];
50
+ /**
51
+ * The kind this one corrects. Made only from an issued document of that kind, which the paper
52
+ * names: a credit note without its invoice number is not a credit note.
53
+ */
54
+ credits?: string;
38
55
  }
39
56
  export declare const TRANSACTION_KINDS: readonly TransactionKind[];
40
57
  /**
@@ -45,9 +62,8 @@ export declare const TRANSACTION_KINDS: readonly TransactionKind[];
45
62
  * A product decision, like the kinds themselves — §12.4: *"transactiesoorten zijn van ons, niet
46
63
  * van de organisatie"*.
47
64
  *
48
- * `credit_note` is deliberately absent. Crediting an invoice is its own small feature — which
49
- * lines, partial credits, the reference back — and a kind you can create but not fill correctly is
50
- * worse than one you cannot create at all.
65
+ * A credit note credits one issued invoice, whole or in part: the lines come over negated and a
66
+ * person lowers or removes what is not credited.
51
67
  */
52
68
  export declare const ENABLED_TRANSACTION_KINDS: readonly string[];
53
69
  /** The kinds a reader can browse, one per route segment. A credit note files with the invoices. */
@@ -60,3 +76,8 @@ export declare function listedTransactionKinds(): TransactionKind[];
60
76
  * amounts on a guess is worse than showing a document with a strange label.
61
77
  */
62
78
  export declare function transactionKind(key: string): TransactionKind;
79
+ /** Dutch status names, for the same server-side readers as {@link TransactionKind.name}. */
80
+ export declare const STATUS_NAMES: Record<TransactionStatus, string>;
81
+ /** Where a person may move this document from its current status. Empty on a draft's issue. */
82
+ export declare function nextStatuses(kindKey: string, from: TransactionStatus): readonly TransactionStatus[];
83
+ export declare function canTransition(kindKey: string, from: TransactionStatus, to: TransactionStatus): boolean;
@@ -44,14 +44,6 @@ export interface PaymentTerm {
44
44
  * would make the answer depend on which timezone the server happened to be in.
45
45
  */
46
46
  export declare function dueDateFrom(issuedAt: number, dueDays: number): number;
47
- /**
48
- * The term that applies, out of the shared table and one administration's own.
49
- *
50
- * Shared rows first, then the administration's over them, by code — the same `shadowByKey` the VAT
51
- * table uses. Kept in domain rather than in the app because both the server and the screen have to
52
- * land on the same answer.
53
- */
54
- export declare function shadowTermsByCode(rows: readonly PaymentTerm[], businessEntityId?: string): PaymentTerm[];
55
47
  /**
56
48
  * The condition as it was copied onto a document.
57
49
  *
@@ -1,4 +1,7 @@
1
+ import { DocumentBlock } from '../../platform/document-blocks';
2
+ import { DocumentSender } from '../document-template/types';
1
3
  import { Cents } from '../money/money';
4
+ import { TaxRateKind } from '../money/tax';
2
5
  import { OwnerScope } from '../scope/types';
3
6
  import { TransactionPaymentTerm } from './payment-term';
4
7
  /**
@@ -95,6 +98,12 @@ export interface Transaction {
95
98
  expiresAt?: number;
96
99
  /** Only on a numbered kind, and only at the moment of issuing. */
97
100
  number?: string;
101
+ /**
102
+ * The paper as it went out: blocks and letterhead, filled at issue. A frozen document shows
103
+ * this and never re-renders — the customer's address, the sender's IBAN, a VAT rate and the
104
+ * template may all change afterwards, and an invoice must keep saying what it said.
105
+ */
106
+ issuedPaper?: IssuedPaper;
98
107
  /** Posted — to whichever set of books. Set by the push, never by a person. */
99
108
  postedAt?: number;
100
109
  /** The rendered PDF in `apps/storage`. A reference, never the content. */
@@ -126,7 +135,15 @@ export interface Transaction {
126
135
  * A union and not a free string: kinds and their statuses are **ours**, not the organisation's.
127
136
  * Labels follow from the key as `status_<key>`.
128
137
  */
129
- export type TransactionStatus = "draft" | "sent" | "accepted" | "rejected" | "expired" | "confirmed" | "delivered" | "open" | "paid" | "overdue" | "settled" | "cancelled";
138
+ export type TransactionStatus = "draft" | "sent" | "accepted" | "rejected" | "expired" | "confirmed" | "delivered" | "open" | "paid" | "overdue" | "settled" | "cancelled"
139
+ /** A newer version of this document went out. Set by the server, never by a person. */
140
+ | "superseded";
141
+ export interface IssuedPaper {
142
+ blocks: DocumentBlock[];
143
+ sender: DocumentSender;
144
+ templateId?: string;
145
+ customerName?: string;
146
+ }
130
147
  export interface TransactionLine {
131
148
  /** Stable within the transaction, so a version diff can follow a line. */
132
149
  id: string;
@@ -178,6 +195,9 @@ export interface TransactionTotals {
178
195
  /** Per rate, because that is what the invoice and the bookkeeping both need. */
179
196
  byRate: {
180
197
  taxRateKey: string;
198
+ /** As it was when priced. Absent on rows priced before it was stored. */
199
+ percent?: number;
200
+ kind?: TaxRateKind;
181
201
  netCents: Cents;
182
202
  taxCents: Cents;
183
203
  }[];
@@ -5,7 +5,13 @@
5
5
  */
6
6
  export type WebhookMethod = "POST" | "PUT";
7
7
  export type WebhookContentType = "json" | "multipart";
8
- export type WebhookTrigger = "interactions:created" | "interactions:updated" | "activities:created" | "activities:updated";
8
+ /**
9
+ * The bus events a webhook can listen to — full names, the same string as a rule's
10
+ * `Trigger.event.name`. Add one here and the automations app subscribes to it.
11
+ */
12
+ export declare const WEBHOOK_EVENTS: readonly ["communication:interactions:created", "communication:interactions:updated", "communication:activities:created", "communication:activities:updated"];
13
+ export type WebhookTrigger = (typeof WEBHOOK_EVENTS)[number];
14
+ export declare function isWebhookEvent(value: unknown): value is WebhookTrigger;
9
15
  export interface Webhook {
10
16
  id: string;
11
17
  organizationId: string;
@@ -4,3 +4,5 @@ export * from './item-types';
4
4
  export * from './keys';
5
5
  export * from './ladder';
6
6
  export * from './types';
7
+ export * from './view';
8
+ export * from './recurrence';
@@ -104,3 +104,6 @@ export declare function validateStatuses(statuses: readonly WorkStatus[]): Statu
104
104
  * move nobody can unblock.
105
105
  */
106
106
  export declare function statusRequiresApproval(statusKey: string, ladder: readonly WorkStatus[]): boolean;
107
+ /** How an item ended, read off its project's resolution flag. `undefined` = open or neither. */
108
+ export type WorkOutcome = "won" | "lost";
109
+ export declare function outcomeOf(resolution: string | undefined, project?: WorkProject | null): WorkOutcome | undefined;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * A repeating item: closing it makes the next one, the Asana "on completion" model. No schedule
3
+ * and no cron — the next occurrence exists the moment this one is done, so nothing can be missed
4
+ * by a job that did not run.
5
+ */
6
+ export interface WorkRecurrence {
7
+ every: "day" | "week" | "month";
8
+ /** Every `interval` units; 1 = every week, 2 = every other week. */
9
+ interval: number;
10
+ }
11
+ /** A recurrence as a body sent it, or `undefined` when it is not one. */
12
+ export declare function parseRecurrence(raw: unknown): WorkRecurrence | undefined;
13
+ /** `ms` moved on by one recurrence step, in local calendar terms (a month is a month). */
14
+ export declare function stepDate(ms: number, recurrence: WorkRecurrence): number;
15
+ /**
16
+ * The next occurrence's dates. From the old due date when it had one (a weekly report stays on
17
+ * Friday even when finished on Monday), else from when it was closed. The start keeps its
18
+ * distance to the due date.
19
+ */
20
+ export declare function nextOccurrenceDates(item: {
21
+ dueDate?: number;
22
+ startDate?: number;
23
+ }, recurrence: WorkRecurrence, closedAt: number): {
24
+ dueDate: number;
25
+ startDate?: number;
26
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,4 @@
1
+ import { WorkRecurrence } from './recurrence';
1
2
  import { Relation } from '../../platform/resource-source';
2
3
  import { OwnerScope } from '../scope/types';
3
4
  /**
@@ -61,15 +62,16 @@ export interface WorkStatus {
61
62
  /**
62
63
  * A resolution: *how* something ended, apart from where it sits.
63
64
  *
64
- * Deliberately a free label with no fixed meaning and no outcome flag. A law firm distinguishes
65
- * "settled" from "judgment", a sales team "won" from "lost", and neither fits an enum we invent.
66
- * The price is in the plan: nothing can compute how much ended well. If that question comes, a
67
- * `positive?: boolean` belongs here.
65
+ * A free label: a law firm distinguishes "settled" from "judgment", a sales team "won" from
66
+ * "lost", and neither fits an enum we invent. `positive` is the one meaning a query may read —
67
+ * whether it ended well — so a win rate never guesses which label means good.
68
68
  */
69
69
  export interface WorkResolution {
70
70
  key: string;
71
71
  label: string;
72
72
  order: number;
73
+ /** `true` ended well, `false` ended badly, absent says neither (postponed, transferred). */
74
+ positive?: boolean;
73
75
  }
74
76
  /**
75
77
  * An item kind: an icon with a label, never a workflow.
@@ -227,18 +229,32 @@ export interface WorkCycle {
227
229
  committedSeconds?: number;
228
230
  /** Written once, when the cycle is completed. See {@link WorkCycleSummary}. */
229
231
  summary?: WorkCycleSummary;
232
+ /** One point per day while it runs, for the burndown. See {@link WorkCycleDay}. */
233
+ series?: WorkCycleDay[];
230
234
  /** Ids of this cycle in source systems. Empty on one created here. */
231
235
  externalIds?: string[];
232
236
  createdBy: string;
233
237
  createdAt?: number;
234
238
  updatedAt?: number;
235
239
  }
240
+ /**
241
+ * Where a running cycle stood on one day. The hourly job overwrites today's point, so the last
242
+ * one of a day is what that day ended on; a day the job missed is simply absent (a gap, never an
243
+ * invented value). Embedded on the cycle: a sprint has a few dozen days, never thousands.
244
+ */
245
+ export interface WorkCycleDay {
246
+ /** Start of the day, epoch ms (UTC). */
247
+ day: number;
248
+ open: number;
249
+ openSeconds: number;
250
+ done: number;
251
+ }
236
252
  /**
237
253
  * What a cycle delivered, frozen at completion.
238
254
  *
239
- * One row written once, not a nightly snapshot: items move, so a burndown needs a daily series —
240
- * but "what did this team get done in the last eight cycles" needs eight rows and no rollup at
241
- * all. Compare against {@link WorkCycle.committedCount}, which was counted at the start.
255
+ * One row written once: "what did this team get done in the last eight cycles" needs eight rows
256
+ * and no rollup. The day-by-day view is {@link WorkCycle.series}. Compare against
257
+ * {@link WorkCycle.committedCount}, which was counted at the start.
242
258
  */
243
259
  export interface WorkCycleSummary {
244
260
  completed: number;
@@ -389,6 +405,10 @@ export interface WorkItem {
389
405
  dueDate?: number;
390
406
  /** Set as soon as the status moves to category `done`, cleared when it comes back. */
391
407
  closedAt?: number;
408
+ /** Closing makes the next one; see `WorkRecurrence`. */
409
+ recurrence?: WorkRecurrence;
410
+ /** The occurrence this one's closing made: set once, so a reopen-and-close makes no second. */
411
+ nextOccurrenceId?: string;
392
412
  estimateSeconds?: number;
393
413
  /**
394
414
  * Keys of the still-open items this one is `blocked_by`. **A read-time projection**, never
@@ -0,0 +1,27 @@
1
+ import { SavedView, SavedViewSort } from '../saved-view/types';
2
+ /**
3
+ * Work's saved view: a {@link SavedView} over work items, optionally pinned to one project.
4
+ * The filter keys are declared once, here; the filter bar, the server's cleaning and the
5
+ * stored shape all derive from these two lists, so a new filter is one edit, not four.
6
+ */
7
+ /** Multi-value filters: empty or absent = no filter on that axis. */
8
+ export declare const WORK_VIEW_LIST_FILTERS: readonly ["statusKeys", "typeKeys", "labels", "priority", "assignees"];
9
+ export type WorkViewListFilter = (typeof WORK_VIEW_LIST_FILTERS)[number];
10
+ /**
11
+ * On/off filters. `watchingOnly` and `reportedByMe` are about the viewer, so the server resolves
12
+ * them; the bar only shows `blockedOnly`.
13
+ */
14
+ export declare const WORK_VIEW_FLAGS: readonly ["blockedOnly", "watchingOnly", "reportedByMe"];
15
+ export type WorkViewFlag = (typeof WORK_VIEW_FLAGS)[number];
16
+ export type WorkViewFilters = {
17
+ search?: string;
18
+ } & Partial<Record<WorkViewListFilter, string[]>> & Partial<Record<WorkViewFlag, boolean>>;
19
+ export declare const WORK_SORT_FIELDS: readonly ["priority", "dueDate", "updatedAt", "createdAt", "title", "estimateSeconds"];
20
+ export type WorkSortField = (typeof WORK_SORT_FIELDS)[number];
21
+ export type WorkViewSort = SavedViewSort<WorkSortField>;
22
+ export declare const WORK_VIEW_LAYOUTS: readonly ["list", "board", "calendar", "workload"];
23
+ export type WorkViewLayout = (typeof WORK_VIEW_LAYOUTS)[number];
24
+ export type WorkView = SavedView<WorkViewFilters, WorkViewLayout, WorkSortField> & {
25
+ /** Pinned to one project; absent = across everything the viewer can see. */
26
+ projectId?: string;
27
+ };