152 lines
5.3 KiB
Python
152 lines
5.3 KiB
Python
"""商家罚款规格:解析、序列化、后台维护辅助。"""
|
|
from decimal import Decimal, InvalidOperation
|
|
|
|
from orders.models import PenaltySpec
|
|
|
|
|
|
def serialize_spec(spec):
|
|
return {
|
|
'id': spec.id,
|
|
'club_id': spec.ClubID or '',
|
|
'name': spec.Name or '',
|
|
'amount': float(spec.Amount or 0),
|
|
'amount_str': f'{Decimal(str(spec.Amount or 0)):.2f}',
|
|
'enabled': bool(spec.Enabled),
|
|
'sort_order': int(spec.SortOrder or 0),
|
|
'remark': spec.Remark or '',
|
|
'create_time': spec.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if spec.CreateTime else '',
|
|
'update_time': spec.UpdateTime.strftime('%Y-%m-%d %H:%M:%S') if spec.UpdateTime else '',
|
|
}
|
|
|
|
|
|
def list_enabled_specs(club_id):
|
|
club_id = (club_id or '').strip() or 'xq'
|
|
qs = (
|
|
PenaltySpec.objects
|
|
.filter(ClubID=club_id, Enabled=True)
|
|
.order_by('SortOrder', 'id')
|
|
)
|
|
return [serialize_spec(s) for s in qs]
|
|
|
|
|
|
def list_all_specs(club_id):
|
|
club_id = (club_id or '').strip() or 'xq'
|
|
qs = (
|
|
PenaltySpec.objects
|
|
.filter(ClubID=club_id)
|
|
.order_by('SortOrder', 'id')
|
|
)
|
|
return [serialize_spec(s) for s in qs]
|
|
|
|
|
|
def resolve_enabled_spec(club_id, spec_id):
|
|
"""
|
|
商家申请用:必须同俱乐部且启用。
|
|
成功返回 {'ok': True, 'spec': PenaltySpec, 'amount': Decimal, 'name': str}
|
|
"""
|
|
club_id = (club_id or '').strip() or 'xq'
|
|
if spec_id is None or spec_id == '':
|
|
return {'ok': False, 'code': 2, 'msg': '请选择罚款规格'}
|
|
try:
|
|
sid = int(spec_id)
|
|
except (TypeError, ValueError):
|
|
return {'ok': False, 'code': 2, 'msg': '罚款规格无效'}
|
|
try:
|
|
spec = PenaltySpec.objects.get(id=sid)
|
|
except PenaltySpec.DoesNotExist:
|
|
return {'ok': False, 'code': 2, 'msg': '罚款规格不存在'}
|
|
if (spec.ClubID or '').strip() != club_id:
|
|
return {'ok': False, 'code': 2, 'msg': '罚款规格不属于当前俱乐部'}
|
|
if not spec.Enabled:
|
|
return {'ok': False, 'code': 2, 'msg': '该罚款规格已停用,请重新选择'}
|
|
amount = Decimal(str(spec.Amount or 0))
|
|
if amount <= 0:
|
|
return {'ok': False, 'code': 2, 'msg': '罚款规格金额异常,请联系客服'}
|
|
return {
|
|
'ok': True,
|
|
'spec': spec,
|
|
'amount': amount,
|
|
'name': (spec.Name or '').strip()[:100],
|
|
'spec_id': spec.id,
|
|
}
|
|
|
|
|
|
def create_spec(club_id, name, amount, *, enabled=True, sort_order=0, remark=''):
|
|
club_id = (club_id or '').strip() or 'xq'
|
|
name = (name or '').strip()
|
|
if not name:
|
|
return {'ok': False, 'code': 400, 'msg': '规格名称不能为空'}
|
|
if len(name) > 100:
|
|
return {'ok': False, 'code': 400, 'msg': '规格名称最多100字'}
|
|
try:
|
|
amt = Decimal(str(amount))
|
|
if amt <= 0:
|
|
raise InvalidOperation
|
|
except (InvalidOperation, TypeError, ValueError):
|
|
return {'ok': False, 'code': 400, 'msg': '金额必须为正数'}
|
|
try:
|
|
sort_order = int(sort_order or 0)
|
|
except (TypeError, ValueError):
|
|
sort_order = 0
|
|
spec = PenaltySpec.objects.create(
|
|
ClubID=club_id[:16],
|
|
Name=name,
|
|
Amount=amt,
|
|
Enabled=bool(enabled),
|
|
SortOrder=sort_order,
|
|
Remark=(remark or '').strip()[:200],
|
|
)
|
|
return {'ok': True, 'code': 0, 'msg': '已创建', 'data': serialize_spec(spec)}
|
|
|
|
|
|
def update_spec(club_id, spec_id, *, name=None, amount=None, enabled=None, sort_order=None, remark=None):
|
|
club_id = (club_id or '').strip() or 'xq'
|
|
try:
|
|
sid = int(spec_id)
|
|
except (TypeError, ValueError):
|
|
return {'ok': False, 'code': 400, 'msg': '规格ID无效'}
|
|
try:
|
|
spec = PenaltySpec.objects.get(id=sid, ClubID=club_id)
|
|
except PenaltySpec.DoesNotExist:
|
|
return {'ok': False, 'code': 404, 'msg': '规格不存在'}
|
|
|
|
if name is not None:
|
|
name = str(name).strip()
|
|
if not name:
|
|
return {'ok': False, 'code': 400, 'msg': '规格名称不能为空'}
|
|
if len(name) > 100:
|
|
return {'ok': False, 'code': 400, 'msg': '规格名称最多100字'}
|
|
spec.Name = name
|
|
if amount is not None:
|
|
try:
|
|
amt = Decimal(str(amount))
|
|
if amt <= 0:
|
|
raise InvalidOperation
|
|
except (InvalidOperation, TypeError, ValueError):
|
|
return {'ok': False, 'code': 400, 'msg': '金额必须为正数'}
|
|
spec.Amount = amt
|
|
if enabled is not None:
|
|
spec.Enabled = bool(enabled)
|
|
if sort_order is not None:
|
|
try:
|
|
spec.SortOrder = int(sort_order)
|
|
except (TypeError, ValueError):
|
|
return {'ok': False, 'code': 400, 'msg': '排序须为整数'}
|
|
if remark is not None:
|
|
spec.Remark = str(remark).strip()[:200]
|
|
spec.save()
|
|
return {'ok': True, 'code': 0, 'msg': '已更新', 'data': serialize_spec(spec)}
|
|
|
|
|
|
def delete_spec(club_id, spec_id):
|
|
"""物理删除规格;已生成罚单仍保留快照,不受影响。"""
|
|
club_id = (club_id or '').strip() or 'xq'
|
|
try:
|
|
sid = int(spec_id)
|
|
except (TypeError, ValueError):
|
|
return {'ok': False, 'code': 400, 'msg': '规格ID无效'}
|
|
deleted, _ = PenaltySpec.objects.filter(id=sid, ClubID=club_id).delete()
|
|
if not deleted:
|
|
return {'ok': False, 'code': 404, 'msg': '规格不存在'}
|
|
return {'ok': True, 'code': 0, 'msg': '已删除'}
|