includio-cms 0.15.0 → 0.15.2

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 (83) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/DOCS.md +231 -1
  3. package/ROADMAP.md +7 -2
  4. package/dist/admin/client/shop/shipping-method-edit-page.svelte +1 -0
  5. package/dist/admin/client/shop/shipping-method-form.svelte +89 -21
  6. package/dist/admin/client/shop/shipping-method-form.svelte.d.ts +8 -1
  7. package/dist/admin/client/shop/shipping-method-new-page.svelte +1 -0
  8. package/dist/admin/client/shop/shipping-methods-list-page.svelte +7 -4
  9. package/dist/admin/client/shop/shop-products-list-page.svelte +2 -2
  10. package/dist/admin/components/fields/shop-field.svelte +63 -22
  11. package/dist/admin/remote/shop.remote.d.ts +16 -56
  12. package/dist/admin/remote/shop.remote.js +6 -4
  13. package/dist/cli/scaffold/admin.js +32 -0
  14. package/dist/db-postgres/schema/shop/order.d.ts +34 -0
  15. package/dist/db-postgres/schema/shop/order.js +2 -0
  16. package/dist/db-postgres/schema/shop/product.d.ts +4 -4
  17. package/dist/db-postgres/schema/shop/product.js +3 -2
  18. package/dist/db-postgres/schema/shop/productVariant.d.ts +4 -4
  19. package/dist/db-postgres/schema/shop/productVariant.js +3 -2
  20. package/dist/db-postgres/schema/shop/shippingMethod.d.ts +23 -4
  21. package/dist/db-postgres/schema/shop/shippingMethod.js +4 -2
  22. package/dist/shop/adapters/payu/client.d.ts +22 -0
  23. package/dist/shop/adapters/payu/client.js +78 -0
  24. package/dist/shop/adapters/payu/index.d.ts +24 -0
  25. package/dist/shop/adapters/payu/index.js +88 -0
  26. package/dist/shop/adapters/payu/payload.d.ts +48 -0
  27. package/dist/shop/adapters/payu/payload.js +48 -0
  28. package/dist/shop/adapters/payu/signature.d.ts +12 -0
  29. package/dist/shop/adapters/payu/signature.js +50 -0
  30. package/dist/shop/adapters/payu/status-map.d.ts +3 -0
  31. package/dist/shop/adapters/payu/status-map.js +14 -0
  32. package/dist/shop/cart/order-token-cookie.d.ts +9 -0
  33. package/dist/shop/cart/order-token-cookie.js +40 -0
  34. package/dist/shop/client/index.d.ts +64 -1
  35. package/dist/shop/client/index.js +9 -0
  36. package/dist/shop/client/use-order.svelte.d.ts +32 -0
  37. package/dist/shop/client/use-order.svelte.js +105 -0
  38. package/dist/shop/http/checkout-handler.js +47 -4
  39. package/dist/shop/http/index.d.ts +4 -0
  40. package/dist/shop/http/index.js +4 -0
  41. package/dist/shop/http/order-handler.d.ts +4 -0
  42. package/dist/shop/http/order-handler.js +85 -0
  43. package/dist/shop/http/refresh-payment-handler.d.ts +4 -0
  44. package/dist/shop/http/refresh-payment-handler.js +73 -0
  45. package/dist/shop/http/retry-payment-handler.d.ts +4 -0
  46. package/dist/shop/http/retry-payment-handler.js +99 -0
  47. package/dist/shop/http/retry-payment-logic.d.ts +2 -0
  48. package/dist/shop/http/retry-payment-logic.js +4 -0
  49. package/dist/shop/http/shipping-handler.js +2 -1
  50. package/dist/shop/http/webhook-handler.d.ts +4 -0
  51. package/dist/shop/http/webhook-handler.js +73 -0
  52. package/dist/shop/http/webhook-logic.d.ts +4 -0
  53. package/dist/shop/http/webhook-logic.js +21 -0
  54. package/dist/shop/index.d.ts +3 -1
  55. package/dist/shop/index.js +3 -1
  56. package/dist/shop/pricing.d.ts +4 -0
  57. package/dist/shop/pricing.js +18 -0
  58. package/dist/shop/server/cart-hydrate.js +6 -3
  59. package/dist/shop/server/email.js +18 -2
  60. package/dist/shop/server/order-access-url.d.ts +7 -0
  61. package/dist/shop/server/order-access-url.js +6 -0
  62. package/dist/shop/server/orders.d.ts +1 -0
  63. package/dist/shop/server/orders.js +12 -0
  64. package/dist/shop/server/payment-compat.d.ts +5 -0
  65. package/dist/shop/server/payment-compat.js +9 -0
  66. package/dist/shop/server/populate.d.ts +2 -0
  67. package/dist/shop/server/shipping.d.ts +12 -4
  68. package/dist/shop/server/shipping.js +24 -14
  69. package/dist/shop/server/shop-data.d.ts +8 -2
  70. package/dist/shop/server/shop-data.js +18 -10
  71. package/dist/shop/svelte/OrderStatus.svelte +368 -0
  72. package/dist/shop/svelte/OrderStatus.svelte.d.ts +14 -0
  73. package/dist/shop/svelte/index.d.ts +3 -0
  74. package/dist/shop/svelte/index.js +2 -0
  75. package/dist/shop/svelte/labels.d.ts +25 -0
  76. package/dist/shop/svelte/labels.js +41 -0
  77. package/dist/shop/types.d.ts +19 -1
  78. package/dist/updates/0.15.1/index.d.ts +2 -0
  79. package/dist/updates/0.15.1/index.js +27 -0
  80. package/dist/updates/0.15.2/index.d.ts +2 -0
  81. package/dist/updates/0.15.2/index.js +18 -0
  82. package/dist/updates/index.js +3 -1
  83. package/package.json +5 -1
