hesabixArc/hesabixAPI/adapters/api/v1/warehouse_docs.py
2025-11-09 05:16:37 +00:00

116 lines
4.5 KiB
Python

from typing import Dict, Any
from fastapi import APIRouter, Depends, Request, Body
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
from adapters.db.models.document import Document
from adapters.db.models.warehouse_document import WarehouseDocument
from adapters.db.models.warehouse_document_line import WarehouseDocumentLine
from app.services.warehouse_service import create_from_invoice, post_warehouse_document, warehouse_document_to_dict
router = APIRouter(prefix="/warehouse-docs", tags=["warehouse_docs"])
@router.post("/business/{business_id}/from-invoice/{invoice_id}")
@require_business_access("business_id")
def create_warehouse_doc_from_invoice(
request: Request,
business_id: int,
invoice_id: int,
payload: Dict[str, Any] = Body(default={}),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
) -> Dict[str, Any]:
inv = db.query(Document).filter(Document.id == invoice_id).first()
if not inv or inv.business_id != business_id:
from app.core.responses import ApiError
raise ApiError("DOCUMENT_NOT_FOUND", "Invoice document not found", http_status=404)
lines = payload.get("lines") or []
wh_type = payload.get("doc_type") or ("issue" if inv.document_type in ("invoice_sales", "invoice_purchase_return", "invoice_waste", "invoice_direct_consumption") else "receipt")
wh = create_from_invoice(db, business_id, inv, lines, wh_type, ctx.get_user_id())
db.commit()
return success_response(data={"id": wh.id, "code": wh.code, "status": wh.status}, request=request)
@router.post("/business/{business_id}/{wh_id}/post")
@require_business_access("business_id")
def post_warehouse_doc_endpoint(
request: Request,
business_id: int,
wh_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
) -> Dict[str, Any]:
res = post_warehouse_document(db, wh_id)
db.commit()
return success_response(data=res, request=request)
@router.get("/business/{business_id}/{wh_id}")
@require_business_access("business_id")
def get_warehouse_doc(
request: Request,
business_id: int,
wh_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
) -> Dict[str, Any]:
wh = db.query(WarehouseDocument).filter(WarehouseDocument.id == wh_id).first()
if not wh or wh.business_id != business_id:
from app.core.responses import ApiError
raise ApiError("NOT_FOUND", "Warehouse document not found", http_status=404)
return success_response(data={"item": warehouse_document_to_dict(db, wh)}, request=request)
@router.post("/business/{business_id}/search")
@require_business_access("business_id")
def search_warehouse_docs(
request: Request,
business_id: int,
body: Dict[str, Any] = Body(default={}),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
) -> Dict[str, Any]:
q = db.query(WarehouseDocument).filter(WarehouseDocument.business_id == business_id)
# فیلتر ساده بر اساس نوع/وضعیت/تاریخ
doc_type = body.get("doc_type")
status = body.get("status")
source_document_id = body.get("source_document_id")
source_type = body.get("source_type")
from_date = body.get("from_date")
to_date = body.get("to_date")
try:
if isinstance(doc_type, str) and doc_type:
q = q.filter(WarehouseDocument.doc_type == doc_type)
if isinstance(status, str) and status:
q = q.filter(WarehouseDocument.status == status)
if isinstance(source_document_id, int):
q = q.filter(WarehouseDocument.source_document_id == source_document_id)
if isinstance(source_type, str) and source_type:
q = q.filter(WarehouseDocument.source_type == source_type)
if isinstance(from_date, str) and from_date:
from app.services.transfer_service import _parse_iso_date as _p
q = q.filter(WarehouseDocument.document_date >= _p(from_date))
if isinstance(to_date, str) and to_date:
from app.services.transfer_service import _parse_iso_date as _p
q = q.filter(WarehouseDocument.document_date <= _p(to_date))
except Exception:
pass
q = q.order_by(WarehouseDocument.document_date.desc(), WarehouseDocument.id.desc())
take = int(body.get("take") or 20)
skip = int(body.get("skip") or 0)
total = q.count()
items = q.offset(skip).limit(take).all()
return success_response(data={
"items": [warehouse_document_to_dict(db, wh) for wh in items],
"total": total,
"page": (skip // max(1, take)) + 1,
"limit": take,
}, request=request)