コンテンツにスキップ

$p.apiUpdateSite

概要

AjaxのPOSTリクエストにより、サイト情報を更新します。

構文

JavaScript
$p.apiUpdateSite({
    id: (更新対象サイトID),
    data: {
        (更新するサイト情報)
    },
    done: (任意の処理),
    fail: (任意の処理),
    always: (任意の処理)
});

各パラメータの説明

パラメータ名 説明 必須
id 更新対象のサイトID ○
data POSTするJSONデータ ※欄外補足参照 -
done API通信成功 ○
fail API通信失敗 -
always 完了時 -

※POSTするJSONデータは、サイトパッケージをエクスポートした際の"Site”パラメータと同等の値を設定する必要があります。$p.apiGetSiteでサイト情報を取得したのち、更新したい項目を変更してリクエストデータを作成するような処理を想定します。

使用例

JavaScript
$p.apiUpdateSite({
  id: 123,
  data: {
    TenantId: 1,
    Title: 'サイト名',
    ReferenceType: 'Issues',
    InheritPermission: 99999,
    SiteSettings: {
      Version: 1.017,
      ReferenceType: 'Issues',
      GridColumns: [
        'IssueId',
        'TitleBody',
        'Comments',
        'StartTime',
        'CompletionTime',
        'WorkValue',
        'ProgressRate',
        'RemainingWorkValue',
        'Status',
        'Manager',
        'Owner',
        'Updator',
        'UpdatedTime'
      ],
      EditorColumnHash: {
        General: [
          'IssueId',
          'Ver',
          'Title',
          'Body',
          'StartTime',
          'CompletionTime',
          'WorkValue',
          'ProgressRate',
          'RemainingWorkValue',
          'Status',
          'Manager',
          'Owner',
          'Comments'
        ]
      }
    },
    done: function (data) {
      //任意の処理
    },
    fail: function (data) {
      //任意の処理
    },
    always: function (data) {
      //任意の処理
    }
  }
});

サンプルコード

Note

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

1. 案件レコードの担当者・承認者を、案件サイトのアクセス権に反映する

案件ごとに作った案件サイト(案件の担当者と承認者に限って権限を付けたサイト)について、担当者や承認者が交代したときに、案件管理テーブルのレコードでプロセス「権限反映」を押すと、案件サイトのアクセス権を今の担当者・承認者に合わせます。$p.apiGetSiteで今のアクセス権を取得し、ユーザーに付けた権限を担当者(書き込み)と承認者(読取専用)に入れ替えて、$p.apiUpdateSiteでアクセス権のみを書き戻します。組織・グループに付けた権限と、サイトの管理者の権限はそのまま残します。

実務での使いどころ

案件やプロジェクトごとにサイトを作り、関係者に限って見られるようにしていると、異動や担当替えのたびにサイトのアクセス権を直す必要があります。画面で直すには、案件サイトを開いて「テーブルの管理」のアクセス制御で、前任者を外して後任者を加える操作が要り、案件が多いと直し忘れが起こります。このサンプルを使うと、案件レコードの担当者・承認者を変えてボタンを押せば、案件サイトのアクセス権がレコードの内容に合わせて直り、反映した日時もレコードに残ります。

事前準備

1:案件管理のテーブル(記録テーブル)に以下の項目を有効化してください。

項目コード 内容
分類A(ClassA) 案件コード
タイトル(Title) 案件名
分類B(ClassB) 案件担当者。選択肢一覧に[[Users*]]を設定します
分類C(ClassC) 承認者。選択肢一覧に[[Users*]]を設定します
分類D(ClassD) 案件サイトのID
日付A(DateA) 権限の最終反映日時。スクリプトが入れます。時刻まで表示する書式にします

2:「テーブルの管理 > プロセス」タブで、プロセス「権限反映」を追加します。画面種別は「編集」、実行種別は「追加したボタン」、アクション種別は「保存」、現在の状況と変更後の状況は空のまま、OnClickはapplySitePermissions($(this))にします。
3:スクリプトを登録します。
 3-1:「テーブルの管理 > スクリプト」タブで「新規作成」を選択する。
 3-2:タイトル: 任意の名前(例:権限反映)
 3-3:スクリプト: 下記サンプルコードを貼り付け
 3-4:出力先:「編集」にチェック

