Refactor and streamline premise creation logic.

- Removed redundant HS code checks in `materialCheck` of `PreCalculationCheckService`.
- Introduced `PropertyService` to manage default tariffs in `PremiseCreationService`.
- Adjusted `fillPremise` method to default to `SystemPropertyMappingId.TARIFF_RATE` when no tariff is specified.
- Improved code readability with formatting and added comments for better context.
This commit is contained in:
Jan 2025-12-07 18:15:25 +01:00
parent 767964b20f
commit a72adce690
3 changed files with 34 additions and 22 deletions

View file

@ -46,6 +46,7 @@ public class TaxationResolverService {
private Map<TaxationResolverRequest, TaxationResolverApiResponse> doRequests(List<TaxationResolverRequest> requests) { private Map<TaxationResolverRequest, TaxationResolverApiResponse> doRequests(List<TaxationResolverRequest> requests) {
/* country id -> union type */
Map<Integer, CustomUnionType> union = requests.stream() Map<Integer, CustomUnionType> union = requests.stream()
.map(TaxationResolverRequest::countryId) .map(TaxationResolverRequest::countryId)
.distinct() .distinct()
@ -57,8 +58,10 @@ public class TaxationResolverService {
.orElseThrow() .orElseThrow()
)); ));
var byCustomUnion = requests.stream().collect(Collectors.groupingBy(r -> (union.get(r.countryId())))); var byCustomUnion = requests.stream().collect(Collectors.groupingBy(r -> (union.get(r.countryId()))));
/* split by incomplete hs codes and complete hs codes */
var filteredRequests = byCustomUnion.getOrDefault(CustomUnionType.NONE, Collections.emptyList()).stream().collect(Collectors.partitioningBy(r -> r.material().getHsCode() != null && r.material().getHsCode().length() < 10)); var filteredRequests = byCustomUnion.getOrDefault(CustomUnionType.NONE, Collections.emptyList()).stream().collect(Collectors.partitioningBy(r -> r.material().getHsCode() != null && r.material().getHsCode().length() < 10));
var joined = Stream.concat( var joined = Stream.concat(
@ -293,7 +296,7 @@ public class TaxationResolverService {
} }
} }
if (selectedDuty != null && (maxDuty - minDuty < 0.02)) { if (selectedDuty != null && (maxDuty - minDuty <= 0.02)) {
return new TaxationResolverResponse(selectedDuty, selectedMeasure, selectedHsCode, request.material(), request.countryId()); return new TaxationResolverResponse(selectedDuty, selectedMeasure, selectedHsCode, request.material(), request.countryId());
} }

View file

