@things-factory/operato-mms 4.0.11 → 4.0.12

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 (45) hide show
  1. package/client/menu.js +40 -2
  2. package/client/pages/catalogue-variation/product-variations.js +1 -1
  3. package/client/pages/order/logistics/lazada-order-init-batch-popup.js +1 -2
  4. package/client/pages/order/logistics/request-ro-popup.js +69 -4
  5. package/client/pages/order/logistics/shopee-order-init-batch-popup.js +1 -2
  6. package/client/pages/order/order-by-store.js +71 -3
  7. package/client/pages/reports/sales-by-platform/home.js +144 -0
  8. package/client/pages/reports/sales-by-platform/index.js +3 -0
  9. package/client/pages/reports/sales-by-platform/lazada-sales-report.js +504 -0
  10. package/client/pages/reports/sales-by-platform/shopee-sales-report.js +496 -0
  11. package/client/pages/setting/marketplace-setting.js +9 -6
  12. package/client/route.js +13 -0
  13. package/dist-server/graphql/resolvers/index.js +2 -1
  14. package/dist-server/graphql/resolvers/index.js.map +1 -1
  15. package/dist-server/graphql/resolvers/interface-with-hub/auto-add-release-order.js +3 -1
  16. package/dist-server/graphql/resolvers/interface-with-hub/auto-add-release-order.js.map +1 -1
  17. package/dist-server/graphql/resolvers/shipping-provider/index.js +6 -0
  18. package/dist-server/graphql/resolvers/shipping-provider/index.js.map +1 -0
  19. package/dist-server/graphql/resolvers/shipping-provider/shipping-providers.js +32 -0
  20. package/dist-server/graphql/resolvers/shipping-provider/shipping-providers.js.map +1 -0
  21. package/dist-server/graphql/types/index.js +3 -2
  22. package/dist-server/graphql/types/index.js.map +1 -1
  23. package/dist-server/graphql/types/shipping-provider/index.js +10 -0
  24. package/dist-server/graphql/types/shipping-provider/index.js.map +1 -0
  25. package/dist-server/graphql/types/shipping-provider/shipping-provider-list.js +13 -0
  26. package/dist-server/graphql/types/shipping-provider/shipping-provider-list.js.map +1 -0
  27. package/dist-server/graphql/types/shipping-provider/shipping-provider.js +13 -0
  28. package/dist-server/graphql/types/shipping-provider/shipping-provider.js.map +1 -0
  29. package/dist-server/routers/etrax-router.js +2 -2
  30. package/dist-server/routers/etrax-router.js.map +1 -1
  31. package/package.json +61 -61
  32. package/server/graphql/resolvers/index.ts +2 -1
  33. package/server/graphql/resolvers/interface-with-hub/auto-add-release-order.ts +3 -1
  34. package/server/graphql/resolvers/shipping-provider/index.ts +5 -0
  35. package/server/graphql/resolvers/shipping-provider/shipping-providers.ts +37 -0
  36. package/server/graphql/types/index.ts +3 -2
  37. package/server/graphql/types/shipping-provider/index.ts +8 -0
  38. package/server/graphql/types/shipping-provider/shipping-provider-list.ts +7 -0
  39. package/server/graphql/types/shipping-provider/shipping-provider.ts +7 -0
  40. package/server/routers/etrax-router.ts +2 -2
  41. package/things-factory.config.js +13 -1
  42. package/translations/en.json +63 -15
  43. package/translations/ko.json +57 -9
  44. package/translations/ms.json +57 -9
  45. package/translations/zh.json +57 -9
package/client/menu.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import '@material/mwc-icon'
2
- import { store } from '@things-factory/shell'
2
+
3
3
  import { updateMenuTemplate } from '@things-factory/lite-menu'
4
+ import { store } from '@things-factory/shell'
4
5
 
5
- var stores
6
+ var stores, platforms
6
7
 
