@faststore/api 3.44.0 → 3.45.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 (110) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/__generated__/schema.d.ts +742 -0
  3. package/dist/cjs/src/__generated__/schema.js +1 -0
  4. package/dist/cjs/src/__generated__/schema.js.map +1 -1
  5. package/dist/cjs/src/index.d.ts +5 -1
  6. package/dist/cjs/src/platforms/errors.d.ts +5 -1
  7. package/dist/cjs/src/platforms/errors.js +9 -1
  8. package/dist/cjs/src/platforms/errors.js.map +1 -1
  9. package/dist/cjs/src/platforms/vtex/clients/commerce/Contract.d.ts +7 -0
  10. package/dist/cjs/src/platforms/vtex/clients/commerce/Contract.js +3 -0
  11. package/dist/cjs/src/platforms/vtex/clients/commerce/Contract.js.map +1 -0
  12. package/dist/cjs/src/platforms/vtex/clients/commerce/index.d.ts +39 -1
  13. package/dist/cjs/src/platforms/vtex/clients/commerce/index.js +117 -4
  14. package/dist/cjs/src/platforms/vtex/clients/commerce/index.js.map +1 -1
  15. package/dist/cjs/src/platforms/vtex/clients/commerce/types/Unit.d.ts +18 -0
  16. package/dist/cjs/src/platforms/vtex/clients/commerce/types/Unit.js +3 -0
  17. package/dist/cjs/src/platforms/vtex/clients/commerce/types/Unit.js.map +1 -0
  18. package/dist/cjs/src/platforms/vtex/clients/commerce/types/VtexId.d.ts +11 -0
  19. package/dist/cjs/src/platforms/vtex/clients/commerce/types/VtexId.js +3 -0
  20. package/dist/cjs/src/platforms/vtex/clients/commerce/types/VtexId.js.map +1 -0
  21. package/dist/cjs/src/platforms/vtex/clients/index.d.ts +35 -0
  22. package/dist/cjs/src/platforms/vtex/index.d.ts +6 -1
  23. package/dist/cjs/src/platforms/vtex/index.js +3 -0
  24. package/dist/cjs/src/platforms/vtex/index.js.map +1 -1
  25. package/dist/cjs/src/platforms/vtex/resolvers/cancelOrder.d.ts +3 -0
  26. package/dist/cjs/src/platforms/vtex/resolvers/cancelOrder.js +13 -0
  27. package/dist/cjs/src/platforms/vtex/resolvers/cancelOrder.js.map +1 -0
  28. package/dist/cjs/src/platforms/vtex/resolvers/mutation.d.ts +2 -1
  29. package/dist/cjs/src/platforms/vtex/resolvers/mutation.js +2 -0
  30. package/dist/cjs/src/platforms/vtex/resolvers/mutation.js.map +1 -1
  31. package/dist/cjs/src/platforms/vtex/resolvers/query.d.ts +3 -1
  32. package/dist/cjs/src/platforms/vtex/resolvers/query.js +28 -0
  33. package/dist/cjs/src/platforms/vtex/resolvers/query.js.map +1 -1
  34. package/dist/cjs/src/platforms/vtex/resolvers/userOrder.d.ts +7 -0
  35. package/dist/cjs/src/platforms/vtex/resolvers/userOrder.js +161 -0
  36. package/dist/cjs/src/platforms/vtex/resolvers/userOrder.js.map +1 -0
  37. package/dist/cjs/src/platforms/vtex/resolvers/validateSession.d.ts +1 -1
  38. package/dist/cjs/src/platforms/vtex/resolvers/validateSession.js +43 -7
  39. package/dist/cjs/src/platforms/vtex/resolvers/validateSession.js.map +1 -1
  40. package/dist/cjs/src/platforms/vtex/utils/cookies.d.ts +2 -0
  41. package/dist/cjs/src/platforms/vtex/utils/cookies.js +23 -1
  42. package/dist/cjs/src/platforms/vtex/utils/cookies.js.map +1 -1
  43. package/dist/cjs/src/typeDefs/mutation.graphql +4 -0
  44. package/dist/cjs/src/typeDefs/query.graphql +46 -0
  45. package/dist/cjs/src/typeDefs/session.graphql +16 -0
  46. package/dist/cjs/src/typeDefs/userOrder.graphql +714 -0
  47. package/dist/esm/package.json +1 -1
  48. package/dist/esm/src/__generated__/schema.d.ts +742 -0
  49. package/dist/esm/src/__generated__/schema.js +1 -0
  50. package/dist/esm/src/__generated__/schema.js.map +1 -1
  51. package/dist/esm/src/index.d.ts +5 -1
  52. package/dist/esm/src/platforms/errors.d.ts +5 -1
  53. package/dist/esm/src/platforms/errors.js +6 -0
  54. package/dist/esm/src/platforms/errors.js.map +1 -1
  55. package/dist/esm/src/platforms/vtex/clients/commerce/Contract.d.ts +7 -0
  56. package/dist/esm/src/platforms/vtex/clients/commerce/Contract.js +2 -0
  57. package/dist/esm/src/platforms/vtex/clients/commerce/Contract.js.map +1 -0
  58. package/dist/esm/src/platforms/vtex/clients/commerce/index.d.ts +39 -1
  59. package/dist/esm/src/platforms/vtex/clients/commerce/index.js +118 -5
  60. package/dist/esm/src/platforms/vtex/clients/commerce/index.js.map +1 -1
  61. package/dist/esm/src/platforms/vtex/clients/commerce/types/Unit.d.ts +18 -0
  62. package/dist/esm/src/platforms/vtex/clients/commerce/types/Unit.js +2 -0
  63. package/dist/esm/src/platforms/vtex/clients/commerce/types/Unit.js.map +1 -0
  64. package/dist/esm/src/platforms/vtex/clients/commerce/types/VtexId.d.ts +11 -0
  65. package/dist/esm/src/platforms/vtex/clients/commerce/types/VtexId.js +2 -0
  66. package/dist/esm/src/platforms/vtex/clients/commerce/types/VtexId.js.map +1 -0
  67. package/dist/esm/src/platforms/vtex/clients/index.d.ts +35 -0
  68. package/dist/esm/src/platforms/vtex/index.d.ts +6 -1
  69. package/dist/esm/src/platforms/vtex/index.js +3 -0
  70. package/dist/esm/src/platforms/vtex/index.js.map +1 -1
  71. package/dist/esm/src/platforms/vtex/resolvers/cancelOrder.d.ts +3 -0
  72. package/dist/esm/src/platforms/vtex/resolvers/cancelOrder.js +9 -0
  73. package/dist/esm/src/platforms/vtex/resolvers/cancelOrder.js.map +1 -0
  74. package/dist/esm/src/platforms/vtex/resolvers/mutation.d.ts +2 -1
  75. package/dist/esm/src/platforms/vtex/resolvers/mutation.js +2 -0
  76. package/dist/esm/src/platforms/vtex/resolvers/mutation.js.map +1 -1
  77. package/dist/esm/src/platforms/vtex/resolvers/query.d.ts +3 -1
  78. package/dist/esm/src/platforms/vtex/resolvers/query.js +29 -1
  79. package/dist/esm/src/platforms/vtex/resolvers/query.js.map +1 -1
  80. package/dist/esm/src/platforms/vtex/resolvers/userOrder.d.ts +7 -0
  81. package/dist/esm/src/platforms/vtex/resolvers/userOrder.js +158 -0
  82. package/dist/esm/src/platforms/vtex/resolvers/userOrder.js.map +1 -0
  83. package/dist/esm/src/platforms/vtex/resolvers/validateSession.d.ts +1 -1
  84. package/dist/esm/src/platforms/vtex/resolvers/validateSession.js +43 -7
  85. package/dist/esm/src/platforms/vtex/resolvers/validateSession.js.map +1 -1
  86. package/dist/esm/src/platforms/vtex/utils/cookies.d.ts +2 -0
  87. package/dist/esm/src/platforms/vtex/utils/cookies.js +20 -0
  88. package/dist/esm/src/platforms/vtex/utils/cookies.js.map +1 -1
  89. package/dist/esm/src/typeDefs/mutation.graphql +4 -0
  90. package/dist/esm/src/typeDefs/query.graphql +46 -0
  91. package/dist/esm/src/typeDefs/session.graphql +16 -0
  92. package/dist/esm/src/typeDefs/userOrder.graphql +714 -0
  93. package/package.json +2 -2
  94. package/src/__generated__/schema.ts +816 -0
  95. package/src/platforms/errors.ts +14 -1
  96. package/src/platforms/vtex/clients/commerce/Contract.ts +7 -0
  97. package/src/platforms/vtex/clients/commerce/index.ts +218 -8
  98. package/src/platforms/vtex/clients/commerce/types/Unit.ts +19 -0
  99. package/src/platforms/vtex/clients/commerce/types/VtexId.ts +11 -0
  100. package/src/platforms/vtex/index.ts +4 -0
  101. package/src/platforms/vtex/resolvers/cancelOrder.ts +20 -0
  102. package/src/platforms/vtex/resolvers/mutation.ts +2 -0
  103. package/src/platforms/vtex/resolvers/query.ts +57 -2
  104. package/src/platforms/vtex/resolvers/userOrder.ts +205 -0
  105. package/src/platforms/vtex/resolvers/validateSession.ts +53 -7
  106. package/src/platforms/vtex/utils/cookies.ts +25 -0
  107. package/src/typeDefs/mutation.graphql +4 -0
  108. package/src/typeDefs/query.graphql +46 -0
  109. package/src/typeDefs/session.graphql +16 -0
  110. package/src/typeDefs/userOrder.graphql +714 -0
