Skip to content

Commit 64495f6

Browse files
OMS multiple shipment support with pickups
nit Empty commit to trigger CI Empty commit to trigger CI
1 parent 3748b56 commit 64495f6

File tree

2 files changed

+136
-106
lines changed

2 files changed

+136
-106
lines changed

packages/template-retail-react-app/app/pages/account/order-detail.jsx

Lines changed: 110 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@ const AccountOrderDetail = () => {
134134
)
135135
const isLoading = isOrderLoading || !order
136136

137+
// Check if order has OMS data
138+
const isOmsOrder = useMemo(() => !!order?.omsData, [order?.omsData])
139+
140+
// Check if order is OMS multi-shipment order
141+
const isOmsMultiShipment = useMemo(
142+
() =>
143+
isOmsOrder &&
144+
((order?.omsData?.shipments?.length ?? 0) > 1 || (order?.shipments?.length ?? 0) > 1),
145+
[isOmsOrder, order?.omsData?.shipments?.length, order?.shipments?.length]
146+
)
147+
137148
const {pickupShipments, deliveryShipments} = useMemo(() => {
138149
return storeLocatorEnabled
139150
? groupShipmentsByDeliveryOption(order)
@@ -164,6 +175,67 @@ const AccountOrderDetail = () => {
164175
[storeData?.data]
165176
)
166177

178+
const renderShippingMethod = (
179+
shippingMethodName,
180+
shippingStatus,
181+
trackingNumber,
182+
trackingUrl,
183+
shipmentsLength,
184+
index
185+
) => (
186+
<Stack spacing={1}>
187+
<Heading as="h2" fontSize="sm" pt={1}>
188+
{shipmentsLength > 1 ? (
189+
<FormattedMessage
190+
defaultMessage="Shipping Method {number}"
191+
id="account_order_detail.heading.shipping_method_number"
192+
values={{number: index + 1}}
193+
/>
194+
) : (
195+
<FormattedMessage
196+
defaultMessage="Shipping Method"
197+
id="account_order_detail.heading.shipping_method"
198+
/>
199+
)}
200+
</Heading>
201+
<Box>
202+
<Text fontSize="sm" textTransform="titlecase">
203+
{{
204+
not_shipped: formatMessage({
205+
defaultMessage: 'Not shipped',
206+
id: 'account_order_detail.shipping_status.not_shipped'
207+
}),
208+
part_shipped: formatMessage({
209+
defaultMessage: 'Partially shipped',
210+
id: 'account_order_detail.shipping_status.part_shipped'
211+
}),
212+
shipped: formatMessage({
213+
defaultMessage: 'Shipped',
214+
id: 'account_order_detail.shipping_status.shipped'
215+
})
216+
}[shippingStatus] || shippingStatus}
217+
</Text>
218+
<Text fontSize="sm">{shippingMethodName}</Text>
219+
{trackingNumber && (
220+
<Text fontSize="sm">
221+
<FormattedMessage
222+
defaultMessage="Tracking Number"
223+
id="account_order_detail.label.tracking_number"
224+
/>
225+
:{' '}
226+
{trackingUrl ? (
227+
<ChakraLink href={trackingUrl} isExternal color="blue.600">
228+
{trackingNumber}
229+
</ChakraLink>
230+
) : (
231+
trackingNumber
232+
)}
233+
</Text>
234+
)}
235+
</Box>
236+
</Stack>
237+
)
238+
167239
const paymentCard = order?.paymentInstruments?.[0]?.paymentCard
168240
const CardIcon = getCreditCardIcon(paymentCard?.cardType)
169241
const itemCount = order?.productItems?.reduce((count, item) => item.quantity + count, 0) || 0
@@ -325,86 +397,31 @@ const AccountOrderDetail = () => {
325397
</Stack>
326398
)
327399
})}
328-
329400
{/* Delivery Shipments */}
330-
{deliveryShipments.map((shipment, index) => {
331-
// Hide shipping address for OMS multi-shipment orders
332-
// Can't reliably correlate OMS shipments to ECOM addresses by index
333-
const isOmsOrder = !!order?.omsData
334-
const omsShipment = isOmsOrder
335-
? order.omsData.shipments?.[index]
336-
: null
337-
const isOmsMultiShipment =
338-
isOmsOrder &&
339-
(order.omsData.shipments?.length > 1 ||
340-
order.shipments?.length > 1)
401+
{!isOmsMultiShipment &&
402+
deliveryShipments.map((shipment, index) => {
403+
const omsShipment = isOmsOrder
404+
? order.omsData.shipments?.[index]
405+
: null
341406

342-
const shippingMethodName =
343-
omsShipment?.provider || shipment.shippingMethod.name
344-
const shippingStatus =
345-
omsShipment?.status || shipment.shippingStatus
346-
const trackingNumber =
347-
omsShipment?.trackingNumber || shipment.trackingNumber
348-
const trackingUrl = omsShipment?.trackingUrl
407+
const shippingMethodName =
408+
omsShipment?.provider || shipment.shippingMethod.name
409+
const shippingStatus =
410+
omsShipment?.status || shipment.shippingStatus
411+
const trackingNumber =
412+
omsShipment?.trackingNumber || shipment.trackingNumber
413+
const trackingUrl = omsShipment?.trackingUrl
349414

350-
return (
351-
<React.Fragment key={`delivery-${index}`}>
352-
<Stack spacing={1}>
353-
<Heading as="h2" fontSize="sm" pt={1}>
354-
{deliveryShipments.length > 1 ? (
355-
<FormattedMessage
356-
defaultMessage="Shipping Method {number}"
357-
id="account_order_detail.heading.shipping_method_number"
358-
values={{number: index + 1}}
359-
/>
360-
) : (
361-
<FormattedMessage
362-
defaultMessage="Shipping Method"
363-
id="account_order_detail.heading.shipping_method"
364-
/>
365-
)}
366-
</Heading>
367-
<Box>
368-
<Text fontSize="sm" textTransform="titlecase">
369-
{{
370-
not_shipped: formatMessage({
371-
defaultMessage: 'Not shipped',
372-
id: 'account_order_detail.shipping_status.not_shipped'
373-
}),
374-
part_shipped: formatMessage({
375-
defaultMessage: 'Partially shipped',
376-
id: 'account_order_detail.shipping_status.part_shipped'
377-
}),
378-
shipped: formatMessage({
379-
defaultMessage: 'Shipped',
380-
id: 'account_order_detail.shipping_status.shipped'
381-
})
382-
}[shippingStatus] || shippingStatus}
383-
</Text>
384-
<Text fontSize="sm">{shippingMethodName}</Text>
385-
{trackingNumber && (
386-
<Text fontSize="sm">
387-
<FormattedMessage
388-
defaultMessage="Tracking Number"
389-
id="account_order_detail.label.tracking_number"
390-
/>
391-
:{' '}
392-
{trackingUrl ? (
393-
<ChakraLink
394-
href={trackingUrl}
395-
isExternal
396-
color="blue.600"
397-
>
398-
{trackingNumber}
399-
</ChakraLink>
400-
) : (
401-
trackingNumber
402-
)}
403-
</Text>
404-
)}
405-
</Box>
406-
</Stack>
407-
{!isOmsMultiShipment && (
415+
return (
416+
<React.Fragment key={`delivery-${index}`}>
417+
{renderShippingMethod(
418+
shippingMethodName,
419+
shippingStatus,
420+
trackingNumber,
421+
trackingUrl,
422+
deliveryShipments.length,
423+
index
424+
)}
408425
<Stack spacing={1}>
409426
<Heading as="h2" fontSize="sm" pt={1}>
410427
{deliveryShipments.length > 1 ? (
@@ -437,10 +454,24 @@ const AccountOrderDetail = () => {
437454
</Text>
438455
</Box>
439456
</Stack>
457+
</React.Fragment>
458+
)
459+
})}
460+
461+
{/* OMS multi-shipment: show OMS shipment info only;*/}
462+
{isOmsMultiShipment &&
463+
order?.omsData?.shipments?.map((shipment, index) => (
464+
<React.Fragment key={`oms-shipment-${index}`}>
465+
{renderShippingMethod(
466+
shipment.provider,
467+
shipment.status,
468+
shipment.trackingNumber,
469+
shipment.trackingUrl,
470+
order?.omsData?.shipments?.length ?? 0,
471+
index
440472
)}
441473
</React.Fragment>
442-
)
443-
})}
474+
))}
444475

445476
{/* Payment Method */}
446477
{paymentCard && (

packages/template-retail-react-app/app/pages/account/orders.test.js

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ describe('OMS Single shipment with partial data (missing provider, trackingUrl)'
795795
})
796796
})
797797

798-
describe('BOPIS Order with OMS - Pickup and Delivery', () => {
798+
describe('BOPIS Order with OMS Single Pickup and Single Delivery', () => {
799799
// Helper to create BOPIS order with OMS data
800800
const createBopisOmsOrder = (overrides = {}) => ({
801801
orderNo: 'BOPIS-OMS-001',
@@ -825,7 +825,6 @@ describe('BOPIS Order with OMS - Pickup and Delivery', () => {
825825
shippingMethod: {
826826
name: 'Ground'
827827
},
828-
trackingNumber: 'ECOM-TRACK-OLD',
829828
shippingAddress: {
830829
fullName: 'Sarah Johnson',
831830
address1: '456 Delivery St',
@@ -887,18 +886,8 @@ describe('BOPIS Order with OMS - Pickup and Delivery', () => {
887886
expect(await screen.findByText('Shipping Method')).toBeInTheDocument()
888887
expect(await screen.findByText(/FedEx/i)).toBeInTheDocument()
889888
expect(screen.queryByText(/Ground/i)).not.toBeInTheDocument()
890-
})
891-
892-
test('should display OMS tracking number as clickable link for delivery shipment', async () => {
893-
setupOrderDetailsPage(createBopisOmsOrder())
894-
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
895889
const trackingLink = await screen.findByRole('link', {name: /BOPIS-TRACK-123/i})
896890
expect(trackingLink).toHaveAttribute('href', 'https://tracking.fedex.com/BOPIS-TRACK-123')
897-
})
898-
899-
test('should display OMS shipment status for delivery shipment', async () => {
900-
setupOrderDetailsPage(createBopisOmsOrder())
901-
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
902891
expect(await screen.findByText(/SHIPPED/i)).toBeInTheDocument()
903892
})
904893

@@ -1131,17 +1120,27 @@ describe('BOPIS Order with OMS - Multiple Pickup Locations', () => {
11311120
expect(await screen.findByText(/Partially Ready/i)).toBeInTheDocument()
11321121
})
11331122

1134-
test('should display OMS provider and tracking for delivery shipment', async () => {
1123+
test('should display OMS shipment 1 with UPS provider and tracking', async () => {
11351124
setupOrderDetailsPage(createMultiPickupBopisOmsOrder())
11361125
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
11371126
expect(await screen.findByText(/UPS/i)).toBeInTheDocument()
1127+
expect(await screen.findByText(/SHIPPED/i)).toBeInTheDocument()
11381128
const trackingLink = await screen.findByRole('link', {name: /MULTI-TRACK-456/i})
11391129
expect(trackingLink).toHaveAttribute(
11401130
'href',
11411131
'https://www.ups.com/track?loc=en_US&tracknum=MULTI-TRACK-456'
11421132
)
11431133
})
11441134

1135+
test('should display OMS shipment 2 with FedEx provider and tracking', async () => {
1136+
setupOrderDetailsPage(createMultiPickupBopisOmsOrder())
1137+
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
1138+
expect(await screen.findByText(/FedEx/i)).toBeInTheDocument()
1139+
expect(await screen.findByText(/PENDING/i)).toBeInTheDocument()
1140+
const trackingLink = await screen.findByRole('link', {name: /MULTI-TRACK-789/i})
1141+
expect(trackingLink).toHaveAttribute('href', 'https://tracking.fedex.com/MULTI-TRACK-789')
1142+
})
1143+
11451144
test('should NOT display shipping address for multi-pickup BOPIS OMS order', async () => {
11461145
setupOrderDetailsPage(createMultiPickupBopisOmsOrder())
11471146
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
@@ -1164,6 +1163,12 @@ describe('BOPIS Order with OMS - Pickup and Delivery Shipments', () => {
11641163
provider: 'FedEx',
11651164
trackingNumber: 'OMS-TRACK-456',
11661165
trackingUrl: 'https://tracking.fedex.com/OMS-TRACK-456'
1166+
},
1167+
{
1168+
status: 'NEW',
1169+
provider: 'UPS',
1170+
trackingNumber: 'OMS-TRACK-123',
1171+
trackingUrl: 'https://tracking.fedex.com/OMS-TRACK-123'
11671172
}
11681173
]
11691174
},
@@ -1180,8 +1185,6 @@ describe('BOPIS Order with OMS - Pickup and Delivery Shipments', () => {
11801185
shippingMethod: {
11811186
name: 'Ground'
11821187
},
1183-
shippingStatus: 'shipped',
1184-
trackingNumber: 'ECOM-TRACK-OLD',
11851188
shippingAddress: {
11861189
firstName: 'John',
11871190
lastName: 'Doe'
@@ -1230,31 +1233,27 @@ describe('BOPIS Order with OMS - Pickup and Delivery Shipments', () => {
12301233
expect(await screen.findByText(/100 Market St/i)).toBeInTheDocument()
12311234
})
12321235

1233-
test('should display OMS provider for delivery shipment', async () => {
1234-
setupOrderDetailsPage(createOmsBopisWithDelivery())
1235-
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
1236-
expect(await screen.findByText(/FedEx/i)).toBeInTheDocument()
1237-
expect(screen.queryByText(/Ground/i)).not.toBeInTheDocument()
1238-
})
1239-
1240-
test('should display OMS tracking number as clickable link for delivery', async () => {
1236+
test('should display OMS shipment 1 and link', async () => {
12411237
setupOrderDetailsPage(createOmsBopisWithDelivery())
12421238
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
1239+
expect(await screen.findByText(/FEDEX/i)).toBeInTheDocument()
1240+
expect(await screen.findByText(/SHIPPED/i)).toBeInTheDocument()
12431241
const trackingLink = await screen.findByRole('link', {name: /OMS-TRACK-456/i})
12441242
expect(trackingLink).toHaveAttribute('href', 'https://tracking.fedex.com/OMS-TRACK-456')
12451243
})
12461244

1247-
test('should display OMS shipment status for delivery', async () => {
1245+
test('should display OMS shipment 2 and link', async () => {
12481246
setupOrderDetailsPage(createOmsBopisWithDelivery())
12491247
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
1250-
expect(await screen.findByText(/SHIPPED/i)).toBeInTheDocument()
1248+
expect(await screen.findByText(/UPS/i)).toBeInTheDocument()
1249+
expect(await screen.findByText(/NEW/i)).toBeInTheDocument()
1250+
const trackingLink = await screen.findByRole('link', {name: /OMS-TRACK-123/i})
1251+
expect(trackingLink).toHaveAttribute('href', 'https://tracking.fedex.com/OMS-TRACK-123')
12511252
})
12521253

12531254
test('should NOT display shipping address for OMS BOPIS order with multiple shipments', async () => {
12541255
setupOrderDetailsPage(createOmsBopisWithDelivery())
12551256
expect(await screen.findByTestId('account-order-details-page')).toBeInTheDocument()
1256-
// Shipping address should be hidden for OMS multi-shipment orders
1257-
// (order has 2 shipments: 1 pickup + 1 delivery, so order.shipments?.length > 1)
12581257
expect(screen.queryByRole('heading', {name: /^shipping address$/i})).not.toBeInTheDocument()
12591258
expect(screen.queryByText(/John Doe/i)).not.toBeInTheDocument()
12601259
})

0 commit comments

Comments
 (0)