6 Commits

Author SHA1 Message Date
548342798e Use Lombok plugin
All checks were successful
Backend Build and Test / build (push) Successful in 39s
2026-03-02 18:12:10 +01:00
e2ac1bfd3d Split API controller 2026-03-02 18:10:01 +01:00
03aa050f6a Actually add lombok support 2026-03-02 18:09:38 +01:00
6beba890e8 Ignore more eclipse stuff 2026-03-02 18:09:26 +01:00
94380db02d Use lombok @getter @setter 2026-03-02 18:09:08 +01:00
b3410e3a5f Add Eclipse files to gitignore 2026-03-02 18:08:47 +01:00
12 changed files with 293 additions and 372 deletions

View File

@@ -1,2 +1,8 @@
.gradle/ .gradle/
build/ build/
# Eclispe Directories
/.classpath
/.project
/bin
/.settings

View File

@@ -2,6 +2,7 @@ plugins {
java java
id("org.springframework.boot") version "4.0.3" id("org.springframework.boot") version "4.0.3"
id("io.spring.dependency-management") version "1.1.7" id("io.spring.dependency-management") version "1.1.7"
id("io.freefair.lombok") version "9.2.0"
} }
group = "be.seeseepuff" group = "be.seeseepuff"

View File

@@ -1,7 +1,8 @@
package be.seeseepuff.allowanceplanner.controller; package be.seeseepuff.allowanceplanner.controller;
import be.seeseepuff.allowanceplanner.dto.*; import be.seeseepuff.allowanceplanner.dto.*;
import be.seeseepuff.allowanceplanner.service.*; import be.seeseepuff.allowanceplanner.service.AllowanceService;
import be.seeseepuff.allowanceplanner.service.UserService;
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.*;
@@ -12,86 +13,15 @@ import java.util.Optional;
@RestController @RestController
@RequestMapping("/api") @RequestMapping("/api")
@CrossOrigin(origins = "*") @CrossOrigin(origins = "*")
public class ApiController { public class AllowanceController {
private final UserService userService; private final UserService userService;
private final AllowanceService allowanceService; private final AllowanceService allowanceService;
private final TaskService taskService;
private final TransferService transferService;
private final MigrationService migrationService;
public ApiController(UserService userService, public AllowanceController(UserService userService, AllowanceService allowanceService) {
AllowanceService allowanceService,
TaskService taskService,
TransferService transferService,
MigrationService migrationService) {
this.userService = userService; this.userService = userService;
this.allowanceService = allowanceService; this.allowanceService = allowanceService;
this.taskService = taskService;
this.transferService = transferService;
this.migrationService = migrationService;
} }
// ---- Users ----
@GetMapping("/users")
public List<UserDto> getUsers() {
return userService.getUsers();
}
@GetMapping("/user/{userId}")
public ResponseEntity<?> getUser(@PathVariable String userId) {
int id;
try {
id = Integer.parseInt(userId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid user ID"));
}
Optional<UserWithAllowanceDto> user = userService.getUser(id);
if (user.isEmpty()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("User not found"));
}
return ResponseEntity.ok(user.get());
}
// ---- History ----
@PostMapping("/user/{userId}/history")
public ResponseEntity<?> postHistory(@PathVariable String userId, @RequestBody PostHistoryRequest request) {
int id;
try {
id = Integer.parseInt(userId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid user ID"));
}
if (request.description() == null || request.description().isEmpty()) {
return ResponseEntity.badRequest().body(new ErrorResponse("Description cannot be empty"));
}
if (!userService.userExists(id)) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("User not found"));
}
allowanceService.addHistory(id, request);
return ResponseEntity.ok(new MessageResponse("History updated successfully"));
}
@GetMapping("/user/{userId}/history")
public ResponseEntity<?> getHistory(@PathVariable String userId) {
int id;
try {
id = Integer.parseInt(userId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid user ID"));
}
List<HistoryDto> history = allowanceService.getHistory(id);
return ResponseEntity.ok(history);
}
// ---- Allowances ----
@GetMapping("/user/{userId}/allowance") @GetMapping("/user/{userId}/allowance")
public ResponseEntity<?> getUserAllowance(@PathVariable String userId) { public ResponseEntity<?> getUserAllowance(@PathVariable String userId) {
int id; int id;
@@ -288,118 +218,4 @@ public class ApiController {
} }
return ResponseEntity.ok(new MessageResponse("Allowance completed successfully")); return ResponseEntity.ok(new MessageResponse("Allowance completed successfully"));
} }
// ---- Tasks ----
@PostMapping("/tasks")
public ResponseEntity<?> createTask(@RequestBody CreateTaskRequest request) {
if (request.name() == null || request.name().isEmpty()) {
return ResponseEntity.badRequest().body(new ErrorResponse("Task name cannot be empty"));
}
if (request.schedule() != null) {
return ResponseEntity.badRequest().body(new ErrorResponse("Schedules are not yet supported"));
}
if (request.assigned() != null) {
if (!userService.userExists(request.assigned())) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("User not found"));
}
}
int taskId = taskService.createTask(request);
return ResponseEntity.status(HttpStatus.CREATED).body(new IdResponse(taskId));
}
@GetMapping("/tasks")
public List<TaskDto> getTasks() {
return taskService.getTasks();
}
@GetMapping("/task/{taskId}")
public ResponseEntity<?> getTask(@PathVariable String taskId) {
int id;
try {
id = Integer.parseInt(taskId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid task ID"));
}
Optional<TaskDto> task = taskService.getTask(id);
if (task.isEmpty()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Task not found"));
}
return ResponseEntity.ok(task.get());
}
@PutMapping("/task/{taskId}")
public ResponseEntity<?> putTask(@PathVariable String taskId, @RequestBody CreateTaskRequest request) {
int id;
try {
id = Integer.parseInt(taskId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid task ID"));
}
Optional<TaskDto> existing = taskService.getTask(id);
if (existing.isEmpty()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Task not found"));
}
taskService.updateTask(id, request);
return ResponseEntity.ok(new MessageResponse("Task updated successfully"));
}
@DeleteMapping("/task/{taskId}")
public ResponseEntity<?> deleteTask(@PathVariable String taskId) {
int id;
try {
id = Integer.parseInt(taskId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid task ID"));
}
if (!taskService.hasTask(id)) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Task not found"));
}
taskService.deleteTask(id);
return ResponseEntity.ok(new MessageResponse("Task deleted successfully"));
}
@PostMapping("/task/{taskId}/complete")
public ResponseEntity<?> completeTask(@PathVariable String taskId) {
int id;
try {
id = Integer.parseInt(taskId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid task ID"));
}
boolean completed = taskService.completeTask(id);
if (!completed) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Task not found"));
}
return ResponseEntity.ok(new MessageResponse("Task completed successfully"));
}
// ---- Transfer ----
@PostMapping("/transfer")
public ResponseEntity<?> transfer(@RequestBody TransferRequest request) {
TransferService.TransferResult result = transferService.transfer(request);
return switch (result.status()) {
case SUCCESS -> ResponseEntity.ok(new MessageResponse(result.message()));
case BAD_REQUEST -> ResponseEntity.badRequest().body(new ErrorResponse(result.message()));
case NOT_FOUND -> ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(result.message()));
};
}
// ---- Migration ----
@PostMapping("/import")
public ResponseEntity<?> importData(@RequestBody MigrationDto data) {
migrationService.importData(data);
return ResponseEntity.ok(new MessageResponse("Import successful"));
}
} }

