"""R11 适配器:渠道佣金与代理商套利。 源明细:SrcTerminalBinding 映射到:Entity(IMEI, MSISDN) + 关系(BOUND_DEVICE) + MetricEvent """ from __future__ import annotations import uuid from sqlalchemy.orm import Session from app.datahub.graph_repo import add_relationship, upsert_entity from app.datahub.models import MetricEvent from app.datahub.ontology import EntityType, RelationshipType from app.datahub.staging import SrcTerminalBinding from app.ingest.base import BaseAdapter, IngestResult from app.ingest.registry import register_adapter @register_adapter class TerminalBindingAdapter(BaseAdapter): """SrcTerminalBinding → Entity(IMEI, MSISDN) + BOUND_DEVICE + MetricEvent。""" source_system = "BSS" staging_table = "src_terminal_binding" def ingest( self, session: Session, data_version_id: uuid.UUID | None = None, batch_size: int = 1000, ) -> IngestResult: result = IngestResult() query = session.query(SrcTerminalBinding) if data_version_id: query = query.filter(SrcTerminalBinding.data_version_id == data_version_id) rows = query.limit(batch_size).all() for row in rows: try: # IMEI 实体 imei_entity = upsert_entity( session, entity_type=EntityType.IMEI, business_key=row.imei, display_name=row.brand_model or row.imei, attributes={ "brand_model": row.brand_model, "region": row.region, }, data_version_id=data_version_id, ) result.entities.append(imei_entity) # MSISDN 实体 msisdn_entity = upsert_entity( session, entity_type=EntityType.MSISDN, business_key=row.msisdn, display_name=row.msisdn, attributes={"region": row.region}, data_version_id=data_version_id, ) result.entities.append(msisdn_entity) # 绑定关系 rel = add_relationship( session, RelationshipType.BOUND_DEVICE, msisdn_entity, imei_entity, attributes={ "activate_time": str(row.activate_time) if row.activate_time else None, "subsidy_amount": row.subsidy_amount, }, data_version_id=data_version_id, ) result.relationships.append(rel) # 终端激活/补贴事件 if row.activate_time: event = MetricEvent( event_time=row.activate_time, subject_type="imei", subject_key=row.imei, metric_name="terminal_activate", metric_value=row.subsidy_amount + row.commission_amount, attributes={ "msisdn": row.msisdn, "subsidy_amount": row.subsidy_amount, "commission_amount": row.commission_amount, "online_days": row.online_days, "post_activate_traffic_mb": row.post_activate_traffic_mb, "cross_province_flag": row.cross_province_flag, }, data_version_id=data_version_id, ) session.add(event) result.metric_events.append(event) result.row_count += 1 except Exception: result.error_count += 1 return result