/** * サービスレポート_出張経費精算入力 - pvc-desktop-main.js */ (function () { "use strict"; /** * システムコントロールの情報 */ const systemInfo = { 通常_開始時間: 0, 通常_終了時間: 0, 平日残業_開始時間1: 0, 平日残業_終了時間1: 0, 平日残業_開始時間2: 0, 平日残業_終了時間2: 0, 深夜_開始時間: 0, 深夜_終了時間: 0, 休日残業_開始時間: 0, 休日残業_終了時間: 0, 平日25割増_開始時間1: 0, 平日25割増_終了時間1: 0, 平日25割増_開始時間2: 0, 平日25割増_終了時間2: 0, 平日50割増_開始時間: 0, 平日50割増_終了時間: 0, 土曜25割増_開始時間: 0, 土曜25割増_終了時間: 0, 土曜50割増_開始時間: 0, 土曜50割増_終了時間: 0, }; /** * 管理者グループコード */ const adminGroupCode = "Administrators"; /** * 管理者かどうか */ let isAdmin = false; /** * サービスレポート承認者かどうか */ let isServiceReportAuthorizer = false; /** * section が「サービス」かどうか(詳細画面で使用) */ let isSectionService = false; /** * 詳細画面表示時の処理を行います。 */ kintone.events.on( ["app.record.detail.show"], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; let isKintaiKyouseiTantou = false; // Repairグループの開閉設定 setRepairGroupOpen(record); pvc.util.ui.showSpinner(); return getLoginUserGroupCodes() .then(function (groupCodes) { // 管理者かどうかを取得 isAdmin = groupCodes.indexOf(adminGroupCode) !== -1; setHiddenField(isAdmin); // システムコントロールの「サービス」と section に設定された組織と一致するか、 // およびログインユーザーが「勤怠強制連携担当者」に設定されたユーザーするかを取得 var detailUserCode = record.engineer_mechanic.value.length > 0 ? record.engineer_mechanic.value[0].code : ""; return getSystemControlRecord(detailUserCode).then(function (systemRecord) { isSectionService = false; if ( systemRecord != null && systemRecord.サービス.value.length > 0 ) { const serviceCodeList = systemRecord.サービス.value.map(function ( orgs ) { return orgs.code; }); isSectionService = record.section.value.some(function (orgs) { return serviceCodeList.indexOf(orgs.code) !== -1; }); const loginUserCode = kintone.getLoginUser().code; isKintaiKyouseiTantou = systemRecord.勤怠強制連携担当者.value.some(function (user) { return user.code === loginUserCode; }); } }); }) .then(function () { if (isSectionService && isKintaiKyouseiTantou) { // セクションに設定された組織が「サービス」、かつログインユーザーが勤怠強制連携担当者の場合 createKintaiKyouseiRenkeiButton(); } pvc.util.ui.hideSpinner(); return event; }) .catch(function (error) { console.error(error); alert("システムエラーが発生しました"); pvc.util.ui.hideSpinner(); return event; }); } ); /** * 新規登録・編集画面表示時の処理を行います。 */ kintone.events.on( ["app.record.create.show", "app.record.edit.show"], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; // テーブル行追加・削除ボタンの非表示設定 setHiddenTableRowButton(); // 作業時間情報テーブルの行数制限を設定 setLimitSagyouJikanJououTableRows(record); // Repairグループの開閉設定 setRepairGroupOpen(record); pvc.util.ui.showSpinner(); return getLoginUserGroupCodes() .then(function (groupCodes) { // 管理者かどうかを取得 isAdmin = groupCodes.indexOf(adminGroupCode) !== -1; var editUserCode = record.engineer_mechanic.value.length > 0 ? record.engineer_mechanic.value[0].code : ""; return getSystemControlRecord(editUserCode).then(function (systemRecord) { if (systemRecord != null) { // サービスレポート承認者グループに所属するユーザーかどうかを取得 const serviceReportAuthorizerCodes = systemRecord.サービスレポート承認者グループ.value.map(function ( group ) { return group.code; }); isServiceReportAuthorizer = serviceReportAuthorizerCodes.some( function (serviceReportAuthorizerCode) { return groupCodes.indexOf(serviceReportAuthorizerCode) !== -1; } ); // システムコントロール情報の設定 setSystemControlField(systemRecord, record); setSystemInfo(record); } }); }) .then(function () { setHiddenField(isAdmin); setDisabledField(record, isServiceReportAuthorizer); pvc.util.ui.hideSpinner(); return event; }) .catch(function (error) { pvc.util.ui.hideSpinner(); console.error(error); alert("システムエラーが発生しました"); return event; }); } ); /** * 「作業時間情報」変更時の処理を行います。 */ kintone.events.on( [ "app.record.create.change.作業時間情報", "app.record.edit.change.作業時間情報", ], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; // 作業時間情報テーブルの行数制限 setLimitSagyouJikanJououTableRows(record); if (event.changes.row != null) { // 行追加の場合、作業時間情報テーブルの編集不可の設定 record.作業時間情報.value.forEach(function (row) { setDisabledSagyouJikanJouhouTableRow(row); }); } return event; } ); /** * 「作業時間情報_date」変更時の処理を行います。 */ kintone.events.on( [ "app.record.create.change.作業時間情報_date", "app.record.edit.change.作業時間情報_date", ], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { /** @type {kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_作業時間情報} */ const changeRowValue = event.changes.row.value; const date = pvc.util.obj.toDate(changeRowValue.作業時間情報_date.value); if (date == null) { changeRowValue.作業時間情報_day.value = ""; } else { const youbiList = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; changeRowValue.作業時間情報_day.value = youbiList[date.getDay()]; } return event; } ); /** * 作業時間情報テーブルの時間入力フィールド変更時の処理を行います。 */ kintone.events.on( [ "app.record.create.change.作業時間情報_Working_from", "app.record.edit.change.作業時間情報_Working_from", "app.record.create.change.作業時間情報_Working_to", "app.record.edit.change.作業時間情報_Working_to", "app.record.create.change.作業時間情報_Travelling_from", "app.record.edit.change.作業時間情報_Travelling_from", "app.record.create.change.作業時間情報_Travelling_to", "app.record.edit.change.作業時間情報_Travelling_to", "app.record.create.change.作業時間情報_W_Break_min", "app.record.edit.change.作業時間情報_W_Break_min", "app.record.create.change.作業時間情報_T_Break_min", "app.record.edit.change.作業時間情報_T_Break_min", ], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { /** @type {kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_作業時間情報} */ const changeRowValue = event.changes.row.value; calcSagyouJikanJouhouRowValue(changeRowValue); return event; } ); /** * 「交通費明細」変更時の処理を行います。 */ kintone.events.on( [ "app.record.create.change.交通費明細", "app.record.edit.change.交通費明細", ], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; if (event.changes.row == null) { // 行削除の場合、交通費明細の計算 calcKoutuhiMeisaiTotal(record); } return event; } ); /** * 「交通費明細_勘定科目」および「交通費明細_金額」変更時の処理を行います。 */ kintone.events.on( [ "app.record.create.change.交通費明細_勘定科目", "app.record.edit.change.交通費明細_勘定科目", "app.record.create.change.交通費明細_金額", "app.record.edit.change.交通費明細_金額", ], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; // 交通費明細の計算 calcKoutuhiMeisaiTotal(record); return event; } ); /** * 「経費明細」変更時の処理を行います。 */ kintone.events.on( ["app.record.create.change.経費明細", "app.record.edit.change.経費明細"], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; if (event.changes.row == null) { // 行削除の場合、経費明細の計算 calcKeihiMeisaiTotal(record); } return event; } ); /** * 「経費明細_勘定科目」および「経費明細_金額」変更時の処理を行います。 */ kintone.events.on( [ "app.record.create.change.経費明細_勘定科目", "app.record.edit.change.経費明細_勘定科目", "app.record.create.change.経費明細_金額", "app.record.edit.change.経費明細_金額", ], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; // 経費明細の計算 calcKeihiMeisaiTotal(record); return event; } ); /** * 新規登録・編集画面保存前の処理を行います。 */ kintone.events.on( ["app.record.create.submit", "app.record.edit.submit"], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; let isTableErr = false; const error15minutesMessage = "15分単位で入力してください"; const errorReverseTimeMessage = "終了時間が開始時間よりも小さくなっています"; record.作業時間情報.value.forEach(function (row) { if (!isTime15Minutes(row.value.作業時間情報_Working_from.value || "")) { row.value.作業時間情報_Working_from.error = error15minutesMessage; isTableErr = true; } if (!isTime15Minutes(row.value.作業時間情報_Working_to.value || "")) { row.value.作業時間情報_Working_to.error = error15minutesMessage; isTableErr = true; } if ( !isTime15Minutes(row.value.作業時間情報_Travelling_from.value || "") ) { row.value.作業時間情報_Travelling_from.error = error15minutesMessage; isTableErr = true; } if ( !isTime15Minutes(row.value.作業時間情報_Travelling_to.value || "") ) { row.value.作業時間情報_Travelling_to.error = error15minutesMessage; isTableErr = true; } const workFrom = toMinutesNum( row.value.作業時間情報_Working_from.value || "", null ); const workTo = toMinutesNum( row.value.作業時間情報_Working_to.value || "", workFrom ); if (workFrom != null && workTo != null && workFrom > workTo) { row.value.作業時間情報_Working_to.error = errorReverseTimeMessage; isTableErr = true; } const travellingFrom = toMinutesNum( row.value.作業時間情報_Travelling_from.value || "", null ); const travellingTo = toMinutesNum( row.value.作業時間情報_Travelling_to.value || "", travellingFrom ); if ( travellingFrom != null && travellingTo != null && travellingFrom > travellingTo ) { row.value.作業時間情報_Travelling_to.error = errorReverseTimeMessage; isTableErr = true; } }); if (isTableErr) { event.error = "作業時間情報テーブルの入力にエラーがあります。"; return event; } pvc.util.ui.showSpinner(); setTyouhyouUserNameField(record); // 帳票用Repair情報を設定 setTyouhyouyouRepairTable(record); // Categoryの":"より前の数値を設定 const categorySplitArr = (record.Category.value || "").split(":"); record.Category_No.value = categorySplitArr.length > 0 ? categorySplitArr[0] : null; // 帳票用Repairテーブルの行数を元にサービスレポートのページ数を設定 record.サービスレポート_ページ数.value = record.帳票用Repairテーブル.value.length <= 1 ? "1" : record.帳票用Repairテーブル.value.length >= 2 && record.帳票用Repairテーブル.value.length <= 4 ? "2" : "3"; return setKintaiRenkeiJohouTable(record) .then(function () { // 「engineer_mechanic」のユーザー情報から社員番号を設定 if (record.engineer_mechanic.value.length > 0) { return getUserInfo(record.engineer_mechanic.value[0].code).then( function (userInfo) { if (userInfo != null) { record.社員番号.value = userInfo.employeeNumber; } } ); } }) .then(function () { pvc.util.ui.hideSpinner(); return event; }) .catch(function (error) { console.error(error); alert("システムエラーが発生しました"); pvc.util.ui.hideSpinner(); return event; }); } ); /** * プロセス管理のアクション実行時の処理を行います。 */ kintone.events.on( ["app.record.detail.process.proceed"], function ( /** @type {kintone.AppEvent__サービスレポート_出張経費精算入力} */ event ) { const record = event.record; const processInfo = pvc.env.app.サービスレポート_出張経費精算入力.process; if ( event.status.value === processInfo.status.未申請 && event.nextStatus.value === processInfo.status.所属部長承認 ) { // ステータスが「未申請」から「所属部長承認」になった時 record.申請日.value = pvc.util.date.format(new Date(), "yyyy-MM-dd"); } if ( event.status.value === processInfo.status.所属部長承認 && event.nextStatus.value === processInfo.status.技術部確認担当者承認 ) { // ステータスが「所属部長承認」から「技術部確認担当者承認」になった時 record.所属部長.value = [ { code: kintone.getLoginUser().code, }, ]; record.所属部長承認日.value = pvc.util.date.format( new Date(), "yyyy-MM-dd" ); } else if ( event.status.value === processInfo.status.技術部確認担当者承認 && (event.nextStatus.value === processInfo.status.財務管理承認 || event.nextStatus.value === processInfo.status.承認完了) ) { // ステータスが「技術部確認担当者承認」から「財務管理承認」または「承認完了」になった時 record.技術部確認担当者.value = [ { code: kintone.getLoginUser().code, }, ]; record.技術部確認担当者承認日.value = pvc.util.date.format( new Date(), "yyyy-MM-dd" ); } else if ( event.status.value === processInfo.status.財務管理承認 && event.nextStatus.value === processInfo.status.承認完了 ) { // ステータスが「財務管理承認」から「承認完了」になった時 record.財務管理.value = [ { code: kintone.getLoginUser().code, }, ]; record.財務管理承認日.value = pvc.util.date.format( new Date(), "yyyy-MM-dd" ); } else if ( event.status.value === processInfo.status.財務管理承認 && event.nextStatus.value === processInfo.status.技術部確認担当者承認 ) { // ステータスが「財務管理承認」から「技術部確認担当者承認」になった(差し戻し)時 record.技術部確認担当者.value = []; record.技術部確認担当者承認日.value = null; record.財務管理.value = []; record.財務管理承認日.value = null; } else if ( event.status.value === processInfo.status.技術部確認担当者承認 && event.nextStatus.value === processInfo.status.所属部長承認 ) { // ステータスが「技術部確認担当者承認」から「所属部長承認」になった(差し戻し)時 record.所属部長.value = []; record.所属部長承認日.value = null; record.技術部確認担当者.value = []; record.技術部確認担当者承認日.value = null; record.財務管理.value = []; record.財務管理承認日.value = null; } else if (event.nextStatus.value === processInfo.status.未申請) { // ステータスが「未申請」になった(差し戻し)時 record.申請日.value = null; record.所属部長.value = []; record.所属部長承認日.value = null; record.技術部確認担当者.value = []; record.技術部確認担当者承認日.value = null; record.財務管理.value = []; record.財務管理承認日.value = null; } if ( event.status.value === processInfo.status.所属部長承認 && event.nextStatus.value === processInfo.status.技術部確認担当者承認 && isSectionService ) { // ステータスが「所属部長承認」から「技術部確認担当者承認」になった場合で、セクションに設定された組織が「サービス」の場合 pvc.util.ui.showSpinner(); return upsertTimeReport(record, true) .then(function () { // TIME REPORT連携済みフラグを連携済みに設定 record.TIME_REPORT連携フラグ.value = "連携済み"; pvc.util.ui.hideSpinner(); return event; }) .catch(function (error) { console.error(error); event.error = "システムエラーが発生しました"; pvc.util.ui.hideSpinner(); return event; }); } return event; } ); /** * フィールドの使用不可を設定します。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record * @param {boolean} isServiceReportAuthorizer */ function setDisabledField(record, isServiceReportAuthorizer) { record.No.disabled = true; record.Trans_CD.disabled = true; record.Trans_交通費金額.disabled = true; record.Trans_ETC_CD.disabled = true; record.Trans_ETC金額.disabled = true; record.FUEL_COST_CD.disabled = true; record.FUEL_COST金額.disabled = true; record.Daily_Allowance_CD.disabled = true; record.Daily_Allowance金額.disabled = true; record.Hotel_Expence_CD.disabled = true; record.Hotel_Expence金額.disabled = true; record.Entertaimant_CD.disabled = true; record.Entertaimant金額.disabled = true; record.Meeting_fee_CD.disabled = true; record.Meeting_fee金額.disabled = true; record.Plant_Supply_CD.disabled = true; record.Plant_Supply金額.disabled = true; record.Package_Shipmant_CD.disabled = true; record.Package_Shipmant金額.disabled = true; record.Printing_matter_CD.disabled = true; record.Printing_matter金額.disabled = true; record.Other_Expence金額.disabled = true; record.Trans_Overseas_CD.disabled = true; record.Trans_Overseas金額.disabled = true; record.Daily_Allowance_Overseas_CD.disabled = true; record.Daily_Allowance_Overseas金額.disabled = true; record.Hotel_Expense_Overseas_CD.disabled = true; record.Hotel_Expense_Overseas金額.disabled = true; record.勤怠_開始日付.disabled = true; record.勤怠_終了日付.disabled = true; record.申請日.disabled = true; record.所属部長.disabled = true; record.所属部長承認日.disabled = true; record.技術部確認担当者.disabled = true; record.技術部確認担当者承認日.disabled = true; record.財務管理.disabled = true; record.財務管理承認日.disabled = true; // サービスレポート承認者以外は編集不可の項目 record.チェック.disabled = !isServiceReportAuthorizer; record.Final_job_No.disabled = !isServiceReportAuthorizer; record.add_engineer.disabled = !isServiceReportAuthorizer; record.subcontractor1.disabled = !isServiceReportAuthorizer; record.subcontractor2.disabled = !isServiceReportAuthorizer; record.billing_address1.disabled = !isServiceReportAuthorizer; record.billing_address2.disabled = !isServiceReportAuthorizer; record.remark1.disabled = !isServiceReportAuthorizer; record.remark2.disabled = !isServiceReportAuthorizer; // 作業時間情報テーブルの編集不可の設定 record.作業時間情報.value.forEach(setDisabledSagyouJikanJouhouTableRow); record.勤怠連携情報.value.forEach(function (row) { Object.keys(row.value).forEach(function (key) { // @ts-ignore row.value[key].disabled = true; }); }); } /** * 作業時間情報テーブルの行の編集不可の設定を行います。 * @param {{ value: kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_作業時間情報 }} row */ function setDisabledSagyouJikanJouhouTableRow(row) { row.value.作業時間情報_day.disabled = true; row.value.作業時間情報_HOURS.disabled = true; } /** * フィールドの非表示を設定します。 * @param {boolean} isAdmin */ function setHiddenField(isAdmin) { setHiddenShown("システムグループ", false); setHiddenShown("帳票用Repairテーブル", false); // 管理者以外には非表示 setHiddenShown("勤怠連携情報", isAdmin); setHiddenShown("勤怠_開始日付", isAdmin); setHiddenShown("勤怠_終了日付", isAdmin); setHiddenShown("勤務時間計", isAdmin); setHiddenShown("移動時間計", isAdmin); setHiddenShown("残業時間計", isAdmin); setHiddenShown("割増時間計_25", isAdmin); setHiddenShown("割増時間計_50", isAdmin); setHiddenShown("走行距離計", isAdmin); /** * フィールドの表示・非表示を切り替える * @param {keyof kintone.AppRecord__サービスレポート_出張経費精算入力 | keyof kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_作業時間情報 | keyof kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_交通費明細 | keyof kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_経費明細 | keyof kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_勤怠連携情報 } fieldCode * @param {boolean} shown */ function setHiddenShown(fieldCode, shown) { kintone.app.record.setFieldShown(fieldCode, shown); } } /** * サブテーブルの行追加・行削除ボタンを非表示に設定する。 */ function setHiddenTableRowButton() { Array.prototype.forEach.call( document.querySelectorAll(".subtable-gaia"), function (/** @type {HTMLElement} */ table, index) { if (index === 3) { // 4番目のサブテーブル(勤怠連携情報テーブル) table.classList.add("pvc-desktop-main__rowButtonHiddenTable"); } } ); } /** * 交通費明細の合計を計算します。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record */ function calcKoutuhiMeisaiTotal(record) { const totalInfo = { 交通費金額: 0, ETC金額: 0, 日当金額: 0, ガソリン金額: 0, 交通費海外金額: 0, 日当海外金額: 0, }; record.交通費明細.value.forEach(function (row) { switch (row.value.交通費明細_勘定科目.value) { case "交通費": totalInfo.交通費金額 += pvc.util.obj.toNumber(row.value.交通費明細_金額.value) || 0; break; case "ETC": totalInfo.ETC金額 += pvc.util.obj.toNumber(row.value.交通費明細_金額.value) || 0; break; case "ガソリン": totalInfo.ガソリン金額 += pvc.util.obj.toNumber(row.value.交通費明細_金額.value) || 0; break; case "日当": totalInfo.日当金額 += pvc.util.obj.toNumber(row.value.交通費明細_金額.value) || 0; break; case "交通費(海外)": totalInfo.交通費海外金額 += pvc.util.obj.toNumber(row.value.交通費明細_金額.value) || 0; break; case "日当(海外)": totalInfo.日当海外金額 += pvc.util.obj.toNumber(row.value.交通費明細_金額.value) || 0; break; } }); record.Trans_交通費金額.value = String(totalInfo.交通費金額); record.Trans_ETC金額.value = String(totalInfo.ETC金額); record.FUEL_COST金額.value = String(totalInfo.ガソリン金額); record.Daily_Allowance金額.value = String(totalInfo.日当金額); record.Trans_Overseas金額.value = String(totalInfo.交通費海外金額); record.Daily_Allowance_Overseas金額.value = String(totalInfo.日当海外金額); } /** * 経費明細の合計を計算します。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record */ function calcKeihiMeisaiTotal(record) { const totalInfo = { 宿泊費: 0, 交際費: 0, 会議費: 0, 消耗品: 0, 宅配便: 0, コピー: 0, その他: 0, 宿泊費海外: 0, }; record.経費明細.value.forEach(function (row) { switch (row.value.経費明細_勘定科目.value) { case "宿泊費": totalInfo.宿泊費 += pvc.util.obj.toNumber(row.value.経費明細_金額.value) || 0; break; case "交際費": totalInfo.交際費 += pvc.util.obj.toNumber(row.value.経費明細_金額.value) || 0; break; case "会議費": totalInfo.会議費 += pvc.util.obj.toNumber(row.value.経費明細_金額.value) || 0; break; case "消耗品:工具": totalInfo.消耗品 += pvc.util.obj.toNumber(row.value.経費明細_金額.value) || 0; break; case "宅配便": totalInfo.宅配便 += pvc.util.obj.toNumber(row.value.経費明細_金額.value) || 0; break; case "コピー": totalInfo.コピー += pvc.util.obj.toNumber(row.value.経費明細_金額.value) || 0; break; case "その他": totalInfo.その他 += pvc.util.obj.toNumber(row.value.経費明細_金額.value) || 0; break; case "宿泊費(海外)": totalInfo.宿泊費海外 += pvc.util.obj.toNumber(row.value.経費明細_金額.value) || 0; break; } }); record.Hotel_Expence金額.value = String(totalInfo.宿泊費); record.Entertaimant金額.value = String(totalInfo.交際費); record.Meeting_fee金額.value = String(totalInfo.会議費); record.Plant_Supply金額.value = String(totalInfo.消耗品); record.Package_Shipmant金額.value = String(totalInfo.宅配便); record.Printing_matter金額.value = String(totalInfo.コピー); record.Other_Expence金額.value = String(totalInfo.その他); record.Hotel_Expense_Overseas金額.value = String(totalInfo.宿泊費海外); } /** * 作業時間情報テーブルの行の計算を行います。 * @param {kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_作業時間情報} rowValue */ function calcSagyouJikanJouhouRowValue(rowValue) { const timeInfo = { Working_from: toMinutesNum(rowValue.作業時間情報_Working_from.value || "", null) || 0, Working_to: 0, W_Break_min: toMinutesNum(rowValue.作業時間情報_W_Break_min.value || "", null) || 0, Travelling_from: toMinutesNum(rowValue.作業時間情報_Travelling_from.value || "", null) || 0, Travelling_to: 0, T_Break_min: toMinutesNum(rowValue.作業時間情報_T_Break_min.value || "", null) || 0, HOURS: 0, }; // 終了時間の設定 timeInfo.Working_to = toMinutesNum( rowValue.作業時間情報_Working_to.value || "", timeInfo.Working_from ) || 0; timeInfo.Travelling_to = toMinutesNum( rowValue.作業時間情報_Travelling_to.value || "", timeInfo.Travelling_from ) || 0; // 計算処理 timeInfo.HOURS = timeInfo.Working_to - timeInfo.Working_from + (timeInfo.Travelling_to - timeInfo.Travelling_from) - timeInfo.W_Break_min - timeInfo.T_Break_min; // 計算結果の分数を時間数値に変換して設定 rowValue.作業時間情報_HOURS.value = String(toHoursNum(timeInfo.HOURS)); } /** * HH:mm形式の文字列を分数に変換する。 * @param {string} strDate HH:mm形式の文字列 * @param {number | null} fromNum 終了時間の場合、開始時間の分数 * @returns {number | null} */ function toMinutesNum(strDate, fromNum) { if (!/-?\d+:\d{2}/.test(strDate)) { // 時刻形式(マイナスは可能)以外の場合 return null; } let isMinus = strDate[0] === "-"; const numArr = strDate.replace("-", "").split(":"); const hh = pvc.util.obj.toNumber(numArr[0]) || 0; const mm = pvc.util.obj.toNumber(numArr[1]) || 0; let result = hh * 60 + mm; if (fromNum != null && result === 0) { // 終了時間かつ、終了時間が00:00の場合 result += 24 * 60; } return (isMinus ? -1 : 1) * result; } /** * 分数を元に、HH:mm形式の文字列に変換する。 * @param {number} minutesNum * @returns {string} */ function toTimeStr(minutesNum) { // 24:00以上の時間は設定出来ないため、減算しておく const absNum = Math.abs(minutesNum) % (24 * 60); const hh = pvc.util.str.padLeft(String(Math.floor(absNum / 60)), "0", 2); const mm = pvc.util.str.padLeft(String(absNum % 60), "0", 2); return (minutesNum < 0 ? "-" : "") + hh + ":" + mm; } /** * 分数を元に、小数1桁の時間数値に変換する。 * @param {number} minutesNum * @returns {number} */ function toHoursNum(minutesNum) { return Math.round((minutesNum * 10.0) / 60.0) / 10; } /** * 指定された時間帯に含まれる、From-Toの時間差の分数を計算します。 * @param {number} fromNum 開始時間の分数 * @param {number} toNum 終了時間の分数 * @param {{ from: number, to: number }[]} timeZoneArr 対象の時間帯の配列(時間帯の重複は無しとする) * @returns {number} */ function calcIncludedTimeZoneMinuteNum(fromNum, toNum, timeZoneArr) { /** * 指定の時間帯に含まれた分数のリスト * @type {number[]} **/ const includeTimeNumList = []; if (fromNum >= toNum) { // 時間差が0以下の場合 return 0; } timeZoneArr.forEach(function (timeZone) { if (timeZone.from <= timeZone.to) { // 正しいFrom-Toになっている場合 if (fromNum <= timeZone.to && toNum >= timeZone.from) { // 指定の時間帯に含まれている場合、含まれている分数を結果数値リストに追加 includeTimeNumList.push( (toNum > timeZone.to ? timeZone.to : toNum) - (fromNum <= timeZone.from ? timeZone.from : fromNum) ); } } else { // To が Fromより小さい場合、00:00~To および From~(To+24:00)の二つの時間帯を対象とみなす const zeroFrom = 0; const zeroTo = timeZone.to; const over24From = timeZone.from; const over24To = timeZone.to + 24 * 60; if (fromNum <= zeroTo && toNum >= zeroFrom) { // 00:00~Toの時間帯に含まれている場合、含まれている分数を結果数値リストに追加 includeTimeNumList.push( (toNum > zeroTo ? zeroTo : toNum) - (fromNum <= zeroFrom ? zeroFrom : fromNum) ); } if (fromNum <= over24To && toNum >= over24From) { // From~(To+24:00)の時間帯に含まれている場合、含まれている分数を結果数値リストに追加 includeTimeNumList.push( (toNum > over24To ? over24To : toNum) - (fromNum <= over24From ? over24From : fromNum) ); } } }); // 指定の時間帯に含まれた分数の合計値 return pvc.util.array.sum(includeTimeNumList); } /** * システムコントロールのレコードを取得します。 * @param {string} userCode - ユーザーコード(engineer_mechanic.コード) * @returns {Promise} */ function getSystemControlRecord(userCode) { // ステップ1: SIGNATURE_MASTERアプリからユーザーの勤務パターンNOを取得 return new KintoneRestAPIClient().record .getRecords({ app: pvc.env.app.SIGNATURE_MASTER.appId, query: pvc.util.kintone.makeQuery("担当者 in ((@担当者))", { 担当者: userCode, }), fields: ["$id", "担当者", "勤務パターンNO"], }) .then(function (resp) { // ステップ2: 勤務パターンNOを取得、不存在または未設定の場合は"1"とする var patternNo = "1"; if (resp.records.length > 0) { var signatureRecord = resp.records[0]; if ( signatureRecord.勤務パターンNO != null && signatureRecord.勤務パターンNO.value != null && signatureRecord.勤務パターンNO.value !== "" ) { patternNo = signatureRecord.勤務パターンNO.value; } } // ステップ3: システムコントロールからパターンNO等于勤務パターンNO的记录を取得 return new KintoneRestAPIClient().record .getRecords({ app: pvc.env.app.システムコントロール.appId, query: pvc.util.kintone.makeQuery("パターンNO in ((@パターンNO))", { パターンNO: patternNo, }), }) .then(function (systemResp) { return systemResp.records.length > 0 ? systemResp.records[0] : null; }); }); } /** * システムコントロール関連のフィールドに値を設定します。 * @param {kintone.AppRecord__システムコントロール} systemRecord * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record */ function setSystemControlField(systemRecord, record) { record.システム_通常_開始時間.value = systemRecord.通常_開始時間.value || "00:00"; record.システム_通常_終了時間.value = systemRecord.通常_終了時間.value || "00:00"; record.システム_平日残業_開始時間1.value = systemRecord.平日残業_開始時間1.value || "00:00"; record.システム_平日残業_終了時間1.value = systemRecord.平日残業_終了時間1.value || "00:00"; record.システム_平日残業_開始時間2.value = systemRecord.平日残業_開始時間2.value || "00:00"; record.システム_平日残業_終了時間2.value = systemRecord.平日残業_終了時間2.value || "00:00"; record.システム_深夜_開始時間.value = systemRecord.深夜_開始時間.value || "00:00"; record.システム_深夜_終了時間.value = systemRecord.深夜_終了時間.value || "00:00"; record.システム_休日残業_開始時間.value = systemRecord.休日残業_開始時間.value || "00:00"; record.システム_休日残業_終了時間.value = systemRecord.休日残業_終了時間.value || "00:00"; record.システム_平日25割増_開始時間1.value = systemRecord.平日25割増_開始時間1.value || "00:00"; record.システム_平日25割増_終了時間1.value = systemRecord.平日25割増_終了時間1.value || "00:00"; record.システム_平日25割増_開始時間2.value = systemRecord.平日25割増_開始時間2.value || "00:00"; record.システム_平日25割増_終了時間2.value = systemRecord.平日25割増_終了時間2.value || "00:00"; record.システム_平日50割増_開始時間.value = systemRecord.平日50割増_開始時間.value || "00:00"; record.システム_平日50割増_終了時間.value = systemRecord.平日50割増_終了時間.value || "00:00"; record.システム_土曜25割増_開始時間.value = systemRecord.土曜25割増_開始時間.value || "00:00"; record.システム_土曜25割増_終了時間.value = systemRecord.土曜25割増_終了時間.value || "00:00"; record.システム_土曜50割増_開始時間.value = systemRecord.土曜50割増_開始時間.value || "00:00"; record.システム_土曜50割増_終了時間.value = systemRecord.土曜50割増_終了時間.value || "00:00"; } /** * システムコントロールフィールドからシステム時間情報を設定します。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record */ function setSystemInfo(record) { systemInfo.通常_開始時間 = toMinutesNum(record.システム_通常_開始時間.value || "", null) || 0; systemInfo.通常_終了時間 = toMinutesNum( record.システム_通常_終了時間.value || "", systemInfo.通常_開始時間 ) || 0; systemInfo.平日残業_開始時間1 = toMinutesNum(record.システム_平日残業_開始時間1.value || "", null) || 0; systemInfo.平日残業_終了時間1 = toMinutesNum( record.システム_平日残業_終了時間1.value || "", systemInfo.平日残業_開始時間1 ) || 0; systemInfo.平日残業_開始時間2 = toMinutesNum(record.システム_平日残業_開始時間2.value || "", null) || 0; systemInfo.平日残業_終了時間2 = toMinutesNum( record.システム_平日残業_終了時間2.value || "", systemInfo.平日残業_開始時間2 ) || 0; systemInfo.深夜_開始時間 = toMinutesNum(record.システム_深夜_開始時間.value || "", null) || 0; systemInfo.深夜_終了時間 = toMinutesNum( record.システム_深夜_終了時間.value || "", systemInfo.深夜_終了時間 ) || 0; systemInfo.休日残業_開始時間 = toMinutesNum(record.システム_休日残業_開始時間.value || "", null) || 0; systemInfo.休日残業_終了時間 = toMinutesNum( record.システム_休日残業_終了時間.value || "", systemInfo.休日残業_終了時間 ) || 0; systemInfo.平日25割増_開始時間1 = toMinutesNum(record.システム_平日25割増_開始時間1.value || "", null) || 0; systemInfo.平日25割増_終了時間1 = toMinutesNum( record.システム_平日25割増_終了時間1.value || "", systemInfo.平日25割増_終了時間1 ) || 0; systemInfo.平日25割増_開始時間2 = toMinutesNum(record.システム_平日25割増_開始時間2.value || "", null) || 0; systemInfo.平日25割増_終了時間2 = toMinutesNum( record.システム_平日25割増_終了時間2.value || "", systemInfo.平日25割増_開始時間2 ) || 0; systemInfo.平日50割増_開始時間 = toMinutesNum(record.システム_平日50割増_開始時間.value || "", null) || 0; systemInfo.平日50割増_終了時間 = toMinutesNum( record.システム_平日50割増_終了時間.value || "", systemInfo.平日50割増_開始時間 ) || 0; systemInfo.土曜25割増_開始時間 = toMinutesNum(record.システム_土曜25割増_開始時間.value || "", null) || 0; systemInfo.土曜25割増_終了時間 = toMinutesNum( record.システム_土曜25割増_終了時間.value || "", systemInfo.土曜25割増_開始時間 ) || 0; systemInfo.土曜50割増_開始時間 = toMinutesNum(record.システム_土曜50割増_開始時間.value || "", null) || 0; systemInfo.土曜50割増_終了時間 = toMinutesNum( record.システム_土曜50割増_終了時間.value || "", systemInfo.土曜50割増_開始時間 ) || 0; } /** * 指定範囲の祝祭日マスタデータを取得します。 * @param {Date} fromDate * @param {Date} toDate * @returns {Promise} */ function getSyukusaijituMaster(fromDate, toDate) { return new KintoneRestAPIClient().record .getAllRecords({ app: pvc.env.app.祝祭日マスタ.appId, condition: pvc.util.kintone.makeQuery( "日付 >= (@fromDate) and 日付 <= (@toDate)", { fromDate: pvc.util.date.format(fromDate, "yyyy-MM-dd"), toDate: pvc.util.date.format(toDate, "yyyy-MM-dd"), } ), }) .then(function (records) { return records; }); } /** * ログインユーザーの所属グループコードリストを取得します。 * @returns {Promise} */ function getLoginUserGroupCodes() { return kintone .api(kintone.api.url("/v1/user/groups", true), "GET", { code: kintone.getLoginUser().code, }) .then(function (resp) { return resp.groups.map(function ( /** @type {kintone.AppFieldValue_GROUP} */ group ) { return group.code; }); }); } /** * 勤怠連携情報テーブル関連の値を設定します。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record * @returns {Promise} */ function setKintaiRenkeiJohouTable(record) { // ブランク以外の日付でグループ化して日付順にソート const dateGroupInfo = pvc.util.array .groupBy(record.作業時間情報.value, function (row) { return row.value.作業時間情報_date.value || ""; }) .filter(function (g) { return !pvc.util.obj.isEmpty(g.key); }) .sort(function (g1, g2) { return pvc.util.obj.compare( pvc.util.obj.toDate(g1.key) || new Date(0), pvc.util.obj.toDate(g2.key) || new Date(0) ); }); if (dateGroupInfo.length === 0) { // 日付の設定された行がない場合 record.勤怠_開始日付.value = null; record.勤怠_終了日付.value = null; record.勤怠連携情報.value = []; return kintone.Promise.resolve(); } const strMinDate = dateGroupInfo[0].key; const strMaxDate = dateGroupInfo[dateGroupInfo.length - 1].key; return getSyukusaijituMaster( pvc.util.obj.toDate(strMinDate) || new Date(), pvc.util.obj.toDate(strMaxDate) || new Date() ).then(function (syukusaijituRecords) { const syukusaijituList = syukusaijituRecords.map(function ( syukusaijituRecord ) { return syukusaijituRecord.日付.value || ""; }); record.勤怠連携情報.value = dateGroupInfo.map(function (g) { const firstRow = g.items[0]; const dayKubun = syukusaijituList.indexOf( firstRow.value.作業時間情報_date.value || "" ) !== -1 ? "祭日" : firstRow.value.作業時間情報_day.value === "Sun" ? "日曜" : firstRow.value.作業時間情報_day.value === "Sat" ? "土曜" : "平日"; const totalTimeInfo = { 勤務開始時間: -1, 勤務終了時間: -1, 勤務時間: 0, 移動時間: 0, 基準勤務時間: 0, 全勤務時間_移動時間除く: 0, 残業時間: 0, 平日残業: 0, 平日深夜: 0, 休日残業: 0, 休日深夜: 0, 割増時間_25: 0, 割増時間_50: 0, 走行距離: 0, 休憩: 0, }; // 日付毎の集計処理 g.items.forEach(function (row) { const timeInfo = { Working_from: toMinutesNum( row.value.作業時間情報_Working_from.value || "", null ), /** @type {number | null} */ Working_to: 0, W_Break_min: toMinutesNum( row.value.作業時間情報_W_Break_min.value || "", null ) || 0, Travelling_from: toMinutesNum( row.value.作業時間情報_Travelling_from.value || "", null ), /** @type {number | null} */ Travelling_to: 0, T_Break_min: toMinutesNum( row.value.作業時間情報_T_Break_min.value || "", null ) || 0, HOURS: pvc.util.obj.toNumber(row.value.作業時間情報_HOURS.value) || 0, Service_car_KM: pvc.util.obj.toNumber( row.value.作業時間情報_Service_car_KM.value ) || 0, }; // 終了時間の設定 timeInfo.Working_to = toMinutesNum( row.value.作業時間情報_Working_to.value || "", timeInfo.Working_from ); timeInfo.Travelling_to = toMinutesNum( row.value.作業時間情報_Travelling_to.value || "", timeInfo.Travelling_from ); // 勤務開始時間に一番小さい開始時間を設定 if (timeInfo.Working_from != null) { totalTimeInfo.勤務開始時間 = totalTimeInfo.勤務開始時間 === -1 || totalTimeInfo.勤務開始時間 > timeInfo.Working_from ? timeInfo.Working_from : totalTimeInfo.勤務開始時間; } if (timeInfo.Travelling_from != null) { totalTimeInfo.勤務開始時間 = totalTimeInfo.勤務開始時間 === -1 || totalTimeInfo.勤務開始時間 > timeInfo.Travelling_from ? timeInfo.Travelling_from : totalTimeInfo.勤務開始時間; } // 勤務終了時間に一番大きい終了時間を設定 if (timeInfo.Working_to != null) { totalTimeInfo.勤務終了時間 = totalTimeInfo.勤務終了時間 === -1 || totalTimeInfo.勤務終了時間 < timeInfo.Working_to ? timeInfo.Working_to : totalTimeInfo.勤務終了時間; } if (timeInfo.Travelling_to != null) { totalTimeInfo.勤務終了時間 = totalTimeInfo.勤務終了時間 === -1 || totalTimeInfo.勤務終了時間 < timeInfo.Travelling_to ? timeInfo.Travelling_to : totalTimeInfo.勤務終了時間; } totalTimeInfo.勤務時間 += timeInfo.HOURS; totalTimeInfo.移動時間 += (timeInfo.Travelling_to || 0) - (timeInfo.Travelling_from || 0) - timeInfo.T_Break_min; // 基準勤務時間の計算 let workTime = 0; let travelTime = 0; // workTimeの計算 if (timeInfo.Working_from != null && timeInfo.Working_to != null) { // Workingの時間が両方ブランクでない場合 if ( timeInfo.Working_to > systemInfo.通常_終了時間 && systemInfo.通常_開始時間 - timeInfo.Working_from < timeInfo.Working_to - systemInfo.通常_終了時間 ) { // Working_toが通常終了時間より後で、開始時間より通常勤務時間外の時間が大きい場合 workTime = calcIncludedTimeZoneMinuteNum( timeInfo.Working_from, timeInfo.Working_to - timeInfo.W_Break_min, [ { from: systemInfo.通常_開始時間, to: systemInfo.通常_終了時間, }, ] ); } else { // 開始時間の通常勤務時間外の時間が大きい、または無い場合 workTime = calcIncludedTimeZoneMinuteNum( timeInfo.Working_from + timeInfo.W_Break_min, timeInfo.Working_to, [ { from: systemInfo.通常_開始時間, to: systemInfo.通常_終了時間, }, ] ); } } // travelTimeの計算 if ( timeInfo.Travelling_from != null && timeInfo.Travelling_to != null ) { // Travellingの時間が両方ブランクでない場合 if ( timeInfo.Travelling_to > systemInfo.通常_終了時間 && systemInfo.通常_開始時間 - timeInfo.Travelling_from < timeInfo.Travelling_to - systemInfo.通常_終了時間 ) { // Travelling_toが通常終了時間より後で、開始時間より通常勤務時間外の時間が大きい場合 travelTime = calcIncludedTimeZoneMinuteNum( timeInfo.Travelling_from, timeInfo.Travelling_to - timeInfo.W_Break_min, [ { from: systemInfo.通常_開始時間, to: systemInfo.通常_終了時間, }, ] ); } else { // 開始時間の通常勤務時間外の時間が大きい、または無い場合 travelTime = calcIncludedTimeZoneMinuteNum( timeInfo.Travelling_from + timeInfo.W_Break_min, timeInfo.Travelling_to, [ { from: systemInfo.通常_開始時間, to: systemInfo.通常_終了時間, }, ] ); } } totalTimeInfo.基準勤務時間 += workTime + travelTime; totalTimeInfo.休憩 += timeInfo.W_Break_min; totalTimeInfo.休憩 += timeInfo.T_Break_min; // 残業時間の計算 const w_zangyouInfo = getZangyouInfo( timeInfo.Working_from, timeInfo.Working_to, dayKubun !== "平日" ); const t_zangyouInfo = getZangyouInfo( timeInfo.Travelling_from, timeInfo.Travelling_to, dayKubun !== "平日" ); // 休憩時間を通常 → 残業 → 深夜の順で減算する const w_zangyouResult = calcOrderSubtraction( timeInfo.W_Break_min, w_zangyouInfo.通常, w_zangyouInfo.残業, w_zangyouInfo.深夜 ); const t_zangyouResult = calcOrderSubtraction( timeInfo.T_Break_min, t_zangyouInfo.通常, t_zangyouInfo.残業, t_zangyouInfo.深夜 ); // 残業時間情報に加算 const g_残業 = w_zangyouResult.num2 + t_zangyouResult.num2; const g_深夜 = w_zangyouResult.num3 + t_zangyouResult.num3; if (dayKubun === "平日") { totalTimeInfo.平日残業 += g_残業; totalTimeInfo.平日深夜 += g_深夜; } else { totalTimeInfo.休日残業 += g_残業; totalTimeInfo.休日深夜 += g_深夜; } totalTimeInfo.残業時間 += g_残業 + g_深夜; // 割増時間の計算 const w_warimasiInfo = getWarimasiInfo( timeInfo.Working_from, timeInfo.Working_to, dayKubun ); // 休憩時間を割増時間外 → 割増時間_25 → 割増時間_50の順で減算する const w_warimasiResult = calcOrderSubtraction( timeInfo.W_Break_min, w_warimasiInfo.割増時間外, w_warimasiInfo.割増時間_25, w_warimasiInfo.割増時間_50 ); // 割増時間情報に加算 totalTimeInfo.割増時間_25 += w_warimasiResult.num2; totalTimeInfo.割増時間_50 += w_warimasiResult.num3; totalTimeInfo.走行距離 += timeInfo.Service_car_KM; }); // 集計した勤務時間と移動時間から計算 // ※勤務時間は元のHOURSの時点で小数1桁の時間数値になっているので変換しない totalTimeInfo.全勤務時間_移動時間除く = totalTimeInfo.勤務時間 - toHoursNum(totalTimeInfo.移動時間); return { /** @type {kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_勤怠連携情報} */ value: { 勤怠連携情報_勤怠_日付: { type: "DATE", value: firstRow.value.作業時間情報_date.value, }, 勤怠連携情報_曜日: { type: "SINGLE_LINE_TEXT", value: firstRow.value.作業時間情報_day.value, }, 勤怠連携情報_区分: { type: "SINGLE_LINE_TEXT", value: dayKubun, }, 勤怠連携情報_勤務開始時間: { type: "TIME", value: toTimeStr( totalTimeInfo.勤務開始時間 < 0 ? 0 : totalTimeInfo.勤務開始時間 ), }, 勤怠連携情報_勤務終了時間: { type: "TIME", value: toTimeStr( totalTimeInfo.勤務終了時間 < 0 ? 0 : totalTimeInfo.勤務終了時間 ), }, 勤怠連携情報_休憩時間: { type: "TIME", value: toTimeStr(totalTimeInfo.休憩), }, 勤怠連携情報_勤務時間: { type: "NUMBER", value: String(totalTimeInfo.勤務時間), // 勤務時間は元のHOURSの時点で小数1桁の時間数値になっているので変換しない }, 勤怠連携情報_移動時間: { type: "NUMBER", value: String(toHoursNum(totalTimeInfo.移動時間)), }, // 勤怠連携情報_基準勤務時間: { // type: "NUMBER", // value: String(toHoursNum(totalTimeInfo.基準勤務時間)), // }, // TODO:確認待ちでひとまず計算ロジックを残しつつ、以下の計算に変更 勤怠連携情報_基準勤務時間: { type: "NUMBER", value: String( totalTimeInfo.勤務時間 - toHoursNum(totalTimeInfo.残業時間) ), }, 勤怠連携情報_全勤務時間_移動時間除く: { type: "NUMBER", value: String(totalTimeInfo.全勤務時間_移動時間除く), // 計算時に小数1桁の時間数値になっているので変換しない }, 勤怠連携情報_残業時間: { type: "NUMBER", value: String(toHoursNum(totalTimeInfo.残業時間)), }, 勤怠連携情報_平日残業: { type: "NUMBER", value: String(toHoursNum(totalTimeInfo.平日残業)), }, 勤怠連携情報_平日深夜: { type: "NUMBER", value: String(toHoursNum(totalTimeInfo.平日深夜)), }, 勤怠連携情報_休日残業: { type: "NUMBER", value: String(toHoursNum(totalTimeInfo.休日残業)), }, 勤怠連携情報_休日深夜: { type: "NUMBER", value: String(toHoursNum(totalTimeInfo.休日深夜)), }, 勤怠連携情報_割増時間_25: { type: "NUMBER", value: String(toHoursNum(totalTimeInfo.割増時間_25)), }, 勤怠連携情報_割増時間_50: { type: "NUMBER", value: String(toHoursNum(totalTimeInfo.割増時間_50)), }, 勤怠連携情報_走行距離: { type: "NUMBER", value: String(totalTimeInfo.走行距離), // 手入力の時間数値ではないため変換しない }, }, }; }); // 最小と最大日付を設定 record.勤怠_開始日付.value = strMinDate; record.勤怠_終了日付.value = strMaxDate; }); } /** * 残業時間情報を取得します * @param {number | null} fromTime * @param {number | null} toTime * @param {boolean} isHoliday 休日かどうか * @returns {{ 通常: number, 残業: number, 深夜: number }} */ function getZangyouInfo(fromTime, toTime, isHoliday) { let tuujouJikan = 0; let zangyouJikan = 0; let sinyaJikan = 0; if (fromTime != null && toTime != null) { zangyouJikan = calcIncludedTimeZoneMinuteNum( fromTime, toTime, // 平日と休日で対象となる時間帯を変更 isHoliday ? [ { from: systemInfo.休日残業_開始時間, to: systemInfo.休日残業_終了時間, }, ] : [ { from: systemInfo.平日残業_開始時間1, to: systemInfo.平日残業_終了時間1, }, { from: systemInfo.平日残業_開始時間2, to: systemInfo.平日残業_終了時間2, }, ] ); sinyaJikan = calcIncludedTimeZoneMinuteNum(fromTime, toTime, [ { from: systemInfo.深夜_開始時間, to: systemInfo.深夜_終了時間 }, ]); tuujouJikan = toTime - fromTime - (zangyouJikan + sinyaJikan); } return { 通常: tuujouJikan, 残業: zangyouJikan, 深夜: sinyaJikan, }; } /** * 割増時間情報を取得します * @param {number | null} fromTime * @param {number | null} toTime * @param {"祭日" | "土曜" | "日曜" | "平日"} dayKubun 休日かどうか * @returns {{ 割増時間外: number, 割増時間_25: number, 割増時間_50: number }} */ function getWarimasiInfo(fromTime, toTime, dayKubun) { // Workingの時間を計算 let warimasiJikangai = 0; let warimasi_25 = 0; let warimasi_50 = 0; if (fromTime != null && toTime != null) { if (dayKubun === "日曜" || dayKubun === "祭日") { // 日曜または祭日の場合、全て50%割増時間とする warimasiJikangai = 0; warimasi_25 = 0; warimasi_50 = toTime - fromTime; } else { warimasi_25 = calcIncludedTimeZoneMinuteNum( fromTime, toTime, // 区分で対象となる時間帯を変更 dayKubun === "平日" ? [ { from: systemInfo.平日25割増_開始時間1, to: systemInfo.平日25割増_終了時間1, }, { from: systemInfo.平日25割増_開始時間2, to: systemInfo.平日25割増_終了時間2, }, ] : [ { from: systemInfo.土曜25割増_開始時間, to: systemInfo.土曜25割増_終了時間, }, ] ); warimasi_50 = calcIncludedTimeZoneMinuteNum( fromTime, toTime, // 区分で対象となる時間帯を変更 dayKubun === "平日" ? [ { from: systemInfo.平日50割増_開始時間, to: systemInfo.平日50割増_終了時間, }, ] : [ { from: systemInfo.土曜50割増_開始時間, to: systemInfo.土曜50割増_終了時間, }, ] ); warimasiJikangai = toTime - fromTime - (warimasi_25 + warimasi_50); } } return { 割増時間外: warimasiJikangai, 割増時間_25: warimasi_25, 割増時間_50: warimasi_50, }; } /** * 1番目の引数の値を、2→3→4番目の引数の値順にマイナスにならない様に減算した結果を返却する。 * ※マイナス値が3つの数値より大きい場合、最後の値がマイナスとなる * @param {number} minusNum * @param {number} num1 * @param {number} num2 * @param {number} num3 * @returns {{ num1: number, num2: number, num3: number,}} */ function calcOrderSubtraction(minusNum, num1, num2, num3) { const result1 = num1 - minusNum; const result2 = num2 - (result1 < 0 ? result1 * -1 : 0); const result3 = num3 - (result2 < 0 ? result2 * -1 : 0); return { num1: result1 > 0 ? result1 : 0, num2: result2 > 0 ? result2 : 0, num3: result3, }; } /** * TIME REPORTアプリの同一日付の勤怠情報を更新、または新規登録する。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record * @param {boolean} triggerFromProcessKanri * @returns {Promise} */ function upsertTimeReport(record, triggerFromProcessKanri) { const dateFrom = pvc.util.obj.toDate(record.勤怠_開始日付.value); const dateTo = pvc.util.obj.toDate(record.勤怠_終了日付.value); if ( record.勤怠連携情報.value.length <= 0 || dateFrom == null || dateTo == null ) { // 必要な項目が設定されていない場合は処理終了 return kintone.Promise.resolve(); } const engineerCode = record.engineer_mechanic.value.length > 0 ? record.engineer_mechanic.value[0].code : ""; const nengetuFrom = toTimeReportNengetu(dateFrom); const nengetuTo = toTimeReportNengetu(dateTo); return new KintoneRestAPIClient().record .getAllRecords({ app: pvc.env.app.サービスレポート_出張経費精算入力.appId, condition: pvc.util.kintone.makeQuery( 'TIME_REPORT連携フラグ in ("連携済み") and engineer_mechanic in ((@engineer)) and 勤怠_終了日付 >= (@開始日付) and 勤怠_開始日付 <= (@終了日付) and $id != (@レコード番号)', { engineer: engineerCode, 開始日付: record.勤怠_開始日付.value || "", 終了日付: record.勤怠_終了日付.value || "", レコード番号: record.$id != null ? record.$id.value : "0", } ), }) .then(function ( /** @type {kintone.AppRecord__サービスレポート_出張経費精算入力[]} */ duplicateServiceRecords ) { /** * サービスレポート・出張経費精算入力で重複している日付範囲のデータを日付毎にグループ化 */ const duplicateDayGroup = pvc.util.array.groupBy( duplicateServiceRecords.reduce(function ( /** @type {kintone.AppRecord__サービスレポート_出張経費精算入力["勤怠連携情報"]["value"]} */ result, dRecord ) { result = result.concat(dRecord.勤怠連携情報.value); return result; }, []), function (row) { return row.value.勤怠連携情報_勤怠_日付.value || ""; } ); return new KintoneRestAPIClient().record .getAllRecords({ app: pvc.env.app.TIME_REPORT.appId, condition: pvc.util.kintone.makeQuery( "氏名 in ((@氏名)) and 検索用年月 >= (@年月From) and 検索用年月 <= (@年月To)", { 氏名: engineerCode, 年月From: nengetuFrom, 年月To: nengetuTo, } ), }) .then(function ( /** @type {kintone.AppRecord__TIME_REPORT[]} */ timeReportRecords ) { /** @type {Partial[]} */ const addRecords = []; /** @type {{ id: string, record: Partial }[]} */ const updateRecords = []; pvc.util.array .groupBy(record.勤怠連携情報.value, function (row) { const date = pvc.util.obj.toDate( row.value.勤怠連携情報_勤怠_日付.value ); if (date == null) { return ""; } return toTimeReportNengetu(date); }) .forEach(function (g) { if (pvc.util.obj.isEmpty(g.key)) { return; } const timeReportRecord = pvc.util.array.find( timeReportRecords, function (record) { return record.検索用年月.value === g.key; } ); if (timeReportRecord != null) { // 既存のデータが存在する場合 if ( triggerFromProcessKanri === false || (triggerFromProcessKanri === true && timeReportRecord.ステータス.value !== "承認完了") ) { // プロセス管理からの処理の場合、ステータスが「承認完了」の場合は、更新しない // 勤怠連携情報テーブルの値を元に行データの更新 updateTimeReportTableRows( timeReportRecord.TIME_REPORT.value, g.items, duplicateDayGroup ); updateRecords.push({ id: timeReportRecord.$id.value, record: { TIME_REPORT: { value: timeReportRecord.TIME_REPORT.value, }, }, }); } } else { // 既存のデータが存在しない場合 const year = Math.floor(Number(g.key) / 100); const month = Number(g.key) % 100; const timeReportRows = getTimeReportTableRows(year, month); // 勤怠連携情報テーブルの値を元に作成した行データの更新 updateTimeReportTableRows( timeReportRows, g.items, duplicateDayGroup ); addRecords.push({ YEAR: { value: String(year), }, MONTH: { value: String(month), }, 氏名: { value: [{ code: engineerCode }], }, TIME_REPORT: { value: timeReportRows, }, 検索用年月: { value: g.key, }, }); } }); if (updateRecords.length > 0) { return new KintoneRestAPIClient().record .updateAllRecords({ app: pvc.env.app.TIME_REPORT.appId, records: updateRecords, }) .then(function () { return addRecords; }); } return addRecords; }) .then(function (addRecords) { if (addRecords.length > 0) { return getUserYuusennSosikiCode(engineerCode).then(function ( yuusennSosikiCode ) { addRecords.forEach(function (addRecord) { // 全ての登録用レコードの所属に engineer_mechanic の優先する組織を設定 addRecord.所属 = { value: yuusennSosikiCode != null ? [{ code: yuusennSosikiCode }] : [], }; }); return new KintoneRestAPIClient().record.addAllRecords({ app: pvc.env.app.TIME_REPORT.appId, records: addRecords, }); }); } }); }) .then(); } /** * 指定されたユーザーの優先する組織のコードを取得します。 * @param {string} userCode * @returns {Promise} */ function getUserYuusennSosikiCode(userCode) { if (pvc.util.obj.isEmpty(userCode)) { return kintone.Promise.resolve(null); } return getUserInfo(userCode).then(function (userInfo) { if (userInfo != null && userInfo.primaryOrganization != null) { return kintone .api(kintone.api.url("/v1/organizations", true), "GET", { ids: [userInfo.primaryOrganization], }) .then(function ( /** @type {{ organizations: { code: string }[] }} */ respOrgs ) { return respOrgs.organizations.length > 0 ? respOrgs.organizations[0].code : null; }); } return null; }); } /** * 指定された日付をTIME REPORTアプリの検索用年月のyyyyMM形式の文字列に変換します。 * @param {Date} date * @returns {string} */ function toTimeReportNengetu(date) { let year = date.getFullYear(); let month = date.getMonth() + 1; const day = date.getDate(); if (day >= 26 && day <= 31) { if (month === 12) { // 月が12で日付が26~31日の場合は年に+1で月は1 year++; month = 1; } else { // 月が12以外で日付が26~31日の場合は月に+1 month++; } } // YYYYMM形式の文字列をキーとして返却 return String(year) + pvc.util.str.padLeft(String(month), "0", 2); } /** * yyyyMMの年月値からTIME REPORTテーブルの1ヶ月分の行を取得します。 * @param {number} year * @param {number} month * @returns {{ value: kintone.AppFieldRowValue_TIME_REPORT_TIME_REPORT }[]} */ function getTimeReportTableRows(year, month) { // 前月26日が開始日 const fromDate = new Date(year, month - 2, 26); // 今月25日が終了日 const toDate = new Date(year, month - 1, 25); /** @type {{ value: kintone.AppFieldRowValue_TIME_REPORT_TIME_REPORT }[]} */ const result = []; const rowDate = new Date(fromDate.getTime()); const youbiList = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; while (rowDate.getTime() <= toDate.getTime()) { const youbi = youbiList[rowDate.getDay()]; result.push({ value: { TIME_REPORT_DATE: { type: "NUMBER", value: String(rowDate.getDate()), }, TIME_REPORT_DAY: { type: "SINGLE_LINE_TEXT", value: youbi, }, TIME_REPORT_START_TIME: { type: "TIME", value: "", }, TIME_REPORT_END_TIME: { type: "TIME", value: "", }, TIME_REPORT_W_BREAK: { type: "TIME", value: "", }, TIME_REPORT_WORKING_HOURS: { type: "NUMBER", value: "", }, TIME_REPORT_W_DAY: { type: "NUMBER", value: "", }, TIME_REPORT_W_END: { type: "NUMBER", value: "", }, TIME_REPORT_M_NI_W_DAY: { type: "NUMBER", value: "", }, TIME_REPORT_M_NI_W_END: { type: "NUMBER", value: "", }, TIME_REPORT_M_NI: { type: "NUMBER", value: "", }, TIME_REPORT_TOTAL: { type: "CALC", value: "", }, TIME_REPORT_PAID: { type: "NUMBER", value: "", }, TIME_REPORT_OTHER: { type: "NUMBER", value: "", }, TIME_REPORT_SICK: { type: "NUMBER", value: "", }, TIME_REPORT_日付: { type: "DATE", value: pvc.util.date.format(rowDate, "yyyy-MM-dd"), }, }, }); // 行の日付に+1日 rowDate.setDate(rowDate.getDate() + 1); } return result; } /** * 勤怠連携情報テーブルのデータを元に、TIME REPORTテーブルの該当する行の値を更新します。 * @param {{ value: kintone.AppFieldRowValue_TIME_REPORT_TIME_REPORT }[]} timeReportRows * @param {{ value: kintone.AppFieldRowValue_サービスレポート_出張経費精算入力_勤怠連携情報 }[]} kintaiRenkeiRows * @param {{ key: string, items: kintone.AppRecord__サービスレポート_出張経費精算入力["勤怠連携情報"]["value"] }[]} duplicateDayGroup */ function updateTimeReportTableRows( timeReportRows, kintaiRenkeiRows, duplicateDayGroup ) { kintaiRenkeiRows.forEach(function (kintaiRenkeiRow) { const timeReportRow = pvc.util.array.find(timeReportRows, function (row) { return ( row.value.TIME_REPORT_日付.value === kintaiRenkeiRow.value.勤怠連携情報_勤怠_日付.value ); }); if (timeReportRow != null) { const timeInfo = { 勤務開始時間: toMinutesNum( kintaiRenkeiRow.value.勤怠連携情報_勤務開始時間.value || "", null ) || 0, 勤務終了時間: 0, 休憩時間: toMinutesNum( kintaiRenkeiRow.value.勤怠連携情報_休憩時間.value || "", null ) || 0, 勤務時間: pvc.util.obj.toNumber( kintaiRenkeiRow.value.勤怠連携情報_勤務時間.value ) || 0, 平日残業: pvc.util.obj.toNumber( kintaiRenkeiRow.value.勤怠連携情報_平日残業.value ) || 0, 平日深夜: pvc.util.obj.toNumber( kintaiRenkeiRow.value.勤怠連携情報_平日深夜.value ) || 0, 休日残業: pvc.util.obj.toNumber( kintaiRenkeiRow.value.勤怠連携情報_休日残業.value ) || 0, 休日深夜: pvc.util.obj.toNumber( kintaiRenkeiRow.value.勤怠連携情報_休日深夜.value ) || 0, }; if (timeInfo.勤務時間 !== 0) { timeInfo.勤務終了時間 = toMinutesNum( kintaiRenkeiRow.value.勤怠連携情報_勤務終了時間.value || "", timeInfo.勤務開始時間 ) || 0; } // 重複している日付データがあればそれを集計 const deplicateData = pvc.util.array.find( duplicateDayGroup, function (g) { return ( g.key === (kintaiRenkeiRow.value.勤怠連携情報_勤怠_日付.value || "") ); } ); if (deplicateData != null) { deplicateData.items.forEach(function (deplicateRow) { const kinmuNum = pvc.util.obj.toNumber( deplicateRow.value.勤怠連携情報_勤務時間.value ) || 0; const fromNum = toMinutesNum( deplicateRow.value.勤怠連携情報_勤務開始時間.value || "", null ) || 0; const toNum = kinmuNum === 0 ? 0 : toMinutesNum( deplicateRow.value.勤怠連携情報_勤務終了時間.value || "", fromNum ) || 0; // 小さい方を勤務開始時間に設定 timeInfo.勤務開始時間 = timeInfo.勤務開始時間 < fromNum ? timeInfo.勤務開始時間 : fromNum; // 大きい方を勤務開始時間に設定 timeInfo.勤務終了時間 = timeInfo.勤務終了時間 > toNum ? timeInfo.勤務終了時間 : toNum; // 各時間に加算 timeInfo.休憩時間 += toMinutesNum( deplicateRow.value.勤怠連携情報_休憩時間.value || "", null ) || 0; timeInfo.勤務時間 += kinmuNum; timeInfo.平日残業 += pvc.util.obj.toNumber( deplicateRow.value.勤怠連携情報_平日残業.value ) || 0; timeInfo.平日深夜 += pvc.util.obj.toNumber( deplicateRow.value.勤怠連携情報_平日深夜.value ) || 0; timeInfo.休日残業 += pvc.util.obj.toNumber( deplicateRow.value.勤怠連携情報_休日残業.value ) || 0; timeInfo.休日深夜 += pvc.util.obj.toNumber( deplicateRow.value.勤怠連携情報_休日深夜.value ) || 0; }); } // TIME REPORTの行に設定 const isAllZero = Object.keys(timeInfo).every(function (key) { // @ts-ignore return timeInfo[key] === 0; }); timeReportRow.value.TIME_REPORT_START_TIME.value = isAllZero ? null : toTimeStr(timeInfo.勤務開始時間); timeReportRow.value.TIME_REPORT_END_TIME.value = isAllZero ? null : toTimeStr(timeInfo.勤務終了時間); timeReportRow.value.TIME_REPORT_W_BREAK.value = isAllZero ? null : toTimeStr(timeInfo.休憩時間); timeReportRow.value.TIME_REPORT_WORKING_HOURS.value = isAllZero ? null : String( timeInfo.勤務時間 - timeInfo.平日残業 - timeInfo.平日深夜 - timeInfo.休日残業 - timeInfo.休日深夜 ); timeReportRow.value.TIME_REPORT_W_DAY.value = isAllZero ? null : String(timeInfo.平日残業); timeReportRow.value.TIME_REPORT_W_END.value = isAllZero ? null : String(timeInfo.休日残業); timeReportRow.value.TIME_REPORT_M_NI_W_DAY.value = isAllZero ? null : String(timeInfo.平日深夜); timeReportRow.value.TIME_REPORT_M_NI_W_END.value = isAllZero ? null : String(timeInfo.休日深夜); timeReportRow.value.TIME_REPORT_M_NI.value = isAllZero ? null : String(timeInfo.平日深夜 + timeInfo.休日深夜); } }); } /** * 勤怠強制連携ボタンを作成します */ function createKintaiKyouseiRenkeiButton() { if ( document.querySelector(".pvc-desktop-main__kintaiKyouseiRenkeiButton") != null ) { // ボタンが作成済みなら処理中止 return; } const rootDiv = document.createElement("div"); rootDiv.classList.add("pvc-desktop-main__rootDiv"); const btnUI = new pvc.util.ui.Button({ text: "勤怠強制連携", type: "submit", }); btnUI.element.classList.add("pvc-desktop-main__kintaiKyouseiRenkeiButton"); rootDiv.appendChild(btnUI.element); btnUI.onClick = function () { if (!confirm("TIME REPORTへの連携処理を行います。よろしいですか?")) { return; } const r = kintone.app.record.get(); pvc.util.ui.showSpinner(); upsertTimeReport(r.record, false) .then(function () { // TIME REPORT連携済みフラグの更新処理 return updateTimeReportRenkeiFlag(r.record); }) .then(function () { alert("連携処理が完了しました。"); pvc.util.ui.hideSpinner(); }) .catch(function (error) { console.error(error); alert("システムエラーが発生しました"); pvc.util.ui.hideSpinner(); }); }; kintone.app.record.getHeaderMenuSpaceElement().appendChild(rootDiv); } /** * 時間入力が15分単位(またはブランク)になっているかどうか * @param {string} strTime * @returns {boolean} */ function isTime15Minutes(strTime) { return ( pvc.util.obj.isEmpty(strTime) || Number(strTime.slice(-2)) % 15 === 0 ); } /** * 帳票用Repairテーブルに入力されているRepair情報を設定します。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record */ function setTyouhyouyouRepairTable(record) { record.帳票用Repairテーブル.value = []; for (let repairNum = 1; repairNum <= 7; repairNum++) { const strNum = String(repairNum); if ( // @ts-ignore !pvc.util.obj.isEmpty(record["complaint" + strNum].value) || // @ts-ignore !pvc.util.obj.isEmpty(record["complaint_description" + strNum].value) ) { record.帳票用Repairテーブル.value.push({ value: { 帳票用Repairテーブル_part_number: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["part_number" + strNum].value, }, 帳票用Repairテーブル_description: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["description" + strNum].value, }, 帳票用Repairテーブル_PT: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["PT" + strNum].value, }, 帳票用Repairテーブル_HBG: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["HBG" + strNum].value, }, 帳票用Repairテーブル_UBG: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["UBG" + strNum].value, }, 帳票用Repairテーブル_TBG: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["TBG" + strNum].value, }, 帳票用Repairテーブル_FB: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["FB" + strNum].value, }, 帳票用Repairテーブル_BEH: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["BEH" + strNum].value, }, 帳票用Repairテーブル_UR: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["UR" + strNum].value, }, 帳票用Repairテーブル_ALF: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["ALF" + strNum].value, }, 帳票用Repairテーブル_VU: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["VU" + strNum].value, }, 帳票用Repairテーブル_complaint: { type: "DROP_DOWN", // @ts-ignore value: record["complaint" + strNum].value, }, 帳票用Repairテーブル_complaint_description: { type: "MULTI_LINE_TEXT", // @ts-ignore value: record["complaint_description" + strNum].value, }, 帳票用Repairテーブル_work_done: { type: "DROP_DOWN", // @ts-ignore value: record["work_done" + strNum].value, }, 帳票用Repairテーブル_work_done_discription: { type: "MULTI_LINE_TEXT", // @ts-ignore value: record["work_done_discription" + strNum].value, }, 帳票用Repairテーブル_serial_No_new_part: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["serial_No_new_part" + strNum].value, }, 帳票用Repairテーブル_serial_No_old_part: { type: "SINGLE_LINE_TEXT", // @ts-ignore value: record["serial_No_old_part" + strNum].value, }, 帳票用Repairテーブル_pending: { type: "CHECK_BOX", // @ts-ignore value: record["pending" + strNum].value, }, 帳票用Repairテーブル_finished: { type: "CHECK_BOX", // @ts-ignore value: record["finished" + strNum].value, }, }, }); } } } /** * 指定されたユーザーコードの情報を取得します。 * @param {string} userCode * @returns {Promise} */ function getUserInfo(userCode) { return kintone .api(kintone.api.url("/v1/users", true), "GET", { codes: [userCode], }) .then(function (/** @type {{ users: kintone.UserInfo[] }} */ resp) { return resp.users.length > 0 ? resp.users[0] : null; }); } /** * 帳票用ユーザー名フィールドに値を設定します。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record */ function setTyouhyouUserNameField(record) { // assistance_fromのユーザー1~4番目までの名称を帳票用に設定 record.帳票用assistance_from1.value = record.assistance_from.value.length >= 1 ? record.assistance_from.value[0].name || null : null; record.帳票用assistance_from2.value = record.assistance_from.value.length >= 2 ? record.assistance_from.value[1].name || null : null; record.帳票用assistance_from3.value = record.assistance_from.value.length >= 3 ? record.assistance_from.value[2].name || null : null; record.帳票用assistance_from4.value = record.assistance_from.value.length >= 4 ? record.assistance_from.value[3].name || null : null; record.帳票用assistance_from5.value = record.assistance_from.value.length >= 5 ? record.assistance_from.value[4].name || null : null; // add_engineerのユーザー1~4番目までの名称を帳票用に設定 record.帳票用add_engineer1.value = record.add_engineer.value.length >= 1 ? record.add_engineer.value[0].name || null : null; record.帳票用add_engineer2.value = record.add_engineer.value.length >= 2 ? record.add_engineer.value[1].name || null : null; record.帳票用add_engineer3.value = record.add_engineer.value.length >= 3 ? record.add_engineer.value[2].name || null : null; record.帳票用add_engineer4.value = record.add_engineer.value.length >= 4 ? record.add_engineer.value[3].name || null : null; } /** * TIME REPORT連携フラグの更新処理を行います。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record * @returns {Promise} */ function updateTimeReportRenkeiFlag(record) { if (record.TIME_REPORT連携フラグ.value === "連携済み") { return kintone.Promise.resolve(); } return new KintoneRestAPIClient().record .updateRecord({ app: pvc.env.app.サービスレポート_出張経費精算入力.appId, id: record.$id.value, /** @type {Partial} */ record: { TIME_REPORT連携フラグ: { value: "連携済み", }, }, }) .then(); } /** * 作業時間情報テーブルに行数制限を設定します。 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record */ function setLimitSagyouJikanJououTableRows(record) { const maxRowNum = 20; const sagyouTableClass = "pvc-desktop-main__sagyouJikanJouhouTable"; let sagyouTable = document.querySelector("." + sagyouTableClass); if (sagyouTable == null) { // 初回のClassがまだ設定されていない場合 Array.prototype.forEach.call( document.querySelectorAll(".subtable-gaia"), function (/** @type {HTMLElement} */ table, index) { if (index === 0) { // 1番目のサブテーブル(作業時間情報テーブル) table.classList.add(sagyouTableClass); sagyouTable = table; } } ); } // 行追加ボタンの表示制御 const sagyouTableRowCount = record.作業時間情報.value.length; if (sagyouTable != null) { if (sagyouTableRowCount >= maxRowNum) { // 指定行数以上にならないように行追加ボタンを非表示に設定 sagyouTable.classList.add(sagyouTableClass + "--hiddenAddRowButton"); } else { sagyouTable.classList.remove(sagyouTableClass + "--hiddenAddRowButton"); } } // 制限を超えた行の削除処理 if (sagyouTableRowCount >= maxRowNum) { // 連続でボタンを押すと非表示より先に追加されることがあるため、指定行数以上の行は削除する record.作業時間情報.value = record.作業時間情報.value.filter(function ( row, i ) { return i < maxRowNum; }); } } /** * Repairグループで値が入力されているグループを開いた状態に設定 * @param {kintone.AppRecord__サービスレポート_出張経費精算入力} record */ function setRepairGroupOpen(record) { const repairFieldList = [ "part_number", "description", "PT", "HBG", "UBG", "TBG", "FB", "BEH", "UR", "ALF", "VU", "complaint", "complaint_description", "work_done", "work_done_discription", "serial_No_new_part", "serial_No_old_part", "pending", "finished", ]; for (let repairNo = 1; repairNo <= 7; repairNo++) { kintone.app.record.setGroupFieldOpen( "Repair" + repairNo, repairFieldList.some(function (field) { // @ts-ignore return !pvc.util.obj.isEmpty(record[field + repairNo].value); }) ); } } })();