Merge pull request #9 from abhi1693/jarvis/fix-departments-post

Fix Mission Control: POST /departments atomic + 409 on conflicts
This commit is contained in:
Abhimanyu Saharan
2026-02-02 13:45:50 +05:30
committed by GitHub

View File

@@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.exc import IntegrityError
from sqlmodel import Session, select from sqlmodel import Session, select
from app.api.utils import log_activity, get_actor_employee_id from app.api.utils import log_activity, get_actor_employee_id
@@ -17,16 +18,40 @@ def list_departments(session: Session = Depends(get_session)):
@router.post("/departments", response_model=Department) @router.post("/departments", response_model=Department)
def create_department(payload: DepartmentCreate, session: Session = Depends(get_session), actor_employee_id: int = Depends(get_actor_employee_id)): def create_department(
payload: DepartmentCreate,
session: Session = Depends(get_session),
actor_employee_id: int = Depends(get_actor_employee_id),
):
"""Create a department.
Important: keep the operation atomic. We flush to get dept.id, log the activity,
then commit once. We also translate common DB integrity errors into 409s.
"""
dept = Department(name=payload.name, head_employee_id=payload.head_employee_id) dept = Department(name=payload.name, head_employee_id=payload.head_employee_id)
session.add(dept) session.add(dept)
try:
session.flush() # assigns dept.id without committing
log_activity(
session,
actor_employee_id=actor_employee_id,
entity_type="department",
entity_id=dept.id,
verb="created",
payload={"name": dept.name},
)
session.commit() session.commit()
except IntegrityError:
session.rollback()
raise HTTPException(status_code=409, detail="Department already exists or violates constraints")
session.refresh(dept) session.refresh(dept)
log_activity(session, actor_employee_id=actor_employee_id, entity_type="department", entity_id=dept.id, verb="created", payload={"name": dept.name})
session.commit()
return dept return dept
@router.patch("/departments/{department_id}", response_model=Department) @router.patch("/departments/{department_id}", response_model=Department)
def update_department(department_id: int, payload: DepartmentUpdate, session: Session = Depends(get_session), actor_employee_id: int = Depends(get_actor_employee_id)): def update_department(department_id: int, payload: DepartmentUpdate, session: Session = Depends(get_session), actor_employee_id: int = Depends(get_actor_employee_id)):
dept = session.get(Department, department_id) dept = session.get(Department, department_id)