Skip to main content

Interacting with products

The "Catalog" schema is one of the fundamentals in shop management. It will also allow you to retrieve products from the catalog and to edit them, manage your stock ...

Introduction#

The product catalog is built from different schemas and their relationships. The schemas that make it up are listed below:

To illustrate the schema of the product catalog, it is important to analyze the following graph where the relationships between the listed schemas are represented.

Some explanations:

  • Each VariantPrice has a unique Price, for example "Tarif Boutique" or "Tarif Ecommerce.
  • Each Product has a Category (represented as folder in the application) and a unique Tax (20%, 10%, 5.5% ...).
  • Each Product has a list of Variant, where each variant represents the same product with different characteristics (alcohol volume, quantity, year ...)
  • Each Variant has a stock property which lets you know the stock at a given time. The entity StockActivity gives a history of stock increments and decrementations on the Variant.

Ahead of this documentation, each schema is explained separately.

Fetch a product data#

note

We highly recommend to check the Playground Guide and test it yourself!

After analyzing the flowchart, we can see that the product query is very complete, it reaches many levels of relationships and details through the diagrams.

Thus, to include all the fundamental fields while keeping it simple, it is possible to use the following query:

REQUEST /graphql

query {
product(id: "e59b278f-c86c-4024-acc9-7e8e89802c0d") {
id
name
kind
producer
category {
name
}
tax {
name
}
variants {
edges {
node {
name
stock {
rawQuantity
formattedQuantity
}
variantPrices {
edges {
node {
valueIncludingTax
valueExcludingTax
toQuantity
fromQuantity
price {
name
taxIncluded
}
}
}
}
stockActivities {
edges {
node {
kind
quantity
}
}
}
}
}
}
}
}

RESPONSE /graphql

{
"data": {
"product": {
"id": "e59b278f-c86c-4024-acc9-7e8e89802c0d",
"name": "Samorens",
"kind": "WINE",
"producer": "Ferraton",
"category": {
"name": "Blanc"
},
"tax": {
"name": "TVA 20%"
},
"variants": {
"edges": [
{
"node": {
"name": "2018, 0.75L",
"stock": {
"rawQuantity": 5,
"formattedQuantity": "5"
},
"variantPrices": {
"edges": [
{
"node": {
"valueIncludingTax": 16,
"valueExcludingTax": 13.33,
"toQuantity": null,
"fromQuantity": null,
"price": {
"name": "Tarif Pro",
"taxIncluded": false
}
}
},
{
"node": {
"valueIncludingTax": 13.5,
"valueExcludingTax": 11.25,
"toQuantity": -1,
"fromQuantity": 6,
"price": {
"name": "Tarif Cave",
"taxIncluded": true
}
}
},
{
"node": {
"valueIncludingTax": 14,
"valueExcludingTax": 11.6,
"toQuantity": 5,
"fromQuantity": 1,
"price": {
"name": "Tarif Cave",
"taxIncluded": true
}
}
}
]
},
"stockActivities": {
"edges": [
{
"node": {
"kind": "SALE",
"quantity": 1
}
},
{
"node": {
"kind": "RESET",
"quantity": 6
}
}
]
}
}
}
]
}
}
}
}

Yes, it's a giant query.

Thanks to this query, we can perceive the power and simplicity of GraphQL: it is possible to retrieve very complex data easily.

We now have all the fundamental elements of a product sheet gathered in the same query! For the rest of this guide, we will come back to some details and particularities of the responses of this query.

General use#

Product variants#

Each product has one or more variants. A variant can correspond to a specific capacity/vintage... For example, the same wine can be sold in "BIB" or "0,75L" format. This will result in the presence of two Variant entities on the same Product entity.

REQUEST /graphql

query {
products {
edges {
node {
name
variants {
edges {
node {
name
stock {
rawQuantity
}
}
}
}
}
}
}
}

RESPONSE /graphql

{
"data": {
"products": {
"edges": [
{
"node": {
"name": "Samorens",
"variants": {
"edges": [
{
"node": {
"name": "2018, 0.75L",
"stock": {
"rawQuantity": 12
}
}
}
{
"node": {
"name": "2018, BIB 10L",
"stock": {
"rawQuantity": 4
}
}
}
]
}
}
}
]
}
}
}

Note that each variant of a product has its own stock and selling prices.

Kind of product#

A merchant can sell several kinds of products in his store, each with its own business specificities. Today there are four kinds of product in Wino:

  • SPIRITUROUS: composes the group of distillates and beverages with high alcohol content. E.g. vodkas, whiskys, etc.
  • WINE: composes the group of wines. It is possible to see in the schema Product that the product has several other properties that further characterize this group of products. For example, productWineType, productWhiteWineType, color, etc.
  • BEER: composes the group of beers. It is possible to see in the schema Product that the product has several other properties that further characterize this group of products. For example, beerType, color, etc.
  • SIMPLE: composes the group of simple drinks and other products related to the target market. E.g. juices, cheeses, etc.

Within the Variant and Product schemas, we therefore bring together different specific types to allow retailers to better segment and categorize their product references.

The following query will give one example of each kind and their specifications (to be run in the playground !).

REQUEST /graphql

query {
products {
edges {
node {
id
name
kind
producer
country
# Specific fields for wines and beers
color
# Specific fields for wines
region
designation
wineType
# Specific fields for beers
beerType
}
}
}
}

Formatted data#

All fields that start with formatted are automatically generated by the API from schema information. The idea related to these fields is to perform the necessary formatting, reducing the work for the front-end. In this sense, the information processing is even more located in the back-end and these variables are not allocated in the database, only generated from your call in queries. These fields should not be inserted in mutations and can be searched within queries.

