@questwork/q-store-model 0.1.35 → 0.1.36

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.
@@ -95,12 +95,15 @@ __webpack_require__.d(__webpack_exports__, {
95
95
  ChainManager: () => (/* reexport */ ChainManager),
96
96
  ChainManagerFactory: () => (/* reexport */ ChainManagerFactory),
97
97
  ChainTarget: () => (/* reexport */ ChainTarget),
98
+ CouponManager: () => (/* reexport */ CouponManager),
98
99
  CreditNote: () => (/* reexport */ CreditNote),
99
100
  CreditNoteLine: () => (/* reexport */ CreditNoteLine),
100
101
  CreditNoteRepo: () => (/* reexport */ CreditNoteRepo),
101
102
  Currency: () => (/* reexport */ Currency),
102
103
  Invoice: () => (/* reexport */ Invoice),
103
104
  InvoiceLine: () => (/* reexport */ InvoiceLine),
105
+ ItemOption: () => (/* reexport */ ItemOption),
106
+ ItemOptionLocale: () => (/* reexport */ ItemOptionLocale),
104
107
  KeyValueObject: () => (/* reexport */ q_utilities_.KeyValueObject),
105
108
  Merchandise: () => (/* reexport */ Merchandise),
106
109
  PaymentGateway: () => (/* reexport */ PaymentGateway),
@@ -109,9 +112,11 @@ __webpack_require__.d(__webpack_exports__, {
109
112
  PriceStrategy: () => (/* reexport */ PriceStrategy),
110
113
  Product: () => (/* reexport */ Product),
111
114
  Status: () => (/* reexport */ Status),
115
+ StoreItem: () => (/* reexport */ StoreItem),
112
116
  Transaction: () => (/* reexport */ Transaction),
113
117
  WalletItem: () => (/* reexport */ WalletItem),
114
118
  adminSettle: () => (/* reexport */ adminSettle),
119
+ calculateByCoupon: () => (/* reexport */ calculateByCoupon),
115
120
  calculator: () => (/* reexport */ calculator),
116
121
  checkDuplicate: () => (/* reexport */ checkDuplicate),
117
122
  convertTimestampToString: () => (/* reexport */ convertTimestampToString),
@@ -147,6 +152,8 @@ __webpack_require__.d(models_namespaceObject, {
147
152
  Currency: () => (Currency),
148
153
  Invoice: () => (Invoice),
149
154
  InvoiceLine: () => (InvoiceLine),
155
+ ItemOption: () => (ItemOption),
156
+ ItemOptionLocale: () => (ItemOptionLocale),
150
157
  KeyValueObject: () => (q_utilities_.KeyValueObject),
151
158
  Merchandise: () => (Merchandise),
152
159
  PaymentGateway: () => (PaymentGateway),
@@ -155,6 +162,7 @@ __webpack_require__.d(models_namespaceObject, {
155
162
  PriceStrategy: () => (PriceStrategy),
156
163
  Product: () => (Product),
157
164
  Status: () => (Status),
165
+ StoreItem: () => (StoreItem),
158
166
  Transaction: () => (Transaction),
159
167
  WalletItem: () => (WalletItem)
160
168
  });
@@ -754,20 +762,83 @@ const stringHelper = {
754
762
 
755
763
 
756
764
 
765
+ ;// ./lib/models/itemOption/itemOptionLocale.js
766
+ const itemOptionLocale_updateAllowedProps = [
767
+ 'label',
768
+ 'locale',
769
+ 'value'
770
+ ]
771
+
772
+ class ItemOptionLocale {
773
+ constructor(options = {}) {
774
+ options = options || {}
775
+ this.locale = options.locale
776
+ this.label = options.label
777
+ this.value = options.value || ''
778
+ }
779
+ static dummyData() {
780
+ return {
781
+ // locale: 'zh-hk',
782
+ }
783
+ }
784
+ static init(options = {}) {
785
+ if (options instanceof this) {
786
+ return options
787
+ }
788
+ const instance = new this(options)
789
+ return instance.isValid ? instance : null
790
+ }
791
+ static initFromArray(arr = []) {
792
+ if (Array.isArray(arr)) {
793
+ return arr.map((a) => this.init(a))
794
+ }
795
+ return []
796
+ }
797
+ static initOnlyValidFromArray(arr = []) {
798
+ return this.initFromArray(arr).filter((i) => i)
799
+ }
800
+ static get _classname() {
801
+ return 'ItemOptionLocale'
802
+ }
803
+ static get _superclass() {
804
+ return 'ItemOptionLocale'
805
+ }
806
+
807
+ get isValid() {
808
+ return !!this
809
+ }
810
+
811
+ update(update) {
812
+ Object.keys(update).forEach((key) => {
813
+ if (itemOptionLocale_updateAllowedProps.includes(key)) {
814
+ this[key] = update[key]
815
+ }
816
+ })
817
+ return this
818
+ }
819
+ }
820
+
821
+
822
+
757
823
  ;// ./lib/models/itemOption/itemOption.js
758
824
 
759
825
 
826
+
760
827
  const itemOption_updateAllowedProps = [
761
828
  'description',
762
829
  'key',
763
830
  'label',
764
831
  'type',
765
- 'value'
832
+ 'value',
833
+ 'locales'
766
834
  ]
767
835
 
768
836
  class ItemOption {
769
837
  constructor(options = {}) {
770
838
  options = options || {}
839
+ const { _ItemOptionLocale } = options._constructor || {}
840
+ this._ItemOptionLocale = _ItemOptionLocale && (_ItemOptionLocale._superclass === ItemOptionLocale._superclass) ? _ItemOptionLocale : ItemOptionLocale
841
+
771
842
  this.approved = options.approved || false
772
843
  this.description = options.description
773
844
  // this.header = options.header
@@ -775,9 +846,11 @@ class ItemOption {
775
846
  this.itemOptionType = options.itemOptionType || 'ItemOption'
776
847
  this.key = options.key
777
848
  this.label = options.label
849
+ this.layout = options.layout
778
850
  this.required = options.required || false
779
851
  this.type = options.type
780
852
  this.value = options.value || ''
853
+ this.locales = this._ItemOptionLocale.initOnlyValidFromArray(options.locales)
781
854
  }
782
855
  static dummyData() {
783
856
  return {
@@ -838,7 +911,12 @@ class ItemOption {
838
911
  update(update) {
839
912
  Object.keys(update).forEach((key) => {
840
913
  if (itemOption_updateAllowedProps.includes(key)) {
841
- this[key] = update[key]
914
+ if (key === 'locales') {
915
+ this[key] = this._ItemOptionLocale.initOnlyValidFromArray(update[key])
916
+ } else {
917
+ this[key] = update[key]
918
+ }
919
+ // this[key] = update[key]
842
920
  }
843
921
  })
844
922
  return this
@@ -860,6 +938,7 @@ function itemOption_setCode(options, key) {
860
938
 
861
939
 
862
940
 
941
+
863
942
  ;// ./lib/models/merchandiseOption/merchandiseOption.js
864
943
  class MerchandiseOption {
865
944
  constructor(options = {}) {
@@ -1169,7 +1248,7 @@ class PriceStrategy {
1169
1248
  acc = acc || matchAnd(key, value, payload)
1170
1249
  // Object.keys(value).forEach((path) => {
1171
1250
  // const val = lodash.get(payload[key], path)
1172
- // acc = acc || matcher(val, value[path])
1251
+ // acc = acc || _matcher(val, value[path])
1173
1252
  // })
1174
1253
  return acc
1175
1254
  }, false)
@@ -1223,7 +1302,8 @@ class PriceStrategy {
1223
1302
  function matchAnd(key, value, payload) {
1224
1303
  return Object.keys(value).reduce((acc, path) => {
1225
1304
  const val = external_lodash_.get(payload[key], path)
1226
- acc = acc && matcher(val, value[path])
1305
+ const actions = Object.keys(value[path])
1306
+ acc = acc && _matcher(val, value[path], actions, true)
1227
1307
  return acc
1228
1308
  }, true)
1229
1309
  }
@@ -1234,20 +1314,40 @@ function matchAnd(key, value, payload) {
1234
1314
  * @param {Object} [formula={}] - The formula object to check the value against.
1235
1315
  * @returns {boolean} - Whether the value matches the formula.
1236
1316
  */
1237
- function matcher(val, formula = {}) {
1238
- const [action] = Object.keys(formula)
1317
+ function _matcher(val, formula = {}, actions = [], match = true) {
1318
+ // const actions = Object.keys(formula)
1319
+ if (!match || actions.length === 0) {
1320
+ return match
1321
+ }
1322
+ const action = actions.shift()
1323
+ // const [action] = Object.keys(formula)
1239
1324
  const formulaValue = formula[action]
1325
+ match = _match({ action, formulaValue, val })
1326
+ return _matcher(val, formula, actions, match)
1327
+ }
1328
+
1329
+ function _match({ action, formulaValue, val }) {
1240
1330
  switch (action) {
1331
+ case 'elemMatch':
1241
1332
  case '$elemMatch': // val is array and formulaValue is object
1242
1333
  return (val || []).some((v) => {
1243
1334
  return (Object.keys(formulaValue)).filter((key) => {
1244
1335
  return Object.prototype.hasOwnProperty.call(v, key) && v[key] === formulaValue[key]
1245
1336
  }).length > 0
1246
1337
  })
1338
+ case 'eq':
1247
1339
  case '$eq':
1248
1340
  return external_lodash_.isEqual(val, formulaValue)
1341
+ case 'gt':
1342
+ case '$gt':
1343
+ return val > formulaValue
1344
+ case 'gte':
1345
+ case '$gte':
1346
+ return val >= formulaValue
1249
1347
  case '$in':
1250
1348
  return formulaValue.includes(val)
1349
+ case '$includes':
1350
+ return val.includes(formulaValue)
1251
1351
  case '$keyValue':
1252
1352
  if (Array.isArray(val)) {
1253
1353
  return (val.find((remark) => {
@@ -1258,6 +1358,15 @@ function matcher(val, formula = {}) {
1258
1358
  return formulaValue.key === val.key && formulaValue.values.includes(val.value)
1259
1359
  }
1260
1360
  return false
1361
+ case 'lt':
1362
+ case '$lt':
1363
+ return val < formulaValue
1364
+ case 'lte':
1365
+ case '$lte':
1366
+ return val <= formulaValue
1367
+ case 'ne':
1368
+ case '$ne':
1369
+ return val !== formulaValue
1261
1370
  default:
1262
1371
  return true
1263
1372
  }
@@ -1311,7 +1420,7 @@ class Price {
1311
1420
  name: 'Standard',
1312
1421
  dateBegin: new Date().valueOf(),
1313
1422
  dateEnd: new Date().valueOf() + 1,
1314
- priceStrategies: [this._PriceStrategy.dummyData()],
1423
+ priceStrategies: [PriceStrategy.dummyData()],
1315
1424
  // roles: []
1316
1425
  // qtyPerTransaction: QtyPerTransaction.init()
1317
1426
  }
@@ -1469,16 +1578,15 @@ class Price {
1469
1578
 
1470
1579
 
1471
1580
  const product_updateAllowedProps = [
1472
- 'active',
1473
- 'deleted',
1581
+ 'couponDetails',
1474
1582
  'description',
1475
1583
  'entitlements',
1476
1584
  'intangible',
1477
1585
  'limitPercentage',
1586
+ 'lineOptions',
1478
1587
  'maxPerWallet',
1479
1588
  'name',
1480
1589
  'originalStock',
1481
- 'owner',
1482
1590
  'printable',
1483
1591
  'printLayoutCodes',
1484
1592
  'printLayoutMappingCodes',
@@ -1486,34 +1594,31 @@ const product_updateAllowedProps = [
1486
1594
  // 'productCategoryCodes',
1487
1595
  'productGroupName',
1488
1596
  'productOptions',
1489
- 'remarks',
1490
1597
  'requiredProductCode',
1491
1598
  'stock'
1492
1599
  ]
1493
1600
 
1494
- class Product {
1601
+ class Product extends q_utilities_.TenantAwareEntity {
1495
1602
  constructor(options = {}) {
1496
1603
  options = options || {}
1604
+ super(options)
1605
+
1497
1606
  const { _ItemOption } = options._constructor || {}
1498
1607
  this._ItemOption = _ItemOption && (_ItemOption._superclass === ItemOption) ? _ItemOption : ItemOption
1499
1608
 
1500
1609
  const id = options._id || options.id
1501
1610
  this.id = setId(id)
1502
1611
  this._type = options._type || 'Product'
1503
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
1504
- this.created = options.created || (new Date()).valueOf()
1505
- this.creator = options.creator
1506
- this.deleted = options.deleted || false
1612
+
1613
+ this.couponDetails = options.couponDetails
1507
1614
  this.description = options.description || ''
1508
1615
  this.entitlements = options.entitlements // ['freeRegistration'], ['presidentialDinner', 'galaDinner']
1509
1616
  this.intangible = options.intangible || false
1510
1617
  this.limitPercentage = options.limitPercentage || 100
1618
+ this.lineOptions = this._ItemOption.initOnlyValidFromArray(options.lineOptions)
1511
1619
  this.maxPerWallet = options.maxPerWallet || 1
1512
- this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
1513
- this.modified = options.modified || (new Date()).valueOf()
1514
1620
  this.name = options.name || ''
1515
1621
  this.originalStock = options.originalStock || 0
1516
- this.owner = options.owner
1517
1622
  this.printable = options.printable || false
1518
1623
  this.printLayoutCodes = options.printLayoutCodes || []
1519
1624
  // will be not use property 'printLayoutMappingCodes'
@@ -1523,10 +1628,9 @@ class Product {
1523
1628
  this.productCode = product_setCode(options, 'productCode')
1524
1629
  this.productGroupName = (typeof options.productGroupName !== 'undefined') ? options.productGroupName.toUpperCase() : options.productGroupName || 'DEFAULT'
1525
1630
  this.productOptions = this._ItemOption.initOnlyValidFromArray(options.productOptions)
1631
+ this.productType = options.productType || 'Product'
1526
1632
  this.requiredProductCode = options.requiredProductCode
1527
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
1528
1633
  this.stock = options.stock || 0
1529
- this.tenantCode = options.tenantCode
1530
1634
  }
1531
1635
 
1532
1636
  // class method
@@ -1536,22 +1640,6 @@ class Product {
1536
1640
  tenantCode: 'tenantCode'
1537
1641
  }
1538
1642
  }
1539
- static init(options = {}) {
1540
- if (options instanceof this) {
1541
- return options
1542
- }
1543
- const instance = new this(options)
1544
- return instance.isValid ? instance : null
1545
- }
1546
- static initFromArray(arr = []) {
1547
- if (Array.isArray(arr)) {
1548
- return arr.map((a) => this.init(a))
1549
- }
1550
- return []
1551
- }
1552
- static initOnlyValidFromArray(arr = []) {
1553
- return this.initFromArray(arr).filter((i) => i)
1554
- }
1555
1643
  static get _classname() {
1556
1644
  return 'Product'
1557
1645
  }
@@ -1561,11 +1649,17 @@ class Product {
1561
1649
 
1562
1650
  // getters
1563
1651
  get isValid() {
1564
- return !!this.tenantCode && !!this.name
1652
+ return super.isValid && !!this.name
1565
1653
  }
1566
1654
  get isBadge() {
1567
1655
  return this.productGroupName === 'BADGE'
1568
1656
  }
1657
+ get isCoupon() {
1658
+ return this.productGroupName === 'COUPON'
1659
+ }
1660
+ get isItemCoupon() {
1661
+ return this.couponDetails ? this.couponDetails.item : false
1662
+ }
1569
1663
  get isPrintable() {
1570
1664
  return this.printLayoutMappingCodes.length > 0
1571
1665
  }
@@ -1604,6 +1698,12 @@ class Product {
1604
1698
  return acc
1605
1699
  }, { errMsgs: [] })
1606
1700
  }
1701
+ getCode() {
1702
+ return this.productCode
1703
+ }
1704
+ getMetadataValueByKey(key) {
1705
+ return q_utilities_.Metadata.getValueByKey(this.metadata || [], key)
1706
+ }
1607
1707
  getProductOptionByKey(key) {
1608
1708
  const arr = this._ItemOption.getByKey(this.productOptions, key)
1609
1709
  if (arr.length === 1) {
@@ -1614,28 +1714,32 @@ class Product {
1614
1714
  hasStock(qty) {
1615
1715
  return this.stock >= qty
1616
1716
  }
1717
+ isApplicableCoupon(obj) {
1718
+ const { merchandiseCodes = [] } = this.couponDetails || {}
1719
+ return merchandiseCodes.length > 0 ? merchandiseCodes.includes(obj.merchandiseCode) : true
1720
+ }
1721
+ isQualified(data) {
1722
+ const rules = this.getMetadataValueByKey('RULES') || []
1723
+ return (rules.length === 0)
1724
+ ? true
1725
+ : rules.reduce((acc, r) => {
1726
+ return acc || (0,q_utilities_.getValidation)(r, data, _getDataByKey, q_utilities_.KeyValueObject)
1727
+ }, false)
1728
+ }
1617
1729
  isTicket() {
1618
1730
  return false
1619
1731
  }
1620
- setModified() {
1621
- this.modified = (new Date()).valueOf()
1622
- return this
1623
- }
1624
1732
  update(update) {
1625
1733
  Object.keys(update).forEach((key) => {
1626
1734
  if (product_updateAllowedProps.includes(key)) {
1627
- if (key === 'metadata') {
1628
- this[key] = q_utilities_.Metadata.initOnlyValidFromArray(update[key])
1629
- } else if (key === 'productOptions') {
1735
+ if (key === 'productOptions' || key === 'lineOptions') {
1630
1736
  this[key] = this._ItemOption.initOnlyValidFromArray(update[key])
1631
- } else if (key === 'remarks') {
1632
- this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
1633
1737
  } else {
1634
1738
  this[key] = update[key]
1635
1739
  }
1636
1740
  }
1637
1741
  })
1638
- return this.setModified()
1742
+ return super.update(update)
1639
1743
  }
1640
1744
  }
1641
1745
 
@@ -1654,6 +1758,10 @@ function product_setCode(options, key) {
1654
1758
  return stringHelper.setCode()
1655
1759
  }
1656
1760
 
1761
+ function _getDataByKey(key, data) {
1762
+ return (0,q_utilities_.getValueByKeys)(key.split('.'), data)
1763
+ }
1764
+
1657
1765
 
1658
1766
 
1659
1767
  ;// ./lib/models/product/productRepo.js
@@ -1693,11 +1801,8 @@ class ProductRepo extends q_utilities_.Repo {
1693
1801
 
1694
1802
 
1695
1803
 
1696
-
1697
1804
  const merchandise_updateAllowedProps = [
1698
- 'active',
1699
1805
  'defaultCurrency',
1700
- 'deleted',
1701
1806
  'description',
1702
1807
  'eventSessionCode',
1703
1808
  'intangible',
@@ -1705,23 +1810,22 @@ const merchandise_updateAllowedProps = [
1705
1810
  'max',
1706
1811
  'merchandiseCategoryCodes',
1707
1812
  'merchandiseOptions',
1708
- 'metadata',
1709
1813
  'name',
1710
1814
  'onlyFor',
1711
- 'owner',
1712
1815
  'prices',
1713
1816
  'pricings',
1714
1817
  'priority',
1715
1818
  'productCodes',
1716
- 'remarks',
1717
1819
  'sku',
1718
1820
  'stock',
1719
1821
  'visibleBy'
1720
1822
  ]
1721
1823
 
1722
- class Merchandise {
1824
+ class Merchandise extends q_utilities_.TenantAwareEntity {
1723
1825
  constructor(options = {}) {
1724
1826
  options = options || {}
1827
+ super(options)
1828
+
1725
1829
  const { _ItemOption, _ItemOptionFillIn, _MerchandiseOption, _Price, _Product } = options._constructor || {}
1726
1830
  this._ItemOption = _ItemOption && (_ItemOption._superclass === ItemOption._superclass) ? _I_ItemOptiontemOptionFillIn : ItemOption
1727
1831
  this._ItemOptionFillIn = _ItemOptionFillIn && (_ItemOptionFillIn._superclass === ItemOptionFillIn._superclass) ? _ItemOptionFillIn : ItemOptionFillIn
@@ -1730,16 +1834,11 @@ class Merchandise {
1730
1834
  this._Product = _Product && (_Product._superclass === Product._superclass) ? _Product : Product
1731
1835
 
1732
1836
  this._products = options._products || []
1733
- this._tenant = options._tenant
1734
1837
  this._type = options._type || 'Merchandise'
1735
1838
 
1736
1839
  const id = options._id || options.id
1737
1840
  this.id = merchandise_setId(id)
1738
- this._type = options._type || 'Merchandise'
1739
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
1740
- this.created = options.created || (new Date()).valueOf()
1741
- this.creator = options.creator
1742
- this.deleted = options.deleted || false
1841
+
1743
1842
  this.defaultCurrency = options.defaultCurrency || 'HKD'
1744
1843
  this.description = options.description
1745
1844
  this.free = options.free || false
@@ -1748,17 +1847,12 @@ class Merchandise {
1748
1847
  this.merchandiseCategoryCodes = options.merchandiseCategoryCodes || []
1749
1848
  this.merchandiseCode = merchandise_setCode(options, 'merchandiseCode')
1750
1849
  this.merchandiseOptions = initMerchandiseOptions(this, options)
1751
- this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
1752
- this.modified = options.modified || (new Date()).valueOf()
1753
1850
  this.name = options.name || ''
1754
- this.owner = options.owner
1755
1851
  this.prices = this._Price.initOnlyValidFromArray(options.prices)
1756
1852
  this.productCodes = options.productCodes || []
1757
1853
  this.priority = options.priority || 100
1758
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
1759
1854
  this.sku = options.sku || ''
1760
1855
  this.stock = options.stock || 0
1761
- this.tenantCode = options.tenantCode
1762
1856
  }
1763
1857
 
1764
1858
  // Class Mehtods
@@ -1779,22 +1873,6 @@ class Merchandise {
1779
1873
  tenantCode: '85223977000',
1780
1874
  }
1781
1875
  }
1782
- static init(options = {}) {
1783
- if (options instanceof this) {
1784
- return options
1785
- }
1786
- const instance = new this(options)
1787
- return instance.isValid ? instance : null
1788
- }
1789
- static initFromArray(arr = []) {
1790
- if (Array.isArray(arr)) {
1791
- return arr.map((a) => this.init(a))
1792
- }
1793
- return []
1794
- }
1795
- static initOnlyValidFromArray(arr = []) {
1796
- return this.initFromArray(arr).filter((i) => i)
1797
- }
1798
1876
  static get _classname() {
1799
1877
  return 'Merchandise'
1800
1878
  }
@@ -1848,7 +1926,7 @@ class Merchandise {
1848
1926
  return this.printOut.isPrintable
1849
1927
  }
1850
1928
  get isValid() {
1851
- return !!this.tenantCode && !!this.name && (!!this.productCodes && this.productCodes.length > 0)
1929
+ return super.isValid && !!this.name && (!!this.productCodes && this.productCodes.length > 0)
1852
1930
  }
1853
1931
  get products() {
1854
1932
  return this._Product.initOnlyValidFromArray(this._products || [])
@@ -1995,6 +2073,43 @@ class Merchandise {
1995
2073
  }
1996
2074
  return info
1997
2075
  }
2076
+ getBeginAndEndDates() {
2077
+ const dates = {
2078
+ dateBegin: null,
2079
+ dateEnd: null
2080
+ }
2081
+ // BUG this.pricings is undefind
2082
+ return this.pricings.reduce((acc, pricing) => {
2083
+ if (!acc.dateBegin || (pricing.dateBegin > acc.dateBegin)) {
2084
+ acc.dateBegin = pricing.dateBegin
2085
+ }
2086
+
2087
+ if (!acc.dateEnd || (pricing.dateEnd <= acc.dateEnd)) {
2088
+ acc.dateEnd = pricing.dateEnd
2089
+ }
2090
+ return acc
2091
+ }, dates)
2092
+ }
2093
+ getCode() {
2094
+ return this.merchandiseCode
2095
+ }
2096
+ getCurrentPrice() {
2097
+ const timestamp = (new Date()).valueOf()
2098
+ const prices = this.getPricesByTime(timestamp)
2099
+ if (prices.length === 1) {
2100
+ return prices[0]
2101
+ }
2102
+ return null
2103
+ }
2104
+ getCurrentPriceByRoleCodes(roleCodes) {
2105
+ const timestamp = (new Date()).valueOf()
2106
+ let prices = this.getPricesByTime(timestamp)
2107
+ prices = Price.getPricesByRoleCodes(prices, roleCodes)
2108
+ if (prices.length === 1) {
2109
+ return prices[0]
2110
+ }
2111
+ return null
2112
+ }
1998
2113
  getItemOptionInfos(cartItems = []) {
1999
2114
  return cartItems.reduce((acc, cartItem) => {
2000
2115
  const itemOptionFillIns = cartItem.getItemOptionFillIns()
@@ -2021,47 +2136,13 @@ class Merchandise {
2021
2136
  }
2022
2137
  return null
2023
2138
  }
2024
- getProducts() {
2025
- return this.products || []
2026
- }
2027
- getCurrentPriceByRoleCodes(roleCodes) {
2028
- const timestamp = (new Date()).valueOf()
2029
- let prices = this.getPricesByTime(timestamp)
2030
- prices = Price.getPricesByRoleCodes(prices, roleCodes)
2031
- if (prices.length === 1) {
2032
- return prices[0]
2033
- }
2034
- return null
2035
- }
2036
- getCurrentPrice() {
2037
- const timestamp = (new Date()).valueOf()
2038
- const prices = this.getPricesByTime(timestamp)
2039
- if (prices.length === 1) {
2040
- return prices[0]
2041
- }
2042
- return null
2139
+ getPrices() {
2140
+ return this.prices ? this.prices : []
2043
2141
  }
2044
2142
  getPricesByTime(timestamp) {
2045
2143
  const copyDate = timestamp || (new Date()).valueOf()
2046
2144
  return Price.getPricesByTime(this.prices, copyDate)
2047
2145
  }
2048
- getBeginAndEndDates() {
2049
- const dates = {
2050
- dateBegin: null,
2051
- dateEnd: null
2052
- }
2053
- // BUG this.pricings is undefind
2054
- return this.pricings.reduce((acc, pricing) => {
2055
- if (!acc.dateBegin || (pricing.dateBegin > acc.dateBegin)) {
2056
- acc.dateBegin = pricing.dateBegin
2057
- }
2058
-
2059
- if (!acc.dateEnd || (pricing.dateEnd <= acc.dateEnd)) {
2060
- acc.dateEnd = pricing.dateEnd
2061
- }
2062
- return acc
2063
- }, dates)
2064
- }
2065
2146
  getPriceByTimeAndRoleCodes(timestamp, roleCodes) {
2066
2147
  let prices = this.getPricesByTime(timestamp)
2067
2148
  prices = Price.getPricesByRoleCodes(prices, roleCodes)
@@ -2070,14 +2151,13 @@ class Merchandise {
2070
2151
  }
2071
2152
  return null
2072
2153
  }
2073
- getPrices() {
2074
- return this.prices ? this.prices : []
2075
- }
2076
- getRemarksByKey(key) {
2077
- return q_utilities_.KeyValueObject.getValuesByKey(this.remarks, key)
2154
+ getProducts() {
2155
+ return this.products || []
2078
2156
  }
2079
- getStock() {
2080
- return this.stock || 0
2157
+ getProductsMetadataValuesByKey(key) {
2158
+ return this.products.map((p) => {
2159
+ return p.getMetadataValueByKey(key)
2160
+ }).filter((i) => i)
2081
2161
  }
2082
2162
  getProductsQty(qty = 1) {
2083
2163
  return this.productCodes.reduce((acc, productCode) => {
@@ -2089,13 +2169,16 @@ class Merchandise {
2089
2169
  return acc
2090
2170
  }, {})
2091
2171
  }
2172
+ getRemarksByKey(key) {
2173
+ return q_utilities_.KeyValueObject.getValuesByKey(this.remarks, key)
2174
+ }
2175
+ getStock() {
2176
+ return this.stock || 0
2177
+ }
2178
+
2092
2179
  reachLimit(qty) {
2093
2180
  return this.max < qty
2094
2181
  }
2095
- setModified() {
2096
- this.modified = (new Date()).valueOf()
2097
- return this
2098
- }
2099
2182
  setPrices(prices) {
2100
2183
  if (Array.isArray(prices)) {
2101
2184
  this.prices = Price.initOnlyValidFromArray(prices)
@@ -2109,18 +2192,14 @@ class Merchandise {
2109
2192
  this[key] = this._ItemOption.initOnlyValidFromArray(update[key])
2110
2193
  } else if (key === 'merchandiseOptions' && !!this.tenantCode) {
2111
2194
  this[key] = MerchandiseOption.initOnlyValidFromArray(update[key])
2112
- } else if (key === 'metadata') {
2113
- this[key] = q_utilities_.Metadata.initOnlyValidFromArray(update[key])
2114
2195
  } else if (key === 'prices') {
2115
2196
  this[key] = Price.initOnlyValidFromArray(update[key])
2116
- } else if (key === 'remarks') {
2117
- this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
2118
2197
  } else {
2119
2198
  this[key] = update[key]
2120
2199
  }
2121
2200
  }
2122
2201
  })
2123
- return this.setModified()
2202
+ return super.update(update)
2124
2203
  }
2125
2204
  }
2126
2205
 
@@ -2640,6 +2719,9 @@ class Status {
2640
2719
  // this.cancelled = null
2641
2720
  // return this
2642
2721
  // }
2722
+ unSetOnHold() {
2723
+ this.onHold = null
2724
+ }
2643
2725
  update(update) {
2644
2726
  Object.keys(update).forEach((key) => {
2645
2727
  if (!notUpdateAllowedProps.includes(key)) {
@@ -2661,14 +2743,14 @@ class Status {
2661
2743
  // import { WalletItem } from '../walletItem/index.js'
2662
2744
 
2663
2745
  const cart_updateAllowedProps = [
2664
- 'active',
2665
- 'remarks',
2666
- 'deleted',
2746
+
2667
2747
  ]
2668
2748
 
2669
- class Cart {
2749
+ class Cart extends q_utilities_.TenantAwareEntity {
2670
2750
  constructor(options = {}) {
2671
2751
  options = options || {}
2752
+ super(options)
2753
+
2672
2754
  const { _CartItem, _Merchandise, _Status } = options._constructor || {}
2673
2755
  this._CartItem = _CartItem && (_CartItem._superclass === CartItem._superclass) ? _CartItem : CartItem
2674
2756
  this._Merchandise = _Merchandise && (_Merchandise._superclass === Merchandise._superclass) ? _Merchandise : Merchandise
@@ -2681,18 +2763,9 @@ class Cart {
2681
2763
  this._merchandises = options._merchandises
2682
2764
  this._type = options._type || 'Cart'
2683
2765
 
2684
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
2685
2766
  this.cartCode = cart_setCode(options, 'cartCode')
2686
2767
  this.cartItems = this._CartItem.initOnlyValidFromArray(options.cartItems)
2687
- this.created = options.created || (new Date()).valueOf()
2688
- this.creator = options.creator
2689
- this.deleted = options.deleted || false
2690
- this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
2691
- this.modified = options.modified || (new Date()).valueOf()
2692
- this.owner = options.owner
2693
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
2694
2768
  this.status = this._Status.init(options.status)
2695
- this.tenantCode = options.tenantCode
2696
2769
  }
2697
2770
 
2698
2771
  // Class Methods
@@ -2702,22 +2775,6 @@ class Cart {
2702
2775
  tenantCode: 'tenantCode'
2703
2776
  }
2704
2777
  }
2705
- static init(options = {}) {
2706
- if (options instanceof this) {
2707
- return options
2708
- }
2709
- const instance = new this(options)
2710
- return instance.isValid ? instance : null
2711
- }
2712
- static initFromArray(arr = []) {
2713
- if (Array.isArray(arr)) {
2714
- return arr.map((a) => this.init(a))
2715
- }
2716
- return []
2717
- }
2718
- static initOnlyValidFromArray(arr = []) {
2719
- return this.initFromArray(arr).filter((i) => i)
2720
- }
2721
2778
  static get _classname() {
2722
2779
  return 'Cart'
2723
2780
  }
@@ -2727,7 +2784,7 @@ class Cart {
2727
2784
 
2728
2785
  // getters
2729
2786
  get isValid() {
2730
- return !!this.tenantCode
2787
+ return super.isValid
2731
2788
  }
2732
2789
  get isActive() {
2733
2790
  return !!this.active
@@ -2843,6 +2900,9 @@ class Cart {
2843
2900
  getCartItemCodes() {
2844
2901
  return this.cartItems.map((cartItem) => cartItem.cartItemCode)
2845
2902
  }
2903
+ getCode() {
2904
+ return this.cartCode
2905
+ }
2846
2906
  getCurrencyCode() {
2847
2907
  return this.cartItems.length > 0
2848
2908
  ? this.cartItems[0].getCurrencyCode()
@@ -2896,10 +2956,6 @@ class Cart {
2896
2956
  this.status.setCompleted()
2897
2957
  return this.setModified()
2898
2958
  }
2899
- setModified() {
2900
- this.modified = (new Date()).valueOf()
2901
- return this
2902
- }
2903
2959
  updateAvailable({ isCoordinator, selectCartItems }) {
2904
2960
  try {
2905
2961
  if (!isCoordinator) {
@@ -2913,16 +2969,10 @@ class Cart {
2913
2969
  update(update) {
2914
2970
  Object.keys(update).forEach((key) => {
2915
2971
  if (cart_updateAllowedProps.includes(key)) {
2916
- if (key === 'metadata') {
2917
- this[key] = q_utilities_.Metadata.initOnlyValidFromArray(update[key])
2918
- } else if (key === 'remarks') {
2919
- this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
2920
- } else {
2921
- this[key] = update[key]
2922
- }
2972
+ this[key] = update[key]
2923
2973
  }
2924
2974
  })
2925
- return this.setModified()
2975
+ return super.update(update)
2926
2976
  }
2927
2977
  updateStock() {
2928
2978
  if (this.cartItems.length === 0) {
@@ -3008,22 +3058,20 @@ class CartRepo extends q_utilities_.Repo {
3008
3058
 
3009
3059
 
3010
3060
  const category_updateAllowedProps = [
3011
- 'active',
3012
3061
  'codes',
3013
- 'deleted',
3014
3062
  'description',
3015
3063
  'max',
3016
3064
  'min',
3017
3065
  'name',
3018
- 'owner',
3019
3066
  'priority',
3020
3067
  'productCodes',
3021
- 'remarks',
3022
3068
  ]
3023
3069
 
3024
- class Category {
3070
+ class Category extends q_utilities_.TenantAwareEntity {
3025
3071
  constructor(options) {
3026
3072
  options = options || {}
3073
+ super(options)
3074
+
3027
3075
  const { _Product } = options._constructor || {}
3028
3076
  this._Product = _Product && (_Product._superclass === Product._superclass) ? _Product : Product
3029
3077
 
@@ -3032,22 +3080,15 @@ class Category {
3032
3080
 
3033
3081
  const id = options._id || options.id
3034
3082
  this.id = category_setId(id)
3035
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
3083
+
3036
3084
  this.categoryCode = category_setCode(options, 'categoryCode')
3037
3085
  this.codes = options.codes || []
3038
- this.created = options.created || (new Date()).valueOf()
3039
- this.creator = options.creator
3040
- this.deleted = options.deleted || false
3041
3086
  this.description = options.description
3042
3087
  this.max = options.max || 1
3043
3088
  this.min = options.min || 0
3044
- this.modified = options.modified || (new Date()).valueOf()
3045
3089
  this.name = options.name
3046
- this.owner = options.owner
3047
3090
  this.priority = options.priority || 10
3048
3091
  this.productCodes = options.productCodes || []
3049
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
3050
- this.tenantCode = options.tenantCode
3051
3092
  }
3052
3093
 
3053
3094
  // class methods
@@ -3057,22 +3098,6 @@ class Category {
3057
3098
  tenantCode: 'tenantCode'
3058
3099
  }
3059
3100
  }
3060
- static init(options = {}) {
3061
- if (options instanceof this) {
3062
- return options
3063
- }
3064
- const instance = new this(options)
3065
- return instance.isValid ? instance : null
3066
- }
3067
- static initFromArray(arr = []) {
3068
- if (Array.isArray(arr)) {
3069
- return arr.map((a) => this.init(a))
3070
- }
3071
- return []
3072
- }
3073
- static initOnlyValidFromArray(arr = []) {
3074
- return this.initFromArray(arr).filter((i) => i)
3075
- }
3076
3101
  static get _classname() {
3077
3102
  return 'Category'
3078
3103
  }
@@ -3082,29 +3107,20 @@ class Category {
3082
3107
 
3083
3108
  // getters
3084
3109
  get isValid() {
3085
- return !!this.name && !!this.tenantCode && this.max > this. min
3110
+ return super.isValid && !!this.name && this.max > this. min
3086
3111
  }
3087
3112
  get products() {
3088
3113
  return this._Product.initOnlyValidFromArray(this._products)
3089
3114
  }
3090
3115
 
3091
3116
  // instance methods
3092
- setModified() {
3093
- this.modified = (new Date()).valueOf()
3094
- return this
3095
- }
3096
-
3097
3117
  update(update) {
3098
3118
  Object.keys(update).forEach((key) => {
3099
3119
  if (category_updateAllowedProps.includes(key)) {
3100
- if (key === 'remarks') {
3101
- this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
3102
- } else {
3103
- this[key] = update[key]
3104
- }
3120
+ this[key] = update[key]
3105
3121
  }
3106
3122
  })
3107
- return this.setModified()
3123
+ return super.update(update)
3108
3124
  }
3109
3125
  }
3110
3126
 
@@ -3161,20 +3177,19 @@ class CategoryRepo extends q_utilities_.Repo {
3161
3177
 
3162
3178
 
3163
3179
  const creditNoteLine_updateAllowedProps = [
3164
- 'active',
3165
3180
  'amount',
3166
3181
  // 'deduction',
3167
- 'deleted',
3168
3182
  'description',
3169
3183
  // 'discount',
3170
3184
  'qty',
3171
- 'remarks',
3172
3185
  // 'unitPrice'
3173
3186
  ]
3174
3187
 
3175
- class CreditNoteLine {
3188
+ class CreditNoteLine extends q_utilities_.TenantAwareEntity {
3176
3189
  constructor(options = {}) {
3177
3190
  options = options || {}
3191
+ super(options)
3192
+
3178
3193
  const { _Amount } = options._constructor || {}
3179
3194
  this._Amount = _Amount && (_Amount._superclass === Amount._superclass) ? _Amount : Amount
3180
3195
 
@@ -3183,21 +3198,14 @@ class CreditNoteLine {
3183
3198
 
3184
3199
  const id = options._id || options.id
3185
3200
  this.id = creditNoteLine_setId(id)
3186
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
3201
+
3187
3202
  this.amount = this._Amount.init(options.amount)
3188
- this.created = options.created || (new Date()).valueOf()
3189
- this.creator = options.creator
3190
3203
  this.creditNoteCode = options.creditNoteCode
3191
3204
  this.creditNoteLineCode = creditNoteLine_setCode(options, 'creditNoteLineCode')
3192
3205
  // this.deduction = this._Amount.init(options.deduction)
3193
- this.deleted = options.deleted || false
3194
3206
  this.description = options.description
3195
3207
  // this.discount = options.discount || 0
3196
- this.modified = options.modified || (new Date()).valueOf()
3197
- this.owner = options.owner
3198
3208
  this.qty = options.qty || 1
3199
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
3200
- this.tenantCode = options.tenantCode
3201
3209
  // this.unitPrice = Amount.init(options.unitPrice)
3202
3210
  }
3203
3211
 
@@ -3208,22 +3216,6 @@ class CreditNoteLine {
3208
3216
  tenantCode: 'tenantCode'
3209
3217
  }
3210
3218
  }
3211
- static init(options = {}) {
3212
- if (options instanceof this) {
3213
- return options
3214
- }
3215
- const instance = new this(options)
3216
- return instance.isValid ? instance : null
3217
- }
3218
- static initFromArray(arr = []) {
3219
- if (Array.isArray(arr)) {
3220
- return arr.map((a) => this.init(a))
3221
- }
3222
- return []
3223
- }
3224
- static initOnlyValidFromArray(arr = []) {
3225
- return this.initFromArray(arr).filter((i) => i)
3226
- }
3227
3219
  static get _classname() {
3228
3220
  return 'CreditNoteLine'
3229
3221
  }
@@ -3234,7 +3226,7 @@ class CreditNoteLine {
3234
3226
 
3235
3227
  // getters
3236
3228
  get isValid() {
3237
- return !!this.creditNoteCode && !!this.tenantCode
3229
+ return super.isValid && !!this.creditNoteCode
3238
3230
  }
3239
3231
 
3240
3232
  // instance methods
@@ -3245,10 +3237,6 @@ class CreditNoteLine {
3245
3237
  }
3246
3238
  return this
3247
3239
  }
3248
- setModified() {
3249
- this.modified = (new Date()).valueOf()
3250
- return this
3251
- }
3252
3240
 
3253
3241
  update(update) {
3254
3242
  Object.keys(update).forEach((key) => {
@@ -3262,7 +3250,7 @@ class CreditNoteLine {
3262
3250
  }
3263
3251
  }
3264
3252
  })
3265
- return this.setModified()
3253
+ return super.update(update)
3266
3254
  }
3267
3255
  }
3268
3256
 
@@ -3321,17 +3309,16 @@ class CreditNoteLineRepo extends q_utilities_.Repo {
3321
3309
 
3322
3310
 
3323
3311
  const creditNote_updateAllowedProps = [
3324
- 'active',
3325
- 'deleted',
3326
3312
  'description',
3327
- 'remarks',
3328
3313
  'status'
3329
3314
  ]
3330
3315
 
3331
- class CreditNote {
3316
+ class CreditNote extends q_utilities_.TenantAwareEntity {
3332
3317
  constructor(options = {}) {
3333
3318
  options = options || {}
3334
- const { _Amount, _CreditNoteLine } = options._constructor || {}
3319
+ super(options)
3320
+
3321
+ const { _Amount, _CreditNoteLine, _Status } = options._constructor || {}
3335
3322
  this._Amount = _Amount && (_Amount._superclass === Amount._superclass) ? _Amount : Amount
3336
3323
  this._CreditNoteLine = _CreditNoteLine && (_CreditNoteLine._superclass === CreditNoteLine._superclass) ? _CreditNoteLine : CreditNoteLine
3337
3324
  this._Status = _Status && (_Status._superclass === Status._superclass) ? _Status : Status
@@ -3340,21 +3327,13 @@ class CreditNote {
3340
3327
 
3341
3328
  const id = options._id || options.id
3342
3329
  this.id = creditNote_setId(id)
3343
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
3330
+
3344
3331
  this.amount = this._Amount.init(options.amount)
3345
- this.created = options.created || (new Date()).valueOf()
3346
- this.creator = options.creator
3347
3332
  this.creditNoteCode = creditNote_setCode(options, 'creditNoteCode')
3348
3333
  this.creditNoteLines = this._CreditNoteLine.initOnlyValidFromArray(options.creditNoteLines)
3349
- this.deleted = options.deleted || false
3350
3334
  this.description = options.description
3351
3335
  this.invoiceCode = options.invoiceCode
3352
- this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
3353
- this.modified = options.modified || (new Date()).valueOf()
3354
- this.owner = options.owner
3355
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
3356
3336
  this.status = this._Status.init(options.status)
3357
- this.tenantCode = options.tenantCode
3358
3337
  }
3359
3338
 
3360
3339
  // Class Methods
@@ -3364,22 +3343,6 @@ class CreditNote {
3364
3343
  tenantCode: 'tenantCode'
3365
3344
  }
3366
3345
  }
3367
- static init(options = {}) {
3368
- if (options instanceof this) {
3369
- return options
3370
- }
3371
- const instance = new this(options)
3372
- return instance.isValid ? instance : null
3373
- }
3374
- static initFromArray(arr = []) {
3375
- if (Array.isArray(arr)) {
3376
- return arr.map((a) => this.init(a))
3377
- }
3378
- return []
3379
- }
3380
- static initOnlyValidFromArray(arr = []) {
3381
- return this.initFromArray(arr).filter((i) => i)
3382
- }
3383
3346
  static get _classname() {
3384
3347
  return 'CreditNote'
3385
3348
  }
@@ -3397,9 +3360,11 @@ class CreditNote {
3397
3360
  }
3398
3361
 
3399
3362
  get isValid() {
3400
- return !!this.tenantCode && !!this.invoiceCode
3363
+ return super.isValid && !!this.invoiceCode
3364
+ }
3365
+ getCode() {
3366
+ return this.creditNoteCode
3401
3367
  }
3402
-
3403
3368
  setAmount(amount) {
3404
3369
  const a = this_Amount.init(amount)
3405
3370
  if (this.isPending && a) {
@@ -3411,10 +3376,6 @@ class CreditNote {
3411
3376
  this.status.setCompleted()
3412
3377
  return this.setModified()
3413
3378
  }
3414
- setModified() {
3415
- this.modified = (new Date()).valueOf()
3416
- return this
3417
- }
3418
3379
  setPaid(t) {
3419
3380
  this.status.setPaid(t)
3420
3381
  return this.setModified()
@@ -3424,10 +3385,6 @@ class CreditNote {
3424
3385
  if (creditNote_updateAllowedProps.includes(key)) {
3425
3386
  if (key === 'amount') {
3426
3387
  this[key] = this._Amount.init(update[key])
3427
- } else if (key === 'metadata') {
3428
- this[key] = q_utilities_.Metadata.initOnlyValidFromArray(update[key])
3429
- } else if (key === 'remarks') {
3430
- this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
3431
3388
  } else if (key === 'status') {
3432
3389
  this[key] = this._Status.init(update[key])
3433
3390
  } else {
@@ -3435,7 +3392,7 @@ class CreditNote {
3435
3392
  }
3436
3393
  }
3437
3394
  })
3438
- return this.setModified()
3395
+ return super.update(update)
3439
3396
  }
3440
3397
  }
3441
3398
 
@@ -3489,35 +3446,27 @@ class CreditNoteRepo extends q_utilities_.Repo {
3489
3446
 
3490
3447
 
3491
3448
  const currency_updateAllowedProps = [
3492
- 'active',
3493
- 'deleted',
3494
3449
  'description',
3495
3450
  'name',
3496
- 'remarks',
3497
3451
  'symbol'
3498
3452
  ]
3499
3453
 
3500
- class Currency {
3454
+ class Currency extends q_utilities_.TenantAwareEntity {
3501
3455
  constructor(options = {}) {
3502
3456
  options = options || {}
3457
+ super(options)
3458
+
3503
3459
  const id = options._id || options.id
3504
3460
  this.id = currency_setId(id)
3505
3461
 
3506
3462
  this._type = options._type || 'Currency'
3507
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
3463
+
3508
3464
  this.code = options.code // 'HKD'
3509
- this.created = options.created || (new Date()).valueOf()
3510
- this.creator = options.creator
3511
3465
  this.currencyCode = currency_setCode(options, 'currencyCode')
3512
- this.deleted = options.deleted || false
3513
3466
  this.description = options.description
3514
3467
  this.factor = options.factor || 1 // 100
3515
- this.modified = options.modified || (new Date()).valueOf()
3516
3468
  this.name = options.name
3517
- this.owner = options.owner
3518
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
3519
3469
  this.symbol = options.symbol || null
3520
- this.tenantCode = options.tenantCode
3521
3470
  this.unit = options.unit
3522
3471
  }
3523
3472
  static dummyData() {
@@ -3529,22 +3478,6 @@ class Currency {
3529
3478
  unit: 'Cent',
3530
3479
  }
3531
3480
  }
3532
- static init(options = {}) {
3533
- if (options instanceof this) {
3534
- return options
3535
- }
3536
- const instance = new this(options)
3537
- return instance.isValid ? instance : null
3538
- }
3539
- static initFromArray(arr = []) {
3540
- if (Array.isArray(arr)) {
3541
- return arr.map((a) => this.init(a))
3542
- }
3543
- return []
3544
- }
3545
- static initOnlyValidFromArray(arr = []) {
3546
- return this.initFromArray(arr).filter((i) => i)
3547
- }
3548
3481
  static get _classname() {
3549
3482
  return 'Currency'
3550
3483
  }
@@ -3553,29 +3486,23 @@ class Currency {
3553
3486
  }
3554
3487
 
3555
3488
  get isValid() {
3556
- return !!this.code && typeof this.factor === 'number' && !!this.name && !!this.unit && !!this.tenantCode
3489
+ return super.isValid && !!this.code && typeof this.factor === 'number' && !!this.name && !!this.unit
3557
3490
  }
3558
3491
 
3559
3492
  fromCurrencyValue(value) {
3560
3493
  return value / this.factor
3561
3494
  }
3562
-
3563
- setModified() {
3564
- this.modified = (new Date()).valueOf()
3565
- return this
3495
+ getCode() {
3496
+ return this.currencyCode
3566
3497
  }
3567
3498
 
3568
3499
  update(update) {
3569
3500
  Object.keys(update).forEach((key) => {
3570
3501
  if (currency_updateAllowedProps.includes(key)) {
3571
- if (key === 'remarks') {
3572
- this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
3573
- } else {
3574
- this[key] = update[key]
3575
- }
3502
+ this[key] = update[key]
3576
3503
  }
3577
3504
  })
3578
- return this.setModified()
3505
+ return super.update(update)
3579
3506
  }
3580
3507
  }
3581
3508
 
@@ -3626,6 +3553,74 @@ class CurrencyRepo extends q_utilities_.Repo {
3626
3553
 
3627
3554
 
3628
3555
 
3556
+ ;// ./lib/helpers/getPurchaseOptionValue/getPurchaseOptionValue.js
3557
+ function getPurchaseOptionValue(options) {
3558
+ const {
3559
+ delimiter = ': ',
3560
+ key,
3561
+ purchaseOptions,
3562
+ tag = 'div'
3563
+ } = options || {}
3564
+ if (!key) {
3565
+ return purchaseOptions.reduce((acc, purchaseOption) => {
3566
+ const arr = _getOnePurchaseOptionValue({
3567
+ delimiter, purchaseOption, tag
3568
+ })
3569
+ if (tag) {
3570
+ acc.push(`<${tag}>${arr.join('')}</${tag}>`)
3571
+ } else {
3572
+ acc.push(`${arr.join('; ')}`)
3573
+ }
3574
+ return acc
3575
+ }, [])
3576
+ }
3577
+ const purchaseOption = (purchaseOptions || []).find((po) => {
3578
+ return !!key && po.key === key
3579
+ })
3580
+ if (!purchaseOption) {
3581
+ return []
3582
+ }
3583
+ return _getOnePurchaseOptionValue({
3584
+ delimiter, purchaseOption, tag
3585
+ })
3586
+ }
3587
+
3588
+ function _getOnePurchaseOptionValue({
3589
+ delimiter = ': ',
3590
+ purchaseOption,
3591
+ tag = 'div'
3592
+ }) {
3593
+ return (purchaseOption.value || []).reduce((acc, val) => {
3594
+ const { label, value = {} } = val || {}
3595
+ const _label = label ?? ''
3596
+ if (Array.isArray(value)) {
3597
+ if (tag) {
3598
+ acc.push(`<${tag}>${_label}${delimiter}${value.join(delimiter)}</${tag}>`)
3599
+ } else {
3600
+ acc.push(`${_label}${delimiter}${value.join(delimiter)}`)
3601
+ }
3602
+ } else if (typeof value === 'object') {
3603
+ Object.keys(value).map((key) => {
3604
+ if (tag) {
3605
+ acc.push(`<${tag}>${key}${delimiter}${value[key]}</${tag}>`)
3606
+ } else {
3607
+ acc.push(`${key}${delimiter}${value[key]}`)
3608
+ }
3609
+ })
3610
+ } else {
3611
+ if (tag) {
3612
+ acc.push(`<${tag}>${_label}${delimiter}${value}</${tag}>`)
3613
+ } else {
3614
+ acc.push(`${_label}${delimiter}${value}`)
3615
+ }
3616
+ }
3617
+
3618
+ return acc
3619
+ }, [])
3620
+ }
3621
+
3622
+
3623
+
3629
3624
  ;// ./lib/models/invoiceLine/invoiceLine.js
3630
3625
 
3631
3626
 
@@ -3634,22 +3629,22 @@ class CurrencyRepo extends q_utilities_.Repo {
3634
3629
 
3635
3630
 
3636
3631
 
3632
+
3637
3633
  const invoiceLine_updateAllowedProps = [
3638
- 'active',
3639
3634
  'amount',
3640
3635
  'deduction',
3641
- 'deleted',
3642
3636
  'description',
3643
3637
  'discount',
3644
3638
  'purchaseOptions',
3645
3639
  'qty',
3646
- 'remarks',
3647
3640
  'unitPrice'
3648
3641
  ]
3649
3642
 
3650
- class InvoiceLine {
3643
+ class InvoiceLine extends q_utilities_.TenantAwareEntity {
3651
3644
  constructor(options = {}) {
3652
3645
  options = options || {}
3646
+ super(options)
3647
+
3653
3648
  const { _Amount, _Invoice, _Merchandise, _Status } = options._constructor || {}
3654
3649
  this._Amount = _Amount && (_Amount._superclass === Amount._superclass) ? _Amount : Amount
3655
3650
  this._Invoice = _Invoice && (_Invoice._superclass === Invoice._superclass) ? _Invoice : Invoice
@@ -3662,23 +3657,16 @@ class InvoiceLine {
3662
3657
  const id = options._id || options.id
3663
3658
  this.id = invoiceLine_setId(id)
3664
3659
  this._type = options._type || 'InvoiceLine'
3665
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
3666
3660
  this.amount = this._Amount.init(options.amount)
3667
- this.created = options.created || (new Date()).valueOf()
3668
- this.creator = options.creator
3669
3661
  this.deduction = this._Amount.init(options.deduction)
3670
- this.deleted = options.deleted || false
3671
3662
  this.description = options.description
3672
3663
  this.discount = options.discount || 0
3673
3664
  this.invoiceCode = options.invoiceCode
3674
3665
  this.invoiceLineCode = invoiceLine_setCode(options, 'invoiceLineCode')
3675
3666
  this.merchandiseCode = options.merchandiseCode
3676
- this.modified = options.modified || (new Date()).valueOf()
3677
3667
  this.purchaseOptions = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.purchaseOptions)
3678
3668
  this.qty = options.qty || 1
3679
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
3680
3669
  this.status = this._Status.init(options.status)
3681
- this.tenantCode = options.tenantCode
3682
3670
  this.unitPrice = this._Amount.init(options.unitPrice)
3683
3671
  this.waived = options.waived || 0
3684
3672
  }
@@ -3691,24 +3679,8 @@ class InvoiceLine {
3691
3679
  tenantCode: 'tenantCode'
3692
3680
  }
3693
3681
  }
3694
- static init(options = {}) {
3695
- if (options instanceof this) {
3696
- return options
3697
- }
3698
- const instance = new this(options)
3699
- return instance.isValid ? instance : null
3700
- }
3701
- static initFromArray(arr = []) {
3702
- if (Array.isArray(arr)) {
3703
- return arr.map((a) => this.init(a))
3704
- }
3705
- return []
3706
- }
3707
- static initOnlyValidFromArray(arr = []) {
3708
- return this.initFromArray(arr).filter((i) => i)
3709
- }
3710
- static get _classname() {
3711
- return 'InvoiceLine'
3682
+ static get _classname() {
3683
+ return 'InvoiceLine'
3712
3684
  }
3713
3685
  static get _superclass() {
3714
3686
  return 'InvoiceLine'
@@ -3716,7 +3688,7 @@ class InvoiceLine {
3716
3688
 
3717
3689
  // getters
3718
3690
  get isValid() {
3719
- return !!this.amount && !!this.invoiceCode && !!this.tenantCode
3691
+ return super.isValid && !!this.amount && !!this.invoiceCode
3720
3692
  }
3721
3693
  get invoice() {
3722
3694
  return this._Invoice.init(this._invoice)
@@ -3726,11 +3698,13 @@ class InvoiceLine {
3726
3698
  }
3727
3699
 
3728
3700
  // instance methods
3729
- setModified() {
3730
- this.modified = (new Date()).valueOf()
3731
- return this
3701
+ getPurchaseOptionValue(options) {
3702
+ const { delimiter, key, tag } = options || {}
3703
+ return getPurchaseOptionValue({
3704
+ key,
3705
+ purchaseOptions: this.purchaseOptions
3706
+ })
3732
3707
  }
3733
-
3734
3708
  update(update) {
3735
3709
  Object.keys(update).forEach((key) => {
3736
3710
  if (invoiceLine_updateAllowedProps.includes(key)) {
@@ -3743,7 +3717,7 @@ class InvoiceLine {
3743
3717
  }
3744
3718
  }
3745
3719
  })
3746
- return this.setModified()
3720
+ return super.update(update)
3747
3721
  }
3748
3722
  }
3749
3723
 
@@ -3853,45 +3827,38 @@ class Issuer {
3853
3827
 
3854
3828
 
3855
3829
 
3830
+
3856
3831
  // import { Transaction } from '../transaction/index.js'
3857
3832
 
3858
3833
  const walletItem_updateAllowedProps = [
3859
- 'active',
3860
- 'deleted',
3861
- 'owner',
3862
3834
  'purchaseOptions',
3863
3835
  'qty',
3864
- 'remarks',
3865
3836
  'status',
3866
3837
  ]
3867
3838
 
3868
- class WalletItem {
3839
+ class WalletItem extends q_utilities_.TenantAwareEntity {
3869
3840
  constructor(options = {}) {
3870
3841
  options = options || {}
3842
+ super(options)
3843
+
3871
3844
  const { _Product, _Status } = options._constructor || {}
3872
3845
  this._Product = _Product && (_Product._superclass === Product._superclass) ? _Product : Product
3873
3846
  this._Status = _Status && (_Status._superclass === Status._superclass) ? _Status : Status
3874
3847
  // this._Transaction = _Transaction && (_Transaction._superclass === Transaction._superclass) ? _Transaction : Transaction
3875
3848
 
3849
+ this._eventRegistration = options._eventRegistration
3850
+ this._invoiceLine = options._invoiceLine
3876
3851
  this._product = options._product
3877
3852
  this._tenant = options._tenant
3878
3853
  this._transaction = options._transaction
3879
3854
 
3880
3855
  const id = options._id || options.id
3881
3856
  this.id = walletItem_setId(id)
3882
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
3883
- this.created = options.created || (new Date()).valueOf()
3884
- this.creator = options.creator
3885
- this.deleted = options.deleted || false
3886
- this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
3887
- this.modified = options.modified || (new Date()).valueOf()
3888
- this.owner = options.owner
3857
+ this.invoiceLineCode = options.invoiceLineCode
3889
3858
  this.productCode = options.productCode
3890
3859
  this.purchaseOptions = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.purchaseOptions)
3891
3860
  this.qty = options.qty || 1
3892
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
3893
3861
  this.status = this._Status.init(options.status)
3894
- this.tenantCode = options.tenantCode
3895
3862
  this.transactionCode = options.transactionCode
3896
3863
  this.walletItemCode = walletItem_setCode(options, 'walletItemCode')
3897
3864
  }
@@ -3907,22 +3874,7 @@ class WalletItem {
3907
3874
  transactionCode: 'transactionCode'
3908
3875
  }
3909
3876
  }
3910
- static init(options = {}) {
3911
- if (options instanceof this) {
3912
- return options
3913
- }
3914
- const instance = new this(options)
3915
- return instance.isValid ? instance : null
3916
- }
3917
- static initFromArray(arr = []) {
3918
- if (Array.isArray(arr)) {
3919
- return arr.map((a) => this.init(a))
3920
- }
3921
- return []
3922
- }
3923
- static initOnlyValidFromArray(arr = []) {
3924
- return this.initFromArray(arr).filter((i) => i)
3925
- }
3877
+
3926
3878
  static get _classname() {
3927
3879
  return 'WalletItem'
3928
3880
  }
@@ -3932,11 +3884,14 @@ class WalletItem {
3932
3884
 
3933
3885
  // getters
3934
3886
  get isValid() {
3935
- return !!this.tenantCode && !!this.productCode
3887
+ return super.isValid && !!this.productCode
3936
3888
  }
3937
3889
  get isAssigned() {
3938
3890
  return this.status.isAssigned
3939
3891
  }
3892
+ get isAvailableCoupon() {
3893
+ return this.isCoupon && !this.isCancelled && !this.isUsed
3894
+ }
3940
3895
  get isCancelled() {
3941
3896
  return this.status.isCancelled
3942
3897
  }
@@ -3946,9 +3901,21 @@ class WalletItem {
3946
3901
  get isConfirmed() {
3947
3902
  return this.status.isConfirmed
3948
3903
  }
3904
+ get isCoupon() {
3905
+ return this.product ? this.product.isCoupon : false
3906
+ }
3949
3907
  get isDelivered() {
3950
3908
  return this.status.isDelivered
3951
3909
  }
3910
+ get isInWallet() {
3911
+ return !this.isCancelled && !this.isRefundRequested
3912
+ }
3913
+ get isItemCoupon() {
3914
+ return this.product ? this.product.isItemCoupon : false
3915
+ }
3916
+ get isOnHold() {
3917
+ return this.status.onHold
3918
+ }
3952
3919
  get isOwned() {
3953
3920
  return (
3954
3921
  !this.isCancelled && !this.isRejected && !this.isRefunded
@@ -3972,6 +3939,9 @@ class WalletItem {
3972
3939
  get isRefunded() {
3973
3940
  return this.status.isRefunded
3974
3941
  }
3942
+ get isRefundRequested() {
3943
+ return this.status.isRefundRequested
3944
+ }
3975
3945
  get isRejected() {
3976
3946
  return this.status.rejected
3977
3947
  }
@@ -3987,6 +3957,10 @@ class WalletItem {
3987
3957
  get isWaived() {
3988
3958
  return this.status.isWaived
3989
3959
  }
3960
+
3961
+ get couponDetails() {
3962
+ return this.product ? this.product.couponDetails : null
3963
+ }
3990
3964
  get product() {
3991
3965
  return this._Product.init(this._product)
3992
3966
  }
@@ -4018,8 +3992,23 @@ class WalletItem {
4018
3992
  return this
4019
3993
  }
4020
3994
  }
3995
+ getCode() {
3996
+ return this.walletItemCode
3997
+ }
3998
+ getPurchaseOptionValue(options) {
3999
+ const { delimiter, key, tag } = options || {}
4000
+ return getPurchaseOptionValue({
4001
+ delimiter,
4002
+ key,
4003
+ purchaseOptions: this.purchaseOptions,
4004
+ tag,
4005
+ })
4006
+ }
4007
+ isApplicableCoupon(obj) {
4008
+ return this.isAvailableCoupon && (this.product ? this.product.isApplicableCoupon(obj) : false)
4009
+ }
4021
4010
  isSameOwner(userId) {
4022
- return userId
4011
+ return userId && this.owner
4023
4012
  ? (userId === this.owner)
4024
4013
  : false
4025
4014
  }
@@ -4035,8 +4024,8 @@ class WalletItem {
4035
4024
  this.status.setDelivered(value)
4036
4025
  return this
4037
4026
  }
4038
- setModified() {
4039
- this.modified = (new Date()).valueOf()
4027
+ setOnHold() {
4028
+ this.status.setOnHold()
4040
4029
  return this
4041
4030
  }
4042
4031
  setPaid() {
@@ -4069,6 +4058,11 @@ class WalletItem {
4069
4058
  // this.statusTimestamp.setUsed()
4070
4059
  return this
4071
4060
  }
4061
+ setUsedCouponFor(walletItemCode) {
4062
+ const _usedFor = q_utilities_.KeyValueObject.foundValueByKey(this.metadata, 'USED_COUPON_FOR') || []
4063
+ _usedFor.push(walletItemCode)
4064
+ this.metadata = q_utilities_.Metadata.insertOrUpdateRecord(this.metadata, 'USED_COUPON_FOR', _usedFor)
4065
+ }
4072
4066
  setWaived() {
4073
4067
  this.status.setWaived()
4074
4068
  return this
@@ -4089,12 +4083,14 @@ class WalletItem {
4089
4083
  // walletItemCode: this.walletItemCode
4090
4084
  // }
4091
4085
  // }
4086
+ unSetOnHold() {
4087
+ this.status.unSetOnHold()
4088
+ return this
4089
+ }
4092
4090
  update(update) {
4093
4091
  Object.keys(update).forEach((key) => {
4094
4092
  if (walletItem_updateAllowedProps.includes(key)) {
4095
- if (key === 'metadata') {
4096
- this[key] = q_utilities_.Metadata.initOnlyValidFromArray(update[key])
4097
- } else if (key === 'purchaseOptions' || key === 'remarks') {
4093
+ if (key === 'purchaseOptions') {
4098
4094
  this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
4099
4095
  } else if (key === 'status') {
4100
4096
  this[key] = this._Status.init(update[key])
@@ -4103,7 +4099,7 @@ class WalletItem {
4103
4099
  }
4104
4100
  }
4105
4101
  })
4106
- return this.setModified()
4102
+ return super.update(update)
4107
4103
  }
4108
4104
  }
4109
4105
 
@@ -4159,18 +4155,17 @@ class WalletItemRepo extends q_utilities_.Repo {
4159
4155
 
4160
4156
 
4161
4157
  const transaction_updateAllowedProps = [
4162
- 'active',
4163
4158
  'amount',
4164
4159
  'couponCodes',
4165
- 'deleted',
4166
4160
  // 'refundedAmount',
4167
- 'remarks',
4168
4161
  'status'
4169
4162
  ]
4170
4163
 
4171
- class Transaction {
4164
+ class Transaction extends q_utilities_.TenantAwareEntity {
4172
4165
  constructor(options = {}) {
4173
4166
  options = options || {}
4167
+ super(options)
4168
+
4174
4169
  const { _Amount, _Status, _WalletItem } = options._constructor || {}
4175
4170
  this._Amount = _Amount && (_Amount._superclass === Amount._superclass) ? _Amount : Amount
4176
4171
  this._Status = _Status && (_Status._superclass === Status._superclass) ? _Status : Status
@@ -4186,22 +4181,14 @@ class Transaction {
4186
4181
  const id = options._id || options.id
4187
4182
  this.id = transaction_setId(id)
4188
4183
  this._type = options._type || 'Transaction'
4189
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
4184
+
4190
4185
  this.amount = this._Amount.init(options.amount)
4191
4186
  this.couponCodes = options.couponCodes || []
4192
- this.created = options.created || (new Date()).valueOf()
4193
- this.creator = options.creator
4194
4187
  this.creditNoteCodes = options.creditNoteCodes || []
4195
- this.deleted = options.deleted || false
4196
4188
  this.invoiceCode = options.invoiceCode
4197
- this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
4198
- this.modified = options.modified || (new Date()).valueOf()
4199
- this.owner = options.owner
4200
4189
  this.paymentGatewayCode = options.paymentGatewayCode
4201
4190
  this.paymentResultRef = options.paymentResultRef
4202
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
4203
4191
  this.status = this._Status.init(options.status)
4204
- this.tenantCode = options.tenantCode
4205
4192
  this.transactionCode = transaction_setCode(options, 'transactionCode')
4206
4193
  }
4207
4194
 
@@ -4212,22 +4199,6 @@ class Transaction {
4212
4199
  tenantCode: 'tenantCode'
4213
4200
  }
4214
4201
  }
4215
- static init(options = {}) {
4216
- if (options instanceof this) {
4217
- return options
4218
- }
4219
- const instance = new this(options)
4220
- return instance.isValid ? instance : null
4221
- }
4222
- static initFromArray(arr = []) {
4223
- if (Array.isArray(arr)) {
4224
- return arr.map((a) => this.init(a))
4225
- }
4226
- return []
4227
- }
4228
- static initOnlyValidFromArray(arr = []) {
4229
- return this.initFromArray(arr).filter((i) => i)
4230
- }
4231
4202
  static get _classname() {
4232
4203
  return 'Transaction'
4233
4204
  }
@@ -4237,7 +4208,7 @@ class Transaction {
4237
4208
 
4238
4209
  // getters
4239
4210
  get isValid() {
4240
- return !!this.tenantCode
4211
+ return super.isValid
4241
4212
  }
4242
4213
  get isActive() {
4243
4214
  return this.active === true
@@ -4376,9 +4347,6 @@ class Transaction {
4376
4347
  setFailed() {
4377
4348
  return this.status.setFailed()
4378
4349
  }
4379
- setModified() {
4380
- return this.modified = (new Date()).valueOf()
4381
- }
4382
4350
  setOnHold() {
4383
4351
  return this.status.setOnHold()
4384
4352
  }
@@ -4435,10 +4403,6 @@ class Transaction {
4435
4403
  if (transaction_updateAllowedProps.includes(key)) {
4436
4404
  if (key === 'amount') {
4437
4405
  this[key] = this._Amount.init(update[key])
4438
- } else if (key === 'metadata') {
4439
- this[key] = q_utilities_.Metadata.initOnlyValidFromArray(update[key])
4440
- } else if (key === 'remarks') {
4441
- this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
4442
4406
  } else if (key === 'status') {
4443
4407
  this[key] = this._Status.init(update[key])
4444
4408
  // } else if (key === 'refundedAmount') {
@@ -4448,7 +4412,7 @@ class Transaction {
4448
4412
  }
4449
4413
  }
4450
4414
  })
4451
- return this.setModified()
4415
+ return super.update(update)
4452
4416
  }
4453
4417
  // updatePayment(payment = {}) {
4454
4418
  // this.payments = Payment.updatePaymentItem(this.payments, payment)
@@ -4523,21 +4487,19 @@ class TransactionRepo extends q_utilities_.Repo {
4523
4487
 
4524
4488
 
4525
4489
  const invoice_updateAllowedProps = [
4526
- 'active',
4527
4490
  'checkoutDateTime',
4528
- 'deleted',
4529
4491
  'description',
4530
4492
  'invoiceDate',
4531
4493
  'issuer',
4532
- 'metadata',
4533
- 'remarks',
4534
4494
  'revisionNumber',
4535
4495
  'status'
4536
4496
  ]
4537
4497
 
4538
- class Invoice {
4498
+ class Invoice extends q_utilities_.TenantAwareEntity {
4539
4499
  constructor(options) {
4540
4500
  options = options || {}
4501
+ super(options)
4502
+
4541
4503
  const { _Amount, _Cart, _InvoiceLine, _Issuer, _Status, _Transaction } = options._constructor || {}
4542
4504
  this._Amount = _Amount && (_Amount._superclass === Amount._superclass) ? _Amount : Amount
4543
4505
  this._Cart = _Cart && (_Cart._superclass === Cart._superclass) ? _Cart : Cart
@@ -4553,25 +4515,16 @@ class Invoice {
4553
4515
  const id = options._id || options.id
4554
4516
  this.id = invoice_setId(id)
4555
4517
  this._type = options._type || 'Invoice'
4556
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
4557
4518
  this.amount = this._Amount.init(options.amount)
4558
4519
  this.cartCode = options.cartCode
4559
4520
  this.checkoutDateTime = options.checkoutDateTime || (new Date()).valueOf()
4560
- this.created = options.created || (new Date()).valueOf()
4561
- this.creator = options.creator
4562
- this.deleted = options.deleted || false
4563
4521
  this.description = options.description
4564
4522
  this.invoiceCode = invoice_setCode(options, 'invoiceCode')
4565
4523
  this.invoiceDate = options.invoiceDate || (new Date()).valueOf()
4566
4524
  this.invoiceNumber = options.invoiceNumber
4567
4525
  this.issuer = this._Issuer.init(options.issuer)
4568
- this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
4569
- this.modified = options.modified || (new Date()).valueOf()
4570
- this.owner = options.owner
4571
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
4572
4526
  this.revisionNumber = options.revisionNumber || 1
4573
4527
  this.status = this._Status.init(options.status)
4574
- this.tenantCode = options.tenantCode
4575
4528
  }
4576
4529
 
4577
4530
  static dummyData() {
@@ -4579,22 +4532,6 @@ class Invoice {
4579
4532
  tenantCode: 'tenantCode'
4580
4533
  }
4581
4534
  }
4582
- static init(options = {}) {
4583
- if (options instanceof this) {
4584
- return options
4585
- }
4586
- const instance = new this(options)
4587
- return instance.isValid ? instance : null
4588
- }
4589
- static initFromArray(arr = []) {
4590
- if (Array.isArray(arr)) {
4591
- return arr.map((a) => this.init(a))
4592
- }
4593
- return []
4594
- }
4595
- static initOnlyValidFromArray(arr = []) {
4596
- return this.initFromArray(arr).filter((i) => i)
4597
- }
4598
4535
  static get _classname() {
4599
4536
  return 'Invoice'
4600
4537
  }
@@ -4603,7 +4540,7 @@ class Invoice {
4603
4540
  }
4604
4541
 
4605
4542
  get isValid() {
4606
- return !!this.tenantCode
4543
+ return super.isValid
4607
4544
  }
4608
4545
  get cart() {
4609
4546
  return this._Cart.init(this._cart)
@@ -4676,7 +4613,9 @@ class Invoice {
4676
4613
  getAmount() {
4677
4614
  return this.amount
4678
4615
  }
4679
-
4616
+ getCode() {
4617
+ return this.invoiceCode
4618
+ }
4680
4619
  getCurrencyCode() {
4681
4620
  return this.amount ? this.amount.getCurrencyCode() : null
4682
4621
  }
@@ -4700,12 +4639,6 @@ class Invoice {
4700
4639
  }
4701
4640
  return this
4702
4641
  }
4703
-
4704
- setModified() {
4705
- this.modified = (new Date()).valueOf()
4706
- return this
4707
- }
4708
-
4709
4642
  setCompleted() {
4710
4643
  this.status.setCompleted()
4711
4644
  return this.setModified()
@@ -4719,12 +4652,8 @@ class Invoice {
4719
4652
  update(update) {
4720
4653
  Object.keys(update).forEach((key) => {
4721
4654
  if (invoice_updateAllowedProps.includes(key)) {
4722
- if (key === 'remarks') {
4723
- this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
4724
- } else if (key === 'amount') {
4655
+ if (key === 'amount') {
4725
4656
  this[key] = this._Amount.init(update[key])
4726
- } else if (key === 'metadata') {
4727
- this[key] = q_utilities_.Metadata.initOnlyValidFromArray(update[key])
4728
4657
  } else if (key === 'issuer') {
4729
4658
  this[key] = this._Issuer.init(update[key])
4730
4659
  } else if (key === 'status') {
@@ -4734,7 +4663,7 @@ class Invoice {
4734
4663
  }
4735
4664
  }
4736
4665
  })
4737
- return this.setModified()
4666
+ return super.update(update)
4738
4667
  }
4739
4668
  }
4740
4669
 
@@ -4789,40 +4718,33 @@ class InvoiceRepo extends q_utilities_.Repo {
4789
4718
  ;// ./lib/models/paymentGateway/paymentGateway.js
4790
4719
 
4791
4720
 
4721
+
4792
4722
  const paymentGateway_updateAllowedProps = [
4793
- 'active',
4794
- 'deleted',
4795
4723
  'label',
4796
4724
  'logoUrl',
4797
4725
  'name',
4798
- 'owner',
4799
4726
  'sandbox',
4800
4727
  'setting'
4801
4728
  ]
4802
4729
 
4803
-
4804
- class PaymentGateway {
4730
+ class PaymentGateway extends q_utilities_.TenantAwareEntity {
4805
4731
  constructor(options = {}) {
4806
4732
  options = options || {}
4733
+ super(options)
4734
+
4807
4735
  const id = options._id || options.id
4808
4736
  this.id = paymentGateway_setId(id)
4809
4737
  this._type = options._type || 'PaymentGateway'
4810
- this.active = (typeof options.active !== 'undefined') ? !!options.active : true
4811
- this.created = options.created || (new Date()).valueOf()
4812
- this.creator = options.creator
4813
- this.deleted = options.deleted || false
4738
+
4814
4739
  this.hasWebhook = options.hasWebhook || false
4815
4740
  this.label = options.label
4816
4741
  this.logoUrl = options.logoUrl
4817
- this.modified = options.modified || (new Date()).valueOf()
4818
4742
  this.name = options.name || ''
4819
- this.owner = options.owner
4820
4743
  this.paymentGatewayCode = paymentGateway_setCode(options, 'paymentGatewayCode')
4821
4744
  this.paymentGatewayType = options.paymentGatewayType || 'PaymentGateway'
4822
4745
  this.paymentResultType = options.paymentResultType || 'PaymentResult'
4823
4746
  this.sandbox = options.sandbox || false
4824
4747
  this.setting = options.setting || null
4825
- this.tenantCode = options.tenantCode
4826
4748
  }
4827
4749
  static dummyData() {
4828
4750
  return {
@@ -4830,22 +4752,6 @@ class PaymentGateway {
4830
4752
  tenantCode: 'tenantCode'
4831
4753
  }
4832
4754
  }
4833
- static init(options = {}) {
4834
- if (options instanceof this) {
4835
- return options
4836
- }
4837
- const instance = new this(options)
4838
- return instance.isValid ? instance : null
4839
- }
4840
- static initFromArray(arr = []) {
4841
- if (Array.isArray(arr)) {
4842
- return arr.map((a) => this.init(a))
4843
- }
4844
- return []
4845
- }
4846
- static initOnlyValidFromArray(arr = []) {
4847
- return this.initFromArray(arr).filter((i) => i)
4848
- }
4849
4755
  static get _classname() {
4850
4756
  return 'PaymentGateway'
4851
4757
  }
@@ -4855,7 +4761,7 @@ class PaymentGateway {
4855
4761
 
4856
4762
  // getters
4857
4763
  get isValid() {
4858
- return !!this.name && !!this.tenantCode
4764
+ return super.isValid && !!this.name
4859
4765
  }
4860
4766
 
4861
4767
  // instance methods
@@ -4865,6 +4771,9 @@ class PaymentGateway {
4865
4771
  async getAppPayParams() {
4866
4772
  throw new Error(`${this._classname} subclass should implement getAppPayParams`)
4867
4773
  }
4774
+ getCode() {
4775
+ return this.paymentGatewayCode
4776
+ }
4868
4777
  async updatePayment() {
4869
4778
  throw new Error(`${this._classname} subclass should implement updatePayment`)
4870
4779
  }
@@ -4878,18 +4787,13 @@ class PaymentGateway {
4878
4787
  setCompletedRelatedStatus(status) {
4879
4788
  throw new Error(`${this.name} subclass should implement setCompletedRelatedStatus`)
4880
4789
  }
4881
-
4882
- setModified() {
4883
- this.modified = (new Date()).valueOf()
4884
- return this
4885
- }
4886
4790
  update(update) {
4887
4791
  Object.keys(update).forEach((key) => {
4888
4792
  if (paymentGateway_updateAllowedProps.includes(key)) {
4889
4793
  this[key] = update[key]
4890
4794
  }
4891
4795
  })
4892
- return this.setModified()
4796
+ return super.update(update)
4893
4797
  }
4894
4798
  }
4895
4799
 
@@ -4950,9 +4854,11 @@ const paymentResult_updateAllowedProps = [
4950
4854
  'result'
4951
4855
  ]
4952
4856
 
4953
- class PaymentResult {
4857
+ class PaymentResult extends q_utilities_.TenantAwareEntity {
4954
4858
  constructor(options = {}) {
4955
4859
  options = options || {}
4860
+ super(options)
4861
+
4956
4862
  const { _Transaction } = options._constructor || {}
4957
4863
  this._Transaction = _Transaction && (_Transaction._superclass === Transaction._superclass) ? _Transaction : Transaction
4958
4864
 
@@ -4961,20 +4867,12 @@ class PaymentResult {
4961
4867
 
4962
4868
  const id = options._id || options.id
4963
4869
  this.id = paymentResult_setId(id)
4964
- this.active = typeof options.active !== 'undefined' ? !!options.active : true
4965
- this.created = options.created || (new Date()).valueOf()
4966
- this.creator = options.creator
4967
- this.deleted = options.deleted || false
4968
- this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
4969
- this.modified = options.modified || (new Date()).valueOf()
4970
- this.owner = options.owner
4870
+
4971
4871
  this.paymentResultCode = paymentResult_setCode(options, 'paymentResultCode')
4972
4872
  this.paymentResultType = options.paymentResultType || 'PaymentResult'
4973
- this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
4974
4873
  this.result = options.result
4975
4874
  this.resultRef = options.resultRef
4976
4875
  this.resultType = options.resultType
4977
- this.tenantCode = options.tenantCode
4978
4876
  // this.transaction = this._Transaction.init(options.transaction)
4979
4877
  this.transactionCode = options.transactionCode
4980
4878
  }
@@ -4989,22 +4887,6 @@ class PaymentResult {
4989
4887
  transactionCode: 'transactionCode'
4990
4888
  }
4991
4889
  }
4992
- static init(options = {}) {
4993
- if (options instanceof this) {
4994
- return options
4995
- }
4996
- const instance = new this(options)
4997
- return instance.isValid ? instance : null
4998
- }
4999
- static initFromArray(arr = []) {
5000
- if (Array.isArray(arr)) {
5001
- return arr.map((a) => this.init(a))
5002
- }
5003
- return []
5004
- }
5005
- static initOnlyValidFromArray(arr = []) {
5006
- return this.initFromArray(arr).filter((i) => i)
5007
- }
5008
4890
  static get _classname() {
5009
4891
  return 'PaymentResult'
5010
4892
  }
@@ -5014,7 +4896,7 @@ class PaymentResult {
5014
4896
 
5015
4897
  // getters
5016
4898
  get isValid() {
5017
- return !!this.resultType && !!this.tenantCode && !!this.transactionCode
4899
+ return super.isValid && !!this.resultType && !!this.transactionCode
5018
4900
  // return !!this.result && !!this.resultType && !!this.tenantCode
5019
4901
  }
5020
4902
  get amount() {
@@ -5024,7 +4906,7 @@ class PaymentResult {
5024
4906
  throw new Error(`${this._classname} subclass should implement get paymentMethod`)
5025
4907
  }
5026
4908
  get transaction() {
5027
- return this._transaction.init(this._transaction)
4909
+ return this._Transaction.init(this._transaction)
5028
4910
  }
5029
4911
 
5030
4912
  // instance methods
@@ -5040,71 +4922,288 @@ class PaymentResult {
5040
4922
  return this
5041
4923
  }
5042
4924
 
5043
- compareStatus(paymentResult) {
5044
- throw new Error(`${this.paymentResultType} subclass should implement compareStatus`)
5045
- }
5046
- getPaidAmount() {
5047
- throw new Error(`${this.paymentResultType} subclass should implement getPaidAmount`)
5048
- }
5049
- getPaidTimestamp() {
5050
- throw new Error(
5051
- `${this.paymentResultType} subclass should implement getPaidTimestamp in milliseconds`
5052
- )
4925
+ compareStatus(paymentResult) {
4926
+ throw new Error(`${this.paymentResultType} subclass should implement compareStatus`)
4927
+ }
4928
+ getCode() {
4929
+ return this.paymentResultCode
4930
+ }
4931
+ getPaidAmount() {
4932
+ throw new Error(`${this.paymentResultType} subclass should implement getPaidAmount`)
4933
+ }
4934
+ getPaidTimestamp() {
4935
+ throw new Error(
4936
+ `${this.paymentResultType} subclass should implement getPaidTimestamp in milliseconds`
4937
+ )
4938
+ }
4939
+ getPaymentCode() {
4940
+ throw new Error(`${this.paymentResultType} subclass should implement getPaymentCode`)
4941
+ }
4942
+ getTransactionStatus() {
4943
+ throw new Error(`${this.paymentResultType} subclass should implement getTransactionStatus`)
4944
+ }
4945
+ handlePayment(payment) {
4946
+ if (!this.isForThisPayment(payment)) {
4947
+ return { payment, err: new Error('the payment result is not for this payment') }
4948
+ }
4949
+ if (!this.isSameAmount(payment)) {
4950
+ return { payment, err: new Error('the amount was not matched') }
4951
+ }
4952
+ try {
4953
+ payment.settled()
4954
+ payment
4955
+ .setPaidAmount(this.getPaidAmount())
4956
+ .setPaidTimestamp(this.getPaidTimestamp())
4957
+ .setPaymentResultCode(this.paymentResultCode)
4958
+ return { payment, err: null }
4959
+ } catch (err) {
4960
+ return { payment, err }
4961
+ }
4962
+ }
4963
+ isForThisPayment(payment) {
4964
+ return this.getPaymentCode() === payment.paymentCode
4965
+ }
4966
+ isSameAmount(payment) {
4967
+ return this.getPaidAmount() === payment.getAmount()
4968
+ }
4969
+ isSuccess() {
4970
+ throw new Error(`${this.paymentResultType} subclass should implement isSuccess`)
4971
+ }
4972
+ setupMetadata() {
4973
+ const amount = this.amount
4974
+ const paymentMethod = this.paymentMethod
4975
+ q_utilities_.Metadata.addItem(this.metadata, 'AMOUNT', amount)
4976
+ q_utilities_.Metadata.addItem(this.metadata, 'PAYMENT_METHOD', paymentMethod)
4977
+ q_utilities_.KeyValueObject.addItem(this.remarks, 'amount', amount)
4978
+ q_utilities_.KeyValueObject.addItem(this.remarks, 'paymentMethod', paymentMethod)
4979
+ return this
4980
+ }
4981
+ setupRemarks() {
4982
+ return this.setupMetadata()
4983
+ }
4984
+ update(update) {
4985
+ Object.keys(update).forEach((key) => {
4986
+ if (paymentResult_updateAllowedProps.includes(key)) {
4987
+ this[key] = update[key]
4988
+ }
4989
+ })
4990
+ return super.update(update)
4991
+ }
4992
+ }
4993
+
4994
+ function paymentResult_setCode(options, key) {
4995
+ const copyOptions = options || {}
4996
+ if (copyOptions[key]) {
4997
+ return copyOptions[key]
4998
+ }
4999
+ return stringHelper.setCode()
5000
+ }
5001
+
5002
+ function paymentResult_setId(id) {
5003
+ if (id && typeof id.toString === 'function') {
5004
+ return id.toString()
5005
+ }
5006
+ return id
5007
+ }
5008
+
5009
+
5010
+
5011
+ ;// ./lib/models/paymentResult/paymentResultRepo.js
5012
+
5013
+
5014
+
5015
+ class PaymentResultRepo extends q_utilities_.Repo {
5016
+ constructor(options = {}) {
5017
+ options = options || {}
5018
+ super(options)
5019
+ const { _PaymentResult } = options._constructor || {}
5020
+ this._PaymentResult = _PaymentResult && (_PaymentResult._superclass === PaymentResult._superclass) ? _PaymentResult : PaymentResult
5021
+ }
5022
+ static get _classname() {
5023
+ return 'PaymentResultRepo'
5024
+ }
5025
+ init(options) {
5026
+ return this._PaymentResult.init(options)
5027
+ }
5028
+ }
5029
+
5030
+
5031
+
5032
+ ;// ./lib/models/paymentResult/index.js
5033
+
5034
+
5035
+
5036
+
5037
+
5038
+
5039
+ ;// ./lib/models/status/index.js
5040
+
5041
+
5042
+
5043
+
5044
+
5045
+ ;// ./lib/models/storeItem/storeItem.js
5046
+
5047
+
5048
+
5049
+
5050
+
5051
+ const storeItem_updateAllowedProps = [
5052
+ 'active',
5053
+ 'deleted',
5054
+ 'description',
5055
+ 'intangible',
5056
+ 'limitPercentage',
5057
+ 'lineOptions',
5058
+ 'maxPerWallet',
5059
+ 'name',
5060
+ 'originalStock',
5061
+ 'owner',
5062
+ 'productOptions',
5063
+ 'remarks',
5064
+ 'requiredStoreItemCode',
5065
+ 'stock'
5066
+ ]
5067
+
5068
+ class StoreItem {
5069
+ constructor(options = {}) {
5070
+ options = options || {}
5071
+ const { _ItemOption } = options._constructor || {}
5072
+ this._ItemOption = _ItemOption && (_ItemOption._superclass === ItemOption) ? _ItemOption : ItemOption
5073
+
5074
+ const id = options._id || options.id
5075
+ this.id = storeItem_setId(id)
5076
+ this._type = options._type || 'StoreItem'
5077
+ this.active = (typeof options.active !== 'undefined') ? !!options.active : true
5078
+ this.created = options.created || (new Date()).valueOf()
5079
+ this.creator = options.creator
5080
+ this.deleted = options.deleted || false
5081
+ this.description = options.description || ''
5082
+ this.intangible = options.intangible || false
5083
+ this.limitPercentage = options.limitPercentage || 100
5084
+ this.lineOptions = this._ItemOption.initOnlyValidFromArray(options.lineOptions)
5085
+ this.maxPerWallet = options.maxPerWallet || 1
5086
+ this.metadata = q_utilities_.Metadata.initOnlyValidFromArray(options.metadata)
5087
+ this.modified = options.modified || (new Date()).valueOf()
5088
+ this.name = options.name || ''
5089
+ this.originalStock = options.originalStock || 0
5090
+ this.owner = options.owner
5091
+ this.productCode = storeItem_setCode(options, 'productCode')
5092
+ this.productOptions = this._ItemOption.initOnlyValidFromArray(options.productOptions)
5093
+ this.requiredStoreItemCode = options.requiredStoreItemCode
5094
+ this.remarks = q_utilities_.KeyValueObject.initOnlyValidFromArray(options.remarks)
5095
+ this.stock = options.stock || 0
5096
+ this.storeItemType = options.storeItemType || 'StoreItem'
5097
+ this.tenantCode = options.tenantCode
5098
+ }
5099
+
5100
+ // class method
5101
+ static dummyData() {
5102
+ return {
5103
+ name: 'badge',
5104
+ tenantCode: 'tenantCode'
5105
+ }
5106
+ }
5107
+ static init(options = {}) {
5108
+ if (options instanceof this) {
5109
+ return options
5110
+ }
5111
+ const instance = new this(options)
5112
+ return instance.isValid ? instance : null
5113
+ }
5114
+ static initFromArray(arr = []) {
5115
+ if (Array.isArray(arr)) {
5116
+ return arr.map((a) => this.init(a))
5117
+ }
5118
+ return []
5119
+ }
5120
+ static initOnlyValidFromArray(arr = []) {
5121
+ return this.initFromArray(arr).filter((i) => i)
5122
+ }
5123
+ static get _classname() {
5124
+ return 'StoreItem'
5125
+ }
5126
+ static get _superclass() {
5127
+ return 'StoreItem'
5128
+ }
5129
+
5130
+ // getters
5131
+ get isValid() {
5132
+ return !!this.tenantCode && !!this.name
5133
+ }
5134
+ get isReachedLimitPercentage() {
5135
+ return this.soldPercentage >= this.limitPercentage
5136
+ }
5137
+ get soldPercentage() {
5138
+ return ((this.originalStock - this.stock) / this.originalStock) * 100
5139
+ }
5140
+ get summary() {
5141
+ return {
5142
+ product: this,
5143
+ productCode: this.productCode,
5144
+ name: this.name,
5145
+ }
5146
+ }
5147
+
5148
+ // instance methods
5149
+ ableToHave(qty) {
5150
+ return this.maxPerWallet >= qty
5151
+ }
5152
+
5153
+ checkStoreItemItemOptions(itemOptionFillIns = []) {
5154
+ const copyItemOptionsFillIns = ItemOptionFillIn.getItemOptionFillInsByTarget({ itemOptionFillIns, target: 'StoreItem', targetCode: this.productCode })
5155
+ return copyItemOptionsFillIns.reduce((acc, fillIn) => {
5156
+ const key = fillIn.getKey()
5157
+ const itemOption = this.getStoreItemOptionByKey(key)
5158
+ if (!itemOption) {
5159
+ acc.errMsgs.push(`options of the product(${this.productCode}) does not contain key: "${key}"`)
5160
+ return acc
5161
+ }
5162
+ const isValid = itemOption.isValidFillInValue(fillIn.getValue())
5163
+ if (!isValid) {
5164
+ acc.errMsgs.push(`the product(${this.productCode}) option's(${key}) fillInValue is invalid`)
5165
+ }
5166
+ return acc
5167
+ }, { errMsgs: [] })
5053
5168
  }
5054
- getPaymentCode() {
5055
- throw new Error(`${this.paymentResultType} subclass should implement getPaymentCode`)
5169
+ getCode() {
5170
+ return this.productCode
5056
5171
  }
5057
- getTransactionStatus() {
5058
- throw new Error(`${this.paymentResultType} subclass should implement getTransactionStatus`)
5172
+ getMetadataValueByKey(key) {
5173
+ return q_utilities_.Metadata.getValueByKey(this.metadata || [], key)
5059
5174
  }
5060
- handlePayment(payment) {
5061
- if (!this.isForThisPayment(payment)) {
5062
- return { payment, err: new Error('the payment result is not for this payment') }
5063
- }
5064
- if (!this.isSameAmount(payment)) {
5065
- return { payment, err: new Error('the amount was not matched') }
5066
- }
5067
- try {
5068
- payment.settled()
5069
- payment
5070
- .setPaidAmount(this.getPaidAmount())
5071
- .setPaidTimestamp(this.getPaidTimestamp())
5072
- .setPaymentResultCode(this.paymentResultCode)
5073
- return { payment, err: null }
5074
- } catch (err) {
5075
- return { payment, err }
5175
+ getStoreItemOptionByKey(key) {
5176
+ const arr = this._ItemOption.getByKey(this.productOptions, key)
5177
+ if (arr.length === 1) {
5178
+ return arr[0]
5076
5179
  }
5180
+ return null
5077
5181
  }
5078
- isForThisPayment(payment) {
5079
- return this.getPaymentCode() === payment.paymentCode
5182
+ hasStock(qty) {
5183
+ return this.stock >= qty
5080
5184
  }
5081
- isSameAmount(payment) {
5082
- return this.getPaidAmount() === payment.getAmount()
5185
+ isQualified(data) {
5186
+ const rules = this.getMetadataValueByKey('RULES') || []
5187
+ return (rules.length === 0)
5188
+ ? true
5189
+ : rules.reduce((acc, r) => {
5190
+ return acc || (0,q_utilities_.getValidation)(r, data, storeItem_getDataByKey, q_utilities_.KeyValueObject)
5191
+ }, false)
5083
5192
  }
5084
- isSuccess() {
5085
- throw new Error(`${this.paymentResultType} subclass should implement isSuccess`)
5193
+ isTicket() {
5194
+ return false
5086
5195
  }
5087
5196
  setModified() {
5088
5197
  this.modified = (new Date()).valueOf()
5089
5198
  return this
5090
5199
  }
5091
- setupMetadata() {
5092
- const amount = this.amount
5093
- const paymentMethod = this.paymentMethod
5094
- q_utilities_.Metadata.addItem(this.metadata, 'AMOUNT', amount)
5095
- q_utilities_.Metadata.addItem(this.metadata, 'PAYMENT_METHOD', paymentMethod)
5096
- q_utilities_.KeyValueObject.addItem(this.remarks, 'amount', amount)
5097
- q_utilities_.KeyValueObject.addItem(this.remarks, 'paymentMethod', paymentMethod)
5098
- return this
5099
- }
5100
- setupRemarks() {
5101
- return this.setupMetadata()
5102
- }
5103
5200
  update(update) {
5104
5201
  Object.keys(update).forEach((key) => {
5105
- if (paymentResult_updateAllowedProps.includes(key)) {
5202
+ if (storeItem_updateAllowedProps.includes(key)) {
5106
5203
  if (key === 'metadata') {
5107
5204
  this[key] = q_utilities_.Metadata.initOnlyValidFromArray(update[key])
5205
+ } else if (key === 'productOptions') {
5206
+ this[key] = this._ItemOption.initOnlyValidFromArray(update[key])
5108
5207
  } else if (key === 'remarks') {
5109
5208
  this[key] = q_utilities_.KeyValueObject.initOnlyValidFromArray(update[key])
5110
5209
  } else {
@@ -5116,58 +5215,35 @@ class PaymentResult {
5116
5215
  }
5117
5216
  }
5118
5217
 
5119
- function paymentResult_setCode(options, key) {
5120
- const copyOptions = options || {}
5121
- if (copyOptions[key]) {
5122
- return copyOptions[key]
5123
- }
5124
- return stringHelper.setCode()
5125
- }
5126
-
5127
- function paymentResult_setId(id) {
5218
+ function storeItem_setId(id) {
5128
5219
  if (id && typeof id.toString === 'function') {
5129
5220
  return id.toString()
5130
5221
  }
5131
5222
  return id
5132
5223
  }
5133
5224
 
5134
-
5135
-
5136
- ;// ./lib/models/paymentResult/paymentResultRepo.js
5137
-
5138
-
5139
-
5140
- class PaymentResultRepo extends q_utilities_.Repo {
5141
- constructor(options = {}) {
5142
- options = options || {}
5143
- super(options)
5144
- const { _PaymentResult } = options._constructor || {}
5145
- this._PaymentResult = _PaymentResult && (_PaymentResult._superclass === PaymentResult._superclass) ? _PaymentResult : PaymentResult
5146
- }
5147
- static get _classname() {
5148
- return 'PaymentResultRepo'
5149
- }
5150
- init(options) {
5151
- return this._PaymentResult.init(options)
5225
+ function storeItem_setCode(options, key) {
5226
+ const copyOptions = options || {}
5227
+ if (copyOptions[key]) {
5228
+ return copyOptions[key]
5152
5229
  }
5230
+ return stringHelper.setCode()
5153
5231
  }
5154
5232
 
5155
-
5156
-
5157
- ;// ./lib/models/paymentResult/index.js
5158
-
5159
-
5233
+ function storeItem_getDataByKey(key, data) {
5234
+ return (0,q_utilities_.getValueByKeys)(key.split('.'), data)
5235
+ }
5160
5236
 
5161
5237
 
5162
5238
 
5239
+ ;// ./lib/models/storeItem/index.js
5163
5240
 
5164
- ;// ./lib/models/status/index.js
5165
5241
 
5166
5242
 
5167
5243
 
5244
+ ;// ./lib/models/index.js
5168
5245
 
5169
5246
 
5170
- ;// ./lib/models/index.js
5171
5247
 
5172
5248
 
5173
5249
 
@@ -5299,6 +5375,34 @@ class Chain {
5299
5375
 
5300
5376
 
5301
5377
 
5378
+ ;// ./lib/helpers/calculateByCoupon/calculateCoupon.js
5379
+
5380
+ function calculateByCoupon({ coupon, price }) {
5381
+ const { couponDetails } = coupon
5382
+ if (!couponDetails) {
5383
+ return 0
5384
+ }
5385
+ const { type, item } = couponDetails
5386
+ if (item) {
5387
+ switch(type) {
5388
+ case ('Percentage'): {
5389
+ return _caculateByPercentage(price, couponDetails)
5390
+ }
5391
+ default: {
5392
+ return 0
5393
+ }
5394
+ }
5395
+ }
5396
+ }
5397
+
5398
+ function _caculateByPercentage(price, couponDetails) {
5399
+ const { value } = couponDetails
5400
+ return price.value * (value / 100)
5401
+ }
5402
+
5403
+
5404
+
5405
+
5302
5406
  ;// ./lib/eventManager/chains/helpers.js
5303
5407
 
5304
5408
 
@@ -5307,6 +5411,7 @@ class Chain {
5307
5411
 
5308
5412
 
5309
5413
 
5414
+
5310
5415
  ;// ./lib/eventManager/chains/chainCategoryLimit.js
5311
5416
 
5312
5417
 
@@ -5426,6 +5531,7 @@ class ChainGetPrice extends Chain {
5426
5531
  // }
5427
5532
  })
5428
5533
  cutEntitlements(lines, entitlements, this.currency.code)
5534
+ // useCoupons(lines, this.currency.code)
5429
5535
  // getAmount()
5430
5536
  await this.next(chainTarget)
5431
5537
  } catch (err) {
@@ -5642,6 +5748,13 @@ function getStrategiesByRestrictions(prices, line, user) {
5642
5748
  }
5643
5749
 
5644
5750
 
5751
+ // function useCoupons(lines, currencyCode) {
5752
+ // lines.forEach((line) => {
5753
+
5754
+ // })
5755
+ // }
5756
+
5757
+
5645
5758
 
5646
5759
  ;// ./lib/eventManager/chains/ChainGetPriceForGroup.js
5647
5760
 
@@ -5897,7 +6010,7 @@ class ChainMerchandiseLimit extends Chain {
5897
6010
  const stock = merchandise.getStock()
5898
6011
  if (stock === 0) {
5899
6012
  line.disabled = true
5900
- line.errors.push('Sold out.')
6013
+ line.errors.push('Full.')
5901
6014
  } else {
5902
6015
  const { qty } = updatedItem
5903
6016
  updatedItem.qty = qty > stock ? stock : qty
@@ -5942,7 +6055,7 @@ class ChainProductLimit extends Chain {
5942
6055
  // const newRest = balance - ordered
5943
6056
  if (balance === 0) {
5944
6057
  updatedItem.qty = 0
5945
- line.errors.push(`"${name}" is out of stock`)
6058
+ // line.errors.push(`"${name}" is out of stock`)
5946
6059
  } else {
5947
6060
  const ordered = (productQty * qty)
5948
6061
  const newBalance = balance - ordered
@@ -6086,22 +6199,141 @@ class ChainPurchaseOptions extends Chain {
6086
6199
  if (required && !value && !notFinishRequired) {
6087
6200
  notFinishRequired = true
6088
6201
  line.validated = false
6089
- line.errors.push('Need to fill in options.')
6202
+ line.errors.push('Please fill in the option(s).')
6090
6203
  }
6091
6204
  if (validated && !notFinishValidated) {
6092
6205
  notFinishValidated = true
6093
- line.errors.push('Has not validated options.')
6206
+ line.errors.push('Invalid option(s).')
6094
6207
  }
6095
6208
  })
6096
6209
  })
6097
6210
  })
6098
6211
  await this.next(chainTarget)
6099
6212
  } catch (err) {
6100
- chainTarget.addException('check product restriction fail', err.message)
6213
+ chainTarget.addException('Check product restriction failed.', err.message)
6214
+ this.exitChain()
6215
+ }
6216
+ }
6217
+ }
6218
+
6219
+
6220
+
6221
+ ;// ./lib/eventManager/chains/chainRelatedCoupons.js
6222
+
6223
+ // import { WalletItem } from '../../models/walletItem/index.js'
6224
+
6225
+ class ChainRelatedCoupons extends Chain {
6226
+ constructor(options = {}) {
6227
+ super(options)
6228
+ this.autoUseCoupon = options.autoUseCoupon || false
6229
+ this.currency = options.currency
6230
+ this.walletItems = options.walletItems
6231
+ }
6232
+
6233
+ async handleRequest(chainTarget) {
6234
+ try {
6235
+ const { lines, users } = chainTarget
6236
+ // const walletItems = WalletItem.initOnlyValidFromArray(this.walletItems)
6237
+ const couponWalletItems = this.walletItems.filter((i) => i.isCoupon)
6238
+ lines.forEach((line) => {
6239
+ _calculateAmountByCoupons({ line, currencyCode: this.currency.code })
6240
+ _updateRelatedCoupons(line, couponWalletItems, this.autoUseCoupon, this.currency.code)
6241
+ })
6242
+ lines.forEach((line) => {
6243
+ _getAvailableCoupons(line)
6244
+ })
6245
+ await this.next(chainTarget)
6246
+ } catch (err) {
6247
+ chainTarget.addException('calculate categories limit fail', err.message)
6101
6248
  this.exitChain()
6102
6249
  }
6103
6250
  }
6104
6251
  }
6252
+ function _calculateAmountByCoupons({ line, currencyCode }) {
6253
+ const { usedCoupons = {}, updatedItem } = line
6254
+ Object.keys(usedCoupons).forEach((key) => {
6255
+ usedCoupons[key].forEach((coupon) => {
6256
+ const obj = _calculateAmountByOneCoupon({ updatedItem, coupon, currencyCode })
6257
+ Object.assign(updatedItem, obj)
6258
+ })
6259
+ })
6260
+ }
6261
+
6262
+ function _calculateAmountByOneCoupon({ updatedItem, coupon, currencyCode }) {
6263
+ const { couponDetails, walletItemCode } = coupon
6264
+ if (!couponDetails) {
6265
+ return updatedItem
6266
+ }
6267
+ const { price, qty, discount, remarks, subTotal } = updatedItem
6268
+ const _discount = calculateByCoupon({ coupon, price })
6269
+ const discountValue = _discount + discount.value
6270
+ const subTotalValue = subTotal.value > _discount ? subTotal.value - _discount : 0
6271
+ const _usedCoupons = q_utilities_.KeyValueObject.foundValueByKey(remarks, 'USED_ITEM_COUPONS') || []
6272
+ _usedCoupons.push(walletItemCode)
6273
+ return {
6274
+ ...updatedItem,
6275
+ discount: Amount.init({ value: discountValue, currencyCode }),
6276
+ remarks: q_utilities_.KeyValueObject.insertOrUpdateRecord(remarks, 'USED_ITEM_COUPONS', _usedCoupons ),
6277
+ subTotal: Amount.init({ value: subTotalValue, currencyCode })
6278
+ }
6279
+ }
6280
+
6281
+
6282
+ function _getAvailableCoupons(line) {
6283
+ const { relatedCoupons = [] } = line
6284
+ line.relatedCoupons = relatedCoupons.map((c) => ({
6285
+ ...c,
6286
+ availableCoupons: c.coupons.filter((_c) => (!_c.isOnHold))
6287
+ }))
6288
+ }
6289
+
6290
+ function _getRelatedCoupons(cartItemLine, couponWalletItems, autoUseCoupon, currencyCode) {
6291
+ const { merchandise, usedCoupons = {}, updatedItem = {} } = cartItemLine
6292
+ const relatedWalletItems = couponWalletItems.filter(
6293
+ item => item.isApplicableCoupon(merchandise) && item.isItemCoupon
6294
+ )
6295
+ // .sort((a, b) => (
6296
+ // b.couponDetails.value - a.couponDetails.value
6297
+ // ))
6298
+ return relatedWalletItems.reduce((acc, w) => {
6299
+ const productCode = w.product.productCode
6300
+ let exist = acc.find((i) => i.productCode === productCode)
6301
+ const isOnHold = w.isOnHold // max? || only use One Coupon?
6302
+ if (!exist) {
6303
+ exist = {
6304
+ coupons: [],
6305
+ product: w.product,
6306
+ productCode: productCode,
6307
+ usedQty: (usedCoupons[productCode] || []).length
6308
+ }
6309
+ acc.push(exist)
6310
+ }
6311
+ exist.coupons.push(w)
6312
+ const { qty: itemQty, subTotal } = updatedItem
6313
+ if (autoUseCoupon && !isOnHold && exist.usedQty < itemQty && subTotal.value > 0) {
6314
+ // use coupon
6315
+ w.setOnHold()
6316
+ usedCoupons[productCode] = [
6317
+ ...usedCoupons[productCode] || [],
6318
+ w
6319
+ ]
6320
+ const obj = _calculateAmountByOneCoupon({ updatedItem, currencyCode, coupon: w })
6321
+ Object.assign(updatedItem, obj)
6322
+ exist.usedQty = usedCoupons[productCode].length
6323
+ }
6324
+ return acc
6325
+ }, [])
6326
+ }
6327
+
6328
+
6329
+ function _updateRelatedCoupons(line, couponWalletItems, autoUseCoupon, currencyCode) {
6330
+ if (couponWalletItems.length > 0) {
6331
+ line.relatedCoupons = _getRelatedCoupons(line, couponWalletItems, autoUseCoupon, currencyCode)
6332
+ }
6333
+ }
6334
+
6335
+
6336
+
6105
6337
 
6106
6338
 
6107
6339
 
@@ -6117,6 +6349,7 @@ class ChainPurchaseOptions extends Chain {
6117
6349
 
6118
6350
 
6119
6351
 
6352
+
6120
6353
  ;// ./lib/helpers/corHelper/chainException.js
6121
6354
 
6122
6355
  class ChainException {
@@ -6378,6 +6611,7 @@ class ChainManagerFactory {
6378
6611
 
6379
6612
  function _calculateAmountChainsFactory(payload) {
6380
6613
  const {
6614
+ autoUseCoupon,
6381
6615
  categories,
6382
6616
  currency,
6383
6617
  dateTime,
@@ -6401,6 +6635,7 @@ function _calculateAmountChainsFactory(payload) {
6401
6635
  new ChainGetPrice({
6402
6636
  currency, dateTime, entitlements, merchandises
6403
6637
  }),
6638
+ new ChainRelatedCoupons({ currency, autoUseCoupon, walletItems }),
6404
6639
  ]
6405
6640
  }
6406
6641
 
@@ -6542,6 +6777,11 @@ function getFakeClass() {
6542
6777
 
6543
6778
 
6544
6779
 
6780
+ ;// ./lib/helpers/calculateByCoupon/index.js
6781
+
6782
+
6783
+
6784
+
6545
6785
  ;// ./lib/helpers/corHelper/index.js
6546
6786
 
6547
6787
 
@@ -6549,6 +6789,150 @@ function getFakeClass() {
6549
6789
 
6550
6790
 
6551
6791
 
6792
+ ;// ./lib/helpers/getRolesChangesRelatedCouponsHelper/getRolesChangesRelatedCouponsHelper.js
6793
+ function getRolesChangesRelatedCouponsHelper({ newRoles, originalRoles }) {
6794
+ const couponFromNewRoles = _getCouponsByRoles(newRoles)
6795
+ const couponFromOriginalRoles = _getCouponsByRoles(originalRoles)
6796
+ const allKeys = new Set([
6797
+ ...Object.keys(couponFromNewRoles),
6798
+ ...Object.keys(couponFromOriginalRoles)
6799
+ ])
6800
+ return Array.from(allKeys).reduce((acc, key) => {
6801
+ const newValue = couponFromNewRoles[key] || 0;
6802
+ const originalValue = couponFromOriginalRoles[key] || 0;
6803
+ const delta = newValue - originalValue;
6804
+ if (delta !== 0) {
6805
+ acc.push({
6806
+ key,
6807
+ value: {
6808
+ delta,
6809
+ newValue,
6810
+ originalValue
6811
+ }
6812
+ });
6813
+ }
6814
+ return acc
6815
+ }, [])
6816
+ }
6817
+
6818
+
6819
+ function _getCouponsByRoles(roles) {
6820
+ return roles.reduce((acc, role) => {
6821
+ const couponCodes = role.getCouponCodes()
6822
+ couponCodes.forEach((c) => {
6823
+ const { key, value } = c
6824
+ acc[key] = acc[key] ? acc[key] + value : value
6825
+ })
6826
+ return acc
6827
+ }, {})
6828
+ }
6829
+
6830
+
6831
+
6832
+ ;// ./lib/helpers/couponManager/couponManager.js
6833
+
6834
+
6835
+
6836
+
6837
+ class CouponManager {
6838
+ constructor(options) {
6839
+ this.products = options.products || []
6840
+ this.walletItems = options.walletItems || []
6841
+ this.originalRoles = options.originalRoles || []
6842
+ this.newRoles = options.newRoles || []
6843
+ }
6844
+
6845
+ static init(options = {}) {
6846
+ if (options instanceof this) {
6847
+ return options
6848
+ }
6849
+ const instance = new this(options)
6850
+ return instance.isValid ? instance : null
6851
+ }
6852
+
6853
+ get isValid() {
6854
+ return !!this
6855
+ }
6856
+
6857
+ get couponProducts() {
6858
+ return this.products.filter((p) => p.isCoupon)
6859
+ }
6860
+
6861
+ get couponWalletItems() {
6862
+ return this.walletItems.filter((w) => w.isCoupon)
6863
+ }
6864
+
6865
+ get roleRelatedCoupons() {
6866
+ return getRolesChangesRelatedCouponsHelper({ newRoles: this.newRoles, originalRoles: this.originalRoles })
6867
+ }
6868
+
6869
+
6870
+ get couponItemList() {
6871
+ return this.couponProducts.map((p) => {
6872
+ const relatedWalletItems = this.walletItems.filter(
6873
+ item => item.productCode === p.productCode
6874
+ )
6875
+
6876
+ const usedCoupons = relatedWalletItems.filter(item => item.isUsed)
6877
+ usedCoupons.forEach((c) => {
6878
+ c.useForWalletItems = this.walletItems.filter((item) => (c.useFor || []).includes(item.walletItemCode)) // useFor
6879
+ })
6880
+
6881
+ const availableCoupons = relatedWalletItems.filter(item => !item.isAvailableCoupon)
6882
+
6883
+ const roleBase = q_utilities_.KeyValueObject.foundValueByKey(this.roleRelatedCoupons, p.productCode) || {}
6884
+
6885
+ const remainingQuota = p.maxPerWallet - (usedCoupons.length + availableCoupons.length)
6886
+
6887
+ const { qty, remarks } = _handler({ product: p, availableCoupons, roleBase, remainingQuota })
6888
+
6889
+ return {
6890
+ product: p,
6891
+ usedCoupons,
6892
+ availableCoupons,
6893
+ alreadyHave: usedCoupons.length + availableCoupons.length,
6894
+ maxLimit: p.maxPerWallet,
6895
+ remainingQuota,
6896
+ qty,
6897
+ roleBase,
6898
+ remarks
6899
+ };
6900
+ })
6901
+ }
6902
+
6903
+ setNewRoles() {
6904
+ this.newRoles = newRoles
6905
+ }
6906
+
6907
+ }
6908
+
6909
+
6910
+
6911
+
6912
+ function _handler({ product, remainingQuota, availableCoupons, roleBase }) {
6913
+ const { delta = 0 } = roleBase
6914
+ const { maxPerWallet } = product
6915
+ let qty = delta
6916
+ const remarks = []
6917
+ if (delta > 0 && maxPerWallet && delta > remainingQuota) {
6918
+ qty = 0
6919
+ remarks.push(`max ${maxPerWallet}`)
6920
+ }
6921
+ if (delta < 0 && maxPerWallet && availableCoupons.length < delta) {
6922
+ qty = availableCoupons.length
6923
+ remarks.push(`only ${availableCoupons.length} could be cancelled`)
6924
+ }
6925
+ return {
6926
+ qty,
6927
+ remarks
6928
+ }
6929
+ }
6930
+
6931
+ ;// ./lib/helpers/couponManager/index.js
6932
+
6933
+
6934
+
6935
+
6552
6936
  ;// ./lib/helpers/dateHelper/handler/handler.js
6553
6937
  class Handler {
6554
6938
  constructor(date) {
@@ -6676,7 +7060,11 @@ function createDate(timestamp) {
6676
7060
  const mthIdx = Number(mthStr) - 1
6677
7061
  return new Date(timestamp.slice(0, 4), mthIdx, timestamp.slice(6, 8))
6678
7062
  }
6679
- throw new Error('timestamp does not meet the requirements')
7063
+ try {
7064
+ return new Date(timestamp)
7065
+ } catch (e) {
7066
+ throw new Error('timestamp does not meet the requirements')
7067
+ }
6680
7068
  }
6681
7069
 
6682
7070
  function convert(date, dateFormat) {
@@ -6945,6 +7333,8 @@ function isDescendingOrder({ arr = [], key }) {
6945
7333
 
6946
7334
 
6947
7335
 
7336
+
7337
+
6948
7338
  ;// ./lib/index.js
6949
7339
 
6950
7340
  const models = models_namespaceObject