update
This commit is contained in:
parent
a4980481eb
commit
bc83d4ccfc
|
|
@ -18,6 +18,7 @@
|
|||
- `displayName` 取 `employeeInfo.customProperties.extDDNIC_606508_303466862`。
|
||||
- `department` 写入“EHR 部门编码 + EHR 部门名称”,例如 `V000076 IT`。
|
||||
- `streetAddress` 默认取 `translateProperties.extgzddxx1_606508_892394263Text`。
|
||||
- `st`、`l`、`physicalDeliveryOfficeName` 默认按 `extgzddxx1_606508_892394263` 的原始值做映射。
|
||||
|
||||
## public_cfg 示例
|
||||
|
||||
|
|
@ -68,9 +69,23 @@
|
|||
- `ldap_verify_tls`: 是否校验证书,默认 `true`。
|
||||
- `proxy_alias_domain`: 生成 `smtp:<sAMAccountName>@domain` 别名时使用的域名。
|
||||
- `department_code_ad_attribute`: 部门编码写入的 AD 属性,默认 `departmentNumber`。
|
||||
- `work_location_value_key`: 工作地点原始值字段编码,默认 `extgzddxx1_606508_892394263`,用于映射 AD 省、市、办公室。
|
||||
- `street_address_key`: 具体地址字段编码,默认 `extgzddxx1_606508_892394263Text`,写入 AD 的 `streetAddress`;取不到时会兜底尝试 `WorkSpacevalue` 和 `extgzddxx_606508_618643707`。
|
||||
- `default_company`: 固定公司名;不传时尝试取 EHR 根组织名称。
|
||||
- `location_mappings`: 工作地点到 AD 国家、省、市字段的映射。
|
||||
- `location_mappings`: 工作地点原始值到 AD 国家、省、市、办公室字段的映射,可覆盖内置映射。
|
||||
|
||||
内置工作地点映射:
|
||||
|
||||
| EHR 原始值 | AD st | AD l | AD Office |
|
||||
| --- | --- | --- | --- |
|
||||
| `qjjdizcpjk` | 上海 | 上海 | 上海张江 |
|
||||
| `j1lw6k13ya` | 陕西 | 西安 | 西安环普 |
|
||||
| `uzwlfke8vd` | 广州 | 深圳 | 深圳田厦 |
|
||||
| `mrtkjjhoxx` | 上海 | 上海 | 上海徐汇 |
|
||||
| `t21uyq5qvx` | 北京 | 北京 | 北京 |
|
||||
| `nhu45qlh80` | 四川 | 成都 | 成都 |
|
||||
| `5sntzs5dlr` | 加拿大 | 加拿大 | 多伦多 |
|
||||
| `1` | 上海 | 上海 | 上海闵行 |
|
||||
|
||||
## 指定用户同步示例
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from extensions.sync_ehr_to_ad.api import ActiveDirectoryClient, SyncEhrToAdApi
|
|||
logger = logging.getLogger("connecthub.extensions.sync_ehr_to_ad")
|
||||
|
||||
_EHR_AD_ACCOUNT_KEY = "extADAccountName_606508_511687157"
|
||||
_EHR_WORK_LOCATION_VALUE_KEY = "extgzddxx1_606508_892394263"
|
||||
_EHR_WORK_LOCATION_TEXT_KEY = "extgzddxx1_606508_892394263Text"
|
||||
_EHR_STREET_ADDRESS_KEY = _EHR_WORK_LOCATION_TEXT_KEY
|
||||
_EHR_STREET_ADDRESS_FALLBACK_KEYS = ("WorkSpacevalue", "extgzddxx_606508_618643707")
|
||||
|
|
@ -102,6 +103,30 @@ def _field_value(item: dict[str, Any], key: str) -> str:
|
|||
return ""
|
||||
|
||||
|
||||
def _field_raw_value(item: dict[str, Any], key: str) -> str:
|
||||
emp = item.get("employeeInfo") or {}
|
||||
rec = item.get("recordInfo") or {}
|
||||
for node in (emp, rec):
|
||||
if not isinstance(node, dict):
|
||||
continue
|
||||
s = _scalar_value(node.get(key))
|
||||
if s:
|
||||
return s
|
||||
s = _custom_prop_value(node.get("customProperties"), key)
|
||||
if s:
|
||||
return s
|
||||
for child in node.values():
|
||||
if not isinstance(child, dict):
|
||||
continue
|
||||
s = _scalar_value(child.get(key))
|
||||
if s:
|
||||
return s
|
||||
s = _custom_prop_value(child.get("customProperties"), key)
|
||||
if s:
|
||||
return s
|
||||
return ""
|
||||
|
||||
|
||||
def _field_translate_or_value(item: dict[str, Any], key: str) -> str:
|
||||
emp = item.get("employeeInfo") or {}
|
||||
rec = item.get("recordInfo") or {}
|
||||
|
|
@ -266,6 +291,82 @@ def _location_from_workplace(workplace: str, mappings: dict[str, Any] | None = N
|
|||
return {}
|
||||
|
||||
|
||||
def _location_from_workspace_value(value: str, mappings: dict[str, Any] | None = None) -> dict[str, Any]:
|
||||
code = str(value or "").strip()
|
||||
defaults: dict[str, dict[str, Any]] = {
|
||||
"qjjdizcpjk": {
|
||||
"co": "China",
|
||||
"c": "CN",
|
||||
"countryCode": 156,
|
||||
"st": "上海",
|
||||
"l": "上海",
|
||||
"office": "上海张江",
|
||||
},
|
||||
"j1lw6k13ya": {
|
||||
"co": "China",
|
||||
"c": "CN",
|
||||
"countryCode": 156,
|
||||
"st": "陕西",
|
||||
"l": "西安",
|
||||
"office": "西安环普",
|
||||
},
|
||||
"uyglfkg8vd": {
|
||||
"co": "China",
|
||||
"c": "CN",
|
||||
"countryCode": 156,
|
||||
"st": "广州",
|
||||
"l": "深圳",
|
||||
"office": "深圳田厦",
|
||||
},
|
||||
"mrtkjjhoxx": {
|
||||
"co": "China",
|
||||
"c": "CN",
|
||||
"countryCode": 156,
|
||||
"st": "上海",
|
||||
"l": "上海",
|
||||
"office": "上海徐汇",
|
||||
},
|
||||
"t21uyq5qvx": {
|
||||
"co": "China",
|
||||
"c": "CN",
|
||||
"countryCode": 156,
|
||||
"st": "北京",
|
||||
"l": "北京",
|
||||
"office": "北京",
|
||||
},
|
||||
"nhu45qlh80": {
|
||||
"co": "China",
|
||||
"c": "CN",
|
||||
"countryCode": 156,
|
||||
"st": "四川",
|
||||
"l": "成都",
|
||||
"office": "成都",
|
||||
},
|
||||
"5sntzg5dlr": {
|
||||
"co": "Canada",
|
||||
"c": "CA",
|
||||
"countryCode": 124,
|
||||
"st": "加拿大",
|
||||
"l": "加拿大",
|
||||
"office": "多伦多",
|
||||
},
|
||||
"1": {
|
||||
"co": "China",
|
||||
"c": "CN",
|
||||
"countryCode": 156,
|
||||
"st": "上海",
|
||||
"l": "上海",
|
||||
"office": "上海闵行",
|
||||
},
|
||||
}
|
||||
merged = dict(defaults)
|
||||
if isinstance(mappings, dict):
|
||||
for k, v in mappings.items():
|
||||
if isinstance(v, dict):
|
||||
merged[str(k).strip()] = v
|
||||
return dict(merged.get(code, {}))
|
||||
|
||||
|
||||
def _org_name(org: dict[str, Any]) -> str:
|
||||
for key in ("name", "Name", "shortName", "ShortName"):
|
||||
s = str(org.get(key) or "").strip()
|
||||
|
|
@ -390,6 +491,7 @@ class SyncEhrToAdUserJob(BaseJob):
|
|||
max_users = int(params.get("max_users") or 0)
|
||||
connect_timeout_s = int(params.get("ldap_connect_timeout_s") or 10)
|
||||
domain_account_key = str(params.get("domain_account_custom_key") or "").strip() or _EHR_AD_ACCOUNT_KEY
|
||||
work_location_value_key = str(params.get("work_location_value_key") or "").strip() or _EHR_WORK_LOCATION_VALUE_KEY
|
||||
work_location_text_key = str(params.get("work_location_text_key") or "").strip() or _EHR_WORK_LOCATION_TEXT_KEY
|
||||
street_address_key = str(params.get("street_address_key") or "").strip() or _EHR_STREET_ADDRESS_KEY
|
||||
proxy_alias_domain = str(params.get("proxy_alias_domain") or "").strip() or None
|
||||
|
|
@ -566,6 +668,7 @@ class SyncEhrToAdUserJob(BaseJob):
|
|||
job_number = str(rec.get("jobNumber") or rec.get("JobNumber") or "").strip()
|
||||
mobile = _field_value(item, "MobilePhone") or _extract_mobile_phone(emp)
|
||||
office = _field_translate_or_value(item, "Place")
|
||||
workplace_value = _field_raw_value(item, work_location_value_key)
|
||||
workplace_text = _field_translate_or_value(item, work_location_text_key)
|
||||
street_address = _field_value(item, street_address_key)
|
||||
if not street_address:
|
||||
|
|
@ -583,7 +686,20 @@ class SyncEhrToAdUserJob(BaseJob):
|
|||
street_address,
|
||||
)
|
||||
company = default_company or _root_org_name(org, org_by_oid)
|
||||
location_attrs = _location_from_workplace(workplace_text or office, location_mappings)
|
||||
location_attrs = _location_from_workspace_value(workplace_value, location_mappings) or _location_from_workplace(
|
||||
workplace_text or office, location_mappings
|
||||
)
|
||||
office = str(location_attrs.get("office") or office or "").strip()
|
||||
if verbose_trace:
|
||||
logger.info(
|
||||
"AD 办公地点映射:sam=%s workspace_key=%s workspace_value=%r province=%r city=%r office=%r",
|
||||
sam,
|
||||
work_location_value_key,
|
||||
workplace_value,
|
||||
location_attrs.get("st"),
|
||||
location_attrs.get("l"),
|
||||
office,
|
||||
)
|
||||
|
||||
manager_dn = ""
|
||||
manager_uid = _to_int_safe(rec.get("pOIdEmpAdmin") or rec.get("POIdEmpAdmin"))
|
||||
|
|
|
|||
Loading…
Reference in New Issue