@porulle/adapter-woocommerce 0.76.0 → 0.77.1

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/webhooks.js CHANGED
@@ -96,6 +96,8 @@ const refundSchema = z.object({
96
96
  /** What the merchant refunded, positive, in the store's currency: part of a line is less than the line. */
97
97
  amount: z.string().nullish(),
98
98
  line_items: z.array(z.object({ product_id: id, variation_id: id, quantity: z.number() })).default([]),
99
+ /** Delivery refunded: one entry per order shipping item, total negative. */
100
+ shipping_lines: z.array(z.object({ total: z.string().nullish() })).default([]),
99
101
  });
100
102
  function meta(entries, key) {
101
103
  return entries.find((entry) => entry.key === key)?.value;
@@ -180,6 +182,9 @@ export async function orderEvents(client, remoteOrderId) {
180
182
  return refund;
181
183
  const currency = order.currency ?? client.credentials.currency;
182
184
  const amount = currency ? toMinorUnits(refund.value.data.amount, currency) : undefined;
185
+ const shipping = currency
186
+ ? refund.value.data.shipping_lines.reduce((sum, line) => sum + Math.abs(toMinorUnits(line.total, currency) ?? 0), 0)
187
+ : 0;
183
188
  events.push({
184
189
  kind: "refund.created",
185
190
  remoteOrderId: order.id,
@@ -189,6 +194,7 @@ export async function orderEvents(client, remoteOrderId) {
189
194
  return quantity > 0 ? [{ externalVariantId: line.variation_id !== "0" ? line.variation_id : line.product_id, quantity }] : [];
190
195
  }),
191
196
  ...(amount === undefined ? {} : { amount: Math.abs(amount) }),
197
+ ...(shipping > 0 ? { shippingAmount: shipping } : {}),
192
198
  });
193
199
  }
194
200
  return Ok(events);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@porulle/adapter-woocommerce",
3
- "version": "0.76.0",
3
+ "version": "0.77.1",
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.76.0"
19
+ "@porulle/core": "0.77.1"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^24.5.2",
package/src/orders.ts CHANGED
@@ -14,6 +14,7 @@ export const wooOrderSchema = z.object({
14
14
  date_created_gmt: z.string().nullish(),
15
15
  meta_data: z.array(z.object({ key: z.string(), value: z.unknown() })).default([]),
16
16
  line_items: z.array(z.object({ id, product_id: id, variation_id: id, quantity: z.number(), total: z.string().nullish() })).default([]),
17
+ shipping_lines: z.array(z.object({ id, total: z.string().nullish() })).default([]),
17
18
  refunds: z.array(z.object({ id, total: z.string().nullish() })).default([]),
18
19
  });
19
20
  export type WooOrder = z.infer<typeof wooOrderSchema>;
@@ -111,7 +112,12 @@ export async function pushOrder(client: WooClient, slice: ChannelOrderSlice, opt
111
112
 
112
113
  const currency = slice.currency;
113
114
  const decimals = client.credentials.priceDecimals;
114
- const discounts = allocate(slice.lines.map((line) => line.totalPrice), slice.discount?.amount ?? 0);
115
+ // The platform's own per-line discount when it sends one, so the store's line totals are what the
116
+ // platform refunds a line at; otherwise the slice's discount split here.
117
+ const shares = slice.lines.map((line) => line.discountAmount ?? 0);
118
+ const discounts = slice.discount !== undefined && shares.reduce((sum, share) => sum + share, 0) === slice.discount.amount
119
+ ? shares
120
+ : allocate(slice.lines.map((line) => line.totalPrice), slice.discount?.amount ?? 0);
115
121
  const [firstName = "", ...rest] = slice.customer.name.trim().split(/\s+/);
116
122
  const source = slice.customer.shippingAddress;
117
123
  const address = {
@@ -217,6 +223,13 @@ export async function recordRefund(client: WooClient, remoteId: string, input: C
217
223
  if (!storeLine) return Err({ code: "CHANNEL_MAPPING_MISSING", message: `Order ${remoteId} has no line for ${line.externalVariantId}.`, retriable: false });
218
224
  lineItems.push({ id: storeLine.id, quantity: line.quantity, refund_total: moneyString(line.amount, currency, decimals) });
219
225
  }
226
+ // Delivery is refunded against the order's shipping item, as wp-admin does it.
227
+ const shippingAmount = input.shippingAmount ?? 0;
228
+ if (shippingAmount > 0) {
229
+ const shippingLine = order.shipping_lines[0];
230
+ if (!shippingLine) return Err({ code: "CHANNEL_MAPPING_MISSING", message: `Order ${remoteId} has no delivery line to refund.`, retriable: false });
231
+ lineItems.push({ id: shippingLine.id, quantity: 0, refund_total: moneyString(shippingAmount, currency, decimals) });
232
+ }
220
233
  const created = await client.send("POST", `/wc/v3/orders/${encodeURIComponent(remoteId)}/refunds`, {
221
234
  amount: moneyString(input.amount, currency, decimals),
222
235
  reason: input.reason,
package/src/webhooks.ts CHANGED
@@ -97,6 +97,8 @@ const refundSchema = z.object({
97
97
  /** What the merchant refunded, positive, in the store's currency: part of a line is less than the line. */
98
98
  amount: z.string().nullish(),
99
99
  line_items: z.array(z.object({ product_id: id, variation_id: id, quantity: z.number() })).default([]),
100
+ /** Delivery refunded: one entry per order shipping item, total negative. */
101
+ shipping_lines: z.array(z.object({ total: z.string().nullish() })).default([]),
100
102
  });
101
103
 
102
104
  function meta(entries: Array<{ key: string; value: unknown }>, key: string): unknown {
@@ -175,6 +177,9 @@ export async function orderEvents(client: WooClient, remoteOrderId: string): Pro
175
177
  if (!refund.ok) return refund;
176
178
  const currency = order.currency ?? client.credentials.currency;
177
179
  const amount = currency ? toMinorUnits(refund.value.data.amount, currency) : undefined;
180
+ const shipping = currency
181
+ ? refund.value.data.shipping_lines.reduce((sum, line) => sum + Math.abs(toMinorUnits(line.total, currency) ?? 0), 0)
182
+ : 0;
178
183
  events.push({
179
184
  kind: "refund.created",
180
185
  remoteOrderId: order.id,
@@ -184,6 +189,7 @@ export async function orderEvents(client: WooClient, remoteOrderId: string): Pro
184
189
  return quantity > 0 ? [{ externalVariantId: line.variation_id !== "0" ? line.variation_id : line.product_id, quantity }] : [];
185
190
  }),
186
191
  ...(amount === undefined ? {} : { amount: Math.abs(amount) }),
192
+ ...(shipping > 0 ? { shippingAmount: shipping } : {}),
187
193
  });
188
194
  }
189
195
  return Ok(events);