Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/adapters/api/v1/warehouse_locations.py
2026-04-25 02:31:13 +03:30

174 lines
6.9 KiB
Python
Executable file

from typing import Dict, Any, Optional
from fastapi import APIRouter, Depends, Request, Body, Query
from sqlalchemy.orm import Session
from adapters.db.session import get_db
from adapters.db.models.warehouse import Warehouse
from app.core.auth_dependency import get_current_user, AuthContext
from app.core.permissions import require_business_access, require_business_permission_by_entity_dep
from app.core.responses import success_response, ApiError, format_datetime_fields
from adapters.api.v1.schema_models.warehouse_location import (
WarehouseLocationCreateRequest,
WarehouseLocationUpdateRequest,
WarehousePlacementCreateRequest,
WarehousePlacementUpdateRequest,
)
from app.services.warehouse_location_service import (
list_locations_tree,
create_location,
update_location,
delete_location,
list_placements,
create_placement,
update_placement,
delete_placement,
)
from app.services.warehouse_placement_sync import placement_reconciliation_for_warehouse
router = APIRouter(prefix="/warehouses", tags=["چیدمان انبار"])
@router.get("/business/{business_id}/{warehouse_id}/locations")
@require_business_access("business_id")
def list_locations_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "view", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
data = list_locations_tree(db, business_id, warehouse_id)
return success_response(data=data, request=request)
@router.post("/business/{business_id}/{warehouse_id}/locations")
@require_business_access("business_id")
def create_location_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
payload: WarehouseLocationCreateRequest = Body(...),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "add", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
result = create_location(db, business_id, warehouse_id, payload.model_dump(exclude_unset=True))
return success_response(data=format_datetime_fields(result, request), request=request)
@router.put("/business/{business_id}/{warehouse_id}/locations/{location_id}")
@require_business_access("business_id")
def update_location_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
location_id: int,
payload: WarehouseLocationUpdateRequest = Body(...),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "edit", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
result = update_location(db, business_id, warehouse_id, location_id, payload.model_dump(exclude_unset=True))
if not result:
raise ApiError("NOT_FOUND", "محل یافت نشد", http_status=404)
return success_response(data=format_datetime_fields(result, request), request=request)
@router.delete("/business/{business_id}/{warehouse_id}/locations/{location_id}")
@require_business_access("business_id")
def delete_location_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
location_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "delete", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
ok = delete_location(db, business_id, warehouse_id, location_id)
return success_response({"deleted": ok}, request=request)
@router.get("/business/{business_id}/{warehouse_id}/placement-reconciliation")
@require_business_access("business_id")
def placement_reconciliation_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
as_of_date: Optional[str] = Query(None),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "view", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
"""مجموع قرارگیری‌های ثبت‌شده در مقابل موجودی حسابداری (کالاهایی که حداقل یک رکورد قرارگیری دارند)."""
data = placement_reconciliation_for_warehouse(
db, business_id, warehouse_id, as_of_date=as_of_date
)
return success_response(data=data, request=request)
@router.get("/business/{business_id}/{warehouse_id}/placements")
@require_business_access("business_id")
def list_placements_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
product_id: Optional[int] = Query(None),
location_id: Optional[int] = Query(None),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "view", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
data = list_placements(db, business_id, warehouse_id, product_id=product_id, location_id=location_id)
return success_response(data=data, request=request)
@router.post("/business/{business_id}/{warehouse_id}/placements")
@require_business_access("business_id")
def create_placement_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
payload: WarehousePlacementCreateRequest = Body(...),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "edit", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
result = create_placement(db, business_id, warehouse_id, payload.model_dump(exclude_unset=True))
return success_response(data=format_datetime_fields(result, request), request=request)
@router.put("/business/{business_id}/{warehouse_id}/placements/{placement_id}")
@require_business_access("business_id")
def update_placement_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
placement_id: int,
payload: WarehousePlacementUpdateRequest = Body(...),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "edit", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
result = update_placement(db, business_id, warehouse_id, placement_id, payload.model_dump(exclude_unset=True))
if not result:
raise ApiError("NOT_FOUND", "رکورد قرارگیری یافت نشد", http_status=404)
return success_response(data=format_datetime_fields(result, request), request=request)
@router.delete("/business/{business_id}/{warehouse_id}/placements/{placement_id}")
@require_business_access("business_id")
def delete_placement_endpoint(
request: Request,
business_id: int,
warehouse_id: int,
placement_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_by_entity_dep("warehouses", "edit", Warehouse, "warehouse_id")),
) -> Dict[str, Any]:
ok = delete_placement(db, business_id, warehouse_id, placement_id)
return success_response({"deleted": ok}, request=request)