from __future__ import annotations from typing import Any from asgiref.sync import sync_to_async from .client import MDY_ENDPOINT_GET_FILTER_ROWS, get_default_mingdaoyun_client from .mappings import ( MDY_WORKSHEET_ID_CUSTOMER, MDY_WORKSHEET_ID_FABRIC, MDY_WORKSHEET_ID_PLATE_ORDER, MDY_WORKSHEET_ID_PRODUCT, ) from .models import Customer, Fabric, Product from .parsers import pick_customer, pick_fabric, pick_product async def fetch_products_from_mingdaoyun(page: int = 1, page_size: int = 100) -> tuple[list[Product], int]: """从明道云获取产品列表""" client = get_default_mingdaoyun_client() response = await client.post( endpoint=MDY_ENDPOINT_GET_FILTER_ROWS, data={ "worksheetId": MDY_WORKSHEET_ID_PRODUCT, "pageIndex": page, "pageSize": page_size, "sortId": "ctime", "isAsc": True, }, ) data = response.get("data") if isinstance(response, dict) else None if data: print( f'[product-sync] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}' ) else: print(f"[product-sync] page={page} size={page_size} received empty data") if not data: return [], 0 products = [pick_product(item) for item in data.get("rows", [])] total_count = data.get("total", 0) return products, total_count async def fetch_customers_from_mingdaoyun(page: int = 1, page_size: int = 100) -> tuple[list[Customer], int]: """从明道云获取客户列表""" client = get_default_mingdaoyun_client() response = await client.post( endpoint=MDY_ENDPOINT_GET_FILTER_ROWS, data={ "worksheetId": MDY_WORKSHEET_ID_CUSTOMER, "pageIndex": page, "pageSize": page_size, "sortId": "ctime", "isAsc": True, }, ) data = response.get("data") if isinstance(response, dict) else None if data: print( f'[customer-sync] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}' ) else: print(f"[customer-sync] page={page} size={page_size} received empty data") if not data: return [], 0 customers = [pick_customer(item) for item in data.get("rows", [])] total_count = data.get("total", 0) return customers, total_count async def fetch_row_by_rowid_from_mingdaoyun( worksheet_id: str, rowid: str, *, sort_id: str = "ctime", is_asc: bool = False, list_type: int = 1, not_get_total: bool = True, data_type: int = 2, filter_type: int = 3, control_id: str = "rowId", ) -> dict[str, Any] | None: """按 rowId 查询工作表的单条记录(仅封装 rowId 等值查询)。 按照明道云 getFilterRows 的 filters 结构构造请求: - dataType=2 表示字符串 - filterType=3 表示“相等” 返回: - 匹配到记录:返回第一条 row dict - 未匹配或响应无 data:返回 None """ client = get_default_mingdaoyun_client() response = await client.post( endpoint=MDY_ENDPOINT_GET_FILTER_ROWS, data={ "worksheetId": worksheet_id, "listType": list_type, "sortId": sort_id, "isAsc": is_asc, "notGetTotal": not_get_total, "filters": [ { "controlId": control_id, "dataType": data_type, "filterType": filter_type, "value": rowid, } ], }, ) data = response.get("data") if isinstance(response, dict) else None if not data: return None rows = data.get("rows") or [] if not rows: return None if isinstance(rows[0], dict): return rows[0] return None async def fetch_plate_orders_from_mingdaoyun( page: int = 1, page_size: int = 100, *, sort_id: str = "ctime", is_asc: bool = True, ) -> tuple[list[dict[str, Any]], int]: """从明道云获取“开版数据表”记录列表(原始行字典,不做字段映射解析)""" client = get_default_mingdaoyun_client() response = await client.post( endpoint=MDY_ENDPOINT_GET_FILTER_ROWS, data={ "worksheetId": MDY_WORKSHEET_ID_PLATE_ORDER, "pageIndex": page, "pageSize": page_size, "sortId": sort_id, "isAsc": is_asc, }, ) data = response.get("data") if isinstance(response, dict) else None if data: print( f'[plate-order-fetch] page={page} size={page_size} rows={len(data.get("rows", []))} total={data.get("total")}' ) else: print(f"[plate-order-fetch] page={page} size={page_size} received empty data") if not data: return [], 0 rows = data.get("rows", []) total_count = data.get("total", 0) return rows, total_count async def sync_fabric_from_mingdaoyun(page: int = 1, page_size: int = 100) -> int: """从明道云同步面料数据(用于创建/更新 QuickInput: 布料名)""" client = get_default_mingdaoyun_client() response = await client.post( endpoint=MDY_ENDPOINT_GET_FILTER_ROWS, data={ "worksheetId": MDY_WORKSHEET_ID_FABRIC, "pageIndex": page, "pageSize": page_size, "sortId": "ctime", "isAsc": False, }, ) data = response.get("data") if isinstance(response, dict) else None if data: rows = data.get("rows", []) print(f"[fabric-sync] fetch rows={len(rows)} total={data.get('total')}") if rows: print(f"[fabric-sync] first row keys: {list(rows[0].keys())[:10]}") print(f"[fabric-sync] first row sample: {rows[0]}") else: print(f"[fabric-sync] fetch empty data (page={page}, size={page_size})") if not data: return 0 fabrics = [pick_fabric(item) for item in data.get("rows", [])] total_count = data.get("total", 0) await sync_to_async(_create_fabric_quick_inputs)( page, page_size, fabrics, ) return total_count def _create_fabric_quick_inputs(page: int, page_size: int, fabrics: list[Fabric]) -> None: from basic_info import models as basic_models total = len(fabrics) created_count = 0 sample_names = [fabric.name for fabric in fabrics[:5]] print(f"[fabric-sync] page={page} size={page_size} fetched={total}") print(f"[fabric-sync] sample names: {sample_names}") for fabric in fabrics: if not fabric.name: continue obj, created = basic_models.QuickInput.objects.update_or_create( name=fabric.name, group="布料名", defaults={"value": fabric.name}, ) if created: created_count += 1 print(f"[fabric-sync] page={page} new_records={created_count} updated_or_existing={total - created_count}")