includio-cms 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/API.md +58 -2
  2. package/CHANGELOG.md +105 -0
  3. package/DOCS.md +1 -1
  4. package/ROADMAP.md +8 -0
  5. package/dist/admin/auth-client.d.ts +42 -42
  6. package/dist/admin/client/admin/admin-layout.svelte +12 -2
  7. package/dist/admin/client/admin/admin-layout.svelte.d.ts +2 -1
  8. package/dist/admin/client/collection/data-table.svelte +0 -39
  9. package/dist/admin/client/collection/data-table.svelte.d.ts +0 -2
  10. package/dist/admin/client/shop/coupon-schema.d.ts +1 -1
  11. package/dist/admin/client/shop/refund-dialog.svelte +37 -1
  12. package/dist/admin/client/shop/refund-dialog.svelte.d.ts +3 -0
  13. package/dist/admin/client/shop/shop-order-detail-page.svelte +192 -0
  14. package/dist/admin/components/fields/field-renderer.svelte +6 -1
  15. package/dist/admin/components/fields/icon-field.svelte +86 -0
  16. package/dist/admin/components/fields/icon-field.svelte.d.ts +8 -0
  17. package/dist/admin/components/fields/icon-picker-dialog.svelte +174 -0
  18. package/dist/admin/components/fields/icon-picker-dialog.svelte.d.ts +11 -0
  19. package/dist/admin/components/fields/object-field.svelte +27 -7
  20. package/dist/admin/components/fields/shop-field.svelte +210 -20
  21. package/dist/admin/components/layout/layout-tabs.svelte +1 -0
  22. package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte +109 -0
  23. package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte.d.ts +9 -0
  24. package/dist/admin/helpers/build-icon-set-map.d.ts +8 -0
  25. package/dist/admin/helpers/build-icon-set-map.js +16 -0
  26. package/dist/admin/helpers/index.d.ts +2 -0
  27. package/dist/admin/helpers/index.js +2 -0
  28. package/dist/admin/remote/shop.remote.d.ts +116 -24
  29. package/dist/admin/remote/shop.remote.js +79 -6
  30. package/dist/admin/state/icon-sets.svelte.d.ts +9 -0
  31. package/dist/admin/state/icon-sets.svelte.js +20 -0
  32. package/dist/cli/scaffold/admin.js +2 -2
  33. package/dist/components/ui/checkbox/checkbox.svelte +3 -3
  34. package/dist/core/cms.d.ts +11 -2
  35. package/dist/core/cms.js +29 -0
  36. package/dist/core/fields/fieldSchemaToTs.js +7 -0
  37. package/dist/core/server/generator/fields.d.ts +2 -0
  38. package/dist/core/server/generator/fields.js +34 -1
  39. package/dist/core/server/generator/generator.js +2 -1
  40. package/dist/db-postgres/schema/shop/index.d.ts +1 -0
  41. package/dist/db-postgres/schema/shop/index.js +1 -0
  42. package/dist/db-postgres/schema/shop/invoice.d.ts +254 -0
  43. package/dist/db-postgres/schema/shop/invoice.js +27 -0
  44. package/dist/db-postgres/schema/shop/order.d.ts +107 -1
  45. package/dist/db-postgres/schema/shop/order.js +7 -1
  46. package/dist/db-postgres/schema/shop/payment.d.ts +20 -0
  47. package/dist/db-postgres/schema/shop/payment.js +4 -1
  48. package/dist/db-postgres/schema/shop/product.d.ts +20 -0
  49. package/dist/db-postgres/schema/shop/product.js +3 -1
  50. package/dist/db-postgres/schema/shop/productVariant.d.ts +12 -2
  51. package/dist/db-postgres/schema/shop/productVariant.js +22 -0
  52. package/dist/paraglide/messages/_index.d.ts +36 -3
  53. package/dist/paraglide/messages/_index.js +71 -3
  54. package/dist/paraglide/messages/en.d.ts +5 -0
  55. package/dist/paraglide/messages/en.js +14 -0
  56. package/dist/paraglide/messages/pl.d.ts +5 -0
  57. package/dist/paraglide/messages/pl.js +14 -0
  58. package/dist/shop/adapters/fakturownia/client.d.ts +28 -0
  59. package/dist/shop/adapters/fakturownia/client.js +67 -0
  60. package/dist/shop/adapters/fakturownia/index.d.ts +27 -0
  61. package/dist/shop/adapters/fakturownia/index.js +36 -0
  62. package/dist/shop/adapters/fakturownia/payload.d.ts +35 -0
  63. package/dist/shop/adapters/fakturownia/payload.js +45 -0
  64. package/dist/shop/cart/types.d.ts +1 -0
  65. package/dist/shop/client/index.d.ts +61 -0
  66. package/dist/shop/client/index.js +5 -1
  67. package/dist/shop/expiry.d.ts +35 -0
  68. package/dist/shop/expiry.js +68 -0
  69. package/dist/shop/http/balance-handler.d.ts +20 -0
  70. package/dist/shop/http/balance-handler.js +91 -0
  71. package/dist/shop/http/cart-handler.js +19 -0
  72. package/dist/shop/http/checkout-handler.js +30 -1
  73. package/dist/shop/http/index.d.ts +2 -0
  74. package/dist/shop/http/index.js +2 -0
  75. package/dist/shop/http/upcoming-handler.d.ts +16 -0
  76. package/dist/shop/http/upcoming-handler.js +65 -0
  77. package/dist/shop/http/webhook-handler.js +46 -9
  78. package/dist/shop/index.d.ts +7 -1
  79. package/dist/shop/index.js +10 -1
  80. package/dist/shop/nip.d.ts +12 -0
  81. package/dist/shop/nip.js +23 -0
  82. package/dist/shop/server/balance-payment.d.ts +40 -0
  83. package/dist/shop/server/balance-payment.js +140 -0
  84. package/dist/shop/server/cart-hydrate.js +2 -0
  85. package/dist/shop/server/init.d.ts +14 -0
  86. package/dist/shop/server/init.js +35 -0
  87. package/dist/shop/server/invoices.d.ts +64 -0
  88. package/dist/shop/server/invoices.js +237 -0
  89. package/dist/shop/server/orders.d.ts +38 -0
  90. package/dist/shop/server/orders.js +152 -2
  91. package/dist/shop/server/payment-policy.d.ts +35 -0
  92. package/dist/shop/server/payment-policy.js +55 -0
  93. package/dist/shop/server/payments.d.ts +29 -0
  94. package/dist/shop/server/payments.js +64 -0
  95. package/dist/shop/server/populate.d.ts +1 -1
  96. package/dist/shop/server/refund.d.ts +17 -12
  97. package/dist/shop/server/refund.js +96 -13
  98. package/dist/shop/server/shop-data.d.ts +4 -1
  99. package/dist/shop/server/shop-data.js +24 -2
  100. package/dist/shop/template.d.ts +13 -0
  101. package/dist/shop/template.js +98 -0
  102. package/dist/shop/types.d.ts +208 -1
  103. package/dist/shop/variant-attributes.d.ts +28 -0
  104. package/dist/shop/variant-attributes.js +69 -0
  105. package/dist/sveltekit/server/index.d.ts +1 -0
  106. package/dist/sveltekit/server/index.js +2 -0
  107. package/dist/types/cms.d.ts +4 -3
  108. package/dist/types/cms.schema.d.ts +1 -1
  109. package/dist/types/cms.schema.js +9 -0
  110. package/dist/types/fields.d.ts +21 -2
  111. package/dist/types/index.d.ts +1 -1
  112. package/dist/types/index.js +1 -1
  113. package/dist/types/plugins.d.ts +40 -0
  114. package/dist/types/plugins.js +4 -1
  115. package/dist/updates/0.26.1/index.d.ts +2 -0
  116. package/dist/updates/0.26.1/index.js +19 -0
  117. package/dist/updates/0.27.0/index.d.ts +2 -0
  118. package/dist/updates/0.27.0/index.js +50 -0
  119. package/dist/updates/0.28.0/index.d.ts +2 -0
  120. package/dist/updates/0.28.0/index.js +38 -0
  121. package/dist/updates/index.js +7 -1
  122. package/package.json +1 -1
  123. package/dist/paraglide/messages/hello_world.d.ts +0 -5
  124. package/dist/paraglide/messages/hello_world.js +0 -33
  125. package/dist/paraglide/messages/login_hello.d.ts +0 -16
  126. package/dist/paraglide/messages/login_hello.js +0 -34
  127. package/dist/paraglide/messages/login_please_login.d.ts +0 -16
  128. package/dist/paraglide/messages/login_please_login.js +0 -34
