| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- from fastapi import APIRouter, Depends, HTTPException
- from typing import List, Optional
- import db
- import schemas
- import auth_utils
- import json
- from dependencies import require_admin
- from services.audit_service import audit_service
- router = APIRouter(tags=["catalog"])
- @router.get("/materials", response_model=List[schemas.MaterialBase])
- async def get_materials():
- # Get active materials
- materials = db.execute_query("SELECT * FROM materials WHERE is_active = TRUE")
-
- # Get active stock
- stock = db.execute_query("SELECT material_id, color_name FROM warehouse_stock WHERE is_active = TRUE")
-
- # Map colors to materials
- color_map = {}
- for s in stock:
- m_id = s['material_id']
- if m_id not in color_map:
- color_map[m_id] = []
- color_map[m_id].append(s['color_name'])
-
- # Filter and attach colors
- result = []
- for m in materials:
- m['available_colors'] = color_map.get(m['id'], [])
- # Only show on site if there are available colors in warehouse
- if m['available_colors']:
- result.append(m)
-
- return result
- @router.get("/services", response_model=List[schemas.ServiceBase])
- async def get_services():
- return db.execute_query("SELECT * FROM services WHERE is_active = TRUE")
- @router.get("/admin/materials", response_model=List[schemas.MaterialBase])
- async def admin_get_materials(admin: dict = Depends(require_admin)):
- # Get all materials
- materials = db.execute_query("SELECT * FROM materials ORDER BY id DESC")
-
- # Get stock (including inactive for admin)
- stock = db.execute_query("SELECT material_id, color_name FROM warehouse_stock")
-
- color_map = {}
- for s in stock:
- m_id = s['material_id']
- if m_id not in color_map:
- color_map[m_id] = []
- color_map[m_id].append(s['color_name'])
-
- for m in materials:
- # Merge warehouse colors with any legacy colors in available_colors
- legacy_colors = []
- if m.get('available_colors') and isinstance(m['available_colors'], str):
- try: legacy_colors = json.loads(m['available_colors'])
- except: pass
-
- # Priority to warehouse colors
- warehouse_colors = color_map.get(m['id'], [])
- # Combine them (unique)
- m['available_colors'] = list(set(warehouse_colors + (legacy_colors or [])))
-
- return materials
- @router.post("/admin/materials")
- async def admin_create_material(data: schemas.MaterialCreate, admin: dict = Depends(require_admin)):
- colors_json = json.dumps(data.available_colors) if data.available_colors else None
- query = "INSERT INTO materials (name_en, name_ru, name_ua, name_me, desc_en, desc_ru, desc_ua, desc_me, long_desc_en, long_desc_ru, long_desc_ua, long_desc_me, price_per_cm3, available_colors, is_active) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
- params = (data.name_en, data.name_ru, data.name_ua, data.name_me, data.desc_en, data.desc_ru, data.desc_ua, data.desc_me, data.long_desc_en, data.long_desc_ru, data.long_desc_ua, data.long_desc_me, data.price_per_cm3, colors_json, data.is_active)
- mat_id = db.execute_commit(query, params)
-
- await audit_service.log(
- user_id=admin.get("id"),
- action="create_material",
- target_type="material",
- target_id=mat_id,
- details=data.dict()
- )
- return {"id": mat_id}
- @router.patch("/admin/materials/{mat_id}")
- async def admin_update_material(mat_id: int, data: schemas.MaterialUpdate, admin: dict = Depends(require_admin)):
- update_fields = []
- params = []
- for field, value in data.dict(exclude_unset=True).items():
- update_fields.append(f"{field} = %s")
- if isinstance(value, list):
- params.append(json.dumps(value))
- else:
- params.append(value)
- if update_fields:
- query = f"UPDATE materials SET {', '.join(update_fields)} WHERE id = %s"
- params.append(mat_id)
- db.execute_commit(query, tuple(params))
-
- await audit_service.log(
- user_id=admin.get("id"),
- action="update_material",
- target_type="material",
- target_id=mat_id,
- details={"updated_fields": data.dict(exclude_unset=True)}
- )
- return {"id": mat_id}
- @router.get("/admin/services", response_model=List[schemas.ServiceBase])
- async def admin_get_services(admin: dict = Depends(require_admin)):
- return db.execute_query("SELECT * FROM services ORDER BY id DESC")
- @router.post("/admin/services")
- async def admin_create_service(data: schemas.ServiceCreate, admin: dict = Depends(require_admin)):
- query = "INSERT INTO services (name_en, name_ru, name_ua, name_me, desc_en, desc_ru, desc_ua, desc_me, tech_type, is_active) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
- srv_id = db.execute_commit(query, (data.name_en, data.name_ru, data.name_ua, data.name_me, data.desc_en, data.desc_ru, data.desc_ua, data.desc_me, data.tech_type, data.is_active))
-
- await audit_service.log(
- user_id=admin.get("id"),
- action="create_service",
- target_type="service",
- target_id=srv_id,
- details=data.dict()
- )
- return {"id": srv_id}
- @router.patch("/admin/services/{srv_id}")
- async def admin_update_service(srv_id: int, data: schemas.ServiceUpdate, admin: dict = Depends(require_admin)):
- update_fields = []
- params = []
- for field, value in data.dict(exclude_unset=True).items():
- update_fields.append(f"{field} = %s")
- if isinstance(value, list):
- params.append(json.dumps(value))
- else:
- params.append(value)
- if update_fields:
- query = f"UPDATE services SET {', '.join(update_fields)} WHERE id = %s"
- params.append(srv_id)
- db.execute_commit(query, tuple(params))
-
- await audit_service.log(
- user_id=admin.get("id"),
- action="update_service",
- target_type="service",
- target_id=srv_id,
- details={"updated_fields": data.dict(exclude_unset=True)}
- )
- return {"id": srv_id}
- @router.delete("/admin/materials/{mat_id}")
- async def admin_delete_material(mat_id: int, admin: dict = Depends(require_admin)):
- db.execute_commit("DELETE FROM materials WHERE id = %s", (mat_id,))
- await audit_service.log(
- user_id=admin.get("id"),
- action="delete_material",
- target_type="material",
- target_id=mat_id
- )
- return {"id": mat_id, "status": "deleted"}
- @router.delete("/admin/services/{srv_id}")
- async def admin_delete_service(srv_id: int, admin: dict = Depends(require_admin)):
- db.execute_commit("DELETE FROM services WHERE id = %s", (srv_id,))
- await audit_service.log(
- user_id=admin.get("id"),
- action="delete_service",
- target_type="service",
- target_id=srv_id
- )
- return {"id": srv_id, "status": "deleted"}
|