@managemint-solutions/sdk 0.65.0 → 0.66.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.
@@ -15,6 +15,7 @@ const TEMPLATE_LIST_SELECT = `
15
15
  name,
16
16
  category,
17
17
  number_prefix,
18
+ due_days,
18
19
  archived,
19
20
  visibility
20
21
  `;
@@ -27,6 +28,7 @@ const TEMPLATE_DETAIL_SELECT = `
27
28
  name,
28
29
  category,
29
30
  number_prefix,
31
+ due_days,
30
32
  variables,
31
33
  blocks,
32
34
  blocks_version,
@@ -43,6 +45,7 @@ const templateRow = (input) => ({
43
45
  name: input.name,
44
46
  category: input.category ?? '',
45
47
  number_prefix: input.number_prefix ?? '',
48
+ due_days: input.due_days ?? null,
46
49
  variables: input.variables,
47
50
  blocks: input.blocks,
48
51
  });
@@ -41,6 +41,9 @@ type DocumentRow = {
41
41
  repeat_from: string | null;
42
42
  issue_at: string | null;
43
43
  email: DocumentEmail | null;
44
+ /** When it falls due: days after issue on a draft, the date itself (YYYY-MM-DD) once picked or issued. */
45
+ due_days: number | null;
46
+ due_at: string | null;
44
47
  };
45
48
  /**
46
49
  * A document as the sdk reads it. `my_role` (what the caller may do with it), `payments` (read
@@ -58,7 +61,7 @@ export type DocumentSendEvent = Pick<DocumentSend, 'recipients' | 'cc' | 'subjec
58
61
  * the cron's, for the drafts it makes.
59
62
  */
60
63
  export type CreateDocumentRow = Omit<DocumentRow, 'status' | 'number_sequence' | 'number' | 'issued_at' | 'issued_by' | 'voided_at' | 'voided_by' | 'void_reason' | keyof DocumentScheduleRow> & Partial<DocumentScheduleRow>;
61
- type DocumentScheduleRow = Pick<DocumentRow, 'repeat' | 'repeat_next_at' | 'repeat_until' | 'repeat_paused' | 'repeat_from' | 'issue_at' | 'email'>;
64
+ type DocumentScheduleRow = Pick<DocumentRow, 'repeat' | 'repeat_next_at' | 'repeat_until' | 'repeat_paused' | 'repeat_from' | 'issue_at' | 'email' | 'due_days' | 'due_at'>;
62
65
  /**
63
66
  * A draft save, an issue or a void: whichever columns it changes - never the visibility, which
64
67
  * members hold no grant on after create (the visibility route changes it on the service role).
@@ -82,8 +85,9 @@ export declare class DocumentsResource {
82
85
  * Newest first; `search` matches the title and the number. Recurring parents are a list of
83
86
  * their own: `recurring` lists them alone, and every other list leaves them out. `ids` keeps
84
87
  * the list to (`in`) or away from (`not_in`) the documents named - the api's payment filter
85
- * passes the paid ones - and `payable` to issued documents with a total above zero. The
86
- * DTO's `payment` itself is the api's to turn into those two; the list ignores it.
88
+ * passes the paid ones - and `payable` to issued documents with a total above zero;
89
+ * `due_before` to documents due on or before that date. The DTO's `payment` and `overdue`
90
+ * are the api's to turn into those; the list ignores them.
87
91
  */
88
92
  list(query: GetDocumentsDto & {
89
93
  organization_id?: string | null;
@@ -31,6 +31,8 @@ const DOCUMENT_LIST_SELECT = `
31
31
  repeat_paused,
32
32
  repeat_from,
33
33
  issue_at,
34
+ due_days,
35
+ due_at,
34
36
  visibility
35
37
  `;
36
38
  const DOCUMENT_DETAIL_SELECT = `
@@ -67,6 +69,8 @@ const DOCUMENT_DETAIL_SELECT = `
67
69
  repeat_from,
68
70
  issue_at,
69
71
  email,
72
+ due_days,
73
+ due_at,
70
74
  visibility
71
75
  `;
72
76
  /** How long a signed image URL in rendered HTML stays valid - long enough to keep a preview open. */
