@evershop/evershop 1.0.0 → 1.1.0

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.
Files changed (214) hide show
  1. package/bin/build/client/index.js +1 -1
  2. package/bin/build/complie.js +1 -1
  3. package/bin/build/index.js +1 -1
  4. package/bin/build/server/index.js +1 -1
  5. package/bin/build/server/useDDL.js +1 -1
  6. package/bin/dev/index.js +2 -1
  7. package/bin/evershop +8 -7
  8. package/bin/extension/index.js +1 -1
  9. package/bin/install/index.js +1 -1
  10. package/bin/lib/addDefaultMiddlewareFuncs.js +2 -2
  11. package/bin/lib/app.js +1 -1
  12. package/bin/lib/bootstrap/migrate.js +1 -1
  13. package/bin/lib/buildEntry.js +1 -1
  14. package/bin/lib/onError.js +1 -1
  15. package/bin/lib/onListening.js +1 -1
  16. package/bin/lib/startUp.js +10 -9
  17. package/bin/lib/watch/watchComponents.js +16 -26
  18. package/bin/lib/watch/watchMF.js +1 -1
  19. package/bin/lib/watch/watchMR.js +1 -1
  20. package/bin/lib/watch/watchSchema.js +1 -1
  21. package/bin/user/changePassword.js +1 -1
  22. package/bin/user/create.js +1 -1
  23. package/package.json +2 -2
  24. package/src/components/admin/catalog/productEdit/category/CategoryItem.jsx +1 -1
  25. package/src/components/admin/catalog/productEdit/category/CategoryTree.jsx +1 -1
  26. package/src/components/admin/catalog/productEdit/variants/CreateVariantGroup.jsx +3 -8
  27. package/src/components/admin/catalog/productEdit/variants/Variant.jsx +1 -1
  28. package/src/components/admin/catalog/productEdit/variants/VariantModal.jsx +62 -6
  29. package/src/components/admin/catalog/productEdit/variants/Variants.jsx +1 -1
  30. package/src/components/admin/checkout/shippingSetting/Method.jsx +130 -0
  31. package/src/components/admin/{oms → checkout}/shippingSetting/MethodForm.jsx +124 -13
  32. package/src/components/admin/{oms → checkout}/shippingSetting/Methods.jsx +2 -2
  33. package/src/components/admin/checkout/shippingSetting/PriceBasedPrice.jsx +101 -0
  34. package/src/components/admin/checkout/shippingSetting/WeightBasedPrice.jsx +101 -0
  35. package/src/components/admin/{oms → checkout}/shippingSetting/Zone.jsx +34 -4
  36. package/src/components/admin/{oms → checkout}/shippingSetting/Zones.jsx +6 -3
  37. package/src/components/admin/promotion/couponEdit/AttributeGroupSelector.jsx +5 -5
  38. package/src/components/admin/promotion/couponEdit/CategorySelector.jsx +5 -5
  39. package/src/components/admin/promotion/couponEdit/CollectionSelector.jsx +5 -5
  40. package/src/components/admin/promotion/couponEdit/ProductSkuSelector.jsx +27 -6
  41. package/src/components/common/context/checkout.jsx +8 -14
  42. package/src/components/common/form/Field.jsx +1 -1
  43. package/src/components/common/form/fields/Input.jsx +2 -1
  44. package/src/components/common/form/validator.js +6 -2
  45. package/src/components/common/grid/headers/Dummy.jsx +1 -1
  46. package/src/components/common/grid/headers/Sortable.jsx +148 -0
  47. package/src/components/common/grid/rows/StatusRow.jsx +1 -1
  48. package/src/components/common/list/Filter.jsx +83 -0
  49. package/src/components/common/list/Filter.scss +39 -0
  50. package/src/components/frontStore/catalog/categoryView/filter/AttributeFilter.jsx +19 -5
  51. package/src/components/frontStore/catalog/categoryView/filter/CategoryFilter.jsx +59 -52
  52. package/src/components/frontStore/catalog/categoryView/filter/PriceFilter.jsx +20 -11
  53. package/src/components/frontStore/catalog/product/list/SortOptions.jsx +4 -2
  54. package/src/components/frontStore/catalog/product/list/Sorting.jsx +5 -5
  55. package/src/components/frontStore/checkout/checkout/payment/paymentStep/StepContent.jsx +9 -6
  56. package/src/components/frontStore/stripe/checkout/CheckoutForm.jsx +8 -4
  57. package/src/lib/event/callSubscibers.js +14 -11
  58. package/src/lib/event/event-manager.js +1 -1
  59. package/src/lib/event/loadSubscribers.js +2 -2
  60. package/src/lib/helpers.js +3 -1
  61. package/src/lib/log/CustomColorize.js +22 -0
  62. package/src/lib/log/logger.js +153 -19
  63. package/src/lib/middleware/Handler.js +2 -3
  64. package/src/lib/middleware/async.js +5 -9
  65. package/src/lib/middleware/sync.js +5 -10
  66. package/src/lib/middleware/tests/app/app.js +1 -1
  67. package/src/lib/router/buildAbsoluteUrl.js +1 -1
  68. package/src/lib/util/buildFilterFromUrl.js +31 -64
  69. package/src/lib/util/defaultPaginationFilters.js +102 -0
  70. package/src/lib/util/filterOperationMapp.js +16 -0
  71. package/src/lib/util/registry.js +44 -6
  72. package/src/lib/webpack/dev/createConfigClient.js +2 -0
  73. package/src/lib/webpack/loaders/AreaLoader.js +1 -1
  74. package/src/lib/webpack/loaders/loadTranslationFromCsv.js +1 -1
  75. package/src/lib/webpack/plugins/Tailwindcss.js +1 -1
  76. package/src/modules/auth/graphql/types/AdminUser/AdminUser.admin.resolvers.js +6 -6
  77. package/src/modules/auth/pages/admin/adminLogin/LoginForm.jsx +1 -15
  78. package/src/modules/base/api/global/[apiResponse]apiErrorHandler.js +2 -2
  79. package/src/modules/base/pages/global/[response]errorHandler.js +2 -2
  80. package/src/modules/catalog/api/addProductToCategory/addProducts.js +1 -1
  81. package/src/modules/catalog/api/addProductToCollection/addProducts.js +35 -22
  82. package/src/modules/catalog/api/removeProductFromCollection/removeProducts.js +20 -5
  83. package/src/modules/catalog/bootstrap.js +63 -0
  84. package/src/modules/catalog/graphql/types/Attribute/Attribute.admin.graphql +2 -2
  85. package/src/modules/catalog/graphql/types/Attribute/Attribute.admin.resolvers.js +48 -276
  86. package/src/modules/catalog/graphql/types/Category/Category.graphql +15 -2
  87. package/src/modules/catalog/graphql/types/Category/Category.resolvers.js +2 -2
  88. package/src/modules/catalog/graphql/types/Collection/Collection.resolvers.js +2 -2
  89. package/src/modules/catalog/graphql/types/Product/Product.resolvers.js +1 -1
  90. package/src/modules/catalog/graphql/types/Product/Variant/Variant.graphql +2 -2
  91. package/src/modules/catalog/graphql/types/Product/Variant/Variant.resolvers.js +68 -92
  92. package/src/modules/catalog/pages/admin/attributeEdit+attributeNew/General.jsx +13 -9
  93. package/src/modules/catalog/pages/admin/attributeGrid/Grid.jsx +82 -39
  94. package/src/modules/catalog/pages/admin/attributeGrid/index.js +1 -1
  95. package/src/modules/catalog/pages/admin/categoryEdit/Products.jsx +5 -5
  96. package/src/modules/catalog/pages/admin/categoryGrid/Grid.jsx +48 -16
  97. package/src/modules/catalog/pages/admin/categoryGrid/index.js +1 -1
  98. package/src/modules/catalog/pages/admin/collectionEdit/Products.jsx +5 -5
  99. package/src/modules/catalog/pages/admin/collectionGrid/Grid.jsx +46 -5
  100. package/src/modules/catalog/pages/admin/collectionGrid/index.js +1 -1
  101. package/src/modules/catalog/pages/admin/productEdit+productNew/Attributes.jsx +28 -24
  102. package/src/modules/catalog/pages/admin/productGrid/Grid.jsx +158 -26
  103. package/src/modules/catalog/pages/admin/productGrid/index.js +1 -2
  104. package/src/modules/catalog/pages/frontStore/all/SearchBox.jsx +2 -1
  105. package/src/modules/catalog/pages/frontStore/catalogSearch/[index]filters.js +4 -59
  106. package/src/modules/catalog/pages/frontStore/catalogSearch/index.js +11 -0
  107. package/src/modules/catalog/pages/frontStore/categoryView/Filter.jsx +22 -6
  108. package/src/modules/catalog/pages/frontStore/categoryView/Filter.scss +2 -0
  109. package/src/modules/catalog/pages/frontStore/categoryView/[index]filters.js +5 -105
  110. package/src/modules/catalog/pages/frontStore/homepage/FeaturedProducts.jsx +1 -1
  111. package/src/modules/catalog/pages/frontStore/productView/Form.jsx +8 -3
  112. package/src/modules/catalog/pages/frontStore/productView/Variants.jsx +102 -40
  113. package/src/modules/catalog/services/AttributeCollection.js +59 -0
  114. package/src/modules/catalog/services/AttributeGroupCollection.js +100 -0
  115. package/src/modules/catalog/services/CategoryCollection.js +27 -84
  116. package/src/modules/catalog/services/CollectionCollection.js +24 -72
  117. package/src/modules/catalog/services/ProductCollection.js +50 -216
  118. package/src/modules/catalog/services/attribute/deleteProductAttribute.js +15 -0
  119. package/src/modules/catalog/services/getAttributeGroupsBaseQuery.js +3 -0
  120. package/src/modules/catalog/services/getAttributesBaseQuery.js +3 -0
  121. package/src/modules/catalog/services/getCollectionsBaseQuery.js +0 -1
  122. package/src/modules/catalog/services/product/updateProduct.js +8 -2
  123. package/src/modules/catalog/services/registerDefaultAttributeCollectionFilters.js +149 -0
  124. package/src/modules/catalog/services/registerDefaultCategoryCollectionFilters.js +85 -0
  125. package/src/modules/catalog/services/registerDefaultCollectionCollectionFilters.js +65 -0
  126. package/src/modules/catalog/services/registerDefaultProductCollectionFilters.js +219 -0
  127. package/src/modules/catalog/subscribers/category_created/buildUrlRewrite.js +1 -1
  128. package/src/modules/catalog/subscribers/category_deleted/deleteUrlRewrite.js +1 -1
  129. package/src/modules/catalog/subscribers/category_updated/builUrlRewrite.js +1 -1
  130. package/src/modules/catalog/subscribers/product_created/builUrlRewrite.js +1 -1
  131. package/src/modules/catalog/subscribers/product_deleted/deleteUrlRewrite.js +1 -1
  132. package/src/modules/catalog/subscribers/product_image_added/localGenerateProductImageVariant.js +3 -3
  133. package/src/modules/checkout/api/addCartShippingMethod/saveShippingMethod.js +6 -1
  134. package/src/modules/checkout/api/createCart/[context]bodyParser[auth].js +5 -0
  135. package/src/modules/checkout/api/createCart/createNewCart.js +92 -0
  136. package/src/modules/checkout/api/createCart/payloadSchema.json +44 -0
  137. package/src/modules/checkout/api/createCart/route.json +5 -0
  138. package/src/modules/checkout/api/deleteShippingZone/deleteShippingZone.js +58 -0
  139. package/src/modules/checkout/api/deleteShippingZone/route.json +5 -0
  140. package/src/modules/checkout/api/deleteShippingZoneMethod/deleteShippingZoneMethod.js +85 -0
  141. package/src/modules/checkout/api/deleteShippingZoneMethod/route.json +5 -0
  142. package/src/modules/checkout/api/getShippingMethods/sendMethods.js +37 -0
  143. package/src/modules/checkout/api/updateShippingMethod/[context]borderParser[auth].js +5 -0
  144. package/src/modules/checkout/api/updateShippingMethod/payloadSchema.json +12 -0
  145. package/src/modules/checkout/api/updateShippingMethod/route.json +5 -0
  146. package/src/modules/checkout/api/updateShippingMethod/updateShippingMethod.js +64 -0
  147. package/src/modules/checkout/api/updateShippingZoneMethod/payloadSchema.json +43 -1
  148. package/src/modules/checkout/api/updateShippingZoneMethod/updateShippingZoneMethod.js +17 -3
  149. package/src/modules/checkout/bootstrap.js +1 -1
  150. package/src/modules/checkout/graphql/types/ShippingMethod/ShippingMethod.graphql +1 -0
  151. package/src/modules/checkout/graphql/types/ShippingMethod/ShippingMethod.resolvers.js +4 -0
  152. package/src/modules/checkout/graphql/types/ShippingZone/ShippingZone.graphql +21 -1
  153. package/src/modules/checkout/graphql/types/ShippingZone/ShippingZone.resolvers.js +34 -4
  154. package/src/modules/checkout/graphql/types/Weight/Weight.resolvers.js +8 -11
  155. package/src/modules/checkout/migration/Version-1.0.5.js +28 -0
  156. package/src/modules/{oms → checkout}/pages/admin/shippingSetting/ShippingSetting.jsx +66 -43
  157. package/src/modules/checkout/pages/frontStore/all/[auth]addCustomerToCart.js +3 -3
  158. package/src/modules/checkout/pages/frontStore/checkout/PaymentStep.jsx +3 -2
  159. package/src/modules/checkout/pages/frontStore/checkout/ShippingMethods.jsx +23 -10
  160. package/src/modules/checkout/pages/frontStore/checkout/SummaryMobile.jsx +132 -0
  161. package/src/modules/checkout/pages/frontStore/checkout/SummaryMobile.scss +7 -0
  162. package/src/modules/checkout/services/cart/Cart.js +23 -7
  163. package/src/modules/checkout/services/cart/DataObject.js +3 -3
  164. package/src/modules/checkout/services/cart/registerCartBaseFields.js +32 -0
  165. package/src/modules/checkout/services/cart/registerCartItemBaseFields.js +3 -2
  166. package/src/modules/cms/bootstrap.js +17 -0
  167. package/src/modules/cms/graphql/types/CmsPage/CmsPage.resolvers.js +2 -11
  168. package/src/modules/cms/pages/admin/all/Layout.scss +3 -2
  169. package/src/modules/cms/pages/admin/all/SearchBox.jsx +1 -1
  170. package/src/modules/cms/pages/admin/cmsPageGrid/Grid.jsx +62 -9
  171. package/src/modules/cms/pages/admin/cmsPageGrid/index.js +1 -2
  172. package/src/modules/cms/services/CMSPageCollection.js +23 -70
  173. package/src/modules/cms/services/registerDefaultPageCollectionFilters.js +62 -0
  174. package/src/modules/cms/services/tailwind.admin.config.js +6 -1
  175. package/src/modules/customer/api/createCustomer/[bodyParser]createCustomer.js +2 -2
  176. package/src/modules/customer/api/resetPassword/[bodyParser]resetPassword.js +2 -2
  177. package/src/modules/customer/api/updatePassword/[bodyParser]updatePassword.js +2 -2
  178. package/src/modules/customer/bootstrap.js +29 -0
  179. package/src/modules/customer/graphql/types/Customer/Customer.admin.resolvers.js +2 -4
  180. package/src/modules/customer/pages/admin/customerGrid/Grid.jsx +108 -14
  181. package/src/modules/customer/pages/admin/customerGrid/index.js +1 -2
  182. package/src/modules/customer/pages/frontStore/login/LoginForm.jsx +0 -1
  183. package/src/modules/customer/services/CustomerCollection.js +23 -104
  184. package/src/modules/customer/services/CustomerGroupCollection.js +21 -70
  185. package/src/modules/customer/services/registerDefaultCustomerCollectionFilters.js +90 -0
  186. package/src/modules/customer/services/registerDefaultCustomerGroupCollectionFilters.js +50 -0
  187. package/src/modules/graphql/pages/global/[bodyParser]buildQuery[graphql].js +1 -1
  188. package/src/modules/graphql/pages/global/[buildQuery]graphql[notification].js +1 -1
  189. package/src/modules/graphql/services/graphqlMiddleware.js +1 -1
  190. package/src/modules/oms/bootstrap.js +17 -0
  191. package/src/modules/oms/graphql/types/Order/Order.admin.resolvers.js +1 -1
  192. package/src/modules/oms/graphql/types/Order/Order.resolvers.js +2 -1
  193. package/src/modules/oms/pages/admin/orderGrid/Grid.jsx +152 -51
  194. package/src/modules/oms/pages/admin/orderGrid/index.js +1 -2
  195. package/src/modules/oms/services/OrderCollection.js +19 -139
  196. package/src/modules/oms/services/registerDefaultOrderCollectionFilters.js +121 -0
  197. package/src/modules/promotion/bootstrap.js +16 -0
  198. package/src/modules/promotion/graphql/types/Coupon/Coupon.admin.resolvers.js +2 -7
  199. package/src/modules/promotion/pages/admin/couponGrid/Grid.jsx +157 -33
  200. package/src/modules/promotion/pages/admin/couponGrid/index.js +1 -2
  201. package/src/modules/promotion/services/CouponCollection.js +21 -130
  202. package/src/modules/promotion/services/registerDefaultCouponCollectionFilters.js +72 -0
  203. package/src/modules/stripe/api/stripeWebHook/[bodyJson]webhook.js +4 -2
  204. package/src/modules/tax/bootstrap.js +17 -0
  205. package/src/modules/tax/services/TaxClassCollection.js +22 -56
  206. package/src/modules/tax/services/registerDefaultTaxClassCollectionFilters.js +49 -0
  207. package/src/components/admin/oms/shippingSetting/Method.jsx +0 -73
  208. package/src/components/common/grid/headers/Basic.jsx +0 -55
  209. package/src/lib/log/debuger.js +0 -89
  210. package/src/modules/customer/pages/frontStore/login/LoginButton.jsx +0 -27
  211. /package/src/components/admin/{oms → checkout}/shippingSetting/ZoneForm.jsx +0 -0
  212. /package/src/modules/{oms → checkout}/pages/admin/all/ShippingSettingMenu.jsx +0 -0
  213. /package/src/modules/{oms → checkout}/pages/admin/shippingSetting/index.js +0 -0
  214. /package/src/modules/{oms → checkout}/pages/admin/shippingSetting/route.json +0 -0
