From 814b2221c80287594dd18d801305ab6ec04e19f6 Mon Sep 17 00:00:00 2001 From: Cedric Date: Sat, 10 May 2025 19:07:50 +0200 Subject: [PATCH 1/2] #7 --- dev-docker-compose.yml | 52 +++++++++++++++++++ docker-compose.yml | 2 +- dockerfile | 2 +- .../controller/AppUserController.java | 2 +- .../controller/ExpenseListController.java | 1 + .../model/DTO/ExpenseListDTO.java | 8 +++ .../UsernameAlreadyExistsException.java | 2 +- .../app/xpensely_server/model/Expense.java | 2 +- .../xpensely_server/model/ExpenseList.java | 9 ++++ .../model/XpenselyCustomCategory.java | 37 +++++++++++++ .../model/XpenselyStandardCategories.java | 29 +++++++++++ .../model/XpenselyStandardCategory.java | 27 ++++++++++ .../preparation/DataInitializer.java | 35 +++++++++++++ .../XpenselyCustomCategoryRepository.java | 10 ++++ .../XpenselyStandardCategoriesRepository.java | 11 ++++ .../security/SecurityConfig.java | 19 ++++--- .../services/ExpenseListService.java | 27 +++++++++- .../xpensely_server/services/UserService.java | 2 +- .../ExpenseListRepositoryTest.java | 26 ++++++++++ .../XpenselyServerApplicationTests.java | 13 ----- 20 files changed, 288 insertions(+), 28 deletions(-) create mode 100644 dev-docker-compose.yml create mode 100644 src/main/java/de/zendric/app/xpensely_server/model/DTO/ExpenseListDTO.java rename src/main/java/de/zendric/app/xpensely_server/model/{ => Exception}/UsernameAlreadyExistsException.java (84%) create mode 100644 src/main/java/de/zendric/app/xpensely_server/model/XpenselyCustomCategory.java create mode 100644 src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategories.java create mode 100644 src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategory.java create mode 100644 src/main/java/de/zendric/app/xpensely_server/preparation/DataInitializer.java create mode 100644 src/main/java/de/zendric/app/xpensely_server/repo/XpenselyCustomCategoryRepository.java create mode 100644 src/main/java/de/zendric/app/xpensely_server/repo/XpenselyStandardCategoriesRepository.java create mode 100644 src/test/java/de/zendric/app/xpensely_Server/ExpenseListRepositoryTest.java delete mode 100644 src/test/java/de/zendric/app/xpensely_Server/XpenselyServerApplicationTests.java diff --git a/dev-docker-compose.yml b/dev-docker-compose.yml new file mode 100644 index 0000000..972d12c --- /dev/null +++ b/dev-docker-compose.yml @@ -0,0 +1,52 @@ +version: "3.8" +services: + xpensely-server: + build: + context: . + dockerfile: Dockerfile + image: xpensely-server:local + labels: + net.unraid.docker.icon: https://tea.zendric.de/Cedric/XpenselyServer/raw/branch/main/src/main/resources/static/xpensely_icon_white.png + container_name: xpensely-server + ports: + - 3636:8080 + environment: + GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID} + GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET} + DB_PORT: 5432 + DB_P_NAME: xpensely + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + SPRING_PROFILES_ACTIVE: test + depends_on: + postgresdb: + condition: service_healthy + networks: + - xpensely-network + postgresdb: + labels: + net.unraid.docker.icon: https://raw.githubusercontent.com/docker-library/docs/01c12653951b2fe592c1f93a13b4e289ada0e3a1/postgres/logo.png + image: postgres:14 + container_name: postgresdb + ports: + - 5435:5432 + environment: + POSTGRES_DB: xpensely + POSTGRES_USER: ${DB_USERNAME} + POSTGRES_PASSWORD: ${DB_PASSWORD} + networks: + - xpensely-network + volumes: + - db_data:/var/lib/postgresql/data + restart: unless-stopped + healthcheck: + test: + - CMD-SHELL + - pg_isready -U ${DB_USERNAME} -d xpensely + interval: 10s + timeout: 5s + retries: 5 +volumes: + db_data: null +networks: + xpensely-network: null diff --git a/docker-compose.yml b/docker-compose.yml index 7d64546..dad15a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,7 +25,7 @@ services: image: postgres:14 container_name: postgresdb ports: - - 5432:5432 + - 5435:5432 environment: POSTGRES_DB: xpensely POSTGRES_USER: ${DB_USERNAME} diff --git a/dockerfile b/dockerfile index f7e9a76..a3702e8 100644 --- a/dockerfile +++ b/dockerfile @@ -4,4 +4,4 @@ COPY ./target/*.jar app.jar EXPOSE 8080 -ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file +ENTRYPOINT ["java","-jar", "app.jar"] \ No newline at end of file diff --git a/src/main/java/de/zendric/app/xpensely_server/controller/AppUserController.java b/src/main/java/de/zendric/app/xpensely_server/controller/AppUserController.java index e0b9994..597d733 100644 --- a/src/main/java/de/zendric/app/xpensely_server/controller/AppUserController.java +++ b/src/main/java/de/zendric/app/xpensely_server/controller/AppUserController.java @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController; import de.zendric.app.xpensely_server.model.AppUser; import de.zendric.app.xpensely_server.model.AppUserCreateRequest; -import de.zendric.app.xpensely_server.model.UsernameAlreadyExistsException; +import de.zendric.app.xpensely_server.model.Exception.UsernameAlreadyExistsException; import de.zendric.app.xpensely_server.services.UserService; @RestController diff --git a/src/main/java/de/zendric/app/xpensely_server/controller/ExpenseListController.java b/src/main/java/de/zendric/app/xpensely_server/controller/ExpenseListController.java index 3a407fb..ff06c54 100644 --- a/src/main/java/de/zendric/app/xpensely_server/controller/ExpenseListController.java +++ b/src/main/java/de/zendric/app/xpensely_server/controller/ExpenseListController.java @@ -96,6 +96,7 @@ class ExpenseListController { } @PostMapping("/create") + // TODO add handling of categories by using DTO public ResponseEntity create(@RequestBody ExpenseList expenseList) { try { if (expenseList.getOwner() != null) { diff --git a/src/main/java/de/zendric/app/xpensely_server/model/DTO/ExpenseListDTO.java b/src/main/java/de/zendric/app/xpensely_server/model/DTO/ExpenseListDTO.java new file mode 100644 index 0000000..4912984 --- /dev/null +++ b/src/main/java/de/zendric/app/xpensely_server/model/DTO/ExpenseListDTO.java @@ -0,0 +1,8 @@ +package de.zendric.app.xpensely_server.model.DTO; + +public class ExpenseListDTO { + + // TODO should combine the two categories two one; + + // private List availableCategories; +} diff --git a/src/main/java/de/zendric/app/xpensely_server/model/UsernameAlreadyExistsException.java b/src/main/java/de/zendric/app/xpensely_server/model/Exception/UsernameAlreadyExistsException.java similarity index 84% rename from src/main/java/de/zendric/app/xpensely_server/model/UsernameAlreadyExistsException.java rename to src/main/java/de/zendric/app/xpensely_server/model/Exception/UsernameAlreadyExistsException.java index b0645d8..e0240b7 100644 --- a/src/main/java/de/zendric/app/xpensely_server/model/UsernameAlreadyExistsException.java +++ b/src/main/java/de/zendric/app/xpensely_server/model/Exception/UsernameAlreadyExistsException.java @@ -1,4 +1,4 @@ -package de.zendric.app.xpensely_server.model; +package de.zendric.app.xpensely_server.model.Exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/src/main/java/de/zendric/app/xpensely_server/model/Expense.java b/src/main/java/de/zendric/app/xpensely_server/model/Expense.java index ab7bab7..9e97e24 100644 --- a/src/main/java/de/zendric/app/xpensely_server/model/Expense.java +++ b/src/main/java/de/zendric/app/xpensely_server/model/Expense.java @@ -34,7 +34,7 @@ public class Expense { private Double amount; private Double personalUseAmount; private Double otherPersonAmount; - + private String category; private LocalDate date; @ManyToOne diff --git a/src/main/java/de/zendric/app/xpensely_server/model/ExpenseList.java b/src/main/java/de/zendric/app/xpensely_server/model/ExpenseList.java index a31f9de..4902f2f 100644 --- a/src/main/java/de/zendric/app/xpensely_server/model/ExpenseList.java +++ b/src/main/java/de/zendric/app/xpensely_server/model/ExpenseList.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -40,6 +41,14 @@ public class ExpenseList { @ManyToOne private AppUser sharedWith; + @ManyToOne(fetch = FetchType.EAGER) + private XpenselyStandardCategories xpenselyStandardCategories; + + @OneToMany(mappedBy = "expenseList", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonManagedReference + @jakarta.persistence.OrderBy("name ASC") + private List customCategories; + @OneToMany(mappedBy = "expenseList", cascade = CascadeType.ALL, orphanRemoval = true) @JsonManagedReference @jakarta.persistence.OrderBy("date ASC, id ASC") diff --git a/src/main/java/de/zendric/app/xpensely_server/model/XpenselyCustomCategory.java b/src/main/java/de/zendric/app/xpensely_server/model/XpenselyCustomCategory.java new file mode 100644 index 0000000..21f01aa --- /dev/null +++ b/src/main/java/de/zendric/app/xpensely_server/model/XpenselyCustomCategory.java @@ -0,0 +1,37 @@ +package de.zendric.app.xpensely_server.model; + +import com.fasterxml.jackson.annotation.JsonBackReference; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class XpenselyCustomCategory { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @Column(name = "color_code", length = 7, nullable = false) + private String colorCode; + + @ManyToOne + @JoinColumn(name = "expense_list_id", nullable = false) + @JsonBackReference + private ExpenseList expenseList; +} diff --git a/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategories.java b/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategories.java new file mode 100644 index 0000000..44ecb3a --- /dev/null +++ b/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategories.java @@ -0,0 +1,29 @@ +package de.zendric.app.xpensely_server.model; + +import java.util.List; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class XpenselyStandardCategories { + + @Id + private Long id; + + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "global_categories_id") + private List categories; +} \ No newline at end of file diff --git a/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategory.java b/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategory.java new file mode 100644 index 0000000..74e1219 --- /dev/null +++ b/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategory.java @@ -0,0 +1,27 @@ +package de.zendric.app.xpensely_server.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class XpenselyStandardCategory { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @Column(name = "color_code", length = 7, nullable = false) + private String colorCode; +} diff --git a/src/main/java/de/zendric/app/xpensely_server/preparation/DataInitializer.java b/src/main/java/de/zendric/app/xpensely_server/preparation/DataInitializer.java new file mode 100644 index 0000000..a065c9f --- /dev/null +++ b/src/main/java/de/zendric/app/xpensely_server/preparation/DataInitializer.java @@ -0,0 +1,35 @@ +package de.zendric.app.xpensely_server.preparation; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import de.zendric.app.xpensely_server.model.XpenselyStandardCategories; +import de.zendric.app.xpensely_server.model.XpenselyStandardCategory; +import de.zendric.app.xpensely_server.repo.XpenselyStandardCategoriesRepository; + +@Component +public class DataInitializer implements CommandLineRunner { + + @Autowired + private XpenselyStandardCategoriesRepository globalRepo; + + @Override + public void run(String... args) throws Exception { + if (!globalRepo.findById(1L).isPresent()) { + XpenselyStandardCategories global = new XpenselyStandardCategories(); + global.setId(1L); + + List categories = List.of( + new XpenselyStandardCategory(null, "Food", "#FF5733"), + new XpenselyStandardCategory(null, "Transportation", "#33C3FF"), + new XpenselyStandardCategory(null, "Entertainment", "#33FF57"), + new XpenselyStandardCategory(null, "Shopping", "#FF33A8"), + new XpenselyStandardCategory(null, "Bills", "#33FFEA")); + global.setCategories(categories); + globalRepo.save(global); + } + } +} diff --git a/src/main/java/de/zendric/app/xpensely_server/repo/XpenselyCustomCategoryRepository.java b/src/main/java/de/zendric/app/xpensely_server/repo/XpenselyCustomCategoryRepository.java new file mode 100644 index 0000000..0b051a9 --- /dev/null +++ b/src/main/java/de/zendric/app/xpensely_server/repo/XpenselyCustomCategoryRepository.java @@ -0,0 +1,10 @@ +package de.zendric.app.xpensely_server.repo; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import de.zendric.app.xpensely_server.model.XpenselyCustomCategory; + +@Repository +public interface XpenselyCustomCategoryRepository extends JpaRepository { +} diff --git a/src/main/java/de/zendric/app/xpensely_server/repo/XpenselyStandardCategoriesRepository.java b/src/main/java/de/zendric/app/xpensely_server/repo/XpenselyStandardCategoriesRepository.java new file mode 100644 index 0000000..9c59792 --- /dev/null +++ b/src/main/java/de/zendric/app/xpensely_server/repo/XpenselyStandardCategoriesRepository.java @@ -0,0 +1,11 @@ +package de.zendric.app.xpensely_server.repo; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import de.zendric.app.xpensely_server.model.XpenselyStandardCategories; + +@Repository +public interface XpenselyStandardCategoriesRepository extends JpaRepository { + +} diff --git a/src/main/java/de/zendric/app/xpensely_server/security/SecurityConfig.java b/src/main/java/de/zendric/app/xpensely_server/security/SecurityConfig.java index b4883a3..d0d2465 100644 --- a/src/main/java/de/zendric/app/xpensely_server/security/SecurityConfig.java +++ b/src/main/java/de/zendric/app/xpensely_server/security/SecurityConfig.java @@ -2,6 +2,7 @@ package de.zendric.app.xpensely_server.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -10,17 +11,19 @@ import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { - // @Bean - // public SecurityFilterChain securityFilterChain(HttpSecurity http) throws - // Exception { - // http.authorizeHttpRequests(auth -> auth - // .anyRequest().permitAll()).csrf().disable(); - // ; + @Bean + @Profile("test") // Only enable this for testing + public SecurityFilterChain testSecurityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(auth -> auth + .anyRequest().permitAll()) + .csrf().disable(); - // return http.build(); - // } + return http.build(); + } @Bean + @Profile("!test") public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth diff --git a/src/main/java/de/zendric/app/xpensely_server/services/ExpenseListService.java b/src/main/java/de/zendric/app/xpensely_server/services/ExpenseListService.java index 445ab1f..87ac564 100644 --- a/src/main/java/de/zendric/app/xpensely_server/services/ExpenseListService.java +++ b/src/main/java/de/zendric/app/xpensely_server/services/ExpenseListService.java @@ -14,8 +14,10 @@ import org.springframework.transaction.annotation.Transactional; import de.zendric.app.xpensely_server.model.AppUser; import de.zendric.app.xpensely_server.model.Expense; import de.zendric.app.xpensely_server.model.ExpenseList; +import de.zendric.app.xpensely_server.model.XpenselyCustomCategory; import de.zendric.app.xpensely_server.repo.ExpenseListRepository; import de.zendric.app.xpensely_server.repo.ExpenseRepository; +import de.zendric.app.xpensely_server.repo.XpenselyCustomCategoryRepository; import jakarta.persistence.EntityManager; @Service @@ -24,14 +26,17 @@ public class ExpenseListService { private ExpenseListRepository repository; private final ExpenseRepository expenseRepository; + private XpenselyCustomCategoryRepository customCategoryRepository; @Autowired private EntityManager entityManager; @Autowired - public ExpenseListService(ExpenseListRepository repository, ExpenseRepository expenseRepository) { + public ExpenseListService(ExpenseListRepository repository, ExpenseRepository expenseRepository, + XpenselyCustomCategoryRepository customCategoryRepository) { this.repository = repository; this.expenseRepository = expenseRepository; + this.customCategoryRepository = customCategoryRepository; } public List getAllLists() { @@ -181,4 +186,24 @@ public class ExpenseListService { return expenseRepository.save(existingExpense); } + + // TODO implement API for this + public XpenselyCustomCategory addCustomCategory(Long expenseListId, XpenselyCustomCategory customCategory) { + ExpenseList expenseList = repository.findById(expenseListId) + .orElseThrow(() -> new RuntimeException("Expense List not found")); + customCategory.setExpenseList(expenseList); + + return customCategoryRepository.save(customCategory); + } + + // TODO implement API for this + public void deleteCustomCategory(Long expenseListId, Long categoryId) { + XpenselyCustomCategory category = customCategoryRepository.findById(categoryId) + .orElseThrow(() -> new RuntimeException("Custom Category not found")); + if (!category.getExpenseList().getId().equals(expenseListId)) { + throw new RuntimeException("Category does not belong to the specified Expense List"); + } + customCategoryRepository.delete(category); + } + } \ No newline at end of file diff --git a/src/main/java/de/zendric/app/xpensely_server/services/UserService.java b/src/main/java/de/zendric/app/xpensely_server/services/UserService.java index 58298dc..dc0dee7 100644 --- a/src/main/java/de/zendric/app/xpensely_server/services/UserService.java +++ b/src/main/java/de/zendric/app/xpensely_server/services/UserService.java @@ -6,7 +6,7 @@ import java.util.Optional; import org.springframework.stereotype.Service; import de.zendric.app.xpensely_server.model.AppUser; -import de.zendric.app.xpensely_server.model.UsernameAlreadyExistsException; +import de.zendric.app.xpensely_server.model.Exception.UsernameAlreadyExistsException; import de.zendric.app.xpensely_server.repo.UserRepository; @Service diff --git a/src/test/java/de/zendric/app/xpensely_Server/ExpenseListRepositoryTest.java b/src/test/java/de/zendric/app/xpensely_Server/ExpenseListRepositoryTest.java new file mode 100644 index 0000000..6a4cb49 --- /dev/null +++ b/src/test/java/de/zendric/app/xpensely_Server/ExpenseListRepositoryTest.java @@ -0,0 +1,26 @@ +package de.zendric.app.xpensely_Server; + +import java.util.Optional; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import de.zendric.app.xpensely_server.model.ExpenseList; +import de.zendric.app.xpensely_server.repo.ExpenseListRepository; + +@DataJpaTest +class ExpenseListRepositoryTest { + + @Autowired + private ExpenseListRepository expenseListRepository; + + @Test + void testFindExpenseListById() { + // Assuming an ExpenseList with id = 1 exists in your test DB. + Optional optionalExpenseList = expenseListRepository.findById(1L); + + ExpenseList expenseList = optionalExpenseList.get(); + System.out.println("ExpenseList name: " + expenseList.getName()); + } +} diff --git a/src/test/java/de/zendric/app/xpensely_Server/XpenselyServerApplicationTests.java b/src/test/java/de/zendric/app/xpensely_Server/XpenselyServerApplicationTests.java deleted file mode 100644 index 3c78751..0000000 --- a/src/test/java/de/zendric/app/xpensely_Server/XpenselyServerApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.zendric.app.xpensely_Server; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class XpenselyServerApplicationTests { - - @Test - void contextLoads() { - } - -} -- 2.49.1 From 15792bad28d3fb0d6abb45b459fd5dfbb122f6ca Mon Sep 17 00:00:00 2001 From: Cedric Date: Sun, 11 May 2025 00:59:54 +0200 Subject: [PATCH 2/2] Add CategoryService and integrate category handling in ExpenseListController - Introduced CategoryService to manage standard categories. - Updated ExpenseListController to set default categories when creating an expense list. - Modified ExpenseChangeRequest and ExpenseInput to include category field. - Enhanced DataInitializer to ensure standard categories are initialized. --- .../controller/ExpenseListController.java | 9 +++++- .../model/DTO/ExpenseListDTO.java | 2 +- .../model/ExpenseChangeRequest.java | 2 ++ .../xpensely_server/model/ExpenseInput.java | 2 ++ .../model/XpenselyStandardCategories.java | 2 +- .../preparation/DataInitializer.java | 29 +++++++++++-------- .../services/CategoryService.java | 24 +++++++++++++++ .../services/ExpenseListService.java | 1 + 8 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 src/main/java/de/zendric/app/xpensely_server/services/CategoryService.java diff --git a/src/main/java/de/zendric/app/xpensely_server/controller/ExpenseListController.java b/src/main/java/de/zendric/app/xpensely_server/controller/ExpenseListController.java index ff06c54..efaa067 100644 --- a/src/main/java/de/zendric/app/xpensely_server/controller/ExpenseListController.java +++ b/src/main/java/de/zendric/app/xpensely_server/controller/ExpenseListController.java @@ -24,6 +24,8 @@ import de.zendric.app.xpensely_server.model.ExpenseChangeRequest; import de.zendric.app.xpensely_server.model.ExpenseInput; import de.zendric.app.xpensely_server.model.ExpenseList; import de.zendric.app.xpensely_server.model.InviteRequest; +import de.zendric.app.xpensely_server.model.XpenselyStandardCategories; +import de.zendric.app.xpensely_server.services.CategoryService; import de.zendric.app.xpensely_server.services.ExpenseListService; import de.zendric.app.xpensely_server.services.UserService; @@ -33,11 +35,14 @@ class ExpenseListController { private ExpenseListService expenseListService; private UserService userService; + private CategoryService categoryService; @Autowired - public ExpenseListController(ExpenseListService expenseListService, UserService userService) { + public ExpenseListController(ExpenseListService expenseListService, UserService userService, + CategoryService categoryService) { this.expenseListService = expenseListService; this.userService = userService; + this.categoryService = categoryService; } @GetMapping("/all") @@ -105,6 +110,8 @@ class ExpenseListController { throw new IllegalArgumentException("Owner does not exist."); } expenseList.setOwner(existingOwner); + XpenselyStandardCategories standardCategories = categoryService.getDefaultCategories(); + expenseList.setXpenselyStandardCategories(standardCategories); } else { throw new IllegalArgumentException("Owner is required."); } diff --git a/src/main/java/de/zendric/app/xpensely_server/model/DTO/ExpenseListDTO.java b/src/main/java/de/zendric/app/xpensely_server/model/DTO/ExpenseListDTO.java index 4912984..7e06f3b 100644 --- a/src/main/java/de/zendric/app/xpensely_server/model/DTO/ExpenseListDTO.java +++ b/src/main/java/de/zendric/app/xpensely_server/model/DTO/ExpenseListDTO.java @@ -2,7 +2,7 @@ package de.zendric.app.xpensely_server.model.DTO; public class ExpenseListDTO { - // TODO should combine the two categories two one; + // TODO should combine the two categories to one; // private List availableCategories; } diff --git a/src/main/java/de/zendric/app/xpensely_server/model/ExpenseChangeRequest.java b/src/main/java/de/zendric/app/xpensely_server/model/ExpenseChangeRequest.java index c028b00..65f8edd 100644 --- a/src/main/java/de/zendric/app/xpensely_server/model/ExpenseChangeRequest.java +++ b/src/main/java/de/zendric/app/xpensely_server/model/ExpenseChangeRequest.java @@ -18,6 +18,7 @@ public class ExpenseChangeRequest { private Double personalUseAmount; private Double otherPersonAmount; private LocalDate date; + private String category; public Expense convertToExpense(Long userId, ExpenseList expenseList) { AppUser appUser = new AppUser(); @@ -33,6 +34,7 @@ public class ExpenseChangeRequest { expense.setId(id); expense.setOwner(appUser); expense.setTitle(title); + expense.setCategory(category); return expense; } diff --git a/src/main/java/de/zendric/app/xpensely_server/model/ExpenseInput.java b/src/main/java/de/zendric/app/xpensely_server/model/ExpenseInput.java index ac2e7a6..3fb17ad 100644 --- a/src/main/java/de/zendric/app/xpensely_server/model/ExpenseInput.java +++ b/src/main/java/de/zendric/app/xpensely_server/model/ExpenseInput.java @@ -29,6 +29,7 @@ public class ExpenseInput { private Double otherPersonAmount; private LocalDate date; + private String category; private ExpenseList expenseList; @@ -46,6 +47,7 @@ public class ExpenseInput { expense.setId(id); expense.setOwner(appUser); expense.setTitle(title); + expense.setCategory(category); return expense; } diff --git a/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategories.java b/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategories.java index 44ecb3a..296b587 100644 --- a/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategories.java +++ b/src/main/java/de/zendric/app/xpensely_server/model/XpenselyStandardCategories.java @@ -23,7 +23,7 @@ public class XpenselyStandardCategories { @Id private Long id; - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) @JoinColumn(name = "global_categories_id") private List categories; } \ No newline at end of file diff --git a/src/main/java/de/zendric/app/xpensely_server/preparation/DataInitializer.java b/src/main/java/de/zendric/app/xpensely_server/preparation/DataInitializer.java index a065c9f..5cc944d 100644 --- a/src/main/java/de/zendric/app/xpensely_server/preparation/DataInitializer.java +++ b/src/main/java/de/zendric/app/xpensely_server/preparation/DataInitializer.java @@ -1,6 +1,7 @@ package de.zendric.app.xpensely_server.preparation; import java.util.List; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; @@ -18,18 +19,22 @@ public class DataInitializer implements CommandLineRunner { @Override public void run(String... args) throws Exception { - if (!globalRepo.findById(1L).isPresent()) { - XpenselyStandardCategories global = new XpenselyStandardCategories(); - global.setId(1L); + Optional optional = globalRepo.findById(1L); - List categories = List.of( - new XpenselyStandardCategory(null, "Food", "#FF5733"), - new XpenselyStandardCategory(null, "Transportation", "#33C3FF"), - new XpenselyStandardCategory(null, "Entertainment", "#33FF57"), - new XpenselyStandardCategory(null, "Shopping", "#FF33A8"), - new XpenselyStandardCategory(null, "Bills", "#33FFEA")); - global.setCategories(categories); - globalRepo.save(global); - } + XpenselyStandardCategories global = optional.orElseGet(() -> { + XpenselyStandardCategories g = new XpenselyStandardCategories(); + g.setId(1L); + return g; + }); + + List categories = List.of( + new XpenselyStandardCategory(null, "Food", "#FF5733"), + new XpenselyStandardCategory(null, "Transportation", "#33C3FF"), + new XpenselyStandardCategory(null, "Entertainment", "#33FF57"), + new XpenselyStandardCategory(null, "Shopping", "#FF33A8"), + new XpenselyStandardCategory(null, "Household", "#FFC733"), + new XpenselyStandardCategory(null, "Other", "#9D33FF")); + global.setCategories(categories); + globalRepo.save(global); } } diff --git a/src/main/java/de/zendric/app/xpensely_server/services/CategoryService.java b/src/main/java/de/zendric/app/xpensely_server/services/CategoryService.java new file mode 100644 index 0000000..76b34f0 --- /dev/null +++ b/src/main/java/de/zendric/app/xpensely_server/services/CategoryService.java @@ -0,0 +1,24 @@ +package de.zendric.app.xpensely_server.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import de.zendric.app.xpensely_server.model.XpenselyStandardCategories; +import de.zendric.app.xpensely_server.repo.XpenselyStandardCategoriesRepository; + +@Service +public class CategoryService { + + private final XpenselyStandardCategoriesRepository standardCategoriesRepo; + + @Autowired + public CategoryService(XpenselyStandardCategoriesRepository standardCategoriesRepo) { + this.standardCategoriesRepo = standardCategoriesRepo; + } + + public XpenselyStandardCategories getDefaultCategories() { + return standardCategoriesRepo.findById(1L) + .orElseThrow(() -> new IllegalStateException("Standard categories not found")); + } + +} \ No newline at end of file diff --git a/src/main/java/de/zendric/app/xpensely_server/services/ExpenseListService.java b/src/main/java/de/zendric/app/xpensely_server/services/ExpenseListService.java index 87ac564..0ee1be6 100644 --- a/src/main/java/de/zendric/app/xpensely_server/services/ExpenseListService.java +++ b/src/main/java/de/zendric/app/xpensely_server/services/ExpenseListService.java @@ -183,6 +183,7 @@ public class ExpenseListService { existingExpense.setOtherPersonAmount(updatedExpense.getOtherPersonAmount()); existingExpense.setDate(updatedExpense.getDate()); existingExpense.setOwner(updatedExpense.getOwner()); + existingExpense.setCategory(updatedExpense.getCategory()); return expenseRepository.save(existingExpense); } -- 2.49.1