メインコンテンツまでスキップ

実績工数データを他の管理システムに反映する


概要

TimeTracker NXで入力された実績工数は、社内の採算管理や勤怠管理にとっても重要なデータです。Web APIを活用することにより、実績工数データを社内で運用している他のシステムに簡単に取り込むことができます。

利用場面

  • 日単位の実績工数データを勤怠管理システムに反映
  • 週単位/月単位の実績工数データを勤怠管理システムに反映

使用するAPI

以下のAPIを使用します。

  • ユーザーの取得
  • 実績工数の取得

サンプルスクリプト

//======================================================================
// 日単位の実績工数を取得する
//======================================================================
//======================================================================
// 外部ファイル(ライブラリ、他ファイル)のインクルード
//======================================================================

const https = require('https'); // HTTPS通信を利用する場合に設定する
const http = require('http'); // HTTP通信を利用する場合に設定する
const axios = require('axios');
const fs = require('fs');
const iconv = require("iconv-lite");


//======================================================================
// 共通部の定義
//======================================================================

// APIを呼び出すURLを設定する
const baseURLString = 'http://yourserver/TimeTrackerNX/api';

// サーバースペックに合わせてウェイト時間を設定する
// 1分間に1500件程度の処理に収まるようするため、
// 目安として推奨スペックでは100ms程度とする 
const requestWaitTime = 100; //単位:ms

//----------------------------------------------------------------------
// Web API間の処理待ち関数
//----------------------------------------------------------------------
async function wait(time){
const d1 = new Date();
while (true) {
const d2 = new Date();
if (d2 - d1 > time) {
break;
}
}
}

//======================================================================
// メイン処理
//======================================================================
main();

async function main(){

// 引数チェック
if (process.argv.length < 3){
return 'enter username and password';
}

const userName = process.argv[2];
var pass;
var authString; //ブロック内スコープから外に出すためvarで宣言(固定値)

// 引数でパスワードが未入力の場合は空白とみなす
if (process.argv.length > 3){
pass = process.argv[3];
} else {
pass = '';
}

// 認証情報を取得する
var sendUrl = baseURLString + '/auth/token';

try{
const { data } = await axios.post(
sendUrl,
{
loginName : userName,
password : pass
},
/*
// https通信時に使用する
httpsAgent : new https.Agent({
rejectUnauthorized: false
})
*/
);
authString = 'Bearer ' + data.token;

} catch (err) {
console.log(err);
}

// 以降のAPI通信で利用する送信ヘッダを作成する
const request = axios.create({
baseURL : baseURLString,
headers :{
'Authorization' : authString
},
/*
// https通信時に使用する
httpsAgent : new https.Agent({
rejectUnauthorized: false
})
*/
});

// 実績出力の対象ユーザーを取得
var sendUrl = '/system/users';

try {
// 所属組織を指定してユーザーIDを取得する(リクエストに検索条件の所属組織を設定して送信)
const { data } = await request.get(
sendUrl,
{
params: {
organizations : '開発2課'
}
}
);

// 初回のデータ書き込み時に見出しを追加するためのフラグを設定
var headerFlag = 1;

// 指定した組織に所属するユーザーの実績工数を一人ずつ取得する
for (var key in data.data){
sendUrl = '/system/users/' + data.data[key].id + '/timeEntries';

// 対象ユーザーの実績工数を取得する(リクエストに取得期間の開始日・終了日を設定して送信)
try {
const { data } = await request.get(
sendUrl,
{
params: {
startDate : '2019-03-01',
finishDate : '2019-03-31'
}
}
);

// 取得したデータをCSV形式で出力する
outputData(headerFlag, data);

// 初回のデータ書き込みが終わったタイミングでフラグを無効にする
if(headerFlag == 1){
headerFlag = 0;
}

/*
// 取得したデータをJSON形式で出力(1ユーザーごとに追加するので"[][][]"と続く出力になる)
fs.appendFileSync('./output.json',JSON.stringify(data,undefined,4),function(err){
if (err) {
console.log(err);
}
});
*/
} catch (e) {
console.log(e);
}
await wait(requestWaitTime);
}
} catch (e) {
console.log(e);
}
}

function outputData(headerFlag, data){
var filepath = './output.csv';
var buffer;

// 初回の書き込みのみヘッダを追加
if(headerFlag == 1){

buffer = 'projectId,projectName,projectCode,workDate,startTime,finishTime,time,memo,workItemId,workItemName,workItemNumber,workItemTypeId,userId,userName,timeEntryCategoryId,timeEntryCategory,processCategoryId,processCategory,isLocked,isDeleted,id,createdAt,createdBy,updatedAt,updatedBy\n';

fs.writeFileSync(filepath, iconv.encode(buffer, 'Shift_JIS'), function(err){
if (err) {
console.log(err);
}
});
}

// 1行分ごとにデータをファイルへ追記する
for (var key in data.data){
var array = [
data.data[key].projectId,
data.data[key].projectName,
data.data[key].projectCode,
data.data[key].workDate,
data.data[key].startTime,
data.data[key].finishTime,
data.data[key].time,
data.data[key].memo,
data.data[key].workItemId,
data.data[key].workItemName,
data.data[key].workItemNumber,
data.data[key].workItemTypeId,
data.data[key].userId,
data.data[key].userName,
data.data[key].timeEntryCategoryId,
data.data[key].timeEntryCategory,
data.data[key].processCategoryId,
data.data[key].processCategory,
data.data[key].isLocked,
data.data[key].isDeleted,
data.data[key].id,
data.data[key].createdAt,
data.data[key].createdBy,
data.data[key].updatedAt,
data.data[key].updatedBy
]
buffer = array.join(',') + '\n';

fs.appendFileSync(filepath, iconv.encode(buffer, 'Shift_JIS'), function(err){
if (err) {
console.log(err);
}
});
}
}