externalize business constants
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
package com.petshop.backend;
|
||||
|
||||
import com.petshop.backend.config.BusinessProperties;
|
||||
import com.petshop.backend.config.FlywayContextInitializer;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.data.web.config.EnableSpringDataWebSupport;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties(BusinessProperties.class)
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@EnableSpringDataWebSupport(pageSerializationMode = EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.petshop.backend.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalTime;
|
||||
|
||||
@ConfigurationProperties(prefix = "petshop.business")
|
||||
public record BusinessProperties(
|
||||
LocalTime openTime,
|
||||
LocalTime closeTime,
|
||||
int slotIntervalMinutes,
|
||||
long maxImageSizeBytes,
|
||||
BigDecimal employeeDiscountPercent,
|
||||
int loyaltyPointsPerDollar
|
||||
) {
|
||||
public BusinessProperties {
|
||||
if (openTime == null) openTime = LocalTime.of(9, 0);
|
||||
if (closeTime == null) closeTime = LocalTime.of(17, 0);
|
||||
if (slotIntervalMinutes <= 0) slotIntervalMinutes = 30;
|
||||
if (maxImageSizeBytes <= 0) maxImageSizeBytes = 5 * 1024 * 1024;
|
||||
if (employeeDiscountPercent == null) employeeDiscountPercent = new BigDecimal("0.10");
|
||||
if (loyaltyPointsPerDollar <= 0) loyaltyPointsPerDollar = 20;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import com.petshop.backend.repository.PetRepository;
|
||||
import com.petshop.backend.repository.ServiceRepository;
|
||||
import com.petshop.backend.repository.StoreRepository;
|
||||
import com.petshop.backend.repository.UserRepository;
|
||||
import com.petshop.backend.config.BusinessProperties;
|
||||
import com.petshop.backend.util.AuthenticationHelper;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
@@ -47,8 +48,9 @@ public class AppointmentService {
|
||||
private final UserRepository userRepository;
|
||||
private final AdoptionRepository adoptionRepository;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
private final BusinessProperties businessProperties;
|
||||
|
||||
public AppointmentService(AppointmentRepository appointmentRepository, ServiceRepository serviceRepository, PetRepository petRepository, StoreRepository storeRepository, UserRepository userRepository, AdoptionRepository adoptionRepository, ApplicationEventPublisher eventPublisher) {
|
||||
public AppointmentService(AppointmentRepository appointmentRepository, ServiceRepository serviceRepository, PetRepository petRepository, StoreRepository storeRepository, UserRepository userRepository, AdoptionRepository adoptionRepository, ApplicationEventPublisher eventPublisher, BusinessProperties businessProperties) {
|
||||
this.appointmentRepository = appointmentRepository;
|
||||
this.serviceRepository = serviceRepository;
|
||||
this.petRepository = petRepository;
|
||||
@@ -56,6 +58,7 @@ public class AppointmentService {
|
||||
this.userRepository = userRepository;
|
||||
this.adoptionRepository = adoptionRepository;
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.businessProperties = businessProperties;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@@ -240,8 +243,8 @@ public class AppointmentService {
|
||||
.collect(Collectors.groupingBy(a -> a.getEmployee().getId()));
|
||||
|
||||
List<String> availableSlots = new ArrayList<>();
|
||||
LocalTime startTime = LocalTime.of(9, 0);
|
||||
LocalTime endTime = LocalTime.of(17, 0);
|
||||
LocalTime startTime = businessProperties.openTime();
|
||||
LocalTime endTime = businessProperties.closeTime();
|
||||
LocalTime latestStart = endTime.minusMinutes(service.getServiceDuration());
|
||||
|
||||
LocalTime currentTime = startTime;
|
||||
@@ -255,7 +258,7 @@ public class AppointmentService {
|
||||
if (anyEmployeeAvailable) {
|
||||
availableSlots.add(currentTime.toString());
|
||||
}
|
||||
currentTime = currentTime.plusMinutes(30);
|
||||
currentTime = currentTime.plusMinutes(businessProperties.slotIntervalMinutes());
|
||||
}
|
||||
|
||||
return availableSlots;
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.petshop.backend.entity.*;
|
||||
import com.petshop.backend.exception.BusinessException;
|
||||
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||
import com.petshop.backend.repository.*;
|
||||
import com.petshop.backend.util.BusinessConstants;
|
||||
import com.petshop.backend.config.BusinessProperties;
|
||||
import com.stripe.Stripe;
|
||||
import com.stripe.exception.StripeException;
|
||||
import com.stripe.model.PaymentIntent;
|
||||
@@ -25,8 +25,6 @@ import java.util.List;
|
||||
@Service
|
||||
public class CartService {
|
||||
|
||||
private static final int LOYALTY_POINTS_PER_DOLLAR = BusinessConstants.LOYALTY_POINTS_PER_DOLLAR;
|
||||
|
||||
private final CartRepository cartRepository;
|
||||
private final CartItemRepository cartItemRepository;
|
||||
private final UserRepository userRepository;
|
||||
@@ -36,6 +34,7 @@ public class CartService {
|
||||
private final CouponService couponService;
|
||||
private final SaleRepository saleRepository;
|
||||
private final SaleService saleService;
|
||||
private final BusinessProperties businessProperties;
|
||||
|
||||
@Value("${stripe.secret-key:}")
|
||||
private String stripeSecretKey;
|
||||
@@ -48,7 +47,8 @@ public class CartService {
|
||||
CouponRepository couponRepository,
|
||||
CouponService couponService,
|
||||
SaleRepository saleRepository,
|
||||
SaleService saleService) {
|
||||
SaleService saleService,
|
||||
BusinessProperties businessProperties) {
|
||||
this.cartRepository = cartRepository;
|
||||
this.cartItemRepository = cartItemRepository;
|
||||
this.userRepository = userRepository;
|
||||
@@ -58,6 +58,7 @@ public class CartService {
|
||||
this.couponService = couponService;
|
||||
this.saleRepository = saleRepository;
|
||||
this.saleService = saleService;
|
||||
this.businessProperties = businessProperties;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@@ -473,7 +474,7 @@ public class CartService {
|
||||
}
|
||||
|
||||
int availablePoints = user.getLoyaltyPoints() != null ? user.getLoyaltyPoints() : 0;
|
||||
int wholeDollars = availablePoints / LOYALTY_POINTS_PER_DOLLAR;
|
||||
int wholeDollars = availablePoints / businessProperties.loyaltyPointsPerDollar();
|
||||
if (wholeDollars <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.petshop.backend.exception.ResourceNotFoundException;
|
||||
import com.petshop.backend.event.SaleReceiptEvent;
|
||||
import com.petshop.backend.repository.*;
|
||||
import com.petshop.backend.util.AuthenticationHelper;
|
||||
import com.petshop.backend.util.BusinessConstants;
|
||||
import com.petshop.backend.config.BusinessProperties;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -25,9 +25,6 @@ import java.util.List;
|
||||
@Service
|
||||
public class SaleService {
|
||||
|
||||
private static final BigDecimal EMPLOYEE_DISCOUNT_PERCENT = BusinessConstants.EMPLOYEE_DISCOUNT_PERCENT;
|
||||
private static final int LOYALTY_POINTS_PER_DOLLAR = BusinessConstants.LOYALTY_POINTS_PER_DOLLAR;
|
||||
|
||||
private final SaleRepository saleRepository;
|
||||
private final ProductRepository productRepository;
|
||||
private final StoreRepository storeRepository;
|
||||
@@ -37,8 +34,9 @@ public class SaleService {
|
||||
private final CouponService couponService;
|
||||
private final CartRepository cartRepository;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
private final BusinessProperties businessProperties;
|
||||
|
||||
public SaleService(SaleRepository saleRepository, ProductRepository productRepository, StoreRepository storeRepository, InventoryRepository inventoryRepository, UserRepository userRepository, CouponRepository couponRepository, CouponService couponService, CartRepository cartRepository, ApplicationEventPublisher eventPublisher) {
|
||||
public SaleService(SaleRepository saleRepository, ProductRepository productRepository, StoreRepository storeRepository, InventoryRepository inventoryRepository, UserRepository userRepository, CouponRepository couponRepository, CouponService couponService, CartRepository cartRepository, ApplicationEventPublisher eventPublisher, BusinessProperties businessProperties) {
|
||||
this.saleRepository = saleRepository;
|
||||
this.productRepository = productRepository;
|
||||
this.storeRepository = storeRepository;
|
||||
@@ -48,6 +46,7 @@ public class SaleService {
|
||||
this.couponService = couponService;
|
||||
this.cartRepository = cartRepository;
|
||||
this.eventPublisher = eventPublisher;
|
||||
this.businessProperties = businessProperties;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@@ -251,7 +250,7 @@ public class SaleService {
|
||||
int pointsDeducted;
|
||||
if (request.getPointsUsed() != null && request.getPointsUsed() > 0) {
|
||||
loyaltyDiscount = BigDecimal.valueOf(request.getPointsUsed())
|
||||
.divide(BigDecimal.valueOf(LOYALTY_POINTS_PER_DOLLAR), 2, RoundingMode.HALF_UP)
|
||||
.divide(BigDecimal.valueOf(businessProperties.loyaltyPointsPerDollar()), 2, RoundingMode.HALF_UP)
|
||||
.min(remainingAfterDiscounts.max(BigDecimal.ZERO))
|
||||
.setScale(2, RoundingMode.HALF_UP);
|
||||
pointsDeducted = request.getPointsUsed();
|
||||
@@ -292,7 +291,7 @@ public class SaleService {
|
||||
}
|
||||
|
||||
if (customer.getRole() == User.Role.STAFF || customer.getRole() == User.Role.ADMIN) {
|
||||
return remainingAmount.multiply(EMPLOYEE_DISCOUNT_PERCENT).setScale(2, RoundingMode.HALF_UP);
|
||||
return remainingAmount.multiply(businessProperties.employeeDiscountPercent()).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
return BigDecimal.ZERO;
|
||||
@@ -304,7 +303,7 @@ public class SaleService {
|
||||
}
|
||||
|
||||
int availablePoints = customer.getLoyaltyPoints() != null ? customer.getLoyaltyPoints() : 0;
|
||||
int wholeDollars = availablePoints / LOYALTY_POINTS_PER_DOLLAR;
|
||||
int wholeDollars = availablePoints / businessProperties.loyaltyPointsPerDollar();
|
||||
if (wholeDollars <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
@@ -319,7 +318,7 @@ public class SaleService {
|
||||
if (loyaltyDiscount == null || loyaltyDiscount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return loyaltyDiscount.setScale(0, RoundingMode.DOWN).intValue() * LOYALTY_POINTS_PER_DOLLAR;
|
||||
return loyaltyDiscount.setScale(0, RoundingMode.DOWN).intValue() * businessProperties.loyaltyPointsPerDollar();
|
||||
}
|
||||
|
||||
private User resolveWebsiteSaleEmployee(Long storeId) {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.petshop.backend.util;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public final class BusinessConstants {
|
||||
|
||||
private BusinessConstants() {}
|
||||
|
||||
public static final int LOYALTY_POINTS_PER_DOLLAR = 20;
|
||||
public static final BigDecimal EMPLOYEE_DISCOUNT_PERCENT = new BigDecimal("0.10");
|
||||
}
|
||||
@@ -61,6 +61,15 @@ app:
|
||||
frontend-url: ${FRONTEND_URL:http://localhost:3000}
|
||||
allowed-origins: ${ALLOWED_ORIGINS:http://localhost:3000,http://localhost:3001,http://127.0.0.1:3000,https://petshop-web.nicepond-c7280126.westus2.azurecontainerapps.io}
|
||||
|
||||
petshop:
|
||||
business:
|
||||
open-time: "09:00"
|
||||
close-time: "17:00"
|
||||
slot-interval-minutes: 30
|
||||
max-image-size-bytes: 5242880
|
||||
employee-discount-percent: 0.10
|
||||
loyalty-points-per-dollar: 20
|
||||
|
||||
azure:
|
||||
storage:
|
||||
connection-string: ${AZURE_STORAGE_CONNECTION_STRING:}
|
||||
|
||||
Reference in New Issue
Block a user