---
# System prepended metadata

title: SDP 主檔更新流程

---

# SDP 主檔更新流程

## 以 [cust_id + meter_id] 取得 0 個 sdp_id，用[event.meter_id + event.meter_id] 產生新的 sdp_id 定義為 sdp_id_new

1. 調整 `event.read_time = event.read_time - (rec_no + 1)` 日
2. 取得 `event.meter_id` 所有歷程 (select * from mdes.sdp where meter_id = event.meter_id`) 並依 `sdp_start_time` 排序
3. 判斷 `event.read_time` 落在 meter_id 歷程的位置:

    3.1 `event.read_time` 落在 meter_id 歷程中，則踢錯 (E31025 "event.read_time 落在現有相同 meter_id 的歷程起訖時間中(不應有 masterless 事件)")

    3.2 未落在既有歷程中:
    
    - 新增一筆 sdpid 建立主檔：
        - `sdpid`：用新產生的 sdpid_new
        - `sdp_start_time`：調整為 `rec_no = 0` 的 `event.read_time`
        - `sdp_end_time`：找出 meter_id 歷程中 `sdp_start_time` 比 `event.read_time` 大且為最早的時間作為 `sdp_end_time`，若找不到符合的 `sdp_start_time` 則填入 `sdp_end_time = '9999-12-31'`
        - 以meter_id+cust_id為條件查詢nbs/rnbs_hist,有符合資料則填入`contact`、`address`、`energy_type`、`meter_grp_id`
        - 更新 Redis 及發布 Kafka新增事件
        


## 以 [cust_id + meter_id] 取得 1 個不重複 sdp_id, 定義為 sdp_id_old

> constant:
> `event.sdp_start_time`: datetime
> 以 event.read_time 和 rec 推到 0 計算得到
> 
> `sdp_id_old_hist`: pd.Dataframe
> 以 sdp_id_old 查詢組成的 dataframe
> 
> `select_row_by_sdp_start_time`: pd.Dataframe
> 選出 sdp_id_old_hist 運作期間包含 event.sdp_start_time 的 row, 可能為 1 或 0 筆
> 
> `next_row_by_sdp_start_time`: pd.Dataframe
> 選出 select_row_by_sdp_start_time 的下一筆, 可能為 1 或 ０ 筆

1. 調整 `event.read_time = event.read_time - (rec_no + 1)` 日
2. 取得 `sdp_id_old` 所有歷程 (查詢 `select * from mdes.sdp where sdp_id = sdp_id_old`) 並依 `sdp_start_time` 排序
3. 判斷 `event.read_time` 落在 sdpid 歷程的位置:

    3.1 若 `event.read_time` 與現有歷程的 `sdp_start_time` 相同，則踢錯 (E31026 `event.read_time` 與 `sdpid_id` 既有歷程的 `sdp_start_time` 相同)
    
    3.2 判斷 `event.sdp_start_time` 與`next_row_by_sdp_start_time` 歷程時間是否連續且與 event 內容相同 (比對cust_id`、`meter_id`、`touid`、`ct`、`pt`、`ctpt等六欄位)，若符合條件則定義check_flag=Y
     
    3.3 落在不同表號歷程中:
    
    - 若該筆歷程的 `sdp.sdp_end_time = '9999-12-31'` 則踢錯 (E31021 `meter_id` 與 `sdpid` 中活著表號歷程重疊)
    - 如果 prev_row 或 next_row 不是 event.meter_id 踢錯 E31023
    - 將該筆歷程的 `sdp_end_time` 更新為 `event.read_time`，更新 Redis，Kafka 發布一筆 `sdp_end_time` 異動
        - if check_flag<>Y則新增一筆歷程 (該筆歷程切成兩筆)：
            - 複製該筆歷程替換 `cust_id`、`meter_id`、`touid`、`ct`、`pt`、`ctpt`、`volt_type`、`multi_type`、`dist_id` 來自 event，`mitime` = 系統時間，`update_user_id = 'mn_stream_1'`，`sdp_start_time = event.read_time`，`sdp_end_time` 為該筆歷程的 `sdp_end_time`
            - 更新 Redis，Kafka 發布一筆新增歷程
        - if check_flag=Y則更改sdp_start_time(下一筆歷程時間往前推):
            - 更新下一筆歷程的 sdp_start_time 為 event.read_time
            - 更新 Redis，Kafka 發布一筆歷程異動

    3.4 落在相同表號歷程中:
    - event 內容與meter_id的歷程比對：`meter_id`、cust_id`、`touid`、`ct`、`pt`、`ctpt` 等六欄
        - 六欄皆相同：event 內容重複不須處理，更新 Redis
        - 有任一欄不相同則將該筆歷程的`sdp_end_time`更新為`event.read_time`，Kafka 發布一筆 `sdp_end_time` 異動
            - if check_flag=Y則更改sdp_start_time(下一筆歷程時間往前推)
                - 更新下一筆歷程的 sdp_start_time 為 event.read_time，更新 Redis，Kafka 發布一筆歷程異動
             - if check_flag<>Y則新增一筆歷程 (該筆歷程切成兩筆)
                - 複製該筆歷程替換`cust_id`、`meter_id`、`touid`、`ct`、`pt`、`ctpt`、`volt_type`、`multi_type`、`dist_id` 來自 event，mtime=系統時間，update_user_id='mn_stream_1'，`sdp_start_time = event.read_time`，`sdp_end_time` 為該筆歷程的 `sdp_end_time`，Kafka 發布一筆新增歷程。

  
    3.5 未落在現有歷程中:
    - 如果 prev_row 或 next_row 不是 event.meter_id 踢錯 E31023
    - 新增一筆歷程 (更新 Redis 及發布 Kafka)：
        - `sdpid`：繼承現有 `sdp_id`
        - `sdp_start_time`：調整為 `rec_no = 0` 的 `event.read_time`
        - `sdp_end_time`：找出 sdpid 歷程中 `sdp_start_time` 比 `event.read_time` 大且為最早的時間作為 `sdp_end_time`