- An XML file that contains the code below is available to download
- kintone-record-datetime-field.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
/**
* @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 トークン
* @return {string} result.basic Basic 認証設定
*/
const prepare = () => {
const auth = configs.get("conf_auth");
const basic = configs.get("conf_basic");
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,
basic
};
};
/**
* 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,
basic
} = prepare();
const records = getRecords(apiUri, apiToken, basic, {
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 {String} basic Basic 認証設定
* @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, basic, {
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);
if (basic !== "" && basic !== null) {
request = request.authSetting(basic);
}
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);
};
Pingback: Starting Processes According to Records Shown in kintone Calendar. – Questetra Support