Skip to content

Instantly share code, notes, and snippets.

@tkc49
Last active July 23, 2024 09:59
Show Gist options
  • Save tkc49/becb670b0fc9c06940e999163143ec6a to your computer and use it in GitHub Desktop.
Save tkc49/becb670b0fc9c06940e999163143ec6a to your computer and use it in GitHub Desktop.
稼働率を計算するプログラム
(function($) {
'use strict';
dayjs.locale('ja');
// アプリIDの定義
const APP_IDS = {
facilityManagement: 5, // 施設管理アプリ
facilityReservation: 6, // 施設予約管理アプリ
utilizationManagement: 7 // 稼働率管理アプリ
};
// レコードを取得する関数
async function fetchRecords(appId, query = '') {
const allRecords = [];
let lastId = 0;
const limit = 500;
try {
while (true) {
const response = await kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {
app: appId,
query: `${query} ${lastId ? `and $id > ${lastId}` : ''} order by $id asc limit ${limit}`,
totalCount: true
});
allRecords.push(...response.records);
if (allRecords.length >= response.totalCount || response.records.length < limit) {
break;
}
lastId = response.records[response.records.length - 1].$id.value;
}
return allRecords;
} catch (error) {
console.error(`Error fetching records from app ID ${appId}:`, error);
await Swal.fire({
icon: 'error',
title: 'エラー',
text: `アプリID ${appId} からレコードを取得中にエラーが発生しました。`
});
}
}
// レコードを登録する関数
function postRecords(appId, records) {
const chunkSize = 100;
for (let i = 0; i < records.length; i += chunkSize) {
const chunk = records.slice(i, i + chunkSize);
const body = { app: appId, records: chunk };
// レコードを登録するAPIを呼び出す
kintone.api(kintone.api.url('/k/v1/records', true), 'POST', body, function(resp) {
console.log('Records successfully upserted to app ID:', appId);
}, async function(error) {
console.error('Error upserting records:', error);
await Swal.fire({
icon: 'error',
title: 'エラー',
text: 'レコードの登録中にエラーが発生しました。'
});
});
}
}
// 施設管理情報を取得する関数
function getFacilityManagementInfo() {
return fetchRecords(APP_IDS.facilityManagement);
}
// 稼働率管理のレコードを削除する関数
async function deleteUtilizationManagement(selectedDate) {
const firstDayString = dayjs(selectedDate).startOf('month').format('YYYY-MM-DD');
const lastDayString = dayjs(selectedDate).endOf('month').format('YYYY-MM-DD');
const query = `日付 >= "${firstDayString}" and 日付 <= "${lastDayString}"`;
try {
const records = await fetchRecords(APP_IDS.utilizationManagement, query);
const ids = records.map(record => record.$id.value);
console.log('IDs to delete:', ids);
const deleteChunks = [];
for (let i = 0; i < ids.length; i += 100) {
deleteChunks.push(ids.slice(i, i + 100));
}
// レコードを削除するAPIを呼び出す
const deletePromises = deleteChunks.map(chunk => {
return kintone.api(kintone.api.url('/k/v1/records', true), 'DELETE', { app: APP_IDS.utilizationManagement, ids: chunk });
});
await Promise.all(deletePromises);
} catch (error) {
console.error('Error deleting records:', error);
await Swal.fire({
icon: 'error',
title: 'エラー',
text: 'レコードの削除中にエラーが発生しました。'
});
}
}
// 施設予約情報を取得する関数
function getFacilityReservationInfo(selectedDate) {
const firstDayString = dayjs(selectedDate).startOf('month').format('YYYY-MM-DD');
const lastDayString = dayjs(selectedDate).endOf('month').format('YYYY-MM-DD');
const query = `利用日 >= "${firstDayString}" and 利用日 <= "${lastDayString}" and キャンセル not in ("キャンセル")`;
return fetchRecords(APP_IDS.facilityReservation, query);
}
// 稼働率管理のレコードを作成する関数
async function createUtilizationManagement(selectedDate, facilityManagementInfo, facilityReservationInfo) {
const firstDayString = dayjs(selectedDate).startOf('month').format('YYYY-MM-DD');
const lastDayString = dayjs(selectedDate).endOf('month').format('YYYY-MM-DD');
const utilizationManagement = [];
const monthlyUtilizationByFacility = {};
let currentDate = dayjs(firstDayString);
while (currentDate.isBefore(lastDayString) || currentDate.isSame(lastDayString)) {
const dateString = currentDate.format('YYYY-MM-DD');
const utilizationByFacility = {};
facilityManagementInfo.forEach(facility => {
const facilityName = facility.施設名.value;
utilizationByFacility[facilityName] = {
利用時間合計: 0,
利用可能合計: parseFloat(facility.利用可能時間.value)
};
if (!monthlyUtilizationByFacility[facilityName]) {
monthlyUtilizationByFacility[facilityName] = {
利用時間合計: 0,
利用可能合計: 0
};
}
});
facilityReservationInfo.forEach(reservation => {
if (reservation.利用日.value === dateString) {
const facilityName = reservation.施設名.value;
utilizationByFacility[facilityName].利用時間合計 += parseFloat(reservation.利用時間.value);
}
});
// 日次の稼働率管理レコードを作成する
Object.keys(utilizationByFacility).forEach(facilityName => {
utilizationManagement.push({
対象: { value: '日次' },
会議室名: { value: facilityName },
日付: { value: dateString },
利用時間合計: { value: utilizationByFacility[facilityName].利用時間合計 },
利用可能時間合計: { value: utilizationByFacility[facilityName].利用可能合計 }
});
monthlyUtilizationByFacility[facilityName].利用時間合計 += utilizationByFacility[facilityName].利用時間合計;
monthlyUtilizationByFacility[facilityName].利用可能合計 += utilizationByFacility[facilityName].利用可能合計;
});
currentDate = currentDate.add(1, 'day');
}
// 月次の稼働率管理レコードを作成する
Object.keys(monthlyUtilizationByFacility).forEach(facilityName => {
utilizationManagement.push({
対象: { value: '月次' },
会議室名: { value: facilityName },
日付: { value: selectedDate },
利用時間合計: { value: monthlyUtilizationByFacility[facilityName].利用時間合計 },
利用可能時間合計: { value: monthlyUtilizationByFacility[facilityName].利用可能合計 }
});
});
postRecords(APP_IDS.utilizationManagement, utilizationManagement);
}
// 月選択ボックスを初期化する関数
function initializeMonthSelectBox() {
const headerMenuSpace = kintone.app.getHeaderMenuSpaceElement();
if (!headerMenuSpace) {
return;
}
if (document.getElementById('containerDiv')) {
return;
}
const containerDiv = document.createElement('div');
containerDiv.id = 'containerDiv';
const input = document.createElement('input');
input.id = 'monthSelectBox';
input.type = 'text';
const button = document.createElement('button');
button.id = 'submitButton';
button.textContent = '作成する';
containerDiv.appendChild(input);
containerDiv.appendChild(button);
headerMenuSpace.appendChild(containerDiv);
// 月選択ボックスに日付ピッカーを設定する
$(input).datepicker({
dateFormat: 'yy-mm',
changeMonth: true,
changeYear: true,
showButtonPanel: true,
monthNames: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
monthNamesShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
isRTL: false,
yearSuffix: '年',
showMonthAfterYear: true,
onClose: function(dateText, inst) {
const month = $("#ui-datepicker-div .ui-datepicker-month :selected").val();
const year = $("#ui-datepicker-div .ui-datepicker-year :selected").val();
$(this).datepicker('setDate', new Date(year, month, 1));
}
});
$("#monthSelectBox").focus(function () {
$(".ui-datepicker-calendar").hide();
$("#ui-datepicker-div").position({
my: "center top",
at: "center bottom",
of: $(this)
});
});
// ボタンのクリックイベントを設定する
button.addEventListener('click', async function() {
Swal.fire({
title: '処理中',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
}
});
const selectedDate = $('#monthSelectBox').val();
if (selectedDate) {
// 稼働率管理アプリの対象の日付を削除する
await deleteUtilizationManagement(selectedDate);
const facilityManagementInfo = await getFacilityManagementInfo();
const facilityReservationInfo = await getFacilityReservationInfo(selectedDate);
await createUtilizationManagement(selectedDate, facilityManagementInfo, facilityReservationInfo);
Swal.close();
await Swal.fire({
icon: 'success',
title: '処理完了',
text: '稼働率管理アプリにデータを作成しました'
});
location.reload();
} else {
await Swal.fire({
icon: 'error',
title: 'エラー',
text: '年月が選択されていません',
didOpen: () => {
Swal.hideLoading();
},
showCancelButton: false,
confirmButtonText: 'OK',
});
}
});
}
// アプリのインデックスページが表示されたときに月選択ボックスを初期化する
kintone.events.on('app.record.index.show', () => {
initializeMonthSelectBox();
});
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment