mirror of
https://gitea.gofwd.group/Forward_Group/ballistic-builder-spring.git
synced 2026-01-20 16:51:03 -05:00
new admin endpoints and cleaned up product dto for faster response
This commit is contained in:
@@ -70,7 +70,7 @@ public class SecurityConfig {
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration cfg = new CorsConfiguration();
|
||||
cfg.setAllowedOrigins(List.of("http://localhost:3000"));
|
||||
cfg.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
cfg.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
|
||||
cfg.setAllowedHeaders(List.of("Authorization", "Content-Type"));
|
||||
cfg.setExposedHeaders(List.of("Authorization"));
|
||||
cfg.setAllowCredentials(true);
|
||||
|
||||
@@ -6,6 +6,9 @@ import group.goforward.battlbuilder.web.dto.ProductSummaryDto;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -23,13 +26,14 @@ public class ProductV1Controller {
|
||||
@GetMapping
|
||||
@Cacheable(
|
||||
value = "gunbuilderProductsV1",
|
||||
key = "#platform + '::' + (#partRoles == null ? 'ALL' : #partRoles.toString())"
|
||||
key = "#platform + '::' + (#partRoles == null ? 'ALL' : #partRoles.toString()) + '::' + #pageable.pageNumber + '::' + #pageable.pageSize"
|
||||
)
|
||||
public List<ProductSummaryDto> getProducts(
|
||||
public Page<ProductSummaryDto> getProducts(
|
||||
@RequestParam(defaultValue = "AR-15") String platform,
|
||||
@RequestParam(required = false, name = "partRoles") List<String> partRoles
|
||||
@RequestParam(required = false, name = "partRoles") List<String> partRoles,
|
||||
@PageableDefault(size = 50) Pageable pageable
|
||||
) {
|
||||
return productQueryService.getProducts(platform, partRoles);
|
||||
return productQueryService.getProductsPage(platform, partRoles, pageable);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/offers")
|
||||
|
||||
@@ -8,7 +8,6 @@ import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import group.goforward.battlbuilder.model.PartRoleSource;
|
||||
|
||||
@Entity
|
||||
@Table(name = "products")
|
||||
@@ -130,6 +129,24 @@ public class Product {
|
||||
public String getCaliberGroup() { return caliberGroup; }
|
||||
public void setCaliberGroup(String caliberGroup) { this.caliberGroup = caliberGroup; }
|
||||
|
||||
/* Admin Management */
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "visibility", nullable = false)
|
||||
private ProductVisibility visibility = ProductVisibility.PUBLIC;
|
||||
|
||||
@Column(name = "builder_eligible", nullable = false)
|
||||
private Boolean builderEligible = true;
|
||||
|
||||
@Column(name = "admin_locked", nullable = false)
|
||||
private Boolean adminLocked = false;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "status", nullable = false)
|
||||
private ProductStatus status = ProductStatus.ACTIVE;
|
||||
|
||||
@Column(name = "admin_note")
|
||||
private String adminNote;
|
||||
|
||||
// --- lifecycle hooks ---
|
||||
@PrePersist
|
||||
public void prePersist() {
|
||||
@@ -237,6 +254,22 @@ public class Product {
|
||||
public Boolean getPartRoleLocked() { return partRoleLocked; }
|
||||
public void setPartRoleLocked(Boolean partRoleLocked) { this.partRoleLocked = partRoleLocked; }
|
||||
|
||||
|
||||
// --- Admin Getters/setters
|
||||
public ProductVisibility getVisibility() { return visibility; }
|
||||
public void setVisibility(ProductVisibility visibility) { this.visibility = visibility; }
|
||||
|
||||
public Boolean getBuilderEligible() { return builderEligible; }
|
||||
public void setBuilderEligible(Boolean builderEligible) { this.builderEligible = builderEligible; }
|
||||
|
||||
public Boolean getAdminLocked() { return adminLocked; }
|
||||
public void setAdminLocked(Boolean adminLocked) { this.adminLocked = adminLocked; }
|
||||
|
||||
public ProductStatus getStatus() { return status; }
|
||||
public void setStatus(ProductStatus status) { this.status = status; }
|
||||
|
||||
public String getAdminNote() { return adminNote; }
|
||||
public void setAdminNote(String adminNote) { this.adminNote = adminNote; }
|
||||
// --- computed helpers ---
|
||||
|
||||
public BigDecimal getBestOfferPrice() {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package group.goforward.battlbuilder.model;
|
||||
|
||||
public enum ProductStatus {
|
||||
ACTIVE,
|
||||
DISABLED,
|
||||
ARCHIVED
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package group.goforward.battlbuilder.model;
|
||||
|
||||
public enum ProductVisibility {
|
||||
PUBLIC,
|
||||
HIDDEN
|
||||
}
|
||||
@@ -10,12 +10,16 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ProductRepository extends JpaRepository<Product, Integer> {
|
||||
public interface ProductRepository
|
||||
extends JpaRepository<Product, Integer>,
|
||||
JpaSpecificationExecutor<Product> {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -238,6 +242,20 @@ where po.product_id = p.id
|
||||
List<Product> findByMerchantIdAndRawCategoryKey(@Param("merchantId") Integer merchantId,
|
||||
@Param("rawCategoryKey") String rawCategoryKey);
|
||||
|
||||
|
||||
@Query("SELECT p FROM Product p JOIN FETCH p.brand b WHERE p.deletedAt IS NULL")
|
||||
Page<Product> findAllWithBrand(Pageable pageable);
|
||||
|
||||
@Query("SELECT p FROM Product p JOIN FETCH p.brand b WHERE p.platform = :platform AND p.deletedAt IS NULL")
|
||||
Page<Product> findByPlatformWithBrand(String platform, Pageable pageable);
|
||||
|
||||
@Query("SELECT p FROM Product p JOIN FETCH p.brand b WHERE p.partRole IN :roles AND p.deletedAt IS NULL")
|
||||
Page<Product> findByPartRoleInWithBrand(List<String> roles, Pageable pageable);
|
||||
|
||||
@Query("SELECT p FROM Product p JOIN FETCH p.brand b WHERE p.platform = :platform AND p.partRole IN :roles AND p.deletedAt IS NULL")
|
||||
Page<Product> findByPlatformAndPartRoleInWithBrand(String platform, List<String> roles, Pageable pageable);
|
||||
|
||||
|
||||
// -------------------------------------------------
|
||||
// Admin import-status dashboard (summary)
|
||||
// -------------------------------------------------
|
||||
|
||||
@@ -5,6 +5,9 @@ import group.goforward.battlbuilder.web.dto.ProductSummaryDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
public interface ProductQueryService {
|
||||
|
||||
List<ProductSummaryDto> getProducts(String platform, List<String> partRoles);
|
||||
@@ -12,4 +15,6 @@ public interface ProductQueryService {
|
||||
List<ProductOfferDto> getOffersForProduct(Integer productId);
|
||||
|
||||
ProductSummaryDto getProductById(Integer productId);
|
||||
|
||||
Page<ProductSummaryDto> getProductsPage(String platform, List<String> partRoles, Pageable pageable);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
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 org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
public interface AdminProductService {
|
||||
|
||||
Page<ProductAdminRowDto> search(
|
||||
AdminProductSearchRequest request,
|
||||
Pageable pageable
|
||||
);
|
||||
|
||||
int bulkUpdate(ProductBulkUpdateRequest request);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package group.goforward.battlbuilder.services.admin.impl;
|
||||
|
||||
import group.goforward.battlbuilder.model.Product;
|
||||
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.ProductAdminRowDto;
|
||||
import group.goforward.battlbuilder.web.dto.admin.ProductBulkUpdateRequest;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class AdminProductServiceImpl implements AdminProductService {
|
||||
|
||||
private final ProductRepository productRepository;
|
||||
|
||||
public AdminProductServiceImpl(ProductRepository productRepository) {
|
||||
this.productRepository = productRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ProductAdminRowDto> search(
|
||||
AdminProductSearchRequest request,
|
||||
Pageable pageable
|
||||
) {
|
||||
Specification<Product> spec =
|
||||
ProductSpecifications.adminSearch(request);
|
||||
|
||||
return productRepository
|
||||
.findAll(spec, pageable)
|
||||
.map(ProductAdminRowDto::fromEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bulkUpdate(ProductBulkUpdateRequest request) {
|
||||
var products = productRepository.findAllById(request.getProductIds());
|
||||
|
||||
products.forEach(p -> {
|
||||
if (request.getVisibility() != null) {
|
||||
p.setVisibility(request.getVisibility());
|
||||
}
|
||||
if (request.getStatus() != null) {
|
||||
p.setStatus(request.getStatus());
|
||||
}
|
||||
if (request.getBuilderEligible() != null) {
|
||||
p.setBuilderEligible(request.getBuilderEligible());
|
||||
}
|
||||
if (request.getAdminLocked() != null) {
|
||||
p.setAdminLocked(request.getAdminLocked());
|
||||
}
|
||||
if (request.getAdminNote() != null) {
|
||||
p.setAdminNote(request.getAdminNote());
|
||||
}
|
||||
});
|
||||
|
||||
productRepository.saveAll(products);
|
||||
return products.size();
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,15 @@ import org.springframework.stereotype.Service;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Service
|
||||
public class ProductQueryServiceImpl implements ProductQueryService {
|
||||
@@ -69,6 +78,57 @@ public class ProductQueryServiceImpl implements ProductQueryService {
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ProductSummaryDto> getProductsPage(String platform, List<String> partRoles, Pageable pageable) {
|
||||
final boolean allPlatforms = platform != null && platform.equalsIgnoreCase("ALL");
|
||||
|
||||
Page<Product> productPage;
|
||||
|
||||
if (partRoles == null || partRoles.isEmpty()) {
|
||||
productPage = allPlatforms
|
||||
? productRepository.findAllWithBrand(pageable)
|
||||
: productRepository.findByPlatformWithBrand(platform, pageable);
|
||||
} else {
|
||||
productPage = allPlatforms
|
||||
? productRepository.findByPartRoleInWithBrand(partRoles, pageable)
|
||||
: productRepository.findByPlatformAndPartRoleInWithBrand(platform, partRoles, pageable);
|
||||
}
|
||||
|
||||
List<Product> products = productPage.getContent();
|
||||
if (products.isEmpty()) {
|
||||
return Page.empty(pageable);
|
||||
}
|
||||
|
||||
List<Integer> productIds = products.stream().map(Product::getId).toList();
|
||||
|
||||
// Only fetch offers for THIS PAGE of products
|
||||
List<ProductOffer> allOffers = productOfferRepository.findByProduct_IdIn(productIds);
|
||||
|
||||
Map<Integer, List<ProductOffer>> offersByProductId = allOffers.stream()
|
||||
.filter(o -> o.getProduct() != null && o.getProduct().getId() != null)
|
||||
.collect(Collectors.groupingBy(o -> o.getProduct().getId()));
|
||||
|
||||
List<ProductSummaryDto> dtos = products.stream()
|
||||
.map(p -> {
|
||||
List<ProductOffer> offersForProduct =
|
||||
offersByProductId.getOrDefault(p.getId(), Collections.emptyList());
|
||||
|
||||
ProductOffer bestOffer = pickBestOffer(offersForProduct);
|
||||
|
||||
BigDecimal price = bestOffer != null ? bestOffer.getEffectivePrice() : null;
|
||||
String buyUrl = bestOffer != null ? bestOffer.getBuyUrl() : null;
|
||||
|
||||
return ProductMapper.toSummary(p, price, buyUrl);
|
||||
})
|
||||
.toList();
|
||||
|
||||
return new PageImpl<>(dtos, pageable, productPage.getTotalElements());
|
||||
}
|
||||
|
||||
//
|
||||
// Product Offers
|
||||
//
|
||||
|
||||
@Override
|
||||
public List<ProductOfferDto> getOffersForProduct(Integer productId) {
|
||||
// ✅ canonical repo method
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package group.goforward.battlbuilder.specs;
|
||||
|
||||
import group.goforward.battlbuilder.model.ImportStatus;
|
||||
import group.goforward.battlbuilder.model.Product;
|
||||
import group.goforward.battlbuilder.model.ProductStatus;
|
||||
import group.goforward.battlbuilder.model.ProductVisibility;
|
||||
import group.goforward.battlbuilder.web.dto.admin.AdminProductSearchRequest;
|
||||
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class ProductSpecifications {
|
||||
|
||||
private ProductSpecifications() {}
|
||||
|
||||
public static Specification<Product> adminSearch(AdminProductSearchRequest req) {
|
||||
return (root, query, cb) -> {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
// Always exclude soft-deleted
|
||||
predicates.add(cb.isNull(root.get("deletedAt")));
|
||||
|
||||
if (req == null) {
|
||||
return cb.and(predicates.toArray(new Predicate[0]));
|
||||
}
|
||||
|
||||
if (hasText(req.getPlatform())) {
|
||||
predicates.add(cb.equal(root.get("platform"), req.getPlatform()));
|
||||
}
|
||||
|
||||
if (hasText(req.getPartRole())) {
|
||||
// If you normalize partRole elsewhere, keep it consistent here.
|
||||
predicates.add(cb.equal(cb.lower(root.get("partRole")), req.getPartRole().toLowerCase()));
|
||||
}
|
||||
|
||||
if (req.getImportStatus() != null) {
|
||||
predicates.add(cb.equal(root.get("importStatus"), req.getImportStatus()));
|
||||
}
|
||||
|
||||
if (req.getVisibility() != null) {
|
||||
predicates.add(cb.equal(root.get("visibility"), req.getVisibility()));
|
||||
}
|
||||
|
||||
if (req.getStatus() != null) {
|
||||
predicates.add(cb.equal(root.get("status"), req.getStatus()));
|
||||
}
|
||||
|
||||
if (req.getBuilderEligible() != null) {
|
||||
predicates.add(cb.equal(root.get("builderEligible"), req.getBuilderEligible()));
|
||||
}
|
||||
|
||||
if (req.getAdminLocked() != null) {
|
||||
predicates.add(cb.equal(root.get("adminLocked"), req.getAdminLocked()));
|
||||
}
|
||||
|
||||
if (hasText(req.getQ())) {
|
||||
String like = "%" + req.getQ().trim().toLowerCase() + "%";
|
||||
|
||||
Predicate name = cb.like(cb.lower(root.get("name")), like);
|
||||
Predicate slug = cb.like(cb.lower(root.get("slug")), like);
|
||||
|
||||
// mpn/upc are nullable
|
||||
Predicate mpn = cb.like(cb.lower(cb.coalesce(root.get("mpn"), "")), like);
|
||||
Predicate upc = cb.like(cb.lower(cb.coalesce(root.get("upc"), "")), like);
|
||||
|
||||
predicates.add(cb.or(name, slug, mpn, upc));
|
||||
}
|
||||
|
||||
return cb.and(predicates.toArray(new Predicate[0]));
|
||||
};
|
||||
}
|
||||
|
||||
// --- reusable small specs (optional, but nice to have) ---
|
||||
|
||||
public static Specification<Product> notDeleted() {
|
||||
return (root, query, cb) -> cb.isNull(root.get("deletedAt"));
|
||||
}
|
||||
|
||||
public static Specification<Product> platform(String platform) {
|
||||
return (root, query, cb) -> cb.equal(root.get("platform"), platform);
|
||||
}
|
||||
|
||||
public static Specification<Product> partRoleEquals(String partRole) {
|
||||
return (root, query, cb) -> cb.equal(cb.lower(root.get("partRole")), partRole.toLowerCase());
|
||||
}
|
||||
|
||||
public static Specification<Product> importStatus(ImportStatus status) {
|
||||
return (root, query, cb) -> cb.equal(root.get("importStatus"), status);
|
||||
}
|
||||
|
||||
public static Specification<Product> visibility(ProductVisibility visibility) {
|
||||
return (root, query, cb) -> cb.equal(root.get("visibility"), visibility);
|
||||
}
|
||||
|
||||
public static Specification<Product> status(ProductStatus status) {
|
||||
return (root, query, cb) -> cb.equal(root.get("status"), status);
|
||||
}
|
||||
|
||||
public static Specification<Product> builderEligible(Boolean builderEligible) {
|
||||
return (root, query, cb) -> cb.equal(root.get("builderEligible"), builderEligible);
|
||||
}
|
||||
|
||||
public static Specification<Product> adminLocked(Boolean adminLocked) {
|
||||
return (root, query, cb) -> cb.equal(root.get("adminLocked"), adminLocked);
|
||||
}
|
||||
|
||||
private static boolean hasText(String s) {
|
||||
return s != null && !s.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
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.ProductAdminRowDto;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/admin/products")
|
||||
public class AdminProductController {
|
||||
|
||||
private final AdminProductService adminProductService;
|
||||
|
||||
public AdminProductController(AdminProductService adminProductService) {
|
||||
this.adminProductService = adminProductService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin product list (paged + filterable)
|
||||
*/
|
||||
@GetMapping
|
||||
public Page<ProductAdminRowDto> search(
|
||||
AdminProductSearchRequest request,
|
||||
Pageable pageable
|
||||
) {
|
||||
return adminProductService.search(request, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package group.goforward.battlbuilder.web.dto.admin;
|
||||
|
||||
import group.goforward.battlbuilder.model.ImportStatus;
|
||||
import group.goforward.battlbuilder.model.ProductStatus;
|
||||
import group.goforward.battlbuilder.model.ProductVisibility;
|
||||
|
||||
/**
|
||||
* Bound from query params on:
|
||||
* GET /api/v1/admin/products?platform=AR-15&q=mini&visibility=PUBLIC...
|
||||
*/
|
||||
public class AdminProductSearchRequest {
|
||||
|
||||
private String q;
|
||||
private String platform;
|
||||
private String partRole;
|
||||
|
||||
private ImportStatus importStatus;
|
||||
private ProductVisibility visibility;
|
||||
private ProductStatus status;
|
||||
|
||||
private Boolean builderEligible;
|
||||
private Boolean adminLocked;
|
||||
|
||||
// --- getters/setters ---
|
||||
|
||||
public String getQ() { return q; }
|
||||
public void setQ(String q) { this.q = q; }
|
||||
|
||||
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 ImportStatus getImportStatus() { return importStatus; }
|
||||
public void setImportStatus(ImportStatus importStatus) { this.importStatus = importStatus; }
|
||||
|
||||
public ProductVisibility getVisibility() { return visibility; }
|
||||
public void setVisibility(ProductVisibility visibility) { this.visibility = visibility; }
|
||||
|
||||
public ProductStatus getStatus() { return status; }
|
||||
public void setStatus(ProductStatus status) { this.status = status; }
|
||||
|
||||
public Boolean getBuilderEligible() { return builderEligible; }
|
||||
public void setBuilderEligible(Boolean builderEligible) { this.builderEligible = builderEligible; }
|
||||
|
||||
public Boolean getAdminLocked() { return adminLocked; }
|
||||
public void setAdminLocked(Boolean adminLocked) { this.adminLocked = adminLocked; }
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package group.goforward.battlbuilder.web.dto.admin;
|
||||
|
||||
import group.goforward.battlbuilder.model.ImportStatus;
|
||||
import group.goforward.battlbuilder.model.Product;
|
||||
import group.goforward.battlbuilder.model.ProductStatus;
|
||||
import group.goforward.battlbuilder.model.ProductVisibility;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Lightweight row for the admin products table.
|
||||
* Avoids fetching offers unless you explicitly want it.
|
||||
*/
|
||||
public class ProductAdminRowDto {
|
||||
|
||||
private Integer id;
|
||||
private UUID uuid;
|
||||
|
||||
private String name;
|
||||
private String slug;
|
||||
|
||||
private String platform;
|
||||
private String partRole;
|
||||
|
||||
private String brandName;
|
||||
|
||||
private ImportStatus importStatus;
|
||||
|
||||
private ProductVisibility visibility;
|
||||
private ProductStatus status;
|
||||
private Boolean builderEligible;
|
||||
private Boolean adminLocked;
|
||||
|
||||
private String adminNote;
|
||||
|
||||
private String mainImageUrl;
|
||||
|
||||
private Instant createdAt;
|
||||
private Instant updatedAt;
|
||||
|
||||
|
||||
public static ProductAdminRowDto fromEntity(Product p) {
|
||||
ProductAdminRowDto dto = new ProductAdminRowDto();
|
||||
|
||||
dto.id = p.getId();
|
||||
dto.uuid = p.getUuid();
|
||||
|
||||
dto.name = p.getName();
|
||||
dto.slug = p.getSlug();
|
||||
|
||||
dto.platform = p.getPlatform();
|
||||
dto.partRole = p.getPartRole();
|
||||
|
||||
dto.brandName = (p.getBrand() != null) ? p.getBrand().getName() : null;
|
||||
|
||||
dto.importStatus = p.getImportStatus();
|
||||
|
||||
dto.visibility = p.getVisibility();
|
||||
dto.status = p.getStatus();
|
||||
dto.builderEligible = p.getBuilderEligible();
|
||||
dto.adminLocked = p.getAdminLocked();
|
||||
|
||||
dto.adminNote = p.getAdminNote();
|
||||
dto.mainImageUrl = p.getMainImageUrl();
|
||||
|
||||
dto.createdAt = p.getCreatedAt();
|
||||
dto.updatedAt = p.getUpdatedAt();
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
// --- getters/setters ---
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getSlug() {
|
||||
return slug;
|
||||
}
|
||||
|
||||
public void setSlug(String slug) {
|
||||
this.slug = slug;
|
||||
}
|
||||
|
||||
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 String getBrandName() {
|
||||
return brandName;
|
||||
}
|
||||
|
||||
public void setBrandName(String brandName) {
|
||||
this.brandName = brandName;
|
||||
}
|
||||
|
||||
public ImportStatus getImportStatus() {
|
||||
return importStatus;
|
||||
}
|
||||
|
||||
public void setImportStatus(ImportStatus importStatus) {
|
||||
this.importStatus = importStatus;
|
||||
}
|
||||
|
||||
public ProductVisibility getVisibility() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
public void setVisibility(ProductVisibility visibility) {
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
public ProductStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(ProductStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Boolean getBuilderEligible() {
|
||||
return builderEligible;
|
||||
}
|
||||
|
||||
public void setBuilderEligible(Boolean builderEligible) {
|
||||
this.builderEligible = builderEligible;
|
||||
}
|
||||
|
||||
public Boolean getAdminLocked() {
|
||||
return adminLocked;
|
||||
}
|
||||
|
||||
public void setAdminLocked(Boolean adminLocked) {
|
||||
this.adminLocked = adminLocked;
|
||||
}
|
||||
|
||||
public String getAdminNote() {
|
||||
return adminNote;
|
||||
}
|
||||
|
||||
public void setAdminNote(String adminNote) {
|
||||
this.adminNote = adminNote;
|
||||
}
|
||||
|
||||
public String getMainImageUrl() {
|
||||
return mainImageUrl;
|
||||
}
|
||||
|
||||
public void setMainImageUrl(String mainImageUrl) {
|
||||
this.mainImageUrl = mainImageUrl;
|
||||
}
|
||||
|
||||
public Instant getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Instant createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Instant getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(Instant updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package group.goforward.battlbuilder.web.dto.admin;
|
||||
|
||||
import group.goforward.battlbuilder.model.ProductStatus;
|
||||
import group.goforward.battlbuilder.model.ProductVisibility;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ProductBulkUpdateRequest {
|
||||
|
||||
private Set<Integer> productIds;
|
||||
|
||||
private ProductVisibility visibility;
|
||||
private ProductStatus status;
|
||||
|
||||
private Boolean builderEligible;
|
||||
private Boolean adminLocked;
|
||||
|
||||
private String adminNote;
|
||||
|
||||
// --- getters/setters ---
|
||||
|
||||
public Set<Integer> getProductIds() { return productIds; }
|
||||
public void setProductIds(Set<Integer> productIds) { this.productIds = productIds; }
|
||||
|
||||
public ProductVisibility getVisibility() { return visibility; }
|
||||
public void setVisibility(ProductVisibility visibility) { this.visibility = visibility; }
|
||||
|
||||
public ProductStatus getStatus() { return status; }
|
||||
public void setStatus(ProductStatus status) { this.status = status; }
|
||||
|
||||
public Boolean getBuilderEligible() { return builderEligible; }
|
||||
public void setBuilderEligible(Boolean builderEligible) { this.builderEligible = builderEligible; }
|
||||
|
||||
public Boolean getAdminLocked() { return adminLocked; }
|
||||
public void setAdminLocked(Boolean adminLocked) { this.adminLocked = adminLocked; }
|
||||
|
||||
public String getAdminNote() { return adminNote; }
|
||||
public void setAdminNote(String adminNote) { this.adminNote = adminNote; }
|
||||
}
|
||||
Reference in New Issue
Block a user