Files
gmv-analytics/__pycache__/project_bitable_common.cpython-312.pyc
T

679 lines
87 KiB
Plaintext
Raw Normal View History

Ë
2026-09-08 11:22:42 +08:00
ÕqKj‚ãóþ—ddlZddlZddlZddlmZddlmZddlmZmZm Z m
2026-04-10 18:35:01 +08:00
Z
ddl m Z ddl
mZddlmZddlmZddlZddlZdd lmZdd
lmZmZee«j7«j8Zed z Zed z Zd
2026-09-08 11:22:42 +08:00
Z dZ!gd¢Z"gd¢Z#ed¬«Gd„d««Z$e$dddd¬«e$dddd¬«dœZ%ed¬«Gd„d««Z&ed¬«Gd „d!««Z'ed¬«Gd"„d#««Z(ed¬«Gd$„d%««Z)ed¬«Gd&„d'««Z*eGd(„d)««Z+d*e,d+e,d,dfd-„Z-d+e,d,dfd.„Z.d+e,d,dfd/„Z/d’d0e0ed1e1d,e,fd2„Z2efd3ed,dfd4„Z3d,e,fd5„Z4d,efd6„Z5d,e,fd7„Z6d,e,fd8„Z7d,e,fd9„Z8d,e,fd:„Z9d,e,fd;„Z:d,e,fd<„Z;d=e0e<e,efd>e,d,e,fd?„Z=d@e,d,efdA„Z>d@e,d,e,fdB„Z?dCe,d,e,fdD„Z@dEe,d,e0e,fdF„ZAdGed,e<e,e,ffdH„ZBdIe,dJe<e,e,fd,e,fdK„ZCd,ejˆjŠfdL„ZFdMedNedOe$d,e0e&fdP„ZGdQe0e&dJe<e,e,fdOe$d,e<e,e<eHe1e1fe<ee<e,e fffffdR„ZIdMedNedSe<e,e<eHe1e1fe<ee<e,e ffffd,e<e,e<eHe1e1fe<ee<e,e fffffdT„ZJdUe*d,e+fdV„ZKd,e,fdW„ZLGdX„dY«ZMdZe,d,e<e,e,ffd[„ZNd\e,d]e,d^e,dMedNed,df d_„ZOd“d`e,dae,dzd,e,fdb„ZP d”dce,d]e,d^e,dMedNed`e,dae,dzd,dfdd„ZQ d“dee0e'dEe,dfe1dge1dhe<e,e,fdzd,e'f di„ZRd@e d,eSfdj„ZTdkedOe$d,e,fdl„ZUd@ed,eSdzfdm„ZVdMedNed,e0efdn„ZWdMedNed,e<eHe1e1fe0effdo„ZX d“d=e0e<e,efdpe,dqeYe,dzd,e0e<e,effdr„ZZdked,eYe,fds„Z[dteMdue'dpe,dqeYe,dzdve\d,df dw„Z]dMedNed^e,dpe,dxe,dve\dye\d,dfdz„Z^d{e+dMedNed,dfd|„Z_ d•d{e+dked}e\d~eYe,dzd,df
2026-04-10 18:35:01 +08:00
d„Z`dked^e,dpe,dxe,dve\dye\d,dfd€„ZadteMdue'dpe,d�e<ee<e,e ffdve\dOe$d,eHe(eYe,ffd‚„Zbd{e+dƒe,dMedNed,e)f
2026-09-08 11:22:42 +08:00
d„„Zcdƒe,dMedNed^e,d…edpe,dxe,dve\dye\d,dfd†„Zddked,e,fd‡„Zedked,e,fdˆ„Zfdked,e,fd‰„Zgd,e,fdŠ„ZhdteMdue'dked‹e,dve\d,eYe,f dŒ„Zid{e+dMedNed,e)fd�„ZjdMedNed^e,dpe,dve\dye\d,dfdŽ„Zkd{e+dked,dfd�„Zld{e+dked,dfd�„Zmd{e+dMedNed,dfd‘„Zny)–éN©Ú defaultdict)Ú dataclass)ÚdateÚdatetimeÚ timedeltaÚtimezone)ÚDecimal)ÚPath)ÚAny)Úurlparse)Ú
load_workbook)Ú
2026-09-08 11:22:42 +08:00
get_loggerÚ
setup_loggingz.envu店铺映射表.xlsxz
2026-04-01õ 店铺å��ç§°)u业务店铺å��ç§°ru 门店å��ç§°u店铺uå��ç§°©õ 大眼ç�›õ 羽心堂ÚMMMJÚEMõ 春回ç›�ú
BROKEN ZOOT)Úfrozencó6—eZdZUeed<eed<eed<eed<y)Ú MetricConfigÚnameÚ descriptionÚ sql_templateÚ field_suffixN©Ú__name__Ú
__module__Ú __qualname__ÚstrÚ__annotations__©óú>/Users/edy/YXT_Project/gmv-analytics/project_bitable_common.pyrrs…à
ƒIØÓØÓØÔr'rÚsalesu 销售é¢�u 总销售é¢�u
SET TIMEZONE = 'Asia/Shanghai';
WITH base_data AS (
2026-09-08 11:22:42 +08:00
SELECT
f.支付时间::DATE AS 统计日期,
2026-04-10 18:35:01 +08:00
f.店铺主键,
s.店铺�称 AS 原始店铺�称,
p.�牌�称,
p.商��称,
f.业务模�,
f.实付分摊金�
FROM analytics_layer.fact_sales f
LEFT JOIN analytics_layer.dim_shop s
ON f.店铺主键 = s.店铺主键
LEFT JOIN analytics_layer.dim_product p
ON f.商�主键 = p.商�主键
AND f.统一规格编� = p.统一规格编�
WHERE f.支付时间 >= %(start_ts)s
AND f.支付时间 < %(end_ts_exclusive)s
),
brand_split AS (
SELECT
2026-09-08 11:22:42 +08:00
统计日期,
店铺主键,
2026-04-10 18:35:01 +08:00
原始店铺�称,
2026-09-08 11:22:42 +08:00
业务模�,
CASE
2026-09-08 11:22:42 +08:00
WHEN COALESCE(原始店铺�称, '') LIKE '%%羽心堂分销%%'
THEN '羽心堂分销'
2026-09-08 11:22:42 +08:00
WHEN 店铺主键 IN (1,28,29) AND COALESCE(�牌�称, '') LIKE '羽心堂'
2026-09-08 11:22:42 +08:00
THEN 原始店铺�称 || '_羽心堂'
WHEN 店铺主键 IN (1,28,29) AND COALESCE(�牌�称, '') LIKE '春回�'
THEN 原始店铺�称 || '_春回�'
WHEN 店铺主键 IN (1,28,29) AND COALESCE(�牌�称, '') LIKE 'Mama Mujer'
THEN 原始店铺�称 || '_Mama Mujer'
WHEN 店铺主键 IN (1,28,29)
AND (
2026-09-08 11:22:42 +08:00
COALESCE(�牌�称, '') LIKE 'ERBA MIGINA'
OR COALESCE(商��称, '') ILIKE '%%ERBA MIGINA%%'
OR COALESCE(商��称, '') ~* '(^|[^A-Za-z])EM([^A-Za-z]|$)'
)
2026-04-10 18:35:01 +08:00
THEN 原始店铺�称 || '_ERBA MIGINA'
2026-09-08 11:22:42 +08:00
WHEN 店铺主键 IN (1,28,29) AND COALESCE(�牌�称, '') LIKE 'BROKEN ZOO'
THEN 原始店铺�称 || '_BROKEN ZOO'
2026-09-08 11:22:42 +08:00
WHEN 店铺主键 IN (1,28,29)
THEN 原始店铺�称 || '_其他'
WHEN 店铺主键 IN (3,9) AND COALESCE(�牌�称, '') LIKE '羽心堂'
2026-04-10 18:35:01 +08:00
THEN 原始店铺�称 || '_羽心堂'
WHEN 店铺主键 IN (3,9) AND COALESCE(�牌�称, '') LIKE 'Mama Mujer'
THEN 原始店铺�称 || '_Mama Mujer'
2026-04-10 18:35:01 +08:00
WHEN 店铺主键 IN (3,9)
THEN 原始店铺�称 || '_其他'
2026-04-10 18:35:01 +08:00
WHEN 店铺主键 IS NULL OR 原始店铺�称 IS NULL
2026-04-10 18:35:01 +08:00
THEN '分销/SEEDING'
ELSE 原始店铺�称
2026-04-10 18:35:01 +08:00
END AS 店铺�称,
实付分摊金�
FROM base_data
),
2026-04-10 18:35:01 +08:00
shop_brand_detail AS (
SELECT
统计日期,
2026-09-08 11:22:42 +08:00
店铺主键,
店铺�称,
SUM(实付分摊金�) AS 总销售�
FROM brand_split
GROUP BY 1,2,3
),
union_data AS (
SELECT
统计日期,
店铺�称,
总销售�
FROM shop_brand_detail
WHERE NOT (
店铺主键 IN (1,9,28,29)
AND 店铺�称 LIKE '%%_其他'
)
UNION ALL
SELECT
统计日期,
原始店铺�称 AS 店铺�称,
SUM(实付分摊金�) AS 总销售�
FROM base_data
WHERE 店铺主键 IN (1,28,29,3)
GROUP BY 1,2
UNION ALL
SELECT
统计日期,
原始店铺�称 || '_�益金' AS 店铺�称,
SUM(实付分摊金�) AS 总销售�
2026-04-10 18:35:01 +08:00
FROM base_data
WHERE 店铺主键 IN (5,11,14,22,26)
AND 业务模� = '充值购物金'
GROUP BY 1,2
2026-09-08 11:22:42 +08:00
)
SELECT
统计日期,
2026-04-10 18:35:01 +08:00
店铺�称,
2026-09-08 11:22:42 +08:00
SUM(总销售�) AS 总销售�
FROM union_data
2026-09-08 11:22:42 +08:00
GROUP BY 1,2
ORDER BY 统计日期 DESC, 总销售� DESC;
)rrrrÚrefundu 退款é¢�uÔ
SET TIMEZONE = 'Asia/Shanghai';
WITH sales_base AS (
SELECT
fs.*,
TRIM(fs."平�订��") AS "原平�订��",
split_part(TRIM(fs."平�订��"), '-', 1) AS "主订��"
FROM analytics_layer.fact_sales fs
WHERE fs."订�状�" IN ('已关闭', '已�消', '交易关闭')
AND NULLIF(TRIM(fs."平�订��"), '') IS NOT NULL
AND fs."支付时间" IS NOT NULL
AND fs."支付时间" >= %(start_ts)s
AND fs."支付时间" < %(end_ts_exclusive)s
),
missing_order_keys AS (
SELECT DISTINCT
sb."主订��"
FROM sales_base sb
WHERE NOT EXISTS (
SELECT 1
FROM analytics_layer.fact_returns fr
WHERE split_part(TRIM(fr."平�订��"), '-', 1) = sb."主订��"
AND NULLIF(TRIM(fr."平�订��"), '') IS NOT NULL
)
),
missing_return_sales AS (
SELECT
sb."支付时间"::DATE AS 统计日期,
sb."店铺主键",
SUM(sb."实付分摊金�") AS 补充退款金�
FROM sales_base sb
JOIN missing_order_keys mok
ON sb."主订��" = mok."主订��"
WHERE sb."店铺主键" NOT IN (5,11,14,22,26)
GROUP BY
sb."支付时间"::DATE,
sb."店铺主键"
),
2026-04-10 18:35:01 +08:00
base_data AS (
SELECT
2026-09-08 11:22:42 +08:00
f.完结时间::DATE AS 统计日期,
2026-04-10 18:35:01 +08:00
f.店铺主键,
f.平�订��,
s.店铺�称 AS 原始店铺�称,
p.�牌�称,
p.商��称,
f.退款金�
FROM analytics_layer.fact_returns f
LEFT JOIN analytics_layer.dim_shop s
ON f.店铺主键 = s.店铺主键
LEFT JOIN analytics_layer.dim_product p
2026-04-10 18:35:01 +08:00
ON f.商�主键 = p.商�主键
2026-09-08 11:22:42 +08:00
AND f.统一规格编� = p.统一规格编�
WHERE f.完结时间 >= %(start_ts)s
AND f.完结时间 < %(end_ts_exclusive)s
),
sales_order_flag AS (
SELECT
fs.平�订��,
fs.店铺主键,
TRUE AS 订�存在于销售表,
BOOL_OR(fs.业务模� = '充值购物金') AS 是�充值购物金订�
FROM analytics_layer.fact_sales fs
INNER JOIN (
SELECT DISTINCT
平�订��,
店铺主键
FROM base_data
WHERE 店铺主键 IN (5,11,14,22,26)
) r
2026-04-10 18:35:01 +08:00
ON fs.平�订�� = r.平�订��
AND fs.店铺主键 = r.店铺主键
GROUP BY
fs.平�订��,
fs.店铺主键
),
brand_split AS (
2026-04-10 18:35:01 +08:00
SELECT
2026-09-08 11:22:42 +08:00
统计日期,
店铺主键,
2026-09-08 11:22:42 +08:00
原始店铺�称,
CASE
2026-09-08 11:22:42 +08:00
WHEN 店铺主键 IN (1,28,29) AND COALESCE(�牌�称, '') LIKE '羽心堂'
2026-09-08 11:22:42 +08:00
THEN 原始店铺�称 || '_羽心堂'
WHEN 店铺主键 IN (1,28,29) AND COALESCE(�牌�称, '') LIKE '春回�'
THEN 原始店铺�称 || '_春回�'
WHEN 店铺主键 IN (1,28,29) AND COALESCE(�牌�称, '') LIKE 'Mama Mujer'
THEN 原始店铺�称 || '_Mama Mujer'
WHEN 店铺主键 IN (1,28,29)
AND (
2026-09-08 11:22:42 +08:00
COALESCE(�牌�称, '') LIKE 'ERBA MIGINA'
OR COALESCE(商��称, '') ILIKE '%%ERBA MIGINA%%'
OR COALESCE(商��称, '') ~* '(^|[^A-Za-z])EM([^A-Za-z]|$)'
)
2026-04-10 18:35:01 +08:00
THEN 原始店铺�称 || '_ERBA MIGINA'
2026-09-08 11:22:42 +08:00
WHEN 店铺主键 IN (1,28,29) AND COALESCE(�牌�称, '') LIKE 'BROKEN ZOO'
THEN 原始店铺�称 || '_BROKEN ZOO'
2026-09-08 11:22:42 +08:00
WHEN 店铺主键 IN (1,28,29)
THEN 原始店铺�称 || '_其他'
WHEN 店铺主键 IN (3,9) AND COALESCE(�牌�称, '') LIKE '羽心堂'
2026-04-10 18:35:01 +08:00
THEN 原始店铺�称 || '_羽心堂'
WHEN 店铺主键 IN (3,9) AND COALESCE(�牌�称, '') LIKE 'Mama Mujer'
THEN 原始店铺�称 || '_Mama Mujer'
2026-04-10 18:35:01 +08:00
WHEN 店铺主键 IN (3,9)
THEN 原始店铺�称 || '_其他'
2026-04-10 18:35:01 +08:00
WHEN 店铺主键 IS NULL OR 原始店铺�称 IS NULL
THEN '分销/SEEDING'
2026-04-10 18:35:01 +08:00
ELSE 原始店铺�称
END AS 店铺�称,
退款金�
FROM base_data
),
2026-04-10 18:35:01 +08:00
shop_brand_detail AS (
SELECT
统计日期,
2026-09-08 11:22:42 +08:00
店铺主键,
店铺�称,
SUM(退款金�) AS 总退款金�
FROM brand_split
GROUP BY 1,2,3
),
union_data AS (
SELECT
统计日期,
店铺�称,
总退款金�
FROM shop_brand_detail
WHERE NOT (
店铺主键 IN (1,9,28,29)
AND 店铺�称 LIKE '%%_其他'
)
UNION ALL
SELECT
统计日期,
原始店铺�称 AS 店铺�称,
SUM(退款金�) AS 总退款金�
FROM base_data
WHERE 店铺主键 IN (1,28,29,3)
GROUP BY 1,2
UNION ALL
SELECT
r.统计日期,
r.原始店铺�称 || '_�益金' AS 店铺�称,
SUM(r.退款金�) AS 总退款金�
FROM base_data r
LEFT JOIN sales_order_flag sof
ON r.平�订�� = sof.平�订��
AND r.店铺主键 = sof.店铺主键
WHERE r.店铺主键 IN (5,11,14,22,26)
AND (
sof.订�存在于销售表 IS NULL
OR sof.是�充值购物金订� = TRUE
)
GROUP BY 1,2
UNION ALL
SELECT
mrs.统计日期,
COALESCE(s.店铺�称, '未知店铺') AS 店铺�称,
SUM(mrs.补充退款金�) AS 总退款金�
2026-04-10 18:35:01 +08:00
FROM missing_return_sales mrs
LEFT JOIN analytics_layer.dim_shop s
ON mrs.店铺主键 = s.店铺主键
GROUP BY 1,2
2026-09-08 11:22:42 +08:00
)
SELECT
统计日期,
2026-09-08 11:22:42 +08:00
店铺�称,
2026-04-10 18:35:01 +08:00
SUM(总退款金�) AS 总退款金�
FROM union_data
2026-09-08 11:22:42 +08:00
GROUP BY
统计日期,
店铺�称
2026-03-17 10:49:42 +08:00
ORDER BY 统计日期 DESC, 总退款金� DESC;
2026-09-08 11:22:42 +08:00
©r)r*có,—eZdZUeed<eed<eed<y)Ú MetricRowÚ stat_dateÚ
bi_store_nameÚamountN)r!r"r#rr%r$r
r&r'r(r-r-gs…àƒOØÓØ „Or'r-có"—eZdZUeed<eed<y)Ú TableInfoÚtable_idrNr r&r'r(r2r2ns …àƒMØ
2026-04-10 18:35:01 +08:00
2026-09-08 11:22:42 +08:00
„Ir'r2có.—eZdZUeeed<eeed<y)Ú
SyncResultÚsql_only_storesÚfeishu_only_storesN)r!r"r#Úlistr$r%r&r'r(r5r5ts…à˜#‘YÓØ˜S™ Ô!r'r5có—eZdZUeeed<y)ÚMetricSyncArtifactsÚcreated_fieldsN)r!r"r#Úsetr$r%r&r'r(r:r:zs …à˜‘HÔr'r:cót—eZdZUeed<eed<eed<eed<eed<eed<dZeed<dZeed <dZ eed
<y ) ÚDailySyncConfigÚbase_urlÚ mapping_fileÚstore_field_nameÚtable_map_fileÚdry_runÚskip_missing_tablesÚÚchat_idÚreport_image_pathÚ
group_webhookN)
r!r"r#r$r%r ÚboolrFrGrHr&r'r(r>r>sC…àƒMØÓØÓØÓØ
2026-09-08 11:22:42 +08:00
ƒMØÓØ€GˆSÓØÐ�sÓØ€M�3Ôr'r>cóZ—eZdZUded<eded<eeefed<eeefed<eed<y) ÚDailySyncContextÚFeishuBitableClientÚclientr2ÚtablesÚmappingÚtable_overridesÚconfigN)r!r"r#r%r8Údictr$r>r&r'r(rKrKŒs5…à !Ó!Ø �Ñ ÓØ
�#�s�(‰^ÓØ˜#˜s˜(‘^Ó#Ø Ôr'rKÚ
level_nameÚmessageÚreturncóœ— ddlm}|«}t||j «d«}t |«r ||«yy#t$rYywxYw)Nr)Úget_run_logger)Úprefect.loggingrWÚ ExceptionÚgetattrÚlowerÚcallable)rSrTrWÚprefect_loggerÚ
log_methods r(Ú_log_to_prefectr_•sT€ðÝ2á'Ó)ˆô˜¨×)9Ñ)9Ó);¸TÓB€JÜ�
2026-09-08 11:22:42 +08:00
ÔÙ�7Õðøô òÙðús‚
?¿ A Á
A cóN—t«j|«td|«y)NÚINFO)rÚinfor_©rTs r(Úlog_steprd¡s€ÜƒL×Ñ�gÔÜ�F˜GÕ$r'cóN—t«j|«td|«y)NÚDEBUG)rÚdebugr_rcs r(Ú log_debugrh¦s€ÜƒL×Ñ�wÔÜ�G˜WÕ%r'ÚvaluesÚlimitcó\—t|«|kr t|«S|d|›dt|«›d�S)Nu ... å…±u项)Úlenr$)rirjs r(Ú preview_listrm«s6€Ü
ˆ6ƒ{�eÒÜ�6‹{ÐØ�V�eˆnÐ
˜X¤c¨&£k ]°#Ð 6Ð6r'Úenv_filecó²—|j«std|›�«ytd|›�«|jd¬«j«D]{}|j «}|r|j d«sd|vrŒ+|j
2026-09-08 11:22:42 +08:00
dd«\}}tjj|j «|j ««Œ}td¬ «y)
Nu&未找到 .env 文件,跳过加载: u加载环境å�˜é‡�: úutf-8©ÚencodingÚ#Ú=éT)Úforce) ÚexistsrdÚ read_textÚ
splitlinesÚstripÚ
startswithÚsplitÚosÚenvironÚ
2026-09-08 11:22:42 +08:00
setdefaultr)rnÚraw_lineÚlineÚkeyÚvalues r(Ú load_dotenvr„±s²€Ø �?‰?Ô ÜÐ9¸(¸ÐDÔEØÜ Ð# H :Ð
.Ô/Ø×&Ñ&°Ð&Ó8×CÑCÖEˆØ�~‰~ÓˆÙ�t—‘ sÔ+¨s¸$©Ø Ø—Z‘Z  QÓ'‰
ˆˆUÜ
�
2026-09-08 11:22:42 +08:00
‰
×јcŸi™i›k¨5¯;©;«=Õ9ð Fô ˜Ör'cóJ—tjd«}|s td«‚|S)NÚFEISHU_BASE_URLu"缺少环境å�˜é‡� FEISHU_BASE_URL)r}ÚgetenvÚ
ValueError)r?s r(Ú get_base_urlr‰¿s%€Ü�y‰yÐ*Ó+€HÙ ÜÐ=Ó>Ð>Ø €Or'cóZ—ttjdtt«««S)NÚPROJECT_MAPPING_FILE)r r}r‡r$ÚDEFAULT_MAPPING_FILEr&r'r(Úget_mapping_filer�Æs€Ü ”— ‘ Ð0´#Ô6JÓ2KÓLÓ MÐMr'có6—tjdt«S)NÚFEISHU_STORE_FIELD_NAME)r}r‡ÚDEFAULT_STORE_FIELD_NAMEr&r'r(Úget_store_field_namer‘Ês€Ü
�9‰9Ð.Ô0HÓ IÐIr'có6—tjdt«S)NÚSYNC_START_DATE)r}r‡ÚDEFAULT_START_DATEr&r'r(Úget_default_start_dater•Îs€Ü
�9‰9Ð&Ô(:Ó ;Ð;r'có`—tj«td¬«z
j«S©Nru©Údays)rÚtodayrÚ isoformatr&r'r(Úget_default_end_daterœÒs!€Ü �J‰J‹Lœ9¨!Ô,Ñ ,× 7Ñ 7Ó 9Ð9r'cóP—gd¢}|D]}tj|«}|sŒ|cSy)N)ÚFEISHU_BOT_WEBHOOKÚFEISHU_ROBOT_WEBHOOKÚFEISHU_WEBHOOKÚLARK_BOT_WEBHOOKÚLARK_ROBOT_WEBHOOKÚ
GROUP_WEBHOOKrE©r}r‡)Ú
candidatesr‚rƒs r(Úget_group_webhook_urlr¦Ös/€ò€JóˆÜ— ‘ ˜#“ˆÚ ØŠLðð r'có.—tjdd«S)NÚFEISHU_CHAT_IDrEr¤r&r'r(Úget_feishu_chat_idr©æs€Ü
�9‰9Ð% rÓ *Ð*r'có.—tjdd«S)NÚFEISHU_REPORT_IMAGE_PATHrEr¤r&r'r(Úget_feishu_report_image_pathr¬ês€Ü
�9‰9Ð/°Ó 4Ð4r'ÚfieldsÚpreferred_field_namecó¶—|D�cgc] }t|jd«xsd«‘Œ"}}||vr|StD]
2026-09-08 11:22:42 +08:00
}||vsŒ|cStd|›d|›�«‚cc}w)NÚ
field_namerEu'未找到店铺å��称字段: preferred=u, å�¯ç”¨å­—段=)r$ÚgetÚSTORE_FIELD_CANDIDATESrˆ)r­r®ÚitemÚ field_namesÚ candidates r(Úresolve_store_field_namer¶îsu€ÙAGÓHÁ¸”3�t—x‘x  Ó-Ò3°Õ4À€KÐHؘ{Ñ*Ø#Ð#ß+ˆ Ø ˜ Ò #ØÒ ð,ô Ð>Ð?SÐ>TÐTcÐdoÐcpÐqÓ
rÐrùò
Is…%ArƒcóJ—tj|d«j«S)Nz%Y-%m-%d)rÚstrptimer©rƒs r(Ú
validate_daterºøs€Ü × Ñ ˜U JÓ /× 4Ñ 4Ó 6Ð6r'cóT—tjdd|xsd«j«S)Nu[\s_\-()()]+rE)ÚreÚsubr[r¹s r(Únormalize_textr¾üs#€Ü
2026-09-08 11:22:42 +08:00
�6‰6Ð% r¨5ª;°BÓ 7× =Ñ =Ó ?Ð?r'Ú
store_namec󘇗|xsdŠdgd¢fddgfdddgfddgfddgfg}|D]\}}tˆfd „|D««sŒ|cSd
‰vsd ‰vry
y) NrEr)ÚMamaÚmmmjrrrú ERBA MIGINArrc3ó&•K—|]}|‰v–—Œ
y­w©Nr&)Ú.0Úkeywordrs €r(Ú <genexpr>z#classify_project.<locals>.<genexpr>
2026-09-08 11:22:42 +08:00
søèø€Ð7©h 7ˆw˜$Œ©hùóƒru大西瓜籽妈妈)Úany)r¿Úprioritized_rulesÚprojectÚkeywordsrs @r(Úclassify_projectrÎs…ø€Ø Ò ˜€Dà Ò)Ð*Ø �{�mÐ$Ø
��mÐ$Ð%Ø �{�mÐ$Ø ˜ �~Ð&ð Ðó/ш�Ü Ó7©hÓ7Õ 7ØŠNð/ð�dÑÐ2°dÑ:ØØ
2026-09-08 11:22:42 +08:00
r'rÌcóL—dgdggd¢ddgdggd¢dœ}|j||g«S) Nu大眼ç�›ä¹°ä¹°ä¹°r)rz
Mama Mujerz
MAMA MUJERrrÃr)rÚ BROKENZOOu 葆ç¦�颂r©r±)rÌÚaliasess r(Úget_project_table_aliasesrÓs<€à*Ð+Ø!�]Ú4Ø�]Ð#Ø!�]Ú>ñ
€Gð �;‰;�w   Ó *Ð*r'ÚpathcóŽ—td|›�«t|d¬«}|j}i}|jdd¬«D]m}|sŒt |«dk\r
|dd\}}}nt |«dk\r |dd\}}nŒ6|r|sŒ;t |«j
2026-09-08 11:22:42 +08:00
«|t |«j
«<Œotdt |«›d�«|S) Nu加载店铺映射表: T)Ú data_onlyé)Úmin_rowÚ values_onlyéu店铺映射加载完æˆ�: õ æ�¡)rdrÚactiveÚ iter_rowsrlr$rz)rÔÚwbÚwsrOÚrowÚ_Ú
business_nameÚbi_names r(Úload_store_mappingräs΀Ü Ð& t fÐ
-Ô.Ü �t tÔ ,€BØ �‰€BØ €GØ�|‰| A°4ˆ|Ö8ˆÙØ Ü ˆs‹8�qŠ=Ø(+¨B¨Q¨Ñ %ˆAˆ}™gÜ
�‹X˜Š]Ø%(¨¨! WÑ "ˆM™7à Ù¡GØ Ü(+¨MÓ(:×(@Ñ(@Ó(Bˆ”�G“ ×"Ñ"Ó$Ò%ð9ô
Ð)¬#¨g«,¨°tÐ
<Ô=Ø €Nr'r/Ú
store_mappingcó&—|j|d«S©NrErÑ)r/rås r(Úresolve_business_store_namerè2s€Ø × Ñ ˜]¨BÓ /Ð/r'c ó—gd¢}|D�cgc]}tj|«rŒ|‘Œ}}|rtddj|«›�«‚t dtj
d›dtj
2026-09-08 11:22:42 +08:00
d›dtj
d ›�«t
jtj
dtj
2026-03-16 14:21:12 +08:00
dtj
2026-09-08 11:22:42 +08:00
d
tj
2026-04-10 18:35:01 +08:00
d tj
d ¬ «Scc}w)
N)ÚANALYTICS_DB_HOSTÚANALYTICS_DB_PORTÚANALYTICS_DB_USERÚANALYTICS_DB_PASSWORDÚANALYTICS_DB_NAMEu缺少数æ�®åº“环境å�˜é‡�: ú, u连接 PostgreSQL: host=rêz port=rëz db=rîrìrí)ÚhostÚportÚuserÚpasswordÚdbname)r}r‡rˆÚjoinrdr~Úpsycopg2Úconnect)Úrequiredr‚Úmissings r(Úget_db_connectionrú6sö€ò€Hñ'Ó=™h�s¬b¯i©i¸­nŠs˜h€GÐ=ÙÜÐ8¸¿¹À7Ó9KÐ8LÐMÓNÐNÜ Ø
"¤2§:¡:Ð.AÑ#BÐ"CÀ6Ì"Ï*É*ÐUhÑJiÐIjÐjnÔoq×oyÑoyð{NñpOðoPð Qôô × Ñ Ü
�Z‰ZÐ+Ñ
2026-09-08 11:22:42 +08:00
,Ü
�Z‰ZÐ+Ñ
2026-04-10 18:35:01 +08:00
,Ü
2026-09-08 11:22:42 +08:00
�Z‰ZÐ+Ñ
,Ü—‘Ð3Ñ4Ü�z‰zÐ-Ñ.ô  ðùò
>s
2026-09-08 11:22:42 +08:00
‰C?¤C?Ú
start_dateÚend_dateÚ
2026-03-17 10:49:42 +08:00
metric_configc
2026-09-08 11:22:42 +08:00
óf—|j«›d�}|td¬«zj«›d�}td|j›d|›d|›d�«t «5}|j «5}|j
|j||dœ«|j«}ddd«ddd«t|j›d t«›d
�«|D�cgc]8}t|d |dxsd j«|d
xs td«¬«‘Œ:c}S#1swYŒyxYw#1swYŒ}xYwcc}w)Nz 00:00:00rur˜u 开始查询z: ú -> u (å�³å¼€åŒºé—´))Ústart_tsÚend_ts_exclusiveu查询完æˆ�: u 行rrEr×Ú0)r.r/r0)
r›rrdrrúÚcursorÚexecuterÚfetchallrlr-rzr
) rûrürýrrÚconnÚcurÚrowsràs r(Úfetch_metric_rowsr Ms,€Ø×&Ñ&Ó(Ð)¨Ð3€HØ#¤i°QÔ&7Ñ7×BÑBÓDÐEÀYÐOÐÜ ˆ|˜M×5Ñ5Ð6°b¸¸
À$ÐGWÐFXÐXgÐ
hÔiÜ Ô  Ø
�[‰[Œ]˜cØ �K‰K˜
2026-09-08 11:22:42 +08:00
×2Ñ2ÀÐ_oÑ4pÔ qØ—<‘<“>ˆD÷÷
ô
�
×)Ñ)Ð*¨.¼¸T»¸ À4Ð
2026-03-17 10:49:42 +08:00
HÔIñó áˆCô ˜C ™F°3°q±6²<¸R×2FÑ2FÓ2HÐQTÐUVÑQWÒQgÔ[bÐcfÓ[gÖhØñ ð÷ ˆ]ú÷
Ð üò
2026-09-08 11:22:42 +08:00
 s*ÁD"Á.0DÂD"Ã=D.ÄD ÄD"Ä"D+rcó8—td|j›�«td„«}|D]¨}t|j|«}|sŒt |«}|sŒ*|j j|j jf}||||j j|td««}||jz||||j |<Œªt|«} td„|j«D««}