View File

@@ -0,0 +1,57 @@
package be.seeseepuff.allowanceplanner.controller;
import be.seeseepuff.allowanceplanner.dto.*;
import be.seeseepuff.allowanceplanner.service.AllowanceService;
import be.seeseepuff.allowanceplanner.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
public class HistoryController {
private final UserService userService;
private final AllowanceService allowanceService;
public HistoryController(UserService userService, AllowanceService allowanceService) {
this.userService = userService;
this.allowanceService = allowanceService;
}
@PostMapping("/user/{userId}/history")
public ResponseEntity<?> postHistory(@PathVariable String userId, @RequestBody PostHistoryRequest request) {
int id;
try {
id = Integer.parseInt(userId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid user ID"));
}
if (request.description() == null || request.description().isEmpty()) {
return ResponseEntity.badRequest().body(new ErrorResponse("Description cannot be empty"));
}
if (!userService.userExists(id)) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("User not found"));
}
allowanceService.addHistory(id, request);
return ResponseEntity.ok(new MessageResponse("History updated successfully"));
}
@GetMapping("/user/{userId}/history")
public ResponseEntity<?> getHistory(@PathVariable String userId) {
int id;
try {
id = Integer.parseInt(userId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid user ID"));
}
List<HistoryDto> history = allowanceService.getHistory(id);
return ResponseEntity.ok(history);
}
}

