@things-factory/operato-wms 4.3.656 → 4.3.660

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.
@@ -82,7 +82,8 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
82
82
  productData: Object,
83
83
  newProductData: Object,
84
84
  strictEditable: Boolean,
85
- userRole: Array
85
+ userRole: Array,
86
+ enableDirectInbound: Boolean
86
87
  }
87
88
  }
88
89
 
@@ -132,9 +133,7 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
132
133
  raised
133
134
  @click="${this._addEditProducts.bind(this, true)}"
134
135
  label="${i18next.t('button.submit')}"
135
- class="${this.status !== 'PENDING'
136
- ? 'hidden'
137
- : ''}"
136
+ class="${this.status !== 'PENDING' ? 'hidden' : ''}"
138
137
  ></mwc-button>
139
138
  </div>
140
139
  `
@@ -148,286 +147,364 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
148
147
 
149
148
  async firstUpdated() {
150
149
  this.enableLotIdInput = await fetchSettingRule('enable-lot-id-input')
150
+ this.enableDirectInbound = await fetchSettingRule('enable-direct-gan-order')
151
+
152
+ const fields = [
153
+ 'batchId',
154
+ 'productSku',
155
+ 'product',
156
+ 'brand',
157
+ 'packingType',
158
+ 'uomValue',
159
+ 'uom',
160
+ 'packQty',
161
+ 'totalUomValue',
162
+ 'palletQty',
163
+ 'palletId',
164
+ 'expDate',
165
+ 'manufactureDate',
166
+ 'batchIdRef',
167
+ 'warehouse',
168
+ 'location',
169
+ 'unitPrice',
170
+ 'remark',
171
+ 'status'
172
+ ]
173
+
174
+ const columns = [
175
+ { type: 'gutter', gutterName: 'sequence' },
176
+ { type: 'string', name: 'id', hidden: true },
177
+ {
178
+ type: 'string',
179
+ name: 'batchId',
180
+ header: i18next.t('field.batch_id'),
181
+ record: { editable: true },
182
+ width: 150
183
+ },
184
+ {
185
+ type: 'string',
186
+ name: 'productSku',
187
+ header: i18next.t('field.sku'),
188
+ width: 150
189
+ },
190
+ {
191
+ type: 'object',
192
+ name: 'product',
193
+ header: i18next.t('field.product'),
194
+ width: 350
195
+ },
196
+ {
197
+ type: 'object',
198
+ name: 'brand',
199
+ header: i18next.t('field.brand'),
200
+ width: 150
201
+ },
202
+ {
203
+ type: 'code',
204
+ name: 'packingType',
205
+ header: i18next.t('field.packing_type'),
206
+ record: { editable: !this.strictEditable, codeName: 'PACKING_TYPES' },
207
+ width: 150
208
+ },
209
+ {
210
+ type: 'float',
211
+ name: 'uomValue',
212
+ header: i18next.t('field.uom_value'),
213
+ record: { editable: !this.strictEditable, options: { min: 0 } },
214
+ width: 80
215
+ },
216
+ {
217
+ type: 'code',
218
+ name: 'uom',
219
+ header: i18next.t('field.uom'),
220
+ record: { editable: !this.strictEditable, codeName: 'WEIGHT_UNITS' },
221
+ width: 80
222
+ },
223
+ {
224
+ type: 'float',
225
+ name: 'packQty',
226
+ header: i18next.t('field.pack_qty'),
227
+ record: { editable: true, options: { min: 0 } },
228
+ width: 80
229
+ },
230
+ {
231
+ type: 'float',
232
+ name: 'totalUomValue',
233
+ header: i18next.t('field.total_uom_value'),
234
+ width: 120
235
+ },
236
+ {
237
+ type: 'integer',
238
+ name: 'palletQty',
239
+ header: i18next.t('field.pallet_qty'),
240
+ record: { editable: true, options: { min: 0 } },
241
+ width: 80
242
+ },
243
+ ...(this._enableLotIdInput
244
+ ? [
245
+ {
246
+ type: 'string',
247
+ name: 'palletId',
248
+ header: i18next.t('field.lot_id'),
249
+ imex: { header: i18next.t('field.lot_id'), key: 'palletId', width: 25, type: 'string' },
250
+ record: { editable: editable },
251
+ width: 150
252
+ }
253
+ ]
254
+ : []),
255
+ {
256
+ type: 'date',
257
+ name: 'manufactureDate',
258
+ header: i18next.t('field.manufacture_date'),
259
+ record: { editable: true },
260
+ width: 120
261
+ },
262
+ {
263
+ type: 'string',
264
+ name: 'batchIdRef',
265
+ header: i18next.t('field.batch_no_ref'),
266
+ record: { editable: true },
267
+ width: 150
268
+ },
269
+ {
270
+ type: 'float',
271
+ name: 'unitPrice',
272
+ header: i18next.t('field.unit_price'),
273
+ record: { editable: true },
274
+ width: 80
275
+ },
276
+ {
277
+ type: 'string',
278
+ name: 'remark',
279
+ header: i18next.t('field.remark'),
280
+ record: { editable: true },
281
+ width: 300
282
+ },
283
+ {
284
+ type: 'string',
285
+ name: 'status',
286
+ header: i18next.t('field.status'),
287
+ width: 130
288
+ }
289
+ ]
290
+
291
+ function insertAfter(cols, anchorName, newCols) {
292
+ const idx = cols.findIndex(c => c.name === anchorName)
293
+ if (idx >= 0) cols.splice(idx + 1, 0, ...newCols)
294
+ }
295
+
296
+ function createExpDateColumn() {
297
+ return {
298
+ type: 'date',
299
+ name: 'expDate',
300
+ header: i18next.t('field.exp_date'),
301
+ record: { editable: true },
302
+ width: 120
303
+ }
304
+ }
305
+
306
+ function createWarehouseColumn() {
307
+ return {
308
+ type: 'object',
309
+ name: 'warehouse',
310
+ header: i18next.t('field.warehouse'),
311
+ width: 150
312
+ }
313
+ }
314
+
315
+ function createLocationColumn(clickHandler) {
316
+ return {
317
+ type: 'object',
318
+ name: 'location',
319
+ header: i18next.t('field.location'),
320
+ record: { editable: true },
321
+ handlers: {
322
+ click: (columns, data, column, record, rowIndex) => {
323
+ clickHandler(rowIndex)
324
+ }
325
+ },
326
+ width: 150
327
+ }
328
+ }
329
+
330
+ if (this.enableDirectInbound) {
331
+ const anchor = this.enableLotIdInput ? 'palletId' : 'palletQty'
332
+ insertAfter(columns, anchor, [createExpDateColumn()])
333
+ insertAfter(columns, 'batchIdRef', [
334
+ createWarehouseColumn(),
335
+ createLocationColumn(rowIndex => this._openLocationSelection(rowIndex))
336
+ ])
337
+ }
338
+
151
339
  this.editProductConfig = {
152
340
  pagination: { infinite: true },
153
341
  rows: { selectable: { multiple: true }, appendable: false },
154
342
  list: {
155
- fields: [
156
- 'batchId',
157
- 'productSku',
158
- 'product',
159
- 'brand',
160
- 'packingType',
161
- 'uomValue',
162
- 'uom',
163
- 'packQty',
164
- 'totalUomValue',
165
- 'palletQty',
166
- 'palletId',
167
- 'manufactureDate',
168
- 'batchIdRef',
169
- 'unitPrice',
170
- 'remark',
171
- 'status'
172
- ]
343
+ fields
173
344
  },
174
- columns: [
175
- { type: 'gutter', gutterName: 'sequence' },
176
- {
177
- type: 'string',
178
- name: 'id',
179
- hidden: true
180
- },
181
- {
182
- type: 'string',
183
- name: 'batchId',
184
- header: i18next.t('field.batch_id'),
185
- record: { editable: true },
186
- width: 150
187
- },
188
- {
189
- type: 'string',
190
- name: 'productSku',
191
- header: i18next.t('field.sku'),
192
- width: 150
193
- },
194
- {
195
- type: 'object',
196
- name: 'product',
197
- header: i18next.t('field.product'),
198
- width: 350
199
- },
200
- {
201
- type: 'object',
202
- name: 'brand',
203
- header: i18next.t('field.brand'),
204
- width: 150
205
- },
206
- {
207
- type: 'code',
208
- name: 'packingType',
209
- header: i18next.t('field.packing_type'),
210
- record: { editable: !this.strictEditable, codeName: 'PACKING_TYPES' },
211
- width: 150
212
- },
213
- {
214
- type: 'float',
215
- name: 'uomValue',
216
- header: i18next.t('field.uom_value'),
217
- record: { editable: !this.strictEditable, options: { min: 0 } },
218
- width: 80
219
- },
220
- {
221
- type: 'code',
222
- name: 'uom',
223
- header: i18next.t('field.uom'),
224
- record: { editable: !this.strictEditable, codeName: 'WEIGHT_UNITS' },
225
- width: 80
226
- },
227
- {
228
- type: 'float',
229
- name: 'packQty',
230
- header: i18next.t('field.pack_qty'),
231
- record: { editable: true, options: { min: 0 } },
232
- width: 80
233
- },
234
- {
235
- type: 'float',
236
- name: 'totalUomValue',
237
- header: i18next.t('field.total_uom_value'),
238
- width: 120
239
- },
240
- {
241
- type: 'integer',
242
- name: 'palletQty',
243
- header: i18next.t('field.pallet_qty'),
244
- record: { editable: true, options: { min: 0 } },
245
- width: 80
246
- },
247
- {
248
- type: 'string',
249
- name: 'palletId',
250
- header: i18next.t('field.lot_id'),
251
- width: 80
252
- },
253
- {
254
- type: 'date',
255
- name: 'manufactureDate',
256
- header: i18next.t('field.manufacture_date'),
257
- record: { editable: true },
258
- width: 120
259
- },
260
- {
261
- type: 'string',
262
- name: 'batchIdRef',
263
- header: i18next.t('field.batch_no_ref'),
264
- record: { editable: true },
265
- width: 150
266
- },
267
- {
268
- type: 'float',
269
- name: 'unitPrice',
270
- header: i18next.t('field.unit_price'),
271
- record: { editable: true },
272
- width: 80
273
- },
274
- {
275
- type: 'string',
276
- name: 'remark',
277
- header: i18next.t('field.remark'),
278
- record: { editable: true },
279
- width: 300
280
- },
281
- {
282
- type: 'string',
283
- name: 'status',
284
- header: i18next.t('field.status'),
285
- width: 130
345
+ columns
346
+ }
347
+
348
+ const addFields = [
349
+ 'batchId',
350
+ 'productName',
351
+ 'packingType',
352
+ 'uomValue',
353
+ 'uom',
354
+ 'packQty',
355
+ 'totalUomValue',
356
+ 'palletQty',
357
+ 'palletId',
358
+ 'expDate',
359
+ 'manufactureDate',
360
+ 'batchIdRef',
361
+ 'warehouse',
362
+ 'location',
363
+ 'unitPrice',
364
+ 'remark'
365
+ ]
366
+
367
+ const addColumns = [
368
+ { type: 'gutter', gutterName: 'sequence' },
369
+ {
370
+ type: 'gutter',
371
+ gutterName: 'button',
372
+ icon: 'close',
373
+ handlers: {
374
+ click: (columns, data, column, record, rowIndex) => {
375
+ const newData = data.records.filter((_, idx) => idx !== rowIndex)
376
+ this.newProductData = { ...this.newProductData, records: newData }
377
+ this.addProductGrist.dirtyData.records = newData
378
+ }
286
379
  }
287
- ]
380
+ },
381
+ {
382
+ type: 'string',
383
+ name: 'batchId',
384
+ header: i18next.t('field.batch_id'),
385
+ record: { editable: true },
386
+ width: 150
387
+ },
388
+ {
389
+ type: 'string',
390
+ name: 'productName',
391
+ header: i18next.t('field.product'),
392
+ imex: { header: i18next.t('field.product'), key: 'productName', width: 50, type: 'string' },
393
+ handlers: {
394
+ click: (columns, data, column, record, rowIndex) => {
395
+ this._openProductSelection(rowIndex)
396
+ }
397
+ },
398
+ width: 350
399
+ },
400
+ {
401
+ type: 'object',
402
+ name: 'product',
403
+ hidden: true
404
+ },
405
+ {
406
+ type: 'object',
407
+ name: 'brand',
408
+ header: i18next.t('field.brand'),
409
+ width: 150
410
+ },
411
+ {
412
+ type: 'code',
413
+ name: 'packingType',
414
+ header: i18next.t('field.packing_type'),
415
+ record: { editable: !this.strictEditable, codeName: 'PACKING_TYPES' },
416
+ width: 150
417
+ },
418
+ {
419
+ type: 'float',
420
+ name: 'uomValue',
421
+ header: i18next.t('field.uom_value'),
422
+ record: { editable: !this.strictEditable, options: { min: 0 } },
423
+ width: 80
424
+ },
425
+ {
426
+ type: 'code',
427
+ name: 'uom',
428
+ header: i18next.t('field.uom'),
429
+ record: { editable: !this.strictEditable, codeName: 'WEIGHT_UNITS' },
430
+ width: 80
431
+ },
432
+ {
433
+ type: 'float',
434
+ name: 'packQty',
435
+ header: i18next.t('field.pack_qty'),
436
+ record: { editable: true, options: { min: 0 } },
437
+ width: 80
438
+ },
439
+ {
440
+ type: 'float',
441
+ name: 'totalUomValue',
442
+ header: i18next.t('field.total_uom_value'),
443
+ width: 120
444
+ },
445
+ {
446
+ type: 'integer',
447
+ name: 'palletQty',
448
+ header: i18next.t('field.pallet_qty'),
449
+ record: { editable: true, options: { min: 0 } },
450
+ width: 80
451
+ },
452
+ ...(this.enableLotIdInput
453
+ ? [
454
+ {
455
+ type: 'string',
456
+ name: 'palletId',
457
+ header: i18next.t('field.lot_id'),
458
+ width: 80
459
+ }
460
+ ]
461
+ : []),
462
+ {
463
+ type: 'date',
464
+ name: 'manufactureDate',
465
+ header: i18next.t('field.manufacture_date'),
466
+ record: { editable: true },
467
+ width: 120
468
+ },
469
+ {
470
+ type: 'string',
471
+ name: 'batchIdRef',
472
+ header: i18next.t('field.batch_no_ref'),
473
+ record: { editable: true },
474
+ width: 150
475
+ },
476
+ {
477
+ type: 'float',
478
+ name: 'unitPrice',
479
+ header: i18next.t('field.unit_price'),
480
+ record: { editable: true },
481
+ width: 80
482
+ },
483
+ {
484
+ type: 'string',
485
+ name: 'remark',
486
+ header: i18next.t('field.remark'),
487
+ record: { editable: true },
488
+ width: 300
489
+ }
490
+ ]
491
+
492
+ if (this.enableDirectInbound) {
493
+ const anchor = this.enableLotIdInput ? 'palletId' : 'palletQty'
494
+ insertAfter(addColumns, anchor, [createExpDateColumn()])
495
+ insertAfter(addColumns, 'batchIdRef', [
496
+ createWarehouseColumn(),
497
+ createLocationColumn(rowIndex => this._openAddLocationSelection(rowIndex))
498
+ ])
288
499
  }
289
500
 
290
501
  this.addProductConfig = {
291
502
  pagination: { infinite: true },
292
503
  rows: { selectable: { multiple: true } },
293
504
  list: {
294
- fields: [
295
- 'batchId',
296
- 'productName',
297
- 'packingType',
298
- 'uomValue',
299
- 'uom',
300
- 'packQty',
301
- 'totalUomValue',
302
- 'palletQty',
303
- 'palletId',
304
- 'manufactureDate',
305
- 'batchIdRef',
306
- 'unitPrice',
307
- 'remark'
308
- ]
505
+ fields: addFields
309
506
  },
310
- columns: [
311
- { type: 'gutter', gutterName: 'sequence' },
312
- {
313
- type: 'gutter',
314
- gutterName: 'button',
315
- icon: 'close',
316
- handlers: {
317
- click: (columns, data, column, record, rowIndex) => {
318
- const newData = data.records.filter((_, idx) => idx !== rowIndex)
319
- this.newProductData = { ...this.newProductData, records: newData }
320
- this.addProductGrist.dirtyData.records = newData
321
- }
322
- }
323
- },
324
- {
325
- type: 'string',
326
- name: 'batchId',
327
- header: i18next.t('field.batch_id'),
328
- record: { editable: true },
329
- width: 150
330
- },
331
- {
332
- type: 'string',
333
- name: 'productName',
334
- header: i18next.t('field.product'),
335
- imex: { header: i18next.t('field.product'), key: 'productName', width: 50, type: 'string' },
336
- handlers: {
337
- click: (columns, data, column, record, rowIndex) => {
338
- this._openProductSelection(rowIndex)
339
- }
340
- },
341
- width: 350
342
- },
343
- {
344
- type: 'object',
345
- name: 'product',
346
- hidden: true
347
- },
348
- {
349
- type: 'object',
350
- name: 'brand',
351
- header: i18next.t('field.brand'),
352
- width: 150
353
- },
354
- {
355
- type: 'code',
356
- name: 'packingType',
357
- header: i18next.t('field.packing_type'),
358
- record: { editable: !this.strictEditable, codeName: 'PACKING_TYPES' },
359
- width: 150
360
- },
361
- {
362
- type: 'float',
363
- name: 'uomValue',
364
- header: i18next.t('field.uom_value'),
365
- record: { editable: !this.strictEditable, options: { min: 0 } },
366
- width: 80
367
- },
368
- {
369
- type: 'code',
370
- name: 'uom',
371
- header: i18next.t('field.uom'),
372
- record: { editable: !this.strictEditable, codeName: 'WEIGHT_UNITS' },
373
- width: 80
374
- },
375
- {
376
- type: 'float',
377
- name: 'packQty',
378
- header: i18next.t('field.pack_qty'),
379
- record: { editable: true, options: { min: 0 } },
380
- width: 80
381
- },
382
- {
383
- type: 'float',
384
- name: 'totalUomValue',
385
- header: i18next.t('field.total_uom_value'),
386
- width: 120
387
- },
388
- {
389
- type: 'integer',
390
- name: 'palletQty',
391
- header: i18next.t('field.pallet_qty'),
392
- record: { editable: true, options: { min: 0 } },
393
- width: 80
394
- },
395
- {
396
- type: 'string',
397
- name: 'palletId',
398
- header: i18next.t('field.lot_id'),
399
- record: { editable: true },
400
- width: 120
401
- },
402
- {
403
- type: 'date',
404
- name: 'manufactureDate',
405
- header: i18next.t('field.manufacture_date'),
406
- record: { editable: true },
407
- width: 120
408
- },
409
- {
410
- type: 'string',
411
- name: 'batchIdRef',
412
- header: i18next.t('field.batch_no_ref'),
413
- record: { editable: true },
414
- width: 150
415
- },
416
- {
417
- type: 'float',
418
- name: 'unitPrice',
419
- header: i18next.t('field.unit_price'),
420
- record: { editable: true },
421
- width: 80
422
- },
423
- {
424
- type: 'string',
425
- name: 'remark',
426
- header: i18next.t('field.remark'),
427
- record: { editable: true },
428
- width: 300
429
- }
430
- ]
507
+ columns: addColumns
431
508
  }
432
509
 
433
510
  this.userRole = await this.fetchUserRoleHandler()
@@ -443,7 +520,10 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
443
520
 
444
521
  async _onProductChangeHandler(event) {
445
522
  try {
446
- this._checkProductDuplication()
523
+ if (!this.enableDirectInbound) {
524
+ this._checkProductDuplication()
525
+ }
526
+
447
527
  let changeRecord = event.detail.after
448
528
  const changedColumn = event.detail.column.name
449
529
 
@@ -478,6 +558,17 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
478
558
  throw new Error(i18next.t('text.invalid_x', { state: { x: i18next.t('label.pallet_qty') } }))
479
559
  }
480
560
  }
561
+
562
+ if (changedColumn === 'expDate') {
563
+ if (!changeRecord.product?.isRequiredCheckExpiry) {
564
+ delete changeRecord.expDate
565
+ throw new Error(
566
+ i18next.t('text.exp_date_not_required_for_this_product', {
567
+ defaultValue: `Expiry date is not required for this product`
568
+ })
569
+ )
570
+ }
571
+ }
481
572
  } catch (e) {
482
573
  const beforeValue = event.detail.before && event.detail.before[event.detail.column.name]
483
574
  if (beforeValue) {
@@ -581,7 +672,7 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
581
672
  if (matchingRow?.length > 0) isDuplicated = true
582
673
 
583
674
  if (isDuplicated) {
584
- throw new Error(i18next.t('text.duplicated_lot_id'))
675
+ throw new Error(i18next.t('text.duplicated_batch_id'))
585
676
  }
586
677
  } else if (this.enableLotIdInput) {
587
678
  const addedNewRows = this.addProductGrist.dirtyData.records
@@ -613,6 +704,102 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
613
704
  }
614
705
  }
615
706
 
707
+ _openLocationSelection(rowIndex) {
708
+ openPopup(
709
+ html`
710
+ <buffer-location-selector
711
+ .bizplaceId="${this._bizplaceId}"
712
+ .data="${this.productData}"
713
+ .enableDirectInbound="${this.enableDirectInbound}"
714
+ @selected="${async e => {
715
+ this.editProductGrist.dirtyData.records[rowIndex].location = { id: e.detail.id, name: e.detail.name }
716
+ this.editProductGrist.dirtyData.records[rowIndex].warehouse = {
717
+ id: e.detail.warehouse.id,
718
+ name: e.detail.warehouse.name
719
+ }
720
+ this.editProductGrist.dirtyData.records[rowIndex].__dirty__ = true
721
+
722
+ if (this.editProductGrist.dirtyData.records.length !== rowIndex) {
723
+ // update existing product data records
724
+ this.editProductGrist.dirtyData.records.splice(rowIndex, 1, {
725
+ ...this.editProductGrist.dirtyData.records[rowIndex]
726
+ })
727
+
728
+ this.productData = {
729
+ ...this.productData,
730
+ records: [...this.editProductGrist.dirtyData.records]
731
+ }
732
+
733
+ this.editProductGrist.data.records = this.editProductGrist.dirtyData.records
734
+ } else {
735
+ this.productData = {
736
+ ...this.productData,
737
+ records: [...this.editProductGrist.dirtyData.records]
738
+ }
739
+ }
740
+ }}"
741
+ ></buffer-location-selector>
742
+ `,
743
+ {
744
+ backdrop: true,
745
+ size: 'large',
746
+ title: i18next.t('title.select_location', 'Select Location')
747
+ }
748
+ )
749
+ }
750
+
751
+ _openAddLocationSelection(rowIndex) {
752
+ openPopup(
753
+ html`
754
+ <buffer-location-selector
755
+ .bizplaceId="${this._bizplaceId}"
756
+ .data="${this.newProductData}"
757
+ .enableDirectInbound="${this.enableDirectInbound}"
758
+ @selected="${async e => {
759
+ this.addProductGrist.dirtyData.records[rowIndex].location = { id: e.detail.id, name: e.detail.name }
760
+ this.addProductGrist.dirtyData.records[rowIndex].warehouse = {
761
+ id: e.detail.warehouse.id,
762
+ name: e.detail.warehouse.name
763
+ }
764
+ this.addProductGrist.dirtyData.records[rowIndex].__dirty__ = true
765
+
766
+ if (this.addProductGrist.dirtyData.records.length !== rowIndex) {
767
+ // update existing product data records
768
+ this.addProductGrist.dirtyData.records.splice(rowIndex, 1, {
769
+ ...this.addProductGrist.dirtyData.records[rowIndex]
770
+ })
771
+
772
+ this.newProductData = {
773
+ ...this.newProductData,
774
+ records: [...this.addProductGrist.dirtyData.records]
775
+ }
776
+
777
+ this.addProductGrist.data.records = this.addProductGrist.dirtyData.records
778
+ } else {
779
+ this.newProductData = {
780
+ ...this.newProductData,
781
+ records: [...this.addProductGrist.dirtyData.records]
782
+ }
783
+ }
784
+ }}"
785
+ ></buffer-location-selector>
786
+ `,
787
+ {
788
+ backdrop: true,
789
+ size: 'large',
790
+ title: i18next.t('title.select_location', 'Select Location')
791
+ }
792
+ )
793
+ }
794
+
795
+ async pageUpdated(changes, lifecycle) {
796
+ if (this.active) {
797
+ await this.updateComplete
798
+
799
+ this.editProductGrist.config = this.editProductConfig
800
+ }
801
+ }
802
+
616
803
  _openProductSelection(rowIndex) {
617
804
  if (this.bizplace?.id) {
618
805
  openPopup(
@@ -656,6 +843,10 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
656
843
 
657
844
  async _addEditProducts(approveAdminAddEditProducts) {
658
845
  try {
846
+ if (this.enableDirectInbound) {
847
+ approveAdminAddEditProducts = false
848
+ }
849
+
659
850
  this._validateProducts()
660
851
 
661
852
  let existingOrderProducts = []
@@ -715,7 +906,7 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
715
906
  }
716
907
 
717
908
  _getNewOrderProducts() {
718
- const isStatusPending = this.status === 'PENDING' ? true : false
909
+ const isStatusPending = this.status === 'PENDING' && !this.enableDirectInbound
719
910
  return this.addProductGrist.dirtyData.records.map(record => {
720
911
  record.unitPrice = parseFloat(record.unitPrice) || 0
721
912
 
@@ -734,7 +925,7 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
734
925
  adjustedUomValue: !isStatusPending ? (record?.uomValue ? record.uomValue : 0) : null,
735
926
  uom: isStatusPending ? record.uom : 'N/A',
736
927
  adjustedUom: !isStatusPending ? record.uom : null,
737
- packQty: isStatusPending ? (record.packQty ? parseFloat(record.packQty).toFixed(3) : 0) : 0,
928
+ packQty: isStatusPending ? (record.packQty ? parseFloat(parseFloat(record.packQty).toFixed(3)) : 0) : 0,
738
929
  adjustedPackQty: !isStatusPending ? record.packQty : null,
739
930
  totalUomValue: isStatusPending ? record.totalUomValue : 'N/A',
740
931
  adjustedTotalUomValue: record?.totalUomValue && !isStatusPending ? record.totalUomValue : 'N/A',
@@ -744,14 +935,17 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
744
935
  unitPrice: isStatusPending ? record.unitPrice : 0,
745
936
  adjustedUnitPrice: record?.unitPrice && !isStatusPending ? record.unitPrice : null,
746
937
  remark: record?.remark ? record.remark : null,
747
- packingSize: record.packingSize || record.product.packingSize
938
+ packingSize: record.packingSize || record.product.packingSize,
939
+ expDate: record?.expDate ? record.expDate : null,
940
+ location: record?.location ? record.location : null,
941
+ warehouse: record?.warehouse ? record.warehouse : null
748
942
  }
749
943
  })
750
944
  }
751
945
 
752
946
  _getExistingOrderProducts() {
753
947
  let editedOrderProducts = []
754
- const isStatusPending = this.status === 'PENDING' ? true : false
948
+ const isStatusPending = this.status === 'PENDING' && !this.enableDirectInbound
755
949
  if (this.editProductGrist.dirtyData.records.some(record => record.__dirty__)) {
756
950
  this.editProductGrist.dirtyData.records.map(record => {
757
951
  record.unitPrice = parseFloat(record.unitPrice)
@@ -796,6 +990,21 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
796
990
  ? null
797
991
  : record.totalUomValue
798
992
  : null,
993
+ adjustedExpDate: !isStatusPending
994
+ ? record.expDate == record.__origin__.expDate
995
+ ? null
996
+ : record.expDate
997
+ : null,
998
+ adjustedWarehouse: !isStatusPending
999
+ ? record.warehouse == record.__origin__?.__origin__?.warehouse
1000
+ ? null
1001
+ : record.warehouse
1002
+ : null,
1003
+ adjustedLocation: !isStatusPending
1004
+ ? record.location == record.__origin__?.__origin__?.location
1005
+ ? null
1006
+ : record.location
1007
+ : null,
799
1008
  manufactureDate: record?.manufactureDate ? record.manufactureDate : null,
800
1009
  palletId: record?.palletId ? record.palletId : null,
801
1010
  adjustedUnitPrice: record?.unitPrice && !isStatusPending ? record.unitPrice : null,
@@ -809,7 +1018,10 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
809
1018
  uomValue: record.uomValue,
810
1019
  uom: record.uom,
811
1020
  batchId: record.batchId,
812
- totalUomValue: record.totalUomValue
1021
+ totalUomValue: record.totalUomValue,
1022
+ expDate: record.__origin__.expDate,
1023
+ location: record.__origin__.location,
1024
+ warehouse: record.__origin__.warehouse
813
1025
  })
814
1026
  })
815
1027
  })
@@ -832,6 +1044,29 @@ export class EditProductPopup extends localize(i18next)(LitElement) {
832
1044
  ) {
833
1045
  throw new Error(i18next.t('text.empty_value_in_add_product_list'))
834
1046
  }
1047
+
1048
+ this.addProductGrist.dirtyData.records.forEach((record, index) => {
1049
+ if (this.enableDirectInbound && record?.product?.isRequiredCheckExpiry && !record.expDate) {
1050
+ throw new Error(
1051
+ i18next.t('text.exp_date_required_for_product', {
1052
+ defaultValue: `Add Product Row ${index + 1}: Expiry date is required for product "${record.product.name}"`,
1053
+ product: record.product.name,
1054
+ row: index + 1
1055
+ })
1056
+ )
1057
+ }
1058
+
1059
+ if (!record.location || !record.location.id) {
1060
+ throw new Error(
1061
+ i18next.t('text.location_required_for_product', {
1062
+ defaultValue: `Add Product Row ${index + 1}: Location is missing for product "${record.product.name}"`,
1063
+ product: record.product.name,
1064
+ row: index + 1
1065
+ })
1066
+ )
1067
+ }
1068
+ })
1069
+
835
1070
  this.editProductGrist.dirtyData.records.forEach(record => {
836
1071
  if (record.packQty === 0 && !record.remark) {
837
1072
  throw new Error(i18next.t('text.remark_is_empty_kindly_fill_in_to_proceed'))