2026-03-17 10:49:42 +08:00
t|j›d| ›d|
2026-09-08 11:22:42 +08:00
›�«|S)Nu 开始按项目/月/日期è�šå�ˆcó—td„«S)Ncó —tt«SrÅ)rrRr&r'r(Ú<lambda>z9build_project_metrics.<locals>.<lambda>.<locals>.<lambda>cs €¤K´Ô$5r'rr&r'r(r
z'build_project_metrics.<locals>.<lambda>cs
€” Ñ5Ô6r'rc3ó2K—|]}t|«–—Œy­wrÅ)rl)rÆÚmonthss r(rÈz(build_project_metrics.<locals>.<genexpr>psèø€ÐAÑ0@ f”c˜&—kÑ0@ùó‚uè�šå�ˆå®Œæˆ�: 项目=u,项目月份组å�ˆ=)rdrrrèr/rÎr.ÚyearÚmonthr±r
2026-09-08 11:22:42 +08:00
r0rlÚsumri) rrårýÚgroupedràÚbusiness_store_namerÌÚ month_keyÚcurrent_amountÚ
2026-04-10 18:35:01 +08:00
project_countÚ month_counts r(Úbuild_project_metricsr\s€ô
2026-09-08 11:22:42 +08:00

2026-04-10 18:35:01 +08:00
Ð/°
2026-09-08 11:22:42 +08:00
×0IÑ0IÐ/JÐ
2026-04-10 18:35:01 +08:00
KÔLÜP[Ù6óQ€GóˆÜ9¸#×:KÑ:KÈ]Ó[ÐÙ"Ø Ü"Ð#6Ó7ˆÙØ Ø—]‘]×'Ñ'¨¯©×)<Ñ)<Ð=ˆ Ø  Ñ)¨)Ñ4°S·]±]ÑC×GÑGÐH[Ô]dÐehÓ]iÓjˆØJXÐ[^×[eÑ[eÑJeˆ�јÑ# C§M¡MÑ2Ð3FÒGðô˜“L€MÜÑA°·±Ô0@ÓAÓA€KÜ �
2026-09-08 11:22:42 +08:00
×)Ñ)Ð*Ð*?À
¸ÐNdÐepÐdqÐ
rÔsØ €Nr'Úgrouped_metricscó°—|j«D����cic]3\}}||j«D��cic]\}}|t|«“Œc}}“Œ5}}}}}|}||krn|j|jf}tD]8}|j |i«} | j |i«}
|
2026-03-24 16:33:14 +08:00
j |i«Œ:|t
2026-04-10 18:35:01 +08:00
d¬«z
}||krŒn|Scc}}wcc}}}}wr—)ÚitemsrRrrÚSUPPORTED_PROJECTSrr) rûrürrÌÚ
2026-09-08 11:22:42 +08:00
month_dictrÚdate_mapÚresultÚcurrentÚproject_monthsÚmetrics_by_dates r(Úbuild_target_project_monthsr%usë€ð$3×#8Ñ#8Ô#:öá#:Ñ ˆG�Zð Àz×GWÑGWÔGYÔZÑGYÑ0C° ¸8�)œT (›^Ñ+ÐGYÒZÑZØ#:ð óð€GØ
2026-03-17 10:49:42 +08:00
�XÒ
Ø—\‘\ 7§=¡=Ð1ˆ ß)ˆGØ#×.Ñ.¨w¸Ó;ˆNØ,×7Ñ7¸ À2ÓFˆOØ × &Ñ & w°Õ 3ð*ð ”9 !Ô$Ñ$ˆð
2026-09-08 11:22:42 +08:00
�XÓ
2026-03-17 10:49:42 +08:00
ð €Mùó[ùõs–C
2026-09-08 11:22:42 +08:00
²C
2026-03-17 10:49:42 +08:00
ÁC
2026-09-08 11:22:42 +08:00
Ã
C
2026-04-10 18:35:01 +08:00
rQcóô—t|j«}t|j«}|rt dt |«›d�«t
2026-09-08 11:22:42 +08:00
|j«}|j«}t|||||¬«S)Nu加载表å��映射完æˆ�: rÛ)rMrNrOrPrQ)
2026-04-10 18:35:01 +08:00
rär@Úload_table_name_overridesrBrdrlrLr?Ú list_tablesrK)rQrOrPrMrNs r(Úbuild_daily_sync_contextr)‰su€Ü  ×!4Ñ!4Ó5€GÜ/°×0EÑ0EÓF€OÙÜÐ-¬c°/Ó.BÐ-CÀ4ÐHÔIÜ
 §¡Ó
