Class Groups tab working

This commit is contained in:
2025-03-08 18:45:51 -05:00
parent 868daeb517
commit 01c27d0c5a
18 changed files with 466 additions and 6 deletions

View File

@@ -0,0 +1,34 @@
CREATE TABLE raid_builder.class_group(
class_group_id uuid PRIMARY KEY,
raid_group_id uuid REFERENCES raid_builder.raid_group(raid_group_id) NOT NULL,
class_group_name text NOT NULL,
--Auditing
modified_by uuid,
modified_date timestamptz,
created_by uuid NOT NULL,
created_date timestamptz NOT NULL
);
CREATE INDEX idx_class_group_raid_group_id ON raid_builder.class_group(raid_group_id);
GRANT ALL ON TABLE raid_builder.class_group TO raid_builder;
CREATE TABLE raid_builder.class_group_game_class_xref(
class_group_game_class_xref_id uuid PRIMARY KEY,
class_group_id uuid REFERENCES raid_builder.class_group(class_group_id) NOT NULL,
game_class_id uuid REFERENCES raid_builder.game_class(game_class_id) NOT NULL,
--Auditing
modified_by uuid,
modified_date timestamptz,
created_by uuid NOT NULL,
created_date timestamptz NOT NULL
);
CREATE INDEX idx_class_group_game_class_xref_class_group_id ON raid_builder.class_group_game_class_xref(class_group_id);
CREATE INDEX idx_class_group_game_class_xref_game_class_id ON raid_builder.class_group_game_class_xref(game_class_id);
GRANT ALL ON TABLE raid_builder.class_group_game_class_xref TO raid_builder;

View File

