forked from erp-dev/erp
fix: change backfill product image
This commit is contained in:
@@ -2,11 +2,11 @@ from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db.models import Q
|
||||
|
||||
from api_v1.tasks import _fetch_external_product_image, _upload_product_image
|
||||
from basic_info.models import Product
|
||||
from printing.models import PrintingJob
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = '为 image 为空但 get_primary_image_url() 非空的 Product 通过外部 image API 回补图片'
|
||||
help = '为来自外部印染订单的生产子单所关联且 image 为空的 Product 通过 external_raw.YanSe 回补图片'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--merchant-id', type=int, help='仅处理指定商户的产品')
|
||||
@@ -18,24 +18,33 @@ class Command(BaseCommand):
|
||||
help='仅输出将处理的产品,不实际请求外部 API 或写库',
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _extract_request_name(job: PrintingJob) -> str:
|
||||
raw = job.external_raw or {}
|
||||
if isinstance(raw, dict):
|
||||
request_name = str(raw.get('YanSe') or '').strip()
|
||||
if request_name:
|
||||
return request_name
|
||||
return str(job.external_product_name or '').strip()
|
||||
|
||||
def handle(self, *args, **options):
|
||||
queryset = Product.objects.filter(
|
||||
Q(image__isnull=True) | Q(image=''),
|
||||
).exclude(
|
||||
name__isnull=True,
|
||||
).exclude(
|
||||
name='',
|
||||
).select_related('merchant')
|
||||
queryset = (
|
||||
PrintingJob.objects.filter(
|
||||
printing_order__external_order_id__isnull=False,
|
||||
)
|
||||
.exclude(printing_order__external_order_id='')
|
||||
.filter(Q(product__image__isnull=True) | Q(product__image=''))
|
||||
.select_related('product', 'printing_order', 'product__merchant')
|
||||
.order_by('-id')
|
||||
)
|
||||
|
||||
merchant_id = options.get('merchant_id')
|
||||
if merchant_id:
|
||||
queryset = queryset.filter(merchant_id=merchant_id)
|
||||
queryset = queryset.filter(product__merchant_id=merchant_id)
|
||||
|
||||
product_id = options.get('product_id')
|
||||
if product_id:
|
||||
queryset = queryset.filter(id=product_id)
|
||||
|
||||
queryset = queryset.order_by('-id')
|
||||
queryset = queryset.filter(product_id=product_id)
|
||||
|
||||
limit = options.get('limit')
|
||||
if limit is not None:
|
||||
@@ -45,44 +54,60 @@ class Command(BaseCommand):
|
||||
|
||||
success_count = 0
|
||||
failed_count = 0
|
||||
skipped_count = 0
|
||||
skipped_no_primary_count = 0
|
||||
skipped_with_image_count = 0
|
||||
skipped_without_request_name_count = 0
|
||||
skipped_duplicate_product_count = 0
|
||||
selected_count = 0
|
||||
scanned_count = 0
|
||||
dry_run = bool(options.get('dry_run'))
|
||||
seen_product_ids = set()
|
||||
|
||||
for product in queryset.iterator(chunk_size=1000):
|
||||
for job in queryset.iterator(chunk_size=1000):
|
||||
scanned_count += 1
|
||||
product = job.product
|
||||
if product.image:
|
||||
skipped_count += 1
|
||||
skipped_with_image_count += 1
|
||||
continue
|
||||
|
||||
if not product.get_primary_image_url():
|
||||
skipped_no_primary_count += 1
|
||||
if product.id in seen_product_ids:
|
||||
skipped_duplicate_product_count += 1
|
||||
continue
|
||||
|
||||
request_name = self._extract_request_name(job)
|
||||
if not request_name:
|
||||
skipped_without_request_name_count += 1
|
||||
continue
|
||||
|
||||
seen_product_ids.add(product.id)
|
||||
|
||||
selected_count += 1
|
||||
if dry_run:
|
||||
self.stdout.write(
|
||||
f'[DRY-RUN] product_id={product.id} merchant_id={product.merchant_id} name={product.name}'
|
||||
'[DRY-RUN] '
|
||||
f'job_id={job.id} '
|
||||
f'product_id={product.id} '
|
||||
f'merchant_id={product.merchant_id} '
|
||||
f'product_name={product.name} '
|
||||
f'request_name={request_name}'
|
||||
)
|
||||
else:
|
||||
try:
|
||||
image_payload = _fetch_external_product_image(product.name)
|
||||
image_payload = _fetch_external_product_image(request_name)
|
||||
_upload_product_image(product, image_payload)
|
||||
except Exception as exc:
|
||||
failed_count += 1
|
||||
self.stderr.write(
|
||||
self.style.ERROR(
|
||||
f'补图失败: product_id={product.id} merchant_id={product.merchant_id} '
|
||||
f'name={product.name} error={exc}'
|
||||
f'补图失败: job_id={job.id} product_id={product.id} merchant_id={product.merchant_id} '
|
||||
f'product_name={product.name} request_name={request_name} error={exc}'
|
||||
)
|
||||
)
|
||||
else:
|
||||
success_count += 1
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f'补图成功: product_id={product.id} merchant_id={product.merchant_id} name={product.name}'
|
||||
f'补图成功: job_id={job.id} product_id={product.id} merchant_id={product.merchant_id} '
|
||||
f'product_name={product.name} request_name={request_name}'
|
||||
)
|
||||
)
|
||||
|
||||
@@ -99,7 +124,8 @@ class Command(BaseCommand):
|
||||
f'selected={selected_count} '
|
||||
f'success={success_count} '
|
||||
f'failed={failed_count} '
|
||||
f'skipped_with_image={skipped_count} '
|
||||
f'skipped_without_primary_url={skipped_no_primary_count}'
|
||||
f'skipped_with_image={skipped_with_image_count} '
|
||||
f'skipped_without_request_name={skipped_without_request_name_count} '
|
||||
f'skipped_duplicate_product={skipped_duplicate_product_count}'
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user