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.
- package/CHANGELOG.md +61 -0
- package/DOCS.md +231 -1
- package/ROADMAP.md +7 -2
- package/dist/admin/client/shop/shipping-method-edit-page.svelte +1 -0
- package/dist/admin/client/shop/shipping-method-form.svelte +89 -21
- package/dist/admin/client/shop/shipping-method-form.svelte.d.ts +8 -1
- package/dist/admin/client/shop/shipping-method-new-page.svelte +1 -0
- package/dist/admin/client/shop/shipping-methods-list-page.svelte +7 -4
- package/dist/admin/client/shop/shop-products-list-page.svelte +2 -2
- package/dist/admin/components/fields/shop-field.svelte +63 -22
- package/dist/admin/remote/shop.remote.d.ts +16 -56
- package/dist/admin/remote/shop.remote.js +6 -4
- package/dist/cli/scaffold/admin.js +32 -0
- package/dist/db-postgres/schema/shop/order.d.ts +34 -0
- package/dist/db-postgres/schema/shop/order.js +2 -0
- package/dist/db-postgres/schema/shop/product.d.ts +4 -4
- package/dist/db-postgres/schema/shop/product.js +3 -2
- package/dist/db-postgres/schema/shop/productVariant.d.ts +4 -4
- package/dist/db-postgres/schema/shop/productVariant.js +3 -2
- package/dist/db-postgres/schema/shop/shippingMethod.d.ts +23 -4
- package/dist/db-postgres/schema/shop/shippingMethod.js +4 -2
- package/dist/shop/adapters/payu/client.d.ts +22 -0
- package/dist/shop/adapters/payu/client.js +78 -0
- package/dist/shop/adapters/payu/index.d.ts +24 -0
- package/dist/shop/adapters/payu/index.js +88 -0
- package/dist/shop/adapters/payu/payload.d.ts +48 -0
- package/dist/shop/adapters/payu/payload.js +48 -0
- package/dist/shop/adapters/payu/signature.d.ts +12 -0
- package/dist/shop/adapters/payu/signature.js +50 -0
- package/dist/shop/adapters/payu/status-map.d.ts +3 -0
- package/dist/shop/adapters/payu/status-map.js +14 -0
- package/dist/shop/cart/order-token-cookie.d.ts +9 -0
- package/dist/shop/cart/order-token-cookie.js +40 -0
- package/dist/shop/client/index.d.ts +64 -1
- package/dist/shop/client/index.js +9 -0
- package/dist/shop/client/use-order.svelte.d.ts +32 -0
- package/dist/shop/client/use-order.svelte.js +105 -0
- package/dist/shop/http/checkout-handler.js +47 -4
- package/dist/shop/http/index.d.ts +4 -0
- package/dist/shop/http/index.js +4 -0
- package/dist/shop/http/order-handler.d.ts +4 -0
- package/dist/shop/http/order-handler.js +85 -0
- package/dist/shop/http/refresh-payment-handler.d.ts +4 -0
- package/dist/shop/http/refresh-payment-handler.js +73 -0
- package/dist/shop/http/retry-payment-handler.d.ts +4 -0
- package/dist/shop/http/retry-payment-handler.js +99 -0
- package/dist/shop/http/retry-payment-logic.d.ts +2 -0
- package/dist/shop/http/retry-payment-logic.js +4 -0
- package/dist/shop/http/shipping-handler.js +2 -1
- package/dist/shop/http/webhook-handler.d.ts +4 -0
- package/dist/shop/http/webhook-handler.js +73 -0
- package/dist/shop/http/webhook-logic.d.ts +4 -0
- package/dist/shop/http/webhook-logic.js +21 -0
- package/dist/shop/index.d.ts +3 -1
- package/dist/shop/index.js +3 -1
- package/dist/shop/pricing.d.ts +4 -0
- package/dist/shop/pricing.js +18 -0
- package/dist/shop/server/cart-hydrate.js +6 -3
- package/dist/shop/server/email.js +18 -2
- package/dist/shop/server/order-access-url.d.ts +7 -0
- package/dist/shop/server/order-access-url.js +6 -0
- package/dist/shop/server/orders.d.ts +1 -0
- package/dist/shop/server/orders.js +12 -0
- package/dist/shop/server/payment-compat.d.ts +5 -0
- package/dist/shop/server/payment-compat.js +9 -0
- package/dist/shop/server/populate.d.ts +2 -0
- package/dist/shop/server/shipping.d.ts +12 -4
- package/dist/shop/server/shipping.js +24 -14
- package/dist/shop/server/shop-data.d.ts +8 -2
- package/dist/shop/server/shop-data.js +18 -10
- package/dist/shop/svelte/OrderStatus.svelte +368 -0
- package/dist/shop/svelte/OrderStatus.svelte.d.ts +14 -0
- package/dist/shop/svelte/index.d.ts +3 -0
- package/dist/shop/svelte/index.js +2 -0
- package/dist/shop/svelte/labels.d.ts +25 -0
- package/dist/shop/svelte/labels.js +41 -0
- package/dist/shop/types.d.ts +19 -1
- package/dist/updates/0.15.1/index.d.ts +2 -0
- package/dist/updates/0.15.1/index.js +27 -0
- package/dist/updates/0.15.2/index.d.ts +2 -0
- package/dist/updates/0.15.2/index.js +18 -0
- package/dist/updates/index.js +3 -1
- 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
|
-
|
|
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
|
|
42
|
-
|
|
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
|
|
50
|
-
return
|
|
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
|
|
54
|
+
const preservedPln = newMode === 'net' ? netPln : grossPln;
|
|
57
55
|
inputMode = newMode;
|
|
58
|
-
inputPrice =
|
|
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
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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">{
|
|
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">{
|
|
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">{
|
|
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
|
-
<
|
|
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
|
-
|
|
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().
|
|
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().
|
|
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().
|
|
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: "
|
|
43
|
-
columnType: "
|
|
44
|
-
data:
|
|
45
|
-
driverParam: string
|
|
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
|
-
|
|
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: "
|
|
79
|
-
columnType: "
|
|
80
|
-
data:
|
|
81
|
-
driverParam: string
|
|
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
|
-
|
|
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: "
|
|
65
|
-
columnType: "
|
|
66
|
-
data:
|
|
67
|
-
driverParam: string
|
|
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
|
-
|
|
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
|
+
}
|