ztechno_core 0.0.132 → 0.0.133

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.
@@ -36,8 +36,8 @@ class InvoiceStatusLogOrm extends orm_1.ZOrm {
36
36
  CREATE TABLE IF NOT EXISTS \`${this.alias}\` (
37
37
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
38
38
  invoice_id BIGINT UNSIGNED NOT NULL,
39
- from_status ENUM('draft','pending','paid','failed','canceled','expired','refunded','archived') NULL,
40
- to_status ENUM('draft','pending','paid','failed','canceled','expired','refunded','archived') NOT NULL,
39
+ from_status ENUM('draft','pending','paid','failed','canceled','expired','refunded') NULL,
40
+ to_status ENUM('draft','pending','paid','failed','canceled','expired','refunded') NOT NULL,
41
41
  actor_type ENUM('webhook','system','admin') NOT NULL,
42
42
  mollie_payment_id VARCHAR(64) NULL,
43
43
  note VARCHAR(512) NULL,
@@ -54,6 +54,9 @@ export declare class InvoicesOrm extends ZOrm {
54
54
  ): Promise<void>;
55
55
  finalizePayToken(id: number): Promise<void>;
56
56
  incrementTimesSent(id: number): Promise<void>;
57
+ setArchivedAt(id: number): Promise<void>;
58
+ clearArchivedAt(id: number): Promise<void>;
59
+ isArchived(invoice: ZInvoice): boolean;
57
60
  updateMutableFields(
58
61
  id: number,
59
62
  fields: {
@@ -190,6 +190,29 @@ class InvoicesOrm extends orm_1.ZOrm {
190
190
  { id },
191
191
  );
192
192
  }
193
+ async setArchivedAt(id) {
194
+ await this.sqlService.query(
195
+ /*SQL*/ `
196
+ UPDATE \`${this.alias}\`
197
+ SET archived_at=NOW(), updated_at=NOW()
198
+ WHERE id=:id
199
+ `,
200
+ { id },
201
+ );
202
+ }
203
+ async clearArchivedAt(id) {
204
+ await this.sqlService.query(
205
+ /*SQL*/ `
206
+ UPDATE \`${this.alias}\`
207
+ SET archived_at=NULL, updated_at=NOW()
208
+ WHERE id=:id
209
+ `,
210
+ { id },
211
+ );
212
+ }
213
+ isArchived(invoice) {
214
+ return invoice.archived_at != null;
215
+ }
193
216
  async updateMutableFields(id, fields) {
194
217
  const sets = [];
195
218
  const params = { id };
@@ -235,7 +258,7 @@ class InvoicesOrm extends orm_1.ZOrm {
235
258
  pay_token_hash CHAR(64),
236
259
  pay_token_expires_at DATETIME,
237
260
  pay_token_finalized_at DATETIME,
238
- status ENUM('draft','pending','paid','failed','canceled','expired','refunded','archived') NOT NULL DEFAULT 'draft',
261
+ status ENUM('draft','pending','paid','failed','canceled','expired','refunded') NOT NULL DEFAULT 'draft',
239
262
  amount_due DECIMAL(12,2) NOT NULL,
240
263
  amount_paid DECIMAL(12,2) NOT NULL DEFAULT 0,
241
264
  currency CHAR(3) NOT NULL DEFAULT 'EUR',
@@ -246,6 +269,7 @@ class InvoicesOrm extends orm_1.ZOrm {
246
269
  paid_at DATETIME,
247
270
  checkout_url VARCHAR(512),
248
271
  times_sent INT NOT NULL DEFAULT 0,
272
+ archived_at DATETIME NULL,
249
273
  metadata JSON NULL,
250
274
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
251
275
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
@@ -50,7 +50,7 @@ export declare class InvoiceService {
50
50
  private ensureSubscriptionInvoiceSchema;
51
51
  private ensureSubsidyItemTypeSchema;
52
52
  private ensureSentCountSchema;
53
- private ensureArchivedStatusSchema;
53
+ private ensureArchivedAtSchema;
54
54
  private ensureInvoicePaymentSchema;
55
55
  private generateInvoiceNumber;
56
56
  private getWebhookUrl;
@@ -88,6 +88,7 @@ export declare class InvoiceService {
88
88
  },
89
89
  ): Promise<ZInvoice>;
90
90
  archiveInvoice(invoiceId: number): Promise<ZInvoice>;
91
+ unarchiveInvoice(invoiceId: number): Promise<ZInvoice>;
91
92
  duplicateInvoice(
92
93
  sourceInvoiceId: number,
93
94
  customerId: number,
@@ -70,7 +70,7 @@ class InvoiceService {
70
70
  await this.ensureInvoicePaymentSchema();
71
71
  await this.ensureSubsidyItemTypeSchema();
72
72
  await this.ensureSentCountSchema();
73
- await this.ensureArchivedStatusSchema();
73
+ await this.ensureArchivedAtSchema();
74
74
  }
75
75
  async ensurePayTokenSchema() {
76
76
  const table = this.invoicesOrm.alias;
@@ -142,17 +142,14 @@ class InvoiceService {
142
142
  );
143
143
  }
144
144
  }
145
- async ensureArchivedStatusSchema() {
145
+ async ensureArchivedAtSchema() {
146
146
  const table = this.invoicesOrm.alias;
147
147
  const rows = await this.opt.sqlService.exec({
148
- query: `SELECT COLUMN_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=:schema AND TABLE_NAME=:tableName AND COLUMN_NAME='status' LIMIT 1`,
148
+ query: `SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=:schema AND TABLE_NAME=:tableName AND COLUMN_NAME='archived_at' LIMIT 1`,
149
149
  params: { schema: this.opt.sqlService.database, tableName: table },
150
150
  });
151
- const colType = rows?.[0]?.COLUMN_TYPE ?? '';
152
- if (colType && !colType.includes('archived')) {
153
- await this.opt.sqlService.query(
154
- `ALTER TABLE \`${table}\` MODIFY COLUMN status ENUM('draft','pending','paid','failed','canceled','expired','refunded','archived') NOT NULL DEFAULT 'draft'`,
155
- );
151
+ if (!rows?.[0]) {
152
+ await this.opt.sqlService.query(`ALTER TABLE \`${table}\` ADD COLUMN archived_at DATETIME NULL AFTER times_sent`);
156
153
  }
157
154
  }
158
155
  async ensureInvoicePaymentSchema() {
@@ -451,6 +448,8 @@ class InvoiceService {
451
448
  if (!invoice) throw new Error(`Invoice ${invoiceId} not found`);
452
449
  if (invoice.status !== 'draft')
453
450
  throw new Error(`Invoice ${invoice.invoice_number} cannot be edited (status: ${invoice.status})`);
451
+ if (this.invoicesOrm.isArchived(invoice))
452
+ throw new Error(`Invoice ${invoice.invoice_number} cannot be edited (archived)`);
454
453
  if ((invoice.times_sent ?? 0) > 0)
455
454
  throw new Error(
456
455
  `Invoice ${invoice.invoice_number} cannot be edited (already sent ${invoice.times_sent} time(s))`,
@@ -484,16 +483,36 @@ class InvoiceService {
484
483
  if (!invoice) {
485
484
  throw new Error(`Invoice ${invoiceId} not found`);
486
485
  }
487
- if (invoice.status === 'paid') {
488
- throw new Error(`Cannot archive a paid invoice (${invoice.invoice_number})`);
486
+ if (this.invoicesOrm.isArchived(invoice)) {
487
+ return invoice;
489
488
  }
490
- if (invoice.status === 'archived') {
489
+ await this.invoicesOrm.setArchivedAt(invoiceId);
490
+ // Audit log: record archive event
491
+ await this.invoiceStatusLogOrm.insert({
492
+ invoice_id: invoiceId,
493
+ from_status: invoice.status,
494
+ to_status: invoice.status,
495
+ actor_type: 'admin',
496
+ note: 'Invoice archived (archived_at set)',
497
+ });
498
+ return await this.invoicesOrm.findById(invoiceId);
499
+ }
500
+ async unarchiveInvoice(invoiceId) {
501
+ const invoice = await this.invoicesOrm.findById(invoiceId);
502
+ if (!invoice) {
503
+ throw new Error(`Invoice ${invoiceId} not found`);
504
+ }
505
+ if (!this.invoicesOrm.isArchived(invoice)) {
491
506
  return invoice;
492
507
  }
493
- await this.invoicesOrm.updateStatus(invoiceId, 'archived', undefined, undefined, {
494
- fromStatus: invoice.status,
495
- actorType: 'admin',
496
- note: 'Invoice archived',
508
+ await this.invoicesOrm.clearArchivedAt(invoiceId);
509
+ // Audit log: record unarchive event
510
+ await this.invoiceStatusLogOrm.insert({
511
+ invoice_id: invoiceId,
512
+ from_status: invoice.status,
513
+ to_status: invoice.status,
514
+ actor_type: 'admin',
515
+ note: 'Invoice unarchived (archived_at cleared)',
497
516
  });
498
517
  return await this.invoicesOrm.findById(invoiceId);
499
518
  }
@@ -18,7 +18,7 @@ export type ZCustomer = {
18
18
  updated_at?: string | Date;
19
19
  };
20
20
  export type ZInvoiceItemType = 'service' | 'subsidy';
21
- export type ZInvoiceStatus = 'draft' | 'pending' | 'paid' | 'failed' | 'canceled' | 'expired' | 'refunded' | 'archived';
21
+ export type ZInvoiceStatus = 'draft' | 'pending' | 'paid' | 'failed' | 'canceled' | 'expired' | 'refunded';
22
22
  export type ZInvoiceItem = {
23
23
  id?: number;
24
24
  invoice_id: number;
@@ -77,6 +77,7 @@ export type ZInvoice = {
77
77
  paid_at?: string | null;
78
78
  checkout_url?: string | null;
79
79
  times_sent?: number;
80
+ archived_at?: string | null;
80
81
  metadata?: any;
81
82
  created_at?: string | Date;
82
83
  updated_at?: string | Date;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ztechno_core",
3
- "version": "0.0.132",
3
+ "version": "0.0.133",
4
4
  "description": "Core files for ztechno framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",