2025-10-27 22:17:45 +03:30
|
|
|
from typing import Dict, Any, Optional
|
|
|
|
|
from fastapi import APIRouter, Depends, Request, Query
|
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
|
|
|
|
from adapters.db.session import get_db
|
|
|
|
|
from app.core.auth_dependency import get_current_user, AuthContext
|
|
|
|
|
from app.core.permissions import require_business_access
|
|
|
|
|
from app.core.responses import success_response, ApiError, format_datetime_fields
|
|
|
|
|
from adapters.api.v1.schema_models.product_bom import (
|
|
|
|
|
ProductBOMCreateRequest,
|
|
|
|
|
ProductBOMUpdateRequest,
|
|
|
|
|
BOMExplosionRequest,
|
2025-10-31 21:32:23 +03:30
|
|
|
ProductionDraftRequest,
|
2025-10-27 22:17:45 +03:30
|
|
|
)
|
|
|
|
|
from app.services.bom_service import (
|
|
|
|
|
create_bom,
|
|
|
|
|
get_bom,
|
|
|
|
|
list_boms,
|
|
|
|
|
update_bom,
|
|
|
|
|
delete_bom,
|
|
|
|
|
explode_bom,
|
2025-10-31 21:32:23 +03:30
|
|
|
produce_draft,
|
2025-10-27 22:17:45 +03:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/boms", tags=["boms"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/business/{business_id}")
|
|
|
|
|
@require_business_access("business_id")
|
|
|
|
|
def create_bom_endpoint(
|
|
|
|
|
request: Request,
|
|
|
|
|
business_id: int,
|
|
|
|
|
payload: ProductBOMCreateRequest,
|
|
|
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
) -> Dict[str, Any]:
|
|
|
|
|
if not ctx.has_business_permission("inventory", "write"):
|
|
|
|
|
raise ApiError("FORBIDDEN", "Missing business permission: inventory.write", http_status=403)
|
|
|
|
|
result = create_bom(db, business_id, payload)
|
|
|
|
|
return success_response(data=format_datetime_fields(result["data"], request), request=request, message=result.get("message"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/business/{business_id}")
|
|
|
|
|
@require_business_access("business_id")
|
|
|
|
|
def list_boms_endpoint(
|
|
|
|
|
request: Request,
|
|
|
|
|
business_id: int,
|
|
|
|
|
product_id: int | None = Query(default=None),
|
|
|
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
) -> Dict[str, Any]:
|
|
|
|
|
if not ctx.can_read_section("inventory"):
|
|
|
|
|
raise ApiError("FORBIDDEN", "Missing business permission: inventory.read", http_status=403)
|
|
|
|
|
result = list_boms(db, business_id, product_id)
|
|
|
|
|
return success_response(data=format_datetime_fields(result, request), request=request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/business/{business_id}/{bom_id}")
|
|
|
|
|
@require_business_access("business_id")
|
|
|
|
|
def get_bom_endpoint(
|
|
|
|
|
request: Request,
|
|
|
|
|
business_id: int,
|
|
|
|
|
bom_id: int,
|
|
|
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
) -> Dict[str, Any]:
|
|
|
|
|
if not ctx.can_read_section("inventory"):
|
|
|
|
|
raise ApiError("FORBIDDEN", "Missing business permission: inventory.read", http_status=403)
|
|
|
|
|
item = get_bom(db, business_id, bom_id)
|
|
|
|
|
if not item:
|
|
|
|
|
raise ApiError("NOT_FOUND", "BOM not found", http_status=404)
|
|
|
|
|
return success_response(data=format_datetime_fields({"item": item}, request), request=request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.put("/business/{business_id}/{bom_id}")
|
|
|
|
|
@require_business_access("business_id")
|
|
|
|
|
def update_bom_endpoint(
|
|
|
|
|
request: Request,
|
|
|
|
|
business_id: int,
|
|
|
|
|
bom_id: int,
|
|
|
|
|
payload: ProductBOMUpdateRequest,
|
|
|
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
) -> Dict[str, Any]:
|
|
|
|
|
if not ctx.has_business_permission("inventory", "write"):
|
|
|
|
|
raise ApiError("FORBIDDEN", "Missing business permission: inventory.write", http_status=403)
|
|
|
|
|
result = update_bom(db, business_id, bom_id, payload)
|
|
|
|
|
if not result:
|
|
|
|
|
raise ApiError("NOT_FOUND", "BOM not found", http_status=404)
|
|
|
|
|
return success_response(data=format_datetime_fields(result["data"], request), request=request, message=result.get("message"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete("/business/{business_id}/{bom_id}")
|
|
|
|
|
@require_business_access("business_id")
|
|
|
|
|
def delete_bom_endpoint(
|
|
|
|
|
request: Request,
|
|
|
|
|
business_id: int,
|
|
|
|
|
bom_id: int,
|
|
|
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
) -> Dict[str, Any]:
|
|
|
|
|
if not ctx.has_business_permission("inventory", "delete"):
|
|
|
|
|
raise ApiError("FORBIDDEN", "Missing business permission: inventory.delete", http_status=403)
|
|
|
|
|
ok = delete_bom(db, business_id, bom_id)
|
|
|
|
|
return success_response({"deleted": ok}, request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/business/{business_id}/explode")
|
|
|
|
|
@require_business_access("business_id")
|
|
|
|
|
def explode_bom_endpoint(
|
|
|
|
|
request: Request,
|
|
|
|
|
business_id: int,
|
|
|
|
|
payload: BOMExplosionRequest,
|
|
|
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
) -> Dict[str, Any]:
|
|
|
|
|
if not ctx.can_read_section("inventory"):
|
|
|
|
|
raise ApiError("FORBIDDEN", "Missing business permission: inventory.read", http_status=403)
|
|
|
|
|
result = explode_bom(db, business_id, payload)
|
|
|
|
|
return success_response(data=format_datetime_fields(result, request), request=request)
|
2025-10-31 21:32:23 +03:30
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/business/{business_id}/produce_draft")
|
|
|
|
|
@require_business_access("business_id")
|
|
|
|
|
def produce_draft_endpoint(
|
|
|
|
|
request: Request,
|
|
|
|
|
business_id: int,
|
|
|
|
|
payload: ProductionDraftRequest,
|
|
|
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
|
|
|
db: Session = Depends(get_db),
|
|
|
|
|
) -> Dict[str, Any]:
|
|
|
|
|
if not ctx.has_business_permission("inventory", "write"):
|
|
|
|
|
raise ApiError("FORBIDDEN", "Missing business permission: inventory.write", http_status=403)
|
|
|
|
|
result = produce_draft(db, business_id, payload)
|
|
|
|
|
return success_response(data=format_datetime_fields(result, request), request=request)
|