organizing

This commit is contained in:
2026-01-06 12:23:14 -05:00
parent 887ccc01d5
commit f0f12d76a6
68 changed files with 667 additions and 614 deletions

View File

@@ -1,4 +1,4 @@
/** /**
* Query projections for the catalog domain. * Query projections for the catalog domain.
*/ */
package group.goforward.battlbuilder.catalog.query; package group.goforward.battlbuilder.catalog.query;

View File

@@ -1,4 +1,4 @@
/** /**
* Command line runners and CLI utilities. * Command line runners and CLI utilities.
*/ */
package group.goforward.battlbuilder.cli; package group.goforward.battlbuilder.cli;

View File

@@ -1,74 +1,74 @@
package group.goforward.battlbuilder.utils; package group.goforward.battlbuilder.common;
import java.time.LocalDateTime; import java.time.LocalDateTime;
/** /**
* @param <T> * @param <T>
*/ */
public class ApiResponse<T> { public class ApiResponse<T> {
private static final String API_SUCCESS = "success"; private static final String API_SUCCESS = "success";
private static final String API_FAILURE = "failure"; private static final String API_FAILURE = "failure";
private static final String API_ERROR = "error"; private static final String API_ERROR = "error";
private String[] messages; private String[] messages;
private T data; private T data;
private String status; private String status;
private LocalDateTime timestamp; private LocalDateTime timestamp;
private ApiResponse(String status, String[] message, T data) { private ApiResponse(String status, String[] message, T data) {
this.status = status; this.status = status;
this.messages = message; this.messages = message;
this.data = data; this.data = data;
this.timestamp = LocalDateTime.now(); this.timestamp = LocalDateTime.now();
} }
public static <T> ApiResponse<T> error(String message, T data) { public static <T> ApiResponse<T> error(String message, T data) {
String[] msg = {message}; // ✅ Include the message String[] msg = {message}; // ✅ Include the message
return new ApiResponse<>(API_ERROR, msg, data); return new ApiResponse<>(API_ERROR, msg, data);
} }
public static <T> ApiResponse<T> success(T data, String emailSentSuccessfully) { public static <T> ApiResponse<T> success(T data, String emailSentSuccessfully) {
String[] msg = {}; String[] msg = {};
return new ApiResponse<>(API_SUCCESS, msg, data); return new ApiResponse<>(API_SUCCESS, msg, data);
} }
public static <T> ApiResponse<T> error(String[] messages) { public static <T> ApiResponse<T> error(String[] messages) {
return new ApiResponse<>(API_ERROR, messages, null); return new ApiResponse<>(API_ERROR, messages, null);
} }
public static <T> ApiResponse<T> error(String message) { public static <T> ApiResponse<T> error(String message) {
String[] msg = {}; String[] msg = {};
return new ApiResponse<>(API_ERROR, msg, null); return new ApiResponse<>(API_ERROR, msg, null);
} }
public String[] getMessages() { public String[] getMessages() {
return messages; return messages;
} }
public void setMessages(String[] messages) { public void setMessages(String[] messages) {
this.messages = messages; this.messages = messages;
} }
public T getData() {return data;} public T getData() {return data;}
public void setData(T data) { public void setData(T data) {
this.data = data; this.data = data;
} }
public String getStatus() { public String getStatus() {
return status; return status;
} }
public void setStatus(String status) { public void setStatus(String status) {
this.status = status; this.status = status;
} }
public LocalDateTime getTimestamp() { public LocalDateTime getTimestamp() {
return timestamp; return timestamp;
} }
public void setTimestamp(LocalDateTime timestamp) { public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
} }

View File

@@ -1,20 +1,18 @@
package group.goforward.battlbuilder.utils; package group.goforward.battlbuilder.common;
import org.springframework.context.annotation.Bean; public class Counter {
public class Counter { Integer count = 0;
public void addOne() {
Integer count = 0; count +=1;
public void addOne() { }
count +=1;
} public Integer getCount() {
return count;
public Integer getCount() { }
return count;
} private void setCount(Integer count) {
this.count = count;
private void setCount(Integer count) { }
this.count = count;
} }
}

View File

@@ -8,4 +8,4 @@
* @version 1.0 * @version 1.0
* @since 2025-12-10 * @since 2025-12-10
*/ */
package group.goforward.battlbuilder.utils; package group.goforward.battlbuilder.common;

View File

@@ -1,22 +1,22 @@
package group.goforward.battlbuilder.configuration; package group.goforward.battlbuilder.config;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@EnableCaching @EnableCaching
public class CacheConfig { public class CacheConfig {
@Bean @Bean
public CacheManager cacheManager() { public CacheManager cacheManager() {
// Must match the @Cacheable value(s) used in controllers/services. // Must match the @Cacheable value(s) used in controllers/services.
// ProductV1Controller uses: "gunbuilderProductsV1" // ProductV1Controller uses: "gunbuilderProductsV1"
return new ConcurrentMapCacheManager( return new ConcurrentMapCacheManager(
"gunbuilderProductsV1", "gunbuilderProductsV1",
"gunbuilderProducts" // keep if anything else still references it "gunbuilderProducts" // keep if anything else still references it
); );
} }
} }

View File

@@ -1,84 +1,84 @@
// src/main/java/com/example/config/CorsConfig.java // src/main/java/com/example/config/CorsConfig.java
package group.goforward.battlbuilder.configuration; package group.goforward.battlbuilder.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; import org.springframework.web.filter.CorsFilter;
import java.util.Arrays; import java.util.Arrays;
@Configuration @Configuration
public class CorsConfig { public class CorsConfig {
@Bean @Bean
public CorsFilter corsFilter() { public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration(); CorsConfiguration config = new CorsConfiguration();
// Allow credentials // Allow credentials
config.setAllowCredentials(true); config.setAllowCredentials(true);
// Allow Angular development server // Allow Angular development server
config.setAllowedOrigins(Arrays.asList( config.setAllowedOrigins(Arrays.asList(
"http://localhost:4200", "http://localhost:4200",
"http://localhost:4201", "http://localhost:4201",
"http://localhost:8070", "http://localhost:8070",
"https://localhost:8070", "https://localhost:8070",
"http://localhost:8080", "http://localhost:8080",
"https://localhost:8080", "https://localhost:8080",
"http://localhost:3000", "http://localhost:3000",
"https://localhost:3000", "https://localhost:3000",
"https://localhost:3000/gunbuilder", "https://localhost:3000/gunbuilder",
"http://localhost:3000/gunbuilder", "http://localhost:3000/gunbuilder",
"https://localhost:3000/builder", "https://localhost:3000/builder",
"http://localhost:3000/builder" "http://localhost:3000/builder"
)); ));
// Allow all headers // Allow all headers
config.addAllowedHeader("*"); config.addAllowedHeader("*");
// Allow all HTTP methods // Allow all HTTP methods
config.setAllowedMethods(Arrays.asList( config.setAllowedMethods(Arrays.asList(
"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS" "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"
)); ));
// Expose headers // Expose headers
config.setExposedHeaders(Arrays.asList( config.setExposedHeaders(Arrays.asList(
"Authorization", "Authorization",
"Content-Type", "Content-Type",
"X-Total-Count" "X-Total-Count"
)); ));
// Max age for preflight cache (1 hour) // Max age for preflight cache (1 hour)
config.setMaxAge(3600L); config.setMaxAge(3600L);
source.registerCorsConfiguration("/**", config); source.registerCorsConfiguration("/**", config);
return new CorsFilter(source); return new CorsFilter(source);
} }
} }
// Alternative using WebMvcConfigurer: // Alternative using WebMvcConfigurer:
/* /*
package group.goforward.citysites.config; package group.goforward.citysites.config;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration @Configuration
public class WebConfig implements WebMvcConfigurer { public class WebConfig implements WebMvcConfigurer {
@Override @Override
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**") registry.addMapping("/api/**")
.allowedOrigins("http://localhost:4200") .allowedOrigins("http://localhost:4200")
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
.allowedHeaders("*") .allowedHeaders("*")
.allowCredentials(true) .allowCredentials(true)
.maxAge(3600); .maxAge(3600);
} }
} }
*/ */

