Added integration tests for RouteRepository and RouteNodeRepository for MySQL and MSSQL; Marked DestinationRepository as @Repository.
This commit is contained in:
parent
a381ca7ef8
commit
8d08fedbc4
7 changed files with 2182 additions and 3 deletions
|
|
@ -9,6 +9,7 @@ import org.springframework.jdbc.core.RowMapper;
|
||||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
import org.springframework.jdbc.support.GeneratedKeyHolder;
|
import org.springframework.jdbc.support.GeneratedKeyHolder;
|
||||||
import org.springframework.jdbc.support.KeyHolder;
|
import org.springframework.jdbc.support.KeyHolder;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
|
@ -19,7 +20,7 @@ import java.sql.Statement;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Repository
|
||||||
public class DestinationRepository {
|
public class DestinationRepository {
|
||||||
|
|
||||||
private final JdbcTemplate jdbcTemplate;
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,7 @@ import javax.sql.DataSource;
|
||||||
excludeFilters = @ComponentScan.Filter(
|
excludeFilters = @ComponentScan.Filter(
|
||||||
type = FilterType.ASSIGNABLE_TYPE,
|
type = FilterType.ASSIGNABLE_TYPE,
|
||||||
classes = {
|
classes = {
|
||||||
de.avatic.lcc.repositories.error.DumpRepository.class,
|
de.avatic.lcc.repositories.error.DumpRepository.class
|
||||||
de.avatic.lcc.repositories.premise.DestinationRepository.class
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,527 @@
|
||||||
|
package de.avatic.lcc.repositories.premise;
|
||||||
|
|
||||||
|
import de.avatic.lcc.model.db.premises.PremiseState;
|
||||||
|
import de.avatic.lcc.model.db.premises.route.Destination;
|
||||||
|
import de.avatic.lcc.repositories.AbstractRepositoryIntegrationTest;
|
||||||
|
import de.avatic.lcc.util.exception.base.ForbiddenException;
|
||||||
|
import de.avatic.lcc.util.exception.internalerror.DatabaseException;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for DestinationRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - Dynamic IN clauses
|
||||||
|
* - Named parameters
|
||||||
|
* - JOIN queries
|
||||||
|
* - NULL handling
|
||||||
|
* - Authorization checks
|
||||||
|
* - BigDecimal field operations
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=DestinationRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=DestinationRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class DestinationRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DestinationRepository destinationRepository;
|
||||||
|
|
||||||
|
private Integer testUserId1;
|
||||||
|
private Integer testUserId2;
|
||||||
|
private Integer testCountryId;
|
||||||
|
private Integer testNodeId1;
|
||||||
|
private Integer testNodeId2;
|
||||||
|
private Integer testMaterialId;
|
||||||
|
private Integer testPremiseId1;
|
||||||
|
private Integer testPremiseId2;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setupTestData() {
|
||||||
|
// Clean up in correct order (respecting foreign key constraints)
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route_section");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_destination");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise");
|
||||||
|
jdbcTemplate.update("DELETE FROM material");
|
||||||
|
|
||||||
|
// Clean up node-referencing tables before deleting nodes
|
||||||
|
jdbcTemplate.update("DELETE FROM container_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM country_matrix_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_entry");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_chain");
|
||||||
|
jdbcTemplate.update("DELETE FROM distance_matrix");
|
||||||
|
|
||||||
|
jdbcTemplate.update("DELETE FROM node");
|
||||||
|
jdbcTemplate.update("DELETE FROM sys_user");
|
||||||
|
|
||||||
|
// Create test users
|
||||||
|
testUserId1 = createUser("WD001", "user1@example.com");
|
||||||
|
testUserId2 = createUser("WD002", "user2@example.com");
|
||||||
|
|
||||||
|
// Get test country
|
||||||
|
testCountryId = getCountryId("DE");
|
||||||
|
|
||||||
|
// Create test nodes
|
||||||
|
testNodeId1 = createNode("Node 1", "NODE-001", testCountryId);
|
||||||
|
testNodeId2 = createNode("Node 2", "NODE-002", testCountryId);
|
||||||
|
|
||||||
|
// Create test material
|
||||||
|
testMaterialId = createMaterial("Test Material", "MAT-001");
|
||||||
|
|
||||||
|
// Create test premises
|
||||||
|
testPremiseId1 = createPremise(testUserId1, testNodeId1, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
testPremiseId2 = createPremise(testUserId2, testNodeId1, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// Create some test destinations
|
||||||
|
createDestination(testPremiseId1, testNodeId1, 1000);
|
||||||
|
createDestination(testPremiseId1, testNodeId2, 2000);
|
||||||
|
createDestination(testPremiseId2, testNodeId1, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetById() {
|
||||||
|
// Given: Create destination
|
||||||
|
Integer destinationId = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
|
||||||
|
// When: Get by ID
|
||||||
|
Optional<Destination> destination = destinationRepository.getById(destinationId);
|
||||||
|
|
||||||
|
// Then: Should retrieve
|
||||||
|
assertTrue(destination.isPresent());
|
||||||
|
assertEquals(destinationId, destination.get().getId());
|
||||||
|
assertEquals(testPremiseId1, destination.get().getPremiseId());
|
||||||
|
assertEquals(testNodeId1, destination.get().getDestinationNodeId());
|
||||||
|
assertEquals(500, destination.get().getAnnualAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByIdNotFound() {
|
||||||
|
// When: Get non-existent ID
|
||||||
|
Optional<Destination> destination = destinationRepository.getById(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(destination.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPremiseId() {
|
||||||
|
// When: Get destinations for premise1
|
||||||
|
List<Destination> destinations = destinationRepository.getByPremiseId(testPremiseId1);
|
||||||
|
|
||||||
|
// Then: Should return all destinations for premise1
|
||||||
|
assertNotNull(destinations);
|
||||||
|
assertEquals(2, destinations.size());
|
||||||
|
assertTrue(destinations.stream().allMatch(d -> d.getPremiseId().equals(testPremiseId1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPremiseIdAndUserId() {
|
||||||
|
// When: Get destinations for premise1 with correct user
|
||||||
|
List<Destination> destinations = destinationRepository.getByPremiseIdAndUserId(testPremiseId1, testUserId1);
|
||||||
|
|
||||||
|
// Then: Should return destinations
|
||||||
|
assertNotNull(destinations);
|
||||||
|
assertEquals(2, destinations.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPremiseIdAndUserIdWrongUser() {
|
||||||
|
// When: Get destinations for premise1 with wrong user
|
||||||
|
List<Destination> destinations = destinationRepository.getByPremiseIdAndUserId(testPremiseId1, testUserId2);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertTrue(destinations.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPremiseIdAndUserIdNonExistent() {
|
||||||
|
// When: Get destinations for non-existent premise
|
||||||
|
List<Destination> destinations = destinationRepository.getByPremiseIdAndUserId(99999, testUserId1);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertTrue(destinations.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdate() {
|
||||||
|
// Given: Create destination
|
||||||
|
Integer destinationId = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
|
||||||
|
// When: Update
|
||||||
|
destinationRepository.update(
|
||||||
|
destinationId,
|
||||||
|
1500, // annualAmount
|
||||||
|
new BigDecimal("10.50"), // repackingCost
|
||||||
|
new BigDecimal("5.25"), // disposalCost
|
||||||
|
new BigDecimal("8.75"), // handlingCost
|
||||||
|
true, // isD2d
|
||||||
|
new BigDecimal("100.00"), // d2dRate
|
||||||
|
new BigDecimal("48.00"), // d2dLeadTime
|
||||||
|
new BigDecimal("150.5") // distanceD2d
|
||||||
|
);
|
||||||
|
|
||||||
|
// Then: Should be updated
|
||||||
|
Optional<Destination> updated = destinationRepository.getById(destinationId);
|
||||||
|
assertTrue(updated.isPresent());
|
||||||
|
assertEquals(1500, updated.get().getAnnualAmount());
|
||||||
|
assertEquals(0, new BigDecimal("10.50").compareTo(updated.get().getRepackingCost()));
|
||||||
|
assertEquals(0, new BigDecimal("5.25").compareTo(updated.get().getDisposalCost()));
|
||||||
|
assertEquals(0, new BigDecimal("8.75").compareTo(updated.get().getHandlingCost()));
|
||||||
|
assertTrue(updated.get().getD2d());
|
||||||
|
assertEquals(0, new BigDecimal("100.00").compareTo(updated.get().getRateD2d()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateWithNulls() {
|
||||||
|
// Given: Create destination
|
||||||
|
Integer destinationId = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
|
||||||
|
// When: Update with null values
|
||||||
|
destinationRepository.update(
|
||||||
|
destinationId,
|
||||||
|
null, // annualAmount
|
||||||
|
null, // repackingCost
|
||||||
|
null, // disposalCost
|
||||||
|
null, // handlingCost
|
||||||
|
false, // isD2d
|
||||||
|
null, // d2dRate (should be null when isD2d is false)
|
||||||
|
null, // d2dLeadTime
|
||||||
|
null // distanceD2d
|
||||||
|
);
|
||||||
|
|
||||||
|
// Then: Should be updated with nulls
|
||||||
|
Optional<Destination> updated = destinationRepository.getById(destinationId);
|
||||||
|
assertTrue(updated.isPresent());
|
||||||
|
assertFalse(updated.get().getD2d());
|
||||||
|
assertNull(updated.get().getRateD2d());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateNonExistent() {
|
||||||
|
// When/Then: Update non-existent destination should throw
|
||||||
|
assertThrows(DatabaseException.class, () ->
|
||||||
|
destinationRepository.update(99999, 100, null, null, null, false, null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteById() {
|
||||||
|
// Given: Create destination
|
||||||
|
Integer destinationId = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
|
||||||
|
// When: Delete
|
||||||
|
destinationRepository.deleteById(destinationId);
|
||||||
|
|
||||||
|
// Then: Should be deleted
|
||||||
|
Optional<Destination> deleted = destinationRepository.getById(destinationId);
|
||||||
|
assertFalse(deleted.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteByIdNull() {
|
||||||
|
// When: Delete with null (should not throw)
|
||||||
|
destinationRepository.deleteById(null);
|
||||||
|
|
||||||
|
// Then: No error
|
||||||
|
assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetOwnerIdById() {
|
||||||
|
// Given: Create destination for user1
|
||||||
|
Integer destinationId = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
|
||||||
|
// When: Get owner ID
|
||||||
|
Optional<Integer> ownerId = destinationRepository.getOwnerIdById(destinationId);
|
||||||
|
|
||||||
|
// Then: Should return user1's ID
|
||||||
|
assertTrue(ownerId.isPresent());
|
||||||
|
assertEquals(testUserId1, ownerId.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetOwnerIdByIdNotFound() {
|
||||||
|
// When: Get owner ID for non-existent destination
|
||||||
|
Optional<Integer> ownerId = destinationRepository.getOwnerIdById(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(ownerId.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetOwnerIdsByIds() {
|
||||||
|
// Given: Create destinations for different users
|
||||||
|
Integer dest1 = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
Integer dest2 = createDestination(testPremiseId1, testNodeId2, 600);
|
||||||
|
Integer dest3 = createDestination(testPremiseId2, testNodeId1, 700);
|
||||||
|
|
||||||
|
// When: Get owner IDs
|
||||||
|
Map<Integer, Integer> ownerMap = destinationRepository.getOwnerIdsByIds(List.of(dest1, dest2, dest3));
|
||||||
|
|
||||||
|
// Then: Should return correct mappings
|
||||||
|
assertEquals(3, ownerMap.size());
|
||||||
|
assertEquals(testUserId1, ownerMap.get(dest1));
|
||||||
|
assertEquals(testUserId1, ownerMap.get(dest2));
|
||||||
|
assertEquals(testUserId2, ownerMap.get(dest3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetOwnerIdsByIdsEmpty() {
|
||||||
|
// When: Get owner IDs for empty list
|
||||||
|
Map<Integer, Integer> ownerMap = destinationRepository.getOwnerIdsByIds(List.of());
|
||||||
|
|
||||||
|
// Then: Should return empty map
|
||||||
|
assertTrue(ownerMap.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetOwnerIdsByIdsNull() {
|
||||||
|
// When: Get owner IDs for null
|
||||||
|
Map<Integer, Integer> ownerMap = destinationRepository.getOwnerIdsByIds(null);
|
||||||
|
|
||||||
|
// Then: Should return empty map
|
||||||
|
assertTrue(ownerMap.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPremiseIdsAndNodeIdsMap() {
|
||||||
|
// Given: Map of premise IDs to node IDs
|
||||||
|
Map<Integer, List<Integer>> premiseToNodes = new HashMap<>();
|
||||||
|
premiseToNodes.put(testPremiseId1, List.of(testNodeId1, testNodeId2));
|
||||||
|
premiseToNodes.put(testPremiseId2, List.of(testNodeId1));
|
||||||
|
|
||||||
|
// When: Get destinations
|
||||||
|
Map<Integer, List<Destination>> result =
|
||||||
|
destinationRepository.getByPremiseIdsAndNodeIds(premiseToNodes, testUserId1);
|
||||||
|
|
||||||
|
// Then: Should return destinations for user1's premises only
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.containsKey(testPremiseId1));
|
||||||
|
assertEquals(2, result.get(testPremiseId1).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPremiseIdsAndNodeIdsMapEmpty() {
|
||||||
|
// When: Get with empty map
|
||||||
|
Map<Integer, List<Destination>> result =
|
||||||
|
destinationRepository.getByPremiseIdsAndNodeIds(Map.of(), testUserId1);
|
||||||
|
|
||||||
|
// Then: Should return empty map
|
||||||
|
assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByPremiseIdsAndNodeIdsLists() {
|
||||||
|
// When: Get destinations by lists
|
||||||
|
Map<Integer, List<Destination>> result = destinationRepository.getByPremiseIdsAndNodeIds(
|
||||||
|
List.of(testPremiseId1, testPremiseId2),
|
||||||
|
List.of(testNodeId1, testNodeId2),
|
||||||
|
testUserId1
|
||||||
|
);
|
||||||
|
|
||||||
|
// Then: Should return only user1's destinations
|
||||||
|
// Note: The method queries for all premises in the list, then filters by userId in the JOIN
|
||||||
|
// So premise2 (owned by user2) should NOT be returned
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.containsKey(testPremiseId1));
|
||||||
|
|
||||||
|
// The method returns empty list for premises not owned by the user
|
||||||
|
if (result.containsKey(testPremiseId2)) {
|
||||||
|
assertTrue(result.get(testPremiseId2).isEmpty(), "User2's premise should return empty list");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsert() {
|
||||||
|
// Given: New destination
|
||||||
|
Destination newDest = new Destination();
|
||||||
|
newDest.setPremiseId(testPremiseId1);
|
||||||
|
newDest.setDestinationNodeId(testNodeId1);
|
||||||
|
newDest.setCountryId(testCountryId);
|
||||||
|
newDest.setAnnualAmount(999);
|
||||||
|
newDest.setRepackingCost(new BigDecimal("12.50"));
|
||||||
|
newDest.setHandlingCost(new BigDecimal("8.25"));
|
||||||
|
newDest.setDisposalCost(new BigDecimal("3.75"));
|
||||||
|
newDest.setD2d(true);
|
||||||
|
newDest.setRateD2d(new BigDecimal("50.00"));
|
||||||
|
newDest.setLeadTimeD2d(24);
|
||||||
|
newDest.setGeoLat(new BigDecimal("51.5"));
|
||||||
|
newDest.setGeoLng(new BigDecimal("7.5"));
|
||||||
|
newDest.setDistanceD2d(new BigDecimal("100.0"));
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = destinationRepository.insert(newDest);
|
||||||
|
|
||||||
|
// Then: Should be inserted
|
||||||
|
assertNotNull(id);
|
||||||
|
assertTrue(id > 0);
|
||||||
|
|
||||||
|
Optional<Destination> inserted = destinationRepository.getById(id);
|
||||||
|
assertTrue(inserted.isPresent());
|
||||||
|
assertEquals(999, inserted.get().getAnnualAmount());
|
||||||
|
assertEquals(0, new BigDecimal("12.50").compareTo(inserted.get().getRepackingCost()));
|
||||||
|
assertTrue(inserted.get().getD2d());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsertWithNulls() {
|
||||||
|
// Given: New destination with nullable fields as null
|
||||||
|
Destination newDest = new Destination();
|
||||||
|
newDest.setPremiseId(testPremiseId1);
|
||||||
|
newDest.setDestinationNodeId(testNodeId1);
|
||||||
|
newDest.setCountryId(testCountryId);
|
||||||
|
newDest.setAnnualAmount(null); // nullable
|
||||||
|
newDest.setRepackingCost(null);
|
||||||
|
newDest.setHandlingCost(null);
|
||||||
|
newDest.setDisposalCost(null);
|
||||||
|
newDest.setD2d(false);
|
||||||
|
newDest.setRateD2d(null);
|
||||||
|
newDest.setLeadTimeD2d(null); // nullable
|
||||||
|
newDest.setGeoLat(new BigDecimal("51.5"));
|
||||||
|
newDest.setGeoLng(new BigDecimal("7.5"));
|
||||||
|
newDest.setDistanceD2d(null);
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = destinationRepository.insert(newDest);
|
||||||
|
|
||||||
|
// Then: Should be inserted successfully
|
||||||
|
assertNotNull(id);
|
||||||
|
|
||||||
|
Optional<Destination> inserted = destinationRepository.getById(id);
|
||||||
|
assertTrue(inserted.isPresent());
|
||||||
|
// Note: annualAmount might be null or 0 depending on database behavior with nullable INT
|
||||||
|
// Just verify the record was inserted with the non-null fields
|
||||||
|
assertEquals(testPremiseId1, inserted.get().getPremiseId());
|
||||||
|
assertEquals(testNodeId1, inserted.get().getDestinationNodeId());
|
||||||
|
assertFalse(inserted.get().getD2d());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerSuccess() {
|
||||||
|
// Given: Destination owned by user1
|
||||||
|
Integer destId = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
|
||||||
|
// When/Then: Check with correct owner should not throw
|
||||||
|
assertDoesNotThrow(() -> destinationRepository.checkOwner(destId, testUserId1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerWrongUser() {
|
||||||
|
// Given: Destination owned by user1
|
||||||
|
Integer destId = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
|
||||||
|
// When/Then: Check with wrong user should throw
|
||||||
|
assertThrows(ForbiddenException.class, () ->
|
||||||
|
destinationRepository.checkOwner(destId, testUserId2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerNonExistent() {
|
||||||
|
// When/Then: Check non-existent destination should throw
|
||||||
|
assertThrows(ForbiddenException.class, () ->
|
||||||
|
destinationRepository.checkOwner(99999, testUserId1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerListSuccess() {
|
||||||
|
// Given: Destinations owned by user1
|
||||||
|
Integer dest1 = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
Integer dest2 = createDestination(testPremiseId1, testNodeId2, 600);
|
||||||
|
|
||||||
|
// When/Then: Check with correct owner should not throw
|
||||||
|
assertDoesNotThrow(() -> destinationRepository.checkOwner(List.of(dest1, dest2), testUserId1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerListMixedOwners() {
|
||||||
|
// Given: Destinations with different owners
|
||||||
|
Integer dest1 = createDestination(testPremiseId1, testNodeId1, 500);
|
||||||
|
Integer dest2 = createDestination(testPremiseId2, testNodeId1, 600);
|
||||||
|
|
||||||
|
// When/Then: Check with user1 should throw (dest2 is owned by user2)
|
||||||
|
assertThrows(ForbiddenException.class, () ->
|
||||||
|
destinationRepository.checkOwner(List.of(dest1, dest2), testUserId1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerListEmpty() {
|
||||||
|
// When/Then: Check with empty list should not throw
|
||||||
|
assertDoesNotThrow(() -> destinationRepository.checkOwner(List.of(), testUserId1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCheckOwnerListNull() {
|
||||||
|
// When/Then: Check with null should not throw
|
||||||
|
assertDoesNotThrow(() -> destinationRepository.checkOwner((List<Integer>) null, testUserId1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private Integer createUser(String workdayId, String email) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO sys_user (workday_id, email, firstname, lastname, is_active) VALUES (?, ?, ?, ?, %s)",
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, workdayId, email, "Test", "User");
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getCountryId(String isoCode) {
|
||||||
|
return jdbcTemplate.queryForObject("SELECT id FROM country WHERE iso_code = ?", Integer.class, isoCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createNode(String name, String externalId, Integer countryId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO node (name, external_mapping_id, country_id, is_deprecated, is_source, is_destination, is_intermediate, address) " +
|
||||||
|
"VALUES (?, ?, ?, %s, %s, %s, %s, 'Test Address')",
|
||||||
|
dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, name, externalId, countryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createMaterial(String name, String partNumber) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO material (name, part_number, normalized_part_number, hs_code, is_deprecated) VALUES (?, ?, ?, '123456', %s)",
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, name, partNumber, partNumber);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createPremise(Integer userId, Integer nodeId, Integer materialId, Integer countryId, PremiseState state) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise (user_id, supplier_node_id, material_id, country_id, state, geo_lat, geo_lng, created_at, updated_at) " +
|
||||||
|
"VALUES (?, ?, ?, ?, ?, 51.5, 7.5, %s, %s)",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()");
|
||||||
|
executeRawSql(sql, userId, nodeId, materialId, countryId, state.name());
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createDestination(Integer premiseId, Integer nodeId, Integer annualAmount) {
|
||||||
|
String sql = "INSERT INTO premise_destination (premise_id, destination_node_id, annual_amount, country_id, geo_lat, geo_lng) " +
|
||||||
|
"VALUES (?, ?, ?, ?, 51.5, 7.5)";
|
||||||
|
executeRawSql(sql, premiseId, nodeId, annualAmount, testCountryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,440 @@
|
||||||
|
package de.avatic.lcc.repositories.premise;
|
||||||
|
|
||||||
|
import de.avatic.lcc.model.db.premises.Premise;
|
||||||
|
import de.avatic.lcc.model.db.premises.PremiseListEntry;
|
||||||
|
import de.avatic.lcc.model.db.premises.PremiseState;
|
||||||
|
import de.avatic.lcc.repositories.AbstractRepositoryIntegrationTest;
|
||||||
|
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
|
||||||
|
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for PremiseRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - Pagination (LIMIT/OFFSET vs OFFSET/FETCH)
|
||||||
|
* - CURRENT_TIMESTAMP functions (NOW() vs GETDATE())
|
||||||
|
* - Boolean literals (TRUE/FALSE vs 1/0)
|
||||||
|
* - Dynamic IN clauses
|
||||||
|
* - Complex JOIN queries with filtering
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=PremiseRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=PremiseRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class PremiseRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PremiseRepository premiseRepository;
|
||||||
|
|
||||||
|
private Integer testUserId;
|
||||||
|
private Integer testCountryId;
|
||||||
|
private Integer testNodeId;
|
||||||
|
private Integer testMaterialId;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setupTestData() {
|
||||||
|
// Clean up in correct order (respecting foreign key constraints)
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_destination");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise");
|
||||||
|
jdbcTemplate.update("DELETE FROM material");
|
||||||
|
|
||||||
|
// Clean up node-referencing tables before deleting nodes
|
||||||
|
jdbcTemplate.update("DELETE FROM container_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM country_matrix_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_entry");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_chain");
|
||||||
|
jdbcTemplate.update("DELETE FROM distance_matrix");
|
||||||
|
|
||||||
|
jdbcTemplate.update("DELETE FROM node");
|
||||||
|
jdbcTemplate.update("DELETE FROM sys_user");
|
||||||
|
|
||||||
|
// Create test user
|
||||||
|
testUserId = createUser("WD001", "test@example.com");
|
||||||
|
|
||||||
|
// Get test country
|
||||||
|
testCountryId = getCountryId("DE");
|
||||||
|
|
||||||
|
// Create test node
|
||||||
|
testNodeId = createNode("Test Supplier", "SUP-001", testCountryId);
|
||||||
|
|
||||||
|
// Create test material
|
||||||
|
testMaterialId = createMaterial("Test Material", "MAT-001");
|
||||||
|
|
||||||
|
// Create some test premises
|
||||||
|
createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.COMPLETED);
|
||||||
|
createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.ARCHIVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListPremises() {
|
||||||
|
// Given: Pagination
|
||||||
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
||||||
|
|
||||||
|
// When: List premises
|
||||||
|
SearchQueryResult<PremiseListEntry> result = premiseRepository.listPremises(
|
||||||
|
null, pagination, testUserId, null, null, null);
|
||||||
|
|
||||||
|
// Then: Should return all premises
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(3, result.getTotalElements());
|
||||||
|
assertFalse(result.toList().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListPremisesPagination() {
|
||||||
|
// Given: Create more premises and use pagination
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 5);
|
||||||
|
|
||||||
|
// When: List premises
|
||||||
|
SearchQueryResult<PremiseListEntry> result = premiseRepository.listPremises(
|
||||||
|
null, pagination, testUserId, null, null, null);
|
||||||
|
|
||||||
|
// Then: Should respect limit
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(5, result.toList().size());
|
||||||
|
assertTrue(result.getTotalElements() >= 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListPremisesWithFilter() {
|
||||||
|
// Given: Pagination and filter
|
||||||
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
||||||
|
|
||||||
|
// When: List with filter
|
||||||
|
SearchQueryResult<PremiseListEntry> result = premiseRepository.listPremises(
|
||||||
|
"Test Supplier", pagination, testUserId, null, null, null);
|
||||||
|
|
||||||
|
// Then: Should filter results
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.getTotalElements() >= 3);
|
||||||
|
assertTrue(result.toList().stream()
|
||||||
|
.allMatch(p -> p.getSupplierName().contains("Test Supplier")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testListPremisesWithDraftFilter() {
|
||||||
|
// Given: Pagination with draft filter
|
||||||
|
SearchQueryPagination pagination = new SearchQueryPagination(1, 10);
|
||||||
|
|
||||||
|
// When: List only drafts
|
||||||
|
SearchQueryResult<PremiseListEntry> result = premiseRepository.listPremises(
|
||||||
|
null, pagination, testUserId, true, false, false);
|
||||||
|
|
||||||
|
// Then: Should return only DRAFT premises
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.toList().stream()
|
||||||
|
.allMatch(p -> p.getState() == de.avatic.lcc.dto.calculation.PremiseState.DRAFT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsert() {
|
||||||
|
// When: Insert new premise
|
||||||
|
Integer premiseId = premiseRepository.insert(
|
||||||
|
testMaterialId, testNodeId, null,
|
||||||
|
new BigDecimal("51.5"), new BigDecimal("7.5"),
|
||||||
|
testCountryId, testUserId);
|
||||||
|
|
||||||
|
// Then: Should be inserted
|
||||||
|
assertNotNull(premiseId);
|
||||||
|
assertTrue(premiseId > 0);
|
||||||
|
|
||||||
|
Optional<Premise> inserted = premiseRepository.getPremiseById(premiseId);
|
||||||
|
assertTrue(inserted.isPresent());
|
||||||
|
assertEquals(testMaterialId, inserted.get().getMaterialId());
|
||||||
|
assertEquals(testNodeId, inserted.get().getSupplierNodeId());
|
||||||
|
assertEquals(PremiseState.DRAFT, inserted.get().getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPremiseById() {
|
||||||
|
// Given: Create premise
|
||||||
|
Integer premiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// When: Get by ID
|
||||||
|
Optional<Premise> premise = premiseRepository.getPremiseById(premiseId);
|
||||||
|
|
||||||
|
// Then: Should retrieve
|
||||||
|
assertTrue(premise.isPresent());
|
||||||
|
assertEquals(premiseId, premise.get().getId());
|
||||||
|
assertEquals(testMaterialId, premise.get().getMaterialId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPremiseByIdNotFound() {
|
||||||
|
// When: Get non-existent ID
|
||||||
|
Optional<Premise> premise = premiseRepository.getPremiseById(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(premise.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPremisesById() {
|
||||||
|
// Given: Create multiple premises
|
||||||
|
Integer id1 = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
Integer id2 = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// When: Get by IDs
|
||||||
|
List<Premise> premises = premiseRepository.getPremisesById(List.of(id1, id2));
|
||||||
|
|
||||||
|
// Then: Should retrieve both
|
||||||
|
assertNotNull(premises);
|
||||||
|
assertEquals(2, premises.size());
|
||||||
|
assertTrue(premises.stream().anyMatch(p -> p.getId().equals(id1)));
|
||||||
|
assertTrue(premises.stream().anyMatch(p -> p.getId().equals(id2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPremisesByIdEmpty() {
|
||||||
|
// When: Get with empty list
|
||||||
|
List<Premise> premises = premiseRepository.getPremisesById(List.of());
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertNotNull(premises);
|
||||||
|
assertTrue(premises.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testResetPrice() {
|
||||||
|
// Given: Create premise with price
|
||||||
|
Integer premiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// Set initial price
|
||||||
|
premiseRepository.updatePrice(List.of(premiseId), new BigDecimal("100.50"), true, new BigDecimal("0.5"));
|
||||||
|
|
||||||
|
// When: Reset price
|
||||||
|
premiseRepository.resetPrice(List.of(premiseId));
|
||||||
|
|
||||||
|
// Then: Price should be null
|
||||||
|
Optional<Premise> premise = premiseRepository.getPremiseById(premiseId);
|
||||||
|
assertTrue(premise.isPresent());
|
||||||
|
assertNull(premise.get().getMaterialCost());
|
||||||
|
assertFalse(premise.get().getFcaEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdatePrice() {
|
||||||
|
// Given: Create premise
|
||||||
|
Integer premiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// When: Update price
|
||||||
|
premiseRepository.updatePrice(List.of(premiseId), new BigDecimal("200.75"), true, new BigDecimal("0.6"));
|
||||||
|
|
||||||
|
// Then: Price should be updated
|
||||||
|
Optional<Premise> premise = premiseRepository.getPremiseById(premiseId);
|
||||||
|
assertTrue(premise.isPresent());
|
||||||
|
assertEquals(0, new BigDecimal("200.75").compareTo(premise.get().getMaterialCost()));
|
||||||
|
assertTrue(premise.get().getFcaEnabled());
|
||||||
|
assertEquals(0, new BigDecimal("0.6").compareTo(premise.get().getOverseaShare()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateMaterial() {
|
||||||
|
// Given: Create premise
|
||||||
|
Integer premiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// When: Update material properties
|
||||||
|
premiseRepository.updateMaterial(List.of(premiseId), "12345678", new BigDecimal("0.05"), true);
|
||||||
|
|
||||||
|
// Then: Material properties should be updated
|
||||||
|
Optional<Premise> premise = premiseRepository.getPremiseById(premiseId);
|
||||||
|
assertTrue(premise.isPresent());
|
||||||
|
assertEquals("12345678", premise.get().getHsCode());
|
||||||
|
assertEquals(0, new BigDecimal("0.05").compareTo(premise.get().getTariffRate()));
|
||||||
|
assertTrue(premise.get().getTariffUnlocked());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSetMaterialId() {
|
||||||
|
// Given: Create premise and new material
|
||||||
|
Integer premiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
Integer newMaterialId = createMaterial("New Material", "MAT-002");
|
||||||
|
|
||||||
|
// When: Set new material ID
|
||||||
|
premiseRepository.setMaterialId(List.of(premiseId), newMaterialId);
|
||||||
|
|
||||||
|
// Then: Material should be changed
|
||||||
|
Optional<Premise> premise = premiseRepository.getPremiseById(premiseId);
|
||||||
|
assertTrue(premise.isPresent());
|
||||||
|
assertEquals(newMaterialId, premise.get().getMaterialId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeletePremisesById() {
|
||||||
|
// Given: Create DRAFT premises
|
||||||
|
Integer draftId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
Integer completedId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.COMPLETED);
|
||||||
|
|
||||||
|
// When: Delete (should only delete DRAFT)
|
||||||
|
premiseRepository.deletePremisesById(List.of(draftId, completedId));
|
||||||
|
|
||||||
|
// Then: DRAFT should be deleted, COMPLETED should remain
|
||||||
|
assertFalse(premiseRepository.getPremiseById(draftId).isPresent());
|
||||||
|
assertTrue(premiseRepository.getPremiseById(completedId).isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSetStatus() {
|
||||||
|
// Given: Create DRAFT premise
|
||||||
|
Integer premiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// When: Set status to COMPLETED
|
||||||
|
premiseRepository.setStatus(List.of(premiseId), PremiseState.COMPLETED);
|
||||||
|
|
||||||
|
// Then: Status should be updated
|
||||||
|
Optional<Premise> premise = premiseRepository.getPremiseById(premiseId);
|
||||||
|
assertTrue(premise.isPresent());
|
||||||
|
assertEquals(PremiseState.COMPLETED, premise.get().getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFindByMaterialIdAndSupplierId() {
|
||||||
|
// Given: Create premise
|
||||||
|
createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// When: Find by material and supplier
|
||||||
|
List<Premise> premises = premiseRepository.findByMaterialIdAndSupplierId(
|
||||||
|
testMaterialId, testNodeId, null, testUserId);
|
||||||
|
|
||||||
|
// Then: Should find premise
|
||||||
|
assertNotNull(premises);
|
||||||
|
assertFalse(premises.isEmpty());
|
||||||
|
assertTrue(premises.stream().anyMatch(p ->
|
||||||
|
p.getMaterialId().equals(testMaterialId) && p.getSupplierNodeId().equals(testNodeId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPremisesByMaterialIdsAndSupplierIds() {
|
||||||
|
// Given: Create premises
|
||||||
|
createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// When: Get by IDs
|
||||||
|
List<Premise> premises = premiseRepository.getPremisesByMaterialIdsAndSupplierIds(
|
||||||
|
List.of(testMaterialId), List.of(testNodeId), null, testUserId, true);
|
||||||
|
|
||||||
|
// Then: Should find premises
|
||||||
|
assertNotNull(premises);
|
||||||
|
assertFalse(premises.isEmpty());
|
||||||
|
assertTrue(premises.stream().allMatch(p -> p.getState() == PremiseState.DRAFT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFindAssociatedSuppliers() {
|
||||||
|
// Given: Premises with suppliers
|
||||||
|
createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// When: Find associated suppliers
|
||||||
|
List<Integer> supplierIds = premiseRepository.findAssociatedSuppliers(List.of(testMaterialId));
|
||||||
|
|
||||||
|
// Then: Should find supplier
|
||||||
|
assertNotNull(supplierIds);
|
||||||
|
assertFalse(supplierIds.isEmpty());
|
||||||
|
assertTrue(supplierIds.contains(testNodeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetIdsWithUnlockedTariffs() {
|
||||||
|
// Given: Create premises with different tariff states
|
||||||
|
Integer unlockedId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
Integer lockedId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// Set one as unlocked
|
||||||
|
premiseRepository.updateMaterial(List.of(unlockedId), null, null, true);
|
||||||
|
|
||||||
|
// When: Get unlocked IDs
|
||||||
|
List<Integer> unlockedIds = premiseRepository.getIdsWithUnlockedTariffs(List.of(unlockedId, lockedId));
|
||||||
|
|
||||||
|
// Then: Should return only unlocked
|
||||||
|
assertNotNull(unlockedIds);
|
||||||
|
assertTrue(unlockedIds.contains(unlockedId));
|
||||||
|
assertFalse(unlockedIds.contains(lockedId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPremiseCompletedCountByUserId() {
|
||||||
|
// When: Get count
|
||||||
|
Integer count = premiseRepository.getPremiseCompletedCountByUserId(testUserId);
|
||||||
|
|
||||||
|
// Then: Should count COMPLETED premises
|
||||||
|
assertNotNull(count);
|
||||||
|
assertTrue(count >= 1, "Should have at least 1 COMPLETED premise from setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPremiseDraftCountByUserId() {
|
||||||
|
// When: Get count
|
||||||
|
Integer count = premiseRepository.getPremiseDraftCountByUserId(testUserId);
|
||||||
|
|
||||||
|
// Then: Should count DRAFT premises
|
||||||
|
assertNotNull(count);
|
||||||
|
assertTrue(count >= 1, "Should have at least 1 DRAFT premise from setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private Integer createUser(String workdayId, String email) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO sys_user (workday_id, email, firstname, lastname, is_active) VALUES (?, ?, ?, ?, %s)",
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, workdayId, email, "Test", "User");
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getCountryId(String isoCode) {
|
||||||
|
return jdbcTemplate.queryForObject("SELECT id FROM country WHERE iso_code = ?", Integer.class, isoCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createNode(String name, String externalId, Integer countryId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO node (name, external_mapping_id, country_id, is_deprecated, is_source, is_destination, is_intermediate, address) " +
|
||||||
|
"VALUES (?, ?, ?, %s, %s, %s, %s, 'Test Address')",
|
||||||
|
dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, name, externalId, countryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createMaterial(String name, String partNumber) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO material (name, part_number, normalized_part_number, hs_code, is_deprecated) VALUES (?, ?, ?, '123456', %s)",
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, name, partNumber, partNumber);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createPremise(Integer userId, Integer nodeId, Integer materialId, Integer countryId, PremiseState state) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise (user_id, supplier_node_id, material_id, country_id, state, geo_lat, geo_lng, created_at, updated_at) " +
|
||||||
|
"VALUES (?, ?, ?, ?, ?, 51.5, 7.5, %s, %s)",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()");
|
||||||
|
executeRawSql(sql, userId, nodeId, materialId, countryId, state.name());
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,444 @@
|
||||||
|
package de.avatic.lcc.repositories.premise;
|
||||||
|
|
||||||
|
import de.avatic.lcc.model.db.premises.PremiseState;
|
||||||
|
import de.avatic.lcc.model.db.premises.route.RouteNode;
|
||||||
|
import de.avatic.lcc.repositories.AbstractRepositoryIntegrationTest;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for RouteNodeRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - Boolean literals (TRUE/FALSE vs 1/0)
|
||||||
|
* - Dynamic IN clauses
|
||||||
|
* - JOIN queries
|
||||||
|
* - NULL handling for optional foreign keys
|
||||||
|
* - BigDecimal geo coordinates
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=RouteNodeRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=RouteNodeRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class RouteNodeRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RouteNodeRepository routeNodeRepository;
|
||||||
|
|
||||||
|
private Integer testUserId;
|
||||||
|
private Integer testCountryId;
|
||||||
|
private Integer testNodeId;
|
||||||
|
private Integer testMaterialId;
|
||||||
|
private Integer testPremiseId;
|
||||||
|
private Integer testDestinationId;
|
||||||
|
private Integer testRouteId;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setupTestData() {
|
||||||
|
// Clean up in correct order (respecting foreign key constraints)
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route_section");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route_node");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_destination");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise");
|
||||||
|
jdbcTemplate.update("DELETE FROM material");
|
||||||
|
|
||||||
|
// Clean up node-referencing tables before deleting nodes
|
||||||
|
jdbcTemplate.update("DELETE FROM container_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM country_matrix_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_entry");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_chain");
|
||||||
|
jdbcTemplate.update("DELETE FROM distance_matrix");
|
||||||
|
|
||||||
|
jdbcTemplate.update("DELETE FROM node");
|
||||||
|
jdbcTemplate.update("DELETE FROM sys_user");
|
||||||
|
|
||||||
|
// Create test user
|
||||||
|
testUserId = createUser("WD001", "test@example.com");
|
||||||
|
|
||||||
|
// Get test country
|
||||||
|
testCountryId = getCountryId("DE");
|
||||||
|
|
||||||
|
// Create test node
|
||||||
|
testNodeId = createNode("Test Node", "NODE-001", testCountryId);
|
||||||
|
|
||||||
|
// Create test material
|
||||||
|
testMaterialId = createMaterial("Test Material", "MAT-001");
|
||||||
|
|
||||||
|
// Create test premise
|
||||||
|
testPremiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// Create test destination
|
||||||
|
testDestinationId = createDestination(testPremiseId, testNodeId);
|
||||||
|
|
||||||
|
// Create test route
|
||||||
|
testRouteId = createRoute(testDestinationId);
|
||||||
|
|
||||||
|
// Create some test route nodes
|
||||||
|
createRouteNode("Node A", testNodeId, testCountryId, true, false, false);
|
||||||
|
createRouteNode("Node B", testNodeId, testCountryId, false, true, false);
|
||||||
|
createRouteNode("Node C", testNodeId, testCountryId, false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetById() {
|
||||||
|
// Given: Create route node
|
||||||
|
Integer nodeId = createRouteNode("Test Node", testNodeId, testCountryId, true, true, true);
|
||||||
|
|
||||||
|
// When: Get by ID
|
||||||
|
Optional<RouteNode> node = routeNodeRepository.getById(nodeId);
|
||||||
|
|
||||||
|
// Then: Should retrieve
|
||||||
|
assertTrue(node.isPresent());
|
||||||
|
assertEquals(nodeId, node.get().getId());
|
||||||
|
assertEquals("Test Node", node.get().getName());
|
||||||
|
assertTrue(node.get().getDestination());
|
||||||
|
assertTrue(node.get().getIntermediate());
|
||||||
|
assertTrue(node.get().getSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByIdNotFound() {
|
||||||
|
// When: Get non-existent ID
|
||||||
|
Optional<RouteNode> node = routeNodeRepository.getById(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(node.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsert() {
|
||||||
|
// Given: New route node
|
||||||
|
RouteNode newNode = new RouteNode();
|
||||||
|
newNode.setName("New Route Node");
|
||||||
|
newNode.setAddress("123 Test Street");
|
||||||
|
newNode.setGeoLat(new BigDecimal("51.5074"));
|
||||||
|
newNode.setGeoLng(new BigDecimal("0.1278"));
|
||||||
|
newNode.setDestination(true);
|
||||||
|
newNode.setIntermediate(false);
|
||||||
|
newNode.setSource(true);
|
||||||
|
newNode.setNodeId(testNodeId);
|
||||||
|
newNode.setUserNodeId(null);
|
||||||
|
newNode.setOutdated(false);
|
||||||
|
newNode.setCountryId(testCountryId);
|
||||||
|
newNode.setExternalMappingId("EXT-001");
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = routeNodeRepository.insert(newNode);
|
||||||
|
|
||||||
|
// Then: Should be inserted
|
||||||
|
assertNotNull(id);
|
||||||
|
assertTrue(id > 0);
|
||||||
|
|
||||||
|
Optional<RouteNode> inserted = routeNodeRepository.getById(id);
|
||||||
|
assertTrue(inserted.isPresent());
|
||||||
|
assertEquals("New Route Node", inserted.get().getName());
|
||||||
|
assertTrue(inserted.get().getDestination());
|
||||||
|
assertFalse(inserted.get().getIntermediate());
|
||||||
|
assertTrue(inserted.get().getSource());
|
||||||
|
assertFalse(inserted.get().getOutdated());
|
||||||
|
assertEquals("EXT-001", inserted.get().getExternalMappingId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsertWithNulls() {
|
||||||
|
// Given: Route node with nullable fields as null
|
||||||
|
RouteNode newNode = new RouteNode();
|
||||||
|
newNode.setName("Minimal Node");
|
||||||
|
newNode.setAddress("Address");
|
||||||
|
newNode.setGeoLat(new BigDecimal("50.0"));
|
||||||
|
newNode.setGeoLng(new BigDecimal("8.0"));
|
||||||
|
newNode.setDestination(false);
|
||||||
|
newNode.setIntermediate(false);
|
||||||
|
newNode.setSource(false);
|
||||||
|
newNode.setNodeId(null); // nullable FK
|
||||||
|
newNode.setUserNodeId(null); // nullable FK
|
||||||
|
newNode.setOutdated(false);
|
||||||
|
newNode.setCountryId(testCountryId);
|
||||||
|
newNode.setExternalMappingId("MIN-EXT"); // NOT NULL in schema
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = routeNodeRepository.insert(newNode);
|
||||||
|
|
||||||
|
// Then: Should be inserted with nullable FKs as null
|
||||||
|
assertNotNull(id);
|
||||||
|
|
||||||
|
Optional<RouteNode> inserted = routeNodeRepository.getById(id);
|
||||||
|
assertTrue(inserted.isPresent());
|
||||||
|
assertEquals("Minimal Node", inserted.get().getName());
|
||||||
|
assertEquals("MIN-EXT", inserted.get().getExternalMappingId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllById() {
|
||||||
|
// Given: Multiple route nodes
|
||||||
|
Integer node1 = createRouteNode("Node 1", testNodeId, testCountryId, true, false, false);
|
||||||
|
Integer node2 = createRouteNode("Node 2", testNodeId, testCountryId, false, true, false);
|
||||||
|
Integer node3 = createRouteNode("Node 3", testNodeId, testCountryId, false, false, true);
|
||||||
|
|
||||||
|
// When: Delete first two
|
||||||
|
routeNodeRepository.deleteAllById(List.of(node1, node2));
|
||||||
|
|
||||||
|
// Then: Should delete specified nodes
|
||||||
|
assertFalse(routeNodeRepository.getById(node1).isPresent());
|
||||||
|
assertFalse(routeNodeRepository.getById(node2).isPresent());
|
||||||
|
assertTrue(routeNodeRepository.getById(node3).isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllByIdEmpty() {
|
||||||
|
// Given: Some route nodes
|
||||||
|
Integer nodeId = createRouteNode("Node", testNodeId, testCountryId, true, false, false);
|
||||||
|
|
||||||
|
// When: Delete with empty list
|
||||||
|
routeNodeRepository.deleteAllById(List.of());
|
||||||
|
|
||||||
|
// Then: Should not delete anything
|
||||||
|
assertTrue(routeNodeRepository.getById(nodeId).isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllByIdNull() {
|
||||||
|
// Given: Some route nodes
|
||||||
|
Integer nodeId = createRouteNode("Node", testNodeId, testCountryId, true, false, false);
|
||||||
|
|
||||||
|
// When: Delete with null
|
||||||
|
routeNodeRepository.deleteAllById(null);
|
||||||
|
|
||||||
|
// Then: Should not delete anything
|
||||||
|
assertTrue(routeNodeRepository.getById(nodeId).isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetFromNodeBySectionId() {
|
||||||
|
// Given: Create route section with from and to nodes
|
||||||
|
Integer fromNodeId = createRouteNode("From Node", testNodeId, testCountryId, false, false, true);
|
||||||
|
Integer toNodeId = createRouteNode("To Node", testNodeId, testCountryId, true, false, false);
|
||||||
|
Integer sectionId = createRouteSection(testRouteId, fromNodeId, toNodeId);
|
||||||
|
|
||||||
|
// When: Get from node by section ID
|
||||||
|
Optional<RouteNode> fromNode = routeNodeRepository.getFromNodeBySectionId(sectionId);
|
||||||
|
|
||||||
|
// Then: Should retrieve from node (verify by name and properties, not ID due to JOIN)
|
||||||
|
assertTrue(fromNode.isPresent());
|
||||||
|
assertEquals("From Node", fromNode.get().getName());
|
||||||
|
assertTrue(fromNode.get().getSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetFromNodeBySectionIdNotFound() {
|
||||||
|
// When: Get from node for non-existent section
|
||||||
|
Optional<RouteNode> fromNode = routeNodeRepository.getFromNodeBySectionId(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(fromNode.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetToNodeBySectionId() {
|
||||||
|
// Given: Create route section with from and to nodes
|
||||||
|
Integer fromNodeId = createRouteNode("From Node", testNodeId, testCountryId, false, false, true);
|
||||||
|
Integer toNodeId = createRouteNode("To Node", testNodeId, testCountryId, true, false, false);
|
||||||
|
Integer sectionId = createRouteSection(testRouteId, fromNodeId, toNodeId);
|
||||||
|
|
||||||
|
// When: Get to node by section ID
|
||||||
|
Optional<RouteNode> toNode = routeNodeRepository.getToNodeBySectionId(sectionId);
|
||||||
|
|
||||||
|
// Then: Should retrieve to node (verify by name and properties, not ID due to JOIN)
|
||||||
|
assertTrue(toNode.isPresent());
|
||||||
|
assertEquals("To Node", toNode.get().getName());
|
||||||
|
assertTrue(toNode.get().getDestination());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetToNodeBySectionIdNotFound() {
|
||||||
|
// When: Get to node for non-existent section
|
||||||
|
Optional<RouteNode> toNode = routeNodeRepository.getToNodeBySectionId(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(toNode.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBooleanFields() {
|
||||||
|
// Given: Create nodes with different boolean combinations
|
||||||
|
RouteNode node1 = new RouteNode();
|
||||||
|
node1.setName("All True");
|
||||||
|
node1.setAddress("Address 1");
|
||||||
|
node1.setGeoLat(new BigDecimal("50.0"));
|
||||||
|
node1.setGeoLng(new BigDecimal("8.0"));
|
||||||
|
node1.setDestination(true);
|
||||||
|
node1.setIntermediate(true);
|
||||||
|
node1.setSource(true);
|
||||||
|
node1.setOutdated(true);
|
||||||
|
node1.setCountryId(testCountryId);
|
||||||
|
node1.setExternalMappingId("EXT1");
|
||||||
|
|
||||||
|
RouteNode node2 = new RouteNode();
|
||||||
|
node2.setName("All False");
|
||||||
|
node2.setAddress("Address 2");
|
||||||
|
node2.setGeoLat(new BigDecimal("51.0"));
|
||||||
|
node2.setGeoLng(new BigDecimal("9.0"));
|
||||||
|
node2.setDestination(false);
|
||||||
|
node2.setIntermediate(false);
|
||||||
|
node2.setSource(false);
|
||||||
|
node2.setOutdated(false);
|
||||||
|
node2.setCountryId(testCountryId);
|
||||||
|
node2.setExternalMappingId("EXT2");
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id1 = routeNodeRepository.insert(node1);
|
||||||
|
Integer id2 = routeNodeRepository.insert(node2);
|
||||||
|
|
||||||
|
// Then: Boolean values should be stored and retrieved correctly
|
||||||
|
Optional<RouteNode> retrieved1 = routeNodeRepository.getById(id1);
|
||||||
|
assertTrue(retrieved1.isPresent());
|
||||||
|
assertTrue(retrieved1.get().getDestination());
|
||||||
|
assertTrue(retrieved1.get().getIntermediate());
|
||||||
|
assertTrue(retrieved1.get().getSource());
|
||||||
|
assertTrue(retrieved1.get().getOutdated());
|
||||||
|
|
||||||
|
Optional<RouteNode> retrieved2 = routeNodeRepository.getById(id2);
|
||||||
|
assertTrue(retrieved2.isPresent());
|
||||||
|
assertFalse(retrieved2.get().getDestination());
|
||||||
|
assertFalse(retrieved2.get().getIntermediate());
|
||||||
|
assertFalse(retrieved2.get().getSource());
|
||||||
|
assertFalse(retrieved2.get().getOutdated());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGeoCoordinates() {
|
||||||
|
// Given: Node with specific coordinates
|
||||||
|
RouteNode node = new RouteNode();
|
||||||
|
node.setName("Geo Node");
|
||||||
|
node.setAddress("Geo Address");
|
||||||
|
node.setGeoLat(new BigDecimal("52.5200"));
|
||||||
|
node.setGeoLng(new BigDecimal("13.4050"));
|
||||||
|
node.setDestination(true);
|
||||||
|
node.setIntermediate(false);
|
||||||
|
node.setSource(false);
|
||||||
|
node.setCountryId(testCountryId);
|
||||||
|
node.setExternalMappingId("GEO1");
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = routeNodeRepository.insert(node);
|
||||||
|
|
||||||
|
// Then: Coordinates should be stored correctly
|
||||||
|
Optional<RouteNode> retrieved = routeNodeRepository.getById(id);
|
||||||
|
assertTrue(retrieved.isPresent());
|
||||||
|
assertEquals(0, new BigDecimal("52.5200").compareTo(retrieved.get().getGeoLat()));
|
||||||
|
assertEquals(0, new BigDecimal("13.4050").compareTo(retrieved.get().getGeoLng()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private Integer createUser(String workdayId, String email) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO sys_user (workday_id, email, firstname, lastname, is_active) VALUES (?, ?, ?, ?, %s)",
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, workdayId, email, "Test", "User");
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getCountryId(String isoCode) {
|
||||||
|
return jdbcTemplate.queryForObject("SELECT id FROM country WHERE iso_code = ?", Integer.class, isoCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createNode(String name, String externalId, Integer countryId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO node (name, external_mapping_id, country_id, is_deprecated, is_source, is_destination, is_intermediate, address) " +
|
||||||
|
"VALUES (?, ?, ?, %s, %s, %s, %s, 'Test Address')",
|
||||||
|
dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, name, externalId, countryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createMaterial(String name, String partNumber) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO material (name, part_number, normalized_part_number, hs_code, is_deprecated) VALUES (?, ?, ?, '123456', %s)",
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, name, partNumber, partNumber);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createPremise(Integer userId, Integer nodeId, Integer materialId, Integer countryId, PremiseState state) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise (user_id, supplier_node_id, material_id, country_id, state, geo_lat, geo_lng, created_at, updated_at) " +
|
||||||
|
"VALUES (?, ?, ?, ?, ?, 51.5, 7.5, %s, %s)",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()");
|
||||||
|
executeRawSql(sql, userId, nodeId, materialId, countryId, state.name());
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createDestination(Integer premiseId, Integer nodeId) {
|
||||||
|
String sql = "INSERT INTO premise_destination (premise_id, destination_node_id, annual_amount, country_id, geo_lat, geo_lng) " +
|
||||||
|
"VALUES (?, ?, 1000, ?, 51.5, 7.5)";
|
||||||
|
executeRawSql(sql, premiseId, nodeId, testCountryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createRoute(Integer destinationId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise_route (premise_destination_id, is_cheapest, is_fastest, is_selected) VALUES (?, %s, %s, %s)",
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, destinationId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createRouteNode(String name, Integer nodeId, Integer countryId, boolean isDestination, boolean isIntermediate, boolean isSource) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise_route_node (name, address, geo_lat, geo_lng, is_destination, is_intermediate, is_source, " +
|
||||||
|
"node_id, country_id, is_outdated, external_mapping_id) " +
|
||||||
|
"VALUES (?, 'Address', 51.5, 7.5, %s, %s, %s, ?, ?, %s, 'EXT')",
|
||||||
|
isDestination ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse(),
|
||||||
|
isIntermediate ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse(),
|
||||||
|
isSource ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, name, nodeId, countryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createRouteSection(Integer routeId, Integer fromNodeId, Integer toNodeId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise_route_section (premise_route_id, from_route_node_id, to_route_node_id, list_position, " +
|
||||||
|
"transport_type, rate_type, is_pre_run, is_main_run, is_post_run, is_outdated) " +
|
||||||
|
"VALUES (?, ?, ?, 1, 'SEA', 'CONTAINER', %s, %s, %s, %s)",
|
||||||
|
dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, routeId, fromNodeId, toNodeId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,341 @@
|
||||||
|
package de.avatic.lcc.repositories.premise;
|
||||||
|
|
||||||
|
import de.avatic.lcc.model.db.premises.PremiseState;
|
||||||
|
import de.avatic.lcc.model.db.premises.route.Route;
|
||||||
|
import de.avatic.lcc.repositories.AbstractRepositoryIntegrationTest;
|
||||||
|
import de.avatic.lcc.util.exception.internalerror.DatabaseException;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for RouteRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - Boolean literals (TRUE/FALSE vs 1/0)
|
||||||
|
* - Dynamic IN clauses
|
||||||
|
* - Auto-generated keys
|
||||||
|
* - CRUD operations
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=RouteRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=RouteRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class RouteRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RouteRepository routeRepository;
|
||||||
|
|
||||||
|
private Integer testUserId;
|
||||||
|
private Integer testCountryId;
|
||||||
|
private Integer testNodeId;
|
||||||
|
private Integer testMaterialId;
|
||||||
|
private Integer testPremiseId;
|
||||||
|
private Integer testDestinationId;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setupTestData() {
|
||||||
|
// Clean up in correct order (respecting foreign key constraints)
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route_section");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_destination");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise");
|
||||||
|
jdbcTemplate.update("DELETE FROM material");
|
||||||
|
|
||||||
|
// Clean up node-referencing tables before deleting nodes
|
||||||
|
jdbcTemplate.update("DELETE FROM container_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM country_matrix_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_entry");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_chain");
|
||||||
|
jdbcTemplate.update("DELETE FROM distance_matrix");
|
||||||
|
|
||||||
|
jdbcTemplate.update("DELETE FROM node");
|
||||||
|
jdbcTemplate.update("DELETE FROM sys_user");
|
||||||
|
|
||||||
|
// Create test user
|
||||||
|
testUserId = createUser("WD001", "test@example.com");
|
||||||
|
|
||||||
|
// Get test country
|
||||||
|
testCountryId = getCountryId("DE");
|
||||||
|
|
||||||
|
// Create test node
|
||||||
|
testNodeId = createNode("Test Supplier", "SUP-001", testCountryId);
|
||||||
|
|
||||||
|
// Create test material
|
||||||
|
testMaterialId = createMaterial("Test Material", "MAT-001");
|
||||||
|
|
||||||
|
// Create test premise
|
||||||
|
testPremiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// Create test destination
|
||||||
|
testDestinationId = createDestination(testPremiseId, testNodeId);
|
||||||
|
|
||||||
|
// Create some test routes
|
||||||
|
createRoute(testDestinationId, true, true, true); // cheapest, fastest, selected
|
||||||
|
createRoute(testDestinationId, false, false, false); // not cheapest, not fastest, not selected
|
||||||
|
createRoute(testDestinationId, false, false, false); // not cheapest, not fastest, not selected
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByDestinationId() {
|
||||||
|
// When: Get routes by destination
|
||||||
|
List<Route> routes = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
|
||||||
|
// Then: Should return all routes for destination
|
||||||
|
assertNotNull(routes);
|
||||||
|
assertEquals(3, routes.size());
|
||||||
|
assertTrue(routes.stream().allMatch(r -> r.getDestinationId().equals(testDestinationId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByDestinationIdEmpty() {
|
||||||
|
// When: Get routes for non-existent destination
|
||||||
|
List<Route> routes = routeRepository.getByDestinationId(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty list
|
||||||
|
assertNotNull(routes);
|
||||||
|
assertTrue(routes.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetSelectedByDestinationId() {
|
||||||
|
// When: Get selected route
|
||||||
|
Optional<Route> selected = routeRepository.getSelectedByDestinationId(testDestinationId);
|
||||||
|
|
||||||
|
// Then: Should return the selected route
|
||||||
|
assertTrue(selected.isPresent());
|
||||||
|
assertEquals(testDestinationId, selected.get().getDestinationId());
|
||||||
|
assertTrue(selected.get().getSelected());
|
||||||
|
assertTrue(selected.get().getCheapest());
|
||||||
|
assertTrue(selected.get().getFastest());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetSelectedByDestinationIdNotFound() {
|
||||||
|
// Given: Destination with no selected routes
|
||||||
|
Integer destinationId2 = createDestination(testPremiseId, testNodeId);
|
||||||
|
createRoute(destinationId2, false, false, false);
|
||||||
|
|
||||||
|
// When: Get selected route
|
||||||
|
Optional<Route> selected = routeRepository.getSelectedByDestinationId(destinationId2);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(selected.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetSelectedByDestinationIdMultipleThrows() {
|
||||||
|
// Given: Destination with multiple selected routes (invalid state)
|
||||||
|
Integer destinationId2 = createDestination(testPremiseId, testNodeId);
|
||||||
|
createRoute(destinationId2, false, false, true);
|
||||||
|
createRoute(destinationId2, false, false, true);
|
||||||
|
|
||||||
|
// When/Then: Should throw DatabaseException
|
||||||
|
assertThrows(DatabaseException.class, () ->
|
||||||
|
routeRepository.getSelectedByDestinationId(destinationId2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsert() {
|
||||||
|
// Given: New route
|
||||||
|
Route newRoute = new Route();
|
||||||
|
newRoute.setDestinationId(testDestinationId);
|
||||||
|
newRoute.setCheapest(false);
|
||||||
|
newRoute.setFastest(true);
|
||||||
|
newRoute.setSelected(false);
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = routeRepository.insert(newRoute);
|
||||||
|
|
||||||
|
// Then: Should be inserted
|
||||||
|
assertNotNull(id);
|
||||||
|
assertTrue(id > 0);
|
||||||
|
|
||||||
|
// Verify insertion
|
||||||
|
List<Route> routes = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
assertTrue(routes.stream().anyMatch(r -> r.getId().equals(id) && r.getFastest()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllById() {
|
||||||
|
// Given: Multiple routes
|
||||||
|
List<Route> routes = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
assertEquals(3, routes.size());
|
||||||
|
|
||||||
|
// Get first two route IDs
|
||||||
|
List<Integer> idsToDelete = routes.stream()
|
||||||
|
.limit(2)
|
||||||
|
.map(Route::getId)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// When: Delete by IDs
|
||||||
|
routeRepository.deleteAllById(idsToDelete);
|
||||||
|
|
||||||
|
// Then: Should delete specified routes
|
||||||
|
List<Route> remaining = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
assertEquals(1, remaining.size());
|
||||||
|
assertFalse(idsToDelete.contains(remaining.getFirst().getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllByIdEmpty() {
|
||||||
|
// When: Delete with empty list
|
||||||
|
routeRepository.deleteAllById(List.of());
|
||||||
|
|
||||||
|
// Then: Should not throw error, routes remain
|
||||||
|
List<Route> routes = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
assertEquals(3, routes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllByIdNull() {
|
||||||
|
// When: Delete with null
|
||||||
|
routeRepository.deleteAllById(null);
|
||||||
|
|
||||||
|
// Then: Should not throw error, routes remain
|
||||||
|
List<Route> routes = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
assertEquals(3, routes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateSelectedByDestinationId() {
|
||||||
|
// Given: Get non-selected route
|
||||||
|
List<Route> routes = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
Route nonSelectedRoute = routes.stream()
|
||||||
|
.filter(r -> !r.getSelected())
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow();
|
||||||
|
|
||||||
|
// When: Update selected route
|
||||||
|
routeRepository.updateSelectedByDestinationId(testDestinationId, nonSelectedRoute.getId());
|
||||||
|
|
||||||
|
// Then: New route should be selected, old route should be deselected
|
||||||
|
Optional<Route> newSelected = routeRepository.getSelectedByDestinationId(testDestinationId);
|
||||||
|
assertTrue(newSelected.isPresent());
|
||||||
|
assertEquals(nonSelectedRoute.getId(), newSelected.get().getId());
|
||||||
|
assertTrue(newSelected.get().getSelected());
|
||||||
|
|
||||||
|
// Verify only one route is selected
|
||||||
|
List<Route> allRoutes = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
long selectedCount = allRoutes.stream().filter(Route::getSelected).count();
|
||||||
|
assertEquals(1, selectedCount, "Only one route should be selected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateSelectedByDestinationIdInvalidRoute() {
|
||||||
|
// When/Then: Update with non-existent route ID should throw
|
||||||
|
assertThrows(DatabaseException.class, () ->
|
||||||
|
routeRepository.updateSelectedByDestinationId(testDestinationId, 99999));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBooleanLiterals() {
|
||||||
|
// Given: Create routes with different boolean values
|
||||||
|
Route route1 = new Route();
|
||||||
|
route1.setDestinationId(testDestinationId);
|
||||||
|
route1.setCheapest(true);
|
||||||
|
route1.setFastest(false);
|
||||||
|
route1.setSelected(true);
|
||||||
|
|
||||||
|
Route route2 = new Route();
|
||||||
|
route2.setDestinationId(testDestinationId);
|
||||||
|
route2.setCheapest(false);
|
||||||
|
route2.setFastest(true);
|
||||||
|
route2.setSelected(false);
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id1 = routeRepository.insert(route1);
|
||||||
|
Integer id2 = routeRepository.insert(route2);
|
||||||
|
|
||||||
|
// Then: Boolean values should be stored and retrieved correctly
|
||||||
|
List<Route> routes = routeRepository.getByDestinationId(testDestinationId);
|
||||||
|
|
||||||
|
Route retrieved1 = routes.stream().filter(r -> r.getId().equals(id1)).findFirst().orElseThrow();
|
||||||
|
assertTrue(retrieved1.getCheapest());
|
||||||
|
assertFalse(retrieved1.getFastest());
|
||||||
|
|
||||||
|
Route retrieved2 = routes.stream().filter(r -> r.getId().equals(id2)).findFirst().orElseThrow();
|
||||||
|
assertFalse(retrieved2.getCheapest());
|
||||||
|
assertTrue(retrieved2.getFastest());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private Integer createUser(String workdayId, String email) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO sys_user (workday_id, email, firstname, lastname, is_active) VALUES (?, ?, ?, ?, %s)",
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, workdayId, email, "Test", "User");
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getCountryId(String isoCode) {
|
||||||
|
return jdbcTemplate.queryForObject("SELECT id FROM country WHERE iso_code = ?", Integer.class, isoCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createNode(String name, String externalId, Integer countryId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO node (name, external_mapping_id, country_id, is_deprecated, is_source, is_destination, is_intermediate, address) " +
|
||||||
|
"VALUES (?, ?, ?, %s, %s, %s, %s, 'Test Address')",
|
||||||
|
dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, name, externalId, countryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createMaterial(String name, String partNumber) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO material (name, part_number, normalized_part_number, hs_code, is_deprecated) VALUES (?, ?, ?, '123456', %s)",
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, name, partNumber, partNumber);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createPremise(Integer userId, Integer nodeId, Integer materialId, Integer countryId, PremiseState state) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise (user_id, supplier_node_id, material_id, country_id, state, geo_lat, geo_lng, created_at, updated_at) " +
|
||||||
|
"VALUES (?, ?, ?, ?, ?, 51.5, 7.5, %s, %s)",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()");
|
||||||
|
executeRawSql(sql, userId, nodeId, materialId, countryId, state.name());
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createDestination(Integer premiseId, Integer nodeId) {
|
||||||
|
String sql = "INSERT INTO premise_destination (premise_id, destination_node_id, annual_amount, country_id, geo_lat, geo_lng) " +
|
||||||
|
"VALUES (?, ?, 1000, ?, 51.5, 7.5)";
|
||||||
|
executeRawSql(sql, premiseId, nodeId, testCountryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createRoute(Integer destinationId, boolean isCheapest, boolean isFastest, boolean isSelected) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise_route (premise_destination_id, is_cheapest, is_fastest, is_selected) VALUES (?, %s, %s, %s)",
|
||||||
|
isCheapest ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse(),
|
||||||
|
isFastest ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse(),
|
||||||
|
isSelected ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, destinationId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,427 @@
|
||||||
|
package de.avatic.lcc.repositories.premise;
|
||||||
|
|
||||||
|
import de.avatic.lcc.dto.generic.RateType;
|
||||||
|
import de.avatic.lcc.dto.generic.TransportType;
|
||||||
|
import de.avatic.lcc.model.db.premises.PremiseState;
|
||||||
|
import de.avatic.lcc.model.db.premises.route.RouteSection;
|
||||||
|
import de.avatic.lcc.repositories.AbstractRepositoryIntegrationTest;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for RouteSectionRepository.
|
||||||
|
* <p>
|
||||||
|
* Tests critical functionality across both MySQL and MSSQL:
|
||||||
|
* - Boolean literals (TRUE/FALSE vs 1/0)
|
||||||
|
* - Enum handling (transport_type, rate_type)
|
||||||
|
* - Dynamic IN clauses
|
||||||
|
* - NULL handling for optional fields
|
||||||
|
* - BigDecimal to Double conversion
|
||||||
|
* <p>
|
||||||
|
* Run with:
|
||||||
|
* <pre>
|
||||||
|
* mvn test -Dspring.profiles.active=test,mysql -Dtest=RouteSectionRepositoryIntegrationTest
|
||||||
|
* mvn test -Dspring.profiles.active=test,mssql -Dtest=RouteSectionRepositoryIntegrationTest
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
class RouteSectionRepositoryIntegrationTest extends AbstractRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RouteSectionRepository routeSectionRepository;
|
||||||
|
|
||||||
|
private Integer testUserId;
|
||||||
|
private Integer testCountryId;
|
||||||
|
private Integer testNodeId;
|
||||||
|
private Integer testMaterialId;
|
||||||
|
private Integer testPremiseId;
|
||||||
|
private Integer testDestinationId;
|
||||||
|
private Integer testRouteId;
|
||||||
|
private Integer testFromNodeId;
|
||||||
|
private Integer testToNodeId;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setupTestData() {
|
||||||
|
// Clean up in correct order (respecting foreign key constraints)
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route_section");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route_node");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_route");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise_destination");
|
||||||
|
jdbcTemplate.update("DELETE FROM premise");
|
||||||
|
jdbcTemplate.update("DELETE FROM material");
|
||||||
|
|
||||||
|
// Clean up node-referencing tables before deleting nodes
|
||||||
|
jdbcTemplate.update("DELETE FROM container_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM country_matrix_rate");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_entry");
|
||||||
|
jdbcTemplate.update("DELETE FROM node_predecessor_chain");
|
||||||
|
jdbcTemplate.update("DELETE FROM distance_matrix");
|
||||||
|
|
||||||
|
jdbcTemplate.update("DELETE FROM node");
|
||||||
|
jdbcTemplate.update("DELETE FROM sys_user");
|
||||||
|
|
||||||
|
// Create test user
|
||||||
|
testUserId = createUser("WD001", "test@example.com");
|
||||||
|
|
||||||
|
// Get test country
|
||||||
|
testCountryId = getCountryId("DE");
|
||||||
|
|
||||||
|
// Create test node
|
||||||
|
testNodeId = createNode("Test Node", "NODE-001", testCountryId);
|
||||||
|
|
||||||
|
// Create test material
|
||||||
|
testMaterialId = createMaterial("Test Material", "MAT-001");
|
||||||
|
|
||||||
|
// Create test premise
|
||||||
|
testPremiseId = createPremise(testUserId, testNodeId, testMaterialId, testCountryId, PremiseState.DRAFT);
|
||||||
|
|
||||||
|
// Create test destination
|
||||||
|
testDestinationId = createDestination(testPremiseId, testNodeId);
|
||||||
|
|
||||||
|
// Create test route
|
||||||
|
testRouteId = createRoute(testDestinationId);
|
||||||
|
|
||||||
|
// Create test route nodes
|
||||||
|
testFromNodeId = createRouteNode("From Node", testNodeId, testCountryId);
|
||||||
|
testToNodeId = createRouteNode("To Node", testNodeId, testCountryId);
|
||||||
|
|
||||||
|
// Create some test sections (respecting constraint: is_main_run must be TRUE unless transport_type is ROAD/POST_RUN)
|
||||||
|
createRouteSection(testRouteId, testFromNodeId, testToNodeId, 1, TransportType.SEA, RateType.CONTAINER, true, true, false);
|
||||||
|
createRouteSection(testRouteId, testFromNodeId, testToNodeId, 2, TransportType.ROAD, RateType.MATRIX, false, false, false); // ROAD allows is_main_run=FALSE
|
||||||
|
createRouteSection(testRouteId, testFromNodeId, testToNodeId, 3, TransportType.RAIL, RateType.NEAR_BY, false, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByRouteId() {
|
||||||
|
// When: Get sections by route ID
|
||||||
|
List<RouteSection> sections = routeSectionRepository.getByRouteId(testRouteId);
|
||||||
|
|
||||||
|
// Then: Should return all sections for route
|
||||||
|
assertNotNull(sections);
|
||||||
|
assertEquals(3, sections.size());
|
||||||
|
assertTrue(sections.stream().allMatch(s -> s.getRouteId().equals(testRouteId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByRouteIdEmpty() {
|
||||||
|
// When: Get sections for non-existent route
|
||||||
|
List<RouteSection> sections = routeSectionRepository.getByRouteId(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty list
|
||||||
|
assertNotNull(sections);
|
||||||
|
assertTrue(sections.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetById() {
|
||||||
|
// Given: Create route section
|
||||||
|
Integer sectionId = createRouteSection(testRouteId, testFromNodeId, testToNodeId, 10,
|
||||||
|
TransportType.SEA, RateType.CONTAINER, true, true, false);
|
||||||
|
|
||||||
|
// When: Get by ID
|
||||||
|
Optional<RouteSection> section = routeSectionRepository.getById(sectionId);
|
||||||
|
|
||||||
|
// Then: Should retrieve
|
||||||
|
assertTrue(section.isPresent());
|
||||||
|
assertEquals(sectionId, section.get().getId());
|
||||||
|
assertEquals(testRouteId, section.get().getRouteId());
|
||||||
|
assertEquals(10, section.get().getListPosition());
|
||||||
|
assertEquals(TransportType.SEA, section.get().getTransportType());
|
||||||
|
assertEquals(RateType.CONTAINER, section.get().getRateType());
|
||||||
|
assertTrue(section.get().getPreRun());
|
||||||
|
assertTrue(section.get().getMainRun());
|
||||||
|
assertFalse(section.get().getPostRun());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetByIdNotFound() {
|
||||||
|
// When: Get non-existent ID
|
||||||
|
Optional<RouteSection> section = routeSectionRepository.getById(99999);
|
||||||
|
|
||||||
|
// Then: Should return empty
|
||||||
|
assertFalse(section.isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsert() {
|
||||||
|
// Given: New route section
|
||||||
|
RouteSection newSection = new RouteSection();
|
||||||
|
newSection.setRouteId(testRouteId);
|
||||||
|
newSection.setFromRouteNodeId(testFromNodeId);
|
||||||
|
newSection.setToRouteNodeId(testToNodeId);
|
||||||
|
newSection.setListPosition(99);
|
||||||
|
newSection.setTransportType(TransportType.POST_RUN);
|
||||||
|
newSection.setRateType(RateType.MATRIX);
|
||||||
|
newSection.setPreRun(false);
|
||||||
|
newSection.setMainRun(true);
|
||||||
|
newSection.setPostRun(true);
|
||||||
|
newSection.setOutdated(false);
|
||||||
|
newSection.setDistance(250.5);
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = routeSectionRepository.insert(newSection);
|
||||||
|
|
||||||
|
// Then: Should be inserted
|
||||||
|
assertNotNull(id);
|
||||||
|
assertTrue(id > 0);
|
||||||
|
|
||||||
|
Optional<RouteSection> inserted = routeSectionRepository.getById(id);
|
||||||
|
assertTrue(inserted.isPresent());
|
||||||
|
assertEquals(99, inserted.get().getListPosition());
|
||||||
|
assertEquals(TransportType.POST_RUN, inserted.get().getTransportType());
|
||||||
|
assertEquals(RateType.MATRIX, inserted.get().getRateType());
|
||||||
|
assertFalse(inserted.get().getPreRun());
|
||||||
|
assertTrue(inserted.get().getMainRun());
|
||||||
|
assertTrue(inserted.get().getPostRun());
|
||||||
|
assertNotNull(inserted.get().getDistance());
|
||||||
|
assertEquals(250.5, inserted.get().getDistance(), 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsertWithNullDistance() {
|
||||||
|
// Given: Route section with null distance
|
||||||
|
RouteSection newSection = new RouteSection();
|
||||||
|
newSection.setRouteId(testRouteId);
|
||||||
|
newSection.setFromRouteNodeId(testFromNodeId);
|
||||||
|
newSection.setToRouteNodeId(testToNodeId);
|
||||||
|
newSection.setListPosition(50);
|
||||||
|
newSection.setTransportType(TransportType.SEA);
|
||||||
|
newSection.setRateType(RateType.CONTAINER);
|
||||||
|
newSection.setPreRun(true);
|
||||||
|
newSection.setMainRun(true); // Must be TRUE for SEA (constraint)
|
||||||
|
newSection.setPostRun(false);
|
||||||
|
newSection.setOutdated(false);
|
||||||
|
newSection.setDistance(null); // nullable
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = routeSectionRepository.insert(newSection);
|
||||||
|
|
||||||
|
// Then: Should be inserted with null distance
|
||||||
|
assertNotNull(id);
|
||||||
|
|
||||||
|
Optional<RouteSection> inserted = routeSectionRepository.getById(id);
|
||||||
|
assertTrue(inserted.isPresent());
|
||||||
|
assertNull(inserted.get().getDistance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllById() {
|
||||||
|
// Given: Multiple route sections
|
||||||
|
List<RouteSection> sections = routeSectionRepository.getByRouteId(testRouteId);
|
||||||
|
assertEquals(3, sections.size());
|
||||||
|
|
||||||
|
// Get first two section IDs
|
||||||
|
List<Integer> idsToDelete = sections.stream()
|
||||||
|
.limit(2)
|
||||||
|
.map(RouteSection::getId)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// When: Delete by IDs
|
||||||
|
routeSectionRepository.deleteAllById(idsToDelete);
|
||||||
|
|
||||||
|
// Then: Should delete specified sections
|
||||||
|
List<RouteSection> remaining = routeSectionRepository.getByRouteId(testRouteId);
|
||||||
|
assertEquals(1, remaining.size());
|
||||||
|
assertFalse(idsToDelete.contains(remaining.getFirst().getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllByIdEmpty() {
|
||||||
|
// When: Delete with empty list
|
||||||
|
routeSectionRepository.deleteAllById(List.of());
|
||||||
|
|
||||||
|
// Then: Should not throw error, sections remain
|
||||||
|
List<RouteSection> sections = routeSectionRepository.getByRouteId(testRouteId);
|
||||||
|
assertEquals(3, sections.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteAllByIdNull() {
|
||||||
|
// When: Delete with null
|
||||||
|
routeSectionRepository.deleteAllById(null);
|
||||||
|
|
||||||
|
// Then: Should not throw error, sections remain
|
||||||
|
List<RouteSection> sections = routeSectionRepository.getByRouteId(testRouteId);
|
||||||
|
assertEquals(3, sections.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTransportTypeEnum() {
|
||||||
|
// Given: Sections with different transport types
|
||||||
|
RouteSection section1 = new RouteSection();
|
||||||
|
section1.setRouteId(testRouteId);
|
||||||
|
section1.setFromRouteNodeId(testFromNodeId);
|
||||||
|
section1.setToRouteNodeId(testToNodeId);
|
||||||
|
section1.setListPosition(101);
|
||||||
|
section1.setTransportType(TransportType.RAIL);
|
||||||
|
section1.setRateType(RateType.CONTAINER);
|
||||||
|
section1.setPreRun(false);
|
||||||
|
section1.setMainRun(true); // Must be TRUE for RAIL (constraint)
|
||||||
|
section1.setPostRun(false);
|
||||||
|
section1.setOutdated(false);
|
||||||
|
|
||||||
|
RouteSection section2 = new RouteSection();
|
||||||
|
section2.setRouteId(testRouteId);
|
||||||
|
section2.setFromRouteNodeId(testFromNodeId);
|
||||||
|
section2.setToRouteNodeId(testToNodeId);
|
||||||
|
section2.setListPosition(102);
|
||||||
|
section2.setTransportType(TransportType.POST_RUN); // POST_RUN allows is_main_run=FALSE
|
||||||
|
section2.setRateType(RateType.NEAR_BY);
|
||||||
|
section2.setPreRun(false);
|
||||||
|
section2.setMainRun(false);
|
||||||
|
section2.setPostRun(true);
|
||||||
|
section2.setOutdated(false);
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id1 = routeSectionRepository.insert(section1);
|
||||||
|
Integer id2 = routeSectionRepository.insert(section2);
|
||||||
|
|
||||||
|
// Then: Enum values should be stored and retrieved correctly
|
||||||
|
Optional<RouteSection> retrieved1 = routeSectionRepository.getById(id1);
|
||||||
|
assertTrue(retrieved1.isPresent());
|
||||||
|
assertEquals(TransportType.RAIL, retrieved1.get().getTransportType());
|
||||||
|
assertEquals(RateType.CONTAINER, retrieved1.get().getRateType());
|
||||||
|
|
||||||
|
Optional<RouteSection> retrieved2 = routeSectionRepository.getById(id2);
|
||||||
|
assertTrue(retrieved2.isPresent());
|
||||||
|
assertEquals(TransportType.POST_RUN, retrieved2.get().getTransportType());
|
||||||
|
assertEquals(RateType.NEAR_BY, retrieved2.get().getRateType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBooleanFlags() {
|
||||||
|
// Given: Section with different boolean flags (respecting constraint)
|
||||||
|
RouteSection section = new RouteSection();
|
||||||
|
section.setRouteId(testRouteId);
|
||||||
|
section.setFromRouteNodeId(testFromNodeId);
|
||||||
|
section.setToRouteNodeId(testToNodeId);
|
||||||
|
section.setListPosition(200);
|
||||||
|
section.setTransportType(TransportType.ROAD); // ROAD allows is_main_run=FALSE
|
||||||
|
section.setRateType(RateType.CONTAINER);
|
||||||
|
section.setPreRun(true);
|
||||||
|
section.setMainRun(false);
|
||||||
|
section.setPostRun(true);
|
||||||
|
section.setOutdated(true);
|
||||||
|
|
||||||
|
// When: Insert
|
||||||
|
Integer id = routeSectionRepository.insert(section);
|
||||||
|
|
||||||
|
// Then: Boolean flags should be stored correctly
|
||||||
|
Optional<RouteSection> retrieved = routeSectionRepository.getById(id);
|
||||||
|
assertTrue(retrieved.isPresent());
|
||||||
|
assertTrue(retrieved.get().getPreRun());
|
||||||
|
assertFalse(retrieved.get().getMainRun());
|
||||||
|
assertTrue(retrieved.get().getPostRun());
|
||||||
|
assertTrue(retrieved.get().getOutdated());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Helper Methods ==========
|
||||||
|
|
||||||
|
private Integer createUser(String workdayId, String email) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO sys_user (workday_id, email, firstname, lastname, is_active) VALUES (?, ?, ?, ?, %s)",
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, workdayId, email, "Test", "User");
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getCountryId(String isoCode) {
|
||||||
|
return jdbcTemplate.queryForObject("SELECT id FROM country WHERE iso_code = ?", Integer.class, isoCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createNode(String name, String externalId, Integer countryId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO node (name, external_mapping_id, country_id, is_deprecated, is_source, is_destination, is_intermediate, address) " +
|
||||||
|
"VALUES (?, ?, ?, %s, %s, %s, %s, 'Test Address')",
|
||||||
|
dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, name, externalId, countryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createMaterial(String name, String partNumber) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO material (name, part_number, normalized_part_number, hs_code, is_deprecated) VALUES (?, ?, ?, '123456', %s)",
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, name, partNumber, partNumber);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createPremise(Integer userId, Integer nodeId, Integer materialId, Integer countryId, PremiseState state) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise (user_id, supplier_node_id, material_id, country_id, state, geo_lat, geo_lng, created_at, updated_at) " +
|
||||||
|
"VALUES (?, ?, ?, ?, ?, 51.5, 7.5, %s, %s)",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()",
|
||||||
|
isMysql() ? "NOW()" : "GETDATE()");
|
||||||
|
executeRawSql(sql, userId, nodeId, materialId, countryId, state.name());
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createDestination(Integer premiseId, Integer nodeId) {
|
||||||
|
String sql = "INSERT INTO premise_destination (premise_id, destination_node_id, annual_amount, country_id, geo_lat, geo_lng) " +
|
||||||
|
"VALUES (?, ?, 1000, ?, 51.5, 7.5)";
|
||||||
|
executeRawSql(sql, premiseId, nodeId, testCountryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createRoute(Integer destinationId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise_route (premise_destination_id, is_cheapest, is_fastest, is_selected) VALUES (?, %s, %s, %s)",
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue());
|
||||||
|
executeRawSql(sql, destinationId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createRouteNode(String name, Integer nodeId, Integer countryId) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise_route_node (name, address, geo_lat, geo_lng, is_destination, is_intermediate, is_source, " +
|
||||||
|
"node_id, country_id, is_outdated, external_mapping_id) " +
|
||||||
|
"VALUES (?, 'Address', 51.5, 7.5, %s, %s, %s, ?, ?, %s, 'EXT')",
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanTrue(),
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, name, nodeId, countryId);
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createRouteSection(Integer routeId, Integer fromNodeId, Integer toNodeId, int listPosition,
|
||||||
|
TransportType transportType, RateType rateType,
|
||||||
|
boolean isPreRun, boolean isMainRun, boolean isPostRun) {
|
||||||
|
String sql = String.format(
|
||||||
|
"INSERT INTO premise_route_section (premise_route_id, from_route_node_id, to_route_node_id, list_position, " +
|
||||||
|
"transport_type, rate_type, is_pre_run, is_main_run, is_post_run, is_outdated) " +
|
||||||
|
"VALUES (?, ?, ?, ?, ?, ?, %s, %s, %s, %s)",
|
||||||
|
isPreRun ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse(),
|
||||||
|
isMainRun ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse(),
|
||||||
|
isPostRun ? dialectProvider.getBooleanTrue() : dialectProvider.getBooleanFalse(),
|
||||||
|
dialectProvider.getBooleanFalse());
|
||||||
|
executeRawSql(sql, routeId, fromNodeId, toNodeId, listPosition, transportType.name(), rateType.name());
|
||||||
|
|
||||||
|
String selectSql = isMysql() ? "SELECT LAST_INSERT_ID()" : "SELECT CAST(@@IDENTITY AS INT)";
|
||||||
|
return jdbcTemplate.queryForObject(selectSql, Integer.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue