includio-cms 0.15.1 → 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 (41) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/DOCS.md +1 -1
  3. package/ROADMAP.md +6 -1
  4. package/dist/admin/client/shop/shipping-method-form.svelte +24 -21
  5. package/dist/admin/client/shop/shipping-method-form.svelte.d.ts +1 -1
  6. package/dist/admin/client/shop/shipping-methods-list-page.svelte +7 -4
  7. package/dist/admin/client/shop/shop-products-list-page.svelte +2 -2
  8. package/dist/admin/components/fields/shop-field.svelte +63 -22
  9. package/dist/admin/remote/shop.remote.d.ts +4 -60
  10. package/dist/admin/remote/shop.remote.js +3 -3
  11. package/dist/db-postgres/schema/shop/product.d.ts +4 -4
  12. package/dist/db-postgres/schema/shop/product.js +3 -2
  13. package/dist/db-postgres/schema/shop/productVariant.d.ts +4 -4
  14. package/dist/db-postgres/schema/shop/productVariant.js +3 -2
  15. package/dist/db-postgres/schema/shop/shippingMethod.d.ts +4 -4
  16. package/dist/db-postgres/schema/shop/shippingMethod.js +3 -2
  17. package/dist/paraglide/messages/_index.d.ts +36 -3
  18. package/dist/paraglide/messages/_index.js +71 -3
  19. package/dist/paraglide/messages/en.d.ts +5 -0
  20. package/dist/paraglide/messages/en.js +14 -0
  21. package/dist/paraglide/messages/pl.d.ts +5 -0
  22. package/dist/paraglide/messages/pl.js +14 -0
  23. package/dist/shop/client/index.d.ts +1 -0
  24. package/dist/shop/pricing.d.ts +4 -0
  25. package/dist/shop/pricing.js +18 -0
  26. package/dist/shop/server/cart-hydrate.js +6 -3
  27. package/dist/shop/server/populate.d.ts +2 -0
  28. package/dist/shop/server/shipping.d.ts +11 -4
  29. package/dist/shop/server/shipping.js +21 -14
  30. package/dist/shop/server/shop-data.d.ts +8 -2
  31. package/dist/shop/server/shop-data.js +18 -10
  32. package/dist/updates/0.15.2/index.d.ts +2 -0
  33. package/dist/updates/0.15.2/index.js +18 -0
  34. package/dist/updates/index.js +2 -1
  35. package/package.json +1 -1
  36. package/dist/paraglide/messages/hello_world.d.ts +0 -5
  37. package/dist/paraglide/messages/hello_world.js +0 -33
  38. package/dist/paraglide/messages/login_hello.d.ts +0 -16
  39. package/dist/paraglide/messages/login_hello.js +0 -34
  40. package/dist/paraglide/messages/login_please_login.d.ts +0 -16
  41. package/dist/paraglide/messages/login_please_login.js +0 -34
package/CHANGELOG.md CHANGED
@@ -3,6 +3,33 @@
3
3
  All notable changes to includio-cms are documented here.
4
4
  Generated from `src/lib/updates/` — do not edit manually.
5
5
 
6
+ ## 0.15.2 — 2026-04-15
7
+
8
+ Shop: cena przechowywana jako numeric(20,6) — eliminacja driftu brutto/netto po reload; toggle netto/brutto per wariant.
9
+
10
+ ### Added
11
+ - Warianty produktu mają teraz toggle netto/brutto obok pola "Zmiana ceny" — spójne z toggle'em ceny bazowej. Delta zapisywana kanonicznie jako netto.
12
+
13
+ ### Fixed
14
+ - Shop: po wpisaniu ceny brutto (np. 65,00 zł przy VAT 23%) i refreshu, cena nie "ucieka" o ±1 grosz. Wartości przechowywane są jako PLN z 6 miejscami po przecinku (wzorzec PrestaShop), zamiast jednostek groszy — brutto zawsze odtwarzane z netto bez utraty informacji.
15
+ - Shipping: ta sama poprawka dla ceny metody wysyłki (stored jako netto PLN z 6dp).
16
+
17
+ ### Breaking
18
+ - Kolumny `shop_products.base_price`, `shop_product_variants.price_delta`, `shop_shipping_methods.price` zmieniły typ z `integer` (grosze) na `numeric(20,6)` (PLN). Snapshot zamówienia (`shop_orders.*`, `shop_order_items.price_*_snapshot`) pozostaje w groszach (`integer`) — KSeF-compatible.
19
+ - Publiczne typy `ShopDataWithVariants.basePrice`, `VariantRow.priceDelta`, `ShippingMethodRow.price` — wartość dalej `number`, ale wyrażona w PLN (nie groszach). Dla konsumentów SDK/populate: mnożenie × 100 jeśli potrzebujesz groszy.
20
+
21
+ ### Migration
22
+
23
+ ```sql
24
+ ALTER TABLE shop_products ALTER COLUMN base_price TYPE numeric(20,6) USING (base_price::numeric / 100);
25
+ ALTER TABLE shop_product_variants ALTER COLUMN price_delta TYPE numeric(20,6) USING (price_delta::numeric / 100);
26
+ ALTER TABLE shop_shipping_methods ALTER COLUMN price TYPE numeric(20,6) USING (price::numeric / 100);
27
+ ```
28
+
29
+ ### Notes
30
+
31
+ Migrację SQL trzeba uruchomić RAZ, PRZED `db:push` — dzieli istniejące wartości ÷100, bo stare dane były w groszach, a nowy typ przechowuje PLN. Po migracji `db:push` tylko zsynchronizuje schemat (bez zmiany danych).
32
+
6
33
  ## 0.15.1 — 2026-04-15
