> ## Documentation Index
> Fetch the complete documentation index at: https://help.dingtalk.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 勤怠 API とイベントによる社員の出勤状況の取得

> 勤怠打刻イベントと勤怠 API で社員の打刻データを収集し、正常・遅刻・欠勤などのステータスを自動判定して出勤状況を監視する方法を解説します。

# 勤怠データの可視化：リアルタイムの出勤状況監視と異常アラート

## 概要

本ソリューションは、社員の勤怠状況を企業のダッシュボードにエンドツーエンドで表示します。DingTalk オープンプラットフォームの Stream プッシュの仕組みと勤怠 API を使用して、データをリアルタイムに収集し、ステータスを自動判定して、標準化されたデータを出力します。

### 背景

企業では、社員の勤怠状況をリアルタイムに把握する必要があります。特に製造現場、カスタマーサービスセンター、小売店舗では、管理者がダッシュボードで現在勤務中の人数、遅刻、欠勤などの主要な指標を確認しています。しかし、DingTalk 標準の勤怠データは管理コンソール内にあり、企業独自のダッシュボードシステムと直接接続できません。そのため、次のような問題が発生します。

* **データ取得の遅延**：人事担当者が勤怠レポートを手動でエクスポートする必要があり、秒単位での更新ができません。
* **システム連携の難しさ**：標準化された API がないため、社内の BI やダッシュボードシステムに勤怠データを組み込むことが困難です。
* **ステータス判定の複雑さ**：打刻時刻だけでは「正常／遅刻／欠勤」を判定できません。担当者がシフト設定のルールと手動で照合する必要があります。
* **監視の死角**：想定外の場所からの打刻や代理打刻などの異常な打刻に対して、リアルタイムにアラートを発信できません。

### 主なメリット

本ソリューションは、勤怠データをリアルタイムに収集・分析します。手動でエクスポートしていたオフラインデータを API ベースのリアルタイムストリームに置き換えることで、意思決定の効率とデータの透明性を大幅に向上させます。

* **リアルタイムのデータ収集**：Stream プッシュの仕組みにより、打刻のたびにミリ秒単位でサーバーへコールバックが送信されます。体感できる遅延なくデータを同期できます。
* **ステータスの自動判定**：打刻時刻をシフト設定のルールと自動で照合し、「正常／遅刻／早退／欠勤」などのステータスを正確に識別します。
* **標準化された API 出力**：統一された RESTful API により、ダッシュボード、BI システム、OA のカンバンボードとシームレスに連携できます。
* **履歴の完全な追跡**：過去の勤怠記録を一括で照会できるため、月次統計や傾向分析などの詳細な分析にも対応します。

### ユースケース

本ソリューションは、次のような業務シナリオに適しています。

* **製造現場のダッシュボード**：生産ラインごとの勤務中の人数、欠勤率、遅刻アラートをリアルタイムに表示し、生産計画を支援します。
* **カスタマーサービスセンターの監視**：オペレーターの勤怠を監視して適切な人員配置を確保し、リソースを迅速に再配分します。
* **小売店舗の管理**：各店舗の社員の打刻状況を監視し、来店客数に合わせてシフトを調整します。
* **本社の統合管理センター**：グループ全体の勤怠データを集約し、地域横断の比較や異常アラートを支援します。

## 代表的な業務シナリオ

### シナリオ 1：製造現場でのリアルタイム出勤状況監視

#### 課題

従来は、現場の責任者が 2 時間ごとに生産ラインごとの勤務中の人数を手作業で数えていました。1 回の集計に 30 分かかり、集計が終わる頃にはデータがすでに古くなっています。突発的な欠勤が発生しても生産計画をすぐに調整できず、生産能力の損失につながります。

#### 導入効果

* **自動化されたフロー**

  エンドツーエンドのフロー：

  1. 社員が DingTalk App で出勤または退勤の打刻を行います。
  2. 打刻データが **Stream** チャンネル（コールバック）を通じてリアルタイムにプッシュされます。
  3. 企業のサーバーがデータを受信し、**シフト設定**のルールと照合してステータスを自動判定します。
  4. 判定結果をデータベースに書き込み、パフォーマンス向上のため **Redis** にキャッシュします。
  5. **API** を通じてデータを返し、ダッシュボードに最新の出勤状況をリアルタイムに表示します。
* **主な利点**

  * **秒単位の更新**：打刻から 1 秒以内にダッシュボードが更新されるため、管理者は人員配置をリアルタイムに把握できます。
  * **自動アラート**：欠勤率がしきい値（例：10%）を超えると、SMS または DingTalk の通知が自動送信され、迅速に対応できます。
  * **履歴との比較**：前年同期比・前期比の分析により季節的な欠勤傾向を把握し、シフトの最適化に役立てます。
  * **多角的なフィルタリング**：生産ライン、チーム、職種で絞り込み、問題のある領域を特定します。

