Skip to content

Commit 018c6bb

Browse files
OBPIH-7298 Add create putaway test (#62)
* update receiving service * add elements to navbar * update appConfig * update locationConfig * update fixtures * add elements to page * update types * add new location * add putaway pages * add old view shipment page * add transaction pages * add shipmentUtils * add create putaway test * OBPIH-7298 Add create receiving bin service method * OBPIH-7298 Add create receiving in tests * update env example * update page elements and naming * add putaway test * add page locators * add location deactivation to receive tests * add focus on fields * improve selectors * fix export test --------- Co-authored-by: Alan Nadolny <[email protected]>
1 parent ad4a224 commit 018c6bb

33 files changed

+805
-97
lines changed

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ USER_ALT_USERNAME=alt
66
USER_ALT_PASSWORD=password
77
USER_MANAGER_USERNAME=manager
88
USER_MANAGER_PASSWORD=password
9+
USER_IMPERSONATOR_USERNAME=impersonator
10+
USER_IMPERSONATOR_PASSWORD=password
911
LOCATION_MAIN=locationId
1012
LOCATION_NO_MANAGE_INVENOTRY_DEPOT=locationId
1113
LOCATION_SUPPLIER=locationId
1214
LOCATION_SUPPLIER_ALT=locationId
1315
LOCATION_DEPOT=locationId
1416
LOCATION_NO_PICK_AND_PUTAWAY_STOCK_DEPOT=locationId
17+
LOCATION_INTERNAL=locationId
1518
LOCATION_WARD=locationId
1619
PRODUCT_ONE=productId
1720
PRODUCT_TWO=productId

.github/workflows/playwright.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ jobs:
6767
LOCATION_DEPOT: ${{ secrets.LOCATION_DEPOT }}
6868
LOCATION_WARD: ${{ secrets.LOCATION_WARD }}
6969
LOCATION_NO_PICK_AND_PUTAWAY_STOCK_DEPOT: ${{ secrets.LOCATION_NO_PICK_AND_PUTAWAY_STOCK_DEPOT }}
70+
LOCATION_INTERNAL: ${{ secrets.LOCATION_INTERNAL }}
7071
PRODUCT_ONE: ${{ secrets.PRODUCT_ONE }}
7172
PRODUCT_TWO: ${{ secrets.PRODUCT_TWO }}
7273
PRODUCT_THREE: ${{ secrets.PRODUCT_THREE }}

src/api/ReceivingService.ts

Lines changed: 102 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import BaseServiceModel from '@/api/BaseServiceModel';
55
import { PartialReceiptStatus } from '@/constants/PartialReceiptStatus';
66
import {
77
ApiResponse,
8-
Container, ReceiptPayload,
8+
Container,
9+
ReceiptPayload,
910
ReceiptResponse,
1011
ReceivingItemPayload,
1112
ShipmentItem,
@@ -52,7 +53,7 @@ class ReceivingService extends BaseServiceModel {
5253
try {
5354
await this.changeReceiptStatus(id, PartialReceiptStatus.ROLLBACK);
5455
} catch (error) {
55-
throw new Error('Problem rolling back partial receipt')
56+
throw new Error('Problem rolling back partial receipt');
5657
}
5758
}
5859

@@ -78,17 +79,21 @@ class ReceivingService extends BaseServiceModel {
7879
*/
7980
async updateReceivingItems(
8081
id: string,
81-
items: ReceivingItemPayload[],
82+
items: ReceivingItemPayload[]
8283
): Promise<void> {
8384
try {
8485
const receipt = await this.getReceipt(id);
8586
const shipmentItemsToUpdate = this.extractShipmentItemIds(items);
86-
const containers = this.buildUpdatedContainers(receipt.data.containers, items, shipmentItemsToUpdate);
87+
const containers = this.buildUpdatedContainers(
88+
receipt.data.containers,
89+
items,
90+
shipmentItemsToUpdate
91+
);
8792
const payload: ReceiptPayload = {
8893
...receipt.data,
8994
containers: containers,
9095
recipient: receipt?.data?.recipient?.id,
91-
}
96+
};
9297
await this.request.post(`./api/partialReceiving/${id}`, {
9398
data: payload,
9499
});
@@ -97,6 +102,28 @@ class ReceivingService extends BaseServiceModel {
97102
}
98103
}
99104

105+
/*
106+
As arguments take the shipment id and the receipt object. It should be called before updating items
107+
to create a receiving bin.
108+
*/
109+
async createReceivingBin(
110+
id: string,
111+
receipt: ReceiptResponse,
112+
): Promise<void> {
113+
try {
114+
const payload: ReceiptPayload = {
115+
...receipt,
116+
containers: this.createEmptyContainers(receipt?.containers),
117+
recipient: receipt.recipient?.id,
118+
};
119+
await this.request.post(`./api/partialReceiving/${id}`, {
120+
data: payload,
121+
});
122+
} catch (error) {
123+
throw new Error('Problem creating receiving bin');
124+
}
125+
}
126+
100127
/*
101128
As arguments take the shipment id, id of receipt item that needs to be split,
102129
new lines are an array filled with new items, including the original one, that is split.
@@ -133,14 +160,19 @@ class ReceivingService extends BaseServiceModel {
133160
async splitReceivingLine(
134161
id: string,
135162
originalReceiptItemId: string,
136-
newLines: ReceivingItemPayload[],
163+
newLines: ReceivingItemPayload[]
137164
) {
138165
try {
139166
const receipt = await this.getReceipt(id);
140167

141-
const originalShipmentItem = this.findOriginalShipmentItem(receipt.data.containers, originalReceiptItemId);
168+
const originalShipmentItem = this.findOriginalShipmentItem(
169+
receipt.data.containers,
170+
originalReceiptItemId
171+
);
142172
if (!originalShipmentItem) {
143-
throw new Error(`Original shipment item with ID ${originalReceiptItemId} not found`);
173+
throw new Error(
174+
`Original shipment item with ID ${originalReceiptItemId} not found`
175+
);
144176
}
145177

146178
this.validateQuantity(originalShipmentItem.quantityShipped, newLines);
@@ -159,17 +191,40 @@ class ReceivingService extends BaseServiceModel {
159191
}
160192
}
161193

162-
private findOriginalShipmentItem(containers: Container[], receiptItemId: string): ShipmentItem | undefined {
163-
return _.flatten(containers.map(c => c.shipmentItems))
164-
.find(item => item.receiptItemId === receiptItemId);
194+
private createEmptyContainers(
195+
containers: Container[]
196+
): Container[] {
197+
return containers?.map((container) => {
198+
return {
199+
...container,
200+
shipmentItems: container?.shipmentItems?.map(shipmentItem => ({
201+
...shipmentItem,
202+
quantityReceiving: 0,
203+
}))
204+
}
205+
})
165206
}
166207

167-
private validateQuantity(originalQuantityShipped: number | undefined, newLines: ReceivingItemPayload[]) {
208+
private findOriginalShipmentItem(
209+
containers: Container[],
210+
receiptItemId: string
211+
): ShipmentItem | undefined {
212+
return _.flatten(containers.map((c) => c.shipmentItems)).find(
213+
(item) => item.receiptItemId === receiptItemId
214+
);
215+
}
216+
217+
private validateQuantity(
218+
originalQuantityShipped: number | undefined,
219+
newLines: ReceivingItemPayload[]
220+
) {
168221
const sumOfQuantityShipped = _.sumBy(newLines, 'quantityShipped');
169222
const originalQty = originalQuantityShipped || 0;
170223

171224
if (originalQty < sumOfQuantityShipped) {
172-
throw new Error('Sum of quantity shipped is greater than the original quantity shipped');
225+
throw new Error(
226+
'Sum of quantity shipped is greater than the original quantity shipped'
227+
);
173228
}
174229
}
175230

@@ -178,41 +233,45 @@ class ReceivingService extends BaseServiceModel {
178233
originalReceiptItemId: string,
179234
newLines: ReceivingItemPayload[]
180235
): UnflattenContainer[] {
181-
const splittedItem = newLines.find(line => line.receiptItemId === originalReceiptItemId);
182-
const linesToSave = newLines.filter(line => !line.receiptItemId);
236+
const splittedItem = newLines.find(
237+
(line) => line.receiptItemId === originalReceiptItemId
238+
);
239+
const linesToSave = newLines.filter((line) => !line.receiptItemId);
183240

184-
return containers.map(container => {
241+
return containers.map((container) => {
185242
const updatedShipmentItems = _.flatten(
186243
container.shipmentItems.map((shipmentItem: ShipmentItem) => {
187244
if (shipmentItem.receiptItemId === originalReceiptItemId) {
188-
return [
189-
{ ...shipmentItem, ...splittedItem },
190-
...linesToSave
191-
];
245+
return [{ ...shipmentItem, ...splittedItem }, ...linesToSave];
192246
}
193247
return shipmentItem;
194248
})
195249
);
196250

197-
return unflatten({ ...container, shipmentItems: updatedShipmentItems }) as UnflattenContainer;
251+
return unflatten({
252+
...container,
253+
shipmentItems: updatedShipmentItems,
254+
}) as UnflattenContainer;
198255
});
199256
}
200257

201-
private buildPayload(receiptData: ReceiptResponse, containers: UnflattenContainer[]): ReceiptPayload {
258+
private buildPayload(
259+
receiptData: ReceiptResponse,
260+
containers: UnflattenContainer[]
261+
): ReceiptPayload {
202262
return {
203263
...receiptData,
204264
containers,
205-
recipient: receiptData.recipient.id
265+
recipient: receiptData.recipient.id,
206266
};
207267
}
208268

209269
private async saveSplitLines(id: string, payload: ReceiptPayload) {
210270
await this.request.post(`./api/partialReceiving/${id}`, {
211-
data: payload
271+
data: payload,
212272
});
213273
}
214274

215-
216275
private async changeReceiptStatus(
217276
id: string,
218277
status: PartialReceiptStatus
@@ -233,42 +292,47 @@ class ReceivingService extends BaseServiceModel {
233292
private buildUpdatedContainers(
234293
containers: Container[],
235294
items: ReceivingItemPayload[],
236-
shipmentItemsToUpdate: string[],
295+
shipmentItemsToUpdate: string[]
237296
): UnflattenContainer[] {
238297
return containers.map((container) => {
239298
return unflatten({
240299
...container,
241-
shipmentItems: container.shipmentItems.map((shipmentItem: ShipmentItem) => {
242-
if (shipmentItemsToUpdate.includes(shipmentItem.shipmentItemId)) {
243-
const updatedItem = this.findItemToUpdate(items, shipmentItem.shipmentItemId);
244-
return this.mergeShipmentItem(shipmentItem, updatedItem);
245-
}
300+
shipmentItems: container.shipmentItems.map(
301+
(shipmentItem: ShipmentItem) => {
302+
if (shipmentItemsToUpdate.includes(shipmentItem.shipmentItemId)) {
303+
const updatedItem = this.findItemToUpdate(
304+
items,
305+
shipmentItem.shipmentItemId
306+
);
307+
return this.mergeShipmentItem(shipmentItem, updatedItem);
308+
}
246309

247-
return shipmentItem;
248-
}),
310+
return shipmentItem;
311+
}
312+
),
249313
}) as UnflattenContainer;
250314
});
251315
}
252316

253317
private findItemToUpdate(
254318
items: ReceivingItemPayload[],
255-
shipmentItemId: string,
319+
shipmentItemId: string
256320
): ReceivingItemPayload | undefined {
257321
return items.find((item) => item.shipmentItemId === shipmentItemId);
258322
}
259323

260324
private mergeShipmentItem(
261325
original: ShipmentItem,
262-
update?: ReceivingItemPayload,
326+
update?: ReceivingItemPayload
263327
): ShipmentItem {
264328
return {
265329
...original,
266-
binLocationId: update?.binLocationId ?? original.binLocationId,
267-
quantityReceiving: update?.quantityReceiving ?? original.quantityReceiving,
330+
'binLocation.name': update?.binLocationName ?? original.binLocationName,
331+
quantityReceiving:
332+
update?.quantityReceiving ?? original.quantityReceiving,
268333
comment: update?.comment ?? original.comment,
269334
};
270335
}
271-
272336
}
273337

274338
export default ReceivingService;

src/components/Navbar.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ class Navbar extends BasePageModel {
3131
return this.navbar.getByRole('menuitem', { name: 'Edit Profile' });
3232
}
3333

34+
get refreshCachesButton() {
35+
return this.navbar.getByRole('menuitem', { name: 'Refresh Caches' });
36+
}
37+
3438
// Nav Items
3539
get dashboard() {
3640
return this.getNavItem('Dashboard');
@@ -79,6 +83,18 @@ class Navbar extends BasePageModel {
7983
get listProducts() {
8084
return this.getNavItem('List Products');
8185
}
86+
87+
get inbound() {
88+
return this.getNavItem('Inbound');
89+
}
90+
91+
get createPutaway() {
92+
return this.getNavItem('Create Putaway');
93+
}
94+
95+
get transactions() {
96+
return this.getNavItem('Transactions');
97+
}
8298
}
8399

84100
export default Navbar;

src/config/AppConfig.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export enum LOCATION_KEY {
2525
DEPOT = 'depot',
2626
WARD = 'ward',
2727
NO_PICK_AND_PUTAWAY_STOCK = 'noPickAndPutawayStockDepot',
28+
BIN_LOCATION = 'internalLocation',
2829
}
2930

3031
export enum PRODUCT_KEY {
@@ -256,6 +257,19 @@ class AppConfig {
256257
required: false,
257258
type: LocationTypeCode.DEPOT,
258259
}),
260+
261+
internalLocation: new LocationConfig({
262+
id: env.get('LOCATION_INTERNAL').asString(),
263+
key: LOCATION_KEY.BIN_LOCATION,
264+
name: this.uniqueIdentifier.generateUniqueString('bin-location'),
265+
requiredActivityCodes: new Set([
266+
ActivityCode.PICK_STOCK,
267+
ActivityCode.PUTAWAY_STOCK,
268+
]),
269+
required: false,
270+
type: LocationTypeCode.BIN_LOCATION,
271+
parentLocation: env.get('LOCATION_MAIN').required().asString(),
272+
}),
259273
};
260274

261275
this.products = {
@@ -292,7 +306,7 @@ class AppConfig {
292306
key: PRODUCT_KEY.FIVE,
293307
name: this.uniqueIdentifier.generateUniqueString('aa-product-five'),
294308
//'aa' part was added to improve visibility of ordering products alphabetically
295-
quantity: 160,
309+
quantity: 0,
296310
required: false,
297311
}),
298312
};

src/config/LocationConfig.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type LocationConfigProps = {
99
key: string;
1010
requiredActivityCodes: Set<ActivityCode>;
1111
type: LocationTypeCode;
12+
parentLocation?: string;
1213
} & (
1314
| {
1415
id: string;
@@ -29,6 +30,7 @@ class LocationConfig {
2930
type: LocationTypeCode;
3031
required: boolean;
3132
key: string;
33+
parentLocation?: string;
3234

3335
constructor({
3436
key,
@@ -37,13 +39,15 @@ class LocationConfig {
3739
requiredActivityCodes,
3840
type,
3941
required,
42+
parentLocation,
4043
}: LocationConfigProps) {
4144
this.id = id || '';
4245
this.name = name || '';
4346
this.requiredActivityCodes = requiredActivityCodes;
4447
this.type = type;
4548
this.required = required ?? false;
4649
this.key = key;
50+
this.parentLocation = parentLocation || '';
4751
}
4852

4953
/** Should create a new location for testing

0 commit comments

Comments
 (0)