@@ -1,16 +1,24 @@
1
1
  const { camelCase } = require('@evershop/evershop/src/lib/util/camelCase');
2
2
  const { getConfig } = require('@evershop/evershop/src/lib/util/getConfig');
3
- const uniqid = require('uniqid');
4
- const { select, value, node } = require('@evershop/postgres-query-builder');
3
+
4
+ const { select, node, sql } = require('@evershop/postgres-query-builder');
5
5
  const { pool } = require('@evershop/evershop/src/lib/postgres/connection');
6
+ const { getValue } = require('@evershop/evershop/src/lib/util/registry');
6
7
 
7
8
  class ProductCollection {
8
9
  constructor(baseQuery) {
9
10
  this.baseQuery = baseQuery;
11
+ this.baseQuery.orderBy('product.product_id', 'DESC');
10
12
  }
11
13
 
12
- async init(args, { filters = [] }, { user }) {
13
- if (!user) {
14
+ /**
15
+ *
16
+ * @param {{key: String, operation: String, value: String}[]} filters
17
+ * @param {boolean} isAdmin
18
+ */
19
+ async init(filters = [], isAdmin = false) {
20
+ // If the user is not admin, we need to filter out the out of stock products and the disabled products
21
+ if (!isAdmin) {
14
22
  this.baseQuery.andWhere('product.status', '=', 1);
15
23
  if (getConfig('catalog.showOutOfStockProduct', false) === false) {
16
24
  this.baseQuery
@@ -23,210 +31,37 @@ class ProductCollection {
23
31
  }
24
32
  }
25
33
  const currentFilters = [];
26
- // Keyword filter
27
- const keywordFilter = filters.find((f) => f.key === 'keyword');
28
- if (keywordFilter) {
29
- const where = this.baseQuery.getWhere();
30
- const bindingKey = `keyword_${uniqid()}`;
31
- where.addRaw(
32
- 'AND',
33
- `to_tsvector('simple', product_description.name || ' ' || product_description.description) @@ websearch_to_tsquery('simple', :${bindingKey})`,
34
- {
35
- [bindingKey]: keywordFilter.value
36
- }
37
- );
38
- currentFilters.push({
39
- key: 'keyword',
40
- operation: '=',
41
- value: keywordFilter.value
42
- });
43
- }
44
-
45
- // Price filter
46
- const minPrice = filters.find((f) => f.key === 'minPrice');
47
- const maxPrice = filters.find((f) => f.key === 'maxPrice');
48
- if (minPrice && Number.isNaN(parseFloat(minPrice.value)) === false) {
49
- this.baseQuery.andWhere('product.price', '>=', minPrice.value);
50
- currentFilters.push({
51
- key: 'minPrice',
52
- operation: '=',
53
- value: minPrice.value
54
- });
55
- }
56
- if (maxPrice && Number.isNaN(parseFloat(maxPrice.value)) === false) {
57
- this.baseQuery.andWhere('product.price', '<=', maxPrice.value);
58
- currentFilters.push({
59
- key: 'maxPrice',
60
- operation: '=',
61
- value: maxPrice.value
62
- });
63
- }
64
-
65
- // Name filter
66
- const nameFilter = filters.find((f) => f.key === 'name');
67
- if (nameFilter) {
68
- this.baseQuery.andWhere(
69
- 'product_description.name',
70
- 'ILIKE',
71
- `%${nameFilter.value}%`
72
- );
73
- currentFilters.push({
74
- key: 'name',
75
- operation: '=',
76
- value: nameFilter.value
77
- });
78
- }
79
-
80
- // Qty filter
81
- const qtyFilter = filters.find((f) => f.key === 'qty');
82
- if (qtyFilter) {
83
- const [min, max] = qtyFilter.value.split('-').map((v) => parseFloat(v));
84
- let currentQtyFilter;
85
- if (Number.isNaN(min) === false) {
86
- this.baseQuery.andWhere('product_inventory.qty', '>=', min);
87
- currentQtyFilter = { key: 'qty', operation: '=', value: `${min}` };
88
- }
89
-
90
- if (Number.isNaN(max) === false) {
91
- this.baseQuery.andWhere('product_inventory.qty', '<=', max);
92
- currentQtyFilter = {
93
- key: 'qty',
94
- operation: '=',
95
- value: `${currentQtyFilter.value}-${max}`
96
- };
97
- }
98
- if (currentQtyFilter) {
99
- currentFilters.push(currentQtyFilter);
100
- }
101
- }
102
-
103
- // Sku filter
104
- const skuFilter = filters.find((f) => f.key === 'sku');
105
- if (skuFilter) {
106
- // Support like, equal and IN
107
- if (['LIKE', 'like'].includes(skuFilter.operation)) {
108
- this.baseQuery.andWhere('product.sku', 'ILIKE', `%${skuFilter.value}%`);
109
- currentFilters.push({
110
- key: 'sku',
111
- operation: 'like',
112
- value: skuFilter.value
113
- });
114
- } else if (['IN', 'in'].includes(skuFilter.operation)) {
115
- const values = skuFilter.value
116
- .split(',')
117
- .map((v) => v.trim())
118
- .filter((v) => v.length > 0);
119
- if (values.length > 0) {
120
- this.baseQuery.andWhere('product.sku', 'IN', values);
121
- currentFilters.push({
122
- key: 'sku',
123
- operation: 'in',
124
- value: values.join(',')
125
- });
126
- }
127
- } else {
128
- this.baseQuery.andWhere('product.sku', '=', skuFilter.value);
129
- currentFilters.push({
130
- key: 'sku',
131
- operation: '=',
132
- value: skuFilter.value
133
- });
134
- }
135
- }
136
-
137
- // Status filter
138
- const statusFilter = filters.find((f) => f.key === 'status');
139
- if (statusFilter) {
140
- this.baseQuery.andWhere('product.status', '=', statusFilter.value);
141
- currentFilters.push({
142
- key: 'status',
143
- operation: '=',
144
- value: statusFilter.value
145
- });
146
- }
147
-
148
- // Apply category filters
149
- const categoryFilter = filters.find((f) => f.key === 'cat');
150
- if (categoryFilter) {
151
- const values = categoryFilter.value
152
- .split(',')
153
- .map((v) => parseInt(v, 10))
154
- .filter((v) => Number.isNaN(v) === false);
155
- this.baseQuery.andWhere('product.category_id', 'IN', values);
156
-
157
- currentFilters.push({
158
- key: 'cat',
159
- operation: '=',
160
- value: values.join(',')
161
- });
162
- }
163
-
164
34
  // Attribute filter
165
35
  const filterableAttributes = await select()
166
36
  .from('attribute')
167
37
  .where('type', '=', 'select')
168
38
  .and('is_filterable', '=', 1)
169
39
  .execute(pool);
170
- // Attribute filters
171
- filters.forEach((filter) => {
172
- const attribute = filterableAttributes.find(
173
- (a) => a.attribute_code === filter.key
174
- );
175
- if (!attribute) {
176
- return;
40
+ // Apply the filters
41
+ const productCollectionFilters = await getValue(
42
+ 'productCollectionFilters',
43
+ [],
44
+ {
45
+ isAdmin,
46
+ filterableAttributes
177
47
  }
48
+ );
178
49
 
179
- const values = filter.value
180
- .split(',')
181
- .map((v) => parseInt(v, 10))
182
- .filter((v) => Number.isNaN(v) === false);
183
- if (values.length > 0) {
184
- const alias = `attribute_${uniqid()}`;
185
- this.baseQuery
186
- .innerJoin('product_attribute_value_index', alias)
187
- .on(`${alias}.product_id`, '=', 'product.product_id')
188
- .and(`${alias}.attribute_id`, '=', value(attribute.attribute_id))
189
- .and(`${alias}.option_id`, 'IN', value(values));
50
+ productCollectionFilters.forEach((filter) => {
51
+ const check = filters.find(
52
+ (f) => f.key === filter.key && filter.operation.includes(f.operation)
53
+ );
54
+ if (filter.key === '*' || check) {
55
+ filter.callback(
56
+ this.baseQuery,
57
+ check?.operation,
58
+ check?.value,
59
+ currentFilters
60
+ );
190
61
  }
191
- currentFilters.push({
192
- key: filter.key,
193
- operation: filter.operation,
194
- value: values.join(',')
195
- });
196
62
  });
197
63
 
198
- const sortBy = filters.find((f) => f.key === 'sortBy');
199
- const sortOrder = filters.find(
200
- (f) =>
201
- f.key === 'sortOrder' &&
202
- ['ASC', 'DESC', 'asc', 'desc'].includes(f.value)
203
- ) || { value: 'DESC' };
204
- if (sortBy && sortBy.value === 'price') {
205
- this.baseQuery.orderBy('product.price', sortOrder.value);
206
- currentFilters.push({
207
- key: 'sortBy',
208
- operation: '=',
209
- value: sortBy.value
210
- });
211
- } else if (sortBy && sortBy.value === 'name') {
212
- this.baseQuery.orderBy('product_description.name`', sortOrder.value);
213
- currentFilters.push({
214
- key: 'sortBy',
215
- operation: '=',
216
- value: sortBy.value
217
- });
218
- } else {
219
- this.baseQuery.orderBy('product.product_id', sortOrder.value);
220
- }
221
- if (sortOrder.key) {
222
- currentFilters.push({
223
- key: 'sortOrder',
224
- operation: '=',
225
- value: sortOrder.value
226
- });
227
- }
228
-
229
- if (!user) {
64
+ if (!isAdmin) {
230
65
  // Visibility. For variant group
231
66
  const copy = this.baseQuery.clone();
232
67
  // Get all group that have at lease 1 item visibile
@@ -261,31 +96,30 @@ class ProductCollection {
261
96
  } else {
262
97
  this.baseQuery.andWhere('product.visibility', '=', 't');
263
98
  }
99
+ } else {
100
+ const onePerVariantGroupQuery = this.baseQuery.clone();
101
+ onePerVariantGroupQuery.removeLimit();
102
+ onePerVariantGroupQuery.select(
103
+ sql(
104
+ 'DISTINCT ON (COALESCE(product.variant_group_id, random())) product.product_id',
105
+ 'product_id'
106
+ )
107
+ );
108
+ onePerVariantGroupQuery.removeOrderBy();
109
+ const onePerGroup = await onePerVariantGroupQuery.execute(pool);
110
+ this.baseQuery.andWhere(
111
+ 'product.product_id',
112
+ 'IN',
113
+ onePerGroup.map((v) => v.product_id)
114
+ );
264
115
  }
265
116
 
266
117
  // Clone the main query for getting total right before doing the paging
267
118
  const totalQuery = this.baseQuery.clone();
268
119
  totalQuery.select('COUNT(product.product_id)', 'total');
269
120
  totalQuery.removeOrderBy();
270
- // Paging
271
- const page = filters.find((f) => f.key === 'page') || { value: 1 };
272
- const limit = filters.find((f) => f.key === 'limit' && f.value > 0) || {
273
- value: 20
274
- }; // TODO: Get from the config
275
- currentFilters.push({
276
- key: 'page',
277
- operation: '=',
278
- value: page.value
279
- });
280
- currentFilters.push({
281
- key: 'limit',
282
- operation: '=',
283
- value: limit.value
284
- });
285
- this.baseQuery.limit(
286
- (page.value - 1) * parseInt(limit.value, 10),
287
- parseInt(limit.value, 10)
288
- );
121
+ totalQuery.removeLimit();
122
+
289
123
  this.currentFilters = currentFilters;
290
124
  this.totalQuery = totalQuery;
291
125
  }
@@ -30,6 +30,21 @@ async function deleteAttribute(uuid, context) {
30
30
  if (!attribute) {
31
31
  throw new Error('Invalid attribute id');
32
32
  }
33
+
34
+ // Make sure the attribute is not being used in any variant group
35
+ const variantGroup = await select()
36
+ .from('variant_group')
37
+ .where('attribute_one', '=', attribute.attribute_id)
38
+ .or('attribute_two', '=', attribute.attribute_id)
39
+ .or('attribute_three', '=', attribute.attribute_id)
40
+ .or('attribute_four', '=', attribute.attribute_id)
41
+ .or('attribute_five', '=', attribute.attribute_id)
42
+ .load(connection);
43
+ if (variantGroup) {
44
+ throw new Error(
45
+ `The attribute "${attribute.attribute_name}" is being used in a variant group`
46
+ );
47
+ }
33
48
  await hookable(deleteAttributeData, { ...context, connection, attribute })(
34
49
  uuid,
35
50
  connection
@@ -0,0 +1,3 @@
1
+ const { select } = require('@evershop/postgres-query-builder');
2
+
3
+ module.exports.getAttributeGroupsBaseQuery = () => select().from('attribute_group');
@@ -0,0 +1,3 @@
1
+ const { select } = require('@evershop/postgres-query-builder');
2
+
3
+ module.exports.getAttributesBaseQuery = () => select().from('attribute');
@@ -2,6 +2,5 @@ const { select } = require('@evershop/postgres-query-builder');
2
2
 
3
3
  module.exports.getCollectionsBaseQuery = () => {
4
4
  const query = select().from('collection');
5
-
6
5
  return query;
7
6
  };
@@ -16,7 +16,7 @@ const {
16
16
  const {
17
17
  getConnection
18
18
  } = require('@evershop/evershop/src/lib/postgres/connection');
19
- const { debug } = require('@evershop/evershop/src/lib/log/debuger');
19
+ const { error } = require('@evershop/evershop/src/lib/log/logger');
20
20
  const { getAjv } = require('../../../base/services/getAjv');
21
21
  const productDataSchema = require('./productDataSchema.json');
22
22
 
@@ -51,6 +51,12 @@ async function updateProductInventory(inventoryData, productId, connection) {
51
51
  }
52
52
  }
53
53
 
54
+ /**
55
+ * @param {number} productId
56
+ * @param {[{attribute_code: string, value}]} attributes
57
+ * @param {*} connection
58
+ * @returns
59
+ */
54
60
  async function saveProductAttributes(productId, attributes, connection) {
55
61
  for (let i = 0; i < attributes.length; i += 1) {
56
62
  const attribute = attributes[i];
@@ -248,7 +254,7 @@ async function updateProductImages(images, productId, connection) {
248
254
  )
249
255
  );
250
256
  } catch (e) {
251
- debug('critical', e);
257
+ error(e);
252
258
  throw e;
253
259
  }
254
260
  }
@@ -0,0 +1,149 @@
1
+ const {
2
+ OPERATION_MAP
3
+ } = require('@evershop/evershop/src/lib/util/filterOperationMapp');
4
+ const { getValueSync } = require('@evershop/evershop/src/lib/util/registry');
5
+
6
+ module.exports = async function registerDefaultAttributeCollectionFilters() {
7
+ // List of default supported filters
8
+ const defaultFilters = [
9
+ {
10
+ key: 'name',
11
+ operation: ['like', 'nlike'],
12
+ callback: (query, operation, value, currentFilters) => {
13
+ query.andWhere(
14
+ 'attribute.attribute_name',
15
+ OPERATION_MAP[operation],
16
+ `%${value}%`
17
+ );
18
+ currentFilters.push({
19
+ key: 'name',
20
+ operation,
21
+ value
22
+ });
23
+ }
24
+ },
25
+ {
26
+ key: 'code',
27
+ operation: ['eq', 'like', 'nlike', 'in'],
28
+ callback: (query, operation, value, currentFilters) => {
29
+ if (operation === 'in') {
30
+ query.andWhere(
31
+ 'attribute.attribute_code',
32
+ OPERATION_MAP[operation],
33
+ value.split(',')
34
+ );
35
+ } else if (operation === 'eq') {
36
+ query.andWhere(
37
+ 'attribute.attribute_code',
38
+ OPERATION_MAP[operation],
39
+ value
40
+ );
41
+ } else {
42
+ query.andWhere(
43
+ 'attribute.attribute_code',
44
+ OPERATION_MAP[operation],
45
+ `%${value}%`
46
+ );
47
+ }
48
+ currentFilters.push({
49
+ key: 'code',
50
+ operation,
51
+ value
52
+ });
53
+ }
54
+ },
55
+ {
56
+ key: 'group',
57
+ operation: ['in', 'eq'],
58
+ callback: (query, operation, value, currentFilters) => {
59
+ query
60
+ .innerJoin('attribute_group_link')
61
+ .on(
62
+ 'attribute.attribute_id',
63
+ '=',
64
+ 'attribute_group_link.attribute_id'
65
+ );
66
+ query.andWhere(
67
+ 'attribute_group_link.group_id',
68
+ OPERATION_MAP[operation],
69
+ value
70
+ );
71
+ currentFilters.push({
72
+ key: 'group',
73
+ operation,
74
+ value
75
+ });
76
+ }
77
+ },
78
+ {
79
+ key: 'type',
80
+ operation: ['eq', 'neq'],
81
+ callback: (query, operation, value, currentFilters) => {
82
+ query.andWhere('attribute.type', OPERATION_MAP[operation], value);
83
+ currentFilters.push({
84
+ key: 'type',
85
+ operation,
86
+ value
87
+ });
88
+ }
89
+ },
90
+ {
91
+ key: 'is_required',
92
+ operation: ['eq'],
93
+ callback: (query, operation, value, currentFilters) => {
94
+ query.andWhere(
95
+ 'attribute.is_required',
96
+ OPERATION_MAP[operation],
97
+ value
98
+ );
99
+ currentFilters.push({
100
+ key: 'is_required',
101
+ operation,
102
+ value
103
+ });
104
+ }
105
+ },
106
+ {
107
+ key: 'is_filterable',
108
+ operation: ['eq'],
109
+ callback: (query, operation, value, currentFilters) => {
110
+ query.andWhere(
111
+ 'attribute.is_filterable',
112
+ OPERATION_MAP[operation],
113
+ value
114
+ );
115
+ currentFilters.push({
116
+ key: 'is_filterable',
117
+ operation,
118
+ value
119
+ });
120
+ }
121
+ },
122
+ {
123
+ key: 'ob',
124
+ operation: ['eq'],
125
+ callback: (query, operation, value, currentFilters) => {
126
+ const attributeCollectionSortBy = getValueSync(
127
+ 'attributeCollectionSortBy',
128
+ {
129
+ name: (query) => query.orderBy('attribute.name'),
130
+ type: (query) => query.orderBy('attribute.type'),
131
+ is_required: (query) => query.orderBy('attribute.is_required'),
132
+ is_filterable: (query) => query.orderBy('attribute.is_filterable')
133
+ }
134
+ );
135
+
136
+ if (attributeCollectionSortBy[value]) {
137
+ attributeCollectionSortBy[value](query, operation);
138
+ currentFilters.push({
139
+ key: 'ob',
140
+ operation,
141
+ value
142
+ });
143
+ }
144
+ }
145
+ }
146
+ ];
147
+
148
+ return defaultFilters;
149
+ };
@@ -0,0 +1,85 @@
1
+ const {
2
+ OPERATION_MAP
3
+ } = require('@evershop/evershop/src/lib/util/filterOperationMapp');
4
+ const { getValueSync } = require('@evershop/evershop/src/lib/util/registry');
5
+
6
+ module.exports = async function registerDefaultCategoryCollectionFilters() {
7
+ const { isAdmin } = this;
8
+ // List of default supported filters
9
+ const defaultFilters = [
10
+ {
11
+ key: 'name',
12
+ operation: ['like'],
13
+ callback: (query, operation, value, currentFilters) => {
14
+ query.andWhere(
15
+ 'category_description.name',
16
+ OPERATION_MAP[operation],
17
+ `%${value}%`
18
+ );
19
+ currentFilters.push({
20
+ key: 'name',
21
+ operation,
22
+ value
23
+ });
24
+ }
25
+ },
26
+ {
27
+ key: 'status',
28
+ operation: ['eq'],
29
+ callback: (query, operation, value, currentFilters) => {
30
+ query.andWhere('category.status', OPERATION_MAP[operation], value);
31
+ currentFilters.push({
32
+ key: 'status',
33
+ operation,
34
+ value
35
+ });
36
+ }
37
+ },
38
+ {
39
+ key: 'include_in_nav',
40
+ operation: ['eq'],
41
+ callback: (query, operation, value, currentFilters) => {
42
+ query.andWhere(
43
+ 'category.include_in_nav',
44
+ OPERATION_MAP[operation],
45
+ value
46
+ );
47
+ currentFilters.push({
48
+ key: 'include_in_nav',
49
+ operation,
50
+ value
51
+ });
52
+ }
53
+ },
54
+ {
55
+ key: 'ob',
56
+ operation: ['eq'],
57
+ callback: (query, operation, value, currentFilters) => {
58
+ const categorySortBy = getValueSync(
59
+ 'categoryCollectionSortBy',
60
+ {
61
+ name: (query) => query.orderBy('category_description.name'),
62
+ include_in_nav: (query) => query.orderBy('category.include_in_nav'),
63
+ status: (query) => query.orderBy('category.status')
64
+ },
65
+ {
66
+ isAdmin
67
+ }
68
+ );
69
+
70
+ if (categorySortBy[value]) {
71
+ categorySortBy[value](query, operation);
72
+ currentFilters.push({
73
+ key: 'ob',
74
+ operation,
75
+ value
76
+ });
77
+ } else {
78
+ query.orderBy('category.category_id', 'DESC');
79
+ }
80
+ }
81
+ }
82
+ ];
83
+
84
+ return defaultFilters;
85
+ };
@@ -0,0 +1,65 @@
1
+ const {
2
+ OPERATION_MAP
3
+ } = require('@evershop/evershop/src/lib/util/filterOperationMapp');
4
+ const { getValueSync } = require('@evershop/evershop/src/lib/util/registry');
5
+
6
+ module.exports = async function registerDefaultCollectionCollectionFilters() {
7
+ // List of default supported filters
8
+ const defaultFilters = [
9
+ {
10
+ key: 'name',
11
+ operation: ['like'],
12
+ callback: (query, operation, value, currentFilters) => {
13
+ query.andWhere(
14
+ 'collection.name',
15
+ OPERATION_MAP[operation],
16
+ `%${value}%`
17
+ );
18
+ currentFilters.push({
19
+ key: 'name',
20
+ operation,
21
+ value
22
+ });
23
+ }
24
+ },
25
+ {
26
+ key: 'code',
27
+ operation: ['like', 'eq'],
28
+ callback: (query, operation, value, currentFilters) => {
29
+ query.andWhere(
30
+ 'collection.code',
31
+ OPERATION_MAP[operation],
32
+ `%${value}%`
33
+ );
34
+ currentFilters.push({
35
+ key: 'code',
36
+ operation,
37
+ value
38
+ });
39
+ }
40
+ },
41
+ {
42
+ key: 'ob',
43
+ operation: ['eq'],
44
+ callback: (query, operation, value, currentFilters) => {
45
+ const collectionSortBy = getValueSync('collectionCollectionSortBy', {
46
+ name: (query) => query.orderBy('collection.name'),
47
+ code: (query) => query.orderBy('collection.code')
48
+ });
49
+
50
+ if (collectionSortBy[value]) {
51
+ collectionSortBy[value](query, operation);
52
+ currentFilters.push({
53
+ key: 'ob',
54
+ operation,
55
+ value
56
+ });
57
+ } else {
58
+ query.orderBy('collection.collection_id', 'DESC');
59
+ }
60
+ }
61
+ }
62
+ ];
63
+
64
+ return defaultFilters;
65
+ };