@@ -0,0 +1,159 @@
package com.mattrixwv.raidbuilder.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mattrixwv.raidbuilder.annotation.AccountAuthorization;
import com.mattrixwv.raidbuilder.annotation.RaidGroupAuthorization;
import com.mattrixwv.raidbuilder.entity.ClassGroup;
import com.mattrixwv.raidbuilder.entity.ClassGroupGameClassXref;
import com.mattrixwv.raidbuilder.service.ClassGroupService;
import com.mattrixwv.raidbuilder.util.DatabaseTypeUtil.AccountPermissionType;
import com.mattrixwv.raidbuilder.util.DatabaseTypeUtil.RaidGroupPermissionType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequestMapping("/raidGroup/{raidGroupId}/classGroup")
@RequiredArgsConstructor
public class ClassGroupController{
private final ObjectMapper mapper = new ObjectMapper();
private final ClassGroupService classGroupService;
@GetMapping
@AccountAuthorization(permissions = {AccountPermissionType.ADMIN, AccountPermissionType.USER})
@RaidGroupAuthorization(permissions = {RaidGroupPermissionType.ADMIN, RaidGroupPermissionType.LEADER, RaidGroupPermissionType.RAIDER})
public List<ClassGroup> getClassGroupByRaidGroupId(@PathVariable("raidGroupId") UUID raidGroupId, @RequestParam("page") int page, @RequestParam("pageSize") int pageSize, @RequestParam(name = "searchTerm", required = false) String searchTerm){
log.info("Getting class groups for raid group {} page {} of size {} with search {}", raidGroupId, page, pageSize, searchTerm);
List<ClassGroup> classGroups;
if(searchTerm == null){
classGroups = classGroupService.getClassGroupsByRaidGroupId(raidGroupId, page, pageSize);
}
else{
classGroups = classGroupService.getClassGroupsByRaidGroupIdAndSearchTerm(raidGroupId, page, pageSize, searchTerm);
}
return classGroups;
}
@GetMapping("/count")
@AccountAuthorization(permissions = {AccountPermissionType.ADMIN, AccountPermissionType.USER})
@RaidGroupAuthorization(permissions = {RaidGroupPermissionType.ADMIN, RaidGroupPermissionType.LEADER, RaidGroupPermissionType.RAIDER})
public ObjectNode getClassGroupCountByRaidGroupId(@PathVariable("raidGroupId") UUID raidGroupId, @RequestParam(name = "searchTerm", required = false) String searchTerm){
log.info("Getting class group count for raid group {} with search {}", raidGroupId, searchTerm);
Long count;
if(searchTerm == null){
count = classGroupService.getClassGroupCountByRaidGroupId(raidGroupId);
}
else{
count = classGroupService.getClassGroupCountByRaidGroupId(raidGroupId, searchTerm);
}
ObjectNode returnNode = mapper.createObjectNode();
returnNode.put("count", count);
returnNode.put("status", "success");
return returnNode;
}
@GetMapping("/{classGroupId}")
@AccountAuthorization(permissions = {AccountPermissionType.ADMIN, AccountPermissionType.USER})
@RaidGroupAuthorization(permissions = {RaidGroupPermissionType.ADMIN, RaidGroupPermissionType.LEADER, RaidGroupPermissionType.RAIDER})
public ClassGroup getClassGroup(@PathVariable("raidGroupId") UUID raidGroupId, @PathVariable("classGroupId") UUID classGroupId){
log.info("Getting class group {} for raid group {}", classGroupId, raidGroupId);
return classGroupService.getClassGroup(classGroupId, raidGroupId);
}
@PostMapping
@AccountAuthorization(permissions = {AccountPermissionType.ADMIN, AccountPermissionType.USER})
@RaidGroupAuthorization(permissions = {RaidGroupPermissionType.ADMIN, RaidGroupPermissionType.LEADER})
public ObjectNode createClassGroup(@PathVariable("raidGroupId") UUID raidGroupId, @RequestBody ObjectNode bodyNode) throws JsonProcessingException{
log.info("Creating class group for raid group {}", raidGroupId);
ClassGroup classGroup = mapper.treeToValue(bodyNode.get("classGroup"), ClassGroup.class);
UUID[] gameClassIds = mapper.treeToValue(bodyNode.get("gameClassIds"), UUID[].class);
List<ClassGroupGameClassXref> xrefs = new ArrayList<>(gameClassIds.length);
for(UUID gameClassId : gameClassIds){
ClassGroupGameClassXref xref = new ClassGroupGameClassXref();
xref.setGameClassId(gameClassId);
xrefs.add(xref);
}
classGroup = classGroupService.createClassGroup(classGroup, xrefs);
ObjectNode returnNode = mapper.createObjectNode();
returnNode.put("classGroupId", classGroup.getClassGroupId().toString());
returnNode.put("status", "success");
return returnNode;
}
@PutMapping("/{classGroupId}")
@AccountAuthorization(permissions = {AccountPermissionType.ADMIN, AccountPermissionType.USER})
@RaidGroupAuthorization(permissions = {RaidGroupPermissionType.ADMIN, RaidGroupPermissionType.LEADER})
public ObjectNode updateClassGroup(@PathVariable("raidGroupId") UUID raidGroupId, @PathVariable("classGroupId") UUID classGroupId, @RequestBody ObjectNode bodyNode) throws JsonProcessingException{
log.info("Updating class group {} for raid group {}", classGroupId, raidGroupId);
ClassGroup classGroup = mapper.treeToValue(bodyNode.get("classGroup"), ClassGroup.class);
UUID[] gameClassIds = mapper.treeToValue(bodyNode.get("gameClassIds"), UUID[].class);
List<ClassGroupGameClassXref> xrefs = new ArrayList<>(gameClassIds.length);
for(UUID gameClassId : gameClassIds){
ClassGroupGameClassXref xref = new ClassGroupGameClassXref();
xref.setClassGroupId(classGroup.getClassGroupId());
xref.setGameClassId(gameClassId);
xrefs.add(xref);
}
classGroupService.updateClassGroup(classGroup, xrefs);
ObjectNode returnNode = mapper.createObjectNode();
returnNode.put("classGroupId", classGroup.getClassGroupId().toString());
returnNode.put("status", "success");
return returnNode;
}
@DeleteMapping("/{classGroupId}")
@AccountAuthorization(permissions = {AccountPermissionType.ADMIN, AccountPermissionType.USER})
@RaidGroupAuthorization(permissions = {RaidGroupPermissionType.ADMIN, RaidGroupPermissionType.LEADER})
public ObjectNode deleteClassGroup(@PathVariable("raidGroupId") UUID raidGroupId, @PathVariable("classGroupId") UUID classGroupId){
log.info("Deleting class group {} for raid group {}", classGroupId, raidGroupId);
classGroupService.deleteClassGroup(classGroupId, raidGroupId);
ObjectNode returnNode = mapper.createObjectNode();
returnNode.put("status", "success");
return returnNode;
}
}

