+Data Structure Changes

+Api Functionality
This commit is contained in:
2025-01-05 01:30:28 +01:00
parent b3d5b5ad11
commit f26f365b3c
9 changed files with 114 additions and 5 deletions

View File

@@ -39,6 +39,10 @@
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId> <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency> </dependency>

View File

@@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
@@ -19,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
import de.zendric.app.xpensely_server.model.AppUser; import de.zendric.app.xpensely_server.model.AppUser;
import de.zendric.app.xpensely_server.model.Expense; import de.zendric.app.xpensely_server.model.Expense;
import de.zendric.app.xpensely_server.model.ExpenseChangeRequest;
import de.zendric.app.xpensely_server.model.ExpenseInput; import de.zendric.app.xpensely_server.model.ExpenseInput;
import de.zendric.app.xpensely_server.model.ExpenseList; import de.zendric.app.xpensely_server.model.ExpenseList;
import de.zendric.app.xpensely_server.model.InviteRequest; import de.zendric.app.xpensely_server.model.InviteRequest;
@@ -142,6 +144,26 @@ class ExpenseListController {
} }
} }
@PutMapping("/{id}/update")
public ResponseEntity<Expense> updateExpenseInList(
@PathVariable("id") Long expenseListId,
@RequestBody ExpenseChangeRequest expenseChangeRequest) {
try {
AppUser expenseOwner = userService.getUserByName(expenseChangeRequest.getOwnerName());
Optional<ExpenseList> expenseList = expenseListService.findById(expenseListId);
if (expenseList.isPresent()) {
Expense expense = expenseChangeRequest.convertToExpense(expenseOwner.getId(), expenseList.get());
Expense addedExpense = expenseListService.updateExpense(expenseListId, expense);
return new ResponseEntity<>(addedExpense, HttpStatus.CREATED);
}
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
}
@DeleteMapping("/{id}/delete") @DeleteMapping("/{id}/delete")
public ResponseEntity<Expense> deleteExpenseFromList( public ResponseEntity<Expense> deleteExpenseFromList(
@PathVariable("id") Long expenseListId, @PathVariable("id") Long expenseListId,

View File

@@ -32,7 +32,8 @@ public class Expense {
private AppUser owner; private AppUser owner;
private Double amount; private Double amount;
private Double deviation; private Double personalUseAmount;
private Double otherPersonAmount;
private LocalDate date; private LocalDate date;

View File

@@ -0,0 +1,39 @@
package de.zendric.app.xpensely_server.model;
import java.time.LocalDate;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExpenseChangeRequest {
private Long id;
private String title;
private String ownerName;
private Double amount;
private Double personalUseAmount;
private Double otherPersonAmount;
private LocalDate date;
public Expense convertToExpense(Long userId, ExpenseList expenseList) {
AppUser appUser = new AppUser();
appUser.setId(userId);
appUser.setUsername(ownerName);
Expense expense = new Expense();
expense.setAmount(amount);
expense.setDate(date);
expense.setPersonalUseAmount(personalUseAmount);
expense.setOtherPersonAmount(otherPersonAmount);
expense.setExpenseList(expenseList);
expense.setId(id);
expense.setOwner(appUser);
expense.setTitle(title);
return expense;
}
}

View File

@@ -25,7 +25,8 @@ public class ExpenseInput {
private String owner; private String owner;
private Double amount; private Double amount;
private Double deviation; private Double personalUseAmount;
private Double otherPersonAmount;
private LocalDate date; private LocalDate date;
@@ -39,7 +40,7 @@ public class ExpenseInput {
Expense expense = new Expense(); Expense expense = new Expense();
expense.setAmount(amount); expense.setAmount(amount);
expense.setDate(date); expense.setDate(date);
expense.setDeviation(deviation); expense.setPersonalUseAmount(personalUseAmount);
expense.setExpenseList(expenseList); expense.setExpenseList(expenseList);
expense.setId(id); expense.setId(id);
expense.setOwner(appUser); expense.setOwner(appUser);

View File

@@ -42,6 +42,7 @@ public class ExpenseList {
@OneToMany(mappedBy = "expenseList", cascade = CascadeType.ALL, orphanRemoval = true) @OneToMany(mappedBy = "expenseList", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference @JsonManagedReference
@jakarta.persistence.OrderBy("date ASC, id ASC")
private List<Expense> expenses; private List<Expense> expenses;
public void addExpense(Expense expense) { public void addExpense(Expense expense) {

View File

@@ -1,5 +1,7 @@
package de.zendric.app.xpensely_server.repo; package de.zendric.app.xpensely_server.repo;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@@ -7,4 +9,5 @@ import de.zendric.app.xpensely_server.model.Expense;
@Repository @Repository
public interface ExpenseRepository extends JpaRepository<Expense, Long> { public interface ExpenseRepository extends JpaRepository<Expense, Long> {
List<Expense> findAllByOrderByDateAsc();
} }

View File

@@ -10,10 +10,27 @@ import org.springframework.security.web.SecurityFilterChain;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
public class SecurityConfig { public class SecurityConfig {
// @Bean
// public SecurityFilterChain securityFilterChain(HttpSecurity http) throws
// Exception {
// http.authorizeHttpRequests(auth -> auth
// .anyRequest().permitAll()).csrf().disable();
// ;
// return http.build();
// }
@Bean @Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth http
.anyRequest().authenticated()).oauth2Login(Customizer.withDefaults()); .authorizeHttpRequests(auth -> auth
.anyRequest().authenticated() // Require authentication for all requests
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults()) // Enable JWT validation
)
.oauth2Login(Customizer.withDefaults()) // Optional if you want OAuth2 login
.csrf().disable(); // Disable CSRF for simplicity in APIs (consider enabling it for forms)
return http.build(); return http.build();
} }

View File

@@ -160,4 +160,25 @@ public class ExpenseListService {
public ExpenseList findByInviteCode(String inviteCode) { public ExpenseList findByInviteCode(String inviteCode) {
return repository.findByInviteCode(inviteCode); return repository.findByInviteCode(inviteCode);
} }
public Expense updateExpense(Long expenseListId, Expense updatedExpense) {
ExpenseList expenseList = repository.findById(expenseListId)
.orElseThrow(() -> new IllegalArgumentException("ExpenseList not found"));
if (!expenseList.getExpenses().stream()
.anyMatch(expense -> expense.getId().equals(updatedExpense.getId()))) {
throw new IllegalArgumentException("Expense does not belong to the specified ExpenseList");
}
Expense existingExpense = expenseRepository.findById(updatedExpense.getId())
.orElseThrow(() -> new IllegalArgumentException("Expense not found"));
existingExpense.setTitle(updatedExpense.getTitle());
existingExpense.setAmount(updatedExpense.getAmount());
existingExpense.setPersonalUseAmount(updatedExpense.getPersonalUseAmount());
existingExpense.setOtherPersonAmount(updatedExpense.getOtherPersonAmount());
existingExpense.setDate(updatedExpense.getDate());
existingExpense.setOwner(updatedExpense.getOwner());
return expenseRepository.save(existingExpense);
}
} }