Last active
July 23, 2024 09:59
-
-
Save tkc49/becb670b0fc9c06940e999163143ec6a to your computer and use it in GitHub Desktop.
稼働率を計算するプログラム
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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