@ -7,6 +7,7 @@ import de.avatic.lcc.model.db.premises.Premise;
import de.avatic.lcc.model.db.premises.PremiseState; import de.avatic.lcc.model.db.premises.PremiseState;
import de.avatic.lcc.model.db.properties.PackagingProperty; import de.avatic.lcc.model.db.properties.PackagingProperty;
import de.avatic.lcc.model.db.properties.PackagingPropertyMappingId; import de.avatic.lcc.model.db.properties.PackagingPropertyMappingId;
import de.avatic.lcc.model.db.properties.SystemPropertyMappingId;
import de.avatic.lcc.repositories.MaterialRepository; import de.avatic.lcc.repositories.MaterialRepository;
import de.avatic.lcc.repositories.NodeRepository; import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.packaging.PackagingDimensionRepository; import de.avatic.lcc.repositories.packaging.PackagingDimensionRepository;
@ -14,8 +15,9 @@ import de.avatic.lcc.repositories.packaging.PackagingPropertiesRepository;
import de.avatic.lcc.repositories.packaging.PackagingRepository; import de.avatic.lcc.repositories.packaging.PackagingRepository;
import de.avatic.lcc.repositories.premise.PremiseRepository; import de.avatic.lcc.repositories.premise.PremiseRepository;
import de.avatic.lcc.repositories.users.UserNodeRepository; import de.avatic.lcc.repositories.users.UserNodeRepository;
import de.avatic.lcc.service.api.CustomApiService;
import de.avatic.lcc.service.access.DestinationService; import de.avatic.lcc.service.access.DestinationService;
import de.avatic.lcc.service.access.PropertyService;
import de.avatic.lcc.service.api.CustomApiService;
import de.avatic.lcc.service.api.TaxationResolverService; import de.avatic.lcc.service.api.TaxationResolverService;
import de.avatic.lcc.service.transformer.generic.DimensionTransformer; import de.avatic.lcc.service.transformer.generic.DimensionTransformer;
import de.avatic.lcc.service.transformer.premise.PremiseTransformer; import de.avatic.lcc.service.transformer.premise.PremiseTransformer;
@ -27,7 +29,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;
@Service @Service
@ -44,8 +48,9 @@ public class PremiseCreationService {
private final PackagingPropertiesRepository packagingPropertiesRepository; private final PackagingPropertiesRepository packagingPropertiesRepository;
private final AuthorizationService authorizationService; private final AuthorizationService authorizationService;
private final TaxationResolverService taxationResolverService; private final TaxationResolverService taxationResolverService;
private final PropertyService propertyService;
public PremiseCreationService(PremiseRepository premiseRepository, PremiseTransformer premiseTransformer, DestinationService destinationService, UserNodeRepository userNodeRepository, NodeRepository nodeRepository, MaterialRepository materialRepository, DimensionTransformer dimensionTransformer, PackagingRepository packagingRepository, PackagingDimensionRepository packagingDimensionRepository, PackagingPropertiesRepository packagingPropertiesRepository, CustomApiService customApiService, AuthorizationService authorizationService, TaxationResolverService taxationResolverService) { public PremiseCreationService(PremiseRepository premiseRepository, PremiseTransformer premiseTransformer, DestinationService destinationService, UserNodeRepository userNodeRepository, NodeRepository nodeRepository, MaterialRepository materialRepository, DimensionTransformer dimensionTransformer, PackagingRepository packagingRepository, PackagingDimensionRepository packagingDimensionRepository, PackagingPropertiesRepository packagingPropertiesRepository, CustomApiService customApiService, AuthorizationService authorizationService, TaxationResolverService taxationResolverService, PropertyService propertyService) {
this.premiseRepository = premiseRepository; this.premiseRepository = premiseRepository;
this.premiseTransformer = premiseTransformer; this.premiseTransformer = premiseTransformer;
this.destinationService = destinationService; this.destinationService = destinationService;
@ -59,6 +64,7 @@ public class PremiseCreationService {
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.taxationResolverService = taxationResolverService; this.taxationResolverService = taxationResolverService;
this.propertyService = propertyService;
} }
@Transactional @Transactional
@ -66,6 +72,8 @@ public class PremiseCreationService {
var userId = authorizationService.getUserId(); var userId = authorizationService.getUserId();
userNodeRepository.checkOwner(userSupplierIds, userId); userNodeRepository.checkOwner(userSupplierIds, userId);
Optional<Double> defaultTariff = propertyService.getProperty(SystemPropertyMappingId.TARIFF_RATE);
/* Build all resulting premises */ /* Build all resulting premises */
List<TemporaryPremise> premises = Stream.concat( List<TemporaryPremise> premises = Stream.concat(
supplierIds.stream().flatMap(id -> materialIds.stream().map(materialId -> new TemporaryPremise(materialId, id, null, false))), supplierIds.stream().flatMap(id -> materialIds.stream().map(materialId -> new TemporaryPremise(materialId, id, null, false))),
@ -82,13 +90,13 @@ public class PremiseCreationService {
if (p.getPremise() == null) { // create new if (p.getPremise() == null) { // create new
p.setId(premiseRepository.insert(p.getMaterialId(), p.getSupplierId(), p.getUserSupplierId(), p.getGeoLat(), p.getGeoLng(), p.getCountryId(), userId)); p.setId(premiseRepository.insert(p.getMaterialId(), p.getSupplierId(), p.getUserSupplierId(), p.getGeoLat(), p.getGeoLng(), p.getCountryId(), userId));
fillPremise(p, tariffs, userId); fillPremise(p, tariffs, defaultTariff, userId);
} else if (p.getPremise().getState().equals(PremiseState.DRAFT)) { // recycle } else if (p.getPremise().getState().equals(PremiseState.DRAFT)) { // recycle
p.setId(p.getPremise().getId()); p.setId(p.getPremise().getId());
if (createEmpty) { if (createEmpty) {
// reset to defaults. // reset to defaults.
fillPremise(p, tariffs, userId); fillPremise(p, tariffs, defaultTariff, userId);
// remove destinations // remove destinations
destinationService.deleteAllDestinationsByPremiseId(Collections.singletonList(p.getId()), false); destinationService.deleteAllDestinationsByPremiseId(Collections.singletonList(p.getId()), false);
} }
@ -105,7 +113,6 @@ public class PremiseCreationService {
} }
private void copyPremise(TemporaryPremise p, Integer userId) { private void copyPremise(TemporaryPremise p, Integer userId) {
var old = p.getPremise(); var old = p.getPremise();
@ -115,12 +122,12 @@ public class PremiseCreationService {
premiseRepository.setPackagingId(p.getId(), old.getPackagingId()); premiseRepository.setPackagingId(p.getId(), old.getPackagingId());
} }
private void fillPremise(TemporaryPremise p, List<TaxationResolverService.TaxationResolverResponse> tariffs, Integer userId) { private void fillPremise(TemporaryPremise p, List<TaxationResolverService.TaxationResolverResponse> tariffs, Optional<Double> optTariff, Integer userId) {
if (!p.isUserSupplier()) { if (!p.isUserSupplier()) {
var packaging = packagingRepository.getByMaterialIdAndSupplierId(p.getMaterialId(), p.getSupplierId()); var packaging = packagingRepository.getByMaterialIdAndSupplierId(p.getMaterialId(), p.getSupplierId());
Optional<PackagingDimension> hu = packaging.flatMap( o -> packagingDimensionRepository.getById(o.getHuId())); Optional<PackagingDimension> hu = packaging.flatMap(o -> packagingDimensionRepository.getById(o.getHuId()));
Optional<PackagingDimension> shu = packaging.flatMap(o ->packagingDimensionRepository.getById(o.getShuId())); Optional<PackagingDimension> shu = packaging.flatMap(o -> packagingDimensionRepository.getById(o.getShuId()));
if (hu.isPresent() && shu.isPresent()) { if (hu.isPresent() && shu.isPresent()) {
boolean stackable = packagingPropertiesRepository.getByPackagingIdAndType(packaging.get().getId(), PackagingPropertyMappingId.STACKABLE.name()).map(PackagingProperty::getValue).map(Boolean::valueOf).orElse(false); boolean stackable = packagingPropertiesRepository.getByPackagingIdAndType(packaging.get().getId(), PackagingPropertyMappingId.STACKABLE.name()).map(PackagingProperty::getValue).map(Boolean::valueOf).orElse(false);
@ -135,13 +142,15 @@ public class PremiseCreationService {
premiseRepository.resetPrice(Collections.singletonList(p.getId())); premiseRepository.resetPrice(Collections.singletonList(p.getId()));
} }
var defaultTariff = optTariff.orElse(null);
tariffs.stream() tariffs.stream()
.filter(r -> r.material().getId().equals(p.getMaterialId()) && r.countryId().equals(p.getCountryId())) .filter(r -> r.material().getId().equals(p.getMaterialId()) && r.countryId().equals(p.getCountryId()))
.findFirst() .findFirst()
.ifPresent(value -> premiseRepository.updateMaterial(Collections.singletonList( .ifPresent(value -> premiseRepository.updateMaterial(Collections.singletonList(
p.getId()), p.getId()),
value.actualHsCode(), value.actualHsCode(),
value.tariffRate() == null ? null : BigDecimal.valueOf(value.tariffRate()), value.tariffRate() == null ? (defaultTariff == null ? null : BigDecimal.valueOf(defaultTariff)) : BigDecimal.valueOf(value.tariffRate()),
value.tariffRate() == null)); value.tariffRate() == null));
} }
@ -175,10 +184,10 @@ public class PremiseCreationService {
userNodeRepository.getById(temporaryPremise.getUserSupplierId()).orElseThrow(() -> new NotFoundException(NotFoundException.NotFoundType.USER_NODE, "id", String.valueOf(temporaryPremise.getUserSupplierId()))) : userNodeRepository.getById(temporaryPremise.getUserSupplierId()).orElseThrow(() -> new NotFoundException(NotFoundException.NotFoundType.USER_NODE, "id", String.valueOf(temporaryPremise.getUserSupplierId()))) :
nodeRepository.getById(temporaryPremise.getSupplierId()).orElseThrow(() -> new NotFoundException(NotFoundException.NotFoundType.NODE, "id", String.valueOf(temporaryPremise.getSupplierId()))); nodeRepository.getById(temporaryPremise.getSupplierId()).orElseThrow(() -> new NotFoundException(NotFoundException.NotFoundType.NODE, "id", String.valueOf(temporaryPremise.getSupplierId())));
if(temporaryPremise.isUserSupplier()) { if (temporaryPremise.isUserSupplier()) {
var id = userNodeRepository.getOwnerById(temporaryPremise.getUserSupplierId()); var id = userNodeRepository.getOwnerById(temporaryPremise.getUserSupplierId());
if(id.isPresent() && !id.get().equals(userId)) { if (id.isPresent() && !id.get().equals(userId)) {
throw new ForbiddenException("Unable to access this node id " + temporaryPremise.getUserSupplierId()); throw new ForbiddenException("Unable to access this node id " + temporaryPremise.getUserSupplierId());
} }
} }

View file

@ -324,14 +324,14 @@ public class PreCalculationCheckService {
private void materialCheck(Premise premise) { private void materialCheck(Premise premise) {
if (premise.getTariffUnlocked()) { // if (premise.getTariffUnlocked()) {
if (premise.getHsCode() == null || premise.getHsCode().length() < 10) // if (premise.getHsCode() == null || premise.getHsCode().length() < 10)
throw new PremiseValidationError("Invalid HS code (10 digits expected)."); // throw new PremiseValidationError("Invalid HS code (10 digits expected).");
//
var isDeclarable = eUTaxationResolverService.validate(premise.getHsCode()); // var isDeclarable = eUTaxationResolverService.validate(premise.getHsCode());
//
if (!isDeclarable) throw new PremiseValidationError("Invalid HS code (not declarable)."); // if (!isDeclarable) throw new PremiseValidationError("Invalid HS code (not declarable).");
} // }
if (premise.getTariffRate() == null) { if (premise.getTariffRate() == null) {
throw new PremiseValidationError("Tariff rate not entered."); throw new PremiseValidationError("Tariff rate not entered.");