127 lines
4.5 KiB
Python
127 lines
4.5 KiB
Python
from app import db
|
||
from app.models.inbound.service import StockService
|
||
from app.models.material_base import MaterialBase
|
||
from datetime import datetime, timedelta
|
||
import re
|
||
|
||
|
||
class ServiceService:
|
||
"""服务权益库存业务逻辑"""
|
||
|
||
SKU_PREFIX = 'SRV'
|
||
SKU_DATE_FORMAT = '%Y%m%d'
|
||
SKU_SUFFIX_LEN = 4
|
||
|
||
@classmethod
|
||
def _generate_sku(cls):
|
||
"""生成唯一SKU,格式 SRV-YYYYMMDD-XXXX"""
|
||
today_str = datetime.now().strftime(cls.SKU_DATE_FORMAT)
|
||
prefix = f'{cls.SKU_PREFIX}-{today_str}-'
|
||
# 查找今天已有的最大后缀
|
||
max_sku = db.session.query(db.func.max(StockService.sku)).filter(
|
||
StockService.sku.like(f'{prefix}%')
|
||
).scalar()
|
||
if not max_sku:
|
||
suffix_num = 1
|
||
else:
|
||
# 提取后缀数字
|
||
suffix_part = max_sku.replace(prefix, '')
|
||
match = re.match(r'^(\d+)', suffix_part)
|
||
suffix_num = int(match.group(1)) if match else 0
|
||
suffix_num += 1
|
||
# 格式化为4位数字,左侧补零
|
||
suffix = str(suffix_num).zfill(cls.SKU_SUFFIX_LEN)
|
||
return f'{prefix}{suffix}'
|
||
|
||
@classmethod
|
||
def create_service(cls, data):
|
||
"""创建服务权益记录"""
|
||
# 检查基础物料是否存在
|
||
base = MaterialBase.query.get(data.get('base_id'))
|
||
if not base:
|
||
raise ValueError('基础物料不存在')
|
||
# 生成SKU
|
||
sku = cls._generate_sku()
|
||
service = StockService(
|
||
base_id=data['base_id'],
|
||
sku=sku,
|
||
sale_price=data['sale_price'],
|
||
provider_name=data['provider_name'],
|
||
description=data.get('description', '')
|
||
)
|
||
db.session.add(service)
|
||
db.session.commit()
|
||
return service
|
||
|
||
@classmethod
|
||
def get_service(cls, service_id):
|
||
"""获取单个服务权益"""
|
||
service = StockService.query.filter_by(id=service_id, is_deleted=False).first()
|
||
if not service:
|
||
raise ValueError('服务权益记录不存在')
|
||
return service
|
||
|
||
@classmethod
|
||
def update_service(cls, service_id, data):
|
||
"""更新服务权益记录"""
|
||
service = cls.get_service(service_id)
|
||
# 不允许修改 base_id 和 sku(业务上不允许变更基础物料)
|
||
if 'sale_price' in data:
|
||
service.sale_price = data['sale_price']
|
||
if 'provider_name' in data:
|
||
service.provider_name = data['provider_name']
|
||
if 'description' in data:
|
||
service.description = data.get('description', '')
|
||
service.updated_at = datetime.now()
|
||
db.session.commit()
|
||
return service
|
||
|
||
@classmethod
|
||
def delete_service(cls, service_id):
|
||
"""软删除服务权益"""
|
||
service = cls.get_service(service_id)
|
||
service.is_deleted = True
|
||
service.updated_at = datetime.now()
|
||
db.session.commit()
|
||
return True
|
||
|
||
@classmethod
|
||
def get_service_list(cls, page=1, per_page=20, keyword=None,
|
||
start_date=None, end_date=None, provider_name=None):
|
||
"""分页查询服务权益列表"""
|
||
query = StockService.query.filter_by(is_deleted=False)
|
||
# 关键词搜索:可搜索 SKU 或 关联物料名称
|
||
if keyword:
|
||
# 子查询查找物料名称匹配的 base_id
|
||
subquery = MaterialBase.query.filter(
|
||
MaterialBase.name.ilike(f'%{keyword}%')
|
||
).subquery()
|
||
query = query.filter(
|
||
db.or_(
|
||
StockService.sku.ilike(f'%{keyword}%'),
|
||
StockService.base_id.in_([row.id for row in db.session.query(subquery.c.id)])
|
||
)
|
||
)
|
||
if start_date:
|
||
start = datetime.strptime(start_date, '%Y-%m-%d')
|
||
query = query.filter(StockService.created_at >= start)
|
||
if end_date:
|
||
end = datetime.strptime(end_date, '%Y-%m-%d')
|
||
# 包含当天
|
||
end = end + timedelta(days=1) - timedelta(seconds=1)
|
||
query = query.filter(StockService.created_at <= end)
|
||
if provider_name:
|
||
query = query.filter(StockService.provider_name.ilike(f'%{provider_name}%'))
|
||
# 总数
|
||
total = query.count()
|
||
# 分页
|
||
items = query.order_by(StockService.created_at.desc())\
|
||
.offset((page - 1) * per_page)\
|
||
.limit(per_page).all()
|
||
return {
|
||
'items': [item.to_dict() for item in items],
|
||
'total': total,
|
||
'page': page,
|
||
'per_page': per_page
|
||
}
|