@@ -1,6 +1,6 @@
1
1
  import { mkdirSync, readFileSync, writeFileSync, existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- import { generateTsTypeFromFields, generateFlatTsTypeFromFields, generateInlineBlockTypeString, setGeneratorCustomFields } from './fields.js';
3
+ import { generateTsTypeFromFields, generateFlatTsTypeFromFields, generateInlineBlockTypeString, setGeneratorCustomFields, setGeneratorShopVariantAttributes } from './fields.js';
4
4
  import { generateTsTypeFromFormFields } from './formFields.js';
5
5
  import { generateZodSchemaStringFromFormFieldsAsString } from './formFieldSchemaToString.js';
6
6
  import { toPascalCase, quoteKey } from './utils.js';
@@ -312,6 +312,7 @@ export function generateRuntime(config) {
312
312
  }
313
313
  }
314
314
  setGeneratorCustomFields(customFields);
315
+ setGeneratorShopVariantAttributes(config.shop?.variantAttributes ?? {});
315
316
  createCmsRuntimeDir();
316
317
  generateTypes(config);
317
318
  generateAPI(config);
@@ -7,6 +7,7 @@ export * from './orderStatusHistory.js';
7
7
  export * from './payment.js';
8
8
  export * from './stockReservation.js';
9
9
  export * from './refunds.js';