@@ -1,4 +1,8 @@
1
- type ErrorType = 'BadRequestError' | 'NotFoundError' | 'RedirectError'
1
+ type ErrorType =
2
+ | 'BadRequestError'
3
+ | 'NotFoundError'
4
+ | 'RedirectError'
5
+ | 'ForbiddenError'
2
6
 
3
7
  interface Extension {
4
8
  type: ErrorType
@@ -27,6 +31,12 @@ export class NotFoundError extends FastStoreError {
27
31
  }
28
32
  }
29
33
 
34
+ export class ForbiddenError extends FastStoreError {
35
+ constructor(message?: string) {
36
+ super({ status: 403, type: 'ForbiddenError' }, message)
37
+ }
38
+ }
39
+
30
40
  export const isFastStoreError = (error: any): error is FastStoreError =>
31
41
  error?.name === 'FastStoreError'
32
42
 
@@ -35,3 +45,6 @@ export const isNotFoundError = (error: any): error is NotFoundError =>
35
45
 
36
46
  export const isBadRequestError = (error: any): error is BadRequestError =>
37
47
  error?.extensions?.type === 'BadRequestError'
48
+
49
+ export const isForbiddenError = (error: any): error is ForbiddenError =>
50
+ error?.extensions?.type === 'ForbiddenError'
@@ -0,0 +1,7 @@
1
+ export interface ContractResponse {
2
+ isCorporate: boolean
3
+ corporateName: string
4
+ firstName: string
5
+ lastName: string
6
+ userName: string
7
+ }
@@ -2,10 +2,22 @@ import { parse } from 'cookie'
2
2
  import type { FACET_CROSS_SELLING_MAP } from '../../utils/facets'
