From c5bb58888afa8db748a555d7d4021e0d1952f976 Mon Sep 17 00:00:00 2001 From: zaine Date: Thu, 19 Mar 2026 17:30:04 +0000 Subject: [PATCH] updating --- .../controller/CompetenciesController.java | 4 +- .../zaine/app/controller/WirdController.java | 78 +++++++++++++++++++ .../java/org/zaine/app/dto/WirdEntryDTO.java | 20 +++++ .../java/org/zaine/app/model/WirdEntry.java | 43 ++++++++++ .../app/repositories/WirdEntryRepository.java | 35 +++++++++ .../zaine/app/service/CommentsService.java | 4 + .../app/service/CompetenciesService.java | 4 + .../org/zaine/app/service/WirdService.java | 42 ++++++++++ .../java/org/zaine/app/ApplicationTest.java | 3 - .../app/service/CommentsServiceTest.java | 9 +++ .../app/service/CompetenciesServiceTest.java | 12 +++ 11 files changed, 248 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/zaine/app/controller/WirdController.java create mode 100644 src/main/java/org/zaine/app/dto/WirdEntryDTO.java create mode 100644 src/main/java/org/zaine/app/model/WirdEntry.java create mode 100644 src/main/java/org/zaine/app/repositories/WirdEntryRepository.java create mode 100644 src/main/java/org/zaine/app/service/WirdService.java diff --git a/src/main/java/org/zaine/app/controller/CompetenciesController.java b/src/main/java/org/zaine/app/controller/CompetenciesController.java index 180b72b..96cf346 100755 --- a/src/main/java/org/zaine/app/controller/CompetenciesController.java +++ b/src/main/java/org/zaine/app/controller/CompetenciesController.java @@ -1,7 +1,5 @@ package org.zaine.app.controller; -import java.lang.System.Logger; import java.util.List; -import java.util.Map; import org.zaine.app.dto.CompetenciesDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -17,7 +15,7 @@ import org.zaine.app.service.CompetenciesService; @RestController @RequestMapping("/api/competencies") public class CompetenciesController { - private static final Logger logger = System.getLogger(CompetenciesController.class.getName()); + //private static final Logger logger = System.getLogger(CompetenciesController.class.getName()); @Autowired private CompetenciesService competenciesService; diff --git a/src/main/java/org/zaine/app/controller/WirdController.java b/src/main/java/org/zaine/app/controller/WirdController.java new file mode 100644 index 0000000..68a11e4 --- /dev/null +++ b/src/main/java/org/zaine/app/controller/WirdController.java @@ -0,0 +1,78 @@ +package org.zaine.app.controller; + +import java.lang.System.Logger; +import java.time.LocalDate; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.zaine.app.dto.WirdEntryDTO; +import org.zaine.app.model.WirdEntry; +import org.zaine.app.service.WirdService; + +@RestController +@RequestMapping("/api/wird") +public class WirdController { + + private static final Logger logger = System.getLogger(WirdController.class.getName()); + + @Autowired + private WirdService wirdService; + + /** + * GET /api/wird/entries + * Returns all entries, newest first. Used by history table and today cards. + */ + @GetMapping("/entries") + public List getAllEntries() { + logger.log(Logger.Level.INFO, "Fetching all wird entries"); + return wirdService.getAllEntries(); + } + + /** + * GET /api/wird/entries/today + * Convenience endpoint for today's entries only. + */ + @GetMapping("/entries/today") + public List getTodayEntries() { + return wirdService.getTodayEntries(); + } + + /** + * GET /api/wird/entries/range?from=2025-01-01&to=2025-01-31 + * Used by trend chart to fetch a date window. + */ + @GetMapping("/entries/range") + public List getEntriesInRange( + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to) { + return wirdService.getEntriesInRange(from, to); + } + + /** + * GET /api/wird/entries/range?from=...&to=...&type=durood + * Filtered by wird type — useful if you want to extend the chart later. + */ + @GetMapping("/entries/type/{type}") + public List getEntriesByType( + @PathVariable String type, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from, + @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to) { + return wirdService.getEntriesByTypeInRange(type, from, to); + } + + /** + * POST /api/wird/entries + * Body: { wirdType, date, value, notes } + * Creates a new log entry. + */ + @PostMapping("/entries") + public ResponseEntity createEntry(@RequestBody WirdEntryDTO dto) { + logger.log(Logger.Level.INFO, "Creating wird entry: {0} on {1}", dto.getWirdType(), dto.getDate()); + WirdEntry saved = wirdService.createEntry(dto); + return ResponseEntity.ok(saved); + } +} + diff --git a/src/main/java/org/zaine/app/dto/WirdEntryDTO.java b/src/main/java/org/zaine/app/dto/WirdEntryDTO.java new file mode 100644 index 0000000..5ad61b6 --- /dev/null +++ b/src/main/java/org/zaine/app/dto/WirdEntryDTO.java @@ -0,0 +1,20 @@ +package org.zaine.app.dto; + +import java.math.BigDecimal; +import java.time.LocalDate; + +public class WirdEntryDTO { + private String wirdType; + private LocalDate date; + private BigDecimal value; + private String notes; + + public String getWirdType() { return wirdType; } + public void setWirdType(String t) { this.wirdType = t; } + public LocalDate getDate() { return date; } + public void setDate(LocalDate d) { this.date = d; } + public BigDecimal getValue() { return value; } + public void setValue(BigDecimal v) { this.value = v; } + public String getNotes() { return notes; } + public void setNotes(String n) { this.notes = n; } +} diff --git a/src/main/java/org/zaine/app/model/WirdEntry.java b/src/main/java/org/zaine/app/model/WirdEntry.java new file mode 100644 index 0000000..68d9ce9 --- /dev/null +++ b/src/main/java/org/zaine/app/model/WirdEntry.java @@ -0,0 +1,43 @@ +package org.zaine.app.model; + +import jakarta.persistence.*; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.OffsetDateTime; + +@Entity +@Table(name = "wird_entries") +public class WirdEntry { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "wird_type", nullable = false) + private String wirdType; + + @Column(nullable = false) + private LocalDate date; + + @Column(nullable = false, precision = 10, scale = 2) + private BigDecimal value; + + @Column + private String notes; + + @Column(name = "created_at", insertable = false, updatable = false) + private OffsetDateTime createdAt; + + // ── Getters & Setters ─────────────────────────────────── // + + public Long getId() { return id; } + public String getWirdType() { return wirdType; } + public void setWirdType(String t) { this.wirdType = t; } + public LocalDate getDate() { return date; } + public void setDate(LocalDate d) { this.date = d; } + public BigDecimal getValue() { return value; } + public void setValue(BigDecimal v) { this.value = v; } + public String getNotes() { return notes; } + public void setNotes(String n) { this.notes = n; } + public OffsetDateTime getCreatedAt() { return createdAt; } +} diff --git a/src/main/java/org/zaine/app/repositories/WirdEntryRepository.java b/src/main/java/org/zaine/app/repositories/WirdEntryRepository.java new file mode 100644 index 0000000..795b602 --- /dev/null +++ b/src/main/java/org/zaine/app/repositories/WirdEntryRepository.java @@ -0,0 +1,35 @@ +package org.zaine.app.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import org.zaine.app.model.WirdEntry; + +import java.time.LocalDate; +import java.util.List; + +@Repository +public interface WirdEntryRepository extends JpaRepository { + + // All entries ordered newest first (for history table) + List findAllByOrderByDateDescCreatedAtDesc(); + + // Entries for a specific date (today's cards) + List findByDateOrderByCreatedAtDesc(LocalDate date); + + // Entries within a date range for a specific wird type (trend chart) + @Query("SELECT e FROM WirdEntry e WHERE e.wirdType = :type AND e.date BETWEEN :from AND :to ORDER BY e.date ASC") + List findByTypeAndDateRange( + @Param("type") String type, + @Param("from") LocalDate from, + @Param("to") LocalDate to + ); + + // All entries for a date range (bulk fetch for chart, avoids N+1) + @Query("SELECT e FROM WirdEntry e WHERE e.date BETWEEN :from AND :to ORDER BY e.date ASC, e.wirdType ASC") + List findByDateRange( + @Param("from") LocalDate from, + @Param("to") LocalDate to + ); +} diff --git a/src/main/java/org/zaine/app/service/CommentsService.java b/src/main/java/org/zaine/app/service/CommentsService.java index 9b7c022..021c09c 100755 --- a/src/main/java/org/zaine/app/service/CommentsService.java +++ b/src/main/java/org/zaine/app/service/CommentsService.java @@ -32,6 +32,10 @@ public class CommentsService { public Comments getCommentById(Integer id) { logger.log(System.Logger.Level.INFO, "Entering getCommentById with id: " + id); + if (id == null) { + logger.log(System.Logger.Level.WARNING, "Comment id is null. Operation aborted."); + return null; + } return commentsRepository.findById(id).get(); } diff --git a/src/main/java/org/zaine/app/service/CompetenciesService.java b/src/main/java/org/zaine/app/service/CompetenciesService.java index f35e872..8984ec8 100755 --- a/src/main/java/org/zaine/app/service/CompetenciesService.java +++ b/src/main/java/org/zaine/app/service/CompetenciesService.java @@ -26,6 +26,10 @@ public class CompetenciesService { public Competencies getCompetencyById(Integer id) { logger.log(System.Logger.Level.INFO, "Entering getCompetencyById with id: " + id); + if (id == null) { + logger.log(System.Logger.Level.WARNING, "Competency id is null. Operation aborted."); + return null; + } return competenciesRepository.findById(id).get(); } diff --git a/src/main/java/org/zaine/app/service/WirdService.java b/src/main/java/org/zaine/app/service/WirdService.java new file mode 100644 index 0000000..077e02f --- /dev/null +++ b/src/main/java/org/zaine/app/service/WirdService.java @@ -0,0 +1,42 @@ +package org.zaine.app.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.zaine.app.dto.WirdEntryDTO; +import org.zaine.app.model.WirdEntry; +import org.zaine.app.repositories.WirdEntryRepository; + +import java.time.LocalDate; +import java.util.List; + +@Service +public class WirdService { + + @Autowired + private WirdEntryRepository repo; + + public List getAllEntries() { + return repo.findAllByOrderByDateDescCreatedAtDesc(); + } + + public List getTodayEntries() { + return repo.findByDateOrderByCreatedAtDesc(LocalDate.now()); + } + + public List getEntriesInRange(LocalDate from, LocalDate to) { + return repo.findByDateRange(from, to); + } + + public List getEntriesByTypeInRange(String type, LocalDate from, LocalDate to) { + return repo.findByTypeAndDateRange(type, from, to); + } + + public WirdEntry createEntry(WirdEntryDTO dto) { + WirdEntry entry = new WirdEntry(); + entry.setWirdType(dto.getWirdType()); + entry.setDate(dto.getDate() != null ? dto.getDate() : LocalDate.now()); + entry.setValue(dto.getValue()); + entry.setNotes(dto.getNotes()); + return repo.save(entry); + } +} diff --git a/src/test/java/org/zaine/app/ApplicationTest.java b/src/test/java/org/zaine/app/ApplicationTest.java index b45797e..ce5deae 100755 --- a/src/test/java/org/zaine/app/ApplicationTest.java +++ b/src/test/java/org/zaine/app/ApplicationTest.java @@ -1,8 +1,5 @@ package org.zaine.app; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.Test; public class ApplicationTest { diff --git a/src/test/java/org/zaine/app/service/CommentsServiceTest.java b/src/test/java/org/zaine/app/service/CommentsServiceTest.java index 25490c7..ebecfe4 100755 --- a/src/test/java/org/zaine/app/service/CommentsServiceTest.java +++ b/src/test/java/org/zaine/app/service/CommentsServiceTest.java @@ -4,6 +4,8 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import java.util.Arrays; import java.util.List; +import java.lang.System.Logger; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -14,6 +16,9 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) public class CommentsServiceTest { + + private static final Logger logger = System.getLogger(CompetenciesService.class.getName()); + @InjectMocks private CommentsService commentsService; @@ -58,6 +63,10 @@ public class CommentsServiceTest { public void testGetCommentByIdReturnsComment() { Comments comment = new Comments(); Integer id = comment.getId(); + if (id == null) { + logger.log(System.Logger.Level.WARNING, "Comment id is null. Operation aborted."); + return; + } when(commentsRepository.findById(id)).thenReturn(java.util.Optional.of(comment)); Comments result = commentsService.getCommentById(id); diff --git a/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java b/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java index 382ba0d..b2fc729 100755 --- a/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java +++ b/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java @@ -11,12 +11,16 @@ import org.zaine.app.model.Competencies; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; + +import java.lang.System.Logger; import java.util.Arrays; import java.util.Optional; @ExtendWith(org.mockito.junit.jupiter.MockitoExtension.class) public class CompetenciesServiceTest { + private static final Logger logger = System.getLogger(CompetenciesService.class.getName()); + @InjectMocks private CompetenciesService competenciesService; @@ -41,6 +45,10 @@ public class CompetenciesServiceTest { public void testGetCompetencyByIdReturnsCompetency() { Competencies comp = new Competencies(); @NotNull Integer id = comp.getId(); + if (id == null) { + logger.log(System.Logger.Level.WARNING, "Competency id is null. Operation aborted."); + return; + } when(competenciesRepository.findById(id)).thenReturn(Optional.of(comp)); @@ -53,6 +61,10 @@ public class CompetenciesServiceTest { public void testUpdateCompetencyStatusUpdatesCorrectly() { Competencies comp = new Competencies(); @NotNull Integer id = comp.getId(); + if (id == null) { + logger.log(System.Logger.Level.WARNING, "Competency id is null. Operation aborted."); + return; + } when(competenciesRepository.findById(id)).thenReturn(Optional.of(comp)); competenciesService.updateCompetencyState(id, "completed");