10
+ export * from './invoice.js';
10
11
  export * from './webhookEvents.js';
11
12
  export * from './coupons.js';
12
13
  export * from './couponRedemptions.js';
@@ -7,6 +7,7 @@ export * from './orderStatusHistory.js';
7
7
  export * from './payment.js';
8
8
  export * from './stockReservation.js';
9
9
  export * from './refunds.js';
10
+ export * from './invoice.js';
10
11
  export * from './webhookEvents.js';
11
12
  export * from './coupons.js';
12
13
  export * from './couponRedemptions.js';
@@ -0,0 +1,254 @@
1
+ export type ShopInvoiceStatus = 'pending' | 'issued' | 'sent' | 'failed';
2
+ /**
3
+ * One invoice per order (`order_id` is unique → idempotency guard). `external_id`
4
+ * / `number` / `pdf_url` come from the invoicing provider once issued. The
5
+ * `attempts` / `next_retry_at` columns are reserved for a future automatic-retry
6
+ * mechanism; the current flow only retries manually from the admin.
7
+ */
8
+ export declare const shopInvoicesTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
9
+ name: "shop_invoices";
10
+ schema: undefined;
11
+ columns: {
12
+ id: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
13
+ name: "id";
14
+ tableName: "shop_invoices";
15
+ dataType: "string";
16
+ columnType: "PgUUID";
17
+ data: string;
18
+ driverParam: string;
19
+ notNull: true;
20
+ hasDefault: true;
21
+ isPrimaryKey: true;
22
+ isAutoincrement: false;
23
+ hasRuntimeDefault: false;
24
+ enumValues: undefined;
25
+ baseColumn: never;
26
+ identity: undefined;
27
+ generated: undefined;
28
+ }, {}, {}>;
29
+ orderId: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
30
+ name: "order_id";
31
+ tableName: "shop_invoices";
32
+ dataType: "string";
33
+ columnType: "PgUUID";
34
+ data: string;
35
+ driverParam: string;
36
+ notNull: true;
37
+ hasDefault: false;
38
+ isPrimaryKey: false;
39
+ isAutoincrement: false;
40
+ hasRuntimeDefault: false;
41
+ enumValues: undefined;
42
+ baseColumn: never;
43
+ identity: undefined;
44
+ generated: undefined;
45
+ }, {}, {}>;
46
+ provider: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
47
+ name: "provider";
48
+ tableName: "shop_invoices";
49
+ dataType: "string";
50
+ columnType: "PgText";
51
+ data: string;
52
+ driverParam: string;
53
+ notNull: true;
54
+ hasDefault: false;
55
+ isPrimaryKey: false;
56
+ isAutoincrement: false;
57
+ hasRuntimeDefault: false;
58
+ enumValues: [string, ...string[]];
59
+ baseColumn: never;
60
+ identity: undefined;
61
+ generated: undefined;
62
+ }, {}, {}>;
63
+ externalId: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
64
+ name: "external_id";
65
+ tableName: "shop_invoices";
66
+ dataType: "string";
67
+ columnType: "PgText";
68
+ data: string;
69
+ driverParam: string;
70
+ notNull: false;
71
+ hasDefault: false;
72
+ isPrimaryKey: false;
73
+ isAutoincrement: false;
74
+ hasRuntimeDefault: false;
75
+ enumValues: [string, ...string[]];
76
+ baseColumn: never;
77
+ identity: undefined;
78
+ generated: undefined;
79
+ }, {}, {}>;
80
+ number: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
81
+ name: "number";
82
+ tableName: "shop_invoices";
83
+ dataType: "string";
84
+ columnType: "PgText";
85
+ data: string;
86
+ driverParam: string;
87
+ notNull: false;
88
+ hasDefault: false;
89
+ isPrimaryKey: false;
90
+ isAutoincrement: false;
91
+ hasRuntimeDefault: false;
92
+ enumValues: [string, ...string[]];
93
+ baseColumn: never;
94
+ identity: undefined;
95
+ generated: undefined;
96
+ }, {}, {}>;
97
+ pdfUrl: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
98
+ name: "pdf_url";
99
+ tableName: "shop_invoices";
100
+ dataType: "string";
101
+ columnType: "PgText";
102
+ data: string;
103
+ driverParam: string;
104
+ notNull: false;
105
+ hasDefault: false;
106
+ isPrimaryKey: false;
107
+ isAutoincrement: false;
108
+ hasRuntimeDefault: false;
109
+ enumValues: [string, ...string[]];
110
+ baseColumn: never;
111
+ identity: undefined;
112
+ generated: undefined;
113
+ }, {}, {}>;
114
+ kind: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
115
+ name: "kind";
116
+ tableName: "shop_invoices";
117
+ dataType: "string";
118
+ columnType: "PgText";
119
+ data: string;
120
+ driverParam: string;
121
+ notNull: true;
122
+ hasDefault: true;
123
+ isPrimaryKey: false;
124
+ isAutoincrement: false;
125
+ hasRuntimeDefault: false;
126
+ enumValues: [string, ...string[]];
127
+ baseColumn: never;
128
+ identity: undefined;
129
+ generated: undefined;
130
+ }, {}, {}>;
131
+ status: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
132
+ name: "status";
133
+ tableName: "shop_invoices";
134
+ dataType: "string";
135
+ columnType: "PgText";
136
+ data: ShopInvoiceStatus;
137
+ driverParam: string;
138
+ notNull: true;
139
+ hasDefault: true;
140
+ isPrimaryKey: false;
141
+ isAutoincrement: false;
142
+ hasRuntimeDefault: false;
143
+ enumValues: [string, ...string[]];
144
+ baseColumn: never;
145
+ identity: undefined;
146
+ generated: undefined;
147
+ }, {}, {
148
+ $type: ShopInvoiceStatus;
149
+ }>;
150
+ attempts: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
151
+ name: "attempts";
152
+ tableName: "shop_invoices";
153
+ dataType: "number";
154
+ columnType: "PgInteger";
155
+ data: number;
156
+ driverParam: string | number;
157
+ notNull: true;
158
+ hasDefault: true;
159
+ isPrimaryKey: false;
160
+ isAutoincrement: false;
161
+ hasRuntimeDefault: false;
162
+ enumValues: undefined;
163
+ baseColumn: never;
164
+ identity: undefined;
165
+ generated: undefined;
166
+ }, {}, {}>;
167
+ nextRetryAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
168
+ name: "next_retry_at";
169
+ tableName: "shop_invoices";
170
+ dataType: "date";
171
+ columnType: "PgTimestamp";
172
+ data: Date;
173
+ driverParam: string;
174
+ notNull: false;
175
+ hasDefault: false;
176
+ isPrimaryKey: false;
177
+ isAutoincrement: false;
178
+ hasRuntimeDefault: false;
179
+ enumValues: undefined;
180
+ baseColumn: never;
181
+ identity: undefined;
182
+ generated: undefined;
183
+ }, {}, {}>;
184
+ lastError: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
185
+ name: "last_error";
186
+ tableName: "shop_invoices";
187
+ dataType: "string";
188
+ columnType: "PgText";
189
+ data: string;
190
+ driverParam: string;
191
+ notNull: false;
192
+ hasDefault: false;
193
+ isPrimaryKey: false;
194
+ isAutoincrement: false;
195
+ hasRuntimeDefault: false;
196
+ enumValues: [string, ...string[]];
197
+ baseColumn: never;
198
+ identity: undefined;
199
+ generated: undefined;
200
+ }, {}, {}>;
201
+ raw: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
202
+ name: "raw";
203
+ tableName: "shop_invoices";
204
+ dataType: "json";
205
+ columnType: "PgJsonb";
206
+ data: unknown;
207
+ driverParam: unknown;
208
+ notNull: false;
209
+ hasDefault: false;
210
+ isPrimaryKey: false;
211
+ isAutoincrement: false;
212
+ hasRuntimeDefault: false;
213
+ enumValues: undefined;
214
+ baseColumn: never;
215
+ identity: undefined;
216
+ generated: undefined;
217
+ }, {}, {}>;
218
+ createdAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
219
+ name: "created_at";
220
+ tableName: "shop_invoices";
221
+ dataType: "date";
222
+ columnType: "PgTimestamp";
223
+ data: Date;
224
+ driverParam: string;
225
+ notNull: true;
226
+ hasDefault: true;
227
+ isPrimaryKey: false;
228
+ isAutoincrement: false;
229
+ hasRuntimeDefault: false;
230
+ enumValues: undefined;
231
+ baseColumn: never;
232
+ identity: undefined;
233
+ generated: undefined;
234
+ }, {}, {}>;
235
+ updatedAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
236
+ name: "updated_at";
237
+ tableName: "shop_invoices";
238
+ dataType: "date";
239
+ columnType: "PgTimestamp";
240
+ data: Date;
241
+ driverParam: string;
242
+ notNull: true;
243
+ hasDefault: true;
244
+ isPrimaryKey: false;
245
+ isAutoincrement: false;
246
+ hasRuntimeDefault: false;
247
+ enumValues: undefined;
248
+ baseColumn: never;
249
+ identity: undefined;
250
+ generated: undefined;
251
+ }, {}, {}>;
252
+ };
253
+ dialect: "pg";
254
+ }>;
@@ -0,0 +1,27 @@
1
+ import { integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
2
+ import { shopOrdersTable } from './order.js';
3
+ /**
4
+ * One invoice per order (`order_id` is unique → idempotency guard). `external_id`
5
+ * / `number` / `pdf_url` come from the invoicing provider once issued. The
6
+ * `attempts` / `next_retry_at` columns are reserved for a future automatic-retry
7
+ * mechanism; the current flow only retries manually from the admin.
8
+ */
9
+ export const shopInvoicesTable = pgTable('shop_invoices', {
10
+ id: uuid('id').primaryKey().defaultRandom(),
11
+ orderId: uuid('order_id')
12
+ .notNull()
13
+ .unique()
14
+ .references(() => shopOrdersTable.id, { onDelete: 'cascade' }),
15
+ provider: text('provider').notNull(),
16
+ externalId: text('external_id'),
17
+ number: text('number'),
18
+ pdfUrl: text('pdf_url'),
19
+ kind: text('kind').notNull().default('vat'),
20
+ status: text('status').$type().notNull().default('pending'),
21
+ attempts: integer('attempts').notNull().default(0),
22
+ nextRetryAt: timestamp('next_retry_at', { withTimezone: true }),
23
+ lastError: text('last_error'),
24
+ raw: jsonb('raw'),
25
+ createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
26
+ updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
27
+ });
@@ -1,4 +1,4 @@
1
- import type { OrderStatus } from '../../../shop/types.js';
1
+ import type { OrderStatus, PartialPayment } from '../../../shop/types.js';
2
2
  export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
3
3
  name: "shop_orders";
4
4
  schema: undefined;
@@ -124,6 +124,40 @@ export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with
124
124
  identity: undefined;
125
125
  generated: undefined;
126
126
  }, {}, {}>;