1€FØ
×
Ñ
Ó
2026-09-08 11:22:42 +08:00
!€FÜ ØØØØ'Øô  ðr'cód—tjd«}tjd«}|r|s td«‚td«t j
2026-03-16 14:21:12 +08:00
d||dœd¬«}|j
2026-09-08 11:22:42 +08:00
«|j«}|jd «d
2026-03-16 14:21:12 +08:00
k7rtd |›�«‚td «|d
S)NÚ
FEISHU_APP_IDÚFEISHU_APP_SECRETu:缺少飞书环境å�˜é‡� FEISHU_APP_ID / FEISHU_APP_SECRETu&开始获å�–飞书 tenant_access_tokenzEhttps://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal)Úapp_idÚ
2026-09-08 11:22:42 +08:00
app_secreté©ÚjsonÚtimeoutÚcoderu获å�–飞书 token 失败: u'飞书 tenant_access_token 获å�–æˆ�功Útenant_access_token)
r}r‡rˆrdÚrequestsÚpostÚraise_for_statusr1r±Ú RuntimeError)r-r.ÚrespÚpayloads r(Úget_feishu_tokenr;™s§€Ü
�Y‰Y�Ó
2026-03-17 10:49:42 +08:00
'€FÜ—‘Ð.Ó/€JÙ ™ÜÐUÓVÐVÜ Ð
2026-03-16 14:21:12 +08:00
5Ô6Ü �=‰=ØOبjÑ
2026-09-08 11:22:42 +08:00
9Øô €Dð
 ×ÑÔØ�i‰i‹k€G؇{�{�6Ó˜aÒÜÐ8¸¸ ÐBÓCÐCÜ Ð
6Ô7Ø Ð(Ñ )Ð)r'c
ó^—eZdZdeddfd„Zededefd„«Zdedededeeeffd „Z de
e fd
2026-03-17 10:49:42 +08:00
„Z d ede
2026-03-16 14:21:12 +08:00
eeeffd „Z
d ed
2026-09-08 11:22:42 +08:00
edefd„Zd ed
2026-03-17 10:49:42 +08:00
edefd„Zd ed
edefd„Zd ede
eeefdeeeffd„Zd ede
2026-09-08 11:22:42 +08:00
eeeffd„Zd ededeeefddfd„Zd edeeefdeeeffd„Zy)rLr?rUNcóR—||_|j|«|_td|j›�«t «|_i|_i|_d|_tj«|_ |jjjd|j
2026-03-16 14:21:12 +08:00
›�ddœ«y)Nu(è§£æž�飞书 Base URL æˆ�功: app_token=úBearer úapplication/json; charset=utf-8©Ú
Authorizationz Content-Type)r?Úextract_app_tokenÚ app_tokenrdr;ÚtokenÚ
2026-09-08 11:22:42 +08:00
_fields_cacheÚ_records_cacheÚ
_tables_cacher5ÚSessionÚsessionÚheadersÚupdate)Úselfr?s r(Ú__init__zFeishuBitableClient.__init__­s�€Ø ˆŒ
Ø×/Ñ/°Ó9ˆŒÜÐ;¸D¿N¹NÐ;KÐLÔMÜ%Ó'ˆŒ
2026-03-16 14:21:12 +08:00
Ø>@ˆÔØ?AˆÔØ59ˆÔÜ×'Ñ'Ó)ˆŒ Ø � ‰ ×Ñ×#Ñ#à#*¨4¯:©:¨,Ð!7Ø Añ
õ
r'có¸—t|«jjd«}tjd|«}|st d|›�«‚|j
d«S)NÚ/z base/([^/]+)u$无法从链接中解æž� app_token: ru)r
2026-09-08 11:22:42 +08:00
rÔrzr¼ÚsearchrˆÚgroup)r?rÔÚmatchs r(rBz%FeishuBitableClient.extract_app_token½sQ€ä˜Ó!×&Ñ&×,Ñ,¨SÓ1ˆÜ— ‘ ˜/¨4Ó0ˆÙÜÐCÀHÀ:ÐNÓOÐ OØ�{‰{˜1‹~Ðr'ÚmethodrÔÚkwargsc óh—d|›�}|jd«}|rtd|›d|›d|›�«ntd|›d|›�«|jj||fddi|¤Ž} |j «}|jd k\rj|jd «xsi}td
|j›d|›d|jd«›d|jd«›d|jdd«›d|›� «‚|jd«dk7r]|jd «xsi}td|›d|jd«›d|jd«›d|jdd«›d|›�
2026-03-17 10:49:42 +08:00
«‚|jd«xsiS#t
$r9|j
2026-09-08 11:22:42 +08:00
«td|j›d |jdd
›�«‚wxYw)Nzhttps://open.feishu.cnÚparamsu请求飞书接å�£: Ú z params=r2é<u-飞书接å�£è¿”回了é�ž JSON å“�应: status=ú, body=éôé�Úerroru飞书接å�£ HTTP z: code=r3z msg=Úmsgz log_id=Úlog_idrEz payload=ru飞书接å�£å¤±è´¥ Údata)
2026-09-08 11:22:42 +08:00
r±rhrIÚrequestr1rˆr7r8Ú status_codeÚtext) rLrSrÔrTÚurlrVr9r:r\s r(r`zFeishuBitableClient.requestÅsö€Ø& t fÐ-ˆØ—‘˜HÓ%ˆÙ Ü Ð,¨V¨H°A°d°V¸8ÀFÀ8ÐLÕ Mä Ð,¨V¨H°A°d°VÐ<Ô =Ø#ˆt�|‰|×#Ñ# F¨CÑF¸ÐF¸vÑFˆð {Ø—i‘i“kˆGð × Ñ ˜sÒ "Ø—K‘K Ó(Ò.¨BˆEÜØ$ T×%5Ñ%5Ð$6°a¸°v¸WÀWÇ[Á[ÐQWÓEXÐDYÐY^Ð_f×_jÑ_jÐkpÓ_qÐ^rðsØŸ)™) H¨bÓ1Ð2°)¸G¸9ðFóð
2026-03-17 10:49:42 +08:00
ð �;‰;�vÓ  !Ò #Ø—K‘K Ó(Ò.¨BˆEÜØ% d V¨7°7·;±;¸vÓ3FÐ2GÀuÈWÏ[É[ÐY^ÓM_ÐL`ðaØŸ)™) H¨bÓ1Ð2°)¸G¸9ðFóð
ð�{‰{˜6Ó"Ò( bÐ(øôò {Ø × !Ñ !Ô #ÜÐ!NÈt×O_ÑO_ÐN`Ð`gÐhl×hqÑhqÐrvÐsvÐhwÐgxÐyÓzÐ zð {ús
Á E/Å/AF1c ód—|j�-tdt|j«›�«|jStd«g}d} i}|r||d<|j dd|j
›d�|¬«}|j
2026-09-08 11:22:42 +08:00
d «xsgD]$}|jt|d
|d ¬ ««Œ&|j
d
d«sn|j
d«xsd}|snŒ“tdt|D�cgc]}|j‘Œc}«›�«tdt|«›d�«||_|Scc}w)Nu命中数æ�®è¡¨ç¼“å­˜: 表数=u'开始获å�–多维表格数æ�®è¡¨åˆ—表rEÚ
page_tokenÚGETú/open-apis/bitable/v1/apps/z/tables©rVrr3r)r3rÚhas_moreFu 飞书返回的数æ�®è¡¨å��ç§°: uæ•°æ�®è¡¨åˆ—表获å�–完æˆ�: u 个) rGrhrlrdr`rCr±Úappendr2rmr)rLrrerVr_r³s r(r(zFeishuBitableClient.list_tablesàsB€Ø × Ñ Ð )Ü Ð6´s¸4×;MÑ;MÓ7NÐ6OÐPÔ QØ×%Ñ%Ð %ÜÐ:Ô;Ø!#ˆØˆ
ØØ%'ˆFÙØ'1��|Ñ$Ø—<‘< Ð)DÀTÇ^Á^ÐDTÐT[Ð'\Ðek�<ÓlˆDØŸ™ Ó)Ò/¨RÒ/�Ø— ‘ œY°°ZÑ0@ÀtÈFÁ|ÔTÕUð0à—8‘8˜J¨Ô.ØØŸ™ ,Ó/Ò5°2ˆJÙØðô Ð4´\ÑY^ÓB_ÑY^ÐQUÀ4Ç9Ã9ÐY^ÑB_Ó5`Ð4aÐbÔcÜÐ0´°U³° ¸DÐAÔBØ"ˆÔ؈ ùòC`sÃ,D-r3cóΗ||jvr6td|›dt|j|«›�«|j|Std|›�«g}d}t«}d} |dz
}ddi}|r+||d <||vrt d
2026-09-08 11:22:42 +08:00
|›d |›�«‚|j |«td |›d
|›d |xsd›�«|j
2026-03-24 16:33:14 +08:00
dd|j›d|›d�|¬«}|j|jd«xsg«|jdd«}|jd «xsd} td|›d
|›dt|«›d|›d| xsd›�
«|sn3| st d|›dt|«›�«‚| }|dk\rt d|›�«‚�Œ||j|<td|›d t|D�
cgc]}
|
2026-09-08 11:22:42 +08:00
jd!d«‘Œc}
«›�«td"|›dt|«›�«|Scc}
w)#Nu命中字段缓存: table_id=õ , 字段数=u#开始获å�–字段列表: table_id=rErruÚ page_sizeédreu@字段列表分页出现é‡�å¤� page_token,已中断: table_id=ú
2026-03-24 16:33:14 +08:00
, page_token=u#获å�–字段列表分页: table_id=ú, page=ú<first>rfrgú/tables/ú/fieldsrhrriFu#字段列表分页完æˆ�: table_id=u, 累计字段数=z , has_more=ú, next_page_token=ú<empty>uG字段列表分页返回 has_more=True 但 page_token 为空: table_id=u, 已获å�–字段数=u7字段列表分页超过 100 页,已中断: table_id=u&飞书返回的字段å��ç§°: table_id=ú , fields=r°u#字段列表获å�–完æˆ�: table_id=) rErhrlr<r8Úaddr`rCÚextendr±rm) rLr3rreÚ seen_tokensÚ
page_indexrVr_riÚnext_page_tokenr³s r(Ú list_fieldszFeishuBitableClient.list_fieldsøsÀ€Ø �t×)Ñ)Ñ )Ü Ð5°h°Z¸|ÌCÐPT×PbÑPbÐckÑPlÓLmÐKnÐoÔ pØ×%Ñ% hÑ/Ð /ÜÐ7¸°zÐBÔCØ&(ˆØˆ
2026-09-08 11:22:42 +08:00
Ü #£ˆ ؈
2026-04-10 18:35:01 +08:00
ØØ ˜!‰OˆJØ! 3Ð'ˆFÙØ'1��|Ñ$Ø Ñ,Ü&Ð)iÐjrÐisðtAðBLðAMð(NóOðOØ—‘ 
Ô+Ü Ð;¸H¸:ÀWÈZÈLÐXeÐfpÒf}Ðt}Ðe~Ðô
AØ—<‘<ØØ-¨d¯n©nÐ-=¸XÀhÀZÈwÐWØð óˆDð
�L‰L˜Ÿ™ 'Ó*Ò0¨bÔ 1Ø—x‘x 
¨EÓ2ˆHØ"Ÿh™h |Ó4Ò:¸ˆOÜ Ø5°h°Z¸wÀzÀlÐRdÔehÐinÓeoÐdpðqØ$˜:Ð%7¸Ò8TÈ9Ð7UðWô
ñØÙ"Ü"Ð%lÐmuÐlvðwLôMPðQVóMWðLXð$YóZðZØ(ˆJؘSÒ Ü"Ð%\Ð]eÐ\fÐ#gÓhÐhñ7ð8(-ˆ×ј8Ñ$ÜÐ:¸8¸*ÀIÌlñDIó\JñDIÐ{Ð\`×\dÑ\dÐeqÐsuÕ\vðDIñ\JóOKðNLðMô NÜÐ7¸°zÀÌcÐRWËjÈ\ÐZÔ[؈ ùò\JsÆ G"r°cóh‡—td|›d‰›�«|j|«}tˆfd„|D««rtd|›d‰›�«ytd|›d‰›�«|j dd|j
›d |›d
2026-09-08 11:22:42 +08:00
�‰d d d
idœ¬«|j j|d«td|›d‰›�«y)Nu#检查字段是å�¦å­˜åœ¨: table_id=ú, field=c3óF•K—|]}|jd«‰k(–—Œy­w©r°NrÑ©rÆr³r°s €r(rÈz:FeishuBitableClient.ensure_number_field.<locals>.<genexpr>%ó øèø€ÐGÁ¸ˆt�x‰x˜ Ó%¨Õ3Áùóƒ!u)字段已存在,跳过创建: table_id=Fu#开始创建数字字段: table_id=ÚPOSTrgrrrsr×Ú formatterz0.00©r°ÚtypeÚproperty©r1u字段创建完æˆ�: table_id=T©rhr|rÊrdr`rCrEÚpop©rLr3r°r­s ` r(Úensure_number_fieldz'FeishuBitableClient.ensure_number_field"sÔø€ÜÐ7¸°zÀÈ*ÈÐVÔWØ×!Ñ! (Ó+ˆÜ ÓGÁÓGÔ GÜ ÐAÀ(ÀÈ8ÐT^ÐS_Ð`Ô aØÜÐ6°x°jÀÈÈ ÐUÔVØ � ‰ Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ7Ð SØ *°AÀ[ÐRXÐDYÑZð ô
2026-04-10 18:35:01 +08:00
ð
2026-09-08 11:22:42 +08:00
2026-03-16 14:21:12 +08:00
×Ñ×јx¨Ô.ÜÐ0°°
2026-04-10 18:35:01 +08:00
¸(À:À,ÐOÔPØr'cób‡—td|›d‰›�«|j|«}tˆfd„|D««rtd|›d‰›�«ytd|›d‰›�«|j dd|j
2026-03-16 14:21:12 +08:00
›d |›d
2026-03-24 16:33:14 +08:00
�‰d d œ¬
2026-04-10 18:35:01 +08:00
«|j j|d«td|›d‰›�«y)Nu)检查文本字段是å�¦å­˜åœ¨: table_id=r~c3óF•K—|]}|jd«‰k(–—Œy­wr€rÑr�s €r(rÈz8FeishuBitableClient.ensure_text_field.<locals>.<genexpr>5r‚rƒu/文本字段已存在,跳过创建: table_id=Fu#开始创建文本字段: table_id=r„rgrrrsru)r°r‡r‰u#文本字段创建完æˆ�: table_id=TrŠrŒs ` r(Úensure_text_fieldz%FeishuBitableClient.ensure_text_field2sÎø€ÜÐ=¸h¸ZÀxÐPZÈ|Ð\Ô]Ø×!Ñ! (Ó+ˆÜ ÓGÁÓGÔ GÜ ÐGÈÀzÐQYÐZdÐYeÐfÔ gØÜÐ6°x°jÀÈÈ ÐUÔVØ � ‰ Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ7Ð SØ *°AÑ6ð ô
ð
2026-09-08 11:22:42 +08:00
2026-03-17 10:49:42 +08:00
×Ñ×јx¨Ô.ÜÐ6°x°jÀÈÈ ÐUÔVØr'c ój‡—td|›d‰›�«|j|«}tˆfd„|D««rtd|›d‰›�«ytd|›d‰›�«|j dd|j
2026-09-08 11:22:42 +08:00
›d |›d
�‰d d dd
œdœ¬«|j j|d«td|›d‰›�«y)Nu)检查日期字段是å�¦å­˜åœ¨: table_id=r~c3óF•K—|]}|jd«‰k(–—Œy­wr€rÑr�s €r(rÈz8FeishuBitableClient.ensure_date_field.<locals>.<genexpr>Er‚rƒu/日期字段已存在,跳过创建: table_id=Fu#开始创建日期字段: table_id=r„rgrrrséz
2026-04-10 18:35:01 +08:00
yyyy-MM-dd)Údate_formatterÚ auto_fillr†r‰u#日期字段创建完æˆ�: table_id=TrŠrŒs ` r(Úensure_date_fieldz%FeishuBitableClient.ensure_date_fieldBsÙø€ÜÐ=¸h¸ZÀxÐPZÈ|Ð\Ô]Ø×!Ñ! (Ó+ˆÜ ÓGÁÓGÔ GÜ ÐGÈÀzÐQYÐZdÐYeÐfÔ gØÜÐ6°x°jÀÈÈ ÐUÔVØ � ‰ Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ7Ð Sà(ØØ/;È%ÑPñð ô
2026-09-08 11:22:42 +08:00
ð
2026-03-24 16:33:14 +08:00
×Ñ×јx¨Ô.ÜÐ6°x°jÀÈÈ ÐUÔVØr'Ú field_groupscó—td|›d|D�cgc]5}|jd«xsdt|jd«xsg«f‘Œ7c}›�«|jdd|j›d|›d �d
2026-09-08 11:22:42 +08:00
|i¬ «}td |›�«|Scc}w)
Nu#开始创建字段编组: table_id=z , groups=rrEÚchildrenr„rgrrz
/field_groupsr—r‰u)字段编组创建请求完æˆ�: table_id=)rdr±rlr`rC)rLr3r—rQr_s r(Úcreate_field_groupsz'FeishuBitableClient.create_field_groupsVs®€ÜØ1°(°ð<Ù`lÓmÑ`lÐW\˜Ÿ ™  &Ó)Ò/¨R´°U·Y±Y¸zÓ5JÒ5PÈbÓ1QÒRÐ`lÑmÐnð
pô
2026-03-17 10:49:42 +08:00
ð�|‰|Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ=Ð YØ  ,Ð/ðó
ˆô
2026-03-17 10:49:42 +08:00
Ð<¸X¸JÐGÔH؈ ùònsŽ:Bc óf—||jvr6td|›dt|j|«›�«|j|Std|›�«g}d}d} |dz
2026-09-08 11:22:42 +08:00
}ddi}|r||d <td
|›d |›d |xsd
2026-03-17 10:49:42 +08:00
›�«|jdd|j›d|›d�|¬«}|j |j
d«xsg«|j
d «xsd}td|›d |›dt|«›d|xsd›�«|snŒ®td|›dt|«›�«||j|<|S)Nu命中记录缓存: table_id=u , 记录数=u#开始获å�–记录列表: table_id=rErrurmrZreu#获å�–记录列表分页: table_id=rprorqrfrgrrú/recordsrhru#记录列表分页完æˆ�: table_id=u, 累计记录数=rtruu#记录列表获å�–完æˆ�: table_id=)rFrhrlr`rCrxr±)rLr3rrerzrVr_s r(Ú list_recordsz FeishuBitableClient.list_recordscs‰€Ø �t×*Ñ*Ñ *Ü Ð5°h°Z¸|ÌCÐPT×PcÑPcÐdlÑPmÓLnÐKoÐpÔ qØ×&Ñ& xÑ0Ð 0ÜÐ7¸°zÐBÔCØ&(ˆØˆ
؈
2026-03-17 10:49:42 +08:00
ØØ ˜!‰OˆJØ! 3Ð'ˆFÙØ'1��|Ñ$Ü Ð;¸H¸:ÀWÈZÈLÐXeÐfpÒf}Ðt}Ðe~Ðô
AØ—<‘<ØØ-¨d¯n©nÐ-=¸XÀhÀZÈxÐXØð óˆDð
�L‰L˜Ÿ™ 'Ó*Ò0¨bÔ 1ØŸ™ ,Ó/Ò5°2ˆJÜ Ø5°h°Z¸wÀzÀlðS#Ü#& u£: ,Ð.@ÀÒAXÈyÐ@Yð[ô
ñØð%ô& Ð7¸°zÀÌcÐRWËjÈ\ÐZÔ[Ø(-ˆ×јHÑ%؈ r'Ú record_idr­c ód—td|›d|›dt|j««›�«|jdd|j›d|›d|›�d|i¬ «|j
j
|«}|�?|D]9}|j
2026-09-08 11:22:42 +08:00
d
«|k(sŒ|jdi«j|«yyy) Nu更新记录: table_id=z , record_id=rvÚPUTrgrrz /records/r­r‰rž) rhr8Úkeysr`rCrFr±rrK)rLr3ržr­Úcached_recordsr³s r(Ú
update_recordz!FeishuBitableClient.update_record‚s€ÜÐ+¨H¨:°\À)ÀÈIÔVZÐ[a×[fÑ[fÓ[hÓViÐUjÐkÔlØ � ‰ Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ9ÐU^ÐT_Ð `ؘFÐ#ð ô
2026-03-17 10:49:42 +08:00
ð
2026-09-08 11:22:42 +08:00
×,Ñ,×0Ñ0°Ó:ˆØ Ð %Û&�Ø—8‘8˜KÓ(¨IÓ5Ø—O‘O H¨bÓ1×8Ñ8¸Ô@Ùñ'ð &r'c ó*—td|›dt|j««›�«|jdd|j›d|›d�d|i¬«}|j d «xsi}||j vr |r|j |j|«|S)
Nu新增记录: table_id=rvr„rgrrrœr­r‰Úrecord)rhr8r¡r`rCr±rFrj)rLr3r­r_r¥s r(Ú
create_recordz!FeishuBitableClient.create_record�sœ€ÜÐ+¨H¨:°Y¼tÀFÇKÁKÃMÓ?RÐ>SÐTÔUØ�|‰|Ø Ø)¨$¯.©.Ð)9¸À(ÀÈ8Ð TؘFÐ#ðó
ˆð
—‘˜(Ó#Ò) rˆØ �t×*Ñ*Ñ *©vØ × Ñ  Ñ )× 0Ñ 0°Ô 8؈
2026-03-24 16:33:14 +08:00
r')r!r"r#r$rMÚ staticmethodrBr rRr`r8r2r(r|rIr�r�r–ršr�r£r¦r&r'r(rLrL¬sˆ„ð
 ð
¨ó
ð ð Cð¨Còóðð)˜cð)¨ð)¸ð)ÀÀSÈ#ÀXÁó)ð6˜T )™_óð0( Cð(¨D°°c¸3°h±Ñ,@ó(ðT¨Cð¸SðÀTóð ¨#ð¸3ðÀ4óð ¨#ð¸3ðÀ4óð( ¨Cð ¸tÀDÈÈcÈÁNÑ?Sð ÐX\Ð]`ÐbeÐ]eÑXfó ð Sð¨T°$°s¸C°x±.Ñ-Aóð>  cð °cð À4ÈÈSÈÁ>ð ÐVZó ð
 cð
