# -*- coding: utf-8 -*- """订单ETL任务""" import json from .base_task import BaseTask, TaskContext from loaders.facts.order import OrderLoader from models.parsers import TypeParser class OrdersTask(BaseTask): """订单数据ETL任务""" def get_task_code(self) -> str: return "ORDERS" # ------------------------------------------------------------------ E/T/L hooks def extract(self, context: TaskContext) -> dict: """调用 API 拉取订单记录""" params = self._merge_common_params( { "siteId": context.store_id, "rangeStartTime": TypeParser.format_timestamp(context.window_start, self.tz), "rangeEndTime": TypeParser.format_timestamp(context.window_end, self.tz), } ) records, pages_meta = self.api.get_paginated( endpoint="/Site/GetAllOrderSettleList", params=params, page_size=self.config.get("api.page_size", 200), data_path=("data",), list_key="settleList", ) return {"records": records, "meta": pages_meta} def transform(self, extracted: dict, context: TaskContext) -> dict: """解析原始订单 JSON""" parsed_records = [] skipped = 0 for rec in extracted.get("records", []): parsed = self._parse_order(rec, context.store_id) if parsed: parsed_records.append(parsed) else: skipped += 1 return { "records": parsed_records, "fetched": len(extracted.get("records", [])), "skipped": skipped, } def load(self, transformed: dict, context: TaskContext) -> dict: """写入 fact_order""" loader = OrderLoader(self.db) inserted, updated, loader_skipped = loader.upsert_orders( transformed["records"], context.store_id ) counts = { "fetched": transformed["fetched"], "inserted": inserted, "updated": updated, "skipped": transformed["skipped"] + loader_skipped, "errors": 0, } return counts # ------------------------------------------------------------------ helpers def _parse_order(self, raw: dict, store_id: int) -> dict | None: """解析单条订单记录""" try: return { "store_id": store_id, "order_id": TypeParser.parse_int(raw.get("orderId")), "order_no": raw.get("orderNo"), "member_id": TypeParser.parse_int(raw.get("memberId")), "table_id": TypeParser.parse_int(raw.get("tableId")), "order_time": TypeParser.parse_timestamp(raw.get("orderTime"), self.tz), "end_time": TypeParser.parse_timestamp(raw.get("endTime"), self.tz), "total_amount": TypeParser.parse_decimal(raw.get("totalAmount")), "discount_amount": TypeParser.parse_decimal(raw.get("discountAmount")), "final_amount": TypeParser.parse_decimal(raw.get("finalAmount")), "pay_status": raw.get("payStatus"), "order_status": raw.get("orderStatus"), "remark": raw.get("remark"), "raw_data": json.dumps(raw, ensure_ascii=False), } except Exception as exc: self.logger.warning("解析订单失败: %s, 原始数据: %s", exc, raw) return None