@@ -27,6 +27,7 @@
27
27
  sku: string;
28
28
  name: string;
29
29
  priceDelta: string;
30
+ priceDeltaMode: InputMode;
30
31
  stock: string;
31
32
  }>
32
33
  >([]);
@@ -36,35 +37,34 @@
36
37
  let errorMessage = $state<string | null>(null);
37
38
  let successMessage = $state<string | null>(null);
38
39
 
39
- const inputPriceCents = $derived(Math.round(parseFloat(inputPrice || '0') * 100));
40
+ // PLN-precise math — storage w numeric(20,6). Round do groszy tylko przy prezentacji.
41
+ const inputPln = $derived(parseFloat(inputPrice || '0') || 0);
40
42
  const vat = $derived(Number(vatRate) || 0);
41
- const netCents = $derived(
42
- inputMode === 'net' ? inputPriceCents : Math.round(inputPriceCents / (1 + vat / 100))
43
- );
44
- const grossCents = $derived(
45
- inputMode === 'gross' ? inputPriceCents : Math.round(inputPriceCents * (1 + vat / 100))
46
- );
47
- const vatCents = $derived(grossCents - netCents);
43
+ const netPln = $derived(inputMode === 'net' ? inputPln : inputPln / (1 + vat / 100));
44
+ const grossPln = $derived(inputMode === 'gross' ? inputPln : inputPln * (1 + vat / 100));
45
+ const vatPln = $derived(grossPln - netPln);
48
46
 