### シナリオ 2：カスタマーサービスセンターでの人員配置の最適化

#### 課題

カスタマーサービスの責任者は、各時間帯に実際に勤務している人数をリアルタイムに把握できません。その結果、ピーク時には人手が不足し、閑散時には人員が過剰になりがちです。これにより顧客満足度が低下し、運用コストが増加します。

#### 導入効果

* **自動化されたフロー**

  自動化されたフローは次の 5 段階で構成されます。

  1. カスタマーサービスのオペレーターが **DingTalk** で打刻し、打刻時刻と位置情報が記録されます。
  2. **Stream** が打刻イベントをサーバーへリアルタイムにプッシュします（ミリ秒単位のコールバック）。
  3. AI が出勤ステータスを判定し、履歴の照会や分析のために勤怠データを保存します。
  4. ヒートマップエンジンが時間帯ごとの人員分布を算出し、ピーク、閑散期、人員不足のリスクを特定します。
  5. 大型スクリーンのダッシュボードに予測曲線とシフトの提案を表示し、管理者の意思決定と早期警告を支援します。
* **主な利点**

  * **ヒートマップ表示**：タイムラインとオペレーター数で人員の集中箇所を可視化します。
  * **予測に基づくシフト設定**：履歴データから今後 2 時間の人員需要を予測し、事前にシフトを調整します。
  * **異常検知**：遅刻の繰り返しや頻繁な早退などのパターンを自動で識別し、要注意リストを作成します。
  * **パフォーマンスとの相関分析**：勤怠データを応答率や顧客満足度などの KPI と関連付け、人員投資の効果を定量化します。

## 実装ガイド

### 技術アーキテクチャ

本ソリューションは、DingTalk オープンプラットフォームのサーバー API と Stream プッシュの仕組みを使用します。主な技術コンポーネントは次のとおりです。

* **認証レイヤー**：`Client ID` と `Client Secret` を使用して `access_token` を取得し、API 呼び出しを保護します。
* **リアルタイムデータ取り込みレイヤー**：Stream プッシュを設定して勤怠打刻イベントをサブスクライブし、サーバーでミリ秒単位でコールバックを受信します。
* **ステータス判定エンジン**：ローカルのアルゴリズムで打刻時刻をシフト設定のルールと照合し、「正常／遅刻／重度の遅刻／欠勤」のステータスを自動で識別します。
* **データの保存とキャッシュ**：勤怠グループのシフト設定ルールは 1 時間ごとに全量同期します。打刻記録はリアルタイムにデータベースへ書き込み、キャッシュします。
* **標準化された API 出力レイヤー**：RESTful API でダッシュボードや BI システムにデータを提供し、多角的なフィルタリングと集計クエリに対応します。

データフロー：社員が DingTalk App で打刻 → Stream がリアルタイムにコールバックをプッシュ → 企業のサーバーがデータを受信してステータスを判定 → データベースへの書き込みとキャッシュ → ダッシュボード API がデータを返却。

### 前提条件

本ソリューションを実装する前に、次の要件を満たしていることを確認してください。

