diff --git a/src/main/java/de/avatic/lcc/controller/MaterialController.java b/src/main/java/de/avatic/lcc/controller/MaterialController.java index becf544..e732764 100644 --- a/src/main/java/de/avatic/lcc/controller/MaterialController.java +++ b/src/main/java/de/avatic/lcc/controller/MaterialController.java @@ -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; diff --git a/src/main/java/de/avatic/lcc/controller/PackagingController.java b/src/main/java/de/avatic/lcc/controller/PackagingController.java new file mode 100644 index 0000000..ac50fce --- /dev/null +++ b/src/main/java/de/avatic/lcc/controller/PackagingController.java @@ -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> listPackaging( + @RequestParam(defaultValue = "20") int limit, + @RequestParam(defaultValue = "0") int page, + @RequestParam(required = false) Integer materialId, + @RequestParam(required = false) Integer supplierId) { + + SearchQueryResult 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 getPackagingDetails(@PathVariable Integer id) { + return ResponseEntity.ok(packagingService.getPackaging(id)); + } + + + @PutMapping("/{id}") + public ResponseEntity updatePackaging(@PathVariable Integer id, @RequestBody Packaging packaging) { + packagingService.updatePackaging(id, packaging); + return ResponseEntity.noContent().build(); + } + + + @DeleteMapping("/{id}") + public ResponseEntity deletePackagingDetails(@PathVariable Integer id) { + return ResponseEntity.ok(packagingService.deletePackaging(id)); + } + + @PostMapping("/") + public ResponseEntity addPackaging(@RequestBody Packaging packaging) { + return ResponseEntity.ok(packagingService.addPackaging(packaging)); + } + + +} diff --git a/src/main/java/de/avatic/lcc/model/nodes/Location.java b/src/main/java/de/avatic/lcc/model/nodes/Location.java index 3d0b7df..fdd4edb 100644 --- a/src/main/java/de/avatic/lcc/model/nodes/Location.java +++ b/src/main/java/de/avatic/lcc/model/nodes/Location.java @@ -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; + } } diff --git a/src/main/java/de/avatic/lcc/model/nodes/NodeListEntry.java b/src/main/java/de/avatic/lcc/model/nodes/NodeListEntry.java index 8e6c899..ea5cc2f 100644 --- a/src/main/java/de/avatic/lcc/model/nodes/NodeListEntry.java +++ b/src/main/java/de/avatic/lcc/model/nodes/NodeListEntry.java @@ -10,8 +10,7 @@ public class NodeListEntry { private String name; private CountryListEntry country; private String address; - private Location location; - private List types; + private List 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 getTypes() { + public List getTypes() { return types; } - public void setTypes(List types) { + public void setTypes(List types) { this.types = types; } } diff --git a/src/main/java/de/avatic/lcc/model/nodes/NodeType.java b/src/main/java/de/avatic/lcc/model/nodes/NodeType.java new file mode 100644 index 0000000..1a5682d --- /dev/null +++ b/src/main/java/de/avatic/lcc/model/nodes/NodeType.java @@ -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; + } +} diff --git a/src/main/java/de/avatic/lcc/model/packaging/DimensionUnit.java b/src/main/java/de/avatic/lcc/model/packaging/DimensionUnit.java index 53e2275..34241d2 100644 --- a/src/main/java/de/avatic/lcc/model/packaging/DimensionUnit.java +++ b/src/main/java/de/avatic/lcc/model/packaging/DimensionUnit.java @@ -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); + } } diff --git a/src/main/java/de/avatic/lcc/model/packaging/Packaging.java b/src/main/java/de/avatic/lcc/model/packaging/Packaging.java index 462b40a..ac7f751 100644 --- a/src/main/java/de/avatic/lcc/model/packaging/Packaging.java +++ b/src/main/java/de/avatic/lcc/model/packaging/Packaging.java @@ -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 supplierNode; + private NodeListEntry supplier; - @NotNull - private AggregateReference material; + private MaterialListEntry material; - private AggregateReference parent; + @JsonProperty("handling_unit") + private PackagingDimension hu; - @MappedCollection(idColumn = "packaging_id") - private Set 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 getSupplierNode() { - return supplierNode; + public NodeListEntry getSupplier() { + return supplier; } - public void setSupplierNode(AggregateReference supplierNode) { - this.supplierNode = supplierNode; + public void setSupplier(NodeListEntry supplier) { + this.supplier = supplier; } - public AggregateReference getMaterial() { + public MaterialListEntry getMaterial() { return material; } - public void setMaterial(AggregateReference material) { + public void setMaterial(MaterialListEntry material) { this.material = material; } - public AggregateReference getParent() { - return parent; + public PackagingDimension getHu() { + return hu; } - public void setParent(AggregateReference 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; } } diff --git a/src/main/java/de/avatic/lcc/model/packaging/PackagingDimension.java b/src/main/java/de/avatic/lcc/model/packaging/PackagingDimension.java new file mode 100644 index 0000000..797cca8 --- /dev/null +++ b/src/main/java/de/avatic/lcc/model/packaging/PackagingDimension.java @@ -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; + } +} diff --git a/src/main/java/de/avatic/lcc/model/packaging/PackagingListEntry.java b/src/main/java/de/avatic/lcc/model/packaging/PackagingListEntry.java index e9ecc1e..671294e 100644 --- a/src/main/java/de/avatic/lcc/model/packaging/PackagingListEntry.java +++ b/src/main/java/de/avatic/lcc/model/packaging/PackagingListEntry.java @@ -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; } } diff --git a/src/main/java/de/avatic/lcc/model/packaging/PackagingProperty.java b/src/main/java/de/avatic/lcc/model/packaging/PackagingProperty.java index 5538ca5..1902bfb 100644 --- a/src/main/java/de/avatic/lcc/model/packaging/PackagingProperty.java +++ b/src/main/java/de/avatic/lcc/model/packaging/PackagingProperty.java @@ -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; } diff --git a/src/main/java/de/avatic/lcc/model/packaging/WeightUnit.java b/src/main/java/de/avatic/lcc/model/packaging/WeightUnit.java index cbe00c6..f8a3a52 100644 --- a/src/main/java/de/avatic/lcc/model/packaging/WeightUnit.java +++ b/src/main/java/de/avatic/lcc/model/packaging/WeightUnit.java @@ -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); + } } \ No newline at end of file diff --git a/src/main/java/de/avatic/lcc/repositories/MaterialRepository.java b/src/main/java/de/avatic/lcc/repositories/MaterialRepository.java index 33add49..33905f1 100644 --- a/src/main/java/de/avatic/lcc/repositories/MaterialRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/MaterialRepository.java @@ -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,57 +73,59 @@ 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 node ON packaging.supplier_node_id = node.id + 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(); + 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.setDimensionUnit(dimensionUnit); - packagingEntry.setWeight(UnitConverter.convert(packagingRs.getInt("weight"), weightUnit)); - packagingEntry.setWeightUnit(weightUnit); - packagingEntry.setContentUnitCount(packagingRs.getInt("content_unit_count")); - packagingEntry.setType(packagingRs.getString("type")); + packagingEntry.setId(packagingRs.getInt("id")); + packagingEntry.setParentId(packagingRs.getInt("parent_id")); + 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(weightUnit.convertFromG(packagingRs.getInt("weight"))); + packagingEntry.setWeightUnit(weightUnit); + packagingEntry.setContentUnitCount(packagingRs.getInt("content_unit_count")); + packagingEntry.setType(packagingRs.getString("type")); - if (packagingRs.getObject("supplier_id") != null) { - NodeListEntry supplier = new NodeListEntry(); - supplier.setId(packagingRs.getInt("supplier_id")); - supplier.setName(packagingRs.getString("supplier_name")); + if (packagingRs.getObject("supplier_id") != null) { + 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) { - CountryListEntry country = new CountryListEntry(); - country.setId(packagingRs.getInt("country_id")); - country.setName(packagingRs.getString("country_name")); - country.setIsoCode(packagingRs.getString("country_iso_code")); - country.setRegionCode(packagingRs.getString("country_region_code")); - supplier.setCountry(country); - } - - packagingEntry.setSupplier(supplier); + if (packagingRs.getObject("country_id") != null) { + CountryListEntry country = new CountryListEntry(); + country.setId(packagingRs.getInt("country_id")); + country.setName(packagingRs.getString("country_name")); + country.setIsoCode(packagingRs.getString("country_iso_code")); + country.setRegionCode(packagingRs.getString("country_region_code")); + supplier.setCountry(country); } - return packagingEntry; - }, material.getId()); + packagingEntry.setSupplier(supplier); + } - material.setPackaging(packaging); - } + return packagingEntry; + }, material.getId()); + + material.setPackaging(packaging); return Optional.of(material); } diff --git a/src/main/java/de/avatic/lcc/repositories/PackagingRepository.java b/src/main/java/de/avatic/lcc/repositories/PackagingRepository.java new file mode 100644 index 0000000..1362cc2 --- /dev/null +++ b/src/main/java/de/avatic/lcc/repositories/PackagingRepository.java @@ -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 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(); + 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(); + 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 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 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 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(); + + 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 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 deleteById(Integer id) { + return Optional.empty(); + } + + @Transactional + public Optional create(Packaging packaging) { + return Optional.empty(); + } + + +} diff --git a/src/main/java/de/avatic/lcc/repositories/utils/SearchQueryPagination.java b/src/main/java/de/avatic/lcc/repositories/pagination/SearchQueryPagination.java similarity index 88% rename from src/main/java/de/avatic/lcc/repositories/utils/SearchQueryPagination.java rename to src/main/java/de/avatic/lcc/repositories/pagination/SearchQueryPagination.java index 2efebf0..b872829 100644 --- a/src/main/java/de/avatic/lcc/repositories/utils/SearchQueryPagination.java +++ b/src/main/java/de/avatic/lcc/repositories/pagination/SearchQueryPagination.java @@ -1,4 +1,4 @@ -package de.avatic.lcc.repositories.utils; +package de.avatic.lcc.repositories.pagination; public class SearchQueryPagination { diff --git a/src/main/java/de/avatic/lcc/repositories/pagination/SearchQueryResult.java b/src/main/java/de/avatic/lcc/repositories/pagination/SearchQueryResult.java new file mode 100644 index 0000000..5f56a80 --- /dev/null +++ b/src/main/java/de/avatic/lcc/repositories/pagination/SearchQueryResult.java @@ -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). + *