°4¸¸S¸±>ð
ÀdÈ3ÐPSÈ8Ánô
r'rLÚ path_textcó—|siSt|«}|j«std|›�«‚tj|j d¬««}|j
«D��cic]\}}t|«t|«“Œc}}Scc}}w)Nu未找到表å��映射文件: rprq)r rwÚFileNotFoundErrorr1Úloadsrxrr$)r¨rÔr:r‚rƒs r(r'r'�sw€Ù ؈ Ü � ‹?€DØ �;‰;Œ=ÜÐ"?À¸vÐ FÓGÐGÜ�j‰j˜Ÿ™°˜Ó9Ó:€GØ3:·=±=´?Ô C±?¡Z S¨%ŒC�‹H”c˜%“jÑ °?Ò CÐCùÓ CsÁ&B Ú webhook_urlÚtitler?c óz—|s td«ydddidd|dœdœd d
d |j«›d |j«›d
2026-09-08 11:22:42 +08:00
|›d�dœdœgdœdœ}td«tj||d¬«}|j «|j «}|j
d«dvrtd|›�«‚td«y)Nu;未é…�置飞书群机器人 webhook,跳过群消æ�¯æŽ¨é€�Ú interactiveÚwide_screen_modeTÚblueÚ
2026-03-24 16:33:14 +08:00
plain_text©ÚtagÚcontent©Útemplater­ÚdivÚlark_mdõ**å�Œæ­¥èŒƒå›´**
õ 至 u.
2026-03-24 16:33:14 +08:00
**多维表格**
[点击打开多维表格](Ú)©r´rb©rQÚheaderÚelements)Úmsg_typeÚcardu!开始推é€�飞书群å�¡ç‰‡æ¶ˆæ�¯r/r0r3)rNu飞书群消æ�¯æŽ¨é€�失败: u!飞书群å�¡ç‰‡æ¶ˆæ�¯æŽ¨é€�完æˆ�)rdr›r5r6r7r1r±r8)r¬r­r?rûrürÂr9r:s r(Úsend_feishu_sync_cardrçsè€ñ ÜÐNÔOØà!à)¨4Ð0à"Ø!-¸%Ñ@ñð !à(à0°×1EÑ1EÓ1GÐ0HÈÈh×N`ÑN`ÓNbÐMcðdLØLTÈ:ÐUVðXññ ð ñ

