1
0
forked from erp-dev/erp

fix: added name filter for api_man apis, fixed plate_orders search exclude id (only search via design_code)

This commit is contained in:
2025-12-09 14:15:31 +08:00
parent a36a7e5265
commit 86d0c916ca
8 changed files with 8391 additions and 35 deletions

View File

@@ -198,13 +198,13 @@ def _upsert_product(product_data, merchant, category):
@shared_task(bind=True)
def sync_mdy_products(self, page_size: int = 300, max_pages: int = 5, max_records: int | None = None):
def sync_mdy_products(self, page_size: int = 300, max_pages: int | None = None, max_records: int | None = None):
"""
从明道云同步产品数据
从明道云同步产品数据(按 ctime 升序遍历,依赖 last_ctime/rowid 游标)
"""
merchant = _get_mdy_merchant()
category = _get_mdy_category(merchant)
max_records = max_records or page_size
max_records = max_records or 0 # 0 表示不限制
last_sync = api_models.DataSync.objects.filter(
table_name=api_models.DataSync.TableName.PRODUCT
@@ -217,23 +217,29 @@ def sync_mdy_products(self, page_size: int = 300, max_pages: int = 5, max_record
total_count = 0
latest_ctime = last_ctime
latest_rowid = last_rowid
reached_existing = False
while page_index <= max_pages and synced_rows < max_records:
while True:
if max_pages is not None and page_index > max_pages:
break
if max_records and synced_rows >= max_records:
break
products, total = _run_fetch(page_index, page_size)
total_count = total
if not products:
break
for item in products:
if max_records and synced_rows >= max_records:
break
product_ctime = _parse_mdy_datetime(item.created_at)
# 跳过已同步到的游标
if last_ctime and product_ctime:
if product_ctime < last_ctime:
reached_existing = True
break
continue
if product_ctime == last_ctime and last_rowid and item.rowid == last_rowid:
reached_existing = True
break
continue
changed = _upsert_product(item, merchant, category)
if changed:
@@ -242,10 +248,8 @@ def sync_mdy_products(self, page_size: int = 300, max_pages: int = 5, max_record
latest_ctime = product_ctime
latest_rowid = item.rowid
if synced_rows >= max_records:
break
if reached_existing or synced_rows >= max_records or len(products) < page_size:
# 若返回不足一页,说明到尾部,可结束
if len(products) < page_size:
break
page_index += 1
@@ -259,7 +263,7 @@ def sync_mdy_products(self, page_size: int = 300, max_pages: int = 5, max_record
total_count=total_count,
last_ctime=record_last_ctime,
last_rowid=record_last_rowid,
note='reached existing data' if reached_existing else '',
note='asc scan',
)
payload = {
@@ -308,12 +312,12 @@ def _upsert_customer(customer_data, merchant):
@shared_task(bind=True)
def sync_mdy_customers(self, page_size: int = 300, max_pages: int = 5, max_records: int | None = None):
def sync_mdy_customers(self, page_size: int = 300, max_pages: int | None = None, max_records: int | None = None):
"""
从明道云同步客户数据
从明道云同步客户数据(按 ctime 升序遍历,依赖 last_ctime/rowid 游标)
"""
merchant = _get_mdy_merchant()
max_records = max_records or page_size
max_records = max_records or 0 # 0 表示不限制
last_sync = api_models.DataSync.objects.filter(
table_name=api_models.DataSync.TableName.CUSTOMER
@@ -326,23 +330,28 @@ def sync_mdy_customers(self, page_size: int = 300, max_pages: int = 5, max_recor
total_count = 0
latest_ctime = last_ctime
latest_rowid = last_rowid
reached_existing = False
while page_index <= max_pages and synced_rows < max_records:
while True:
if max_pages is not None and page_index > max_pages:
break
if max_records and synced_rows >= max_records:
break
customers, total = _run_fetch_customers(page_index, page_size)
total_count = total
if not customers:
break
for item in customers:
if max_records and synced_rows >= max_records:
break
record_ctime = _parse_mdy_datetime(item.created_at)
if last_ctime and record_ctime:
if record_ctime < last_ctime:
reached_existing = True
break
continue
if record_ctime == last_ctime and last_rowid and item.rowid == last_rowid:
reached_existing = True
break
continue
changed = _upsert_customer(item, merchant)
if changed:
@@ -351,10 +360,7 @@ def sync_mdy_customers(self, page_size: int = 300, max_pages: int = 5, max_recor
latest_ctime = record_ctime
latest_rowid = item.rowid
if synced_rows >= max_records:
break
if reached_existing or synced_rows >= max_records or len(customers) < page_size:
if len(customers) < page_size:
break
page_index += 1
@@ -368,7 +374,7 @@ def sync_mdy_customers(self, page_size: int = 300, max_pages: int = 5, max_recor
total_count=total_count,
last_ctime=record_last_ctime,
last_rowid=record_last_rowid,
note='reached existing data' if reached_existing else '',
note='asc scan',
)
payload = {

View File

@@ -8,6 +8,8 @@ from rest_framework.permissions import BasePermission
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.permissions import DjangoModelPermissions
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
from django.db.models import CharField
from django.db.models.functions import Cast, Coalesce
from django_filters.rest_framework import DjangoFilterBackend
from django_filters import rest_framework as django_filters
from django_filters import IsoDateTimeFilter
@@ -590,7 +592,8 @@ class PlateOrderViewSet(viewsets.ModelViewSet):
pagination_class = LimitOffsetPagination
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_class = PlateOrderFilterSet
search_fields = ['design_code', 'style_name', 'customer__name', 'fabric']
# design_code_normalized: 当 design_code 为空时用 id 兜底,便于搜索数字编号
search_fields = ['design_code', 'design_code_normalized', 'style_name', 'customer__name', 'fabric']
ordering_fields = [
'id', 'created_at', 'updated_at', 'plate_date',
'required_completion_date', 'completion_date',
@@ -618,6 +621,10 @@ class PlateOrderViewSet(viewsets.ModelViewSet):
queryset = super().get_queryset()
if self.action in ['list', 'retrieve']:
queryset = queryset.select_related('customer', 'salesperson', 'merchandiser', 'business_object')
# 为搜索提供 design_code 的兜底(为空时使用主键字符串)
queryset = queryset.annotate(
design_code_normalized=Coalesce('design_code', Cast('id', output_field=CharField()))
)
return queryset
def destroy(self, request, *args, **kwargs):