Added bulk material update endpoint and support for deprecation handling logic:

- **Controller**: Introduced `updateMaterial` method in `MaterialController` for batch material updates.
- **Service**: Implemented update logic in `MaterialService` to handle both updates and deprecations based on the new `MaterialUpdateDTO`.
- **Transformer**: Updated `MaterialUpdateDTOTransformer` to map deprecation status and remove unused fields.
- **Repository**: Added `updateByPartNumber` and `deleteByIds` methods in `MaterialRepository` for efficient updates and deprecations.
This commit is contained in:
Jan 2025-11-06 20:22:48 +01:00
parent 6ab0f4d630
commit ae10417c44
5 changed files with 67 additions and 51 deletions

View file

@ -1,10 +1,12 @@
package de.avatic.lcc.controller.configuration;
import de.avatic.lcc.dto.configuration.material.update.MaterialUpdateDTO;
import de.avatic.lcc.dto.configuration.material.view.MaterialDetailDTO;
import de.avatic.lcc.dto.generic.MaterialDTO;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.service.access.MaterialService;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
@ -65,4 +67,11 @@ public class MaterialController {
public ResponseEntity<MaterialDetailDTO> getMaterialDetails(@PathVariable Integer id) {
return ResponseEntity.ok(materialService.getMaterial(id));
}
@PutMapping({"/", ""})
@PreAuthorize("hasRole('MATERIAL')")
public ResponseEntity<Void> updateMaterial(List<@Size(max = 100, min = 1) MaterialUpdateDTO> materials) {
materialService.updateMaterial(materials);
return ResponseEntity.ok().build();
}
}

View file