3
3
  import { fetchAPI } from '../fetch'
4
4
 
5
- import type { StoreMarketingData } from '../../../..'
5
+ import type {
6
+ IUserOrderCancel,
7
+ QueryListUserOrdersArgs,
8
+ StoreMarketingData,
9
+ UserOrder,
10
+ UserOrderCancel,
11
+ UserOrderListResult,
12
+ } from '../../../..'
6
13
  import type { Context, Options } from '../../index'
7
14
  import type { Channel } from '../../utils/channel'
8
- import { getStoreCookie, getWithCookie } from '../../utils/cookies'
15
+ import {
16
+ getStoreCookie,
17
+ getWithAutCookie,
18
+ getWithCookie,
19
+ } from '../../utils/cookies'
20
+ import type { ContractResponse } from './Contract'
9
21
  import type { Address, AddressInput } from './types/Address'
10
22
  import type { Brand } from './types/Brand'
11
23
  import type { CategoryTree } from './types/CategoryTree'
@@ -22,6 +34,8 @@ import type {
22
34
  SimulationArgs,
23
35
  SimulationOptions,
24
36
  } from './types/Simulation'
37
+ import type { ScopesByUnit, UnitResponse } from './types/Unit'
38
+ import type { VtexIdResponse } from './types/VtexId'
25
39
 
26
40
  type ValueOf<T> = T extends Record<string, infer K> ? K : never
27
41
 
@@ -39,6 +53,7 @@ export const VtexCommerce = (
39
53
  const base = `https://${account}.${environment}.com.br`
40
54
  const storeCookies = getStoreCookie(ctx)
41
55
  const withCookie = getWithCookie(ctx)
56
+ const withAutCookie = getWithAutCookie(ctx)
42
57
 
43
58
  const host =
44
59
  new Headers(ctx.headers).get('x-forwarded-host') ?? ctx.headers?.host ?? ''
@@ -351,6 +366,29 @@ export const VtexCommerce = (
351
366
  { storeCookies }
352
367
  )
353
368
  },