2026-09-08 11:22:42 +08:00
ñ €Dô,
2026-03-17 10:49:42 +08:00
Ð
2026-03-24 16:33:14 +08:00
0Ô1Ü �=‰=˜¨4¸Ô <€DØ×ÑÔØ�i‰i‹k€G؇{�{�6Ó )Ñ+ÜÐ:¸7¸)ÐDÓEÐEÜ Ð
2026-09-08 11:22:42 +08:00
0Õ1r'Ú
image_pathrDcó^—|syt|«}|j«std|›�«‚|xs
2026-03-17 10:49:42 +08:00
t«}dd|›�i}|j d«5}d|j
2026-09-08 11:22:42 +08:00
|dfi}dd i}t
d
|›�«tjd |||d ¬
«}ddd«j«|j«}|jd«dk7rtd|›�«‚|jd«xsijd«xsd} | std|›�«‚t
d| ›�«| S#1swYŒ“xYw)NrEu未找到预览图文件: rAr>ÚrbÚimagezapplication/octet-streamÚ
image_typerTu 开始上传飞书消æ�¯å›¾ç‰‡: z-https://open.feishu.cn/open-apis/im/v1/imagesrX)rJr_Úfilesr2r3ru飞书图片上传失败: r_Ú image_keyu0飞书图片上传æˆ�功但未返回 image_key: u*飞书消æ�¯å›¾ç‰‡ä¸Šä¼ å®Œæˆ�: image_key=)
r rwrªr;Úopenrrdr5r6r7r1r±r8)
rÄrDrÔrJÚ
image_filerÉr_r9r:rÊs
r(Úupload_feishu_imagerÍÐsE€Ù ØÜ �
Ó €DØ �;‰;Œ=ÜÐ"<¸T¸FÐ CÓDÐDØ Ò 'Ô%Ó'€EØ '¨%¨Ð 1Ð2€GØ
�‰�4Œ˜Jؘ4Ÿ9™9 jÐ2LÐMÐNˆØ˜iÐ(ˆÜÐ3°D°6Ð:Ô;Ü�}‰}ÐLÐV]ÐdhÐpuð@BôCˆ÷
ð
 ×ÑÔØ�i‰i‹k€G؇{�{�6Ó˜aÒÜÐ7¸°yÐAÓBÐBØ—+‘+˜fÓ%Ò+¨×0Ñ0°Ó=ÒDÀ"€IÙ ÜÐMÈgÈYÐWÓXÐXÜ Ð9¸)¸Ð
EÔFØ Ð÷
ˆús Á>D#Ä#D,rFc ó6—|s td«y|xs
2026-04-10 18:35:01 +08:00
t«}|r
2026-09-08 11:22:42 +08:00
t||¬«nd}ddd|j«›d|j«›d|›d |›d
2026-04-10 18:35:01 +08:00
� d œd œg}|r|j d
|ddd œdœ«|j ddddd œd|dœgdœ«|dt j ddidd|d œdœ|dœd¬«dœ} d |›�d!d"œ}
td#|›�«tjd$|
| d%¬&«} | j «} | jd*k\rtd+| j›d,| ›�«‚| jd-«d.k7rtd/| ›�«‚td0«y#t$r9| j«td'| j›d(| jdd)›�«‚wxYw)1Nu<未é…�ç½® FEISHU_CHAT_ID,跳过应用机器人å�¡ç‰‡æŽ¨é€�)rDrEr¸r¹rºr»u
**多维表格**
[z](r¼r³r½Úimgr²u报表预览图)r´Úimg_keyÚaltÚactionÚbuttonu打开仪表盘Úprimary)r´rbr‡rc)r´Úactionsr¯r°Tr±r¶r¾F)Ú ensure_ascii)Ú
receive_idrÁrµr>r?r@u4开始通过应用机器人å�‘é€�群å�¡ç‰‡: chat_id=zGhttps://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_idrX)rJr1r2u>应用机器人å�‘é€�群å�¡ç‰‡å¤±è´¥ï¼Œè¿”回é�ž JSON: status=rYrZr[u-应用机器人å�‘é€�群å�¡ç‰‡å¤±è´¥: status=z
2026-09-08 11:22:42 +08:00
, payload=r3ru&应用机器人å�‘é€�群å�¡ç‰‡å¤±è´¥: u$应用机器人群å�¡ç‰‡å�‘é€�完æˆ�)rdr;rÍr›rjr1Údumpsr5r6rˆr7r8rarbr±)
2026-04-10 18:35:01 +08:00
rFr­r?rûrürÄrDrÊrÀrTrJr9r:s
r(Úsend_feishu_app_cardrÙès1€ñ ÜÐOÔPØØ Ò 'Ô%Ó'€EÙ@JÔ# J°eÕ<ÐPR€Iðà à(¨×)=Ñ)=Ó)?Ð(@ÀÀh×FXÑFXÓFZÐE[ð\*Ø*/¨°°8°*¸Að?ññ
2026-09-08 11:22:42 +08:00
ð &€HñØ�‰ °)ÈLÐevÑDwÑxÔyØ ‡O�Oàð$Ø$0Ð=NÑOØ%Ø#ñ ðñ
ô ðØ!Ü—:‘:à-¨tÐ4Ø'-À ÐY^Ñ8_Ñ`Ø$ñ
2026-04-10 18:35:01 +08:00
ð
2026-09-08 11:22:42 +08:00
ô

