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
|
@@ -6,6 +6,7 @@ import { hydrateCart } from './cart-hydrate.js';
|
|
|
6
6
|
import { resolveShippingPrice } from './shipping.js';
|
|
7
7
|
import { generateOrderNumber } from './order-number.js';
|
|
8
8
|
import { sendOrderStatusEmail } from './email.js';
|
|
9
|
+
import { isPaymentMethodAllowed } from './payment-compat.js';
|
|
9
10
|
const STOCK_RESERVATION_TTL_MINUTES = 30;
|
|
10
11
|
async function purgeExpiredReservations() {
|
|
11
12
|
const db = getShopDb();
|
|
@@ -60,6 +61,10 @@ export async function createOrderFromCart(input) {
|
|
|
60
61
|
if (!shippingMethod || !shippingMethod.isActive) {
|
|
61
62
|
throw new Error('Shipping method not found or inactive.');
|
|
62
63
|
}
|
|
64
|
+
// Shipping ↔ payment compatibility: empty/null list = all payment methods allowed.
|
|
65
|
+
if (!isPaymentMethodAllowed(input.paymentMethod, shippingMethod.allowedPaymentMethods)) {
|
|
66
|
+
throw new Error(`Payment method "${input.paymentMethod}" not available for the selected shipping method.`);
|
|
67
|
+
}
|
|
63
68
|
// Hydrate cart server-side (authoritative pricing)
|
|
64
69
|
const snapshot = await hydrateCart(input.cartItems, { language: input.language });
|
|
65
70
|
if (snapshot.items.length === 0 || snapshot.itemCount === 0) {
|
|
@@ -244,6 +249,13 @@ export async function updateOrderStatus(orderId, status, opts = {}) {
|
|
|
244
249
|
void sendOrderStatusEmail(orderId, status);
|
|
245
250
|
return updated;
|
|
246
251
|
}
|
|
252
|
+
export async function setPaymentProviderRef(orderId, ref) {
|
|
253
|
+
const db = getShopDb();
|
|
254
|
+
await db
|
|
255
|
+
.update(shopOrdersTable)
|
|
256
|
+
.set({ paymentProviderRef: ref, updatedAt: new Date() })
|
|
257
|
+
.where(eq(shopOrdersTable.id, orderId));
|
|
258
|
+
}
|
|
247
259
|
export async function getOrderById(id) {
|
|
248
260
|
const db = getShopDb();
|
|
249
261
|
const [row] = await db.select().from(shopOrdersTable).where(eq(shopOrdersTable.id, id));
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when the payment method is allowed for the given shipping method.
|
|
3
|
+
* `allowedPaymentMethods` null/undefined/empty means "no restrictions".
|
|
4
|
+
*/
|
|
5
|
+
export declare function isPaymentMethodAllowed(paymentMethod: string, allowedPaymentMethods: string[] | null | undefined): boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when the payment method is allowed for the given shipping method.
|
|
3
|
+
* `allowedPaymentMethods` null/undefined/empty means "no restrictions".
|
|
4
|
+
*/
|
|
5
|
+
export function isPaymentMethodAllowed(paymentMethod, allowedPaymentMethods) {
|
|
6
|
+
if (!allowedPaymentMethods || allowedPaymentMethods.length === 0)
|
|
7
|
+
return true;
|
|
8
|
+
return allowedPaymentMethods.includes(paymentMethod);
|
|
9
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Field } from '../../types/fields.js';
|
|
2
2
|
export interface PopulatedShopField {
|
|
3
|
+
/** Netto w PLN (number, ≤6dp). Od 0.15.2. */
|
|
3
4
|
basePrice: number;
|
|
4
5
|
vatRate: number;
|
|
5
6
|
isActive: boolean;
|
|
@@ -7,6 +8,7 @@ export interface PopulatedShopField {
|
|
|
7
8
|
id: string;
|
|
8
9
|
sku: string | null;
|
|
9
10
|
name: Record<string, string> | null;
|
|
11
|
+
/** Netto delta w PLN (number, ≤6dp). Od 0.15.2. */
|
|
10
12
|
priceDelta: number;
|
|
11
13
|
stock: number | null;
|
|
12
14
|
attributes: Record<string, string> | null;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { shopShippingMethodsTable } from '../../db-postgres/schema/shop/index.js';
|
|
2
2
|
import type { ShopCarrierType } from '../../db-postgres/schema/shop/shippingMethod.js';
|
|
3
|
-
|
|
3
|
+
type RawShippingMethodRow = typeof shopShippingMethodsTable.$inferSelect;
|
|
4
|
+
export type ShippingMethodRow = Omit<RawShippingMethodRow, 'price'> & {
|
|
5
|
+
price: number;
|
|
6
|
+
};
|
|
4
7
|
export interface ShippingConditions {
|
|
5
8
|
freeAbove?: number;
|
|
6
9
|
}
|
|
@@ -11,6 +14,7 @@ export interface ShippingMethodInput {
|
|
|
11
14
|
vatRate: number;
|
|
12
15
|
carrierType?: ShopCarrierType;
|
|
13
16
|
conditions?: ShippingConditions | null;
|
|
17
|
+
allowedPaymentMethods?: string[] | null;
|
|
14
18
|
isActive?: boolean;
|
|
15
19
|
sortOrder?: number | null;
|
|
16
20
|
}
|
|
@@ -25,10 +29,14 @@ export declare function deleteShippingMethod(id: string): Promise<void>;
|
|
|
25
29
|
export declare function reorderShippingMethods(orderedIds: string[]): Promise<void>;
|
|
26
30
|
/**
|
|
27
31
|
* Resolve effective shipping cost for a given cart.
|
|
28
|
-
* Applies `conditions.freeAbove` threshold against the cart gross total.
|
|
29
|
-
*
|
|
32
|
+
* Applies `conditions.freeAbove` threshold against the cart gross total (grosze).
|
|
33
|
+
* method.price — PLN (numeric 20,6). Zwraca kwoty w groszach (integer) do snapshotu zamówienia.
|
|
30
34
|
*/
|
|
31
|
-
export declare function resolveShippingPrice(method:
|
|
35
|
+
export declare function resolveShippingPrice(method: {
|
|
36
|
+
price: number | string;
|
|
37
|
+
vatRate: number;
|
|
38
|
+
conditions: ShippingConditions | null | unknown;
|
|
39
|
+
}, cartTotalGross: number): {
|
|
32
40
|
net: number;
|
|
33
41
|
gross: number;
|
|
34
42
|
vat: number;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { asc, eq } from 'drizzle-orm';
|
|
2
2
|
import { shopShippingMethodsTable } from '../../db-postgres/schema/shop/index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { grossPlnFromNetPln, toCents } from '../pricing.js';
|
|
4
4
|
import { getShopDb } from './db.js';
|
|
5
|
+
function mapShippingRow(r) {
|
|
6
|
+
return { ...r, price: Number(r.price) };
|
|
7
|
+
}
|
|
5
8
|
function validate(input) {
|
|
6
9
|
if (!input.name || Object.keys(input.name).length === 0) {
|
|
7
10
|
throw new Error('Shipping method name (i18n) is required.');
|
|
8
11
|
}
|
|
9
|
-
if (!Number.
|
|
10
|
-
throw new Error('price must be non-negative
|
|
12
|
+
if (!Number.isFinite(input.price) || input.price < 0 || input.price > 1e9) {
|
|
13
|
+
throw new Error('price must be non-negative finite number (PLN, ≤ 1e9).');
|
|
11
14
|
}
|
|
12
15
|
if (!Number.isInteger(input.vatRate) || input.vatRate < 0 || input.vatRate > 100) {
|
|
13
16
|
throw new Error('vatRate must be integer 0..100.');
|
|
@@ -15,17 +18,18 @@ function validate(input) {
|
|
|
15
18
|
if (input.conditions?.freeAbove != null) {
|
|
16
19
|
const fa = input.conditions.freeAbove;
|
|
17
20
|
if (!Number.isInteger(fa) || fa < 0) {
|
|
18
|
-
throw new Error('conditions.freeAbove must be non-negative integer.');
|
|
21
|
+
throw new Error('conditions.freeAbove must be non-negative integer (grosze).');
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
25
|
export async function listShippingMethods(opts = {}) {
|
|
23
26
|
const db = getShopDb();
|
|
24
|
-
|
|
27
|
+
const rows = await db
|
|
25
28
|
.select()
|
|
26
29
|
.from(shopShippingMethodsTable)
|
|
27
30
|
.where(opts.activeOnly ? eq(shopShippingMethodsTable.isActive, true) : undefined)
|
|
28
31
|
.orderBy(asc(shopShippingMethodsTable.sortOrder), asc(shopShippingMethodsTable.createdAt));
|
|
32
|
+
return rows.map(mapShippingRow);
|
|
29
33
|
}
|
|
30
34
|
export async function getShippingMethod(id) {
|
|
31
35
|
const db = getShopDb();
|
|
@@ -33,7 +37,7 @@ export async function getShippingMethod(id) {
|
|
|
33
37
|
.select()
|
|
34
38
|
.from(shopShippingMethodsTable)
|
|
35
39
|
.where(eq(shopShippingMethodsTable.id, id));
|
|
36
|
-
return row
|
|
40
|
+
return row ? mapShippingRow(row) : null;
|
|
37
41
|
}
|
|
38
42
|
export async function createShippingMethod(input) {
|
|
39
43
|
validate(input);
|
|
@@ -43,15 +47,16 @@ export async function createShippingMethod(input) {
|
|
|
43
47
|
.values({
|
|
44
48
|
name: input.name,
|
|
45
49
|
description: input.description ?? null,
|
|
46
|
-
price: input.price,
|
|
50
|
+
price: String(input.price),
|
|
47
51
|
vatRate: input.vatRate,
|
|
48
52
|
carrierType: input.carrierType ?? 'none',
|
|
49
53
|
conditions: input.conditions ?? null,
|
|
54
|
+
allowedPaymentMethods: input.allowedPaymentMethods ?? null,
|
|
50
55
|
isActive: input.isActive ?? true,
|
|
51
56
|
sortOrder: input.sortOrder ?? null
|
|
52
57
|
})
|
|
53
58
|
.returning();
|
|
54
|
-
return row;
|
|
59
|
+
return mapShippingRow(row);
|
|
55
60
|
}
|
|
56
61
|
export async function updateShippingMethod(id, input) {
|
|
57
62
|
const db = getShopDb();
|
|
@@ -61,13 +66,15 @@ export async function updateShippingMethod(id, input) {
|
|
|
61
66
|
if (input.description !== undefined)
|
|
62
67
|
patch.description = input.description;
|
|
63
68
|
if (input.price !== undefined)
|
|
64
|
-
patch.price = input.price;
|
|
69
|
+
patch.price = String(input.price);
|
|
65
70
|
if (input.vatRate !== undefined)
|
|
66
71
|
patch.vatRate = input.vatRate;
|
|
67
72
|
if (input.carrierType !== undefined)
|
|
68
73
|
patch.carrierType = input.carrierType;
|
|
69
74
|
if (input.conditions !== undefined)
|
|
70
75
|
patch.conditions = input.conditions;
|
|
76
|
+
if (input.allowedPaymentMethods !== undefined)
|
|
77
|
+
patch.allowedPaymentMethods = input.allowedPaymentMethods;
|
|
71
78
|
if (input.isActive !== undefined)
|
|
72
79
|
patch.isActive = input.isActive;
|
|
73
80
|
if (input.sortOrder !== undefined)
|
|
@@ -79,7 +86,7 @@ export async function updateShippingMethod(id, input) {
|
|
|
79
86
|
.returning();
|
|
80
87
|
if (!row)
|
|
81
88
|
throw new Error('Shipping method not found');
|
|
82
|
-
return row;
|
|
89
|
+
return mapShippingRow(row);
|
|
83
90
|
}
|
|
84
91
|
export async function deleteShippingMethod(id) {
|
|
85
92
|
const db = getShopDb();
|
|
@@ -97,15 +104,18 @@ export async function reorderShippingMethods(orderedIds) {
|
|
|
97
104
|
}
|
|
98
105
|
/**
|
|
99
106
|
* Resolve effective shipping cost for a given cart.
|
|
100
|
-
* Applies `conditions.freeAbove` threshold against the cart gross total.
|
|
101
|
-
*
|
|
107
|
+
* Applies `conditions.freeAbove` threshold against the cart gross total (grosze).
|
|
108
|
+
* method.price — PLN (numeric 20,6). Zwraca kwoty w groszach (integer) do snapshotu zamówienia.
|
|
102
109
|
*/
|
|
103
110
|
export function resolveShippingPrice(method, cartTotalGross) {
|
|
104
111
|
const cond = method.conditions ?? null;
|
|
105
112
|
if (cond?.freeAbove != null && cartTotalGross >= cond.freeAbove) {
|
|
106
113
|
return { net: 0, gross: 0, vat: 0, isFree: true };
|
|
107
114
|
}
|
|
108
|
-
const
|
|
109
|
-
|
|
115
|
+
const priceNetPln = Number(method.price);
|
|
116
|
+
const priceGrossPln = grossPlnFromNetPln(priceNetPln, method.vatRate);
|
|
117
|
+
const net = toCents(priceNetPln);
|
|
118
|
+
const gross = toCents(priceGrossPln);
|
|
119
|
+
return { net, gross, vat: gross - net, isFree: false };
|
|
110
120
|
}
|
|
111
121
|
export { validate as validateShippingMethodInput };
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { shopProductsTable, shopProductVariantsTable } from '../../db-postgres/schema/shop/index.js';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
type RawShopDataRow = typeof shopProductsTable.$inferSelect;
|
|
3
|
+
type RawVariantRow = typeof shopProductVariantsTable.$inferSelect;
|
|
4
|
+
export type ShopDataRow = Omit<RawShopDataRow, 'basePrice'> & {
|
|
5
|
+
basePrice: number;
|
|
6
|
+
};
|
|
7
|
+
export type VariantRow = Omit<RawVariantRow, 'priceDelta'> & {
|
|
8
|
+
priceDelta: number;
|
|
9
|
+
};
|
|
4
10
|
export interface ShopDataWithVariants extends ShopDataRow {
|
|
5
11
|
variants: VariantRow[];
|
|
6
12
|
}
|
|
@@ -3,14 +3,21 @@ import { shopProductsTable, shopProductVariantsTable } from '../../db-postgres/s
|
|
|
3
3
|
import { entriesTable } from '../../db-postgres/schema/entry.js';
|
|
4
4
|
import { entryVersionsTable } from '../../db-postgres/schema/entryVersion.js';
|
|
5
5
|
import { getShopDb } from './db.js';
|
|
6
|
+
const MAX_PLN = 1e9;
|
|
6
7
|
function validateShopData(input) {
|
|
7
|
-
if (!Number.
|
|
8
|
-
throw new Error('basePrice must be a non-negative
|
|
8
|
+
if (!Number.isFinite(input.basePrice) || input.basePrice < 0 || input.basePrice > MAX_PLN) {
|
|
9
|
+
throw new Error('basePrice must be a non-negative finite number (PLN, ≤ 1e9).');
|
|
9
10
|
}
|
|
10
11
|
if (!Number.isInteger(input.vatRate) || input.vatRate < 0 || input.vatRate > 100) {
|
|
11
12
|
throw new Error('vatRate must be an integer between 0 and 100.');
|
|
12
13
|
}
|
|
13
14
|
}
|
|
15
|
+
function mapShopRow(r) {
|
|
16
|
+
return { ...r, basePrice: Number(r.basePrice) };
|
|
17
|
+
}
|
|
18
|
+
function mapVariantRow(v) {
|
|
19
|
+
return { ...v, priceDelta: Number(v.priceDelta) };
|
|
20
|
+
}
|
|
14
21
|
export async function getShopDataByEntry(entryId) {
|
|
15
22
|
const db = getShopDb();
|
|
16
23
|
const [row] = await db
|
|
@@ -24,18 +31,19 @@ export async function getShopDataByEntry(entryId) {
|
|
|
24
31
|
.from(shopProductVariantsTable)
|
|
25
32
|
.where(eq(shopProductVariantsTable.productId, row.id))
|
|
26
33
|
.orderBy(asc(shopProductVariantsTable.sortOrder), asc(shopProductVariantsTable.createdAt));
|
|
27
|
-
return { ...row, variants };
|
|
34
|
+
return { ...mapShopRow(row), variants: variants.map(mapVariantRow) };
|
|
28
35
|
}
|
|
29
36
|
export async function upsertShopData(entryId, input, variants) {
|
|
30
37
|
validateShopData(input);
|
|
31
38
|
const db = getShopDb();
|
|
32
39
|
const existing = await getShopDataByEntry(entryId);
|
|
33
40
|
let productId;
|
|
41
|
+
const basePriceSql = String(input.basePrice);
|
|
34
42
|
if (existing) {
|
|
35
43
|
const [updated] = await db
|
|
36
44
|
.update(shopProductsTable)
|
|
37
45
|
.set({
|
|
38
|
-
basePrice:
|
|
46
|
+
basePrice: basePriceSql,
|
|
39
47
|
vatRate: input.vatRate,
|
|
40
48
|
isActive: input.isActive ?? existing.isActive,
|
|
41
49
|
sortOrder: input.sortOrder ?? existing.sortOrder,
|
|
@@ -50,7 +58,7 @@ export async function upsertShopData(entryId, input, variants) {
|
|
|
50
58
|
.insert(shopProductsTable)
|
|
51
59
|
.values({
|
|
52
60
|
entryId,
|
|
53
|
-
basePrice:
|
|
61
|
+
basePrice: basePriceSql,
|
|
54
62
|
vatRate: input.vatRate,
|
|
55
63
|
isActive: input.isActive ?? true,
|
|
56
64
|
sortOrder: input.sortOrder
|
|
@@ -73,7 +81,7 @@ export async function upsertShopData(entryId, input, variants) {
|
|
|
73
81
|
.set({
|
|
74
82
|
sku: v.sku ?? null,
|
|
75
83
|
name: v.name ?? null,
|
|
76
|
-
priceDelta: v.priceDelta ?? 0,
|
|
84
|
+
priceDelta: String(v.priceDelta ?? 0),
|
|
77
85
|
stock: v.stock ?? null,
|
|
78
86
|
attributes: v.attributes ?? null
|
|
79
87
|
})
|
|
@@ -84,7 +92,7 @@ export async function upsertShopData(entryId, input, variants) {
|
|
|
84
92
|
productId,
|
|
85
93
|
sku: v.sku ?? null,
|
|
86
94
|
name: v.name ?? null,
|
|
87
|
-
priceDelta: v.priceDelta ?? 0,
|
|
95
|
+
priceDelta: String(v.priceDelta ?? 0),
|
|
88
96
|
stock: v.stock ?? null,
|
|
89
97
|
attributes: v.attributes ?? null
|
|
90
98
|
});
|
|
@@ -101,7 +109,7 @@ export async function upsertShopData(entryId, input, variants) {
|
|
|
101
109
|
productId,
|
|
102
110
|
sku: null,
|
|
103
111
|
name: null,
|
|
104
|
-
priceDelta: 0,
|
|
112
|
+
priceDelta: '0',
|
|
105
113
|
stock: null,
|
|
106
114
|
attributes: null
|
|
107
115
|
});
|
|
@@ -123,7 +131,7 @@ export async function getDefaultVariant(productId) {
|
|
|
123
131
|
.where(eq(shopProductVariantsTable.productId, productId))
|
|
124
132
|
.orderBy(asc(shopProductVariantsTable.createdAt))
|
|
125
133
|
.limit(1);
|
|
126
|
-
return v
|
|
134
|
+
return v ? mapVariantRow(v) : null;
|
|
127
135
|
}
|
|
128
136
|
export async function deleteShopData(entryId) {
|
|
129
137
|
const db = getShopDb();
|
|
@@ -170,7 +178,7 @@ export async function listShopEntries(opts = {}) {
|
|
|
170
178
|
entryId: r.entryId,
|
|
171
179
|
collectionSlug: r.collectionSlug,
|
|
172
180
|
shopId: r.shopId,
|
|
173
|
-
basePrice: r.basePrice,
|
|
181
|
+
basePrice: Number(r.basePrice),
|
|
174
182
|
vatRate: r.vatRate,
|
|
175
183
|
isActive: r.isActive,
|
|
176
184
|
variantCount: variants.length,
|