97 lines
3.2 KiB
Python
97 lines
3.2 KiB
Python
from pydantic import BaseModel
|
||
|
||
from ...sync_system.strategy import DefaultSyncStrategy
|
||
from ...sync_system.config import StrategyConfig, OrphanAction, UpdateDirection
|
||
from schemas.project.project_base import ProjectResponseBase
|
||
|
||
|
||
class ProjectDomainOption(BaseModel):
|
||
pull_group_plan_production_date: bool = False
|
||
|
||
|
||
class ProjectSyncStrategy(DefaultSyncStrategy[ProjectResponseBase]):
|
||
"""
|
||
Project 同步策略
|
||
|
||
业务规则:
|
||
1. 手动绑定(根节点)
|
||
2. 允许拉取更新(不自动创建)
|
||
3. 依赖公司(company)
|
||
|
||
schema 已在类定义中设置,禁止在初始化时传入其他 schema。
|
||
"""
|
||
|
||
# 类变量:schema 固定为 ProjectResponseBase
|
||
schema = ProjectResponseBase
|
||
domain_option_model = ProjectDomainOption
|
||
|
||
_PULL_ONLY_FIELDS = [
|
||
"ic_plan_first_production_date",
|
||
"ic_plan_full_production_date",
|
||
]
|
||
|
||
# 类变量:默认配置
|
||
default_config = StrategyConfig(
|
||
auto_bind=False,
|
||
auto_bind_fields=[],
|
||
depend_fields={"company_id": "company"},
|
||
local_orphan_action=OrphanAction.CREATE_REMOTE,
|
||
remote_orphan_action=OrphanAction.NONE,
|
||
update_direction=UpdateDirection.PUSH,
|
||
)
|
||
|
||
@property
|
||
def domain_option(self) -> ProjectDomainOption:
|
||
return ProjectDomainOption.model_validate(self.config.domain_option)
|
||
|
||
def get_node_update_payload(self, node):
|
||
payload = dict(node.get_data() or {})
|
||
context = getattr(node, "context", None)
|
||
if not isinstance(context, dict):
|
||
return payload
|
||
|
||
all_info = context.get("all_info")
|
||
if not isinstance(all_info, dict):
|
||
return payload
|
||
|
||
for section_name, section_data in all_info.items():
|
||
if not section_name.endswith("_extension") or not isinstance(section_data, dict):
|
||
continue
|
||
for field_name in self._PULL_ONLY_FIELDS:
|
||
if payload.get(field_name) not in (None, ""):
|
||
continue
|
||
if field_name in section_data:
|
||
payload[field_name] = section_data.get(field_name)
|
||
|
||
return payload
|
||
|
||
async def update_pair(self, local_node, remote_node, data_id_map=None):
|
||
updated_by_id = {}
|
||
|
||
if self.domain_option.pull_group_plan_production_date:
|
||
pull_update = await self.prepare_update_for_direction(
|
||
local_node,
|
||
remote_node,
|
||
UpdateDirection.PULL,
|
||
data_id_map,
|
||
include_fields=self._PULL_ONLY_FIELDS,
|
||
)
|
||
if pull_update is not None:
|
||
updated_by_id[pull_update.node_id] = pull_update
|
||
|
||
generic_exclude_fields = self._PULL_ONLY_FIELDS
|
||
else:
|
||
generic_exclude_fields = None
|
||
|
||
if self.config.update_direction != UpdateDirection.NONE:
|
||
generic_update = await self.prepare_update_for_direction(
|
||
local_node,
|
||
remote_node,
|
||
self.config.update_direction,
|
||
data_id_map,
|
||
exclude_fields=generic_exclude_fields,
|
||
)
|
||
if generic_update is not None:
|
||
updated_by_id[generic_update.node_id] = generic_update
|
||
|
||
return list(updated_by_id.values()) |