@kohost/api-client 7.15.0 → 7.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/commands/getGroups.d.ts +8 -0
- package/dist/commands/getGroups.js +17 -0
- package/dist/commands/getGroups.js.map +1 -0
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.js +3 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/httpClient.js.map +1 -1
- package/dist/lib/emergencyContacts.d.ts +10 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +3 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/sis.d.ts +108 -0
- package/dist/lib/sis.js +11 -0
- package/dist/lib/sis.js.map +1 -0
- package/dist/models/entity.js.map +1 -1
- package/dist/models/group.js +1 -0
- package/dist/models/group.js.map +1 -1
- package/dist/models/system.js +1 -0
- package/dist/models/system.js.map +1 -1
- package/dist/models/systemUser.js +1 -1
- package/dist/models/systemUser.js.map +1 -1
- package/dist/models/ticket.js +2 -0
- package/dist/models/ticket.js.map +1 -1
- package/dist/schemas/announcement.d.ts +16 -1
- package/dist/schemas/announcement.js +16 -1
- package/dist/schemas/announcement.js.map +1 -1
- package/dist/schemas/bill.d.ts +25 -0
- package/dist/schemas/bill.js +25 -0
- package/dist/schemas/bill.js.map +1 -1
- package/dist/schemas/costEntry.d.ts +27 -0
- package/dist/schemas/costEntry.js +36 -21
- package/dist/schemas/costEntry.js.map +1 -1
- package/dist/schemas/definitions.d.ts +96 -3
- package/dist/schemas/definitions.js +58 -3
- package/dist/schemas/definitions.js.map +1 -1
- package/dist/schemas/group.d.ts +4 -0
- package/dist/schemas/group.js +4 -0
- package/dist/schemas/group.js.map +1 -1
- package/dist/schemas/system.d.ts +4 -0
- package/dist/schemas/system.js +4 -0
- package/dist/schemas/system.js.map +1 -1
- package/dist/schemas/systemUser.d.ts +2 -3
- package/dist/schemas/systemUser.js +1 -4
- package/dist/schemas/systemUser.js.map +1 -1
- package/dist/schemas/ticket.d.ts +232 -48
- package/dist/schemas/ticket.js +213 -12
- package/dist/schemas/ticket.js.map +1 -1
- package/dist/useCases/clearAwaitingResponse.d.ts +36 -0
- package/dist/useCases/clearAwaitingResponse.js +47 -0
- package/dist/useCases/clearAwaitingResponse.js.map +1 -0
- package/dist/useCases/clearWorkItemVerification.d.ts +39 -0
- package/dist/useCases/clearWorkItemVerification.js +47 -0
- package/dist/useCases/clearWorkItemVerification.js.map +1 -0
- package/dist/useCases/describeConciergeBillsSummary.d.ts +27 -0
- package/dist/useCases/describeConciergeBillsSummary.js +47 -0
- package/dist/useCases/describeConciergeBillsSummary.js.map +1 -0
- package/dist/useCases/describeConciergeStageCounts.d.ts +27 -0
- package/dist/useCases/describeConciergeStageCounts.js +47 -0
- package/dist/useCases/describeConciergeStageCounts.js.map +1 -0
- package/dist/useCases/describeSISSync.d.ts +27 -0
- package/dist/useCases/describeSISSync.js +47 -0
- package/dist/useCases/describeSISSync.js.map +1 -0
- package/dist/useCases/index.d.ts +12 -0
- package/dist/useCases/index.js +25 -1
- package/dist/useCases/index.js.map +1 -1
- package/dist/useCases/listConciergeWorkspaceBillLines.d.ts +27 -0
- package/dist/useCases/listConciergeWorkspaceBillLines.js +47 -0
- package/dist/useCases/listConciergeWorkspaceBillLines.js.map +1 -0
- package/dist/useCases/listSISHouseholds.d.ts +27 -0
- package/dist/useCases/listSISHouseholds.js +47 -0
- package/dist/useCases/listSISHouseholds.js.map +1 -0
- package/dist/useCases/listSISPeople.d.ts +27 -0
- package/dist/useCases/listSISPeople.js +47 -0
- package/dist/useCases/listSISPeople.js.map +1 -0
- package/dist/useCases/previewAnnouncement.d.ts +27 -0
- package/dist/useCases/previewAnnouncement.js +47 -0
- package/dist/useCases/previewAnnouncement.js.map +1 -0
- package/dist/useCases/setAwaitingResponse.d.ts +36 -0
- package/dist/useCases/setAwaitingResponse.js +47 -0
- package/dist/useCases/setAwaitingResponse.js.map +1 -0
- package/dist/useCases/syncSISRoster.d.ts +27 -0
- package/dist/useCases/syncSISRoster.js +47 -0
- package/dist/useCases/syncSISRoster.js.map +1 -0
- package/dist/useCases/verifyWorkItem.d.ts +39 -0
- package/dist/useCases/verifyWorkItem.js +47 -0
- package/dist/useCases/verifyWorkItem.js.map +1 -0
- package/package.json +5 -5
package/dist/schemas/bill.d.ts
CHANGED
|
@@ -120,6 +120,16 @@ export declare const billSchema: {
|
|
|
120
120
|
readonly default: null;
|
|
121
121
|
readonly description: string;
|
|
122
122
|
};
|
|
123
|
+
readonly propertyId: {
|
|
124
|
+
readonly type: readonly ["string", "null"];
|
|
125
|
+
readonly default: null;
|
|
126
|
+
readonly description: string;
|
|
127
|
+
};
|
|
128
|
+
readonly ticketNumber: {
|
|
129
|
+
readonly type: readonly ["string", "null"];
|
|
130
|
+
readonly default: null;
|
|
131
|
+
readonly description: string;
|
|
132
|
+
};
|
|
123
133
|
readonly categoryId: {
|
|
124
134
|
readonly type: readonly ["string", "null"];
|
|
125
135
|
readonly default: null;
|
|
@@ -151,6 +161,21 @@ export declare const billSchema: {
|
|
|
151
161
|
readonly default: null;
|
|
152
162
|
readonly description: string;
|
|
153
163
|
};
|
|
164
|
+
readonly vendorCost: {
|
|
165
|
+
readonly type: readonly ["integer", "null"];
|
|
166
|
+
readonly default: null;
|
|
167
|
+
readonly description: string;
|
|
168
|
+
};
|
|
169
|
+
readonly vendorId: {
|
|
170
|
+
readonly type: readonly ["string", "null"];
|
|
171
|
+
readonly default: null;
|
|
172
|
+
readonly description: string;
|
|
173
|
+
};
|
|
174
|
+
readonly hasActual: {
|
|
175
|
+
readonly type: "boolean";
|
|
176
|
+
readonly default: false;
|
|
177
|
+
readonly description: string;
|
|
178
|
+
};
|
|
154
179
|
readonly taxable: {
|
|
155
180
|
readonly type: "boolean";
|
|
156
181
|
readonly default: false;
|
package/dist/schemas/bill.js
CHANGED
|
@@ -121,6 +121,16 @@ const billSchema = {
|
|
|
121
121
|
default: null,
|
|
122
122
|
description: "The ID of the claimed cost entry: an entry within the ticket on a `ticket` line, a costs-collection document on an `adhoc` one."
|
|
123
123
|
},
|
|
124
|
+
propertyId: {
|
|
125
|
+
type: ["string", "null"],
|
|
126
|
+
default: null,
|
|
127
|
+
description: "The property the claimed entry belongs to, snapshotted at mark-sent: the source ticket's property on a `ticket` line, the ad hoc entry's attributed property on an `adhoc` one. Lets a cross-organization reader reach the ticket's property scope without a ticket read. Internal, redacted org-side."
|
|
128
|
+
},
|
|
129
|
+
ticketNumber: {
|
|
130
|
+
type: ["string", "null"],
|
|
131
|
+
default: null,
|
|
132
|
+
description: "The source ticket's number, snapshotted at mark-sent. Null on an `adhoc` line. Internal, redacted org-side."
|
|
133
|
+
},
|
|
124
134
|
categoryId: {
|
|
125
135
|
type: ["string", "null"],
|
|
126
136
|
default: null,
|
|
@@ -152,6 +162,21 @@ const billSchema = {
|
|
|
152
162
|
default: null,
|
|
153
163
|
description: "The line description, snapshotted at mark-sent. Null while drafting, when it live-reads from the cost entry."
|
|
154
164
|
},
|
|
165
|
+
vendorCost: {
|
|
166
|
+
type: ["integer", "null"],
|
|
167
|
+
default: null,
|
|
168
|
+
description: "What the claimed entry costs Kohost in integer cents, snapshotted at mark-sent: the vendor actual when recorded, else the estimate. Null while drafting or when the entry carries neither. Re-patched when a late actual lands. Internal, redacted org-side."
|
|
169
|
+
},
|
|
170
|
+
vendorId: {
|
|
171
|
+
type: ["string", "null"],
|
|
172
|
+
default: null,
|
|
173
|
+
description: "The org-scoped Vendor named on the claimed entry, snapshotted at mark-sent. Internal, redacted org-side."
|
|
174
|
+
},
|
|
175
|
+
hasActual: {
|
|
176
|
+
type: "boolean",
|
|
177
|
+
default: false,
|
|
178
|
+
description: "Whether `vendorCost` is the vendor's settled actual rather than the estimate, snapshotted at mark-sent and re-patched when the actual lands. Internal, redacted org-side."
|
|
179
|
+
},
|
|
155
180
|
taxable: {
|
|
156
181
|
type: "boolean",
|
|
157
182
|
default: false,
|
package/dist/schemas/bill.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bill.js","names":[],"sources":["../../.generated/schemas/bill.ts"],"sourcesContent":["import defs, { ISODateString } from \"./definitions\";\nimport type { FromSchema } from \"json-schema-to-ts\";\nimport { mediaFileSchema } from \"./mediaFile\";\n\n// One bill line is a discriminated union on `type`, so `lines.items` is their\n// `oneOf`. The two branches are disjoint via the `type` const plus\n// `additionalProperties: false`, so a line validates against exactly one.\n//\n// A cost line always names its entry by `costId`; `source` says which\n// collection to look it up in. A `ticket` line resolves through\n// `(ticketId, costId)`, an `adhoc` line reads `costId` straight off the costs\n// collection with `ticketId` null. The claim path is what pairs the two, since\n// JSON Schema cannot state the pairing without splitting the branch and\n// breaking the `type` discriminator every reader keys off.\n//\n// While the bill is a draft the line carries only the reference, the picked\n// `categoryId`, and any draft-time adjustment; the customer-facing `amount`,\n// `description`, and `categoryName` are live-read from the claimed entry and\n// snapshotted onto the line at mark-sent. The billed amount is the marked-up\n// actual (or the `adjustedAmount` override, floored at zero) — vendor truth on\n// the entry is never touched.\nconst costLineSchema = {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"type\"],\n properties: {\n id: {\n type: \"string\",\n description: \"Server-minted ID of the bill line.\",\n },\n type: {\n type: \"string\",\n enum: [\"cost\"],\n description: \"Discriminator: a line drawn from a recorded cost entry.\",\n },\n source: {\n type: \"string\",\n enum: [\"ticket\", \"adhoc\"],\n default: \"ticket\",\n description:\n \"Where the claimed cost entry lives, and therefore how `costId` \" +\n \"resolves: on a ticket, or in the costs collection.\",\n },\n ticketId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The ID of the ticket the claimed cost entry lives on. Null on an \" +\n \"`adhoc` line, which no ticket carries.\",\n },\n costId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The ID of the claimed cost entry: an entry within the ticket on a \" +\n \"`ticket` line, a costs-collection document on an `adhoc` one.\",\n },\n categoryId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The picked billing category, inherited from the claimed cost entry \" +\n \"when the claim does not name one. Optional while drafting, required \" +\n \"at mark-sent. Manual pick — never derived from the ticket's issue.\",\n },\n categoryName: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The category name snapshotted at mark-sent. Null while drafting, \" +\n \"when it live-reads from the category library.\",\n },\n adjustedAmount: {\n type: [\"integer\", \"null\"],\n minimum: 0,\n default: null,\n description:\n \"Optional draft-time override of the billed amount in integer cents, \" +\n \"floored at zero, replacing the marked-up actual at display and \" +\n \"snapshot. Requires `adjustmentReason`. A credit (below zero) is a \" +\n \"manual line instead.\",\n },\n adjustmentReason: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Short required reason accompanying `adjustedAmount`, kept for the \" +\n \"internal record.\",\n },\n amount: {\n type: [\"integer\", \"null\"],\n default: null,\n description:\n \"The billed amount in integer cents, snapshotted at mark-sent. Null \" +\n \"while drafting, when it live-reads (marked-up actual or the \" +\n \"adjustment) from the cost entry.\",\n },\n description: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The line description, snapshotted at mark-sent. Null while drafting, \" +\n \"when it live-reads from the cost entry.\",\n },\n taxable: {\n type: \"boolean\",\n default: false,\n description:\n \"Whether the line's amount joins the bill's taxable subtotal. \" +\n \"Customer-facing: locks at mark-sent.\",\n },\n },\n} as const;\n\n// A manual line is a literal customer-facing row with no markup math: a\n// `description` and `amount` (which may be negative, serving as a credit) and\n// an optional `propertyId`. The independent internal fields — informational\n// `cost` (never derives the amount), `vendorId`, the vendor-invoice file, and\n// `vendorInvoiceNumber` — are redacted org-side via `canSeeCostSplit` and stay\n// editable in any bill state.\nconst manualLineSchema = {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"type\", \"description\", \"amount\"],\n properties: {\n id: {\n type: \"string\",\n description: \"Server-minted ID of the bill line.\",\n },\n type: {\n type: \"string\",\n enum: [\"manual\"],\n description: \"Discriminator: a literal, non-ticket line.\",\n },\n description: {\n type: \"string\",\n minLength: 1,\n description: \"The literal customer-facing description.\",\n },\n amount: {\n type: \"integer\",\n description:\n \"The billed amount in integer cents. May be negative, serving as a \" +\n \"credit (reference the reason in the description).\",\n },\n propertyId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The property the manual line is attributed to, when it concerns one.\",\n },\n categoryId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The picked billing category. Optional while drafting, required at \" +\n \"mark-sent.\",\n },\n categoryName: {\n type: [\"string\", \"null\"],\n default: null,\n description: \"The category name snapshotted at mark-sent.\",\n },\n cost: {\n type: [\"integer\", \"null\"],\n default: null,\n description:\n \"Informational internal vendor cost in integer cents. Never derives \" +\n \"the amount. Redacted org-side.\",\n },\n vendorId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Optional reference to the org-scoped Vendor. Internal, redacted \" +\n \"org-side.\",\n },\n vendorInvoice: {\n anyOf: [{ $ref: \"mediaFile.json\" }, { type: \"null\" }],\n default: null,\n description:\n \"The vendor's invoice file backing the line, mirroring the cost-entry \" +\n \"field. Internal, redacted org-side.\",\n },\n vendorInvoiceNumber: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The vendor's own invoice number. Internal, redacted org-side.\",\n },\n taxable: {\n type: \"boolean\",\n default: false,\n description:\n \"Whether the line's amount joins the bill's taxable subtotal. \" +\n \"Customer-facing: locks at mark-sent.\",\n },\n },\n} as const;\n\nexport const billSchema = {\n $schema: \"http://json-schema.org/draft-07/schema\",\n $id: \"bill.json\",\n title: \"Bill\",\n description:\n \"A OneBill bill, stored platform-wide and stamped with its organization: \" +\n \"KFC staff assemble billed lines from the \" +\n \"uninvoiced cost pool (plus manual lines) into a draft, then mark it sent \" +\n \"to freeze and reveal it to the customer. Lifecycle draft → sent → paid, \" +\n \"plus void. Customers see a bill in-app only once sent.\",\n type: \"object\",\n required: [\"id\", \"organizationId\", \"status\", \"currency\", \"lines\"],\n additionalProperties: false,\n properties: {\n id: {\n $ref: \"definitions.json#/definitions/id\",\n },\n type: {\n type: \"string\",\n enum: [\"bill\"],\n default: \"bill\",\n },\n organizationId: {\n type: \"string\",\n description:\n \"The organization the bill invoices. Bills live in one admin-database \" +\n \"collection across every organization, so each carries its owner \" +\n \"explicitly — stamped from the request context at creation, never \" +\n \"client-supplied.\",\n },\n status: {\n type: \"string\",\n enum: [\"draft\", \"sent\", \"paid\", \"void\"],\n default: \"draft\",\n description:\n \"Lifecycle state. `sent` freezes customer-facing fields and reveals \" +\n \"the bill to the org; `paid` records manual payment; `void` releases \" +\n \"cost-entry claims and hides the bill from the org view. Drafts \" +\n \"hard-delete rather than voiding.\",\n },\n invoiceNumber: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Kohost's own invoice number, `KB-<n>` from a single global sequence. \" +\n \"System-assigned at mark-sent and never entered by hand: null while \" +\n \"the bill is a draft, immutable once set. A wrong bill is corrected \" +\n \"by void-and-reissue, so numbers gap and are never reused.\",\n },\n period: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n 'Display-only month label (e.g. \"July 2026\"). A UI hint; the bill\\'s ' +\n \"membership is defined by its lines, not a calendar bucket.\",\n },\n currency: {\n type: \"string\",\n enum: [\"USD\"],\n default: \"USD\",\n description: \"ISO 4217 currency code. USD only in v1.\",\n },\n fileId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The generated bill PDF's media-file ID, minted atomically at \" +\n \"mark-sent.\",\n },\n fileUrl: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The generated bill PDF's file-store URL, snapshotted at mark-sent \" +\n \"alongside fileId. Held so the sent-bill surface and the sent \" +\n \"notification email can mint a signed, unauthenticated download link \" +\n \"without a file lookup. Unsigned on its own (a bare link 401s).\",\n },\n memo: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Internal KFC-only note. Never customer-facing; editable in any state.\",\n },\n billingAddress: {\n anyOf: [\n { $ref: \"definitions.json#/definitions/address\" },\n { type: \"null\" },\n ],\n default: null,\n description:\n \"The org billing address snapshotted at mark-sent. Null while \" +\n \"drafting, when it live-reads from the Organization. Mark-sent \" +\n \"requires a complete address (line1, city, state, postalCode).\",\n },\n taxRate: {\n type: [\"number\", \"null\"],\n default: null,\n minimum: 0,\n description:\n \"Tax rate as a plain float percent applied to the taxable line \" +\n \"subtotal. While drafting, null means the platform default rate; the \" +\n \"effective rate is snapshotted at mark-sent.\",\n },\n taxExempt: {\n type: \"boolean\",\n default: false,\n description:\n \"The organization's tax exemption snapshotted at mark-sent. While \" +\n \"drafting it live-reads from the Organization.\",\n },\n shippingAmount: {\n type: [\"integer\", \"null\"],\n default: null,\n minimum: 0,\n description:\n \"Shipping & handling in integer cents, added to the grand total on \" +\n \"top of the line subtotal and tax. Null means none.\",\n },\n lines: {\n type: \"array\",\n default: [],\n description:\n \"The bill's lines: cost lines claimed from the uninvoiced pool and \" +\n \"literal manual lines.\",\n items: {\n oneOf: [costLineSchema, manualLineSchema],\n },\n },\n sentAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the bill was marked sent. Absent until sent.\",\n },\n paidAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the bill was marked paid. Absent until paid.\",\n },\n voidedAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the bill was voided. Absent unless voided.\",\n },\n createdAt: {\n $ref: \"definitions.json#/definitions/date\",\n },\n updatedAt: {\n $ref: \"definitions.json#/definitions/date\",\n },\n },\n} as const;\n\nexport type BillSchema = FromSchema<\n typeof billSchema,\n {\n references: [typeof defs, typeof mediaFileSchema];\n deserialize: [\n {\n pattern: {\n format: \"date-time\";\n };\n output: Date | ISODateString;\n },\n ];\n }\n>;\n\n/** One line on a bill: a cost line or a manual line. */\nexport type BillLine = NonNullable<BillSchema[\"lines\"]>[number];\n"],"mappings":"AAwMA,MAAa,aAAa;CACxB,SAAS;CACT,KAAK;CACL,OAAO;CACP,aACE;CAKF,MAAM;CACN,UAAU;EAAC;EAAM;EAAkB;EAAU;EAAY;CAAO;CAChE,sBAAsB;CACtB,YAAY;EACV,IAAI,EACF,MAAM,mCACR;EACA,MAAM;GACJ,MAAM;GACN,MAAM,CAAC,MAAM;GACb,SAAS;EACX;EACA,gBAAgB;GACd,MAAM;GACN,aACE;EAIJ;EACA,QAAQ;GACN,MAAM;GACN,MAAM;IAAC;IAAS;IAAQ;IAAQ;GAAM;GACtC,SAAS;GACT,aACE;EAIJ;EACA,eAAe;GACb,MAAM,CAAC,UAAU,MAAM;GACvB,SAAS;GACT,aACE;EAIJ;EACA,QAAQ;GACN,MAAM,CAAC,UAAU,MAAM;GACvB,SAAS;GACT,aACE;EAEJ;EACA,UAAU;GACR,MAAM;GACN,MAAM,CAAC,KAAK;GACZ,SAAS;GACT,aAAa;EACf;EACA,QAAQ;GACN,MAAM,CAAC,UAAU,MAAM;GACvB,SAAS;GACT,aACE;EAEJ;EACA,SAAS;GACP,MAAM,CAAC,UAAU,MAAM;GACvB,SAAS;GACT,aACE;EAIJ;EACA,MAAM;GACJ,MAAM,CAAC,UAAU,MAAM;GACvB,SAAS;GACT,aACE;EACJ;EACA,gBAAgB;GACd,OAAO,CACL,EAAE,MAAM,wCAAwC,GAChD,EAAE,MAAM,OAAO,CACjB;GACA,SAAS;GACT,aACE;EAGJ;EACA,SAAS;GACP,MAAM,CAAC,UAAU,MAAM;GACvB,SAAS;GACT,SAAS;GACT,aACE;EAGJ;EACA,WAAW;GACT,MAAM;GACN,SAAS;GACT,aACE;EAEJ;EACA,gBAAgB;GACd,MAAM,CAAC,WAAW,MAAM;GACxB,SAAS;GACT,SAAS;GACT,aACE;EAEJ;EACA,OAAO;GACL,MAAM;GACN,SAAS,CAAC;GACV,aACE;GAEF,OAAO,EACL,OAAO,CAAC;IAhTd,MAAM;IACN,sBAAsB;IACtB,UAAU,CAAC,MAAM,MAAM;IACvB,YAAY;KACV,IAAI;MACF,MAAM;MACN,aAAa;KACf;KACA,MAAM;MACJ,MAAM;MACN,MAAM,CAAC,MAAM;MACb,aAAa;KACf;KACA,QAAQ;MACN,MAAM;MACN,MAAM,CAAC,UAAU,OAAO;MACxB,SAAS;MACT,aACE;KAEJ;KACA,UAAU;MACR,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KAEJ;KACA,QAAQ;MACN,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KAEJ;KACA,YAAY;MACV,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KAGJ;KACA,cAAc;MACZ,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KAEJ;KACA,gBAAgB;MACd,MAAM,CAAC,WAAW,MAAM;MACxB,SAAS;MACT,SAAS;MACT,aACE;KAIJ;KACA,kBAAkB;MAChB,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KAEJ;KACA,QAAQ;MACN,MAAM,CAAC,WAAW,MAAM;MACxB,SAAS;MACT,aACE;KAGJ;KACA,aAAa;MACX,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KAEJ;KACA,SAAS;MACP,MAAM;MACN,SAAS;MACT,aACE;KAEJ;IACF;GAuNc,GAAgB;IA7M9B,MAAM;IACN,sBAAsB;IACtB,UAAU;KAAC;KAAM;KAAQ;KAAe;IAAQ;IAChD,YAAY;KACV,IAAI;MACF,MAAM;MACN,aAAa;KACf;KACA,MAAM;MACJ,MAAM;MACN,MAAM,CAAC,QAAQ;MACf,aAAa;KACf;KACA,aAAa;MACX,MAAM;MACN,WAAW;MACX,aAAa;KACf;KACA,QAAQ;MACN,MAAM;MACN,aACE;KAEJ;KACA,YAAY;MACV,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KACJ;KACA,YAAY;MACV,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KAEJ;KACA,cAAc;MACZ,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aAAa;KACf;KACA,MAAM;MACJ,MAAM,CAAC,WAAW,MAAM;MACxB,SAAS;MACT,aACE;KAEJ;KACA,UAAU;MACR,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KAEJ;KACA,eAAe;MACb,OAAO,CAAC,EAAE,MAAM,iBAAiB,GAAG,EAAE,MAAM,OAAO,CAAC;MACpD,SAAS;MACT,aACE;KAEJ;KACA,qBAAqB;MACnB,MAAM,CAAC,UAAU,MAAM;MACvB,SAAS;MACT,aACE;KACJ;KACA,SAAS;MACP,MAAM;MACN,SAAS;MACT,aACE;KAEJ;IACF;GAiI8B,CAAgB,EAC1C;EACF;EACA,QAAQ;GACN,MAAM;GACN,aAAa;EACf;EACA,QAAQ;GACN,MAAM;GACN,aAAa;EACf;EACA,UAAU;GACR,MAAM;GACN,aAAa;EACf;EACA,WAAW,EACT,MAAM,qCACR;EACA,WAAW,EACT,MAAM,qCACR;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"bill.js","names":[],"sources":["../../.generated/schemas/bill.ts"],"sourcesContent":["import defs, { ISODateString } from \"./definitions\";\nimport type { FromSchema } from \"json-schema-to-ts\";\nimport { mediaFileSchema } from \"./mediaFile\";\n\n// One bill line is a discriminated union on `type`, so `lines.items` is their\n// `oneOf`. The two branches are disjoint via the `type` const plus\n// `additionalProperties: false`, so a line validates against exactly one.\n//\n// A cost line always names its entry by `costId`; `source` says which\n// collection to look it up in. A `ticket` line resolves through\n// `(ticketId, costId)`, an `adhoc` line reads `costId` straight off the costs\n// collection with `ticketId` null. The claim path is what pairs the two, since\n// JSON Schema cannot state the pairing without splitting the branch and\n// breaking the `type` discriminator every reader keys off.\n//\n// While the bill is a draft the line carries only the reference, the picked\n// `categoryId`, and any draft-time adjustment; the customer-facing `amount`,\n// `description`, and `categoryName` are live-read from the claimed entry and\n// snapshotted onto the line at mark-sent. The billed amount is the marked-up\n// actual (or the `adjustedAmount` override, floored at zero) — vendor truth on\n// the entry is never touched.\n//\n// `vendorCost`, `vendorId` and `hasActual` are a derived snapshot of that\n// vendor truth, written at mark-sent beside `amount` and re-patched when a\n// late actual lands on the claimed entry, so the transactions view and period\n// margin read one collection. `propertyId` and `ticketNumber` are snapshotted\n// beside them so that reader can address the source ticket's property without\n// resolving the ticket. The entry stays the source of truth; the vendor\n// invoice number and files are read live from it, never snapshotted.\nconst costLineSchema = {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"type\"],\n properties: {\n id: {\n type: \"string\",\n description: \"Server-minted ID of the bill line.\",\n },\n type: {\n type: \"string\",\n enum: [\"cost\"],\n description: \"Discriminator: a line drawn from a recorded cost entry.\",\n },\n source: {\n type: \"string\",\n enum: [\"ticket\", \"adhoc\"],\n default: \"ticket\",\n description:\n \"Where the claimed cost entry lives, and therefore how `costId` \" +\n \"resolves: on a ticket, or in the costs collection.\",\n },\n ticketId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The ID of the ticket the claimed cost entry lives on. Null on an \" +\n \"`adhoc` line, which no ticket carries.\",\n },\n costId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The ID of the claimed cost entry: an entry within the ticket on a \" +\n \"`ticket` line, a costs-collection document on an `adhoc` one.\",\n },\n propertyId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The property the claimed entry belongs to, snapshotted at \" +\n \"mark-sent: the source ticket's property on a `ticket` line, the \" +\n \"ad hoc entry's attributed property on an `adhoc` one. Lets a \" +\n \"cross-organization reader reach the ticket's property scope \" +\n \"without a ticket read. Internal, redacted org-side.\",\n },\n ticketNumber: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The source ticket's number, snapshotted at mark-sent. Null on an \" +\n \"`adhoc` line. Internal, redacted org-side.\",\n },\n categoryId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The picked billing category, inherited from the claimed cost entry \" +\n \"when the claim does not name one. Optional while drafting, required \" +\n \"at mark-sent. Manual pick — never derived from the ticket's issue.\",\n },\n categoryName: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The category name snapshotted at mark-sent. Null while drafting, \" +\n \"when it live-reads from the category library.\",\n },\n adjustedAmount: {\n type: [\"integer\", \"null\"],\n minimum: 0,\n default: null,\n description:\n \"Optional draft-time override of the billed amount in integer cents, \" +\n \"floored at zero, replacing the marked-up actual at display and \" +\n \"snapshot. Requires `adjustmentReason`. A credit (below zero) is a \" +\n \"manual line instead.\",\n },\n adjustmentReason: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Short required reason accompanying `adjustedAmount`, kept for the \" +\n \"internal record.\",\n },\n amount: {\n type: [\"integer\", \"null\"],\n default: null,\n description:\n \"The billed amount in integer cents, snapshotted at mark-sent. Null \" +\n \"while drafting, when it live-reads (marked-up actual or the \" +\n \"adjustment) from the cost entry.\",\n },\n description: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The line description, snapshotted at mark-sent. Null while drafting, \" +\n \"when it live-reads from the cost entry.\",\n },\n vendorCost: {\n type: [\"integer\", \"null\"],\n default: null,\n description:\n \"What the claimed entry costs Kohost in integer cents, snapshotted \" +\n \"at mark-sent: the vendor actual when recorded, else the estimate. \" +\n \"Null while drafting or when the entry carries neither. Re-patched \" +\n \"when a late actual lands. Internal, redacted org-side.\",\n },\n vendorId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The org-scoped Vendor named on the claimed entry, snapshotted at \" +\n \"mark-sent. Internal, redacted org-side.\",\n },\n hasActual: {\n type: \"boolean\",\n default: false,\n description:\n \"Whether `vendorCost` is the vendor's settled actual rather than the \" +\n \"estimate, snapshotted at mark-sent and re-patched when the actual \" +\n \"lands. Internal, redacted org-side.\",\n },\n taxable: {\n type: \"boolean\",\n default: false,\n description:\n \"Whether the line's amount joins the bill's taxable subtotal. \" +\n \"Customer-facing: locks at mark-sent.\",\n },\n },\n} as const;\n\n// A manual line is a literal customer-facing row with no markup math: a\n// `description` and `amount` (which may be negative, serving as a credit) and\n// an optional `propertyId`. The independent internal fields — informational\n// `cost` (never derives the amount), `vendorId`, the vendor-invoice file, and\n// `vendorInvoiceNumber` — are redacted org-side via `canSeeCostSplit` and stay\n// editable in any bill state.\nconst manualLineSchema = {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"type\", \"description\", \"amount\"],\n properties: {\n id: {\n type: \"string\",\n description: \"Server-minted ID of the bill line.\",\n },\n type: {\n type: \"string\",\n enum: [\"manual\"],\n description: \"Discriminator: a literal, non-ticket line.\",\n },\n description: {\n type: \"string\",\n minLength: 1,\n description: \"The literal customer-facing description.\",\n },\n amount: {\n type: \"integer\",\n description:\n \"The billed amount in integer cents. May be negative, serving as a \" +\n \"credit (reference the reason in the description).\",\n },\n propertyId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The property the manual line is attributed to, when it concerns one.\",\n },\n categoryId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The picked billing category. Optional while drafting, required at \" +\n \"mark-sent.\",\n },\n categoryName: {\n type: [\"string\", \"null\"],\n default: null,\n description: \"The category name snapshotted at mark-sent.\",\n },\n cost: {\n type: [\"integer\", \"null\"],\n default: null,\n description:\n \"Informational internal vendor cost in integer cents. Never derives \" +\n \"the amount. Redacted org-side.\",\n },\n vendorId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Optional reference to the org-scoped Vendor. Internal, redacted \" +\n \"org-side.\",\n },\n vendorInvoice: {\n anyOf: [{ $ref: \"mediaFile.json\" }, { type: \"null\" }],\n default: null,\n description:\n \"The vendor's invoice file backing the line, mirroring the cost-entry \" +\n \"field. Internal, redacted org-side.\",\n },\n vendorInvoiceNumber: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The vendor's own invoice number. Internal, redacted org-side.\",\n },\n taxable: {\n type: \"boolean\",\n default: false,\n description:\n \"Whether the line's amount joins the bill's taxable subtotal. \" +\n \"Customer-facing: locks at mark-sent.\",\n },\n },\n} as const;\n\nexport const billSchema = {\n $schema: \"http://json-schema.org/draft-07/schema\",\n $id: \"bill.json\",\n title: \"Bill\",\n description:\n \"A OneBill bill, stored platform-wide and stamped with its organization: \" +\n \"KFC staff assemble billed lines from the \" +\n \"uninvoiced cost pool (plus manual lines) into a draft, then mark it sent \" +\n \"to freeze and reveal it to the customer. Lifecycle draft → sent → paid, \" +\n \"plus void. Customers see a bill in-app only once sent.\",\n type: \"object\",\n required: [\"id\", \"organizationId\", \"status\", \"currency\", \"lines\"],\n additionalProperties: false,\n properties: {\n id: {\n $ref: \"definitions.json#/definitions/id\",\n },\n type: {\n type: \"string\",\n enum: [\"bill\"],\n default: \"bill\",\n },\n organizationId: {\n type: \"string\",\n description:\n \"The organization the bill invoices. Bills live in one admin-database \" +\n \"collection across every organization, so each carries its owner \" +\n \"explicitly — stamped from the request context at creation, never \" +\n \"client-supplied.\",\n },\n status: {\n type: \"string\",\n enum: [\"draft\", \"sent\", \"paid\", \"void\"],\n default: \"draft\",\n description:\n \"Lifecycle state. `sent` freezes customer-facing fields and reveals \" +\n \"the bill to the org; `paid` records manual payment; `void` releases \" +\n \"cost-entry claims and hides the bill from the org view. Drafts \" +\n \"hard-delete rather than voiding.\",\n },\n invoiceNumber: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Kohost's own invoice number, `KB-<n>` from a single global sequence. \" +\n \"System-assigned at mark-sent and never entered by hand: null while \" +\n \"the bill is a draft, immutable once set. A wrong bill is corrected \" +\n \"by void-and-reissue, so numbers gap and are never reused.\",\n },\n period: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n 'Display-only month label (e.g. \"July 2026\"). A UI hint; the bill\\'s ' +\n \"membership is defined by its lines, not a calendar bucket.\",\n },\n currency: {\n type: \"string\",\n enum: [\"USD\"],\n default: \"USD\",\n description: \"ISO 4217 currency code. USD only in v1.\",\n },\n fileId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The generated bill PDF's media-file ID, minted atomically at \" +\n \"mark-sent.\",\n },\n fileUrl: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The generated bill PDF's file-store URL, snapshotted at mark-sent \" +\n \"alongside fileId. Held so the sent-bill surface and the sent \" +\n \"notification email can mint a signed, unauthenticated download link \" +\n \"without a file lookup. Unsigned on its own (a bare link 401s).\",\n },\n memo: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Internal KFC-only note. Never customer-facing; editable in any state.\",\n },\n billingAddress: {\n anyOf: [\n { $ref: \"definitions.json#/definitions/address\" },\n { type: \"null\" },\n ],\n default: null,\n description:\n \"The org billing address snapshotted at mark-sent. Null while \" +\n \"drafting, when it live-reads from the Organization. Mark-sent \" +\n \"requires a complete address (line1, city, state, postalCode).\",\n },\n taxRate: {\n type: [\"number\", \"null\"],\n default: null,\n minimum: 0,\n description:\n \"Tax rate as a plain float percent applied to the taxable line \" +\n \"subtotal. While drafting, null means the platform default rate; the \" +\n \"effective rate is snapshotted at mark-sent.\",\n },\n taxExempt: {\n type: \"boolean\",\n default: false,\n description:\n \"The organization's tax exemption snapshotted at mark-sent. While \" +\n \"drafting it live-reads from the Organization.\",\n },\n shippingAmount: {\n type: [\"integer\", \"null\"],\n default: null,\n minimum: 0,\n description:\n \"Shipping & handling in integer cents, added to the grand total on \" +\n \"top of the line subtotal and tax. Null means none.\",\n },\n lines: {\n type: \"array\",\n default: [],\n description:\n \"The bill's lines: cost lines claimed from the uninvoiced pool and \" +\n \"literal manual lines.\",\n items: {\n oneOf: [costLineSchema, manualLineSchema],\n },\n },\n sentAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the bill was marked sent. Absent until sent.\",\n },\n paidAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the bill was marked paid. Absent until paid.\",\n },\n voidedAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the bill was voided. Absent unless voided.\",\n },\n createdAt: {\n $ref: \"definitions.json#/definitions/date\",\n },\n updatedAt: {\n $ref: \"definitions.json#/definitions/date\",\n },\n },\n} as const;\n\nexport type BillSchema = FromSchema<\n typeof billSchema,\n {\n references: [typeof defs, typeof mediaFileSchema];\n deserialize: [\n {\n pattern: {\n format: \"date-time\";\n };\n output: Date | ISODateString;\n },\n ];\n }\n>;\n\n/** One line on a bill: a cost line or a manual line. */\nexport type BillLine = NonNullable<BillSchema[\"lines\"]>[number];\n"],"mappings":"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"}
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The same phase on a host that admits a Pending cost, where `null` means the
|
|
3
|
+
* amount is not known yet. Only the ticket cost entry takes this shape: a
|
|
4
|
+
* ticket is what a vendor quote is awaited on.
|
|
5
|
+
*/
|
|
6
|
+
export declare const nullableMoney: (description: string) => {
|
|
7
|
+
readonly type: readonly ["object", "null"];
|
|
8
|
+
readonly additionalProperties: false;
|
|
9
|
+
readonly required: readonly ["amount", "recordedBy", "recordedAt"];
|
|
10
|
+
readonly default: null;
|
|
11
|
+
readonly description: string;
|
|
12
|
+
readonly properties: {
|
|
13
|
+
readonly amount: {
|
|
14
|
+
readonly type: "integer";
|
|
15
|
+
readonly minimum: 0;
|
|
16
|
+
readonly description: "The amount in integer cents.";
|
|
17
|
+
};
|
|
18
|
+
readonly recordedBy: {
|
|
19
|
+
readonly type: "string";
|
|
20
|
+
readonly description: "The ID of the user who recorded the amount.";
|
|
21
|
+
};
|
|
22
|
+
readonly recordedAt: {
|
|
23
|
+
readonly $ref: "definitions.json#/definitions/date";
|
|
24
|
+
readonly description: "When the amount was recorded.";
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
};
|
|
1
28
|
/**
|
|
2
29
|
* The append-only billing review history, over whichever actions the host
|
|
3
30
|
* admits. A ticket cost can be voided (withdrawn from the customer); a
|
|
@@ -1,28 +1,43 @@
|
|
|
1
1
|
//#region .generated/schemas/costEntry.ts
|
|
2
|
+
const moneyProperties = {
|
|
3
|
+
amount: {
|
|
4
|
+
type: "integer",
|
|
5
|
+
minimum: 0,
|
|
6
|
+
description: "The amount in integer cents."
|
|
7
|
+
},
|
|
8
|
+
recordedBy: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "The ID of the user who recorded the amount."
|
|
11
|
+
},
|
|
12
|
+
recordedAt: {
|
|
13
|
+
$ref: "definitions.json#/definitions/date",
|
|
14
|
+
description: "When the amount was recorded."
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const moneyRequired = [
|
|
18
|
+
"amount",
|
|
19
|
+
"recordedBy",
|
|
20
|
+
"recordedAt"
|
|
21
|
+
];
|
|
2
22
|
const money = (description) => ({
|
|
3
23
|
type: "object",
|
|
4
24
|
additionalProperties: false,
|
|
5
|
-
required:
|
|
6
|
-
"amount",
|
|
7
|
-
"recordedBy",
|
|
8
|
-
"recordedAt"
|
|
9
|
-
],
|
|
25
|
+
required: moneyRequired,
|
|
10
26
|
description,
|
|
11
|
-
properties:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
27
|
+
properties: moneyProperties
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* The same phase on a host that admits a Pending cost, where `null` means the
|
|
31
|
+
* amount is not known yet. Only the ticket cost entry takes this shape: a
|
|
32
|
+
* ticket is what a vendor quote is awaited on.
|
|
33
|
+
*/
|
|
34
|
+
const nullableMoney = (description) => ({
|
|
35
|
+
type: ["object", "null"],
|
|
36
|
+
additionalProperties: false,
|
|
37
|
+
required: moneyRequired,
|
|
38
|
+
default: null,
|
|
39
|
+
description,
|
|
40
|
+
properties: moneyProperties
|
|
26
41
|
});
|
|
27
42
|
/**
|
|
28
43
|
* The append-only billing review history, over whichever actions the host
|
|
@@ -157,6 +172,6 @@ const costEntryProperties = {
|
|
|
157
172
|
])
|
|
158
173
|
};
|
|
159
174
|
//#endregion
|
|
160
|
-
export { costBillingReview, costEntryProperties, costEntryRequired };
|
|
175
|
+
export { costBillingReview, costEntryProperties, costEntryRequired, nullableMoney };
|
|
161
176
|
|
|
162
177
|
//# sourceMappingURL=costEntry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"costEntry.js","names":[],"sources":["../../.generated/schemas/costEntry.ts"],"sourcesContent":["// The cost-entry core: the money shape and reconciliation lifecycle every\n// OneBill cost carries, whether a Ticket embeds it or it stands alone in the\n// costs collection. Both hosts spread these consts into their own `properties`\n// and `required` rather than `$ref`-ing this file: draft-07 resolves `allOf`\n// against `additionalProperties: false` per subschema, so a composed entry\n// would reject every field the other half declared, and `FromSchema` derives\n// nothing useful from a reference it cannot inline.\n//\n// Nothing here is exported with a name ending in \"Schema\" and the model\n// generator skips this file by name (`scripts/generate-source-models.js`):\n// these are fragments, not an entity.\n\nconst money = (description: string) =>\n ({\n type: \"object\",\n additionalProperties: false,\n required: [\"amount\", \"recordedBy\", \"recordedAt\"],\n description,\n properties: {\n amount: {\n type: \"integer\",\n minimum: 0,\n description: \"The amount in integer cents.\",\n },\n recordedBy: {\n type: \"string\",\n description: \"The ID of the user who recorded the amount.\",\n },\n recordedAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the amount was recorded.\",\n },\n },\n }) as const;\n\n/**\n * The append-only billing review history, over whichever actions the host\n * admits. A ticket cost can be voided (withdrawn from the customer); a\n * standalone cost has no ticket to withdraw it from, so its history stops at\n * write-offs and divergence acknowledgements.\n */\nexport const costBillingReview = <const Actions extends readonly string[]>(\n actions: Actions,\n) =>\n ({\n type: \"array\",\n default: [],\n description:\n \"Append-only billing review history for the entry (approval-history \" +\n \"pattern): reversible write-offs, and billed-vs-price divergence \" +\n \"acknowledgements. Internal, redacted org-side.\",\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"action\", \"performedAt\"],\n properties: {\n id: {\n type: \"string\",\n description: \"The ID of the billing review entry.\",\n },\n action: {\n type: \"string\",\n enum: actions,\n },\n performedBy: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The ID of the user whose write appended this entry. Null when \" +\n \"the write was not user-attributable.\",\n },\n performedAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the entry was appended.\",\n },\n note: {\n type: [\"string\", \"null\"],\n default: null,\n description: \"Free-text rationale for the action.\",\n },\n billedAmount: {\n type: \"integer\",\n minimum: 0,\n description:\n \"divergenceAcknowledged only: the amount a bill line already \" +\n \"charged for this entry, in integer cents, frozen at ack time.\",\n },\n priceAmount: {\n type: \"integer\",\n minimum: 0,\n description:\n \"divergenceAcknowledged only: the entry's stored customer price \" +\n \"in integer cents at ack time. A divergence is a billed line \" +\n \"that no longer matches the price behind it — a price corrected \" +\n \"after the cost was claimed — so the ack silences this one pair \" +\n \"and any later price move re-flags it. A vendor actual arriving \" +\n \"after billing is not a divergence: it moves margin, not what \" +\n \"the customer owes.\",\n },\n },\n },\n }) as const;\n\nexport const costEntryRequired = [\n \"id\",\n \"description\",\n \"currency\",\n \"price\",\n \"estimate\",\n \"markup\",\n] as const;\n\nexport const costEntryProperties = {\n id: {\n type: \"string\",\n description: \"The ID of the cost entry.\",\n },\n description: {\n type: \"string\",\n description: \"What the cost covers.\",\n },\n currency: {\n type: \"string\",\n default: \"USD\",\n description: \"ISO 4217 currency code of the entry's amounts.\",\n },\n price: money(\n \"The authoritative customer price — what the org is charged, what the \" +\n \"approval gate totals, and what a bill line bills. Seeded at recording \" +\n \"from the estimate and the markup, and from then on independent of all \" +\n \"three: editing `estimate`, `actual`, or `markup` never moves it. Only \" +\n \"an explicit price write does.\",\n ),\n estimate: money(\"The vendor cost estimate phase of the entry.\"),\n actual: money(\n \"The settled vendor cost, recorded once the vendor's figure is known.\",\n ),\n markup: {\n type: \"object\",\n additionalProperties: false,\n required: [\"percent\"],\n properties: {\n percent: {\n type: \"number\",\n description:\n \"Markup percent the price was derived at, uncapped in either \" +\n \"direction. Context for how the price was arrived at, not the \" +\n \"source of truth for any amount: `price` is stored, so re-keying \" +\n \"this percent prices nothing. A biller may charge under the vendor \" +\n \"cost as a deliberate comp, and this records that as the negative \" +\n \"percent it is rather than as a floor of zero the price never came \" +\n \"from.\",\n },\n custom: {\n type: \"boolean\",\n default: false,\n description:\n \"Whether the percent was overridden by hand rather than keyed from \" +\n \"the configured markup tiers. Custom percents are never re-keyed on \" +\n \"estimate edits.\",\n },\n },\n },\n vendorId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The Vendor the charge is owed to. A plain reference — no rollups — \" +\n \"resolved inside the entry's own organization. Internal, redacted \" +\n \"org-side with the rest of the cost split.\",\n },\n categoryId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The billing category classifying this cost. `AddBillLine` snapshots \" +\n \"it onto the claiming line, which owns its own category from then on. \" +\n \"Internal, redacted org-side with the rest of the cost split.\",\n },\n vendorInvoices: {\n type: \"array\",\n items: { $ref: \"mediaFile.json\" },\n default: [],\n description:\n \"The vendor's paperwork backing the entry's amounts — an invoice plus \" +\n \"whatever came with it. Internal: the file-store cannot enforce \" +\n \"roster-only reads, so the boundary is this field living on the full \" +\n \"shape only, and the redacted projection never carries it.\",\n },\n vendorInvoiceNumber: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The vendor's own invoice number. Internal, redacted org-side like the \" +\n \"rest of the cost split.\",\n },\n billId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Backlink to the bill whose draft claimed this cost as a line. Written \" +\n \"when a draft bill adds the line, cleared on line removal, draft \" +\n \"delete, or bill void; a claimed cost leaves the uninvoiced pool, \" +\n \"making double-invoicing structurally impossible. Server-maintained at \" +\n \"the repository, never set by clients.\",\n },\n writtenOff: {\n type: \"boolean\",\n default: false,\n description:\n \"Server-maintained denormalization of billingReview (approvalState \" +\n \"pattern): true after a writtenOff entry until a reinstated entry \" +\n \"follows. A written-off cost leaves the uninvoiced pool. Never set by \" +\n \"clients.\",\n },\n billingReview: costBillingReview([\n \"writtenOff\",\n \"reinstated\",\n \"divergenceAcknowledged\",\n ]),\n} as const;\n"],"mappings":";AAYA,MAAM,SAAS,iBACZ;CACC,MAAM;CACN,sBAAsB;CACtB,UAAU;EAAC;EAAU;EAAc;CAAY;CAC/C;CACA,YAAY;EACV,QAAQ;GACN,MAAM;GACN,SAAS;GACT,aAAa;EACf;EACA,YAAY;GACV,MAAM;GACN,aAAa;EACf;EACA,YAAY;GACV,MAAM;GACN,aAAa;EACf;CACF;AACF;;;;;;;AAQF,MAAa,qBACX,aAEC;CACC,MAAM;CACN,SAAS,CAAC;CACV,aACE;CAGF,OAAO;EACL,MAAM;EACN,sBAAsB;EACtB,UAAU;GAAC;GAAM;GAAU;EAAa;EACxC,YAAY;GACV,IAAI;IACF,MAAM;IACN,aAAa;GACf;GACA,QAAQ;IACN,MAAM;IACN,MAAM;GACR;GACA,aAAa;IACX,MAAM,CAAC,UAAU,MAAM;IACvB,SAAS;IACT,aACE;GAEJ;GACA,aAAa;IACX,MAAM;IACN,aAAa;GACf;GACA,MAAM;IACJ,MAAM,CAAC,UAAU,MAAM;IACvB,SAAS;IACT,aAAa;GACf;GACA,cAAc;IACZ,MAAM;IACN,SAAS;IACT,aACE;GAEJ;GACA,aAAa;IACX,MAAM;IACN,SAAS;IACT,aACE;GAOJ;EACF;CACF;AACF;AAEF,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,sBAAsB;CACjC,IAAI;EACF,MAAM;EACN,aAAa;CACf;CACA,aAAa;EACX,MAAM;EACN,aAAa;CACf;CACA,UAAU;EACR,MAAM;EACN,SAAS;EACT,aAAa;CACf;CACA,OAAO,MACL,sTAKF;CACA,UAAU,MAAM,8CAA8C;CAC9D,QAAQ,MACN,sEACF;CACA,QAAQ;EACN,MAAM;EACN,sBAAsB;EACtB,UAAU,CAAC,SAAS;EACpB,YAAY;GACV,SAAS;IACP,MAAM;IACN,aACE;GAOJ;GACA,QAAQ;IACN,MAAM;IACN,SAAS;IACT,aACE;GAGJ;EACF;CACF;CACA,UAAU;EACR,MAAM,CAAC,UAAU,MAAM;EACvB,SAAS;EACT,aACE;CAGJ;CACA,YAAY;EACV,MAAM,CAAC,UAAU,MAAM;EACvB,SAAS;EACT,aACE;CAGJ;CACA,gBAAgB;EACd,MAAM;EACN,OAAO,EAAE,MAAM,iBAAiB;EAChC,SAAS,CAAC;EACV,aACE;CAIJ;CACA,qBAAqB;EACnB,MAAM,CAAC,UAAU,MAAM;EACvB,SAAS;EACT,aACE;CAEJ;CACA,QAAQ;EACN,MAAM,CAAC,UAAU,MAAM;EACvB,SAAS;EACT,aACE;CAKJ;CACA,YAAY;EACV,MAAM;EACN,SAAS;EACT,aACE;CAIJ;CACA,eAAe,kBAAkB;EAC/B;EACA;EACA;CACF,CAAC;AACH"}
|
|
1
|
+
{"version":3,"file":"costEntry.js","names":[],"sources":["../../.generated/schemas/costEntry.ts"],"sourcesContent":["// The cost-entry core: the money shape and reconciliation lifecycle every\n// OneBill cost carries, whether a Ticket embeds it or it stands alone in the\n// costs collection. Both hosts spread these consts into their own `properties`\n// and `required` rather than `$ref`-ing this file: draft-07 resolves `allOf`\n// against `additionalProperties: false` per subschema, so a composed entry\n// would reject every field the other half declared, and `FromSchema` derives\n// nothing useful from a reference it cannot inline.\n//\n// Nothing here is exported with a name ending in \"Schema\" and the model\n// generator skips this file by name (`scripts/generate-source-models.js`):\n// these are fragments, not an entity.\n\nconst moneyProperties = {\n amount: {\n type: \"integer\",\n minimum: 0,\n description: \"The amount in integer cents.\",\n },\n recordedBy: {\n type: \"string\",\n description: \"The ID of the user who recorded the amount.\",\n },\n recordedAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the amount was recorded.\",\n },\n} as const;\n\nconst moneyRequired = [\"amount\", \"recordedBy\", \"recordedAt\"] as const;\n\nconst money = (description: string) =>\n ({\n type: \"object\",\n additionalProperties: false,\n required: moneyRequired,\n description,\n properties: moneyProperties,\n }) as const;\n\n/**\n * The same phase on a host that admits a Pending cost, where `null` means the\n * amount is not known yet. Only the ticket cost entry takes this shape: a\n * ticket is what a vendor quote is awaited on.\n */\nexport const nullableMoney = (description: string) =>\n ({\n type: [\"object\", \"null\"],\n additionalProperties: false,\n required: moneyRequired,\n default: null,\n description,\n properties: moneyProperties,\n }) as const;\n\n/**\n * The append-only billing review history, over whichever actions the host\n * admits. A ticket cost can be voided (withdrawn from the customer); a\n * standalone cost has no ticket to withdraw it from, so its history stops at\n * write-offs and divergence acknowledgements.\n */\nexport const costBillingReview = <const Actions extends readonly string[]>(\n actions: Actions,\n) =>\n ({\n type: \"array\",\n default: [],\n description:\n \"Append-only billing review history for the entry (approval-history \" +\n \"pattern): reversible write-offs, and billed-vs-price divergence \" +\n \"acknowledgements. Internal, redacted org-side.\",\n items: {\n type: \"object\",\n additionalProperties: false,\n required: [\"id\", \"action\", \"performedAt\"],\n properties: {\n id: {\n type: \"string\",\n description: \"The ID of the billing review entry.\",\n },\n action: {\n type: \"string\",\n enum: actions,\n },\n performedBy: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The ID of the user whose write appended this entry. Null when \" +\n \"the write was not user-attributable.\",\n },\n performedAt: {\n $ref: \"definitions.json#/definitions/date\",\n description: \"When the entry was appended.\",\n },\n note: {\n type: [\"string\", \"null\"],\n default: null,\n description: \"Free-text rationale for the action.\",\n },\n billedAmount: {\n type: \"integer\",\n minimum: 0,\n description:\n \"divergenceAcknowledged only: the amount a bill line already \" +\n \"charged for this entry, in integer cents, frozen at ack time.\",\n },\n priceAmount: {\n type: \"integer\",\n minimum: 0,\n description:\n \"divergenceAcknowledged only: the entry's stored customer price \" +\n \"in integer cents at ack time. A divergence is a billed line \" +\n \"that no longer matches the price behind it — a price corrected \" +\n \"after the cost was claimed — so the ack silences this one pair \" +\n \"and any later price move re-flags it. A vendor actual arriving \" +\n \"after billing is not a divergence: it moves margin, not what \" +\n \"the customer owes.\",\n },\n },\n },\n }) as const;\n\nexport const costEntryRequired = [\n \"id\",\n \"description\",\n \"currency\",\n \"price\",\n \"estimate\",\n \"markup\",\n] as const;\n\nexport const costEntryProperties = {\n id: {\n type: \"string\",\n description: \"The ID of the cost entry.\",\n },\n description: {\n type: \"string\",\n description: \"What the cost covers.\",\n },\n currency: {\n type: \"string\",\n default: \"USD\",\n description: \"ISO 4217 currency code of the entry's amounts.\",\n },\n price: money(\n \"The authoritative customer price — what the org is charged, what the \" +\n \"approval gate totals, and what a bill line bills. Seeded at recording \" +\n \"from the estimate and the markup, and from then on independent of all \" +\n \"three: editing `estimate`, `actual`, or `markup` never moves it. Only \" +\n \"an explicit price write does.\",\n ),\n estimate: money(\"The vendor cost estimate phase of the entry.\"),\n actual: money(\n \"The settled vendor cost, recorded once the vendor's figure is known.\",\n ),\n markup: {\n type: \"object\",\n additionalProperties: false,\n required: [\"percent\"],\n properties: {\n percent: {\n type: \"number\",\n description:\n \"Markup percent the price was derived at, uncapped in either \" +\n \"direction. Context for how the price was arrived at, not the \" +\n \"source of truth for any amount: `price` is stored, so re-keying \" +\n \"this percent prices nothing. A biller may charge under the vendor \" +\n \"cost as a deliberate comp, and this records that as the negative \" +\n \"percent it is rather than as a floor of zero the price never came \" +\n \"from.\",\n },\n custom: {\n type: \"boolean\",\n default: false,\n description:\n \"Whether the percent was overridden by hand rather than keyed from \" +\n \"the configured markup tiers. Custom percents are never re-keyed on \" +\n \"estimate edits.\",\n },\n },\n },\n vendorId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The Vendor the charge is owed to. A plain reference — no rollups — \" +\n \"resolved inside the entry's own organization. Internal, redacted \" +\n \"org-side with the rest of the cost split.\",\n },\n categoryId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The billing category classifying this cost. `AddBillLine` snapshots \" +\n \"it onto the claiming line, which owns its own category from then on. \" +\n \"Internal, redacted org-side with the rest of the cost split.\",\n },\n vendorInvoices: {\n type: \"array\",\n items: { $ref: \"mediaFile.json\" },\n default: [],\n description:\n \"The vendor's paperwork backing the entry's amounts — an invoice plus \" +\n \"whatever came with it. Internal: the file-store cannot enforce \" +\n \"roster-only reads, so the boundary is this field living on the full \" +\n \"shape only, and the redacted projection never carries it.\",\n },\n vendorInvoiceNumber: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"The vendor's own invoice number. Internal, redacted org-side like the \" +\n \"rest of the cost split.\",\n },\n billId: {\n type: [\"string\", \"null\"],\n default: null,\n description:\n \"Backlink to the bill whose draft claimed this cost as a line. Written \" +\n \"when a draft bill adds the line, cleared on line removal, draft \" +\n \"delete, or bill void; a claimed cost leaves the uninvoiced pool, \" +\n \"making double-invoicing structurally impossible. Server-maintained at \" +\n \"the repository, never set by clients.\",\n },\n writtenOff: {\n type: \"boolean\",\n default: false,\n description:\n \"Server-maintained denormalization of billingReview (approvalState \" +\n \"pattern): true after a writtenOff entry until a reinstated entry \" +\n \"follows. A written-off cost leaves the uninvoiced pool. Never set by \" +\n \"clients.\",\n },\n billingReview: costBillingReview([\n \"writtenOff\",\n \"reinstated\",\n \"divergenceAcknowledged\",\n ]),\n} as const;\n"],"mappings":";AAYA,MAAM,kBAAkB;CACtB,QAAQ;EACN,MAAM;EACN,SAAS;EACT,aAAa;CACf;CACA,YAAY;EACV,MAAM;EACN,aAAa;CACf;CACA,YAAY;EACV,MAAM;EACN,aAAa;CACf;AACF;AAEA,MAAM,gBAAgB;CAAC;CAAU;CAAc;AAAY;AAE3D,MAAM,SAAS,iBACZ;CACC,MAAM;CACN,sBAAsB;CACtB,UAAU;CACV;CACA,YAAY;AACd;;;;;;AAOF,MAAa,iBAAiB,iBAC3B;CACC,MAAM,CAAC,UAAU,MAAM;CACvB,sBAAsB;CACtB,UAAU;CACV,SAAS;CACT;CACA,YAAY;AACd;;;;;;;AAQF,MAAa,qBACX,aAEC;CACC,MAAM;CACN,SAAS,CAAC;CACV,aACE;CAGF,OAAO;EACL,MAAM;EACN,sBAAsB;EACtB,UAAU;GAAC;GAAM;GAAU;EAAa;EACxC,YAAY;GACV,IAAI;IACF,MAAM;IACN,aAAa;GACf;GACA,QAAQ;IACN,MAAM;IACN,MAAM;GACR;GACA,aAAa;IACX,MAAM,CAAC,UAAU,MAAM;IACvB,SAAS;IACT,aACE;GAEJ;GACA,aAAa;IACX,MAAM;IACN,aAAa;GACf;GACA,MAAM;IACJ,MAAM,CAAC,UAAU,MAAM;IACvB,SAAS;IACT,aAAa;GACf;GACA,cAAc;IACZ,MAAM;IACN,SAAS;IACT,aACE;GAEJ;GACA,aAAa;IACX,MAAM;IACN,SAAS;IACT,aACE;GAOJ;EACF;CACF;AACF;AAEF,MAAa,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,sBAAsB;CACjC,IAAI;EACF,MAAM;EACN,aAAa;CACf;CACA,aAAa;EACX,MAAM;EACN,aAAa;CACf;CACA,UAAU;EACR,MAAM;EACN,SAAS;EACT,aAAa;CACf;CACA,OAAO,MACL,sTAKF;CACA,UAAU,MAAM,8CAA8C;CAC9D,QAAQ,MACN,sEACF;CACA,QAAQ;EACN,MAAM;EACN,sBAAsB;EACtB,UAAU,CAAC,SAAS;EACpB,YAAY;GACV,SAAS;IACP,MAAM;IACN,aACE;GAOJ;GACA,QAAQ;IACN,MAAM;IACN,SAAS;IACT,aACE;GAGJ;EACF;CACF;CACA,UAAU;EACR,MAAM,CAAC,UAAU,MAAM;EACvB,SAAS;EACT,aACE;CAGJ;CACA,YAAY;EACV,MAAM,CAAC,UAAU,MAAM;EACvB,SAAS;EACT,aACE;CAGJ;CACA,gBAAgB;EACd,MAAM;EACN,OAAO,EAAE,MAAM,iBAAiB;EAChC,SAAS,CAAC;EACV,aACE;CAIJ;CACA,qBAAqB;EACnB,MAAM,CAAC,UAAU,MAAM;EACvB,SAAS;EACT,aACE;CAEJ;CACA,QAAQ;EACN,MAAM,CAAC,UAAU,MAAM;EACvB,SAAS;EACT,aACE;CAKJ;CACA,YAAY;EACV,MAAM;EACN,SAAS;EACT,aACE;CAIJ;CACA,eAAe,kBAAkB;EAC/B;EACA;EACA;CACF,CAAC;AACH"}
|
|
@@ -11,11 +11,14 @@ export type PlatformRoleName = (typeof PLATFORM_ROLE_NAMES)[number];
|
|
|
11
11
|
/**
|
|
12
12
|
* The people outside the platform a broadcast may name, sourced from the SIS
|
|
13
13
|
* roster. `students` is every system user the SIS marks as a Student;
|
|
14
|
-
* `
|
|
14
|
+
* `staff` is everybody synced with nothing but the Staff role (faculty and
|
|
15
|
+
* staff); `parents` is everybody else on the roster — every emergency-contact
|
|
15
16
|
* relationship the source system carries, whatever it calls it.
|
|
16
17
|
*/
|
|
17
|
-
export declare const EXTERNAL_AUDIENCE_GROUPS: readonly ["students", "parents"];
|
|
18
|
+
export declare const EXTERNAL_AUDIENCE_GROUPS: readonly ["students", "parents", "staff"];
|
|
18
19
|
export type ExternalAudienceGroup = (typeof EXTERNAL_AUDIENCE_GROUPS)[number];
|
|
20
|
+
export declare const SMS_OPT_OUT_REASONS: readonly ["stop", "vendor"];
|
|
21
|
+
export declare const EMAIL_OPT_OUT_REASONS: readonly ["unsubscribe", "spamReport", "bounce"];
|
|
19
22
|
declare const defs: {
|
|
20
23
|
readonly $schema: "http://json-schema.org/draft-07/schema";
|
|
21
24
|
readonly $id: "definitions.json";
|
|
@@ -208,6 +211,61 @@ declare const defs: {
|
|
|
208
211
|
readonly type: "integer";
|
|
209
212
|
readonly minimum: 0;
|
|
210
213
|
};
|
|
214
|
+
readonly optedOut: {
|
|
215
|
+
readonly type: "integer";
|
|
216
|
+
readonly minimum: 0;
|
|
217
|
+
readonly description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking.";
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
readonly consent: {
|
|
222
|
+
readonly type: "object";
|
|
223
|
+
readonly additionalProperties: false;
|
|
224
|
+
readonly properties: {
|
|
225
|
+
readonly sms: {
|
|
226
|
+
readonly type: "object";
|
|
227
|
+
readonly additionalProperties: false;
|
|
228
|
+
readonly required: readonly ["optedOutAt"];
|
|
229
|
+
readonly properties: {
|
|
230
|
+
readonly optedOutAt: {
|
|
231
|
+
readonly anyOf: readonly [{
|
|
232
|
+
readonly type: readonly ["string", "object"];
|
|
233
|
+
readonly format: "date-time";
|
|
234
|
+
}, {
|
|
235
|
+
readonly type: "null";
|
|
236
|
+
}];
|
|
237
|
+
readonly description: "When the person opted out of this channel; null while they are reachable.";
|
|
238
|
+
};
|
|
239
|
+
readonly reason: {
|
|
240
|
+
readonly type: "string";
|
|
241
|
+
readonly enum: readonly ["stop", "vendor"];
|
|
242
|
+
};
|
|
243
|
+
readonly lastOptOutNoticeAt: {
|
|
244
|
+
readonly type: readonly ["string", "object"];
|
|
245
|
+
readonly format: "date-time";
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
readonly email: {
|
|
250
|
+
readonly type: "object";
|
|
251
|
+
readonly additionalProperties: false;
|
|
252
|
+
readonly required: readonly ["optedOutAt"];
|
|
253
|
+
readonly properties: {
|
|
254
|
+
readonly optedOutAt: {
|
|
255
|
+
readonly anyOf: readonly [{
|
|
256
|
+
readonly type: readonly ["string", "object"];
|
|
257
|
+
readonly format: "date-time";
|
|
258
|
+
}, {
|
|
259
|
+
readonly type: "null";
|
|
260
|
+
}];
|
|
261
|
+
readonly description: "When the person opted out of this channel; null while they are reachable.";
|
|
262
|
+
};
|
|
263
|
+
readonly reason: {
|
|
264
|
+
readonly type: "string";
|
|
265
|
+
readonly enum: readonly ["unsubscribe", "spamReport", "bounce"];
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
};
|
|
211
269
|
};
|
|
212
270
|
};
|
|
213
271
|
readonly audience: {
|
|
@@ -248,7 +306,7 @@ declare const defs: {
|
|
|
248
306
|
readonly description: "Which groups of the external SIS roster were included. Human-triggered sends only; an Automation can never set it.";
|
|
249
307
|
readonly items: {
|
|
250
308
|
readonly type: "string";
|
|
251
|
-
readonly enum: readonly ["students", "parents"];
|
|
309
|
+
readonly enum: readonly ["students", "parents", "staff"];
|
|
252
310
|
};
|
|
253
311
|
};
|
|
254
312
|
readonly emergencyContacts: {
|
|
@@ -284,6 +342,11 @@ declare const defs: {
|
|
|
284
342
|
readonly type: "integer";
|
|
285
343
|
readonly minimum: 0;
|
|
286
344
|
};
|
|
345
|
+
readonly optedOut: {
|
|
346
|
+
readonly type: "integer";
|
|
347
|
+
readonly minimum: 0;
|
|
348
|
+
readonly description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking.";
|
|
349
|
+
};
|
|
287
350
|
};
|
|
288
351
|
};
|
|
289
352
|
readonly external: {
|
|
@@ -303,6 +366,11 @@ declare const defs: {
|
|
|
303
366
|
readonly type: "integer";
|
|
304
367
|
readonly minimum: 0;
|
|
305
368
|
};
|
|
369
|
+
readonly optedOut: {
|
|
370
|
+
readonly type: "integer";
|
|
371
|
+
readonly minimum: 0;
|
|
372
|
+
readonly description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking.";
|
|
373
|
+
};
|
|
306
374
|
readonly byChannel: {
|
|
307
375
|
readonly type: "object";
|
|
308
376
|
readonly additionalProperties: false;
|
|
@@ -325,6 +393,11 @@ declare const defs: {
|
|
|
325
393
|
readonly type: "integer";
|
|
326
394
|
readonly minimum: 0;
|
|
327
395
|
};
|
|
396
|
+
readonly optedOut: {
|
|
397
|
+
readonly type: "integer";
|
|
398
|
+
readonly minimum: 0;
|
|
399
|
+
readonly description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking.";
|
|
400
|
+
};
|
|
328
401
|
};
|
|
329
402
|
};
|
|
330
403
|
readonly email: {
|
|
@@ -344,6 +417,11 @@ declare const defs: {
|
|
|
344
417
|
readonly type: "integer";
|
|
345
418
|
readonly minimum: 0;
|
|
346
419
|
};
|
|
420
|
+
readonly optedOut: {
|
|
421
|
+
readonly type: "integer";
|
|
422
|
+
readonly minimum: 0;
|
|
423
|
+
readonly description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking.";
|
|
424
|
+
};
|
|
347
425
|
};
|
|
348
426
|
};
|
|
349
427
|
};
|
|
@@ -368,6 +446,11 @@ declare const defs: {
|
|
|
368
446
|
readonly type: "integer";
|
|
369
447
|
readonly minimum: 0;
|
|
370
448
|
};
|
|
449
|
+
readonly optedOut: {
|
|
450
|
+
readonly type: "integer";
|
|
451
|
+
readonly minimum: 0;
|
|
452
|
+
readonly description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking.";
|
|
453
|
+
};
|
|
371
454
|
readonly byChannel: {
|
|
372
455
|
readonly type: "object";
|
|
373
456
|
readonly additionalProperties: false;
|
|
@@ -390,6 +473,11 @@ declare const defs: {
|
|
|
390
473
|
readonly type: "integer";
|
|
391
474
|
readonly minimum: 0;
|
|
392
475
|
};
|
|
476
|
+
readonly optedOut: {
|
|
477
|
+
readonly type: "integer";
|
|
478
|
+
readonly minimum: 0;
|
|
479
|
+
readonly description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking.";
|
|
480
|
+
};
|
|
393
481
|
};
|
|
394
482
|
};
|
|
395
483
|
readonly email: {
|
|
@@ -409,6 +497,11 @@ declare const defs: {
|
|
|
409
497
|
readonly type: "integer";
|
|
410
498
|
readonly minimum: 0;
|
|
411
499
|
};
|
|
500
|
+
readonly optedOut: {
|
|
501
|
+
readonly type: "integer";
|
|
502
|
+
readonly minimum: 0;
|
|
503
|
+
readonly description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking.";
|
|
504
|
+
};
|
|
412
505
|
};
|
|
413
506
|
};
|
|
414
507
|
};
|
|
@@ -31,10 +31,15 @@ const PLATFORM_ROLE_NAMES = [
|
|
|
31
31
|
/**
|
|
32
32
|
* The people outside the platform a broadcast may name, sourced from the SIS
|
|
33
33
|
* roster. `students` is every system user the SIS marks as a Student;
|
|
34
|
-
* `
|
|
34
|
+
* `staff` is everybody synced with nothing but the Staff role (faculty and
|
|
35
|
+
* staff); `parents` is everybody else on the roster — every emergency-contact
|
|
35
36
|
* relationship the source system carries, whatever it calls it.
|
|
36
37
|
*/
|
|
37
|
-
const EXTERNAL_AUDIENCE_GROUPS = [
|
|
38
|
+
const EXTERNAL_AUDIENCE_GROUPS = [
|
|
39
|
+
"students",
|
|
40
|
+
"parents",
|
|
41
|
+
"staff"
|
|
42
|
+
];
|
|
38
43
|
const deliveryCountsNode = {
|
|
39
44
|
type: "object",
|
|
40
45
|
additionalProperties: false,
|
|
@@ -55,9 +60,28 @@ const deliveryCountsNode = {
|
|
|
55
60
|
failed: {
|
|
56
61
|
type: "integer",
|
|
57
62
|
minimum: 0
|
|
63
|
+
},
|
|
64
|
+
optedOut: {
|
|
65
|
+
type: "integer",
|
|
66
|
+
minimum: 0,
|
|
67
|
+
description: "Recipients skipped because they opted out of this channel. Counted apart from `failed`; absent on sends recorded before opt-out tracking."
|
|
58
68
|
}
|
|
59
69
|
}
|
|
60
70
|
};
|
|
71
|
+
const SMS_OPT_OUT_REASONS = ["stop", "vendor"];
|
|
72
|
+
const EMAIL_OPT_OUT_REASONS = [
|
|
73
|
+
"unsubscribe",
|
|
74
|
+
"spamReport",
|
|
75
|
+
"bounce"
|
|
76
|
+
];
|
|
77
|
+
const dateNode = {
|
|
78
|
+
type: ["string", "object"],
|
|
79
|
+
format: "date-time"
|
|
80
|
+
};
|
|
81
|
+
const optedOutAtNode = {
|
|
82
|
+
anyOf: [dateNode, { type: "null" }],
|
|
83
|
+
description: "When the person opted out of this channel; null while they are reachable."
|
|
84
|
+
};
|
|
61
85
|
const defs = {
|
|
62
86
|
$schema: "http://json-schema.org/draft-07/schema",
|
|
63
87
|
$id: "definitions.json",
|
|
@@ -347,6 +371,37 @@ const defs = {
|
|
|
347
371
|
enum: NOTIFICATION_CHANNELS
|
|
348
372
|
},
|
|
349
373
|
deliveryCounts: deliveryCountsNode,
|
|
374
|
+
consent: {
|
|
375
|
+
type: "object",
|
|
376
|
+
additionalProperties: false,
|
|
377
|
+
properties: {
|
|
378
|
+
sms: {
|
|
379
|
+
type: "object",
|
|
380
|
+
additionalProperties: false,
|
|
381
|
+
required: ["optedOutAt"],
|
|
382
|
+
properties: {
|
|
383
|
+
optedOutAt: optedOutAtNode,
|
|
384
|
+
reason: {
|
|
385
|
+
type: "string",
|
|
386
|
+
enum: SMS_OPT_OUT_REASONS
|
|
387
|
+
},
|
|
388
|
+
lastOptOutNoticeAt: dateNode
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
email: {
|
|
392
|
+
type: "object",
|
|
393
|
+
additionalProperties: false,
|
|
394
|
+
required: ["optedOutAt"],
|
|
395
|
+
properties: {
|
|
396
|
+
optedOutAt: optedOutAtNode,
|
|
397
|
+
reason: {
|
|
398
|
+
type: "string",
|
|
399
|
+
enum: EMAIL_OPT_OUT_REASONS
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
},
|
|
350
405
|
audience: {
|
|
351
406
|
type: "object",
|
|
352
407
|
additionalProperties: false,
|
|
@@ -449,6 +504,6 @@ const defs = {
|
|
|
449
504
|
}
|
|
450
505
|
};
|
|
451
506
|
//#endregion
|
|
452
|
-
export { EXTERNAL_AUDIENCE_GROUPS, NOTIFICATION_CHANNELS, PLATFORM_ROLE_NAMES, TICKET_NOTIFICATION_EVENTS, defs as default, defs as definitionsSchema };
|
|
507
|
+
export { EMAIL_OPT_OUT_REASONS, EXTERNAL_AUDIENCE_GROUPS, NOTIFICATION_CHANNELS, PLATFORM_ROLE_NAMES, SMS_OPT_OUT_REASONS, TICKET_NOTIFICATION_EVENTS, defs as default, defs as definitionsSchema };
|
|
453
508
|
|
|
454
509
|
//# sourceMappingURL=definitions.js.map
|