Start: kintone: Record's Datetime Field
Start Process when time in Record’s datetime field has passed, on a kintone App. It is able to specify record “Created datetime” “Updated datetime” as datetime field.
Configs
  • C1: Authorization Setting in which API Token is set *
  • C2: Domain (such as xxxxx.kintone.com or xxxxx.cybozu.com) *
  • C3: Guest Space ID (required if the App is in a Guest Space)
  • C4: App ID *
  • C5: Field Code of Datetime Field to be checked *
  • C6: Search Query
  • C7: Data item to save Record ID *
  • C8: Data item to save Datetime data
Script (click to open)

/**
* @typedef {Object} timestamp java.sql.Timestamp オブジェクト
*/

/** 日時フォーマッター */
const datetimeFormatter = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
/**
* @param {string} str 日時文字列
* @return {timestamp} java.sql.Timestamp オブジェクト
*/
const parseDatetime = str => new java.sql.Timestamp(datetimeFormatter.parse(str).getTime());

/**
* configs から必要な情報の取り出し
* @return {object} result 設定情報
* @return {string} result.appId アプリ ID
* @return {string} result.apiUrl API の URL
* @return {string} result.datetimeField チェック対象の日時データのフィールドコード
* @return {string} result.query 検索条件
* @return {string} result.apiToken API トークン
*/
const prepare = () => {
const auth = configs.get("conf_auth");
const domain = configs.get("conf_domain");
const guestSpaceId = configs.get("conf_guestSpaceId");
const appId = configs.get("conf_appId");
const datetimeField = configs.get("conf_datetimeField");
const query = configs.get("conf_query");

checkAppId(appId);
const apiUri = determineApiUri(domain, guestSpaceId);

const apiToken = httpClient.getOAuth2Token(auth);

return {
appId,
apiUri,
datetimeField,
query,
apiToken
};
};

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

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

/**
* アプリ ID が空または不正な文字列であればエラーとする
* @param {String} appId アプリ ID
*/
const checkAppId = (appId) => {
if (appId === "" || appId === null) {
throw "App ID is empty.";
}
if (!isValidId(appId)) {
throw "Invalid App ID.";
}
};

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

/**
* レコードの検索
* @param limit レコード数の上限
* @param timestampLowerLimit timestamp の下限
* @return {Array} records レコード一覧
*/
const list = (limit, timestampLowerLimit) => {
const {
appId,
apiUri,
datetimeField,
query,
apiToken
} = prepare();

const records = getRecords(apiUri, apiToken, {
appId,
datetimeField,
query,
limit,
timestampLowerLimit
});
logRecords(records);
return records;
};

/**
* レコードのログ出力
* @param {Array} records レコード一覧
*/
const logRecords = (records) => {
const replacer = (key, value) => value instanceof java.sql.Timestamp ? datetimeFormatter.format(value) : value;
records.forEach(record => {
engine.log(JSON.stringify(record, replacer));
});
};

/**
* kintone REST API にレコード取得の GET リクエストを送信する
* @param {String} apiUri API の URI
* @param {String} apiToken API トークン
* @param {Object} params API リクエストのパラメータに使用する情報が格納されたオブジェクト
* @param {string} params.appId アプリ ID
* @param {string} params.datetimeField 日時データのフィールドコード
* @param {string} params.query 検索条件
* @param {number} params.limit 結果件数の上限
* @param {timestamp} params.timestampLowerLimit timestamp の下限
* @return {Array} records レコード一覧
* @return {string} records[].id レコードID + 日時データ
* @return {string} records[].recordId レコードID
* @return {timestamp} records[].timestamp レコードの日時データ
*/
const getRecords = (apiUri, apiToken, {
appId,
datetimeField,
query,
limit,
timestampLowerLimit
}) => {
const getRecordsUri = `${apiUri}records.json`;
engine.log(`API URI: ${getRecordsUri}`);
engine.log(`appId: ${appId}`);

let request = httpClient.begin()
.header("X-Cybozu-API-Token", apiToken)
.queryParam('app', appId);

let queryString = `${datetimeField} >= "${datetimeFormatter.format(timestampLowerLimit)}" and ${datetimeField} <= NOW()`;
if (query !== '') {
queryString = `(${query}) and ${queryString}`;
}
queryString = `${queryString} order by ${datetimeField} desc, $id desc limit ${limit}`;
engine.log(`query: ${queryString}`);
request = request.queryParam('query', queryString);
request = request.queryParam('fields[0]', '$id');
request = request.queryParam('fields[1]', datetimeField);
const response = request.get(getRecordsUri);

//when error thrown
const responseJson = response.getResponseAsString();
const status = response.getStatusCode();
if (status >= 300) {
const accessLog = `---GET request--- ${status}\n${responseJson}\n`;
engine.log(accessLog);
throw `Failed to get records. status: ${status}`;
}
const json = JSON.parse(responseJson);

// レコードオブジェクトを整形して返す
const formatRecord = (record) => {
const recordId = String(record['$id']['value']);
const timestamp = parseDatetime(record[datetimeField]['value']);
// recordId と timestamp の組み合わせを id に。日時データの変更に対応するため。
const id = `${recordId}_${timestamp.getTime()}`;
return {
id,
recordId,
timestamp
};
};

return json.records.map(formatRecord);
};

Download

2021-03-19 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/bpmn-icons/start-event-kintone-record-datetime-field/
The Addon-import feature is available with Professional or Enterprise edition.

Notes

  1. To get the API Token, open the App Settings on Kintone and click “API Token” in the App Settings tab.

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

    Do not forget to click “Update App” to apply the update.
  2. 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.
  3. The Questetra BPM Suite will periodically poll the Kintone App to check records. If the App has any records whose data matches the Search Query and whose datetime data in the specified field has newly passed, the process will be started.
  4. Supported field types are: Date and time, Created datetime and Updated datetime. If you specify the field code of Created datetime, processes will be started for newly created records. If you specify the field code of Updated datetime, processes will be started for newly modified records.
  5. See the Kintone Reference for the operators and functions that can be used in the Search Query. Query options (order by, limit, offset) are not supported.
  6. Process will not be started on the first check. Only the check will be done. You can confirm the check status from “Process Log”.
  7. If the App has a large number of records whose datetime data has passed in a short period of time, the processes may not be started for all records. Approx. 90 processes in every 15 minutes.

Capture

%d bloggers like this: