fix: 成交配置禁派单开关可保存,兼容旧 hours 字段与 minutes 列缺失
This commit is contained in:
1 parent
c10727c356
commit
5de74f0444
1 file changed
+71
-23
@@ -70,6 +70,22 @@ def _pick_display_unit(minutes: int) -> tuple[str, int]:
|
||||
return 'm', m
|
||||
|
||||
|
||||
def _as_bool(value, default: bool = False) -> bool:
|
||||
"""兼容 JSON bool / 0|1 / "true"|"false",避免开关保存后读回仍是关。"""
|
||||
if value is None:
|
||||
return default
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
if isinstance(value, (int, float)):
|
||||
return value != 0
|
||||
s = str(value).strip().lower()
|
||||
if s in ('1', 'true', 'yes', 'on', 'y'):
|
||||
return True
|
||||
if s in ('0', 'false', 'no', 'off', 'n', ''):
|
||||
return False
|
||||
return default
|
||||
|
||||
|
||||
def _parse_timeout_to_minutes(
|
||||
data: dict,
|
||||
*,
|
||||
@@ -88,7 +104,8 @@ def _parse_timeout_to_minutes(
|
||||
"""
|
||||
if not isinstance(data, dict):
|
||||
return None
|
||||
unit = (data.get(unit_key) or '').strip().lower()
|
||||
raw_unit = data.get(unit_key)
|
||||
unit = str(raw_unit or '').strip().lower()
|
||||
if value_key in data and data.get(value_key) is not None and unit in ('h', 'm', 'hour', 'hours', 'min', 'minute', 'minutes'):
|
||||
try:
|
||||
val = int(data.get(value_key))
|
||||
@@ -622,11 +639,11 @@ def save_deal_config(club_id: str, data: dict, updated_by: str = '') -> dict:
|
||||
row.dispatch_block_minutes = m_block
|
||||
row.dispatch_block_hours = max(1, (m_block + 59) // 60)
|
||||
|
||||
if 'dispatch_block_enabled' in data and data['dispatch_block_enabled'] is not None:
|
||||
row.dispatch_block_enabled = bool(data['dispatch_block_enabled'])
|
||||
if 'dispatch_block_enabled' in data and data.get('dispatch_block_enabled') is not None:
|
||||
row.dispatch_block_enabled = _as_bool(data.get('dispatch_block_enabled'), False)
|
||||
|
||||
if 'auto_settle_enabled' in data and data['auto_settle_enabled'] is not None:
|
||||
enabled = bool(data['auto_settle_enabled'])
|
||||
if 'auto_settle_enabled' in data and data.get('auto_settle_enabled') is not None:
|
||||
enabled = _as_bool(data.get('auto_settle_enabled'), False)
|
||||
row.auto_settle_enabled = enabled
|
||||
if enabled and not was_auto:
|
||||
row.auto_settle_enabled_at = now
|
||||
@@ -634,8 +651,8 @@ def save_deal_config(club_id: str, data: dict, updated_by: str = '') -> dict:
|
||||
row.auto_settle_enabled_at = None
|
||||
_clear_club_auto_settle_eligible(row.club_id)
|
||||
|
||||
if 'stats_enabled' in data and data['stats_enabled'] is not None:
|
||||
enabled = bool(data['stats_enabled'])
|
||||
if 'stats_enabled' in data and data.get('stats_enabled') is not None:
|
||||
enabled = _as_bool(data.get('stats_enabled'), False)
|
||||
row.stats_enabled = enabled
|
||||
if enabled and not was_stats:
|
||||
# 开启时默认从较早起点计,便于旧单刷新也能出成交率
|
||||
@@ -643,23 +660,24 @@ def save_deal_config(club_id: str, data: dict, updated_by: str = '') -> dict:
|
||||
if not enabled:
|
||||
# 停止写入;保留 since 供只读理解历史起点;再次开启会刷新 since
|
||||
pass
|
||||
if enabled and was_stats and data.get('reset_stats_since'):
|
||||
if enabled and was_stats and _as_bool(data.get('reset_stats_since'), False):
|
||||
row.stats_since = now
|
||||
|
||||
if 'default_partial_settle_ratio' in data and data['default_partial_settle_ratio'] is not None:
|
||||
from decimal import Decimal, InvalidOperation
|
||||
raw = data['default_partial_settle_ratio']
|
||||
# 兼容前端传百分比 10~100
|
||||
try:
|
||||
val = Decimal(str(raw).strip())
|
||||
except (InvalidOperation, ValueError, TypeError) as e:
|
||||
raise ValueError('默认比例结算比例无效') from e
|
||||
if val > 1:
|
||||
val = val / Decimal('100')
|
||||
val = val.quantize(Decimal('0.0001'))
|
||||
if val < Decimal('0.01') or val > Decimal('1'):
|
||||
raise ValueError('默认比例结算比例须在 1%~100%')
|
||||
row.default_partial_settle_ratio = val
|
||||
# 未传或空值时跳过,避免前端误传 undefined/null 把库里的比例冲掉或直接 400
|
||||
if 'default_partial_settle_ratio' in data:
|
||||
raw = data.get('default_partial_settle_ratio')
|
||||
if raw is not None and str(raw).strip() != '' and str(raw).strip().lower() != 'undefined':
|
||||
from decimal import Decimal, InvalidOperation
|
||||
try:
|
||||
val = Decimal(str(raw).strip())
|
||||
except (InvalidOperation, ValueError, TypeError) as e:
|
||||
raise ValueError('默认比例结算比例无效') from e
|
||||
if val > 1:
|
||||
val = val / Decimal('100')
|
||||
val = val.quantize(Decimal('0.0001'))
|
||||
if val < Decimal('0.01') or val > Decimal('1'):
|
||||
raise ValueError('默认比例结算比例须在 1%~100%')
|
||||
row.default_partial_settle_ratio = val
|
||||
|
||||
# 若刚打开统计且 since 空
|
||||
if row.stats_enabled and not row.stats_since:
|
||||
@@ -670,7 +688,7 @@ def save_deal_config(club_id: str, data: dict, updated_by: str = '') -> dict:
|
||||
row.stats_since = _db_datetime(row.stats_since)
|
||||
|
||||
row.updated_by = (updated_by or '')[:32]
|
||||
row.save()
|
||||
_persist_deal_config_row(row)
|
||||
# 保存后触发一次历史回填,保证抢单池马上能刷到成交率/罚款率
|
||||
try:
|
||||
from jituan.models import DealStatEvent
|
||||
@@ -682,6 +700,36 @@ def save_deal_config(club_id: str, data: dict, updated_by: str = '') -> dict:
|
||||
return config_to_dict(row)
|
||||
|
||||
|
||||
def _persist_deal_config_row(row):
|
||||
"""
|
||||
落库。若线上尚未跑 minutes 迁移,回落到只写 hours/开关,避免整次保存 500 导致前端像「保存了又被清空」。
|
||||
"""
|
||||
from jituan.models import ClubOrderDealConfig
|
||||
|
||||
try:
|
||||
row.save()
|
||||
return
|
||||
except Exception as e:
|
||||
err = str(e).lower()
|
||||
if not any(k in err for k in ('minutes_platform', 'minutes_merchant', 'dispatch_block_minutes', 'unknown column')):
|
||||
raise
|
||||
logger.warning('deal config minutes 列不可用,回落 hours 写入 club=%s: %s', row.club_id, e)
|
||||
|
||||
ClubOrderDealConfig.objects.filter(pk=row.pk).update(
|
||||
auto_settle_enabled=bool(row.auto_settle_enabled),
|
||||
auto_settle_enabled_at=row.auto_settle_enabled_at,
|
||||
hours_platform=int(row.hours_platform or 48),
|
||||
hours_merchant=int(row.hours_merchant or 48),
|
||||
dispatch_block_enabled=bool(getattr(row, 'dispatch_block_enabled', False)),
|
||||
dispatch_block_hours=int(getattr(row, 'dispatch_block_hours', None) or 24),
|
||||
stats_enabled=bool(row.stats_enabled),
|
||||
stats_since=row.stats_since,
|
||||
default_partial_settle_ratio=getattr(row, 'default_partial_settle_ratio', None),
|
||||
updated_by=(row.updated_by or '')[:32],
|
||||
)
|
||||
row.refresh_from_db()
|
||||
|
||||
|
||||
def _clear_club_auto_settle_eligible(club_id: str):
|
||||
from orders.models import Order
|
||||
Order.objects.filter(ClubID=club_id, AutoSettleEligible=True).update(
|
||||
|
||||
Reference in new issue
Block a user