Implement Recipe, Planning, Shopping, Pantry, and Admin domains

Outside-in TDD for all 5 remaining domains (128 tests total):
- Recipe: CRUD, ingredients autocomplete/patch, tags, categories (27 tests)
- Planning: week plans, slots, confirm, suggestions, variety score, cooking logs (24 tests)
- Shopping: generate from plan, publish, check/add/remove items (15 tests)
- Pantry: CRUD with expiry sorting (11 tests)
- Admin: user management, password reset, audit logging (13 tests)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-01 21:56:51 +02:00
parent 4f457303d8
commit 9ec703abcd
88 changed files with 5267 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
package com.recipeapp.planning.entity;
import com.recipeapp.auth.entity.UserAccount;
import com.recipeapp.household.entity.Household;
import com.recipeapp.recipe.entity.Recipe;
import jakarta.persistence.*;
import java.time.LocalDate;
import java.util.UUID;
@Entity
@Table(name = "cooking_log")
public class CookingLog {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "recipe_id", nullable = false)
private Recipe recipe;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "household_id", nullable = false)
private Household household;
@Column(name = "cooked_on", nullable = false)
private LocalDate cookedOn;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cooked_by", nullable = false)
private UserAccount cookedBy;
protected CookingLog() {}
public CookingLog(Recipe recipe, Household household, LocalDate cookedOn, UserAccount cookedBy) {
this.recipe = recipe;
this.household = household;
this.cookedOn = cookedOn;
this.cookedBy = cookedBy;
}
public UUID getId() { return id; }
public Recipe getRecipe() { return recipe; }
public Household getHousehold() { return household; }
public LocalDate getCookedOn() { return cookedOn; }
public UserAccount getCookedBy() { return cookedBy; }
}

View File

@@ -0,0 +1,50 @@
package com.recipeapp.planning.entity;
import com.recipeapp.household.entity.Household;
import jakarta.persistence.*;
import java.time.Instant;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Entity
@Table(name = "week_plan")
public class WeekPlan {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "household_id", nullable = false)
private Household household;
@Column(name = "week_start", nullable = false)
private LocalDate weekStart;
@Column(nullable = false, length = 10)
private String status = "draft";
@Column(name = "confirmed_at")
private Instant confirmedAt;
@OneToMany(mappedBy = "weekPlan", cascade = CascadeType.ALL, orphanRemoval = true)
private List<WeekPlanSlot> slots = new ArrayList<>();
protected WeekPlan() {}
public WeekPlan(Household household, LocalDate weekStart) {
this.household = household;
this.weekStart = weekStart;
}
public UUID getId() { return id; }
public Household getHousehold() { return household; }
public LocalDate getWeekStart() { return weekStart; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public Instant getConfirmedAt() { return confirmedAt; }
public void setConfirmedAt(Instant confirmedAt) { this.confirmedAt = confirmedAt; }
public List<WeekPlanSlot> getSlots() { return slots; }
}

View File

@@ -0,0 +1,40 @@
package com.recipeapp.planning.entity;
import com.recipeapp.recipe.entity.Recipe;
import jakarta.persistence.*;
import java.time.LocalDate;
import java.util.UUID;
@Entity
@Table(name = "week_plan_slot")
public class WeekPlanSlot {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "week_plan_id", nullable = false)
private WeekPlan weekPlan;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "recipe_id", nullable = false)
private Recipe recipe;
@Column(name = "slot_date", nullable = false)
private LocalDate slotDate;
protected WeekPlanSlot() {}
public WeekPlanSlot(WeekPlan weekPlan, Recipe recipe, LocalDate slotDate) {
this.weekPlan = weekPlan;
this.recipe = recipe;
this.slotDate = slotDate;
}
public UUID getId() { return id; }
public WeekPlan getWeekPlan() { return weekPlan; }
public Recipe getRecipe() { return recipe; }
public void setRecipe(Recipe recipe) { this.recipe = recipe; }
public LocalDate getSlotDate() { return slotDate; }
}