1
0
forked from erp-dev/erp

fix: create customer when external_order sync to database

This commit is contained in:
2026-03-24 22:14:41 +08:00
parent b48bfc50a5
commit 315b53f5f7
4 changed files with 362 additions and 111 deletions

View File

@@ -330,7 +330,22 @@ def _resolve_external_customer(*, merchant, record: dict):
.first()
)
if not customer:
raise RuntimeError(f'未找到客户: {customer_name}')
defaults = {
'merchant': merchant,
'name': customer_name,
}
sync_user = record.get('_sync_user')
employee = getattr(sync_user, 'employee', None)
if employee and employee.merchant_id == merchant.id:
defaults['created_by'] = employee
customer = basic_models.Customer.objects.create(**defaults)
logger.info(
'外部印染同步自动创建客户: merchant_id=%s customer_name=%s external_customer_id=%s customer_id=%s',
merchant.id,
customer_name,
external_customer_id,
customer.id,
)
return customer, customer_name, external_customer_id
@@ -490,7 +505,12 @@ def _build_external_order_data(
sync_user,
):
first = group_records[0]
customer, external_customer_name, external_customer_id = _resolve_external_customer(merchant=merchant, record=first)
first_with_context = dict(first)
first_with_context['_sync_user'] = sync_user
customer, external_customer_name, external_customer_id = _resolve_external_customer(
merchant=merchant,
record=first_with_context,
)
created_by_user, external_employee_name = _resolve_external_employee_user(
merchant=merchant,
external_employee_name=str(first.get('CaoZY') or '').strip(),
@@ -594,6 +614,126 @@ def _upsert_external_printing_job(*, merchant, printing_order, record: dict, syn
return job, True
def _sync_external_printing_records_batch(
*,
records: list[dict],
merchant,
sync_user,
category,
record_failure,
) -> dict:
orders_created = 0
orders_updated = 0
jobs_created = 0
jobs_updated = 0
failed_record_ids: list[int] = []
failed_records = 0
grouped_records: dict[str, list[dict]] = {}
if not records:
return {
'orders_created': 0,
'orders_updated': 0,
'jobs_created': 0,
'jobs_updated': 0,
'failed_records': 0,
'failed_record_ids': [],
'group_count': 0,
}
grouped_records = _group_external_records(records)
for external_order_id, group_records in grouped_records.items():
successful_records: list[dict] = []
for record in group_records:
try:
_ensure_external_product(
merchant=merchant,
external_product_name=str(record.get('YanSe') or '').strip(),
category=category,
)
except Exception as exc:
error_message = str(exc)
logger.warning(
'外部印染记录产品处理失败: external_record_id=%s external_order_id=%s error=%s',
record.get('ID'),
external_order_id,
error_message,
)
record_failure(record=record, error=error_message)
failed_records += 1
failed_record_ids.append(
_extract_positive_int(record.get('ID'), field_name='ID', allow_blank=False)
)
continue
successful_records.append(record)
if not successful_records:
continue
try:
order, order_created = _upsert_external_printing_order(
merchant=merchant,
external_order_id=external_order_id,
group_records=successful_records,
sync_user=sync_user,
)
if order_created:
orders_created += 1
else:
orders_updated += 1
except Exception as exc:
error_message = str(exc)
logger.warning(
'外部印染记录订单处理失败: external_order_id=%s error=%s',
external_order_id,
error_message,
)
for record in successful_records:
record_failure(record=record, error=error_message)
failed_records += 1
failed_record_ids.append(
_extract_positive_int(record.get('ID'), field_name='ID', allow_blank=False)
)
continue
for record in successful_records:
try:
_job, job_created = _upsert_external_printing_job(
merchant=merchant,
printing_order=order,
record=record,
sync_user=sync_user,
category=category,
)
if job_created:
jobs_created += 1
else:
jobs_updated += 1
except Exception as exc:
error_message = str(exc)
logger.warning(
'外部印染记录任务处理失败: external_record_id=%s external_order_id=%s error=%s',
record.get('ID'),
external_order_id,
error_message,
)
record_failure(record=record, error=error_message)
failed_records += 1
failed_record_ids.append(
_extract_positive_int(record.get('ID'), field_name='ID', allow_blank=False)
)
return {
'orders_created': orders_created,
'orders_updated': orders_updated,
'jobs_created': jobs_created,
'jobs_updated': jobs_updated,
'failed_records': failed_records,
'failed_record_ids': failed_record_ids,
'group_count': len(grouped_records),
}
def _run_fetch(page: int, page_size: int):
return asyncio.run(fetch_products_from_mingdaoyun(page=page, page_size=page_size))
@@ -1158,113 +1298,32 @@ def sync_external_printing_records(self, limit: int = 100):
last_record_id = payload.get('last_record_id')
run_date = timezone.localdate()
orders_created = 0
orders_updated = 0
jobs_created = 0
jobs_updated = 0
failed_record_ids: list[int] = []
failed_records = 0
if records:
grouped_records = _group_external_records(records)
for external_order_id, group_records in grouped_records.items():
successful_records: list[dict] = []
for record in group_records:
try:
_ensure_external_product(
merchant=merchant,
external_product_name=str(record.get('YanSe') or '').strip(),
category=category,
)
except Exception as exc:
error_message = str(exc)
logger.warning(
'外部印染记录产品处理失败: external_record_id=%s external_order_id=%s error=%s',
record.get('ID'),
external_order_id,
error_message,
)
_record_printing_external_sync_failure(
run_date=run_date,
record=record,
error=error_message,
)
failed_records += 1
failed_record_ids.append(
_extract_positive_int(record.get('ID'), field_name='ID', allow_blank=False)
)
continue
successful_records.append(record)
if not successful_records:
continue
try:
order, order_created = _upsert_external_printing_order(
merchant=merchant,
external_order_id=external_order_id,
group_records=successful_records,
sync_user=sync_user,
)
if order_created:
orders_created += 1
else:
orders_updated += 1
except Exception as exc:
error_message = str(exc)
logger.warning(
'外部印染记录订单处理失败: external_order_id=%s error=%s',
external_order_id,
error_message,
)
for record in successful_records:
_record_printing_external_sync_failure(
run_date=run_date,
record=record,
error=error_message,
)
failed_records += 1
failed_record_ids.append(
_extract_positive_int(record.get('ID'), field_name='ID', allow_blank=False)
)
continue
for record in successful_records:
try:
_job, job_created = _upsert_external_printing_job(
merchant=merchant,
printing_order=order,
record=record,
sync_user=sync_user,
category=category,
)
if job_created:
jobs_created += 1
else:
jobs_updated += 1
except Exception as exc:
error_message = str(exc)
logger.warning(
'外部印染记录任务处理失败: external_record_id=%s external_order_id=%s error=%s',
record.get('ID'),
external_order_id,
error_message,
)
_record_printing_external_sync_failure(
run_date=run_date,
record=record,
error=error_message,
)
failed_records += 1
failed_record_ids.append(
_extract_positive_int(record.get('ID'), field_name='ID', allow_blank=False)
)
batch_result = _sync_external_printing_records_batch(
records=records,
merchant=merchant,
sync_user=sync_user,
category=category,
record_failure=lambda *, record, error: _record_printing_external_sync_failure(
run_date=run_date,
record=record,
error=error,
),
)
cursor_payload = None
if last_record_id is not None:
cursor_payload = _advance_external_printing_cursor(cursor_value=int(last_record_id))
else:
grouped_records = {}
batch_result = {
'orders_created': 0,
'orders_updated': 0,
'jobs_created': 0,
'jobs_updated': 0,
'failed_records': 0,
'failed_record_ids': [],
'group_count': 0,
}
cursor_payload = None
api_models.DataSync.objects.create(
@@ -1282,17 +1341,17 @@ def sync_external_printing_records(self, limit: int = 100):
'limit': limit,
'mode': payload.get('mode'),
'count': len(records),
'orders_created': orders_created,
'orders_updated': orders_updated,
'jobs_created': jobs_created,
'jobs_updated': jobs_updated,
'failed_records': failed_records,
'failed_record_ids': failed_record_ids,
'orders_created': batch_result['orders_created'],
'orders_updated': batch_result['orders_updated'],
'jobs_created': batch_result['jobs_created'],
'jobs_updated': batch_result['jobs_updated'],
'failed_records': batch_result['failed_records'],
'failed_record_ids': batch_result['failed_record_ids'],
'last_record_id': last_record_id,
'cursor_before': payload.get('cursor_before'),
'cursor_after': payload.get('cursor_after'),
'cursor_updated': bool(cursor_payload),
'group_count': len(grouped_records),
'group_count': batch_result['group_count'],
}
logger.info('外部印染 records 同步完成: %s', result)
return result