fixes for platforms in admin pages.

This commit is contained in:
2026-01-05 13:43:34 -05:00
parent d52dee105c
commit ae209abb77
7 changed files with 154 additions and 29 deletions

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.controllers;
package group.goforward.battlbuilder.controllers.admin;
import group.goforward.battlbuilder.model.Platform;
import group.goforward.battlbuilder.repos.PlatformRepository;
@@ -36,21 +36,70 @@ public class AdminPlatformController {
.toList();
}
@PostMapping("/add")
public ResponseEntity<Platform> createPlatform(@RequestBody Platform platform) {
/**
* Create new platform (RESTful)
* POST /api/platforms
*/
@PostMapping
public ResponseEntity<PlatformDto> create(@RequestBody Platform platform) {
// Normalize key so we dont end up with Ak47 / ak47 / AK-47 variants
if (platform.getKey() != null) {
platform.setKey(platform.getKey().trim().toUpperCase());
}
// Optional: if label empty, default to key
if (platform.getLabel() == null || platform.getLabel().trim().isEmpty()) {
platform.setLabel(platform.getKey());
}
// Default active = true if omitted
if (platform.getIsActive() == null) {
platform.setIsActive(true);
}
platform.setCreatedAt(OffsetDateTime.now());
platform.setUpdatedAt(OffsetDateTime.now());
Platform created = platformRepository.save(platform);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
return ResponseEntity.status(HttpStatus.CREATED).body(
new PlatformDto(
created.getId(),
created.getKey(),
created.getLabel(),
created.getCreatedAt(),
created.getUpdatedAt(),
created.getIsActive()
)
);
}
@DeleteMapping("/delete/{id}")
public ResponseEntity<Void> deletePlatform(@PathVariable Integer id) {
return platformRepository.findById(id)
.map(platform -> {
platformRepository.deleteById(id);
return ResponseEntity.noContent().<Void>build();
})
.orElse(ResponseEntity.notFound().build());
/**
* (Optional) keep old endpoint temporarily so nothing breaks
*/
@PostMapping("/add")
public ResponseEntity<PlatformDto> createViaAdd(@RequestBody Platform platform) {
return create(platform);
}
}
/**
* Delete platform (RESTful)
* DELETE /api/platforms/{id}
*/
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Integer id) {
if (!platformRepository.existsById(id)) {
return ResponseEntity.notFound().build();
}
platformRepository.deleteById(id);
return ResponseEntity.noContent().build();
}
/**
* (Optional) keep old delete route temporarily
*/
@DeleteMapping("/delete/{id}")
public ResponseEntity<Void> deleteLegacy(@PathVariable Integer id) {
return delete(id);
}
}

View File

@@ -3,16 +3,13 @@ package group.goforward.battlbuilder.services.admin;
import group.goforward.battlbuilder.web.dto.admin.AdminProductSearchRequest;
import group.goforward.battlbuilder.web.dto.admin.ProductAdminRowDto;
import group.goforward.battlbuilder.web.dto.admin.ProductBulkUpdateRequest;
import group.goforward.battlbuilder.web.dto.admin.BulkUpdateResult;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface AdminProductService {
Page<ProductAdminRowDto> search(AdminProductSearchRequest request, Pageable pageable);
Page<ProductAdminRowDto> search(
AdminProductSearchRequest request,
Pageable pageable
);
int bulkUpdate(ProductBulkUpdateRequest request);
BulkUpdateResult bulkUpdate(ProductBulkUpdateRequest request);
}

View File

