Refactor packaging and material update logic in ChangeSupplierService and PremiseCreationService, optimize repository method calls, and simplify PremiseControllerIntegrationTest by utilizing PremiseTestsHelper.
This commit is contained in:
parent
c03cbfb774
commit
eab6ed2e1b
19 changed files with 1067 additions and 609 deletions
|
|
@ -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<DestinationDTO> getDestination(@PathVariable Integer id) {
|
||||
return ResponseEntity.ok(destinationService.getDestination(id));
|
||||
}
|
||||
|
||||
@PutMapping({"/destination({id}", "/destination({id}/"})
|
||||
public ResponseEntity<Void> updateDestination(@PathVariable Integer id, @RequestParam DestinationUpdateDTO destinationUpdateDTO) {
|
||||
@PutMapping({"/destination/{id}", "/destination/{id}/"})
|
||||
public ResponseEntity<Void> 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<Void> deleteDestination(@PathVariable Integer id) {
|
||||
destinationService.deleteDestinationById(id, false);
|
||||
return ResponseEntity.ok().build();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Destination> 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<String, Object> parameters = new HashMap<>();
|
||||
List<String> 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<Integer> 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<Destination> {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -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<Integer> premiseIds, Integer userId, PackagingDimension hu, PackagingDimension shu, Boolean stackable, Boolean mixable) {
|
||||
public void updatePackaging(List<Integer> 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<Integer> premiseIds, Integer userId, PackagingDimension hu, Boolean stackable, Boolean mixable) {
|
||||
public void updatePackaging(List<Integer> 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<Integer> premiseIds, Integer userId, String hsCode, BigDecimal tariffRate) {
|
||||
public void updateMaterial(List<Integer> premiseIds, String hsCode, BigDecimal tariffRate) {
|
||||
|
||||
// Build the SET clause dynamically based on non-null parameters
|
||||
List<String> 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<Integer> premiseIds, int userId, BigDecimal price, Boolean includeFcaFee, BigDecimal overseaShare) {
|
||||
public void updatePrice(List<Integer> premiseIds, BigDecimal price, Boolean includeFcaFee, BigDecimal overseaShare) {
|
||||
// Build dynamic SET clause based on non-null parameters
|
||||
List<String> 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<Integer> 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
|
||||
|
|
|
|||
|
|
@ -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<Route> {
|
||||
@Override
|
||||
public Route mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
|
|
|
|||
|
|
@ -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<Integer> 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<Node> {
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -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<Integer>();
|
||||
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<Destination>();
|
||||
|
||||
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<Integer> ownerId = destinationRepository.getOwnerIdById(id);
|
||||
|
||||
if(ownerId.isPresent() && ownerId.get().equals(userId)) {
|
||||
if (ownerId.isPresent() && ownerId.get().equals(userId)) {
|
||||
List<Route> routes = routeRepository.getByDestinationId(id);
|
||||
|
||||
for(var route : routes) {
|
||||
for (var route : routes) {
|
||||
List<RouteSection> 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<Destination> 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();
|
||||
|
|
|
|||
|
|
@ -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<PremiseDetailDTO> getPremises(List<Integer> 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<Integer>();
|
||||
|
||||
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<String, String> 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<String, String> 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<String, String> 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<Integer> premiseIds) {
|
||||
//TODO check authorization
|
||||
var userId = 1;
|
||||
premiseRepository.checkOwner(premiseIds, userId);
|
||||
|
||||
destinationService.deleteAllDestinationsByPremiseId(premiseIds, false);
|
||||
premiseRepository.deletePremisesById(premiseIds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ public class PremiseCreationService {
|
|||
@Transactional
|
||||
public List<PremiseDetailDTO> createPremises(List<Integer> materialIds, List<Integer> supplierIds, List<Integer> userSupplierIds, boolean createEmpty) {
|
||||
Integer userId = 1; //TODO get user id
|
||||
userNodeRepository.checkOwner(userSupplierIds, userId);
|
||||
|
||||
/* Build all resulting premises */
|
||||
List<TemporaryPremise> 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))));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public class RoutingService {
|
|||
*/
|
||||
|
||||
List<List<Node>> destinationChains = chainResolver.buildChains(destination.getId());
|
||||
destinationChains.forEach(chain -> chain.addFirst(destination));
|
||||
List<Integer> 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<TemporaryRouteObject> cheapestRoutes = new ArrayList<>();
|
||||
|
||||
for(var mainRun : routesByMainRun.keySet()) {
|
||||
for (var mainRun : routesByMainRun.keySet()) {
|
||||
List<TemporaryRouteObject> 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<TemporaryRouteObject> routes) {
|
||||
|
||||
var toRemove = new ArrayList<TemporaryRouteObject>();
|
||||
|
||||
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<ChainQuality, List<List<Node>>> sortByQuality(List<List<Node>> chains, ContainerRate postRun, ContainerRate mainRun) {
|
||||
private Map<ChainQuality, Map<Integer, List<List<Node>>>> sortByQuality(List<List<Node>> chains, List<ContainerRate> postRuns, ContainerRate mainRun) {
|
||||
|
||||
Map<ChainQuality, List<List<Node>>> sortedChains = new HashMap<>();
|
||||
Map<ChainQuality, Map<Integer, List<List<Node>>>> 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<Node> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class CalculationStatusService {
|
|||
}
|
||||
}
|
||||
|
||||
public Integer schedule(ArrayList<Object> calculationIds) {
|
||||
public Integer schedule(ArrayList<Integer> calculationIds) {
|
||||
//TODO
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Integer> 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<Integer> 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<Integer> 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<Integer> 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<Integer> 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<Integer> 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<Integer> 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<Integer> 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<Integer> 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());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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<Premise> 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<Integer> 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<Route> 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<Destination> 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());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue