Integrated EUTaxationApiWrapperService and asynchronous precheck:
- **Backend**: Added `EUTaxationApiWrapperService` to validate HS codes during pre-calculation. Updated `PreCalculationCheckService` to run asynchronously and return `CompletableFuture`. - **Frontend**: Refined toast messages in `CalculationSingleEdit.vue` to handle and display server errors more clearly. - **Database**: Marked distance matrix entries as stale during node updates. - **Other**: Added `customLookupExecutor` for asynchronous processing in `AsyncConfig`. Updated related services and repositories to utilize async improvements.
This commit is contained in:
parent
a17d50b9a6
commit
d9229b3d73
7 changed files with 64 additions and 14 deletions
|
|
@ -170,13 +170,26 @@ export default {
|
||||||
const error = await this.premiseEditStore.startCalculation();
|
const error = await this.premiseEditStore.startCalculation();
|
||||||
|
|
||||||
if (error !== null) {
|
if (error !== null) {
|
||||||
this.$refs.toast.addToast({
|
|
||||||
icon: 'warning',
|
if(error.title === 'Internal Server Error') {
|
||||||
message: error.message,
|
this.$refs.toast.addToast({
|
||||||
title: "Cannot start calculation",
|
icon: 'warning',
|
||||||
variant: 'exception',
|
message: error.message,
|
||||||
duration: 8000
|
title: "Calculation finished with errors",
|
||||||
})
|
variant: 'exception',
|
||||||
|
duration: 8000
|
||||||
|
});
|
||||||
|
this.close();
|
||||||
|
} else {
|
||||||
|
this.$refs.toast.addToast({
|
||||||
|
icon: 'warning',
|
||||||
|
message: error.message,
|
||||||
|
title: "Cannot start calculation",
|
||||||
|
variant: 'exception',
|
||||||
|
duration: 8000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,17 @@ public class AsyncConfig {
|
||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "customLookupExecutor")
|
||||||
|
public Executor customLookupExecutor() {
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
executor.setCorePoolSize(4);
|
||||||
|
executor.setMaxPoolSize(8);
|
||||||
|
executor.setQueueCapacity(100);
|
||||||
|
executor.setThreadNamePrefix("calc-");
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(name = "bulkProcessingExecutor")
|
@Bean(name = "bulkProcessingExecutor")
|
||||||
public Executor bulkProcessingExecutor() {
|
public Executor bulkProcessingExecutor() {
|
||||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,10 @@ public class NodeRepository {
|
||||||
// Mark all linked RouteNodes as outdated
|
// Mark all linked RouteNodes as outdated
|
||||||
jdbcTemplate.update("UPDATE premise_route_node SET is_outdated = TRUE WHERE node_id = ?", node.getId());
|
jdbcTemplate.update("UPDATE premise_route_node SET is_outdated = TRUE WHERE node_id = ?", node.getId());
|
||||||
|
|
||||||
|
// Mark all distance matrix entries as stale
|
||||||
|
jdbcTemplate.update("UPDATE distance_matrix SET state = 'STALE' WHERE ((from_node_id = ?) OR (to_node_id = ?))", node.getId(), node.getId());
|
||||||
|
|
||||||
|
|
||||||
return Optional.of(node.getId());
|
return Optional.of(node.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,8 @@ public class PremisesService {
|
||||||
var validSetId = propertySetRepository.getValidSetId();
|
var validSetId = propertySetRepository.getValidSetId();
|
||||||
var validPeriodId = validityPeriodRepository.getValidPeriodId().orElseThrow(() -> new InternalErrorException("no set of transport rates found that is VALID"));
|
var validPeriodId = validityPeriodRepository.getValidPeriodId().orElseThrow(() -> new InternalErrorException("no set of transport rates found that is VALID"));
|
||||||
|
|
||||||
premises.forEach(premiseId -> preCalculationCheckService.doPrecheck(premiseId, validSetId, validPeriodId));
|
var checkResult = premises.stream().map(premiseId -> preCalculationCheckService.doPrecheck(premiseId, validSetId, validPeriodId)).toList();
|
||||||
|
CompletableFuture.allOf(checkResult.toArray(new CompletableFuture[0])).join();
|
||||||
|
|
||||||
var calculationIds = new ArrayList<Integer>();
|
var calculationIds = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,17 @@ public class EUTaxationApiWrapperService {
|
||||||
this.propertyRepository = propertyRepository;
|
this.propertyRepository = propertyRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean validate(String hsCode) {
|
||||||
|
try {
|
||||||
|
var goodsDescription = eUTaxationApiService.getGoodsDescription(hsCode, "en");
|
||||||
|
return goodsDescription.getReturn().getResult().getData().isDeclarable() == true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
// just continue
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public List<CustomDTO> getTariffRates(String hsCode, List<Integer> countryId) {
|
public List<CustomDTO> getTariffRates(String hsCode, List<Integer> countryId) {
|
||||||
var futures = countryId.stream().map(country -> getTariffRate(hsCode, country)).toList();
|
var futures = countryId.stream().map(country -> getTariffRate(hsCode, country)).toList();
|
||||||
|
|
||||||
|
|
@ -85,7 +96,7 @@ public class EUTaxationApiWrapperService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Async
|
@Async("customLookupExecutor")
|
||||||
public CompletableFuture<CustomDTO> getTariffRate(String hsCode, Integer countryId) {
|
public CompletableFuture<CustomDTO> getTariffRate(String hsCode, Integer countryId) {
|
||||||
var country = countryRepository.getById(countryId);
|
var country = countryRepository.getById(countryId);
|
||||||
String iso = country.orElseThrow().getIsoCode().name();
|
String iso = country.orElseThrow().getIsoCode().name();
|
||||||
|
|
@ -157,7 +168,7 @@ public class EUTaxationApiWrapperService {
|
||||||
|
|
||||||
var dutyRate = measure.getDutyRate();
|
var dutyRate = measure.getDutyRate();
|
||||||
|
|
||||||
if(dutyRate == null) return Optional.empty();
|
if (dutyRate == null) return Optional.empty();
|
||||||
|
|
||||||
if (dutyRate.trim().matches("\\d+\\.\\d+\\s*%")) {
|
if (dutyRate.trim().matches("\\d+\\.\\d+\\s*%")) {
|
||||||
return Optional.of(Double.parseDouble(dutyRate.trim().replace("%", "").trim()) / 100);
|
return Optional.of(Double.parseDouble(dutyRate.trim().replace("%", "").trim()) / 100);
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ public class NodeBulkImportService {
|
||||||
var convertedNode = nodeTransformer.toNodeEntity(excelNode);
|
var convertedNode = nodeTransformer.toNodeEntity(excelNode);
|
||||||
convertedNode.setId(node.get().getId());
|
convertedNode.setId(node.get().getId());
|
||||||
if (!compare(convertedNode, node.get())) {
|
if (!compare(convertedNode, node.get())) {
|
||||||
nodeRepository.update(convertedNode);
|
var id = nodeRepository.update(convertedNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,10 @@ import de.avatic.lcc.repositories.rates.MatrixRateRepository;
|
||||||
import de.avatic.lcc.repositories.rates.ValidityPeriodRepository;
|
import de.avatic.lcc.repositories.rates.ValidityPeriodRepository;
|
||||||
import de.avatic.lcc.service.access.PropertyService;
|
import de.avatic.lcc.service.access.PropertyService;
|
||||||
import de.avatic.lcc.service.api.CustomApiService;
|
import de.avatic.lcc.service.api.CustomApiService;
|
||||||
|
import de.avatic.lcc.service.api.EUTaxationApiWrapperService;
|
||||||
import de.avatic.lcc.service.transformer.generic.DimensionTransformer;
|
import de.avatic.lcc.service.transformer.generic.DimensionTransformer;
|
||||||
import de.avatic.lcc.util.exception.internalerror.PremiseValidationError;
|
import de.avatic.lcc.util.exception.internalerror.PremiseValidationError;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -31,6 +33,7 @@ import java.time.format.DateTimeFormatter;
|
||||||
import java.time.temporal.TemporalUnit;
|
import java.time.temporal.TemporalUnit;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
|
@ -53,8 +56,9 @@ public class PreCalculationCheckService {
|
||||||
private final ValidityPeriodRepository validityPeriodRepository;
|
private final ValidityPeriodRepository validityPeriodRepository;
|
||||||
private final PropertySetRepository propertySetRepository;
|
private final PropertySetRepository propertySetRepository;
|
||||||
private final PropertyRepository propertyRepository;
|
private final PropertyRepository propertyRepository;
|
||||||
|
private final EUTaxationApiWrapperService eUTaxationApiWrapperService;
|
||||||
|
|
||||||
public PreCalculationCheckService(PremiseRepository premiseRepository, CustomApiService customApiService, DestinationRepository destinationRepository, RouteRepository routeRepository, NodeRepository nodeRepository, DimensionTransformer dimensionTransformer, PropertyService propertyService, RouteSectionRepository routeSectionRepository, RouteNodeRepository routeNodeRepository, MatrixRateRepository matrixRateRepository, ContainerRateRepository containerRateRepository, ValidityPeriodRepository validityPeriodRepository, PropertySetRepository propertySetRepository, PropertyRepository propertyRepository) {
|
public PreCalculationCheckService(PremiseRepository premiseRepository, CustomApiService customApiService, DestinationRepository destinationRepository, RouteRepository routeRepository, NodeRepository nodeRepository, DimensionTransformer dimensionTransformer, PropertyService propertyService, RouteSectionRepository routeSectionRepository, RouteNodeRepository routeNodeRepository, MatrixRateRepository matrixRateRepository, ContainerRateRepository containerRateRepository, ValidityPeriodRepository validityPeriodRepository, PropertySetRepository propertySetRepository, PropertyRepository propertyRepository, EUTaxationApiWrapperService eUTaxationApiWrapperService) {
|
||||||
this.premiseRepository = premiseRepository;
|
this.premiseRepository = premiseRepository;
|
||||||
this.customApiService = customApiService;
|
this.customApiService = customApiService;
|
||||||
this.destinationRepository = destinationRepository;
|
this.destinationRepository = destinationRepository;
|
||||||
|
|
@ -70,9 +74,11 @@ public class PreCalculationCheckService {
|
||||||
this.validityPeriodRepository = validityPeriodRepository;
|
this.validityPeriodRepository = validityPeriodRepository;
|
||||||
this.propertySetRepository = propertySetRepository;
|
this.propertySetRepository = propertySetRepository;
|
||||||
this.propertyRepository = propertyRepository;
|
this.propertyRepository = propertyRepository;
|
||||||
|
this.eUTaxationApiWrapperService = eUTaxationApiWrapperService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doPrecheck(Integer premiseId, Integer setId, Integer periodId) {
|
@Async("calculationExecutor")
|
||||||
|
public CompletableFuture<Void> doPrecheck(Integer premiseId, Integer setId, Integer periodId) {
|
||||||
var premise = premiseRepository.getPremiseById(premiseId).orElseThrow();
|
var premise = premiseRepository.getPremiseById(premiseId).orElseThrow();
|
||||||
|
|
||||||
supplierCheck(premise);
|
supplierCheck(premise);
|
||||||
|
|
@ -126,6 +132,7 @@ public class PreCalculationCheckService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void periodCheck(ValidityPeriod period, PropertySet set) {
|
private void periodCheck(ValidityPeriod period, PropertySet set) {
|
||||||
|
|
@ -319,7 +326,10 @@ public class PreCalculationCheckService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void materialCheck(Premise premise) {
|
private void materialCheck(Premise premise) {
|
||||||
if (!customApiService.validate(premise.getHsCode()))
|
|
||||||
|
var isDeclarable = eUTaxationApiWrapperService.validate(premise.getHsCode());
|
||||||
|
|
||||||
|
if (!isDeclarable)
|
||||||
throw new PremiseValidationError("Invalid HS code.");
|
throw new PremiseValidationError("Invalid HS code.");
|
||||||
|
|
||||||
if (premise.getTariffRate() == null) {
|
if (premise.getTariffRate() == null) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue