Public Access
fix: test-email actually sends; vote page pre-checks existing votes; lowercase MealPlanItemStatus everywhere
- /api/admin/test-email now calls get_email_backend().send() instead of only logging.
- /api/meals/vote/{id} GET now queries MealPlanVote and renders 'already voted' confirmation if found.
- api/meals.py: fix remaining uppercase MealPlanItemStatus enum ref (DENIED, APPROVED, PENDING).
- Fixes the 'all meals show as pending' status regression and the 'Error: Already voted' bug.
This commit is contained in:
@@ -135,10 +135,27 @@ def get_all_meal_plans(
|
||||
|
||||
@router.post("/test-email")
|
||||
def test_email(email: str, db: Session = Depends(get_db)):
|
||||
from app.services.email import get_email_backend
|
||||
|
||||
html = "<html><body><h1>MealPlanner Test Email</h1><p>This is a test email from MealPlanner.</p></body></html>"
|
||||
text = "MealPlanner Test Email\n\nThis is a test email from MealPlanner."
|
||||
|
||||
try:
|
||||
backend = get_email_backend()
|
||||
backend.send(
|
||||
to=email,
|
||||
subject="MealPlanner Test Email",
|
||||
html=html,
|
||||
text=text,
|
||||
)
|
||||
status = "sent"
|
||||
except Exception as e:
|
||||
status = f"failed: {e}"
|
||||
|
||||
email_log = EmailLog(
|
||||
recipient_email=email,
|
||||
template="test",
|
||||
status="sent",
|
||||
status=status,
|
||||
created_at=datetime.now()
|
||||
)
|
||||
db.add(email_log)
|
||||
@@ -146,9 +163,10 @@ def test_email(email: str, db: Session = Depends(get_db)):
|
||||
db.refresh(email_log)
|
||||
|
||||
return {
|
||||
"message": "Test email logged",
|
||||
"message": f"Test email {status}",
|
||||
"email_log_id": str(email_log.id),
|
||||
"recipient": email
|
||||
"recipient": email,
|
||||
"status": status,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -156,6 +156,38 @@ def get_vote_page(
|
||||
safe_meal = _html_escape(meal_type)
|
||||
action_url = f"/api/meals/vote/{item_id}?token={_html_escape(token, quote=True)}"
|
||||
|
||||
existing_vote = db.query(MealPlanVote).filter(
|
||||
MealPlanVote.meal_plan_item_id == item_id,
|
||||
MealPlanVote.family_member_id == voter.id,
|
||||
).first()
|
||||
|
||||
if existing_vote:
|
||||
already_voted_html = f"""<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Already Voted</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body {{ font-family: system-ui, sans-serif; max-width: 36rem; margin: 2rem auto;
|
||||
padding: 0 1rem; color: #111; background: #fff; line-height: 1.5; }}
|
||||
h1 {{ font-size: 1.4rem; }}
|
||||
.meal {{ padding: 1rem; border: 1px solid #444; border-radius: 6px; margin: 1rem 0; }}
|
||||
.already-voted {{ margin-top: 1rem; font-weight: bold; color: #0a6b2b; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {safe_voter}, you already voted on this meal</h1>
|
||||
<div class="meal">
|
||||
<div><strong>{safe_recipe}</strong></div>
|
||||
<div>{safe_day} · {safe_meal}</div>
|
||||
</div>
|
||||
<div class="already-voted">Your vote has already been recorded. Thank you!</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
return HTMLResponse(content=already_voted_html, status_code=200)
|
||||
|
||||
html = f"""<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -251,11 +283,11 @@ def submit_vote(
|
||||
).all()
|
||||
|
||||
if any(v.vote is False for v in votes):
|
||||
item.approval_status = MealPlanItemStatus.DENIED
|
||||
item.approval_status = MealPlanItemStatus.denied
|
||||
elif electorate_ids and {v.family_member_id for v in votes} >= electorate_ids:
|
||||
item.approval_status = MealPlanItemStatus.APPROVED
|
||||
item.approval_status = MealPlanItemStatus.approved
|
||||
else:
|
||||
item.approval_status = MealPlanItemStatus.PENDING
|
||||
item.approval_status = MealPlanItemStatus.pending
|
||||
|
||||
db.commit()
|
||||
return {"status": "recorded", "item_status": item.approval_status.value}
|
||||
@@ -282,7 +314,7 @@ def swap_meal_item(item_id: UUID, new_recipe_id: UUID, db: Session = Depends(get
|
||||
raise HTTPException(status_code=404, detail="New recipe not found")
|
||||
|
||||
item.recipe_id = new_recipe_id
|
||||
item.approval_status = MealPlanItemStatus.PENDING
|
||||
item.approval_status = MealPlanItemStatus.pending
|
||||
item.denial_reason = None
|
||||
item.denial_details = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user