タイマー開始: kintone: レコード数

Timer Start: kintone: Number of Records

このアイテムは、kintone アプリから検索クエリに合致するレコード数の数だけ、定期的にプロセスを開始します。 各プロセスの文字型データ項目には、それぞれのレコード ID が設定されます。

Basic Configs
工程名
メモ
Auto Step icon
Configs for this Auto Step
conf_auth
C1: API トークンを設定した認証設定 *
conf_basic
C2: Basic 認証設定(kintone で設定されている場合のみ)
conf_domain
C3: ドメイン(xxxxx.kintone.com または xxxxx.cybozu.com) *
conf_guestSpaceId
C4: ゲストスペース ID(ゲストスペース内のアプリの場合のみ)
conf_appId
C5: アプリ ID *
conf_query
C6: 検索クエリ#{EL}
conf_idData
C7: レコード ID を保存するデータ項目 *

Notes

  • 複数のタイマー時刻を設定することができます
  • 同時に起動できるプロセス数は100に制限されます
  • kintone アプリのAPI トークンを取得するには、アプリの設定画面の「設定(App Settings)」のタブを開き、「API トークン(API Token)」へと進みます

    「生成する(Generate)」をクリックし、権限(Permissions)を選択(「レコード参照(View records)」権限が必要です)したあと、「保存(Save)」をクリックします

    「アプリを更新(Update App)」をクリックして変更を適用するのも忘れないようにしてください
  • kintone アプリのゲストスペース ID(アプリがゲストスペースにある場合)とアプリ ID は、API トークンの設定画面で確認することができます
  • 検索クエリで使用可能な演算子と関数については、kintone のリファレンスを参照してください
    • オプション(order by, limit, offset)は使用できません

Capture

See Also

Script (click to open)
  • 次のスクリプトが記述されている XML ファイルをダウンロードできます
    • kintone-num-of-records.xml (C) Questetra, Inc. (MIT License)
      • コードの参考用にご利用ください
      • アドオンとしてワークフローアプリにインポートすることはできません

function list(limit) {
//// == 工程コンフィグの参照 / Config Retrieving ==
    const auth = configs.getObject("conf_auth");
    const basic = configs.getObject("conf_basic");
    const domain = configs.get("conf_domain");
    const guestSpaceId = configs.get("conf_guestSpaceId");
    const appId = configs.get("conf_appId");
    const query = configs.get("conf_query");

//// == ワークフローデータの参照 / Data Retrieving ==
    const apiUri = determineApiUri(domain, guestSpaceId);
    checkAppId(appId);

    return getRecords(apiUri, auth.getToken(), basic, {app: appId, query}, limit);
}

/**
 * kintone REST API のレコード取得の URI を決定する
 * ドメインが空、または kintone のドメインとして不正な文字列であればエラーとする
 * @param {String} domain  ドメイン
 * @param {String} guestSpaceId  ゲストスペース ID
 * @return {String} apiUri  API の URI
 */
function determineApiUri(domain, guestSpaceId) {
    checkDomain(domain);
    let apiUri;
    if (guestSpaceId === "" || guestSpaceId === null) {
        apiUri = `https://${domain}/k/v1/`;
    } else {
        if (!isValidId(guestSpaceId)) {
            throw new Error("Invalid Guest Space ID.");
        }
        apiUri = `https://${domain}/k/guest/${guestSpaceId}/v1/`;
    }
    return apiUri;
}

/**
 * ドメインが空または不正な文字列であればエラーとする
 * @param {String} domain  ドメイン
 */
function checkDomain(domain) {
    if (domain === "" || domain === null) { // required="true" なので空になることはないが、チェック
        throw new Error("Domain is empty.");
    }
    const reg = new RegExp('^[0-9a-zA-Z-]{3,32}.(?:kintone.com|cybozu.com)$');
    if (!reg.test(domain)) {
        throw new Error("Invalid Kintone domain.");
    }
}

/**
 * アプリ ID が空または不正な文字列であればエラーとする
 * @param {String} appId  アプリ ID
 */
function checkAppId(appId) {
    if (appId === "" || appId === null) { // required="true" なので空になることはないが、チェック
        throw new Error("App ID is empty.");
    }
    if (!isValidId(appId)) {
        throw new Error("Invalid App ID.");
    }
}

/**
 * ID が有効か(自然数か)を判定する
 * @param {String} idString  ID の文字列
 * @return {Boolean}  有効な ID かどうか
 */
function isValidId(idString) {
    const idReg = new RegExp('^[1-9][0-9]*$');
    return idReg.test(idString);
}

/**
 * kintone REST API にレコード取得の GET リクエストを送信する
 * 未取得のレコードがなくなるまで再帰的に実行される
 * @param {String} apiUri  API の URI
 * @param {String} apiToken  API トークン
 * @param {String} basic  Basic 認証設定
 * @param {Object} params  GET リクエストのパラメータに使用する情報が格納されたオブジェクト
 *   プロパティ:  {String} app  アプリ ID
 *              {String} query  検索クエリ
 * @param {Number} limit  1 回のリクエストで取得するレコード数
 * @return {Array<String>} records  レコード ID の配列
 */
function getRecords(apiUri, apiToken, basic, {app, query}, limit) {
    const getRecordsUri = `${apiUri}records.json`;
    let request = httpClient.begin()
        .queryParam("app", app)
        .header("X-Cybozu-API-Token", apiToken);
    if (basic !== null) {
        request = request.authSetting(basic);
    }
    // query パラメータの設定
    if (query === "" || query === null) {
        request = request.queryParam("query", `order by $id asc limit ${limit + 1}`);
    } else {
        request = request.queryParam("query", `( ${query} ) order by $id asc limit ${limit + 1}`);
    }
    request = request.queryParam('fields[0]', '$id');
    const response = request.get(getRecordsUri);
    //when error thrown
    const responseStr = response.getResponseAsString();
    const status = response.getStatusCode();
    if (status >= 300) {
        engine.log(`---GET request--- ${status}\n${responseStr}\n`);
        throw new Error(`Failed to get records. status: ${status}`);
    }
    const records = JSON.parse(responseStr).records;
    if (records.length > limit) {
        throw new Error(`The number of records exceeds the limit ${limit}.`);
    }
    return records.map(record => ({
        id: record.$id.value
    }));
}
%d