updates for zmanagement x4
All checks were successful
Build Org Backend / build (push) Successful in 17s

This commit is contained in:
2026-06-10 16:40:53 +01:00
parent 28d874edd8
commit 4bf7810206
8 changed files with 89 additions and 10 deletions

View File

@@ -2,17 +2,22 @@ package org.zaine.app.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.zaine.app.dto.EveningCheckinRequest;
import org.zaine.app.dto.MorningCheckinRequest;
import org.zaine.app.dto.TodayStatusDTO;
import org.zaine.app.service.CheckinService;
import java.time.LocalDate;
import java.util.List;
@RestController
@RequestMapping("/api/checkin")
@Tag(name = "Check-in", description = "Daily morning and evening check-ins")
@@ -30,6 +35,14 @@ public class CheckinController {
return checkinService.getTodayStatus();
}
@Operation(summary = "Get check-in history")
@GetMapping("/history")
public List<TodayStatusDTO> getHistory(
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to) {
return checkinService.getHistory(from, to);
}
@Operation(summary = "Submit morning check-in")
@PostMapping("/morning")
public ResponseEntity<TodayStatusDTO> submitMorning(@RequestBody MorningCheckinRequest request) {

View File

@@ -6,6 +6,9 @@ public record EveningCheckinRequest(
LocalDate date,
Integer mood,
Integer stressLevel,
Boolean duties,
Boolean zikr,
Boolean salah,
String reflection,
String bestThingToday) {
}

View File

@@ -8,5 +8,8 @@ public record MorningCheckinRequest(
BigDecimal sleepHours,
Integer energyLevel,
Integer mood,
Boolean fajr,
Boolean quran,
Boolean exercise,
String note) {
}

View File

@@ -13,6 +13,13 @@ public record TodayStatusDTO(
Integer morningMoodLevel,
Integer eveningMoodLevel,
Integer stressLevel,
Boolean fajr,
Boolean quran,
Boolean exercise,
Boolean duties,
Boolean zikr,
Boolean salah,
String reflection,
OffsetDateTime morningCompletedAt,
OffsetDateTime eveningCompletedAt) {
}

View File

@@ -36,6 +36,15 @@ public class DailyCheckin {
@Column(name = "morning_note")
private String morningNote;
@Column(name = "fajr")
private Boolean fajr;
@Column(name = "quran")
private Boolean quran;
@Column(name = "exercise")
private Boolean exercise;
@Column(name = "morning_completed_at")
private OffsetDateTime morningCompletedAt;
@@ -51,6 +60,15 @@ public class DailyCheckin {
@Column(name = "best_thing_today")
private String bestThingToday;
@Column(name = "duties")
private Boolean duties;
@Column(name = "zikr")
private Boolean zikr;
@Column(name = "salah")
private Boolean salah;
@Column(name = "evening_completed_at")
private OffsetDateTime eveningCompletedAt;
@@ -83,6 +101,12 @@ public class DailyCheckin {
public void setMorningMoodLevel(Integer morningMoodLevel) { this.morningMoodLevel = morningMoodLevel; }
public String getMorningNote() { return morningNote; }
public void setMorningNote(String morningNote) { this.morningNote = morningNote; }
public Boolean getFajr() { return fajr; }
public void setFajr(Boolean fajr) { this.fajr = fajr; }
public Boolean getQuran() { return quran; }
public void setQuran(Boolean quran) { this.quran = quran; }
public Boolean getExercise() { return exercise; }
public void setExercise(Boolean exercise) { this.exercise = exercise; }
public OffsetDateTime getMorningCompletedAt() { return morningCompletedAt; }
public void setMorningCompletedAt(OffsetDateTime morningCompletedAt) { this.morningCompletedAt = morningCompletedAt; }
public Integer getEveningMoodLevel() { return eveningMoodLevel; }
@@ -93,6 +117,12 @@ public class DailyCheckin {
public void setReflection(String reflection) { this.reflection = reflection; }
public String getBestThingToday() { return bestThingToday; }
public void setBestThingToday(String bestThingToday) { this.bestThingToday = bestThingToday; }
public Boolean getDuties() { return duties; }
public void setDuties(Boolean duties) { this.duties = duties; }
public Boolean getZikr() { return zikr; }
public void setZikr(Boolean zikr) { this.zikr = zikr; }
public Boolean getSalah() { return salah; }
public void setSalah(Boolean salah) { this.salah = salah; }
public OffsetDateTime getEveningCompletedAt() { return eveningCompletedAt; }
public void setEveningCompletedAt(OffsetDateTime eveningCompletedAt) { this.eveningCompletedAt = eveningCompletedAt; }
public OffsetDateTime getCreatedAt() { return createdAt; }

View File

@@ -4,8 +4,10 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.zaine.app.model.DailyCheckin;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
public interface DailyCheckinRepository extends JpaRepository<DailyCheckin, Long> {
Optional<DailyCheckin> findByDate(LocalDate date);
List<DailyCheckin> findByDateBetweenOrderByDateDesc(LocalDate from, LocalDate to);
}

View File

@@ -12,6 +12,7 @@ import org.zaine.app.repositories.DailyCheckinRepository;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.List;
@Service
public class CheckinService {
@@ -26,16 +27,27 @@ public class CheckinService {
return toStatus(getOrCreate(LocalDate.now()));
}
public List<TodayStatusDTO> getHistory(LocalDate from, LocalDate to) {
if (to.isBefore(from)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "to must be on or after from");
}
return dailyCheckinRepository.findByDateBetweenOrderByDateDesc(from, to)
.stream()
.map(this::toStatus)
.toList();
}
public TodayStatusDTO saveMorning(MorningCheckinRequest request) {
LocalDate date = request.date() == null ? LocalDate.now() : request.date();
validateScore(request.energyLevel(), "energyLevel");
validateScore(request.mood(), "mood");
validateSleepHours(request.sleepHours());
DailyCheckin checkin = getOrCreate(date);
checkin.setSleepHours(request.sleepHours());
checkin.setMorningEnergyLevel(request.energyLevel());
checkin.setMorningMoodLevel(request.mood());
checkin.setFajr(request.fajr());
checkin.setQuran(request.quran());
checkin.setExercise(request.exercise());
checkin.setMorningNote(blankToNull(request.note()));
checkin.setMorningCompletedAt(OffsetDateTime.now());
@@ -44,12 +56,13 @@ public class CheckinService {
public TodayStatusDTO saveEvening(EveningCheckinRequest request) {
LocalDate date = request.date() == null ? LocalDate.now() : request.date();
validateScore(request.mood(), "mood");
validateScore(request.stressLevel(), "stressLevel");
DailyCheckin checkin = getOrCreate(date);
checkin.setEveningMoodLevel(request.mood());
checkin.setStressLevel(request.stressLevel());
checkin.setDuties(request.duties());
checkin.setZikr(request.zikr());
checkin.setSalah(request.salah());
checkin.setReflection(blankToNull(request.reflection()));
checkin.setBestThingToday(blankToNull(request.bestThingToday()));
checkin.setEveningCompletedAt(OffsetDateTime.now());
@@ -75,16 +88,17 @@ public class CheckinService {
checkin.getMorningMoodLevel(),
checkin.getEveningMoodLevel(),
checkin.getStressLevel(),
checkin.getFajr(),
checkin.getQuran(),
checkin.getExercise(),
checkin.getDuties(),
checkin.getZikr(),
checkin.getSalah(),
checkin.getReflection(),
checkin.getMorningCompletedAt(),
checkin.getEveningCompletedAt());
}
private void validateScore(Integer value, String fieldName) {
if (value == null || value < 1 || value > 10) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, fieldName + " must be between 1 and 10");
}
}
private void validateSleepHours(BigDecimal sleepHours) {
if (sleepHours == null || sleepHours.compareTo(BigDecimal.ZERO) < 0 || sleepHours.compareTo(new BigDecimal("24")) > 0) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "sleepHours must be between 0 and 24");

View File

@@ -0,0 +1,7 @@
ALTER TABLE daily_checkins
ADD COLUMN IF NOT EXISTS fajr BOOLEAN,
ADD COLUMN IF NOT EXISTS quran BOOLEAN,
ADD COLUMN IF NOT EXISTS exercise BOOLEAN,
ADD COLUMN IF NOT EXISTS duties BOOLEAN,
ADD COLUMN IF NOT EXISTS zikr BOOLEAN,
ADD COLUMN IF NOT EXISTS salah BOOLEAN;