diff --git a/src/main/java/group/goforward/ballistic/controllers/admin/AdminPartRoleMappingController.java b/src/main/java/group/goforward/ballistic/controllers/admin/AdminPartRoleMappingController.java new file mode 100644 index 0000000..7300129 --- /dev/null +++ b/src/main/java/group/goforward/ballistic/controllers/admin/AdminPartRoleMappingController.java @@ -0,0 +1,123 @@ +package group.goforward.ballistic.controllers.admin; + +import group.goforward.ballistic.model.PartCategory; +import group.goforward.ballistic.model.PartRoleMapping; +import group.goforward.ballistic.repos.PartCategoryRepository; +import group.goforward.ballistic.repos.PartRoleMappingRepository; +import group.goforward.ballistic.web.dto.admin.AdminPartRoleMappingDto; +import group.goforward.ballistic.web.dto.admin.CreatePartRoleMappingRequest; +import group.goforward.ballistic.web.dto.admin.UpdatePartRoleMappingRequest; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.util.List; + +@RestController +@RequestMapping("/api/admin/part-role-mappings") +@CrossOrigin +public class AdminPartRoleMappingController { + + private final PartRoleMappingRepository partRoleMappingRepository; + private final PartCategoryRepository partCategoryRepository; + + public AdminPartRoleMappingController( + PartRoleMappingRepository partRoleMappingRepository, + PartCategoryRepository partCategoryRepository + ) { + this.partRoleMappingRepository = partRoleMappingRepository; + this.partCategoryRepository = partCategoryRepository; + } + + // GET /api/admin/part-role-mappings?platform=AR-15 + @GetMapping + public List list( + @RequestParam(name = "platform", required = false) String platform + ) { + List mappings; + + if (platform != null && !platform.isBlank()) { + mappings = partRoleMappingRepository.findByPlatformOrderByPartRoleAsc(platform); + } else { + mappings = partRoleMappingRepository.findAll(); + } + + return mappings.stream() + .map(this::toDto) + .toList(); + } + + // POST /api/admin/part-role-mappings + @PostMapping + public AdminPartRoleMappingDto create( + @RequestBody CreatePartRoleMappingRequest request + ) { + PartCategory category = partCategoryRepository.findBySlug(request.categorySlug()) + .orElseThrow(() -> new ResponseStatusException( + HttpStatus.BAD_REQUEST, + "PartCategory not found for slug: " + request.categorySlug() + )); + + PartRoleMapping mapping = new PartRoleMapping(); + mapping.setPlatform(request.platform()); + mapping.setPartRole(request.partRole()); + mapping.setPartCategory(category); + mapping.setNotes(request.notes()); + + mapping = partRoleMappingRepository.save(mapping); + return toDto(mapping); + } + + // PUT /api/admin/part-role-mappings/{id} + @PutMapping("/{id}") + public AdminPartRoleMappingDto update( + @PathVariable Integer id, + @RequestBody UpdatePartRoleMappingRequest request + ) { + PartRoleMapping mapping = partRoleMappingRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Mapping not found")); + + if (request.platform() != null) { + mapping.setPlatform(request.platform()); + } + if (request.partRole() != null) { + mapping.setPartRole(request.partRole()); + } + if (request.categorySlug() != null) { + PartCategory category = partCategoryRepository.findBySlug(request.categorySlug()) + .orElseThrow(() -> new ResponseStatusException( + HttpStatus.BAD_REQUEST, + "PartCategory not found for slug: " + request.categorySlug() + )); + mapping.setPartCategory(category); + } + if (request.notes() != null) { + mapping.setNotes(request.notes()); + } + + mapping = partRoleMappingRepository.save(mapping); + return toDto(mapping); + } + + // DELETE /api/admin/part-role-mappings/{id} + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void delete(@PathVariable Integer id) { + if (!partRoleMappingRepository.existsById(id)) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Mapping not found"); + } + partRoleMappingRepository.deleteById(id); + } + + private AdminPartRoleMappingDto toDto(PartRoleMapping mapping) { + PartCategory cat = mapping.getPartCategory(); + return new AdminPartRoleMappingDto( + mapping.getId(), + mapping.getPlatform(), + mapping.getPartRole(), + cat != null ? cat.getSlug() : null, + cat != null ? cat.getGroupName() : null, + mapping.getNotes() + ); + } +} \ No newline at end of file diff --git a/src/main/java/group/goforward/ballistic/model/PartRoleMapping.java b/src/main/java/group/goforward/ballistic/model/PartRoleMapping.java new file mode 100644 index 0000000..d336815 --- /dev/null +++ b/src/main/java/group/goforward/ballistic/model/PartRoleMapping.java @@ -0,0 +1,65 @@ +package group.goforward.ballistic.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "part_role_mappings") +public class PartRoleMapping { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + private String platform; // e.g. "AR-15" + + @Column(name = "part_role", nullable = false) + private String partRole; // e.g. "UPPER", "BARREL", etc. + + @ManyToOne(optional = false) + @JoinColumn(name = "part_category_id") + private PartCategory partCategory; + + @Column(columnDefinition = "text") + private String notes; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getPlatform() { + return platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + + public String getPartRole() { + return partRole; + } + + public void setPartRole(String partRole) { + this.partRole = partRole; + } + + public PartCategory getPartCategory() { + return partCategory; + } + + public void setPartCategory(PartCategory partCategory) { + this.partCategory = partCategory; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } +} \ No newline at end of file diff --git a/src/main/java/group/goforward/ballistic/repos/PartRoleMappingRepository.java b/src/main/java/group/goforward/ballistic/repos/PartRoleMappingRepository.java new file mode 100644 index 0000000..b64889e --- /dev/null +++ b/src/main/java/group/goforward/ballistic/repos/PartRoleMappingRepository.java @@ -0,0 +1,12 @@ +package group.goforward.ballistic.repos; + +import group.goforward.ballistic.model.PartRoleMapping; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface PartRoleMappingRepository extends JpaRepository { + + // List mappings for a platform, ordered nicely for the UI + List findByPlatformOrderByPartRoleAsc(String platform); +} \ No newline at end of file diff --git a/src/main/java/group/goforward/ballistic/web/dto/admin/AdminPartRoleMappingDto.java b/src/main/java/group/goforward/ballistic/web/dto/admin/AdminPartRoleMappingDto.java new file mode 100644 index 0000000..1146848 --- /dev/null +++ b/src/main/java/group/goforward/ballistic/web/dto/admin/AdminPartRoleMappingDto.java @@ -0,0 +1,10 @@ +package group.goforward.ballistic.web.dto.admin; + +public record AdminPartRoleMappingDto( + Integer id, + String platform, + String partRole, + String categorySlug, + String groupName, + String notes +) {} \ No newline at end of file diff --git a/src/main/java/group/goforward/ballistic/web/dto/admin/CreatePartRoleMappingRequest.java b/src/main/java/group/goforward/ballistic/web/dto/admin/CreatePartRoleMappingRequest.java new file mode 100644 index 0000000..74445c9 --- /dev/null +++ b/src/main/java/group/goforward/ballistic/web/dto/admin/CreatePartRoleMappingRequest.java @@ -0,0 +1,8 @@ +package group.goforward.ballistic.web.dto.admin; + +public record CreatePartRoleMappingRequest( + String platform, + String partRole, + String categorySlug, + String notes +) {} \ No newline at end of file diff --git a/src/main/java/group/goforward/ballistic/web/dto/admin/UpdatePartRoleMappingRequest.java b/src/main/java/group/goforward/ballistic/web/dto/admin/UpdatePartRoleMappingRequest.java new file mode 100644 index 0000000..b70b9f6 --- /dev/null +++ b/src/main/java/group/goforward/ballistic/web/dto/admin/UpdatePartRoleMappingRequest.java @@ -0,0 +1,8 @@ +package group.goforward.ballistic.web.dto.admin; + +public record UpdatePartRoleMappingRequest( + String platform, + String partRole, + String categorySlug, + String notes +) {} \ No newline at end of file