@porulle/adapter-woocommerce 0.74.5 → 0.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +4 -1
- package/dist/orders.d.ts +8 -1
- package/dist/orders.js +31 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/webhooks.js +6 -1
- package/package.json +2 -2
- package/src/index.ts +4 -1
- package/src/orders.ts +29 -1
- package/src/webhooks.ts +6 -1
package/dist/webhooks.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
-
import { Err, Ok } from "@porulle/core";
|
|
2
|
+
import { Err, Ok, toMinorUnits } from "@porulle/core";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { wooProductSchema, wooVariationSchema } from "./catalog.js";
|
|
5
5
|
import { available } from "./inventory.js";
|
|
@@ -93,6 +93,8 @@ const trackingItem = z.object({
|
|
|
93
93
|
});
|
|
94
94
|
const refundSchema = z.object({
|
|
95
95
|
id,
|
|
96
|
+
/** What the merchant refunded, positive, in the store's currency: part of a line is less than the line. */
|
|
97
|
+
amount: z.string().nullish(),
|
|
96
98
|
line_items: z.array(z.object({ product_id: id, variation_id: id, quantity: z.number() })).default([]),
|
|
97
99
|
});
|
|
98
100
|
function meta(entries, key) {
|
|
@@ -176,6 +178,8 @@ export async function orderEvents(client, remoteOrderId) {
|
|
|
176
178
|
const refund = await client.get(`/wc/v3/orders/${encodeURIComponent(order.id)}/refunds/${encodeURIComponent(summary.id)}`, refundSchema);
|
|
177
179
|
if (!refund.ok)
|
|
178
180
|
return refund;
|
|
181
|
+
const currency = order.currency ?? client.credentials.currency;
|
|
182
|
+
const amount = currency ? toMinorUnits(refund.value.data.amount, currency) : undefined;
|
|
179
183
|
events.push({
|
|
180
184
|
kind: "refund.created",
|
|
181
185
|
remoteOrderId: order.id,
|
|
@@ -184,6 +188,7 @@ export async function orderEvents(client, remoteOrderId) {
|
|
|
184
188
|
const quantity = Math.abs(line.quantity);
|
|
185
189
|
return quantity > 0 ? [{ externalVariantId: line.variation_id !== "0" ? line.variation_id : line.product_id, quantity }] : [];
|
|
186
190
|
}),
|
|
191
|
+
...(amount === undefined ? {} : { amount: Math.abs(amount) }),
|
|
187
192
|
});
|
|
188
193
|
}
|
|
189
194
|
return Ok(events);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@porulle/adapter-woocommerce",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"zod": "^4.1.11",
|
|
19
|
-
"@porulle/core": "0.
|
|
19
|
+
"@porulle/core": "0.76.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^24.5.2",
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { pushCatalog, pushCaches } from "./catalog-push.js";
|
|
|
6
6
|
import { discoverStore, normalizeStoreDomain, probeStore, refusedStoreUrl, wooClient, wooCredentialsSchema } from "./client.js";
|
|
7
7
|
import type { WooClient, WooTransportOptions } from "./client.js";
|
|
8
8
|
import { inventoryFor, inventoryPage } from "./inventory.js";
|
|
9
|
-
import { cancelOrder, orderStatus, pushOrder } from "./orders.js";
|
|
9
|
+
import { cancelOrder, orderStatus, pushOrder, recordRefund } from "./orders.js";
|
|
10
10
|
import { decodeDelivery, orderEvents, registerWebhooks, unregisterWebhooks, verifyDelivery, webhookHealth, WOO_WEBHOOK_TOPICS } from "./webhooks.js";
|
|
11
11
|
|
|
12
12
|
export { normalizeStoreDomain, probeStore, refusedStoreUrl, WOO_BLOCKED_BY_FIREWALL } from "./client.js";
|
|
@@ -164,6 +164,9 @@ export function wooConnector(options: WooConnectorOptions = {}): ChannelConnecto
|
|
|
164
164
|
async cancelOrder(store, remoteId, input) {
|
|
165
165
|
return withClient(store, (client) => cancelOrder(client, remoteId, input));
|
|
166
166
|
},
|
|
167
|
+
async recordRefund(store, remoteId, input) {
|
|
168
|
+
return withClient(store, (client) => recordRefund(client, remoteId, input));
|
|
169
|
+
},
|
|
167
170
|
async pushCatalog(store, items, opts) {
|
|
168
171
|
return withClient(store, (client) => pushCatalog(client, store, items, opts, caches));
|
|
169
172
|
},
|
package/src/orders.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CHANNEL_CANCEL_REFUSED, CHANNEL_OUT_OF_STOCK, CHANNEL_TOTAL_MISMATCH, currencyExponent, Err, Ok, toMinorUnits } from "@porulle/core";
|
|
2
|
-
import type { ChannelCancelOrderInput, ChannelConnectorError, ChannelOrderSlice, ChannelOrderStatus, ChannelPushOrderResult, Result } from "@porulle/core";
|
|
2
|
+
import type { ChannelCancelOrderInput, ChannelConnectorError, ChannelRefundRecord, ChannelOrderSlice, ChannelOrderStatus, ChannelPushOrderResult, Result } from "@porulle/core";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import type { WooClient } from "./client.js";
|
|
5
5
|
import { available } from "./inventory.js";
|
|
@@ -200,6 +200,34 @@ export async function cancelOrder(client: WooClient, remoteId: string, input: Ch
|
|
|
200
200
|
return cancelled.ok ? Ok(undefined) : cancelled;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Books at the store a refund the marketplace already paid the shopper: `api_refund: false` moves no
|
|
205
|
+
* money, `api_restock` puts the stock back, and each line is the store's own order line for the variant.
|
|
206
|
+
*/
|
|
207
|
+
export async function recordRefund(client: WooClient, remoteId: string, input: ChannelRefundRecord): Promise<Result<{ remoteRefundId: string }, ChannelConnectorError>> {
|
|
208
|
+
const read = await client.get(`/wc/v3/orders/${encodeURIComponent(remoteId)}`, wooOrderSchema);
|
|
209
|
+
if (!read.ok) return read;
|
|
210
|
+
const order = read.value.data;
|
|
211
|
+
const currency = order.currency ?? client.credentials.currency;
|
|
212
|
+
if (!currency) return Err({ code: "WOO_CURRENCY_UNKNOWN", message: `Order ${remoteId} names no currency.`, retriable: false });
|
|
213
|
+
const decimals = client.credentials.priceDecimals;
|
|
214
|
+
const lineItems: Array<{ id: string; quantity: number; refund_total: string }> = [];
|
|
215
|
+
for (const line of input.lines) {
|
|
216
|
+
const storeLine = order.line_items.find((candidate) => (candidate.variation_id !== "0" ? candidate.variation_id : candidate.product_id) === line.externalVariantId);
|
|
217
|
+
if (!storeLine) return Err({ code: "CHANNEL_MAPPING_MISSING", message: `Order ${remoteId} has no line for ${line.externalVariantId}.`, retriable: false });
|
|
218
|
+
lineItems.push({ id: storeLine.id, quantity: line.quantity, refund_total: moneyString(line.amount, currency, decimals) });
|
|
219
|
+
}
|
|
220
|
+
const created = await client.send("POST", `/wc/v3/orders/${encodeURIComponent(remoteId)}/refunds`, {
|
|
221
|
+
amount: moneyString(input.amount, currency, decimals),
|
|
222
|
+
reason: input.reason,
|
|
223
|
+
api_refund: false,
|
|
224
|
+
api_restock: input.restock,
|
|
225
|
+
line_items: lineItems,
|
|
226
|
+
}, z.object({ id: z.union([z.number(), z.string()]).transform(String) }));
|
|
227
|
+
if (!created.ok) return Err({ code: created.error.code, message: `The store would not record the refund: ${created.error.message}`, retriable: created.error.retriable === true });
|
|
228
|
+
return Ok({ remoteRefundId: created.value.id });
|
|
229
|
+
}
|
|
230
|
+
|
|
203
231
|
export async function orderStatus(client: WooClient, remoteId: string): Promise<Result<ChannelOrderStatus, ChannelConnectorError>> {
|
|
204
232
|
const read = await client.get(`/wc/v3/orders/${encodeURIComponent(remoteId)}`, wooOrderSchema);
|
|
205
233
|
if (!read.ok) return read;
|
package/src/webhooks.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
-
import { Err, Ok } from "@porulle/core";
|
|
2
|
+
import { Err, Ok, toMinorUnits } from "@porulle/core";
|
|
3
3
|
import type { ChannelConnectorError, ChannelEvent, ChannelShipment, ChannelStore, ChannelWebhookEvent, ChannelWebhookHealth, Result } from "@porulle/core";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { wooProductSchema, wooVariationSchema } from "./catalog.js";
|
|
@@ -94,6 +94,8 @@ const trackingItem = z.object({
|
|
|
94
94
|
});
|
|
95
95
|
const refundSchema = z.object({
|
|
96
96
|
id,
|
|
97
|
+
/** What the merchant refunded, positive, in the store's currency: part of a line is less than the line. */
|
|
98
|
+
amount: z.string().nullish(),
|
|
97
99
|
line_items: z.array(z.object({ product_id: id, variation_id: id, quantity: z.number() })).default([]),
|
|
98
100
|
});
|
|
99
101
|
|
|
@@ -171,6 +173,8 @@ export async function orderEvents(client: WooClient, remoteOrderId: string): Pro
|
|
|
171
173
|
for (const summary of order.refunds) {
|
|
172
174
|
const refund = await client.get(`/wc/v3/orders/${encodeURIComponent(order.id)}/refunds/${encodeURIComponent(summary.id)}`, refundSchema);
|
|
173
175
|
if (!refund.ok) return refund;
|
|
176
|
+
const currency = order.currency ?? client.credentials.currency;
|
|
177
|
+
const amount = currency ? toMinorUnits(refund.value.data.amount, currency) : undefined;
|
|
174
178
|
events.push({
|
|
175
179
|
kind: "refund.created",
|
|
176
180
|
remoteOrderId: order.id,
|
|
@@ -179,6 +183,7 @@ export async function orderEvents(client: WooClient, remoteOrderId: string): Pro
|
|
|
179
183
|
const quantity = Math.abs(line.quantity);
|
|
180
184
|
return quantity > 0 ? [{ externalVariantId: line.variation_id !== "0" ? line.variation_id : line.product_id, quantity }] : [];
|
|
181
185
|
}),
|
|
186
|
+
...(amount === undefined ? {} : { amount: Math.abs(amount) }),
|
|
182
187
|
});
|
|
183
188
|
}
|
|
184
189
|
return Ok(events);
|