from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import Session from backend.app.core.error_codes import ErrorCode from backend.app.core.exceptions import AppException from backend.app.repositories.product_repository import ProductRepository class ProductService: def __init__(self) -> None: self.repository = ProductRepository() def list_categories(self, session: Session | None = None, filters: dict | None = None) -> dict: if session is not None: try: categories = self.repository.list_categories(session, filters or {}) return { "total": len(categories), "page_no": 1, "page_size": len(categories) or 20, "list": [ { "category_id": category.id, "category_name": category.category_name, "category_code": category.category_code, "sort_no": category.sort_no, "status": category.status, "remark": category.remark, } for category in categories ], } except SQLAlchemyError: pass return { "total": 2, "page_no": 1, "page_size": 20, "list": [ {"category_id": 1, "category_name": "工业品", "category_code": "industry", "status": 1}, {"category_id": 2, "category_name": "日用品", "category_code": "daily", "status": 1}, ], } def create_category(self, payload: dict, session: Session | None = None) -> dict: if session is not None: try: if not payload["category_name"].strip(): raise AppException(code=ErrorCode.PARAM_ERROR, message="分类名称不能为空", status_code=400) if not payload["category_code"].strip(): raise AppException(code=ErrorCode.PARAM_ERROR, message="分类编码不能为空", status_code=400) existed = self.repository.get_category_by_code(session, payload["category_code"]) if existed is not None: raise AppException(code=ErrorCode.DUPLICATE, message="分类编码已存在", status_code=400) category = self.repository.create_category(session, payload) session.commit() return { "category_id": category.id, "category_name": category.category_name, "category_code": category.category_code, "status": category.status, } except AppException: session.rollback() raise except SQLAlchemyError: session.rollback() return { "category_id": 3, "category_name": payload["category_name"], "category_code": payload["category_code"], "status": payload.get("status", 1), } def update_category(self, category_id: int, payload: dict, session: Session | None = None) -> dict: if session is not None: try: if not payload["category_name"].strip(): raise AppException(code=ErrorCode.PARAM_ERROR, message="分类名称不能为空", status_code=400) if not payload["category_code"].strip(): raise AppException(code=ErrorCode.PARAM_ERROR, message="分类编码不能为空", status_code=400) category = self.repository.get_category(session, category_id) if category is None: raise AppException(code=ErrorCode.NOT_FOUND, message="产品分类不存在", status_code=404) existed = self.repository.get_category_by_code(session, payload["category_code"]) if existed is not None and existed.id != category_id: raise AppException(code=ErrorCode.DUPLICATE, message="分类编码已存在", status_code=400) self.repository.update_category(session, category, payload) session.commit() return {"category_id": category_id, "updated": True} except AppException: session.rollback() raise except SQLAlchemyError: session.rollback() return {"category_id": category_id, "updated": True} def list_products(self, filters: dict | None = None, session: Session | None = None) -> dict: if session is not None: try: products = self.repository.list_products(session, filters or {}) categories = { category.id: category for category in self.repository.list_categories(session, {}) } return { "total": len(products), "page_no": 1, "page_size": len(products) or 20, "list": [ { "product_id": product.id, "product_name": product.product_name, "specification": product.specification, "unit": product.unit, "category_id": product.category_id, "category_name": categories[product.category_id].category_name if product.category_id in categories else (product.category or ""), "cost_price": float(product.cost_price or 0), "sale_price": float(product.sale_price or 0), "status": product.status, "remark": product.remark, } for product in products ], } except SQLAlchemyError: pass product_list = [ { "product_id": 2001, "product_name": "演示产品A", "specification": "10kg", "unit": "吨", "category_id": 1, "category_name": "工业品", "cost_price": 60, "sale_price": 100, "status": 1, }, { "product_id": 2002, "product_name": "演示产品B", "specification": "20kg", "unit": "吨", "category_id": 1, "category_name": "工业品", "cost_price": 120, "sale_price": 180, "status": 1, }, ] if filters and filters.get("product_name"): product_list = [item for item in product_list if filters["product_name"] in item["product_name"]] return { "total": len(product_list), "page_no": 1, "page_size": 20, "list": product_list, } def create_product(self, payload: dict, session: Session | None = None) -> dict: if session is not None: try: if not payload["product_name"].strip(): raise AppException(code=ErrorCode.PARAM_ERROR, message="产品名称不能为空", status_code=400) if not payload["specification"].strip(): raise AppException(code=ErrorCode.PARAM_ERROR, message="产品规格不能为空", status_code=400) if not payload["unit"].strip(): raise AppException(code=ErrorCode.PARAM_ERROR, message="产品单位不能为空", status_code=400) existed = self.repository.get_product_by_name_and_specification( session, payload["product_name"], payload["specification"], ) if existed is not None: raise AppException(code=ErrorCode.DUPLICATE, message="产品已存在", status_code=400) category = None if payload.get("category_id") is not None: category = self.repository.get_category(session, payload["category_id"]) if category is None or category.status != 1: raise AppException(code=ErrorCode.NOT_FOUND, message="产品分类不存在或已停用", status_code=404) product = self.repository.create_product( session, { **payload, "category": category.category_name if category else None, }, ) session.commit() return { "product_id": product.id, "product_name": product.product_name, "specification": product.specification, "unit": product.unit, "category_id": product.category_id, "status": product.status, } except AppException: session.rollback() raise except SQLAlchemyError: session.rollback() return { "product_id": 2003, "product_name": payload["product_name"], "specification": payload["specification"], "unit": payload["unit"], "status": payload.get("status", 1), } def get_product(self, product_id: int, session: Session | None = None) -> dict: if session is not None: try: product = self.repository.get_product(session, product_id) if product is not None: category_name = product.category or "" if product.category_id is not None: category = self.repository.get_category(session, product.category_id) if category is not None: category_name = category.category_name return { "product_id": product.id, "product_name": product.product_name, "specification": product.specification, "unit": product.unit, "category_id": product.category_id, "category_name": category_name, "cost_price": float(product.cost_price or 0), "sale_price": float(product.sale_price or 0), "status": product.status, "remark": product.remark, } except SQLAlchemyError: pass return { "product_id": product_id, "product_name": "演示产品A", "specification": "10kg", "unit": "吨", "category_id": 1, "category_name": "工业品", "cost_price": 60, "sale_price": 100, "status": 1, } product_service = ProductService()