feat(db): moments_post 表+upsert(朋友圈实体,PK=云客data.id,create_time统一ms)
- MomentsPost 模型:moments_post 表,PK=id(云客 getFriendsterInfo data.id), wechat_id/create_time 建索引,praise/comment/image 存 JSON 列 - 迁移 524da8d2d597(手写 create_table,已应用到 smoke.db 并在临时 SQLite 全链路 upgrade/downgrade 验证) - repos.upsert_moments_posts:批量幂等 upsert;附带修 _build_column_values 对 JSON 列表的误 join(标量列 join 保持不变,dept_route 旧测试仍过) - 修复 3 个 chat_group 旧测试缺 owner_account_id(2026-08-24 复合主键遗留) - 全套 430 测试通过 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,7 @@ Conventions
|
||||
- ``SyncState`` uses ``channel`` to scope a sync cursor (together with
|
||||
``entity_type``).
|
||||
- ``Staff``, ``Department``, ``WechatAccount``, ``WhatsappAccount``,
|
||||
``YkAccount``, ``SyncRun`` carry no ``channel`` column.
|
||||
``YkAccount``, ``SyncRun``, ``MomentsPost`` carry no ``channel`` column.
|
||||
* Primary keys use the natural source id where one exists; otherwise an
|
||||
integer surrogate PK is used (``SyncState``, ``YkAccount``, ``SyncRun``).
|
||||
* ``GroupMember`` uses a composite PK ``(channel, room_id, member_id)``.
|
||||
@@ -592,6 +592,33 @@ class Sms(Base):
|
||||
__table_args__ = (Index("ix_sms_user_time", "user_id", "create_time"),)
|
||||
|
||||
|
||||
class MomentsPost(Base):
|
||||
"""员工朋友圈帖子 — source: ``POST /wechatweb/wechatFriendster/getFriendsterInfo``.
|
||||
|
||||
PK = 云客 ``data.id``。``create_time`` 统一 **ms epoch**(云客返回秒,
|
||||
scraper ×1000)。WeChat-only 实体(无 ``channel`` 列),所属员工微信号
|
||||
由 ``wechat_id`` 标识。
|
||||
"""
|
||||
|
||||
__tablename__ = "moments_post"
|
||||
|
||||
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
||||
wechat_id: Mapped[str] = mapped_column(String(128), index=True)
|
||||
sns_id: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
||||
author_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
author_wxid: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||||
author_avatar: Mapped[str | None] = mapped_column(String(1024), nullable=True)
|
||||
content: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
type_raw: Mapped[str | None] = mapped_column(String(16), nullable=True)
|
||||
create_time: Mapped[int | None] = mapped_column(BigInteger, index=True)
|
||||
praise_json: Mapped[list[dict[str, Any]] | None] = mapped_column(JSON, nullable=True)
|
||||
comment_json: Mapped[list[dict[str, Any]] | None] = mapped_column(JSON, nullable=True)
|
||||
image_urls: Mapped[list[str] | None] = mapped_column(JSON, nullable=True)
|
||||
raw_json: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
|
||||
fetched_at: Mapped[dt.datetime] = _fetched_at()
|
||||
updated_at: Mapped[dt.datetime] = _updated_at()
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# 5. Operational / bookkeeping tables (local; no raw_json/version)
|
||||
# ===========================================================================
|
||||
@@ -696,6 +723,7 @@ __all__ = [
|
||||
"GroupMember",
|
||||
"Media",
|
||||
"Message",
|
||||
"MomentsPost",
|
||||
"PhoneCall",
|
||||
"Sms",
|
||||
"Staff",
|
||||
|
||||
Reference in New Issue
Block a user