127
+ customerNip: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
128
+ name: "customer_nip";
129
+ tableName: "shop_orders";
130
+ dataType: "string";
131
+ columnType: "PgText";
132
+ data: string;
133
+ driverParam: string;
134
+ notNull: false;
135
+ hasDefault: false;
136
+ isPrimaryKey: false;
137
+ isAutoincrement: false;
138
+ hasRuntimeDefault: false;
139
+ enumValues: [string, ...string[]];
140
+ baseColumn: never;
141
+ identity: undefined;
142
+ generated: undefined;
143
+ }, {}, {}>;
144
+ customerCompanyName: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
145
+ name: "customer_company_name";
146
+ tableName: "shop_orders";
147
+ dataType: "string";
148
+ columnType: "PgText";
149
+ data: string;
150
+ driverParam: string;
151
+ notNull: false;
152
+ hasDefault: false;
153
+ isPrimaryKey: false;
154
+ isAutoincrement: false;
155
+ hasRuntimeDefault: false;
156
+ enumValues: [string, ...string[]];
157
+ baseColumn: never;
158
+ identity: undefined;
159
+ generated: undefined;
160
+ }, {}, {}>;
127
161
  shippingAddress: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
128
162
  name: "shipping_address";
129
163
  tableName: "shop_orders";
