新增转盘活动/奖品/机会表与 Czjilu leixing=7 履约;专区 tupian_url;hqsp/详情下发 shi_zhuanpan。普通点单与抢单主链路保持不变。 Co-authored-by: Cursor <cursoragent@cursor.com>
495 lines
21 KiB
Python
495 lines
21 KiB
Python
"""充值订单 czjilu 履约(押金/积分),与 member_recharge 同一套幂等原则。"""
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
from decimal import Decimal
|
||
|
||
from django.db import transaction
|
||
|
||
from backend.utils import update_guanshi_daily_by_action
|
||
from jituan.constants import CLUB_ID_DEFAULT
|
||
from jituan.services.club_penalty import resolve_gsfenhong_club_id
|
||
from orders.models import CommissionRate
|
||
from products.models import Czjilu, Gsfenhong
|
||
from products.czjilu_types import is_czjilu_fulfillable_status
|
||
from users.models import UserDashou, UserGuanshi
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
INTEGRAL_PRICE = Decimal('5.00')
|
||
MAX_INTEGRAL = 10
|
||
INTEGRAL_INCREMENT = 5
|
||
|
||
|
||
class CzjiluFulfillError(Exception):
|
||
def __init__(self, message, code='error'):
|
||
super().__init__(message)
|
||
self.code = code
|
||
|
||
|
||
@transaction.atomic
|
||
def fulfill_zhuanpan(dingdan_id, paid_amount_yuan=None):
|
||
"""转盘购票履约:Czjilu 标已付 + 抽奖机会改为待抽。绝不创建抢单池 Order。"""
|
||
from products.czjilu_types import CZJILU_LEIXING_ZHUANPAN, CZJILU_PAID_STATUS
|
||
from products.models import ZhuanpanJihui
|
||
|
||
try:
|
||
order = Czjilu.query.select_for_update().get(dingdan_id=dingdan_id)
|
||
except Czjilu.DoesNotExist:
|
||
raise CzjiluFulfillError('订单不存在', 'not_found')
|
||
|
||
if order.leixing != CZJILU_LEIXING_ZHUANPAN:
|
||
raise CzjiluFulfillError('订单类型不是转盘购票', 'type_error')
|
||
|
||
if order.zhuangtai == CZJILU_PAID_STATUS:
|
||
return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': CZJILU_PAID_STATUS}
|
||
|
||
if not is_czjilu_fulfillable_status(order.zhuangtai):
|
||
return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}
|
||
|
||
amount = Decimal(str(order.jine))
|
||
if paid_amount_yuan is not None:
|
||
paid = Decimal(str(paid_amount_yuan))
|
||
if abs(paid - amount) > Decimal('0.01'):
|
||
raise CzjiluFulfillError(f'支付金额{paid}与订单{amount}不一致', 'amount_mismatch')
|
||
|
||
jihui = ZhuanpanJihui.query.select_for_update().filter(
|
||
czjilu_dingdan_id=dingdan_id
|
||
).first()
|
||
if not jihui:
|
||
raise CzjiluFulfillError('转盘机会单不存在', 'not_found')
|
||
|
||
order.zhuangtai = CZJILU_PAID_STATUS
|
||
order.save(update_fields=['zhuangtai'])
|
||
|
||
if int(jihui.zhuangtai) == 9:
|
||
jihui.zhuangtai = 1 # 已付待抽
|
||
jihui.save(update_fields=['zhuangtai', 'UpdateTime'])
|
||
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(
|
||
amount,
|
||
getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
|
||
biz_ref=f'cz:{dingdan_id}',
|
||
)
|
||
except Exception as exc:
|
||
logger.error('转盘购票补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
|
||
logger.info('转盘购票履约完成 dingdan=%s jihui=%s', dingdan_id, jihui.id)
|
||
return {
|
||
'already_done': False,
|
||
'dingdan_id': dingdan_id,
|
||
'zhuangtai': CZJILU_PAID_STATUS,
|
||
'jihui_id': jihui.id,
|
||
}
|
||
|
||
|
||
@transaction.atomic
|
||
def fulfill_yajin_recharge(dingdan_id, paid_amount_yuan=None):
|
||
"""押金充值幂等履约:仅待履约状态(9/用户关单2)时入账;已付(3)直接跳过防多加。"""
|
||
order = Czjilu.query.filter(dingdan_id=dingdan_id).select_for_update().first()
|
||
if not order:
|
||
raise CzjiluFulfillError('订单不存在', 'not_found')
|
||
if order.leixing != 2:
|
||
raise CzjiluFulfillError('订单类型不是押金', 'type_error')
|
||
if not is_czjilu_fulfillable_status(order.zhuangtai):
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(
|
||
Decimal(str(order.jine)),
|
||
getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
|
||
biz_ref=f'cz:{dingdan_id}',
|
||
)
|
||
except Exception as exc:
|
||
logger.error('押金补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}
|
||
|
||
amount = Decimal(str(order.jine))
|
||
if paid_amount_yuan is not None:
|
||
paid = Decimal(str(paid_amount_yuan))
|
||
if abs(paid - amount) > Decimal('0.01'):
|
||
raise CzjiluFulfillError(f'支付金额{paid}与订单{amount}不一致', 'amount_mismatch')
|
||
|
||
try:
|
||
dashou = UserDashou.objects.select_for_update().get(user__UserUID=order.yonghuid)
|
||
except UserDashou.DoesNotExist:
|
||
raise CzjiluFulfillError('打手不存在,无法充值押金', 'dashou_not_found')
|
||
|
||
dashou.yajin += amount
|
||
dashou.save(update_fields=['yajin'])
|
||
|
||
order.zhuangtai = 3
|
||
order.save(update_fields=['zhuangtai'])
|
||
|
||
club_id = getattr(order, 'club_id', None) or CLUB_ID_DEFAULT
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(amount, club_id, biz_ref=f'cz:{dingdan_id}')
|
||
except Exception as exc:
|
||
logger.error('押金收支统计失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
|
||
try:
|
||
_apply_yajin_fenhong(order, dashou, amount)
|
||
except Exception as exc:
|
||
logger.error('押金分红失败但押金已到账 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
|
||
logger.info('押金履约完成 dingdan=%s amount=%s', dingdan_id, amount)
|
||
return {'already_done': False, 'dingdan_id': dingdan_id, 'zhuangtai': 3, 'yajin': dashou.yajin}
|
||
|
||
|
||
def _apply_yajin_fenhong(order, dashou, amount):
|
||
if Gsfenhong.query.filter(dingdan_id=order.dingdan_id).exists():
|
||
return
|
||
guanshi_id = dashou.yaoqingren
|
||
if not guanshi_id:
|
||
return
|
||
lilu_obj = CommissionRate.query.filter(Platform='12').first()
|
||
rate = lilu_obj.Rate if lilu_obj and lilu_obj.Rate is not None else Decimal('0')
|
||
if rate <= 0:
|
||
return
|
||
fenhong_jine = (amount * rate).quantize(Decimal('0.01'))
|
||
if fenhong_jine <= 0:
|
||
return
|
||
guanshi = UserGuanshi.objects.select_for_update().get(user__UserUID=guanshi_id)
|
||
guanshi.yue += fenhong_jine
|
||
guanshi.chongzhifenrun += fenhong_jine
|
||
guanshi.save(update_fields=['yue', 'chongzhifenrun'])
|
||
user_main = dashou.user
|
||
Gsfenhong.query.create(
|
||
dingdan_id=order.dingdan_id,
|
||
guanshi=guanshi_id,
|
||
dashouid=order.yonghuid,
|
||
shuoming='押金分红',
|
||
fenhong=fenhong_jine,
|
||
avatar=user_main.Avatar,
|
||
nicheng=dashou.nicheng or '未知打手',
|
||
fenhong_leixing=2,
|
||
club_id=resolve_gsfenhong_club_id(
|
||
dingdan_id=order.dingdan_id, dashouid=order.yonghuid, czjilu=order,
|
||
),
|
||
)
|
||
try:
|
||
update_guanshi_daily_by_action(yonghuid=guanshi_id, action=4, amount=fenhong_jine)
|
||
except Exception as exc:
|
||
logger.error('押金分红日统计失败: %s', exc)
|
||
|
||
|
||
@transaction.atomic
|
||
def fulfill_jifen_recharge(dingdan_id, paid_amount_yuan=None):
|
||
"""积分补充幂等履约:仅待履约状态(9/2)时入账。"""
|
||
order = Czjilu.query.filter(dingdan_id=dingdan_id).select_for_update().first()
|
||
if not order:
|
||
raise CzjiluFulfillError('订单不存在', 'not_found')
|
||
if order.leixing != 3:
|
||
raise CzjiluFulfillError('订单类型不是积分', 'type_error')
|
||
if not is_czjilu_fulfillable_status(order.zhuangtai):
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(
|
||
Decimal(str(order.jine)),
|
||
getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
|
||
biz_ref=f'cz:{dingdan_id}',
|
||
)
|
||
except Exception as exc:
|
||
logger.error('积分补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}
|
||
|
||
amount = Decimal(str(order.jine))
|
||
if paid_amount_yuan is not None:
|
||
paid = Decimal(str(paid_amount_yuan))
|
||
if abs(paid - amount) > Decimal('0.01'):
|
||
raise CzjiluFulfillError(f'支付金额{paid}与订单{amount}不一致', 'amount_mismatch')
|
||
if abs(paid - INTEGRAL_PRICE) > Decimal('0.01'):
|
||
raise CzjiluFulfillError('积分订单金额必须为5元', 'amount_mismatch')
|
||
|
||
try:
|
||
dashou = UserDashou.objects.select_for_update().get(user__UserUID=order.yonghuid)
|
||
except UserDashou.DoesNotExist:
|
||
raise CzjiluFulfillError('打手不存在,无法补充积分', 'dashou_not_found')
|
||
|
||
if dashou.jifen < MAX_INTEGRAL:
|
||
dashou.jifen = min(dashou.jifen + INTEGRAL_INCREMENT, MAX_INTEGRAL)
|
||
dashou.save(update_fields=['jifen'])
|
||
|
||
order.zhuangtai = 3
|
||
order.save(update_fields=['zhuangtai'])
|
||
|
||
club_id = getattr(order, 'club_id', None) or CLUB_ID_DEFAULT
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(amount, club_id, biz_ref=f'cz:{dingdan_id}')
|
||
except Exception as exc:
|
||
logger.error('积分收支统计失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
|
||
logger.info('积分履约完成 dingdan=%s jifen=%s', dingdan_id, dashou.jifen)
|
||
return {'already_done': False, 'dingdan_id': dingdan_id, 'zhuangtai': 3, 'jifen': dashou.jifen}
|
||
|
||
|
||
@transaction.atomic
|
||
def fulfill_fakuan(dingdan_id, paid_amount_yuan=None):
|
||
"""罚款支付幂等履约:仅 zhuangtai==9 时入账。"""
|
||
import re
|
||
from orders.models import Penalty
|
||
from users.fadan_fenhong_utils import process_fadan_fenhong
|
||
|
||
order = Czjilu.query.filter(dingdan_id=dingdan_id).select_for_update().first()
|
||
if not order:
|
||
raise CzjiluFulfillError('订单不存在', 'not_found')
|
||
if order.leixing != 6:
|
||
raise CzjiluFulfillError('订单类型不是罚款', 'type_error')
|
||
if not is_czjilu_fulfillable_status(order.zhuangtai):
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(
|
||
Decimal(str(order.jine)),
|
||
getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
|
||
biz_ref=f'cz:{dingdan_id}',
|
||
)
|
||
except Exception as exc:
|
||
logger.error('罚款补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}
|
||
|
||
amount = Decimal(str(order.jine))
|
||
if paid_amount_yuan is not None:
|
||
paid = Decimal(str(paid_amount_yuan))
|
||
if abs(paid - amount) > Decimal('0.01'):
|
||
raise CzjiluFulfillError(f'支付金额{paid}与订单{amount}不一致', 'amount_mismatch')
|
||
|
||
order.zhuangtai = 3
|
||
order.save(update_fields=['zhuangtai'])
|
||
|
||
# 更新罚单状态为已缴纳(2)并触发分红
|
||
try:
|
||
fadan = None
|
||
m = re.search(r'#fadan:(\d+)', order.shuoming or '')
|
||
if m:
|
||
fadan_id_str = m.group(1)
|
||
fadan = Penalty.query.filter(
|
||
id=int(fadan_id_str),
|
||
PenalizedUserID=order.yonghuid,
|
||
Status__in=[1, 3],
|
||
).first()
|
||
if not fadan:
|
||
logger.warning(
|
||
'罚款订单 %s shuoming 标记罚单 %s 未找到(被处罚者=%s, 状态需为1/3)',
|
||
dingdan_id, fadan_id_str, order.yonghuid,
|
||
)
|
||
else:
|
||
logger.warning(
|
||
'罚款订单 %s shuoming 无 #fadan:xxx 标记,回退金额匹配: %s',
|
||
dingdan_id, order.shuoming,
|
||
)
|
||
if not fadan:
|
||
fadan = Penalty.query.filter(
|
||
PenalizedUserID=order.yonghuid,
|
||
FineAmount=order.jine,
|
||
Status__in=[1, 3],
|
||
).order_by('-CreateTime').first()
|
||
if fadan:
|
||
logger.warning(
|
||
'罚款订单 %s 回退金额匹配到罚单 %s(金额=%s)',
|
||
dingdan_id, fadan.id, order.jine,
|
||
)
|
||
if fadan:
|
||
fadan.Status = 2
|
||
fadan.save(update_fields=['Status'])
|
||
success, msg = process_fadan_fenhong(fadan.id)
|
||
if not success:
|
||
logger.error('罚单 %s 分红处理失败: %s', fadan.id, msg)
|
||
else:
|
||
logger.info('罚单 %s 分红处理完成: %s', fadan.id, msg)
|
||
else:
|
||
logger.error(
|
||
'罚款订单 %s 未找到对应罚单,罚单状态未更新(被处罚者=%s, 金额=%s)',
|
||
dingdan_id, order.yonghuid, order.jine,
|
||
)
|
||
except Exception as exc:
|
||
logger.error('罚款罚单状态更新失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(amount, getattr(order, 'club_id', None) or CLUB_ID_DEFAULT, biz_ref=f'cz:{dingdan_id}')
|
||
except Exception as exc:
|
||
logger.error('罚款收支统计失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
|
||
logger.info('罚款履约完成 dingdan=%s amount=%s', dingdan_id, amount)
|
||
return {'already_done': False, 'dingdan_id': dingdan_id, 'zhuangtai': 3}
|
||
|
||
|
||
@transaction.atomic
|
||
def fulfill_kaohe(dingdan_id, paid_amount_yuan=None):
|
||
"""考核支付幂等履约:仅待履约状态(9/2)时入账。"""
|
||
from rank.models import KaohePayTemp
|
||
from rank.utils import create_shenhe_jilu_from_temp
|
||
from users.business_models import User
|
||
|
||
order = Czjilu.query.filter(dingdan_id=dingdan_id).select_for_update().first()
|
||
if not order:
|
||
raise CzjiluFulfillError('订单不存在', 'not_found')
|
||
if order.leixing != 5:
|
||
raise CzjiluFulfillError('订单类型不是考核', 'type_error')
|
||
if not is_czjilu_fulfillable_status(order.zhuangtai):
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(
|
||
Decimal(str(order.jine)),
|
||
getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
|
||
biz_ref=f'cz:{dingdan_id}',
|
||
)
|
||
except Exception as exc:
|
||
logger.error('考核补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}
|
||
|
||
amount = Decimal(str(order.jine))
|
||
if paid_amount_yuan is not None:
|
||
paid = Decimal(str(paid_amount_yuan))
|
||
if abs(paid - amount) > Decimal('0.01'):
|
||
raise CzjiluFulfillError(f'支付金额{paid}与订单{amount}不一致', 'amount_mismatch')
|
||
|
||
order.zhuangtai = 3
|
||
order.save(update_fields=['zhuangtai'])
|
||
|
||
# 从临时表取业务参数并创建审核记录
|
||
try:
|
||
temp = KaohePayTemp.query.get(dingdan_id=dingdan_id, yonghuid=order.yonghuid)
|
||
user = User.query.get(UserUID=order.yonghuid)
|
||
success, msg, record = create_shenhe_jilu_from_temp(user, temp)
|
||
if not success:
|
||
logger.error('创建审核记录失败 dingdan=%s: %s', dingdan_id, msg)
|
||
order.zhuangtai = 10 # 支付成功但业务处理失败
|
||
order.save(update_fields=['zhuangtai'])
|
||
else:
|
||
logger.info('考核审核记录创建成功 dingdan=%s jilu_id=%s', dingdan_id, getattr(record, 'jilu_id', None))
|
||
except KaohePayTemp.DoesNotExist:
|
||
logger.error('考核临时表无记录 dingdan=%s', dingdan_id)
|
||
order.zhuangtai = 10
|
||
order.save(update_fields=['zhuangtai'])
|
||
except Exception as exc:
|
||
logger.error('考核审核记录创建异常 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
order.zhuangtai = 10
|
||
order.save(update_fields=['zhuangtai'])
|
||
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(amount, getattr(order, 'club_id', None) or CLUB_ID_DEFAULT, biz_ref=f'cz:{dingdan_id}')
|
||
except Exception as exc:
|
||
logger.error('考核收支统计失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
|
||
logger.info('考核履约完成 dingdan=%s amount=%s', dingdan_id, amount)
|
||
return {'already_done': False, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}
|
||
|
||
|
||
@transaction.atomic
|
||
def fulfill_shangjia(dingdan_id, paid_amount_yuan=None):
|
||
"""商家充值幂等履约:仅待履约状态(9/2)时入账;已付(3)跳过防多加。"""
|
||
from users.models import UserShangjia
|
||
|
||
order = Czjilu.query.filter(dingdan_id=dingdan_id).select_for_update().first()
|
||
if not order:
|
||
raise CzjiluFulfillError('订单不存在', 'not_found')
|
||
if order.leixing != 4:
|
||
raise CzjiluFulfillError('订单类型不是商家充值', 'type_error')
|
||
if not is_czjilu_fulfillable_status(order.zhuangtai):
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(
|
||
Decimal(str(order.jine)),
|
||
getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
|
||
biz_ref=f'cz:{dingdan_id}',
|
||
)
|
||
except Exception as exc:
|
||
logger.error('商家充值补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
return {'already_done': True, 'dingdan_id': dingdan_id, 'zhuangtai': order.zhuangtai}
|
||
|
||
amount = Decimal(str(order.jine))
|
||
if paid_amount_yuan is not None:
|
||
paid = Decimal(str(paid_amount_yuan))
|
||
if abs(paid - amount) > Decimal('0.01'):
|
||
raise CzjiluFulfillError(f'支付金额{paid}与订单{amount}不一致', 'amount_mismatch')
|
||
|
||
try:
|
||
shangjia = UserShangjia.objects.select_for_update().get(user__UserUID=order.yonghuid)
|
||
except UserShangjia.DoesNotExist:
|
||
raise CzjiluFulfillError('商家不存在,无法充值', 'shangjia_not_found')
|
||
|
||
shangjia.yue += amount
|
||
shangjia.save(update_fields=['yue'])
|
||
|
||
order.zhuangtai = 3
|
||
order.save(update_fields=['zhuangtai'])
|
||
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(amount, getattr(order, 'club_id', None) or CLUB_ID_DEFAULT, biz_ref=f'cz:{dingdan_id}')
|
||
except Exception as exc:
|
||
logger.error('商家充值收支统计失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
|
||
logger.info('商家充值履约完成 dingdan=%s amount=%s yue=%s', dingdan_id, amount, shangjia.yue)
|
||
return {'already_done': False, 'dingdan_id': dingdan_id, 'zhuangtai': 3, 'yue': shangjia.yue}
|
||
|
||
|
||
def confirm_czjilu_paid(dingdan_id, yonghuid, expected_leixing):
|
||
"""轮询确认:付呗/微信/支付宝官方查单成功后幂等履约(防多加)。"""
|
||
try:
|
||
order = Czjilu.query.get(dingdan_id=dingdan_id, yonghuid=yonghuid)
|
||
except Czjilu.DoesNotExist:
|
||
raise CzjiluFulfillError('订单不存在或不属于当前用户', 'not_found')
|
||
|
||
if order.leixing != expected_leixing:
|
||
raise CzjiluFulfillError('订单类型不匹配', 'type_error')
|
||
|
||
if order.zhuangtai == 3:
|
||
try:
|
||
from jituan.services.szjilu_accounting import repair_wechat_income_if_missing
|
||
repair_wechat_income_if_missing(
|
||
Decimal(str(order.jine)),
|
||
getattr(order, 'club_id', None) or CLUB_ID_DEFAULT,
|
||
biz_ref=f'cz:{dingdan_id}',
|
||
)
|
||
except Exception as exc:
|
||
logger.error('充值单补记收支失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||
return {'already_done': True, 'zhuangtai': 3}
|
||
|
||
if not is_czjilu_fulfillable_status(order.zhuangtai):
|
||
raise CzjiluFulfillError(f'订单状态异常: {order.zhuangtai}', 'status_error')
|
||
|
||
paid = Decimal(str(order.jine))
|
||
club_id = getattr(order, 'club_id', None)
|
||
|
||
from jituan.services.pay_confirm import confirm_remote_payment
|
||
remote = confirm_remote_payment(dingdan_id, club_id, prefer_amount=paid)
|
||
if not remote.get('ok'):
|
||
if remote.get('pending'):
|
||
raise CzjiluFulfillError('支付结果尚未同步,请稍后再试', 'not_paid')
|
||
raise CzjiluFulfillError(remote.get('msg') or '支付未成功', 'not_paid')
|
||
if remote.get('amount') is not None:
|
||
paid = Decimal(str(remote['amount']))
|
||
|
||
# 查单确认支付成功,执行履约(fulfill_* 内行锁+仅 9/2→3,防多加)
|
||
if expected_leixing == 1:
|
||
from jituan.services.member_recharge import fulfill_member_recharge
|
||
return fulfill_member_recharge(dingdan_id, paid_amount_yuan=paid, source='confirm')
|
||
if expected_leixing == 2:
|
||
return fulfill_yajin_recharge(dingdan_id, paid_amount_yuan=paid)
|
||
if expected_leixing == 3:
|
||
return fulfill_jifen_recharge(dingdan_id, paid_amount_yuan=paid)
|
||
if expected_leixing == 4:
|
||
return fulfill_shangjia(dingdan_id, paid_amount_yuan=paid)
|
||
if expected_leixing == 5:
|
||
return fulfill_kaohe(dingdan_id, paid_amount_yuan=paid)
|
||
if expected_leixing == 6:
|
||
return fulfill_fakuan(dingdan_id, paid_amount_yuan=paid)
|
||
if expected_leixing == 7:
|
||
return fulfill_zhuanpan(dingdan_id, paid_amount_yuan=paid)
|
||
raise CzjiluFulfillError('不支持的充值类型', 'type_error')
|
||
|
||
|
||
def repair_czjilu_payment(dingdan_id):
|
||
"""客服补单:官方查单确认已付后,走同一套幂等履约(绝不多加)。"""
|
||
try:
|
||
order = Czjilu.query.get(dingdan_id=dingdan_id)
|
||
except Czjilu.DoesNotExist:
|
||
raise CzjiluFulfillError('订单不存在', 'not_found')
|
||
return confirm_czjilu_paid(dingdan_id, order.yonghuid, expected_leixing=order.leixing)
|