From 571c9ecaa239a5935d754f011e44b138ac618850 Mon Sep 17 00:00:00 2001 From: Matthias Schur <107557548+MattSchur@users.noreply.github.com> Date: Tue, 13 Jun 2023 18:31:24 +0200 Subject: [PATCH 1/2] Rewrite RecalculatePriceHandler --- .../processor/RecalculatePriceHandler.java | 233 +++++++++++------- 1 file changed, 144 insertions(+), 89 deletions(-) diff --git a/srv/src/main/java/com/sap/cap/sflight/processor/RecalculatePriceHandler.java b/srv/src/main/java/com/sap/cap/sflight/processor/RecalculatePriceHandler.java index 07789726..b5087bcd 100644 --- a/srv/src/main/java/com/sap/cap/sflight/processor/RecalculatePriceHandler.java +++ b/srv/src/main/java/com/sap/cap/sflight/processor/RecalculatePriceHandler.java @@ -3,31 +3,37 @@ import static cds.gen.travelservice.TravelService_.BOOKING; import static cds.gen.travelservice.TravelService_.BOOKING_SUPPLEMENT; import static cds.gen.travelservice.TravelService_.TRAVEL; -import static com.sap.cds.ql.CQL.sum; +import static com.sap.cds.services.cds.CqnService.EVENT_CREATE; +import static com.sap.cds.services.cds.CqnService.EVENT_UPDATE; +import static com.sap.cds.services.draft.DraftService.EVENT_DRAFT_CANCEL; +import static com.sap.cds.services.draft.DraftService.EVENT_DRAFT_PATCH; import static java.lang.Boolean.FALSE; +import static java.util.Objects.requireNonNullElse; import java.math.BigDecimal; -import java.util.HashMap; import java.util.Map; -import java.util.Objects; -import java.util.Optional; import org.springframework.stereotype.Component; -import com.sap.cds.Row; +import com.google.common.base.Strings; +import com.sap.cds.Result; +import com.sap.cds.Struct; import com.sap.cds.ql.Select; import com.sap.cds.ql.Update; +import com.sap.cds.ql.cqn.CqnAnalyzer; +import com.sap.cds.ql.cqn.CqnSelect; import com.sap.cds.ql.cqn.CqnUpdate; import com.sap.cds.services.ErrorStatuses; import com.sap.cds.services.ServiceException; -import com.sap.cds.services.cds.CqnService; +import com.sap.cds.services.draft.DraftCancelEventContext; +import com.sap.cds.services.draft.DraftPatchEventContext; import com.sap.cds.services.draft.DraftService; import com.sap.cds.services.handler.EventHandler; import com.sap.cds.services.handler.annotations.After; import com.sap.cds.services.handler.annotations.Before; +import com.sap.cds.services.handler.annotations.On; import com.sap.cds.services.handler.annotations.ServiceName; import com.sap.cds.services.persistence.PersistenceService; -import com.sap.cds.services.utils.StringUtils; import cds.gen.travelservice.Booking; import cds.gen.travelservice.BookingSupplement; @@ -41,6 +47,8 @@ @ServiceName(TravelService_.CDS_NAME) public class RecalculatePriceHandler implements EventHandler { + private static final BigDecimal ZERO = new BigDecimal(0); + private final DraftService draftService; private final PersistenceService persistenceService; @@ -49,112 +57,159 @@ public RecalculatePriceHandler(DraftService draftService, PersistenceService per this.persistenceService = persistenceService; } - @Before(event = {CqnService.EVENT_CREATE, CqnService.EVENT_UPDATE}, entity = {Booking_.CDS_NAME, BookingSupplement_.CDS_NAME}) - public void disableUpdateAndCreateForBookingAndBookingSupplement() { - throw new ServiceException(ErrorStatuses.BAD_REQUEST, "error.booking.only_patch"); + @After(event = { EVENT_CREATE, EVENT_UPDATE }, entity = Travel_.CDS_NAME) + public void calculateTotalPriceOfTravel(Travel travel) { + String travelUUID = travel.getTravelUUID(); + if (!Strings.isNullOrEmpty(travelUUID)) { + BigDecimal totalPrice = calculateTravelPrice(travelUUID); + travel.setTotalPrice(totalPrice); + + persistenceService.run(Update.entity(TRAVEL).data(Map.of( + Travel.TRAVEL_UUID, travelUUID, + Travel.TOTAL_PRICE, totalPrice))); + } } - private static BigDecimal calculateTotalPriceForTravel(CqnService db, String travelUUID, - boolean isActiveEntity) { - // get booking fee - BigDecimal bookingFee = BigDecimal.valueOf(0); - Optional bookingFeeRow = db - .run(Select.from(TRAVEL).columns(Travel_::BookingFee) - .where(t -> t.TravelUUID().eq(travelUUID) - .and(t.IsActiveEntity().eq(isActiveEntity)) - .and(t.BookingFee().isNotNull())) - .limit(1)) - .first(); - if (bookingFeeRow.isPresent()) { - bookingFee = (BigDecimal) bookingFeeRow.get().get("BookingFee"); + private BigDecimal calculateTravelPrice(String travelUUID) { + BigDecimal bookingFee = run(Select.from(TRAVEL) + .columns(t -> t.BookingFee().as("sum")) + .where(t -> t.TravelUUID().eq(travelUUID))); + + BigDecimal flights = run(Select.from(BOOKING) + .columns(b -> b.FlightPrice().sum().as("sum")) + .where(b -> b.to_Travel_TravelUUID().eq(travelUUID))); + + BigDecimal supplements = run(Select.from(BOOKING_SUPPLEMENT) + .columns(s -> s.Price().sum().as("sum")) + .where(s -> s.to_Booking().to_Travel().TravelUUID().eq(travelUUID))); + + return bookingFee.add(flights).add(supplements); + } + + private BigDecimal run(CqnSelect query) { + BigDecimal sum = persistenceService.run(query).first(Price.class).map(Price::sum).orElse(ZERO); + + return nullToZero(sum); + } + + private static interface Price { + BigDecimal sum(); + } + + @On(event = { EVENT_DRAFT_PATCH }, entity = Travel_.CDS_NAME) + public void updateTravelPriceOnBookingFeeUpdate(DraftPatchEventContext context) { + CqnUpdate update = context.getCqn(); + Travel travel = Struct.access(update.data()).as(Travel.class); + BigDecimal newFee = travel.getBookingFee(); + if (newFee != null) { + Map travelKeys = CqnAnalyzer.create(context.getModel()).analyze(update).targetKeys(); + BigDecimal oldFee = selectTravelFee(travelKeys); + BigDecimal travelPrice = selectTravelPrice(travelKeys.get(Travel.TRAVEL_UUID)).add(newFee).subtract(oldFee); + + travel.setTotalPrice(travelPrice); } + } - // get sum of flight prices from all bookings - BigDecimal flightPriceSum = new BigDecimal(0); - Optional flightPriceRow = db - .run(Select.from(BOOKING).columns(b -> sum(b.FlightPrice()).as("FlightPriceSum")) - .where(b -> b.to_Travel_TravelUUID().eq(travelUUID).and(b.IsActiveEntity().eq(isActiveEntity)))) - .first(); + @On(event = { EVENT_DRAFT_PATCH }, entity = Booking_.CDS_NAME) + public void updateTravelPriceOnBookingUpdate(Booking bookingPatch) { + BigDecimal newPrice = bookingPatch.getFlightPrice(); + if (newPrice != null) { + Booking booking = selectBooking(Map.of( + Booking.BOOKING_UUID, bookingPatch.getBookingUUID(), + Booking.IS_ACTIVE_ENTITY, false)); - if (flightPriceRow.isPresent()) { - flightPriceSum = (BigDecimal) Objects.requireNonNullElse(flightPriceRow.get().get("FlightPriceSum"), new BigDecimal(0)); + String travelUUID = booking.getToTravelTravelUUID(); + updateTravelPrice(travelUUID, newPrice, booking.getFlightPrice()); } + } + + @On(event = { EVENT_DRAFT_PATCH }, entity = BookingSupplement_.CDS_NAME) + public void updateTravelPriceOnSupplementUpdate(BookingSupplement supplementPatch) { + BigDecimal newPrice = supplementPatch.getPrice(); + if (newPrice != null) { + BookingSupplement supplement = selectSupplement(Map.of(BookingSupplement.BOOK_SUPPL_UUID, + supplementPatch.getBookSupplUUID(), BookingSupplement.IS_ACTIVE_ENTITY, false)); - // get sum of the prices of all booking supplements for the travel - BigDecimal supplementPriceSum = new BigDecimal(0); - Optional supplementPriceSumRow = db - .run(Select.from(BOOKING_SUPPLEMENT).columns(c -> sum(c.Price()).as("PriceSum")) - .where(b -> b.to_Travel_TravelUUID().eq(travelUUID).and(b.IsActiveEntity().eq(isActiveEntity)))) - .first(); - if (supplementPriceSumRow.isPresent()) { - supplementPriceSum = (BigDecimal) Objects.requireNonNullElse(flightPriceRow.get().get("PriceSum"), new BigDecimal(0)); + String travelUUID = supplement.getToTravelTravelUUID(); + updateTravelPrice(travelUUID, newPrice, supplement.getPrice()); } + } - // update travel's total price - return bookingFee.add(flightPriceSum).add(supplementPriceSum); + private void updateTravelPrice(String travelUUID, BigDecimal newPrice, BigDecimal oldPrice) { + BigDecimal travelPrice = selectTravelPrice(travelUUID).add(newPrice).subtract(nullToZero(oldPrice)); + updateTravelPrice(travelUUID, travelPrice); } - @After(event = {CqnService.EVENT_UPDATE, CqnService.EVENT_CREATE}, entity = Travel_.CDS_NAME) - public void calculateNewTotalPriceForActiveTravel(Travel travel) { + private void updateTravelPrice(String travelUUID, BigDecimal totalPrice) { + draftService.patchDraft(Update.entity(TRAVEL).byId(travelUUID).data(Travel.TOTAL_PRICE, totalPrice)); + } - /* - * Elements annotated with @Core.computed are not transferred during - * DRAFT_SAVE. Normally, we'd re-compute the @Core.computed values after - * DRAFT_SAVE and store them to the active version. For the TravelStatus_code - * this is not possible as they originate as the result of a custom action - * and thus cannot be re-computed. We have to take them from the draft version and - * store them to the active version *before* the DRAFT_SAVE event. - */ + @On(event = { EVENT_DRAFT_CANCEL }, entity = Booking_.CDS_NAME) + public void updateTravelPriceOnCancelBooking(DraftCancelEventContext context) { + Booking booking = selectBooking(entityKeys(context)); + String travelUUID = booking.getToTravelTravelUUID(); + BigDecimal supplementPrice = calculateSupplementPrice(booking.getBookingUUID()); + BigDecimal totalPrice = selectTravelPrice(travelUUID).subtract(supplementPrice) + .subtract(nullToZero(booking.getFlightPrice())); - String travelUUID = travel.getTravelUUID(); - if (StringUtils.isEmpty(travelUUID)) { - return; - } - travel.setTotalPrice(calculateTotalPriceForTravel(persistenceService, travelUUID, true)); + updateTravelPrice(travelUUID, totalPrice); + } - Map data = new HashMap<>(); - data.put(Travel.TOTAL_PRICE, travel.getTotalPrice()); - data.put(Travel.TRAVEL_UUID, travelUUID); - persistenceService.run(Update.entity(TRAVEL).data(data)); + private BigDecimal calculateSupplementPrice(String bookingUUID) { + Result result = draftService.run(Select.from(BOOKING_SUPPLEMENT).columns(s -> s.Price().sum().as("sum")) + .where(s -> s.to_Booking_BookingUUID().eq(bookingUUID).and(s.IsActiveEntity().eq(FALSE)))); + + return nullToZero(result.single(Price.class).sum()); } - @After(event = { DraftService.EVENT_DRAFT_PATCH }, entity = Travel_.CDS_NAME) - public void recalculateTravelPriceIfTravelWasUpdated(final Travel travel) { - if (travel.getTravelUUID() != null && travel.getBookingFee() != null) { // only for patched booking fee - String travelUUID = travel.getTravelUUID(); - travel.setTotalPrice(calculateAndPatchNewTotalPriceForDraft(travelUUID)); + @On(event = { EVENT_DRAFT_CANCEL }, entity = BookingSupplement_.CDS_NAME) + public void updateTravelPriceAfterDeleteBookingSupplement(DraftCancelEventContext context) { + BookingSupplement supplement = selectSupplement(entityKeys(context)); + + if (supplement.getPrice() != null) { + String travelUUID = supplement.getToTravelTravelUUID(); + updateTravelPrice(travelUUID, ZERO, supplement.getPrice()); } } - @After(event = { DraftService.EVENT_DRAFT_PATCH, DraftService.EVENT_DRAFT_NEW }, entity = Booking_.CDS_NAME) - public void recalculateTravelPriceIfFlightPriceWasUpdated(final Booking booking) { - draftService.run(Select.from(BOOKING).columns(bs -> bs.to_Travel().TravelUUID().as(Travel.TRAVEL_UUID)) - .where(bs -> bs.BookingUUID().eq(booking.getBookingUUID()) - .and(bs.IsActiveEntity().eq(FALSE)))) - .first() - .ifPresent(row -> calculateAndPatchNewTotalPriceForDraft((String) row.get(Travel.TRAVEL_UUID))); + private static Map entityKeys(DraftCancelEventContext context) { + return CqnAnalyzer.create(context.getModel()).analyze(context.getCqn()).targetKeys(); + } + + private BigDecimal selectTravelPrice(Object travelUUID) { + CqnSelect query = Select.from(TRAVEL) + .matching(Map.of(Travel.TRAVEL_UUID, travelUUID, Travel.IS_ACTIVE_ENTITY, false)) + .columns(t -> t.TotalPrice().as("sum")); + BigDecimal price = draftService.run(query).single(Price.class).sum(); + + return nullToZero(price); } - @After(event = { DraftService.EVENT_DRAFT_NEW, DraftService.EVENT_DRAFT_PATCH, - DraftService.EVENT_DRAFT_SAVE }, entity = BookingSupplement_.CDS_NAME) - public void recalculateTravelPriceIfPriceWasUpdated(final BookingSupplement bookingSupplement) { - draftService.run(Select.from(BOOKING_SUPPLEMENT) - .columns(bs -> bs.to_Booking().to_Travel().TravelUUID().as(Travel.TRAVEL_UUID)) - .where(bs -> bs.BookSupplUUID().eq(bookingSupplement.getBookSupplUUID()) - .and(bs.IsActiveEntity().eq(FALSE)))) - .first() - .ifPresent(row -> calculateAndPatchNewTotalPriceForDraft((String) row.get(Travel.TRAVEL_UUID))); + private BigDecimal selectTravelFee(Map travelKeys) { + CqnSelect query = Select.from(TRAVEL).matching(travelKeys).columns(b -> b.BookingFee()); + Travel travel = draftService.run(query).single(Travel.class); + + return nullToZero(travel.getBookingFee()); } - private BigDecimal calculateAndPatchNewTotalPriceForDraft(final String travelUUID) { + private Booking selectBooking(Map bookingKeys) { + CqnSelect query = Select.from(BOOKING).matching(bookingKeys).columns(b -> b.BookingUUID(), + b -> b.to_Travel_TravelUUID(), b -> b.FlightPrice()); + return draftService.run(query).single(Booking.class); + } + + private BookingSupplement selectSupplement(Map supplementKeys) { + return draftService.run(Select.from(BOOKING_SUPPLEMENT).matching(supplementKeys) + .columns(s -> s.to_Booking().to_Travel_TravelUUID(), s -> s.Price())).single(BookingSupplement.class); + } - BigDecimal totalPrice = calculateTotalPriceForTravel(draftService, travelUUID, false); - Map map = new HashMap(); - map.put(Travel.TRAVEL_UUID, travelUUID); - map.put(Travel.TOTAL_PRICE, totalPrice); - CqnUpdate update = Update.entity(TRAVEL).data(map); - draftService.patchDraft(update); - return totalPrice; + private static BigDecimal nullToZero(BigDecimal d) { + return requireNonNullElse(d, ZERO); + } + + @Before(event = { EVENT_CREATE, EVENT_UPDATE }, entity = { Booking_.CDS_NAME, BookingSupplement_.CDS_NAME }) + public void disableUpdateAndCreateForBookingAndBookingSupplement() { + throw new ServiceException(ErrorStatuses.BAD_REQUEST, "error.booking.only_patch"); } } From ba2a50f40095e293439f077aba2ffef46d56929c Mon Sep 17 00:00:00 2001 From: Matthias Schur <107557548+MattSchur@users.noreply.github.com> Date: Wed, 14 Jun 2023 17:22:41 +0200 Subject: [PATCH 2/2] Use fluent style accessors --- .../processor/RecalculatePriceHandler.java | 68 +++++++++++-------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/srv/src/main/java/com/sap/cap/sflight/processor/RecalculatePriceHandler.java b/srv/src/main/java/com/sap/cap/sflight/processor/RecalculatePriceHandler.java index 904ae8cb..22c9035b 100644 --- a/srv/src/main/java/com/sap/cap/sflight/processor/RecalculatePriceHandler.java +++ b/srv/src/main/java/com/sap/cap/sflight/processor/RecalculatePriceHandler.java @@ -12,10 +12,10 @@ import java.math.BigDecimal; import java.util.Map; +import java.util.function.UnaryOperator; import org.springframework.stereotype.Component; -import com.google.common.base.Strings; import com.sap.cds.Result; import com.sap.cds.Struct; import com.sap.cds.ql.Select; @@ -35,6 +35,7 @@ import com.sap.cds.services.handler.annotations.ServiceName; import com.sap.cds.services.persistence.PersistenceService; +import cds.gen.sap.fe.cap.travel.TravelModel_; import cds.gen.travelservice.Booking; import cds.gen.travelservice.BookingSupplement; import cds.gen.travelservice.BookingSupplement_; @@ -60,20 +61,20 @@ public RecalculatePriceHandler(DraftService draftService, PersistenceService per @After(event = { EVENT_CREATE, EVENT_UPDATE }, entity = Travel_.CDS_NAME) public void calculateTotalPriceOfTravel(Travel travel) { String travelUUID = travel.travelUUID(); - if (!Strings.isNullOrEmpty(travelUUID)) { + if (travelUUID != null) { BigDecimal totalPrice = calculateTravelPrice(travelUUID); - travel.totalPrice(totalPrice); + persistenceService.run(Update.entity(TRAVEL).data(Travel.create() + .travelUUID(travelUUID) + .totalPrice(totalPrice))); - persistenceService.run(Update.entity(TRAVEL).data(Map.of( - Travel.TRAVEL_UUID, travelUUID, - Travel.TOTAL_PRICE, totalPrice))); + travel.totalPrice(totalPrice); } } private BigDecimal calculateTravelPrice(String travelUUID) { - BigDecimal bookingFee = run(Select.from(TRAVEL) + BigDecimal bookingFee = run(Select.from(TravelModel_.TRAVEL) .columns(t -> t.BookingFee().as("sum")) - .where(t -> t.TravelUUID().eq(travelUUID))); + .byId(travelUUID)); BigDecimal flights = run(Select.from(BOOKING) .columns(b -> b.FlightPrice().sum().as("sum")) @@ -87,12 +88,13 @@ private BigDecimal calculateTravelPrice(String travelUUID) { } private BigDecimal run(CqnSelect query) { - BigDecimal sum = persistenceService.run(query).first(Price.class).map(Price::sum).orElse(ZERO); + Result result = persistenceService.run(query); + BigDecimal sum = result.first(Price.class).map(Price::sum).orElse(ZERO); return nullToZero(sum); } - private static interface Price { + private interface Price { BigDecimal sum(); } @@ -102,7 +104,7 @@ public void updateTravelPriceOnBookingFeeUpdate(DraftPatchEventContext context) Travel travel = Struct.access(update.data()).as(Travel.class); BigDecimal newFee = travel.bookingFee(); if (newFee != null) { - Map travelKeys = CqnAnalyzer.create(context.getModel()).analyze(update).targetKeys(); + var travelKeys = CqnAnalyzer.create(context.getModel()).analyze(update).targetKeys(); BigDecimal oldFee = selectTravelFee(travelKeys); BigDecimal travelPrice = selectTravelPrice(travelKeys.get(Travel.TRAVEL_UUID)).add(newFee).subtract(oldFee); @@ -114,9 +116,9 @@ public void updateTravelPriceOnBookingFeeUpdate(DraftPatchEventContext context) public void updateTravelPriceOnBookingUpdate(Booking bookingPatch) { BigDecimal newPrice = bookingPatch.flightPrice(); if (newPrice != null) { - Booking booking = selectBooking(Map.of( - Booking.BOOKING_UUID, bookingPatch.bookingUUID(), - Booking.IS_ACTIVE_ENTITY, false)); + Booking booking = selectBookingPrice(Booking.create() + .bookingUUID(bookingPatch.bookingUUID()) + .isActiveEntity(false)); String travelUUID = booking.toTravelTravelUUID(); updateTravelPrice(travelUUID, newPrice, booking.flightPrice()); @@ -127,8 +129,9 @@ public void updateTravelPriceOnBookingUpdate(Booking bookingPatch) { public void updateTravelPriceOnSupplementUpdate(BookingSupplement supplementPatch) { BigDecimal newPrice = supplementPatch.price(); if (newPrice != null) { - BookingSupplement supplement = selectSupplement(Map.of(BookingSupplement.BOOK_SUPPL_UUID, - supplementPatch.bookSupplUUID(), BookingSupplement.IS_ACTIVE_ENTITY, false)); + BookingSupplement supplement = selectSupplementPrice(s -> s + .bookSupplUUID(supplementPatch.bookSupplUUID()) + .isActiveEntity(false)); String travelUUID = supplement.toTravelTravelUUID(); updateTravelPrice(travelUUID, newPrice, supplement.price()); @@ -141,12 +144,13 @@ private void updateTravelPrice(String travelUUID, BigDecimal newPrice, BigDecima } private void updateTravelPrice(String travelUUID, BigDecimal totalPrice) { - draftService.patchDraft(Update.entity(TRAVEL).byId(travelUUID).data(Travel.TOTAL_PRICE, totalPrice)); + CqnUpdate update = Update.entity(TRAVEL).byId(travelUUID).data(Travel.TOTAL_PRICE, totalPrice); + draftService.patchDraft(update); } @On(event = { EVENT_DRAFT_CANCEL }, entity = Booking_.CDS_NAME) public void updateTravelPriceOnCancelBooking(DraftCancelEventContext context) { - Booking booking = selectBooking(entityKeys(context)); + Booking booking = selectBookingPrice(entityKeys(context)); String travelUUID = booking.toTravelTravelUUID(); BigDecimal supplementPrice = calculateSupplementPrice(booking.bookingUUID()); BigDecimal totalPrice = selectTravelPrice(travelUUID).subtract(supplementPrice) @@ -158,13 +162,14 @@ public void updateTravelPriceOnCancelBooking(DraftCancelEventContext context) { private BigDecimal calculateSupplementPrice(String bookingUUID) { Result result = draftService.run(Select.from(BOOKING_SUPPLEMENT).columns(s -> s.Price().sum().as("sum")) .where(s -> s.to_Booking_BookingUUID().eq(bookingUUID).and(s.IsActiveEntity().eq(FALSE)))); + Price price = result.single(Price.class); - return nullToZero(result.single(Price.class).sum()); + return nullToZero(price.sum()); } @On(event = { EVENT_DRAFT_CANCEL }, entity = BookingSupplement_.CDS_NAME) public void updateTravelPriceAfterDeleteBookingSupplement(DraftCancelEventContext context) { - BookingSupplement supplement = selectSupplement(entityKeys(context)); + BookingSupplement supplement = selectSupplementPrice(entityKeys(context)); if (supplement.price() != null) { String travelUUID = supplement.toTravelTravelUUID(); @@ -177,9 +182,9 @@ private static Map entityKeys(DraftCancelEventContext context) { } private BigDecimal selectTravelPrice(Object travelUUID) { - CqnSelect query = Select.from(TRAVEL) - .matching(Map.of(Travel.TRAVEL_UUID, travelUUID, Travel.IS_ACTIVE_ENTITY, false)) - .columns(t -> t.TotalPrice().as("sum")); + CqnSelect query = Select.from(TRAVEL).columns(t -> t.TotalPrice().as("sum")).matching(Map.of( + Travel.TRAVEL_UUID, travelUUID, + Travel.IS_ACTIVE_ENTITY, false)); BigDecimal price = draftService.run(query).single(Price.class).sum(); return nullToZero(price); @@ -192,15 +197,20 @@ private BigDecimal selectTravelFee(Map travelKeys) { return nullToZero(travel.bookingFee()); } - private Booking selectBooking(Map bookingKeys) { - CqnSelect query = Select.from(BOOKING).matching(bookingKeys).columns(b -> b.BookingUUID(), - b -> b.to_Travel_TravelUUID(), b -> b.FlightPrice()); + private Booking selectBookingPrice(Map bookingKeys) { + CqnSelect query = Select.from(BOOKING).matching(bookingKeys).columns( + b -> b.BookingUUID(), b -> b.to_Travel_TravelUUID(), b -> b.FlightPrice()); return draftService.run(query).single(Booking.class); } - private BookingSupplement selectSupplement(Map supplementKeys) { - return draftService.run(Select.from(BOOKING_SUPPLEMENT).matching(supplementKeys) - .columns(s -> s.to_Booking().to_Travel_TravelUUID(), s -> s.Price())).single(BookingSupplement.class); + private BookingSupplement selectSupplementPrice(UnaryOperator supplement) { + return selectSupplementPrice(supplement.apply(BookingSupplement.create())); + } + + private BookingSupplement selectSupplementPrice(Map supplementKeys) { + CqnSelect query = Select.from(BOOKING_SUPPLEMENT).matching(supplementKeys) + .columns(s -> s.to_Booking().to_Travel_TravelUUID(), s -> s.Price()); + return draftService.run(query).single(BookingSupplement.class); } private static BigDecimal nullToZero(BigDecimal d) {