Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Seller Quotes] feat: verify if seller accepts quotes to process splitting and notify #59

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
344c77f
feat: add new markeplace splitting quotes on graphql
brunass Nov 26, 2024
a9ece27
feat: checking new field quotesManagedBy when value is SELLER
tiago-freire Nov 30, 2024
d40f705
docs: update CHANGELOG
tiago-freire Dec 2, 2024
58ff10b
feat: add configuration for quote creation
brunass Dec 4, 2024
3cae023
feat: add adjustment for quote seller
brunass Dec 6, 2024
df48022
chore: fix prettier errors
tiago-freire Dec 6, 2024
85622cb
fix: returning ids separated by commas when multiple quotes
tiago-freire Dec 6, 2024
b3a2c6c
fix: check config and default settings with marketplace option
tiago-freire Dec 9, 2024
b3450d2
Merge branch 'quotes-b2b-marketplace-splitting' of github.com:cubos-v…
tiago-freire Dec 9, 2024
ffeadeb
feat: new fields for quotes managed by seller
tiago-freire Dec 9, 2024
1d8b309
feat: new fields to save parent quote; change getQuotes query to filt…
tiago-freire Dec 10, 2024
3613262
feat: create client to notify seller quote
tiago-freire Dec 10, 2024
f81db01
feat: add changelog
brunass Dec 10, 2024
9af7ee0
feat: verify and notify seller quote
tiago-freire Dec 11, 2024
caccc46
chore: removes console.log from SellerQuotesClient
tiago-freire Dec 11, 2024
5c5771f
Merge branch 'feat/splitting-quote-by-seller' of github.com:cubos-vte…
tiago-freire Dec 11, 2024
34901e0
docs: update CHANGELOG and prettier fix on markdown
tiago-freire Dec 14, 2024
70d1c4d
fix: right splitting of seller quotes
tiago-freire Dec 14, 2024
e2730f8
Merge branch 'quotes-b2b-marketplace-splitting' of github.com:cubos-v…
tiago-freire Dec 14, 2024
69d2076
feat: refactor on creating seller quote map; avoid double check of se…
tiago-freire Dec 15, 2024
92ef22e
Merge branch 'feat/notify-seller-quote' of github.com:cubos-vtex/b2b-…
tiago-freire Dec 15, 2024
fbb6529
refactor: seller quotes client constants
tiago-freire Dec 15, 2024
021b359
feat: send creationDate on notify seller quote
tiago-freire Dec 15, 2024
f6a1117
fix: removing approvedBySeller field from quote entity
tiago-freire Dec 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add field quotesManagedBy on appSettings to handle splitting quotes
- Process splitting quote by seller if it accepts to manage quotes
- Notify seller with quote reference data as payload

## [2.6.4] - 2024-10-31

### Fixed

- Only update Status, LastUpdate and UpdateHistory, in expired quotes

## [2.6.3] - 2024-10-30

### Fixed

- Set viewedByCustomer value False when value is null

## [2.6.2] - 2024-10-02

### Added

- Add audit access metrics to all graphql APIs

## [2.6.1] - 2024-09-09

### Fixed

- Set viewedByCustomer value corectly on quote creation

## [2.6.0] - 2024-09-04

### Added

- Add getQuoteEnabledForUser query to be used by the b2b-quotes app

## [2.5.4] - 2024-08-20

### Fixed

- Use listUsersPaginated internally instead of deprecated listUsers

## [2.5.3] - 2024-06-10
Expand Down Expand Up @@ -76,15 +88,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2.3.1] - 2023-09-13

### Fixed

- Use the account to get the token in the header and send it to clear the cart and order

## [2.3.0] - 2023-08-14

### Added

- Send metrics to Analytics (Create Quote and Send Message events)
- Send use quote metrics to Analytics
- Send use quote metrics to Analytics

### Removed

- [ENGINEERS-1247] - Disable cypress tests in PR level

### Changed
Expand Down
6 changes: 6 additions & 0 deletions graphql/appSettings.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ type AppSettings {
}
type AdminSetup {
cartLifeSpan: Int
quotesManagedBy: QuotesManagedBy!
}
input AppSettingsInput {
cartLifeSpan: Int
quotesManagedBy: QuotesManagedBy
}
enum QuotesManagedBy {
MARKETPLACE
SELLER
}
4 changes: 4 additions & 0 deletions graphql/quote.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ type Quote {
viewedBySales: Boolean
viewedByCustomer: Boolean
salesChannel: String
seller: String
approvedBySeller: Boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to have a field only for the seller's approval. A seller quote should use the same status as a regular quote. The only additional information is the seller's name, so you can query this information later.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We understand that once the seller accepts the quote, there is no need to make the request to the seller again. approvedBySeller starts with false when the seller is notified and can become true depending on their approval. The first time the marketplace requests this data, it can save it so that it does not need to be requested again if the seller has approved the quote.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, i think you are right. We can just use the status for seller approval control.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done at f6a1117

parentQuote: String
Copy link
Contributor

@Matheus-Aguilar Matheus-Aguilar Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the split, all quotes are independent. So there is no need to keep a parent quote or children data.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without a link between the sellers quotes and the "parent" quote, it would not be possible to create this screen, for example: https://www.figma.com/design/SDETDCU5obc4Kg4WtmG6FH/RedCloud-%C2%B7-Seller-Quotes-%5BCubos%5D?node-id=263-24328&t=daYlrwPapSKRVfZN-4.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The where assembly that brings the quotes at marketplace side was changed because of this, always adding parentQuote is null in searches: https://github.com/vtex-apps/b2b-quotes-graphql/pull/59/files#diff-9766252b6f3131ecfc785f3869d3129273b19c4a91b52963b62c5d3803c964d7

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "link" between the quotes should be just a name or label and not a parent quote. It's name displayed in this screen

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a relationship based on a string that is input by the user?

hasChildren: Boolean
}

