TariffV2PricingValidator.java
package com.github.jenkaby.bikerental.tariff.web.command.validation;
import com.github.jenkaby.bikerental.shared.domain.utils.MessageCode;
import com.github.jenkaby.bikerental.tariff.domain.model.PricingType;
import com.github.jenkaby.bikerental.tariff.shared.utils.TariffV2FieldNames;
import com.github.jenkaby.bikerental.tariff.web.error.InvalidTariffPricingException;
import com.github.jenkaby.bikerental.tariff.web.query.dto.PricingParams;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
@Component
public class TariffV2PricingValidator {
private static final String INAPPLICABLE_FIELD = MessageCode.INAPPLICABLE_FIELD;
private static final String REQUIRED_FIELD_MISSING = MessageCode.REQUIRED_FIELD_MISSING;
private static final String CONSTRAINT_VIOLATION = MessageCode.CONSTRAINT_VIOLATION;
public void validate(PricingType pricingType, PricingParams dto) {
var firstHourPrice = dto.firstHourPrice();
var hourlyDiscount = dto.hourlyDiscount();
var minimumHourlyPrice = dto.minimumHourlyPrice();
var hourlyPrice = dto.hourlyPrice();
var dailyPrice = dto.dailyPrice();
var overtimeHourlyPrice = dto.overtimeHourlyPrice();
var issuanceFee = dto.issuanceFee();
var minimumDurationMinutes = dto.minimumDurationMinutes();
var minimumDurationSurcharge = dto.minimumDurationSurcharge();
switch (pricingType) {
case DEGRESSIVE_HOURLY -> {
requirePositive(TariffV2FieldNames.FIRST_HOUR_PRICE, firstHourPrice);
requirePositive(TariffV2FieldNames.HOURLY_DISCOUNT, hourlyDiscount);
requirePositive(TariffV2FieldNames.MINIMUM_HOURLY_PRICE, minimumHourlyPrice);
if (minimumHourlyPrice.compareTo(firstHourPrice) > 0) {
throw new InvalidTariffPricingException(TariffV2FieldNames.MINIMUM_HOURLY_PRICE + " must be <= " + TariffV2FieldNames.FIRST_HOUR_PRICE,
CONSTRAINT_VIOLATION + "." + TariffV2FieldNames.MINIMUM_HOURLY_PRICE);
}
requirePositive(TariffV2FieldNames.MINIMUM_DURATION_MINUTES, minimumDurationMinutes);
requirePositive(TariffV2FieldNames.MINIMUM_DURATION_SURCHARGE, minimumDurationSurcharge);
}
case FLAT_HOURLY -> {
requirePositive(TariffV2FieldNames.HOURLY_PRICE, hourlyPrice);
requirePositive(TariffV2FieldNames.MINIMUM_DURATION_MINUTES, minimumDurationMinutes);
requirePositive(TariffV2FieldNames.MINIMUM_DURATION_SURCHARGE, minimumDurationSurcharge);
}
case DAILY -> {
requirePositive(TariffV2FieldNames.DAILY_PRICE, dailyPrice);
requirePositive(TariffV2FieldNames.OVERTIME_HOURLY_PRICE, overtimeHourlyPrice);
}
case FLAT_FEE -> {
requireNonNegative(TariffV2FieldNames.ISSUANCE_FEE, issuanceFee);
}
case SPECIAL -> {
// ignore any fields
}
}
}
private static void requirePositive(String field, Integer value) {
if (isNull(value) || value <= 0) {
throw new InvalidTariffPricingException(field + " is required and must be > 0",
REQUIRED_FIELD_MISSING + "." + field);
}
}
private static void requirePositive(String field, BigDecimal value) {
if (isNull(value) || value.compareTo(BigDecimal.ZERO) <= 0) {
throw new InvalidTariffPricingException(field + " is required and must be > 0",
REQUIRED_FIELD_MISSING + "." + field);
}
}
private static void requireNonNegative(String field, BigDecimal value) {
if (isNull(value) || value.compareTo(BigDecimal.ZERO) < 0) {
throw new InvalidTariffPricingException(field + " is required and must be >= 0",
REQUIRED_FIELD_MISSING + "." + field);
}
}
private static void requireNull(String field, Object value) {
if (nonNull(value)) {
throw new InvalidTariffPricingException(field + " must be null for this pricing type",
INAPPLICABLE_FIELD + "." + field);
}
}
private static void requireNull(String field, Integer value) {
if (nonNull(value)) {
throw new InvalidTariffPricingException(field + " must be null for this pricing type",
INAPPLICABLE_FIELD + "." + field);
}
}
}