View File

@@ -1,10 +1,10 @@
package group.goforward.battlbuilder.configuration; package group.goforward.battlbuilder.config;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
//import org.springframework.data.jpa.repository.config.EnableJpaAuditing; //import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@Configuration @Configuration
public class JpaConfig { public class JpaConfig {
// Enables @CreatedDate / @LastModifiedDate processing // Enables @CreatedDate / @LastModifiedDate processing
} }

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.configuration; package group.goforward.battlbuilder.config;
import io.minio.MinioClient; import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;

View File

@@ -4,27 +4,30 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "shortlinks") @ConfigurationProperties(prefix = "shortlinks")
public class ShortLinksProperties { public class ShortLinksProperties {
/**
* Master switch to enable short links.
*/
private boolean enabled = true;
/** /**
* The public base URL used when generating short links (differs in dev vs prod). * The public base URL used when generating short links (differs in dev vs prod).
* Examples: * Examples:
* - http://localhost:8080 * - http://localhost:8080
* - https://bb.ooo * - https://bb.ooo
*/ */
private String publicBaseUrl = "http://localhost:8080"; public static final String PUBLIC_BASE_URL = "http://localhost:8080";
/** /**
* The frontend base URL used when redirecting BUILD short links. * The frontend base URL used when redirecting BUILD short links.
* Examples: * Examples:
* - http://localhost:3000 * - http://localhost:3000
* - https://battlbuilder.com * - https://battlbuilder.com
*/ */
private String frontendBaseUrl = "http://localhost:3000"; public static final String FRONT_END_BASE_URL = "http://localhost:3000";
/**
* Master switch to enable short links.
*/
private boolean enabled = true;
private String publicBaseUrl = PUBLIC_BASE_URL;
private String frontendBaseUrl = FRONT_END_BASE_URL;
public boolean isEnabled() { public boolean isEnabled() {
return enabled; return enabled;

View File

@@ -8,4 +8,4 @@
* @version 1.0 * @version 1.0
* @since 2025-12-10 * @since 2025-12-10
*/ */
package group.goforward.battlbuilder.configuration; package group.goforward.battlbuilder.config;

View File

@@ -1,6 +1,6 @@
package group.goforward.battlbuilder.controllers.api; package group.goforward.battlbuilder.controllers.api;
import group.goforward.battlbuilder.utils.ApiResponse; import group.goforward.battlbuilder.common.ApiResponse;
import group.goforward.battlbuilder.dto.EmailRequestDto; import group.goforward.battlbuilder.dto.EmailRequestDto;
import group.goforward.battlbuilder.model.EmailRequest; import group.goforward.battlbuilder.model.EmailRequest;
import group.goforward.battlbuilder.model.EmailStatus; import group.goforward.battlbuilder.model.EmailStatus;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.model.User; import group.goforward.battlbuilder.model.User;
import group.goforward.battlbuilder.repos.UserRepository; import group.goforward.battlbuilder.repos.UserRepository;

View File

@@ -1,50 +1,50 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.model.Brand; import group.goforward.battlbuilder.model.Brand;
import group.goforward.battlbuilder.repos.BrandRepository; import group.goforward.battlbuilder.repos.build.BrandRepository;
import group.goforward.battlbuilder.services.BrandService; import group.goforward.battlbuilder.services.BrandService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping({"/api/v1/brands", "/api/brands"}) @RequestMapping({"/api/v1/brands", "/api/brands"})
public class BrandController { public class BrandController {
@Autowired @Autowired
private BrandRepository repo; private BrandRepository repo;
@Autowired @Autowired
private BrandService brandService; private BrandService brandService;
//@Cacheable(value="getAllStates") //@Cacheable(value="getAllStates")
@GetMapping("/all") @GetMapping("/all")
public ResponseEntity<List<Brand>> getAllBrands() { public ResponseEntity<List<Brand>> getAllBrands() {
List<Brand> brand = repo.findAll(); List<Brand> brand = repo.findAll();
return ResponseEntity.ok(brand); return ResponseEntity.ok(brand);
} }
@GetMapping("/{id}") @GetMapping("/{id}")
public ResponseEntity<Brand> getAllBrandsById(@PathVariable Integer id) { public ResponseEntity<Brand> getAllBrandsById(@PathVariable Integer id) {
return repo.findById(id) return repo.findById(id)
.map(ResponseEntity::ok) .map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
} }
@PostMapping("/add") @PostMapping("/add")
public ResponseEntity<Brand> createbrand(@RequestBody Brand item) { public ResponseEntity<Brand> createbrand(@RequestBody Brand item) {
Brand created = brandService.save(item); Brand created = brandService.save(item);
return ResponseEntity.status(HttpStatus.CREATED).body(created); return ResponseEntity.status(HttpStatus.CREATED).body(created);
} }
@DeleteMapping("/delete/{id}") @DeleteMapping("/delete/{id}")
public ResponseEntity<Void> deleteItem(@PathVariable Integer id) { public ResponseEntity<Void> deleteItem(@PathVariable Integer id) {
return brandService.findById(id) return brandService.findById(id)
.map(item -> { .map(item -> {
brandService.deleteById(id); brandService.deleteById(id);
return ResponseEntity.noContent().<Void>build(); return ResponseEntity.noContent().<Void>build();
}) })
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
} }
} }

View File

@@ -1,34 +1,34 @@
package group.goforward.battlbuilder.controllers.api; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.model.Build; import group.goforward.battlbuilder.model.Build;
import group.goforward.battlbuilder.repos.BuildRepository; import group.goforward.battlbuilder.repos.build.BuildRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/v1/api/builds") @RequestMapping("/v1/api/builds")
public class BuildController { public class BuildController {
@Autowired @Autowired
private BuildRepository repo; private BuildRepository repo;
@Autowired @Autowired
// private BuildsService service; // private BuildsService service;
//@Cacheable(value="getAllStates") //@Cacheable(value="getAllStates")
@GetMapping("/all") @GetMapping("/all")
public ResponseEntity<List<Build>> getAll() { public ResponseEntity<List<Build>> getAll() {
List<Build> builds = repo.findAll(); List<Build> builds = repo.findAll();
return ResponseEntity.ok(builds); return ResponseEntity.ok(builds);
} }
@GetMapping("/{id}") @GetMapping("/{id}")
public ResponseEntity<Build> getAllBuildsById(@PathVariable Integer id) { public ResponseEntity<Build> getAllBuildsById(@PathVariable Integer id) {
return repo.findById(id) return repo.findById(id)
.map(ResponseEntity::ok) .map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
} }
} }

View File

@@ -1,10 +1,10 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.services.BuildService; import group.goforward.battlbuilder.services.BuildService;
import group.goforward.battlbuilder.web.dto.BuildDto; import group.goforward.battlbuilder.web.dto.build.BuildDto;
import group.goforward.battlbuilder.web.dto.BuildFeedCardDto; import group.goforward.battlbuilder.web.dto.build.BuildFeedCardDto;
import group.goforward.battlbuilder.web.dto.BuildSummaryDto; import group.goforward.battlbuilder.web.dto.build.BuildSummaryDto;
import group.goforward.battlbuilder.web.dto.UpdateBuildRequest; import group.goforward.battlbuilder.web.dto.UpdateBuildRequestDto;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@@ -68,7 +68,7 @@ public class BuildV1Controller {
* POST /api/v1/builds/me * POST /api/v1/builds/me
*/ */
@PostMapping("/me") @PostMapping("/me")
public ResponseEntity<BuildDto> createMyBuild(@RequestBody UpdateBuildRequest req) { public ResponseEntity<BuildDto> createMyBuild(@RequestBody UpdateBuildRequestDto req) {
return ResponseEntity.ok(buildService.createMyBuild(req)); return ResponseEntity.ok(buildService.createMyBuild(req));
} }
@@ -79,7 +79,7 @@ public class BuildV1Controller {
@PutMapping("/me/{uuid}") @PutMapping("/me/{uuid}")
public ResponseEntity<BuildDto> updateMyBuild( public ResponseEntity<BuildDto> updateMyBuild(
@PathVariable("uuid") UUID uuid, @PathVariable("uuid") UUID uuid,
@RequestBody UpdateBuildRequest req @RequestBody UpdateBuildRequestDto req
) { ) {
return ResponseEntity.ok(buildService.updateMyBuild(uuid, req)); return ResponseEntity.ok(buildService.updateMyBuild(uuid, req));
} }

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.model.PartRoleMapping; import group.goforward.battlbuilder.model.PartRoleMapping;
import group.goforward.battlbuilder.repos.PartCategoryRepository; import group.goforward.battlbuilder.repos.PartCategoryRepository;

View File

@@ -1,7 +1,7 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.services.CatalogQueryService; import group.goforward.battlbuilder.services.CatalogQueryService;
import group.goforward.battlbuilder.web.dto.ProductSummaryDto; import group.goforward.battlbuilder.web.dto.product.ProductSummaryDto;
import group.goforward.battlbuilder.web.dto.catalog.CatalogProductIdsRequest; import group.goforward.battlbuilder.web.dto.catalog.CatalogProductIdsRequest;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.repos.PartCategoryRepository; import group.goforward.battlbuilder.repos.PartCategoryRepository;
import group.goforward.battlbuilder.web.dto.admin.PartCategoryDto; import group.goforward.battlbuilder.web.dto.admin.PartCategoryDto;

View File

@@ -1,40 +1,40 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.services.MerchantFeedImportService; import group.goforward.battlbuilder.services.MerchantFeedImportService;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@RestController @RestController
@RequestMapping({"/api/admin/imports", "/api/v1/admin/imports"}) @RequestMapping({"/api/admin/imports", "/api/v1/admin/imports"})
@CrossOrigin(origins = "http://localhost:3000") @CrossOrigin(origins = "http://localhost:3000")
public class ImportController { public class ImportController {
private final MerchantFeedImportService merchantFeedImportService; private final MerchantFeedImportService merchantFeedImportService;
public ImportController(MerchantFeedImportService merchantFeedImportService) { public ImportController(MerchantFeedImportService merchantFeedImportService) {
this.merchantFeedImportService = merchantFeedImportService; this.merchantFeedImportService = merchantFeedImportService;
} }
/** /**
* Full product + offer import for a merchant. * Full product + offer import for a merchant.
* *
* POST /admin/imports/{merchantId} * POST /admin/imports/{merchantId}
*/ */
@PostMapping("/{merchantId}") @PostMapping("/{merchantId}")
public ResponseEntity<Void> importMerchant(@PathVariable Integer merchantId) { public ResponseEntity<Void> importMerchant(@PathVariable Integer merchantId) {
merchantFeedImportService.importMerchantFeed(merchantId); merchantFeedImportService.importMerchantFeed(merchantId);
return ResponseEntity.noContent().build(); return ResponseEntity.noContent().build();
} }
/** /**
* Offers-only sync (price/stock) for a merchant. * Offers-only sync (price/stock) for a merchant.
* *
* POST /admin/imports/{merchantId}/offers-only * POST /admin/imports/{merchantId}/offers-only
*/ */
@PostMapping("/{merchantId}/offers-only") @PostMapping("/{merchantId}/offers-only")
public ResponseEntity<Void> syncOffersOnly(@PathVariable Integer merchantId) { public ResponseEntity<Void> syncOffersOnly(@PathVariable Integer merchantId) {
merchantFeedImportService.syncOffersOnly(merchantId); merchantFeedImportService.syncOffersOnly(merchantId);
return ResponseEntity.noContent().build(); return ResponseEntity.noContent().build();
} }
} }

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.controllers.api; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.model.User; import group.goforward.battlbuilder.model.User;
import group.goforward.battlbuilder.repos.UserRepository; import group.goforward.battlbuilder.repos.UserRepository;

View File

@@ -1,25 +1,25 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.model.Merchant; import group.goforward.battlbuilder.model.Merchant;
import group.goforward.battlbuilder.repos.MerchantRepository; import group.goforward.battlbuilder.repos.MerchantRepository;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping({"/api/admin", "/api/v1/admin"}) @RequestMapping({"/api/admin", "/api/v1/admin"})
public class MerchantDebugController { public class MerchantDebugController {
private final MerchantRepository merchantRepository; private final MerchantRepository merchantRepository;
public MerchantDebugController(MerchantRepository merchantRepository) { public MerchantDebugController(MerchantRepository merchantRepository) {
this.merchantRepository = merchantRepository; this.merchantRepository = merchantRepository;
} }
@GetMapping("/debug/merchants") @GetMapping("/debug/merchants")
public List<Merchant> listMerchants() { public List<Merchant> listMerchants() {
return merchantRepository.findAll(); return merchantRepository.findAll();
} }
} }

View File

@@ -1,56 +1,54 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.web.dto.ProductOfferDto; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import group.goforward.battlbuilder.web.dto.ProductSummaryDto; import org.springframework.http.ResponseEntity;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import java.util.List;
import java.util.List; /**
* LEGACY CONTROLLER (Deprecated)
/** *
* LEGACY CONTROLLER (Deprecated) * Do not add new features here.
* * Canonical API lives in ProductV1Controller (/api/v1/products).
* Do not add new features here. *
* Canonical API lives in ProductV1Controller (/api/v1/products). * This exists only to keep older clients working temporarily.
* * Disable by default using:
* This exists only to keep older clients working temporarily. * app.api.legacy.enabled=false
* Disable by default using: *
* app.api.legacy.enabled=false * NOTE:
* * Even when disabled, Spring still compiles this class. So it must not reference
* NOTE: * missing services/methods.
* Even when disabled, Spring still compiles this class. So it must not reference */
* missing services/methods. @Deprecated
*/ @RestController
@Deprecated @RequestMapping({"/api/products", "/api/v1/products"})
@RestController @CrossOrigin
@RequestMapping({"/api/products", "/api/v1/products"}) @ConditionalOnProperty(name = "app.api.legacy.enabled", havingValue = "true", matchIfMissing = false)
@CrossOrigin public class ProductController {
@ConditionalOnProperty(name = "app.api.legacy.enabled", havingValue = "true", matchIfMissing = false)
public class ProductController { private static final String MSG =
"Legacy endpoint disabled. Use /api/v1/products instead.";
private static final String MSG =
"Legacy endpoint disabled. Use /api/v1/products instead."; @GetMapping
public ResponseEntity<?> getProducts(
@GetMapping @RequestParam(defaultValue = "AR-15") String platform,
public ResponseEntity<?> getProducts( @RequestParam(required = false, name = "partRoles") List<String> partRoles
@RequestParam(defaultValue = "AR-15") String platform, ) {
@RequestParam(required = false, name = "partRoles") List<String> partRoles // Legacy disabled by design (Option B cleanup)
) { return ResponseEntity.status(410).body(MSG);
// Legacy disabled by design (Option B cleanup) }
return ResponseEntity.status(410).body(MSG);
} @GetMapping("/{id}/offers")
public ResponseEntity<?> getOffersForProduct(@PathVariable("id") Integer productId) {
@GetMapping("/{id}/offers") return ResponseEntity.status(410).body(MSG);
public ResponseEntity<?> getOffersForProduct(@PathVariable("id") Integer productId) { }
return ResponseEntity.status(410).body(MSG);
} @GetMapping("/{id}")
public ResponseEntity<?> getProductById(@PathVariable("id") Integer productId) {
@GetMapping("/{id}") return ResponseEntity.status(410).body(MSG);
public ResponseEntity<?> getProductById(@PathVariable("id") Integer productId) { }
return ResponseEntity.status(410).body(MSG);
} // If you *really* need typed responses for an old client, we can re-add
// a real service layer once we align on the actual ProductQueryService API.
// If you *really* need typed responses for an old client, we can re-add
// a real service layer once we align on the actual ProductQueryService API.
} }

View File

@@ -1,8 +1,8 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.services.ProductQueryService; import group.goforward.battlbuilder.services.ProductQueryService;
import group.goforward.battlbuilder.web.dto.ProductOfferDto; import group.goforward.battlbuilder.web.dto.product.ProductOfferDto;
import group.goforward.battlbuilder.web.dto.ProductSummaryDto; import group.goforward.battlbuilder.web.dto.product.ProductSummaryDto;
import group.goforward.battlbuilder.web.dto.catalog.ProductSort; import group.goforward.battlbuilder.web.dto.catalog.ProductSort;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;

View File

@@ -1,55 +1,55 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.model.State; import group.goforward.battlbuilder.model.State;
import group.goforward.battlbuilder.repos.StateRepository; import group.goforward.battlbuilder.repos.StateRepository;
import group.goforward.battlbuilder.services.admin.StatesService; import group.goforward.battlbuilder.services.admin.StatesService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping({"/api/states", "/api/v1/states"}) @RequestMapping({"/api/states", "/api/v1/states"})
public class StateController { public class StateController {
@Autowired @Autowired
private StateRepository repo; private StateRepository repo;
@Autowired @Autowired
private StatesService statesService; private StatesService statesService;
//@Cacheable(value="getAllStates") //@Cacheable(value="getAllStates")
@GetMapping("/all") @GetMapping("/all")
public ResponseEntity<List<State>> getAllStates() { public ResponseEntity<List<State>> getAllStates() {
List<State> state = repo.findAll(); List<State> state = repo.findAll();
return ResponseEntity.ok(state); return ResponseEntity.ok(state);
} }
@GetMapping("/{id}") @GetMapping("/{id}")
public ResponseEntity<State> getAllStatesById(@PathVariable Integer id) { public ResponseEntity<State> getAllStatesById(@PathVariable Integer id) {
return repo.findById(id) return repo.findById(id)
.map(ResponseEntity::ok) .map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
} }
@GetMapping("/byAbbrev/{abbreviation}") @GetMapping("/byAbbrev/{abbreviation}")
public ResponseEntity<State> getAllStatesByAbbreviation(@PathVariable String abbreviation) { public ResponseEntity<State> getAllStatesByAbbreviation(@PathVariable String abbreviation) {
return repo.findByAbbreviation(abbreviation) return repo.findByAbbreviation(abbreviation)
.map(ResponseEntity::ok) .map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
} }
@PostMapping("/addState") @PostMapping("/addState")
public ResponseEntity<State> createState(@RequestBody State item) { public ResponseEntity<State> createState(@RequestBody State item) {
State created = statesService.save(item); State created = statesService.save(item);
return ResponseEntity.status(HttpStatus.CREATED).body(created); return ResponseEntity.status(HttpStatus.CREATED).body(created);
} }
@DeleteMapping("/deleteState/{id}") @DeleteMapping("/deleteState/{id}")
public ResponseEntity<Void> deleteItem(@PathVariable Integer id) { public ResponseEntity<Void> deleteItem(@PathVariable Integer id) {
return statesService.findById(id) return statesService.findById(id)
.map(item -> { .map(item -> {
statesService.deleteById(id); statesService.deleteById(id);
return ResponseEntity.noContent().<Void>build(); return ResponseEntity.noContent().<Void>build();
}) })
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
} }
} }

View File

@@ -1,52 +1,52 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.api.v1;
import group.goforward.battlbuilder.model.User; import group.goforward.battlbuilder.model.User;
import group.goforward.battlbuilder.repos.UserRepository; import group.goforward.battlbuilder.repos.UserRepository;
import group.goforward.battlbuilder.services.admin.UsersService; import group.goforward.battlbuilder.services.admin.UsersService;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping({"/api/user", "/api/v1/user"}) @RequestMapping({"/api/user", "/api/v1/user"})
public class UserController { public class UserController {
private final UserRepository repo; private final UserRepository repo;
private final UsersService usersService; private final UsersService usersService;
public UserController(UserRepository repo, UsersService usersService) { public UserController(UserRepository repo, UsersService usersService) {
this.repo = repo; this.repo = repo;
this.usersService = usersService; this.usersService = usersService;
} }
@GetMapping("/all") @GetMapping("/all")
public ResponseEntity<List<User>> getAllUsers() { public ResponseEntity<List<User>> getAllUsers() {
List<User> data = repo.findAll(); List<User> data = repo.findAll();
return ResponseEntity.ok(data); return ResponseEntity.ok(data);
} }
@GetMapping("/byId/{id}") @GetMapping("/byId/{id}")
public ResponseEntity<User> getAllStatesById(@PathVariable Integer id) { public ResponseEntity<User> getAllStatesById(@PathVariable Integer id) {
return repo.findById(id) return repo.findById(id)
.map(ResponseEntity::ok) .map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
} }
@PostMapping("/addUser") @PostMapping("/addUser")
public ResponseEntity<User> createUser(@RequestBody User item) { public ResponseEntity<User> createUser(@RequestBody User item) {
User created = usersService.save(item); User created = usersService.save(item);
return ResponseEntity.status(HttpStatus.CREATED).body(created); return ResponseEntity.status(HttpStatus.CREATED).body(created);
} }
@DeleteMapping("/deleteUser/{id}") @DeleteMapping("/deleteUser/{id}")
public ResponseEntity<Void> deleteItem(@PathVariable Integer id) { public ResponseEntity<Void> deleteItem(@PathVariable Integer id) {
return usersService.findById(id) return usersService.findById(id)
.map(item -> { .map(item -> {
usersService.deleteById(id); usersService.deleteById(id);
return ResponseEntity.noContent().<Void>build(); return ResponseEntity.noContent().<Void>build();
}) })
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
} }
} }

View File

@@ -8,4 +8,4 @@
* @version 1.0 * @version 1.0
* @since 2025-12-10 * @since 2025-12-10
*/ */
package group.goforward.battlbuilder.controllers.api; package group.goforward.battlbuilder.controllers.api.v1;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.utils;
import group.goforward.battlbuilder.repos.EmailRequestRepository; import group.goforward.battlbuilder.repos.EmailRequestRepository;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;

View File

@@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class PingController { public class PingController {
@GetMapping("/ping") @GetMapping("/api/ping")
public String ping() { public String ping() {
return "pong"; return "pong";
} }

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.controllers; package group.goforward.battlbuilder.controllers.utils;
import group.goforward.battlbuilder.config.ShortLinksProperties; import group.goforward.battlbuilder.config.ShortLinksProperties;
import group.goforward.battlbuilder.repos.ShortLinkRepository; import group.goforward.battlbuilder.repos.ShortLinkRepository;

View File

@@ -1,7 +1,12 @@
package group.goforward.battlbuilder.enrichment.ai; package group.goforward.battlbuilder.enrichment.ai;
import group.goforward.battlbuilder.enrichment.*;
import group.goforward.battlbuilder.enrichment.ai.dto.CaliberExtractionResult; import group.goforward.battlbuilder.enrichment.ai.dto.CaliberExtractionResult;
import group.goforward.battlbuilder.enrichment.domain.CaliberTaxonomy;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentSource;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentStatus;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentType;
import group.goforward.battlbuilder.enrichment.model.ProductEnrichment;
import group.goforward.battlbuilder.enrichment.repo.ProductEnrichmentRepository;
import group.goforward.battlbuilder.model.Product; import group.goforward.battlbuilder.model.Product;
import group.goforward.battlbuilder.repos.ProductRepository; import group.goforward.battlbuilder.repos.ProductRepository;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;

View File

@@ -1,6 +1,12 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.controller;
import group.goforward.battlbuilder.enrichment.ai.AiEnrichmentOrchestrator; import group.goforward.battlbuilder.enrichment.ai.AiEnrichmentOrchestrator;
import group.goforward.battlbuilder.enrichment.domain.CaliberTaxonomy;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentStatus;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentType;
import group.goforward.battlbuilder.enrichment.model.ProductEnrichment;
import group.goforward.battlbuilder.enrichment.repo.ProductEnrichmentRepository;
import group.goforward.battlbuilder.enrichment.service.CaliberEnrichmentService;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.domain;
import java.util.Optional; import java.util.Optional;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.domain;
import java.util.Locale; import java.util.Locale;

View File

@@ -0,0 +1,11 @@
/**
* Domain objects package for the BattlBuilder application.
* <p>
* Contains Objects with business logic.
*
*
* @author Forward Group, LLC
* @version 1.0
* @since 2025-12-10
*/
package group.goforward.battlbuilder.enrichment.domain;

View File

@@ -1,6 +1,8 @@
package group.goforward.battlbuilder.enrichment.dto; package group.goforward.battlbuilder.enrichment.dto;
import group.goforward.battlbuilder.enrichment.*; import group.goforward.battlbuilder.enrichment.enums.EnrichmentSource;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentStatus;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentType;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;

View File

@@ -0,0 +1,11 @@
/**
* Data Transfer Objects package for the BattlBuilder application.
* <p>
* Contains DTOs for the with Enrichments package.
*
*
* @author Forward Group, LLC
* @version 1.0
* @since 2025-12-10
*/
package group.goforward.battlbuilder.enrichment.dto;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.enums;
public enum EnrichmentSource { public enum EnrichmentSource {
AI, AI,

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.enums;
public enum EnrichmentStatus { public enum EnrichmentStatus {
PENDING_REVIEW, PENDING_REVIEW,

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.enums;
public enum EnrichmentType { public enum EnrichmentType {
CALIBER, CALIBER,

View File

@@ -0,0 +1,11 @@
/**
* Enumeration package for the BattlBuilder application.
* <p>
* Contains enumerations for the Enrichments package.
*
*
* @author Forward Group, LLC
* @version 1.0
* @since 2025-12-10
*/
package group.goforward.battlbuilder.enrichment.enums;

View File

@@ -1,5 +1,8 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.model;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentSource;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentStatus;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentType;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes; import org.hibernate.type.SqlTypes;

View File

@@ -1,5 +1,8 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.repo;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentStatus;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentType;
import group.goforward.battlbuilder.enrichment.model.ProductEnrichment;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;

View File

@@ -1,5 +1,11 @@
package group.goforward.battlbuilder.enrichment; package group.goforward.battlbuilder.enrichment.service;
import group.goforward.battlbuilder.enrichment.domain.CaliberRuleExtractor;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentSource;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentStatus;
import group.goforward.battlbuilder.enrichment.enums.EnrichmentType;
import group.goforward.battlbuilder.enrichment.model.ProductEnrichment;
import group.goforward.battlbuilder.enrichment.repo.ProductEnrichmentRepository;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.repos; package group.goforward.battlbuilder.repos.build;
import group.goforward.battlbuilder.model.Brand; import group.goforward.battlbuilder.model.Brand;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional; import java.util.Optional;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.repos; package group.goforward.battlbuilder.repos.build;
import group.goforward.battlbuilder.model.BuildItem; import group.goforward.battlbuilder.model.BuildItem;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.repos; package group.goforward.battlbuilder.repos.build;
import group.goforward.battlbuilder.model.BuildProfile; import group.goforward.battlbuilder.model.BuildProfile;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.repos; package group.goforward.battlbuilder.repos.build;
import group.goforward.battlbuilder.model.Build; import group.goforward.battlbuilder.model.Build;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;

View File

@@ -1,9 +1,9 @@
package group.goforward.battlbuilder.services; package group.goforward.battlbuilder.services;
import group.goforward.battlbuilder.web.dto.BuildDto; import group.goforward.battlbuilder.web.dto.build.BuildDto;
import group.goforward.battlbuilder.web.dto.BuildFeedCardDto; import group.goforward.battlbuilder.web.dto.build.BuildFeedCardDto;
import group.goforward.battlbuilder.web.dto.BuildSummaryDto; import group.goforward.battlbuilder.web.dto.build.BuildSummaryDto;
import group.goforward.battlbuilder.web.dto.UpdateBuildRequest; import group.goforward.battlbuilder.web.dto.UpdateBuildRequestDto;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@@ -16,9 +16,9 @@ public interface BuildService {
BuildDto getMyBuild(UUID uuid); BuildDto getMyBuild(UUID uuid);
BuildDto createMyBuild(UpdateBuildRequest req); BuildDto createMyBuild(UpdateBuildRequestDto req);
BuildDto updateMyBuild(UUID uuid, UpdateBuildRequest req); BuildDto updateMyBuild(UUID uuid, UpdateBuildRequestDto req);
BuildDto getPublicBuild(UUID uuid); BuildDto getPublicBuild(UUID uuid);

View File

@@ -1,6 +1,6 @@
package group.goforward.battlbuilder.services; package group.goforward.battlbuilder.services;
import group.goforward.battlbuilder.web.dto.ProductSummaryDto; import group.goforward.battlbuilder.web.dto.product.ProductSummaryDto;
import group.goforward.battlbuilder.web.dto.catalog.CatalogProductIdsRequest; import group.goforward.battlbuilder.web.dto.catalog.CatalogProductIdsRequest;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;

View File

@@ -1,7 +1,7 @@
package group.goforward.battlbuilder.services; package group.goforward.battlbuilder.services;
import group.goforward.battlbuilder.web.dto.ProductOfferDto; import group.goforward.battlbuilder.web.dto.product.ProductOfferDto;
import group.goforward.battlbuilder.web.dto.ProductSummaryDto; import group.goforward.battlbuilder.web.dto.product.ProductSummaryDto;
import group.goforward.battlbuilder.web.dto.catalog.ProductSort; import group.goforward.battlbuilder.web.dto.catalog.ProductSort;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;

View File

@@ -2,7 +2,7 @@ package group.goforward.battlbuilder.services.impl;
import group.goforward.battlbuilder.model.Brand; import group.goforward.battlbuilder.model.Brand;
import group.goforward.battlbuilder.repos.BrandRepository; import group.goforward.battlbuilder.repos.build.BrandRepository;
import group.goforward.battlbuilder.services.BrandService; import group.goforward.battlbuilder.services.BrandService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;

View File

@@ -4,17 +4,17 @@ import group.goforward.battlbuilder.model.Build;
import group.goforward.battlbuilder.model.BuildItem; import group.goforward.battlbuilder.model.BuildItem;
import group.goforward.battlbuilder.model.BuildProfile; import group.goforward.battlbuilder.model.BuildProfile;
import group.goforward.battlbuilder.model.ProductOffer; import group.goforward.battlbuilder.model.ProductOffer;
import group.goforward.battlbuilder.repos.BuildItemRepository; import group.goforward.battlbuilder.repos.build.BuildItemRepository;
import group.goforward.battlbuilder.repos.BuildProfileRepository; import group.goforward.battlbuilder.repos.build.BuildProfileRepository;
import group.goforward.battlbuilder.repos.BuildRepository; import group.goforward.battlbuilder.repos.build.BuildRepository;
import group.goforward.battlbuilder.repos.ProductOfferRepository; import group.goforward.battlbuilder.repos.ProductOfferRepository;
import group.goforward.battlbuilder.security.CurrentUserService; import group.goforward.battlbuilder.security.CurrentUserService;
import group.goforward.battlbuilder.services.BuildService; import group.goforward.battlbuilder.services.BuildService;
import group.goforward.battlbuilder.web.dto.BuildDto; import group.goforward.battlbuilder.web.dto.build.BuildDto;
import group.goforward.battlbuilder.web.dto.BuildFeedCardDto; import group.goforward.battlbuilder.web.dto.build.BuildFeedCardDto;
import group.goforward.battlbuilder.web.dto.BuildItemDto; import group.goforward.battlbuilder.web.dto.build.BuildItemDto;
import group.goforward.battlbuilder.web.dto.BuildSummaryDto; import group.goforward.battlbuilder.web.dto.build.BuildSummaryDto;
import group.goforward.battlbuilder.web.dto.UpdateBuildRequest; import group.goforward.battlbuilder.web.dto.UpdateBuildRequestDto;
import group.goforward.battlbuilder.repos.ProductRepository; import group.goforward.battlbuilder.repos.ProductRepository;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
@@ -22,8 +22,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
@@ -189,7 +187,7 @@ public class BuildServiceImpl implements BuildService {
@Override @Override
@Transactional @Transactional
public BuildDto createMyBuild(UpdateBuildRequest req) { public BuildDto createMyBuild(UpdateBuildRequestDto req) {
if (req == null) throw new IllegalArgumentException("request body is required"); if (req == null) throw new IllegalArgumentException("request body is required");
Integer userId = currentUserService.requireUserId(); Integer userId = currentUserService.requireUserId();
@@ -269,7 +267,7 @@ public class BuildServiceImpl implements BuildService {
@Override @Override
@Transactional @Transactional
public BuildDto updateMyBuild(UUID uuid, UpdateBuildRequest req) { public BuildDto updateMyBuild(UUID uuid, UpdateBuildRequestDto req) {
if (uuid == null) throw new IllegalArgumentException("uuid is required"); if (uuid == null) throw new IllegalArgumentException("uuid is required");
if (req == null) throw new IllegalArgumentException("request body is required"); if (req == null) throw new IllegalArgumentException("request body is required");
@@ -326,11 +324,11 @@ public class BuildServiceImpl implements BuildService {
// BuildItem helper // BuildItem helper
// --------------------------- // ---------------------------
private List<BuildItem> buildItemsFromRequest(Build build, List<UpdateBuildRequest.Item> incoming) { private List<BuildItem> buildItemsFromRequest(Build build, List<UpdateBuildRequestDto.Item> incoming) {
List<BuildItem> out = new ArrayList<>(); List<BuildItem> out = new ArrayList<>();
if (incoming == null || incoming.isEmpty()) return out; if (incoming == null || incoming.isEmpty()) return out;
for (UpdateBuildRequest.Item it : incoming) { for (UpdateBuildRequestDto.Item it : incoming) {
if (it == null) continue; if (it == null) continue;
if (it.getProductId() == null) continue; if (it.getProductId() == null) continue;
if (it.getSlot() == null || it.getSlot().isBlank()) continue; if (it.getSlot() == null || it.getSlot().isBlank()) continue;

View File

@@ -7,7 +7,7 @@ import group.goforward.battlbuilder.repos.ProductRepository;
import group.goforward.battlbuilder.repos.spec.CatalogProductSpecifications; import group.goforward.battlbuilder.repos.spec.CatalogProductSpecifications;
import group.goforward.battlbuilder.services.CatalogQueryService; import group.goforward.battlbuilder.services.CatalogQueryService;
import group.goforward.battlbuilder.services.ShortLinkService; import group.goforward.battlbuilder.services.ShortLinkService;
import group.goforward.battlbuilder.web.dto.ProductSummaryDto; import group.goforward.battlbuilder.web.dto.product.ProductSummaryDto;
import group.goforward.battlbuilder.web.dto.catalog.CatalogProductIdsRequest; import group.goforward.battlbuilder.web.dto.catalog.CatalogProductIdsRequest;
import group.goforward.battlbuilder.web.mapper.ProductMapper; import group.goforward.battlbuilder.web.mapper.ProductMapper;
import org.springframework.data.domain.*; import org.springframework.data.domain.*;

View File

@@ -12,7 +12,7 @@ import group.goforward.battlbuilder.model.ImportStatus;
import group.goforward.battlbuilder.model.Merchant; import group.goforward.battlbuilder.model.Merchant;
import group.goforward.battlbuilder.model.Product; import group.goforward.battlbuilder.model.Product;
import group.goforward.battlbuilder.model.ProductOffer; import group.goforward.battlbuilder.model.ProductOffer;
import group.goforward.battlbuilder.repos.BrandRepository; import group.goforward.battlbuilder.repos.build.BrandRepository;
import group.goforward.battlbuilder.repos.MerchantRepository; import group.goforward.battlbuilder.repos.MerchantRepository;
import group.goforward.battlbuilder.repos.ProductOfferRepository; import group.goforward.battlbuilder.repos.ProductOfferRepository;
import group.goforward.battlbuilder.repos.ProductRepository; import group.goforward.battlbuilder.repos.ProductRepository;
@@ -27,7 +27,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;

View File

@@ -6,8 +6,8 @@ import group.goforward.battlbuilder.repos.ProductOfferRepository;
import group.goforward.battlbuilder.repos.ProductRepository; import group.goforward.battlbuilder.repos.ProductRepository;
import group.goforward.battlbuilder.services.ProductQueryService; import group.goforward.battlbuilder.services.ProductQueryService;
import group.goforward.battlbuilder.services.ShortLinkService; import group.goforward.battlbuilder.services.ShortLinkService;
import group.goforward.battlbuilder.web.dto.ProductOfferDto; import group.goforward.battlbuilder.web.dto.product.ProductOfferDto;
import group.goforward.battlbuilder.web.dto.ProductSummaryDto; import group.goforward.battlbuilder.web.dto.product.ProductSummaryDto;
import group.goforward.battlbuilder.web.dto.catalog.ProductSort; import group.goforward.battlbuilder.web.dto.catalog.ProductSort;
import group.goforward.battlbuilder.web.mapper.ProductMapper; import group.goforward.battlbuilder.web.mapper.ProductMapper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;

View File

@@ -9,7 +9,7 @@ import java.util.List;
* NOTE: * NOTE:
* - We reuse this for BOTH create (POST /me) and update (PUT /me/{uuid}) for MVP speed. * - We reuse this for BOTH create (POST /me) and update (PUT /me/{uuid}) for MVP speed.
*/ */
public class UpdateBuildRequest { public class UpdateBuildRequestDto {
private String title; private String title;
private String description; private String description;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.build;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.build;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.build;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.build;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.UUID; import java.util.UUID;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.build;
import java.math.BigDecimal; import java.math.BigDecimal;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.build;
import group.goforward.battlbuilder.model.Build; import group.goforward.battlbuilder.model.Build;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.product;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.product;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;

View File

@@ -1,8 +1,7 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.product;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.List;
public class ProductOfferDto { public class ProductOfferDto {
private String id; private String id;

View File

@@ -1,4 +1,4 @@
package group.goforward.battlbuilder.web.dto; package group.goforward.battlbuilder.web.dto.product;
import java.math.BigDecimal; import java.math.BigDecimal;

View File

@@ -1,7 +1,7 @@
package group.goforward.battlbuilder.web.mapper; package group.goforward.battlbuilder.web.mapper;
import group.goforward.battlbuilder.model.Product; import group.goforward.battlbuilder.model.Product;
import group.goforward.battlbuilder.web.dto.ProductSummaryDto; import group.goforward.battlbuilder.web.dto.product.ProductSummaryDto;
import java.math.BigDecimal; import java.math.BigDecimal;