type QuoteUpdate {
Expand Down
62 changes: 62 additions & 0 deletions node/clients/SellerQuotesClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { InstanceOptions, IOContext } from '@vtex/api'
import { ExternalClient } from '@vtex/api'

const SELLER_CLIENT_OPTIONS: InstanceOptions = {
retries: 5,
timeout: 5000,
exponentialTimeoutCoefficient: 2,
exponentialBackoffCoefficient: 2,
initialBackoffDelay: 100,
}

const BASE_PATH = 'b2b-seller-quotes/_v/0'

const ROUTES = {
verifyQuoteSettings: 'verify-quote-settings',
notifyNewQuote: 'notify-new-quote',
}

export default class SellerQuotesClient extends ExternalClient {
constructor(ctx: IOContext, options?: InstanceOptions) {
super('', ctx, {
...options,
...SELLER_CLIENT_OPTIONS,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
VtexIdclientAutCookie: ctx.authToken,
},
})
}

private getRoute(sellerAccount: string, path: string) {
const subdomain = this.context.production
? sellerAccount
: `${this.context.workspace}--${sellerAccount}`

return `http://${subdomain}.myvtex.com/${BASE_PATH}/${path}`
}

public async verifyQuoteSettings(sellerAccount: string) {
return this.http.get<VerifyQuoteSettingsResponse>(
this.getRoute(sellerAccount, ROUTES.verifyQuoteSettings)
)
}

public async notifyNewQuote(
sellerAccount: string,
quoteId: string,
creationDate: string
) {
const payload: SellerQuoteNotifyInput = {
quoteId,
creationDate,
marketplaceAccount: this.context.account,
}

return this.http.postRaw(
this.getRoute(sellerAccount, ROUTES.notifyNewQuote),
payload
)
}
}
5 changes: 5 additions & 0 deletions node/clients/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import OrdersClient from './OrdersClient'
import Organizations from './organizations'
import StorefrontPermissions from './storefrontPermissions'
import VtexId from './vtexId'
import SellerQuotesClient from './SellerQuotesClient'

export const getTokenToHeader = (ctx: IOContext) => {
// provide authToken (app token) as an admin token as this is a call
Expand Down Expand Up @@ -86,4 +87,8 @@ export class Clients extends IOClients {
public get identity() {
return this.getOrSet('identity', Identity)
}

public get sellerQuotes() {
return this.getOrSet('sellerQuotes', SellerQuotesClient)
}
}
28 changes: 28 additions & 0 deletions node/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export const QUOTE_FIELDS = [
'viewedBySales',
'viewedByCustomer',
'salesChannel',
'seller',
'approvedBySeller',
'parentQuote',
'hasChildren',
]

export const routes = {
Expand Down Expand Up @@ -134,6 +138,22 @@ export const schema = {
title: 'Viewed by Sales',
type: 'boolean',
},
seller: {
title: 'Seller',
type: ['null', 'string'],
},
approvedBySeller: {
title: 'Quote approved by seller',
type: ['null', 'boolean'],
},
parentQuote: {
title: 'Parent quote',
type: ['null', 'string'],
},
hasChildren: {
title: 'Has children',
type: ['null', 'boolean'],
},
},
'v-cache': false,
'v-default-fields': [
Expand All @@ -145,6 +165,10 @@ export const schema = {
'items',
'subtotal',
'status',
'seller',
'approvedBySeller',
'parentQuote',
'hasChildren',
],
'v-immediate-indexing': true,
'v-indexed': [
Expand All @@ -157,5 +181,9 @@ export const schema = {
'organization',
'costCenter',
'salesChannel',
'seller',
'approvedBySeller',
'parentQuote',
'hasChildren',
],
}
12 changes: 0 additions & 12 deletions node/metrics/createQuote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,6 @@ type UserData = {
roleId: string
}

type SessionData = {
Matheus-Aguilar marked this conversation as resolved.
Show resolved Hide resolved
namespaces: {
profile: {
id: { value: string }
email: { value: string }
}
account: {
accountName: { value: string }
}
}
}

type CreateQuoteMetricParam = {
sessionData: SessionData
sendToSalesRep: boolean
Expand Down
2 changes: 1 addition & 1 deletion node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"ramda": "^0.25.0",
"atob": "^2.1.2",
"axios": "0.27.2",
"@vtex/api": "6.47.0"
"@vtex/api": "6.48.0"
},
"devDependencies": {
"@types/atob": "^2.1.2",
Expand Down
Loading