diff --git a/src/actions/ebs-sync/ebs.js b/src/actions/ebs-sync/ebs.js
index d5a5414..24ba124 100644
--- a/src/actions/ebs-sync/ebs.js
+++ b/src/actions/ebs-sync/ebs.js
@@ -608,6 +608,17 @@ const WARRANTY_VITAMIX_ID = {
'070791': '70791',
};
+/**
+ * Strip the virtual-bundle '-VB' suffix from a bundle child SKU.
+ *
+ * Bundle children carry a '-VB' suffix in the order data, but EBS expects the
+ * original product SKU. Applied only to bundle items — simple products keep
+ * their SKU as-is.
+ */
+function stripBundleSuffix(sku) {
+ return String(sku || '').replace(/-VB$/, '');
+}
+
function buildLineItemsXml(order) {
const orderKey = order.friendlyId || order.id;
@@ -627,13 +638,15 @@ function buildLineItemsXml(order) {
if (item.custom?.linkedTo) continue;
if (item.bundleItems?.length) {
- // Bundle: emit each child as its own line item, drop the virtual wrapper
+ // Bundle: emit each child as its own line item, drop the virtual wrapper.
+ // Children carry a '-VB' suffix in the order data; EBS expects the
+ // original SKU, so strip it here (warranty lookup still uses the raw SKU).
for (const child of item.bundleItems) {
const hasWarranty = warrantyBySku.has(child.sku);
const serial = hasWarranty ? `ci${orderKey}-${++serialIndex}` : '';
lines.push(buildLineItemXml(
- child.sku || '', child.quantity ?? 1,
+ stripBundleSuffix(child.sku), child.quantity ?? 1,
child.price?.final || '0.00', child.taxAmount || '0.00', 'Each', serial,
));
diff --git a/test/ebs-sync/ebs-e2e.test.js b/test/ebs-sync/ebs-e2e.test.js
index da7bdb4..29600cf 100644
--- a/test/ebs-sync/ebs-e2e.test.js
+++ b/test/ebs-sync/ebs-e2e.test.js
@@ -597,11 +597,38 @@ describe('ebs-sync e2e', () => {
await syncOrderToEbs(MOCK_CTX, MOCK_PARAMS, PP_BUNDLE_WARRANTY_ORDER, journal);
// Bundle wrapper price (899.95) must NOT appear as a line item
expect(capturedXml).not.toMatch(/UnitSellingPrice="899\.95"/);
- // Each bundle child must appear with its own price
- expect(capturedXml).toMatch(/Sku="061724-04-VB"[\s\S]*?UnitSellingPrice="200\.96"/);
- expect(capturedXml).toMatch(/Sku="069834-VB"[\s\S]*?UnitSellingPrice="17\.43"/);
- expect(capturedXml).toMatch(/Sku="060488-VB"[\s\S]*?UnitSellingPrice="43\.65"/);
- expect(capturedXml).toMatch(/Sku="001372-1093-VB"[\s\S]*?UnitSellingPrice="637\.91"/);
+ // Each bundle child must appear with its own price (with '-VB' suffix stripped)
+ expect(capturedXml).toMatch(/Sku="061724-04"[\s\S]*?UnitSellingPrice="200\.96"/);
+ expect(capturedXml).toMatch(/Sku="069834"[\s\S]*?UnitSellingPrice="17\.43"/);
+ expect(capturedXml).toMatch(/Sku="060488"[\s\S]*?UnitSellingPrice="43\.65"/);
+ expect(capturedXml).toMatch(/Sku="001372-1093"[\s\S]*?UnitSellingPrice="637\.91"/);
+ });
+
+ test("bundle items have their '-VB' suffix stripped to the original SKU", async () => {
+ await syncOrderToEbs(MOCK_CTX, MOCK_PARAMS, PP_BUNDLE_WARRANTY_ORDER, journal);
+ // No bundle SKU should reach EBS with the virtual-bundle '-VB' suffix
+ expect(capturedXml).not.toMatch(/Sku="[^"]*-VB"/);
+ // The original (stripped) SKUs are present
+ expect(capturedXml).toMatch(/Sku="061724-04"/);
+ expect(capturedXml).toMatch(/Sku="069834"/);
+ expect(capturedXml).toMatch(/Sku="060488"/);
+ expect(capturedXml).toMatch(/Sku="001372-1093"/);
+ });
+
+ test("the '-VB' suffix is stripped only for bundle items, not simple products", async () => {
+ // A simple (non-bundle) product whose SKU happens to end in '-VB' must be
+ // left untouched — stripping applies to bundle children only.
+ const order = structuredClone(PP_BUNDLE_WARRANTY_ORDER);
+ order.items.push({
+ sku: '099999-VB',
+ quantity: 1,
+ name: 'Standalone item with VB-like SKU',
+ price: { final: '10.00', currency: 'CAD' },
+ taxAmount: '0.00',
+ });
+ await syncOrderToEbs(MOCK_CTX, MOCK_PARAMS, order, journal);
+ // Simple product keeps its SKU verbatim
+ expect(capturedXml).toMatch(/Sku="099999-VB"/);
});
test('warranty uses UnitOfMeasure="Years" and shares serial with its product', async () => {
diff --git a/test/fixtures/expected-pp-bundle-warranty.xml b/test/fixtures/expected-pp-bundle-warranty.xml
index cebd8a0..8009768 100644
--- a/test/fixtures/expected-pp-bundle-warranty.xml
+++ b/test/fixtures/expected-pp-bundle-warranty.xml
@@ -121,28 +121,28 @@