1
0
forked from erp-dev/erp

feat: retry haobuye sync order

This commit is contained in:
2026-04-07 16:56:46 +08:00
parent ebd687ccdd
commit 76ea445880
15 changed files with 1098 additions and 118 deletions

View File

@@ -1,13 +1,6 @@
from datetime import date
from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone
from api_v1 import models as api_models
from api_v1.tasks import (
_get_printing_sync_product_category,
_get_printing_sync_user,
_sync_external_printing_records_batch,
retry_external_printing_sync_failures_impl,
)
@@ -32,100 +25,14 @@ class Command(BaseCommand):
def handle(self, *args, **options):
limit = options.get('limit')
if limit is not None:
limit = max(1, int(limit))
run_date_text = options.get('run_date')
record_ids = options.get('record_id') or []
sync_user = _get_printing_sync_user()
merchant = sync_user.employee.merchant
category = _get_printing_sync_product_category(merchant)
failures_qs = api_models.PrintingExternalSyncFailure.objects.all().order_by(
'external_record_id',
'-created_at',
'-id',
)
if run_date_text:
try:
failures_qs = failures_qs.filter(run_date=date.fromisoformat(run_date_text))
except ValueError as exc:
raise CommandError(f'--run-date 格式非法: {run_date_text}') from exc
if record_ids:
failures_qs = failures_qs.filter(external_record_id__in=record_ids)
selected_failures = []
selected_record_ids = set()
for failure in failures_qs:
if failure.external_record_id in selected_record_ids:
continue
selected_failures.append(failure)
selected_record_ids.add(failure.external_record_id)
if limit is not None and len(selected_failures) >= limit:
break
if not selected_failures:
self.stdout.write(self.style.SUCCESS(str({'retried_records': 0, 'message': '没有可重试的失败记录'})))
return
retry_records: list[dict] = []
failure_by_record_id: dict[int, api_models.PrintingExternalSyncFailure] = {}
skipped_records = 0
for failure in selected_failures:
raw = failure.raw or {}
if not isinstance(raw, dict) or not raw:
failure.error = '失败记录缺少原始 raw 数据,无法重试'
failure.attempts = int(failure.attempts or 0) + 1
failure.last_attempt_at = timezone.now()
failure.save(update_fields=['error', 'attempts', 'last_attempt_at', 'updated_at'])
skipped_records += 1
continue
retry_records.append(raw)
failure_by_record_id[failure.external_record_id] = failure
def _update_failure(*, record: dict, error: str):
external_record_id = int(record.get('ID') or 0)
failure = failure_by_record_id.get(external_record_id)
if not failure:
return
failure.error = error or ''
failure.raw = record
failure.attempts = int(failure.attempts or 0) + 1
failure.last_attempt_at = timezone.now()
failure.save(update_fields=['error', 'raw', 'attempts', 'last_attempt_at', 'updated_at'])
batch_result = _sync_external_printing_records_batch(
records=retry_records,
merchant=merchant,
sync_user=sync_user,
category=category,
record_failure=_update_failure,
)
failed_ids = set(batch_result['failed_record_ids'])
succeeded_ids = [record_id for record_id in failure_by_record_id.keys() if record_id not in failed_ids]
deleted_failures = 0
if succeeded_ids:
deleted_failures, _deleted_detail = api_models.PrintingExternalSyncFailure.objects.filter(
external_record_id__in=succeeded_ids
).delete()
remaining_failures = api_models.PrintingExternalSyncFailure.objects.count()
result = {
'limit': limit,
'retried_records': len(retry_records),
'skipped_records': skipped_records,
'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'],
'deleted_failures': deleted_failures,
'remaining_failures': remaining_failures,
}
self.stdout.write(self.style.SUCCESS(str(result)))
try:
result = retry_external_printing_sync_failures_impl(
limit=limit,
run_date_text=run_date_text,
record_ids=record_ids,
)
except ValueError as exc:
raise CommandError(f'--run-date 格式非法: {run_date_text}') from exc
self.stdout.write(self.style.SUCCESS(str(result)))