Refactor packaging-related classes and add new repository/service/controller.

Replaced `SearchQueryResult` utility class with a more robust `SearchQueryResult` under a new pagination package. Introduced `PackagingRepository` and `PackagingController` to manage packaging entities. Enhanced data models with new entities (`NodeType`, `PackagingDimension`), and updated existing ones (`Packaging`, `PackagingListEntry`) to improve modularity and support handling units.
This commit is contained in:
Jan 2025-03-25 21:20:22 +01:00
parent 6467a17cf8
commit 2b0ee0d417
18 changed files with 766 additions and 317 deletions

View file

@ -2,7 +2,7 @@ package de.avatic.lcc.controller;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.model.materials.MaterialListEntry;
import de.avatic.lcc.repositories.utils.SearchQueryResult;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.service.MaterialService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;

View file

@ -0,0 +1,69 @@
package de.avatic.lcc.controller;
import de.avatic.lcc.model.packaging.Packaging;
import de.avatic.lcc.model.packaging.PackagingListEntry;
import de.avatic.lcc.repositories.PackagingRepository;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.service.PackagingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/packaging")
public class PackagingController {
private final PackagingRepository packagingRepository;
private final PackagingService packagingService;
@Autowired
public PackagingController(PackagingRepository packagingRepository, PackagingService packagingService) {
this.packagingRepository = packagingRepository;
this.packagingService = packagingService;
}
@GetMapping("/")
public ResponseEntity<List<PackagingListEntry>> listPackaging(
@RequestParam(defaultValue = "20") int limit,
@RequestParam(defaultValue = "0") int page,
@RequestParam(required = false) Integer materialId,
@RequestParam(required = false) Integer supplierId) {
SearchQueryResult<PackagingListEntry> listEntries = packagingService.listPackaging(materialId, supplierId, page, limit);
return ResponseEntity.ok()
.header("X-Total-Count", String.valueOf(listEntries.getTotalElements()))
.header("X-Page-Count", String.valueOf(listEntries.getTotalPages()))
.header("X-Current-Page", String.valueOf(page))
.body(listEntries.toList());
}
@GetMapping("/{id}")
public ResponseEntity<Packaging> getPackagingDetails(@PathVariable Integer id) {
return ResponseEntity.ok(packagingService.getPackaging(id));
}
@PutMapping("/{id}")
public ResponseEntity<Void> updatePackaging(@PathVariable Integer id, @RequestBody Packaging packaging) {
packagingService.updatePackaging(id, packaging);
return ResponseEntity.noContent().build();
}
@DeleteMapping("/{id}")
public ResponseEntity<Integer> deletePackagingDetails(@PathVariable Integer id) {
return ResponseEntity.ok(packagingService.deletePackaging(id));
}
@PostMapping("/")
public ResponseEntity<Integer> addPackaging(@RequestBody Packaging packaging) {
return ResponseEntity.ok(packagingService.addPackaging(packaging));
}
}

View file

