SCORECARDAPIFORSTP / rules.py
zombee11's picture
Upload 28 files
f14009c verified
Raw
History Blame Contribute Delete
3.27 kB
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import func, select
from sqlalchemy.orm import Session
from app.api.dependencies import require_auth
from app.db.session import get_db
from app.models.rule import RuleMaster
from app.schemas.rule import RuleCreate, RuleResponse, RuleStatusUpdate, RuleUpdate
from app.services.audit import rule_to_dict, write_rule_audit
from app.services.rule_repository import RuleRepository
router = APIRouter(prefix="/rules", tags=["Rule Management"], dependencies=[Depends(require_auth)])
repo = RuleRepository()
@router.get("", response_model=list[RuleResponse])
def list_rules(
tenant_id: str | None = None,
product_type: str | None = None,
dealer_id: str | None = None,
rule_type: str | None = None,
is_active: bool | None = Query(default=None),
db: Session = Depends(get_db),
) -> list[RuleMaster]:
return repo.list_rules(db, tenant_id, product_type, dealer_id, rule_type, is_active)
@router.post("", response_model=RuleResponse, status_code=status.HTTP_201_CREATED)
def create_rule(payload: RuleCreate, db: Session = Depends(get_db)) -> RuleMaster:
dealer_filter = (
RuleMaster.dealer_id.is_(None)
if payload.dealer_id is None
else RuleMaster.dealer_id == payload.dealer_id
)
latest_version = db.scalar(
select(func.max(RuleMaster.version)).where(
RuleMaster.rule_code == payload.rule_code,
RuleMaster.tenant_id == payload.tenant_id,
RuleMaster.product_type == payload.product_type,
dealer_filter,
)
)
rule = RuleMaster(**payload.model_dump(), version=(latest_version or 0) + 1)
db.add(rule)
db.flush()
write_rule_audit(db, rule.id, "CREATE", payload.created_by, None, rule_to_dict(rule))
db.commit()
db.refresh(rule)
repo.invalidate(rule.tenant_id, rule.product_type, rule.dealer_id)
return rule
@router.put("/{rule_id}", response_model=RuleResponse)
def update_rule(rule_id: int, payload: RuleUpdate, db: Session = Depends(get_db)) -> RuleMaster:
rule = db.get(RuleMaster, rule_id)
if not rule:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Rule not found")
before = rule_to_dict(rule)
updates = payload.model_dump(exclude_unset=True)
actor = updates.pop("actor", "system")
for field, value in updates.items():
setattr(rule, field, value)
write_rule_audit(db, rule.id, "UPDATE", actor, before, rule_to_dict(rule))
db.commit()
db.refresh(rule)
repo.invalidate(rule.tenant_id, rule.product_type, rule.dealer_id)
return rule
@router.patch("/{rule_id}/status", response_model=RuleResponse)
def update_rule_status(
rule_id: int, payload: RuleStatusUpdate, db: Session = Depends(get_db)
) -> RuleMaster:
rule = db.get(RuleMaster, rule_id)
if not rule:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Rule not found")
before = rule_to_dict(rule)
rule.is_active = payload.is_active
write_rule_audit(db, rule.id, "STATUS_UPDATE", payload.actor, before, rule_to_dict(rule))
db.commit()
db.refresh(rule)
repo.invalidate(rule.tenant_id, rule.product_type, rule.dealer_id)
return rule