@@ -143,6 +177,42 @@ export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with
143
177
  }, {}, {
144
178
  $type: Record<string, string>;
145
179
  }>;
180
+ billingAddress: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
181
+ name: "billing_address";
182
+ tableName: "shop_orders";
183
+ dataType: "json";
184
+ columnType: "PgJsonb";
185
+ data: Record<string, string>;
186
+ driverParam: unknown;
187
+ notNull: false;
188
+ hasDefault: false;
189
+ isPrimaryKey: false;
190
+ isAutoincrement: false;
191
+ hasRuntimeDefault: false;
192
+ enumValues: undefined;
193
+ baseColumn: never;
194
+ identity: undefined;
195
+ generated: undefined;
196
+ }, {}, {
197
+ $type: Record<string, string>;
198
+ }>;
199
+ invoiceRequested: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
200
+ name: "invoice_requested";
201
+ tableName: "shop_orders";
202
+ dataType: "boolean";
203
+ columnType: "PgBoolean";
204
+ data: boolean;
205
+ driverParam: boolean;
206
+ notNull: true;
207
+ hasDefault: true;
208
+ isPrimaryKey: false;
209
+ isAutoincrement: false;
210
+ hasRuntimeDefault: false;
211
+ enumValues: undefined;
212
+ baseColumn: never;
213
+ identity: undefined;
214
+ generated: undefined;
215
+ }, {}, {}>;
146
216
  totalNet: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