@ -4,5 +4,24 @@ public class Location {
private Double longitude;
private Double latitude;
// Getters and setters
public Location(Double longitude, Double latitude) {
this.longitude = longitude;
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
}

View file

@ -10,8 +10,7 @@ public class NodeListEntry {
private String name;
private CountryListEntry country;
private String address;
private Location location;
private List<String> types;
private List<NodeType> types;
public String getName() {
@ -46,19 +45,11 @@ public class NodeListEntry {
this.address = address;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public List<String> getTypes() {
public List<NodeType> getTypes() {
return types;
}
public void setTypes(List<String> types) {
public void setTypes(List<NodeType> types) {
this.types = types;
}
}

View file

@ -0,0 +1,18 @@
package de.avatic.lcc.model.nodes;
import com.fasterxml.jackson.annotation.JsonValue;
public enum NodeType {
SINK("sink"), SOURCE("source"), INTERMEDIATE("intermediate");
private final String displayedType;
NodeType(String displayedType) {
this.displayedType = displayedType;
}
@JsonValue
public String getDisplayedType() {
return displayedType;
}
}

View file

@ -12,5 +12,44 @@ package de.avatic.lcc.model.packaging;
* - MM: Millimeters
*/
public enum DimensionUnit {
M, CM, MM
M("m", 1000.0),
CM("cm", 10.0),
MM("mm", 1.0);
private final String displayedName;
private final double baseFactor;
DimensionUnit(String displayedName, double baseFactor) {
this.displayedName = displayedName;
this.baseFactor = baseFactor;
}
@JsonValue
public String getDisplayedName() {
return displayedName;
}
/**
* Converts a value from one dimension unit to this unit.
*
* @param value the value to convert
* @param fromUnit the source unit
* @return the converted value
* @throws IllegalArgumentException if value or fromUnit is null
*/
public Double convertFrom(Number value, DimensionUnit fromUnit) {
if (value == null || fromUnit == null) {
throw new IllegalArgumentException("Value and fromUnit must not be null");
}
// Convert to base unit (millimeters)
double valueInBaseUnit = value.doubleValue() * fromUnit.baseFactor;
// Convert from base unit to target unit
return valueInBaseUnit / this.baseFactor;
}
public Double convertFromMM(Number value) {
return convertFrom(value, MM);
}
}

View file

@ -1,7 +1,10 @@
package de.avatic.lcc.model.packaging;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.model.materials.MaterialListEntry;
import de.avatic.lcc.model.nodes.Node;
import de.avatic.lcc.model.nodes.NodeListEntry;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import jdk.jfr.Unsigned;
@ -13,62 +16,23 @@ import org.springframework.data.relational.core.mapping.Table;
import java.util.Set;
/**
* Represents a packaging entity in the system. This class defines various
* attributes related to a packaging, including its dimensions, weight, type,
* and associations with other entities such as material and supplier nodes.
* It is used to manage packaging details in the application.
*
* The packaging entity contains details about its size, weight, and content,
* as well as its hierarchical relationship with other packaging or a parent
* packaging.
*/
@Table(name = "packaging")
public class Packaging {
@Id
private Integer id;
@NotNull
@Size(max = 3)
private PackagingType type;
@Unsigned
@NotNull
private Integer length;
@Unsigned
@NotNull
private Integer width;
@Unsigned
@NotNull
private Integer height;
@NotNull
private DimensionUnit displayedDimensionUnit;
@NotNull
private Integer weight;
@NotNull
private WeightUnit displayedWeightUnit;
@NotNull
private Integer contentUnitCount;
@JsonProperty("is_deprecated")
private Boolean isDeprecated;
@NotNull
private AggregateReference<Node,Integer> supplierNode;
private NodeListEntry supplier;
@NotNull
private AggregateReference<Material, Integer> material;
private MaterialListEntry material;
private AggregateReference<Packaging, Integer> parent;
@JsonProperty("handling_unit")
private PackagingDimension hu;
@MappedCollection(idColumn = "packaging_id")
private Set<PackagingProperty> properties;
@JsonProperty("small_handling_unit")
private PackagingDimension shu;
public Integer getId() {
return id;
@ -78,70 +42,6 @@ public class Packaging {
this.id = id;
}
public PackagingType getType() {
return type;
}
public void setType(PackagingType type) {
this.type = type;
}
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public DimensionUnit getDisplayedDimensionUnit() {
return displayedDimensionUnit;
}
public void setDisplayedDimensionUnit(DimensionUnit displayedDimensionUnit) {
this.displayedDimensionUnit = displayedDimensionUnit;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public WeightUnit getDisplayedWeightUnit() {
return displayedWeightUnit;
}
public void setDisplayedWeightUnit(WeightUnit displayedWeightUnit) {
this.displayedWeightUnit = displayedWeightUnit;
}
public Integer getContentUnitCount() {
return contentUnitCount;
}
public void setContentUnitCount(Integer contentUnitCount) {
this.contentUnitCount = contentUnitCount;
}
public Boolean getDeprecated() {
return isDeprecated;
}
@ -150,27 +50,35 @@ public class Packaging {
isDeprecated = deprecated;
}
public AggregateReference<Node, Integer> getSupplierNode() {
return supplierNode;
public NodeListEntry getSupplier() {
return supplier;
}
public void setSupplierNode(AggregateReference<Node, Integer> supplierNode) {
this.supplierNode = supplierNode;
public void setSupplier(NodeListEntry supplier) {
this.supplier = supplier;
}
public AggregateReference<Material, Integer> getMaterial() {
public MaterialListEntry getMaterial() {
return material;
}
public void setMaterial(AggregateReference<Material, Integer> material) {
public void setMaterial(MaterialListEntry material) {
this.material = material;
}
public AggregateReference<Packaging, Integer> getParent() {
return parent;
public PackagingDimension getHu() {
return hu;
}
public void setParent(AggregateReference<Packaging, Integer> parent) {
this.parent = parent;
public void setHu(PackagingDimension hu) {
this.hu = hu;
}
public PackagingDimension getShu() {
return shu;
}
public void setShu(PackagingDimension shu) {
this.shu = shu;
}
}

View file

@ -0,0 +1,110 @@
package de.avatic.lcc.model.packaging;
import com.fasterxml.jackson.annotation.JsonProperty;
public class PackagingDimension {
private Integer id;
private PackagingType type;
private Double length;
private Double width;
private Double height;
@JsonProperty("dimension_unit")
private DimensionUnit dimensionUnit;
private Double weight;
@JsonProperty("weight_unit")
private WeightUnit weightUnit;
@JsonProperty("content_unit_count")
private Integer contentUnitCount;
@JsonProperty("is_deprecated")
private Boolean isDeprecated;
public PackagingType getType() {
return type;
}
public void setType(PackagingType type) {
this.type = type;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Double getLength() {
return length;
}
public void setLength(Double length) {
this.length = length;
}
public Double getWidth() {
return width;
}
public void setWidth(Double width) {
this.width = width;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
public DimensionUnit getDimensionUnit() {
return dimensionUnit;
}
public void setDimensionUnit(DimensionUnit dimensionUnit) {
this.dimensionUnit = dimensionUnit;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
public WeightUnit getWeightUnit() {
return weightUnit;
}
public void setWeightUnit(WeightUnit weightUnit) {
this.weightUnit = weightUnit;
}
public Integer getContentUnitCount() {
return contentUnitCount;
}
public void setContentUnitCount(Integer contentUnitCount) {
this.contentUnitCount = contentUnitCount;
}
public Boolean getDeprecated() {
return isDeprecated;
}
public void setDeprecated(Boolean deprecated) {
isDeprecated = deprecated;
}
}

View file

@ -1,6 +1,7 @@
package de.avatic.lcc.model.packaging;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.avatic.lcc.model.materials.MaterialListEntry;
import de.avatic.lcc.model.nodes.NodeListEntry;
public class PackagingListEntry {
@ -9,33 +10,10 @@ public class PackagingListEntry {
private NodeListEntry supplier;
@JsonProperty("parent_id")
private Integer parentId;
private MaterialListEntry material;
private Double width;
private Double height;
private Double length;
@JsonProperty("dimension_unit")
private String dimensionUnit;
private Double weight;
@JsonProperty("weight_unit")
private String weightUnit;
@JsonProperty("content_unit_count")
private Integer contentUnitCount;
private String type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@JsonProperty("handling_unit")
private PackagingDimension hu;
public Integer getId() {
return id;
@ -53,67 +31,19 @@ public class PackagingListEntry {
this.supplier = supplier;
}
public Integer getParentId() {
return parentId;
public MaterialListEntry getMaterial() {
return material;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
public void setMaterial(MaterialListEntry material) {
this.material = material;
}
public Double getWidth() {
return width;
public PackagingDimension getHu() {
return hu;
}
public void setWidth(Double width) {
this.width = width;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
public Double getLength() {
return length;
}
public void setLength(Double length) {
this.length = length;
}
public String getDimensionUnit() {
return dimensionUnit;
}
public void setDimensionUnit(String dimensionUnit) {
this.dimensionUnit = dimensionUnit;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
public String getWeightUnit() {
return weightUnit;
}
public void setWeightUnit(String weightUnit) {
this.weightUnit = weightUnit;
}
public Integer getContentUnitCount() {
return contentUnitCount;
}
public void setContentUnitCount(Integer contentUnitCount) {
this.contentUnitCount = contentUnitCount;
public void setHu(PackagingDimension hu) {
this.hu = hu;
}
}

View file

@ -7,16 +7,12 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.data.relational.core.mapping.Table;
@Table(name = "packaging_property")
public class PackagingProperty {
@Id
private Integer id;
@Size(max = 500)
private String propertyValue;
@NotNull
private AggregateReference<PackagingPropertyType,Integer> packagingPropertyType;
}

View file

@ -1,5 +1,6 @@
package de.avatic.lcc.model.packaging;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* Represents the supported units of weight measurement in the system.
@ -12,8 +13,44 @@ package de.avatic.lcc.model.packaging;
* - G: Grams
*/
public enum WeightUnit {
T,
KG,
G
T("t", 1000000.0),
KG("kg", 1000.0),
G("g", 1.0);
private final String displayedName;
private final double baseFactor;
WeightUnit(String displayedName, double baseFactor) {
this.displayedName = displayedName;
this.baseFactor = baseFactor;
}
@JsonValue
public String getDisplayedName() {
return displayedName;
}
/**
* Converts a value from one weight unit to this unit.
*
* @param value the value to convert
* @param fromUnit the source unit
* @return the converted value
* @throws IllegalArgumentException if value or fromUnit is null
*/
public Double convertFrom(Number value, WeightUnit fromUnit) {
if (value == null || fromUnit == null) {
throw new IllegalArgumentException("Value and fromUnit must not be null");
}
// Convert to base unit (grams)
double valueInBaseUnit = value.doubleValue() * fromUnit.baseFactor;
// Convert from base unit to target unit
return valueInBaseUnit / this.baseFactor;
}
public Double convertFromG(Number value) {
return convertFrom(value, G);
}
}

View file

@ -4,10 +4,11 @@ import de.avatic.lcc.model.country.CountryListEntry;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.model.materials.MaterialListEntry;
import de.avatic.lcc.model.nodes.NodeListEntry;
import de.avatic.lcc.model.packaging.DimensionUnit;
import de.avatic.lcc.model.packaging.PackagingListEntry;
import de.avatic.lcc.repositories.utils.SearchQueryPagination;
import de.avatic.lcc.repositories.utils.SearchQueryResult;
import de.avatic.lcc.repositories.utils.UnitConverter;
import de.avatic.lcc.model.packaging.WeightUnit;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
@ -72,30 +73,33 @@ public class MaterialRepository {
// Query packaging data for the material
String packagingQuery = """
SELECT packaging.id, parent_id, width, height, length, packaging.displayed_dimension_unit, weight, displayed_weight_unit,
content_unit_count, type,
SELECT packaging.id,
packaging_dimension.id AS hu_dimension_id, packaging_dimension.displayed_dimension_unit AS displayed_dimension_unit,
packaging_dimension.displayed_weight_unit AS displayed_weight_unit, packaging_dimension.width AS width,
packaging_dimension.length AS length, packaging_dimension.height AS height,
packaging_dimension.content_unit_count AS content_unit_count, packaging_dimension.type AS type,
node.id AS supplier_id, node.name AS supplier_name, node.address AS supplier_address,
country.id AS country_id, country.name AS country_name, country.iso_code AS country_iso_code, country.region_code AS country_region_code
FROM packaging
LEFT JOIN packaging_dimension ON packaging.hu_dimension_id = packaging_dimension.id
LEFT JOIN node ON packaging.supplier_node_id = node.id
LEFT JOIN country ON node.country_id = country.id
WHERE material_id = ? AND packaging.is_deprecated = FALSE
""";
if (material != null) {
PackagingListEntry packaging = jdbcTemplate.queryForObject(packagingQuery, (packagingRs, packagingRowNum) -> {
PackagingListEntry packagingEntry = new PackagingListEntry();
String dimensionUnit = packagingRs.getString("displayed_dimension_unit");
String weightUnit = packagingRs.getString("displayed_weight_unit");
DimensionUnit dimensionUnit = DimensionUnit.valueOf(packagingRs.getString("displayed_dimension_unit"));
WeightUnit weightUnit = WeightUnit.valueOf(packagingRs.getString("displayed_weight_unit"));
packagingEntry.setId(packagingRs.getInt("id"));
packagingEntry.setParentId(packagingRs.getInt("parent_id"));
packagingEntry.setWidth(UnitConverter.convert(packagingRs.getInt("width"), dimensionUnit));
packagingEntry.setHeight(UnitConverter.convert(packagingRs.getInt("height"), dimensionUnit));
packagingEntry.setLength(UnitConverter.convert(packagingRs.getInt("length"), dimensionUnit));
packagingEntry.setWidth(dimensionUnit.convertFromMM(packagingRs.getInt("width")));
packagingEntry.setHeight(dimensionUnit.convertFromMM(packagingRs.getInt("height")));
packagingEntry.setLength(dimensionUnit.convertFromMM(packagingRs.getInt("length")));
packagingEntry.setDimensionUnit(dimensionUnit);
packagingEntry.setWeight(UnitConverter.convert(packagingRs.getInt("weight"), weightUnit));
packagingEntry.setWeight(weightUnit.convertFromG(packagingRs.getInt("weight")));
packagingEntry.setWeightUnit(weightUnit);
packagingEntry.setContentUnitCount(packagingRs.getInt("content_unit_count"));
packagingEntry.setType(packagingRs.getString("type"));
@ -104,9 +108,9 @@ public class MaterialRepository {
NodeListEntry supplier = new NodeListEntry();
supplier.setId(packagingRs.getInt("supplier_id"));
supplier.setName(packagingRs.getString("supplier_name"));
supplier.setAddress(packagingRs.getString("supplier_address"));
if(packagingRs.getObject("country_id") != null) {
if (packagingRs.getObject("country_id") != null) {
CountryListEntry country = new CountryListEntry();
country.setId(packagingRs.getInt("country_id"));
country.setName(packagingRs.getString("country_name"));
@ -122,7 +126,6 @@ public class MaterialRepository {
}, material.getId());
material.setPackaging(packaging);
}
return Optional.of(material);
}

View file

@ -0,0 +1,233 @@
package de.avatic.lcc.repositories;
import de.avatic.lcc.model.country.CountryListEntry;
import de.avatic.lcc.model.materials.MaterialListEntry;
import de.avatic.lcc.model.nodes.Location;
import de.avatic.lcc.model.nodes.NodeListEntry;
import de.avatic.lcc.model.nodes.NodeType;
import de.avatic.lcc.model.packaging.*;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Repository
public class PackagingRepository {
private final JdbcTemplate jdbcTemplate;
public PackagingRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Transactional
public SearchQueryResult<PackagingListEntry> listPackaging(Integer materialId, Integer supplierId, boolean excludeDeprecated, SearchQueryPagination pagination) {
StringBuilder queryBuilder = new StringBuilder("""
SELECT id,
FROM packaging
WHERE packaging.is_deprecated = ?""");
if (materialId != null) {
queryBuilder.append(" AND material_id = ?");
}
if (supplierId != null) {
queryBuilder.append(" AND supplier_node_id = ?");
}
queryBuilder.append(" LIMIT ? OFFSET ?");
var params = new ArrayList<Object>();
params.add(excludeDeprecated);
if (materialId != null) {
params.add(materialId);
}
if (supplierId != null) {
params.add(supplierId);
}
params.add(pagination.getLimit());
params.add(pagination.getOffset());
var entries = jdbcTemplate.query(queryBuilder.toString(), (rs, rowNum) -> {
PackagingListEntry data = new PackagingListEntry();
data.setId(rs.getInt("id"));
data.setHu(getPackagingDimensionById(rs.getInt("hu_dimension_id")).orElse(null) );
data.setMaterial(getMaterialListEntryById(rs.getInt("material_id")).orElse(null) );
data.setSupplier(getNodeListEntryById(rs.getInt("supplier_node_id")).orElse(null) );
return data;
}, params.toArray());
return new SearchQueryResult<>(entries, countPackaging(materialId, supplierId, excludeDeprecated), pagination.getLimit(), pagination.getOffset());
}
private Integer countPackaging(Integer materialId, Integer supplierId, boolean excludeDeprecated) {
StringBuilder queryBuilder = new StringBuilder("""
SELECT COUNT(*)
FROM packaging
WHERE packaging.is_deprecated = ?""");
if (materialId != null) {
queryBuilder.append(" AND material_id = ?");
}
if (supplierId != null) {
queryBuilder.append(" AND supplier_node_id = ?");
}
var params = new ArrayList<Object>();
params.add(excludeDeprecated);
if (materialId != null) {
params.add(materialId);
}
if (supplierId != null) {
params.add(supplierId);
}
return jdbcTemplate.queryForObject(queryBuilder.toString(), Integer.class, params.toArray());
}
@Transactional
public Optional<Packaging> getById(Integer id) {
String query = """
SELECT id, supplier_node_id, material_id, hu_dimension_id, shu_dimension_id, is_deprecated
FROM packaging
WHERE packaging.id = ?""";
var packaging = jdbcTemplate.queryForObject(query, (rs, rowNum) -> {
var data = new Packaging();
data.setId(rs.getInt("id"));
data.setDeprecated(rs.getBoolean("is_deprecated"));
data.setHu(getPackagingDimensionById(rs.getInt("hu_dimension_id")).orElse(null) );
data.setShu(getPackagingDimensionById(rs.getInt("shu_dimension_id")).orElse(null) );
data.setMaterial(getMaterialListEntryById(rs.getInt("material_id")).orElse(null) );
data.setSupplier(getNodeListEntryById(rs.getInt("supplier_node_id")).orElse(null) );
return data;
}, id);
return Optional.ofNullable(packaging) ;
}
/* helper to get material preview move to material repo? */
private Optional<MaterialListEntry> getMaterialListEntryById(Integer id) {
String query = """
SELECT material.id AS id, material.name AS name, material.part_number, material.hs_code
FROM material
WHERE material.id = ?""";
var material = jdbcTemplate.queryForObject(query, (rs, rowNum) -> {
var data = new MaterialListEntry();
data.setId(rs.getInt("id"));
data.setName(rs.getString("name"));
data.setPartNumber(rs.getString("part_number"));
data.setHsCode(rs.getString("hs_code"));
return data;
}, id);
return Optional.ofNullable(material);
}
private Optional<NodeListEntry> getNodeListEntryById(Integer id) {
String query = """
SELECT node.id AS id, node.name AS name, node.address as address, node.is_source as is_source, node.is_sink as is_sink, node.is_intermediate as is_intermediate,
country.id AS country_id, country.name AS country_name, country.iso_code AS country_iso_code, country.region_code AS country_region_code
FROM node
LEFT JOIN country ON node.country_id = country.id
WHERE node.id = ?""";
var node = jdbcTemplate.queryForObject(query, (rs, rowNum) -> {
var data = new NodeListEntry();
var types = new ArrayList<NodeType>();
if(rs.getBoolean("is_source")) { types.add(NodeType.SOURCE); };
if(rs.getBoolean("is_sink")) { types.add(NodeType.SINK); };
if(rs.getBoolean("is_intermediate")) { types.add(NodeType.INTERMEDIATE); };
var countryData = new CountryListEntry();
countryData.setId(rs.getInt("country_id"));
countryData.setName(rs.getString("country_name"));
countryData.setIsoCode(rs.getString("country_iso_code"));
countryData.setRegionCode(rs.getString("country_region_code"));
data.setId(rs.getInt("id"));
data.setName(rs.getString("name"));
data.setAddress(rs.getString("address"));
data.setCountry(countryData);
data.setTypes(types);
return data;
}, id);
return Optional.ofNullable(node);
}
@Transactional
public Optional<PackagingDimension> getPackagingDimensionById(Integer id) {
String query = """
SELECT id, displayed_dimension_unit, displayed_weight_unit, width, length, height,
content_unit_count, type, is_deprecated
FROM packaging_dimension
WHERE packaging_dimension.id = ? AND packaging_dimension.is_deprecated = ?""";
var dimension = jdbcTemplate.queryForObject(query, (rs, rowNum) -> {
var data = new PackagingDimension();
data.setId(rs.getInt("id"));
data.setDimensionUnit(DimensionUnit.valueOf(rs.getString("displayed_dimension_unit")));
data.setWeightUnit(WeightUnit.valueOf(rs.getString("displayed_weight_unit")));
data.setType(PackagingType.valueOf(rs.getString("type")));
data.setDeprecated(rs.getBoolean("is_deprecated"));
data.setWeight(data.getWeightUnit().convertFromG(rs.getInt("weight")));
data.setWidth(data.getDimensionUnit().convertFromMM(rs.getInt("width")));
data.setHeight(data.getDimensionUnit().convertFromMM(rs.getInt("height")));
data.setLength(data.getDimensionUnit().convertFromMM(rs.getInt("length")));
return data;
}, id);
return Optional.ofNullable(dimension);
}
@Transactional
public void update(Packaging packaging) {
//
}
@Transactional
public Optional<Integer> deleteById(Integer id) {
return Optional.empty();
}
@Transactional
public Optional<Integer> create(Packaging packaging) {
return Optional.empty();
}
}

View file

@ -1,4 +1,4 @@
package de.avatic.lcc.repositories.utils;
package de.avatic.lcc.repositories.pagination;
public class SearchQueryPagination {

View file

@ -0,0 +1,106 @@
package de.avatic.lcc.repositories.pagination;
import java.util.List;
/**
* Represents the result of a search query with pagination, holding the list of results
* and metadata related to the pagination (such as current page, total pages, and total elements).
* <p>
* A replacement for org.springframework.data.domain.Page, since this project uses spring jdbc
*
* @param <T> The type of the elements contained in the result.
*/
public class SearchQueryResult<T> {
private List<T> result;
private Integer page, totalPages, totalElements;
/**
* Constructs a new SearchQueryResult with the given result list and pagination metadata.
*
* @param result The list of results for the query.
* @param page The current page number (0-indexed).
* @param totalPages The total number of pages.
* @param totalElements The total number of elements across all pages.
*/
public SearchQueryResult(List<T> result, Integer page, Integer totalPages, Integer totalElements) {
this.result = result;
this.page = page;
this.totalPages = totalPages;
this.totalElements = totalElements;
}
/**
* Returns the list of results in this SearchQueryResult.
*
* @return The list of query results.
*/
public List<T> toList() {
return result;
}
/**
* Sets the list of results for this SearchQueryResult.
*
* @param result The list of query results to set.
*/
public void setResult(List<T> result) {
this.result = result;
}
/**
* Returns the current page number of this SearchQueryResult (0-indexed).
*
* @return The current page number.
*/
public int getPage() {
return page;
}
/**
* Sets the current page number of this SearchQueryResult (0-indexed).
*
* @param page The page number to set.
*/
public void setPage(int page) {
this.page = page;
}
/**
* Returns the total number of pages in this SearchQueryResult.
*
* @return The total number of pages.
*/
public int getTotalPages() {
return totalPages;
}
/**
* Sets the total number of pages for this SearchQueryResult.
*
* @param totalPages The total number of pages to set.
*/
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
/**
* Returns the total number of elements in the search results.
*
* @return The total number of elements.
*/
public int getTotalElements() {
return totalElements;
}
/**
* Sets the total number of elements in the search results.
*
* @param totalElements The total number of elements to set.
*/
public void setTotalElements(int totalElements) {
this.totalElements = totalElements;
}
}

View file

@ -1,49 +0,0 @@
package de.avatic.lcc.repositories.utils;
import java.util.List;
public class SearchQueryResult<T> {
private List<T> result;
private Integer page, totalPages, totalElements;
public SearchQueryResult(List<T> result, Integer page, Integer totalPages, Integer totalElements) {
this.result = result;
this.page = page;
this.totalPages = totalPages;
this.totalElements = totalElements;
}
public List<T> toList() {
return result;
}
public void setResult(List<T> result) {
this.result = result;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getTotalElements() {
return totalElements;
}
public void setTotalElements(int totalElements) {
this.totalElements = totalElements;
}
}

View file

@ -3,8 +3,8 @@ package de.avatic.lcc.service;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.model.materials.MaterialListEntry;
import de.avatic.lcc.repositories.MaterialRepository;
import de.avatic.lcc.repositories.utils.SearchQueryPagination;
import de.avatic.lcc.repositories.utils.SearchQueryResult;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import org.springframework.stereotype.Service;
@Service

View file

@ -0,0 +1,39 @@
package de.avatic.lcc.service;
import de.avatic.lcc.model.packaging.Packaging;
import de.avatic.lcc.model.packaging.PackagingListEntry;
import de.avatic.lcc.repositories.PackagingRepository;
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import org.springframework.stereotype.Service;
@Service
public class PackagingService {
private final PackagingRepository packagingRepository;
public PackagingService(PackagingRepository packagingRepository) {
this.packagingRepository = packagingRepository;
}
public SearchQueryResult<PackagingListEntry> listPackaging(Integer materialId, Integer supplierId, int page, int limit) {
return packagingRepository.listPackaging(materialId, supplierId, true, new SearchQueryPagination(page, limit));
}
public void updatePackaging(Integer id, Packaging packaging) {
packaging.setId(id);
packagingRepository.update(packaging);
}
public Integer deletePackaging(Integer id) {
return packagingRepository.deleteById(id).orElseThrow(() -> new RuntimeException("Packaging does not exists " + id));
}
public Integer addPackaging(Packaging packaging) {
return packagingRepository.create(packaging).orElseThrow(() -> new RuntimeException("Unable to create Packaging " + packaging));
}
public Packaging getPackaging(Integer id) {
return packagingRepository.getById(id).orElseThrow(() -> new RuntimeException("Packaging does not exists " + id));
}
}