@things-factory/integration-sellercraft 8.0.0-beta.9 → 8.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. package/dist-server/tsconfig.tsbuildinfo +1 -1
  2. package/package.json +14 -14
  3. package/server/constants/index.ts +2 -0
  4. package/server/constants/order-status-mapping.ts +28 -0
  5. package/server/constants/platform.ts +6 -0
  6. package/server/controllers/index.ts +5 -0
  7. package/server/controllers/sellercraft/apis/add-inbound-order.ts +50 -0
  8. package/server/controllers/sellercraft/apis/echo.ts +14 -0
  9. package/server/controllers/sellercraft/apis/fetch-order-document.ts +18 -0
  10. package/server/controllers/sellercraft/apis/index.ts +8 -0
  11. package/server/controllers/sellercraft/apis/initiate-order-document.ts +17 -0
  12. package/server/controllers/sellercraft/apis/initiate-order-shipment.ts +29 -0
  13. package/server/controllers/sellercraft/apis/pack-marketplace-order.ts +35 -0
  14. package/server/controllers/sellercraft/apis/update-marketplace-order.ts +14 -0
  15. package/server/controllers/sellercraft/apis/update-product.ts +21 -0
  16. package/server/controllers/sellercraft/index.ts +7 -0
  17. package/server/controllers/sellercraft/platform-action.ts +39 -0
  18. package/server/controllers/sellercraft/sellercraft.ts +109 -0
  19. package/server/controllers/sellercraft-api/decorators.ts +52 -0
  20. package/server/controllers/sellercraft-api/index.ts +51 -0
  21. package/server/controllers/sellercraft-api/types.ts +0 -0
  22. package/server/controllers/sellercraft-channel-integration/apis/echo.ts +14 -0
  23. package/server/controllers/sellercraft-channel-integration/apis/index.ts +6 -0
  24. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-categories.ts +37 -0
  25. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-category-attributes.ts +65 -0
  26. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-order-package.ts +62 -0
  27. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-order.ts +92 -0
  28. package/server/controllers/sellercraft-channel-integration/apis/ingest-channel-product.ts +97 -0
  29. package/server/controllers/sellercraft-channel-integration/index.ts +7 -0
  30. package/server/controllers/sellercraft-channel-integration/platform-action.ts +39 -0
  31. package/server/controllers/sellercraft-channel-integration/sellercraft-channel-integration.ts +115 -0
  32. package/server/controllers/sellercraft-channel-integration-api/decorators.ts +45 -0
  33. package/server/controllers/sellercraft-channel-integration-api/index.ts +45 -0
  34. package/server/controllers/sellercraft-channel-integration-api/types.ts +0 -0
  35. package/server/index.ts +7 -0
  36. package/server/middlewares/index.ts +3 -0
  37. package/server/migrations/index.ts +9 -0
  38. package/server/routers/sellercraft-router.ts +326 -0
  39. package/server/routes.ts +32 -0
  40. package/server/service/index.ts +23 -0
  41. package/server/service/marketplace-channel/index.ts +6 -0
  42. package/server/service/marketplace-channel/marketplace-channel-order-mutation.ts +456 -0
  43. package/server/service/marketplace-channel/marketplace-channel-product-mutation.ts +282 -0
  44. package/server/service/marketplace-channel/marketplace-channel.ts +76 -0
  45. package/server/service/sellercraft/index.ts +6 -0
  46. package/server/service/sellercraft/sellercraft-mutation.ts +126 -0
  47. package/server/service/sellercraft/sellercraft-query.ts +43 -0
  48. package/server/service/sellercraft/sellercraft-type.ts +54 -0
  49. package/server/service/sellercraft/sellercraft.ts +96 -0
  50. package/server/utils/tokencraft-util.ts +60 -0
  51. package/tsconfig.json +9 -0