JavaScript
/**
 * ================================================================
 * サンプル01  案件レコードの担当者・承認者を、案件サイトのアクセス権に反映する
 * ================================================================
 *
 * 【概要】
 *   案件ごとに作った案件サイト(案件の担当者と承認者にだけ権限を付けたサイト)に
 *   ついて、担当者や承認者が交代したときに、案件管理テーブルのレコードで
 *   プロセス「権限反映」を押すと、案件サイトのアクセス権を今の担当者・承認者に
 *   合わせます。
 *     1. $p.apiGetSite で、案件サイトの今のアクセス権を取得する
 *     2. ユーザーに付けた権限を外し、担当者(書き込み)と承認者(読取専用)の
 *        権限を加える。組織・グループに付けた権限と、サイトの管理者(サイトの管理と
 *        権限の管理の両方を持つユーザー)の権限はそのまま残す
 *     3. $p.apiUpdateSite でアクセス権だけを書き戻し、反映した日時をレコードに残す
 *
 * 【ポイント】
 *   ・$p.apiUpdateSite に送るのは InheritPermission と Permissions だけにします。
 *     この2つだけを送ると、タイトル・一覧・エディタ・スクリプトなどのサイトの設定は
 *     そのまま残り、アクセス権だけが置き換わります。取得したサイトの情報
 *     (SiteSettings を含む)をまるごと送り返すと、設定全体が置き換わるので
 *     避けてください。
 *   ・Permissions は送った内容でまるごと置き換わります(追記ではありません)。
 *     そのため、取得したアクセス権から組み立て直して送ります。
 *   ・アクセス権には、「サイトの管理」と「権限の管理」の両方を持つ人(ユーザー・
 *     組織・グループのどれか)が少なくとも1つ必要です。いなくなる内容を送ると、
 *     エラー(ステータスコード 500、メッセージ「無し」)になり更新されません。
 *     そのため、管理者のユーザーは外さず、管理者がいなくなるときは送る前に止めます。
 *   ・アクセス権を継承しているサイトは、取得すると Permissions が空になります。
 *     空を「権限なし」として書き戻すと継承を壊すので、継承しているサイトは
 *     変更しません。
 *   ・OnClick を設定したプロセスは、ボタンを押しただけでは保存されません。
 *     アクセス権の更新が成功したあとに $p.set で反映日時を入れてから
 *     $p.execProcess を呼ぶと、その値と一緒にレコードを保存します。
 *
 * 【注意】
 *   ・案件サイトにユーザー単位で付けた権限は、管理者を除き、担当者・承認者以外の
 *     ものも外れます。ほかの人にも権限を付けたい場合は、組織かグループで付けてください。
 *   ・組織をAPIやインポートでまとめて作成・更新した直後は、Pleasanter内部の
 *     組織情報が古いままになり、一部の組織の権限が $p.apiGetSite の Permissions に
 *     含まれないことがあります。その状態で書き戻すと、その組織の権限が消えます。
 *     組織をまとめて作成・更新した直後に使うときは、先にいずれかの組織を1件
 *     更新(画面で保存し直すだけでよい)してから実行してください。
 *
 * 【使い方】
 *   下記の定数を、実際に使用する項目コードに置き換えてください。
 *   あわせて「テーブルの管理 > プロセス」で、プロセス「権限反映」を追加して
 *   ください(画面種別:編集、実行種別:追加したボタン、アクション種別:保存、
 *   現在の状況・変更後の状況:指定しない、OnClick:applySitePermissions($(this)))。
 *   押せるのは、案件サイトの「権限の管理」の権限を持つ人です。
 *   スクリプトの出力先は「編集」にチェックしてください。
 * ================================================================
 */

// ===== 設定 =====
const SITE_ID_COLUMN = 'ClassD'; // 案件サイトのID
const MANAGER_COLUMN = 'ClassB'; // 案件担当者(選択肢一覧に [[Users*]]。値はユーザーID)
const APPROVER_COLUMN = 'ClassC'; // 承認者(選択肢一覧に [[Users*]])
const APPLIED_AT_COLUMN = 'DateA'; // 権限の最終反映日時(スクリプトが入れる)
// 付ける権限(読取 1/作成 2/更新 4/削除 8/メール送信 16 … の合計)
const MANAGER_PERMISSION = 31; // 担当者:書き込み(読取・作成・更新・削除・メール送信)
const APPROVER_PERMISSION = 1; // 承認者:読取専用
// サイトの管理(128)+権限の管理(256)。これを含む権限を持つ人を「管理者」として残す
const MANAGE_PERMISSION = 128 + 256;

// ===== 処理 =====
function showMessage(css, text) {
    $p.clearMessage();
    $p.setMessage('#Message', JSON.stringify({ Css: css, Text: text }));
}

// 失敗の応答から、表示するメッセージを取り出す
function errorMessage(data, fallback) {
    try {
        return JSON.parse(data.responseText).Message || fallback;
    } catch (e) {
        return fallback;
    }
}

// Date を「2026/10/07 14:30」の形にする
function formatDateTime(date) {
    const pad = (n) => String(n).padStart(2, '0');
    return (
        `${date.getFullYear()}/${pad(date.getMonth() + 1)}/${pad(date.getDate())} ` +
        `${pad(date.getHours())}:${pad(date.getMinutes())}`
    );
}

// 「User,2,31」の形の文字列を、種別・ID・権限の値に分ける
function parsePermission(text) {
    const [type, id, value] = text.split(',');
    return { type: type, id: id, value: Number(value) };
}

function isManager(value) {
    return (value & MANAGE_PERMISSION) === MANAGE_PERMISSION;
}