7
34
 
8
35
  Shop: PayU payment adapter + secure order access (token-gated view API, email link).
package/DOCS.md CHANGED
@@ -1,4 +1,4 @@
1
- # Includio CMS Documentation (v0.15.1)
1
+ # Includio CMS Documentation (v0.15.2)
2
2
 
3
3
  > This file is auto-generated from the docs site. For the latest version, update the package.
4
4
 
package/ROADMAP.md CHANGED
@@ -304,8 +304,13 @@
304
304
  - [x] `[feature]` `[P0]` Random Crockford base32 order numbers (`XXXXX-XXXXX`), unguessable
305
305
  - [x] `[feature]` `[P0]` CLI scaffold provisions all shop routes (admin + public API) in consumer app
306
306
  - [x] `[feature]` `[P1]` PayU payment adapter + webhook — shipped in 0.15.1 (access-token-gated order view, idempotent webhooks, MD5 signature, shipping↔payment compat, poll fallback)
307
- - [ ] `[feature]` `[P1]` Stripe payment adapter + webhook — deferred to 0.15.2
307
+ - [ ] `[feature]` `[P1]` Stripe payment adapter + webhook — deferred to 0.15.3
308
308
  - [ ] `[feature]` `[P2]` InPost carrier adapter (headless geowidget config) — deferred to 0.15.3
