Skip to content

Commit 82a3989

Browse files
committed
new logic
1 parent af886ff commit 82a3989

File tree

5 files changed

+52
-178
lines changed

5 files changed

+52
-178
lines changed

Diff for: integration-libs/punchout/core/facade/punchout.service.spec.ts

+22-85
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { TestBed } from '@angular/core/testing';
2-
import { MultiCartFacade, OrderEntry } from '@spartacus/cart/base/root';
2+
import { MultiCartFacade } from '@spartacus/cart/base/root';
33
import { CommandService, RoutingService, UserIdService } from '@spartacus/core';
44
import {
55
PUNCHOUT_ERROR_PAGE_URL,
6-
PunchoutInitialCart,
76
PunchOutLevel,
87
PunchOutOperation,
98
PunchoutRequisition,
@@ -37,6 +36,11 @@ const mockPunchoutRequisitionResponse: PunchoutRequisition = {
3736
orderAsCXML: 'mockCXML',
3837
};
3938

39+
const mockPunchoutInitialRequisition: PunchoutRequisition = {
40+
browseFormPostUrl: 'mockInitialFormUrl',
41+
orderAsCXML: 'mockInitialCXML',
42+
};
43+
4044
const mockSessionId = '123abc';
4145

4246
const mockPunchoutSession: PunchoutSession = {
@@ -53,39 +57,11 @@ const mockPunchoutSession: PunchoutSession = {
5357
const mockPunchoutState: PunchoutState = {
5458
punchoutSessionId: mockSessionId,
5559
punchoutSession: mockPunchoutSession,
56-
punchoutInitialCart: undefined,
60+
punchoutInitialRequisition: undefined,
5761
cancelRequisition: undefined,
62+
closePunchoutSession: undefined,
5863
};
5964

60-
const mockEntries: OrderEntry[] = [
61-
{
62-
quantity: 1,
63-
product: { name: 'product1', code: 'code1' },
64-
},
65-
{
66-
quantity: 1,
67-
product: { name: 'product2', code: 'cod2' },
68-
},
69-
];
70-
71-
const mockStateEntries: { productCode: string; quantity: number }[] = [
72-
{
73-
quantity: 1,
74-
productCode: 'code1',
75-
},
76-
{
77-
quantity: 1,
78-
productCode: 'code2',
79-
},
80-
{
81-
quantity: 2,
82-
productCode: 'code3',
83-
},
84-
];
85-
86-
const mockInitialCart: PunchoutInitialCart = { entries: mockStateEntries };
87-
const mockCart = { entries: mockEntries };
88-
8965
class MockPunchoutStoreService implements Partial<PunchoutStoreService> {
9066
setPunchoutState = () => {};
9167
getPunchoutState = () => of(mockPunchoutState);
@@ -118,10 +94,6 @@ class MockRoutingService implements Partial<RoutingService> {
11894

11995
class MockMultiCartFacade implements Partial<MultiCartFacade> {
12096
loadCart = () => {};
121-
removeEntry = () => {};
122-
addEntries = () => {};
123-
getCart = () => of(mockCart);
124-
isStable = () => of(true);
12597
}
12698

12799
class MockUserIdService implements Partial<UserIdService> {
@@ -162,7 +134,6 @@ describe('Punchoutservice', () => {
162134
});
163135

164136
it('should getPunchoutSession calls connector', (done) => {
165-
spyOn(multiCartFacade, 'getCart').and.returnValue(of(mockCart));
166137
spyOn(connector, 'getPunchoutSession').and.returnValue(
167138
of(mockPunchoutSessionResponse)
168139
);
@@ -220,7 +191,7 @@ describe('Punchoutservice', () => {
220191

221192
it('should getPunchoutSession stays on page when isPageRefresh is true', (done) => {
222193
spyOn(routingService, 'go').and.returnValue(Promise.resolve(true));
223-
spyOn(multiCartFacade, 'getCart').and.returnValue(of(mockCart));
194+
224195
spyOn(connector, 'getPunchoutSessionRequisition').and.returnValue(
225196
of(mockPunchoutRequisitionResponse)
226197
);
@@ -281,25 +252,31 @@ describe('Punchoutservice', () => {
281252

282253
it('should getPunchoutSession opens cart page when no product item and EDIT Level ', (done) => {
283254
spyOn(routingService, 'go').and.returnValue(Promise.resolve(true));
284-
spyOn(multiCartFacade, 'getCart').and.returnValue(of(mockCart));
255+
285256
spyOn(connector, 'getPunchoutSession').and.returnValue(
286257
of({
287258
...mockPunchoutSessionResponse,
288259
selectedItem: '',
289260
})
290261
);
291-
262+
spyOn(connector, 'getPunchoutSessionRequisition').and.returnValue(
263+
of(mockPunchoutInitialRequisition)
264+
);
265+
spyOn(punchoutStoreService, 'updatePunchoutState').and.callThrough();
292266
service.getPunchoutSession(mockSessionInput).subscribe({
293267
next: () => {
294268
expect(routingService.go).toHaveBeenCalledWith({ cxRoute: 'cart' });
269+
expect(punchoutStoreService.updatePunchoutState).toHaveBeenCalledWith({
270+
punchoutInitialRequisition: { ...mockPunchoutInitialRequisition },
271+
});
295272
done();
296273
},
297274
});
298275
});
299276

300277
it('should getPunchoutSession opens pdp when selectedItem is present ', (done) => {
301278
spyOn(routingService, 'go').and.returnValue(Promise.resolve(true));
302-
spyOn(multiCartFacade, 'getCart').and.returnValue(of(mockCart));
279+
303280
spyOn(connector, 'getPunchoutSession').and.returnValue(
304281
of(mockPunchoutSessionResponse)
305282
);
@@ -335,7 +312,8 @@ describe('Punchoutservice', () => {
335312
it('should closePunchoutSession revertToInitialCart in EDIT operation ', (done) => {
336313
const mockState: PunchoutState = {
337314
...mockPunchoutState,
338-
punchoutInitialCart: mockInitialCart,
315+
punchoutInitialRequisition: mockPunchoutInitialRequisition,
316+
closePunchoutSession: true,
339317
punchoutSession: {
340318
...mockPunchoutSession,
341319
punchOutOperation: PunchOutOperation.EDIT,
@@ -347,26 +325,12 @@ describe('Punchoutservice', () => {
347325
);
348326
// spyOn(multiCartFacade, 'deleteCart').and.callThrough();
349327
spyOn(punchoutStoreService, 'updatePunchoutState').and.callThrough();
350-
spyOn(multiCartFacade, 'addEntries').and.callThrough();
351-
spyOn(multiCartFacade, 'removeEntry').and.callThrough();
352-
spyOn(multiCartFacade, 'isStable').and.returnValue(of(true));
353-
spyOn(multiCartFacade, 'getCart').and.returnValue(of(mockCart));
328+
spyOn(connector, 'getPunchoutSessionRequisition').and.callThrough();
354329

355330
service.closePunchoutSession().subscribe({
356331
next: () => {
357332
expect(punchoutStoreService.updatePunchoutState).toHaveBeenCalled();
358-
expect(multiCartFacade.removeEntry).toHaveBeenCalledTimes(
359-
mockCart.entries.length
360-
);
361-
expect(multiCartFacade.isStable).toHaveBeenCalledTimes(2);
362-
expect(multiCartFacade.addEntries).toHaveBeenCalledWith(
363-
mockState.punchoutSession?.customerId as string,
364-
mockState.punchoutSession?.cartId as string,
365-
mockState.punchoutInitialCart?.entries as {
366-
productCode: string;
367-
quantity: number;
368-
}[]
369-
);
333+
expect(connector.getPunchoutSessionRequisition).not.toHaveBeenCalled();
370334
done();
371335
},
372336
});
@@ -375,7 +339,6 @@ describe('Punchoutservice', () => {
375339
it('should closePunchoutSession set cancelRequisition in CREATE operation ', (done) => {
376340
const mockState: PunchoutState = {
377341
...mockPunchoutState,
378-
punchoutInitialCart: mockInitialCart,
379342
punchoutSession: {
380343
...mockPunchoutSession,
381344
punchOutOperation: PunchOutOperation.CREATE,
@@ -406,7 +369,6 @@ describe('Punchoutservice', () => {
406369
it('should closePunchoutSession only go to requisition page in INSPECT operation ', (done) => {
407370
const mockState: PunchoutState = {
408371
...mockPunchoutState,
409-
punchoutInitialCart: mockInitialCart,
410372
punchoutSession: {
411373
...mockPunchoutSession,
412374
punchOutOperation: PunchOutOperation.INSPECT,
@@ -431,29 +393,4 @@ describe('Punchoutservice', () => {
431393
},
432394
});
433395
});
434-
435-
it('should closePunchoutSession throw error when cartId is missing', (done) => {
436-
const mockState: PunchoutState = {
437-
...mockPunchoutState,
438-
punchoutInitialCart: mockInitialCart,
439-
punchoutSession: {
440-
...mockPunchoutSession,
441-
cartId: '',
442-
},
443-
};
444-
spyOn(routingService, 'go').and.returnValue(Promise.resolve(true));
445-
spyOn(punchoutStoreService, 'getPunchoutState').and.returnValue(
446-
of(mockState)
447-
);
448-
449-
spyOn(punchoutStoreService, 'updatePunchoutState').and.callThrough();
450-
spyOn(multiCartFacade, 'addEntries').and.callThrough();
451-
spyOn(multiCartFacade, 'removeEntry').and.callThrough();
452-
453-
service.closePunchoutSession().subscribe({
454-
error: () => {
455-
done();
456-
},
457-
});
458-
});
459396
});

Diff for: integration-libs/punchout/core/facade/punchout.service.ts

+24-86
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ import {
2424
PunchoutStoreService,
2525
} from '@spartacus/punchout/root';
2626

27-
import { Cart, MultiCartFacade } from '@spartacus/cart/base/root';
27+
import { MultiCartFacade } from '@spartacus/cart/base/root';
2828
import {
2929
catchError,
30-
filter,
3130
forkJoin,
3231
map,
3332
Observable,
@@ -100,9 +99,10 @@ export class PunchoutService implements PunchoutFacade {
10099
});
101100
if (
102101
punchoutSession.punchOutOperation === PunchOutOperation.EDIT &&
103-
punchoutSession?.cartId
102+
punchoutSession?.cartId &&
103+
!payload?.isPageRefresh
104104
) {
105-
this.setPunchoutInitialCart(punchoutSession.cartId);
105+
this.setPunchoutInitialRequisition();
106106
}
107107
if (!payload?.isPageRefresh) {
108108
this.routeToTargetPage(punchoutSession);
@@ -122,7 +122,7 @@ export class PunchoutService implements PunchoutFacade {
122122
* getPunchoutRequisition workflow:
123123
* Ensure user is logged-in
124124
* get punchoutSessionId from PunchoutState
125-
* Get PunchoutSessionRequisition from occ api
125+
* Get PunchoutSessionRequisition from occ api OR from PunchoutState
126126
* Redirect to Punchout Error page if error occurs
127127
*/
128128

@@ -138,6 +138,15 @@ export class PunchoutService implements PunchoutFacade {
138138
}),
139139
take(1),
140140
switchMap((punchoutState: PunchoutState) => {
141+
// scenario where user press 'close punchout session' btn in EDIT Cart mode
142+
// initial cart requisition is returned to ARIBA
143+
if (
144+
punchoutState?.closePunchoutSession &&
145+
punchoutState?.punchoutInitialRequisition?.browseFormPostUrl &&
146+
punchoutState.punchoutInitialRequisition?.orderAsCXML
147+
) {
148+
return of({ ...punchoutState.punchoutInitialRequisition });
149+
}
141150
const punchoutSessionId = punchoutState?.punchoutSessionId;
142151
return punchoutSessionId
143152
? this.punchoutConnector.getPunchoutSessionRequisition(
@@ -161,20 +170,18 @@ export class PunchoutService implements PunchoutFacade {
161170
/**
162171
* closePunchoutSession workflow:
163172
* for EDIT operation:
164-
* - Delete all cart entries
165-
* - Restore initial cart entries
166-
* - do same as 'back to requition' button
173+
* - initial Requisition is sent to ARIBA
167174
* for CREATE operation:
168175
* - do same Cancel punchout button
169-
* for INSPECT opeation:
176+
* for INSPECT operation:
170177
* - do same as 'back to requition' button
171178
*/
172179

173180
protected closePunchoutSessionCommand: Command<undefined, boolean> =
174181
this.commandService.create(() => {
175182
return this.punchoutStoreService.getPunchoutState().pipe(
176183
take(1),
177-
switchMap((punchoutState) => {
184+
map((punchoutState) => {
178185
if (
179186
punchoutState.punchoutSession?.punchOutOperation ===
180187
PunchOutOperation.CREATE
@@ -187,19 +194,9 @@ export class PunchoutService implements PunchoutFacade {
187194
PunchOutOperation.EDIT
188195
) {
189196
this.punchoutStoreService.updatePunchoutState({
190-
cancelRequisition: false,
197+
closePunchoutSession: true,
191198
});
192-
return this.revertToInitialCart(punchoutState).pipe(
193-
switchMap(() =>
194-
this.ensureStableCart(
195-
punchoutState.punchoutSession?.cartId as string
196-
)
197-
)
198-
);
199199
}
200-
return of(true);
201-
}),
202-
map(() => {
203200
this.routingService.go(PUNCHOUT_REQUISITION_PAGE_URL);
204201
return true;
205202
}),
@@ -262,76 +259,17 @@ export class PunchoutService implements PunchoutFacade {
262259
);
263260
}
264261

265-
protected setPunchoutInitialCart(cartId: string): void {
266-
this.takeCart(cartId)
267-
.pipe(
268-
map((cart) => {
269-
return cart?.entries?.map((e) => {
270-
return {
271-
productCode: e.product?.code as string,
272-
quantity: e.quantity as number,
273-
};
274-
}) as { productCode: string; quantity: number }[] | undefined;
275-
})
276-
)
262+
protected setPunchoutInitialRequisition(): void {
263+
this.getPunchoutSessionRequisition()
264+
.pipe(take(1))
277265
.subscribe({
278-
next: (
279-
entries: { productCode: string; quantity: number }[] | undefined
280-
) => {
281-
if (entries?.length) {
266+
next: (punchoutRequisition) => {
267+
if (punchoutRequisition) {
282268
this.punchoutStoreService.updatePunchoutState({
283-
punchoutInitialCart: { entries },
269+
punchoutInitialRequisition: { ...punchoutRequisition },
284270
});
285271
}
286272
},
287273
});
288274
}
289-
290-
protected revertToInitialCart(state: PunchoutState): Observable<boolean> {
291-
if (!state?.punchoutSession?.cartId) {
292-
return throwError(() => new Error('Punchout Session CartId missing'));
293-
}
294-
return this.takeCart(state.punchoutSession.cartId).pipe(
295-
switchMap((cart) => {
296-
cart?.entries?.forEach(() => {
297-
this.multiCartFacade.removeEntry(
298-
state.punchoutSession?.customerId as string,
299-
state.punchoutSession?.cartId as string,
300-
0
301-
);
302-
});
303-
if (state.punchoutInitialCart?.entries) {
304-
return this.ensureStableCart(
305-
state.punchoutSession?.cartId as string
306-
).pipe(
307-
tap(() => {
308-
this.multiCartFacade.addEntries(
309-
state.punchoutSession?.customerId as string,
310-
state.punchoutSession?.cartId as string,
311-
state.punchoutInitialCart?.entries as {
312-
productCode: string;
313-
quantity: number;
314-
}[]
315-
);
316-
})
317-
);
318-
}
319-
return of(true);
320-
})
321-
);
322-
}
323-
324-
protected takeCart(cartId: string): Observable<Cart> {
325-
return this.multiCartFacade.getCart(cartId).pipe(
326-
filter((cart) => cart !== undefined),
327-
take(1)
328-
);
329-
}
330-
331-
protected ensureStableCart(cartId: string): Observable<boolean> {
332-
return this.multiCartFacade.isStable(cartId).pipe(
333-
filter((stable) => stable),
334-
take(1)
335-
);
336-
}
337275
}

0 commit comments

Comments
 (0)