View File

@@ -0,0 +1,23 @@
package be.seeseepuff.allowanceplanner.controller;
import be.seeseepuff.allowanceplanner.dto.*;
import be.seeseepuff.allowanceplanner.service.MigrationService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
public class MigrationController {
private final MigrationService migrationService;
public MigrationController(MigrationService migrationService) {
this.migrationService = migrationService;
}
@PostMapping("/import")
public ResponseEntity<?> importData(@RequestBody MigrationDto data) {
migrationService.importData(data);
return ResponseEntity.ok(new MessageResponse("Import successful"));
}
}

View File

@@ -0,0 +1,116 @@
package be.seeseepuff.allowanceplanner.controller;
import be.seeseepuff.allowanceplanner.dto.*;
import be.seeseepuff.allowanceplanner.service.TaskService;
import be.seeseepuff.allowanceplanner.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
public class TaskController {
private final UserService userService;
private final TaskService taskService;
public TaskController(UserService userService, TaskService taskService) {
this.userService = userService;
this.taskService = taskService;
}
@PostMapping("/tasks")
public ResponseEntity<?> createTask(@RequestBody CreateTaskRequest request) {
if (request.name() == null || request.name().isEmpty()) {
return ResponseEntity.badRequest().body(new ErrorResponse("Task name cannot be empty"));
}
if (request.schedule() != null) {
return ResponseEntity.badRequest().body(new ErrorResponse("Schedules are not yet supported"));
}
if (request.assigned() != null) {
if (!userService.userExists(request.assigned())) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("User not found"));
}
}
int taskId = taskService.createTask(request);
return ResponseEntity.status(HttpStatus.CREATED).body(new IdResponse(taskId));
}
@GetMapping("/tasks")
public List<TaskDto> getTasks() {
return taskService.getTasks();
}
@GetMapping("/task/{taskId}")
public ResponseEntity<?> getTask(@PathVariable String taskId) {
int id;
try {
id = Integer.parseInt(taskId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid task ID"));
}
Optional<TaskDto> task = taskService.getTask(id);
if (task.isEmpty()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Task not found"));
}
return ResponseEntity.ok(task.get());
}
@PutMapping("/task/{taskId}")
public ResponseEntity<?> putTask(@PathVariable String taskId, @RequestBody CreateTaskRequest request) {
int id;
try {
id = Integer.parseInt(taskId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid task ID"));
}
Optional<TaskDto> existing = taskService.getTask(id);
if (existing.isEmpty()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Task not found"));
}
taskService.updateTask(id, request);
return ResponseEntity.ok(new MessageResponse("Task updated successfully"));
}
@DeleteMapping("/task/{taskId}")
public ResponseEntity<?> deleteTask(@PathVariable String taskId) {
int id;
try {
id = Integer.parseInt(taskId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid task ID"));
}
if (!taskService.hasTask(id)) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Task not found"));
}
taskService.deleteTask(id);
return ResponseEntity.ok(new MessageResponse("Task deleted successfully"));
}
@PostMapping("/task/{taskId}/complete")
public ResponseEntity<?> completeTask(@PathVariable String taskId) {
int id;
try {
id = Integer.parseInt(taskId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid task ID"));
}
boolean completed = taskService.completeTask(id);
if (!completed) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Task not found"));
}
return ResponseEntity.ok(new MessageResponse("Task completed successfully"));
}
}

View File

@@ -0,0 +1,28 @@
package be.seeseepuff.allowanceplanner.controller;
import be.seeseepuff.allowanceplanner.dto.*;
import be.seeseepuff.allowanceplanner.service.TransferService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
public class TransferController {
private final TransferService transferService;
public TransferController(TransferService transferService) {
this.transferService = transferService;
}
@PostMapping("/transfer")
public ResponseEntity<?> transfer(@RequestBody TransferRequest request) {
TransferService.TransferResult result = transferService.transfer(request);
return switch (result.status()) {
case SUCCESS -> ResponseEntity.ok(new MessageResponse(result.message()));
case BAD_REQUEST -> ResponseEntity.badRequest().body(new ErrorResponse(result.message()));
case NOT_FOUND -> ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(result.message()));
};
}
}