View File

@@ -77,6 +77,15 @@ public class GameClassController{
return countNode;
}
@GetMapping("/classGroup/{classGroupId}")
@AccountAuthorization(permissions = {AccountPermissionType.ADMIN, AccountPermissionType.USER})
public List<GameClass> getByClassGroupId(@PathVariable("classGroupId") UUID classGroupId){
log.info("Getting game classes for class group {}", classGroupId);
return gameClassService.getByClassGroupId(classGroupId);
}
@PostMapping("/game/{gameId}")
@AccountAuthorization(permissions = {AccountPermissionType.ADMIN, AccountPermissionType.USER})

View File

@@ -17,14 +17,12 @@ import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "account", schema = "raid_builder")
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public class Account{
@Id

View File

@@ -16,14 +16,12 @@ import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "account_permission", schema = "raid_builder")
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public class AccountPermission implements GrantedAuthority{
@Id

View File

@@ -14,13 +14,11 @@ import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "account_tutorial_status", schema = "raid_builder")
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public class AccountTutorialStatus{
@Id

View File

@@ -0,0 +1,31 @@
package com.mattrixwv.raidbuilder.entity;
import java.util.UUID;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "class_group", schema = "raid_builder")
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public class ClassGroup extends AuditableEntity{
@Id
@Column(name = "class_group_id")
@GeneratedValue(strategy = GenerationType.UUID)
private UUID classGroupId;
@Column(name = "raid_group_id")
private UUID raidGroupId;
@Column(name = "class_group_name")
private String classGroupName;
}

View File

@@ -0,0 +1,31 @@
package com.mattrixwv.raidbuilder.entity;
import java.util.UUID;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "class_group_game_class_xref", schema = "raid_builder")
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public class ClassGroupGameClassXref extends AuditableEntity{
@Id
@Column(name = "class_group_game_class_xref_id")
@GeneratedValue(strategy = GenerationType.UUID)
private UUID classGroupGameClassXrefId;
@Column(name = "class_group_id")
private UUID classGroupId;
@Column(name = "game_class_id")
private UUID gameClassId;
}

View File

@@ -0,0 +1,5 @@
package com.mattrixwv.raidbuilder.repository.class_group;
public interface ClassGroupCustomRepository{
}

View File

@@ -0,0 +1,27 @@
package com.mattrixwv.raidbuilder.repository.class_group;
import java.util.List;
import java.util.UUID;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import com.mattrixwv.raidbuilder.entity.ClassGroup;
public interface ClassGroupRepository extends ClassGroupCustomRepository, JpaRepository<ClassGroup, UUID>{
public void deleteByClassGroupIdAndRaidGroupId(UUID classGroupId, UUID raidGroupId);
public void deleteAllByRaidGroupId(UUID raidGroupId);
public void deleteAllByRaidGroupIdIn(Iterable<UUID> raidGroupIds);
public ClassGroup findByClassGroupIdAndRaidGroupId(UUID classGroupId, UUID raidGroupId);
public List<ClassGroup> findAllByRaidGroupId(UUID raidGroupId);
public List<ClassGroup> findAllByRaidGroupIdIn(Iterable<UUID> raidGroupIds);
public List<ClassGroup> findAllByRaidGroupId(UUID raidGroupIds, PageRequest pageRequest);
public List<ClassGroup> findAllByRaidGroupIdAndClassGroupNameContainingIgnoreCase(UUID raidGroupId, String searchTerm, PageRequest pageRequest);
public long countByRaidGroupId(UUID raidGroupId);
public long countByRaidGroupIdAndClassGroupNameContainingIgnoreCase(UUID raidGroupId, String searchTerm);
}

View File