309
+
310
+ ## 0.15.2 — Price precision fix
311
+
312
+ - [x] `[fix]` `[P1]` Price drift on reload — storage jako `numeric(20,6)` (PLN z 6dp), brutto round-tripuje bez utraty ±1gr. Snapshot zamówienia dalej w groszach (KSeF). <!-- files: src/lib/db-postgres/schema/shop/product.ts, productVariant.ts, shippingMethod.ts, src/lib/shop/pricing.ts, src/lib/shop/server/cart-hydrate.ts, shipping.ts, shop-data.ts, src/lib/admin/components/fields/shop-field.svelte, src/lib/admin/client/shop/shipping-method-form.svelte -->
313
+ - [x] `[feature]` `[P2]` Variant price toggle netto/brutto (spójne z toggle\'em ceny bazowej)
309
314
  - [x] `[feature]` `[P2]` `nodemailerAdapter` — typowanie `transportOptions` jako `SMTPTransport.Options` (OAuth2, pool, itd.)
310
315
 
311
316
  ## 0.16.0 — SEO module
@@ -10,10 +10,10 @@
10
10
  export interface ShippingFormPayload {
11
11
  name: Record<string, string>;
12
12
  description: Record<string, string> | null;
13
- price: number;
13
+ price: number; // PLN (number, netto)
14
14
  vatRate: number;
15
15
  carrierType: CarrierType;
16
- conditions: { freeAbove?: number } | null;
16
+ conditions: { freeAbove?: number } | null; // freeAbove: grosze
17
17
  allowedPaymentMethods: string[] | null;
18
18
  isActive: boolean;
19
19
  sortOrder: number | null;
@@ -21,7 +21,7 @@
21
21
  export interface ShippingFormInitial {
22
22
  name?: Record<string, string> | unknown;
23
23
  description?: Record<string, string> | unknown | null;
24
- price?: number;
24
+ price?: number | string;
25
25
  vatRate?: number;
26
26
  carrierType?: string;
27
27
  conditions?: { freeAbove?: number } | null;
@@ -69,29 +69,32 @@
69
69
  )
70
70
  );
71
71
  type InputMode = 'net' | 'gross';
72
- let inputMode = $state<InputMode>(initial?.price != null ? 'net' : 'gross');
73
- let inputPrice = $state(initial?.price != null ? (initial.price / 100).toFixed(2) : '0.00');
72
+ // initial.price teraz PLN (number, netto) z API. Hydratujemy jako gross, żeby user widział dokładnie to co wpisał.
73
+ const initialNetPln = initial?.price != null ? Number(initial.price) : null;
74
+ const initialVat = Number(initial?.vatRate ?? vatRates[0] ?? 23);
75
+ let inputMode = $state<InputMode>(initialNetPln != null ? 'gross' : 'gross');
76
+ let inputPrice = $state(
77
+ initialNetPln != null
78
+ ? (initialNetPln * (1 + initialVat / 100)).toFixed(2)
79
+ : '0.00'
80
+ );
74
81
  let vatRate = $state<number | string>(initial?.vatRate ?? vatRates[0] ?? 23);
75
82
 
76
- const inputPriceCents = $derived(Math.round(parseFloat(inputPrice || '0') * 100));
83
+ const inputPln = $derived(parseFloat(inputPrice || '0') || 0);
77
84
  const vat = $derived(Number(vatRate) || 0);
78
- const netCents = $derived(
79
- inputMode === 'net' ? inputPriceCents : Math.round(inputPriceCents / (1 + vat / 100))
80
- );
81
- const grossCents = $derived(
82
- inputMode === 'gross' ? inputPriceCents : Math.round(inputPriceCents * (1 + vat / 100))
83
- );
84
- const vatCents = $derived(grossCents - netCents);
85
+ const netPln = $derived(inputMode === 'net' ? inputPln : inputPln / (1 + vat / 100));
86
+ const grossPln = $derived(inputMode === 'gross' ? inputPln : inputPln * (1 + vat / 100));
87
+ const vatPln = $derived(grossPln - netPln);
85
88
 
86
- function formatCents(cents: number) {
87
- return (cents / 100).toFixed(2);
89
+ function formatPln(pln: number) {
90
+ return pln.toFixed(2);
88
91
  }
89
92
 
90
93
  function switchMode(newMode: InputMode) {
91
94
  if (newMode === inputMode) return;
92
- const preservedCents = newMode === 'net' ? netCents : grossCents;
95
+ const preserved = newMode === 'net' ? netPln : grossPln;
93
96
  inputMode = newMode;
94
- inputPrice = formatCents(preservedCents);
97
+ inputPrice = formatPln(preserved);
95
98
  }
96
99
  let carrierType = $state<CarrierType>((initial?.carrierType as CarrierType) ?? 'none');
97
100
  let isActive = $state(initial?.isActive ?? true);
@@ -126,7 +129,7 @@
126
129
  await onsubmit({
127
130
  name: names,
128
131
  description: Object.values(descriptions).some((d) => d.length > 0) ? descriptions : null,
129
- price: netCents,
132
+ price: netPln,
130
133
  vatRate: Number(vatRate),
131
134
  carrierType,
132
135
  conditions: freeAboveEnabled
@@ -226,15 +229,15 @@
226
229
  <div class="bg-muted/40 border-border grid grid-cols-3 gap-2 rounded-lg border p-2.5 text-center text-xs">
227
230
  <div>
228
231
  <div class="text-muted-foreground font-semibold uppercase tracking-wide">Netto</div>
229
- <div class="text-sm font-bold tabular-nums">{formatCents(netCents)} zł</div>
232
+ <div class="text-sm font-bold tabular-nums">{formatPln(netPln)} zł</div>
230
233
  </div>
231
234
  <div class="border-border border-x">
232
235
  <div class="text-muted-foreground font-semibold uppercase tracking-wide">VAT</div>
233
- <div class="text-sm font-bold tabular-nums">{formatCents(vatCents)} zł</div>
236
+ <div class="text-sm font-bold tabular-nums">{formatPln(vatPln)} zł</div>
234
237
  </div>
235
238
  <div>
236
239
  <div class="text-muted-foreground font-semibold uppercase tracking-wide">Brutto</div>
237
- <div class="text-primary text-sm font-bold tabular-nums">{formatCents(grossCents)} zł</div>
240
+ <div class="text-primary text-sm font-bold tabular-nums">{formatPln(grossPln)} zł</div>
238
241
  </div>
239
242
  </div>
240
243
  <label class="flex items-center gap-2">
@@ -19,7 +19,7 @@ export interface ShippingFormPayload {
19
19
  export interface ShippingFormInitial {
20
20
  name?: Record<string, string> | unknown;
21
21
  description?: Record<string, string> | unknown | null;
22
- price?: number;
22
+ price?: number | string;
23
23
  vatRate?: number;
24
24
  carrierType?: string;
25
25
  conditions?: {
@@ -35,12 +35,15 @@
35
35
  }
36
36
  });
37
37
 
38
- function formatPrice(smallest: number) {
38
+ function formatPricePln(pln: number) {
39
39
  return new Intl.NumberFormat('pl-PL', {
40
40
  style: 'currency',
41
41
  currency: 'PLN',
42
42
  minimumFractionDigits: 2
43
- }).format(smallest / 100);
43
+ }).format(pln);
44
+ }
45
+ function formatPriceCents(cents: number) {
46
+ return formatPricePln(cents / 100);
44
47
  }
45
48
 
46
49
  async function doReorder(fromIndex: number, toIndex: number) {
@@ -143,11 +146,11 @@
143
146
  {resolveI18n(m.name as Record<string, string>, interfaceLanguage.current, '')}
144
147
  </a>
145
148
  </div>
146
- <div>{formatPrice(m.price)}</div>
149
+ <div>{formatPricePln(Number(m.price))}</div>
147
150
  <div>{m.vatRate}%</div>
148
151
  <div>
149
152
  {#if cond?.freeAbove != null}
150
- {formatPrice(cond.freeAbove)}
153
+ {formatPriceCents(cond.freeAbove)}
151
154
  {:else}
152
155
  <span class="text-muted-foreground text-xs">—</span>
153
156
  {/if}
@@ -13,12 +13,12 @@
13
13
  const entriesQuery = $derived(remotes.listShopProductEntries());
14
14
  const collectionsQuery = $derived(remotes.listShopableCollections());
15
15
 
16
- function formatPrice(smallest: number) {
16
+ function formatPrice(pln: number) {
17
17
  return new Intl.NumberFormat('pl-PL', {
18
18
  style: 'currency',
19
19
  currency: 'PLN',
20
20
  minimumFractionDigits: 2
21
- }).format(smallest / 100);
21
+ }).format(pln);
22
22
  }
23
23
 
24
24
  function resolveTitle(data: Record<string, unknown> | null, fallback: string): string {
@@ -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"
@@ -31,36 +31,8 @@ export declare const upsertShopDataForEntry: import("@sveltejs/kit").RemoteComma
31
31
  export declare const deleteShopDataForEntry: import("@sveltejs/kit").RemoteCommand<string, Promise<{
32
32
  success: boolean;
33
33
  }>>;
34
- export declare const listShippingMethodsAdmin: import("@sveltejs/kit").RemoteQueryFunction<void, {
35
- id: string;
36
- name: Record<string, string>;
37
- createdAt: Date;
38
- sortOrder: number | null;
39
- description: Record<string, string> | null;
40
- vatRate: number;
41
- isActive: boolean;
42
- price: number;
43
- carrierType: string;
44
- conditions: {
45
- freeAbove?: number;
46
- } | null;
47
- allowedPaymentMethods: string[] | null;
48
- }[]>;
49
- export declare const getShippingMethodForAdmin: import("@sveltejs/kit").RemoteQueryFunction<string, {
50
- id: string;
51
- name: Record<string, string>;
52
- createdAt: Date;
53
- sortOrder: number | null;
54
- description: Record<string, string> | null;
55
- vatRate: number;
56
- isActive: boolean;
57
- price: number;
58
- carrierType: string;
59
- conditions: {
60
- freeAbove?: number;
61
- } | null;
62
- allowedPaymentMethods: string[] | null;
63
- } | 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>;
64
36
  export declare const createShippingMethodCmd: import("@sveltejs/kit").RemoteCommand<{
65
37
  name: Record<string, string>;
66
38
  price: number;
@@ -73,21 +45,7 @@ export declare const createShippingMethodCmd: import("@sveltejs/kit").RemoteComm
73
45
  allowedPaymentMethods?: string[] | null | undefined;
74
46
  isActive?: boolean | undefined;
75
47
  sortOrder?: number | null | undefined;
76
- }, Promise<{
77
- id: string;
78
- name: Record<string, string>;
79
- createdAt: Date;
80
- sortOrder: number | null;
81
- description: Record<string, string> | null;
82
- vatRate: number;
83
- isActive: boolean;
84
- price: number;
85
- carrierType: string;
86
- conditions: {
87
- freeAbove?: number;
88
- } | null;
89
- allowedPaymentMethods: string[] | null;
90
- }>>;
48
+ }, Promise<import("../../shop/server/shipping.js").ShippingMethodRow>>;
91
49
  export declare const updateShippingMethodCmd: import("@sveltejs/kit").RemoteCommand<{
92
50
  id: string;
93
51
  input: {
@@ -103,21 +61,7 @@ export declare const updateShippingMethodCmd: import("@sveltejs/kit").RemoteComm
103
61
  isActive?: boolean | undefined;
104
62
  sortOrder?: number | null | undefined;
105
63
  };
106
- }, Promise<{
107
- id: string;
108
- name: Record<string, string>;
109
- createdAt: Date;
110
- sortOrder: number | null;
111
- description: Record<string, string> | null;
112
- vatRate: number;
113
- isActive: boolean;
114
- price: number;
115
- carrierType: string;
116
- conditions: {
117
- freeAbove?: number;
118
- } | null;
119
- allowedPaymentMethods: string[] | null;
120
- }>>;
64
+ }, Promise<import("../../shop/server/shipping.js").ShippingMethodRow>>;
121
65
  export declare const deleteShippingMethodCmd: import("@sveltejs/kit").RemoteCommand<string, Promise<{
122
66
  success: boolean;
123
67
  }>>;
@@ -31,7 +31,7 @@ export const getShopDataForEntry = query(z.string(), async (entryId) => {
31
31
  return getShopDataByEntry(entryId);
32
32
  });
33
33
  const shopDataInputSchema = z.object({
34
- basePrice: z.number().int().nonnegative(),
34
+ basePrice: z.number().nonnegative().max(1e9), // PLN (≤6dp)
35
35
  vatRate: z.number().int().min(0).max(100),
36
36
  isActive: z.boolean().optional(),
37
37
  sortOrder: z.number().int().nullable().optional()
@@ -40,7 +40,7 @@ const variantInputSchema = z.object({
40
40
  id: z.string().optional(),
41
41
  sku: z.string().nullable().optional(),
42
42
  name: z.record(z.string(), z.string()).nullable().optional(),
43
- priceDelta: z.number().int().optional(),
43
+ priceDelta: z.number().optional(), // PLN
44
44
  stock: z.number().int().nullable().optional(),
45
45
  attributes: z.record(z.string(), z.string()).nullable().optional()
46
46
  });
@@ -60,7 +60,7 @@ export const deleteShopDataForEntry = command(z.string(), async (entryId) => {
60
60
  const shippingMethodInputSchema = z.object({
61
61
  name: z.record(z.string(), z.string()),
62
62
  description: z.record(z.string(), z.string()).nullable().optional(),
63
- price: z.number().int().nonnegative(),
63
+ price: z.number().nonnegative().max(1e9), // PLN netto (≤6dp)
64
64
  vatRate: z.number().int().min(0).max(100),
65
65
  carrierType: z.string().optional(),
66
66
  conditions: z
@@ -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;
@@ -1,9 +1,10 @@
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(),
@@ -1,3 +1,36 @@
1
- export * from "./hello_world.js";
2
- export * from "./login_hello.js";
3
- export * from "./login_please_login.js";
1
+ export function hello_world(inputs: {
2
+ name: NonNullable<unknown>;
3
+ }, options?: {
4
+ locale?: "en" | "pl";
5
+ }): string;
6
+ /**
7
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
8
+ *
9
+ * - Changing this function will be over-written by the next build.
10
+ *
11
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
12
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
13
+ *
14
+ * @param {{}} inputs
15
+ * @param {{ locale?: "en" | "pl" }} options
16
+ * @returns {string}
17
+ */
18
+ declare function login_hello(inputs?: {}, options?: {
19
+ locale?: "en" | "pl";
20
+ }): string;
21
+ /**
22
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
23
+ *
24
+ * - Changing this function will be over-written by the next build.
25
+ *
26
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
27
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
28
+ *
29
+ * @param {{}} inputs
30
+ * @param {{ locale?: "en" | "pl" }} options
31
+ * @returns {string}
32
+ */
33
+ declare function login_please_login(inputs?: {}, options?: {
34
+ locale?: "en" | "pl";
35
+ }): string;
36
+ export { login_hello as login.hello, login_please_login as login.please_login };