49
- function formatCents(cents: number) {
50
- return (cents / 100).toFixed(2);
47
+ function formatPln(pln: number) {
48
+ return pln.toFixed(2);
51
49
  }
52
50
 
53
51
  function switchMode(newMode: InputMode) {
54
52
  if (newMode === inputMode) return;
55
53
  // Preserve economic value — if user typed gross, switch shows net (computed) in the input, and vice versa.
56
- const preservedCents = newMode === 'net' ? netCents : grossCents;
54
+ const preservedPln = newMode === 'net' ? netPln : grossPln;
57
55
  inputMode = newMode;
58
- inputPrice = formatCents(preservedCents);
56
+ inputPrice = formatPln(preservedPln);
59
57
  }
60
58
 
61
59
  $effect(() => {
62
60
  if (!loaded && dataQuery.ready && configQuery.ready) {
63
61
  const shop = dataQuery.current;
64
62
  if (shop) {
65
- // Shop storage is always netdefault UI to net when hydrating existing data.
66
- inputMode = 'net';
67
- inputPrice = (shop.basePrice / 100).toFixed(2);
63
+ // Hydratacja: pokazujemy brutto (zaokrąglone do 2dp) user widzi dokładnie to co wpisał
64
+ // jeśli wpisywał w trybie gross (bo netto w DB ma 6dp → brutto round-tripuje bez driftu).
65
+ inputMode = 'gross';
66
+ const grossInitial = Number(shop.basePrice) * (1 + Number(shop.vatRate) / 100);
67
+ inputPrice = formatPln(grossInitial);
68
68
  vatRate = shop.vatRate;
69
69
  isActive = shop.isActive;
70
70
  variants = shop.variants.map((v) => ({
@@ -76,7 +76,9 @@
76
76
  Object.values(v.name as Record<string, string>)[0] ?? ''
77
77
  )
78
78
  : '',
79
- priceDelta: (v.priceDelta / 100).toFixed(2),
79
+ // Delta hydratowana jako netto (kanoniczna), mode default 'net' dla istniejących.
80
+ priceDelta: formatPln(Number(v.priceDelta)),
81
+ priceDeltaMode: 'net' as InputMode,
80
82
  stock: v.stock == null ? '' : String(v.stock)
81
83
  }));
82
84
  } else {
@@ -87,16 +89,31 @@
87
89
  }
88
90
  });
89
91
 
92
+ // Konwersja delty variantu (w trybie wpisu user'a) do netto PLN (kanonicznego).
93
+ function variantDeltaNetPln(v: { priceDelta: string; priceDeltaMode: InputMode }): number {
94
+ const raw = parseFloat(v.priceDelta || '0') || 0;
95
+ return v.priceDeltaMode === 'net' ? raw : raw / (1 + vat / 100);
96
+ }
97
+
90
98
  function addVariant() {
91
99
  variants.push({
92
100
  id: undefined,
93
101
  sku: '',
94
102
  name: '',
95
103
  priceDelta: '0.00',
104
+ priceDeltaMode: 'gross',
96
105
  stock: ''
97
106
  });
98
107
  }
99
108
 
109
+ function switchVariantMode(i: number, newMode: InputMode) {
110
+ const v = variants[i];
111
+ if (v.priceDeltaMode === newMode) return;
112
+ const netDelta = variantDeltaNetPln(v);
113
+ const preserved = newMode === 'net' ? netDelta : netDelta * (1 + vat / 100);
114
+ variants[i] = { ...v, priceDeltaMode: newMode, priceDelta: formatPln(preserved) };
115
+ }
116
+
100
117
  function removeVariant(i: number) {
101
118
  variants.splice(i, 1);
102
119
  }
@@ -115,7 +132,7 @@
115
132
  await remotes.upsertShopDataForEntry({
116
133
  entryId,
117
134
  data: {
118
- basePrice: netCents,
135
+ basePrice: netPln,
119
136
  vatRate: Number(vatRate),
120
137
  isActive
121
138
  },
@@ -124,7 +141,7 @@
124
141
  id: v.id,
125
142
  sku: v.sku || null,
126
143
  name: v.name ? { pl: v.name } : null,
127
- priceDelta: Math.round(parseFloat(v.priceDelta || '0') * 100),
144
+ priceDelta: variantDeltaNetPln(v),
128
145
  stock: stockEnabled && v.stock !== '' ? parseInt(v.stock, 10) : null,
129
146
  attributes: null
130
147
  }))
@@ -210,15 +227,15 @@
210
227
  <div class="bg-muted/40 border-border grid grid-cols-3 gap-2 rounded-lg border p-2.5 text-center text-xs">
211
228
  <div>
212
229
  <div class="text-muted-foreground font-semibold uppercase tracking-wide">Netto</div>
213
- <div class="text-sm font-bold tabular-nums">{formatCents(netCents)} zł</div>
230
+ <div class="text-sm font-bold tabular-nums">{formatPln(netPln)} zł</div>
214
231
  </div>
215
232
  <div class="border-border border-x">
216
233
  <div class="text-muted-foreground font-semibold uppercase tracking-wide">VAT</div>
217
- <div class="text-sm font-bold tabular-nums">{formatCents(vatCents)} zł</div>
234
+ <div class="text-sm font-bold tabular-nums">{formatPln(vatPln)} zł</div>
218
235
  </div>
219
236
  <div>
220
237
  <div class="text-muted-foreground font-semibold uppercase tracking-wide">Brutto</div>
221
- <div class="text-primary text-sm font-bold tabular-nums">{formatCents(grossCents)} zł</div>
238
+ <div class="text-primary text-sm font-bold tabular-nums">{formatPln(grossPln)} zł</div>
222
239
  </div>
223
240
  </div>
224
241
  </div>
@@ -253,7 +270,31 @@
253
270
  />