+ * A replacement for org.springframework.data.domain.Page, since this project uses spring jdbc + * + * @param The type of the elements contained in the result. + */ +public class SearchQueryResult { + + private List 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 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 toList() { + return result; + } + + /** + * Sets the list of results for this SearchQueryResult. + * + * @param result The list of query results to set. + */ + public void setResult(List 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; + } +} diff --git a/src/main/java/de/avatic/lcc/repositories/utils/SearchQueryResult.java b/src/main/java/de/avatic/lcc/repositories/utils/SearchQueryResult.java deleted file mode 100644 index 22898f7..0000000 --- a/src/main/java/de/avatic/lcc/repositories/utils/SearchQueryResult.java +++ /dev/null @@ -1,49 +0,0 @@ -package de.avatic.lcc.repositories.utils; - -import java.util.List; - -public class SearchQueryResult { - - private List result; - - private Integer page, totalPages, totalElements; - - public SearchQueryResult(List result, Integer page, Integer totalPages, Integer totalElements) { - this.result = result; - this.page = page; - this.totalPages = totalPages; - this.totalElements = totalElements; - } - - public List toList() { - return result; - } - - public void setResult(List 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; - } -} diff --git a/src/main/java/de/avatic/lcc/service/MaterialService.java b/src/main/java/de/avatic/lcc/service/MaterialService.java index d09e37e..6689066 100644 --- a/src/main/java/de/avatic/lcc/service/MaterialService.java +++ b/src/main/java/de/avatic/lcc/service/MaterialService.java @@ -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 diff --git a/src/main/java/de/avatic/lcc/service/PackagingService.java b/src/main/java/de/avatic/lcc/service/PackagingService.java new file mode 100644 index 0000000..4156f27 --- /dev/null +++ b/src/main/java/de/avatic/lcc/service/PackagingService.java @@ -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 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)); + } +}