diff --git a/src/main/java/de/avatic/lcc/controller/calculation/PremiseController.java b/src/main/java/de/avatic/lcc/controller/calculation/PremiseController.java index 53da4ad..d0f750a 100644 --- a/src/main/java/de/avatic/lcc/controller/calculation/PremiseController.java +++ b/src/main/java/de/avatic/lcc/controller/calculation/PremiseController.java @@ -136,18 +136,18 @@ public class PremiseController { return ResponseEntity.ok(destinationService.createDestination(destinationCreateDTO)); } - @GetMapping({"/destination({id}", "/destination({id}/"}) + @GetMapping({"/destination/{id}", "/destination/{id}/"}) public ResponseEntity getDestination(@PathVariable Integer id) { return ResponseEntity.ok(destinationService.getDestination(id)); } - @PutMapping({"/destination({id}", "/destination({id}/"}) - public ResponseEntity updateDestination(@PathVariable Integer id, @RequestParam DestinationUpdateDTO destinationUpdateDTO) { + @PutMapping({"/destination/{id}", "/destination/{id}/"}) + public ResponseEntity updateDestination(@PathVariable @Min(1) Integer id, @RequestBody @Valid DestinationUpdateDTO destinationUpdateDTO) { destinationService.updateDestination(id, destinationUpdateDTO); return ResponseEntity.ok().build(); } - @DeleteMapping({"/destination({id}", "/destination({id}/"}) + @DeleteMapping({"/destination/{id}", "/destination/{id}/"}) public ResponseEntity deleteDestination(@PathVariable Integer id) { destinationService.deleteDestinationById(id, false); return ResponseEntity.ok().build(); diff --git a/src/main/java/de/avatic/lcc/dto/calculation/RouteDTO.java b/src/main/java/de/avatic/lcc/dto/calculation/RouteDTO.java index e5e6c0f..9961cc3 100644 --- a/src/main/java/de/avatic/lcc/dto/calculation/RouteDTO.java +++ b/src/main/java/de/avatic/lcc/dto/calculation/RouteDTO.java @@ -1,5 +1,6 @@ package de.avatic.lcc.dto.calculation; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.generic.TransportType; @@ -40,6 +41,8 @@ public class RouteDTO { this.type = type; } + + @JsonIgnore public Boolean getSelected() { return isSelected; } @@ -48,6 +51,7 @@ public class RouteDTO { isSelected = selected; } + @JsonIgnore public Boolean getCheapest() { return isCheapest; } @@ -56,6 +60,7 @@ public class RouteDTO { isCheapest = cheapest; } + @JsonIgnore public Boolean getFastest() { return isFastest; } diff --git a/src/main/java/de/avatic/lcc/dto/calculation/edit/destination/DestinationUpdateDTO.java b/src/main/java/de/avatic/lcc/dto/calculation/edit/destination/DestinationUpdateDTO.java index 5f1e795..8080ba8 100644 --- a/src/main/java/de/avatic/lcc/dto/calculation/edit/destination/DestinationUpdateDTO.java +++ b/src/main/java/de/avatic/lcc/dto/calculation/edit/destination/DestinationUpdateDTO.java @@ -1,16 +1,29 @@ package de.avatic.lcc.dto.calculation.edit.destination; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Digits; +import jakarta.validation.constraints.Min; public class DestinationUpdateDTO { @JsonProperty("repacking_cost") + @DecimalMin(value = "0.00", message = "Amount must be greater than or equal 0") + @Digits(integer = 13, fraction = 2, message = "Amount must have at most 2 decimal places") private Number repackingCost; + @JsonProperty("handling_cost") + @DecimalMin(value = "0.00", message = "Amount must be greater than or equal 0") + @Digits(integer = 13, fraction = 2, message = "Amount must have at most 2 decimal places") private Number handlingCost; + @JsonProperty("disposal_cost") + @DecimalMin(value = "0.00", message = "Amount must be greater than or equal 0") + @Digits(integer = 13, fraction = 2, message = "Amount must have at most 2 decimal places") private Number disposalCost; + @JsonProperty("route_selected_id") + @Min(1) private Integer routeSelectedId; public Number getRepackingCost() { diff --git a/src/main/java/de/avatic/lcc/model/premises/route/RouteNode.java b/src/main/java/de/avatic/lcc/model/premises/route/RouteNode.java index 20e62f0..5781aad 100644 --- a/src/main/java/de/avatic/lcc/model/premises/route/RouteNode.java +++ b/src/main/java/de/avatic/lcc/model/premises/route/RouteNode.java @@ -107,7 +107,7 @@ public class RouteNode { } public void setNodeId(Integer nodeId) { - if (nodeId == 0) this.nodeId = null; + if (nodeId == null || nodeId == 0) this.nodeId = null; else this.nodeId = nodeId; } @@ -116,7 +116,7 @@ public class RouteNode { } public void setUserNodeId(Integer userNodeId) { - if (userNodeId == 0) this.userNodeId = null; + if (userNodeId == null || userNodeId == 0) this.userNodeId = null; else this.userNodeId = userNodeId; } diff --git a/src/main/java/de/avatic/lcc/repositories/premise/DestinationRepository.java b/src/main/java/de/avatic/lcc/repositories/premise/DestinationRepository.java index e58f2e0..c7bdf78 100644 --- a/src/main/java/de/avatic/lcc/repositories/premise/DestinationRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/premise/DestinationRepository.java @@ -1,28 +1,34 @@ package de.avatic.lcc.repositories.premise; import de.avatic.lcc.model.premises.route.Destination; +import de.avatic.lcc.util.exception.badrequest.InvalidArgumentException; +import de.avatic.lcc.util.exception.base.ForbiddenException; +import de.avatic.lcc.util.exception.internalerror.DatabaseException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.Collections; -import java.util.List; -import java.util.Optional; +import java.util.*; @Service public class DestinationRepository { private final JdbcTemplate jdbcTemplate; + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; - public DestinationRepository(JdbcTemplate jdbcTemplate) { + + public DestinationRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate) { this.jdbcTemplate = jdbcTemplate; - } + this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; + } @Transactional public Optional getById(Integer id) { @@ -45,9 +51,46 @@ public class DestinationRepository { } @Transactional - public void update(Integer id, Integer userId, Number repackingCost, Number disposalCost, Number handlingCost) { - String query = "UPDATE premise_destination SET repacking_cost = ?, disposal_cost = ?, handling_cost = ? WHERE id = ? AND user_id = ?"; - //TODO + public void update(Integer id, BigDecimal repackingCost, BigDecimal disposalCost, BigDecimal handlingCost) { + if (id == null) { + throw new InvalidArgumentException("ID cannot be null"); + } + + StringBuilder sql = new StringBuilder("UPDATE premise_destination SET "); + Map parameters = new HashMap<>(); + List setClauses = new ArrayList<>(); + + // Build dynamic SET clauses based on non-null parameters + if (repackingCost != null) { + setClauses.add("repacking_cost = :repackingCost"); + parameters.put("repackingCost", repackingCost); + } + + if (disposalCost != null) { + setClauses.add("disposal_cost = :disposalCost"); + parameters.put("disposalCost", disposalCost); + } + + if (handlingCost != null) { + setClauses.add("handling_cost = :handlingCost"); + parameters.put("handlingCost", handlingCost); + } + + // If no parameters to update, return early + if (setClauses.isEmpty()) { + return; + } + + // Complete the SQL statement + sql.append(String.join(", ", setClauses)); + sql.append(" WHERE id = :id"); + parameters.put("id", id); + + int rowsAffected = namedParameterJdbcTemplate.update(sql.toString(), parameters); + + if (rowsAffected == 0) { + throw new DatabaseException("No premise_destination found with id: " + id); + } } @@ -70,7 +113,7 @@ public class DestinationRepository { WHERE pd.id = ?"""; List userId = jdbcTemplate.query(query, (rs, rowNum) -> { - return rs.getInt("userId"); + return rs.getInt("user_id"); }, id); if (userId.isEmpty()) @@ -127,6 +170,15 @@ public class DestinationRepository { } + @Transactional + public void checkOwner(Integer id, Integer userId) { + var ownerId = getOwnerIdById(id); + + if (ownerId.isEmpty() || !ownerId.get().equals(userId)) { + throw new ForbiddenException("Access violation. Accessing destination with id = " + id); + } + } + private static class DestinationMapper implements RowMapper { @Override diff --git a/src/main/java/de/avatic/lcc/repositories/premise/PremiseRepository.java b/src/main/java/de/avatic/lcc/repositories/premise/PremiseRepository.java index d103848..5543740 100644 --- a/src/main/java/de/avatic/lcc/repositories/premise/PremiseRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/premise/PremiseRepository.java @@ -11,6 +11,7 @@ import de.avatic.lcc.model.utils.DimensionUnit; import de.avatic.lcc.model.utils.WeightUnit; import de.avatic.lcc.repositories.pagination.SearchQueryPagination; import de.avatic.lcc.repositories.pagination.SearchQueryResult; +import de.avatic.lcc.util.exception.base.ForbiddenException; import de.avatic.lcc.util.exception.internalerror.DatabaseException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; @@ -160,9 +161,9 @@ public class PremiseRepository { } @Transactional - public void updatePackaging(List premiseIds, Integer userId, PackagingDimension hu, PackagingDimension shu, Boolean stackable, Boolean mixable) { + public void updatePackaging(List premiseIds, PackagingDimension hu, PackagingDimension shu, Boolean stackable, Boolean mixable) { - if (premiseIds == null || premiseIds.isEmpty() || userId == null || hu == null) { + if (premiseIds == null || premiseIds.isEmpty() || hu == null) { return; } @@ -179,7 +180,6 @@ public class PremiseRepository { params.addValue("unitCount", hu.getContentUnitCount()*shu.getContentUnitCount()); params.addValue("stackable", isStackable); params.addValue("mixable", isMixable); - params.addValue("userId", userId); params.addValue("premiseIds", premiseIds); String sql = """ @@ -193,7 +193,7 @@ public class PremiseRepository { hu_unit_count = :unitCount, hu_stackable = :stackable, hu_mixable = :mixable - WHERE user_id = :userId AND id IN (:premiseIds) + WHERE id IN (:premiseIds) """; namedParameterJdbcTemplate.update(sql, params); @@ -201,15 +201,14 @@ public class PremiseRepository { } @Transactional - public void updatePackaging(List premiseIds, Integer userId, PackagingDimension hu, Boolean stackable, Boolean mixable) { + public void updatePackaging(List premiseIds, PackagingDimension hu, Boolean stackable, Boolean mixable) { - if (premiseIds == null || premiseIds.isEmpty() || userId == null) { + if (premiseIds == null || premiseIds.isEmpty()) { return; } MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("userId", userId); params.addValue("premiseIds", premiseIds); StringBuilder sqlBuilder = new StringBuilder("UPDATE premise SET "); @@ -272,7 +271,7 @@ public class PremiseRepository { // Build the complete SQL sqlBuilder.append(String.join(", ", setClauses)); - sqlBuilder.append(" WHERE user_id = :userId AND id IN (:premiseIds)"); + sqlBuilder.append(" WHERE id IN (:premiseIds)"); String sql = sqlBuilder.toString(); var affectedRows = namedParameterJdbcTemplate.update(sql, params); @@ -283,7 +282,7 @@ public class PremiseRepository { } @Transactional - public void updateMaterial(List premiseIds, Integer userId, String hsCode, BigDecimal tariffRate) { + public void updateMaterial(List premiseIds, String hsCode, BigDecimal tariffRate) { // Build the SET clause dynamically based on non-null parameters List setClauses = new ArrayList<>(); @@ -304,9 +303,6 @@ public class PremiseRepository { return; } - // Add userId to parameters - parameters.add(userId); - // Add premiseIds to parameters parameters.addAll(premiseIds); @@ -314,7 +310,7 @@ public class PremiseRepository { String setClause = String.join(", ", setClauses); String query = "UPDATE premise SET " + setClause + - " WHERE user_id = ? AND id IN (" + placeholders + ")"; + " WHERE id IN (" + placeholders + ")"; var affectedRows = jdbcTemplate.update( query, @@ -337,7 +333,7 @@ public class PremiseRepository { } @Transactional - public void updatePrice(List premiseIds, int userId, BigDecimal price, Boolean includeFcaFee, BigDecimal overseaShare) { + public void updatePrice(List premiseIds, BigDecimal price, Boolean includeFcaFee, BigDecimal overseaShare) { // Build dynamic SET clause based on non-null parameters List setClauses = new ArrayList<>(); if (price != null) { @@ -358,7 +354,7 @@ public class PremiseRepository { String placeholders = String.join(",", Collections.nCopies(premiseIds.size(), "?")); String setClause = String.join(", ", setClauses); - String query = "UPDATE premise SET " + setClause + " WHERE user_id = ? AND id IN (" + placeholders + ")"; + String query = "UPDATE premise SET " + setClause + " WHERE id IN (" + placeholders + ")"; var affectedRows = jdbcTemplate.update( query, @@ -376,9 +372,6 @@ public class PremiseRepository { ps.setBigDecimal(parameterIndex++, overseaShare); } - // Set user_id parameter - ps.setInt(parameterIndex++, userId); - // Set premise ID parameters for (Integer premiseId : premiseIds) { ps.setInt(parameterIndex++, premiseId); @@ -608,6 +601,19 @@ public class PremiseRepository { throw new DatabaseException("No premise found with id " + id); } + @Transactional + public void checkOwner(List premiseIds, int userId) { + String query = """ + SELECT id FROM premise WHERE premise.id IN (?) AND user_id <> ? + """; + + var otherIds = jdbcTemplate.queryForList(query, Integer.class, premiseIds, userId); + + if(!otherIds.isEmpty()) { + throw new ForbiddenException("Access violation. Cannot open premise with ids = " + otherIds); + } + } + /** * Encapsulates SQL query building logic diff --git a/src/main/java/de/avatic/lcc/repositories/premise/RouteRepository.java b/src/main/java/de/avatic/lcc/repositories/premise/RouteRepository.java index d604a7e..e67ec4d 100644 --- a/src/main/java/de/avatic/lcc/repositories/premise/RouteRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/premise/RouteRepository.java @@ -1,6 +1,7 @@ package de.avatic.lcc.repositories.premise; import de.avatic.lcc.model.premises.route.Route; +import de.avatic.lcc.util.exception.internalerror.DatabaseException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.GeneratedKeyHolder; @@ -78,6 +79,23 @@ public class RouteRepository { return keyHolder.getKey() != null ? keyHolder.getKey().intValue() : null; } + public void updateSelectedByDestinationId(Integer destinationId, Integer selectedRouteId) { + String deselectQuery = """ + UPDATE premise_route SET is_selected = FALSE WHERE is_selected = TRUE AND premise_destination_id = ? + """; + String selectQuery = """ + UPDATE premise_route SET is_selected = TRUE WHERE id = ? + """; + + jdbcTemplate.update(deselectQuery, destinationId); + var affectedRowsSelect = jdbcTemplate.update(selectQuery, selectedRouteId); + + if (1 != affectedRowsSelect) { + throw new DatabaseException("Unable to select route with id " + selectedRouteId); + } + + } + private static class RouteMapper implements RowMapper { @Override public Route mapRow(ResultSet rs, int rowNum) throws SQLException { diff --git a/src/main/java/de/avatic/lcc/repositories/users/UserNodeRepository.java b/src/main/java/de/avatic/lcc/repositories/users/UserNodeRepository.java index 1efef9b..7dcc4da 100644 --- a/src/main/java/de/avatic/lcc/repositories/users/UserNodeRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/users/UserNodeRepository.java @@ -2,10 +2,12 @@ package de.avatic.lcc.repositories.users; import de.avatic.lcc.model.nodes.Node; import de.avatic.lcc.repositories.NodeRepository; +import de.avatic.lcc.util.exception.base.ForbiddenException; import de.avatic.lcc.util.exception.internalerror.DatabaseException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; import java.sql.ResultSet; import java.sql.SQLException; @@ -110,6 +112,19 @@ public class UserNodeRepository { return Optional.of(ids.getFirst()); } + @Transactional + public void checkOwner(List userNodeIds, Integer userId) { + String query = """ + SELECT id FROM sys_user_node WHERE id IN (?) AND user_id <> ? + """; + + var otherIds = jdbcTemplate.queryForList(query, Integer.class, userNodeIds, userId); + + if(!otherIds.isEmpty()) { + throw new ForbiddenException("Access violation. Cannot open user nodes with ids = " + otherIds); + } + } + private static class NodeMapper implements RowMapper { @Override diff --git a/src/main/java/de/avatic/lcc/service/access/DestinationService.java b/src/main/java/de/avatic/lcc/service/access/DestinationService.java index 9813c6e..ad5e10f 100644 --- a/src/main/java/de/avatic/lcc/service/access/DestinationService.java +++ b/src/main/java/de/avatic/lcc/service/access/DestinationService.java @@ -1,21 +1,26 @@ package de.avatic.lcc.service.access; -import de.avatic.lcc.dto.calculation.edit.destination.DestinationCreateDTO; import de.avatic.lcc.dto.calculation.DestinationDTO; +import de.avatic.lcc.dto.calculation.edit.destination.DestinationCreateDTO; import de.avatic.lcc.dto.calculation.edit.destination.DestinationUpdateDTO; import de.avatic.lcc.model.nodes.Node; import de.avatic.lcc.model.premises.route.*; +import de.avatic.lcc.model.properties.SystemPropertyMappingId; import de.avatic.lcc.repositories.NodeRepository; import de.avatic.lcc.repositories.premise.*; +import de.avatic.lcc.repositories.properties.PropertyRepository; import de.avatic.lcc.repositories.users.UserNodeRepository; import de.avatic.lcc.service.calculation.RoutingService; import de.avatic.lcc.service.transformer.premise.DestinationTransformer; +import de.avatic.lcc.util.exception.base.ForbiddenException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; -import java.sql.Array; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -28,12 +33,15 @@ public class DestinationService { private final RouteRepository routeRepository; private final RouteSectionRepository routeSectionRepository; private final RouteNodeRepository routeNodeRepository; - private final RoutingService routingService;; + private final RoutingService routingService; + ; private final NodeRepository nodeRepository; private final PremiseRepository premiseRepository; private final UserNodeRepository userNodeRepository; + private final PropertyRepository propertyRepository; + private final PropertyService propertyService; - public DestinationService(DestinationRepository destinationRepository, DestinationTransformer destinationTransformer, RouteRepository routeRepository, RouteSectionRepository routeSectionRepository, RouteNodeRepository routeNodeRepository, RoutingService routingService, NodeRepository nodeRepository, PremiseRepository premiseRepository, UserNodeRepository userNodeRepository) { + public DestinationService(DestinationRepository destinationRepository, DestinationTransformer destinationTransformer, RouteRepository routeRepository, RouteSectionRepository routeSectionRepository, RouteNodeRepository routeNodeRepository, RoutingService routingService, NodeRepository nodeRepository, PremiseRepository premiseRepository, UserNodeRepository userNodeRepository, PropertyRepository propertyRepository, PropertyService propertyService) { this.destinationRepository = destinationRepository; this.destinationTransformer = destinationTransformer; this.routeRepository = routeRepository; @@ -43,6 +51,8 @@ public class DestinationService { this.nodeRepository = nodeRepository; this.premiseRepository = premiseRepository; this.userNodeRepository = userNodeRepository; + this.propertyRepository = propertyRepository; + this.propertyService = propertyService; } @Transactional @@ -53,8 +63,8 @@ public class DestinationService { var existingDestinations = destinationRepository.getByPremiseIdsAndNodeId(dto.getPremiseId(), dto.getDestinationNodeId(), userId); var premisesIdsToProcess = new ArrayList(); - for(var premiseId : dto.getPremiseId()) { - if(existingDestinations.stream().map(Destination::getPremiseId).noneMatch(id -> id.equals(premiseId))) { + for (var premiseId : dto.getPremiseId()) { + if (existingDestinations.stream().map(Destination::getPremiseId).noneMatch(id -> id.equals(premiseId))) { premisesIdsToProcess.add(premiseId); } } @@ -65,7 +75,7 @@ public class DestinationService { var destinations = new ArrayList(); - for(var premise : premisesToProcess) { + for (var premise : premisesToProcess) { var destination = new Destination(); destination.setDestinationNodeId(dto.getDestinationNodeId()); destination.setPremiseId(premise.getId()); @@ -96,12 +106,24 @@ public class DestinationService { return destinationTransformer.toDestinationDTO(destinationRepository.getById(id).orElseThrow()); } + @Transactional public void updateDestination(Integer id, DestinationUpdateDTO destinationUpdateDTO) { - //todo check authorization Integer userId = 1; + destinationRepository.checkOwner(id, userId); - destinationRepository.update(id, userId, destinationUpdateDTO.getRepackingCost(), destinationUpdateDTO.getDisposalCost(), destinationUpdateDTO.getHandlingCost()); + + var selectedRouteId = destinationUpdateDTO.getRouteSelectedId(); + + if (selectedRouteId != null) { + routeRepository.updateSelectedByDestinationId(id, selectedRouteId); + } + + + destinationRepository.update(id, + destinationUpdateDTO.getRepackingCost() == null ? null : BigDecimal.valueOf(destinationUpdateDTO.getRepackingCost().doubleValue()), + destinationUpdateDTO.getDisposalCost() == null ? null : BigDecimal.valueOf(destinationUpdateDTO.getDisposalCost().doubleValue()), + destinationUpdateDTO.getHandlingCost() == null ? null : BigDecimal.valueOf(destinationUpdateDTO.getHandlingCost().doubleValue())); } @@ -154,10 +176,10 @@ public class DestinationService { Integer userId = 1; Optional ownerId = destinationRepository.getOwnerIdById(id); - if(ownerId.isPresent() && ownerId.get().equals(userId)) { + if (ownerId.isPresent() && ownerId.get().equals(userId)) { List routes = routeRepository.getByDestinationId(id); - for(var route : routes) { + for (var route : routes) { List sections = routeSectionRepository.getByRouteId(route.getId()); routeSectionRepository.deleteAllById(sections.stream().map(RouteSection::getId).toList()); routeNodeRepository.deleteAllById(sections.stream().flatMap(section -> Stream.of(section.getFromRouteNodeId(), section.getToRouteNodeId())).toList()); @@ -165,13 +187,13 @@ public class DestinationService { routeRepository.deleteAllById(routes.stream().map(Route::getId).toList()); - if(!deleteRoutesOnly) + if (!deleteRoutesOnly) destinationRepository.deleteById(id); return; } - throw new RuntimeException("Not authorized to delete destination with id " + id); + throw new ForbiddenException("Not authorized to delete destination with id " + id); } @@ -180,16 +202,16 @@ public class DestinationService { List destinations = destinationRepository.getByPremiseId(fromPremiseId); - for(Destination destination : destinations) { + for (Destination destination : destinations) { destination.setPremiseId(toPremiseId); Integer destinationId = destinationRepository.insert(destination); - for(Route route : routeRepository.getByDestinationId(destination.getId())) { + for (Route route : routeRepository.getByDestinationId(destination.getId())) { route.setDestinationId(destinationId); Integer routeId = routeRepository.insert(route); - for(RouteSection section : routeSectionRepository.getByRouteId(route.getId())) { + for (RouteSection section : routeSectionRepository.getByRouteId(route.getId())) { section.setRouteId(routeId); RouteNode fromNode = routeNodeRepository.getById(section.getFromRouteNodeId()).orElseThrow(); diff --git a/src/main/java/de/avatic/lcc/service/access/PremisesService.java b/src/main/java/de/avatic/lcc/service/access/PremisesService.java index f068574..671ad51 100644 --- a/src/main/java/de/avatic/lcc/service/access/PremisesService.java +++ b/src/main/java/de/avatic/lcc/service/access/PremisesService.java @@ -15,6 +15,7 @@ import de.avatic.lcc.repositories.premise.PremiseRepository; import de.avatic.lcc.repositories.properties.PropertyRepository; import de.avatic.lcc.repositories.properties.PropertySetRepository; import de.avatic.lcc.repositories.rates.ValidityPeriodRepository; +import de.avatic.lcc.service.calculation.execution.CalculationExecutionService; import de.avatic.lcc.service.calculation.execution.CalculationStatusService; import de.avatic.lcc.service.transformer.generic.DimensionTransformer; import de.avatic.lcc.service.transformer.premise.PremiseTransformer; @@ -39,8 +40,9 @@ public class PremisesService { private final PropertySetRepository propertySetRepository; private final ValidityPeriodRepository validityPeriodRepository; private final CalculationStatusService calculationStatusService; + private final CalculationExecutionService calculationExecutionService; - public PremisesService(PremiseRepository premiseRepository, PremiseTransformer premiseTransformer, DimensionTransformer dimensionTransformer, DestinationService destinationService, CalculationJobRepository calculationJobRepository, PropertyRepository propertyRepository, PropertySetRepository propertySetRepository, ValidityPeriodRepository validityPeriodRepository, CalculationStatusService calculationStatusService) { + public PremisesService(PremiseRepository premiseRepository, PremiseTransformer premiseTransformer, DimensionTransformer dimensionTransformer, DestinationService destinationService, CalculationJobRepository calculationJobRepository, PropertyRepository propertyRepository, PropertySetRepository propertySetRepository, ValidityPeriodRepository validityPeriodRepository, CalculationStatusService calculationStatusService, CalculationExecutionService calculationExecutionService) { this.premiseRepository = premiseRepository; this.premiseTransformer = premiseTransformer; this.dimensionTransformer = dimensionTransformer; @@ -50,6 +52,7 @@ public class PremisesService { this.propertySetRepository = propertySetRepository; this.validityPeriodRepository = validityPeriodRepository; this.calculationStatusService = calculationStatusService; + this.calculationExecutionService = calculationExecutionService; } @Transactional(readOnly = true) @@ -67,8 +70,10 @@ public class PremisesService { @Transactional(readOnly = true) public List getPremises(List premiseIds) { - //TODO check if user authorized - var userId = 0; + //TODO use real user + var userId = 1; + premiseRepository.checkOwner(premiseIds, userId); + return premiseRepository.getPremisesById(premiseIds).stream().map(premiseTransformer::toPremiseDetailDTO).toList(); } @@ -81,7 +86,7 @@ public class PremisesService { var validSetId = propertySetRepository.getValidSetId(); var validPeriodId = validityPeriodRepository.getValidPeriodId().orElseThrow(() -> new InternalErrorException("no valid period found that is VALID")); - var calculationIds = new ArrayList<>(); + var calculationIds = new ArrayList(); premises.forEach(p -> { CalculationJob job = new CalculationJob(); @@ -96,6 +101,8 @@ public class PremisesService { calculationIds.add(calculationJobRepository.insert(job)); }); + + calculationIds.forEach(calculationExecutionService::calculateJob); return calculationStatusService.schedule(calculationIds); } @@ -103,45 +110,46 @@ public class PremisesService { return calculationStatusService.getCalculationStatus(processId); } - public HashMap updatePackaging(PackagingUpdateDTO packagingDTO) { + @Transactional + public void updatePackaging(PackagingUpdateDTO packagingDTO) { //TODO check values. and return errors if needed var userId = 1; // todo get id from current user. + premiseRepository.checkOwner(packagingDTO.getPremiseIds(), userId); var dimensions = packagingDTO.getDimensions() == null ? null : dimensionTransformer.toDimensionEntity(packagingDTO.getDimensions()); - premiseRepository.updatePackaging(packagingDTO.getPremiseIds(), userId, dimensions, packagingDTO.getStackable(), packagingDTO.getMixable()); + premiseRepository.updatePackaging(packagingDTO.getPremiseIds(), dimensions, packagingDTO.getStackable(), packagingDTO.getMixable()); - - return null; } - public HashMap updateMaterial(MaterialUpdateDTO materialUpdateDTO) { + public void updateMaterial(MaterialUpdateDTO materialUpdateDTO) { //TODO check values. and return errors if needed var userId = 1; // todo get id from current user. + premiseRepository.checkOwner(materialUpdateDTO.getPremiseIds(), userId); var tariffRate = materialUpdateDTO.getTariffRate() == null ? null : BigDecimal.valueOf(materialUpdateDTO.getTariffRate().doubleValue()); - premiseRepository.updateMaterial(materialUpdateDTO.getPremiseIds(), userId, materialUpdateDTO.getHsCode(), tariffRate); + premiseRepository.updateMaterial(materialUpdateDTO.getPremiseIds(), materialUpdateDTO.getHsCode(), tariffRate); - return null; } - public HashMap updatePrice(PriceUpdateDTO priceUpdateDTO) { + public void updatePrice(PriceUpdateDTO priceUpdateDTO) { //TODO check values. and return errors if needed var userId = 1; // todo get id from current user. + premiseRepository.checkOwner(priceUpdateDTO.getPremiseIds(), userId); var price = priceUpdateDTO.getPrice() == null ? null : BigDecimal.valueOf(priceUpdateDTO.getPrice().doubleValue()); var overseaShare = priceUpdateDTO.getOverseaShare() == null ? null : BigDecimal.valueOf(priceUpdateDTO.getOverseaShare().doubleValue()); - premiseRepository.updatePrice(priceUpdateDTO.getPremiseIds(), userId, price, priceUpdateDTO.getIncludeFcaFee(),overseaShare); - - - return null; + premiseRepository.updatePrice(priceUpdateDTO.getPremiseIds(), price, priceUpdateDTO.getIncludeFcaFee(),overseaShare); } @Transactional public void delete(List premiseIds) { //TODO check authorization + var userId = 1; + premiseRepository.checkOwner(premiseIds, userId); + destinationService.deleteAllDestinationsByPremiseId(premiseIds, false); premiseRepository.deletePremisesById(premiseIds); } diff --git a/src/main/java/de/avatic/lcc/service/calculation/ChainResolver.java b/src/main/java/de/avatic/lcc/service/calculation/ChainResolver.java index 8813528..13380df 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/ChainResolver.java +++ b/src/main/java/de/avatic/lcc/service/calculation/ChainResolver.java @@ -73,7 +73,7 @@ public class ChainResolver { } if (validationObject.valid()) - foundChains.add(validationObject.getChain()); + foundChains.add(new ArrayList<>(validationObject.getChain())); } else { log.warn("Circular reference detected while building predecessor chain for node {}", nodeId); } diff --git a/src/main/java/de/avatic/lcc/service/calculation/ChangeMaterialService.java b/src/main/java/de/avatic/lcc/service/calculation/ChangeMaterialService.java index cc15c0a..1db86fb 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/ChangeMaterialService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/ChangeMaterialService.java @@ -83,7 +83,7 @@ public class ChangeMaterialService { if (dimension.isPresent()) { boolean stackable = packagingPropertiesRepository.getByPackagingIdAndType(packaging.getFirst().getId(), PackagingPropertyMappingId.STACKABLE.name()).map(PackagingProperty::getValue).map(Boolean::valueOf).orElse(false); boolean mixable = packagingPropertiesRepository.getByPackagingIdAndType(packaging.getFirst().getId(), PackagingPropertyMappingId.MIXABLE.name()).map(PackagingProperty::getValue).map(Boolean::valueOf).orElse(false); - premiseRepository.updatePackaging(Collections.singletonList(premise.getId()), userId, dimension.get(), stackable, mixable); + premiseRepository.updatePackaging(Collections.singletonList(premise.getId()), dimension.get(), stackable, mixable); } } diff --git a/src/main/java/de/avatic/lcc/service/calculation/ChangeSupplierService.java b/src/main/java/de/avatic/lcc/service/calculation/ChangeSupplierService.java index 6ad1c3f..58fb063 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/ChangeSupplierService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/ChangeSupplierService.java @@ -113,7 +113,7 @@ public class ChangeSupplierService { if (dimension.isPresent()) { boolean stackable = packagingPropertiesRepository.getByPackagingIdAndType(packaging.getFirst().getId(), PackagingPropertyMappingId.STACKABLE.name()).map(PackagingProperty::getValue).map(Boolean::valueOf).orElse(false); boolean mixable = packagingPropertiesRepository.getByPackagingIdAndType(packaging.getFirst().getId(), PackagingPropertyMappingId.MIXABLE.name()).map(PackagingProperty::getValue).map(Boolean::valueOf).orElse(false); - premiseRepository.updatePackaging(Collections.singletonList(premise.getId()), userId, dimension.get(), stackable, mixable); + premiseRepository.updatePackaging(Collections.singletonList(premise.getId()), dimension.get(), stackable, mixable); } } } diff --git a/src/main/java/de/avatic/lcc/service/calculation/PremiseCreationService.java b/src/main/java/de/avatic/lcc/service/calculation/PremiseCreationService.java index 2f49fd1..352142a 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/PremiseCreationService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/PremiseCreationService.java @@ -58,6 +58,7 @@ public class PremiseCreationService { @Transactional public List createPremises(List materialIds, List supplierIds, List userSupplierIds, boolean createEmpty) { Integer userId = 1; //TODO get user id + userNodeRepository.checkOwner(userSupplierIds, userId); /* Build all resulting premises */ List premises = Stream.concat( @@ -96,9 +97,9 @@ public class PremiseCreationService { private void copyPremise(TemporaryPremise p, Integer userId) { var old = p.getPremise(); - premiseRepository.updateMaterial(Collections.singletonList(p.getId()), userId, old.getHsCode(), old.getCustomRate()); - premiseRepository.updatePrice(Collections.singletonList(p.getId()), userId, old.getMaterialCost(), old.getFcaEnabled(), old.getOverseaShare()); - premiseRepository.updatePackaging(Collections.singletonList(p.getId()), userId, dimensionTransformer.toDimensionEntity(old), old.getHuStackable(), old.getHuMixable()); + premiseRepository.updateMaterial(Collections.singletonList(p.getId()), old.getHsCode(), old.getCustomRate()); + premiseRepository.updatePrice(Collections.singletonList(p.getId()), old.getMaterialCost(), old.getFcaEnabled(), old.getOverseaShare()); + premiseRepository.updatePackaging(Collections.singletonList(p.getId()), dimensionTransformer.toDimensionEntity(old), old.getHuStackable(), old.getHuMixable()); premiseRepository.setPackagingId(p.getId(), old.getId()); } @@ -112,13 +113,13 @@ public class PremiseCreationService { if (hu.isPresent() && shu.isPresent()) { boolean stackable = packagingPropertiesRepository.getByPackagingIdAndType(packaging.getFirst().getId(), PackagingPropertyMappingId.STACKABLE.name()).map(PackagingProperty::getValue).map(Boolean::valueOf).orElse(false); boolean mixable = packagingPropertiesRepository.getByPackagingIdAndType(packaging.getFirst().getId(), PackagingPropertyMappingId.MIXABLE.name()).map(PackagingProperty::getValue).map(Boolean::valueOf).orElse(false); - premiseRepository.updatePackaging(Collections.singletonList(p.getId()), userId, hu.get(), shu.get(), stackable, mixable); //TODO clarify if the hu unit count in packaging data is total unit count or shu count (shu*hu or hu) + premiseRepository.updatePackaging(Collections.singletonList(p.getId()), hu.get(), shu.get(), stackable, mixable); //TODO clarify if the hu unit count in packaging data is total unit count or shu count (shu*hu or hu) premiseRepository.setPackagingId(p.getId(), packaging.getFirst().getId()); } } var material = materialRepository.getById(p.getMaterialId()); - material.ifPresent(value -> premiseRepository.updateMaterial(Collections.singletonList(p.getId()), userId, value.getHsCode(), customApiService.getTariffRate(value.getHsCode(), getCountryId(p)))); + material.ifPresent(value -> premiseRepository.updateMaterial(Collections.singletonList(p.getId()), value.getHsCode(), customApiService.getTariffRate(value.getHsCode(), getCountryId(p)))); } diff --git a/src/main/java/de/avatic/lcc/service/calculation/RoutingService.java b/src/main/java/de/avatic/lcc/service/calculation/RoutingService.java index d156edb..d3ab3f9 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/RoutingService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/RoutingService.java @@ -60,6 +60,7 @@ public class RoutingService { */ List> destinationChains = chainResolver.buildChains(destination.getId()); + destinationChains.forEach(chain -> chain.addFirst(destination)); List inboundCountries = destinationChains.stream().filter(chain -> !chain.isEmpty()).map(chain -> chain.getLast().getCountryId()).distinct().toList(); /* @@ -86,7 +87,8 @@ public class RoutingService { * At this point all routes with a main run are created. * We find now the best route per main run and throw away the rest. */ - findCheapestPerMainRun(container); + // we cannot do this, because we need all the Intermediate Warehouses to show. + //findCheapestPerMainRun(container); /* * Now we also create routes without main run (matrix rate) @@ -122,11 +124,11 @@ public class RoutingService { routeNode.setAddress(node.getAddress()); routeNode.setGeoLng(node.getGeoLng()); routeNode.setGeoLat(node.getGeoLat()); - routeNode.setUserNodeId(isUserNode? node.getId() : null); + routeNode.setUserNodeId(isUserNode ? node.getId() : null); routeNode.setNodeId(isUserNode ? null : node.getId()); routeNode.setIntermediate(node.getIntermediate() != null ? node.getIntermediate() : false); - routeNode.setDestination(node.getDestination() != null ? node.getIntermediate() : false); - routeNode.setSource(node.getSource() != null ? node.getIntermediate() : false); + routeNode.setDestination(node.getDestination() != null ? node.getDestination() : false); + routeNode.setSource(node.getSource() != null ? node.getSource() : false); routeNode.setOutdated(node.getDeprecated()); return routeNode; @@ -137,6 +139,7 @@ public class RoutingService { routeObj.setCheapest(route.isCheapest()); routeObj.setFastest(route.isFastest()); + routeObj.setSelected(false); return routeObj; } @@ -149,11 +152,11 @@ public class RoutingService { boolean firstSection = true; RouteNode fromNode = null; - for(var section : sections.reversed()) { + for (var section : sections.reversed()) { var routeSection = mapSection(section); - if(firstSection) { - fromNode = mapNode(section.getFromNode(),sourceIsUserNode); + if (firstSection) { + fromNode = mapNode(section.getFromNode(), sourceIsUserNode); firstSection = false; } @@ -168,7 +171,7 @@ public class RoutingService { } - if(section.getType().equals(TemporaryRateObject.TemporaryRateObjectType.MAIN_RUN) || section.getType().equals(TemporaryRateObject.TemporaryRateObjectType.POST_RUN)) + if (section.getType().equals(TemporaryRateObject.TemporaryRateObjectType.MAIN_RUN) || section.getType().equals(TemporaryRateObject.TemporaryRateObjectType.POST_RUN)) passedMainRun = true; routeSection.setListPosition(index++); @@ -189,7 +192,7 @@ public class RoutingService { routeSection.setMainRun(section.getType().equals(TemporaryRateObject.TemporaryRateObjectType.MAIN_RUN)); routeSection.setOutdated(false); - routeSection.setPostRun(false); + routeSection.setPostRun(section.getType().equals(TemporaryRateObject.TemporaryRateObjectType.POST_RUN)); routeSection.setPreRun(false); return routeSection; @@ -198,7 +201,8 @@ public class RoutingService { private RateType mapRateType(TemporaryRateObject rate) { - if (Objects.requireNonNull(rate.getType()) == TemporaryRateObject.TemporaryRateObjectType.MATRIX) { + if (Objects.requireNonNull(rate.getType()) == TemporaryRateObject.TemporaryRateObjectType.MATRIX + || Objects.requireNonNull(rate.getType()) == TemporaryRateObject.TemporaryRateObjectType.NEAR_BY) { return RateType.MATRIX; } return RateType.CONTAINER; @@ -206,8 +210,8 @@ public class RoutingService { private TransportType mapRouteType(TemporaryRateObject rate) { - switch(rate.getType()) { - case CONTAINER, MATRIX -> { + switch (rate.getType()) { + case CONTAINER, MATRIX, NEAR_BY -> { return TransportType.ROAD; } case POST_RUN -> { @@ -230,26 +234,26 @@ public class RoutingService { TemporaryRouteObject fastest = null; double fastestRoute = Double.MAX_VALUE; - for(var route : routes) { + for (var route : routes) { double routeCost = route.getCost(); int leadTime = route.getLeadTime(); - if(routeCost < cheapestCost) { + if (routeCost < cheapestCost) { cheapestCost = routeCost; cheapest = route; } - if(leadTime < fastestRoute) { + if (leadTime < fastestRoute) { fastestRoute = leadTime; fastest = route; } } - if(cheapest != null) { + if (cheapest != null) { cheapest.setCheapest(); } - if(fastest != null) { + if (fastest != null) { fastest.setFastest(); } } @@ -259,21 +263,21 @@ public class RoutingService { var routesByMainRun = container.getRoutes().stream().collect(Collectors.groupingBy(TemporaryRouteObject::getMainRun)); Collection cheapestRoutes = new ArrayList<>(); - for(var mainRun : routesByMainRun.keySet()) { + for (var mainRun : routesByMainRun.keySet()) { List routes = routesByMainRun.get(mainRun); TemporaryRouteObject cheapest = null; double cheapestCost = Double.MAX_VALUE; - for(var route : routes) { + for (var route : routes) { double routeCost = route.getCost(); - if(routeCost < cheapestCost) { + if (routeCost < cheapestCost) { cheapestCost = routeCost; cheapest = route; } } - if(cheapest != null) { + if (cheapest != null) { cheapestRoutes.add(cheapest); } } @@ -361,22 +365,42 @@ public class RoutingService { for (var route : container.getRoutes()) { var mainRun = route.getMainRun(); var sourceChains = chainResolver.buildChains(mainRun.getFromNode().getId()); - + sourceChains.forEach(chain -> chain.addFirst(mainRun.getFromNode())); for (var chain : sourceChains) { Node source = container.getSourceNode(); - boolean chainEndIsSource = source.getId().equals(chain.getLast().getId()); + Node nearByNode = null; + TemporaryRateObject finalSection = null; + SourceConnectionType connectionType = SourceConnectionType.NONE; - // find final section: check if chain end and source node are identical, then check if chain end can be connected to - // source node, if this is not possible use a near-by node - TemporaryRateObject finalSection = (chainEndIsSource) ? null : connectNodes(source, chain.getLast(), container); - finalSection = ((finalSection == null && !chainEndIsSource && nearByNodes != null) ? connectNearByNodes(chain.getLast(), nearByNodes, container) : finalSection); + if (source.getId().equals(chain.getLast().getId())) { + connectionType = SourceConnectionType.CHAIN_END_IS_SOURCE_NODE; + } else if (nearByNodes != null) { + nearByNode = nearByNodes.stream().filter(n -> n.getId().equals(chain.getLast().getId())).findFirst().orElse(null); + if (nearByNode != null) { + connectionType = SourceConnectionType.CHAIN_END_IS_NEAR_BY_NODE; + } + } + if (connectionType == SourceConnectionType.NONE) { + // find final section: check if chain end and source node are identical, then check if chain end can be connected to + // source node, if this is not possible use a near-by node + finalSection = connectNodes(source, chain.getLast(), container); + if (finalSection != null) + connectionType = SourceConnectionType.FINAL_SECTION_WITH_SOURCE_NODE; + } + if (connectionType == SourceConnectionType.NONE) { + finalSection = connectNearByNodes(chain.getLast(), nearByNodes, container); + if (finalSection != null) { + connectionType = SourceConnectionType.FINAL_SECTION_WITH_NEAR_BY_NODE; + nearByNode = finalSection.getToNode(); + } + } - if (finalSection != null || chainEndIsSource) { + if (connectionType != SourceConnectionType.NONE) { boolean routable = true; TemporaryRouteObject duplicate = route.clone(); - for (int idx = 1; idx < chain.size() - 1; idx++) { + for (int idx = 1; idx < chain.size(); idx++) { Node startNode = chain.get(idx); Node endNode = chain.get(idx - 1); @@ -390,20 +414,68 @@ public class RoutingService { } if (routable) { - if (finalSection != null) { - // add final section if necessary, - // if last chain node == source node this can be skipped. + + if (connectionType == SourceConnectionType.FINAL_SECTION_WITH_SOURCE_NODE + || connectionType == SourceConnectionType.FINAL_SECTION_WITH_NEAR_BY_NODE) { duplicate.addSection(finalSection); - if (!finalSection.getFromNode().getId().equals(source.getId())) duplicate.routeOverNearBy(); } + + if (connectionType == SourceConnectionType.FINAL_SECTION_WITH_NEAR_BY_NODE || connectionType == SourceConnectionType.CHAIN_END_IS_NEAR_BY_NODE) { + duplicate.routeOverNearBy(source, nearByNode); + } + routes.add(duplicate); } } } } + + /* + * There might be duplicate routes now, because the same route can be created by "nearby-routing" and container rates + */ + removeDuplicateRoutes(routes); + container.overrideRoutes(routes); } + private void removeDuplicateRoutes(Collection routes) { + + var toRemove = new ArrayList(); + + for (var route : routes) { + var sections = route.getSections(); + + if(sections.getLast().getType().equals(TemporaryRateObject.TemporaryRateObjectType.NEAR_BY)) { + for (var other : routes) { + + //skip same instance. + if(other.equals(route)) continue; + + var otherIter = other.getSections().iterator(); + var iter = sections.iterator(); + boolean same = true; + + while (otherIter.hasNext() && iter.hasNext()) { + var otherSection = otherIter.next(); + var section = iter.next(); + + if (!otherSection.hasSameNodes(section)) { + same = false; + break; + } + } + + if (same && !otherIter.hasNext() && !iter.hasNext()) { + toRemove.add(route); + break; + } + } + } + } + + routes.removeAll(toRemove); + } + private Integer getRegionRadius() { var property = propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.RADIUS_REGION); return property.map(propertyDTO -> Integer.valueOf(propertyDTO.getCurrentValue())).orElseGet(SystemPropertyMappingId.RADIUS_REGION::getDefaultAsInteger); @@ -426,28 +498,25 @@ public class RoutingService { TemporaryRateObject mainRunObj = new TemporaryRateObject(mainRunStartNode, mainRunEndNode, TemporaryRateObject.TemporaryRateObjectType.MAIN_RUN, mainRun); -// var postRuns = container.getPostRuns().get(mainRun.getId()); -// -// var sortedChains = sortByQuality(destinationChains) + var postRuns = container.getPostRuns().get(mainRun.getId()); + var sortedChainMap = sortByQuality(destinationChains, postRuns, mainRun); + for (ChainQuality quality : ChainQuality.values()) { - for (var postRun : container.getPostRuns().get(mainRun.getId())) { + /* if connection quality is bad, do not try to route this and continue. */ + if (quality == ChainQuality.FALLBACK) continue; + if (sortedChainMap.get(quality) == null) continue; + boolean qualityRoutable = false; - Node postRunEndNode = nodeRepository.getById(postRun.getToNodeId()).orElseThrow(); - TemporaryRateObject postRunObj = new TemporaryRateObject(mainRunEndNode,postRunEndNode, TemporaryRateObject.TemporaryRateObjectType.POST_RUN, postRun); + for (var postRun : container.getPostRuns().get(mainRun.getId())) { - var sortedChains = sortByQuality(destinationChains, postRun, mainRun); + Node postRunEndNode = nodeRepository.getById(postRun.getToNodeId()).orElseThrow(); + TemporaryRateObject postRunObj = new TemporaryRateObject(mainRunEndNode, postRunEndNode, TemporaryRateObject.TemporaryRateObjectType.POST_RUN, postRun); - for(ChainQuality quality : ChainQuality.values()) - { - boolean qualityRoutable = false; + var sortedChains = sortedChainMap.get(quality).get(postRun.getId()); + if (sortedChains == null || sortedChains.isEmpty()) continue; - /* if connection quality is bad, do not try to route this and continue. */ - if (quality == ChainQuality.FALLBACK) continue; - - if(sortedChains.get(quality) == null) continue; - - for(var chain : sortedChains.get(quality)) { + for (var chain : sortedChains) { boolean routable = true; TemporaryRouteObject routeObj = new TemporaryRouteObject(); @@ -466,7 +535,7 @@ public class RoutingService { } } - if(routable && quality == ChainQuality.LOW) { + if (routable && quality == ChainQuality.LOW) { var rate = connectNodes(postRunEndNode, chain.getLast(), container); if (rate != null) { @@ -484,30 +553,32 @@ public class RoutingService { container.addRoute(routeObj); } } - - /* if higher quality is routable, do not calculate lower qualities. */ - if(qualityRoutable) - break; - } + /* if higher quality is routable, do not calculate lower qualities. */ + if (qualityRoutable) + break; } } } - private Map>> sortByQuality(List> chains, ContainerRate postRun, ContainerRate mainRun) { + private Map>>> sortByQuality(List> chains, List postRuns, ContainerRate mainRun) { - Map>> sortedChains = new HashMap<>(); + Map>>> sortedChains = new HashMap<>(); - for(var chain : chains) { - ChainQuality chainQuality = getChainQuality(chain, postRun, mainRun); - sortedChains.putIfAbsent(chainQuality, new ArrayList<>()); - sortedChains.get(chainQuality).add(chain); + for (var postRun : postRuns) { + + + for (var chain : chains) { + ChainQuality chainQuality = getChainQuality(chain, postRun, mainRun); + sortedChains.putIfAbsent(chainQuality, new HashMap<>()); + sortedChains.get(chainQuality).putIfAbsent(postRun.getId(), new ArrayList<>()); + sortedChains.get(chainQuality).get(postRun.getId()).add(chain); + } } return sortedChains; } - private ChainQuality getChainQuality(List chain, ContainerRate postRun, ContainerRate mainRun) { if (chain.getLast().getId().equals(postRun.getToNodeId())) { return ChainQuality.MEDIUM; @@ -556,6 +627,10 @@ public class RoutingService { } } + private enum SourceConnectionType { + NONE, CHAIN_END_IS_SOURCE_NODE, CHAIN_END_IS_NEAR_BY_NODE, FINAL_SECTION_WITH_SOURCE_NODE, FINAL_SECTION_WITH_NEAR_BY_NODE + } + private enum ChainQuality { SUPERIOR(2), HIGH(1), MEDIUM(0), LOW(0), FALLBACK(0); @@ -715,10 +790,12 @@ public class RoutingService { clone.nearBy = nearBy; clone.isCheapest = isCheapest; clone.isFastest = isFastest; + clone.quality = quality; return clone; } - public void routeOverNearBy() { + public void routeOverNearBy(Node source, Node nearByNode) { + this.sections.add(new TemporaryRateObject(source, nearByNode, TemporaryRateObject.TemporaryRateObjectType.NEAR_BY)); this.nearBy = true; } @@ -751,7 +828,8 @@ public class RoutingService { StringBuilder sb = new StringBuilder(); - if(!sections.isEmpty()) { + if (!sections.isEmpty()) { + sb.append(sections.getLast().getFromNode().getExternalMappingId()); for (var section : sections.reversed()) { sb.append(" -"); @@ -759,15 +837,17 @@ public class RoutingService { sb.append("-> "); sb.append(section.getToNode().getExternalMappingId()); } + } else sb.append("Empty"); - return String.format("Route: [%s][%s]", quality.name(), sb.toString()); + return String.format("Route: [%s, %s]", quality.name().charAt(0) + (isFastest ? "\uD83D\uDE80" : "") + (isCheapest ? "\uD83D\uDCB2":""), sb); } public void setQuality(ChainQuality quality) { this.quality = quality; } + } @@ -805,7 +885,7 @@ public class RoutingService { if (this.type.equals(that.type)) { if (this.type.equals(TemporaryRateObjectType.MATRIX)) { return Objects.equals(this.fromNode.getCountryId(), that.fromNode.getCountryId()) && Objects.equals(this.toNode.getCountryId(), that.toNode.getCountryId()); - } else if (this.type.equals(TemporaryRateObjectType.CONTAINER) || this.type.equals(TemporaryRateObjectType.MAIN_RUN) || this.type.equals(TemporaryRateObjectType.POST_RUN)) { + } else if (this.type.equals(TemporaryRateObjectType.CONTAINER) || this.type.equals(TemporaryRateObjectType.MAIN_RUN) || this.type.equals(TemporaryRateObjectType.POST_RUN) || this.type.equals(TemporaryRateObjectType.NEAR_BY)) { return Objects.equals(this.fromNode.getId(), that.fromNode.getId()) && Objects.equals(this.toNode.getId(), that.toNode.getId()); } } @@ -849,7 +929,12 @@ public class RoutingService { } public double getCost() { - if(type.equals(TemporaryRateObjectType.MATRIX)) { + + if (type.equals(TemporaryRateObjectType.NEAR_BY)) { + return 0.0; + } + + if (type.equals(TemporaryRateObjectType.MATRIX)) { return matrixRate.getRate().doubleValue() * approxDistance; } else { return containerRate.getRateFeu().doubleValue(); @@ -857,9 +942,12 @@ public class RoutingService { } public int getLeadTime() { - if (type.equals(TemporaryRateObjectType.MATRIX)) { + if (type.equals(TemporaryRateObjectType.MATRIX)) return 3; - } + + if (type.equals(TemporaryRateObjectType.NEAR_BY)) + return 0; + return containerRate.getLeadTime(); } @@ -871,8 +959,19 @@ public class RoutingService { return containerRate.getType(); } + public String getFullDebugText() { + if (type.equals(TemporaryRateObjectType.MATRIX)) { + return String.format("Rate [%s -\uD83D\uDDA9-> %s, %.2f km]", fromNode.getExternalMappingId(), toNode.getExternalMappingId(), approxDistance); + } + return String.format("Rate [%s -\uD83D\uDCE6-> %s]", fromNode.getExternalMappingId(), toNode.getExternalMappingId()); + } + + public boolean hasSameNodes(TemporaryRateObject section) { + return fromNode.getId().equals(section.getFromNode().getId()) && toNode.getId().equals(section.getToNode().getId()); + } + private enum TemporaryRateObjectType { - MATRIX("\uD83D\uDDA9"), CONTAINER("\uD83D\uDCE6"), POST_RUN("\uD83D\uDE9B"), MAIN_RUN("\uD83D\uDEA2"); + NEAR_BY("\uD83D\uDCCD"), MATRIX("\uD83D\uDDA9"), CONTAINER("\uD83D\uDCE6"), POST_RUN("\uD83D\uDE9B"), MAIN_RUN("\uD83D\uDEA2"); private final String debugText; @@ -884,12 +983,5 @@ public class RoutingService { return debugText; } } - - public String getFullDebugText() { - if(type.equals(TemporaryRateObjectType.MATRIX)) { - return String.format("Rate [%s --> %s [%s, %.2f km]", fromNode.getExternalMappingId(), toNode.getExternalMappingId(), type, approxDistance); - } - return String.format("Rate [%s --> %s [%s]", fromNode.getExternalMappingId(), toNode.getExternalMappingId(), type); - } } } diff --git a/src/main/java/de/avatic/lcc/service/calculation/execution/CalculationStatusService.java b/src/main/java/de/avatic/lcc/service/calculation/execution/CalculationStatusService.java index fead8fc..675c566 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/execution/CalculationStatusService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/execution/CalculationStatusService.java @@ -32,7 +32,7 @@ public class CalculationStatusService { } } - public Integer schedule(ArrayList calculationIds) { + public Integer schedule(ArrayList calculationIds) { //TODO return null; } diff --git a/src/test/java/de/avatic/lcc/controller/calculation/DestinationIntegrationTest.java b/src/test/java/de/avatic/lcc/controller/calculation/DestinationIntegrationTest.java new file mode 100644 index 0000000..7be1345 --- /dev/null +++ b/src/test/java/de/avatic/lcc/controller/calculation/DestinationIntegrationTest.java @@ -0,0 +1,366 @@ +package de.avatic.lcc.controller.calculation; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.avatic.lcc.dto.calculation.edit.destination.DestinationCreateDTO; +import de.avatic.lcc.dto.calculation.edit.destination.DestinationUpdateDTO; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +@Import({PremiseControllerTestData.class, PremiseTestsHelper.class}) + +public class DestinationIntegrationTest { + + @Autowired + protected JdbcTemplate jdbcTemplate; + @Autowired + private MockMvc mockMvc; + @Autowired + private ObjectMapper objectMapper; + @Autowired + private PremiseControllerTestData premiseTestData; + @Autowired + private PremiseTestsHelper testHelper; + + @Nested + @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) + class CreateDestinationTests { + + @Test + @DisplayName("POST /api/calculation/destination/ - happy path (create destination)") + public void createDestinationCase1() throws Exception { + + var nodeId = testHelper.getNodeIdByExternalMappingId("AB"); + + var premisesBeforeUpdate = testHelper.getPremisesFromDb(); + var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); + + var dto = new DestinationCreateDTO(); + dto.setPremiseId(Arrays.asList(premise1.getId(), premise3.getId())); + dto.setDestinationNodeId(nodeId); + + mockMvc.perform(post("/api/calculation/destination") + .content(objectMapper.writeValueAsString(dto)) + .contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); + + // TODO check ... + + } + } + + @Nested + @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) + class GetDestinationTests { + + @BeforeEach + void setUp() { + premiseTestData.generateData(); + } + + @AfterEach + void cleanUp() { + premiseTestData.deleteAll(); + } + + @Test + @DisplayName("GET /api/calculation/destination - happy path (get destination)") + public void getDestinationCase1() throws Exception { + + var premisesFromDb = testHelper.getPremisesFromDb(); + var premise1 = premisesFromDb.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + + var destIds = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + + + mockMvc.perform(get("/api/calculation/destination/" + destIds.getFirst())) + .andExpect(status().isOk()).andDo(print()); + + // TODO check ... + + } + } + + @Nested + @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) + class UpdateDestinationTests { + + @BeforeEach + void setUp() { + premiseTestData.generateData(); + } + + @AfterEach + void cleanUp() { + premiseTestData.deleteAll(); + } + + @Test + @DisplayName("PUT /api/calculation/destination - happy path (update destination)") + public void getDestinationCase1() throws Exception { + + var premisesFromDb = testHelper.getPremisesFromDb(); + var premise1 = premisesFromDb.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + + List destId = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destId).asInstanceOf(InstanceOfAssertFactories.LIST).isNotEmpty(); + + var destinationBefore = testHelper.getDestinationById(destId.getFirst()); + var routesBefore = testHelper.getRoutesByDestinationId(destId.getFirst()); + + var dto = new DestinationUpdateDTO(); + dto.setDisposalCost(666.6); + dto.setHandlingCost(777.7); + dto.setRepackingCost(888.8); + dto.setRouteSelectedId(routesBefore.getFirst().getId()); + + mockMvc.perform(put("/api/calculation/destination/" + destId.getFirst()) + .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(print()); + + var destinationAfter = testHelper.getDestinationById(destId.getFirst()); + var routesAfter = testHelper.getRoutesByDestinationId(destId.getFirst()); + + assertThat(destinationAfter).isNotEmpty(); + assertThat(destinationAfter.get().getDisposalCost()).isEqualByComparingTo(BigDecimal.valueOf(666.6)); + assertThat(destinationAfter.get().getHandlingCost()).isEqualByComparingTo(BigDecimal.valueOf(777.7)); + assertThat(destinationAfter.get().getRepackingCost()).isEqualByComparingTo(BigDecimal.valueOf(888.8)); + assertThat(routesAfter.getFirst().getSelected()).isEqualTo(true); + assertThat(routesAfter.getLast().getSelected()).isEqualTo(false); + } + + @Test + @DisplayName("PUT /api/calculation/destination - happy path (partial update destination)") + public void getDestinationCase2() throws Exception { + + var premisesFromDb = testHelper.getPremisesFromDb(); + var premise1 = premisesFromDb.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + + List destId = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destId).asInstanceOf(InstanceOfAssertFactories.LIST).isNotEmpty(); + + var destinationBefore = testHelper.getDestinationById(destId.getFirst()).orElseThrow(); + var routesBefore = testHelper.getRoutesByDestinationId(destId.getFirst()); + + var dto = new DestinationUpdateDTO(); + dto.setDisposalCost(666.6); + dto.setHandlingCost(null); + dto.setRepackingCost(null); + dto.setRouteSelectedId(routesBefore.getLast().getId()); + + mockMvc.perform(put("/api/calculation/destination/" + destId.getFirst()) + .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(print()); + + var destinationAfter = testHelper.getDestinationById(destId.getFirst()); + var routesAfter = testHelper.getRoutesByDestinationId(destId.getFirst()); + + assertThat(destinationAfter).isNotEmpty(); + assertThat(destinationAfter.get().getDisposalCost()).isEqualByComparingTo(BigDecimal.valueOf(666.6)); + assertThat(destinationAfter.get().getHandlingCost()).isEqualByComparingTo(destinationBefore.getHandlingCost()); + assertThat(destinationAfter.get().getRepackingCost()).isEqualByComparingTo(destinationBefore.getHandlingCost()); + assertThat(routesAfter.getFirst().getSelected()).isEqualTo(false); + assertThat(routesAfter.getLast().getSelected()).isEqualTo(true); + } + + @Test + @DisplayName("PUT /api/calculation/destination - error case (negative value)") + public void getDestinationCase3() throws Exception { + + var premisesFromDb = testHelper.getPremisesFromDb(); + var premise1 = premisesFromDb.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + + List destId = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destId).asInstanceOf(InstanceOfAssertFactories.LIST).isNotEmpty(); + + var destinationBefore = testHelper.getDestinationById(destId.getFirst()).orElseThrow(); + var routesBefore = testHelper.getRoutesByDestinationId(destId.getFirst()); + + var dto = new DestinationUpdateDTO(); + dto.setDisposalCost(-666.6); + dto.setHandlingCost(null); + dto.setRepackingCost(null); + dto.setRouteSelectedId(routesBefore.getLast().getId()); + + mockMvc.perform(put("/api/calculation/destination/" + destId.getFirst()) + .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()) + .andDo(print()); + + var destinationAfter = testHelper.getDestinationById(destId.getFirst()); + var routesAfter = testHelper.getRoutesByDestinationId(destId.getFirst()); + + assertThat(destinationAfter).isNotEmpty(); + assertThat(destinationAfter.get().getDisposalCost()).isEqualByComparingTo(destinationBefore.getHandlingCost()); + assertThat(destinationAfter.get().getHandlingCost()).isEqualByComparingTo(destinationBefore.getHandlingCost()); + assertThat(destinationAfter.get().getRepackingCost()).isEqualByComparingTo(destinationBefore.getHandlingCost()); + assertThat(routesAfter.getFirst().getSelected()).isEqualTo(routesBefore.getFirst().getSelected()); + assertThat(routesAfter.getLast().getSelected()).isEqualTo(routesBefore.getLast().getSelected()); + } + + } + + @Nested + @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) + class DeleteDestinationTests { + + @BeforeEach + void setUp() { + premiseTestData.generateData(); + } + + @AfterEach + void cleanUp() { + premiseTestData.deleteAll(); + } + + + @Test + @DisplayName("DELETE /api/calculation/destination - happy path (delete single destination)") + public void deleteDestinationCase1() throws Exception { + + var premisesFromDb = testHelper.getPremisesFromDb(); + var premise1 = premisesFromDb.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + + List destIdsBefore = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destIdsBefore).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(2); + + + mockMvc.perform(delete("/api/calculation/destination/" + destIdsBefore.getFirst())) + .andExpect(status().isOk()) + .andDo(print()); + + List destIdsAfter = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destIdsAfter).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(1); + + var destinationAfter = testHelper.getDestinationById(destIdsBefore.getFirst()); + assertThat(destinationAfter).isEmpty(); + + } + + + @Test + @DisplayName("DELETE /api/calculation/destination - happy path (delete all destination)") + public void deleteDestinationCase2() throws Exception { + + var premisesFromDb = testHelper.getPremisesFromDb(); + var premise1 = premisesFromDb.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + + List destIdsBefore = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destIdsBefore).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(2); + + assertThat(testHelper.getRouteCount()).isNotEqualTo(0); + assertThat(testHelper.getRouteSectionCount()).isNotEqualTo(0); + assertThat(testHelper.getRouteNodeCount()).isNotEqualTo(0); + + + mockMvc.perform(delete("/api/calculation/destination/" + destIdsBefore.getFirst())) + .andExpect(status().isOk()) + .andDo(print()); + + mockMvc.perform(delete("/api/calculation/destination/" + destIdsBefore.getLast())) + .andExpect(status().isOk()) + .andDo(print()); + + List destIdsAfter = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destIdsAfter).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(0); + + assertThat(testHelper.getDestinationById(destIdsBefore.getFirst())).isEmpty(); + assertThat(testHelper.getDestinationById(destIdsBefore.getLast())).isEmpty(); + + assertThat(testHelper.getRouteCount()).isEqualTo(0); + assertThat(testHelper.getRouteSectionCount()).isEqualTo(0); + assertThat(testHelper.getRouteNodeCount()).isEqualTo(0); + } + + + @Test + @DisplayName("DELETE /api/calculation/destination - error case (unknown id)") + public void deleteDestinationCase3() throws Exception { + + var premisesFromDb = testHelper.getPremisesFromDb(); + var premise1 = premisesFromDb.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + + List destIdsBefore = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destIdsBefore).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(2); + + mockMvc.perform(delete("/api/calculation/destination/" + 9999)) + .andExpect(status().isForbidden()) + .andDo(print()); + + List destIdsAfter = testHelper.getDestinationIdsByPremiseId(premise1.getId()); + assertThat(destIdsAfter).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(2); + + } + + } + + @Nested + @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) + @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) + @DisplayName("GET /api/calculation/start - Start Calculations Tests") + class StartCalculationTests { + + @Test + @DisplayName("PUT /api/calculation/start - happy path") + public void startCalculationCase1() throws Exception { + + var nodeId = testHelper.getNodeIdByExternalMappingId("AB"); + + var premisesBeforeUpdate = testHelper.getPremisesFromDb(); + var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); + var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); + + var dto = new DestinationCreateDTO(); + dto.setPremiseId(Arrays.asList(premise1.getId(), premise3.getId())); + dto.setDestinationNodeId(nodeId); + + mockMvc.perform(post("/api/calculation/destination") + .content(objectMapper.writeValueAsString(dto)) + .contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); + + mockMvc.perform(put("/api/calculation/start") + .content(objectMapper.writeValueAsString(Arrays.asList(premise1, premise3))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andDo(print()); + + } + } +} diff --git a/src/test/java/de/avatic/lcc/controller/calculation/PremiseControllerIntegrationTest.java b/src/test/java/de/avatic/lcc/controller/calculation/PremiseControllerIntegrationTest.java index d1166de..0bdfeb6 100644 --- a/src/test/java/de/avatic/lcc/controller/calculation/PremiseControllerIntegrationTest.java +++ b/src/test/java/de/avatic/lcc/controller/calculation/PremiseControllerIntegrationTest.java @@ -3,14 +3,11 @@ package de.avatic.lcc.controller.calculation; import com.fasterxml.jackson.databind.ObjectMapper; import de.avatic.lcc.dto.calculation.create.CreatePremiseDTO; import de.avatic.lcc.dto.calculation.edit.PremiseDetailDTO; -import de.avatic.lcc.dto.calculation.edit.destination.DestinationCreateDTO; import de.avatic.lcc.dto.calculation.edit.masterData.MaterialUpdateDTO; import de.avatic.lcc.dto.calculation.edit.masterData.PackagingUpdateDTO; import de.avatic.lcc.dto.calculation.edit.masterData.PriceUpdateDTO; import de.avatic.lcc.dto.generic.DimensionDTO; -import de.avatic.lcc.model.nodes.Location; import de.avatic.lcc.model.premises.Premise; -import de.avatic.lcc.model.premises.PremiseState; import de.avatic.lcc.model.utils.DimensionUnit; import de.avatic.lcc.model.utils.WeightUnit; import org.assertj.core.api.InstanceOfAssertFactories; @@ -42,7 +39,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @AutoConfigureMockMvc @Transactional @Import(PremiseControllerTestData.class) - public class PremiseControllerIntegrationTest { @Autowired @@ -53,100 +49,9 @@ public class PremiseControllerIntegrationTest { private ObjectMapper objectMapper; @Autowired private PremiseControllerTestData premiseTestData; + @Autowired + private PremiseTestsHelper testsHelper; - private List getPremisesFromDb() { - String query = "SELECT * FROM premise"; - return jdbcTemplate.query(query, (rs, rowNum) -> { - var entity = new Premise(); - - entity.setId(rs.getInt("id")); - - entity.setPackagingId(rs.getInt("packaging_id")); - if (rs.wasNull()) - entity.setPackagingId(null); - - entity.setMaterialId(rs.getInt("material_id")); - if (rs.wasNull()) - entity.setMaterialId(null); - - entity.setSupplierNodeId(rs.getInt("supplier_node_id")); - if (rs.wasNull()) - entity.setSupplierNodeId(null); - - entity.setUserSupplierNodeId(rs.getInt("user_supplier_node_id")); - if (rs.wasNull()) - entity.setUserSupplierNodeId(null); - - entity.setLocation(new Location(rs.getBigDecimal("geo_lng").doubleValue(), rs.getBigDecimal("geo_lat").doubleValue())); - - entity.setCountryId(rs.getInt("country_id")); - if (rs.wasNull()) - entity.setCountryId(null); - - entity.setUserId(rs.getInt("user_id")); - if (rs.wasNull()) - entity.setUserId(null); - - entity.setMaterialCost(rs.getBigDecimal("material_cost")); - - entity.setHsCode(rs.getString("hs_code")); - - entity.setCustomRate(rs.getBigDecimal("tariff_rate")); - - entity.setFcaEnabled(rs.getBoolean("is_fca_enabled")); - if (rs.wasNull()) - entity.setFcaEnabled(null); - - entity.setOverseaShare(rs.getBigDecimal("oversea_share")); - - entity.setIndividualHuHeight(rs.getInt("individual_hu_height")); - if (rs.wasNull()) - entity.setIndividualHuHeight(null); - - entity.setIndividualHuWidth(rs.getInt("individual_hu_width")); - if (rs.wasNull()) - entity.setIndividualHuWidth(null); - - entity.setIndividualHuLength(rs.getInt("individual_hu_length")); - if (rs.wasNull()) - entity.setIndividualHuLength(null); - - entity.setIndividualHuWeight(rs.getInt("individual_hu_weight")); - if (rs.wasNull()) - entity.setIndividualHuWeight(null); - - entity.setHuDisplayedDimensionUnit(DimensionUnit.valueOf(rs.getString("hu_displayed_dimension_unit"))); - entity.setHuDisplayedWeightUnit(WeightUnit.valueOf(rs.getString("hu_displayed_weight_unit"))); - - entity.setHuStackable(rs.getBoolean("hu_stackable")); - if (rs.wasNull()) - entity.setHuStackable(null); - - entity.setHuMixable(rs.getBoolean("hu_mixable")); - if (rs.wasNull()) - entity.setHuMixable(null); - - entity.setHuUnitCount(rs.getInt("hu_unit_count")); - if (rs.wasNull()) - entity.setHuUnitCount(null); - - entity.setState(PremiseState.valueOf(rs.getString("state"))); - entity.setUpdatedAt(rs.getTimestamp("updated_at").toLocalDateTime()); - entity.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime()); - - return entity; - }); - } - - private Integer getNodeIdByExternalMappingId(String mappingId) { - String query = "SELECT id FROM node WHERE external_mapping_id = ? LIMIT 1"; - return jdbcTemplate.queryForObject(query, Integer.class, mappingId); - } - - private Integer getUserNodeIdByName(String name) { - String query = "SELECT id FROM sys_user_node WHERE name = ? LIMIT 1"; - return jdbcTemplate.queryForObject(query, Integer.class, name); - } @Nested @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) @@ -160,10 +65,7 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("GET /api/calculation/view - happy path (no filter)") public void viewMaterialTest() throws Exception { - mockMvc.perform(get("/api/calculation/view")) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$", isA(List.class))); + mockMvc.perform(get("/api/calculation/view")).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$", isA(List.class))); //TODO user login not implemented. user with id 1 is returned at the moment } @@ -172,12 +74,7 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("GET /api/calculation/view - happy path (filtering part number)") public void viewMaterialFilterTest() throws Exception { - mockMvc.perform(get("/api/calculation/view").param("filter", "28152640129")) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$", isA(List.class))) - .andExpect(jsonPath("$[*].material.part_number", - everyItem(equalTo("28152640129")))); + mockMvc.perform(get("/api/calculation/view").param("filter", "28152640129")).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$", isA(List.class))).andExpect(jsonPath("$[*].material.part_number", everyItem(equalTo("28152640129")))); //TODO user login not implemented. user with id 1 is returned at the moment } @@ -185,11 +82,7 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("GET /api/calculation/view - happy path (filtering supplier name)") public void viewMaterialFilterSupplierTest() throws Exception { - mockMvc.perform(get("/api/calculation/view").param("filter", "My Supplier 1")) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$", isA(List.class))) - .andExpect(jsonPath("$[*].supplier.name").value(everyItem(equalTo("My Supplier 1")))); + mockMvc.perform(get("/api/calculation/view").param("filter", "My Supplier 1")).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$", isA(List.class))).andExpect(jsonPath("$[*].supplier.name").value(everyItem(equalTo("My Supplier 1")))); //TODO user login not implemented. user with id 1 is returned at the moment } @@ -213,34 +106,14 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("GET /api/calculation/search - happy path (single)") public void searchSingleMaterialTest() throws Exception { - mockMvc.perform(get("/api/calculation/search") - .param("search", "28152640129")) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$.materials", isA(List.class))) - .andExpect(jsonPath("$.materials", hasSize(1))) - .andExpect(jsonPath("$.supplier", hasSize(1))) - .andExpect(jsonPath("$.user_supplier", hasSize(1))) - .andExpect(jsonPath("$.user_supplier[?(@.name == 'My Supplier 1')]").exists()) - .andExpect(jsonPath("$.user_supplier[?(@.name == 'My Supplier 2')]").isEmpty()); + mockMvc.perform(get("/api/calculation/search").param("search", "28152640129")).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$.materials", isA(List.class))).andExpect(jsonPath("$.materials", hasSize(1))).andExpect(jsonPath("$.supplier", hasSize(1))).andExpect(jsonPath("$.user_supplier", hasSize(1))).andExpect(jsonPath("$.user_supplier[?(@.name == 'My Supplier 1')]").exists()).andExpect(jsonPath("$.user_supplier[?(@.name == 'My Supplier 2')]").isEmpty()); } @Test @DisplayName("GET /api/calculation/search - happy path (muliple)") public void searchMultiMaterialTest() throws Exception { - mockMvc.perform(get("/api/calculation/search") - .param("search", "28152640129 Material 4222640803 bla4222640104bla bla")) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$.materials", isA(List.class))) - .andExpect(jsonPath("$.materials", hasSize(2))) - .andExpect(jsonPath("$.supplier", hasSize(1))) - .andExpect(jsonPath("$.user_supplier", hasSize(1))) - .andExpect(jsonPath("$.user_supplier[?(@.name == 'My Supplier 1')]").exists()) - .andExpect(jsonPath("$.supplier[?(@.name == 'Linde (China) Forklift Truck (Supplier)')]").exists()) - .andExpect(jsonPath("$.materials[?(@.part_number == '28152640129')]").exists()) - .andExpect(jsonPath("$.materials[?(@.part_number == '4222640803')]").exists()); + mockMvc.perform(get("/api/calculation/search").param("search", "28152640129 Material 4222640803 bla4222640104bla bla")).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$.materials", isA(List.class))).andExpect(jsonPath("$.materials", hasSize(2))).andExpect(jsonPath("$.supplier", hasSize(1))).andExpect(jsonPath("$.user_supplier", hasSize(1))).andExpect(jsonPath("$.user_supplier[?(@.name == 'My Supplier 1')]").exists()).andExpect(jsonPath("$.supplier[?(@.name == 'Linde (China) Forklift Truck (Supplier)')]").exists()).andExpect(jsonPath("$.materials[?(@.part_number == '28152640129')]").exists()).andExpect(jsonPath("$.materials[?(@.part_number == '4222640803')]").exists()); } //TODO Test with faulty param @@ -452,8 +325,8 @@ public class PremiseControllerIntegrationTest { public void createPremiseCase1() throws Exception { - var supplierId = getNodeIdByExternalMappingId("LX"); - var premisesBeforeCreate = getPremisesFromDb(); + var supplierId = testsHelper.getNodeIdByExternalMappingId("LX"); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var materialId = getMaterialIdByPartNumber("28152640129"); var dto = new CreatePremiseDTO(); @@ -462,15 +335,10 @@ public class PremiseControllerIntegrationTest { dto.setUserSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(2))) // content_unit_count is in the newest premise set to 2 - .andExpect(jsonPath("$", hasSize(1))) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(2))) // content_unit_count is in the newest premise set to 2 + .andExpect(jsonPath("$", hasSize(1))).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); var dtos = objectMapper.readValue(result.getResponse().getContentAsString(), PremiseDetailDTO[].class); assertThat(premisesBeforeCreate.stream().map(Premise::getId).toList()).asInstanceOf(InstanceOfAssertFactories.LIST).doesNotContain(dtos[0].getId()); @@ -499,8 +367,8 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/create - Recycles DRAFT from same user") public void createPremiseCase2() throws Exception { - var supplierId = getNodeIdByExternalMappingId("LX"); - var premisesBeforeCreate = getPremisesFromDb(); + var supplierId = testsHelper.getNodeIdByExternalMappingId("LX"); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var materialId = getMaterialIdByPartNumber("8222640822"); @@ -510,15 +378,10 @@ public class PremiseControllerIntegrationTest { dto.setUserSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[?(@.material.part_number=='8222640822')].handling_unit.content_unit_count", hasItem(3))) // content_unit_count is in the correct permise set to 3 - .andExpect(jsonPath("$", hasSize(1))) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[?(@.material.part_number=='8222640822')].handling_unit.content_unit_count", hasItem(3))) // content_unit_count is in the correct permise set to 3 + .andExpect(jsonPath("$", hasSize(1))).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); var dtos = objectMapper.readValue(result.getResponse().getContentAsString(), PremiseDetailDTO[].class); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesAfterCreate.size()); @@ -531,8 +394,8 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("POST /api/calculation/create - Recycles COMPLETED from other user") public void createPremiseCase3() throws Exception { - var supplierId = getNodeIdByExternalMappingId("LX"); - var premisesBeforeCreate = getPremisesFromDb(); + var supplierId = testsHelper.getNodeIdByExternalMappingId("LX"); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var materialId = getMaterialIdByPartNumber("3064540201"); @@ -542,15 +405,10 @@ public class PremiseControllerIntegrationTest { dto.setUserSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[?(@.material.part_number=='3064540201')].handling_unit.content_unit_count", hasItem(4))) // content_unit_count is in the correct premise set to 4 - .andExpect(jsonPath("$", hasSize(1))) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[?(@.material.part_number=='3064540201')].handling_unit.content_unit_count", hasItem(4))) // content_unit_count is in the correct premise set to 4 + .andExpect(jsonPath("$", hasSize(1))).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); var dtos = objectMapper.readValue(result.getResponse().getContentAsString(), PremiseDetailDTO[].class); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesBeforeCreate.size() + 1); @@ -562,8 +420,8 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("POST /api/calculation/create - Creates new Premise if no old data") public void createPremiseCase4() throws Exception { - var supplierId = getNodeIdByExternalMappingId("LX"); - var premisesBeforeCreate = getPremisesFromDb(); + var supplierId = testsHelper.getNodeIdByExternalMappingId("LX"); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var materialId = getMaterialIdByPartNumber("8212640113"); @@ -573,15 +431,10 @@ public class PremiseControllerIntegrationTest { dto.setUserSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[?(@.material.part_number=='8212640113')].handling_unit.content_unit_count", hasItem(54))) // content_unit_count is the data from the packaging database. - .andExpect(jsonPath("$", hasSize(1))) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[?(@.material.part_number=='8212640113')].handling_unit.content_unit_count", hasItem(54))) // content_unit_count is the data from the packaging database. + .andExpect(jsonPath("$", hasSize(1))).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); var dtos = objectMapper.readValue(result.getResponse().getContentAsString(), PremiseDetailDTO[].class); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesBeforeCreate.size() + 1); @@ -594,8 +447,8 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("POST /api/calculation/create - Uses UserSupplier DRAFT") public void createPremiseCase5() throws Exception { - var supplierId = getUserNodeIdByName("My Supplier 1"); - var premisesBeforeCreate = getPremisesFromDb(); + var supplierId = testsHelper.getUserNodeIdByName("My Supplier 1"); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var materialId = getMaterialIdByPartNumber("28152640129"); @@ -605,15 +458,10 @@ public class PremiseControllerIntegrationTest { dto.setSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(8))) // content_unit_count is the data from the packaging database. - .andExpect(jsonPath("$", hasSize(1))) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(8))) // content_unit_count is the data from the packaging database. + .andExpect(jsonPath("$", hasSize(1))).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); var dtos = objectMapper.readValue(result.getResponse().getContentAsString(), PremiseDetailDTO[].class); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesBeforeCreate.size()); @@ -625,8 +473,8 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("POST /api/calculation/create - Access Violation UserSupplier") public void createPremiseCase6() throws Exception { - var supplierId = getUserNodeIdByName("My Supplier 2"); - var premisesBeforeCreate = getPremisesFromDb(); + var supplierId = testsHelper.getUserNodeIdByName("My Supplier 2"); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var materialId = getMaterialIdByPartNumber("28152640129"); @@ -636,13 +484,9 @@ public class PremiseControllerIntegrationTest { dto.setSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isForbidden()) - .andDo(print()) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isForbidden()).andDo(print()).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesBeforeCreate.size()); } @@ -650,11 +494,11 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("POST /api/calculation/create - From Scratch behavior test") public void createPremiseCase7() throws Exception { - var supplierId = getNodeIdByExternalMappingId("LX"); + var supplierId = testsHelper.getNodeIdByExternalMappingId("LX"); var materialId1 = getMaterialIdByPartNumber("28152640129"); var materialId2 = getMaterialIdByPartNumber("8222640822"); var materialId4 = getMaterialIdByPartNumber("8212640113"); - var premisesBeforeCreate = getPremisesFromDb(); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var dto = new CreatePremiseDTO(); @@ -664,17 +508,12 @@ public class PremiseControllerIntegrationTest { dto.setCreateEmpty(true); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(1))) // content_unit_count is the data from the packaging database. + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(1))) // content_unit_count is the data from the packaging database. .andExpect(jsonPath("$[?(@.material.part_number=='8222640822')].handling_unit.content_unit_count", hasItem(630))) // content_unit_count is the data from the packaging database. .andExpect(jsonPath("$[?(@.material.part_number=='8212640113')].handling_unit.content_unit_count", hasItem(54))) // content_unit_count is the data from the packaging database. - .andExpect(jsonPath("$", hasSize(3))) - .andReturn(); + .andExpect(jsonPath("$", hasSize(3))).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); var dtos = objectMapper.readValue(result.getResponse().getContentAsString(), PremiseDetailDTO[].class); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesBeforeCreate.size() + 2); @@ -689,7 +528,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/create - Faulty material id") public void createPremiseCase8() throws Exception { - var premisesBeforeCreate = getPremisesFromDb(); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var dto = new CreatePremiseDTO(); @@ -698,13 +537,9 @@ public class PremiseControllerIntegrationTest { dto.setUserSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isBadRequest()) - .andDo(print()) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isBadRequest()).andDo(print()).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesBeforeCreate.size()); @@ -715,7 +550,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/create - Faulty supplier id") public void createPremiseCase9() throws Exception { - var premisesBeforeCreate = getPremisesFromDb(); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var dto = new CreatePremiseDTO(); dto.setMaterialIds(List.of(1)); @@ -723,13 +558,9 @@ public class PremiseControllerIntegrationTest { dto.setUserSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isBadRequest()) - .andDo(print()) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isBadRequest()).andDo(print()).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesBeforeCreate.size()); @@ -739,7 +570,7 @@ public class PremiseControllerIntegrationTest { @Test @DisplayName("POST /api/calculation/create - Faulty user supplier id") public void createPremiseCase10() throws Exception { - var premisesBeforeCreate = getPremisesFromDb(); + var premisesBeforeCreate = testsHelper.getPremisesFromDb(); var dto = new CreatePremiseDTO(); dto.setMaterialIds(List.of(-1)); @@ -747,13 +578,9 @@ public class PremiseControllerIntegrationTest { dto.setSupplierIds(null); - var result = mockMvc.perform(post("/api/calculation/create") - .contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))) - .andExpect(status().isBadRequest()) - .andDo(print()) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/create").contentType(MediaType.APPLICATION_JSON).content(objectMapper.writeValueAsString(dto))).andExpect(status().isBadRequest()).andDo(print()).andReturn(); - var premisesAfterCreate = getPremisesFromDb(); + var premisesAfterCreate = testsHelper.getPremisesFromDb(); assertThat(premisesAfterCreate).asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(premisesBeforeCreate.size()); @@ -799,18 +626,13 @@ public class PremiseControllerIntegrationTest { @DisplayName("GET /api/calculation/edit - Get Single Premiss") public void getPremiseCase1() throws Exception { - var premises = getPremisesFromDb(); + var premises = testsHelper.getPremisesFromDb(); var premise1 = premises.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); - var result = mockMvc.perform(get("/api/calculation/edit") - .content(Collections.singletonList(premise1.getId()).toString()).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(2))) // content_unit_count is in the newest premise set to 2 - .andExpect(jsonPath("$", hasSize(1))) - .andReturn(); + var result = mockMvc.perform(get("/api/calculation/edit").content(Collections.singletonList(premise1.getId()).toString()).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(2))) // content_unit_count is in the newest premise set to 2 + .andExpect(jsonPath("$", hasSize(1))).andReturn(); var dtos = objectMapper.readValue(result.getResponse().getContentAsString(), PremiseDetailDTO[].class); @@ -835,19 +657,12 @@ public class PremiseControllerIntegrationTest { @DisplayName("GET /api/calculation/edit - Get Multiple Premisses") public void getPremiseCase2() throws Exception { - var premises = getPremisesFromDb(); + var premises = testsHelper.getPremisesFromDb(); var premise1 = premises.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premises.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); - var result = mockMvc.perform(get("/api/calculation/edit") - .content(Arrays.asList(premise1.getId(), premise3.getId()).toString()).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(2))) - .andExpect(jsonPath("$[?(@.material.part_number=='8222640822')].handling_unit.content_unit_count", hasItem(3))) - .andExpect(jsonPath("$", hasSize(2))) - .andReturn(); + var result = mockMvc.perform(get("/api/calculation/edit").content(Arrays.asList(premise1.getId(), premise3.getId()).toString()).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[?(@.material.part_number=='28152640129')].handling_unit.content_unit_count", hasItem(2))).andExpect(jsonPath("$[?(@.material.part_number=='8222640822')].handling_unit.content_unit_count", hasItem(3))).andExpect(jsonPath("$", hasSize(2))).andReturn(); var dtos = objectMapper.readValue(result.getResponse().getContentAsString(), PremiseDetailDTO[].class); @@ -886,7 +701,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/material - happy path (update tariff_rate)") public void updateMaterialCase1() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -896,12 +711,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -921,7 +733,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/material - happy path (update hs_code)") public void updateMaterialCase2() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -931,12 +743,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -956,7 +765,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/material - happy path (update both)") public void updateMaterialCase3() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -967,12 +776,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -993,7 +799,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/material - error (invalid hs_code - to long)") public void updateMaterialCase4() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1003,12 +809,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1028,7 +831,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/material - error (invalid hs_code - to short)") public void updateMaterialCase5() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1038,12 +841,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1063,7 +863,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/material - error (invalid hs_code - invalid characters)") public void updateMaterialCase6() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1073,12 +873,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1099,7 +896,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/material - error (invalid hs_code - negative number)") public void updateMaterialCase7() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1109,12 +906,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1134,7 +928,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/material - error (invalid tariff_rate values)") public void updateMaterialCase8() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1145,10 +939,7 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); // negative dto = new MaterialUpdateDTO(); @@ -1156,10 +947,7 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); // to big dto = new MaterialUpdateDTO(); @@ -1167,13 +955,10 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - mockMvc.perform(post("/api/calculation/material") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/material").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1204,7 +989,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/packaging - happy path (update mixable)") public void updatePackagingCase1() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1214,14 +999,10 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - var result = mockMvc.perform(post("/api/calculation/packaging") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/packaging").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()).andReturn(); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1262,7 +1043,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/packaging - happy path (update stackable)") public void updatePackagingCase2() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1272,14 +1053,10 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - var result = mockMvc.perform(post("/api/calculation/packaging") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/packaging").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()).andReturn(); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1320,7 +1097,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/packaging - happy path (update dimensions)") public void updatePackagingCase3() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1338,13 +1115,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - var result = mockMvc.perform(post("/api/calculation/packaging") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/packaging").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()).andReturn(); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1385,7 +1158,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/packaging - error (partial update dimensions)") public void updatePackagingCase4() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); var premise8 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow(); @@ -1403,13 +1176,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId(), premise8.getId())); - var result = mockMvc.perform(post("/api/calculation/packaging") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()) - .andReturn(); + var result = mockMvc.perform(post("/api/calculation/packaging").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()).andReturn(); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1450,7 +1219,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/packaging - happy path (API read-back)") public void updatePackagingCase5() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); @@ -1467,21 +1236,9 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Collections.singletonList(premise1.getId())); - mockMvc.perform(post("/api/calculation/packaging") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()) - .andReturn(); + mockMvc.perform(post("/api/calculation/packaging").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()).andReturn(); - mockMvc.perform(get("/api/calculation/edit") - .content(Collections.singletonList(premise1.getId()).toString()) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()) - .andExpect(jsonPath("$[0].handling_unit.weight").value(55500.0)) - .andExpect(jsonPath("$[0].handling_unit.height").value(1.005)) - .andExpect(jsonPath("$[0].handling_unit.width").value(1.250)) - .andExpect(jsonPath("$[0]['handling_unit']['length']").value(0.7)); + mockMvc.perform(get("/api/calculation/edit").content(Collections.singletonList(premise1.getId()).toString()).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()).andExpect(jsonPath("$[0].handling_unit.weight").value(55500.0)).andExpect(jsonPath("$[0].handling_unit.height").value(1.005)).andExpect(jsonPath("$[0].handling_unit.width").value(1.250)).andExpect(jsonPath("$[0]['handling_unit']['length']").value(0.7)); } @@ -1500,7 +1257,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/price - happy path (update price only)") public void updatePriceCase1() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1510,13 +1267,10 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1537,7 +1291,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/price - error case (set invalid prices)") public void updatePriceCase2() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1547,33 +1301,24 @@ public class PremiseControllerIntegrationTest { dto.setPrice(12.3456); dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); // negative price dto = new PriceUpdateDTO(); dto.setPrice(-12.34); dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); // price == 0 dto = new PriceUpdateDTO(); dto.setPrice(0.00); dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); // check if database is untouched - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1593,7 +1338,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/price - happy path (update oversea share only)") public void updatePriceCase4() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1603,13 +1348,10 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1630,7 +1372,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/price - error case (set invalid oversea share)") public void updatePriceCase5() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1641,10 +1383,7 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); //value to high @@ -1653,13 +1392,10 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1680,7 +1416,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/price - happy path (update include fca fee)") public void updatePriceCase6() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1688,12 +1424,9 @@ public class PremiseControllerIntegrationTest { dto.setIncludeFcaFee(true); dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1712,13 +1445,10 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - premisesAfterUpdate = getPremisesFromDb(); + premisesAfterUpdate = testsHelper.getPremisesFromDb(); premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1739,7 +1469,7 @@ public class PremiseControllerIntegrationTest { @DisplayName("POST /api/calculation/price - happy path (update all values)") public void updatePriceCase7() throws Exception { - var premisesBeforeUpdate = getPremisesFromDb(); + var premisesBeforeUpdate = testsHelper.getPremisesFromDb(); var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1751,13 +1481,10 @@ public class PremiseControllerIntegrationTest { dto.setPremiseIds(Arrays.asList(premise1.getId(), premise3.getId())); - mockMvc.perform(post("/api/calculation/price") - .content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andDo(print()); + mockMvc.perform(post("/api/calculation/price").content(objectMapper.writeValueAsString(dto)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - var premisesAfterUpdate = getPremisesFromDb(); + var premisesAfterUpdate = testsHelper.getPremisesFromDb(); var premiseAfter1 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); @@ -1776,71 +1503,6 @@ public class PremiseControllerIntegrationTest { } - @Nested - @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) - @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) - class CreateDestinationTests { - - @Test - @DisplayName("POST /api/calculation/price - happy path (create destination)") - public void createDestinationCase1() throws Exception { - - var nodeId = getNodeIdByExternalMappingId("AB"); - - var premisesBeforeUpdate = getPremisesFromDb(); - var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow(); - var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow(); - - var dto = new DestinationCreateDTO(); - dto.setPremiseId(Arrays.asList(premise1.getId(), premise3.getId())); - dto.setDestinationNodeId(nodeId); - - mockMvc.perform(post("/api/calculation/destination") - .content(objectMapper.writeValueAsString(dto)) - .contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print()); - - - } - } - - @Nested - @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) - @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) - class GetDestinationTests { - - } - - @Nested - @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) - @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) - class UpdateDestinationTests { - - } - - @Nested - @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) - @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) - class DeleteDestinationTests { - - } - - @Nested - @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS) - @Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) - @Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) - @DisplayName("GET /api/calculation/start - Start Calculations Tests") - class StartCalculationTests { - - } @Nested @Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) diff --git a/src/test/java/de/avatic/lcc/controller/calculation/PremiseTestsHelper.java b/src/test/java/de/avatic/lcc/controller/calculation/PremiseTestsHelper.java new file mode 100644 index 0000000..8ef3dcb --- /dev/null +++ b/src/test/java/de/avatic/lcc/controller/calculation/PremiseTestsHelper.java @@ -0,0 +1,198 @@ +package de.avatic.lcc.controller.calculation; + +import de.avatic.lcc.model.nodes.Location; +import de.avatic.lcc.model.premises.Premise; +import de.avatic.lcc.model.premises.PremiseState; +import de.avatic.lcc.model.premises.route.Destination; +import de.avatic.lcc.model.premises.route.Route; +import de.avatic.lcc.model.utils.DimensionUnit; +import de.avatic.lcc.model.utils.WeightUnit; +import org.springframework.boot.test.context.TestComponent; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.util.List; +import java.util.Optional; + +@TestComponent +public class PremiseTestsHelper { + + private final JdbcTemplate jdbcTemplate; + + public PremiseTestsHelper(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public List getPremisesFromDb() { + String query = "SELECT * FROM premise"; + return jdbcTemplate.query(query, (rs, rowNum) -> { + var entity = new Premise(); + + entity.setId(rs.getInt("id")); + + entity.setPackagingId(rs.getInt("packaging_id")); + if (rs.wasNull()) + entity.setPackagingId(null); + + entity.setMaterialId(rs.getInt("material_id")); + if (rs.wasNull()) + entity.setMaterialId(null); + + entity.setSupplierNodeId(rs.getInt("supplier_node_id")); + if (rs.wasNull()) + entity.setSupplierNodeId(null); + + entity.setUserSupplierNodeId(rs.getInt("user_supplier_node_id")); + if (rs.wasNull()) + entity.setUserSupplierNodeId(null); + + entity.setLocation(new Location(rs.getBigDecimal("geo_lng").doubleValue(), rs.getBigDecimal("geo_lat").doubleValue())); + + entity.setCountryId(rs.getInt("country_id")); + if (rs.wasNull()) + entity.setCountryId(null); + + entity.setUserId(rs.getInt("user_id")); + if (rs.wasNull()) + entity.setUserId(null); + + entity.setMaterialCost(rs.getBigDecimal("material_cost")); + + entity.setHsCode(rs.getString("hs_code")); + + entity.setCustomRate(rs.getBigDecimal("tariff_rate")); + + entity.setFcaEnabled(rs.getBoolean("is_fca_enabled")); + if (rs.wasNull()) + entity.setFcaEnabled(null); + + entity.setOverseaShare(rs.getBigDecimal("oversea_share")); + + entity.setIndividualHuHeight(rs.getInt("individual_hu_height")); + if (rs.wasNull()) + entity.setIndividualHuHeight(null); + + entity.setIndividualHuWidth(rs.getInt("individual_hu_width")); + if (rs.wasNull()) + entity.setIndividualHuWidth(null); + + entity.setIndividualHuLength(rs.getInt("individual_hu_length")); + if (rs.wasNull()) + entity.setIndividualHuLength(null); + + entity.setIndividualHuWeight(rs.getInt("individual_hu_weight")); + if (rs.wasNull()) + entity.setIndividualHuWeight(null); + + entity.setHuDisplayedDimensionUnit(DimensionUnit.valueOf(rs.getString("hu_displayed_dimension_unit"))); + entity.setHuDisplayedWeightUnit(WeightUnit.valueOf(rs.getString("hu_displayed_weight_unit"))); + + entity.setHuStackable(rs.getBoolean("hu_stackable")); + if (rs.wasNull()) + entity.setHuStackable(null); + + entity.setHuMixable(rs.getBoolean("hu_mixable")); + if (rs.wasNull()) + entity.setHuMixable(null); + + entity.setHuUnitCount(rs.getInt("hu_unit_count")); + if (rs.wasNull()) + entity.setHuUnitCount(null); + + entity.setState(PremiseState.valueOf(rs.getString("state"))); + entity.setUpdatedAt(rs.getTimestamp("updated_at").toLocalDateTime()); + entity.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime()); + + return entity; + }); + } + + public Integer getNodeIdByExternalMappingId(String mappingId) { + String query = "SELECT id FROM node WHERE external_mapping_id = ? LIMIT 1"; + return jdbcTemplate.queryForObject(query, Integer.class, mappingId); + } + + public Integer getUserNodeIdByName(String name) { + String query = "SELECT id FROM sys_user_node WHERE name = ? LIMIT 1"; + return jdbcTemplate.queryForObject(query, Integer.class, name); + } + + public List getDestinationIdsByPremiseId(Integer premiseId) { + String query = "SELECT id FROM premise_destination WHERE premise_id = ?"; + + return jdbcTemplate.query(query, (rs, rowNum) -> rs.getInt("id"), premiseId); + } + + public Integer getRouteCount() { + String query = """ + SELECT COUNT(*) FROM premise_route + """; + + return jdbcTemplate.queryForObject(query, Integer.class); + } + + public Integer getRouteSectionCount() { + String query = """ + SELECT COUNT(*) FROM premise_route_section + """; + + return jdbcTemplate.queryForObject(query, Integer.class); + } + + public Integer getRouteNodeCount() { + String query = """ + SELECT COUNT(*) FROM premise_route_node + """; + + return jdbcTemplate.queryForObject(query, Integer.class); + } + + public List getRoutesByDestinationId(Integer destinationId) { + String query = """ + SELECT * FROM premise_route WHERE premise_destination_id = ? + """; + + return jdbcTemplate.query(query, (rs, rowNum) -> { + Route entity = new Route(); + + entity.setId(rs.getInt("id")); + entity.setCheapest(rs.getBoolean("is_cheapest")); + entity.setFastest(rs.getBoolean("is_fastest")); + entity.setSelected(rs.getBoolean("is_selected")); + entity.setDestinationId(rs.getInt("premise_destination_id")); + + return entity; + }, destinationId); + } + + public Optional getDestinationById(Integer id) { + + String query = """ + SELECT * FROM premise_destination WHERE id = ? + """; + + var destinations = jdbcTemplate.query(query,(rs, row) -> { + Destination entity = new Destination(); + + entity.setId(rs.getInt("id")); + entity.setAnnualAmount(rs.getInt("annual_amount")); + entity.setPremiseId(rs.getInt("premise_id")); + entity.setDestinationNodeId(rs.getInt("destination_node_id")); + entity.setRateD2d(rs.getBigDecimal("rate_d2d")); + entity.setD2d(rs.getBoolean("is_d2d")); + entity.setLeadTimeD2d(rs.getInt("lead_time_d2d")); + entity.setRepackingCost(rs.getBigDecimal("repacking_cost")); + entity.setHandlingCost(rs.getBigDecimal("handling_cost")); + entity.setDisposalCost(rs.getBigDecimal("disposal_cost")); + entity.setGeoLat(rs.getBigDecimal("geo_lat")); + entity.setGeoLng(rs.getBigDecimal("geo_lng")); + entity.setCountryId(rs.getInt("country_id")); + + return entity; + }, id); + + if(destinations.isEmpty()) + return Optional.empty(); + + return Optional.ofNullable(destinations.getFirst()); + } +}