369
+ cancelOrder: ({
370
+ orderId,
371
+ customerEmail,
372
+ reason,
373
+ }: IUserOrderCancel): Promise<UserOrderCancel> | undefined => {
374
+ const headers: HeadersInit = withCookie({
375
+ 'content-type': 'application/json',
376
+ 'X-FORWARDED-HOST': forwardedHost,
377
+ })
378
+
379
+ return fetchAPI(
380
+ `${base}/api/checkout/pub/orders/${orderId}/user-cancel-request`,
381
+ {
382
+ method: 'POST',
383
+ headers,
384
+ body: JSON.stringify({
385
+ customerEmail,
386
+ reason,
387
+ }),
388
+ },
389
+ {}
390
+ )
391
+ },
354
392
  },
355
393
  session: (search: string): Promise<Session> => {
356
394
  const params = new URLSearchParams(search)
@@ -392,19 +430,191 @@ export const VtexCommerce = (
392
430
  },
393
431
  profile: {
394
432
  addresses: async (userId: string): Promise<Record<string, string>> => {
433
+ const headers: HeadersInit = withAutCookie(forwardedHost, account)
434
+
435
+ return fetchAPI(
436
+ `${base}/api/profile-system/pvt/profiles/${userId}/addresses`,
437
+ { headers },
438
+ { storeCookies }
439
+ )
440
+ },
441
+ },
442
+ oms: {
443
+ userOrder: ({ orderId }: { orderId: string }): Promise<UserOrder> => {
395
444
  const headers: HeadersInit = withCookie({
396
445
  'content-type': 'application/json',
397
446
  'X-FORWARDED-HOST': forwardedHost,
398
447
  })
399
448
 
400
- const cookies = parse(ctx?.headers?.cookie ?? '')
401
- const VtexIdclientAutCookie =
402
- cookies['VtexIdclientAutCookie_' + account]
403
- headers['VtexIdclientAutCookie'] = VtexIdclientAutCookie
449
+ return fetchAPI(
450
+ `${base}/api/oms/user/orders/${orderId}`,
451
+ {
452
+ method: 'GET',
453
+ headers,
454
+ },
455
+ { storeCookies }
456
+ )
457
+ },
458
+ listUserOrders: ({
459
+ page,
460
+ status,
461
+ dateInitial,
462
+ dateFinal,
463
+ text,
464
+ clientEmail,
465
+ perPage,
466
+ }: QueryListUserOrdersArgs): Promise<UserOrderListResult> => {
467
+ const params = new URLSearchParams()
468
+
469
+ if (dateInitial) {
470
+ const dateInitialTimestamp = new Date(dateInitial).setHours(
471
+ 0,
472
+ 0,
473
+ 0,
474
+ 0
475
+ )
476
+ dateInitial = new Date(dateInitialTimestamp).toISOString()
477
+ }
478
+ if (dateFinal) {
479
+ const dateFinalTimestamp = new Date(dateFinal).setHours(
480
+ 23,
481
+ 59,
482
+ 59,
483
+ 999
484
+ )
485
+ dateFinal = new Date(dateFinalTimestamp).toISOString()
486
+ }
487
+
488
+ if (text) params.append('text', text)
489
+ if (status && status.length > 0) {
490
+ status.forEach((s) =>
491
+ s && s.length > 0 ? params.append('status', s) : null
492
+ )
493
+ }
494
+
495
+ if (dateInitial && dateFinal) {
496
+ params.append(
497
+ 'creation_date',
498
+ `creationDate:[${dateInitial} TO ${dateFinal}]`
499
+ )
500
+ } else if (dateInitial) {
501
+ params.append('creation_date', `creationDate:[${dateInitial} TO *]`)
502
+ } else if (dateFinal) {
503
+ params.append('creation_date', `creationDate:[* TO ${dateFinal}]`)
504
+ }
505
+
506
+ if (clientEmail) params.append('clientEmail', clientEmail)
507
+ if (page) params.append('page', page.toString())
508
+ if (perPage) params.append('per_page', perPage.toString())
509
+
510
+ const headers: HeadersInit = withCookie({
511
+ 'content-type': 'application/json',
512
+ 'X-FORWARDED-HOST': forwardedHost,
513
+ })
404
514
 
405
515
  return fetchAPI(
406
- `${base}/api/profile-system/pvt/profiles/${userId}/addresses`,
407
- { headers },
516
+ `${base}/api/oms/user/orders?${params.toString()}`,
517
+ {
518
+ method: 'GET',
519
+ headers,
520
+ },
521
+ { storeCookies }
522
+ )
523
+ },
524
+ },
525
+ units: {
526
+ getUnitByUserId: ({
527
+ userId,
528
+ }: { userId: string }): Promise<UnitResponse> => {
529
+ const headers: HeadersInit = withAutCookie(forwardedHost, account)
530
+
531
+ return fetchAPI(
532
+ `${base}/api/units/v1/${userId}/unit`,
533
+ {
534
+ method: 'GET',
535
+ headers,
536
+ },
537
+ {}
538
+ )
539
+ },
540
+ getOrgUnitById: ({
541
+ orgUnitId,
542
+ }: { orgUnitId: string }): Promise<UnitResponse> => {
543
+ const headers: HeadersInit = withAutCookie(forwardedHost, account)
544
+
545
+ return fetchAPI(
546
+ `${base}/api/units/v1/${orgUnitId}`,
547
+ {
548
+ method: 'GET',
549
+ headers,
550
+ },
551
+ {}
552
+ )
553
+ },
554
+ getScopesByOrgUnit: ({
555
+ orgUnitId,
556
+ }: { orgUnitId: string }): Promise<ScopesByUnit> => {
557
+ const headers: HeadersInit = withAutCookie(forwardedHost, account)
558
+
559
+ return fetchAPI(
560
+ `${base}/api/units/v1/${orgUnitId}/scopes`,
561
+ {
562
+ method: 'GET',
563
+ headers,
564
+ },
565
+ {}
566
+ )
567
+ },
568
+ },
569
+ licenseManager: {
570
+ getUserById: ({
571
+ userId,
572
+ }: { userId: string }): Promise<{
573
+ id: string
574
+ name: string
575
+ email: string
576
+ }> => {
577
+ const headers: HeadersInit = withAutCookie(forwardedHost, account)
578
+
579
+ return fetchAPI(
580
+ `${base}/api/license-manager/users/${userId}`,
581
+ {
582
+ method: 'GET',
583
+ headers,
584
+ },
585
+ {}
586
+ )
587
+ },
588
+ },
589
+ masterData: {
590
+ getContractById: ({
591
+ contractId,
592
+ }: { contractId: string }): Promise<ContractResponse> => {
593
+ const headers: HeadersInit = withAutCookie(forwardedHost, account)
594
+
595
+ return fetchAPI(
596
+ `${base}/api/dataentities/CL/documents/${contractId}?_fields=_all`,
597
+ {
598
+ method: 'GET',
599
+ headers,
600
+ },
601
+ {}
602
+ )
603
+ },
604
+ },
605
+ vtexid: {
606
+ validate: (): Promise<VtexIdResponse> => {
607
+ const headers: HeadersInit = withAutCookie(forwardedHost, account)
608
+
609
+ return fetchAPI(
610
+ `${base}/api/vtexid/credential/validate`,
611
+ {
612
+ headers,
613
+ body: JSON.stringify({
614
+ token: headers['VtexIdclientAutCookie'],
615
+ }),
616
+ method: 'POST',
617
+ },
408
618
  { storeCookies }
409
619
  )
410
620
  },
@@ -0,0 +1,19 @@
1
+ export interface UnitResponse {
2
+ createdAt: string
3
+ updatedAt: string
4
+ name: string
5
+ path: {
6
+ ids: string
7
+ names: string
8
+ }
9
+ id: string
10
+ customerGroup: string[]
11
+ }
12
+
13
+ export interface ScopesByUnit {
14
+ organizationUnitId: string
15
+ scopes: Array<{
16
+ scope: string
17
+ ids: string[]
18
+ }>
19
+ }
@@ -0,0 +1,11 @@
1
+ export interface VtexIdResponse {
2
+ authStatus: string
3
+ id: string
4
+ user: string
5
+ account: string
6
+ audience: string
7
+ tokenType: string
8
+ customerId: string
9
+ unitName: string
10
+ isRepresentative: boolean
11
+ }
@@ -24,6 +24,7 @@ import { StoreSearchResult } from './resolvers/searchResult'
24
24
  import { StoreSeo } from './resolvers/seo'
25
25
  import { ShippingSLA } from './resolvers/shippingSLA'
26
26
  import { SkuVariants } from './resolvers/skuVariations'
27
+ import { UserOrder } from './resolvers/userOrder'
27
28
  import type { Channel } from './utils/channel'
28
29
  import ChannelMarshal from './utils/channel'
29
30
 
@@ -63,6 +64,7 @@ export interface Context {
63
64
  cookies: Map<string, Record<string, string>>
64
65
  }
65
66
  headers: Record<string, string>
67
+ account: string
66
68
  }
67
69
 
68
70
  export type Resolver<R = unknown, A = unknown, Return = any> = (
@@ -89,6 +91,7 @@ const Resolvers = {
89
91
  StorePropertyValue,
90
92
  SkuVariants,
91
93
  ShippingSLA,
94
+ UserOrder,
92
95
  ObjectOrString,
93
96
  Query,
94
97
  Mutation,
@@ -105,6 +108,7 @@ export const getContextFactory =
105
108
  }
106
109
  ctx.clients = getClients(options, ctx)
107
110
  ctx.loaders = getLoaders(options, ctx)
111
+ ctx.account = options.account
108
112
 
109
113
  return ctx
110
114
  }
@@ -0,0 +1,20 @@
1
+ import type { Context } from '..'
2
+ import type {
3
+ MutationCancelOrderArgs,
4
+ UserOrderCancel,
5
+ } from '../../../__generated__/schema'
6
+ import { BadRequestError } from '../../errors'
7
+
8
+ export const cancelOrder = async (
9
+ _: any,
10
+ { data }: MutationCancelOrderArgs,
11
+ { clients: { commerce } }: Context
12
+ ): Promise<UserOrderCancel | null> => {
13
+ if (!data?.orderId) {
14
+ throw new BadRequestError('Missing orderId')
15
+ }
16
+
17
+ const response = await commerce.checkout.cancelOrder(data)
18
+
19
+ return { data: response?.data }
20
+ }
@@ -1,3 +1,4 @@
1
+ import { cancelOrder } from './cancelOrder'
1
2
  import { subscribeToNewsletter } from './subscribeToNewsletter'
2
3
  import { validateCart } from './validateCart'
3
4
  import { validateSession } from './validateSession'
@@ -6,4 +7,5 @@ export const Mutation = {
6
7
  validateCart,
7
8
  validateSession,
8
9
  subscribeToNewsletter,
10
+ cancelOrder,
9
11
  }
@@ -2,15 +2,17 @@ import type {
2
2
  QueryAllCollectionsArgs,
3
3
  QueryAllProductsArgs,
4
4
  QueryCollectionArgs,
5
+ QueryListUserOrdersArgs,
5
6
  QueryProductArgs,
7
+ QueryProductCountArgs,
6
8
  QueryProfileArgs,
7
9
  QueryRedirectArgs,
8
10
  QuerySearchArgs,
9
11
  QuerySellersArgs,
10
12
  QueryShippingArgs,
11
- QueryProductCountArgs,
13
+ QueryUserOrderArgs,
12
14
  } from '../../../__generated__/schema'
13
- import { BadRequestError, NotFoundError } from '../../errors'
15
+ import { BadRequestError, ForbiddenError, NotFoundError } from '../../errors'
14
16
  import type { CategoryTree } from '../clients/commerce/types/CategoryTree'
15
17
  import type { ProfileAddress } from '../clients/commerce/types/Profile'
16
18
  import type { SearchArgs } from '../clients/search'
@@ -377,4 +379,57 @@ export const Query = {
377
379
 
378
380
  return result
379
381
  },
382
+ userOrder: async (
383
+ _: unknown,
384
+ { orderId }: QueryUserOrderArgs,
385
+ ctx: Context
386
+ ) => {
387
+ const {
388
+ clients: { commerce },
389
+ } = ctx
390
+ if (!orderId) {
391
+ throw new BadRequestError('Missing orderId')
392
+ }
393
+
394
+ try {
395
+ const order = await commerce.oms.userOrder({ orderId })
396
+
397
+ if (!order) {
398
+ throw new NotFoundError(`No order found for id ${orderId}`)
399
+ }
400
+
401
+ return order
402
+ } catch (error) {
403
+ const { message } = JSON.parse((error as Error).message).error as {
404
+ code: string
405
+ message: string
406
+ exception: any
407
+ }
408
+
409
+ if (message.toLowerCase().includes('order not found')) {
410
+ throw new NotFoundError(`No order found for id ${orderId}`)
411
+ }
412
+
413
+ if (message.toLowerCase().includes('acesso negado')) {
414
+ throw new ForbiddenError(
415
+ `You are forbidden to interact with order with id ${orderId}`
416
+ )
417
+ }
418
+
419
+ throw error
420
+ }
421
+ },
422
+ listUserOrders: async (
423
+ _: unknown,
424
+ filters: QueryListUserOrdersArgs,
425
+ ctx: Context
426
+ ) => {
427
+ const {
428
+ clients: { commerce },
429
+ } = ctx
430
+
431
+ const orders = await commerce.oms.listUserOrders(filters)
432
+
433
+ return orders
434
+ },
380
435
  }
