コンテンツにスキップ

組織取得

概要

APIを使用して組織の内容を取得することができます。

事前準備

APIの操作を行う前にAPIキーの作成を実施してください。

リクエスト

下記のリクエスト形式で、jsonデータを送信します。

設定項目 値
HTTPメソッド POST
Content-Type application/json
文字コード UTF-8
URL http://{サーバ名}/api/depts/get (※1)
Body 以下のjsonデータを参考のこと。詳細は「JSONデータレイアウト:共通」、「JSONデータレイアウト:View」を参照してください。

(※1){サーバ名}の部分は、適宜、環境に合わせて編集してください。
  pleasanter.netの場合は以下の形式になります。
  https://pleasanter.net/fs/api/depts/get

組織情報を取得する場合

JSON
{
     "ApiVersion": 1.1,
     "ApiKey": "dD32ai53j3asdK2fre..."
}

条件を指定して一致する組織情報を取得する場合

JSON

{
    "ApiVersion": 1.1,
    "ApiKey": "1ao3ea5kDH2335sar529UY...",
    "View": {
        "ColumnFilterHash": {
            "Groups": "[1,2]"
        }
    }
}

上の例は、グループIDが1または2のグループに含まれる組織が取得されます。

レスポンス

下記の形式のjsonデータが返却されます。
Response部分のデータのレイアウトは「JSONデータレイアウト:Dept」を参照してください。
また、拡張項目(ClassHash/NumHash/DateHash/DescriptionHash/CheckHash)を含めて取得できます。取得できる項目の詳細は「拡張項目」を参照してください。

JSON
{
    "StatusCode": 200,
    "Response": {
        "Offset": 0,
        "PageSize": 200,
        "TotalCount": 1,
        "Data": [
            {
                "TenantId": 1,
                "DeptId": 1,
                "Ver": 1,
                "DeptCode": "1234",
                "DeptName": "システム開発部",
                "Body": "",
                "Disabled": false,
                "Comments": "[]",
                "Creator": 1,
                "Updator": 1,
                "CreatedTime": "2023-04-01T12:00:00",
                "UpdatedTime": "2023-08-15T12:00:00",
                "ApiVersion": 1.1,
                "ClassHash": {
                },
                "NumHash": {
                },
                "DateHash": {
                },
                "DescriptionHash": {
                },
                "CheckHash": {
                },
                "AttachmentsHash": {
                }
            }
        ]
    }
}

サンプルコード

Note

コード内の【 ... 】は適宜修正してください。

1. 組織の新設・廃止・名称変更を検知して、棚卸テーブルへ書き込む

組織取得APIで全組織を取得し、「棚卸テーブル」に保存した前回の状態と比べて、新設・廃止・名称変更があった組織のみを棚卸テーブルへ書き込みます。棚卸テーブルの通知(作成後・更新後)と組み合わせると、組織の変更があったときに限ってメールが届きます。変更が無い組織は書き込まないため、通知も届きません。

実務での使いどころ

組織の新設・統合・廃止のあと、組織を選択肢やアクセス権に使っているテーブルの設定の直し忘れを防ぎたい場面に使えます。組織の管理画面では今の組織の一覧は見られますが、前回から何が変わったかを知らせる機能はありません。夜間などに定期的に実行しておけば、変更があったときに気づけます。

事前準備

1:「棚卸テーブル」(記録テーブル)を作成し、以下の項目を有効化してください。

項目コード 内容
分類A(ClassA) 組織名
分類B(ClassB) 組織コード(突合のキー)
分類C(ClassC) 検知した変更(新設/廃止/再開/名称変更)
分類D(ClassD) 変更前の組織名(名称変更のときのみ)
チェックA(CheckA) 無効
日付A(DateA) 検知日時

2:「棚卸テーブル」の「テーブルの管理 > 通知」で、通知を作成し、「作成後」と「更新後」にチェックしてください。

3:サンプルコードのBASE_URL・API_KEY・INVENTORY_SITE_IDを書き替えてください。APIキーは、全組織を取得できるテナント管理者のものを使います。

Python
# ==========================================================
# 組織マスタの棚卸:組織取得APIで全組織を取得し、棚卸テーブルに保存した前回の状態と比べて、
# 新設・廃止・名称変更があった組織だけを棚卸テーブルへ書き込みます。
# 棚卸テーブルの通知(作成後・更新後)と組み合わせると、組織の変更があったときだけメールが届きます。
# 変更が無い組織は書き込まないため、通知も届きません。
# ==========================================================
import datetime

import requests

# ===== 設定 =====
# APIキーは、全組織を取得できるテナント管理者のものを使ってください
BASE_URL = "【URL】"
API_KEY = "【APIキー】"
INVENTORY_SITE_ID = "【棚卸テーブルのサイトID】"

PAGE_SIZE = 200           # 1回の取得件数
BULK_UPSERT_MAX = 10000   # bulkupsertで1回に送れる件数の上限(General.jsonの既定値)