@@ -0,0 +1,456 @@
1
+ import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'
2
+
3
+ import { StoreAPI } from '@things-factory/integration-marketplace'
4
+ import { getRepository } from '@things-factory/shell'
5
+
6
+ import { SHIPPING_TYPE } from '../../constants'
7
+ import { SellercraftChannelIntegrationAPI } from '../../controllers/sellercraft-channel-integration-api'
8
+ import { getShops } from '../../utils/tokencraft-util'
9
+ import { MarketplaceChannel } from './marketplace-channel'
10
+
11
+ @Resolver()
12
+ export class MarketplaceChannelOrderMutation {
13
+ @Mutation(returns => Boolean)
14
+ async syncAllMarketplaceChannelOrders(
15
+ @Ctx() context: ResolverContext,
16
+ @Arg('fromCreatedDate', { nullable: true }) fromCreatedDate?: string,
17
+ @Arg('toCreatedDate', { nullable: true }) toCreatedDate?: string,
18
+ @Arg('fromUpdatedDate', { nullable: true }) fromUpdatedDate?: string,
19
+ @Arg('toUpdatedDate', { nullable: true }) toUpdatedDate?: string,
20
+ @Arg('channelId', { nullable: true }) channelId?: string,
21
+ @Arg('shopId', { nullable: true }) shopId?: string,
22
+ @Arg('airflow', { nullable: true }) airflow?: boolean
23
+ ): Promise<boolean> {
24
+ let channels: MarketplaceChannel[] = await getRepository(MarketplaceChannel).find({ where: { isActive: true } })
25
+ let errors: any = []
26
+
27
+ if (channelId) {
28
+ channels = channels.filter(channel => channel.channelId == channelId)
29
+ }
30
+
31
+ for (var i = 0; i < channels.length; i++) {
32
+ try {
33
+ const channel: MarketplaceChannel = channels[i]
34
+ let shops: any = await getShops(channel.channelId)
35
+
36
+ if (shopId) {
37
+ shops = shops.filter(shop => shop.channel_shop_id == shopId)
38
+ }
39
+
40
+ for (var j = 0; j < shops.length; j++) {
41
+ try {
42
+ var store = {
43
+ accessKey: shops[j]?.credential?.consumer_key || '',
44
+ accessSecret: shops[j]?.credential?.consumer_secret || '',
45
+ storeURL: shops[j]?.credential?.store_url || '',
46
+ platform: channel.name,
47
+ accessToken: shops[j]?.credential?.access_token, // Magento+, Tiktok
48
+ channelShopId: shops[j]?.channel_shop_id,
49
+ storeId: shops[j]?.credential?.store_url || ''
50
+ }
51
+
52
+ // let countryCode = shops[j].country_code
53
+ // let channelCode = shops[j].org_prefix
54
+ let organisationId = shops[j].account_id
55
+ let channelShopId = shops[j].channel_shop_id
56
+
57
+ let orderResult = []
58
+ let page: number = store.platform == 'magento' ? 1 : 0
59
+ let hasMorePage: boolean = true
60
+ let lastOrderId: string
61
+ let cursor: string
62
+ var limit: number = 20
63
+
64
+ while (hasMorePage) {
65
+ const {
66
+ results: marketplaceOrders,
67
+ more,
68
+ nextCursor
69
+ } = await StoreAPI.getStoreOrders(store, {
70
+ fromCreatedDate,
71
+ toCreatedDate,
72
+ fromUpdatedDate,
73
+ toUpdatedDate,
74
+ pagination: { page, limit },
75
+ lastOrderId,
76
+ nextCursor: cursor
77
+ })
78
+
79
+ var sellercraftStore = { ...store, platform: 'sellercraftChannelIntegration' }
80
+
81
+ let mappedOrderResult = marketplaceOrders.map(order => {
82
+ let id = store.platform == 'magento' || store.platform == 'shopify' ? order.name : order.orderNo
83
+ let {
84
+ firstName: custFirstName,
85
+ lastName: custLastName,
86
+ orderCreatedAt: createdAt,
87
+ orderUpdatedAt: updatedAt,
88
+ status,
89
+ sellercraftStatus,
90
+ isSOF,
91
+ orderLineList,
92
+ sellercraftDisplayOrderNo
93
+ } = order
94
+
95
+ let {
96
+ first_name: billFirstName,
97
+ last_name: billLastName,
98
+ address_1: billAddress1,
99
+ address_2: billAddress2,
100
+ address_3: billAddress3,
101
+ address_4: billAddress4,
102
+ address_5: billAddress5,
103
+ city: billCity,
104
+ postcode: billPostalCode,
105
+ country: billCountry,
106
+ phone: billPhone1,
107
+ phone_2: billPhone2
108
+ } = order?.billing
109
+
110
+ let {
111
+ first_name: shipFirstName,
112
+ last_name: shipLastName,
113
+ address_1: shipAddress1,
114
+ address_2: shipAddress2,
115
+ address_3: shipAddress3,
116
+ address_4: shipAddress4,
117
+ address_5: shipAddress5,
118
+ city: shipCity,
119
+ postcode: shipPostalCode,
120
+ country: shipCountry,
121
+ phone: shipPhone1,
122
+ phone_2: shipPhone2
123
+ } = order.shipping
124
+
125
+ let orderPackage = order?.orderPackage || {}
126
+
127
+ let orderItems = order.orderItems.map(item => {
128
+ let {
129
+ name: id,
130
+ variationId: variationId,
131
+ slaExpiresAt,
132
+ total,
133
+ totalTax,
134
+ subtotal,
135
+ subtotalTax,
136
+ qty
137
+ } = item
138
+
139
+ return {
140
+ id,
141
+ variationId,
142
+ currency: order.orderShipping.collectionCurrency,
143
+ createdAt: order.orderCreatedAt,
144
+ updatedAt: order.orderUpdatedAt,
145
+ charges: [
146
+ {
147
+ name: 'CHARGES_MARKETING',
148
+ grossAmount: 0,
149
+ nettAmount: 0
150
+ },
151
+ {
152
+ name: 'CLAIMS_DAMAGE',
153
+ grossAmount: 0,
154
+ nettAmount: 0
155
+ },
156
+ {
157
+ name: 'CLAIMS_LOST',
158
+ grossAmount: 0,
159
+ nettAmount: 0
160
+ },
161
+ {
162
+ name: 'COMMISSION_PLATFORM',
163
+ grossAmount: 0,
164
+ nettAmount: 0
165
+ },
166
+ {
167
+ name: 'DEPOSIT_PRESALE',
168
+ grossAmount: 0,
169
+ nettAmount: 0
170
+ },
171
+ {
172
+ name: 'FEE_MISCELLANEOUS',
173
+ grossAmount: 0,
174
+ nettAmount: 0
175
+ },
176
+ {
177
+ name: 'FEE_TRANSACTION',
178
+ grossAmount: 0,
179
+ nettAmount: 0
180
+ },
181
+ {
182
+ name: 'PRICE_NORMAL_SELLING',
183
+ grossAmount: total,
184
+ nettAmount: subtotal
185
+ },
186
+ {
187
+ name: 'PRICE_RECOMMENDED_RETAIL',
188
+ grossAmount: 0,
189
+ nettAmount: 0
190
+ },
191
+ {
192
+ name: 'PROMOTIONS_CUSTOMER_RECEIVED',
193
+ grossAmount: 0,
194
+ nettAmount: 0
195
+ },
196
+ {
197
+ name: 'PROMOTIONS_REBATE_PLATFORM',
198
+ grossAmount: 0,
199
+ nettAmount: 0
200
+ },
201
+ {
202
+ name: 'PROMOTIONS_REBATE_SELLER',
203
+ grossAmount: 0,
204
+ nettAmount: 0
205
+ },
206
+ {
207
+ name: 'REVERSAL_CHARGES_MARKETING',
208
+ grossAmount: 0,
209
+ nettAmount: 0
210
+ },
211
+ {
212
+ name: 'REVERSAL_COMMISSION',
213
+ grossAmount: 0,
214
+ nettAmount: 0
215
+ },
216
+ {
217
+ name: 'REVERSAL_FEE_MISCELLANEOUS',
218
+ grossAmount: 0,
219
+ nettAmount: 0
220
+ },
221
+ {
222
+ name: 'REVERSAL_PROMOTIONS_CUSTOMER_RECEIVED',
223
+ grossAmount: 0,
224
+ nettAmount: 0
225
+ },
226
+ {
227
+ name: 'REVERSAL_SELLER_RETURN_REFUND_AMOUNT',
228
+ grossAmount: 0,
229
+ nettAmount: 0
230
+ },
231
+ {
232
+ name: 'REVERSAL_SHIPPING_CUSTOMER_PAID',
233
+ grossAmount: 0,
234
+ nettAmount: 0
235
+ },
236
+ {
237
+ name: 'REVERSAL_SHIPPING_REBATE_PLATFORM',
238
+ grossAmount: 0,
239
+ nettAmount: 0
240
+ },
241
+ {
242
+ name: 'REVERSAL_SHIPPING_SELLER_PAID',
243
+ grossAmount: 0,
244
+ nettAmount: 0
245
+ },
246
+ {
247
+ name: 'SHIPPING_COST_TOTAL',
248
+ grossAmount: 0,
249
+ nettAmount: 0
250
+ },
251
+ {
252
+ name: 'SHIPPING_CUSTOMER_PAID',
253
+ grossAmount: 0,
254
+ nettAmount: 0
255
+ },
256
+ {
257
+ name: 'SHIPPING_REBATE_PLATFORM',
258
+ grossAmount: 0,
259
+ nettAmount: 0
260
+ },
261
+ {
262
+ name: 'SHIPPING_SELLER_PAID',
263
+ grossAmount: 0,
264
+ nettAmount: 0
265
+ },
266
+ {
267
+ name: 'TAXES',
268
+ grossAmount: totalTax,
269
+ nettAmount: subtotalTax
270
+ },
271
+ {
272
+ name: 'VOUCHERS_CUSTOMER_RECEIVED',
273
+ grossAmount: 0,
274
+ nettAmount: 0
275
+ },
276
+ {
277
+ name: 'VOUCHERS_REBATE_PLATFORM',
278
+ grossAmount: 0,
279
+ nettAmount: 0
280
+ },
281
+ {
282
+ name: 'VOUCHERS_REBATE_SELLER',
283
+ grossAmount: 0,
284
+ nettAmount: 0
285
+ }
286
+ ],
287
+ slaExpiresAt,
288
+ qty
289
+ }
290
+ })
291
+
292
+ let mappedOrderItems = []
293
+ orderItems.map(oi => {
294
+ for (let i = 0; i < oi.qty; i++) {
295
+ let orderLine
296
+ if (orderLineList) {
297
+ orderLine = orderLineList?.find(ol => ol.sku_id == oi.variationId) || null
298
+ orderLineList = orderLineList.filter(ol => ol.order_line_id != orderLine.order_line_id)
299
+ }
300
+ mappedOrderItems.push({
301
+ ...oi,
302
+ id: orderLine ? orderLine.order_line_id : `${oi.id}-${i + 1}`
303
+ })
304
+ }
305
+ })
306
+
307
+ return {
308
+ custFirstName,
309
+ custLastName,
310
+ createdAt,
311
+ updatedAt,
312
+ id,
313
+ sellercraftDisplayOrderNo,
314
+ billFirstName,
315
+ billLastName,
316
+ billAddress1: billAddress1?.toString() || shipAddress1?.toString(),
317
+ billAddress2: billAddress2 || shipAddress2,
318
+ billAddress3: billAddress3 || shipAddress3,
319
+ billAddress4: billAddress4 || shipAddress4,
320
+ billAddress5: billAddress5 || shipAddress5,
321
+ billCity: billCity || shipCity,
322
+ billPostalCode: billPostalCode || shipPostalCode,
323
+ billCountry: billCountry || shipCountry,
324
+ billPhone1: billPhone1 || shipPhone1,
325
+ billPhone2: billPhone2 || shipPhone2,
326
+ shipFirstName,
327
+ shipLastName,
328
+ shipAddress1: shipAddress1?.toString(),
329
+ shipAddress2,
330
+ shipAddress3,
331
+ shipAddress4,
332
+ shipAddress5,
333
+ shipCity,
334
+ shipPostalCode,
335
+ shipCountry,
336
+ shipPhone1,
337
+ shipPhone2,
338
+ mappedOrderItems,
339
+ channelShopId,
340
+ organisationId,
341
+ status: sellercraftStatus || status,
342
+ isSOF: isSOF ? isSOF : false,
343
+ orderPackage,
344
+ charges: getOrderCharges(mappedOrderItems)
345
+ }
346
+ })
347
+
348
+ if (mappedOrderResult.length > 0) {
349
+ while (mappedOrderResult.length > 0) {
350
+ let spliceResult = mappedOrderResult.splice(
351
+ 0,
352
+ mappedOrderResult.length >= 20 ? 20 : mappedOrderResult.length
353
+ )
354
+
355
+ try {
356
+ await SellercraftChannelIntegrationAPI.ingestChannelOrder(sellercraftStore, {
357
+ orders: spliceResult
358
+ })
359
+ } catch (e) {
360
+ errors.push({
361
+ name: 'Order Ingestion Error',
362
+ msg: JSON.stringify(e) || {}
363
+ })
364
+ }
365
+
366
+ await Promise.all(
367
+ spliceResult.map(async result => {
368
+ if (!result?.isSOF && result?.orderPackage?.packageId) {
369
+ let orderPackage: any = result.orderPackage
370
+ let newOrderPackage: any = {
371
+ channelShopId,
372
+ nativeOrderId: result.id,
373
+ nativePackageId: orderPackage.packageId,
374
+ shippingTrackingCode: orderPackage.trackingNumber,
375
+ shippingTypeValue: orderPackage?.shippingType
376
+ ? orderPackage.shippingType
377
+ : SHIPPING_TYPE.DROP_SHIPPING,
378
+ warehouseCode: SHIPPING_TYPE.DROP_SHIPPING,
379
+ shipper: {
380
+ name: orderPackage.shippingProvider,
381
+ isCodSupported: orderPackage?.isCodSupport ? orderPackage.isCodSupport : false
382
+ },
383
+ documents: orderPackage?.orderDocument || [],
384
+ shipperLastMile: {
385
+ name: orderPackage.shippingProvider,
386
+ isCodSupported: orderPackage?.isCodSupport ? orderPackage.isCodSupport : false
387
+ },
388
+ orderItemIds: orderPackage?.orderListIdList
389
+ ? orderPackage.orderListIdList
390
+ : result.mappedOrderItems.map(orderItem => orderItem.id)
391
+ }
392
+ try {
393
+ await SellercraftChannelIntegrationAPI.ingestChannelOrderPackage(
394
+ sellercraftStore,
395
+ newOrderPackage
396
+ )
397
+ } catch (e) {
398
+ errors.push({
399
+ name: 'Order Package Ingestion Error',
400
+ msg: JSON.stringify(e) || {}
401
+ })
402
+ }
403
+ }
404
+ })
405
+ )
406
+ }
407
+ }
408
+
409
+ if (more) page++
410
+ hasMorePage = more
411
+ cursor = nextCursor
412
+ }
413
+ } catch (e) {
414
+ errors.push({
415
+ name: 'Order Processing / Mapping Error',
416
+ msg: JSON.stringify(e) || {}
417
+ })
418
+ }
419
+ }
420
+ } catch (e) {
421
+ errors.push({
422
+ name: 'Store Error',
423
+ msg: JSON.stringify(e) || {}
424
+ })
425
+ }
426
+ }
427
+ if (errors.length > 1 && airflow) {
428
+ throw errors
429
+ }
430
+ return true
431
+ }
432
+ }
433
+
434
+ function getOrderCharges(mappedOrderItems) {
435
+ let chargesList = []
436
+
437
+ for (let i = 0; i < mappedOrderItems.length; i++) {
438
+ for (let j = 0; j < mappedOrderItems[i].charges.length; j++) {
439
+ let charge = mappedOrderItems[i].charges[j]
440
+ let foundCharge = chargesList.find(cl => cl.name == charge.name)
441
+ if (foundCharge) {
442
+ foundCharge.grossAmount = parseFloat(foundCharge.grossAmount) + parseFloat(charge.grossAmount)
443
+ foundCharge.nettAmount = parseFloat(foundCharge.nettAmount) + parseFloat(charge.nettAmount)
444
+ chargesList = chargesList.filter(cl => cl.name != charge.name)
445
+ } else {
446
+ foundCharge = {
447
+ name: charge.name,
448
+ grossAmount: charge.grossAmount,
449
+ nettAmount: charge.nettAmount
450
+ }
451
+ }
452
+ chargesList.push(foundCharge)
453
+ }
454
+ }
455
+ return chargesList
456
+ }