@things-factory/product-ui 4.3.151 → 4.3.156

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.
@@ -341,6 +341,13 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
341
341
  header: i18next.t('field.volume'),
342
342
  width: 70
343
343
  },
344
+ {
345
+ type: 'float',
346
+ name: 'costPrice',
347
+ record: { editable: true, options: { min: 0 } },
348
+ header: i18next.t('field.unit_cost'),
349
+ width: 70
350
+ },
344
351
  {
345
352
  type: 'string',
346
353
  name: 'auxUnit1',
@@ -533,6 +540,16 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
533
540
 
534
541
  let data = this._updateRowOption(response.data.productDetails.items)
535
542
 
543
+ data.map(item => {
544
+ if (item.costPrice) {
545
+ item.costPrice = item.costPrice.toFixed(2)
546
+ }
547
+ if (!item.costPrice) {
548
+ item.costPrice = 0
549
+ item.costPrice = item.costPrice.toFixed(2)
550
+ }
551
+ })
552
+
536
553
  if (!response.errors) {
537
554
  this._data = {
538
555
  total: response.data.productDetails.total || 0,
@@ -557,6 +574,9 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
557
574
  this._validate()
558
575
 
559
576
  let patches = this.dataGrist._data.records.map(itm => {
577
+ if (itm.costPrice) {
578
+ itm.costPrice = itm.costPrice
579
+ }
560
580
  return {
561
581
  id: itm.id,
562
582
  name: itm.name,
@@ -597,7 +617,7 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
597
617
  auxValue5: itm.auxValue5,
598
618
  isTrackedAsInventory: itm.isTrackedAsInventory,
599
619
  discountId: itm.discountId,
600
- costPrice: itm.costPrice,
620
+ costPrice: itm?.costPrice ? parseFloat(itm.costPrice) : undefined,
601
621
  mrpPrice: itm.mrpPrice,
602
622
  sellPrice: itm.sellPrice,
603
623
  afterTaxCostPrice: itm.afterTaxCostPrice,
@@ -646,7 +666,9 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
646
666
 
647
667
  _validate() {
648
668
  let errors = []
649
-
669
+ if (this.dataGrist.dirtyRecords.length < 1) {
670
+ throw new Error(i18next.t('text.nothing_changed'))
671
+ }
650
672
  if (!this.dataGrist._data.records.find(x => x.isDefault)) {
651
673
  errors.push({ type: 'isDefault', value: 'Must have 1 default' })
652
674
  }
@@ -693,6 +715,9 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
693
715
  if (!errors.find(err => err.type == 'uomValue'))
694
716
  errors.push({ type: 'uomValue', value: 'UOM Value is required' })
695
717
  }
718
+ if (itm.costPrice < 0) {
719
+ throw new Error(i18next.t('text.unit_cost_cannot_be_negative_value'))
720
+ }
696
721
  return itm
697
722
  })
698
723
 
@@ -707,6 +732,7 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
707
732
  }
708
733
 
709
734
  _fieldChange(e) {
735
+ let unitCostError = ''
710
736
  var { after, before, column, record, row } = e.detail
711
737
  let updatedRecords = {
712
738
  ...this.dataGrist._data,
@@ -736,6 +762,17 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
736
762
  updatedRecords.records[row].uomValue = 1
737
763
  }
738
764
  break
765
+
766
+ case 'costPrice':
767
+ if (isNaN(after) === true) {
768
+ unitCostError = 'not a number'
769
+ updatedRecords.records[row].costPrice = updatedRecords.records[row].__dirtyfields__.costPrice.before
770
+ this._showToast({ type: 'error', message: `Invalid value in Unit Cost (${unitCostError})` })
771
+ }
772
+ if (after < 0) {
773
+ unitCostError = 'negative value'
774
+ }
775
+ break
739
776
  default:
740
777
  break
741
778
  }
@@ -746,7 +783,11 @@ export class ProductDetailsPopup extends localize(i18next)(LitElement) {
746
783
  ...this.dataGrist._data
747
784
  }
748
785
 
749
- this._showToast({ type: 'error', message: `Minimum value of ${column.record.options.min} is required.` })
786
+ if (column.name == 'costPrice') {
787
+ this._showToast({ type: 'error', message: `Invalid value in Unit Cost (${unitCostError})` })
788
+ } else {
789
+ this._showToast({ type: 'error', message: `Minimum value of ${column.record.options.min} is required.` })
790
+ }
750
791
  }
751
792
 
752
793
  this._data = { ...updatedRecords }
@@ -359,6 +359,15 @@ class ProductList extends localize(i18next)(PageView) {
359
359
  sortable: true,
360
360
  width: 140
361
361
  },
362
+ {
363
+ type: 'integer',
364
+ name: 'shelfLife',
365
+ record: { editable: true },
366
+ imex: { header: i18next.t('field.shelf_life'), key: 'shelfLife', width: 30, type: 'integer' },
367
+ header: i18next.t('field.shelf_life'),
368
+ sortable: true,
369
+ width: 140
370
+ },
362
371
  {
363
372
  type: 'boolean',
364
373
  name: 'isRequiredCheckExpiry',
@@ -571,6 +580,14 @@ class ProductList extends localize(i18next)(PageView) {
571
580
  header: i18next.t('field.volume_size'),
572
581
  width: 100
573
582
  },
583
+ {
584
+ type: 'float',
585
+ name: 'costPrice',
586
+ record: { editable: true },
587
+ imex: { header: `${i18next.t('field.unit_cost')} 1`, key: 'costPrice', width: 20, type: 'number' },
588
+ header: `${i18next.t('field.unit_cost')}`,
589
+ width: 100
590
+ },
574
591
  {
575
592
  type: 'string',
576
593
  name: 'auxUnit1',
@@ -722,6 +739,7 @@ class ProductList extends localize(i18next)(PageView) {
722
739
  inventoryAccountCode
723
740
  cogsAccountCode
724
741
  expirationPeriod
742
+ shelfLife
725
743
  isRequiredCheckExpiry
726
744
  isRequireSerialNumberScanning
727
745
  isRequireSerialNumberScanningInbound
@@ -780,9 +798,13 @@ class ProductList extends localize(i18next)(PageView) {
780
798
  total: response.data.myBizplaceProducts.total || 0,
781
799
  records:
782
800
  response.data.myBizplaceProducts.items.map(itm => {
801
+ if (itm.costPrice == NaN || itm.costPrice == null) {
802
+ itm.costPrice = 0
803
+ }
783
804
  return {
784
805
  ...itm,
785
- productRef: { name: itm?.productRef ? '(' + itm.productRef.sku + ') ' + itm.productRef.name : '' }
806
+ productRef: { name: itm?.productRef ? '(' + itm.productRef.sku + ') ' + itm.productRef.name : '' },
807
+ costPrice: parseFloat(itm.costPrice).toFixed(2)
786
808
  }
787
809
  }) || []
788
810
  }
@@ -856,17 +878,26 @@ class ProductList extends localize(i18next)(PageView) {
856
878
  return this.showToast(i18next.t('text.nothing_changed'))
857
879
  }
858
880
 
881
+ this._validate(this.dataGrist.dirtyRecords)
882
+
859
883
  patches = patches.map(patch => {
884
+ if (patch.costPrice) {
885
+ patch.costPrice = parseFloat(patch.costPrice).toFixed(2)
886
+ }
887
+ if (!patch.costPrice) {
888
+ patch.costPrice = 0
889
+ patch.costPrice = parseFloat(patch.costPrice).toFixed(2)
890
+ }
860
891
  return {
861
892
  ...patch,
893
+ costPrice: patch?.costPrice ? parseFloat(patch.costPrice) : undefined,
862
894
  expirationPeriod: patch?.expirationPeriod ? parseInt(patch.expirationPeriod) : undefined,
895
+ shelfLife: patch?.shelfLife ? parseInt(patch.shelfLife) : undefined,
863
896
  productRef: patch.productRef?.id ? { id: patch.productRef?.id } : undefined,
864
897
  parentProductRef: patch.parentProductRef?.id ? { id: patch.parentProductRef?.id } : undefined
865
898
  }
866
899
  })
867
900
 
868
- this._validate(this.dataGrist.dirtyRecords)
869
-
870
901
  const response = await client.mutate({
871
902
  mutation: gql`
872
903
  mutation updateMultipleProduct($patches: [ProductPatch!]!) {
@@ -893,16 +924,28 @@ class ProductList extends localize(i18next)(PageView) {
893
924
  if (!patches?.length) {
894
925
  return this.showToast(i18next.t('text.nothing_changed'))
895
926
  }
896
-
897
927
  patches = patches.map(patch => {
928
+ if (patch.costPrice) {
929
+ patch.costPrice = parseFloat(patch.costPrice).toFixed(2)
930
+ }
931
+ if (!patch.costPrice) {
932
+ if (patch.costPrice == null) {
933
+ patch.costPrice = 0
934
+ patch.costPrice = parseFloat(patch.costPrice).toFixed(2)
935
+ } else {
936
+ patch.costPrice = parseFloat(patch.costPrice).toFixed(2)
937
+ }
938
+ }
898
939
  return {
899
940
  ...patch,
941
+ costPrice: patch?.costPrice ? parseFloat(patch.costPrice) : undefined,
900
942
  uomValue: patch?.uomValue ? parseFloat(patch.uomValue) : undefined,
901
943
  bufferQty: patch?.bufferQty ? parseInt(patch.bufferQty) : undefined,
902
944
  minQty: patch?.minQty ? parseInt(patch.minQty) : undefined,
903
945
  maxQty: patch?.maxQty ? parseInt(patch.maxQty) : undefined,
904
946
  packingSize: patch?.packingSize ? parseInt(patch.packingSize) : undefined,
905
947
  expirationPeriod: patch?.expirationPeriod ? parseInt(patch.expirationPeriod) : undefined,
948
+ shelfLife: patch?.shelfLife ? parseInt(patch.shelfLife) : undefined,
906
949
  productRef: patch.productRef?.id ? { id: patch.productRef?.id } : undefined,
907
950
  pickingStrategy: patch?.pickingStrategy ? patch.pickingStrategy.toUpperCase() : undefined
908
951
  }
@@ -954,6 +997,38 @@ class ProductList extends localize(i18next)(PageView) {
954
997
  if (!errors.find(err => err.type == 'uomValue'))
955
998
  errors.push({ type: 'uomValue', value: 'UOM Value is required' })
956
999
  }
1000
+ if (itm?.shelfLife < 0) {
1001
+ if (!errors.find(err => err.type == 'shelfLife'))
1002
+ errors.push({ type: 'shelfLife', value: 'Shelf Life cannot be negative' })
1003
+ }
1004
+ if (itm?.expirationPeriod < 0) {
1005
+ if (!errors.find(err => err.type == 'expirationPeriod'))
1006
+ errors.push({ type: 'expirationPeriod', value: 'Expiration period cannot be negative' })
1007
+ }
1008
+
1009
+ if (itm.costPrice < 0 && itm.__dirty__ != '+') {
1010
+ if (!errors.find(err => err.type == 'costPrice'))
1011
+ errors.push({ type: 'costPrice', value: 'invalid unit cost (negative value)' })
1012
+ }
1013
+ if (!itm.costPrice && itm.__dirty__ != '+') {
1014
+ if (itm.costPrice == 0) {
1015
+ itm.costPrice = 0
1016
+ } else {
1017
+ errors.push({ type: 'costPrice', value: 'invalid unit cost (not a number)' })
1018
+ }
1019
+ }
1020
+ if (itm.__dirty__ == '+') {
1021
+ if (!itm.costPrice) {
1022
+ if (itm.costPrice == undefined || itm.costPrice == 0) {
1023
+ itm.costPrice = 0
1024
+ } else {
1025
+ errors.push({ type: 'costPrice', value: 'invalid unit cost (not a number)' })
1026
+ }
1027
+ }
1028
+ if (itm.costPrice < 0) {
1029
+ errors.push({ type: 'costPrice', value: 'invalid unit cost (negative value)' })
1030
+ }
1031
+ }
957
1032
  return itm
958
1033
  })
959
1034
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/product-ui",
3
- "version": "4.3.151",
3
+ "version": "4.3.156",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -23,13 +23,13 @@
23
23
  "migration:create": "node ../../node_modules/typeorm/cli.js migration:create -d ./server/migrations"
24
24
  },
25
25
  "dependencies": {
26
- "@things-factory/form-ui": "^4.3.151",
27
- "@things-factory/grist-ui": "^4.3.151",
28
- "@things-factory/i18n-base": "^4.3.151",
29
- "@things-factory/import-ui": "^4.3.151",
30
- "@things-factory/layout-base": "^4.3.151",
31
- "@things-factory/product-base": "^4.3.151",
32
- "@things-factory/shell": "^4.3.151"
26
+ "@things-factory/form-ui": "^4.3.156",
27
+ "@things-factory/grist-ui": "^4.3.156",
28
+ "@things-factory/i18n-base": "^4.3.156",
29
+ "@things-factory/import-ui": "^4.3.156",
30
+ "@things-factory/layout-base": "^4.3.156",
31
+ "@things-factory/product-base": "^4.3.156",
32
+ "@things-factory/shell": "^4.3.156"
33
33
  },
34
- "gitHead": "7edd641774a5fbb9ca8b33f4cfbb7d89a49ab092"
34
+ "gitHead": "cbdf5546969663ba03bb1f4f10666599aa6d00bc"
35
35
  }
@@ -51,6 +51,7 @@
51
51
  "field.require_serial_number_scanning_outbound": "require serial number scanning outbound",
52
52
  "field.require_serial_number_scanning": "require serial number scanning",
53
53
  "field.required_checking_expiry": "required checking expiry",
54
+ "field.shelf_life": "shelf life",
54
55
  "field.sku": "SKU",
55
56
  "field.sub_brand": "sub brand",
56
57
  "field.threshold_qty": "threshold qty",
@@ -63,6 +64,7 @@
63
64
  "field.weight_unit": "weight unit",
64
65
  "field.weight": "weight",
65
66
  "field.width": "width",
67
+ "field.unit_cost": "unit cost",
66
68
  "label.fefo": "FEFO",
67
69
  "label.fmfo": "FMFO",
68
70
  "label.fifo": "FIFO",
@@ -77,5 +77,7 @@
77
77
  "title.product_bundle": "[ko]product bundle",
78
78
  "title.product_set": "[ko]product set",
79
79
  "title.product": "[ko]product",
80
- "field.child_product_detail": "[ko] child product detail"
80
+ "field.child_product_detail": "[ko] child product detail",
81
+ "field.unit_cost": "[ko] unit cost",
82
+ "field.shelf_life": "[ko] shelf life"
81
83
  }
@@ -77,5 +77,7 @@
77
77
  "title.product_bundle": "[ms]product bundle",
78
78
  "title.product_set": "[ms]product set",
79
79
  "title.product": "[ms]product",
80
- "field.child_product_detail": "[ms] child product detail"
80
+ "field.child_product_detail": "[ms] child product detail",
81
+ "field.unit_cost": "[ms] unit cost",
82
+ "field.shelf_life": "[ms] shelf life"
81
83
  }
@@ -77,5 +77,7 @@
77
77
  "title.product_bundle": "[zh]product bundle",
78
78
  "title.product_set": "[zh]product set",
79
79
  "title.product": "[zh]product",
80
- "field.child_product_detail": "[zh] child product detail"
80
+ "field.child_product_detail": "[zh] child product detail",
81
+ "field.unit_cost": "[zh] unit cost",
82
+ "field.shelf_life": "[zh] shelf life"
81
83
  }