Remove packaging-related DTOs and services, add user node functionality

The commit eliminates packaging-related DTOs, services, and transformers that are no longer in use. It introduces functionality to support user node management, including repository methods, new DTOs, and a GeoApiService placeholder. Adjustments were also made to schema constraints and node transformations.
This commit is contained in:
Jan 2025-04-12 16:22:02 +02:00
parent 7eb5667d32
commit 298504384f
50 changed files with 876 additions and 776 deletions

View file

@ -76,6 +76,8 @@ public class CountryController {
* Retrieves detailed information about a specific country based on its ID. * Retrieves detailed information about a specific country based on its ID.
* *
* @param id the identifier of the country to retrieve * @param id the identifier of the country to retrieve
* @param propertySetId an optional query parameter indicating the property set to use for retrieving country properties;
* defaults to 0, which retrieves properties from the current set
* @return a {@link ResponseEntity} containing a {@link CountryDetailDTO} with the country's details * @return a {@link ResponseEntity} containing a {@link CountryDetailDTO} with the country's details
*/ */
@GetMapping("/{id}") @GetMapping("/{id}")

View file

@ -1,6 +1,6 @@
package de.avatic.lcc.controller.configuration; package de.avatic.lcc.controller.configuration;
import de.avatic.lcc.dto.configuration.material.view.MaterialViewDTO; import de.avatic.lcc.dto.configuration.material.view.MaterialDetailDTO;
import de.avatic.lcc.dto.configuration.material.update.MaterialUpdateDTO; import de.avatic.lcc.dto.configuration.material.update.MaterialUpdateDTO;
import de.avatic.lcc.dto.generic.MaterialDTO; import de.avatic.lcc.dto.generic.MaterialDTO;
import de.avatic.lcc.repositories.pagination.SearchQueryResult; import de.avatic.lcc.repositories.pagination.SearchQueryResult;
@ -56,39 +56,7 @@ public class MaterialController {
* @throws RuntimeException if the material with the given ID is not found. * @throws RuntimeException if the material with the given ID is not found.
*/ */
@GetMapping("/{id}") @GetMapping("/{id}")
public ResponseEntity<MaterialViewDTO> getMaterialDetails(@PathVariable Integer id) { public ResponseEntity<MaterialDetailDTO> getMaterialDetails(@PathVariable Integer id) {
return ResponseEntity.ok(materialService.getMaterial(id)); return ResponseEntity.ok(materialService.getMaterial(id));
} }
/**
* Update a material with the specified ID.
*
* @param id Material ID to update
* @param material The updated material details
* @return The updated material
*/
@PutMapping("/{id}")
public ResponseEntity<Integer> updateMaterial(
@PathVariable Integer id,
@RequestBody MaterialUpdateDTO material) {
Check.equals(id, material.getId());
return ResponseEntity.ok(materialService.updateMaterial(id, material));
}
/**
* Soft delete a material by marking it as deprecated.
*
* @param id Material ID
* @return Empty response with status 204 No Content
* @throws RuntimeException if the material with the given ID cannot be found or deleted.
*/
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteMaterial(@PathVariable Integer id) {
ResponseEntity.ok(materialService.deleteMaterial(id));
}
@PostMapping("/")
public ResponseEntity<Integer> createMaterial(@RequestBody MaterialUpdateDTO material) {
return ResponseEntity.ok(materialService.createMaterial(material));
}
} }

View file

@ -1,9 +1,15 @@
package de.avatic.lcc.controller.configuration; package de.avatic.lcc.controller.configuration;
import de.avatic.lcc.dto.configuration.nodes.userNodes.LocateNodeDTO;
import de.avatic.lcc.dto.generic.LocationDTO;
import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.configuration.nodes.view.NodeDetailDTO; import de.avatic.lcc.dto.configuration.nodes.view.NodeDetailDTO;
import de.avatic.lcc.dto.configuration.nodes.update.NodeUpdateDTO; import de.avatic.lcc.dto.configuration.nodes.update.NodeUpdateDTO;
import de.avatic.lcc.dto.generic.NodeType;
import de.avatic.lcc.dto.configuration.nodes.userNodes.AddUserNodeDTO;
import de.avatic.lcc.repositories.pagination.SearchQueryResult; import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.repositories.users.UserNodeRepository;
import de.avatic.lcc.service.GeoApiService;
import de.avatic.lcc.service.configuration.NodeService; import de.avatic.lcc.service.configuration.NodeService;
import de.avatic.lcc.util.Check; import de.avatic.lcc.util.Check;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -15,24 +21,32 @@ import java.util.List;
@RequestMapping("/api/nodes") @RequestMapping("/api/nodes")
public class NodeController { public class NodeController {
private final NodeService nodeService; private final NodeService nodeService;
private final GeoApiService geoApiService;
private final UserNodeRepository userNodeRepository;
public NodeController(NodeService nodeService) { public NodeController(NodeService nodeService, GeoApiService geoApiService, UserNodeRepository userNodeRepository) {
this.nodeService = nodeService; this.nodeService = nodeService;
this.geoApiService = geoApiService;
this.userNodeRepository = userNodeRepository;
} }
@GetMapping("/") @GetMapping("/")
public ResponseEntity<List<NodeDTO>> listNodes(@RequestParam(required = false) String filter, @RequestParam(required = false) int page, @RequestParam(required = false) int limit) { public ResponseEntity<List<NodeDTO>> listNodes(@RequestParam(required = false) String filter, @RequestParam(required = false) int page, @RequestParam(required = false) int limit) {
nodeService.listNodes(filter, page, limit); nodeService.listNodes(filter, page, limit);
SearchQueryResult<NodeDTO> countries = nodeService.listNodes(filter, page, limit); SearchQueryResult<NodeDTO> nodes = nodeService.listNodes(filter, page, limit);
return ResponseEntity.ok() return ResponseEntity.ok()
.header("X-Total-Count", String.valueOf(countries.getTotalElements())) .header("X-Total-Count", String.valueOf(nodes.getTotalElements()))
.header("X-Page-Count", String.valueOf(countries.getTotalPages())) .header("X-Page-Count", String.valueOf(nodes.getTotalPages()))
.header("X-Current-Page", String.valueOf(page)) .header("X-Current-Page", String.valueOf(page))
.body(countries.toList()); .body(nodes.toList());
}
@GetMapping("/search")
public ResponseEntity<List<NodeDTO>> searchNodes(@RequestParam(required = false) String filter, @RequestParam(required = false) int limit, @RequestParam(name = "node_type", required = false) NodeType nodeType, @RequestParam(name = "include_user_node", defaultValue = "false", required = false) boolean includeUserNode) {
return ResponseEntity.ok(nodeService.searchNode(filter, limit, nodeType, includeUserNode));
} }
@GetMapping("/{id}") @GetMapping("/{id}")
@ -50,4 +64,15 @@ public class NodeController {
Check.equals(id, node.getId()); Check.equals(id, node.getId());
return ResponseEntity.ok(nodeService.updateNode(node)); return ResponseEntity.ok(nodeService.updateNode(node));
} }
@GetMapping("/locate")
public ResponseEntity<LocateNodeDTO> locateNode(@RequestParam String address) {
return ResponseEntity.ok(geoApiService.locate(address));
}
@PutMapping("/")
public ResponseEntity<Void> addUserNode(@RequestParam AddUserNodeDTO node) {
nodeService.addUserNode(node);
return ResponseEntity.ok().build();
}
} }

View file