DEPT_CODE_COLUMN = "ClassB"    # 組織コード(突合のキー)
DEPT_NAME_COLUMN = "ClassA"    # 組織名
CHANGE_COLUMN = "ClassC"       # 検知した変更(新設/廃止/再開/名称変更)
OLD_NAME_COLUMN = "ClassD"     # 変更前の組織名(名称変更のときのみ)
DISABLED_COLUMN = "CheckA"     # 無効(廃止)
DETECTED_AT_COLUMN = "DateA"   # 検知日時


def api_post(path, payload):
    """Pleasanter APIへPOSTし、レスポンスのJSONを返す"""
    response = requests.post(
        f"{BASE_URL}{path}",
        json={"ApiVersion": 1.1, "ApiKey": API_KEY, **payload},
        headers={"Content-Type": "application/json"},
        timeout=60,
    )
    response.raise_for_status()
    return response.json()


def fetch_all(path):
    """取得件数に応じてOffsetを進めながら、全件を取得する"""
    rows = []
    while True:
        body = api_post(path, {"Offset": len(rows), "PageSize": PAGE_SIZE})
        page = body["Response"]["Data"]
        rows.extend(page)
        if len(page) == 0 or len(rows) >= body["Response"]["TotalCount"]:
            return rows


def load_last_state():
    """棚卸テーブルに保存した前回の状態を、組織コードごとに返す"""
    state = {}
    for record in fetch_all(f"/api/items/{INVENTORY_SITE_ID}/get"):
        class_hash = record.get("ClassHash") or {}
        code = class_hash.get(DEPT_CODE_COLUMN)
        if code:
            state[code] = {
                "name": class_hash.get(DEPT_NAME_COLUMN, ""),
                "disabled": bool((record.get("CheckHash") or {}).get(DISABLED_COLUMN)),
            }
    return state


def detect_changes(dept, last):
    """前回の状態と比べて、変更の種類のリストを返す(変更が無ければ空)"""
    if last is None:
        return ["新設"]
    changes = []
    if dept["Disabled"] and not last["disabled"]:
        changes.append("廃止")
    if not dept["Disabled"] and last["disabled"]:
        changes.append("再開")
    if dept["DeptName"] != last["name"]:
        changes.append("名称変更")
    return changes


def build_bulk_data(depts, last_state, now):
    """変更があった組織のみを、bulkupsert用のData配列にする"""
    data = []
    for dept in depts:
        code = dept.get("DeptCode")
        if not code:
            print(f"組織コードが空のため対象外:{dept['DeptName']}(組織ID:{dept['DeptId']})")
            continue
        last = last_state.get(code)
        changes = detect_changes(dept, last)
        if not changes:
            continue
        old_name = last["name"] if "名称変更" in changes else ""
        data.append({
            "Title": dept["DeptName"],
            "ClassHash": {
                DEPT_CODE_COLUMN: code,
                DEPT_NAME_COLUMN: dept["DeptName"],
                CHANGE_COLUMN: "・".join(changes),
                OLD_NAME_COLUMN: old_name,
            },
            "CheckHash": {DISABLED_COLUMN: bool(dept["Disabled"])},
            "DateHash": {DETECTED_AT_COLUMN: now.isoformat()},
        })
        print(f"{code} {dept['DeptName']}:{'・'.join(changes)}")
    return data


def bulk_upsert(data):
    """組織コードをキーに、BULK_UPSERT_MAX件ずつ作成・更新する"""
    for i in range(0, len(data), BULK_UPSERT_MAX):
        api_post(f"/api/items/{INVENTORY_SITE_ID}/bulkupsert", {
            "Keys": [DEPT_CODE_COLUMN],
            "KeyNotFoundCreate": True,
            "Data": data[i:i + BULK_UPSERT_MAX],
        })


def main():
    now = datetime.datetime.now()
    depts = fetch_all("/api/depts/get")
    data = build_bulk_data(depts, load_last_state(), now)
    if data:
        bulk_upsert(data)
    print(f"組織 {len(depts)} 件のうち、変更があった {len(data)} 件を棚卸テーブルへ書き込みました。")


if __name__ == "__main__":
    main()

注記

  • 初めて実行したときは、すべての組織が「新設」として書き込まれ、組織の数と同じ件数の通知が届きます。初回は通知を無効にしておき、2回目から有効にしてください。
  • 組織コードが空の組織は、突合のキーが無いため対象外です。
  • 組織の階層(親子関係)の変更は検知しません。

エラー時の確認事項

・API使用時の注意点やエラーが発生する場合の確認事項
・FAQ:変更後の設定ファイルやAPIリクエスト(JSON形式)が正しく認識されない場合の確認事項

仕様変更について

※ 2019年10月よりAPIの仕様が一部変更となりました。
- 分類, 数値, 日付, 説明, チェック項目はjsonにそのまま記載する方法から「~Hash」の中に記載する方法へ変更されました。  

※ 2018年11月よりAPIの仕様が一部変更となりました。
- URLの形式が '/pleasanter/api_items/xxxx' から '/pleasanter/api/items/xxxx' に変更されました。
- Content-Type の指定が'application/x-www-form-urlencoded' から 'application/json'に変更されました。