@@ -0,0 +1,9 @@
package com.mattrixwv.raidbuilder.repository.class_group;
import org.springframework.stereotype.Repository;
@Repository
public class ClassGroupRepositoryImpl implements ClassGroupCustomRepository{
}

View File

@@ -0,0 +1,5 @@
package com.mattrixwv.raidbuilder.repository.class_group_game_class_xref;
public interface ClassGroupGameClassXrefCustomRepository{
}

View File

@@ -0,0 +1,20 @@
package com.mattrixwv.raidbuilder.repository.class_group_game_class_xref;
import java.util.List;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import com.mattrixwv.raidbuilder.entity.ClassGroupGameClassXref;
public interface ClassGroupGameClassXrefRepository extends ClassGroupGameClassXrefCustomRepository, JpaRepository<ClassGroupGameClassXref, UUID>{
public List<ClassGroupGameClassXref> findAllByClassGroupId(UUID classGroupId);
public void deleteAllByClassGroupId(UUID classGroupId);
public void deleteAllByClassGroupIdIn(Iterable<UUID> classGroupIds);
public void deleteAllByGameClassId(UUID gameClassId);
public void deleteAllByGameClassIdIn(Iterable<UUID> gameClassId);
}

View File

@@ -0,0 +1,9 @@
package com.mattrixwv.raidbuilder.repository.class_group_game_class_xref;
import org.springframework.stereotype.Repository;
@Repository
public class ClassGroupGameClassXrefRepositoryImpl implements ClassGroupGameClassXrefCustomRepository{
}

View File

@@ -1,5 +1,12 @@
package com.mattrixwv.raidbuilder.repository.game_class;
import java.util.List;
import java.util.UUID;
import com.mattrixwv.raidbuilder.entity.GameClass;
public interface GameClassCustomRepository{
public List<GameClass> findAllByClassGroupId(UUID classGroupId);
}

View File

@@ -1,9 +1,33 @@
package com.mattrixwv.raidbuilder.repository.game_class;
import java.util.List;
import java.util.UUID;
import org.springframework.stereotype.Repository;
import com.mattrixwv.raidbuilder.entity.GameClass;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
@Repository
@RequiredArgsConstructor
public class GameClassRepositoryImpl implements GameClassCustomRepository{
private final EntityManager entityManager;
@Override
public List<GameClass> findAllByClassGroupId(UUID classGroupId){
String selectString = """
SELECT gc FROM GameClass gc
INNER JOIN ClassGroupGameClassXref xref ON gc.gameClassId = xref.gameClassId
WHERE xref.classGroupId = :classGroupId
""";
return entityManager.createQuery(selectString, GameClass.class)
.setParameter("classGroupId", classGroupId)
.getResultList();
}
}

View File