254
271
  </label>
255
272
  <label class="block">
256
- <span class="text-muted-foreground mb-0.5 block text-xs">Zmiana ceny (PLN)</span>
273
+ <div class="mb-0.5 flex items-center justify-between gap-1">
274
+ <span class="text-muted-foreground text-xs">
275
+ Zmiana ceny ({v.priceDeltaMode === 'net' ? 'netto' : 'brutto'}, PLN)
276
+ </span>
277
+ <div class="bg-muted inline-flex rounded-md p-0.5 text-[10px]">
278
+ <button
279
+ type="button"
280
+ class="rounded px-1.5 py-0.5 {v.priceDeltaMode === 'net'
281
+ ? 'bg-background text-primary font-semibold shadow-sm'
282
+ : 'text-muted-foreground'}"
283
+ onclick={() => switchVariantMode(i, 'net')}
284
+ >
285
+ Netto
286
+ </button>
287
+ <button
288
+ type="button"
289
+ class="rounded px-1.5 py-0.5 {v.priceDeltaMode === 'gross'
290
+ ? 'bg-background text-primary font-semibold shadow-sm'
291
+ : 'text-muted-foreground'}"
292
+ onclick={() => switchVariantMode(i, 'gross')}
293
+ >
294
+ Brutto
295
+ </button>
296
+ </div>
297
+ </div>
257
298
  <input
258
299
  type="number"
259
300
  step="0.01"
@@ -4,6 +4,10 @@ export declare const getShopConfig: import("@sveltejs/kit").RemoteQueryFunction<
4
4
  vatRates: number[];
5
5
  features: Required<import("../../shop/types.js").ShopFeatures>;
6
6
  languages: import("../../types/languages.js").Language[];
7
+ paymentMethods: {
8
+ id: string;
9
+ label: import("../../shop/types.js").I18nText;
10
+ }[];
7
11
  } | null>;
8
12
  export declare const listShopProductEntries: import("@sveltejs/kit").RemoteQueryFunction<void, import("../../shop/server/shop-data.js").ShopEntryListItem[]>;
9
13
  export declare const getShopDataForEntry: import("@sveltejs/kit").RemoteQueryFunction<string, import("../../shop/server/shop-data.js").ShopDataWithVariants | null>;
@@ -27,34 +31,8 @@ export declare const upsertShopDataForEntry: import("@sveltejs/kit").RemoteComma
27
31
  export declare const deleteShopDataForEntry: import("@sveltejs/kit").RemoteCommand<string, Promise<{
28
32
  success: boolean;
29
33
  }>>;