@@ -0,0 +1,205 @@
1
+ import type { Resolver } from '..'
2
+ import type {
3
+ Maybe,
4
+ UserOrderCustomField,
5
+ UserOrderDeliveryOption,
6
+ } from '../../..'
7
+ import type { PromiseType } from '../../../typings'
8
+ import type { Query } from './query'
9
+ import { getLocalizedEstimates } from './shippingSLA'
10
+
11
+ type QueryUserOrder = PromiseType<ReturnType<typeof Query.userOrder>>
12
+
13
+ export type Root = QueryUserOrder
14
+
15
+ const deliveryChannelsMapping = {
16
+ ['pickup-in-point']: 'Pickup',
17
+ delivery: 'Delivery',
18
+ pickup: 'Pickup',
19
+ ['take-away']: 'Take away',
20
+ ['']: '',
21
+ } as const
22
+
23
+ export const UserOrder: Record<string, Resolver<Root>> = {
24
+ orderId: ({ orderId }) => orderId,
25
+ totals: ({ totals }) => totals,
26
+ items: ({ items }) => items,
27
+ shippingData: ({ shippingData }) => shippingData,
28
+ paymentData: ({ paymentData }) => paymentData,
29
+ deliveryOptionsData: (root) => {
30
+ const { shippingData, items } = root
31
+ const logisticsInfo = shippingData?.logisticsInfo || []
32
+ const addresses = shippingData?.selectedAddresses ||
33
+ shippingData?.availableAddresses || [shippingData?.address]
34
+
35
+ const groupedDeliveryOptions = logisticsInfo.reduce(
36
+ (acc, logisticsItem) => {
37
+ const selectedSla = logisticsItem?.selectedSla || '' // Normal / Express
38
+ const deliveryChannel =
39
+ logisticsItem?.selectedDeliveryChannel ||
40
+ logisticsItem?.deliveryChannel ||
41
+ ''
42
+ const deliveryCompany = logisticsItem?.deliveryCompany || '' // Correios / Fedex
43
+ const deliveryWindow = logisticsItem?.deliveryWindow
44
+ const pickupStoreInfo = logisticsItem?.pickupStoreInfo
45
+ const shippingEstimate = logisticsItem?.shippingEstimate || '' // 1bd
46
+ const friendlyShippingEstimate = logisticsItem?.shippingEstimate
47
+ ? getLocalizedEstimates(logisticsItem?.shippingEstimate) // e.g. transform 3bd into Up to 3 business days
48
+ : ''
49
+
50
+ const shippingEstimateDate = logisticsItem?.shippingEstimateDate || '' // 2023-10-02T00:00:00Z
51
+ const addressId = logisticsItem?.addressId || '' // 5230338247839
52
+
53
+ const itemIndex = logisticsItem?.itemIndex ?? 0
54
+ const item = items?.[itemIndex]
55
+ const seller = item?.seller || ''
56
+
57
+ const groupKey = `${selectedSla}|${deliveryChannel}|${deliveryCompany}|${seller}|${shippingEstimate}|${shippingEstimateDate}|${addressId}|${deliveryWindow?.startDateUtc}|${deliveryWindow?.endDateUtc}`
58
+
59
+ const address = addresses?.find(
60
+ (address) => address?.addressId === addressId
61
+ )
62
+
63
+ const friendlyDeliveryOptionName =
64
+ `${deliveryChannelsMapping[deliveryChannel as keyof typeof deliveryChannelsMapping] || ''} ${friendlyShippingEstimate} ${address?.neighborhood ? `to ${address?.neighborhood}` : ''}`.trim()
65
+
66
+ // TODO check other totals like bundleItems etc
67
+ const itemTotal =
68
+ (item?.sellingPrice ?? 0) * (item?.quantity ?? 0) + (item?.tax ?? 0)
69
+
70
+ if (!acc[groupKey]) {
71
+ acc[groupKey] = {
72
+ // static fields
73
+ selectedSla,
74
+ deliveryChannel,
75
+ deliveryCompany,
76
+ deliveryWindow,
77
+ shippingEstimate,
78
+ shippingEstimateDate,
79
+ seller,
80
+ friendlyShippingEstimate,
81
+ friendlyDeliveryOptionName,
82
+ address,
83
+ pickupStoreInfo,
84
+ // dynamic fields
85
+ quantityOfDifferentItems: 0,
86
+ total: 0,
87
+ items: [],
88
+ }
89
+ }
90
+
91
+ if (acc[groupKey]) {
92
+ acc[groupKey].items?.push({
93
+ id: item?.id || '',
94
+ name: item?.name || '',
95
+ quantity: item?.quantity || 0,
96
+ price: item?.price || 0,
97
+ imageUrl: item?.imageUrl || '',
98
+ tax: item?.tax || 0,
99
+ total: itemTotal,
100
+ })
101
+
102
+ acc[groupKey].quantityOfDifferentItems =
103
+ (acc[groupKey].quantityOfDifferentItems ?? 0) + 1
104
+ acc[groupKey].total = (acc[groupKey].total ?? 0) + itemTotal
105
+ }
106
+
107
+ return acc
108
+ },
109
+ {} as Record<string, UserOrderDeliveryOption>
110
+ )
111
+
112
+ const deliveryOptions = Object.values(groupedDeliveryOptions)
113
+
114
+ const contactInformation = shippingData?.contactInformation?.[0]
115
+ const contact = {
116
+ name:
117
+ `${contactInformation?.firstName ?? ''} ${contactInformation?.lastName ?? ''}`.trim() ||
118
+ deliveryOptions?.[0]?.address?.receiverName ||
119
+ '',
120
+ email: contactInformation?.email || '',
121
+ phone: contactInformation?.phone || '',
122
+ }
123
+
124
+ return {
125
+ deliveryOptions,
126
+ contact,
127
+ }
128
+ },
129
+ customFields: (root) => {
130
+ const customFields = root?.customData?.customFields || []
131
+ return Object.values(
132
+ customFields.reduce(
133
+ (
134
+ acc: Record<
135
+ string,
136
+ { type: string; id: string; fields: UserOrderCustomField['fields'] }
137
+ >,
138
+ entry: Maybe<UserOrderCustomField>
139
+ ) => {
140
+ const type = entry?.linkedEntity?.type || ''
141
+ const id = entry?.linkedEntity?.id || ''
142
+ const key = `${type}|${id || ''}`
143
+ if (!acc[key]) {
144
+ acc[key] = { type, id, fields: [] }
145
+ }
146
+ acc[key].fields.push(...(entry?.fields || []))
147
+ return acc
148
+ },
149
+ {}
150
+ )
151
+ )
152
+ // Example of custom fields
153
+ // return [
154
+ // {
155
+ // type: 'item',
156
+ // id: '9009169',
157
+ // fields: [
158
+ // {
159
+ // name: 'costCenter',
160
+ // value: 'CC1',
161
+ // refId: 'externalId',
162
+ // },
163
+ // ],
164
+ // },
165
+ // {
166
+ // type: 'item',
167
+ // id: 'ECEAC03EBA2B4BBFA7E899CD4CA5121B',
168
+ // fields: [
169
+ // {
170
+ // name: 'costCenter',
171
+ // value: 'CC2',
172
+ // refId: 'externalId',
173
+ // },
174
+ // ],
175
+ // },
176
+ // {
177
+ // type: 'address',
178
+ // id: 'work-A1',
179
+ // fields: [
180
+ // {
181
+ // name: 'desktop',
182
+ // value: 'A1',
183
+ // refId: 'externalId',
184
+ // },
185
+ // ],
186
+ // },
187
+ // {
188
+ // type: 'order',
189
+ // id: '',
190
+ // fields: [
191
+ // {
192
+ // name: 'poNumber',
193
+ // value: '111222333',
194
+ // refId: 'externalId',
195
+ // },
196
+ // {
197
+ // name: 'release',
198
+ // value: '123',
199
+ // refId: 'externalId',
200
+ // },
201
+ // ],
202
+ // },
203
+ // ]
204
+ },
205
+ }