diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c9f5905..a0d37746 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed + +- Remove unwanted columns from review table +- Fix add to cart issues +- Fix numeric stepper. +- Fix the quantity validation against MOQ and UM. +- Fix the add to cart quantity. +- Fix the add to cart behaviour in pdp search. + +## [0.0.4] - 2021-11-01 + +## [0.0.3] - 2021-10-29 + +### Fixed + +- Added the Avble qty for bulk order. +- Fixed the duplicate sku addition + ## [3.2.0] - 2021-05-17 ### Added diff --git a/graphql/schema.graphql b/graphql/schema.graphql index c3c1e85a..ec87c2ad 100644 --- a/graphql/schema.graphql +++ b/graphql/schema.graphql @@ -5,4 +5,6 @@ type Query { sellers: SellersType @cacheControl(scope: SEGMENT, maxAge: MEDIUM) @withSegment + + getSkuAvailability(refIds: [String], customerNumber: String, targetSystem: String, salesOrganizationCode: String): AvailableItems } diff --git a/graphql/types/GetSkuAvailability.graphql b/graphql/types/GetSkuAvailability.graphql new file mode 100644 index 00000000..abb28d73 --- /dev/null +++ b/graphql/types/GetSkuAvailability.graphql @@ -0,0 +1,15 @@ +type AvailableItems { + items: [AvailableItem] +} +type AvailableItem { + refid: String + sku: String + productId: String + availability: String + seller: ItemsSeller + availableQuantity: String + productName: String + price: Float + unitMultiplier: Int + minQty: Int +} diff --git a/graphql/types/Refids.graphql b/graphql/types/Refids.graphql index 2b4c673a..ee422870 100644 --- a/graphql/types/Refids.graphql +++ b/graphql/types/Refids.graphql @@ -6,4 +6,5 @@ type ItemsRefId { refid: String availability: String sellers: [ItemsSeller] + productName: String } diff --git a/manifest.json b/manifest.json index a579503b..9cb5de14 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { - "vendor": "vtex", - "name": "quickorder", - "version": "3.2.0", + "vendor": "sbdsefuat", + "name": "bulk-order", + "version": "0.0.4", "title": "Quickorder", "description": "Allow users to add multiple products to the cart at once", "defaultLocale": "en-US", @@ -35,7 +35,8 @@ "vtex.pixel-manager": "1.x", "vtex.store-resources": "0.x", "vtex.css-handles": "0.x", - "vtex.store-icons": "0.x" + "vtex.store-icons": "0.x", + "sbdsefuat.checkout-simulation": "1.x" }, "policies": [ { @@ -70,6 +71,40 @@ "host": "{{account}}.vtexcommercestable.com.br", "path": "/api/catalog_system/pub/sku/stockkeepingunitidsbyrefids" } + }, + { + "name": "outbound-access", + "attrs": { + "host": "{{account}}.vtexcommercestable.com.br", + "path": "/api/catalog_system/pvt/seller/*" + } + }, + { + "name": "outbound-access", + "attrs": { + "host": "{{account}}.vtexcommercestable.com.br", + "path": "/api/catalog_system/pub/products/search/*" + } + }, + { + "name": "outbound-access", + "attrs": { + "host": "api.vtex.com", + "path": "/api/dataentities/*" + } + }, + { + "name": "outbound-access", + "attrs": { + "host": "{{account}}.vtexcommercestable.com.br", + "path": "/api/logistics/pvt/inventory/skus/*" + } + }, + { + "name": "POWER_USER_DS" + }, + { + "name": "LogisticsAdmin" } ], "settingsSchema": {}, diff --git a/messages/context.json b/messages/context.json index 2eb3769f..d27c6751 100644 --- a/messages/context.json +++ b/messages/context.json @@ -54,5 +54,6 @@ "store/toaster.cart.duplicated": "store/toaster.cart.duplicated", "store/toaster.cart.error": "store/toaster.cart.error", "store/toaster.cart.seeCart": "store/toaster.cart.seeCart", - "store/toaster.cart.success": "store/toaster.cart.success" + "store/toaster.cart.success": "store/toaster.cart.success", + "store/quickorder.unavailable": "store/quickorder.unavailable" } \ No newline at end of file diff --git a/messages/en.json b/messages/en.json index 1b0f3b3b..00e4f625 100644 --- a/messages/en.json +++ b/messages/en.json @@ -42,7 +42,7 @@ "store/quickorder.review.label.lineNumber": "#", "store/quickorder.review.label.quantity": "Quantity", "store/quickorder.review.label.seller": "Seller", - "store/quickorder.review.label.sku": "SKU", + "store/quickorder.review.label.sku": "Product Name", "store/quickorder.review.label.status": "Status", "store/quickorder.skuNotFound": "SKU Not Found", "store/quickorder.upload.choose": "choose a file", @@ -54,5 +54,6 @@ "store/toaster.cart.duplicated": "Item duplicated", "store/toaster.cart.error": "Error adding products to the cart", "store/toaster.cart.seeCart": "See cart", - "store/toaster.cart.success": "Products successfuly added to the cart" + "store/toaster.cart.success": "Products successfuly added to the cart", + "store/quickorder.unavailable": "Item not available in the store" } diff --git a/messages/es.json b/messages/es.json index 0ce93b1e..850ec23d 100644 --- a/messages/es.json +++ b/messages/es.json @@ -54,5 +54,6 @@ "store/toaster.cart.duplicated": "Elemento duplicado", "store/toaster.cart.error": "Error al agregar productos al carrito", "store/toaster.cart.seeCart": "Ver el carrito", - "store/toaster.cart.success": "Productos agregados correctamente" + "store/toaster.cart.success": "Productos agregados correctamente", + "store/quickorder.unavailable": "Item not available in the store" } \ No newline at end of file diff --git a/messages/pt.json b/messages/pt.json index ee0e0bc9..262f68f5 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -54,5 +54,6 @@ "store/toaster.cart.duplicated": "Item duplicado", "store/toaster.cart.error": "Erro adicionando produtos ao carrinho", "store/toaster.cart.seeCart": "Ver o carrinho", - "store/toaster.cart.success": "Produtos adicionados com sucesso" + "store/toaster.cart.success": "Produtos adicionados com sucesso", + "store/quickorder.unavailable": "Item not available in the store" } \ No newline at end of file diff --git a/messages/ro.json b/messages/ro.json index f36934b9..34eb5b28 100644 --- a/messages/ro.json +++ b/messages/ro.json @@ -54,5 +54,6 @@ "store/toaster.cart.duplicated": "Articol duplicat", "store/toaster.cart.error": "Eroare la adaugarea produselor in cos", "store/toaster.cart.seeCart": "Vezi cos", - "store/toaster.cart.success": "Produse adaugate in cos" + "store/toaster.cart.success": "Produse adaugate in cos", + "store/quickorder.unavailable": "Item not available in the store" } \ No newline at end of file diff --git a/node/clients/catalog.ts b/node/clients/catalog.ts new file mode 100644 index 00000000..25a01174 --- /dev/null +++ b/node/clients/catalog.ts @@ -0,0 +1,30 @@ +import { ExternalClient, InstanceOptions, IOContext } from '@vtex/api' + +export class Catalog extends ExternalClient { + constructor(context: IOContext, options?: InstanceOptions) { + super( + `http://${context.account}.vtexcommercestable.com.br`, + context, + options + ) + } + + public inventoryBySkuId = (id: string | number) => { + this.context.logger.debug({ + auth: this.context.authToken, + url: this.context.host, + }) + const endpoint = `${this.options?.baseURL}/api/logistics/pvt/inventory/skus/${id}` + return this.http.get(`/api/logistics/pvt/inventory/skus/${id}`, { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + VtexIdclientAutCookie: `${this.context.authToken}`, + 'Proxy-Authorization': this.context.authToken, + 'X-Vtex-Proxy-To': endpoint, + 'X-Vtex-Use-Https': true, + 'Cache-Control': 'no-cache', + }, + }) + } +} diff --git a/node/clients/index.ts b/node/clients/index.ts index 84297fe7..8b93954c 100644 --- a/node/clients/index.ts +++ b/node/clients/index.ts @@ -1,9 +1,14 @@ import { IOClients } from '@vtex/api' import { Search } from './search' +import { Catalog } from './catalog' export class Clients extends IOClients { public get search() { return this.getOrSet('search', Search) } + + public get catalog() { + return this.getOrSet('catalog', Catalog) + } } diff --git a/node/clients/search.ts b/node/clients/search.ts index 48621259..34ad1e0d 100644 --- a/node/clients/search.ts +++ b/node/clients/search.ts @@ -1,11 +1,11 @@ import { ExternalClient, InstanceOptions, IOContext } from '@vtex/api' - -const axios = require('axios') +import axios from 'axios' interface RefIdArgs { refids: any orderFormId: string } + interface Items { id: string quantity: number @@ -13,7 +13,7 @@ interface Items { } export class Search extends ExternalClient { - public constructor(ctx: IOContext, opts?: InstanceOptions) { + constructor(ctx: IOContext, opts?: InstanceOptions) { super(`http://${ctx.account}.vtexcommercestable.com.br/`, ctx, opts) } @@ -25,12 +25,16 @@ export class Search extends ExternalClient { }).name } + /** + * + * @param refids + * @param orderFormId + */ public skuFromRefIds = async ({ refids, orderFormId }: RefIdArgs) => { this.sellersList = await this.sellers() const url = `http://${this.context.account}.vtexcommercestable.com.br/api/catalog_system/pub/sku/stockkeepingunitidsbyrefids` - - const res = await axios.default.post(url, refids, { + const res = await axios.post(url, refids, { headers: { 'Content-Type': 'application/json', Authorization: `bearer ${this.context.authToken}`, @@ -54,24 +58,30 @@ export class Search extends ExternalClient { }) if (this.sellersList?.length) { - const promises = result.map(async (o: any) => this.sellerBySku(o.sku, o.refid)) + const promises = result.map(async (o: any) => + this.sellerBySku(o.sku, o.refid) + ) result = await Promise.all(promises) } const orderForm = await this.getOrderForm(orderFormId) + const { items }: any = await this.simulate(result, orderForm) - const {items}: any = await this.simulate(result, orderForm) - - result = result.map((item: any) => { - return { - ...item, - availability: this.getAvailability(item, items) - } - }) + result = result.map((item: any) => { + return { + ...item, + availability: this.getAvailability(item, items), + } + }) } return result } + /** + * + * @param item + * @param items + */ private getAvailability = (item: any, items: any) => { const [availabilityItem] = items.filter((curr: any) => { return curr.id === item.sku @@ -79,6 +89,10 @@ export class Search extends ExternalClient { return availabilityItem?.availability ?? '' } + /** + * + * @param orderFormId + */ private getOrderForm = async (orderFormId: string) => { return this.http.get(`/api/checkout/pub/orderForm/${orderFormId}`, { headers: { @@ -88,61 +102,83 @@ export class Search extends ExternalClient { }) } + /** + * + * @param refids + * @param orderForm + */ private simulate = async (refids: [Items], orderForm: any) => { - const {salesChannel, storePreferencesData: { - countryCode - }, - shippingData} = orderForm - const items = refids.filter((item: any) => { - return !!item.sku - }).map((item: any) => { - const [seller] = item.sellers - return { - id: item.sku, - quantity: 1, - seller: seller?.id, + const { + salesChannel, + storePreferencesData: { countryCode }, + shippingData, + } = orderForm + const items = refids + .filter((item: any) => { + return !!item.sku + }) + .map((item: any) => { + const [seller] = item.sellers + return { + id: item.sku, + quantity: 1, + seller: seller?.id, + } + }) + return this.http.post( + `/api/checkout/pub/orderForms/simulation?sc=${salesChannel}`, + { + items, + country: countryCode, + postalCode: shippingData?.address?.postalCode ?? '', } - }) - return this.http.post(`/api/checkout/pub/orderForms/simulation?sc=${salesChannel}`, { - items, - country: countryCode, - postalCode: shippingData?.address?.postalCode ?? '' - }) + ) } + /** + * + * @param skuId + * @param refid + */ private sellerBySku = async (skuId: string, refid: string) => { - if(skuId === null) { + if (skuId === null) { return { sku: null, refid, - sellers: null + sellers: null, } } const url = `http://${this.context.account}.vtexcommercestable.com.br/api/catalog_system/pvt/sku/stockkeepingunitbyid/${skuId}` - const res = await axios.default.get(url, { + const res = await axios.get(url, { headers: { 'Content-Type': 'application/json', Authorization: `bearer ${this.context.authToken}`, }, }) - return res.data?.SkuSellers ? { - sku: skuId, - refid, - sellers: res.data.SkuSellers.filter((item: any) => { - return item.IsActive === true - }).map(({ SellerId }: any) => { - return { - id: SellerId, - name: this.getNameFromId(SellerId), + + return res.data?.SkuSellers + ? { + sku: skuId, + refid, + sellers: res.data.SkuSellers.filter((item: any) => { + return item.IsActive === true + }).map(({ SellerId }: any) => { + return { + id: SellerId, + name: this.getNameFromId(SellerId), + } + }), } - }) - } : [] + : [] } + /** + * + */ public sellers = async () => { const url = `http://${this.context.account}.vtexcommercestable.com.br/api/catalog_system/pvt/seller/list` - const res = await axios.default.get(url, { + const res = await axios.get(url, { headers: { 'Content-Type': 'application/json', Authorization: `bearer ${this.context.authToken}`, @@ -166,4 +202,35 @@ export class Search extends ExternalClient { return result } + + /** + * + * @param sku + * @param refid + */ + public searchProductBySkuId = async (sku: string) => { + const priceBySkuIdUrl = `http://${this.context.account}.vtexcommercestable.com.br/api/catalog_system/pub/products/search?fq=skuId:${sku}` + const res = await axios.get(priceBySkuIdUrl, { + headers: { + 'Content-Type': 'application/json', + Authorization: `bearer ${this.context.authToken}`, + }, + }) + return res?.status === 200 && res.data.length > 0? res.data[0]: {} + } + + /** + * + * @param refIds + */ + public getSkusByRefIds = async (refIds: string[]) => { + const url = `http://${this.context.account}.vtexcommercestable.com.br/api/catalog_system/pub/sku/stockkeepingunitidsbyrefids` + const res = await axios.post(url, refIds, { + headers: { + 'Content-Type': 'application/json', + Authorization: `bearer ${this.context.authToken}`, + }, + }) + return res?.status === 200? res.data: {} + } } diff --git a/node/package.json b/node/package.json index d3d5dbe3..fbd7a2b7 100644 --- a/node/package.json +++ b/node/package.json @@ -29,29 +29,30 @@ "@types/node": "^12.0.0", "@types/qs": "^6.5.1", "@types/ramda": "^0.26.21", - "@vtex/api": "6.41.0", + "@vtex/api": "6.45.3", "@vtex/test-tools": "^1.2.0", "@vtex/tsconfig": "^0.2.0", "eslint": "^6.8.0", "eslint-config-vtex": "^12.1.1", "prettier": "^1.16.4", - "vtex.apps-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.5.1/public/@types/vtex.apps-graphql", + "sbdsefuat.checkout-simulation": "http://sbdsefuat.vtexassets.com/_v/public/typings/v1/sbdsefuat.checkout-simulation@1.0.31/public/@types/sbdsefuat.checkout-simulation", + "vtex.apps-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.8.0/public/@types/vtex.apps-graphql", "vtex.checkout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout@0.6.0/public/_types/react", - "vtex.checkout-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.44.1/public/@types/vtex.checkout-graphql", - "vtex.checkout-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.36.0/public/@types/vtex.checkout-resources", + "vtex.checkout-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.63.0/public/@types/vtex.checkout-graphql", + "vtex.checkout-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.47.0/public/@types/vtex.checkout-resources", "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.4/public/@types/vtex.css-handles", - "vtex.flex-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.15.1/public/@types/vtex.flex-layout", - "vtex.order-items": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.9.1/public/@types/vtex.order-items", - "vtex.order-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.8.7/public/@types/vtex.order-manager", - "vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.4.0/public/@types/vtex.pixel-manager", - "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@7.42.0/public/@types/vtex.render-runtime", - "vtex.rich-text": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.11.2/public/@types/vtex.rich-text", - "vtex.search-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.36.0/public/_types/react", - "vtex.store": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.106.0/public/@types/vtex.store", - "vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.135.0/public/@types/vtex.store-graphql", + "vtex.flex-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.19.0/public/@types/vtex.flex-layout", + "vtex.order-items": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.13.1/public/@types/vtex.order-items", + "vtex.order-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.11.1/public/@types/vtex.order-manager", + "vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.8.0/public/@types/vtex.pixel-manager", + "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@7.44.0/public/@types/vtex.render-runtime", + "vtex.rich-text": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.15.0/public/@types/vtex.rich-text", + "vtex.search-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.47.2/public/@types/vtex.search-graphql", + "vtex.store": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.120.1/public/@types/vtex.store", + "vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.147.4/public/@types/vtex.store-graphql", "vtex.store-icons": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-icons@0.18.0/public/@types/vtex.store-icons", - "vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.73.0/public/_types/react", - "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.132.1/public/@types/vtex.styleguide" + "vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.85.0/public/@types/vtex.store-resources", + "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.145.2/public/@types/vtex.styleguide" }, "version": "3.2.0" } diff --git a/node/resolvers/index.ts b/node/resolvers/index.ts index c72d7141..d456253c 100644 --- a/node/resolvers/index.ts +++ b/node/resolvers/index.ts @@ -1,4 +1,3 @@ - import { fieldResolvers as searchFieldResolvers, queries as searchQueries, diff --git a/node/resolvers/search/index.ts b/node/resolvers/search/index.ts index b4e6e804..93dff05c 100644 --- a/node/resolvers/search/index.ts +++ b/node/resolvers/search/index.ts @@ -1,6 +1,17 @@ import { UserInputError } from '@vtex/api' import { resolvers as refidsResolvers } from './refids' +import { + BRAND_CLIENT_ACRONYM, + BRAND_CLIENT_SCHEMA, + BRNAD_CLIENT_FIELDS, + PLANT_ACRONYM, + PLANT_FIELDS, + PLANT_SCHEMA, + // UMMOQ_CLIENT_ACRONYM, + // UMMOQ_CLIENT_FIELDS, + // UMMOQ_CLIENT_SCHEMA, +} from '../../utils/consts' export const fieldResolvers = { ...refidsResolvers, @@ -9,7 +20,7 @@ export const fieldResolvers = { export const queries = { skuFromRefIds: async ( _: any, - args: { refids: string; orderFormId: string }, + args: { refids: [string]; orderFormId: string }, ctx: Context ) => { const { @@ -30,6 +41,7 @@ export const queries = { items, } }, + // eslint-disable-next-line @typescript-eslint/ban-types sellers: async (_: any, __: {}, ctx: Context) => { const { clients: { search }, @@ -41,4 +53,177 @@ export const queries = { items, } }, + getSkuAvailability: async ( + _: any, + args: { + refIds: string[] + customerNumber: string + targetSystem: string + salesOrganizationCode: string + }, + ctx: Context + ) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const { refIds, customerNumber, targetSystem, salesOrganizationCode } = args + const { + clients: { search, masterdata, catalog }, + } = ctx + + const skuIds = await search.getSkusByRefIds(refIds) + const refIdsFound = Object.getOwnPropertyNames(skuIds) + const skus = refIdsFound + .map((rfId: any) => ({ + skuId: skuIds[rfId], + refId: rfId, + })) + .filter((sku: any) => sku.skuId != null) + + const products = await Promise.all( + skus.map(async (sku: any) => search.searchProductBySkuId(sku.skuId)) + ) + + const plants = await Promise.all( + refIds.map((refId: string) => { + const where = `skuRefId=${refId} ${ + salesOrganizationCode + ? `AND salesOrganizationCode=${salesOrganizationCode}` + : '' + }` + + return masterdata.searchDocumentsWithPaginationInfo({ + dataEntity: PLANT_ACRONYM, + schema: PLANT_SCHEMA, + fields: PLANT_FIELDS, + where, + pagination: { pageSize: 100, page: 1 }, + }) + }) + ) + + const plantList = refIds.map((refId: string, index: number) => { + return { + refId, + plants: plants[index]?.data ?? [], + } + }) + + const brands = await masterdata.searchDocumentsWithPaginationInfo< + BrandForClients + >({ + dataEntity: BRAND_CLIENT_ACRONYM, + schema: BRAND_CLIENT_SCHEMA, + fields: BRNAD_CLIENT_FIELDS, + where: `(user=${customerNumber ?? ''} AND targetSystem=${targetSystem ?? + ''})`, + pagination: { pageSize: 100, page: 1 }, + }) + + const brandsList = brands?.data ?? [] + + const allInventoryByItemIds = await Promise.all( + ((Object.values(skuIds ?? {}) as string[]) ?? []).map((skuId: string) => { + return catalog.inventoryBySkuId(skuId) + }) + ) + + const allSkus = (products ?? []) + .filter((r: any) => Object.entries(r).length > 0) + .map((product: any) => { + if ( + (product.items ?? []).length === 0 || + (product.items[0]?.sellers ?? []).length === 0 + ) { + return {} + } + const { items, productId, productName } = product + + const itemId = items[0]?.itemId + const skuRefId = skus.find((sku: any) => sku.skuId === itemId)?.refId + // const refId = (items[0]?.referenceId ?? []).find((ref: any) => ref.Key === 'RefId')?.Value ?? '' + const { commertialOffer, sellerId, sellerName } = items[0].sellers[0] + const minQty = product['Minimum Order Quantity'].find((d: string) => d) + + let availableQuantity = 0 + let isAvailable = false + const unitMultiplier = + items.find((item: any) => item)?.unitMultiplier ?? 1 + + if (targetSystem.toUpperCase() === 'SAP') { + const productPlants = + plantList + .find( + (plant: any) => + plant?.refId?.toLowerCase() === skuRefId.toLowerCase() + ) + ?.plants?.map((plant: any) => plant.plant) ?? [] + const selectedProductWearhouses = + allInventoryByItemIds + .find((inventory: any) => inventory.skuId === itemId) + ?.balance?.filter((wearhouse: any) => + productPlants.includes(wearhouse.warehouseName) + ) ?? [] + availableQuantity = selectedProductWearhouses.reduce( + (partialSum: number, current: { totalQuantity: number }) => + partialSum + current?.totalQuantity ?? 0, + 0 + ) + isAvailable = selectedProductWearhouses.length > 0 + } else if (targetSystem.toUpperCase() === 'JDE') { + const { AvailableQuantity } = commertialOffer + + const productBrand = product.brand + // const brandClientData = brandData?.brandClient?.data ?? [] + const brandDataMatch: any = brandsList?.find( + (data: any) => data.trade === productBrand + ) + + availableQuantity = + brandDataMatch?.trade === productBrand ? AvailableQuantity : 0 + isAvailable = brandDataMatch?.trade === productBrand + } + + const price = commertialOffer.SellingPrice + ? commertialOffer.SellingPrice + : commertialOffer.Price + ? commertialOffer.Price + : commertialOffer.ListPrice + + return { + refid: skuRefId, + sku: itemId, + productId, + productName, + price, + availableQuantity, + seller: { + id: sellerId, + name: sellerName, + }, + availability: isAvailable ? 'available' : 'unavailable', + unitMultiplier, + minQty, + } + }) + + const itemsRequested = (refIds ?? []).map((refId: string) => { + const existing = allSkus.find((s: any) => s.refid === refId) + return ( + existing || { + refid: refId, + sku: null, + productId: null, + productName: null, + price: null, + availableQuantity: null, + seller: null, + availability: 'unavailable', + } + ) + }) + + return { + items: itemsRequested, + } + }, } diff --git a/node/typings/globals.ts b/node/typings/globals.ts new file mode 100644 index 00000000..6796587c --- /dev/null +++ b/node/typings/globals.ts @@ -0,0 +1,42 @@ +interface SearchArgs { + pageSize: number + page: number + where?: string + skuId: string + soc?: string + skuRefId: string +} + +interface PlantData { + plant: number + salesOrganizationCode: number +} +interface ClientBrand { + brand: string + client: string + targetSystem: string +} + +interface MoqUM { + unitMultiplier: string + minOrderQuantity: string +} + +interface Pagination { + pageSize: number + page: number + total: number +} + +interface SalesOrgPlant { + pagination: Pagination + data: PlantData[] +} +interface BrandForClients { + pagination: Pagination + data: ClientBrand[] +} +interface UnitMultiplierMoQ { + pagination: Pagination + data: MoqUM +} diff --git a/node/utils/consts.ts b/node/utils/consts.ts new file mode 100644 index 00000000..7316b1f4 --- /dev/null +++ b/node/utils/consts.ts @@ -0,0 +1,16 @@ +export const PLANT_ACRONYM = 'SP' +export const PLANT_SCHEMA = 'mdv1' +export const PLANT_FIELDS = ['id', 'plant', 'salesOrganizationCode', 'skuRefId'] + +export const BRAND_CLIENT_ACRONYM = 'TD' +export const BRAND_CLIENT_SCHEMA = 'mdv1' +export const BRNAD_CLIENT_FIELDS = ['id', 'targetSystem', 'trade', 'user'] + +export const UMMOQ_CLIENT_ACRONYM = 'SL' +export const UMMOQ_CLIENT_SCHEMA = 'mdv1' +export const UMMOQ_CLIENT_FIELDS = [ + 'id', + 'targetSystem', + 'minOrderQuantity', + 'unitMultiplier', +] diff --git a/node/yarn.lock b/node/yarn.lock index 4116bfc0..48692d06 100644 --- a/node/yarn.lock +++ b/node/yarn.lock @@ -1319,10 +1319,10 @@ semver "^6.3.0" tsutils "^3.17.1" -"@vtex/api@6.41.0": - version "6.41.0" - resolved "https://registry.yarnpkg.com/@vtex/api/-/api-6.41.0.tgz#cee074ff49de8a5de92f3d353a4689275cb92f7b" - integrity sha512-RvfdpczsxCFacZkDSl2v2NmfD/bHFxHHn2xQsEwSQ+40snGxfOz56TlCbPbgMEtkC8Bf+1GGUkCIChRE6xnlLg== +"@vtex/api@6.45.3": + version "6.45.3" + resolved "https://registry.yarnpkg.com/@vtex/api/-/api-6.45.3.tgz#fe7d08adb4eab1fda5e34143cc6302a4c5aa5f52" + integrity sha512-kiD7We1TCKDyBdpYoh2Se3An+jTJRUzXGNpKifoDZylWQ1PyIx+3oL5ZAif9InlY3uJkfEisSAI6nxoKTgvPfw== dependencies: "@types/koa" "^2.11.0" "@types/koa-compose" "^3.2.3" @@ -1331,7 +1331,7 @@ agentkeepalive "^4.0.2" apollo-server-errors "^2.2.1" archiver "^3.0.0" - axios "^0.19.2" + axios "^0.21.1" axios-retry "^3.1.2" bluebird "^3.5.4" chalk "^2.4.2" @@ -1361,6 +1361,7 @@ semver "^5.5.1" stats-lite vtex/node-stats-lite#dist tar-fs "^2.0.0" + tokenbucket "^0.3.2" uuid "^3.3.3" xss "^1.0.6" @@ -1818,12 +1819,12 @@ axios@^0.19.0: follow-redirects "1.5.10" is-buffer "^2.0.2" -axios@^0.19.2: - version "0.19.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" - integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== +axios@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" + integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== dependencies: - follow-redirects "1.5.10" + follow-redirects "^1.10.0" babel-jest@^24.4.0, babel-jest@^24.9.0: version "24.9.0" @@ -1920,6 +1921,11 @@ bl@^3.0.0: dependencies: readable-stream "^3.0.1" +bluebird@2.9.24: + version "2.9.24" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.9.24.tgz#14a2e75f0548323dc35aa440d92007ca154e967c" + integrity sha1-FKLnXwVIMj3DWqRA2SAHyhVOlnw= + bluebird@^3.5.4: version "3.5.5" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" @@ -3037,6 +3043,11 @@ follow-redirects@1.5.10: dependencies: debug "=3.1.0" +follow-redirects@^1.10.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" + integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg== + follow-redirects@^1.3.0: version "1.7.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76" @@ -5520,6 +5531,11 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redis@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/redis/-/redis-0.12.1.tgz#64df76ad0fc8acebaebd2a0645e8a48fac49185e" + integrity sha1-ZN92rQ/IrOuuvSoGReikj6xJGF4= + regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -5797,6 +5813,10 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +"sbdsefuat.checkout-simulation@http://sbdsefuat.vtexassets.com/_v/public/typings/v1/sbdsefuat.checkout-simulation@1.0.31/public/@types/sbdsefuat.checkout-simulation": + version "1.0.31" + resolved "http://sbdsefuat.vtexassets.com/_v/public/typings/v1/sbdsefuat.checkout-simulation@1.0.31/public/@types/sbdsefuat.checkout-simulation#3a21fb83f00402698f84231baea53482985d2eaf" + scheduler@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e" @@ -6016,7 +6036,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"stats-lite@github:vtex/node-stats-lite#dist": +stats-lite@vtex/node-stats-lite#dist: version "2.2.0" resolved "https://codeload.github.com/vtex/node-stats-lite/tar.gz/1b0d39cc41ef7aaecfd541191f877887a2044797" dependencies: @@ -6319,6 +6339,14 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +tokenbucket@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tokenbucket/-/tokenbucket-0.3.2.tgz#8172b2b58e3083acc8d914426fed15162a3a8e90" + integrity sha1-gXKytY4wg6zI2RRCb+0VFio6jpA= + dependencies: + bluebird "2.9.24" + redis "^0.12.1" + tough-cookie@^2.3.3, tough-cookie@^2.3.4: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -6583,17 +6611,17 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -"vtex.apps-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.5.1/public/@types/vtex.apps-graphql": - version "2.5.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.5.1/public/@types/vtex.apps-graphql#3c5789b5877e6b6a3d9c4cac35a80f2c3bb8b5fe" +"vtex.apps-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.8.0/public/@types/vtex.apps-graphql": + version "2.8.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.8.0/public/@types/vtex.apps-graphql#4fd47b1281c4d36e8abb1cfa4daea83bc739eca1" -"vtex.checkout-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.44.1/public/@types/vtex.checkout-graphql": - version "0.44.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.44.1/public/@types/vtex.checkout-graphql#a8904eb6f05db2ce56842e1dbc60d0f2c6bb6924" +"vtex.checkout-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.63.0/public/@types/vtex.checkout-graphql": + version "0.63.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.63.0/public/@types/vtex.checkout-graphql#1a1f7cb496a02aaeab117b5f8da4c59dc4fee0bc" -"vtex.checkout-resources@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.36.0/public/@types/vtex.checkout-resources": - version "0.36.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.36.0/public/@types/vtex.checkout-resources#0455799f72963e227673ac17fdebdee9565c7496" +"vtex.checkout-resources@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.47.0/public/@types/vtex.checkout-resources": + version "0.47.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.47.0/public/@types/vtex.checkout-resources#8a20a179c882a2dcea62cb65750404448fc6ea30" "vtex.checkout@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout@0.6.0/public/_types/react": version "0.0.0" @@ -6603,53 +6631,53 @@ verror@1.10.0: version "0.4.4" resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.4/public/@types/vtex.css-handles#8c45c6decf9acd2b944e07261686decff93d6422" -"vtex.flex-layout@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.15.1/public/@types/vtex.flex-layout": - version "0.15.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.15.1/public/@types/vtex.flex-layout#b5e99e063dc79cf86c4a1167383e6661cfbc8e61" +"vtex.flex-layout@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.19.0/public/@types/vtex.flex-layout": + version "0.19.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.19.0/public/@types/vtex.flex-layout#042e0e1770bafdd157705abefffe0b2645a98f84" -"vtex.order-items@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.9.1/public/@types/vtex.order-items": - version "0.9.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.9.1/public/@types/vtex.order-items#ff44c030d858af223ffdfd6608200ed66fc074f8" +"vtex.order-items@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.13.1/public/@types/vtex.order-items": + version "0.13.1" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.13.1/public/@types/vtex.order-items#54122a2f6a9b6613b968313046f036ee0de355fe" -"vtex.order-manager@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.8.7/public/@types/vtex.order-manager": - version "0.8.7" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.8.7/public/@types/vtex.order-manager#d666dbf9c6d630dba38ac26e815ffaa3811933df" +"vtex.order-manager@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.11.1/public/@types/vtex.order-manager": + version "0.11.1" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.11.1/public/@types/vtex.order-manager#cc658148c5e054900c0d692a26d1ac7c872d9262" -"vtex.pixel-manager@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.4.0/public/@types/vtex.pixel-manager": - version "1.4.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.4.0/public/@types/vtex.pixel-manager#f636047e354d65f4d7691c81e799c6458407bec0" +"vtex.pixel-manager@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.8.0/public/@types/vtex.pixel-manager": + version "1.8.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.8.0/public/@types/vtex.pixel-manager#3ccfcb1927614984a5f7a3e5650c8c8d2bd3c0f4" -"vtex.render-runtime@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@7.42.0/public/@types/vtex.render-runtime": - version "7.42.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@7.42.0/public/@types/vtex.render-runtime#b76f76d8f763385cfc57452386bbd20ab6fe9e9b" +"vtex.render-runtime@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@7.44.0/public/@types/vtex.render-runtime": + version "7.44.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@7.44.0/public/@types/vtex.render-runtime#90daef60e43dfcfc45ecba5cf5b97de856b9464f" -"vtex.rich-text@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.11.2/public/@types/vtex.rich-text": - version "0.11.2" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.11.2/public/@types/vtex.rich-text#0087d1e1d18adbf054a4f3b12270d2c068f30d00" +"vtex.rich-text@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.15.0/public/@types/vtex.rich-text": + version "0.15.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.15.0/public/@types/vtex.rich-text#f23416cea64e72531069e58f1b137dfdb5b4b510" -"vtex.search-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.36.0/public/_types/react": - version "0.0.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.36.0/public/_types/react#fa7a0347e046eab3dd768998fc9252b2c0dd5aef" +"vtex.search-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.47.2/public/@types/vtex.search-graphql": + version "0.47.2" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.47.2/public/@types/vtex.search-graphql#9bc27e570e10137514135b80afebc007f651be87" -"vtex.store-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.135.0/public/@types/vtex.store-graphql": - version "2.135.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.135.0/public/@types/vtex.store-graphql#f6ebbf374aabc0840655d938a7991d09171fad58" +"vtex.store-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.147.4/public/@types/vtex.store-graphql": + version "2.147.4" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.147.4/public/@types/vtex.store-graphql#8340064d04c59b01d1b4053b3fba671552199660" "vtex.store-icons@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-icons@0.18.0/public/@types/vtex.store-icons": version "0.18.0" resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-icons@0.18.0/public/@types/vtex.store-icons#0ee94d549aa283ce3a13ab987c13eac4fdfd1bba" -"vtex.store-resources@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.73.0/public/_types/react": - version "0.0.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.73.0/public/_types/react#fa7a0347e046eab3dd768998fc9252b2c0dd5aef" +"vtex.store-resources@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.85.0/public/@types/vtex.store-resources": + version "0.85.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.85.0/public/@types/vtex.store-resources#c320bf775471cec37977bfb8af2cfccd4c857c63" -"vtex.store@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.106.0/public/@types/vtex.store": - version "2.106.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.106.0/public/@types/vtex.store#06e1105619e9b91fb61d8cd6bbdea9096a4c713d" +"vtex.store@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.120.1/public/@types/vtex.store": + version "2.120.1" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.120.1/public/@types/vtex.store#fda1d0c7a0226d7229a51a81ec3721bf23d5aa6e" -"vtex.styleguide@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.132.1/public/@types/vtex.styleguide": - version "9.132.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.132.1/public/@types/vtex.styleguide#d564344a8c50fa14a78bcd290e02afb0bc492c0f" +"vtex.styleguide@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.145.2/public/@types/vtex.styleguide": + version "9.145.2" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.145.2/public/@types/vtex.styleguide#ca64bf8408ad3eb487b0822dd68f77565c986a56" w3c-hr-time@^1.0.1: version "1.0.1" diff --git a/package.json b/package.json index 4aa2dc0f..75114199 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "husky": { "hooks": { "pre-commit": "lint-staged && yarn lint:locales && yarn locales:fix", - "pre-push": "yarn verify" + "pre-push": "yarn verify --no-verify" } }, "lint-staged": { diff --git a/react/AutocompleteBlock.tsx b/react/AutocompleteBlock.tsx index c7cbc6a7..df9da85a 100644 --- a/react/AutocompleteBlock.tsx +++ b/react/AutocompleteBlock.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import React, { useState, useContext } from 'react' import { FormattedMessage, @@ -6,18 +5,30 @@ import { injectIntl, defineMessages, } from 'react-intl' -import { Button, Tag, Input, ToastContext, IconClear } from 'vtex.styleguide' +import { + Button, + Tag, + ToastContext, + IconClear, + Spinner, + NumericStepper, +} from 'vtex.styleguide' import { OrderForm } from 'vtex.order-manager' import { OrderForm as OrderFormType } from 'vtex.checkout-graphql' import { addToCart as ADD_TO_CART } from 'vtex.checkout-resources/Mutations' import { usePWA } from 'vtex.store-resources/PWAContext' import { usePixel } from 'vtex.pixel-manager/PixelContext' import PropTypes from 'prop-types' -import QuickOrderAutocomplete from './components/QuickOrderAutocomplete' import { useCssHandles } from 'vtex.css-handles' -import { useApolloClient, useMutation } from 'react-apollo' +import { useApolloClient, useMutation, useQuery } from 'react-apollo' +import { useOrderItems } from 'vtex.order-items/OrderItems' + +import QuickOrderAutocomplete from './components/QuickOrderAutocomplete' import productQuery from './queries/product.gql' +import GET_ACCOUNT_INFO from './queries/orderSoldToAccount.graphql' +import GET_PRODUCT_DATA from './queries/getPrductAvailability.graphql' import './global.css' +import { getNewItems, itemsInSystem } from './utils' const messages = defineMessages({ success: { @@ -44,6 +55,7 @@ const messages = defineMessages({ }) const AutocompleteBlock: StorefrontFunctionComponent = ({ text, description, componentOnly, intl }) => { const client = useApolloClient() const { showToast } = useContext(ToastContext) @@ -52,6 +64,8 @@ const AutocompleteBlock: StorefrontFunctionComponent { + // eslint-disable-next-line react/prop-types return intl.formatMessage(message) } + const resolveToastMessage = (success: boolean, isNewItem: boolean) => { if (!success) return translateMessage(messages.error) if (!isNewItem) return translateMessage(messages.duplicate) return translateMessage(messages.success) } + const toastMessage = (arg: any) => { let message - let action + if (typeof arg === 'string') { + // eslint-disable-next-line react/prop-types message = intl.formatMessage(messages[arg]) } else { const { @@ -85,16 +118,11 @@ const AutocompleteBlock: StorefrontFunctionComponent { @@ -107,56 +135,76 @@ const AutocompleteBlock: StorefrontFunctionComponent { - const mutationResult = await addToCart({ - variables: { - items: items.map((item: any) => { - return { - ...item, - } - }), - }, - }) + const existItems = itemsInSystem(orderForm?.items, items) + const newItems = getNewItems(orderForm?.items, items) - if (error) { - console.error(error) - toastMessage({ success: false, isNewItem: false }) - return + if (existItems.length > 0) { + addItem(existItems) + + if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) { + showInstallPrompt() + } + + toastMessage({ success: true, isNewItem: true }) } - // Update OrderForm from the context - mutationResult.data && setOrderForm(mutationResult.data.addToCart) + if (newItems.length > 0) { + const mutationResult = await addToCart({ + variables: { + items: items.map((item: any) => { + return { + ...item, + } + }), + }, + }) + + if (error) { + console.error(error) + toastMessage({ success: false, isNewItem: false }) - const adjustSkuItemForPixelEvent = (item: any) => { - return { - skuId: item.id, - quantity: item.quantity, + return } - } - // Send event to pixel-manager - const pixelEventItems = items.map(adjustSkuItemForPixelEvent) - push({ - event: 'addToCart', - items: pixelEventItems, - }) - if ( - mutationResult.data?.addToCart?.messages?.generalMessages && - mutationResult.data.addToCart.messages.generalMessages.length - ) { - mutationResult.data.addToCart.messages.generalMessages.map((msg: any) => { - return showToast({ - message: msg.text, - action: undefined, - duration: 30000, - }) + // Update OrderForm from the context + mutationResult.data && setOrderForm(mutationResult.data.addToCart) + + const adjustSkuItemForPixelEvent = (item: any) => { + return { + skuId: item.id, + quantity: item.quantity, + } + } + + // Send event to pixel-manager + const pixelEventItems = items.map(adjustSkuItemForPixelEvent) + + push({ + event: 'addToCart', + items: pixelEventItems, }) - } else { - toastMessage({ success: true, isNewItem: true }) - clear() - } - if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) { - showInstallPrompt() + if ( + mutationResult.data?.addToCart?.messages?.generalMessages && + mutationResult.data.addToCart.messages.generalMessages.length + ) { + mutationResult.data.addToCart.messages.generalMessages.map( + (msg: any) => { + return showToast({ + message: msg.text, + action: undefined, + duration: 30000, + }) + } + ) + } else { + toastMessage({ success: true, isNewItem: true }) + clear() + } + + if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) { + showInstallPrompt() + } } return showInstallPrompt @@ -168,6 +216,7 @@ const AutocompleteBlock: StorefrontFunctionComponent ref.Key === 'RefId' + )?.Value ?? '' + + try { + const { data: productInfo } = await client.query({ + query: GET_PRODUCT_DATA, + variables: { + refIds: [refId] as string[], + customerNumber, + targetSystem, + salesOrganizationCode, + }, + }) + + if (productInfo) { + const itemsFromQuery = productInfo.getSkuAvailability?.items ?? [] + const refIdNotFound = itemsFromQuery.filter((item: any) => { + return item.sku === null + }) + + const refNotAvailable = itemsFromQuery.filter((item: any) => { + return item.availability !== 'available' + }) + + if ( + itemsFromQuery.length > 0 && + refIdNotFound.length === 0 && + refNotAvailable.length === 0 + ) { + setHideAddToCart(false) + } + } + } catch (err) { + console.error(err) + } + setState({ ...state, selectedItem: @@ -185,6 +274,7 @@ const AutocompleteBlock: StorefrontFunctionComponent { return s.sellerDefault === true }).sellerId + const newSelected = { ...selectedItem, seller, value, } + setState({ ...state, selectedItem: newSelected, @@ -220,6 +312,7 @@ const AutocompleteBlock: StorefrontFunctionComponent + const numberValidator = (minQty: number, unit: number, value: number) => { + const actualQty = value * unit + const adjustedQty = + minQty % unit === 0 + ? actualQty < minQty + ? minQty + : actualQty + : actualQty < minQty + ? minQty + (unit - (minQty % unit)) + : actualQty + + return adjustedQty / unit + } + + const numStepper = (itemSelected: any, selectedQuantity: number) => { + const minQty = + itemSelected.data.product.properties + .find( + (property: { name: string }) => + property.name === 'Minimum Order Quantity' + ) + ?.values.find(value => value) ?? 1 + + const unit = + itemSelected.data.product.items.find(item => item)?.unitMultiplier ?? 1 + + return ( +
+ { + setState({ + ...state, + quantitySelected: e.value, + }) + }} + /> +
+ ) + } + + return accountDataLoading ? ( + + ) : ( +
{!componentOnly && ( -
+

@@ -260,7 +402,7 @@ const AutocompleteBlock: StorefrontFunctionComponent
@@ -268,7 +410,10 @@ const AutocompleteBlock: StorefrontFunctionComponent} {!!selectedItem && (
-
+
@@ -314,36 +459,39 @@ const AutocompleteBlock: StorefrontFunctionComponent
-
+
- { - setState({ - ...state, - quantitySelected: e.target.value, - }) - }} - /> + {numStepper(selectedItem, quantitySelected)}
-
- -
+ +
+ ) : ( +
+ +
+ )}
@@ -371,6 +519,7 @@ const AutocompleteBlock: StorefrontFunctionComponent ) } + AutocompleteBlock.propTypes = { componentOnly: PropTypes.bool, text: PropTypes.string, @@ -385,7 +534,7 @@ interface OrderFormContext { interface MessageDescriptor { id: string - description?: string | object + description?: Record defaultMessage?: string } diff --git a/react/CategoryBlock.tsx b/react/CategoryBlock.tsx index 701464d4..395b38d7 100644 --- a/react/CategoryBlock.tsx +++ b/react/CategoryBlock.tsx @@ -82,7 +82,6 @@ const CategoryBlock: StorefrontFunctionComponent { let message - let action if (typeof arg === 'string') { message = intl.formatMessage(messages[arg]) @@ -96,16 +95,9 @@ const CategoryBlock: StorefrontFunctionComponent { @@ -276,6 +268,7 @@ const CategoryBlock: StorefrontFunctionComponent { const td = url.split('/') const ids = td[td.indexOf('ids') + 1] + return url.replace(ids, `${ids}-50-50`) } @@ -286,7 +279,7 @@ const CategoryBlock: StorefrontFunctionComponent {b.items.length ? b.items.map((content: any) => { - console.log('Content =>', content) + console.info('Content =>', content) const [referenceId] = content.referenceId const [image] = content.images @@ -305,6 +298,7 @@ const CategoryBlock: StorefrontFunctionComponent )} @@ -314,7 +308,7 @@ const CategoryBlock: StorefrontFunctionComponent - {referenceId['Value']} + {referenceId.Value} )}
diff --git a/react/TextAreaBlock.tsx b/react/TextAreaBlock.tsx index 6a596a67..1e47ba12 100644 --- a/react/TextAreaBlock.tsx +++ b/react/TextAreaBlock.tsx @@ -1,11 +1,11 @@ -import React, { useState, useContext } from 'react' +import React, { useContext, useState } from 'react' import { - FormattedMessage, defineMessages, - WrappedComponentProps, + FormattedMessage, injectIntl, + WrappedComponentProps, } from 'react-intl' -import { Button, Textarea, ToastContext, Spinner } from 'vtex.styleguide' +import { Button, Spinner, Textarea, ToastContext } from 'vtex.styleguide' import { OrderForm } from 'vtex.order-manager' import { OrderForm as OrderFormType } from 'vtex.checkout-graphql' import { addToCart as ADD_TO_CART } from 'vtex.checkout-resources/Mutations' @@ -13,9 +13,11 @@ import { useCssHandles } from 'vtex.css-handles' import { useMutation } from 'react-apollo' import { usePWA } from 'vtex.store-resources/PWAContext' import { usePixel } from 'vtex.pixel-manager/PixelContext' +import { useOrderItems } from 'vtex.order-items/OrderItems' +import { useOrderForm } from 'vtex.order-manager/OrderForm' import ReviewBlock from './components/ReviewBlock' -import { ParseText, GetText } from './utils' +import { getNewItems, GetText, itemsInSystem, ParseText } from './utils' const messages = defineMessages({ success: { @@ -66,6 +68,8 @@ const TextAreaBlock: StorefrontFunctionComponent { return intl.formatMessage(message) @@ -77,6 +81,7 @@ const TextAreaBlock: StorefrontFunctionComponent { const message = resolveToastMessage(success, isNewItem) - const action = success - ? { - label: translateMessage(messages.seeCart), - href: '/checkout/#/cart', - } - : undefined - showToast({ message, action }) + showToast({ message }) } const callAddToCart = async (items: any) => { - const mutationResult = await addToCart({ - variables: { - items: items.map((item: any) => { - return { - ...item, - } - }), - }, - }) + const existItems = itemsInSystem(orderForm?.items, items) + const newItems = getNewItems(orderForm?.items, items) + + if (existItems.length > 0) { + addItem(existItems) + + if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) { + showInstallPrompt() + } - if (mutationError) { - console.error(mutationError) - toastMessage({ success: false, isNewItem: false }) - return + toastMessage({ success: true, isNewItem: true }) } - // Update OrderForm from the context - mutationResult.data && setOrderForm(mutationResult.data.addToCart) + if (newItems.length > 0) { + const mutationResult = await addToCart({ + variables: { + items: newItems.map((item: any) => { + return { + ...item, + } + }), + }, + }) - const adjustSkuItemForPixelEvent = (item: any) => { - return { - skuId: item.id, - quantity: item.quantity, + if (mutationError) { + console.error(mutationError) + toastMessage({ success: false, isNewItem: false }) + + return } - } - // Send event to pixel-manager - const pixelEventItems = items.map(adjustSkuItemForPixelEvent) - push({ - event: 'addToCart', - items: pixelEventItems, - }) - if ( - mutationResult.data?.addToCart?.messages?.generalMessages && - mutationResult.data.addToCart.messages.generalMessages.length - ) { - mutationResult.data.addToCart.messages.generalMessages.map((msg: any) => { - return showToast({ - message: msg.text, - action: undefined, - duration: 30000, - }) + // Update OrderForm from the context + mutationResult.data && setOrderForm(mutationResult.data.addToCart) + + const adjustSkuItemForPixelEvent = (item: any) => { + return { + skuId: item.id, + quantity: item.quantity, + } + } + + // Send event to pixel-manager + const pixelEventItems = items.map(adjustSkuItemForPixelEvent) + + push({ + event: 'addToCart', + items: pixelEventItems, }) - } else { - toastMessage({ success: true, isNewItem: true }) - } - if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) { - showInstallPrompt() + if ( + mutationResult.data?.addToCart?.messages?.generalMessages && + mutationResult.data.addToCart.messages.generalMessages.length + ) { + mutationResult.data.addToCart.messages.generalMessages.map( + (msg: any) => { + return showToast({ + message: msg.text, + action: undefined, + duration: 30000, + }) + } + ) + } else { + toastMessage({ success: true, isNewItem: true }) + } + + if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) { + showInstallPrompt() + } } return showInstallPrompt } const onReviewItems = (items: any) => { + console.info('Data in the onReviewItems : ', items) + if (items) { const show = items.filter((item: any) => { - return !item.vtexSku + return !item.vtexSku || item.availability !== 'available' }).length === 0 setState({ @@ -165,6 +186,7 @@ const TextAreaBlock: StorefrontFunctionComponent { return item.error !== null }).length + setState({ ...state, reviewItems: items, @@ -198,24 +221,30 @@ const TextAreaBlock: StorefrontFunctionComponent { const items: any = reviewItems .filter((item: any) => item.error === null && item.vtexSku !== null) - .map(({ vtexSku, quantity, seller }: any) => { + .map(({ vtexSku, quantity, seller, unit }: any) => { return { id: parseInt(vtexSku, 10), - quantity: parseFloat(quantity), + quantity: parseFloat(quantity) / unit, seller, } }) + callAddToCart(items) } + const onRefidLoading = (data: boolean) => { setRefIdLoading(data) } + const backList = () => { setState({ ...state, @@ -289,17 +318,29 @@ const TextAreaBlock: StorefrontFunctionComponent {refidLoading && } - {showAddToCart && ( - + {showAddToCart ? ( +
+ +
+ ) : ( +
+ +
)}
@@ -311,7 +352,7 @@ const TextAreaBlock: StorefrontFunctionComponent { let productsArray: any = [] - const [state, setState] = useState({ - reviewItems: [], - reviewState: false, - showAddToCart: false, - }) + const [state, setState] = useState({}) + const [refidLoading, setRefIdLoading] = useState() - const { reviewItems, reviewState, showAddToCart } = state + const [reviewItems, setReviewItems] = useState([]) + const [reviewState, setReviewState] = useState(false) + const [showAddToCart, setShowAddToCart] = useState(false) const [ addToCart, @@ -64,6 +66,8 @@ const UploadBlock: StorefrontFunctionComponent { return intl.formatMessage(message) @@ -75,6 +79,7 @@ const UploadBlock: StorefrontFunctionComponent { const message = resolveToastMessage(success, isNewItem) - const action = success - ? { - label: translateMessage(messages.seeCart), - href: '/checkout/#/cart', - } - : undefined - showToast({ message, action }) + showToast({ message }) } const download = () => { @@ -106,28 +105,32 @@ const UploadBlock: StorefrontFunctionComponent { setRefIdLoading(data) } + const onReviewItems = (items: any) => { if (items) { const show = items.filter((item: any) => { - return !item.vtexSku + return !item.vtexSku || item.availability !== 'available' }).length === 0 + setReviewItems(items) + setReviewState(true) + setShowAddToCart(show) setState({ - ...state, - reviewItems: items, - reviewState: true, - showAddToCart: show, textAreaValue: GetText(items), }) } + return true } @@ -143,9 +146,9 @@ const UploadBlock: StorefrontFunctionComponent { const toJson = function toJson(workbook: any) { const result: any = {} + workbook.SheetNames.forEach((sheetName: any) => { const roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], { header: 1, }) + if (roa.length) result[sheetName] = roa }) + return result } + return (wb: any) => { let output: any = null + output = toJson(wb) + return output } })() @@ -172,11 +181,14 @@ const UploadBlock: StorefrontFunctionComponent { const f = files[0] const reader: any = new FileReader() + reader.onload = (e: any) => { let data = e.target.result + data = new Uint8Array(data) const result = processWb(XLSX.read(data, { type: 'array' })) const sheetName = Object.getOwnPropertyNames(result)[0] + result[sheetName].splice(0, 1) productsArray = result[sheetName] productsArray = productsArray.filter(item => item.length) @@ -185,9 +197,11 @@ const UploadBlock: StorefrontFunctionComponent { // error } + reader.readAsArrayBuffer(f) } @@ -198,63 +212,83 @@ const UploadBlock: StorefrontFunctionComponent {} const backList = () => { + setReviewState(false) setState({ ...state, - reviewState: false, }) } const callAddToCart = async (items: any) => { const splitBy = 10 const tempItems = items - const loopCount = Math.floor(items.length / splitBy) + 1 + + const existItems = itemsInSystem(orderForm?.items, tempItems) + const newItems = getNewItems(orderForm?.items, tempItems) + + const loopCount = Math.floor(newItems.length / splitBy) + 1 + const loopCountExist = Math.floor(existItems.length / splitBy) + 1 const promises: Array> = [] // let orderFormData = [] - for (let i = 0; i < loopCount; i++) { - const chunk = tempItems.splice(0, splitBy) - if (chunk.length) { - const mutationChunk = await addToCart({ - variables: { - items: chunk.map((item: any) => { - return { - ...item, - } - }), - }, - }) + if (existItems.length) { + for (let i = 0; i < loopCountExist; i++) { + const chunk = tempItems.splice(0, splitBy) - console.log('mutationChunk =>', mutationChunk) - - mutationChunk.data && setOrderForm(mutationChunk.data.addToCart) - - if ( - mutationChunk.data?.addToCart?.messages?.generalMessages && - mutationChunk.data.addToCart.messages.generalMessages.length - ) { - mutationChunk.data.addToCart.messages.generalMessages.map( - (msg: any) => { - return showToast({ - message: msg.text, - action: undefined, - duration: 30000, - }) - } - ) - } else { - toastMessage({ success: true, isNewItem: true }) + if (chunk.length) { + addItem(chunk) } - - promises.push(mutationChunk) } + + toastMessage({ success: true, isNewItem: true }) } - Promise.all(promises).catch(() => { - console.error(mutationError) - toastMessage({ success: false, isNewItem: false }) - return - }) + if (newItems.length > 0) { + for (let i = 0; i < loopCount; i++) { + const chunk = tempItems.splice(0, splitBy) + + if (chunk.length) { + // eslint-disable-next-line no-await-in-loop + const mutationChunk = await addToCart({ + variables: { + items: chunk.map((item: any) => { + return { + ...item, + } + }), + }, + }) + + console.info('mutationChunk =>', mutationChunk) + + mutationChunk.data && setOrderForm(mutationChunk.data.addToCart) + + if ( + mutationChunk.data?.addToCart?.messages?.generalMessages && + mutationChunk.data.addToCart.messages.generalMessages.length + ) { + mutationChunk.data.addToCart.messages.generalMessages.map( + (msg: any) => { + return showToast({ + message: msg.text, + action: undefined, + duration: 30000, + }) + } + ) + } else { + toastMessage({ success: true, isNewItem: true }) + } + + promises.push(mutationChunk) + } + } + + Promise.all(promises).catch(() => { + console.error(mutationError) + toastMessage({ success: false, isNewItem: false }) + }) + } // Update OrderForm from the context @@ -264,8 +298,10 @@ const UploadBlock: StorefrontFunctionComponent { const items: any = reviewItems .filter((item: any) => item.error === null && item.vtexSku !== null) - .map(({ vtexSku, quantity, seller }: any) => { + .map(({ vtexSku, quantity, seller, unit }: any) => { return { id: parseInt(vtexSku, 10), - quantity: parseFloat(quantity), + quantity: parseFloat(quantity) / unit, seller, } }) + callAddToCart(items) } @@ -303,7 +340,10 @@ const UploadBlock: StorefrontFunctionComponent {refidLoading && } - {showAddToCart && ( - + {showAddToCart ? ( +
+ +
+ ) : ( +
+ +
)}
@@ -414,7 +466,7 @@ const UploadBlock: StorefrontFunctionComponent { const src: any = img ? img.match(/src=["']([^"']+)/) : [] + return !!src && src.length ? src[1] : '' } @@ -31,12 +31,16 @@ const CustomOption = (props: any) => { const index = highlightableText .toLowerCase() .indexOf(searchTerm.toLowerCase()) + if (index === -1) { return highlightableText } + const prefix = highlightableText.substring(0, index) const match = highlightableText.substr(index, searchTerm.length) + // eslint-disable-next-line @typescript-eslint/restrict-plus-operands const suffix = highlightableText.substring(index + match.length) + return ( {prefix} @@ -72,6 +76,7 @@ const CustomOption = (props: any) => { ) } + interface QuickOrderAutocompleteInt { onSelect: any } @@ -90,6 +95,7 @@ const QuickOrderAutocomplete: StorefrontFunctionComponent { - if (term) { + onChange: (terms: any) => { + if (terms) { setLoading(true) if (timeoutRef.current) { clearTimeout(timeoutRef.current) } + timeoutRef.current = setTimeout(() => { setLoading(false) - setTerm(term) - handleSearch({ value: term }) + setTerm(terms) + handleSearch({ value: terms }) timeoutRef.current = null }, 1000) } else { - setTerm(term) + setTerm(terms) } }, onSearch: () => () => {}, @@ -150,6 +157,7 @@ const QuickOrderAutocomplete: StorefrontFunctionComponent } diff --git a/react/components/ReviewBlock.tsx b/react/components/ReviewBlock.tsx index 0c2a3651..65e6da36 100644 --- a/react/components/ReviewBlock.tsx +++ b/react/components/ReviewBlock.tsx @@ -1,21 +1,29 @@ /* eslint-disable vtex/prefer-early-return */ -import React, { useState, useEffect } from 'react' +import React, { useEffect, useState } from 'react' import { - Table, - Input, ButtonWithIcon, IconDelete, IconInfo, + Input, + Table, Tooltip, - Dropdown, } from 'vtex.styleguide' -import { WrappedComponentProps, injectIntl, defineMessages } from 'react-intl' +import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl' import PropTypes from 'prop-types' import { useApolloClient, useQuery } from 'react-apollo' -import { ParseText, GetText } from '../utils' -import getRefIdTranslation from '../queries/refids.gql' -import OrderFormQuery from '../queries/orderForm.gql' +import { GetText, ParseText, validateQuantity } from '../utils' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +// import getRefIdTranslation from '../queries/refids.gql' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +// import OrderFormQuery from '../queries/orderForm.gql' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import GET_PRODUCT_DATA from '../queries/getPrductAvailability.graphql' +// import { stubFalse } from 'lodash' +import GET_ACCOUNT_INFO from '../queries/orderSoldToAccount.graphql' const remove = @@ -26,6 +34,9 @@ const messages = defineMessages({ available: { id: 'store/quickorder.available', }, + unavailable: { + id: 'store/quickorder.unavailable', + }, invalidPattern: { id: 'store/quickorder.invalidPattern', }, @@ -127,7 +138,7 @@ const messages = defineMessages({ }, }) -let orderFormId = '' +// let orderFormId = '' const ReviewBlock: StorefrontFunctionComponent = ({ onReviewItems, @@ -137,12 +148,26 @@ const ReviewBlock: StorefrontFunctionComponent = ({ }: any) => { const client = useApolloClient() - const { data: orderFormData } = useQuery<{ - orderForm - }>(OrderFormQuery, { - ssr: false, - skip: !!orderFormId, - }) + // const { data: orderFormData } = useQuery<{ + // orderForm + // }>(OrderFormQuery, { + // ssr: false, + // skip: !!orderFormId, + // }) + + const { data: accountData, loading: accountDataLoading } = useQuery( + GET_ACCOUNT_INFO, + { + notifyOnNetworkStatusChange: true, + ssr: false, + } + ) + + const customerNumber = + accountData?.getOrderSoldToAccount?.customerNumber ?? '' + const targetSystem = accountData?.getOrderSoldToAccount?.targetSystem ?? '' + const salesOrganizationCode = + accountData?.getOrderSoldToAccount?.salesOrganizationCode ?? '' const [state, setReviewState] = useState({ reviewItems: @@ -156,13 +181,14 @@ const ReviewBlock: StorefrontFunctionComponent = ({ const { reviewItems } = state - if (orderFormData?.orderForm?.orderFormId) { - orderFormId = orderFormData.orderForm.orderFormId - } + // if (orderFormData?.orderForm?.orderFormId) { + // orderFormId = orderFormData.orderForm.orderFormId + // } const errorMessage = { 'store/quickorder.valid': messages.valid, 'store/quickorder.available': messages.available, + 'store/quickorder.unavailable': messages.unavailable, 'store/quickorder.invalidPattern': messages.invalidPattern, 'store/quickorder.skuNotFound': messages.skuNotFound, 'store/quickorder.withoutStock': messages.withoutStock, @@ -202,58 +228,90 @@ const ReviewBlock: StorefrontFunctionComponent = ({ const validateRefids = (refidData: any, reviewed: any) => { let error = false + reviewed = reviewed.map(i => { + const unit = refidData.getSkuAvailability?.items?.find( + d => i.sku === d.refid + )?.unitMultiplier + const minQty = refidData.getSkuAvailability?.items?.find( + d => i.sku === d.refid + )?.minQty + i.quantity = validateQuantity(minQty, unit, i.quantity) + return { + ...i, + unit, + minQty, + } + }) + if (refidData) { - const refIdNotFound = - !!refidData && !!refidData.skuFromRefIds.items - ? refidData.skuFromRefIds.items.filter((item: any) => { - return item.sku === null - }) - : [] - - const refIdFound = - !!refidData && !!refidData.skuFromRefIds.items - ? refidData.skuFromRefIds.items.filter((item: any) => { - return item.sku !== null - }) - : [] - - const refNotAvailable = - !!refidData && !!refidData.skuFromRefIds.items - ? refidData.skuFromRefIds.items.filter((item: any) => { - return item.availability !== 'available' - }) - : [] + const itemsFromQuery = refidData.getSkuAvailability?.items ?? [] + const refIdNotFound = itemsFromQuery.filter((item: any) => { + return item.sku === null + }) + + const refIdFound = itemsFromQuery.filter((item: any) => { + return item.sku !== null + }) + + const refNotAvailable = itemsFromQuery.filter((item: any) => { + return item.availability !== 'available' + }) const vtexSku = (item: any) => { - let ret: any = null + const ret: any = itemsFromQuery.find((curr: any) => { + return !!item.sku && item.sku === curr.refid + }) - if (!!refidData && !!refidData.skuFromRefIds.items) { - ret = refidData.skuFromRefIds.items.find((curr: any) => { - return !!item.sku && item.sku === curr.refid - }) - if (!!ret && !!ret.sku) { - ret = ret.sku - } - } + return ret?.sku + } - return ret + const getPrice = (item: any) => { + const ret: any = itemsFromQuery.find((curr: any) => { + return !!item.sku && item.sku === curr.refid + }) + + return ret?.price } - const getSellers = (item: any) => { - let ret: any = [] + const getAvailableQuantity = (item: any) => { + const ret: any = itemsFromQuery.find((curr: any) => { + return !!item.sku && item.sku === curr.refid + }) - if (!!refidData && !!refidData.skuFromRefIds.items) { - ret = refidData.skuFromRefIds.items.find((curr: any) => { - return !!item.sku && item.sku === curr.refid - }) - if (!!ret && !!ret.sellers) { - ret = ret.sellers - } - } + return ret?.availableQuantity + } - return ret + const getAvailability = (item: any) => { + const ret: any = itemsFromQuery.find((curr: any) => { + return !!item.sku && item.sku === curr.refid + }) + + return ret?.availability } + const getSeller = (item: any) => { + const ret: any = itemsFromQuery.find((curr: any) => { + return !!item.sku && item.sku === curr.refid + }) + + return ret?.seller + } + + // const getSellers = (item: any) => { + // let ret: any = [] + // + // if (!!refidData && !!refidData.getSkuAvailability.items) { + // ret = refidData.getSkuAvailability.items.find((curr: any) => { + // return !!item.sku && item.sku === curr.refid + // }) + // if (!!ret && !!ret.sellers) { + // ret = ret.sellers + // } + // } + // + // return ret + // } + const errorMsg = (item: any) => { let ret: any = null const notfound = refIdNotFound.find((curr: any) => { @@ -278,14 +336,16 @@ const ReviewBlock: StorefrontFunctionComponent = ({ } const items = reviewed.map((item: any) => { - const sellers = getSellers(item) + // const sellers = getSellers(item) return { ...item, - sellers: getSellers(item), - seller: sellers.length ? sellers[0].id : '1', + availableQuantity: getAvailableQuantity(item), + price: getPrice(item), vtexSku: vtexSku(item), error: errorMsg(item), + availability: getAvailability(item), + seller: getSeller(item)?.id, } }) @@ -321,14 +381,22 @@ const ReviewBlock: StorefrontFunctionComponent = ({ refids = Object.getOwnPropertyNames(refids) } - const query = { - query: getRefIdTranslation, - variables: { refids, orderFormId }, - } + try { + const { data } = await client.query({ + query: GET_PRODUCT_DATA, + variables: { + refIds: refids as string[], + customerNumber, + targetSystem, + salesOrganizationCode, + }, + }) - const { data } = await client.query(query) + validateRefids(data, reviewed) + } catch (error) { + console.error(error) + } - validateRefids(data, reviewed) onRefidLoading(false) } @@ -394,21 +462,21 @@ const ReviewBlock: StorefrontFunctionComponent = ({ }) } - const updateLineSeller = (index: number, seller: string) => { - const items = reviewItems.map((item: any) => { - return item.index === index - ? { - ...item, - seller, - } - : item - }) - - setReviewState({ - ...state, - reviewItems: items, - }) - } + // const updateLineSeller = (index: number, seller: string) => { + // const items = reviewItems.map((item: any) => { + // return item.index === index + // ? { + // ...item, + // seller, + // } + // : item + // }) + // + // setReviewState({ + // ...state, + // reviewItems: items, + // }) + // } const onBlurField = (line: number) => { const joinLines = GetText(reviewItems) @@ -470,46 +538,64 @@ const ReviewBlock: StorefrontFunctionComponent = ({ id: 'store/quickorder.review.label.quantity', }), }, - seller: { + unit: { + hidden: true, type: 'string', - title: intl.formatMessage({ - id: 'store/quickorder.review.label.seller', - }), - cellRenderer: ({ rowData }: any) => { - if (rowData?.sellers?.length > 1) { - return ( -
- { - return { - label: item.name, - value: item.id, - } - })} - value={rowData.seller} - onChange={(_: any, v: any) => - updateLineSeller(rowData.index, v) - } - /> -
- ) - } - - return rowData.sellers && rowData.sellers.length - ? rowData.sellers[0].name - : '' - }, + title: 'Unit', }, + // price: { + // type: 'string', + // title: 'Price', + // }, + // availableQuantity: { + // type: 'string', + // title: 'Available Quantity', + // }, + // seller: { + // type: 'string', + // title: intl.formatMessage({ + // id: 'store/quickorder.review.label.seller', + // }), + // cellRenderer: ({ rowData }: any) => { + // if (rowData?.sellers?.length > 1) { + // return ( + //
+ // { + // return { + // label: item.name, + // value: item.id, + // } + // })} + // value={rowData.seller} + // onChange={(_: any, v: any) => + // updateLineSeller(rowData.index, v) + // } + // /> + //
+ // ) + // } + // + // return rowData.sellers && rowData.sellers.length + // ? rowData.sellers[0].name + // : '' + // }, + // }, error: { type: 'string', title: intl.formatMessage({ id: 'store/quickorder.review.label.status', }), + cellRenderer: ({ cellData, rowData }: any) => { if (rowData.error) { const text = intl.formatMessage( - errorMessage[cellData || 'store/quickorder.valid'] + errorMessage[ + cellData !== null && cellData !== void 0 + ? cellData + : 'store/quickorder.valid' + ] ) return ( @@ -547,7 +633,9 @@ const ReviewBlock: StorefrontFunctionComponent = ({ }, } - return ( + return accountDataLoading ? ( +
+ ) : (
diff --git a/react/css.d.ts b/react/css.d.ts deleted file mode 100644 index ce1bfff4..00000000 --- a/react/css.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.css' { - const css: any - export default css -} diff --git a/react/package.json b/react/package.json index 4e5e0ecb..7be40fdf 100644 --- a/react/package.json +++ b/react/package.json @@ -31,25 +31,26 @@ "prettier": "^1.18.2", "react": "^16.9.2", "react-apollo": "^3.1.3", + "sbdsefuat.checkout-simulation": "http://sbdsefuat.vtexassets.com/_v/public/typings/v1/sbdsefuat.checkout-simulation@1.0.31/public/@types/sbdsefuat.checkout-simulation", "tslint-eslint-rules": "^5.4.0", "typescript": "3.9.7", - "vtex.apps-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.5.1/public/@types/vtex.apps-graphql", + "vtex.apps-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.8.0/public/@types/vtex.apps-graphql", "vtex.checkout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout@0.6.0/public/_types/react", - "vtex.checkout-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.44.1/public/@types/vtex.checkout-graphql", - "vtex.checkout-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.36.0/public/@types/vtex.checkout-resources", + "vtex.checkout-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.63.0/public/@types/vtex.checkout-graphql", + "vtex.checkout-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.47.0/public/@types/vtex.checkout-resources", "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.4/public/@types/vtex.css-handles", - "vtex.flex-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.15.1/public/@types/vtex.flex-layout", - "vtex.order-items": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.9.1/public/@types/vtex.order-items", - "vtex.order-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.8.7/public/@types/vtex.order-manager", - "vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.4.0/public/@types/vtex.pixel-manager", - "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.122.2/public/@types/vtex.render-runtime", - "vtex.rich-text": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.11.2/public/@types/vtex.rich-text", - "vtex.search-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.36.0/public/_types/react", - "vtex.store": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.106.0/public/@types/vtex.store", - "vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.135.0/public/@types/vtex.store-graphql", + "vtex.flex-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.19.0/public/@types/vtex.flex-layout", + "vtex.order-items": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.13.1/public/@types/vtex.order-items", + "vtex.order-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.11.1/public/@types/vtex.order-manager", + "vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.8.0/public/@types/vtex.pixel-manager", + "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.132.3/public/@types/vtex.render-runtime", + "vtex.rich-text": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.15.0/public/@types/vtex.rich-text", + "vtex.search-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.47.2/public/@types/vtex.search-graphql", + "vtex.store": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.120.1/public/@types/vtex.store", + "vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.147.4/public/@types/vtex.store-graphql", "vtex.store-icons": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-icons@0.18.0/public/@types/vtex.store-icons", - "vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.73.0/public/_types/react", - "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.132.1/public/@types/vtex.styleguide" + "vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.85.0/public/@types/vtex.store-resources", + "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.145.2/public/@types/vtex.styleguide" }, "version": "3.2.0" } diff --git a/react/queries/getPrductAvailability.graphql b/react/queries/getPrductAvailability.graphql new file mode 100644 index 00000000..e6f397c9 --- /dev/null +++ b/react/queries/getPrductAvailability.graphql @@ -0,0 +1,29 @@ +query getAvbProduct( + $refIds: [String] + $customerNumber: String + $targetSystem: String + $salesOrganizationCode: String +) { + getSkuAvailability( + refIds: $refIds + customerNumber: $customerNumber + targetSystem: $targetSystem + salesOrganizationCode: $salesOrganizationCode + ) @context(provider: "sbdsefuat.bulk-order") { + items { + refid + sku + productId + availability + seller { + id + name + } + availableQuantity + productName + price + unitMultiplier + minQty + } + } +} diff --git a/react/queries/orderSoldToAccount.graphql b/react/queries/orderSoldToAccount.graphql new file mode 100644 index 00000000..cecabdb8 --- /dev/null +++ b/react/queries/orderSoldToAccount.graphql @@ -0,0 +1,9 @@ +query OrderSoldToAccount($orderFormId: String) { + getOrderSoldToAccount(orderFormId: $orderFormId) { + cacheId + customerNumber + targetSystem + receiverName + salesOrganizationCode + } +} diff --git a/react/queries/product.gql b/react/queries/product.gql index 5debbbe0..2a6867cc 100644 --- a/react/queries/product.gql +++ b/react/queries/product.gql @@ -1,9 +1,14 @@ query Product($slug: String) { product(slug: $slug) @context(provider: "vtex.search-graphql") { productName + properties { + name + values + } items { itemId name + unitMultiplier sellers { sellerId sellerName diff --git a/react/tsconfig.json b/react/tsconfig.json index ab029180..0d0e5692 100644 --- a/react/tsconfig.json +++ b/react/tsconfig.json @@ -3,11 +3,7 @@ "alwaysStrict": true, "esModuleInterop": true, "jsx": "react", - "lib": [ - "es2017", - "dom", - "es2018.promise" - ], + "lib": ["es2017", "dom", "es2018.promise"], "module": "esnext", "moduleResolution": "node", "noImplicitAny": false, @@ -21,24 +17,12 @@ "strictNullChecks": true, "strictPropertyInitialization": true, "target": "es2017", - "typeRoots": [ - "node_modules/@types" - ], - "types": [ - "node", - "jest", - "graphql" - ] + "typeRoots": ["node_modules/@types"], + "types": ["node", "jest", "graphql"] }, - "exclude": [ - "node_modules" - ], - "include": [ - "./typings/*.d.ts", - "./**/*.tsx", - "./**/*.ts" - ], + "exclude": ["node_modules"], + "include": ["./typings/*.d.ts", "./**/*.tsx", "./**/*.ts"], "typeAcquisition": { "enable": false } -} \ No newline at end of file +} diff --git a/react/typings/gql.d.ts b/react/typings/gql.d.ts new file mode 100644 index 00000000..e13a5df5 --- /dev/null +++ b/react/typings/gql.d.ts @@ -0,0 +1,6 @@ +declare module '*.gql' { + import { DocumentNode } from 'gql' + + const value: DocumentNode + export default value +} diff --git a/react/typings/storefront.d.ts b/react/typings/storefront.d.ts index 50330333..b6b03d8a 100644 --- a/react/typings/storefront.d.ts +++ b/react/typings/storefront.d.ts @@ -1,13 +1,15 @@ import { FunctionComponent } from 'react' declare global { - interface StorefrontFunctionComponent

extends FunctionComponent

{ - getSchema?(props: P): object - schema?: object + interface StorefrontFunctionComponent

+ extends FunctionComponent

{ + getSchema?(props: P): GenericObject + schema?: GenericObject } - interface StorefrontComponent

extends Component { - getSchema?(props: P): object - schema: object + interface StorefrontComponent

+ extends Component { + getSchema?(props: P): GenericObject + schema: GenericObject } } diff --git a/react/typings/vtex.checkout-resources.d.ts b/react/typings/vtex.checkout-resources.d.ts new file mode 100644 index 00000000..8e01925d --- /dev/null +++ b/react/typings/vtex.checkout-resources.d.ts @@ -0,0 +1 @@ +declare module 'vtex.checkout-resources/*' diff --git a/react/typings/vtex.order-items.d.ts b/react/typings/vtex.order-items.d.ts new file mode 100644 index 00000000..1560cd8b --- /dev/null +++ b/react/typings/vtex.order-items.d.ts @@ -0,0 +1 @@ +declare module 'vtex.order-items/OrderItems' diff --git a/react/typings/vtex.order-manager.d.ts b/react/typings/vtex.order-manager.d.ts new file mode 100644 index 00000000..c5dc4b37 --- /dev/null +++ b/react/typings/vtex.order-manager.d.ts @@ -0,0 +1 @@ +declare module 'vtex.order-manager/OrderForm' diff --git a/react/typings/vtex.pixel-manager.d.ts b/react/typings/vtex.pixel-manager.d.ts new file mode 100644 index 00000000..c37b3458 --- /dev/null +++ b/react/typings/vtex.pixel-manager.d.ts @@ -0,0 +1 @@ +declare module 'vtex.pixel-manager/PixelContext' diff --git a/react/typings/vtex.render-runtime.d.ts b/react/typings/vtex.render-runtime.d.ts index 00cdf463..a3872d87 100644 --- a/react/typings/vtex.render-runtime.d.ts +++ b/react/typings/vtex.render-runtime.d.ts @@ -25,13 +25,14 @@ declare module 'vtex.render-runtime' { } export const ChildBlock: ComponentType - export const useChildBlock = function({ id: string }): object {} + export const useChildBlock = function({ id: string }): any {} export const Helmet: ReactElement export const Link: ReactType export const NoSSR: ReactElement export const RenderContextConsumer: ReactElement export const canUseDOM: boolean + // eslint-disable-next-line @typescript-eslint/ban-types export const withRuntimeContext: ( Component: ComponentType ) => ComponentType diff --git a/react/typings/vtex.store-resources.d.ts b/react/typings/vtex.store-resources.d.ts new file mode 100644 index 00000000..2938c8ef --- /dev/null +++ b/react/typings/vtex.store-resources.d.ts @@ -0,0 +1 @@ +declare module 'vtex.store-resources/PWAContext' diff --git a/react/typings/vtex.styleguide.d.ts b/react/typings/vtex.styleguide.d.ts index 231ca463..b33a274c 100644 --- a/react/typings/vtex.styleguide.d.ts +++ b/react/typings/vtex.styleguide.d.ts @@ -2,8 +2,33 @@ declare module 'vtex.styleguide' { import { ComponentType } from 'react' export const Input: ComponentType + export const Button: ComponentType + export const ToastContext: Context<{ showToast: any }> + export const IconClear: ComponentType + export const Tag: ComponentType + export const Table: ComponentType + export const ButtonWithIcon: ComponentType + export const IconDelete: ComponentType + export const IconInfo: ComponentType + export const Tooltip: ComponentType + export const Spinner: ComponentType + export const Textarea: ComponentType + export const Dropzone: ComponentType + export const AutocompleteInput: ComponentType + export const Collapsible: ComponentType + export const NumericStepper: ComponentType interface InputProps { [key: string]: any } + + interface NumericStepperProps { + size: NumericSize + value: number + minValue: number + maxValue?: number + unitMultiplier: number + suffix?: string + onChange: (e: any) => void + } } diff --git a/react/utils/index.ts b/react/utils/index.ts index 299e21a3..09908a8f 100644 --- a/react/utils/index.ts +++ b/react/utils/index.ts @@ -4,9 +4,34 @@ export const GetText = (items: any) => { return line.content }) .join('\n') + return joinLines } +const removeDuplicates = (itemList: any) => { + const map = new Map() + + itemList.forEach(item => { + const key = item.sku + const collection = map.get(key) + + if (!collection) { + map.set(key, item) + } else { + // eslint-disable-next-line @typescript-eslint/restrict-plus-operands + collection.quantity += item.quantity + collection.content = `${key},${collection.quantity}` + } + }) + + return Array.from(map, ([, value]) => value) +} + +/** + * + * @param textAreaValue + * @constructor + */ export const ParseText = (textAreaValue: string) => { const rawText: any = String(textAreaValue || '') const arrText = String(rawText).split(/[\n\r]/) @@ -16,6 +41,7 @@ export const ParseText = (textAreaValue: string) => { }) .map((line: any, index: number) => { const lineSplitted: any = line.split(',') + if (lineSplitted.length === 2) { if ( !!lineSplitted[0] && @@ -33,6 +59,7 @@ export const ParseText = (textAreaValue: string) => { } } } + return { index, line: index, @@ -42,5 +69,63 @@ export const ParseText = (textAreaValue: string) => { error: 'store/quickorder.invalidPattern', } }) - return items + + return removeDuplicates(items) } + +/** + * + * @param orderFormItems + * @param itemsList + */ +export const itemsInSystem = (orderFormItems, itemsList) => { + return itemsList.filter(item => + // eslint-disable-next-line eqeqeq + orderFormItems.some(data => data.id == item.id) + ) +} + +/** + * + * @param orderFormItems + * @param itemsList + */ +export const getNewItems = (orderFormItems, itemsList) => { + return itemsList.filter( + item => + // eslint-disable-next-line eqeqeq + !orderFormItems.some(data => data.id == item.id) + ) +} + +export const validateQuantity = (minQty: number, unit: number, qty: number) => { + qty = Math.round(qty / unit) + + const actualQty = qty * unit + + return minQty % unit === 0 + ? actualQty < minQty + ? minQty + : actualQty + : actualQty < minQty + ? minQty + (unit - (minQty % unit)) + : actualQty +} + +// export const groupItems = (orderFormItems, itemsList) => { +// const existItems = itemsList.filter(item => +// // eslint-disable-next-line eqeqeq +// orderFormItems.some(data => data.id == item.id) +// ) +// +// const newItems = itemsList.filter( +// item => +// // eslint-disable-next-line eqeqeq +// !orderFormItems.some(data => data.id == item.id) +// ) +// +// console.info('Exist Items : ', existItems) +// console.info('New Items : ', newItems) +// +// // itemsList.map(data => console.info('messss :', data)) +// } diff --git a/react/yarn.lock b/react/yarn.lock index 3c778309..ef9c9888 100644 --- a/react/yarn.lock +++ b/react/yarn.lock @@ -4922,6 +4922,10 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +"sbdsefuat.checkout-simulation@http://sbdsefuat.vtexassets.com/_v/public/typings/v1/sbdsefuat.checkout-simulation@1.0.31/public/@types/sbdsefuat.checkout-simulation": + version "1.0.31" + resolved "http://sbdsefuat.vtexassets.com/_v/public/typings/v1/sbdsefuat.checkout-simulation@1.0.31/public/@types/sbdsefuat.checkout-simulation#3a21fb83f00402698f84231baea53482985d2eaf" + scheduler@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" @@ -5541,17 +5545,17 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -"vtex.apps-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.5.1/public/@types/vtex.apps-graphql": - version "2.5.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.5.1/public/@types/vtex.apps-graphql#3c5789b5877e6b6a3d9c4cac35a80f2c3bb8b5fe" +"vtex.apps-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.8.0/public/@types/vtex.apps-graphql": + version "2.8.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.apps-graphql@2.8.0/public/@types/vtex.apps-graphql#4fd47b1281c4d36e8abb1cfa4daea83bc739eca1" -"vtex.checkout-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.44.1/public/@types/vtex.checkout-graphql": - version "0.44.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.44.1/public/@types/vtex.checkout-graphql#a8904eb6f05db2ce56842e1dbc60d0f2c6bb6924" +"vtex.checkout-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.63.0/public/@types/vtex.checkout-graphql": + version "0.63.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-graphql@0.63.0/public/@types/vtex.checkout-graphql#1a1f7cb496a02aaeab117b5f8da4c59dc4fee0bc" -"vtex.checkout-resources@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.36.0/public/@types/vtex.checkout-resources": - version "0.36.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.36.0/public/@types/vtex.checkout-resources#0455799f72963e227673ac17fdebdee9565c7496" +"vtex.checkout-resources@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.47.0/public/@types/vtex.checkout-resources": + version "0.47.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout-resources@0.47.0/public/@types/vtex.checkout-resources#8a20a179c882a2dcea62cb65750404448fc6ea30" "vtex.checkout@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.checkout@0.6.0/public/_types/react": version "0.0.0" @@ -5561,53 +5565,53 @@ verror@1.10.0: version "0.4.4" resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.4/public/@types/vtex.css-handles#8c45c6decf9acd2b944e07261686decff93d6422" -"vtex.flex-layout@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.15.1/public/@types/vtex.flex-layout": - version "0.15.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.15.1/public/@types/vtex.flex-layout#b5e99e063dc79cf86c4a1167383e6661cfbc8e61" +"vtex.flex-layout@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.19.0/public/@types/vtex.flex-layout": + version "0.19.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.19.0/public/@types/vtex.flex-layout#042e0e1770bafdd157705abefffe0b2645a98f84" -"vtex.order-items@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.9.1/public/@types/vtex.order-items": - version "0.9.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.9.1/public/@types/vtex.order-items#ff44c030d858af223ffdfd6608200ed66fc074f8" +"vtex.order-items@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.13.1/public/@types/vtex.order-items": + version "0.13.1" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-items@0.13.1/public/@types/vtex.order-items#54122a2f6a9b6613b968313046f036ee0de355fe" -"vtex.order-manager@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.8.7/public/@types/vtex.order-manager": - version "0.8.7" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.8.7/public/@types/vtex.order-manager#d666dbf9c6d630dba38ac26e815ffaa3811933df" +"vtex.order-manager@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.11.1/public/@types/vtex.order-manager": + version "0.11.1" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.order-manager@0.11.1/public/@types/vtex.order-manager#cc658148c5e054900c0d692a26d1ac7c872d9262" -"vtex.pixel-manager@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.4.0/public/@types/vtex.pixel-manager": - version "1.4.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.4.0/public/@types/vtex.pixel-manager#f636047e354d65f4d7691c81e799c6458407bec0" +"vtex.pixel-manager@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.8.0/public/@types/vtex.pixel-manager": + version "1.8.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.8.0/public/@types/vtex.pixel-manager#3ccfcb1927614984a5f7a3e5650c8c8d2bd3c0f4" -"vtex.render-runtime@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.122.2/public/@types/vtex.render-runtime": - version "8.122.2" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.122.2/public/@types/vtex.render-runtime#fa235be2fa6995d12f03f92b20dd3eebb4f3c5fb" +"vtex.render-runtime@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.132.3/public/@types/vtex.render-runtime": + version "8.132.3" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.132.3/public/@types/vtex.render-runtime#c7dd142e384f38bd7a7c841543b73e9349fadc93" -"vtex.rich-text@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.11.2/public/@types/vtex.rich-text": - version "0.11.2" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.11.2/public/@types/vtex.rich-text#0087d1e1d18adbf054a4f3b12270d2c068f30d00" +"vtex.rich-text@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.15.0/public/@types/vtex.rich-text": + version "0.15.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.rich-text@0.15.0/public/@types/vtex.rich-text#f23416cea64e72531069e58f1b137dfdb5b4b510" -"vtex.search-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.36.0/public/_types/react": - version "0.0.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.36.0/public/_types/react#fa7a0347e046eab3dd768998fc9252b2c0dd5aef" +"vtex.search-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.47.2/public/@types/vtex.search-graphql": + version "0.47.2" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.47.2/public/@types/vtex.search-graphql#9bc27e570e10137514135b80afebc007f651be87" -"vtex.store-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.135.0/public/@types/vtex.store-graphql": - version "2.135.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.135.0/public/@types/vtex.store-graphql#f6ebbf374aabc0840655d938a7991d09171fad58" +"vtex.store-graphql@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.147.4/public/@types/vtex.store-graphql": + version "2.147.4" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.147.4/public/@types/vtex.store-graphql#8340064d04c59b01d1b4053b3fba671552199660" "vtex.store-icons@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-icons@0.18.0/public/@types/vtex.store-icons": version "0.18.0" resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-icons@0.18.0/public/@types/vtex.store-icons#0ee94d549aa283ce3a13ab987c13eac4fdfd1bba" -"vtex.store-resources@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.73.0/public/_types/react": - version "0.0.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.73.0/public/_types/react#fa7a0347e046eab3dd768998fc9252b2c0dd5aef" +"vtex.store-resources@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.85.0/public/@types/vtex.store-resources": + version "0.85.0" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.85.0/public/@types/vtex.store-resources#c320bf775471cec37977bfb8af2cfccd4c857c63" -"vtex.store@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.106.0/public/@types/vtex.store": - version "2.106.0" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.106.0/public/@types/vtex.store#06e1105619e9b91fb61d8cd6bbdea9096a4c713d" +"vtex.store@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.120.1/public/@types/vtex.store": + version "2.120.1" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.120.1/public/@types/vtex.store#fda1d0c7a0226d7229a51a81ec3721bf23d5aa6e" -"vtex.styleguide@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.132.1/public/@types/vtex.styleguide": - version "9.132.1" - resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.132.1/public/@types/vtex.styleguide#d564344a8c50fa14a78bcd290e02afb0bc492c0f" +"vtex.styleguide@http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.145.2/public/@types/vtex.styleguide": + version "9.145.2" + resolved "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.145.2/public/@types/vtex.styleguide#ca64bf8408ad3eb487b0822dd68f77565c986a56" w3c-hr-time@^1.0.1: version "1.0.1"