30
- export declare const listShippingMethodsAdmin: import("@sveltejs/kit").RemoteQueryFunction<void, {
31
- id: string;
32
- name: Record<string, string>;
33
- createdAt: Date;
34
- sortOrder: number | null;
35
- description: Record<string, string> | null;
36
- vatRate: number;
37
- isActive: boolean;
38
- price: number;
39
- carrierType: string;
40
- conditions: {
41
- freeAbove?: number;
42
- } | null;
43
- }[]>;
44
- export declare const getShippingMethodForAdmin: import("@sveltejs/kit").RemoteQueryFunction<string, {
45
- id: string;
46
- name: Record<string, string>;
47
- createdAt: Date;
48
- sortOrder: number | null;
49
- description: Record<string, string> | null;
50
- vatRate: number;
51
- isActive: boolean;
52
- price: number;
53
- carrierType: string;
54
- conditions: {
55
- freeAbove?: number;
56
- } | null;
57
- } | null>;
34
+ export declare const listShippingMethodsAdmin: import("@sveltejs/kit").RemoteQueryFunction<void, import("../../shop/server/shipping.js").ShippingMethodRow[]>;
35
+ export declare const getShippingMethodForAdmin: import("@sveltejs/kit").RemoteQueryFunction<string, import("../../shop/server/shipping.js").ShippingMethodRow | null>;
58
36
  export declare const createShippingMethodCmd: import("@sveltejs/kit").RemoteCommand<{
59
37
  name: Record<string, string>;
60
38
  price: number;
@@ -64,22 +42,10 @@ export declare const createShippingMethodCmd: import("@sveltejs/kit").RemoteComm
64
42
  conditions?: {
65
43
  freeAbove?: number | undefined;
66
44
  } | null | undefined;
45
+ allowedPaymentMethods?: string[] | null | undefined;
67
46
  isActive?: boolean | undefined;
68
47
  sortOrder?: number | null | undefined;
69
- }, Promise<{
70
- id: string;
71
- name: Record<string, string>;
72
- createdAt: Date;
73
- sortOrder: number | null;
74
- description: Record<string, string> | null;
75
- vatRate: number;
76
- isActive: boolean;
77
- price: number;
78
- carrierType: string;
79
- conditions: {
80
- freeAbove?: number;
81
- } | null;
82
- }>>;
48
+ }, Promise<import("../../shop/server/shipping.js").ShippingMethodRow>>;
83
49
  export declare const updateShippingMethodCmd: import("@sveltejs/kit").RemoteCommand<{
84
50
  id: string;
85
51
  input: {
@@ -91,23 +57,11 @@ export declare const updateShippingMethodCmd: import("@sveltejs/kit").RemoteComm
91
57
  conditions?: {
92
58
  freeAbove?: number | undefined;
93
59
  } | null | undefined;
60
+ allowedPaymentMethods?: string[] | null | undefined;
94
61
  isActive?: boolean | undefined;
95
62
  sortOrder?: number | null | undefined;
96
63
  };
97
- }, Promise<{
98
- id: string;
99
- name: Record<string, string>;
100
- createdAt: Date;
101
- sortOrder: number | null;
102
- description: Record<string, string> | null;
103
- vatRate: number;
104
- isActive: boolean;
105
- price: number;
106
- carrierType: string;
107
- conditions: {
108
- freeAbove?: number;
109
- } | null;
110
- }>>;
64
+ }, Promise<import("../../shop/server/shipping.js").ShippingMethodRow>>;
111
65
  export declare const deleteShippingMethodCmd: import("@sveltejs/kit").RemoteCommand<string, Promise<{
112
66
  success: boolean;
113
67
  }>>;
@@ -126,6 +80,7 @@ export declare const listOrdersAdmin: import("@sveltejs/kit").RemoteQueryFunctio
126
80
  createdAt: Date;
127
81
  updatedAt: Date;
128
82
  language: string | null;
83
+ accessToken: string;
129
84
  consents: {
130
85
  id: string;
131
86
  accepted: boolean;
@@ -145,6 +100,7 @@ export declare const listOrdersAdmin: import("@sveltejs/kit").RemoteQueryFunctio
145
100
  shippingMethodId: string | null;
146
101
  carrierRef: string | null;
147
102
  paymentMethod: string | null;
103
+ paymentProviderRef: string | null;
148
104
  notes: string | null;
149
105
  }[]>;
