69 lines
3.6 KiB
Python
69 lines
3.6 KiB
Python
"""Shared validation for sampling confirmation edits and imports."""
|
||
from datetime import date, datetime, timedelta
|
||
|
||
REASONS = ('价格高', '质感差', '资质不全', '同质化严重')
|
||
SAMPLE_STATUSES = ('未付款', '付款中', '样品到货中', '样品已到货', '不授权', '厂家无货', '停产', '其他')
|
||
# Keep existing imported values editable without silently changing historical records.
|
||
LEGACY_SAMPLE_STATUSES = ('不做', '产品停产', '厂家无现货', '已到货', '待寄出')
|
||
TEXT_LIMITS = {
|
||
'sample_status': 50, 'oa_approval_no': 100, 'express_tracking_no': 100,
|
||
'remark': 65535, 'product_code': 100, 'final_product_name': 300,
|
||
'platform': 200, 'sample_confirmed': 50, 'sample_confirmation_reason': 65535,
|
||
'barcode': 100, 'product_unit_price': 1000,
|
||
}
|
||
EDITABLE = frozenset((*TEXT_LIMITS, 'product_unit_price', 'arrival_date'))
|
||
|
||
|
||
def validate_confirmation_values(data):
|
||
values = {}
|
||
for key in EDITABLE & data.keys():
|
||
raw = data[key]
|
||
value = str(raw).strip() if raw is not None else ''
|
||
if key == 'arrival_date':
|
||
try:
|
||
values[key] = date.fromisoformat(value) if value else None
|
||
except ValueError:
|
||
raise ValueError('到样日期格式错误,请填写YYYY-MM-DD')
|
||
else:
|
||
size = len(value.encode('utf-8')) if TEXT_LIMITS[key] == 65535 else len(value)
|
||
if size > TEXT_LIMITS[key]:
|
||
raise ValueError('字段内容过长')
|
||
if key == 'sample_confirmed' and value not in ('', '做', '不做'):
|
||
raise ValueError('样品确认请选择做或不做')
|
||
if key == 'sample_status' and value not in ('', *SAMPLE_STATUSES, *LEGACY_SAMPLE_STATUSES):
|
||
raise ValueError('请选择有效的样品状态')
|
||
if key == 'sample_confirmation_reason' and value:
|
||
if value == '其他' or value.startswith('其他:'):
|
||
other = str(data.get('other_reason') or '').strip() if value == '其他' else value[3:].strip()
|
||
if not other:
|
||
raise ValueError('选择其他时,请填写具体原因')
|
||
if any(reason in other for reason in REASONS):
|
||
raise ValueError('其他原因不能包含价格高、质感差、资质不全、同质化严重')
|
||
value = '其他:' + other
|
||
if len(value.encode('utf-8')) > 65535:
|
||
raise ValueError('其他原因内容过长')
|
||
elif value not in (*REASONS, '无'):
|
||
raise ValueError('请选择有效的样品确认原因')
|
||
values[key] = value
|
||
if str(data.get('sample_confirmed') or '').strip() == '做' and not str(
|
||
data.get('sample_confirmation_reason') or '').strip():
|
||
values['sample_confirmation_reason'] = '无'
|
||
return values
|
||
|
||
|
||
def confirmation_reminder_state(arrival_date, sample_confirmed, as_of=None):
|
||
"""Return the derived 10-day confirmation reminder state without sending messages."""
|
||
if not arrival_date:
|
||
return {'due_date': None, 'pending': False}
|
||
if isinstance(arrival_date, str):
|
||
try:
|
||
arrival_date = date.fromisoformat(arrival_date[:10])
|
||
except ValueError:
|
||
return {'due_date': None, 'pending': False}
|
||
if isinstance(arrival_date, datetime):
|
||
arrival_date = arrival_date.date()
|
||
due_date = arrival_date + timedelta(days=10)
|
||
today = as_of or date.today()
|
||
pending = not str(sample_confirmed or '').strip() and today >= due_date
|
||
return {'due_date': due_date.isoformat(), 'pending': pending}
|