* **App の準備**：社内アプリを作成して設定します。詳細は [App の作成と設定](https://help.dingtalk.io/ja/open/dingstart/create-application.md) を参照してください。
* **権限の要件**：DingTalk の組織管理者またはサブ管理者の権限を持っていること。
* **開発環境**：Java の開発環境（JDK 1.6 以降）とビルドツールの Maven がインストールされていること。
* **SDK の準備**：DingTalk のサーバーサイド SDK をダウンロードします。詳細は「サーバーサイド SDK のダウンロード」を参照してください。Java、Python、Go などの言語に対応しています。
* **サーバーの要件**：Stream プッシュのコールバックを受信するために、社内にパブリックアクセス可能なサーバーがあること。
* **ダッシュボードシステム**：ダッシュボードシステムが HTTP API によるデータ取り込みに対応していること（ECharts、DataV、Tableau など）。

### コードの実装

ステップ 1：クライアント ID と Client Secret を含む App の認証情報を取得します。

ステップ 2：この例では API 権限は不要です。

ステップ 3：App のアクセス認証情報を取得します。詳細は [社内アプリの access\_token を取得する](https://help.dingtalk.io/ja/open/development/obtain-orgapp-token) を参照してください。API を呼び出す際は、アクセストークンによって呼び出し元が認証されます。

ステップ 4：次の呼び出しフローに従います。

1. 勤怠のサーバー API [勤怠グループ詳細の一括取得](https://help.dingtalk.io/ja/open/development/batch-obtain-attendance-group-details.md) を呼び出し、社内の勤怠グループの始業時刻と終業時刻を取得します。
2. 社員の打刻データを取得するには、勤怠のイベントコールバックを登録します。ドキュメントの説明に従って Stream プッシュ（推奨）を設定し、勤怠イベントをサブスクライブします。
3. ステータス判定ロジックを実装します。リアルタイムにプッシュされた打刻情報（userId、groupId、checkTime）をキャッシュ済みの勤怠グループのシフトと照合し、打刻ステータス（Normal／Late／SeriousLate／Absent）を判定します。
4. ダッシュボードシステム向けに標準化された API を提供し、部門、勤怠グループ、期間などの軸でリアルタイムの出勤データを照会できるようにします。

## 実装手順

### **ステップ 1：App の認証情報を取得する**

1. [DingTalk 開発者コンソール](https://open-dev.dingtalk.io/) にログインします。
2. 対象の App を選択して詳細ページを開きます。
3. **基本情報** > **認証情報と基本情報** をクリックします。
4. App の `Client ID` と `Client Secret` を控えておきます。

### 注意

`Client Secret` は安全に保管し、第三者と共有しないでください。ハードコーディングせず、環境変数またはキー管理システムに保存してください。

### **ステップ 2**：アクセス認証情報（access\_token）を取得する

ステップ 1 で取得した Client ID と Client Secret を使用して、App のアクセス認証情報を取得します。詳細は [社内アプリの access\_token を取得する](https://help.dingtalk.io/ja/open/development/obtain-orgapp-token) を参照してください。

```java theme={"theme":{"light":"github-light","dark":"github-dark"}}
public void getAccessToken() throws ApiException {
  DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.io/gettoken");
  OapiGettokenRequest req = new OapiGettokenRequest();
  req.setAppkey("dingxxxxxxxxxhgn");
  req.setAppsecret("9G_xxxxxxxxxxxxxxx1JDf0Qq3nexxxxxxxxGIO");
  req.setHttpMethod("GET");
  OapiGettokenResponse rsp = client.execute(req);
  System.out.println(rsp.getBody());
}
```

**ベストプラクティス**：

* **キャッシュ戦略**：`access_token` の有効期間は 2 時間です。メモリまたは Redis にキャッシュし、有効期限の 5分前に更新してください。
* **同時実行の制御**：複数のスレッドが同時にトークンを更新することによる競合を防ぐため、分散ロックを使用してください。
* **エラー時の再試行**：ネットワークが不安定な場合は自動で再試行します。再試行は最大 3 回とし、間隔を段階的に延ばします（1s → 2s → 4s）。

### ステップ 3：主要な API を呼び出す

1. **勤怠グループの詳細を一括取得する**：勤怠のサーバー API [勤怠グループ詳細の一括取得](https://help.dingtalk.io/ja/open/development/batch-obtain-attendance-group-details.md) を呼び出し、社内の勤怠グループの始業時刻と終業時刻を取得します。

   ```java theme={"theme":{"light":"github-light","dark":"github-dark"}}
   public void batchGetAttendanceGroups() throws ApiException {
       DingTalkClient client = new DefaultDingTalkClient("https://api.dingtalk.io/topapi/attendance/getsimplegroups");
       OapiAttendanceGetsimplegroupsRequest req = new OapiAttendanceGetsimplegroupsRequest();
       // リクエストパラメータを設定
       OapiAttendanceGetsimplegroupsResponse rsp = client.execute(req, "access_token");
       System.out.println(rsp.getBody());
   }
   ```
2. **Stream プッシュを設定して勤怠イベントをサブスクライブする**：「Stream プッシュの設定（推奨）」のドキュメントに従って勤怠のイベントコールバックを登録し、勤怠イベントをサブスクライブします。

   **コールバックのデータ構造**：

   ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
   {
     "DataList":[
       {
         // 打刻した社員の userId
         "userId":"0126xxxx",
         // 打刻時刻（ミリ秒）
         "checkTime":1570791880000,
         // 打刻時の住所
         "address":"中国科学院工程熱物理研究所 浙江海外ハイレベル人材イノベーションパーク 7号棟東",
         // 組織ID（corpId）
         "corpId":"dingxxxx",
         // 社員が所属する勤怠グループの ID
         "groupId":"4C63xxxx",
         // 打刻地点の緯度
         "latitude":30.285230848524307,
         // 打刻地点の経度
         "longitude":120.01713514539931,
         // 打刻の業務 ID
         "bizId":"FF62xxxx",
         // 位置情報の取得方法
         "locationMethod":"MAP",
       }
     ],
     "EventType":"attendance_check_record"
   }
   ```
3. **ステータス判定ロジック**：

   **コアアルゴリズム**：リアルタイムにプッシュされた打刻情報（userId、groupId、checkTime）をキャッシュ済みの勤怠グループのシフトと照合し、打刻ステータスを判定します。

   ```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
   public String determineAttendanceStatus(String userId, String groupId, String checkTime) {
       // 1. キャッシュからこの勤怠グループのシフト設定ルールを取得
       ScheduleRule rule = cache.getScheduleRule(groupId);

       // 2. 打刻時刻を解析
       LocalDateTime punchTime = LocalDateTime.parse(checkTime, formatter);

       // 3. 予定時刻と比較
       if (punchTime.isBefore(rule.getStartTime().plusMinutes(rule.getLateThreshold()))) {
           return "Normal";  // 定刻どおりの打刻
       } else if (punchTime.isBefore(rule.getStartTime().plusMinutes(rule.getSeriousLateThreshold()))) {
           return "Late";    // 遅刻
       } else {
           return "SeriousLate";  // 重度の遅刻
       }
   }
   ```

   **ステータスの対応表**：

   | **条件** | **返されるステータス** | **ダッシュボードの表示色** |
   | - | - | - |
   | 打刻時刻 ≤ 始業時刻 + 遅刻のしきい値 | Normal | 🟢 緑 |
   | 始業時刻 + 遅刻のしきい値 \< 打刻時刻 ≤ 重度の遅刻のしきい値 | Late | 🟡 黄 |
   | 打刻時刻 > 重度の遅刻のしきい値 | SeriousLate（重度の遅刻） | 🔴 赤 |

**実装チェックリスト**：

* ✅ Stream プッシュが設定済みで、打刻のコールバックを受信できる。
* ✅ 勤怠グループのシフト設定ルールが正しくキャッシュされ、1 時間ごとに自動更新される。
* ✅ ステータス判定ロジックがテストで 100% の正確性を達成している。
* ✅ ダッシュボード API のレスポンス時間が \<200ms である。
* ✅ 異常な打刻（想定外の場所からの打刻など）が正しくフラグ付けされ、アラートがトリガーされる。

## FAQ

* **Q1：Stream プッシュとポーリングの違いは何ですか？**

  A：2 つの方式は、データの取得方法がまったく異なります。

  * **ポーリング**：サーバーが定期的に API を呼び出して打刻記録を照会します。遅延（通常 5～15 分）が発生し、頻繁に呼び出すとレート制限に達しやすくなります。
  * **Stream プッシュ**：社員が打刻するとすぐに、DingTalk が指定の URL へデータをプッシュします。遅延は \<1 秒で、能動的な照会は不要です。リアルタイムのダッシュボードに適しています。

  **主な違い**：Stream プッシュはイベント駆動型で、必要なときだけデータをプッシュします。ポーリングはスケジュール駆動型で、新しいデータの有無にかかわらず API を呼び出します。可能な限り Stream プッシュを使用してください。
* **Q2：社員が「遅刻」か「欠勤」かはどのように判定しますか？**

  A：次のロジックを適用します。

  * **遅刻**：打刻記録はあるものの、打刻時刻が始業時刻に遅刻のしきい値（通常 10～30 分。勤怠グループの設定で変更可能）を加えた時刻より後である場合。
  * **欠勤**：現在時刻（例：午後 3 時）の時点で当日の打刻記録がなく、かつシフト設定のルール上、当日が出勤日である場合。

  **注意**：常にシフト設定のルールを確認してください。社員がシフト上の休日である場合、打刻がなくても欠勤とはみなされません。
* **Q3：想定外の場所からの打刻や代理打刻にはどう対処すればよいですか？**

  A：DingTalk の勤怠イベントコールバックには `LocationResult` フィールドが含まれており、打刻場所が有効かどうかを示します。

  * `Normal`：打刻場所が勤怠グループで許可された範囲内にあります。
  * `Outside`：打刻場所が許可された範囲外にあり、想定外の場所からの打刻の可能性があります。

  **対処方針**：

  * `LocationResult=Abnormal` の記録は、ダッシュボード上でオレンジ色の警告として表示します。
  * 異常な打刻の日次レポートを作成し、人事管理者に送信して確認してもらいます。
  * Wi-Fi や位置情報などの多要素検証を組み合わせて、代理打刻のリスクを低減します。
* **Q4：ダッシュボードの更新頻度はどのくらいが適切ですか？**

  A：業務シナリオによって異なります。

  * **製造現場／カスタマーサービスセンター**：リアルタイム性を確保するため、1～5 秒ごとに更新します。
  * **小売店舗**：パフォーマンスと即時性のバランスを取るため、30 秒～1 分ごとに更新します。
  * **本社の統合管理センター**：秒単位の監視ではなく傾向分析を重視し、5～10 分ごとに更新します。

  **パフォーマンスの最適化**：全量更新ではなく、変更されたデータ（新しい打刻記録など）のみをプッシュする増分更新を使用してください。これにより、ネットワークのオーバーヘッドを 90% 以上削減できます。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.