View File

@@ -0,0 +1,42 @@
package be.seeseepuff.allowanceplanner.controller;
import be.seeseepuff.allowanceplanner.dto.*;
import be.seeseepuff.allowanceplanner.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/users")
public List<UserDto> getUsers() {
return userService.getUsers();
}
@GetMapping("/user/{userId}")
public ResponseEntity<?> getUser(@PathVariable String userId) {
int id;
try {
id = Integer.parseInt(userId);
} catch (NumberFormatException e) {
return ResponseEntity.badRequest().body(new ErrorResponse("Invalid user ID"));
}
Optional<UserWithAllowanceDto> user = userService.getUser(id);
if (user.isEmpty()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("User not found"));
}
return ResponseEntity.ok(user.get());
}
}

View File

@@ -1,9 +1,13 @@
package be.seeseepuff.allowanceplanner.entity; package be.seeseepuff.allowanceplanner.entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity @Entity
@Table(name = "allowances") @Table(name = "allowances")
@Getter
@Setter
public class Allowance { public class Allowance {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -25,60 +29,4 @@ public class Allowance {
private double weight; private double weight;
private Integer colour; private Integer colour;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getTarget() {
return target;
}
public void setTarget(long target) {
this.target = target;
}
public long getBalance() {
return balance;
}
public void setBalance(long balance) {
this.balance = balance;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public Integer getColour() {
return colour;
}
public void setColour(Integer colour) {
this.colour = colour;
}
} }

View File

@@ -1,9 +1,13 @@
package be.seeseepuff.allowanceplanner.entity; package be.seeseepuff.allowanceplanner.entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity @Entity
@Table(name = "history") @Table(name = "history")
@Getter
@Setter
public class History { public class History {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -19,44 +23,4 @@ public class History {
private long amount; private long amount;
private String description; private String description;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public long getAmount() {
return amount;
}
public void setAmount(long amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
} }

View File

@@ -1,9 +1,13 @@
package be.seeseepuff.allowanceplanner.entity; package be.seeseepuff.allowanceplanner.entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity @Entity
@Table(name = "tasks") @Table(name = "tasks")
@Getter
@Setter
public class Task { public class Task {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -23,60 +27,4 @@ public class Task {
@Column(name = "next_run") @Column(name = "next_run")
private Long nextRun; private Long nextRun;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getReward() {
return reward;
}
public void setReward(long reward) {
this.reward = reward;
}
public Integer getAssigned() {
return assigned;
}
public void setAssigned(Integer assigned) {
this.assigned = assigned;
}
public String getSchedule() {
return schedule;
}
public void setSchedule(String schedule) {
this.schedule = schedule;
}
public Long getCompleted() {
return completed;
}
public void setCompleted(Long completed) {
this.completed = completed;
}
public Long getNextRun() {
return nextRun;
}
public void setNextRun(Long nextRun) {
this.nextRun = nextRun;
}
} }

View File

@@ -1,9 +1,13 @@
package be.seeseepuff.allowanceplanner.entity; package be.seeseepuff.allowanceplanner.entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity @Entity
@Table(name = "users") @Table(name = "users")
@Getter
@Setter
public class User { public class User {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -17,36 +21,4 @@ public class User {
@Column(nullable = false) @Column(nullable = false)
private long balance = 0; private long balance = 0;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public long getBalance() {
return balance;
}
public void setBalance(long balance) {
this.balance = balance;
}
} }