fix: 组队仅队长提交修改,组员可见交付;罚单聚合改撤联动
详情返回 can_submit/can_modify;交付图按订单聚合;组队均摊罚单展示总额并联动修改/撤销;罚单 ClubID 归属订单店。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -385,9 +385,23 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
dingdan.save()
|
||||
return Response({'code': 0, 'msg': '退款理由修改成功'})
|
||||
|
||||
def _team_split_siblings(self, fadan, *, include_rejected=False):
|
||||
"""同订单组队均摊罚单;非均摊则只返回自身。"""
|
||||
from orders.services.team_recruit import list_team_split_penalties
|
||||
reason = fadan.Reason or ''
|
||||
if reason.startswith('【组队均摊】') and fadan.RelatedOrderID:
|
||||
sibs = list_team_split_penalties(
|
||||
fadan.RelatedOrderID, include_rejected=include_rejected,
|
||||
)
|
||||
if sibs:
|
||||
return sibs
|
||||
return [fadan]
|
||||
|
||||
def _modify_penalty(self, fadan, liyou, jine_str, processor_id=None):
|
||||
"""修改罚款(待缴纳 / 申诉中 / 平台审核中)"""
|
||||
"""修改罚款(待缴纳 / 申诉中 / 平台审核中);组队均摊联动改总额并重分。"""
|
||||
from utils.penalty_status import PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT
|
||||
from orders.services.team_recruit import _d, MONEY
|
||||
from decimal import ROUND_DOWN
|
||||
if fadan.Status not in (PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT):
|
||||
return Response({'code': 400, 'msg': '当前罚单状态不可修改'})
|
||||
if not liyou.strip():
|
||||
@@ -396,37 +410,70 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
jine = Decimal(jine_str)
|
||||
if jine <= 0:
|
||||
raise ValueError
|
||||
except:
|
||||
except Exception:
|
||||
return Response({'code': 400, 'msg': '罚款金额必须为正数'})
|
||||
siblings = self._team_split_siblings(fadan, include_rejected=False)
|
||||
for s in siblings:
|
||||
if s.Status not in (PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT):
|
||||
return Response({'code': 400, 'msg': '组队均摊罚单状态不一致,无法修改'})
|
||||
reason_text = liyou[:500]
|
||||
if (fadan.Reason or '').startswith('【组队均摊】') and not reason_text.startswith('【组队均摊】'):
|
||||
reason_text = f'【组队均摊】{reason_text}'
|
||||
with transaction.atomic():
|
||||
fadan.Reason = liyou[:500]
|
||||
fadan.FineAmount = jine
|
||||
if processor_id:
|
||||
fadan.ProcessorID = processor_id
|
||||
fadan.ProcessorIdentity = 5 # 小程序商家自行处理
|
||||
fadan.save()
|
||||
lock_penalty_bonus(fadan)
|
||||
k = len(siblings)
|
||||
if k > 1:
|
||||
total = _d(jine)
|
||||
base = (total / Decimal(k)).quantize(MONEY, rounding=ROUND_DOWN)
|
||||
amounts = [base] * k
|
||||
amounts[0] = _d(total - base * (k - 1))
|
||||
# 队长优先(与创建时一致)
|
||||
siblings = sorted(
|
||||
siblings,
|
||||
key=lambda p: 0 if p.id == fadan.id else 1,
|
||||
)
|
||||
for i, s in enumerate(siblings):
|
||||
s.Reason = reason_text
|
||||
s.FineAmount = amounts[i]
|
||||
if processor_id:
|
||||
s.ProcessorID = processor_id
|
||||
s.ProcessorIdentity = 5
|
||||
s.save()
|
||||
lock_penalty_bonus(s)
|
||||
else:
|
||||
fadan.Reason = reason_text
|
||||
fadan.FineAmount = jine
|
||||
if processor_id:
|
||||
fadan.ProcessorID = processor_id
|
||||
fadan.ProcessorIdentity = 5
|
||||
fadan.save()
|
||||
lock_penalty_bonus(fadan)
|
||||
return Response({'code': 0, 'msg': '罚款修改成功'})
|
||||
|
||||
def _cancel_penalty(self, fadan, liyou, processor_id=None):
|
||||
"""撤销罚款(待缴纳 / 申诉中 / 平台审核中 → 已驳回)"""
|
||||
"""撤销罚款;组队均摊一并驳回,避免只撤一张仍挡抢单。"""
|
||||
from utils.penalty_status import PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT, PENALTY_REJECTED
|
||||
if fadan.Status not in (PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT):
|
||||
return Response({'code': 400, 'msg': '当前罚单状态不可撤销'})
|
||||
if not liyou.strip():
|
||||
return Response({'code': 400, 'msg': '驳回理由不能为空'})
|
||||
siblings = self._team_split_siblings(fadan, include_rejected=False)
|
||||
with transaction.atomic():
|
||||
fadan.Status = PENALTY_REJECTED # 已驳回
|
||||
fadan.RejectReason = liyou[:500]
|
||||
if processor_id:
|
||||
fadan.ProcessorID = processor_id
|
||||
fadan.ProcessorIdentity = 5 # 小程序商家撤销=商家作为处理人
|
||||
fadan.save()
|
||||
for s in siblings:
|
||||
if s.Status not in (PENALTY_PENDING_PAY, PENALTY_APPEALING, PENALTY_PLATFORM_AUDIT):
|
||||
continue
|
||||
s.Status = PENALTY_REJECTED
|
||||
s.RejectReason = liyou[:500]
|
||||
if processor_id:
|
||||
s.ProcessorID = processor_id
|
||||
s.ProcessorIdentity = 5
|
||||
s.save()
|
||||
return Response({'code': 0, 'msg': '罚款已撤销(驳回)'})
|
||||
|
||||
def _resubmit_penalty(self, fadan, liyou, jine_str, processor_id=None):
|
||||
"""再次申请罚款(已驳回 → 平台审核中)"""
|
||||
"""再次申请罚款;组队均摊联动总额重分。"""
|
||||
from utils.penalty_status import PENALTY_REJECTED, PENALTY_PLATFORM_AUDIT
|
||||
from orders.services.team_recruit import _d, MONEY
|
||||
from decimal import ROUND_DOWN
|
||||
if fadan.Status != PENALTY_REJECTED:
|
||||
return Response({'code': 400, 'msg': '只有已驳回的罚单可再次申请'})
|
||||
if not liyou.strip():
|
||||
@@ -435,19 +482,33 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
jine = Decimal(jine_str)
|
||||
if jine <= 0:
|
||||
raise ValueError
|
||||
except:
|
||||
except Exception:
|
||||
return Response({'code': 400, 'msg': '罚款金额必须为正数'})
|
||||
siblings = self._team_split_siblings(fadan, include_rejected=True)
|
||||
siblings = [s for s in siblings if s.Status == PENALTY_REJECTED] or [fadan]
|
||||
reason_text = liyou[:500]
|
||||
if (fadan.Reason or '').startswith('【组队均摊】') and not reason_text.startswith('【组队均摊】'):
|
||||
reason_text = f'【组队均摊】{reason_text}'
|
||||
with transaction.atomic():
|
||||
fadan.Status = PENALTY_PLATFORM_AUDIT
|
||||
fadan.Reason = liyou[:500]
|
||||
fadan.FineAmount = jine
|
||||
fadan.RejectReason = '' # 清空驳回理由
|
||||
if processor_id:
|
||||
fadan.ProcessorID = processor_id
|
||||
fadan.ProcessorIdentity = 5
|
||||
fadan.save()
|
||||
lock_penalty_bonus(fadan)
|
||||
logger.info(f"商家重新申请罚单{fadan.id},金额={jine}")
|
||||
k = len(siblings)
|
||||
total = _d(jine)
|
||||
if k > 1:
|
||||
base = (total / Decimal(k)).quantize(MONEY, rounding=ROUND_DOWN)
|
||||
amounts = [base] * k
|
||||
amounts[0] = _d(total - base * (k - 1))
|
||||
else:
|
||||
amounts = [total]
|
||||
for i, s in enumerate(siblings):
|
||||
s.Status = PENALTY_PLATFORM_AUDIT
|
||||
s.Reason = reason_text
|
||||
s.FineAmount = amounts[i] if i < len(amounts) else amounts[-1]
|
||||
s.RejectReason = ''
|
||||
if processor_id:
|
||||
s.ProcessorID = processor_id
|
||||
s.ProcessorIdentity = 5
|
||||
s.save()
|
||||
lock_penalty_bonus(s)
|
||||
logger.info(f"商家重新申请组队罚单 order={fadan.RelatedOrderID} 总额={jine} n={k}")
|
||||
return Response({'code': 0, 'msg': '已重新申请罚款'})
|
||||
|
||||
def _manage_penalty_evidence(self, fadan, data):
|
||||
|
||||
Reference in New Issue
Block a user