- New canonical model: Proposal, ProposalStatus (app/models/proposal.py)
- New canonical router: /projects/{id}/proposals (app/api/routers/proposals.py)
- Schemas renamed: ProposalCreate, ProposalUpdate, ProposalResponse, etc.
- Old propose.py and proposes.py kept as backward-compat shims
- Legacy /proposes API still works (delegates to /proposals handlers)
- DB table name (proposes), column (propose_code), and permission names
(propose.*) kept unchanged for zero-migration compat
- Updated init_wizard.py comments
111 lines
4.1 KiB
Python
111 lines
4.1 KiB
Python
"""Backward-compatibility shim — mounts legacy /proposes routes alongside /proposals.
|
|
|
|
This keeps old API consumers working while the canonical path is now /proposals.
|
|
"""
|
|
from typing import List
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.config import get_db
|
|
from app.api.deps import get_current_user_or_apikey
|
|
from app.models import models
|
|
from app.schemas import schemas
|
|
|
|
# Import all handler functions from the canonical proposals router
|
|
from app.api.routers.proposals import (
|
|
_find_project,
|
|
_find_proposal,
|
|
_serialize_proposal,
|
|
_generate_proposal_code,
|
|
_can_edit_proposal,
|
|
AcceptRequest,
|
|
RejectRequest,
|
|
)
|
|
from app.models.proposal import Proposal, ProposalStatus
|
|
from app.models.milestone import Milestone, MilestoneStatus
|
|
from app.models.task import Task, TaskStatus, TaskPriority
|
|
from app.api.rbac import check_project_role, check_permission, is_global_admin
|
|
from app.services.activity import log_activity
|
|
|
|
# Legacy router — same logic, old URL prefix
|
|
router = APIRouter(prefix="/projects/{project_id}/proposes", tags=["Proposes (legacy)"])
|
|
|
|
|
|
@router.get("", response_model=List[schemas.ProposalResponse])
|
|
def list_proposes(
|
|
project_id: str,
|
|
db: Session = Depends(get_db),
|
|
current_user: models.User = Depends(get_current_user_or_apikey),
|
|
):
|
|
from app.api.routers.proposals import list_proposals
|
|
return list_proposals(project_id=project_id, db=db, current_user=current_user)
|
|
|
|
|
|
@router.post("", response_model=schemas.ProposalResponse, status_code=status.HTTP_201_CREATED)
|
|
def create_propose(
|
|
project_id: str,
|
|
proposal_in: schemas.ProposalCreate,
|
|
db: Session = Depends(get_db),
|
|
current_user: models.User = Depends(get_current_user_or_apikey),
|
|
):
|
|
from app.api.routers.proposals import create_proposal
|
|
return create_proposal(project_id=project_id, proposal_in=proposal_in, db=db, current_user=current_user)
|
|
|
|
|
|
@router.get("/{propose_id}", response_model=schemas.ProposalResponse)
|
|
def get_propose(
|
|
project_id: str,
|
|
propose_id: str,
|
|
db: Session = Depends(get_db),
|
|
current_user: models.User = Depends(get_current_user_or_apikey),
|
|
):
|
|
from app.api.routers.proposals import get_proposal
|
|
return get_proposal(project_id=project_id, proposal_id=propose_id, db=db, current_user=current_user)
|
|
|
|
|
|
@router.patch("/{propose_id}", response_model=schemas.ProposalResponse)
|
|
def update_propose(
|
|
project_id: str,
|
|
propose_id: str,
|
|
proposal_in: schemas.ProposalUpdate,
|
|
db: Session = Depends(get_db),
|
|
current_user: models.User = Depends(get_current_user_or_apikey),
|
|
):
|
|
from app.api.routers.proposals import update_proposal
|
|
return update_proposal(project_id=project_id, proposal_id=propose_id, proposal_in=proposal_in, db=db, current_user=current_user)
|
|
|
|
|
|
@router.post("/{propose_id}/accept", response_model=schemas.ProposalResponse)
|
|
def accept_propose(
|
|
project_id: str,
|
|
propose_id: str,
|
|
body: AcceptRequest,
|
|
db: Session = Depends(get_db),
|
|
current_user: models.User = Depends(get_current_user_or_apikey),
|
|
):
|
|
from app.api.routers.proposals import accept_proposal
|
|
return accept_proposal(project_id=project_id, proposal_id=propose_id, body=body, db=db, current_user=current_user)
|
|
|
|
|
|
@router.post("/{propose_id}/reject", response_model=schemas.ProposalResponse)
|
|
def reject_propose(
|
|
project_id: str,
|
|
propose_id: str,
|
|
body: RejectRequest | None = None,
|
|
db: Session = Depends(get_db),
|
|
current_user: models.User = Depends(get_current_user_or_apikey),
|
|
):
|
|
from app.api.routers.proposals import reject_proposal
|
|
return reject_proposal(project_id=project_id, proposal_id=propose_id, body=body, db=db, current_user=current_user)
|
|
|
|
|
|
@router.post("/{propose_id}/reopen", response_model=schemas.ProposalResponse)
|
|
def reopen_propose(
|
|
project_id: str,
|
|
propose_id: str,
|
|
db: Session = Depends(get_db),
|
|
current_user: models.User = Depends(get_current_user_or_apikey),
|
|
):
|
|
from app.api.routers.proposals import reopen_proposal
|
|
return reopen_proposal(project_id=project_id, proposal_id=propose_id, db=db, current_user=current_user)
|