@@ -102,8 +106,9 @@ class DocumentsResource {
102
106
  * Newest first; `search` matches the title and the number. Recurring parents are a list of
103
107
  * their own: `recurring` lists them alone, and every other list leaves them out. `ids` keeps
104
108
  * the list to (`in`) or away from (`not_in`) the documents named - the api's payment filter
105
- * passes the paid ones - and `payable` to issued documents with a total above zero. The
106
- * DTO's `payment` itself is the api's to turn into those two; the list ignores it.
109
+ * passes the paid ones - and `payable` to issued documents with a total above zero;
110
+ * `due_before` to documents due on or before that date. The DTO's `payment` and `overdue`
111
+ * are the api's to turn into those; the list ignores them.
107
112
  */
108
113
  async list(query) {
109
114
  const page = query.page;
@@ -146,6 +151,9 @@ class DocumentsResource {
146
151
  if (query.payable) {
147
152
  documentsQuery = documentsQuery.eq('status', enum_1.DocumentStatus.ISSUED).gt('total_minor', 0);
148
153
  }
154
+ if (query.due_before) {
155
+ documentsQuery = documentsQuery.lte('due_at', query.due_before);
156
+ }
149
157
  if (trimmedSearch) {
150
158
  documentsQuery = documentsQuery.or((0, transforms_1.orIlike)(['title', 'number'], trimmedSearch));
151
159
  }
@@ -16,6 +16,7 @@ export declare class UpdateDocumentTemplateDto implements UpdateDocumentTemplate
16
16
  readonly name: string;
17
17
  readonly category?: string;
18
18
  readonly number_prefix?: string;
19
+ readonly due_days?: number | null;
19
20
  readonly variables: DocumentVariable[];
20
21
  readonly blocks: DocumentBlock[];
21
22
  }
@@ -32,6 +33,8 @@ export declare class GetDocumentsDto implements GetDocumentsDtoType {
32
33
  readonly recurring?: boolean;
33
34
  readonly repeat_from?: string | null;
34
35
  readonly payment?: DocumentPaymentFilter | null;
36
+ readonly due_before?: string | null;
37
+ readonly overdue?: boolean;
35
38
  readonly page: number;
36
39
  readonly page_size: number;
37
40
  }
@@ -50,6 +53,8 @@ declare class DocumentScheduleDto {
50
53
  readonly repeat_paused?: boolean;
51
54
  readonly issue_at?: string | null;
52
55
  readonly email?: DocumentEmail | null;
56
+ readonly due_days?: number | null;
57
+ readonly due_at?: string | null;
53
58
  }
54
59
  /**
55
60
  * A new draft. Its values cannot be checked here - with a template, the variables they fill are
@@ -79,11 +79,16 @@ __decorate([
79
79
  (0, class_validator_1.IsUUID)('7', { message: 'Invalid template ID format' }),
80
80
  __metadata("design:type", String)
81
81
  ], DocumentTemplateIdDto.prototype, "templateId", void 0);
82
+ /** Days after issue a document falls due: a whole number from 0 to 365. */
83
+ const IsDueDays = (0, validators_1.fromProblem)('isDueDays', (value) => Number.isInteger(value) && value >= 0 && value <= 365
84
+ ? null
85
+ : 'Due days must be a whole number from 0 to 365');
82
86
  /** Saving replaces the whole template. Its visibility changes only through the visibility route. */
83
87
  class UpdateDocumentTemplateDto {
84
88
  name;
85
89
  category;
86
90
  number_prefix;
91
+ due_days;
87
92
  variables;
88
93
  blocks;
89
94
  }
@@ -106,6 +111,12 @@ __decorate([
106
111
  (0, content_1.IsDocumentNumberPrefix)(),
107
112
  __metadata("design:type", String)
108
113
  ], UpdateDocumentTemplateDto.prototype, "number_prefix", void 0);
114
+ __decorate([
115
+ (0, class_validator_1.IsOptional)(),
116
+ (0, validators_1.IsNullable)(),
117
+ IsDueDays(),
118
+ __metadata("design:type", Object)
119
+ ], UpdateDocumentTemplateDto.prototype, "due_days", void 0);
109
120
  __decorate([
110
121
  (0, content_1.IsDocumentVariables)(),
111
122
  __metadata("design:type", Array)
@@ -138,6 +149,9 @@ class GetDocumentsDto {
138
149
  recurring;
139
150
  repeat_from;
140
151
  payment;
152
+ due_before;
153
+ // Issued, due before today, nothing settled - resolved by the api; the sdk list ignores it.
154
+ overdue;
141
155
  page = 1;
142
156
  page_size = 10;
143
157
  }
@@ -193,6 +207,18 @@ __decorate([
193
207
  (0, class_validator_1.IsEnum)(enum_1.DocumentPaymentFilter, { message: `Payment must be one of: ${Object.values(enum_1.DocumentPaymentFilter).join(', ')}` }),
194
208
  __metadata("design:type", Object)
195
209
  ], GetDocumentsDto.prototype, "payment", void 0);
210
+ __decorate([
211
+ (0, class_validator_1.IsOptional)(),
212
+ (0, validators_1.IsNullable)(),
213
+ (0, validators_1.IsCalendarDate)({ message: 'Due before must be a calendar date (YYYY-MM-DD)' }),
214
+ __metadata("design:type", Object)
215
+ ], GetDocumentsDto.prototype, "due_before", void 0);
216
+ __decorate([
217
+ (0, class_validator_1.IsOptional)(),
218
+ (0, class_transformer_1.Transform)(({ value }) => value === true || value === 'true', { toClassOnly: true }),
219
+ (0, class_validator_1.IsBoolean)({ message: 'Overdue must be a boolean' }),
220
+ __metadata("design:type", Boolean)
221
+ ], GetDocumentsDto.prototype, "overdue", void 0);
196
222
  __decorate([
197
223
  (0, class_validator_1.IsOptional)(),
198
224
  (0, class_transformer_1.Transform)(({ value }) => value ? Number(value) : 1, { toClassOnly: true }),
@@ -242,6 +268,8 @@ class DocumentScheduleDto {
242
268
  repeat_paused;
243
269
  issue_at;
244
270
  email;
271
+ due_days;
272
+ due_at;
245
273
  }
246
274
  __decorate([
247
275
  (0, class_validator_1.IsOptional)(),
@@ -278,6 +306,18 @@ __decorate([
278
306
  IsDocumentEmail(),
279
307
  __metadata("design:type", Object)
280
308
  ], DocumentScheduleDto.prototype, "email", void 0);
309
+ __decorate([
310
+ (0, class_validator_1.IsOptional)(),
311
+ (0, validators_1.IsNullable)(),
312
+ IsDueDays(),
313
+ __metadata("design:type", Object)
314
+ ], DocumentScheduleDto.prototype, "due_days", void 0);
315
+ __decorate([
316
+ (0, class_validator_1.IsOptional)(),
317
+ (0, validators_1.IsNullable)(),
318
+ (0, validators_1.IsCalendarDate)({ message: 'Due date must be a calendar date (YYYY-MM-DD)' }),
319
+ __metadata("design:type", Object)
320
+ ], DocumentScheduleDto.prototype, "due_at", void 0);
281
321
  /**
282
322
  * A new draft. Its values cannot be checked here - with a template, the variables they fill are
283
323
  * the template's - so the api checks the draft it composes with `documentProblem`.
@@ -1,2 +1,2 @@
1
1
  export { DOCUMENT_PAGE_MARGINS, fillText, renderBand, renderDocument, type DocumentBand, type PrintableDocument, type RenderedDocument, } from './html';
2
- export { documentTotals, escapeHtml, formatDocumentDate, johannesburgDate, money, MONO_FONT, printsMoney, startingValues, SYSTEM_VARIABLES, systemValues, type DocumentTotals, type SystemValueInputs, } from './values';
2
+ export { documentTotals, dueDateFrom, escapeHtml, formatDocumentDate, johannesburgDate, money, MONO_FONT, printsMoney, startingValues, SYSTEM_VARIABLES, systemValues, type DocumentTotals, type SystemValueInputs, } from './values';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.systemValues = exports.SYSTEM_VARIABLES = exports.startingValues = exports.printsMoney = exports.MONO_FONT = exports.money = exports.johannesburgDate = exports.formatDocumentDate = exports.escapeHtml = exports.documentTotals = exports.renderDocument = exports.renderBand = exports.fillText = exports.DOCUMENT_PAGE_MARGINS = void 0;
3
+ exports.systemValues = exports.SYSTEM_VARIABLES = exports.startingValues = exports.printsMoney = exports.MONO_FONT = exports.money = exports.johannesburgDate = exports.formatDocumentDate = exports.escapeHtml = exports.dueDateFrom = exports.documentTotals = exports.renderDocument = exports.renderBand = exports.fillText = exports.DOCUMENT_PAGE_MARGINS = void 0;
4
4
  // `@managemint-solutions/sdk/documents`: the document renderer and the values it prints, as pure
5
5
  // functions with no dependency beyond the shared entities - no Node, no Nest, no supabase-js, no
6
6
  // DOM - so the api's PDF and the portal's in-browser preview are one renderer. The caller loads
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "renderBand", { enumerable: true, get: function (
12
12
  Object.defineProperty(exports, "renderDocument", { enumerable: true, get: function () { return html_1.renderDocument; } });
13
13
  var values_1 = require("./values");
14
14
  Object.defineProperty(exports, "documentTotals", { enumerable: true, get: function () { return values_1.documentTotals; } });
15
+ Object.defineProperty(exports, "dueDateFrom", { enumerable: true, get: function () { return values_1.dueDateFrom; } });
15
16
  Object.defineProperty(exports, "escapeHtml", { enumerable: true, get: function () { return values_1.escapeHtml; } });
16
17
  Object.defineProperty(exports, "formatDocumentDate", { enumerable: true, get: function () { return values_1.formatDocumentDate; } });
17
18
  Object.defineProperty(exports, "johannesburgDate", { enumerable: true, get: function () { return values_1.johannesburgDate; } });
@@ -75,12 +75,16 @@ export type SystemValueInputs = {
75
75
  number: string | null;
76
76
  /** `YYYY-MM-DD`: today on a draft (`johannesburgDate(new Date())`), the issue date once issued. */
77
77
  issueDate: string;
78
+ /** `YYYY-MM-DD`: when the document falls due; left out (prints as missing) without one. */
79
+ dueDate?: string | null;
78
80
  };
81
+ /** `issueDate` plus `days`, as a calendar date: the due date of a document issued that day. */
82
+ export declare const dueDateFrom: (issueDate: string, days: number) => string;
79
83
  /**
80
84
  * The values filled in for the system variables: the organization's name (its trading name
81
85
  * first), address, registration and VAT numbers, email and phone; the client's name, email, phone,
82
- * address, registration and VAT numbers; the document number; and the issue date with its month
83
- * name and year. A value that is empty is left out, so it prints as missing. The
84
- * page number and count are not values: they are counted page by page as the PDF prints.
86
+ * address, registration and VAT numbers; the document number; the issue date with its month
87
+ * name and year; and the due date. A value that is empty is left out, so it prints as missing.
88
+ * The page number and count are not values: they are counted page by page as the PDF prints.
85
89
  */
86
- export declare const systemValues: ({ organization, client, number, issueDate }: SystemValueInputs) => DocumentVariableValues;
90
+ export declare const systemValues: ({ organization, client, number, issueDate, dueDate }: SystemValueInputs) => DocumentVariableValues;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.systemValues = exports.johannesburgDate = exports.startingValues = exports.printsMoney = exports.documentTotals = exports.lineAmounts = exports.MONO_FONT = exports.formatDocumentDate = exports.money = exports.escapeHtml = exports.safeHref = exports.isObject = exports.SYSTEM_VARIABLES = exports.DOCUMENT_VARIABLE_PATTERN = void 0;
3
+ exports.systemValues = exports.dueDateFrom = exports.johannesburgDate = exports.startingValues = exports.printsMoney = exports.documentTotals = exports.lineAmounts = exports.MONO_FONT = exports.formatDocumentDate = exports.money = exports.escapeHtml = exports.safeHref = exports.isObject = exports.SYSTEM_VARIABLES = exports.DOCUMENT_VARIABLE_PATTERN = void 0;
4
4
  const enum_1 = require("@managemint-solutions/entities/documents/enum");
5
5
  // The values a document prints that nobody types in: one line's amounts, the totals of every line
6
6
  // items block, the system values, and how a value is escaped and formatted. Pure functions with
@@ -33,6 +33,7 @@ exports.SYSTEM_VARIABLES = {
33
33
  [enum_1.DocumentSystemVariable.CLIENT_ADDRESS]: { label: 'Client address', type: enum_1.DocumentVariableType.TEXT },
34
34
  [enum_1.DocumentSystemVariable.CLIENT_REGISTRATION_NUMBER]: { label: 'Client registration number', type: enum_1.DocumentVariableType.TEXT },
35
35
  [enum_1.DocumentSystemVariable.CLIENT_VAT_NUMBER]: { label: 'Client VAT number', type: enum_1.DocumentVariableType.TEXT },
36
+ [enum_1.DocumentSystemVariable.DUE_DATE]: { label: 'Due date', type: enum_1.DocumentVariableType.DATE },
36
37
  };
37
38
  const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
38
39
  exports.isObject = isObject;
@@ -108,14 +109,20 @@ exports.startingValues = startingValues;
108
109
  /** The calendar date (`YYYY-MM-DD`) `now` falls on in Africa/Johannesburg - a draft's issue date. */
109
110
  const johannesburgDate = (now) => new Intl.DateTimeFormat('en-CA', { timeZone: 'Africa/Johannesburg' }).format(now);
110
111
  exports.johannesburgDate = johannesburgDate;
112
+ /** `issueDate` plus `days`, as a calendar date: the due date of a document issued that day. */
113
+ const dueDateFrom = (issueDate, days) => {
114
+ const [year, month, day] = issueDate.split('-').map(Number);
115
+ return new Date(Date.UTC(year, month - 1, day + days)).toISOString().slice(0, 10);
116
+ };
117
+ exports.dueDateFrom = dueDateFrom;
111
118
  /**
112
119
  * The values filled in for the system variables: the organization's name (its trading name
113
120
  * first), address, registration and VAT numbers, email and phone; the client's name, email, phone,
114
- * address, registration and VAT numbers; the document number; and the issue date with its month
115
- * name and year. A value that is empty is left out, so it prints as missing. The
116
- * page number and count are not values: they are counted page by page as the PDF prints.
121
+ * address, registration and VAT numbers; the document number; the issue date with its month
122
+ * name and year; and the due date. A value that is empty is left out, so it prints as missing.
123
+ * The page number and count are not values: they are counted page by page as the PDF prints.
117
124
  */
118
- const systemValues = ({ organization, client, number, issueDate }) => {
125
+ const systemValues = ({ organization, client, number, issueDate, dueDate }) => {
119
126
  const text = (value) => (typeof value === 'string' ? value.trim() : '');
120
127
  const address = (parts) => (parts ?? []).map(text).filter(Boolean).join(', ');
121
128
  const [year, month] = issueDate.split('-');
@@ -136,6 +143,7 @@ const systemValues = ({ organization, client, number, issueDate }) => {
136
143
  [enum_1.DocumentSystemVariable.ISSUE_DATE]: issueDate,
137
144
  [enum_1.DocumentSystemVariable.MONTH]: new Intl.DateTimeFormat('en-ZA', { month: 'long', timeZone: 'UTC' }).format(new Date(Date.UTC(Number(year), Number(month) - 1, 1))),
138
145
  [enum_1.DocumentSystemVariable.YEAR]: year,
146
+ [enum_1.DocumentSystemVariable.DUE_DATE]: dueDate ?? '',
139
147
  };
140
148
  return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== ''));
141
149
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@managemint-solutions/sdk",
3
- "version": "0.65.0",
3
+ "version": "0.66.0",
4
4
  "description": "Typed Supabase data-access SDK for ManageMint Solutions",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Scott Bebington <scottbebington@gmail.com>",
@@ -55,7 +55,7 @@
55
55
  "testEnvironment": "node"
56
56
  },
57
57
  "dependencies": {
58
- "@managemint-solutions/entities": "^1.47.0"
58
+ "@managemint-solutions/entities": "^1.48.0"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@nestjs/common": "^11.0.0",