Timer Start: kintone: Number of Records

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

This item periodically starts processes with the number of records matching the search query from a Kintone App. In each string type data item of each process, each record ID will be set.

Basic Configs
Step Name
Note
Auto Step icon
Configs for this Auto Step
conf_auth
C1: Authorization Setting in which API Token is set *
conf_basic
C2: Basic Auth Setting (required if enabled on Kintone)
conf_domain
C3: Domain (such as xxxxx.kintone.com or xxxxx.cybozu.com) *
conf_guestSpaceId
C4: Guest Space ID (required if the App is in a Guest Space)
conf_appId
C5: App ID *
conf_query
C6: Search Query#{EL}
conf_idData
C7: Data item to save Record ID *

Notes

  • You can set multiple schedules on a Timer
  • The number of Processes that can be started simultaneously is limited to 100
  • To get the API Token, open the App Settings and click “API Token” in the App Settings tab on Kintone

    Click “Generate”, select the Permissions (“View records” permission is required), and click “Save”

    Do not forget to click “Update App” to apply the update
  • Guest Space ID (only when the Kintone App is in a guest space) and App ID can be confirmed in the API Token settings on Kintone
  • See the Kintone Reference for the operators and functions that can be used in Search Query
    • Query options (order by, limit, offset) are not supported

Capture

See Also

Script (click to open)
  • An XML file that contains the code below is available to download
    • kintone-num-of-records.xml (C) Questetra, Inc. (MIT License)
      • Just use it for a reference for the codes
      • This file cannot be imported into a Workflow App as an Add-on

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 bloggers like this: