Skip to content

Commit

Permalink
feat(#549): fetch appropriate reference price from GraphQL (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukashornych committed May 31, 2024
1 parent 0d78a51 commit 0cf2d82
Show file tree
Hide file tree
Showing 24 changed files with 637 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,6 @@ The moment is either extracted from the query as well (if present) or current da
""")
.type(nullable(Boolean.class))
.build();
PropertyDescriptor PRICE = PropertyDescriptor.builder()
.name("price")
.description("""
Single price corresponding to defined arguments picked up from set of all `prices`.
If more than one price is found, the valid one is picked. Validity is check based on query, if desired
validity is not specified in query, current time is used.
""")
.type(nullableRef(PriceDescriptor.THIS))
.build();
PropertyDescriptor PRICES = PropertyDescriptor.builder()
.name("prices")
.description("""
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 @@ -38,13 +38,15 @@
*
* @param name name of property
* @param description can be parametrized with {@link String#format(String, Object...)} parameters
* @param deprecate if present, the property should be marked as deprecated with the specified reason
* @param type optional type descriptor
*
* @author Lukáš Hornych, FG Forrest a.s. (c) 2022
*/
@Builder
public record PropertyDescriptor(@Nonnull String name,
@Nonnull String description,
@Nullable String deprecate,
@Nullable PropertyDataTypeDescriptor type,
@Nullable Object defaultValue) {

Expand All @@ -60,7 +62,7 @@ public record PropertyDescriptor(@Nonnull String name,
}

public PropertyDescriptor(@Nonnull String name, @Nonnull String description) {
this(name, description, null, null);
this(name, description, null, null, null);
}

/**
Expand All @@ -71,6 +73,7 @@ public static PropertyDescriptorBuilder extend(@Nonnull PropertyDescriptor prope
return builder()
.name(propertyDescriptor.name())
.description(propertyDescriptor.description())
.deprecate(propertyDescriptor.deprecate())
.type(propertyDescriptor.type())
.defaultValue(propertyDescriptor.defaultValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@
import io.evitadb.externalApi.graphql.api.catalog.dataApi.builder.constraint.RequireConstraintSchemaBuilder;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.GlobalEntityDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.GraphQLEntityDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.AccompanyingPriceFieldHeaderDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.AssociatedDataFieldHeaderDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.AttributesFieldHeaderDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.ParentsFieldHeaderDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.PriceFieldHeaderDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.PriceForSaleDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.PriceForSaleFieldHeaderDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.PricesFieldHeaderDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.ReferenceFieldHeaderDescriptor;
Expand Down Expand Up @@ -141,6 +143,7 @@ public void buildCommonTypes() {
);
buildingContext.registerType(EntityDescriptor.THIS_REFERENCE.to(objectBuilderTransformer).build());
buildingContext.registerType(buildPriceObject());
buildingContext.registerType(buildPriceForSaleObject());
buildingContext.registerType(buildGlobal());
}

Expand Down Expand Up @@ -326,6 +329,8 @@ private BuiltFieldDescriptor buildEntityPriceForSaleField() {
.to(fieldBuilderTransformer)
.argument(PriceForSaleFieldHeaderDescriptor.PRICE_LIST
.to(argumentBuilderTransformer))
.argument(PriceForSaleFieldHeaderDescriptor.PRICE_LISTS
.to(argumentBuilderTransformer))
.argument(PriceForSaleFieldHeaderDescriptor.CURRENCY
.to(argumentBuilderTransformer)
.type(typeRef(CURRENCY_ENUM.name())))
Expand Down Expand Up @@ -372,6 +377,7 @@ private BuiltFieldDescriptor buildEntityAllPricesForSaleField() {
return new BuiltFieldDescriptor(field, new AllPricesForSaleDataFetcher());
}

// todo #538: deprecated, remove
@Nonnull
private BuiltFieldDescriptor buildEntityPriceField() {
final GraphQLFieldDefinition field = GraphQLEntityDescriptor.PRICE
Expand Down Expand Up @@ -759,6 +765,46 @@ private static GraphQLOutputType buildReferencedEntityObject(@Nullable EntitySch
}


@Nonnull
private GraphQLObjectType buildPriceForSaleObject() {
buildingContext.registerDataFetcher(
PriceForSaleDescriptor.THIS,
PriceForSaleDescriptor.PRICE_WITH_TAX,
new PriceBigDecimalDataFetcher(PriceForSaleDescriptor.PRICE_WITH_TAX.name())
);
buildingContext.registerDataFetcher(
PriceForSaleDescriptor.THIS,
PriceForSaleDescriptor.PRICE_WITHOUT_TAX,
new PriceBigDecimalDataFetcher(PriceForSaleDescriptor.PRICE_WITHOUT_TAX.name())
);
buildingContext.registerDataFetcher(
PriceForSaleDescriptor.THIS,
PriceForSaleDescriptor.TAX_RATE,
new PriceBigDecimalDataFetcher(PriceForSaleDescriptor.TAX_RATE.name())
);
buildingContext.registerDataFetcher(
PriceForSaleDescriptor.THIS,
PriceForSaleDescriptor.ACCOMPANYING_PRICE,
new AccompanyingPriceDataFetcher()
);

return PriceForSaleDescriptor.THIS
.to(objectBuilderTransformer)
.field(PriceForSaleDescriptor.PRICE_WITHOUT_TAX.to(fieldBuilderTransformer.with(priceFieldDecorator)))
.field(PriceForSaleDescriptor.PRICE_WITH_TAX.to(fieldBuilderTransformer.with(priceFieldDecorator)))
.field(PriceForSaleDescriptor.TAX_RATE.to(fieldBuilderTransformer.with(priceFieldDecorator)))
.field(PriceForSaleDescriptor.ACCOMPANYING_PRICE.to(fieldBuilderTransformer)
.argument(AccompanyingPriceFieldHeaderDescriptor.PRICE_LISTS
.to(argumentBuilderTransformer))
.argument(AccompanyingPriceFieldHeaderDescriptor.CURRENCY
.to(argumentBuilderTransformer)
.type(typeRef(CURRENCY_ENUM.name())))
.argument(AccompanyingPriceFieldHeaderDescriptor.LOCALE
.to(argumentBuilderTransformer)
.type(typeRef(LOCALE_ENUM.name()))))
.build();
}

@Nonnull
private GraphQLObjectType buildPriceObject() {
buildingContext.registerDataFetcher(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
*
* _ _ ____ ____
* _____ _(_) |_ __ _| _ \| __ )
* / _ \ \ / / | __/ _` | | | | _ \
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2024
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/FgForrest/evitaDB/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

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

import io.evitadb.api.requestResponse.data.PriceContract;
import io.evitadb.api.requestResponse.data.structure.EntityDecorator;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Delegate;

import javax.annotation.Nonnull;
import java.util.Map;
import java.util.Optional;

/**
* DTO representing prefetched price for sale with other precomputed prices. Other prices can be computed using the
* {@link #getParentEntity()}.
*
* @author Lukáš Hornych, FG Forrest a.s. (c) 2024
*/
@RequiredArgsConstructor
public class PrefetchedPriceForSale implements PriceContract {

@Delegate @Nonnull private final PriceContract priceForSale;

@Nonnull @Getter private final EntityDecorator parentEntity;
@Nonnull @Getter private final Map<String, Optional<PriceContract>> accompanyingPrices;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
import io.evitadb.externalApi.api.catalog.dataApi.model.PriceDescriptor;
import io.evitadb.externalApi.api.model.ObjectDescriptor;
import io.evitadb.externalApi.api.model.PropertyDescriptor;
import io.evitadb.externalApi.graphql.api.catalog.dataApi.model.entity.PriceForSaleDescriptor;

import static io.evitadb.externalApi.api.model.ObjectPropertyDataTypeDescriptor.nonNullListRef;
import static io.evitadb.externalApi.api.model.ObjectPropertyDataTypeDescriptor.nullableRef;
import static io.evitadb.externalApi.api.model.PrimitivePropertyDataTypeDescriptor.nullable;

/**
Expand Down Expand Up @@ -60,6 +62,9 @@ Each entity must be part of at most single hierarchy (tree).
""")
// type is expected to be a list of non-hierarchical version of this entity
.build();
PropertyDescriptor PRICE_FOR_SALE = PropertyDescriptor.extend(EntityDescriptor.PRICE_FOR_SALE)
.type(nullableRef(PriceForSaleDescriptor.THIS))
.build();
PropertyDescriptor ALL_PRICES_FOR_SALE = PropertyDescriptor.builder()
.name("allPricesForSale")
.description("""
Expand All @@ -68,7 +73,21 @@ Each entity must be part of at most single hierarchy (tree).
priority can be extracted.
The moment is either extracted from the query/arguments as well (if present) or current date and time is used.
""")
.type(nonNullListRef(PriceDescriptor.THIS))
.type(nonNullListRef(PriceForSaleDescriptor.THIS))
.build();
// todo #538: deprecated, remove
PropertyDescriptor PRICE = PropertyDescriptor.builder()
.name("price")
.description("""
Single price corresponding to defined arguments picked up from set of all `prices`.
If more than one price is found, the valid one is picked. Validity is check based on query, if desired
validity is not specified in query, current time is used.
""")
.deprecate("""
This field doesn't correctly return price according to computed price for sale and it doesn't
respect price inner record handling. Use `accompanyingPrice` fields within the `priceForSale` field instead.
""")
.type(nullableRef(PriceDescriptor.THIS))
.build();

ObjectDescriptor THIS_NON_HIERARCHICAL = ObjectDescriptor.extend(THIS_CLASSIFIER)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
*
* _ _ ____ ____
* _____ _(_) |_ __ _| _ \| __ )
* / _ \ \ / / | __/ _` | | | | _ \
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* 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.
* You may obtain a copy of the License at
*
* https://github.com/FgForrest/evitaDB/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

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

import io.evitadb.externalApi.api.model.PropertyDescriptor;

import java.time.OffsetDateTime;

import static io.evitadb.externalApi.api.model.PrimitivePropertyDataTypeDescriptor.nonNull;
import static io.evitadb.externalApi.api.model.PrimitivePropertyDataTypeDescriptor.nullable;

/**
* Descriptor of header parameters of {@link PriceForSaleDescriptor#ACCOMPANYING_PRICE} field.
*
* @author Lukáš Hornych, FG Forrest a.s. (c) 2024
*/
public interface AccompanyingPriceFieldHeaderDescriptor {

PropertyDescriptor PRICE_LISTS = PropertyDescriptor.builder()
.name("priceLists")
.description("""
Parameter specifying list of price lists ordered by priority for defining output price.
""")
.type(nonNull(String[].class))
.build();
PropertyDescriptor CURRENCY = PropertyDescriptor.builder()
.name("currency")
.description("""
Parameter specifying desired currency of output price if different currency that already defined is desired.
""")
// type is expected to be a currency enum
.build();
PropertyDescriptor VALID_IN = PropertyDescriptor.builder()
.name("validIn")
.description("""
Parameter specifying when output price should be valid. If both `validInNow` and `validIn` parameters are
specified `validIn` is used.
""")
.type(nullable(OffsetDateTime.class))
.build();
PropertyDescriptor VALID_NOW = PropertyDescriptor.builder()
.name("validNow")
.description("""
Parameter specifying when output price should be valid. The date time is resolved to `now` by evitaDB. If both `validNow`
and `validIn` parameters are specified `validIn` is used.
""")
.type(nullable(Boolean.class))
.build();
PropertyDescriptor LOCALE = PropertyDescriptor.builder()
.name("locale")
.description("""
Parameter specifying desired locale price formatting.
If not specified, desired entity locale is used instead.
""")
// type is expected to be a locale enum
.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 @@ -23,18 +23,18 @@

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

import io.evitadb.externalApi.api.catalog.dataApi.model.EntityDescriptor;
import io.evitadb.externalApi.api.model.PropertyDescriptor;

import static io.evitadb.externalApi.api.model.PrimitivePropertyDataTypeDescriptor.nonNull;

/**
* Descriptor of header parameters of {@link EntityDescriptor#PRICE} field.
* Descriptor of header parameters of {@link io.evitadb.externalApi.graphql.api.catalog.dataApi.model.GraphQLEntityDescriptor#PRICE} field.
*
* @author Lukáš Hornych, FG Forrest a.s. (c) 2023
*/
public
interface PriceFieldHeaderDescriptor {
// todo #538: deprecated, remove
@Deprecated
public interface PriceFieldHeaderDescriptor {

PropertyDescriptor PRICE_LIST = PropertyDescriptor.builder()
.name("priceList")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
*
* _ _ ____ ____
* _____ _(_) |_ __ _| _ \| __ )
* / _ \ \ / / | __/ _` | | | | _ \
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2024
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/FgForrest/evitaDB/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

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

import io.evitadb.externalApi.api.catalog.dataApi.model.PriceDescriptor;
import io.evitadb.externalApi.api.model.ObjectDescriptor;
import io.evitadb.externalApi.api.model.PropertyDescriptor;

import static io.evitadb.externalApi.api.model.ObjectPropertyDataTypeDescriptor.nullableRef;

/**
* Extension of {@link PriceDescriptor} specific for "price for sale" prices.
*
* @author Lukáš Hornych, FG Forrest a.s. (c) 2024
*/
public interface PriceForSaleDescriptor extends PriceDescriptor {

PropertyDescriptor ACCOMPANYING_PRICE = PropertyDescriptor.builder()
.name("accompanyingPrice")
.description("""
Allows to calculate and return additional accompanying prices that relate to the selected price for sale
and adhere to particular price inner record handling logic.
""")
.type(nullableRef(PriceDescriptor.THIS))
.build();

ObjectDescriptor THIS = ObjectDescriptor.extend(PriceDescriptor.THIS)
.name("PriceForSale")
.build();
}
Loading

0 comments on commit 0cf2d82

Please sign in to comment.