mirror of
https://gitea.gofwd.group/Forward_Group/ballistic-builder-spring.git
synced 2026-01-21 01:01:05 -05:00
changes to build so we can create the screen that is missing
This commit is contained in:
32
.idea/dataSources.xml
generated
32
.idea/dataSources.xml
generated
@@ -1,7 +1,35 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
<data-source source="LOCAL" name="r710" uuid="e6a29f5c-71d9-45f0-931b-554bcf8a94ba">
|
<data-source source="LOCAL" name="ss_builder@r710.dev.gofwd.group" uuid="f0642c9f-ddd8-4def-ab05-e99fc501ff79">
|
||||||
|
<driver-ref>postgresql</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<imported>true</imported>
|
||||||
|
<remarks>$PROJECT_DIR$/src/main/resources/application.properties</remarks>
|
||||||
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:postgresql://r710.dev.gofwd.group:5433/ss_builder</jdbc-url>
|
||||||
|
<jdbc-additional-properties>
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||||
|
</jdbc-additional-properties>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
<data-source source="LOCAL" name="ss_builder@r710.dev.gofwd.group [2]" uuid="d2bd5425-01da-4cf0-8755-229e119dac05">
|
||||||
|
<driver-ref>postgresql</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<imported>true</imported>
|
||||||
|
<remarks>$PROJECT_DIR$/src/main/resources/application.properties</remarks>
|
||||||
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:postgresql://r710.dev.gofwd.group:5433/ss_builder</jdbc-url>
|
||||||
|
<jdbc-additional-properties>
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||||
|
</jdbc-additional-properties>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
<data-source source="LOCAL" name="r710" uuid="14176613-3667-4490-82a9-caaa686ecb9c">
|
||||||
<driver-ref>postgresql</driver-ref>
|
<driver-ref>postgresql</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
@@ -13,7 +41,7 @@
|
|||||||
</jdbc-additional-properties>
|
</jdbc-additional-properties>
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
</data-source>
|
</data-source>
|
||||||
<data-source source="LOCAL" name="ss_builder@r710.gofwd.group" uuid="e0fa459b-2f6c-45f1-9c41-66423c870df9">
|
<data-source source="LOCAL" name="ss_builder@r710.gofwd.group" uuid="9ecc288e-c6f1-4444-85ce-ecad1cb0c4df">
|
||||||
<driver-ref>postgresql</driver-ref>
|
<driver-ref>postgresql</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<imported>true</imported>
|
<imported>true</imported>
|
||||||
|
|||||||
19
.mvn/wrapper/maven-wrapper.properties
vendored
19
.mvn/wrapper/maven-wrapper.properties
vendored
@@ -1,19 +0,0 @@
|
|||||||
# Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
# or more contributor license agreements. See the NOTICE file
|
|
||||||
# distributed with this work for additional information
|
|
||||||
# regarding copyright ownership. The ASF licenses this file
|
|
||||||
# to you under the Apache License, Version 2.0 (the
|
|
||||||
# "License"); you may not use this file except in compliance
|
|
||||||
# with the License. You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing,
|
|
||||||
# software distributed under the License is distributed on an
|
|
||||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
# KIND, either express or implied. See the License for the
|
|
||||||
# specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
wrapperVersion=3.3.2
|
|
||||||
distributionType=only-script
|
|
||||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
|
|
||||||
@@ -44,7 +44,7 @@ The frontend Builder depends on this backend for:
|
|||||||
## Tech Stack
|
## Tech Stack
|
||||||
|
|
||||||
- **Spring Boot 3.x**
|
- **Spring Boot 3.x**
|
||||||
- **Java 17**
|
- **Java 21**
|
||||||
- **PostgreSQL**
|
- **PostgreSQL**
|
||||||
- **Hibernate (JPA)**
|
- **Hibernate (JPA)**
|
||||||
- **HikariCP**
|
- **HikariCP**
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package group.goforward.battlbuilder.controllers.api.v1;
|
|||||||
|
|
||||||
import group.goforward.battlbuilder.model.Build;
|
import group.goforward.battlbuilder.model.Build;
|
||||||
import group.goforward.battlbuilder.repos.build.BuildRepository;
|
import group.goforward.battlbuilder.repos.build.BuildRepository;
|
||||||
|
import group.goforward.battlbuilder.web.dto.build.BuildDto;
|
||||||
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.*;
|
||||||
@@ -10,7 +11,7 @@ import java.util.List;
|
|||||||
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/v1/api/builds")
|
@RequestMapping("/api/builds")
|
||||||
public class BuildController {
|
public class BuildController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private BuildRepository repo;
|
private BuildRepository repo;
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
package group.goforward.battlbuilder.domain;
|
||||||
|
;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Imports of data from feeds
|
||||||
|
*
|
||||||
|
* <p>The main entry point for managing the inventory is the
|
||||||
|
* {@link group.goforward.battlbuilder.BattlBuilderApplication} class.</p>
|
||||||
|
*
|
||||||
|
* @since 1.0
|
||||||
|
* @author Sean Strawsburg
|
||||||
|
* @version 1.1
|
||||||
|
*/
|
||||||
|
package group.goforward.battlbuilder.imports;
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package group.goforward.battlbuilder.mapper;
|
||||||
|
|
||||||
|
import group.goforward.battlbuilder.model.BuildItem;
|
||||||
|
import group.goforward.battlbuilder.model.Product;
|
||||||
|
import group.goforward.battlbuilder.web.dto.build.BuildItemDto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class BuildItemMapper {
|
||||||
|
|
||||||
|
private BuildItemMapper() {
|
||||||
|
// utility class
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// BuildItem → BuildItemDto
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public static BuildItemDto toDto(BuildItem item) {
|
||||||
|
if (item == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildItemDto dto = new BuildItemDto();
|
||||||
|
|
||||||
|
dto.setId(item.getId() != null ? String.valueOf(item.getId()) : null);
|
||||||
|
dto.setUuid(item.getUuid());
|
||||||
|
|
||||||
|
dto.setSlot(item.getSlot());
|
||||||
|
dto.setPosition(item.getPosition());
|
||||||
|
dto.setQuantity(item.getQuantity());
|
||||||
|
|
||||||
|
Product product = item.getProduct();
|
||||||
|
if (product != null) {
|
||||||
|
dto.setProductId(product.getId() != null ? String.valueOf(product.getId()) : null);
|
||||||
|
dto.setProductName(product.getName());
|
||||||
|
dto.setProductBrand(
|
||||||
|
product.getBrand() != null ? product.getBrand().getName() : null
|
||||||
|
);
|
||||||
|
dto.setProductImageUrl(product.getMainImageUrl());
|
||||||
|
// bestPrice remains a concern of a pricing service / aggregator
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// BuildItemDto → BuildItem
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public static BuildItem toEntity(BuildItemDto dto) {
|
||||||
|
if (dto == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildItem entity = new BuildItem();
|
||||||
|
|
||||||
|
if (dto.getId() != null && !dto.getId().isBlank()) {
|
||||||
|
try {
|
||||||
|
entity.setId(Integer.valueOf(dto.getId()));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
// leave id null if parsing fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.setUuid(dto.getUuid());
|
||||||
|
entity.setSlot(dto.getSlot());
|
||||||
|
entity.setPosition(dto.getPosition());
|
||||||
|
entity.setQuantity(dto.getQuantity());
|
||||||
|
|
||||||
|
// Product + Build references should be set by the service layer:
|
||||||
|
// - resolve product via ProductRepository using dto.getProductId()
|
||||||
|
// - assign Build via build.addItem(item) or item.setBuild(build)
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// Collection helpers
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public static List<BuildItemDto> toDtoList(List<BuildItem> items) {
|
||||||
|
if (items == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return items.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(BuildItemMapper::toDto)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<BuildItem> toEntityList(List<BuildItemDto> dtos) {
|
||||||
|
if (dtos == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return dtos.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(BuildItemMapper::toEntity)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package group.goforward.battlbuilder.mapper;
|
||||||
|
|
||||||
|
import group.goforward.battlbuilder.model.Build;
|
||||||
|
import group.goforward.battlbuilder.model.BuildItem;
|
||||||
|
import group.goforward.battlbuilder.model.Product;
|
||||||
|
import group.goforward.battlbuilder.web.dto.build.BuildDto;
|
||||||
|
import group.goforward.battlbuilder.web.dto.build.BuildItemDto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class BuildMapper {
|
||||||
|
|
||||||
|
private BuildMapper() {
|
||||||
|
// utility class
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// Build → BuildDto
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public static BuildDto toDto(Build entity) {
|
||||||
|
if (entity == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildDto dto = new BuildDto();
|
||||||
|
|
||||||
|
dto.setId(entity.getId() != null ? String.valueOf(entity.getId()) : null);
|
||||||
|
dto.setUuid(entity.getUuid());
|
||||||
|
|
||||||
|
dto.setTitle(entity.getTitle());
|
||||||
|
dto.setDescription(entity.getDescription());
|
||||||
|
dto.setIsPublic(entity.getIsPublic());
|
||||||
|
|
||||||
|
dto.setCreatedAt(entity.getCreatedAt());
|
||||||
|
dto.setUpdatedAt(entity.getUpdatedAt());
|
||||||
|
|
||||||
|
if (entity.getItems() != null) {
|
||||||
|
dto.setItems(
|
||||||
|
entity.getItems().stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(BuildMapper::toItemDto)
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// BuildDto → Build
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public static Build toEntity(BuildDto dto) {
|
||||||
|
if (dto == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Build entity = new Build();
|
||||||
|
|
||||||
|
if (dto.getId() != null && !dto.getId().isBlank()) {
|
||||||
|
try {
|
||||||
|
entity.setId(Integer.valueOf(dto.getId()));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
// leave id null if it can't be parsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.setUuid(dto.getUuid());
|
||||||
|
|
||||||
|
entity.setTitle(dto.getTitle());
|
||||||
|
entity.setDescription(dto.getDescription());
|
||||||
|
entity.setIsPublic(dto.getIsPublic());
|
||||||
|
|
||||||
|
entity.setCreatedAt(dto.getCreatedAt());
|
||||||
|
entity.setUpdatedAt(dto.getUpdatedAt());
|
||||||
|
|
||||||
|
// Items are typically managed separately (service layer),
|
||||||
|
// so we don't automatically map DTO items back to entities here.
|
||||||
|
// If you want that, wire in a factory/lookup for Product and hydrate BuildItem.
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// BuildItem → BuildItemDto
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
private static BuildItemDto toItemDto(BuildItem item) {
|
||||||
|
BuildItemDto dto = new BuildItemDto();
|
||||||
|
|
||||||
|
dto.setId(item.getId() != null ? String.valueOf(item.getId()) : null);
|
||||||
|
dto.setUuid(item.getUuid());
|
||||||
|
|
||||||
|
dto.setSlot(item.getSlot());
|
||||||
|
dto.setPosition(item.getPosition());
|
||||||
|
dto.setQuantity(item.getQuantity());
|
||||||
|
|
||||||
|
Product product = item.getProduct();
|
||||||
|
if (product != null) {
|
||||||
|
dto.setProductId(product.getId() != null ? String.valueOf(product.getId()) : null);
|
||||||
|
dto.setProductName(product.getName());
|
||||||
|
dto.setProductBrand(
|
||||||
|
product.getBrand() != null ? product.getBrand().getName() : null
|
||||||
|
);
|
||||||
|
dto.setProductImageUrl(product.getMainImageUrl());
|
||||||
|
// bestPrice is intentionally left for service-layer aggregation
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// Collection helpers
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public static List<BuildDto> toDtoList(List<Build> entities) {
|
||||||
|
if (entities == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return entities.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(BuildMapper::toDto)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package group.goforward.battlbuilder.model;
|
package group.goforward.battlbuilder.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonManagedReference;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
import org.hibernate.annotations.ColumnDefault;
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -60,6 +63,10 @@ public class Build {
|
|||||||
@Column(name = "deleted_at")
|
@Column(name = "deleted_at")
|
||||||
private OffsetDateTime deletedAt;
|
private OffsetDateTime deletedAt;
|
||||||
|
|
||||||
|
@JsonManagedReference
|
||||||
|
@OneToMany(mappedBy = "build", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
private List<BuildItem> items = new ArrayList<>();
|
||||||
|
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
// Hibernate lifecycle
|
// Hibernate lifecycle
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
@@ -106,4 +113,22 @@ public class Build {
|
|||||||
|
|
||||||
public OffsetDateTime getDeletedAt() { return deletedAt; }
|
public OffsetDateTime getDeletedAt() { return deletedAt; }
|
||||||
public void setDeletedAt(OffsetDateTime deletedAt) { this.deletedAt = deletedAt; }
|
public void setDeletedAt(OffsetDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||||
|
|
||||||
|
public List<BuildItem> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<BuildItem> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItem(BuildItem item) {
|
||||||
|
items.add(item);
|
||||||
|
item.setBuild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeItem(BuildItem item) {
|
||||||
|
items.remove(item);
|
||||||
|
item.setBuild(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package group.goforward.battlbuilder.model;
|
package group.goforward.battlbuilder.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonBackReference;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import org.hibernate.annotations.ColumnDefault;
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
@@ -22,6 +23,7 @@ public class BuildItem {
|
|||||||
@Column(name = "uuid", nullable = false)
|
@Column(name = "uuid", nullable = false)
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
|
|
||||||
|
@JsonBackReference
|
||||||
@NotNull
|
@NotNull
|
||||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||||
@OnDelete(action = OnDeleteAction.CASCADE)
|
@OnDelete(action = OnDeleteAction.CASCADE)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class Product {
|
|||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "brand_id", nullable = false)
|
@JoinColumn(name = "brand_id", nullable = true)
|
||||||
private Brand brand;
|
private Brand brand;
|
||||||
|
|
||||||
@Column(name = "name", nullable = false)
|
@Column(name = "name", nullable = false)
|
||||||
|
|||||||
@@ -79,3 +79,6 @@ app.beta.invite.tokenMinutes=30
|
|||||||
ai.minConfidence=0.75
|
ai.minConfidence=0.75
|
||||||
ai.openai.apiKey=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
|
ai.openai.apiKey=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
|
||||||
ai.openai.model=gpt-4.1-mini
|
ai.openai.model=gpt-4.1-mini
|
||||||
|
|
||||||
|
|
||||||
|
spring.jackson.serialization.fail-on-empty-beans=false
|
||||||
Reference in New Issue
Block a user