avant codex
This commit is contained in:
59
backend/app/routers/astuces.py
Normal file
59
backend/app/routers/astuces.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlmodel import Session, select
|
||||
from app.database import get_session
|
||||
from app.models.astuce import Astuce
|
||||
|
||||
router = APIRouter(tags=["astuces"])
|
||||
|
||||
|
||||
@router.get("/astuces", response_model=List[Astuce])
|
||||
def list_astuces(
|
||||
entity_type: Optional[str] = Query(None),
|
||||
entity_id: Optional[int] = Query(None),
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
q = select(Astuce)
|
||||
if entity_type:
|
||||
q = q.where(Astuce.entity_type == entity_type)
|
||||
if entity_id is not None:
|
||||
q = q.where(Astuce.entity_id == entity_id)
|
||||
return session.exec(q).all()
|
||||
|
||||
|
||||
@router.post("/astuces", response_model=Astuce, status_code=status.HTTP_201_CREATED)
|
||||
def create_astuce(a: Astuce, session: Session = Depends(get_session)):
|
||||
session.add(a)
|
||||
session.commit()
|
||||
session.refresh(a)
|
||||
return a
|
||||
|
||||
|
||||
@router.get("/astuces/{id}", response_model=Astuce)
|
||||
def get_astuce(id: int, session: Session = Depends(get_session)):
|
||||
a = session.get(Astuce, id)
|
||||
if not a:
|
||||
raise HTTPException(404, "Astuce introuvable")
|
||||
return a
|
||||
|
||||
|
||||
@router.put("/astuces/{id}", response_model=Astuce)
|
||||
def update_astuce(id: int, data: Astuce, session: Session = Depends(get_session)):
|
||||
a = session.get(Astuce, id)
|
||||
if not a:
|
||||
raise HTTPException(404, "Astuce introuvable")
|
||||
for k, v in data.model_dump(exclude_unset=True, exclude={"id", "created_at"}).items():
|
||||
setattr(a, k, v)
|
||||
session.add(a)
|
||||
session.commit()
|
||||
session.refresh(a)
|
||||
return a
|
||||
|
||||
|
||||
@router.delete("/astuces/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_astuce(id: int, session: Session = Depends(get_session)):
|
||||
a = session.get(Astuce, id)
|
||||
if not a:
|
||||
raise HTTPException(404, "Astuce introuvable")
|
||||
session.delete(a)
|
||||
session.commit()
|
||||
18
backend/app/routers/dictons.py
Normal file
18
backend/app/routers/dictons.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlmodel import Session, select
|
||||
from app.database import get_session
|
||||
from app.models.dicton import Dicton
|
||||
|
||||
router = APIRouter(tags=["dictons"])
|
||||
|
||||
|
||||
@router.get("/dictons", response_model=List[Dicton])
|
||||
def list_dictons(
|
||||
mois: Optional[int] = Query(None),
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
q = select(Dicton)
|
||||
if mois:
|
||||
q = q.where(Dicton.mois == mois)
|
||||
return session.exec(q).all()
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
@@ -38,7 +38,7 @@ def update_garden(id: int, data: Garden, session: Session = Depends(get_session)
|
||||
raise HTTPException(status_code=404, detail="Jardin introuvable")
|
||||
for k, v in data.model_dump(exclude_unset=True, exclude={"id", "created_at"}).items():
|
||||
setattr(g, k, v)
|
||||
g.updated_at = datetime.utcnow()
|
||||
g.updated_at = datetime.now(timezone.utc)
|
||||
session.add(g)
|
||||
session.commit()
|
||||
session.refresh(g)
|
||||
|
||||
36
backend/app/routers/lunar.py
Normal file
36
backend/app/routers/lunar.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import calendar
|
||||
from datetime import date
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
|
||||
router = APIRouter(tags=["lunaire"])
|
||||
|
||||
# Cache en mémoire : {mois_str: list[dict]}
|
||||
_CACHE: dict[str, list[dict]] = {}
|
||||
|
||||
|
||||
@router.get("/lunar")
|
||||
def get_lunar(
|
||||
month: str = Query(..., description="Format YYYY-MM"),
|
||||
) -> list[dict[str, Any]]:
|
||||
if month in _CACHE:
|
||||
return _CACHE[month]
|
||||
try:
|
||||
year, mon = int(month[:4]), int(month[5:7])
|
||||
except (ValueError, IndexError):
|
||||
raise HTTPException(400, "Format attendu : YYYY-MM")
|
||||
last_day = calendar.monthrange(year, mon)[1]
|
||||
start = date(year, mon, 1)
|
||||
end = date(year, mon, last_day)
|
||||
try:
|
||||
from app.services.lunar import build_calendar
|
||||
from dataclasses import asdict
|
||||
|
||||
result = [asdict(d) for d in build_calendar(start, end)]
|
||||
except ImportError:
|
||||
raise HTTPException(503, "Service lunaire non disponible (skyfield non installé)")
|
||||
except Exception as e:
|
||||
raise HTTPException(500, f"Erreur calcul lunaire : {e}")
|
||||
_CACHE[month] = result
|
||||
return result
|
||||
@@ -2,13 +2,20 @@ import os
|
||||
import uuid
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile, status
|
||||
from fastapi import APIRouter, Body, Depends, File, HTTPException, Query, UploadFile, status
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from app.config import UPLOAD_DIR
|
||||
from app.database import get_session
|
||||
from app.models.media import Attachment, Media
|
||||
|
||||
|
||||
class MediaPatch(BaseModel):
|
||||
entity_type: Optional[str] = None
|
||||
entity_id: Optional[int] = None
|
||||
titre: Optional[str] = None
|
||||
|
||||
router = APIRouter(tags=["media"])
|
||||
|
||||
|
||||
@@ -81,6 +88,19 @@ def create_media(m: Media, session: Session = Depends(get_session)):
|
||||
return m
|
||||
|
||||
|
||||
@router.patch("/media/{id}", response_model=Media)
|
||||
def update_media(id: int, payload: MediaPatch, session: Session = Depends(get_session)):
|
||||
m = session.get(Media, id)
|
||||
if not m:
|
||||
raise HTTPException(404, "Media introuvable")
|
||||
for k, v in payload.model_dump(exclude_none=True).items():
|
||||
setattr(m, k, v)
|
||||
session.add(m)
|
||||
session.commit()
|
||||
session.refresh(m)
|
||||
return m
|
||||
|
||||
|
||||
@router.delete("/media/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_media(id: int, session: Session = Depends(get_session)):
|
||||
m = session.get(Media, id)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlmodel import Session, select
|
||||
from app.database import get_session
|
||||
from app.models.planting import Planting, PlantingEvent
|
||||
from app.models.planting import Planting, PlantingCreate, PlantingEvent
|
||||
|
||||
router = APIRouter(tags=["plantations"])
|
||||
|
||||
@@ -14,7 +14,8 @@ def list_plantings(session: Session = Depends(get_session)):
|
||||
|
||||
|
||||
@router.post("/plantings", response_model=Planting, status_code=status.HTTP_201_CREATED)
|
||||
def create_planting(p: Planting, session: Session = Depends(get_session)):
|
||||
def create_planting(data: PlantingCreate, session: Session = Depends(get_session)):
|
||||
p = Planting(**data.model_dump())
|
||||
session.add(p)
|
||||
session.commit()
|
||||
session.refresh(p)
|
||||
@@ -30,13 +31,13 @@ def get_planting(id: int, session: Session = Depends(get_session)):
|
||||
|
||||
|
||||
@router.put("/plantings/{id}", response_model=Planting)
|
||||
def update_planting(id: int, data: Planting, session: Session = Depends(get_session)):
|
||||
def update_planting(id: int, data: PlantingCreate, session: Session = Depends(get_session)):
|
||||
p = session.get(Planting, id)
|
||||
if not p:
|
||||
raise HTTPException(status_code=404, detail="Plantation introuvable")
|
||||
for k, v in data.model_dump(exclude_unset=True, exclude={"id", "created_at"}).items():
|
||||
for k, v in data.model_dump(exclude_unset=True).items():
|
||||
setattr(p, k, v)
|
||||
p.updated_at = datetime.utcnow()
|
||||
p.updated_at = datetime.now(timezone.utc)
|
||||
session.add(p)
|
||||
session.commit()
|
||||
session.refresh(p)
|
||||
|
||||
56
backend/app/routers/plants.py
Normal file
56
backend/app/routers/plants.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlmodel import Session, select
|
||||
from app.database import get_session
|
||||
from app.models.plant import Plant
|
||||
|
||||
router = APIRouter(tags=["plantes"])
|
||||
|
||||
|
||||
@router.get("/plants", response_model=List[Plant])
|
||||
def list_plants(
|
||||
categorie: Optional[str] = Query(None),
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
q = select(Plant)
|
||||
if categorie:
|
||||
q = q.where(Plant.categorie == categorie)
|
||||
return session.exec(q).all()
|
||||
|
||||
|
||||
@router.post("/plants", response_model=Plant, status_code=status.HTTP_201_CREATED)
|
||||
def create_plant(p: Plant, session: Session = Depends(get_session)):
|
||||
session.add(p)
|
||||
session.commit()
|
||||
session.refresh(p)
|
||||
return p
|
||||
|
||||
|
||||
@router.get("/plants/{id}", response_model=Plant)
|
||||
def get_plant(id: int, session: Session = Depends(get_session)):
|
||||
p = session.get(Plant, id)
|
||||
if not p:
|
||||
raise HTTPException(404, "Plante introuvable")
|
||||
return p
|
||||
|
||||
|
||||
@router.put("/plants/{id}", response_model=Plant)
|
||||
def update_plant(id: int, data: Plant, session: Session = Depends(get_session)):
|
||||
p = session.get(Plant, id)
|
||||
if not p:
|
||||
raise HTTPException(404, "Plante introuvable")
|
||||
for k, v in data.model_dump(exclude_unset=True, exclude={"id", "created_at"}).items():
|
||||
setattr(p, k, v)
|
||||
session.add(p)
|
||||
session.commit()
|
||||
session.refresh(p)
|
||||
return p
|
||||
|
||||
|
||||
@router.delete("/plants/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_plant(id: int, session: Session = Depends(get_session)):
|
||||
p = session.get(Plant, id)
|
||||
if not p:
|
||||
raise HTTPException(404, "Plante introuvable")
|
||||
session.delete(p)
|
||||
session.commit()
|
||||
84
backend/app/routers/recoltes.py
Normal file
84
backend/app/routers/recoltes.py
Normal file
@@ -0,0 +1,84 @@
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlmodel import Session, select
|
||||
from app.database import get_session
|
||||
from app.models.recolte import Observation, ObservationCreate, Recolte, RecolteCreate
|
||||
|
||||
router = APIRouter(tags=["récoltes"])
|
||||
|
||||
|
||||
# ── Récoltes (nested sous plantings) ──────────────────────────────────────────
|
||||
|
||||
@router.get("/plantings/{planting_id}/recoltes", response_model=List[Recolte])
|
||||
def list_recoltes(planting_id: int, session: Session = Depends(get_session)):
|
||||
return session.exec(
|
||||
select(Recolte).where(Recolte.plantation_id == planting_id)
|
||||
).all()
|
||||
|
||||
|
||||
@router.post(
|
||||
"/plantings/{planting_id}/recoltes",
|
||||
response_model=Recolte,
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
)
|
||||
def create_recolte(
|
||||
planting_id: int,
|
||||
data: RecolteCreate,
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
r = Recolte(plantation_id=planting_id, **data.model_dump())
|
||||
session.add(r)
|
||||
session.commit()
|
||||
session.refresh(r)
|
||||
return r
|
||||
|
||||
|
||||
@router.delete("/recoltes/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_recolte(id: int, session: Session = Depends(get_session)):
|
||||
r = session.get(Recolte, id)
|
||||
if not r:
|
||||
raise HTTPException(404, "Récolte introuvable")
|
||||
session.delete(r)
|
||||
session.commit()
|
||||
|
||||
|
||||
# ── Observations ───────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/observations", response_model=List[Observation])
|
||||
def list_observations(
|
||||
plantation_id: Optional[int] = Query(None),
|
||||
garden_id: Optional[int] = Query(None),
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
q = select(Observation)
|
||||
if plantation_id is not None:
|
||||
q = q.where(Observation.plantation_id == plantation_id)
|
||||
if garden_id is not None:
|
||||
q = q.where(Observation.garden_id == garden_id)
|
||||
return session.exec(q).all()
|
||||
|
||||
|
||||
@router.post("/observations", response_model=Observation, status_code=status.HTTP_201_CREATED)
|
||||
def create_observation(data: ObservationCreate, session: Session = Depends(get_session)):
|
||||
o = Observation(**data.model_dump())
|
||||
session.add(o)
|
||||
session.commit()
|
||||
session.refresh(o)
|
||||
return o
|
||||
|
||||
|
||||
@router.get("/observations/{id}", response_model=Observation)
|
||||
def get_observation(id: int, session: Session = Depends(get_session)):
|
||||
o = session.get(Observation, id)
|
||||
if not o:
|
||||
raise HTTPException(404, "Observation introuvable")
|
||||
return o
|
||||
|
||||
|
||||
@router.delete("/observations/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_observation(id: int, session: Session = Depends(get_session)):
|
||||
o = session.get(Observation, id)
|
||||
if not o:
|
||||
raise HTTPException(404, "Observation introuvable")
|
||||
session.delete(o)
|
||||
session.commit()
|
||||
@@ -1,8 +1,7 @@
|
||||
from datetime import date
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlmodel import Session, select
|
||||
from app.database import get_session
|
||||
from app.models.settings import UserSettings, LunarCalendarEntry
|
||||
from app.models.settings import UserSettings
|
||||
|
||||
router = APIRouter(tags=["réglages"])
|
||||
|
||||
@@ -24,16 +23,3 @@ def update_settings(data: dict, session: Session = Depends(get_session)):
|
||||
session.add(row)
|
||||
session.commit()
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@router.get("/lunar")
|
||||
def get_lunar(month: str, session: Session = Depends(get_session)):
|
||||
year, m = map(int, month.split("-"))
|
||||
first = date(year, m, 1)
|
||||
last_m, last_y = (m + 1, year) if m < 12 else (1, year + 1)
|
||||
last = date(last_y, last_m, 1)
|
||||
return session.exec(
|
||||
select(LunarCalendarEntry)
|
||||
.where(LunarCalendarEntry.jour >= first)
|
||||
.where(LunarCalendarEntry.jour < last)
|
||||
).all()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlmodel import Session, select
|
||||
from app.database import get_session
|
||||
from app.models.task import Task
|
||||
from app.models.task import Task, TaskCreate
|
||||
|
||||
router = APIRouter(tags=["tâches"])
|
||||
|
||||
@@ -23,7 +23,8 @@ def list_tasks(
|
||||
|
||||
|
||||
@router.post("/tasks", response_model=Task, status_code=status.HTTP_201_CREATED)
|
||||
def create_task(t: Task, session: Session = Depends(get_session)):
|
||||
def create_task(data: TaskCreate, session: Session = Depends(get_session)):
|
||||
t = Task(**data.model_dump())
|
||||
session.add(t)
|
||||
session.commit()
|
||||
session.refresh(t)
|
||||
@@ -39,13 +40,26 @@ def get_task(id: int, session: Session = Depends(get_session)):
|
||||
|
||||
|
||||
@router.put("/tasks/{id}", response_model=Task)
|
||||
def update_task(id: int, data: Task, session: Session = Depends(get_session)):
|
||||
def update_task(id: int, data: TaskCreate, session: Session = Depends(get_session)):
|
||||
t = session.get(Task, id)
|
||||
if not t:
|
||||
raise HTTPException(status_code=404, detail="Tâche introuvable")
|
||||
for k, v in data.model_dump(exclude_unset=True, exclude={"id", "created_at"}).items():
|
||||
for k, v in data.model_dump(exclude_unset=True).items():
|
||||
setattr(t, k, v)
|
||||
t.updated_at = datetime.utcnow()
|
||||
t.updated_at = datetime.now(timezone.utc)
|
||||
session.add(t)
|
||||
session.commit()
|
||||
session.refresh(t)
|
||||
return t
|
||||
|
||||
|
||||
@router.put("/tasks/{id}/statut", response_model=Task)
|
||||
def update_statut(id: int, statut: str, session: Session = Depends(get_session)):
|
||||
t = session.get(Task, id)
|
||||
if not t:
|
||||
raise HTTPException(status_code=404, detail="Tâche introuvable")
|
||||
t.statut = statut
|
||||
t.updated_at = datetime.now(timezone.utc)
|
||||
session.add(t)
|
||||
session.commit()
|
||||
session.refresh(t)
|
||||
|
||||
56
backend/app/routers/tools.py
Normal file
56
backend/app/routers/tools.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlmodel import Session, select
|
||||
from app.database import get_session
|
||||
from app.models.tool import Tool
|
||||
|
||||
router = APIRouter(tags=["outils"])
|
||||
|
||||
|
||||
@router.get("/tools", response_model=List[Tool])
|
||||
def list_tools(
|
||||
categorie: Optional[str] = Query(None),
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
q = select(Tool)
|
||||
if categorie:
|
||||
q = q.where(Tool.categorie == categorie)
|
||||
return session.exec(q).all()
|
||||
|
||||
|
||||
@router.post("/tools", response_model=Tool, status_code=status.HTTP_201_CREATED)
|
||||
def create_tool(t: Tool, session: Session = Depends(get_session)):
|
||||
session.add(t)
|
||||
session.commit()
|
||||
session.refresh(t)
|
||||
return t
|
||||
|
||||
|
||||
@router.get("/tools/{id}", response_model=Tool)
|
||||
def get_tool(id: int, session: Session = Depends(get_session)):
|
||||
t = session.get(Tool, id)
|
||||
if not t:
|
||||
raise HTTPException(404, "Outil introuvable")
|
||||
return t
|
||||
|
||||
|
||||
@router.put("/tools/{id}", response_model=Tool)
|
||||
def update_tool(id: int, data: Tool, session: Session = Depends(get_session)):
|
||||
t = session.get(Tool, id)
|
||||
if not t:
|
||||
raise HTTPException(404, "Outil introuvable")
|
||||
for k, v in data.model_dump(exclude_unset=True, exclude={"id", "created_at"}).items():
|
||||
setattr(t, k, v)
|
||||
session.add(t)
|
||||
session.commit()
|
||||
session.refresh(t)
|
||||
return t
|
||||
|
||||
|
||||
@router.delete("/tools/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def delete_tool(id: int, session: Session = Depends(get_session)):
|
||||
t = session.get(Tool, id)
|
||||
if not t:
|
||||
raise HTTPException(404, "Outil introuvable")
|
||||
session.delete(t)
|
||||
session.commit()
|
||||
Reference in New Issue
Block a user