147
217
  name: "total_net";
148
218
  tableName: "shop_orders";
@@ -459,6 +529,42 @@ export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with
459
529
  identity: undefined;
460
530
  generated: undefined;
461
531
  }, {}, {}>;
532
+ partialPayment: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
533
+ name: "partial_payment";
534
+ tableName: "shop_orders";
535
+ dataType: "json";
536
+ columnType: "PgJsonb";
537
+ data: PartialPayment | null;
538
+ driverParam: unknown;
539
+ notNull: false;
540
+ hasDefault: false;
541
+ isPrimaryKey: false;
542
+ isAutoincrement: false;
543
+ hasRuntimeDefault: false;
544
+ enumValues: undefined;
545
+ baseColumn: never;
546
+ identity: undefined;
547
+ generated: undefined;
548
+ }, {}, {
549
+ $type: PartialPayment | null;
550
+ }>;
551
+ balanceOwed: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
552
+ name: "balance_owed";
553
+ tableName: "shop_orders";
554
+ dataType: "boolean";
555
+ columnType: "PgBoolean";
556
+ data: boolean;
557
+ driverParam: boolean;
558
+ notNull: true;
559
+ hasDefault: true;
560
+ isPrimaryKey: false;
561
+ isAutoincrement: false;
562
+ hasRuntimeDefault: false;
563
+ enumValues: undefined;
564
+ baseColumn: never;
565
+ identity: undefined;
566
+ generated: undefined;
567
+ }, {}, {}>;
462
568
  createdAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
463
569
  name: "created_at";
464
570
  tableName: "shop_orders";