@ -1,12 +1,11 @@
package de.avatic.lcc.controller.configuration; package de.avatic.lcc.controller.configuration;
import de.avatic.lcc.dto.configuration.properties.PropertySetDTO; import de.avatic.lcc.dto.generic.ValidityPeriodDTO;
import de.avatic.lcc.dto.generic.PropertyDTO; import de.avatic.lcc.dto.generic.PropertyDTO;
import de.avatic.lcc.model.country.IsoCode; import de.avatic.lcc.model.country.IsoCode;
import de.avatic.lcc.model.properties.PropertySet;
import de.avatic.lcc.service.configuration.CountryService; import de.avatic.lcc.service.configuration.CountryService;
import de.avatic.lcc.service.configuration.PropertiesService; import de.avatic.lcc.service.configuration.PropertyService;
import de.avatic.lcc.service.configuration.StagedChangesService; import de.avatic.lcc.service.configuration.PropertyStagedChangesService;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -20,19 +19,19 @@ import java.util.List;
@RequestMapping("/properties") @RequestMapping("/properties")
public class PropertyController { public class PropertyController {
private final PropertiesService propertiesService; private final PropertyService propertyService;
private final StagedChangesService stagedChangesService; private final PropertyStagedChangesService propertyStagedChangesService;
private final CountryService countryService; private final CountryService countryService;
/** /**
* Constructs a new PropertyController with the provided services. * Constructs a new PropertyController with the provided services.
* *
* @param propertiesService Service for managing properties. * @param propertyService Service for managing properties.
* @param stagedChangesService Service for managing staged changes. * @param propertyStagedChangesService Service for managing staged changes.
*/ */
public PropertyController(PropertiesService propertiesService, StagedChangesService stagedChangesService, CountryService countryService) { public PropertyController(PropertyService propertyService, PropertyStagedChangesService propertyStagedChangesService, CountryService countryService) {
this.propertiesService = propertiesService; this.propertyService = propertyService;
this.stagedChangesService = stagedChangesService; this.propertyStagedChangesService = propertyStagedChangesService;
this.countryService = countryService; this.countryService = countryService;
} }
@ -43,12 +42,30 @@ public class PropertyController {
*/ */
@GetMapping("/") @GetMapping("/")
public ResponseEntity<List<PropertyDTO>> listProperties(@RequestParam(name = "property_set", defaultValue = "0", required = false) Integer propertySetId) { public ResponseEntity<List<PropertyDTO>> listProperties(@RequestParam(name = "property_set", defaultValue = "0", required = false) Integer propertySetId) {
return ResponseEntity.ok(propertiesService.listProperties(propertySetId)); return ResponseEntity.ok(propertyService.listProperties(propertySetId));
} }
/**
* Retrieves all validity periods of the application properties.
*
* @return ResponseEntity containing the list of ValidityPeriodDTO objects.
*/
@GetMapping("/periods") @GetMapping("/periods")
public ResponseEntity<List<PropertySetDTO>> listPeriods() { public ResponseEntity<List<ValidityPeriodDTO>> listPeriods() {
return ResponseEntity.ok(propertiesService.listPropertySets()); return ResponseEntity.ok(propertyService.listPropertySets());
}
/**
* 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) {
propertyService.invalidate(id);
return ResponseEntity.ok().build();
} }
/** /**
@ -74,7 +91,7 @@ public class PropertyController {
*/ */
@PutMapping("/system/{external_mapping_id}") @PutMapping("/system/{external_mapping_id}")
public ResponseEntity<Void> setProperties(@PathVariable(name = "external_mapping_id") String externalMappingId, @RequestBody String value) { public ResponseEntity<Void> setProperties(@PathVariable(name = "external_mapping_id") String externalMappingId, @RequestBody String value) {
propertiesService.setProperties(externalMappingId, value); propertyService.setProperties(externalMappingId, value);
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@ -85,7 +102,7 @@ public class PropertyController {
*/ */
@GetMapping("/staged_changes") @GetMapping("/staged_changes")
public ResponseEntity<Boolean> checkPropertiesDrafts() { public ResponseEntity<Boolean> checkPropertiesDrafts() {
return ResponseEntity.ok(stagedChangesService.hasPropertiesDraft()); return ResponseEntity.ok(propertyStagedChangesService.hasPropertiesDraft());
} }
/** /**
@ -95,7 +112,7 @@ public class PropertyController {
*/ */
@PutMapping("/staged_changes") @PutMapping("/staged_changes")
public ResponseEntity<Void> approvePropertiesDrafts() { public ResponseEntity<Void> approvePropertiesDrafts() {
stagedChangesService.approvePropertiesDrafts(); propertyStagedChangesService.applyDraft();
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }

View file

@ -5,7 +5,7 @@ import de.avatic.lcc.dto.configuration.rates.ContainerRateDTO;
import de.avatic.lcc.repositories.pagination.SearchQueryResult; import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.service.configuration.ContainerRateService; import de.avatic.lcc.service.configuration.ContainerRateService;
import de.avatic.lcc.service.configuration.MatrixRateService; import de.avatic.lcc.service.configuration.MatrixRateService;
import de.avatic.lcc.service.configuration.StagedChangesService; import de.avatic.lcc.service.configuration.PropertyStagedChangesService;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -19,12 +19,12 @@ public class RateController {
private final MatrixRateService matrixRateService; private final MatrixRateService matrixRateService;
private final ContainerRateService containerRateService; private final ContainerRateService containerRateService;
private final StagedChangesService stagedChangesService; private final PropertyStagedChangesService propertyStagedChangesService;
public RateController(MatrixRateService matrixRateService, ContainerRateService containerRateService, StagedChangesService stagedChangesService) { public RateController(MatrixRateService matrixRateService, ContainerRateService containerRateService, PropertyStagedChangesService propertyStagedChangesService) {
this.matrixRateService = matrixRateService; this.matrixRateService = matrixRateService;
this.containerRateService = containerRateService; this.containerRateService = containerRateService;
this.stagedChangesService = stagedChangesService; this.propertyStagedChangesService = propertyStagedChangesService;
} }
@GetMapping("/container") @GetMapping("/container")
@ -90,12 +90,12 @@ public class RateController {
@GetMapping("/staged_changes") @GetMapping("/staged_changes")
public ResponseEntity<Boolean> checkRateDrafts() { public ResponseEntity<Boolean> checkRateDrafts() {
return ResponseEntity.ok(stagedChangesService.hasRateDrafts()); return ResponseEntity.ok(propertyStagedChangesService.hasRateDrafts());
} }
@PutMapping("/staged_changes") @PutMapping("/staged_changes")
public ResponseEntity<Void> approveRateDrafts() { public ResponseEntity<Void> approveRateDrafts() {
stagedChangesService.approveRateDrafts(); propertyStagedChangesService.approveRateDrafts();
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
} }

View file

@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
public class MaterialViewDTO { public class MaterialDetailDTO {
private Integer id; private Integer id;
@JsonProperty("part_number") @JsonProperty("part_number")
@ -16,14 +16,13 @@ public class MaterialViewDTO {
@JsonProperty("hs_code") @JsonProperty("hs_code")
private String hsCode; private String hsCode;
@JsonProperty("packaging") @JsonProperty("packaging")
private List<MaterialViewPackagingDTO> handlingUnits; private List<MaterialDetailPackagingDTO> handlingUnits;
public MaterialViewDTO() { public MaterialDetailDTO() {
} }
public MaterialViewDTO(Integer id, String partNumber, String name, String hs_code, List<MaterialViewPackagingDTO> handling_units) { public MaterialDetailDTO(Integer id, String partNumber, String name, String hs_code, List<MaterialDetailPackagingDTO> handling_units) {
this.id = id; this.id = id;
this.partNumber = partNumber; this.partNumber = partNumber;
this.name = name; this.name = name;
@ -68,11 +67,11 @@ public class MaterialViewDTO {
} }
@JsonProperty("handling_units") @JsonProperty("handling_units")
public List<MaterialViewPackagingDTO> getHandlingUnits() { public List<MaterialDetailPackagingDTO> getHandlingUnits() {
return handlingUnits; return handlingUnits;
} }
public void setHandlingUnits(List<MaterialViewPackagingDTO> handlingUnits) { public void setHandlingUnits(List<MaterialDetailPackagingDTO> handlingUnits) {
this.handlingUnits = handlingUnits; this.handlingUnits = handlingUnits;
} }
@ -91,7 +90,7 @@ public class MaterialViewDTO {
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
MaterialViewDTO that = (MaterialViewDTO) o; MaterialDetailDTO that = (MaterialDetailDTO) o;
return Objects.equals(id, that.id) && return Objects.equals(id, that.id) &&
Objects.equals(partNumber, that.partNumber) && Objects.equals(partNumber, that.partNumber) &&
Objects.equals(name, that.name) && Objects.equals(name, that.name) &&

View file

@ -3,8 +3,11 @@ package de.avatic.lcc.dto.configuration.material.view;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.dto.generic.DimensionDTO; import de.avatic.lcc.dto.generic.DimensionDTO;
import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.generic.PropertyDTO;
public class MaterialViewPackagingDTO { import java.util.List;
public class MaterialDetailPackagingDTO {
private Integer id; private Integer id;
@ -19,6 +22,16 @@ public class MaterialViewPackagingDTO {
@JsonProperty("small_handling_unit") @JsonProperty("small_handling_unit")
private DimensionDTO shu; private DimensionDTO shu;
private List<PropertyDTO> properties;
public List<PropertyDTO> getProperties() {
return properties;
}
public void setProperties(List<PropertyDTO> properties) {
this.properties = properties;
}
public Integer getId() { public Integer getId() {
return id; return id;
} }

View file

@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.dto.generic.CountryDTO; import de.avatic.lcc.dto.generic.CountryDTO;
import de.avatic.lcc.dto.generic.LocationDTO; import de.avatic.lcc.dto.generic.LocationDTO;
import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.generic.NodeTypeDTO; import de.avatic.lcc.dto.generic.NodeType;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -15,7 +15,7 @@ public class NodeUpdateDTO {
private String name; private String name;
private CountryDTO country; private CountryDTO country;
private String address; private String address;
private List<NodeTypeDTO> types; private List<NodeType> types;
private LocationDTO location; private LocationDTO location;
@JsonProperty("is_deprecated") @JsonProperty("is_deprecated")
private Boolean isDeprecated; private Boolean isDeprecated;

View file

@ -0,0 +1,38 @@
package de.avatic.lcc.dto.configuration.nodes.userNodes;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.dto.generic.LocationDTO;
import de.avatic.lcc.dto.generic.NodeType;
import java.util.List;
public class AddUserNodeDTO {
private String name;
private String address;
private LocationDTO location;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public LocationDTO getLocation() {
return location;
}
public void setLocation(LocationDTO location) {
this.location = location;
}
}

View file

@ -0,0 +1,35 @@
package de.avatic.lcc.dto.configuration.nodes.userNodes;
import de.avatic.lcc.dto.generic.CountryDTO;
import de.avatic.lcc.dto.generic.LocationDTO;
public class LocateNodeDTO {
private String address;
private CountryDTO country;
private LocationDTO location;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public CountryDTO getCountry() {
return country;
}
public void setCountry(CountryDTO country) {
this.country = country;
}
public LocationDTO getLocation() {
return location;
}
public void setLocation(LocationDTO location) {
this.location = location;
}
}

View file

@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.dto.generic.CountryDTO; import de.avatic.lcc.dto.generic.CountryDTO;
import de.avatic.lcc.dto.generic.LocationDTO; import de.avatic.lcc.dto.generic.LocationDTO;
import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.generic.NodeTypeDTO; import de.avatic.lcc.dto.generic.NodeType;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -15,7 +15,7 @@ public class NodeDetailDTO {
private String name; private String name;
private CountryDTO country; private CountryDTO country;
private String address; private String address;
private List<NodeTypeDTO> types; private List<NodeType> types;
private LocationDTO location; private LocationDTO location;
@JsonProperty("is_deprecated") @JsonProperty("is_deprecated")
private Boolean isDeprecated; private Boolean isDeprecated;
@ -56,11 +56,11 @@ public class NodeDetailDTO {
this.address = address; this.address = address;
} }
public List<NodeTypeDTO> getTypes() { public List<NodeType> getTypes() {
return types; return types;
} }
public void setTypes(List<NodeTypeDTO> types) { public void setTypes(List<NodeType> types) {
this.types = types; this.types = types;
} }

View file

@ -1,84 +0,0 @@
package de.avatic.lcc.dto.configuration.packaging.update;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.dto.generic.DimensionDTO;
import java.util.Map;
public class PackagingUpdateDTO {
private Integer id;
@JsonProperty("is_deprecated")
private Boolean isDeprecated;
private Integer supplierId;
private Integer materialId;
@JsonProperty("handling_unit")
private DimensionDTO hu;
@JsonProperty("small_handling_unit")
private DimensionDTO shu;
@JsonProperty("properties")
private Map<String, String> properties;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Boolean getDeprecated() {
return isDeprecated;
}
public void setDeprecated(Boolean deprecated) {
isDeprecated = deprecated;
}
public Integer getSupplierId() {
return supplierId;
}
public void setSupplierId(Integer supplierId) {
this.supplierId = supplierId;
}
public Integer getMaterialId() {
return materialId;
}
public void setMaterialId(Integer materialId) {
this.materialId = materialId;
}
public DimensionDTO getHu() {
return hu;
}
public void setHu(DimensionDTO hu) {
this.hu = hu;
}
public DimensionDTO getShu() {
return shu;
}
public void setShu(DimensionDTO shu) {
this.shu = shu;
}
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
}

View file

@ -1,85 +0,0 @@
package de.avatic.lcc.dto.configuration.packaging.view;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.dto.generic.DimensionDTO;
import de.avatic.lcc.dto.generic.MaterialDTO;
import de.avatic.lcc.dto.generic.NodeDTO;
import java.util.List;
public class PackagingViewDTO {
private Integer id;
@JsonProperty("is_deprecated")
private Boolean isDeprecated;
private NodeDTO supplier;
private MaterialDTO material;
@JsonProperty("handling_unit")
private DimensionDTO hu;
@JsonProperty("small_handling_unit")
private DimensionDTO shu;
private List<PackagingViewPropertyDTO> properties;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Boolean getDeprecated() {
return isDeprecated;
}
public void setDeprecated(Boolean deprecated) {
isDeprecated = deprecated;
}
public NodeDTO getSupplier() {
return supplier;
}
public void setSupplier(NodeDTO supplier) {
this.supplier = supplier;
}
public MaterialDTO getMaterial() {
return material;
}
public void setMaterial(MaterialDTO material) {
this.material = material;
}
public DimensionDTO getHu() {
return hu;
}
public void setHu(DimensionDTO hu) {
this.hu = hu;
}
public DimensionDTO getShu() {
return shu;
}
public void setShu(DimensionDTO shu) {
this.shu = shu;
}
public List<PackagingViewPropertyDTO> getProperties() {
return properties;
}
public void setProperties(List<PackagingViewPropertyDTO> properties) {
this.properties = properties;
}
}

View file

@ -1,71 +0,0 @@
package de.avatic.lcc.dto.configuration.packaging.view;
import com.fasterxml.jackson.annotation.JsonProperty;
public class PackagingViewPropertyDTO {
private String name;
@JsonProperty("external_mapping_id")
private String externalMappingId;
@JsonProperty("is_required")
private Boolean isRequired;
@JsonProperty("data_type")
private String dataType;
@JsonProperty("current_value")
private String currentValue;
@JsonProperty("validation_rule")
private String validationRule;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getExternalMappingId() {
return externalMappingId;
}
public void setExternalMappingId(String externalMappingId) {
this.externalMappingId = externalMappingId;
}
public Boolean getRequired() {
return isRequired;
}
public void setRequired(Boolean required) {
isRequired = required;
}
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
public String getCurrentValue() {
return currentValue;
}
public void setCurrentValue(String currentValue) {
this.currentValue = currentValue;
}
public String getValidationRule() {
return validationRule;
}
public void setValidationRule(String validationRule) {
this.validationRule = validationRule;
}
}

View file

@ -10,12 +10,23 @@ public class NodeDTO {
private String name; private String name;
private CountryDTO country; private CountryDTO country;
private String address; private String address;
private List<NodeTypeDTO> types; private List<NodeType> types;
private LocationDTO location; private LocationDTO location;
@JsonProperty("is_user_node")
private Boolean isUserNode;
@JsonProperty("is_deprecated") @JsonProperty("is_deprecated")
private Boolean isDeprecated; private Boolean isDeprecated;
public Boolean getUserNode() {
return isUserNode;
}
public void setUserNode(Boolean userNode) {
isUserNode = userNode;
}
public Integer getId() { public Integer getId() {
return id; return id;
} }
@ -48,11 +59,11 @@ public class NodeDTO {
this.address = address; this.address = address;
} }
public List<NodeTypeDTO> getTypes() { public List<NodeType> getTypes() {
return types; return types;
} }
public void setTypes(List<NodeTypeDTO> types) { public void setTypes(List<NodeType> types) {
this.types = types; this.types = types;
} }

View file

@ -7,7 +7,7 @@ import com.fasterxml.jackson.annotation.JsonValue;
* A node can be categorized as SINK, SOURCE, or INTERMEDIATE, depending * A node can be categorized as SINK, SOURCE, or INTERMEDIATE, depending
* on its role within a network or process. * on its role within a network or process.
*/ */
public enum NodeTypeDTO { public enum NodeType {
/** /**
* Represents a node that consumes resources or products (end-point of flow). * Represents a node that consumes resources or products (end-point of flow).
*/ */
@ -30,7 +30,7 @@ public enum NodeTypeDTO {
* *
* @param displayedType The string representation of the node type. * @param displayedType The string representation of the node type.
*/ */
NodeTypeDTO(String displayedType) { NodeType(String displayedType) {
this.displayedType = displayedType; this.displayedType = displayedType;
} }

View file

@ -1,15 +1,18 @@
package de.avatic.lcc.dto.configuration.properties; package de.avatic.lcc.dto.generic;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.model.properties.PropertySetState; import de.avatic.lcc.model.properties.PropertySetState;
import java.time.LocalDateTime; import java.time.LocalDateTime;
public class PropertySetDTO { public class ValidityPeriodDTO {
private Integer id; private Integer id;
@JsonProperty("start_date")
private LocalDateTime startDate; private LocalDateTime startDate;
@JsonProperty("end_date")
private LocalDateTime endDate; private LocalDateTime endDate;
private PropertySetState state; private PropertySetState state;

View file

@ -1,7 +1,7 @@
package de.avatic.lcc.model.materials; package de.avatic.lcc.model.materials;
import de.avatic.lcc.model.country.CountryListEntry; import de.avatic.lcc.model.country.CountryListEntry;
import de.avatic.lcc.dto.generic.NodeTypeDTO; import de.avatic.lcc.dto.generic.NodeType;
import java.util.List; import java.util.List;
@ -11,7 +11,7 @@ public class MaterialSupplier {
private String name; private String name;
private CountryListEntry country; private CountryListEntry country;
private String address; private String address;
private List<NodeTypeDTO> types; private List<NodeType> types;
public String getName() { public String getName() {
@ -46,11 +46,11 @@ public class MaterialSupplier {
this.address = address; this.address = address;
} }
public List<NodeTypeDTO> getTypes() { public List<NodeType> getTypes() {
return types; return types;
} }
public void setTypes(List<NodeTypeDTO> types) { public void setTypes(List<NodeType> types) {
this.types = types; this.types = types;
} }
} }

View file

@ -2,8 +2,8 @@ package de.avatic.lcc.model.premisses;
import de.avatic.lcc.model.materials.Material; import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.model.nodes.Node; import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.model.packaging.Packaging;
import de.avatic.lcc.model.utils.DimensionUnit; import de.avatic.lcc.model.utils.DimensionUnit;
import de.avatic.lcc.dto.configuration.packaging.view.PackagingViewDTO;
import de.avatic.lcc.model.utils.WeightUnit; import de.avatic.lcc.model.utils.WeightUnit;
import de.avatic.lcc.model.user.SysUser; import de.avatic.lcc.model.user.SysUser;
import jakarta.validation.constraints.Digits; import jakarta.validation.constraints.Digits;
@ -89,7 +89,7 @@ public class Premiss {
private AggregateReference<Node, Integer> userSupplierNode; private AggregateReference<Node, Integer> userSupplierNode;
@Column("packaging_id") @Column("packaging_id")
private AggregateReference<PackagingViewDTO, Integer> packaging; private Packaging packaging;
@NotNull @NotNull
private AggregateReference<SysUser, Integer> user; private AggregateReference<SysUser, Integer> user;
@ -273,11 +273,11 @@ public class Premiss {
this.userSupplierNode = userSupplierNode; this.userSupplierNode = userSupplierNode;
} }
public AggregateReference<PackagingViewDTO, Integer> getPackaging() { public Packaging getPackaging() {
return packaging; return packaging;
} }
public void setPackaging(AggregateReference<PackagingViewDTO, Integer> packaging) { public void setPackaging(Packaging packaging) {
this.packaging = packaging; this.packaging = packaging;
} }

View file

@ -5,7 +5,7 @@ import jakarta.validation.constraints.Size;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.relational.core.mapping.Table;
@Deprecated
@Table(name = "sys_group") @Table(name = "sys_group")
public class SysGroup { public class SysGroup {

View file

@ -8,7 +8,7 @@ import org.springframework.data.relational.core.mapping.Table;
import java.util.Set; import java.util.Set;
@Deprecated
@Table(name = "sys_user") @Table(name = "sys_user")
public class SysUser { public class SysUser {

View file

@ -6,7 +6,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.mapping.AggregateReference; import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.data.relational.core.mapping.Column; import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.relational.core.mapping.Table;
@Deprecated
@Table(name = "sys_user_group_mapping") @Table(name = "sys_user_group_mapping")
public class SysUserGroupMapping { public class SysUserGroupMapping {

View file

@ -8,7 +8,7 @@ import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal; import java.math.BigDecimal;
@Deprecated
@Table(name = "sys_user_node") @Table(name = "sys_user_node")
public class SysUserNode { public class SysUserNode {

View file

@ -1,5 +1,6 @@
package de.avatic.lcc.repositories; package de.avatic.lcc.repositories;
import de.avatic.lcc.dto.generic.NodeType;
import de.avatic.lcc.model.nodes.Node; import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination; import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult; import de.avatic.lcc.repositories.pagination.SearchQueryResult;
@ -65,9 +66,19 @@ public class NodeRepository {
@Transactional @Transactional
public SearchQueryResult<Node> listNodes(String filter, Boolean excludeDeprecated, SearchQueryPagination pagination) { public SearchQueryResult<Node> listNodes(String filter, Boolean excludeDeprecated, SearchQueryPagination pagination) {
String query = buildQuery(filter, excludeDeprecated, pagination); String query = buildQuery(filter, excludeDeprecated, pagination);
String countQuery = buildCountQuery(filter, excludeDeprecated);
List<Node> entities = null;
Integer totalCount = 0;
if(filter == null) {
entities = jdbcTemplate.query(query, new NodeMapper(), pagination.getLimit(), pagination.getOffset());
totalCount = jdbcTemplate.queryForObject(countQuery, Integer.class);
}
else {
entities= jdbcTemplate.query(query, new NodeMapper(), "%" + filter + "%", "%" + filter + "%", "%" + filter + "%", pagination.getLimit(), pagination.getOffset());
totalCount = jdbcTemplate.queryForObject(countQuery, Integer.class, "%" + filter + "%", "%" + filter + "%", "%" + filter + "%");
}
List<Node> entities = jdbcTemplate.query(query, new NodeMapper(), "%" + filter + "%", "%" + filter + "%", "%" + filter + "%", pagination.getLimit(), pagination.getOffset());
Integer totalCount = jdbcTemplate.queryForObject(buildCountQuery(filter, excludeDeprecated), Integer.class, "%" + filter + "%", "%" + filter + "%", "%" + filter + "%");
return new SearchQueryResult<>(entities, pagination.getPage(), totalCount, pagination.getLimit()); return new SearchQueryResult<>(entities, pagination.getPage(), totalCount, pagination.getLimit());
} }
@ -119,6 +130,27 @@ public class NodeRepository {
return Optional.ofNullable(jdbcTemplate.update(query, node.getId()) == 0 ? null : node.getId()); return Optional.ofNullable(jdbcTemplate.update(query, node.getId()) == 0 ? null : node.getId());
} }
public List<Node> searchNode(String filter, int limit, NodeType nodeType, boolean excludeDeprecated) {
StringBuilder queryBuilder = new StringBuilder().append("SELECT * FROM node WHERE (name LIKE ? OR address LIKE ?)");
if(nodeType != null) {
queryBuilder.append(" AND node_type = ?");
}
if(excludeDeprecated) {
queryBuilder.append(" AND is_deprecated = false");
}
queryBuilder.append(" LIMIT ?");
if(nodeType != null)
{
return jdbcTemplate.query(queryBuilder.toString(),new NodeMapper(), "%" + filter + "%", "%" + filter + "%", nodeType.name(), limit);
}
return jdbcTemplate.query(queryBuilder.toString(),new NodeMapper(), "%" + filter + "%", "%" + filter + "%", limit);
}
private class NodeMapper implements RowMapper<Node> { private class NodeMapper implements RowMapper<Node> {
@Override @Override

View file

@ -89,4 +89,20 @@ public class CountryPropertyRepository {
return dto; return dto;
}, id, propertySetId); }, id, propertySetId);
} }
public void fillDraft(Integer setId) {
String query = """
SELECT type.id AS typeId, property.property_value as value, property.country_id AS country_id FROM country_property_type AS type
LEFT JOIN country_property AS property ON property.country_property_type_id = type.id
LEFT JOIN property_set AS propertySet ON propertySet.id = property.property_set_id WHERE propertySet.state = 'VALID'""";
jdbcTemplate.query(query, (rs, rowNum) -> {
String insertQuery = "INSERT IGNORE INTO country_property (property_value, country_id, country_property_type_id, property_set_id) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(insertQuery, rs.getString("value"), rs.getInt("country_id"), rs.getInt("typeId"), setId);
return null;
});
}
} }

View file

@ -88,4 +88,20 @@ public class PropertyRepository {
return dto; return dto;
}, propertySetId); }, propertySetId);
} }
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'""";
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);
return null;
});
}
} }

View file

@ -13,6 +13,10 @@ import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.List; import java.util.List;
/**
* Repository class for managing and querying property sets.
* Provides methods for fetching, updating, and creating property set records in the database.
*/
@Repository @Repository
public class PropertySetRepository { public class PropertySetRepository {
@ -22,6 +26,11 @@ public class PropertySetRepository {
this.jdbcTemplate = jdbcTemplate; this.jdbcTemplate = jdbcTemplate;
} }
/**
* Retrieves a list of all property sets from the database.
*
* @return A list of {@link PropertySet} objects containing property set information.
*/
@Transactional @Transactional
public List<PropertySet> listPropertySets() { public List<PropertySet> listPropertySets() {
String query = "SELECT id, start_date, end_date, state FROM property_set"; String query = "SELECT id, start_date, end_date, state FROM property_set";
@ -29,49 +38,83 @@ public class PropertySetRepository {
return jdbcTemplate.query(query, new PropertySetMapper()); return jdbcTemplate.query(query, new PropertySetMapper());
} }
/**
* Retrieves the ID of the draft property set.
* If no draft property set exists, a new one is created.
*
* @return The ID of the draft {@link PropertySet}.
*/
@Transactional @Transactional
public Integer getDraftSetId() { public Integer getDraftSetId() {
return getDraftSet().getId(); return getDraftSet().getId();
} }
/**
* Retrieves the draft property set. If no draft exists, it creates a new one.
*
* @return The {@link PropertySet} object representing the draft state.
*/
@Transactional @Transactional
public PropertySet getDraftSet() { public PropertySet getDraftSet() {
createSet(); 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(), PropertySetState.DRAFT.name());
} }
@Transactional
public boolean hasDraftSet() {
Integer count = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM property_set WHERE state = ?", Integer.class, PropertySetState.DRAFT.name());
return !(count == null || count == 0);
}
private void createSet() { 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 = ?)", PropertySetState.DRAFT.name(), PropertySetState.DRAFT.name());
} }
/**
* Retrieves the currently valid property set.
*
* @return The {@link PropertySet} object in the valid state, or null if none exists.
*/
public PropertySet getValidSet() { 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(), PropertySetState.VALID.name());
} }
@Transactional
/**
* Applies the draft property set, marking it as valid and expiring the current valid set.
* Updates the timestamps for the draft and valid states accordingly.
*/
public void applyDraft() { public void applyDraft() {
final Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis()); final Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis());
if(hasDraftSet()) /* 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 = ?, 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 = ?, start_date = ? WHERE id = ? AND state = ? ", PropertySetState.VALID.name(), currentTimestamp, PropertySetState.DRAFT.name());
//TODO: fill all missing values in draft set!
}
} }
/**
* Invalidates a specific property set by its ID if its current state is expired.
*
* @param id The ID of the property set to invalidate.
*/
@Transactional @Transactional
public void invalidateById(Integer id) { 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 = ? ", PropertySetState.INVALID.name(), id, PropertySetState.EXPIRED.name());
} }
/**
* Checks if the current draft property set has any associated properties.
*
* @return {@code true} if properties exist for the draft set, {@code false} otherwise.
*/
@Transactional
public Boolean hasPropertiesDraft() {
var setId = getDraftSetId();
String query = """
SELECT (SELECT COUNT(*) FROM system_property WHERE property_set_id = ?) + (SELECT COUNT(*) FROM country_property WHERE property_set_id = ?) AS total_count""";
var totalCount = jdbcTemplate.queryForObject(query, Integer.class, setId, setId);
return totalCount != null && totalCount > 0;
}
/**
* Mapper class for converting SQL query results into {@link PropertySet} objects.
*/
private static class PropertySetMapper implements RowMapper<PropertySet> { private static class PropertySetMapper implements RowMapper<PropertySet> {
@Override @Override

View file

@ -0,0 +1,51 @@
package de.avatic.lcc.repositories.users;
import de.avatic.lcc.model.nodes.Node;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.Collection;
@Repository
public class UserNodeRepository {
private final JdbcTemplate jdbcTemplate;
public UserNodeRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public Node getUserNode(String userId) {
}
public Collection<Node> searchNode(String filter, int limit, int userId, boolean excludeDeprecated) {
StringBuilder queryBuilder = new StringBuilder().append("SELECT * FROM sys_user_node WHERE user_id = ? AND (name LIKE ? OR address LIKE ?)");
if (excludeDeprecated) {
queryBuilder.append(" AND is_deprecated = FALSE");
}
queryBuilder.append("LIMIT ?");
return jdbcTemplate.query(queryBuilder.toString(), (rs, rowNum) -> {
var node = new Node();
node.setId(rs.getInt("id"));
node.setName(rs.getString("name"));
node.setAddress(rs.getString("address"));
node.setGeoLat(rs.getBigDecimal("geo_lat"));
node.setGeoLng(rs.getBigDecimal("geo_lng"));
node.setDeprecated(rs.getBoolean("deprecated"));
node.setCountryId(rs.getInt("country_id"));
return node;
}, userId, '%'+filter+'%','%'+filter+'%', limit );
}
public void add(Node node) {
// todo insert user node
}
}

View file

@ -0,0 +1,15 @@
package de.avatic.lcc.service;
import de.avatic.lcc.dto.configuration.nodes.userNodes.LocateNodeDTO;
import org.springframework.stereotype.Service;
@Service
public class GeoApiService {
public LocateNodeDTO locate(String address) {
//TODO implementation missing
return null;
}
}

View file

@ -15,6 +15,10 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.Optional; import java.util.Optional;
/**
* Service class for managing country-related data and operations.
* Provides methods for setting properties, listing countries, and retrieving country details.
*/
@Service @Service
public class CountryService { public class CountryService {
@ -30,6 +34,15 @@ public class CountryService {
this.propertySetRepository = propertySetRepository; this.propertySetRepository = propertySetRepository;
} }
/**
* Sets a property value for a country identified by its ISO code.
*
* @param isoCode The ISO code identifying the country.
* @param mappingId The identifier for the property to be set.
* @param value The value of the property to be set.
* <p>
* This is a transactional operation.
*/
@Transactional @Transactional
public void setProperties(IsoCode isoCode, String mappingId, String value) { public void setProperties(IsoCode isoCode, String mappingId, String value) {
//todo validate property value! //todo validate property value!
@ -37,16 +50,44 @@ public class CountryService {
countryPropertyRepository.setProperty(propertySetRepository.getDraftSetId(), country.orElseThrow().getId(), mappingId, value); countryPropertyRepository.setProperty(propertySetRepository.getDraftSetId(), country.orElseThrow().getId(), mappingId, value);
} }
/**
* Retrieves a paginated list of countries filtered by the specified criteria.
*
* @param filter The filter criteria for the countries.
* @param page The page number for pagination.
* @param limit The number of countries per page.
* @return A paginated result containing country DTOs that match the filter criteria.
* <p>
* This is a transactional operation.
*/
@Transactional @Transactional
public SearchQueryResult<CountryDTO> listCountries(String filter, int page, int limit) { public SearchQueryResult<CountryDTO> listCountries(String filter, int page, int limit) {
return SearchQueryResult.map(countryRepository.listCountries(filter, true, new SearchQueryPagination(page, limit)), countryTransformer::toCountryDTO); return SearchQueryResult.map(countryRepository.listCountries(filter, true, new SearchQueryPagination(page, limit)), countryTransformer::toCountryDTO);
} }
/**
* Retrieves a complete list of countries filtered by the specified criteria.
*
* @param filter The filter criteria for the countries.
* @return A result containing country DTOs that match the filter criteria.
* <p>
* This is a transactional operation.
*/
@Transactional @Transactional
public SearchQueryResult<CountryDTO> listCountries(String filter) { public SearchQueryResult<CountryDTO> listCountries(String filter) {
return SearchQueryResult.map(countryRepository.listCountries(filter, true), countryTransformer::toCountryDTO); return SearchQueryResult.map(countryRepository.listCountries(filter, true), countryTransformer::toCountryDTO);
} }
/**
* Retrieves detailed information about a specific country, including its properties.
*
* @param id The unique identifier of the country.
* @param propertySetId The property set ID for filtering associated properties.
* If set to 0, retrieves all properties for the country.
* @return An optional containing the detailed information of the country, or empty if not found.
* <p>
* This is a transactional operation.
*/
@Transactional @Transactional
public Optional<CountryDetailDTO> getCountry(Integer id, Integer propertySetId) { public Optional<CountryDetailDTO> getCountry(Integer id, Integer propertySetId) {
var country = countryRepository.getById(id); var country = countryRepository.getById(id);
@ -60,14 +101,13 @@ public class CountryService {
dto.setName(entity.getIsoCode().getFullName()); dto.setName(entity.getIsoCode().getFullName());
dto.setId(entity.getId()); dto.setId(entity.getId());
if(0 == propertySetId) { if (0 == propertySetId) {
dto.setProperties(countryPropertyRepository.listPropertiesByCountryId(entity.getId())); dto.setProperties(countryPropertyRepository.listPropertiesByCountryId(entity.getId()));
} else { } else {
dto.setProperties(countryPropertyRepository.listPropertiesByCountryIdAndPropertySetId(entity.getId(), propertySetId)); dto.setProperties(countryPropertyRepository.listPropertiesByCountryIdAndPropertySetId(entity.getId(), propertySetId));
} }
return Optional.of(dto); return Optional.of(dto);
} }

View file

@ -1,7 +1,7 @@
package de.avatic.lcc.service.configuration; package de.avatic.lcc.service.configuration;
import de.avatic.lcc.dto.configuration.material.update.MaterialUpdateDTO; import de.avatic.lcc.dto.configuration.material.update.MaterialUpdateDTO;
import de.avatic.lcc.dto.configuration.material.view.MaterialViewDTO; import de.avatic.lcc.dto.configuration.material.view.MaterialDetailDTO;
import de.avatic.lcc.dto.generic.MaterialDTO; import de.avatic.lcc.dto.generic.MaterialDTO;
import de.avatic.lcc.model.materials.Material; import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.repositories.MaterialRepository; import de.avatic.lcc.repositories.MaterialRepository;
@ -9,43 +9,90 @@ import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult; import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.service.transformer.generic.MaterialTransformer; import de.avatic.lcc.service.transformer.generic.MaterialTransformer;
import de.avatic.lcc.service.transformer.material.MaterialUpdateDTOTransformer; import de.avatic.lcc.service.transformer.material.MaterialUpdateDTOTransformer;
import de.avatic.lcc.service.transformer.material.MaterialViewDTOTransformer; import de.avatic.lcc.service.transformer.material.MaterialDetailTransformer;
import de.avatic.lcc.util.exception.clienterror.MaterialNotFoundException; import de.avatic.lcc.util.exception.clienterror.MaterialNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/**
* Service class responsible for managing materials. Provides functionality to
* list, retrieve, and manipulate material data. Acts as a bridge between the
* repository and transformer layers.
*/
@Service @Service
public class MaterialService { public class MaterialService {
private final MaterialUpdateDTOTransformer materialUpdateDTOTransformer;
private final MaterialRepository materialRepository; private final MaterialRepository materialRepository;
private final MaterialTransformer materialTransformer; private final MaterialTransformer materialTransformer;
private final MaterialViewDTOTransformer materialViewDTOTransformer; private final MaterialDetailTransformer materialDetailTransformer;
public MaterialService(MaterialRepository materialRepository, MaterialUpdateDTOTransformer materialUpdateDTOTransformer, MaterialTransformer materialTransformer, MaterialViewDTOTransformer materialViewDTOTransformer) { /**
* Constructor for MaterialService.
*
* @param materialRepository repository for accessing material data
* @param materialTransformer transformer to convert material entities to DTOs
* @param materialDetailTransformer transformer to convert material entities to detail DTOs
*/
public MaterialService(MaterialRepository materialRepository, MaterialTransformer materialTransformer, MaterialDetailTransformer materialDetailTransformer) {
this.materialRepository = materialRepository; this.materialRepository = materialRepository;
this.materialUpdateDTOTransformer = materialUpdateDTOTransformer;
this.materialTransformer = materialTransformer; this.materialTransformer = materialTransformer;
this.materialViewDTOTransformer = materialViewDTOTransformer; this.materialDetailTransformer = materialDetailTransformer;
} }
/**
* Lists materials based on a filter and pagination parameters.
*
* @param filter the search filter to apply
* @param page the page number for pagination (zero-based)
* @param limit the maximum number of items per page
* @return a {@link SearchQueryResult} containing a list of material DTOs and pagination details
*/
public SearchQueryResult<MaterialDTO> listMaterial(String filter, int page, int limit) { public SearchQueryResult<MaterialDTO> listMaterial(String filter, int page, int limit) {
SearchQueryResult<Material> queryResult = materialRepository.listMaterials(filter, true, new SearchQueryPagination(page, limit)); SearchQueryResult<Material> queryResult = materialRepository.listMaterials(filter, true, new SearchQueryPagination(page, limit));
return SearchQueryResult.map(queryResult, materialTransformer::toMaterialDTO); return SearchQueryResult.map(queryResult, materialTransformer::toMaterialDTO);
} }
public MaterialViewDTO getMaterial(Integer id) { /**
return materialViewDTOTransformer.toMaterialViewDTO(materialRepository.getById(id).orElseThrow(() -> new MaterialNotFoundException(id))); * Retrieves the details of a specific material by its ID.
*
* @param id the unique identifier of the material
* @return a {@link MaterialDetailDTO} representing the material details
* @throws MaterialNotFoundException if no material with the given ID is found
*/
public MaterialDetailDTO getMaterial(Integer id) {
return materialDetailTransformer.toMaterialDetailDTO(materialRepository.getById(id).orElseThrow(() -> new MaterialNotFoundException(id)));
} }
public Integer updateMaterial(Integer id, MaterialUpdateDTO dto) { /**
* Updates an existing material with new data.
*
* @param id the ID of the material to update
* @param dto the data transfer object containing the updated material details
* @return the ID of the updated material
* @throws MaterialNotFoundException if no material with the given ID is found
*/
/* public Integer updateMaterial(Integer id, MaterialUpdateDTO dto) {
return materialRepository.update(materialUpdateDTOTransformer.fromMaterialUpdateDTO(dto)).orElseThrow(() -> new MaterialNotFoundException(id)); return materialRepository.update(materialUpdateDTOTransformer.fromMaterialUpdateDTO(dto)).orElseThrow(() -> new MaterialNotFoundException(id));
} }*/
public Integer createMaterial(MaterialUpdateDTO dto) { /**
* Creates a new material based on the provided data.
*
* @param dto the data transfer object containing the new material details
* @return the ID of the newly created material
* @throws RuntimeException if the material could not be created
*/
/* public Integer createMaterial(MaterialUpdateDTO dto) {
return materialRepository.create(materialUpdateDTOTransformer.fromMaterialUpdateDTO(dto)).orElseThrow(() -> new RuntimeException("Unable to create Material " + dto)); return materialRepository.create(materialUpdateDTOTransformer.fromMaterialUpdateDTO(dto)).orElseThrow(() -> new RuntimeException("Unable to create Material " + dto));
} }*/
public Integer deleteMaterial(Integer id) { /**
* Marks a material as deprecated by its ID.
*
* @param id the ID of the material to deprecate
* @return the ID of the deprecated material
* @throws MaterialNotFoundException if no material with the given ID is found
*/
/* public Integer deleteMaterial(Integer id) {
return materialRepository.setDeprecatedById(id).orElseThrow(() -> new MaterialNotFoundException(id)); return materialRepository.setDeprecatedById(id).orElseThrow(() -> new MaterialNotFoundException(id));
} }*/
} }

View file

@ -1,30 +1,40 @@
package de.avatic.lcc.service.configuration; package de.avatic.lcc.service.configuration;
import de.avatic.lcc.dto.configuration.nodes.userNodes.AddUserNodeDTO;
import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.configuration.nodes.view.NodeDetailDTO; import de.avatic.lcc.dto.configuration.nodes.view.NodeDetailDTO;
import de.avatic.lcc.dto.configuration.nodes.update.NodeUpdateDTO; import de.avatic.lcc.dto.configuration.nodes.update.NodeUpdateDTO;
import de.avatic.lcc.dto.generic.NodeType;
import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.repositories.NodeRepository; import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination; import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult; import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.repositories.users.UserNodeRepository;
import de.avatic.lcc.service.transformer.nodes.NodeUpdateDTOTransformer; import de.avatic.lcc.service.transformer.nodes.NodeUpdateDTOTransformer;
import de.avatic.lcc.service.transformer.nodes.NodeViewDTOTransformer; import de.avatic.lcc.service.transformer.nodes.NodeDetailTransformer;
import de.avatic.lcc.service.transformer.generic.NodeTransformer; import de.avatic.lcc.service.transformer.generic.NodeTransformer;
import de.avatic.lcc.util.exception.clienterror.NodeNotFoundException; import de.avatic.lcc.util.exception.clienterror.NodeNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Service @Service
public class NodeService { public class NodeService {
private final NodeRepository nodeRepository; private final NodeRepository nodeRepository;
private final NodeTransformer nodeTransformer; private final NodeTransformer nodeTransformer;
private final NodeViewDTOTransformer nodeViewDTOTransformer; private final NodeDetailTransformer nodeDetailTransformer;
private final NodeUpdateDTOTransformer nodeUpdateDTOTransformer; private final NodeUpdateDTOTransformer nodeUpdateDTOTransformer;
private final UserNodeRepository userNodeRepository;
public NodeService(NodeRepository nodeRepository, NodeTransformer nodeTransformer, NodeViewDTOTransformer nodeViewDTOTransformer, NodeUpdateDTOTransformer nodeUpdateDTOTransformer) { public NodeService(NodeRepository nodeRepository, NodeTransformer nodeTransformer, NodeDetailTransformer nodeDetailTransformer, NodeUpdateDTOTransformer nodeUpdateDTOTransformer, UserNodeRepository userNodeRepository) {
this.nodeRepository = nodeRepository; this.nodeRepository = nodeRepository;
this.nodeTransformer = nodeTransformer; this.nodeTransformer = nodeTransformer;
this.nodeViewDTOTransformer = nodeViewDTOTransformer; this.nodeDetailTransformer = nodeDetailTransformer;
this.nodeUpdateDTOTransformer = nodeUpdateDTOTransformer; this.nodeUpdateDTOTransformer = nodeUpdateDTOTransformer;
this.userNodeRepository = userNodeRepository;
} }
public SearchQueryResult<NodeDTO> listNodes(String filter, int page, int limit) { public SearchQueryResult<NodeDTO> listNodes(String filter, int page, int limit) {
@ -32,11 +42,11 @@ public class NodeService {
} }
public SearchQueryResult<NodeDetailDTO> listNodesView(String filter, int page, int limit) { public SearchQueryResult<NodeDetailDTO> listNodesView(String filter, int page, int limit) {
return SearchQueryResult.map(nodeRepository.listNodes(filter, true, new SearchQueryPagination(page, limit)), nodeViewDTOTransformer::toNodeViewDTO); return SearchQueryResult.map(nodeRepository.listNodes(filter, true, new SearchQueryPagination(page, limit)), nodeDetailTransformer::toNodeViewDTO);
} }
public NodeDetailDTO getNode(Integer id) { public NodeDetailDTO getNode(Integer id) {
return nodeViewDTOTransformer.toNodeViewDTO(nodeRepository.getById(id).orElseThrow(() -> new NodeNotFoundException(id))); return nodeDetailTransformer.toNodeViewDTO(nodeRepository.getById(id).orElseThrow(() -> new NodeNotFoundException(id)));
} }
public Integer deleteNode(Integer id) { public Integer deleteNode(Integer id) {
@ -46,4 +56,41 @@ public class NodeService {
public Integer updateNode(NodeUpdateDTO dto) { public Integer updateNode(NodeUpdateDTO dto) {
return nodeRepository.update(nodeUpdateDTOTransformer.fromNodeUpdateDTO(dto)).orElseThrow(() -> new NodeNotFoundException(dto.getId())); return nodeRepository.update(nodeUpdateDTOTransformer.fromNodeUpdateDTO(dto)).orElseThrow(() -> new NodeNotFoundException(dto.getId()));
} }
public List<NodeDTO> searchNode(String filter, int limit, NodeType nodeType, boolean includeUserNode) {
List<NodeDTO> nodes = new ArrayList<>();
int userId = 1; //TODO get current user's id
if( includeUserNode && NodeType.SOURCE.equals(nodeType)) {
nodes.addAll(userNodeRepository.searchNode(filter, limit, userId, true).stream().map(nodeTransformer::toNodeDTO).toList());
nodes.forEach(node -> node.setUserNode(true));
limit -= nodes.size();
}
if(limit > 0) {
nodes.addAll(nodeRepository.searchNode(filter, limit, nodeType, true).stream().map(nodeTransformer::toNodeDTO).toList());
}
return nodes;
}
public void addUserNode(AddUserNodeDTO dto) {
Node node = new Node();
node.setName(dto.getName());
node.setAddress(dto.getAddress());
node.setGeoLng(BigDecimal.valueOf(dto.getLocation().getLongitude()));
node.setGeoLat(BigDecimal.valueOf(dto.getLocation().getLatitude()));
node.setSink(false);
node.setSource(true);
node.setIntermediate(false);
node.setDeprecated(false);
//todo resolve country
node.setCountryId(0);
userNodeRepository.add(node);
}
} }

View file

@ -1,132 +0,0 @@
package de.avatic.lcc.service.configuration;
import de.avatic.lcc.dto.configuration.packaging.update.PackagingUpdateDTO;
import de.avatic.lcc.dto.configuration.packaging.view.PackagingViewDTO;
import de.avatic.lcc.model.country.Country;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.model.packaging.Packaging;
import de.avatic.lcc.model.packaging.PackagingDimension;
import de.avatic.lcc.model.properties.PackagingProperty;
import de.avatic.lcc.model.properties.PropertyType;
import de.avatic.lcc.repositories.country.CountryRepository;
import de.avatic.lcc.repositories.MaterialRepository;
import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.packaging.PackagingDimensionRepository;
import de.avatic.lcc.repositories.packaging.PackagingRepository;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.repositories.packaging.PackagingPropertiesRepository;
import de.avatic.lcc.service.transformer.packaging.PackagingTransformerService;
import de.avatic.lcc.service.transformer.generic.DimensionTransformer;
import de.avatic.lcc.service.transformer.generic.MaterialTransformer;
import de.avatic.lcc.service.transformer.generic.NodeTransformer;
import de.avatic.lcc.util.Check;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
public class PackagingService {
private final PackagingRepository packagingRepository;
private final PackagingDimensionRepository packagingDimensionRepository;
private final NodeRepository nodeRepository;
private final MaterialRepository materialRepository;
private final CountryRepository countryRepository;
private final PackagingTransformerService packagingTransformerService;
private final PackagingPropertiesRepository packagingPropertiesRepository;
private final MaterialTransformer materialTransformer;
private final NodeTransformer nodeTransformer;
private final DimensionTransformer dimensionTransformer;
public PackagingService(PackagingRepository packagingRepository, PackagingDimensionRepository packagingDimensionRepository, NodeRepository nodeRepository, MaterialRepository materialRepository, CountryRepository countryRepository, PackagingTransformerService packagingTransformerService, PackagingPropertiesRepository packagingPropertiesRepository, MaterialTransformer materialTransformer, NodeTransformer nodeTransformer, DimensionTransformer dimensionTransformer) {
this.packagingRepository = packagingRepository;
this.packagingDimensionRepository = packagingDimensionRepository;
this.nodeRepository = nodeRepository;
this.materialRepository = materialRepository;
this.countryRepository = countryRepository;
this.packagingTransformerService = packagingTransformerService;
this.packagingPropertiesRepository = packagingPropertiesRepository;
this.materialTransformer = materialTransformer;
this.nodeTransformer = nodeTransformer;
this.dimensionTransformer = dimensionTransformer;
}
@Transactional
public SearchQueryResult<PackagingViewDTO> listPackaging(Integer materialId, Integer supplierId, int page, int limit) {
return SearchQueryResult.map(packagingRepository.listPackaging(materialId, supplierId, true, new SearchQueryPagination(page, limit)), this::toPackagingGetDTO);
}
private PackagingViewDTO toPackagingGetDTO(Packaging packaging) {
PackagingViewDTO dtoEntry = new PackagingViewDTO();
Optional<Node> node = nodeRepository.getById(packaging.getSupplierId());
Optional<Material> material = materialRepository.getById(packaging.getMaterialId());
dtoEntry.setHu(dimensionTransformer.toDimensionDTO(packagingDimensionRepository.getById(packaging.getHuId()).orElseThrow()));
dtoEntry.setShu(dimensionTransformer.toDimensionDTO(packagingDimensionRepository.getById(packaging.getShuId()).orElseThrow()));
dtoEntry.setSupplier(nodeTransformer.toNodeDTO(node.orElseThrow()));
dtoEntry.setMaterial(materialTransformer.toMaterialDTO(material.orElseThrow()));
return dtoEntry;
}
@Transactional
public PackagingViewDTO getPackaging(Integer id) {
Optional<Packaging> packaging = packagingRepository.getById(id);
Optional<Material> material = materialRepository.getById(packaging.orElseThrow().getMaterialId());
Optional<Node> supplier = nodeRepository.getById(packaging.orElseThrow().getSupplierId());
Optional<Country> country = countryRepository.getById(supplier.orElseThrow().getCountryId());
Optional<PackagingDimension> hu = packagingDimensionRepository.getById(packaging.orElseThrow().getHuId());
Optional<PackagingDimension> shu = packagingDimensionRepository.getById(packaging.orElseThrow().getShuId());
List<PackagingProperty> properties = packagingPropertiesRepository.getByPackagingId(id);
return packagingTransformerService.convertToPackagingGetDTO(packaging, material, supplier, country, hu, shu, properties).orElseThrow();
}
@Transactional
public void updatePackaging(Integer id, PackagingUpdateDTO dto) {
Optional<Packaging> entity = packagingRepository.getById(id);
if (entity.isEmpty()) throw new RuntimeException("Packaging does not exists " + id);
// check integrity
Check.equals(dto.getHu().getId(), entity.get().getHuId());
Check.equals(dto.getHu().getId(), entity.get().getHuId());
Check.equals(dto.getId(), id);
packagingDimensionRepository.update(dimensionTransformer.toDimensionEntity(dto.getHu()));
packagingDimensionRepository.update(dimensionTransformer.toDimensionEntity(dto.getShu()));
List<PropertyType> types = packagingPropertiesRepository.listTypes();
for(PropertyType type : types) {
var value = dto.getProperties().get(type.getExternalMappingId());
if(value != null) {
packagingPropertiesRepository.update(id, type.getId(), value);
}
}
packagingRepository.update(packagingTransformerService.convertFromPackagingPostDTO(dto));
}
public Integer deletePackaging(Integer id) {
return packagingRepository.setDeprecatedById(id).orElseThrow(() -> new RuntimeException("Packaging does not exists " + id));
}
@Transactional
public Integer createPackaging(PackagingUpdateDTO dto) {
Optional<Integer> huId = packagingDimensionRepository.insert(dimensionTransformer.toDimensionEntity(dto.getHu()));
Optional<Integer> shuId = packagingDimensionRepository.insert(dimensionTransformer.toDimensionEntity(dto.getShu()));
Packaging entity = packagingTransformerService.convertFromPackagingPostDTO(dto);
entity.setHuId(huId.orElseThrow());
entity.setShuId(shuId.orElseThrow());
return packagingRepository.insert(entity).orElseThrow(() -> new RuntimeException("Unable to create Packaging " + entity));
}
}

View file

@ -1,52 +0,0 @@
package de.avatic.lcc.service.configuration;
import de.avatic.lcc.dto.configuration.properties.PropertySetDTO;
import de.avatic.lcc.dto.generic.PropertyDTO;
import de.avatic.lcc.model.properties.PropertySet;
import de.avatic.lcc.repositories.properties.PropertyRepository;
import de.avatic.lcc.repositories.properties.PropertySetRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class PropertiesService {
private final PropertyRepository propertyRepository;
private final PropertySetRepository propertySetRepository;
public PropertiesService(PropertyRepository propertyRepository, PropertySetRepository propertySetRepository) {
this.propertyRepository = propertyRepository;
this.propertySetRepository = propertySetRepository;
}
@Transactional
public void setProperties(String mappingId, String value) {
//todo validate if property value is set correctly!
propertyRepository.setProperty(propertySetRepository.getDraftSetId(), mappingId, value);
}
public List<PropertyDTO> listProperties(Integer propertySetId) {
if(propertySetId == 0)
return propertyRepository.listProperties();
return propertyRepository.listPropertiesBySetId(propertySetId);
}
public List<PropertySetDTO> listPropertySets() {
return propertySetRepository.listPropertySets().stream().map(propertySet -> {
PropertySetDTO dto = new PropertySetDTO();
dto.setId(propertySet.getId());
dto.setEndDate(propertySet.getEndDate());
dto.setStartDate(propertySet.getStartDate());
dto.setState(propertySet.getState());
return dto;
}).toList();
}
}

View file

@ -0,0 +1,85 @@
package de.avatic.lcc.service.configuration;
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 org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class PropertyService {
private final PropertyRepository propertyRepository;
private final PropertySetRepository propertySetRepository;
/**
* Constructs the PropertyService with the provided repositories.
*
* @param propertyRepository the repository to manage properties
* @param propertySetRepository the repository to manage property sets
*/
public PropertyService(PropertyRepository propertyRepository, PropertySetRepository propertySetRepository) {
this.propertyRepository = propertyRepository;
this.propertySetRepository = propertySetRepository;
}
/**
* Sets a property value for a given mapping ID.
*
* @param mappingId the identifier of the property to be updated
* @param value the new value to be set for the property
*/
@Transactional
public void setProperties(String mappingId, String value) {
//todo validate if property value is set correctly!
propertyRepository.setProperty(propertySetRepository.getDraftSetId(), mappingId, value);
}
/**
* 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.
*
* @param propertySetId the ID of the property set (0 for all properties)
* @return a list of properties as {@link PropertyDTO}
*/
public List<PropertyDTO> listProperties(Integer propertySetId) {
if (propertySetId == 0)
return propertyRepository.listProperties();
return propertyRepository.listPropertiesBySetId(propertySetId);
}
/**
* Retrieves a list of all property sets, mapping them to validity period data transfer objects.
*
* @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();
}
/**
* Invalidates a property set by its ID.
*
* @param id the ID of the property set to invalidate
*/
public void invalidate(Integer id) {
propertySetRepository.invalidateById(id);
}
}

View file

@ -0,0 +1,56 @@
package de.avatic.lcc.service.configuration;
import de.avatic.lcc.repositories.country.CountryPropertyRepository;
import de.avatic.lcc.repositories.properties.PropertyRepository;
import de.avatic.lcc.repositories.properties.PropertySetRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* A service class responsible for managing staged changes to properties.
* It provides functionalities to check for property drafts and apply them
* when necessary.
*/
@Service
public class PropertyStagedChangesService {
private final PropertySetRepository propertySetRepository;
private final PropertyRepository propertyRepository;
private final CountryPropertyRepository countryPropertyRepository;
/**
* Constructs a new {@code PropertyStagedChangesService} with the required repositories.
*
* @param propertySetRepository the repository for managing property sets
* @param propertyRepository the repository for managing properties
* @param countryPropertyRepository the repository for managing country-specific properties
*/
public PropertyStagedChangesService(PropertySetRepository propertySetRepository, PropertyRepository propertyRepository, CountryPropertyRepository countryPropertyRepository) {
this.propertySetRepository = propertySetRepository;
this.propertyRepository = propertyRepository;
this.countryPropertyRepository = countryPropertyRepository;
}
/**
* Checks if there are any staged (draft) properties that have not yet been applied.
*
* @return {@code true} if there are property drafts, {@code false} otherwise
*/
public Boolean hasPropertiesDraft() {
return propertySetRepository.hasPropertiesDraft();
}
/**
* Applies all staged (draft) properties if there are any present.
* This method is transactional to ensure that all changes are applied atomically.
*/
@Transactional
public void applyDraft() {
if(!propertySetRepository.hasPropertiesDraft()) return;
Integer setId = propertySetRepository.getDraftSetId();
countryPropertyRepository.fillDraft(setId);
propertyRepository.fillDraft(setId);
propertySetRepository.applyDraft();
}
}

View file

@ -1,35 +0,0 @@
package de.avatic.lcc.service.configuration;
import de.avatic.lcc.repositories.properties.PropertyRepository;
import de.avatic.lcc.repositories.properties.PropertySetRepository;
import org.springframework.stereotype.Service;
@Service
public class StagedChangesService {
private final PropertySetRepository propertySetRepository;
private final PropertyRepository propertyRepository;
public StagedChangesService(PropertySetRepository propertySetRepository, PropertyRepository propertyRepository) {
this.propertySetRepository = propertySetRepository;
this.propertyRepository = propertyRepository;
}
public Boolean hasRateDrafts() {
return false;
}
public void approveRateDrafts() {
}
public Boolean hasPropertiesDraft() {
propertyRepository.listPropertiesBySetId(propertySetRepository.getDraftSetId());
return null;
}
public void approvePropertiesDrafts() {
}
}

View file

@ -1,7 +1,7 @@
package de.avatic.lcc.service.transformer.generic; package de.avatic.lcc.service.transformer.generic;
import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.generic.NodeTypeDTO; import de.avatic.lcc.dto.generic.NodeType;
import de.avatic.lcc.model.nodes.Node; import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.repositories.country.CountryRepository; import de.avatic.lcc.repositories.country.CountryRepository;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -24,18 +24,19 @@ public class NodeTransformer {
public NodeDTO toNodeDTO(Node entity) { public NodeDTO toNodeDTO(Node entity) {
NodeDTO dto = new NodeDTO(); NodeDTO dto = new NodeDTO();
ArrayList<NodeTypeDTO> types = new ArrayList<>(); ArrayList<NodeType> types = new ArrayList<>();
if (entity.getSink()) types.add(NodeTypeDTO.DESTINATION); if (entity.getSink()) types.add(NodeType.DESTINATION);
if (entity.getSource()) types.add(NodeTypeDTO.SOURCE); if (entity.getSource()) types.add(NodeType.SOURCE);
if (entity.getIntermediate()) types.add(NodeTypeDTO.INTERMEDIATE); if (entity.getIntermediate()) types.add(NodeType.INTERMEDIATE);
dto.setId(entity.getId()); dto.setId(entity.getId());
dto.setName(entity.getName()); dto.setName(entity.getName());
dto.setAddress(entity.getAddress()); dto.setAddress(entity.getAddress());
dto.setCountry(countryTransformerService.toCountryDTO(countryRepository.getById(entity.getCountryId())).orElseThrow()); dto.setCountry(countryTransformerService.toCountryDTO(countryRepository.getById(entity.getCountryId()).orElseThrow()));
dto.setTypes(types); dto.setTypes(types);
dto.setDeprecated(entity.getDeprecated()); dto.setDeprecated(entity.getDeprecated());
dto.setLocation(locationTransformer.toLocationDTO(entity)); dto.setLocation(locationTransformer.toLocationDTO(entity));
dto.setUserNode(false);
return dto; return dto;
} }

View file

@ -0,0 +1,36 @@
package de.avatic.lcc.service.transformer.material;
import de.avatic.lcc.dto.generic.PropertyDTO;
import de.avatic.lcc.model.properties.PackagingProperty;
import org.springframework.stereotype.Service;
/**
* Service that transforms {@link PackagingProperty} objects into {@link PropertyDTO} objects.
* This transformer handles the conversion of material packaging properties into a format
* that can be used in other application layers.
*/
@Service
public class MaterialDetailPackagingPropertyTransformer {
/**
* Converts a {@link PackagingProperty} object to a {@link PropertyDTO}.
* This method maps the values and metadata of packaging properties for external consumption.
*
* @param property the {@link PackagingProperty} to transform
* @return the transformed {@link PropertyDTO} object with mapped values
*/
public PropertyDTO toPropertyDTO(PackagingProperty property) {
PropertyDTO dto = new PropertyDTO();
dto.setCurrentValue(property.getValue());
dto.setDataType(property.getType().getDataType().name());
dto.setRequired(property.getType().getRequired());
dto.setName(property.getType().getName());
dto.setExternalMappingId(property.getType().getExternalMappingId());
dto.setValidationRule(property.getType().getValidationRule());
return dto;
}
}

View file

@ -0,0 +1,78 @@
package de.avatic.lcc.service.transformer.material;
import de.avatic.lcc.dto.configuration.material.view.MaterialDetailPackagingDTO;
import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.model.packaging.Packaging;
import de.avatic.lcc.model.packaging.PackagingDimension;
import de.avatic.lcc.model.properties.PackagingProperty;
import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.packaging.PackagingDimensionRepository;
import de.avatic.lcc.repositories.packaging.PackagingPropertiesRepository;
import de.avatic.lcc.service.transformer.generic.DimensionTransformer;
import de.avatic.lcc.service.transformer.generic.NodeTransformer;
import org.springframework.data.mapping.model.Property;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
import static java.util.stream.Collectors.toList;
/**
* Transformer service to convert {@link Packaging} entities into {@link MaterialDetailPackagingDTO} objects.
* This service includes logic for mapping associated supplier, dimensions, and properties.
*/
@Service
public class MaterialDetailPackagingTransformer {
private final NodeRepository nodeRepository;
private final PackagingDimensionRepository packagingDimensionRepository;
private final DimensionTransformer dimensionTransformer;
private final NodeTransformer nodeTransformer;
private final PackagingPropertiesRepository packagingPropertiesRepository;
private final MaterialDetailPackagingPropertyTransformer materialDetailPackagingPropertyTransformer;
/**
* Constructs a MaterialDetailPackagingTransformer with required dependencies.
*
* @param nodeRepository Repository for managing {@link Node} entities
* @param packagingDimensionRepository Repository for managing {@link PackagingDimension} entities
* @param dimensionTransformer Transformer for converting dimensions into DTOs
* @param nodeTransformer Transformer for converting nodes into DTOs
* @param packagingPropertiesRepository Repository for managing packaging properties
* @param materialDetailPackagingPropertyTransformer Transformer for converting packaging properties into DTOs
*/
public MaterialDetailPackagingTransformer(NodeRepository nodeRepository, PackagingDimensionRepository packagingDimensionRepository, DimensionTransformer dimensionTransformer, NodeTransformer nodeTransformer, PackagingPropertiesRepository packagingPropertiesRepository, MaterialDetailPackagingPropertyTransformer materialDetailPackagingPropertyTransformer) {
this.nodeRepository = nodeRepository;
this.packagingDimensionRepository = packagingDimensionRepository;
this.dimensionTransformer = dimensionTransformer;
this.nodeTransformer = nodeTransformer;
this.packagingPropertiesRepository = packagingPropertiesRepository;
this.materialDetailPackagingPropertyTransformer = materialDetailPackagingPropertyTransformer;
}
/**
* Converts a {@link Packaging} entity into a {@link MaterialDetailPackagingDTO}.
*
* @param entity The {@link Packaging} entity to transform
* @return The transformed {@link MaterialDetailPackagingDTO} object
* @throws java.util.NoSuchElementException if any referenced related entity is not found
*/
public MaterialDetailPackagingDTO toMaterialViewPackagingDTO(Packaging entity) {
Optional<Node> supplier = nodeRepository.getById(entity.getSupplierId());
Optional<PackagingDimension> hu = packagingDimensionRepository.getById(entity.getHuId());
Optional<PackagingDimension> shu = packagingDimensionRepository.getById(entity.getShuId());
List<PackagingProperty> properties = packagingPropertiesRepository.getByPackagingId(entity.getId());
MaterialDetailPackagingDTO dto = new MaterialDetailPackagingDTO();
dto.setId(entity.getId());
dto.setDeprecated(entity.getDeprecated());
dto.setHu(dimensionTransformer.toDimensionDTO(hu.orElseThrow()));
dto.setShu(dimensionTransformer.toDimensionDTO(shu.orElseThrow()));
dto.setSupplier(nodeTransformer.toNodeDTO(supplier.orElseThrow()));
dto.setProperties(properties.stream().map(materialDetailPackagingPropertyTransformer::toPropertyDTO).toList());
return dto;
}
}

View file

@ -0,0 +1,47 @@
package de.avatic.lcc.service.transformer.material;
import de.avatic.lcc.dto.configuration.material.view.MaterialDetailDTO;
import de.avatic.lcc.dto.configuration.material.view.MaterialDetailPackagingDTO;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.repositories.packaging.PackagingRepository;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Transforms {@link Material} entities into {@link MaterialDetailDTO} objects.
* This is used to map material entity data to a DTO for viewing material details.
*/
@Service
public class MaterialDetailTransformer {
private final PackagingRepository packagingRepository;
private final MaterialDetailPackagingTransformer materialDetailPackagingTransformer;
public MaterialDetailTransformer(PackagingRepository packagingRepository, MaterialDetailPackagingTransformer materialDetailPackagingTransformer) {
this.packagingRepository = packagingRepository;
this.materialDetailPackagingTransformer = materialDetailPackagingTransformer;
}
/**
* Converts a {@link Material} entity into a {@link MaterialDetailDTO}.
*
* @param entity the material entity to convert
* @return a {@link MaterialDetailDTO} containing detailed information about the material
*/
public MaterialDetailDTO toMaterialDetailDTO(Material entity) {
MaterialDetailDTO dto = new MaterialDetailDTO();
List<MaterialDetailPackagingDTO> packaging = packagingRepository.getByMaterialId(entity.getId()).stream().map(materialDetailPackagingTransformer::toMaterialViewPackagingDTO).toList();
dto.setId(entity.getId());
dto.setPartNumber(entity.getPartNumber());
dto.setName(entity.getName());
dto.setHsCode(entity.getHsCode());
dto.setHandlingUnits(packaging);
return dto;
}
}

View file

@ -4,6 +4,7 @@ import de.avatic.lcc.dto.configuration.material.update.MaterialUpdateDTO;
import de.avatic.lcc.model.materials.Material; import de.avatic.lcc.model.materials.Material;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Deprecated
@Service @Service
public class MaterialUpdateDTOTransformer { public class MaterialUpdateDTOTransformer {

View file

@ -1,27 +0,0 @@
package de.avatic.lcc.service.transformer.material;
import de.avatic.lcc.dto.configuration.material.view.MaterialViewDTO;
import de.avatic.lcc.dto.configuration.material.view.MaterialViewPackagingDTO;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.repositories.packaging.PackagingRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class MaterialViewDTOTransformer {
private final PackagingRepository packagingRepository;
private final MaterialViewPackagingDTOTransformer materialViewPackagingDTOTransformer;
public MaterialViewDTOTransformer(PackagingRepository packagingRepository, MaterialViewPackagingDTOTransformer materialViewPackagingDTOTransformer) {
this.packagingRepository = packagingRepository;
this.materialViewPackagingDTOTransformer = materialViewPackagingDTOTransformer;
}
public MaterialViewDTO toMaterialViewDTO(Material material) {
List<MaterialViewPackagingDTO> packaging = packagingRepository.getByMaterialId(material.getId()).stream().map(materialViewPackagingDTOTransformer::toMaterialViewPackagingDTO).toList();
}
}

View file

@ -1,45 +0,0 @@
package de.avatic.lcc.service.transformer.material;
import de.avatic.lcc.dto.configuration.material.view.MaterialViewPackagingDTO;
import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.model.packaging.Packaging;
import de.avatic.lcc.model.packaging.PackagingDimension;
import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.packaging.PackagingDimensionRepository;
import de.avatic.lcc.service.transformer.generic.DimensionTransformer;
import de.avatic.lcc.service.transformer.generic.NodeTransformer;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
public class MaterialViewPackagingDTOTransformer {
private final NodeRepository nodeRepository;
private final PackagingDimensionRepository packagingDimensionRepository;
private final DimensionTransformer dimensionTransformer;
private final NodeTransformer nodeTransformer;
public MaterialViewPackagingDTOTransformer(NodeRepository nodeRepository, PackagingDimensionRepository packagingDimensionRepository, DimensionTransformer dimensionTransformer, NodeTransformer nodeTransformer) {
this.nodeRepository = nodeRepository;
this.packagingDimensionRepository = packagingDimensionRepository;
this.dimensionTransformer = dimensionTransformer;
this.nodeTransformer = nodeTransformer;
}
public MaterialViewPackagingDTO toMaterialViewPackagingDTO(Packaging entity) {
Optional<Node> supplier = nodeRepository.getById(entity.getSupplierId());
Optional<PackagingDimension> hu = packagingDimensionRepository.getById(entity.getHuId());
Optional<PackagingDimension> shu = packagingDimensionRepository.getById(entity.getShuId());
MaterialViewPackagingDTO dto = new MaterialViewPackagingDTO();
dto.setId(entity.getId());
dto.setDeprecated(entity.getDeprecated());
dto.setHu(dimensionTransformer.toDimensionDTO(hu.orElseThrow()));
dto.setShu(dimensionTransformer.toDimensionDTO(shu.orElseThrow()));
dto.setSupplier(nodeTransformer.toNodeDTO(supplier.orElseThrow()));
return dto;
}
}

View file

@ -1,7 +1,7 @@
package de.avatic.lcc.service.transformer.nodes; package de.avatic.lcc.service.transformer.nodes;
import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.generic.NodeTypeDTO; import de.avatic.lcc.dto.generic.NodeType;
import de.avatic.lcc.dto.configuration.nodes.view.NodeDetailDTO; import de.avatic.lcc.dto.configuration.nodes.view.NodeDetailDTO;
import de.avatic.lcc.model.nodes.Node; import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.repositories.country.CountryRepository; import de.avatic.lcc.repositories.country.CountryRepository;
@ -16,7 +16,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
@Service @Service
public class NodeViewDTOTransformer { public class NodeDetailTransformer {
private final CountryTransformer countryTransformer; private final CountryTransformer countryTransformer;
private final CountryRepository countryRepository; private final CountryRepository countryRepository;
@ -24,7 +24,7 @@ public class NodeViewDTOTransformer {
private final NodeTransformer nodeTransformer; private final NodeTransformer nodeTransformer;
private final NodeRepository nodeRepository; private final NodeRepository nodeRepository;
public NodeViewDTOTransformer(CountryTransformer countryTransformer, CountryRepository countryRepository, LocationTransformer locationTransformer, NodeTransformer nodeTransformer, NodeRepository nodeRepository) { public NodeDetailTransformer(CountryTransformer countryTransformer, CountryRepository countryRepository, LocationTransformer locationTransformer, NodeTransformer nodeTransformer, NodeRepository nodeRepository) {
this.countryTransformer = countryTransformer; this.countryTransformer = countryTransformer;
this.countryRepository = countryRepository; this.countryRepository = countryRepository;
this.locationTransformer = locationTransformer; this.locationTransformer = locationTransformer;
@ -53,11 +53,11 @@ public class NodeViewDTOTransformer {
return dto; return dto;
} }
private ArrayList<NodeTypeDTO> toNodeTypeArrayList(Node entity) { private ArrayList<NodeType> toNodeTypeArrayList(Node entity) {
ArrayList<NodeTypeDTO> types = new ArrayList<>(); ArrayList<NodeType> types = new ArrayList<>();
if (entity.getSink()) types.add(NodeTypeDTO.DESTINATION); if (entity.getSink()) types.add(NodeType.DESTINATION);
if (entity.getSource()) types.add(NodeTypeDTO.SOURCE); if (entity.getSource()) types.add(NodeType.SOURCE);
if (entity.getIntermediate()) types.add(NodeTypeDTO.INTERMEDIATE); if (entity.getIntermediate()) types.add(NodeType.INTERMEDIATE);
return types; return types;
} }

View file

@ -13,7 +13,7 @@ public class NodeUpdateDTOTransformer {
Node entity = new Node(); Node entity = new Node();
entity.setId(dto.getId()); entity.setId(dto.getId());
entity.setSink(dto.get); //entity.setSink(dto.get);
return entity; return entity;
} }

View file

@ -1,69 +0,0 @@
package de.avatic.lcc.service.transformer.packaging;
import de.avatic.lcc.dto.configuration.packaging.view.PackagingViewDTO;
import de.avatic.lcc.dto.configuration.packaging.update.PackagingUpdateDTO;
import de.avatic.lcc.model.country.Country;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.model.packaging.Packaging;
import de.avatic.lcc.model.packaging.PackagingDimension;
import de.avatic.lcc.model.properties.PackagingProperty;
import de.avatic.lcc.service.transformer.generic.DimensionTransformer;
import de.avatic.lcc.service.transformer.generic.MaterialTransformer;
import de.avatic.lcc.service.transformer.generic.NodeTransformer;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class PackagingTransformerService {
//TODO refactor to new format
private final MaterialTransformer materialTransformer;
private final DimensionTransformer dimensionTransformer;
private final NodeTransformer nodeTransformer;
private final PackagingViewPropertyDTOTransformer packagingViewPropertyDTOTransformer;
public PackagingTransformerService(MaterialTransformer materialTransformer, DimensionTransformer dimensionTransformer, NodeTransformer nodeTransformer, PackagingViewPropertyDTOTransformer packagingViewPropertyDTOTransformer) {
this.materialTransformer = materialTransformer;
this.dimensionTransformer = dimensionTransformer;
this.nodeTransformer = nodeTransformer;
this.packagingViewPropertyDTOTransformer = packagingViewPropertyDTOTransformer;
}
public Optional<PackagingViewDTO> convertToPackagingGetDTO(Optional<Packaging> packaging, Optional<Material> material, Optional<Node> supplier, Optional<Country> country, Optional<PackagingDimension> hu, Optional<PackagingDimension> shu, List<PackagingProperty> properties) {
if(packaging.isEmpty()) return Optional.empty();
Packaging data = packaging.get();
var dto = new PackagingViewDTO();
dto.setId(data.getId());
dto.setMaterial(materialTransformer.toMaterialDTO(material.orElseThrow()));
dto.setSupplier(nodeTransformer.toNodeDTO(supplier.orElseThrow()));
dto.setHu(dimensionTransformer.toDimensionDTO(hu.orElseThrow()));
dto.setShu(dimensionTransformer.toDimensionDTO(shu.orElseThrow()));
dto.setDeprecated(data.getDeprecated());
dto.setProperties(properties.stream().map(packagingViewPropertyDTOTransformer::toPackagingViewPropertyDTO).toList());
return Optional.of(dto);
}
public Packaging convertFromPackagingPostDTO(PackagingUpdateDTO dto) {
var entity = new Packaging();
entity.setId(dto.getId());
entity.setDeprecated(dto.getDeprecated());
entity.setSupplierId(dto.getSupplierId());
entity.setMaterialId(dto.getMaterialId());
entity.setHuId(dto.getHu().getId());
entity.setShuId(dto.getShu().getId());
return entity;
}
}

View file

@ -1,22 +0,0 @@
package de.avatic.lcc.service.transformer.packaging;
import de.avatic.lcc.dto.configuration.packaging.view.PackagingViewPropertyDTO;
import de.avatic.lcc.model.properties.PackagingProperty;
import org.springframework.stereotype.Service;
@Service
public class PackagingViewPropertyDTOTransformer {
public PackagingViewPropertyDTO toPackagingViewPropertyDTO(PackagingProperty property) {
PackagingViewPropertyDTO dto = new PackagingViewPropertyDTO();
dto.setCurrentValue(property.getValue());
dto.setDataType(property.getType().getDataType().name());
dto.setRequired(property.getType().getRequired());
dto.setName(property.getType().getName());
dto.setExternalMappingId(property.getType().getExternalMappingId());
dto.setValidationRule(property.getType().getValidationRule());
return dto;
}
}

View file

@ -22,7 +22,6 @@ public class UserTransformer {
} }
public User fromUserDTO(UserDTO dto) { public User fromUserDTO(UserDTO dto) {
User entity = new User(); User entity = new User();

View file

@ -35,7 +35,8 @@ CREATE TABLE IF NOT EXISTS `system_property`
FOREIGN KEY (`property_set_id`) REFERENCES `property_set` (`id`), FOREIGN KEY (`property_set_id`) REFERENCES `property_set` (`id`),
FOREIGN KEY (`system_property_type_id`) REFERENCES `system_property_type` (`id`), FOREIGN KEY (`system_property_type_id`) REFERENCES `system_property_type` (`id`),
INDEX `idx_system_property_type_id` (system_property_type_id), INDEX `idx_system_property_type_id` (system_property_type_id),
INDEX `idx_property_set_id` (id) INDEX `idx_property_set_id` (id),
UNIQUE KEY `idx_country_property` (`system_property_type_id`, `property_set_id`)
) COMMENT 'Stores system-wide configuration properties'; ) COMMENT 'Stores system-wide configuration properties';
-- country -- country