@@ -0,0 +1,88 @@
package com.mattrixwv.raidbuilder.service;
import java.util.List;
import java.util.UUID;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.mattrixwv.raidbuilder.entity.ClassGroup;
import com.mattrixwv.raidbuilder.entity.ClassGroupGameClassXref;
import com.mattrixwv.raidbuilder.repository.class_group.ClassGroupRepository;
import com.mattrixwv.raidbuilder.repository.class_group_game_class_xref.ClassGroupGameClassXrefRepository;
import lombok.RequiredArgsConstructor;
@Service
@Transactional(rollbackFor = Exception.class)
@RequiredArgsConstructor
public class ClassGroupService{
private final ClassGroupRepository classGroupRepository;
private final ClassGroupGameClassXrefRepository cggcXrefRepository;
//Write
public ClassGroup createClassGroup(ClassGroup classGroup, Iterable<ClassGroupGameClassXref> xrefs){
classGroup = classGroupRepository.save(classGroup);
final UUID classGroupId = classGroup.getClassGroupId();
xrefs.forEach(xref -> xref.setClassGroupId(classGroupId));
cggcXrefRepository.saveAll(xrefs);
return classGroup;
}
public ClassGroup updateClassGroup(ClassGroup classGroup, Iterable<ClassGroupGameClassXref> xrefs){
classGroupRepository.save(classGroup);
final UUID classGroupId = classGroup.getClassGroupId();
xrefs.forEach(xref -> xref.setClassGroupId(classGroupId));
cggcXrefRepository.deleteAllByClassGroupId(classGroupId);
cggcXrefRepository.saveAll(xrefs);
return classGroup;
}
public void deleteClassGroup(UUID classGroupId, UUID raidGroupId){
cggcXrefRepository.deleteAllByClassGroupId(classGroupId);
classGroupRepository.deleteByClassGroupIdAndRaidGroupId(classGroupId, raidGroupId);
}
public void deleteByRaidGroupId(UUID raidGroupId){
List<ClassGroup> classGroups = classGroupRepository.findAllByRaidGroupId(raidGroupId);
cggcXrefRepository.deleteAllByClassGroupIdIn(classGroups.stream().map(ClassGroup::getClassGroupId).toList());
classGroupRepository.deleteAllByRaidGroupId(raidGroupId);
}
public void deleteByRaidGroupIds(Iterable<UUID> raidGroupIds){
List<ClassGroup> classGroups = classGroupRepository.findAllByRaidGroupIdIn(raidGroupIds);
cggcXrefRepository.deleteAllByClassGroupIdIn(classGroups.stream().map(ClassGroup::getClassGroupId).toList());
classGroupRepository.deleteAllByRaidGroupIdIn(raidGroupIds);
}
//Read
public ClassGroup getClassGroup(UUID classGroupId, UUID raidGroupId){
return classGroupRepository.findByClassGroupIdAndRaidGroupId(classGroupId, raidGroupId);
}
public List<ClassGroup> getClassGroupsByRaidGroupId(UUID raidGroupId, int page, int pageSize){
return classGroupRepository.findAllByRaidGroupId(raidGroupId, PageRequest.of(page, pageSize, Sort.by("classGroupName").ascending()));
}
public List<ClassGroup> getClassGroupsByRaidGroupIdAndSearchTerm(UUID raidGroupId, int page, int pageSize, String searchTerm){
return classGroupRepository.findAllByRaidGroupIdAndClassGroupNameContainingIgnoreCase(raidGroupId, searchTerm, PageRequest.of(page, pageSize, Sort.by("classGroupName").ascending()));
}
public long getClassGroupCountByRaidGroupId(UUID raidGroupId){
return classGroupRepository.countByRaidGroupId(raidGroupId);
}
public long getClassGroupCountByRaidGroupId(UUID raidGroupId, String searchTerm){
return classGroupRepository.countByRaidGroupIdAndClassGroupNameContainingIgnoreCase(raidGroupId, searchTerm);
}
}

View File

@@ -15,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.mattrixwv.raidbuilder.entity.GameClass;
import com.mattrixwv.raidbuilder.repository.class_group_game_class_xref.ClassGroupGameClassXrefRepository;
import com.mattrixwv.raidbuilder.repository.game_class.GameClassRepository;
import lombok.RequiredArgsConstructor;
@@ -27,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
@RequiredArgsConstructor
public class GameClassService{
private final GameClassRepository gameClassRepository;
private final ClassGroupGameClassXrefRepository cggcXrefRepository;
//Values
@Value("${uploadFileDirectory}")
private String uploadFileDirectory;
@@ -90,6 +92,7 @@ public class GameClassService{
}
}
cggcXrefRepository.deleteAllByGameClassId(gameClassId);
gameClassRepository.deleteById(gameClassId);
}
@@ -105,6 +108,7 @@ public class GameClassService{
}
}
cggcXrefRepository.deleteAllByGameClassIdIn(gameClasses.stream().map(GameClass::getGameClassId).toList());
gameClassRepository.deleteByGameId(gameId);
}
@@ -123,6 +127,10 @@ public class GameClassService{
return gameClassRepository.findAllByGameIdAndGameClassNameContainingIgnoreCase(gameId, searchTerm, PageRequest.of(page, pageSize, Sort.by("gameClassName").ascending()));
}
public List<GameClass> getByClassGroupId(UUID classGroupId){
return gameClassRepository.findAllByClassGroupId(classGroupId);
}
public long countByGameId(UUID gameId){
return gameClassRepository.countByGameId(gameId);
}