@@ -5,6 +5,7 @@ import group.goforward.battlbuilder.repos.ProductRepository;
import group.goforward.battlbuilder.services.admin.AdminProductService;
import group.goforward.battlbuilder.specs.ProductSpecifications;
import group.goforward.battlbuilder.web.dto.admin.AdminProductSearchRequest;
import group.goforward.battlbuilder.web.dto.admin.BulkUpdateResult;
import group.goforward.battlbuilder.web.dto.admin.ProductAdminRowDto;
import group.goforward.battlbuilder.web.dto.admin.ProductBulkUpdateRequest;
@@ -38,28 +39,75 @@ public class AdminProductServiceImpl implements AdminProductService {
}
@Override
public int bulkUpdate(ProductBulkUpdateRequest request) {
public BulkUpdateResult bulkUpdate(ProductBulkUpdateRequest request) {
var products = productRepository.findAllById(request.getProductIds());
products.forEach(p -> {
int updated = 0;
int skippedLocked = 0;
for (var p : products) {
boolean changed = false;
// --- straightforward fields ---
if (request.getVisibility() != null) {
p.setVisibility(request.getVisibility());
changed = true;
}
if (request.getStatus() != null) {
p.setStatus(request.getStatus());
changed = true;
}
if (request.getBuilderEligible() != null) {
p.setBuilderEligible(request.getBuilderEligible());
changed = true;
}
if (request.getAdminLocked() != null) {
p.setAdminLocked(request.getAdminLocked());
changed = true;
}
if (request.getAdminNote() != null) {
p.setAdminNote(request.getAdminNote());
changed = true;
}
});
// --- platform update with lock semantics ---
if (request.getPlatform() != null) {
boolean isLocked = Boolean.TRUE.equals(p.getPlatformLocked());
boolean override = Boolean.TRUE.equals(request.getPlatformLocked()); // request says "I'm allowed to touch locked ones"
if (isLocked && !override) {
skippedLocked++;
} else {
if (!request.getPlatform().equals(p.getPlatform())) {
p.setPlatform(request.getPlatform());
changed = true;
}
}
}
// --- apply platformLocked toggle (even if platform isn't being changed) ---
if (request.getPlatformLocked() != null) {
if (!request.getPlatformLocked().equals(p.getPlatformLocked())) {
p.setPlatformLocked(request.getPlatformLocked());
changed = true;
}
}
if (changed) updated++;
}
productRepository.saveAll(products);
return products.size();
productRepository.flush(); // ✅ ensures UPDATEs are executed now
var check = productRepository.findAllById(request.getProductIds());
for (var p : check) {
System.out.println(
"AFTER FLUSH id=" + p.getId()
+ " platform=" + p.getPlatform()
+ " platformLocked=" + p.getPlatformLocked()
);
}
return new BulkUpdateResult(updated, skippedLocked);
}
}

View File

@@ -3,6 +3,7 @@ package group.goforward.battlbuilder.web.admin;
import group.goforward.battlbuilder.services.admin.AdminProductService;
import group.goforward.battlbuilder.web.dto.admin.AdminProductSearchRequest;
import group.goforward.battlbuilder.web.dto.admin.ProductBulkUpdateRequest;
import group.goforward.battlbuilder.web.dto.admin.BulkUpdateResult;
import group.goforward.battlbuilder.web.dto.admin.ProductAdminRowDto;
import org.springframework.data.domain.Page;
@@ -36,10 +37,11 @@ public class AdminProductController {
* Bulk admin actions (disable, hide, lock, etc.)
*/
@PatchMapping("/bulk")
public Map<String, Object> bulkUpdate(
@RequestBody ProductBulkUpdateRequest request
) {
int updated = adminProductService.bulkUpdate(request);
return Map.of("updatedCount", updated);
public Map<String, Object> bulkUpdate(@RequestBody ProductBulkUpdateRequest request) {
BulkUpdateResult result = adminProductService.bulkUpdate(request);
return Map.of(
"updatedCount", result.updatedCount(),
"skippedLockedCount", result.skippedLockedCount()
);
}
}

View File

@@ -0,0 +1,6 @@
package group.goforward.battlbuilder.web.dto.admin;
public record BulkUpdateResult(
int updatedCount,
int skippedLockedCount
) {}

View File

@@ -0,0 +1,16 @@
package group.goforward.battlbuilder.web.dto.admin;
public class PlatformCreateRequest {
private String key;
private String label;
private Boolean isActive;
public String getKey() { return key; }
public void setKey(String key) { this.key = key; }
public String getLabel() { return label; }
public void setLabel(String label) { this.label = label; }
public Boolean getIsActive() { return isActive; }
public void setIsActive(Boolean isActive) { this.isActive = isActive; }
}

View File

@@ -8,7 +8,8 @@ import java.util.Set;
public class ProductBulkUpdateRequest {
private Set<Integer> productIds;
private String platform;
private Boolean platformLocked;
private ProductVisibility visibility;
private ProductStatus status;
@@ -36,4 +37,10 @@ public class ProductBulkUpdateRequest {
public String getAdminNote() { return adminNote; }
public void setAdminNote(String adminNote) { this.adminNote = adminNote; }
public String getPlatform() { return platform; }
public void setPlatform(String platform) { this.platform = platform; }
public Boolean getPlatformLocked() { return platformLocked; }
public void setPlatformLocked(Boolean platformLocked) { this.platformLocked = platformLocked; }
}