7
8
  store.subscribe(() => {
8
9
  var state = store.getState()
@@ -13,6 +14,14 @@ store.subscribe(() => {
13
14
 
14
15
  stores = state.mms.stores
15
16
 
17
+ // At the moment, only Sales by Platform will use this variable
18
+ // and currently only support for lazada and shopee
19
+ platforms = stores
20
+ .map(store => store.platform)
21
+ .filter((v, i, a) => a.indexOf(v) === i)
22
+ .filter(v => ['lazada', 'shopee'].indexOf(v) !== -1)
23
+ .sort()
24
+
16
25
  updateMenuTemplate(
17
26
  getMenuTemplate({
18
27
  stores: stores || []
@@ -103,6 +112,35 @@ function getMenuTemplate({ stores }) {
103
112
  path: 'mms-inventory-product',
104
113
  icon: 'storage'
105
114
  },
115
+ {
116
+ name: 'report',
117
+ type: 'group'
118
+ },
119
+ {
120
+ name: 'sales by platform',
121
+ path: 'mms-report-sales-by-platform-home',
122
+ icon: 'assessment',
123
+ menus: [
124
+ ...platforms.map(platform => {
125
+ return {
126
+ name: platform,
127
+ path: `${platform}-sales-report`,
128
+ icon: 'store'
129
+ }
130
+ })
131
+ // to be removed. it was here for testing purpose
132
+ /* {
133
+ name: 'lazada',
134
+ path: 'lazada-sales-report',
135
+ icon: 'store'
136
+ },
137
+ {
138
+ name: 'shopee',
139
+ path: 'shopee-sales-report',
140
+ icon: 'store'
141
+ } */
142
+ ]
143
+ },
106
144
  {
107
145
  name: 'store integration',
108
146
  type: 'group'
@@ -270,7 +270,7 @@ class ProductVariations extends localize(i18next)(PageView) {
270
270
  }
271
271
 
272
272
  async _fetchProducts({ page, limit, sorters = [{ name: 'status' }] }) {
273
- let filters = []
273
+ let filters = [{ name: 'status', operator: 'noteq', value: 'INACTIVE' }]
274
274
  if (this.store) {
275
275
  filters.push({
276
276
  name: 'marketplaceStoreId',
@@ -147,7 +147,6 @@ class LazadaOrderInitBatchPopup extends localize(i18next)(LitElement) {
147
147
  return { emphasized }
148
148
  }
149
149
  },
150
- pagination: { infinite: true },
151
150
  columns: [
152
151
  { type: 'gutter', gutterName: 'sequence' },
153
152
  { type: 'gutter', gutterName: 'row-selector', multiple: true },
@@ -405,7 +404,7 @@ class LazadaOrderInitBatchPopup extends localize(i18next)(LitElement) {
405
404
  return itm
406
405
  })
407
406
  return {
408
- total: records.length || 0,
407
+ total: response.data.marketplaceOrdersForBatchInit.total || 0,
409
408
  records
410
409
  }
411
410
  }
@@ -60,7 +60,9 @@ class RequestROPopup extends LitElement {
60
60
  warehouseId: String,
61
61
  store: Object,
62
62
  marketplaceOrders: Object,
63
- config: Object
63
+ config: Object,
64
+ _searchFields: Array,
65
+ _shippingProviders: Array
64
66
  }
65
67
  }
66
68
 
@@ -73,6 +75,10 @@ class RequestROPopup extends LitElement {
73
75
  return this.shadowRoot.querySelector('data-grist')
74
76
  }
75
77
 
78
+ get searchForm() {
79
+ return this.shadowRoot.querySelector('search-form')
80
+ }
81
+
76
82
  render() {
77
83
  return html`
78
84
  <div class="container">
@@ -88,7 +94,9 @@ class RequestROPopup extends LitElement {
88
94
  )}
89
95
  </select>
90
96
  </form>
91
-
97
+
98
+ <search-form id="search-form" .fields=${this._searchFields} @submit=${e =>
99
+ this.dataGrist.fetch()}></search-form>
92
100
 
93
101
  <div class="grist">
94
102
  <data-grist
@@ -110,8 +118,44 @@ class RequestROPopup extends LitElement {
110
118
  async firstUpdated() {
111
119
  this.warehouses = await this.fetchWarehouses()
112
120
  this.warehouseId = this.warehouses[0]?.id || null
121
+ this._shippingProviders = await this._fetchShippingProviders()
113
122
  this.requestUpdate()
114
123
 
124
+ this._searchFields = [
125
+ {
126
+ label: i18next.t('field.shipping_provider'),
127
+ name: 'shippingProvider',
128
+ type: 'select',
129
+ props: {
130
+ searchOper: 'eq'
131
+ },
132
+ options: [
133
+ { value: '' },
134
+ ...this._shippingProviders.map(item => {
135
+ return {
136
+ name: item.shippingProvider,
137
+ value: item.shippingProvider
138
+ }
139
+ })
140
+ ]
141
+ },
142
+ {
143
+ label: i18next.t('field.item_count'),
144
+ name: 'itemCount',
145
+ type: 'select',
146
+ props: {
147
+ searchOper: 'gte'
148
+ },
149
+ options: [{ value: '' }, { name: 'Single Item', value: 1 }, { name: 'Multiple Item', value: 2 }]
150
+ },
151
+ {
152
+ label: i18next.t('field.sku'),
153
+ name: 'sku',
154
+ type: 'text',
155
+ props: { searchOper: 'i_like' }
156
+ }
157
+ ]
158
+
115
159
  this.config = {
116
160
  list: {
117
161
  fields: [
@@ -237,6 +281,27 @@ class RequestROPopup extends LitElement {
237
281
  }
238
282
  }
239
283
 
284
+ async _fetchShippingProviders() {
285
+ let statuses = this.getROCreatableStatus()
286
+
287
+ const response = await client.query({
288
+ query: gql`
289
+ query shippingProviders($storeId: String!, $statuses: [String]) {
290
+ shippingProviders(storeId: $storeId, statuses: $statuses) {
291
+ items {
292
+ shippingProvider
293
+ }
294
+ }
295
+ }
296
+ `,
297
+ variables: { storeId: this.store.id, statuses }
298
+ })
299
+
300
+ if (!response.errors) {
301
+ return response.data.shippingProviders.items
302
+ }
303
+ }
304
+
240
305
  async addReleaseOrder() {
241
306
  try {
242
307
  if (!this.warehouseId) {
@@ -282,7 +347,7 @@ class RequestROPopup extends LitElement {
282
347
  }
283
348
 
284
349
  async fetchHandler({ page, limit, sorters = [{ name: 'orderUpdatedAt', desc: true }] }) {
285
- let filters = []
350
+ let filters = [...this.searchForm.queryFilters]
286
351
 
287
352
  if (this.store) {
288
353
  filters.push(
@@ -443,7 +508,7 @@ class RequestROPopup extends LitElement {
443
508
  break
444
509
 
445
510
  case PLATFORM.WOOCOMMERCE.value:
446
- roCreatableStatus = ['pending', 'processing']
511
+ roCreatableStatus = ['processing']
447
512
  break
448
513
 
449
514
  case PLATFORM.MAGENTO.value:
@@ -198,7 +198,6 @@ class ShopeeOrderInitBatchPopup extends localize(i18next)(LitElement) {
198
198
  return { emphasized }
199
199
  }
200
200
  },
201
- pagination: { infinite: true },
202
201
  columns: [
203
202
  { type: 'gutter', gutterName: 'sequence' },
204
203
  { type: 'gutter', gutterName: 'row-selector', multiple: true },
@@ -527,7 +526,7 @@ class ShopeeOrderInitBatchPopup extends localize(i18next)(LitElement) {
527
526
  }
528
527
 
529
528
  return {
530
- total: records.length || 0,
529
+ total: response.data.marketplaceOrdersForBatchInit.total || 0,
531
530
  records
532
531
  }
533
532
  }
@@ -28,7 +28,8 @@ class OrderByStore extends localize(i18next)(PageView) {
28
28
  config: Object,
29
29
  excelConfig: Object,
30
30
  data: Object,
31
- enableRO: Boolean
31
+ enableRO: Boolean,
32
+ _shippingProviders: Array
32
33
  }
33
34
  }
34
35
 
@@ -145,6 +146,7 @@ class OrderByStore extends localize(i18next)(PageView) {
145
146
 
146
147
  async pageInitialized() {
147
148
  const _orderStatus = await getCodeByName('ORDER_STATUS')
149
+ this._shippingProviders = await this._fetchShippingProviders()
148
150
 
149
151
  await this.fetchFulfillmentCenters()
150
152
 
@@ -169,6 +171,38 @@ class OrderByStore extends localize(i18next)(PageView) {
169
171
  })
170
172
  ],
171
173
  props: { searchOper: 'eq' }
174
+ },
175
+ {
176
+ label: i18next.t('field.shipping_provider'),
177
+ name: 'shippingProvider',
178
+ type: 'select',
179
+ props: {
180
+ searchOper: 'eq'
181
+ },
182
+ options: [
183
+ { value: '' },
184
+ ...this._shippingProviders.map(item => {
185
+ return {
186
+ name: item.shippingProvider,
187
+ value: item.shippingProvider
188
+ }
189
+ })
190
+ ]
191
+ },
192
+ {
193
+ label: i18next.t('field.item_count'),
194
+ name: 'itemCount',
195
+ type: 'select',
196
+ props: {
197
+ searchOper: 'gte'
198
+ },
199
+ options: [{ value: '' }, { name: 'Single Item', value: 1 }, { name: 'Multiple Item', value: 2 }]
200
+ },
201
+ {
202
+ label: i18next.t('field.sku'),
203
+ name: 'sku',
204
+ type: 'text',
205
+ props: { searchOper: 'i_like' }
172
206
  }
173
207
  ]
174
208
 
@@ -308,6 +342,21 @@ class OrderByStore extends localize(i18next)(PageView) {
308
342
  if ('resourceId' in changes) {
309
343
  if (lifecycle.resourceId) {
310
344
  this.store = await this.fetchStore(lifecycle.resourceId)
345
+ this._shippingProviders = await this._fetchShippingProviders()
346
+
347
+ this._searchFields = this._searchFields.map(searchField => {
348
+ if (searchField.name === 'shippingProvider')
349
+ searchField.options = [
350
+ { value: '' },
351
+ ...this._shippingProviders.map(item => {
352
+ return {
353
+ name: item.shippingProvider,
354
+ value: item.shippingProvider
355
+ }
356
+ })
357
+ ]
358
+ return searchField
359
+ })
311
360
  } else {
312
361
  this.store = null
313
362
  }
@@ -486,9 +535,9 @@ class OrderByStore extends localize(i18next)(PageView) {
486
535
  if (marketplaceOrderShipping?.trackingNo) {
487
536
  const trackingNos = JSON.parse(marketplaceOrderShipping.trackingNo)
488
537
  newTrackingNo = trackingNos.map(item => item.tracking_code)
538
+ let uniqueTrackingNos = [...new Set(newTrackingNo)]
539
+ item = uniqueTrackingNos.join(', ')
489
540
  }
490
- let uniqueTrackingNos = [...new Set(newTrackingNo)]
491
- item = uniqueTrackingNos.join(', ')
492
541
  } else {
493
542
  item = marketplaceOrderShipping.trackingNo
494
543
  }
@@ -845,6 +894,25 @@ class OrderByStore extends localize(i18next)(PageView) {
845
894
  }
846
895
  }
847
896
 
897
+ async _fetchShippingProviders() {
898
+ const response = await client.query({
899
+ query: gql`
900
+ query shippingProviders($storeId: String!) {
901
+ shippingProviders(storeId: $storeId) {
902
+ items {
903
+ shippingProvider
904
+ }
905
+ }
906
+ }
907
+ `,
908
+ variables: { storeId: this.lifecycle.resourceId }
909
+ })
910
+
911
+ if (!response.errors) {
912
+ return response.data.shippingProviders.items
913
+ }
914
+ }
915
+
848
916
  _showToast({ type, message }) {
849
917
  document.dispatchEvent(
850
918
  new CustomEvent('notify', {
@@ -0,0 +1,144 @@
1
+ import { css, html } from 'lit-element'
2
+ import { connect } from 'pwa-helpers/connect-mixin.js'
3
+
4
+ import { PageView, store } from '@things-factory/shell'
5
+
6
+ class SalesByPlatformHome extends connect(store)(PageView) {
7
+ static get styles() {
8
+ return [
9
+ css`
10
+ :host {
11
+ display: block;
12
+ background-color: var(--main-section-background-color);
13
+ padding: var(--padding-wide);
14
+ overflow: auto;
15
+ --bizplace-cards-size: 150px;
16
+ }
17
+ h2 {
18
+ margin: var(--title-margin);
19
+ font: var(--title-font);
20
+ color: var(--title-text-color);
21
+ }
22
+ input {
23
+ display: block;
24
+ }
25
+ [page-description] {
26
+ margin: var(--page-description-margin);
27
+ font: var(--page-description-font);
28
+ color: var(--page-description-color);
29
+ }
30
+ [button-primary] {
31
+ background-color: var(--button-primary-background-color);
32
+ border: var(--button-border);
33
+ border-radius: var(--button-border-radius);
34
+ padding: var(--button-padding);
35
+ color: var(--button-primary-color);
36
+ font: var(--button-primary-font);
37
+ text-transform: var(--button-text-transform);
38
+ text-decoration: none;
39
+ }
40
+ [button-primary]:hover {
41
+ background-color: var(--button-primary-active-background-color);
42
+ box-shadow: var(--button-active-box-shadow);
43
+ }
44
+ img {
45
+ max-width: 45%;
46
+ float: right;
47
+ }
48
+ ul {
49
+ margin: 0 0 var(--margin-wide) 0;
50
+ padding: 0;
51
+ overflow: hidden;
52
+ list-style: none;
53
+ }
54
+ li {
55
+ display: block;
56
+ float: left;
57
+ background-color: var(--theme-white-color);
58
+ border-radius: var(--border-radius);
59
+ border: 1px solid var(--theme-white-color);
60
+ box-shadow: var(--box-shadow);
61
+ margin: var(--margin-narrow) var(--margin-default) var(--margin-default) 0;
62
+ padding: var(--padding-default) var(--padding-default) var(--padding-narrow) var(--padding-default);
63
+ text-align: center;
64
+ }
65
+ li:hover {
66
+ border: 1px solid var(--primary-color);
67
+ }
68
+ * {
69
+ display: block;
70
+ }
71
+ a {
72
+ width: var(--bizplace-cards-size);
73
+ cursor: pointer;
74
+ text-decoration: none;
75
+ font-size: var(--fontsize-small);
76
+ color: var(--secondary-color);
77
+ }
78
+ mwc-icon {
79
+ color: var(--primary-color);
80
+ }
81
+ strong {
82
+ max-width: 100%;
83
+
84
+ font-size: 1.2em;
85
+ color: var(--secondary-text-color);
86
+ }
87
+ a,
88
+ strong @media screen and (max-width: 600px) {
89
+ [field] {
90
+ grid-column: span 2;
91
+ }
92
+ img {
93
+ display: none;
94
+ }
95
+ }
96
+ `
97
+ ]
98
+ }
99
+
100
+ static get properties() {
101
+ return {
102
+ _platforms: Array
103
+ }
104
+ }
105
+
106
+ get context() {
107
+ return {
108
+ title: `ecommerce products`
109
+ }
110
+ }
111
+
112
+ render() {
113
+ const platforms = this._platforms || []
114
+
115
+ return html`
116
+ <h2>Sales Report</h2>
117
+ <p page-description>View your day to day sales report.</p>
118
+
119
+ <img src="/assets/images/image-products.png" alt="products home graphic image" />
120
+
121
+ <ul marketplaceStore>
122
+ ${platforms.map(
123
+ platform => html`
124
+ <li>
125
+ <a href="${platform}-sales-report">
126
+ <mwc-icon>${'widgets'}</mwc-icon>
127
+ <strong>${platform}</strong>
128
+ </a>
129
+ </li>
130
+ `
131
+ )}
132
+ </ul>
133
+ `
134
+ }
135
+
136
+ stateChanged(state) {
137
+ this._platforms = state.mms?.stores
138
+ .map(store => store.platform)
139
+ .filter((v, i, a) => a.indexOf(v) === i)
140
+ .filter(v => ['lazada', 'shopee'].indexOf(v) !== -1)
141
+ }
142
+ }
143
+
144
+ window.customElements.define('mms-report-sales-by-platform-home', SalesByPlatformHome)
@@ -0,0 +1,3 @@
1
+ export * from './home'
2
+ export * from './lazada-sales-report'
3
+ export * from './shopee-sales-report'