Skip to content

Commit

Permalink
fix(#486): fix behaviour of multiplePricesForSaleAvailable, leaving…
Browse files Browse the repository at this point in the history
… out duplicate prices
  • Loading branch information
lukashornych committed Mar 11, 2024
1 parent 378f270 commit 0c87465
Show file tree
Hide file tree
Showing 17 changed files with 345 additions and 178 deletions.
Original file line number Diff line number Diff line change
@@ -1,106 +1,106 @@
```json
{
"data": {
"queryProduct": {
"recordPage": {
"data": [
{
"primaryKey": 103911,
"attributes": {
"code": "apple-ipad-10-2-10th-generation-2022"
},
"priceForSale": {
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
"allPricesForSale": [
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "436.36",
"priceWithTax": "528.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "436.36",
"priceWithTax": "528.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "436.36",
"priceWithTax": "528.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "436.36",
"priceWithTax": "528.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
}
],
"multiplePricesForSaleAvailable": true
}
]
}
}
"queryProduct": {
"recordPage": {
"data": [
{
"primaryKey": 103911,
"attributes": {
"code": "apple-ipad-10-2-10th-generation-2022"
},
"priceForSale": {
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
"allPricesForSale": [
{
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "395.87",
"priceWithTax": "479.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "412.4",
"priceWithTax": "499.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "436.36",
"priceWithTax": "528.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "436.36",
"priceWithTax": "528.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "436.36",
"priceWithTax": "528.0",
"taxRate": "21.0"
},
{
"priceWithoutTax": "436.36",
"priceWithTax": "528.0",
"taxRate": "21.0"
}
],
"multiplePricesForSaleAvailable": true
}
]
}
}
}
}
```
33 changes: 23 additions & 10 deletions documentation/user/en/query/requirements/fetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -944,9 +944,13 @@ still want to fetch them to display in the UI for the user.

<LS to="r">

For entities that have either `FIRST_OCCURENCE` or `SUM` inner record handling with prices
for multiple referenced entities grouped by the `innerRecordId`, the `multiplePricesForSaleAvailable` field will be returned
indicating whether there are multiple prices for sale available or just one.
For entities that have either `FIRST_OCCURENCE` or `SUM` inner record handling, the `multiplePricesForSaleAvailable`
property is returned, indicating whether there are multiple _unique_ prices for sale (grouped by the `innerRecordId`).
It is important to note that it doesn't simply return the count of all prices for sale.
Instead, it uses the [`priceType`](../requirements/price.md#price-type) constraint to determine the uniqueness of each
price value. This means that even if there are, say, 3 prices for sale, but they all have the same value, this property
will return `false`. This is especially useful for the
UI to determine whether to display a price range or just a single price without having to fetch all prices for sale.

</LS>

Expand Down Expand Up @@ -1152,13 +1156,22 @@ As you can see, the price for sale matching the custom arguments is returned.

</Note>

Similarly, you can use `allPricesForSale`, which is almost the same as `priceForSale`, but returns all prices for the
sale of the entity. This makes sense if an entity has either `FIRST_OCCURENCE` or `SUM` inner record handling with prices
for multiple referenced entities grouped by the `innerRecordId`. In the case of the `priceForSale` field, only the lowest
price for sale would be returned, but this may not be sufficient if you want to display more complex pricing for the entity.
You can use the `allPricesForSale` field to get all these prices and display more complex information. You can also
use the simpler `multiplePricesForSaleAvailable` field to simply check if there are multiple prices for sale available or
just one without fetching the actual price objects.
Similarly, you can use `allPricesForSale`, which is almost the same as `priceForSale`, but returns all prices for sale
of the entity grouped by the `innerRecordId`. This usually only makes sense for master products with variants
(i.e. `FIRST_OCCURENCE` inner record handling) where the master product has prices for all of its variants, where you may
want to know (and display) prices for sale for each variant (or some kind of range). For the `NONE` inner record handling,
this will always return at most the actual single price for sale. For the `SUM` inner record handling, this will return prices for sale
for each `innerRecordId` in the same way as for the `FIRST_OCCURNCE`, but the use cases are limited.

The returned list of prices is sorted by the price value from the lowest to the highest depending on the [`priceType`](../requirements/price.md#price-type)
constraint used.

There is also the simpler `multiplePricesForSaleAvailable` field, which returns a boolean indicating whether there are
multiple _unique_ prices for sale. It is important to note that it doesn't simply return the count of `allPricesForSale`.
Instead, it uses the [`priceType`](../requirements/price.md#price-type) constraint to determine the uniqueness of each
price value. This means that even if there are, say, 3 prices for sale, but they all have the same value, this field
will return `false` (as opposed to `allPricesForSale`, which would return all prices). This is especially useful for the
UI to determine whether to display a price range or just a single price without having to fetch all prices for sale.

<SourceCodeTabs langSpecificTabOnly>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ private BuiltFieldDescriptor buildGetEntityField(@Nonnull CollectionGraphQLSchem
.argument(GetEntityHeaderDescriptor.PRICE_VALID_IN
.to(argumentBuilderTransformer))
.argument(GetEntityHeaderDescriptor.PRICE_VALID_NOW
.to(argumentBuilderTransformer))
.argument(GetEntityHeaderDescriptor.PRICE_TYPE
.to(argumentBuilderTransformer));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2023
* Copyright (c) 2023-2024
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -23,6 +23,7 @@

package io.evitadb.externalApi.graphql.api.catalog.dataApi.model;

import io.evitadb.api.query.require.QueryPriceMode;
import io.evitadb.externalApi.api.catalog.dataApi.model.CatalogDataApiRootDescriptor;
import io.evitadb.externalApi.api.model.PropertyDescriptor;

Expand Down Expand Up @@ -82,4 +83,12 @@ public interface GetEntityHeaderDescriptor {
""")
.type(nullable(Boolean.class))
.build();
PropertyDescriptor PRICE_TYPE = PropertyDescriptor.builder()
.name("priceType")
.description("""
Parameter specifying which price type (with/without tax) will be used for handling filtering and sorting constraints.
By default, the "with tax" price type is used.
""")
.type(nullable(QueryPriceMode.class))
.build();
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2023
* Copyright (c) 2023-2024
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -31,6 +31,7 @@
import io.evitadb.api.query.Query;
import io.evitadb.api.query.filter.FilterBy;
import io.evitadb.api.query.require.EntityFetch;
import io.evitadb.api.query.require.QueryPriceMode;
import io.evitadb.api.query.require.Require;
import io.evitadb.api.requestResponse.data.EntityClassifier;
import io.evitadb.api.requestResponse.data.structure.EntityDecorator;
Expand Down Expand Up @@ -166,7 +167,7 @@ private Require buildRequire(@Nonnull DataFetchingEnvironment environment, @Nonn
)
.orElse(null);

return require(entityFetch);
return require(entityFetch, priceType(arguments.priceType()));
}

@Nonnull
Expand All @@ -189,6 +190,7 @@ private record Arguments(@Nullable Integer primaryKey,
@Nullable String[] priceInPriceLists,
@Nullable OffsetDateTime priceValidIn,
boolean priceValidInNow,
@Nonnull QueryPriceMode priceType,
@Nonnull Map<AttributeSchemaContract, Object> uniqueAttributes) {

private static Arguments from(@Nonnull DataFetchingEnvironment environment, @Nonnull EntitySchemaContract entitySchema) {
Expand All @@ -205,6 +207,8 @@ private static Arguments from(@Nonnull DataFetchingEnvironment environment, @Non
final OffsetDateTime priceValidIn = (OffsetDateTime) arguments.remove(GetEntityHeaderDescriptor.PRICE_VALID_IN.name());
final boolean priceValidInNow = (boolean) Optional.ofNullable(arguments.remove(GetEntityHeaderDescriptor.PRICE_VALID_NOW.name()))
.orElse(false);
final QueryPriceMode priceType = (QueryPriceMode) Optional.ofNullable(arguments.remove(GetEntityHeaderDescriptor.PRICE_TYPE.name()))
.orElse(QueryPriceMode.WITH_TAX);

// left over arguments are unique attribute filters as defined by schema
final Map<AttributeSchemaContract, Object> uniqueAttributes = extractUniqueAttributesFromArguments(arguments, entitySchema);
Expand All @@ -223,6 +227,7 @@ private static Arguments from(@Nonnull DataFetchingEnvironment environment, @Non
(priceInPriceLists != null ? priceInPriceLists.toArray(String[]::new) : null),
priceValidIn,
priceValidInNow,
priceType,
uniqueAttributes
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2023
* Copyright (c) 2023-2024
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -35,7 +35,6 @@
import io.evitadb.api.query.require.EntityContentRequire;
import io.evitadb.api.query.require.EntityFetch;
import io.evitadb.api.query.require.Require;
import io.evitadb.api.requestResponse.data.EntityClassifier;
import io.evitadb.api.requestResponse.data.SealedEntity;
import io.evitadb.api.requestResponse.data.structure.EntityDecorator;
import io.evitadb.api.requestResponse.data.structure.EntityReference;
Expand Down
Loading

0 comments on commit 0c87465

Please sign in to comment.