ñ €Gð# 5 'Ð*Ø9ñ€Gô
ÐCÀGÀ9Ð
MÔNÜ �=‰=ØQØØ
Øô  €Dð HØ—)‘)“+ˆð ×ј3ÒÜÐJÈ4×K[ÑK[ÐJ\Ð\fÐgnÐfoÐpÓqÐq؇{�{�6Ó˜aÒÜÐCÀGÀ9ÐMÓNÐNÜ Ð
2026-03-17 10:49:42 +08:00
3Õ4øô òHØ ×ÑÔÜÐ[Ð\`×\lÑ\lÐ[mÐmtÐuy×u~Ñu~ð@DðADðvEðuFðGóHð HðHús
2026-09-08 11:22:42 +08:00
Ã.EÅAFrNrrÚ overridesc
ó,‡—td|›d|d›d|d›�«|xsi}|›d|d›d|d›�}||vrI||}|D]0}|j|k(sŒtd|›d|j›�«|cStd |›d
�«‚t|«D�cgc]
2026-09-08 11:22:42 +08:00
}t |«‘Œ} }t |«|›d �|d›d �|d›|d›�|d›d |d›d �|d›d|d›�|d›d
|d›�|d›d|d›�h}
t
2026-03-17 10:49:42 +08:00
d|›dt|«›�«g} g} |D]q}t |j«Štˆfd„| D««}
2026-04-10 18:35:01 +08:00
|
r| j|j«|
sŒLtˆfd„|
D««sŒa| j|«Œst| «dk(r+td|›d|d›d|d›d| dj›�«| dS| s9|D�cgc]}|j‘Œ}}td|›d|d›d|d›d| xsd›d|›�
«‚td|›d|d›d|d›ddjd„| D««›�«‚cc}wcc}w)Nu开始匹é…�目标表: 项目=õ , 月份=Ú04dÚ-Ú02dÚ:u命中表å��映射: rÿu表å��映射命中了 u,但飞书中ä¸�存在该表u月uå¹´ráÚ.u项目表å��别å��: 项目=z
, aliases=c3ó&•K—|]}|‰v–—Œ
y­wrÅr&)rÆÚaliasÚnormalized_names €r(rÈz$find_target_table.<locals>.<genexpr>Usøèø€ÐXÑDW¸5˜e Ô6ÑDWùrÉc3ó8•K—|]}t|«‰v–—Œy­wrÅ©r¾)rÆrDräs €r(rÈz$find_target_table.<locals>.<genexpr>Zsøèø€ÐRÁ\¸EŒ~˜eÓ$¨Ô7Á\ùsƒruu匹é…�到目标表: 项目=õ, 表=ru未找到匹é…�表: 项目=u, 项目相关表=z[]u , 全部表=u=匹é…�到多个表,请æ��ä¾› table_map_file 指定: 项目=rïc3ó4K—|]}|j–—Œy­wrÅ)r)rÆÚts r(rÈz$find_target_table.<locals>.<genexpr>es7èø€ð@\ñQ[ðLMðAB÷AGõAGñQ[ùs‚) rdrrˆrÓr¾r$rhrÊrjrlrõ)rNrÌrrrÚÚ override_keyÚ target_nameÚtablerãÚnormalized_projectsÚ month_tokensr¥Úproject_related_tablesÚmatched_projectÚall_table_namesräs @r(Úfind_target_tablerò4sø€ô
2026-04-10 18:35:01 +08:00
Ð-¨g¨Y°iÀÀS¸zÈÈ5ÐQTÈ+Ð
2026-03-16 14:21:12 +08:00
VÔWØ’˜R€IØ�Y˜a  S˜z¨¨5°¨+Ð6€LØ�yÑ Ø  Ñ-ˆ ÛˆEØ�z‰z˜[Ó(ÜÐ/° ¨~¸TÀ%Ç*Á*ÀÐNÔOØ’ ðôÐ1°+°Ð>\Ð]Ó^Ð^Ü>WÐX_Ô>`ÓaÑ>`°Uœ>¨%Õ0Ð>`ÐÐaä ˆE‹
2026-03-17 10:49:42 +08:00
Ø ˆ'�ˆ
Ø �ˆ+�SÐØ �ˆ*�U˜3�KÐ Ø �ˆ*�C˜˜c�{ #Ð&Ø �ˆ*�A�e˜C�[Ð!Ø �ˆ*�A�e˜C�[Ð!Ø �ˆ*�A�e˜C�[Ð!ð €LôÐ+¨G¨9°JÔ?XÐY`Ó?aÐ>bÐcÔdØ€JØÐÛˆÜ(¨¯©Ó4ˆÜÓXÑDWÓXÓXˆÙ Ø "× )Ñ )¨%¯*©*Ô 5ÙØ Ü ÓRÁ\ÓRÕ RØ × Ñ ˜eÕ $ðô ˆ:ƒ˜!ÒÜÐ.¨w¨i°yÀÀcÀ
È!ÈEÐRUÈ;ÐV\Ð]gÐhiÑ]j×]oÑ]oÐ\pÐqÔrؘ!‰}ÐÙ Ù39Ó:±6¨%˜5Ÿ:›:°6ˆÐ:ÜØ)¨'¨°)¸DÀ¸:ÀQÀuÈSÀkÐQcÐdzòeCðCðdDðDPðQ`ðPað
bó
2026-03-24 16:33:14 +08:00
ð
2026-04-10 18:35:01 +08:00
ô Ø
GÈÀyÐPYÐZ^Ð_bÐYcÐcdÐejÐknÐdoÐouÐvz×vÑvñ@\ñQ[ó@\ów\ðv]ð ^ó ðùò?bùò6;s ÂH Æ(HcóH—t|jtd«««S)Nz0.01)ÚfloatÚquantizer
r¹s r(Údecimal_to_numberröis€Ü �—‘¤¨£Ó0Ó 1Ð1r'r.có>—|jd|j›�«S)Nz%m-%d)Ústrftimer)r.rýs r(Úget_metric_field_namerùms!€Ø × Ñ   m×&@Ñ&@Ð%AÐBÓ CÐCr'có6—|dvryt|t«ryt|ttf«rt t|«d«St|t
2026-03-17 10:49:42 +08:00
«r9|j
2026-04-10 18:35:01 +08:00
«jdd«}|sy t t|«d«Sy#t$rYywxYw)Nrçr×Ú,rE) Ú
isinstancerIÚintrôÚroundr$rzÚreplacerˆ)rƒrbs r(Ú parse_numberrqs�€Ø �
2026-03-17 10:49:42 +08:00
ÑØÜ�%œÔØÜ�%œ#œu˜Ô&Ü”U˜5“\ 1Ó%Ð%Ü�%œÔØ�{‰{‹}×$Ñ$ S¨"Ó-ˆÙØð Üœ˜t› aÓ(Ð (ð øôò Ùð úsÁ6B  BÂBcó’—g}|}||kr=|j|«tj|j«dz«}||krŒ=|S)Nru)rjrÚ fromordinalÚ toordinal)rûrüÚdatesr"s r(Ú
2026-03-24 16:33:14 +08:00
iter_datesrƒsO€Ø €EØ€GØ
2026-03-17 10:49:42 +08:00
�XÒ
Ø
� ‰ �WÔÜ×"Ñ" 7×#4Ñ#4Ó#6¸Ñ#:Ó;ˆð �XÓ
ð €Lr'cóš—tt«}t||«D],}||j|jfj |«Œ.|SrÅ)rr8rrrrj)rûrürr.s r(Úbuild_group_dates_by_monthrŒsB€Ü1<¼TÓ1B€GÜ 
¨HÖ5ˆ Ø�—‘ §¡Ð1Ñ2×9Ñ9¸)ÕDð6à €Nr'rAÚallowed_field_namescó*—g}g}g}|D]Ã}t|jd«xsd«j«}t|jd«xsd«j«}|sŒ^||k(rŒd|�||vrŒkd|dœ} |t«k(r|j | «Œ�d|j «vr|j | «Œ³|j | «ŒÅg}
2026-03-24 16:33:14 +08:00
|r|
j d|dœ«|r|
2026-03-17 10:49:42 +08:00
j d |dœ«|r|
2026-09-08 11:22:42 +08:00
j d
|dœ«|