150
106
  export declare const getOrderForAdmin: import("@sveltejs/kit").RemoteQueryFunction<string, {
@@ -155,6 +111,7 @@ export declare const getOrderForAdmin: import("@sveltejs/kit").RemoteQueryFuncti
155
111
  createdAt: Date;
156
112
  updatedAt: Date;
157
113
  language: string | null;
114
+ accessToken: string;
158
115
  consents: {
159
116
  id: string;
160
117
  accepted: boolean;
@@ -174,6 +131,7 @@ export declare const getOrderForAdmin: import("@sveltejs/kit").RemoteQueryFuncti
174
131
  shippingMethodId: string | null;
175
132
  carrierRef: string | null;
176
133
  paymentMethod: string | null;
134
+ paymentProviderRef: string | null;
177
135
  notes: string | null;
178
136
  };
179
137
  items: {
@@ -208,6 +166,7 @@ export declare const updateOrderStatusCmd: import("@sveltejs/kit").RemoteCommand
208
166
  createdAt: Date;
209
167
  updatedAt: Date;
210
168
  language: string | null;
169
+ accessToken: string;
211
170
  consents: {
212
171
  id: string;
213
172
  accepted: boolean;
@@ -227,6 +186,7 @@ export declare const updateOrderStatusCmd: import("@sveltejs/kit").RemoteCommand
227
186
  shippingMethodId: string | null;
228
187
  carrierRef: string | null;
229
188
  paymentMethod: string | null;
189
+ paymentProviderRef: string | null;
230
190
  notes: string | null;
231
191
  }>>;
232
192
  export declare const resendOrderEmailCmd: import("@sveltejs/kit").RemoteCommand<{
@@ -18,7 +18,8 @@ export const getShopConfig = query(async () => {
18
18
  currency: shop.currency,
19
19
  vatRates: shop.vatRates,
20
20
  features: shop.features,
21
- languages: getCMS().languages
21
+ languages: getCMS().languages,
22
+ paymentMethods: shop.payment.map((p) => ({ id: p.id, label: p.label }))
22
23
  };
23
24
  });
24
25
  export const listShopProductEntries = query(async () => {
@@ -30,7 +31,7 @@ export const getShopDataForEntry = query(z.string(), async (entryId) => {
30
31
  return getShopDataByEntry(entryId);
31
32
  });
32
33
  const shopDataInputSchema = z.object({
33
- basePrice: z.number().int().nonnegative(),
34
+ basePrice: z.number().nonnegative().max(1e9), // PLN (≤6dp)
34
35
  vatRate: z.number().int().min(0).max(100),
35
36
  isActive: z.boolean().optional(),
36
37
  sortOrder: z.number().int().nullable().optional()
@@ -39,7 +40,7 @@ const variantInputSchema = z.object({
39
40
  id: z.string().optional(),
40
41
  sku: z.string().nullable().optional(),
41
42
  name: z.record(z.string(), z.string()).nullable().optional(),
42
- priceDelta: z.number().int().optional(),
43
+ priceDelta: z.number().optional(), // PLN
43
44
  stock: z.number().int().nullable().optional(),
44
45
  attributes: z.record(z.string(), z.string()).nullable().optional()
45
46
  });
@@ -59,13 +60,14 @@ export const deleteShopDataForEntry = command(z.string(), async (entryId) => {
59
60
  const shippingMethodInputSchema = z.object({
60
61
  name: z.record(z.string(), z.string()),
61
62
  description: z.record(z.string(), z.string()).nullable().optional(),
62
- price: z.number().int().nonnegative(),
63
+ price: z.number().nonnegative().max(1e9), // PLN netto (≤6dp)
63
64
  vatRate: z.number().int().min(0).max(100),
64
65
  carrierType: z.string().optional(),
65
66
  conditions: z
66
67
  .object({ freeAbove: z.number().int().nonnegative().optional() })
67
68
  .nullable()
68
69
  .optional(),
70
+ allowedPaymentMethods: z.array(z.string()).nullable().optional(),
69
71
  isActive: z.boolean().optional(),
70
72
  sortOrder: z.number().int().nullable().optional()
71
73
  });
@@ -214,6 +214,38 @@ export const { GET } = createShippingMethodsHandler();
214
214
  import { createCheckoutHandler } from 'includio-cms/shop/http';
215
215
 
216
216
  export const { POST } = createCheckoutHandler();
217
+ `
218
+ },
219
+ {
220
+ path: 'api/shop/orders/[number]/+server.ts',
221
+ content: `${GENERATED_COMMENT_TS}
222
+ import { createOrderHandler } from 'includio-cms/shop/http';
223
+
224
+ export const { GET } = createOrderHandler();
225
+ `
226
+ },
227
+ {
228
+ path: 'api/shop/webhooks/[provider]/+server.ts',
229
+ content: `${GENERATED_COMMENT_TS}
230
+ import { createPaymentWebhookHandler } from 'includio-cms/shop/http';
231
+
232
+ export const { POST } = createPaymentWebhookHandler();
233
+ `
234
+ },
235
+ {
236
+ path: 'api/shop/orders/[number]/refresh-payment/+server.ts',
237
+ content: `${GENERATED_COMMENT_TS}
238
+ import { createRefreshPaymentHandler } from 'includio-cms/shop/http';
239
+
240
+ export const { POST } = createRefreshPaymentHandler();
241
+ `
242
+ },
243
+ {
244
+ path: 'api/shop/orders/[number]/retry-payment/+server.ts',
245
+ content: `${GENERATED_COMMENT_TS}
246
+ import { createRetryPaymentHandler } from 'includio-cms/shop/http';
247
+
248
+ export const { POST } = createRetryPaymentHandler();
217
249
  `
218
250
  },
219
251
  {
@@ -296,6 +296,23 @@ export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with
296
296
  identity: undefined;
297
297
  generated: undefined;
298
298
  }, {}, {}>;
299
+ paymentProviderRef: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
300
+ name: "payment_provider_ref";
301
+ tableName: "shop_orders";
302
+ dataType: "string";
303
+ columnType: "PgText";
304
+ data: string;
305
+ driverParam: string;
306
+ notNull: false;
307
+ hasDefault: false;
308
+ isPrimaryKey: false;
309
+ isAutoincrement: false;
310
+ hasRuntimeDefault: false;
311
+ enumValues: [string, ...string[]];
312
+ baseColumn: never;
313
+ identity: undefined;
314
+ generated: undefined;
315
+ }, {}, {}>;
299
316
  consents: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
300
317
  name: "consents";
301
318
  tableName: "shop_orders";
@@ -357,6 +374,23 @@ export declare const shopOrdersTable: import("drizzle-orm/pg-core/table", { with
357
374
  identity: undefined;
358
375
  generated: undefined;
359
376
  }, {}, {}>;
377
+ accessToken: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
378
+ name: "access_token";
379
+ tableName: "shop_orders";
380
+ dataType: "string";
381
+ columnType: "PgUUID";
382
+ data: string;
383
+ driverParam: string;
384
+ notNull: true;
385
+ hasDefault: true;
386
+ isPrimaryKey: false;
387
+ isAutoincrement: false;
388
+ hasRuntimeDefault: false;
389
+ enumValues: undefined;
390
+ baseColumn: never;
391
+ identity: undefined;
392
+ generated: undefined;
393
+ }, {}, {}>;
360
394
  createdAt: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
361
395
  name: "created_at";
362
396
  tableName: "shop_orders";
@@ -20,9 +20,11 @@ export const shopOrdersTable = pgTable('shop_orders', {
20
20
  carrierType: text('carrier_type'),
21
21
  carrierRef: text('carrier_ref'),
22
22
  paymentMethod: text('payment_method'),
23
+ paymentProviderRef: text('payment_provider_ref'),
23
24
  consents: jsonb('consents').$type(),
24
25
  notes: text('notes'),
25
26
  language: text('language'),
27
+ accessToken: uuid('access_token').defaultRandom().notNull(),
26
28
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
27
29
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
28
30
  });
@@ -39,10 +39,10 @@ export declare const shopProductsTable: import("drizzle-orm/pg-core/table", { wi
39
39
  basePrice: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
40
40
  name: "base_price";
41
41
  tableName: "shop_products";
42
- dataType: "number";
43
- columnType: "PgInteger";
44
- data: number;
45
- driverParam: string | number;
42
+ dataType: "string";
43
+ columnType: "PgNumeric";
44
+ data: string;
45
+ driverParam: string;
46
46
  notNull: true;
47
47
  hasDefault: false;
48
48
  isPrimaryKey: false;
@@ -1,4 +1,4 @@
1
- import { boolean, integer, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core';
1
+ import { boolean, integer, 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(),
@@ -6,7 +6,8 @@ export const shopProductsTable = pgTable('shop_products', {
6
6
  .notNull()
7
7
  .unique()
8
8
  .references(() => entriesTable.id, { onDelete: 'cascade' }),
9
- basePrice: integer('base_price').notNull(),
9
+ // PLN z 6dp (wzorzec PrestaShop DECIMAL(20,6)) — netto kanoniczne. Konwersja do groszy raz, przy snapshot zamówienia.
10
+ basePrice: numeric('base_price', { precision: 20, scale: 6 }).notNull(),
10
11
  vatRate: integer('vat_rate').notNull(),
11
12
  isActive: boolean('is_active').default(true).notNull(),
12
13
  sortOrder: integer('sort_order'),
@@ -75,10 +75,10 @@ export declare const shopProductVariantsTable: import("drizzle-orm/pg-core/table
75
75
  priceDelta: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
76
76
  name: "price_delta";
77
77
  tableName: "shop_product_variants";
78
- dataType: "number";
79
- columnType: "PgInteger";
80
- data: number;
81
- driverParam: string | number;
78
+ dataType: "string";
79
+ columnType: "PgNumeric";
80
+ data: string;
81
+ driverParam: string;
82
82
  notNull: true;
83
83
  hasDefault: true;
84
84
  isPrimaryKey: false;
@@ -1,4 +1,4 @@
1
- import { integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
1
+ import { integer, jsonb, numeric, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
2
2
  import { shopProductsTable } from './product.js';
3
3
  export const shopProductVariantsTable = pgTable('shop_product_variants', {
4
4
  id: uuid('id').primaryKey().defaultRandom(),
@@ -7,7 +7,8 @@ export const shopProductVariantsTable = pgTable('shop_product_variants', {
7
7
  .references(() => shopProductsTable.id, { onDelete: 'cascade' }),
8
8
  sku: text('sku'),
9
9
  name: jsonb('name').$type(),
10
- priceDelta: integer('price_delta').default(0).notNull(),
10
+ // PLN z 6dp (netto delta, może być ujemne w przyszłości — obecnie schema nonneg)
11
+ priceDelta: numeric('price_delta', { precision: 20, scale: 6 }).default('0').notNull(),
11
12
  stock: integer('stock'),
12
13
  attributes: jsonb('attributes').$type(),
13
14
  sortOrder: integer('sort_order'),
@@ -61,10 +61,10 @@ export declare const shopShippingMethodsTable: import("drizzle-orm/pg-core/table
61
61
  price: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
62
62
  name: "price";
63
63
  tableName: "shop_shipping_methods";
64
- dataType: "number";
65
- columnType: "PgInteger";
66
- data: number;
67
- driverParam: string | number;
64
+ dataType: "string";
65
+ columnType: "PgNumeric";
66
+ data: string;
67
+ driverParam: string;
68
68
  notNull: true;
69
69
  hasDefault: false;
70
70
  isPrimaryKey: false;
@@ -134,6 +134,25 @@ export declare const shopShippingMethodsTable: import("drizzle-orm/pg-core/table
134
134
  freeAbove?: number;
135
135
  };
136
136
  }>;
137
+ allowedPaymentMethods: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
138
+ name: "allowed_payment_methods";
139
+ tableName: "shop_shipping_methods";
140
+ dataType: "json";
141
+ columnType: "PgJsonb";
142
+ data: string[] | null;
143
+ driverParam: unknown;
144
+ notNull: false;
145
+ hasDefault: false;
146
+ isPrimaryKey: false;
147
+ isAutoincrement: false;
148
+ hasRuntimeDefault: false;
149
+ enumValues: undefined;
150
+ baseColumn: never;
151
+ identity: undefined;
152
+ generated: undefined;
153
+ }, {}, {
154
+ $type: string[] | null;
155
+ }>;
137
156
  isActive: import("drizzle-orm/pg-core", { with: { "resolution-mode": "require" } }).PgColumn<{
138
157
  name: "is_active";
139
158
  tableName: "shop_shipping_methods";
@@ -1,12 +1,14 @@
1
- import { boolean, integer, jsonb, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
1
+ import { boolean, integer, jsonb, numeric, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
2
2
  export const shopShippingMethodsTable = pgTable('shop_shipping_methods', {
3
3
  id: uuid('id').primaryKey().defaultRandom(),
4
4
  name: jsonb('name').$type().notNull(),
5
5
  description: jsonb('description').$type(),
6
- price: integer('price').notNull(),
6
+ // PLN z 6dp, netto kanoniczne. freeAbove (w conditions) — cents/grosze (porównywane z totalGross w groszach).
7
+ price: numeric('price', { precision: 20, scale: 6 }).notNull(),
7
8
  vatRate: integer('vat_rate').notNull(),
8
9
  carrierType: text('carrier_type').$type().default('none').notNull(),
9
10
  conditions: jsonb('conditions').$type(),
11
+ allowedPaymentMethods: jsonb('allowed_payment_methods').$type(),
10
12
  isActive: boolean('is_active').default(true).notNull(),
11
13
  sortOrder: integer('sort_order'),
12
14
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull()
@@ -0,0 +1,22 @@
1
+ import type { PayuOrderPayload } from './payload.js';
2
+ export type PayuEnvironment = 'sandbox' | 'production';
3
+ export declare function payuBaseUrl(env: PayuEnvironment): string;
4
+ export interface PayuClientOptions {
5
+ clientId: string;
6
+ clientSecret: string;
7
+ environment: PayuEnvironment;
8
+ fetch?: typeof fetch;
9
+ }
10
+ export declare class PayuClient {
11
+ private readonly opts;
12
+ private cachedToken;
13
+ private readonly fetchImpl;
14
+ constructor(opts: PayuClientOptions);
15
+ private get base();
16
+ getAccessToken(): Promise<string>;
17
+ createOrder(payload: PayuOrderPayload): Promise<{
18
+ redirectUri: string;
19
+ orderId: string;
20
+ }>;
21
+ getOrder(payuOrderId: string): Promise<unknown>;
22
+ }