Refactor rates and validity period handling structure

Removed CountryMatrixRate and integrated improved validity period management, including new repositories and services. Introduced ValidityPeriodService, updated route mappings in RateController, and replaced PropertySetState with ValidityPeriodState. Adjusted related classes for consistency and clarity.
This commit is contained in:
Jan 2025-04-13 11:55:59 +02:00
parent 298504384f
commit 2f58b0b3ba
31 changed files with 1153 additions and 195 deletions

View file

@ -23,12 +23,11 @@ public class NodeController {
private final NodeService nodeService;
private final GeoApiService geoApiService;
private final UserNodeRepository userNodeRepository;
public NodeController(NodeService nodeService, GeoApiService geoApiService, UserNodeRepository userNodeRepository) {
public NodeController(NodeService nodeService, GeoApiService geoApiService) {
this.nodeService = nodeService;
this.geoApiService = geoApiService;
this.userNodeRepository = userNodeRepository;
}
@GetMapping("/")

View file

@ -5,7 +5,7 @@ import de.avatic.lcc.dto.generic.PropertyDTO;
import de.avatic.lcc.model.country.IsoCode;
import de.avatic.lcc.service.configuration.CountryService;
import de.avatic.lcc.service.configuration.PropertyService;
import de.avatic.lcc.service.configuration.PropertyStagedChangesService;
import de.avatic.lcc.service.configuration.PropertyApprovalService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@ -20,18 +20,18 @@ import java.util.List;
public class PropertyController {
private final PropertyService propertyService;
private final PropertyStagedChangesService propertyStagedChangesService;
private final PropertyApprovalService propertyApprovalService;
private final CountryService countryService;
/**
* Constructs a new PropertyController with the provided services.
*
* @param propertyService Service for managing properties.
* @param propertyStagedChangesService Service for managing staged changes.
* @param propertyApprovalService Service for managing staged changes.
*/
public PropertyController(PropertyService propertyService, PropertyStagedChangesService propertyStagedChangesService, CountryService countryService) {
public PropertyController(PropertyService propertyService, PropertyApprovalService propertyApprovalService, CountryService countryService) {
this.propertyService = propertyService;
this.propertyStagedChangesService = propertyStagedChangesService;
this.propertyApprovalService = propertyApprovalService;
this.countryService = countryService;
}
@ -102,7 +102,7 @@ public class PropertyController {
*/
@GetMapping("/staged_changes")
public ResponseEntity<Boolean> checkPropertiesDrafts() {
return ResponseEntity.ok(propertyStagedChangesService.hasPropertiesDraft());
return ResponseEntity.ok(propertyApprovalService.hasPropertiesDraft());
}
/**
@ -112,7 +112,7 @@ public class PropertyController {
*/
@PutMapping("/staged_changes")
public ResponseEntity<Void> approvePropertiesDrafts() {
propertyStagedChangesService.applyDraft();
propertyApprovalService.applyDraft();
return ResponseEntity.ok().build();
}

View file

@ -2,10 +2,12 @@ package de.avatic.lcc.controller.configuration;
import de.avatic.lcc.dto.configuration.matrixrates.MatrixRateDTO;
import de.avatic.lcc.dto.configuration.rates.ContainerRateDTO;
import de.avatic.lcc.dto.generic.ValidityPeriodDTO;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.service.configuration.ContainerRateService;
import de.avatic.lcc.service.configuration.MatrixRateService;
import de.avatic.lcc.service.configuration.PropertyStagedChangesService;
import de.avatic.lcc.service.configuration.RateApprovalService;
import de.avatic.lcc.service.configuration.ValidityPeriodService;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@ -19,31 +21,50 @@ public class RateController {
private final MatrixRateService matrixRateService;
private final ContainerRateService containerRateService;
private final PropertyStagedChangesService propertyStagedChangesService;
private final RateApprovalService rateApprovalService;
private final ValidityPeriodService validityPeriodService;
public RateController(MatrixRateService matrixRateService, ContainerRateService containerRateService, PropertyStagedChangesService propertyStagedChangesService) {
/**
* Constructs a RateController instance with the specified services.
*
* @param matrixRateService the service responsible for handling matrix rate operations
* @param containerRateService the service responsible for managing container rates
* @param rateApprovalService the service responsible for rate approval processes
* @param validityPeriodService the service responsible for managing validity period operations
*/
public RateController(MatrixRateService matrixRateService, ContainerRateService containerRateService, RateApprovalService rateApprovalService, ValidityPeriodService validityPeriodService) {
this.matrixRateService = matrixRateService;
this.containerRateService = containerRateService;
this.propertyStagedChangesService = propertyStagedChangesService;
this.rateApprovalService = rateApprovalService;
this.validityPeriodService = validityPeriodService;
}
/**
* Retrieves a list of container rates based on the provided query parameters.
*
* @param limit the maximum number of container rates to return, defaults to 20 if not specified
* @param page the page number to retrieve, defaults to 0 if not specified
* @param validityPeriodId the ID of the validity period to filter container rates, optional
* @param validAt the specific date and time to filter container rates, optional
* @return a ResponseEntity containing the list of container rates and additional pagination headers
*/
@GetMapping("/container")
public ResponseEntity<List<ContainerRateDTO>> listContainerRates(
@RequestParam(defaultValue = "20") int limit,
@RequestParam(defaultValue = "0") int page,
@RequestParam(required = false) Integer valid,
@RequestParam(name= "valid", required = false) Integer validityPeriodId,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime validAt) {
SearchQueryResult<ContainerRateDTO> containerRates = null;
if(validAt != null) {
containerRates = containerRateService.listContainerRates(limit, page, validAt);
containerRates = containerRateService.listRates(limit, page, validAt);
}
else if(valid != null) {
containerRates = containerRateService.listContainerRates(limit, page, valid);
else if(validityPeriodId != null) {
containerRates = containerRateService.listRates(limit, page, validityPeriodId);
}
else {
containerRates = containerRateService.listContainerRates(limit, page);
containerRates = containerRateService.listRates(limit, page);
}
return ResponseEntity.ok()
@ -53,11 +74,27 @@ public class RateController {
.body(containerRates.toList());
}
/**
* Retrieves the rate information for a container by its unique identifier.
*
* @param id the unique identifier of the container whose rate information is to be retrieved
* @return a ResponseEntity containing the ContainerRateDTO with the rate information of the specified container
*/
@GetMapping("/container/{id}")
public ResponseEntity<ContainerRateDTO> getContainerRate(@PathVariable Integer id) {
return ResponseEntity.ok(containerRateService.getContainerRate(id));
}
/**
* Retrieves a list of matrix rates with optional filters.
*
* @param limit the maximum number of records to return (default is 20).
* @param page the page index to retrieve, starting from 0 (default is 0).
* @param valid an optional filter to retrieve records based on validity (null if not provided).
* @param validAt an optional filter for retrieving records valid at a specific date and time (null if not provided).
* @return a {@link ResponseEntity} containing a list of {@link MatrixRateDTO} wrapped in the response body,
* including pagination headers.
*/
@GetMapping("/matrix")
public ResponseEntity<List<MatrixRateDTO>> listMatrixRates(
@RequestParam(defaultValue = "20") int limit,
@ -83,19 +120,59 @@ public class RateController {
.header("X-Current-Page", String.valueOf(page))
.body(rates.toList());
}
/**
* Retrieves the matrix rate for the specified ID.
*
* @param id the unique identifier of the matrix rate to retrieve
* @return a ResponseEntity containing the MatrixRateDTO for the specified ID
*/
@GetMapping("/matrix/{id}")
public ResponseEntity<MatrixRateDTO> getMatrixRate(@PathVariable Integer id) {
return ResponseEntity.ok(matrixRateService.getRate(id));
}
@GetMapping("/staged_changes")
public ResponseEntity<Boolean> checkRateDrafts() {
return ResponseEntity.ok(propertyStagedChangesService.hasRateDrafts());
/**
* Retrieves all validity periods of the application properties.
*
* @return ResponseEntity containing the list of ValidityPeriodDTO objects.
*/
@GetMapping("/periods")
public ResponseEntity<List<ValidityPeriodDTO>> listPeriods() {
return ResponseEntity.ok(validityPeriodService.listPeriods());
}
/**
* Invalidates a specific validity period by its ID.
*
* @param id The ID of the validity period to invalidate.
* @return ResponseEntity indicating the operation status.
*/
@DeleteMapping("/periods/{id}")
public ResponseEntity<Void> invalidatePeriod(@PathVariable Integer id) {
validityPeriodService.invalidate(id);
return ResponseEntity.ok().build();
}
/**
* Checks if there are any rate drafts in the rate approval service.
*
* @return ResponseEntity containing a Boolean value indicating
* whether rate drafts exist (true) or not (false).
*/
@GetMapping("/staged_changes")
public ResponseEntity<Boolean> checkRateDrafts() {
return ResponseEntity.ok(rateApprovalService.hasRateDrafts());
}
/**
* Approves the staged rate drafts by invoking the rate approval service.
*
* @return ResponseEntity with HTTP 200 status if the operation is successful.
*/
@PutMapping("/staged_changes")
public ResponseEntity<Void> approveRateDrafts() {
propertyStagedChangesService.approveRateDrafts();
rateApprovalService.approveRateDrafts();
return ResponseEntity.ok().build();
}
}

View file

@ -0,0 +1,42 @@
package de.avatic.lcc.controller.custom;
import de.avatic.lcc.service.calculation.CustomApiService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller for handling custom tariff related requests.
* Provides endpoints for retrieving tariff rates based on HS code and country ID.
*/
@RestController
@RequestMapping("/api/customs")
public class CustomController {
private final CustomApiService customApiService;
/**
* Constructs a new instance of CustomController with the given service.
*
* @param customApiService the service responsible for custom tariff calculations
*/
public CustomController(CustomApiService customApiService) {
this.customApiService = customApiService;
}
/**
* Retrieves the tariff rate for the specified HS code and country ID.
*
* @param hsCode the HS code representing the product classification
* @param countryId the ID of the country for which the tariff rate is required
* @return a {@code ResponseEntity} containing the tariff rate as a {@code Number}
*/
@GetMapping("/")
public ResponseEntity<Number> getTariffRate(@RequestParam(value = "hs_code") String hsCode, @RequestParam(value = "country_id") Integer countryId) {
return ResponseEntity.ok(customApiService.getTariffRate(hsCode, countryId));
}
}

View file

@ -1,4 +1,42 @@
package de.avatic.lcc.dto.configuration.matrixrates;
import de.avatic.lcc.dto.generic.NodeDTO;
public class MatrixRateDTO {
private Integer id;
private NodeDTO origin;
private NodeDTO destination;
private Number rate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public NodeDTO getOrigin() {
return origin;
}
public void setOrigin(NodeDTO origin) {
this.origin = origin;
}
public NodeDTO getDestination() {
return destination;
}
public void setDestination(NodeDTO destination) {
this.destination = destination;
}
public Number getRate() {
return rate;
}
public void setRate(Number rate) {
this.rate = rate;
}
}

View file

@ -1,4 +1,81 @@
package de.avatic.lcc.dto.configuration.rates;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.generic.RouteType;
import de.avatic.lcc.dto.generic.ValidityPeriodDTO;
import java.util.HashMap;
public class ContainerRateDTO {
private Integer id;
private NodeDTO origin;
private NodeDTO destination;
private RouteType type;
private HashMap<String, Number> rates;
@JsonProperty("lead_time")
private Number leadTime;
private ValidityPeriodDTO validityPeriod;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public NodeDTO getOrigin() {
return origin;
}
public void setOrigin(NodeDTO origin) {
this.origin = origin;
}
public NodeDTO getDestination() {
return destination;
}
public void setDestination(NodeDTO destination) {
this.destination = destination;
}
public RouteType getType() {
return type;
}
public void setType(RouteType type) {
this.type = type;
}
public HashMap<String, Number> getRates() {
return rates;
}
public void setRates(HashMap<String, Number> rates) {
this.rates = rates;
}
public Number getLeadTime() {
return leadTime;
}
public void setLeadTime(Number leadTime) {
this.leadTime = leadTime;
}
public ValidityPeriodDTO getValidityPeriod() {
return validityPeriod;
}
public void setValidityPeriod(ValidityPeriodDTO validityPeriod) {
this.validityPeriod = validityPeriod;
}
}

View file

@ -1,4 +1,4 @@
package de.avatic.lcc.dto.report;
package de.avatic.lcc.dto.generic;
public enum ContainerType {
FEU, TEU, HQ

View file

@ -1,5 +1,5 @@
package de.avatic.lcc.dto.generic;
public enum RouteType {
RAIL, SEA, D2D, ROAD
RAIL, SEA, D2D, ROAD, POST_RUN
}

View file

@ -1,7 +1,7 @@
package de.avatic.lcc.dto.generic;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.model.properties.PropertySetState;
import de.avatic.lcc.model.rates.ValidityPeriodState;
import java.time.LocalDateTime;
@ -15,7 +15,7 @@ public class ValidityPeriodDTO {
@JsonProperty("end_date")
private LocalDateTime endDate;
private PropertySetState state;
private ValidityPeriodState state;
public Integer getId() {
return id;
@ -41,11 +41,11 @@ public class ValidityPeriodDTO {
this.endDate = endDate;
}
public PropertySetState getState() {
public ValidityPeriodState getState() {
return state;
}
public void setState(PropertySetState state) {
public void setState(ValidityPeriodState state) {
this.state = state;
}
}

View file

@ -1,6 +1,7 @@
package de.avatic.lcc.dto.report;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.dto.generic.ContainerType;
public class ReportContainerDTO {

View file

@ -1,14 +1,15 @@
package de.avatic.lcc.model.properties;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.MappedCollection;
import org.springframework.data.relational.core.mapping.Table;
import de.avatic.lcc.model.rates.ValidityPeriodState;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.Set;
/**
* Represents a set of properties with a defined validity period.
* This class includes information about the start and end dates
* as well as the state of the validity period.
*/
public class PropertySet {
private Integer id;
@ -17,38 +18,77 @@ public class PropertySet {
private LocalDateTime endDate;
private PropertySetState state;
private ValidityPeriodState state;
/**
* Gets the unique identifier of the property set.
*
* @return the ID of the property set
*/
public Integer getId() {
return id;
}
/**
* Sets the unique identifier of the property set.
*
* @param id the ID to set
*/
public void setId(Integer id) {
this.id = id;
}
/**
* Gets the start date of the validity period for this property set.
*
* @return the start date of the validity period
*/
public LocalDateTime getStartDate() {
return startDate;
}
/**
* Sets the start date of the validity period for this property set.
*
* @param startDate the start date to set
*/
public void setStartDate(LocalDateTime startDate) {
this.startDate = startDate;
}
/**
* Gets the end date of the validity period for this property set.
*
* @return the end date of the validity period
*/
public LocalDateTime getEndDate() {
return endDate;
}
/**
* Sets the end date of the validity period for this property set.
*
* @param endDate the end date to set
*/
public void setEndDate(LocalDateTime endDate) {
this.endDate = endDate;
}
public PropertySetState getState() {
/**
* Gets the state of the validity period for this property set.
*
* @return the state of the validity period
*/
public ValidityPeriodState getState() {
return state;
}
public void setState(PropertySetState state) {
/**
* Sets the state of the validity period for this property set.
*
* @param state the state of the validity period to set
*/
public void setState(ValidityPeriodState state) {
this.state = state;
}
}

View file

@ -1,5 +0,0 @@
package de.avatic.lcc.model.properties;
public enum PropertySetState {
DRAFT, VALID, INVALID, EXPIRED
}

View file

@ -15,35 +15,29 @@ import java.math.BigDecimal;
@Table(name = "container_rate")
public class ContainerRate {
@Id
private Integer id;
@Column("container_rate_type")
private ContainerRateType type;
@NotNull
@Digits(integer = 15, fraction = 2)
private BigDecimal rateTeu;
@NotNull
@Digits(integer = 15, fraction = 2)
private BigDecimal rateFeu;
@NotNull
@Digits(integer = 15, fraction = 2)
private BigDecimal rateHc;
@Unsigned
@NotNull
private Integer leadTime;
@NotNull
@Column("from_node_id")
private AggregateReference<Node,Integer> fromNode;
private Integer fromNodeId;
@NotNull
@Column("to_node_id")
private AggregateReference<Node,Integer>toNode;
private Integer toNodeId;
private Integer validityPeriodId;
public Integer getId() {
return id;
@ -93,19 +87,27 @@ public class ContainerRate {
this.leadTime = leadTime;
}
public AggregateReference<Node, Integer> getFromNode() {
return fromNode;
public Integer getFromNodeId() {
return fromNodeId;
}
public void setFromNode(AggregateReference<Node, Integer> fromNode) {
this.fromNode = fromNode;
public void setFromNodeId(Integer fromNodeId) {
this.fromNodeId = fromNodeId;
}
public AggregateReference<Node, Integer> getToNode() {
return toNode;
public Integer getToNodeId() {
return toNodeId;
}
public void setToNode(AggregateReference<Node, Integer> toNode) {
this.toNode = toNode;
public void setToNodeId(Integer toNodeId) {
this.toNodeId = toNodeId;
}
public Integer getValidityPeriodId() {
return validityPeriodId;
}
public void setValidityPeriodId(Integer validityPeriodId) {
this.validityPeriodId = validityPeriodId;
}
}

View file

@ -1,59 +0,0 @@
package de.avatic.lcc.model.rates;
import de.avatic.lcc.model.country.Country;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotNull;
import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
@Table(name = "country_matrix_rate")
public class CountryMatrixRate {
@Id
private Integer id;
@Digits(integer = 15, fraction = 2)
private BigDecimal rate;
@NotNull
private AggregateReference<Country, Integer> fromCountry;
@NotNull
private AggregateReference<Country, Integer> toCountry;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public BigDecimal getRate() {
return rate;
}
public void setRate(BigDecimal rate) {
this.rate = rate;
}
public AggregateReference<Country, Integer> getFromCountry() {
return fromCountry;
}
public void setFromCountry(AggregateReference<Country, Integer> fromCountry) {
this.fromCountry = fromCountry;
}
public AggregateReference<Country, Integer> getToCountry() {
return toCountry;
}
public void setToCountry(AggregateReference<Country, Integer> toCountry) {
this.toCountry = toCountry;
}
}

View file

@ -0,0 +1,52 @@
package de.avatic.lcc.model.rates;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
public class MatrixRate {
private Integer id;
@Digits(integer = 15, fraction = 2)
private BigDecimal rate;
@NotNull
private Integer fromCountry;
@NotNull
private Integer toCountry;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public BigDecimal getRate() {
return rate;
}
public void setRate(BigDecimal rate) {
this.rate = rate;
}
public Integer getFromCountry() {
return fromCountry;
}
public void setFromCountry(Integer fromCountry) {
this.fromCountry = fromCountry;
}
public Integer getToCountry() {
return toCountry;
}
public void setToCountry(Integer toCountry) {
this.toCountry = toCountry;
}
}

View file

@ -1,33 +1,49 @@
package de.avatic.lcc.model.rates;
import de.avatic.lcc.model.properties.PropertySetState;
import jakarta.validation.constraints.NotNull;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.MappedCollection;
import org.springframework.data.relational.core.mapping.Table;
import java.time.OffsetDateTime;
import java.util.Set;
import java.time.LocalDateTime;
@Table(name = "validity_period")
public class ValidityPeriod {
@Id
private Integer id;
@NotNull
private OffsetDateTime startDate;
private LocalDateTime startDate;
@NotNull
private OffsetDateTime endDate;
private LocalDateTime endDate;
private PropertySetState state;
private ValidityPeriodState state;
@MappedCollection(idColumn = "validity_period_id")
private Set<ContainerRate> containerRates;
@MappedCollection(idColumn = "validity_period_id")
private Set<CountryMatrixRate> countryMatrixRates;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public LocalDateTime getStartDate() {
return startDate;
}
public void setStartDate(LocalDateTime startDate) {
this.startDate = startDate;
}
public LocalDateTime getEndDate() {
return endDate;
}
public void setEndDate(LocalDateTime endDate) {
this.endDate = endDate;
}
public ValidityPeriodState getState() {
return state;
}
public void setState(ValidityPeriodState state) {
this.state = state;
}
}

View file

@ -0,0 +1,28 @@
package de.avatic.lcc.model.rates;
/**
* Represents the state of a validity period, which indicates the current
* lifecycle or status of a specific period of validity.
*/
public enum ValidityPeriodState {
/**
* The validity period is in a draft state and is not finalized.
*/
DRAFT,
/**
* The validity period is active and currently valid.
*/
VALID,
/**
* The validity period has been invalidated and is no longer valid.
*/
INVALID,
/**
* The validity period has expired and is no longer applicable.
*/
EXPIRED
}

View file

@ -1,4 +0,0 @@
package de.avatic.lcc.repositories;
public class ContainerRateRepository {
}

View file

@ -1,13 +1,21 @@
package de.avatic.lcc.repositories.properties;
import de.avatic.lcc.dto.generic.PropertyDTO;
import de.avatic.lcc.model.rates.ValidityPeriodState;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
* Repository for managing operations related to properties and property sets.
* Provides methods for saving, retrieving, and manipulating property data in the database.
*/
@Repository
public class PropertyRepository {
@ -17,6 +25,14 @@ public class PropertyRepository {
this.jdbcTemplate = jdbcTemplate;
}
/**
* Updates or inserts a property value for a specific property set and mapping ID.
* This method performs an upsert operation to ensure the property value is updated if it exists.
*
* @param setId the ID of the property set to which the property belongs
* @param mappingId the external mapping ID of the property type
* @param value the value to set for the property
*/
@Transactional
public void setProperty(Integer setId, String mappingId, String value) {
var typeId = getTypeIdByMappingId(mappingId);
@ -28,11 +44,23 @@ public class PropertyRepository {
jdbcTemplate.update(query, setId, typeId, value, value);
}
/**
* Retrieves the database ID of a property type based on its external mapping ID.
*
* @param mappingId the external mapping ID of the property type
* @return the ID of the property type in the database
*/
private Integer getTypeIdByMappingId(String mappingId) {
String query = "SELECT id FROM system_property_type WHERE external_mapping_id = ?";
return jdbcTemplate.queryForObject(query, Integer.class, mappingId);
}
/**
* Retrieves a list of all properties, including their draft and valid values,
* along with metadata such as validation rules and data types.
*
* @return a list of {@link PropertyDTO} objects representing the properties
*/
@Transactional
public List<PropertyDTO> listProperties() {
@ -44,25 +72,19 @@ public class PropertyRepository {
LEFT JOIN system_property AS valid ON valid.system_property_type_id = type.id
LEFT JOIN property_set AS draftSet ON draftSet.id = draft.property_set_id
LEFT JOIN property_set AS validSet ON validSet.id = valid.property_set_id
WHERE draftSet.state = 'DRAFT' AND validSet.state = 'VALID'
WHERE draftSet.state = ? AND validSet.state = ?
""";
return jdbcTemplate.query(query, (rs, rowNum) -> {
var dto = new PropertyDTO();
dto.setName(rs.getString("name"));
dto.setDraftValue(rs.getString("draftValue"));
dto.setCurrentValue(rs.getString("validValue"));
dto.setValidationRule(rs.getString("validationRule"));
dto.setExternalMappingId(rs.getString("externalMappingId"));
dto.setRequired(true);
dto.setDataType(rs.getString("dataType"));
return dto;
});
return jdbcTemplate.query(query, new PropertyMapper(), ValidityPeriodState.DRAFT.name(), ValidityPeriodState.VALID.name());
}
/**
* Retrieves properties for a specific property set ID where the state of the set is "EXPIRED."
*
* @param propertySetId the ID of the property set
* @return a list of {@link PropertyDTO} representing the properties of the specified set
*/
public List<PropertyDTO> listPropertiesBySetId(Integer propertySetId) {
String query = """
@ -71,10 +93,15 @@ public class PropertyRepository {
FROM system_property_type AS type
LEFT JOIN system_property AS property ON property.system_property_type_id = type.id
LEFT JOIN property_set AS propertySet ON propertySet.id = property.property_set_id
WHERE propertySet.state = 'EXPIRED' AND propertySet.id = ?
WHERE propertySet.state = ? AND propertySet.id = ?
""";
return jdbcTemplate.query(query, (rs, rowNum) -> {
return jdbcTemplate.query(query, new PropertyMapper(),ValidityPeriodState.EXPIRED.name(), propertySetId);
}
private static class PropertyMapper implements RowMapper<PropertyDTO> {
@Override
public PropertyDTO mapRow(ResultSet rs, int rowNum) throws SQLException {
var dto = new PropertyDTO();
dto.setName(rs.getString("name"));
@ -86,20 +113,26 @@ public class PropertyRepository {
dto.setDataType(rs.getString("dataType"));
return dto;
}, propertySetId);
}
}
/**
* Fills the draft property set with values from a valid property set.
* This method ensures that the draft set contains all properties with their latest valid values.
*
* @param setId the ID of the draft property set to fill
*/
public void fillDraft(Integer setId) {
String query = """
SELECT type.id AS typeId, property.property_value as value FROM country_property_type AS type
LEFT JOIN system_property AS property ON property.system_property_type_id = type.id
LEFT JOIN property_set AS propertySet ON propertySet.id = property.property_set_id WHERE propertySet.state = 'VALID'""";
LEFT JOIN property_set AS propertySet ON propertySet.id = property.property_set_id WHERE propertySet.state = ?""";
jdbcTemplate.query(query, (rs, rowNum) -> {
String insertQuery = "INSERT IGNORE INTO system_property (property_value, system_property_type_id, property_set_id) VALUES (?, ?, ?)";
jdbcTemplate.update(insertQuery, rs.getString("value"), rs.getInt("country_id"), rs.getInt("typeId"), setId);
jdbcTemplate.update(insertQuery, rs.getString("value"), rs.getInt("country_id"), rs.getInt("typeId"), setId, ValidityPeriodState.VALID.name());
return null;
});

View file

@ -2,7 +2,7 @@ package de.avatic.lcc.repositories.properties;
import de.avatic.lcc.model.properties.PropertySet;
import de.avatic.lcc.model.properties.PropertySetState;
import de.avatic.lcc.model.rates.ValidityPeriodState;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
@ -57,11 +57,11 @@ public class PropertySetRepository {
@Transactional
public PropertySet getDraftSet() {
createSet();
return jdbcTemplate.queryForObject("SELECT id, start_date, end_date, state FROM property_set WHERE state = ?", new PropertySetMapper(), PropertySetState.DRAFT.name());
return jdbcTemplate.queryForObject("SELECT id, start_date, end_date, state FROM property_set WHERE state = ?", new PropertySetMapper(), ValidityPeriodState.DRAFT.name());
}
private void createSet() {
jdbcTemplate.update("INSERT INTO property_set (state) SELECT ? WHERE NOT EXISTS (SELECT 1 FROM property_set WHERE state = ?)", PropertySetState.DRAFT.name(), PropertySetState.DRAFT.name());
jdbcTemplate.update("INSERT INTO property_set (state) SELECT ? WHERE NOT EXISTS (SELECT 1 FROM property_set WHERE state = ?)", ValidityPeriodState.DRAFT.name(), ValidityPeriodState.DRAFT.name());
}
/**
@ -70,7 +70,7 @@ public class PropertySetRepository {
* @return The {@link PropertySet} object in the valid state, or null if none exists.
*/
public PropertySet getValidSet() {
return jdbcTemplate.queryForObject("SELECT id, start_date, end_date, state FROM property_set WHERE state = ?", new PropertySetMapper(), PropertySetState.VALID.name());
return jdbcTemplate.queryForObject("SELECT id, start_date, end_date, state FROM property_set WHERE state = ?", new PropertySetMapper(), ValidityPeriodState.VALID.name());
}
@ -82,9 +82,11 @@ public class PropertySetRepository {
final Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis());
/* set current to expired */
jdbcTemplate.update("UPDATE property_set SET state = ?, end_date = ? WHERE state = ? ", PropertySetState.EXPIRED.name(), currentTimestamp, PropertySetState.VALID.name());
jdbcTemplate.update("UPDATE property_set SET state = ?, start_date = ? WHERE id = ? AND state = ? ", PropertySetState.VALID.name(), currentTimestamp, PropertySetState.DRAFT.name());
jdbcTemplate.update("UPDATE property_set SET state = ?, end_date = ? WHERE state = ? ", ValidityPeriodState.EXPIRED.name(), currentTimestamp, ValidityPeriodState.VALID.name());
jdbcTemplate.update("UPDATE property_set SET state = ?, start_date = ? WHERE id = ? AND state = ? ", ValidityPeriodState.VALID.name(), currentTimestamp, ValidityPeriodState.DRAFT.name());
/* create a new draft */
createSet();
}
/**
@ -94,7 +96,7 @@ public class PropertySetRepository {
*/
@Transactional
public void invalidateById(Integer id) {
jdbcTemplate.update("UPDATE property_set SET state = ? WHERE id = ? AND state = ? ", PropertySetState.INVALID.name(), id, PropertySetState.EXPIRED.name());
jdbcTemplate.update("UPDATE property_set SET state = ? WHERE id = ? AND state = ? ", ValidityPeriodState.INVALID.name(), id, ValidityPeriodState.EXPIRED.name());
}
/**

View file

@ -0,0 +1,54 @@
package de.avatic.lcc.repositories.rates;
import de.avatic.lcc.model.rates.ContainerRate;
import de.avatic.lcc.model.rates.ContainerRateType;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
@Repository
public class ContainerRateRepository {
private final JdbcTemplate jdbcTemplate;
public ContainerRateRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public SearchQueryResult<ContainerRate> listRatesByPeriodId(SearchQueryPagination pagination, Integer periodId) {
String query = "SELECT * FROM container_rate WHERE validity_period_id = ? ORDER BY id LIMIT ? OFFSET ?";
String countQuery = "SELECT COUNT(*) FROM container_rate WHERE validity_period_id = ?";
Integer totalCount = jdbcTemplate.queryForObject(countQuery, Integer.class, periodId);
return new SearchQueryResult<>(jdbcTemplate.query(query, new ContainerRateMapper(), periodId, pagination.getLimit(), pagination.getOffset()), pagination.getPage(), totalCount, pagination.getLimit());
}
public ContainerRate getById(Integer id) {
String query = "SELECT * FROM container_rate WHERE id = ?";
return jdbcTemplate.queryForObject(query, new ContainerRateMapper(), id);
}
private static class ContainerRateMapper implements RowMapper<ContainerRate> {
@Override
public ContainerRate mapRow(ResultSet rs, int rowNum) throws SQLException {
var entity = new ContainerRate();
entity.setId(rs.getInt("id"));
entity.setValidityPeriodId(rs.getInt("validity_period_id"));
entity.setFromNodeId(rs.getInt("from_node_id"));
entity.setToNodeId(rs.getInt("to_node_id"));
entity.setType(ContainerRateType.valueOf(rs.getString("type")));
entity.setLeadTime(rs.getInt("lead_time"));
entity.setRateFeu(rs.getBigDecimal("rate_feu"));
entity.setRateTeu(rs.getBigDecimal("rate_teu"));
entity.setRateHc(rs.getBigDecimal("rate_hc"));
return entity;
}
}
}

View file

@ -0,0 +1,99 @@
package de.avatic.lcc.repositories.rates;
import de.avatic.lcc.dto.configuration.matrixrates.MatrixRateDTO;
import de.avatic.lcc.model.rates.MatrixRate;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Repository for managing {@link MatrixRate} entities, including retrieval and mapping of MatrixRate rows
* from the database.
*/
@Repository
public class MatrixRateRepository {
private final JdbcTemplate jdbcTemplate;
/**
* Instantiates the repository by injecting a {@link JdbcTemplate}.
*
* @param jdbcTemplate the {@link JdbcTemplate} to be used for database interactions
*/
public MatrixRateRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* Retrieves a paginated list of all {@link MatrixRate} entries from the database.
*
* @param pagination the {@link SearchQueryPagination} object containing limit, offset, and page details
* @return a {@link SearchQueryResult} containing a list of {@link MatrixRate} entities, total count,
* and pagination details
*/
@Transactional
public SearchQueryResult<MatrixRate> listRates(SearchQueryPagination pagination) {
String query = "SELECT * FROM country_matrix_rate ORDER BY id LIMIT ? OFFSET ?";
var totalCount = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM country_matrix_rate", Integer.class);
return new SearchQueryResult<>(jdbcTemplate.query(query, new MatrixRateMapper(), pagination.getLimit(), pagination.getOffset()), pagination.getPage(), totalCount, pagination.getLimit());
}
/**
* Retrieves a paginated list of {@link MatrixRate} entries filtered by a specific validity period ID.
*
* @param pagination the {@link SearchQueryPagination} object containing limit, offset, and page details
* @param periodId the ID of the validity period to filter the rates by
* @return a {@link SearchQueryResult} containing a list of filtered {@link MatrixRate} entities,
* total count, and pagination details
*/
@Transactional
public SearchQueryResult<MatrixRate> listRatesByPeriodId(SearchQueryPagination pagination, Integer periodId) {
String query = "SELECT * FROM country_matrix_rate WHERE validity_period_id = ? ORDER BY id LIMIT ? OFFSET ?";
var totalCount = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM country_matrix_rate WHERE validity_period_id = ?", Integer.class);
return new SearchQueryResult<>(jdbcTemplate.query(query, new MatrixRateMapper(), periodId, pagination.getLimit(), pagination.getOffset()), pagination.getPage(), totalCount, pagination.getLimit());
}
/**
* Retrieves a {@link MatrixRate} entity from the database by its unique identifier.
*
* @param id the unique identifier of the {@link MatrixRate} entity to retrieve
* @return the {@link MatrixRate} entity associated with the specified ID
*/
@Transactional
public MatrixRate getById(Integer id) {
String query = "SELECT * FROM country_matrix_rate WHERE id = ?";
return jdbcTemplate.queryForObject(query, new MatrixRateMapper(), id);
}
/**
* Maps rows of a {@link ResultSet} to {@link MatrixRate} objects as required by
* the {@link JdbcTemplate}.
*/
private static class MatrixRateMapper implements RowMapper<MatrixRate> {
/**
* Maps a single row from the {@link ResultSet} to a {@link MatrixRate} entity.
*
* @param rs the {@link ResultSet} containing rows from the database
* @param rowNum the index of the current row
* @return the mapped {@link MatrixRate} entity
* @throws SQLException if an SQL exception occurs while accessing the {@link ResultSet}
*/
@Override
public MatrixRate mapRow(ResultSet rs, int rowNum) throws SQLException {
MatrixRate entity = new MatrixRate();
entity.setId(rs.getInt("id"));
entity.setRate(rs.getBigDecimal("rate"));
entity.setFromCountry(rs.getInt("from_country"));
entity.setToCountry(rs.getInt("to_country"));
return entity;
}
}
}

View file

@ -0,0 +1,181 @@
package de.avatic.lcc.repositories.rates;
import de.avatic.lcc.model.rates.ValidityPeriod;
import de.avatic.lcc.model.rates.ValidityPeriodState;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
/**
* Repository for managing {@link ValidityPeriod} entities.
* Provides methods to retrieve and update validity periods in the database.
*/
@Repository
public class ValidityPeriodRepository {
/**
* The {@link JdbcTemplate} used for interacting with the database.
*/
private final JdbcTemplate jdbcTemplate;
/**
* Constructs a new repository with a given {@link JdbcTemplate}.
*
* @param jdbcTemplate the {@link JdbcTemplate} used for executing SQL queries.
*/
public ValidityPeriodRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* Retrieves all validity periods from the database.
*
* @return a list of {@link ValidityPeriod} objects representing all validity periods.
*/
@Transactional
public List<ValidityPeriod> listPeriods() {
String query = "SELECT * FROM validity_period";
return jdbcTemplate.query(query, new ValidityPeriodMapper());
}
/**
* Finds the ID of the validity period that includes the specified timestamp.
*
* @param validAt the timestamp to check against validity periods.
* @return an {@link Optional} containing the ID if a validity period is found, otherwise empty.
*/
@Transactional
public Optional<Integer> getPeriodId(LocalDateTime validAt) {
String query = "SELECT id FROM validity_period WHERE ? BETWEEN start_date AND end_date";
return Optional.ofNullable(jdbcTemplate.query(query, (rs) -> rs.next() ? rs.getInt("id") : null, validAt));
}
/**
* Sets the state of a validity period to {@code INVALID} for the specified ID
* if its current state is {@code EXPIRED}.
*
* @param id the ID of the validity period to invalidate.
*/
@Transactional
public void invalidateById(Integer id) {
jdbcTemplate.update("UPDATE validity_period SET state = ? WHERE id = ? AND state = ? ", ValidityPeriodState.INVALID.name(), id, ValidityPeriodState.EXPIRED.name());
}
/**
* Retrieves a {@link ValidityPeriod} by its ID.
*
* @param id the unique identifier of the validity period.
* @return the {@link ValidityPeriod} corresponding to the ID.
*/
public ValidityPeriod getById(Integer id) {
String query = "SELECT * FROM validity_period WHERE id = ?";
return jdbcTemplate.queryForObject(query, new ValidityPeriodMapper(), id);
}
/**
* Creates a draft validity period if none exists in the database.
*/
private void createSet() {
jdbcTemplate.update("INSERT INTO validity_period (state) SELECT ? WHERE NOT EXISTS (SELECT 1 FROM validity_period WHERE state = ?)", ValidityPeriodState.DRAFT.name(), ValidityPeriodState.DRAFT.name());
}
/**
* Retrieves the ID of the validity period currently in the {@code VALID} state.
*
* @return the ID of the valid {@link ValidityPeriod}.
*/
public Integer getValidPeriodId() {
return getValidPeriod().getId();
}
/**
* Retrieves the validity period currently in the {@code VALID} state.
*
* @return the {@link ValidityPeriod} in the {@code VALID} state.
*/
public ValidityPeriod getValidPeriod() {
String query = "SELECT * FROM validity_period WHERE state = ?";
return jdbcTemplate.queryForObject(query, new ValidityPeriodMapper(), ValidityPeriodState.VALID.name());
}
/**
* Retrieves the validity period currently in the {@code DRAFT} state.
*
* @return the {@link ValidityPeriod} in the {@code DRAFT} state.
*/
public ValidityPeriod getDraftPeriod() {
String query = "SELECT * FROM validity_period WHERE state = ?";
return jdbcTemplate.queryForObject(query, new ValidityPeriodMapper(), ValidityPeriodState.DRAFT.name());
}
/**
* Retrieves the ID of the validity period currently in the {@code DRAFT} state.
*
* @return the ID of the draft {@link ValidityPeriod}.
*/
public Integer getDraftPeriodId() {
return getDraftPeriod().getId();
}
/**
* Checks if there are any draft matrix rates associated with the current draft validity period.
*
* @return {@code true} if draft matrix rates exist for the current draft validity period;
* {@code false} otherwise.
*/
@Transactional
public boolean hasRateDrafts() {
Integer id = getDraftPeriodId();
if(id == null) return false;
String query = "SELECT COUNT(*) FROM country_matrix_rate WHERE validity_period_id = ?";
var totalCount = jdbcTemplate.queryForObject(query, Integer.class, id);
return totalCount != null && totalCount > 0;
}
/**
* Applies the draft validity period, making it the new valid period.
* The current valid period is marked as expired, and timestamps are adjusted accordingly.
*/
@Transactional
public void applyDraft() {
if (!hasRateDrafts()) return;
final Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis());
/* set current to expired */
jdbcTemplate.update("UPDATE validity_period SET state = ?, end_date = ? WHERE state = ? ", ValidityPeriodState.EXPIRED.name(), currentTimestamp, ValidityPeriodState.VALID.name());
jdbcTemplate.update("UPDATE validity_period SET state = ?, start_date = ? WHERE id = ? AND state = ? ", ValidityPeriodState.VALID.name(), currentTimestamp, ValidityPeriodState.DRAFT.name());
}
/**
* Maps rows of a {@link ResultSet} to {@link ValidityPeriod} objects.
*/
private static class ValidityPeriodMapper implements RowMapper<ValidityPeriod> {
@Override
public ValidityPeriod mapRow(ResultSet rs, int rowNum) throws SQLException {
var period = new ValidityPeriod();
period.setId(rs.getInt("id"));
period.setStartDate(rs.getTimestamp("start_date").toLocalDateTime());
period.setEndDate(rs.getTimestamp("end_date").toLocalDateTime());
period.setState(ValidityPeriodState.valueOf(rs.getString("state")));
return period;
}
}
}

View file

@ -0,0 +1,10 @@
package de.avatic.lcc.service.calculation;
import org.springframework.stereotype.Service;
@Service
public class CustomApiService {
public Number getTariffRate(String hsCode, Integer countryId) {
return null;
}
}

View file

@ -1,28 +1,124 @@
package de.avatic.lcc.service.configuration;
import de.avatic.lcc.dto.configuration.rates.ContainerRateDTO;
import de.avatic.lcc.dto.generic.ContainerType;
import de.avatic.lcc.dto.generic.RouteType;
import de.avatic.lcc.model.rates.ContainerRate;
import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.repositories.rates.ContainerRateRepository;
import de.avatic.lcc.repositories.rates.ValidityPeriodRepository;
import de.avatic.lcc.service.transformer.generic.NodeTransformer;
import de.avatic.lcc.service.transformer.rates.ValidityPeriodTransformer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Optional;
/**
* Service class for managing container rates, including retrieval, listing, and
* transformation of container rate data objects. Provides methods to interact with
* repositories and handle business logic for container rates.
*/
@Service
public class ContainerRateService {
private final ValidityPeriodRepository validityPeriodRepository;
private final ContainerRateRepository containerRateRepository;
private final ValidityPeriodTransformer validityPeriodTransformer;
private final NodeTransformer nodeTransformer;
private final NodeRepository nodeRepository;
public SearchQueryResult<ContainerRateDTO> listContainerRates(int limit, int page, LocalDateTime validAt) {
return null;
public ContainerRateService(ValidityPeriodRepository validityPeriodRepository, ContainerRateRepository containerRateRepository, ValidityPeriodTransformer validityPeriodTransformer, NodeTransformer nodeTransformer, NodeRepository nodeRepository) {
this.validityPeriodRepository = validityPeriodRepository;
this.containerRateRepository = containerRateRepository;
this.validityPeriodTransformer = validityPeriodTransformer;
this.nodeTransformer = nodeTransformer;
this.nodeRepository = nodeRepository;
}
public SearchQueryResult<ContainerRateDTO> listContainerRates(int limit, int page, Integer valid) {
return null;
/**
* Retrieves a paginated list of container rates filtered by the specified validity date.
*
* @param limit the maximum number of results to retrieve per page
* @param page the current page number to retrieve
* @param validAt the date for which to find the validity period
* @return a {@link SearchQueryResult} containing container rate DTOs with pagination information
*/
@Transactional
public SearchQueryResult<ContainerRateDTO> listRates(int limit, int page, LocalDateTime validAt) {
Optional<Integer> periodId = validityPeriodRepository.getPeriodId(validAt);
return listRates(limit, page, periodId.orElseThrow());
}
public SearchQueryResult<ContainerRateDTO> listContainerRates(int limit, int page) {
return null;
/**
* Retrieves a paginated list of container rates filtered by a specific validity period ID.
*
* @param limit the maximum number of results to retrieve per page
* @param page the current page number to retrieve
* @param periodId the ID of the validity period to filter the rates by
* @return a {@link SearchQueryResult} containing container rate DTOs with pagination information
*/
@Transactional
public SearchQueryResult<ContainerRateDTO> listRates(int limit, int page, Integer periodId) {
if(null == periodId)
return listRates(limit, page);
return SearchQueryResult.map(containerRateRepository.listRatesByPeriodId(new SearchQueryPagination(limit, page), periodId), this::toContainerRateDTO);
}
/**
* Retrieves a paginated list of all container rates without applying a specific filter.
* It retrieves data for the currently valid validity period.
*
* @param limit the maximum number of results to retrieve per page
* @param page the current page number to retrieve
* @return a {@link SearchQueryResult} containing container rate DTOs with pagination information
*/
@Transactional
public SearchQueryResult<ContainerRateDTO> listRates(int limit, int page) {
Integer id = validityPeriodRepository.getValidPeriodId();
return SearchQueryResult.map(containerRateRepository.listRatesByPeriodId(new SearchQueryPagination(limit, page), id), this::toContainerRateDTO);
}
/**
* Retrieves a container rate by its unique identifier.
*
* @param id the unique identifier of the container rate
* @return a {@link ContainerRateDTO} containing the container rate details
*/
@Transactional
public ContainerRateDTO getContainerRate(Integer id) {
return null;
return toContainerRateDTO(containerRateRepository.getById(id));
}
/**
* Transforms a {@link ContainerRate} entity into a {@link ContainerRateDTO}.
*
* @param entity the {@link ContainerRate} entity to transform
* @return a {@link ContainerRateDTO} containing the transformed data
*/
private ContainerRateDTO toContainerRateDTO(ContainerRate entity) {
ContainerRateDTO dto = new ContainerRateDTO();
dto.setId(entity.getId());
dto.setLeadTime(entity.getLeadTime());
dto.setType(RouteType.valueOf(entity.getType().name()));
dto.setValidityPeriod(validityPeriodTransformer.toValidityPeriodDTO(validityPeriodRepository.getById(entity.getValidityPeriodId())));
dto.setLeadTime(entity.getLeadTime());
dto.setOrigin(nodeTransformer.toNodeDTO(nodeRepository.getById(entity.getFromNodeId()).orElseThrow()));
dto.setDestination(nodeTransformer.toNodeDTO(nodeRepository.getById(entity.getToNodeId()).orElseThrow()));
var rates = new HashMap<String, Number>();
rates.put(ContainerType.HQ.name(), entity.getRateHc());
rates.put(ContainerType.FEU.name(), entity.getRateFeu());
rates.put(ContainerType.TEU.name(), entity.getRateTeu());
dto.setRates(rates);
return dto;
}
}

View file

@ -1,24 +1,108 @@
package de.avatic.lcc.service.configuration;
import de.avatic.lcc.dto.configuration.matrixrates.MatrixRateDTO;
import de.avatic.lcc.dto.configuration.rates.ContainerRateDTO;
import de.avatic.lcc.model.rates.MatrixRate;
import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.repositories.rates.MatrixRateRepository;
import de.avatic.lcc.repositories.rates.ValidityPeriodRepository;
import de.avatic.lcc.service.transformer.generic.NodeTransformer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Optional;
/**
* Service class for managing matrix rates including retrieval, listing, and transformations
* of matrix rate data objects. Provides methods to interact with repositories and handle
* business logic for matrix rates.
*/
@Service
public class MatrixRateService {
private final ValidityPeriodRepository validityPeriodRepository;
private final MatrixRateRepository matrixRateRepository;
private final NodeRepository nodeRepository;
private final NodeTransformer nodeTransformer;
public MatrixRateService(ValidityPeriodRepository validityPeriodRepository, MatrixRateRepository matrixRateRepository, NodeRepository nodeRepository, NodeTransformer nodeTransformer) {
this.validityPeriodRepository = validityPeriodRepository;
this.matrixRateRepository = matrixRateRepository;
this.nodeRepository = nodeRepository;
this.nodeTransformer = nodeTransformer;
}
/**
* Retrieves a paginated list of matrix rates filtered by the specified validity date.
*
* @param limit the maximum number of results to retrieve per page
* @param page the current page number to retrieve
* @param validAt the date for which to find the validity period
* @return a {@link SearchQueryResult} containing matrix rate DTOs with pagination information
*/
@Transactional
public SearchQueryResult<MatrixRateDTO> listRates(int limit, int page, LocalDateTime validAt) {
Optional<Integer> periodId = validityPeriodRepository.getPeriodId(validAt);
return listRates(limit, page, periodId.orElseThrow());
}
public SearchQueryResult<MatrixRateDTO> listRates(int limit, int page, Integer valid) {
/**
* Retrieves a paginated list of matrix rates filtered by a specific validity period ID.
*
* @param limit the maximum number of results to retrieve per page
* @param page the current page number to retrieve
* @param periodId the ID of the validity period to filter the rates by
* @return a {@link SearchQueryResult} containing matrix rate DTOs with pagination information
*/
@Transactional
public SearchQueryResult<MatrixRateDTO> listRates(int limit, int page, Integer periodId) {
if (null == periodId)
return listRates(limit, page);
return SearchQueryResult.map(matrixRateRepository.listRatesByPeriodId(new SearchQueryPagination(limit, page), periodId), this::toMatrixRateDTO);
}
/**
* Retrieves a paginated list of all matrix rates without applying filtering criteria.
* It returns the data of the currently valid validity period.
* @param limit the maximum number of results to retrieve per page
* @param page the current page number to retrieve
* @return a {@link SearchQueryResult} containing matrix rate DTOs with pagination information
*/
@Transactional
public SearchQueryResult<MatrixRateDTO> listRates(int limit, int page) {
Integer id = validityPeriodRepository.getValidPeriodId();
return SearchQueryResult.map(matrixRateRepository.listRatesByPeriodId(new SearchQueryPagination(limit, page), id), this::toMatrixRateDTO);
}
/**
* Retrieves a matrix rate by its unique identifier.
*
* @param id the unique identifier of the matrix rate
* @return a {@link MatrixRateDTO} containing the matrix rate details
*/
@Transactional
public MatrixRateDTO getRate(Integer id) {
return null;
return toMatrixRateDTO(matrixRateRepository.getById(id));
}
/**
* Transforms a {@link MatrixRate} entity into a {@link MatrixRateDTO}.
*
* @param entity the {@link MatrixRate} entity to transform
* @return a {@link MatrixRateDTO} containing the transformed data
*/
private MatrixRateDTO toMatrixRateDTO(MatrixRate entity) {
MatrixRateDTO dto = new MatrixRateDTO();
dto.setId(entity.getId());
dto.setOrigin(nodeTransformer.toNodeDTO(nodeRepository.getById(entity.getFromCountry()).orElseThrow()));
dto.setDestination(nodeTransformer.toNodeDTO(nodeRepository.getById(entity.getToCountry()).orElseThrow()));
dto.setRate(entity.getRate());
return dto;
}
}

View file

@ -12,7 +12,7 @@ import org.springframework.transaction.annotation.Transactional;
* when necessary.
*/
@Service
public class PropertyStagedChangesService {
public class PropertyApprovalService {
private final PropertySetRepository propertySetRepository;
private final PropertyRepository propertyRepository;
private final CountryPropertyRepository countryPropertyRepository;
@ -25,7 +25,7 @@ public class PropertyStagedChangesService {
* @param propertyRepository the repository for managing properties
* @param countryPropertyRepository the repository for managing country-specific properties
*/
public PropertyStagedChangesService(PropertySetRepository propertySetRepository, PropertyRepository propertyRepository, CountryPropertyRepository countryPropertyRepository) {
public PropertyApprovalService(PropertySetRepository propertySetRepository, PropertyRepository propertyRepository, CountryPropertyRepository countryPropertyRepository) {
this.propertySetRepository = propertySetRepository;
this.propertyRepository = propertyRepository;
this.countryPropertyRepository = countryPropertyRepository;

View file

@ -4,6 +4,7 @@ import de.avatic.lcc.dto.generic.ValidityPeriodDTO;
import de.avatic.lcc.dto.generic.PropertyDTO;
import de.avatic.lcc.repositories.properties.PropertyRepository;
import de.avatic.lcc.repositories.properties.PropertySetRepository;
import de.avatic.lcc.service.transformer.rates.ValidityPeriodTransformer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -14,6 +15,7 @@ public class PropertyService {
private final PropertyRepository propertyRepository;
private final PropertySetRepository propertySetRepository;
private final ValidityPeriodTransformer validityPeriodTransformer;
/**
@ -22,9 +24,10 @@ public class PropertyService {
* @param propertyRepository the repository to manage properties
* @param propertySetRepository the repository to manage property sets
*/
public PropertyService(PropertyRepository propertyRepository, PropertySetRepository propertySetRepository) {
public PropertyService(PropertyRepository propertyRepository, PropertySetRepository propertySetRepository, ValidityPeriodTransformer validityPeriodTransformer) {
this.propertyRepository = propertyRepository;
this.propertySetRepository = propertySetRepository;
this.validityPeriodTransformer = validityPeriodTransformer;
}
/**
@ -43,7 +46,8 @@ public class PropertyService {
/**
* Retrieves a list of properties. If a specific property set ID is provided, only
* properties from that set are returned. Otherwise, all properties are returned.
* properties from that set are returned. Otherwise, the properties from the current
* valid set and current draft set are returned.
*
* @param propertySetId the ID of the property set (0 for all properties)
* @return a list of properties as {@link PropertyDTO}
@ -61,16 +65,7 @@ public class PropertyService {
* @return a list of property sets as {@link ValidityPeriodDTO}
*/
public List<ValidityPeriodDTO> listPropertySets() {
return propertySetRepository.listPropertySets().stream().map(propertySet -> {
ValidityPeriodDTO dto = new ValidityPeriodDTO();
dto.setId(propertySet.getId());
dto.setEndDate(propertySet.getEndDate());
dto.setStartDate(propertySet.getStartDate());
dto.setState(propertySet.getState());
return dto;
}).toList();
return propertySetRepository.listPropertySets().stream().map(validityPeriodTransformer::toValidityPeriodDTO).toList();
}
/**

View file

@ -0,0 +1,38 @@
package de.avatic.lcc.service.configuration;
import de.avatic.lcc.repositories.rates.MatrixRateRepository;
import de.avatic.lcc.repositories.rates.ValidityPeriodRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* A service class responsible for approving or verifying rate drafts.
* Provides functionalities to check for unapproved rate drafts and
* apply these drafts when necessary.
*/
@Service
public class RateApprovalService {
private final ValidityPeriodRepository validityPeriodRepository;
public RateApprovalService(ValidityPeriodRepository validityPeriodRepository) {
this.validityPeriodRepository = validityPeriodRepository;
}
/**
* Checks if there are any staged (draft) rates that have not yet been approved.
*
* @return {@code true} if rate drafts exist, {@code false} otherwise.
*/
public boolean hasRateDrafts() {
return validityPeriodRepository.hasRateDrafts();
}
/**
* Approves and applies all staged (draft) rates.
*/
public void approveRateDrafts() {
validityPeriodRepository.applyDraft();
}
}

View file

@ -0,0 +1,28 @@
package de.avatic.lcc.service.configuration;
import de.avatic.lcc.dto.generic.ValidityPeriodDTO;
import de.avatic.lcc.repositories.rates.ValidityPeriodRepository;
import de.avatic.lcc.service.transformer.rates.ValidityPeriodTransformer;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ValidityPeriodService {
private final ValidityPeriodRepository validityPeriodRepository;
private final ValidityPeriodTransformer validityPeriodTransformer;
public ValidityPeriodService(ValidityPeriodRepository validityPeriodRepository, ValidityPeriodTransformer validityPeriodTransformer) {
this.validityPeriodRepository = validityPeriodRepository;
this.validityPeriodTransformer = validityPeriodTransformer;
}
public List<ValidityPeriodDTO> listPeriods() {
return validityPeriodRepository.listPeriods().stream().map(validityPeriodTransformer::toValidityPeriodDTO).toList();
}
public void invalidate(Integer id) {
validityPeriodRepository.invalidateById(id);
}
}

View file

@ -0,0 +1,34 @@
package de.avatic.lcc.service.transformer.rates;
import de.avatic.lcc.dto.generic.ValidityPeriodDTO;
import de.avatic.lcc.model.properties.PropertySet;
import de.avatic.lcc.model.rates.ValidityPeriod;
import org.springframework.stereotype.Service;
@Service
public class ValidityPeriodTransformer {
public ValidityPeriodDTO toValidityPeriodDTO(ValidityPeriod entity) {
ValidityPeriodDTO dto = new ValidityPeriodDTO();
dto.setId(entity.getId());
dto.setEndDate(entity.getEndDate());
dto.setStartDate(entity.getStartDate());
dto.setState(entity.getState());
return dto;
}
public ValidityPeriodDTO toValidityPeriodDTO(PropertySet entity) {
ValidityPeriodDTO dto = new ValidityPeriodDTO();
dto.setId(entity.getId());
dto.setEndDate(entity.getEndDate());
dto.setStartDate(entity.getStartDate());
dto.setState(entity.getState());
return dto;
}
}