@@ -1,4 +1,4 @@
1
- import { integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
1
+ import { boolean, integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
2
2
  import { shopShippingMethodsTable } from './shippingMethod.js';
3
3
  export const shopOrdersTable = pgTable('shop_orders', {
4
4
  id: uuid('id').primaryKey().defaultRandom(),
@@ -8,7 +8,11 @@ export const shopOrdersTable = pgTable('shop_orders', {
8
8
  customerEmail: text('customer_email').notNull(),
9
9
  customerName: text('customer_name'),
10
10
  customerPhone: text('customer_phone'),
11
+ customerNip: text('customer_nip'),
12
+ customerCompanyName: text('customer_company_name'),
11
13
  shippingAddress: jsonb('shipping_address').$type(),
14
+ billingAddress: jsonb('billing_address').$type(),
15
+ invoiceRequested: boolean('invoice_requested').default(false).notNull(),
12
16
  totalNet: integer('total_net').notNull(),
13
17
  totalGross: integer('total_gross').notNull(),
14
18
  vatAmount: integer('vat_amount').notNull(),
@@ -29,6 +33,8 @@ export const shopOrdersTable = pgTable('shop_orders', {
29
33
  notes: text('notes'),
30
34
  language: text('language'),
31
35
  accessToken: uuid('access_token').defaultRandom().notNull(),
36
+ partialPayment: jsonb('partial_payment').$type(),
37
+ balanceOwed: boolean('balance_owed').default(false).notNull(),
32
38
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
33
39
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
34
40
  });
@@ -1,4 +1,7 @@
1
1
  export type ShopPaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'cancelled';
2
+ /** `kind` distinguishes full / deposit / balance payment rows under paymentPolicy A-lite. */
3
+ export declare const shopPaymentKindEnum: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgEnum<["full", "deposit", "balance"]>;
4
+ export type ShopPaymentKind = 'full' | 'deposit' | 'balance';
2
5
  export declare const shopPaymentsTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
3
6
  name: "shop_payments";
4
7
  schema: undefined;
@@ -90,6 +93,23 @@ export declare const shopPaymentsTable: import("drizzle-orm/pg-core/table", { wi
90
93
  }, {}, {
91
94
  $type: ShopPaymentStatus;
92
95
  }>;
96
+ kind: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
97
+ name: "kind";
98
+ tableName: "shop_payments";
99
+ dataType: "string";
100
+ columnType: "PgEnumColumn";
101
+ data: "full" | "deposit" | "balance";
102
+ driverParam: string;
103
+ notNull: true;
104
+ hasDefault: true;
105
+ isPrimaryKey: false;
106
+ isAutoincrement: false;
107
+ hasRuntimeDefault: false;
108
+ enumValues: ["full", "deposit", "balance"];
109
+ baseColumn: never;
110
+ identity: undefined;
111
+ generated: undefined;
112
+ }, {}, {}>;
93
113
  amount: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
94
114
  name: "amount";
95
115
  tableName: "shop_payments";
@@ -1,5 +1,7 @@
1
- import { integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
1
+ import { integer, jsonb, pgEnum, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
2
2
  import { shopOrdersTable } from './order.js';
3
+ /** `kind` distinguishes full / deposit / balance payment rows under paymentPolicy A-lite. */
4
+ export const shopPaymentKindEnum = pgEnum('shop_payment_kind', ['full', 'deposit', 'balance']);
3
5
  export const shopPaymentsTable = pgTable('shop_payments', {
4
6
  id: uuid('id').primaryKey().defaultRandom(),
5
7
  orderId: uuid('order_id')
@@ -8,6 +10,7 @@ export const shopPaymentsTable = pgTable('shop_payments', {
8
10
  provider: text('provider').notNull(),
9
11
  providerRef: text('provider_ref'),
10
12
  status: text('status').$type().notNull().default('pending'),
13
+ kind: shopPaymentKindEnum('kind').notNull().default('full'),
11
14
  amount: integer('amount').notNull(),
12
15
  currency: text('currency').notNull(),
13
16
  raw: jsonb('raw'),
@@ -1,3 +1,4 @@
1
+ import type { PaymentPolicy } from '../../../shop/types.js';
1
2
  export declare const shopProductsTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
2
3
  name: "shop_products";
3
4
  schema: undefined;
@@ -121,6 +122,25 @@ export declare const shopProductsTable: import("drizzle-orm/pg-core/table", { wi
121
122
  identity: undefined;
122
123
  generated: undefined;
123
124
  }, {}, {}>;
125
+ paymentPolicy: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
126
+ name: "payment_policy";
127
+ tableName: "shop_products";
128
+ dataType: "json";
129
+ columnType: "PgJsonb";
130
+ data: PaymentPolicy | null;
131
+ driverParam: unknown;
132
+ notNull: false;
133
+ hasDefault: false;
134
+ isPrimaryKey: false;
135
+ isAutoincrement: false;
136
+ hasRuntimeDefault: false;
137
+ enumValues: undefined;
138
+ baseColumn: never;
139
+ identity: undefined;
140
+ generated: undefined;
141
+ }, {}, {
142
+ $type: PaymentPolicy | null;
143
+ }>;
124
144
  createdAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
125
145
  name: "created_at";
126
146
  tableName: "shop_products";
@@ -1,4 +1,4 @@
1
- import { boolean, integer, numeric, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core';
1
+ import { boolean, integer, jsonb, numeric, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core';
2
2
  import { entriesTable } from '../entry.js';
3
3
  export const shopProductsTable = pgTable('shop_products', {
4
4
  id: uuid('id').primaryKey().defaultRandom(),
@@ -13,6 +13,8 @@ export const shopProductsTable = pgTable('shop_products', {
13
13
  sortOrder: integer('sort_order'),
14
14
  // Null = alert disabled. When stock decrement crosses threshold, fire-and-forget admin email.
15
15
  lowStockThreshold: integer('low_stock_threshold'),
16
+ // Per-product payment policy. Null = full payment (legacy).
17
+ paymentPolicy: jsonb('payment_policy').$type(),
16
18
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
17
19
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
18
20
  });
@@ -1,3 +1,4 @@
1
+ import type { VariantAttribute } from '../../../shop/types.js';
1
2
  export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table", { with: { "resolution-mode": "require" } }).PgTableWithColumns<{
2
3
  name: "shop_product_variants";
3
4
  schema: undefined;
@@ -111,7 +112,7 @@ export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table
111
112
  tableName: "shop_product_variants";
112
113
  dataType: "json";
113
114
  columnType: "PgJsonb";
114
- data: Record<string, string>;
115
+ data: Record<string, unknown>;
115
116
  driverParam: unknown;
116
117
  notNull: false;
117
118
  hasDefault: false;
@@ -123,7 +124,7 @@ export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table
123
124
  identity: undefined;
124
125
  generated: undefined;
125
126
  }, {}, {
126
- $type: Record<string, string>;
127
+ $type: Record<string, unknown>;
127
128
  }>;
128
129
  sortOrder: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
129
130
  name: "sort_order";
@@ -162,3 +163,12 @@ export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table
162
163
  };
163
164
  dialect: "pg";
164
165
  }>;
166
+ /**
167
+ * Build `CREATE INDEX IF NOT EXISTS … USING gin ((attributes->'<key>'))` DDL
168
+ * statements — one per attribute marked `indexable: true`. Drizzle's static
169
+ * schema can't capture user-defined variantAttributes, so apply these at shop
170
+ * bootstrap (or via the migration in `src/lib/updates/0.27.0`).
171
+ * Index name pattern: `shop_variant_attr_<key>_gin_idx`.
172
+ * @internal
173
+ */
174
+ export declare function createVariantAttributeIndexes(attrs: Record<string, VariantAttribute>): string[];
@@ -14,3 +14,25 @@ export const shopProductVariantsTable = pgTable('shop_product_variants', {
14
14
  sortOrder: integer('sort_order'),
15
15
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull()
16
16
  });
17
+ const SAFE_KEY = /^[a-zA-Z][a-zA-Z0-9_]*$/;
18
+ /**
19
+ * Build `CREATE INDEX IF NOT EXISTS … USING gin ((attributes->'<key>'))` DDL
20
+ * statements — one per attribute marked `indexable: true`. Drizzle's static
21
+ * schema can't capture user-defined variantAttributes, so apply these at shop
22
+ * bootstrap (or via the migration in `src/lib/updates/0.27.0`).
23
+ * Index name pattern: `shop_variant_attr_<key>_gin_idx`.
24
+ * @internal
25
+ */
26
+ export function createVariantAttributeIndexes(attrs) {
27
+ const stmts = [];
28
+ for (const [key, attr] of Object.entries(attrs)) {
29
+ if (!attr.indexable)
30
+ continue;
31
+ if (!SAFE_KEY.test(key)) {
32
+ throw new Error(`variantAttribute key "${key}" is not a safe SQL identifier (allowed: [A-Za-z][A-Za-z0-9_]*).`);
33
+ }
34
+ stmts.push(`CREATE INDEX IF NOT EXISTS shop_variant_attr_${key}_gin_idx ` +
35
+ `ON shop_product_variants USING gin ((attributes->'${key}'))`);
36
+ }
37
+ return stmts;
38
+ }