For example, the formattedName field of the Variant schema is the composition of the name of the product associated and the name of the variant.

Here is an example query to check the formatted fields related to the product:

REQUEST /graphql

query {
products {
edges {
node {
id
category {
# A formatted field on `Category`
formattedName
}
variants {
edges {
node {
id
# Some formatted fields on `Variant`
formattedName
formattedDescription
}
}
}
}
}
}
}

Bulk variants#

Products can be sold individually or in bulk within the checkout application. Some, it's possible that the same product is sold in many different ways. For example, A cheese can be packaged individually with a fixed capacity or sold by the cut with a varying capacity.

In this sense, the creation of a product variation is fundamental so that the same product can be managed and distributed in its different forms.

In the following example, a "cheese" product can be defined in three different ways:

REQUEST /graphql

query {
products {
edges {
node {
variants {
edges {
node {
## Formatted properties
formattedName
formattedDescription
# Bulk properties
bulk
capacityUnit
capacityPrecision
capacityValue
}
}
}
}
}
}
}

RESPONSE /graphql

{
"data": {
"products": {
"edges": [
{
"node": {
"variants": {
"edges": [
{
"node": {
"id": "ad5cbe9d-d740-4d8b-a09d-1c6fbc25eb23",
"formattedName": "Brie de Meaux - À l'unité",
"formattedDescription": "Meaux, France",
"bulk": false,
"capacityUnit": null,
"capacityPrecision": null,
"capacityValue": null
}
}
]
}
}
}
]
}
}
}

After analysis of the code, there are several possible cases:

  • When a product is sold in bulk, the capacityUnit and cacpacityPrecision properties must be defined.
  • When a product is sold individually, the capacityUnit, capacityPrecision and capacityValue properties may or may not be defined. It depends on whether the merchant wished to enter these details. It's all or nothing.

It can also be noted that the formattedName field is closely related to these capability properties.

Stock management#

After defining the properties of each product, customizing its features, etc., it's necessary to manage its distribution. For this, the first step is stock management. Stock management is the process related to the calculation, analysis and valuation of the stock of each variant.

The stock management is performed for each variant around the stock object schema:

fragement variant on Variant {
stock {
# Quantity
rawQuantity
formattedQuantity
# State
stockState
# Valuation
rawValuation
formattedValuation
}
}

Use the following query to check the stock of the product:

REQUEST /graphql

query {
products {
edges {
node {
variants {
edges {
node {
stock {
# Quantity
rawQuantity
formattedQuantity
# State
state
# Valuation
rawValuation
formattedValuation
}
}
}
}
}
}
}
}

To go through this example, the stock management is divided into three parts: quantity, state and valuation.

Quantity

The stock quantity of each variant is present in the rawQuantity attribute (in its raw form) and the formattedQuantity attribute (in its formatted form).

The following examples can be observed:

{
"stock": {
"rawQuantity": 10,
"formattedQuantity": "10"
}
}

In the case of a bulk product, the capacityUnit and capacityPrecision properties will be used to format the stock quantity.

State

The stock state has three possible values: OK, ALERT or DANGER. The assignment of these depends on the quantities. Taking a general rule you can assign the meanings:

  • OK: the quantity in stock does not yet present a risk of stock shortage (customized for each type of variant).
  • ALERT: the stock quantity is on the threshold between a safe quantity and the possible stock shortage in case of an unplanned sale.
  • DANGER: out of stock.

Valuation

The idea of stock valuation is based on the weighted average cost.

This cost relates the total cost of purchase and the quantity on a given date. Therefore, the stock valuation is recalculated after each stock activity so that it is possible to always have the current stock value.

Multiple selling prices#

A product can be sold at different prices. For example, a bottle of wine may be sold individually at a certain price in the store. The same bottle can also be sold at another price for a professional (a restaurant for example) who buys in larger quantities (the selling price will then be lower per unit sold).

Thus, depending on the sales context, it is easy to choose the selling price to be applied to the product. The merchant can add as many selling prices (VariantPrice) as there are price lists (Price).

note

The taxIncluded property of the associated Price defines which property of VariantPrice should be used (valueIncludingTaxes or valueExcludingTaxes). If variantPrice.price.taxInlucded is true, it should be used the variantPrice.valueIncludingTax value else it should be used the variantPrice.valueExcludingTax value.

Degressive selling prices#

In addition to being able to apply several selling prices on the same variant, a merchant can define degressive selling prices with quantity increments.

REQUEST /graphql

query {
products {
edges {
node {
variants {
edges {
node {
variantPrices {
edges {
node {
valueIncludingTax
valueExcludingTax
toQuantity
fromQuantity
price {
name
taxIncluded
}
}
}
}
}
}
}
}
}
}
}

RESPONSE /graphql

{
"data": {
"products": {
"variants": {
"edges": [
{
"node": {
"variantPrices": {
"edges": [
{
"node": {
"valueIncludingTax": 14,
"valueExcludingTax": 11.6,
"toQuantity": 5,
"fromQuantity": 1,
"price": {
"name": "Tarif Cave",
"taxIncluded": true
}
}
}
{
"node": {
"valueIncludingTax": 13.5,
"valueExcludingTax": 11.25,
"toQuantity": -1,
"fromQuantity": 6,
"price": {
"name": "Tarif Cave",
"taxIncluded": true
}
}
},
]
}
}
}
]
}
}
}
}
  • When the quantity is between 1 and 5, the first price will be applied: 14.00€.
  • When the quantity is between 6 and more, the second price will be applied: 13.50€.

In this sense, it is possible to adjust these variables to perform the sales management of this variant.


Finally it is possible to perceive the power related to all the use cases present in this schema. Each one of them has its fundamental importance in the whole.