@ -5,38 +5,20 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Objects;
public class MaterialUpdateDTO {
private Integer id;
@JsonProperty("part_number")
private String partNumber;
private String name;
@JsonProperty("hs_code")
private String hsCode;
private boolean delete;
public MaterialUpdateDTO() {
}
public MaterialUpdateDTO(Integer id, String partNumber, String name, String hsCode) {
this.id = id;
this.partNumber = partNumber;
this.name = name;
this.hsCode = hsCode;
}
public String getHsCode() {
return hsCode;
}
public void setHsCode(String hsCode) {
this.hsCode = hsCode;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPartNumber() {
return partNumber;
}
@ -53,28 +35,19 @@ public class MaterialUpdateDTO {
this.name = name;
}
@Override
public String toString() {
return "MaterialSummaryDTO{" +
"id='" + id + '\'' +
", partNumber='" + partNumber + '\'' +
", name='" + name + '\'' +
'}';
public String getHsCode() {
return hsCode;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MaterialUpdateDTO that = (MaterialUpdateDTO) o;
return Objects.equals(id, that.id) &&
Objects.equals(partNumber, that.partNumber) &&
Objects.equals(name, that.name);
public void setHsCode(String hsCode) {
this.hsCode = hsCode;
}
@Override
public int hashCode() {
return Objects.hash(id, partNumber, name);
public boolean isDelete() {
return delete;
}
public void setDelete(boolean delete) {
this.delete = delete;
}
}

View file

@ -155,6 +155,12 @@ public class MaterialRepository {
return Optional.ofNullable(jdbcTemplate.update(updateQuery, material.getName(), material.getPartNumber(), material.getNormalizedPartNumber(), material.getHsCode(), material.getId()) == 0 ? null : material.getId());
}
@Transactional
public void updateByPartNumber(Material material) {
String updateQuery = "UPDATE material SET name = ?, part_number = ?, normalized_part_number = ?, hs_code = ? WHERE normalized_part_number = ?";
jdbcTemplate.update(updateQuery, material.getName(), material.getPartNumber(), material.getNormalizedPartNumber(), material.getHsCode(), material.getNormalizedPartNumber());
}
/**
* Returns all IDs from the input list that don't exist in the material table
* @param ids List of integers to check
@ -198,6 +204,16 @@ public class MaterialRepository {
);
}
public void deleteByIds(List<Integer> ids) {
String placeholders = ids.stream()
.map(id -> "?")
.collect(Collectors.joining(","));
String sql = "UPDATE material SET is_deprecated = TRUE WHERE id IN ("+placeholders+")";
jdbcTemplate.update(sql, ids);
}
private static class MaterialMapper implements RowMapper<Material> {

View file

@ -1,5 +1,6 @@
package de.avatic.lcc.service.access;
import de.avatic.lcc.dto.configuration.material.update.MaterialUpdateDTO;
import de.avatic.lcc.dto.configuration.material.view.MaterialDetailDTO;
import de.avatic.lcc.dto.generic.MaterialDTO;
import de.avatic.lcc.model.db.materials.Material;
@ -8,10 +9,13 @@ import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.service.transformer.generic.MaterialTransformer;
import de.avatic.lcc.service.transformer.material.MaterialDetailTransformer;
import de.avatic.lcc.service.transformer.material.MaterialUpdateDTOTransformer;
import de.avatic.lcc.util.exception.badrequest.MaterialNotFoundException;
import de.avatic.lcc.util.exception.badrequest.NotFoundException;
import jakarta.validation.constraints.Size;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
/**
@ -25,6 +29,7 @@ public class MaterialService {
private final MaterialRepository materialRepository;
private final MaterialTransformer materialTransformer;
private final MaterialDetailTransformer materialDetailTransformer;
private final MaterialUpdateDTOTransformer materialUpdateDTOTransformer;
/**
* Constructor for MaterialService.
@ -33,10 +38,11 @@ public class MaterialService {
* @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) {
public MaterialService(MaterialRepository materialRepository, MaterialTransformer materialTransformer, MaterialDetailTransformer materialDetailTransformer, MaterialUpdateDTOTransformer materialUpdateDTOTransformer) {
this.materialRepository = materialRepository;
this.materialTransformer = materialTransformer;
this.materialDetailTransformer = materialDetailTransformer;
this.materialUpdateDTOTransformer = materialUpdateDTOTransformer;
}
/**
@ -65,6 +71,19 @@ public class MaterialService {
return materialDetailTransformer.toMaterialDetailDTO(materialRepository.getByIdIncludeDeprecated(id).orElseThrow(() -> new NotFoundException(NotFoundException.NotFoundType.MATERIAL, id.toString())));
}
public void updateMaterial(List<@Size(max = 100, min = 1) MaterialUpdateDTO> dtos) {
var materials = dtos.stream().map(materialUpdateDTOTransformer::fromMaterialUpdateDTO).toList();
var toBeDeleted = materials.stream().filter(m -> m.getDeprecated() != null && m.getDeprecated()).map(Material::getId).toList();
var toBeUpdated = materials.stream().filter(m -> m.getDeprecated() != null && m.getDeprecated()).toList();
if (!toBeDeleted.isEmpty())
toBeDeleted.forEach(materialRepository::setDeprecatedById);
if (!toBeUpdated.isEmpty())
toBeUpdated.forEach(materialRepository::updateByPartNumber);
}
/**
* Updates an existing material with new data.
*

View file

@ -4,7 +4,7 @@ import de.avatic.lcc.dto.configuration.material.update.MaterialUpdateDTO;
import de.avatic.lcc.model.db.materials.Material;
import org.springframework.stereotype.Service;
@Deprecated
@Service
public class MaterialUpdateDTOTransformer {
@ -15,8 +15,7 @@ public class MaterialUpdateDTOTransformer {
entity.setNormalizedPartNumber(normalizePartNumber(dto.getPartNumber()));
entity.setPartNumber(dto.getPartNumber());
entity.setName(dto.getName());
entity.setDeprecated(false);
entity.setId(dto.getId());
entity.setDeprecated(!dto.isDelete());
entity.setHsCode(dto.getHsCode());
return entity;