// 今のアクセス権から、ユーザーの権限を担当者・承認者に入れ替えたものを作る
function buildPermissions(current, managerId, approverId) {
    const others = []; // 組織(Dept)・グループ(Group)の権限。そのまま残す
    const userPermissions = {}; // ユーザーID → 権限の値
    current.map(parsePermission).forEach(function (p) {
        if (p.type !== 'User') {
            others.push(`${p.type},${p.id},${p.value}`);
        } else if (isManager(p.value)) {
            // 管理者のユーザーは外さない
            userPermissions[p.id] = p.value;
        }
    });
    // 担当者・承認者の権限を加える。同じ人(管理者を含む)なら、値をビットの論理和で合わせる
    if (managerId) {
        userPermissions[managerId] = (userPermissions[managerId] || 0) | MANAGER_PERMISSION;
    }
    if (approverId) {
        userPermissions[approverId] = (userPermissions[approverId] || 0) | APPROVER_PERMISSION;
    }
    return others.concat(
        Object.keys(userPermissions).map(function (userId) {
            return `User,${userId},${userPermissions[userId]}`;
        })
    );
}

// 管理者(サイトの管理と権限の管理の両方を持つ人)が1つ以上あるか
function hasManager(permissions) {
    return permissions.map(parsePermission).some(function (p) {
        return isManager(p.value);
    });
}

// 並び順を無視して、2つのアクセス権が同じか
function samePermissions(a, b) {
    return JSON.stringify([...a].sort()) === JSON.stringify([...b].sort());
}

// プロセス「権限反映」の OnClick から呼ぶ
function applySitePermissions($button) {
    const siteId = Number($p.getValue(SITE_ID_COLUMN));
    if (!siteId) {
        showMessage('alert-error', '案件サイトのIDが入っていません。');
        return;
    }
    const managerId = String($p.getValue(MANAGER_COLUMN) || '');
    const approverId = String($p.getValue(APPROVER_COLUMN) || '');

    $p.apiGetSite({
        id: siteId,
        done: function (data) {
            const site = data.Response.Data;
            // 継承しているサイトは、InheritPermission が継承元のサイトIDになっている
            if (Number(site.InheritPermission) !== siteId) {
                showMessage(
                    'alert-error',
                    `案件サイト(ID:${siteId})はアクセス権を継承しているため、変更しません。` +
                        `継承元(ID:${site.InheritPermission})のアクセス権を確認してください。`
                );
                return;
            }
            const current = site.Permissions || [];
            const next = buildPermissions(current, managerId, approverId);
            if (samePermissions(current, next)) {
                showMessage('alert-info', 'アクセス権の変更はありません。');
                return;
            }
            if (!hasManager(next)) {
                // 管理者がいなくなる内容は、送ってもエラーになるので送らない
                showMessage(
                    'alert-error',
                    `案件サイト(ID:${siteId})の管理者(サイトの管理と権限の管理の両方を持つ人)が` +
                        'いなくなるため、変更できません。案件サイトに管理者を設定してください。'
                );
                return;
            }
            $p.apiUpdateSite({
                id: siteId,
                // アクセス権だけを送る(SiteSettings は送らない)
                data: { InheritPermission: siteId, Permissions: next },
                done: function () {
                    $p.set($p.getControl(APPLIED_AT_COLUMN), formatDateTime(new Date()));
                    $p.execProcess($button);
                },
                fail: function (error) {
                    showMessage('alert-error', errorMessage(error, 'アクセス権を更新できませんでした。'));
                },
            });
        },
        fail: function (error) {
            showMessage('alert-error', errorMessage(error, `案件サイト(ID:${siteId})を取得できませんでした。`));
        },
    });
}

注意点

  • $p.apiUpdateSiteにはInheritPermissionとPermissionsのみを送っています。この2つのみを送ると、タイトル・一覧・エディタ・スクリプトなどのサイトの設定はそのまま残り、アクセス権のみが置き換わります。取得したサイトの情報(SiteSettingsを含む)をまるごと送り返すと、設定全体が置き換わります。
  • Permissionsは送った内容でまるごと置き換わります。そのため、取得したアクセス権から組み立て直して送っています。
  • アクセス権には、「サイトの管理」と「権限の管理」の両方を持つ人(ユーザー・組織・グループのいずれか)が1つ以上必要です。いなくなる内容を送るとエラーになり更新されないため、サイトの管理者のユーザーは外さず、管理者がいなくなるときは送る前にメッセージを出して止めます。
  • アクセス権を継承している案件サイトは変更しません(継承しているサイトは、取得したアクセス権が空になるため、そのまま書き戻すと継承を壊します)。
  • ボタンを押せるのは、案件サイトの「権限の管理」の権限を持つ人です。
  • 組織をAPIやインポートでまとめて作成・更新した直後は、一部の組織の権限が$p.apiGetSiteの結果に含まれないことがあり、その状態で書き戻すと、その組織の権限が消えます。その場合は、先にいずれかの組織を1件更新(画面で保存し直す)してから実行してください。

関連情報