调整 字段顺序、名称

This commit is contained in:
2026-04-22 17:12:37 +08:00
parent 86f120bc18
commit 7b45d04a6b
6 changed files with 56 additions and 50 deletions
+22 -32
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import json
import re
import time
import uuid
from typing import Any
@@ -160,6 +161,14 @@ class FeishuClient:
if data.get("code") != 0:
raise FeishuApiError(f"新增字段失败({payload.get('field_name')}): {data}")
def _is_managed_field(self, field_name: str) -> bool:
managed_names = {spec.feishu_name for spec in FIELD_SPECS}
managed_names.update(LEGACY_NAME_MAP.keys())
managed_names.update(LEGACY_NAME_MAP.values())
if field_name in managed_names:
return True
return bool(re.fullmatch(r"\d{1,2}月销售数量", field_name) or re.fullmatch(r"\d{6}销售数量", field_name))
def batch_delete_records(self, access_token: str, app_token: str, table_id: str, record_ids: list[str]) -> int:
deleted = 0
for start in range(0, len(record_ids), 500):
@@ -217,40 +226,21 @@ class FeishuClient:
self.update_field(access_token, app_token, table_id, primary_field["field_id"], payload)
time.sleep(0.2)
for old_name, new_name in LEGACY_NAME_MAP.items():
fields = self.list_fields(access_token, app_token, table_id)
field = next((item for item in fields if item.get("field_name") == old_name), None)
if field and old_name != new_name:
payload = {"field_name": new_name, "type": field.get("type")}
if field.get("property") is not None:
payload["property"] = field.get("property")
self.update_field(access_token, app_token, table_id, field["field_id"], payload)
fields = self.list_fields(access_token, app_token, table_id)
for field in fields:
field_name = field.get("field_name")
field_id = field.get("field_id")
if field.get("is_primary") or not field_name or not field_id:
continue
if self._is_managed_field(field_name):
self.delete_field(access_token, app_token, table_id, field_id)
time.sleep(0.2)
fields = self.list_fields(access_token, app_token, table_id)
fields_by_name = {field.get("field_name"): field for field in fields if field.get("field_name")}
for spec in FIELD_SPECS:
field = fields_by_name.get(spec.feishu_name)
if not field:
payload = {"field_name": spec.feishu_name, "type": spec.field_type}
if spec.formatter is not None:
payload["property"] = {"formatter": spec.formatter}
self.create_field(access_token, app_token, table_id, payload)
time.sleep(0.2)
fields = self.list_fields(access_token, app_token, table_id)
fields_by_name = {item.get("field_name"): item for item in fields if item.get("field_name")}
field = fields_by_name.get(spec.feishu_name)
if not field:
continue
current_formatter = (field.get("property") or {}).get("formatter")
if field.get("type") != spec.field_type or current_formatter != spec.formatter:
payload = {"field_name": spec.feishu_name, "type": spec.field_type}
if spec.formatter is not None:
payload["property"] = {"formatter": spec.formatter}
elif field.get("property") is not None:
payload["property"] = field.get("property")
self.update_field(access_token, app_token, table_id, field["field_id"], payload)
time.sleep(0.2)
payload = {"field_name": spec.feishu_name, "type": spec.field_type}
if spec.formatter is not None:
payload["property"] = {"formatter": spec.formatter}
self.create_field(access_token, app_token, table_id, payload)
time.sleep(0.2)
return [field.get("field_name") for field in self.list_fields(access_token, app_token, table_id) if field.get("field_name")]
+19 -6
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
from dataclasses import dataclass
from datetime import date
PRIMARY_FIELD_NAME = "货品编码"
@@ -26,19 +27,28 @@ BRAND_SYNC_TARGETS = [
BrandSyncTarget(brand_name="羽心堂", table_name="羽心堂"),
]
def month_sales_field_name(month_offset: int, today: date | None = None) -> str:
current = today or date.today()
month_index = current.year * 12 + current.month - 1 - month_offset
year = month_index // 12
month = month_index % 12 + 1
return f"{year}{month:02d}销售数量"
FIELD_SPECS = [
FieldSpec("品牌", "品牌名称", 1),
FieldSpec("分类", "一级分类", 1),
FieldSpec("产品类别", "货品简称", 1),
FieldSpec("货品名称", "商品名称", 1),
FieldSpec("分类", "一级分类", 1),
FieldSpec("条形码", "条形码", 1),
FieldSpec("零售价", "零售价", 2, "0.00", 2),
FieldSpec("店铺名称", "店铺名称", 1),
FieldSpec("店铺可用库存", "店铺挂单量", 2, "0", 0),
FieldSpec("总库存", "总库存", 2, "0", 0),
FieldSpec("本月销售数量", "本月销售数量", 2, "0", 0),
FieldSpec("上月销售数量", "上月销售数量", 2, "0", 0),
FieldSpec("上上月销售数量", "上上月销售数量", 2, "0", 0),
FieldSpec(month_sales_field_name(0), "本月销售数量", 2, "0", 0),
FieldSpec(month_sales_field_name(1), "上月销售数量", 2, "0", 0),
FieldSpec(month_sales_field_name(2), "上上月销售数量", 2, "0", 0),
FieldSpec("品牌", "品牌名称", 1),
FieldSpec("产品类别", "货品简称", 1),
]
LEGACY_NAME_MAP = {
@@ -47,5 +57,8 @@ LEGACY_NAME_MAP = {
"货品简称": "产品类别",
"商品名称": "货品名称",
"店铺挂单量": "店铺可用库存",
"本月销售数量": month_sales_field_name(0),
"上月销售数量": month_sales_field_name(1),
"上上月销售数量": month_sales_field_name(2),
"统一规格编码": PRIMARY_FIELD_NAME,
}
+3 -2
View File
@@ -54,6 +54,7 @@ shop_listing_latest AS (
sales_summary AS (
SELECT
fs."统一规格编码",
fs."店铺主键",
SUM(
CASE
WHEN fs."发货时间" >= date_trunc('month', now())
@@ -82,7 +83,7 @@ sales_summary AS (
WHERE NULLIF(TRIM(fs."统一规格编码"), '') IS NOT NULL
AND fs."发货时间" >= date_trunc('month', now()) - INTERVAL '2 month'
AND fs."发货时间" < date_trunc('month', now()) + INTERVAL '1 month'
GROUP BY fs."统一规格编码"
GROUP BY fs."统一规格编码", fs."店铺主键"
),
product_dim AS (
@@ -120,8 +121,8 @@ LEFT JOIN analytics_layer.dim_shop ds
ON sl."店铺主键" = ds."店铺主键"
LEFT JOIN sales_summary ss
ON sl."统一规格编码" = ss."统一规格编码"
AND sl."店铺主键" = ss."店铺主键"
LEFT JOIN product_dim pd
ON sl."统一规格编码" = pd."统一规格编码"
ORDER BY sl."统一规格编码", sl."店铺主键"
"""