from fastapi import APIRouter, Depends, HTTPException, Query, Request from typing import List, Optional import db import schemas from dependencies import require_admin import services.event_hooks as event_hooks from services.audit_service import audit_service from services.warehouse_report_service import warehouse_report_service router = APIRouter(prefix="/admin/warehouse", tags=["warehouse"]) @router.get("/report") async def generate_stock_report( admin: dict = Depends(require_admin) ): url = warehouse_report_service.generate_report() return {"url": url} @router.get("/stock", response_model=dict) async def get_warehouse_stock( page: int = Query(1, ge=1), size: int = Query(50, ge=1, le=100), material_id: Optional[int] = None, admin: dict = Depends(require_admin) ): offset = (page - 1) * size query = """ SELECT w.*, m.name_en as material_name_en FROM warehouse_stock w JOIN materials m ON w.material_id = m.id """ params = [] if material_id: query += " WHERE w.material_id = %s" params.append(material_id) query += " ORDER BY w.created_at DESC LIMIT %s OFFSET %s" params.extend([size, offset]) stock = db.execute_query(query, tuple(params)) count_query = "SELECT COUNT(*) as total FROM warehouse_stock" if material_id: count_query += " WHERE material_id = %s" total_res = db.execute_query(count_query, (material_id,)) else: total_res = db.execute_query(count_query) return { "stock": stock, "total": total_res[0]['total'] if total_res else 0, "page": page, "size": size } @router.post("/stock", response_model=dict) async def add_stock_item( request: Request, data: schemas.WarehouseItemCreate, admin: dict = Depends(require_admin) ): query = """ INSERT INTO warehouse_stock (material_id, color_name, quantity, unit_mass, units_count, notes, is_active) VALUES (%s, %s, %s, %s, %s, %s, %s) """ params = (data.material_id, data.color_name, data.quantity, data.unit_mass, data.units_count, data.notes, data.is_active) item_id = db.execute_commit(query, params) if not item_id: raise HTTPException(status_code=500, detail="Failed to add stock item") await audit_service.log( user_id=admin['id'], action="warehouse_add_item", target_type="warehouse_stock", target_id=item_id, details={ "material_id": data.material_id, "color": data.color_name, "quantity": data.quantity, "units_count": data.units_count }, request=request ) return {"id": item_id, "message": "Stock item added successfully"} @router.patch("/stock/{item_id}", response_model=dict) async def update_stock_item( item_id: int, request: Request, data: schemas.WarehouseItemUpdate, admin: dict = Depends(require_admin) ): update_fields = [] params = [] if data.quantity is not None: update_fields.append("quantity = %s") params.append(data.quantity) if data.unit_mass is not None: update_fields.append("unit_mass = %s") params.append(data.unit_mass) if data.units_count is not None: update_fields.append("units_count = %s") params.append(data.units_count) if data.notes is not None: update_fields.append("notes = %s") params.append(data.notes) if data.is_active is not None: update_fields.append("is_active = %s") params.append(data.is_active) if not update_fields: raise HTTPException(status_code=400, detail="No fields to update") query = f"UPDATE warehouse_stock SET {', '.join(update_fields)} WHERE id = %s" params.append(item_id) db.execute_commit(query, tuple(params)) await audit_service.log( user_id=admin['id'], action="warehouse_update_item", target_type="warehouse_stock", target_id=item_id, details=data.model_dump(exclude_unset=True), request=request ) return {"message": "Stock item updated successfully"} @router.delete("/stock/{item_id}", response_model=dict) async def delete_stock_item( item_id: int, request: Request, admin: dict = Depends(require_admin) ): # Fetch item before deleting for logs item = db.execute_query("SELECT material_id, color_name FROM warehouse_stock WHERE id = %s", (item_id,)) query = "DELETE FROM warehouse_stock WHERE id = %s" db.execute_commit(query, (item_id,)) if item: await audit_service.log( user_id=admin['id'], action="warehouse_delete_item", target_type="warehouse_stock", target_id=item_id, details=item[0], request=request ) return {"message": "Stock item deleted successfully"}