262 lines
11 KiB
Python
262 lines
11 KiB
Python
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()
|