diff --git a/document/PVC.one b/document/開発仕様書/PVC.one
similarity index 100%
rename from document/PVC.one
rename to document/開発仕様書/PVC.one
diff --git a/document/①仕様書_園児別出欠簿入力_20250205.xlsx b/document/開発仕様書/①仕様書_園児別出欠簿入力_20250205.xlsx
similarity index 100%
rename from document/①仕様書_園児別出欠簿入力_20250205.xlsx
rename to document/開発仕様書/①仕様書_園児別出欠簿入力_20250205.xlsx
diff --git a/document/①仕様書_園児別出欠簿入力_20250321.xlsx b/document/開発仕様書/①仕様書_園児別出欠簿入力_20250321.xlsx
similarity index 100%
rename from document/①仕様書_園児別出欠簿入力_20250321.xlsx
rename to document/開発仕様書/①仕様書_園児別出欠簿入力_20250321.xlsx
diff --git a/document/①仕様書_園児別出欠簿入力_20250402.xlsx b/document/開発仕様書/①仕様書_園児別出欠簿入力_20250402.xlsx
similarity index 100%
rename from document/①仕様書_園児別出欠簿入力_20250402.xlsx
rename to document/開発仕様書/①仕様書_園児別出欠簿入力_20250402.xlsx
diff --git a/document/①仕様書_園児別出欠簿入力_20250408.xlsx b/document/開発仕様書/①仕様書_園児別出欠簿入力_20250408.xlsx
similarity index 100%
rename from document/①仕様書_園児別出欠簿入力_20250408.xlsx
rename to document/開発仕様書/①仕様書_園児別出欠簿入力_20250408.xlsx
diff --git a/document/①仕様書_園児別出欠簿入力_20250409.xlsx b/document/開発仕様書/①仕様書_園児別出欠簿入力_20250409.xlsx
similarity index 100%
rename from document/①仕様書_園児別出欠簿入力_20250409.xlsx
rename to document/開発仕様書/①仕様書_園児別出欠簿入力_20250409.xlsx
diff --git a/document/①仕様書_園児別出欠簿入力_20250507.xlsx b/document/開発仕様書/①仕様書_園児別出欠簿入力_20250507.xlsx
similarity index 100%
rename from document/①仕様書_園児別出欠簿入力_20250507.xlsx
rename to document/開発仕様書/①仕様書_園児別出欠簿入力_20250507.xlsx
diff --git a/document/②仕様書_0,1歳日誌出力用_20250205.xlsx b/document/開発仕様書/②仕様書_0,1歳日誌出力用_20250205.xlsx
similarity index 100%
rename from document/②仕様書_0,1歳日誌出力用_20250205.xlsx
rename to document/開発仕様書/②仕様書_0,1歳日誌出力用_20250205.xlsx
diff --git a/document/②仕様書_0,1歳日誌出力用_20250409.xlsx b/document/開発仕様書/②仕様書_0,1歳日誌出力用_20250409.xlsx
similarity index 100%
rename from document/②仕様書_0,1歳日誌出力用_20250409.xlsx
rename to document/開発仕様書/②仕様書_0,1歳日誌出力用_20250409.xlsx
diff --git a/document/③仕様書_2歳以上日誌出力用_20250205.xlsx b/document/開発仕様書/③仕様書_2歳以上日誌出力用_20250205.xlsx
similarity index 100%
rename from document/③仕様書_2歳以上日誌出力用_20250205.xlsx
rename to document/開発仕様書/③仕様書_2歳以上日誌出力用_20250205.xlsx
diff --git a/document/④仕様書_個別配慮_20250205.xlsx b/document/開発仕様書/④仕様書_個別配慮_20250205.xlsx
similarity index 100%
rename from document/④仕様書_個別配慮_20250205.xlsx
rename to document/開発仕様書/④仕様書_個別配慮_20250205.xlsx
diff --git a/document/⑤仕様書_学年別保育計画_20250214.xlsx b/document/開発仕様書/⑤仕様書_学年別保育計画_20250214.xlsx
similarity index 100%
rename from document/⑤仕様書_学年別保育計画_20250214.xlsx
rename to document/開発仕様書/⑤仕様書_学年別保育計画_20250214.xlsx
diff --git a/document/⑥仕様書_保育計画月案_20250214.xlsx b/document/開発仕様書/⑥仕様書_保育計画月案_20250214.xlsx
similarity index 100%
rename from document/⑥仕様書_保育計画月案_20250214.xlsx
rename to document/開発仕様書/⑥仕様書_保育計画月案_20250214.xlsx
diff --git a/document/⑦仕様書_保育計画週案_20250214.xlsx b/document/開発仕様書/⑦仕様書_保育計画週案_20250214.xlsx
similarity index 100%
rename from document/⑦仕様書_保育計画週案_20250214.xlsx
rename to document/開発仕様書/⑦仕様書_保育計画週案_20250214.xlsx
diff --git a/document/⑧仕様書_学期反省・評価_20250214.xlsx b/document/開発仕様書/⑧仕様書_学期反省・評価_20250214.xlsx
similarity index 100%
rename from document/⑧仕様書_学期反省・評価_20250214.xlsx
rename to document/開発仕様書/⑧仕様書_学期反省・評価_20250214.xlsx
diff --git a/document/横山台こども園様_帳票テンプレート(Excel作成分)/ゆり・つき1視診表.xlsx b/document/開発仕様書/横山台こども園様_帳票テンプレート(Excel作成分)/ゆり・つき1視診表.xlsx
similarity index 100%
rename from document/横山台こども園様_帳票テンプレート(Excel作成分)/ゆり・つき1視診表.xlsx
rename to document/開発仕様書/横山台こども園様_帳票テンプレート(Excel作成分)/ゆり・つき1視診表.xlsx
diff --git a/document/横山台こども園様_帳票テンプレート(Excel作成分)/個別配慮.xlsx b/document/開発仕様書/横山台こども園様_帳票テンプレート(Excel作成分)/個別配慮.xlsx
similarity index 100%
rename from document/横山台こども園様_帳票テンプレート(Excel作成分)/個別配慮.xlsx
rename to document/開発仕様書/横山台こども園様_帳票テンプレート(Excel作成分)/個別配慮.xlsx
diff --git a/document/横山台こども園様_帳票テンプレート(Excel作成分)/出欠集計表.xlsx b/document/開発仕様書/横山台こども園様_帳票テンプレート(Excel作成分)/出欠集計表.xlsx
similarity index 100%
rename from document/横山台こども園様_帳票テンプレート(Excel作成分)/出欠集計表.xlsx
rename to document/開発仕様書/横山台こども園様_帳票テンプレート(Excel作成分)/出欠集計表.xlsx
diff --git a/document/横山台こども園様_帳票テンプレート(Excel作成分)/幼児日誌.xlsx b/document/開発仕様書/横山台こども園様_帳票テンプレート(Excel作成分)/幼児日誌.xlsx
similarity index 100%
rename from document/横山台こども園様_帳票テンプレート(Excel作成分)/幼児日誌.xlsx
rename to document/開発仕様書/横山台こども園様_帳票テンプレート(Excel作成分)/幼児日誌.xlsx
diff --git a/document/横山台こども園様_機能一覧.xlsx b/document/開発仕様書/横山台こども園様_機能一覧.xlsx
similarity index 100%
rename from document/横山台こども園様_機能一覧.xlsx
rename to document/開発仕様書/横山台こども園様_機能一覧.xlsx
diff --git a/document/開発仕様書(2次開発)/kintoneスペーステンプレート/園児管理システム.sptpl b/document/開発仕様書(2次開発)/kintoneスペーステンプレート/園児管理システム.sptpl
new file mode 100644
index 0000000..db63e3d
Binary files /dev/null and b/document/開発仕様書(2次開発)/kintoneスペーステンプレート/園児管理システム.sptpl differ
diff --git a/document/開発仕様書(2次開発)/①仕様書_園児別出欠簿入力_20250822.xlsx b/document/開発仕様書(2次開発)/①仕様書_園児別出欠簿入力_20250822.xlsx
new file mode 100644
index 0000000..a8d4724
Binary files /dev/null and b/document/開発仕様書(2次開発)/①仕様書_園児別出欠簿入力_20250822.xlsx differ
diff --git a/document/開発仕様書(2次開発)/④仕様書_個別配慮_20250822.xlsx b/document/開発仕様書(2次開発)/④仕様書_個別配慮_20250822.xlsx
new file mode 100644
index 0000000..7d8003d
Binary files /dev/null and b/document/開発仕様書(2次開発)/④仕様書_個別配慮_20250822.xlsx differ
diff --git a/document/開発仕様書(2次開発)/⑨仕様書_園児台帳_20250822.xlsx b/document/開発仕様書(2次開発)/⑨仕様書_園児台帳_20250822.xlsx
new file mode 100644
index 0000000..dfd3cf2
Binary files /dev/null and b/document/開発仕様書(2次開発)/⑨仕様書_園児台帳_20250822.xlsx differ
diff --git a/document/開発仕様書(2次開発)/⑩仕様書_保育・教育日数マスタ_20250822.xlsx b/document/開発仕様書(2次開発)/⑩仕様書_保育・教育日数マスタ_20250822.xlsx
new file mode 100644
index 0000000..70008e6
Binary files /dev/null and b/document/開発仕様書(2次開発)/⑩仕様書_保育・教育日数マスタ_20250822.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/~$④仕様書_個別配慮_20250911.xlsx b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/~$④仕様書_個別配慮_20250911.xlsx
new file mode 100644
index 0000000..d9fa88c
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/~$④仕様書_個別配慮_20250911.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/~$⑪仕様書_個別支援計画_20250911.xlsx b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/~$⑪仕様書_個別支援計画_20250911.xlsx
new file mode 100644
index 0000000..d9fa88c
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/~$⑪仕様書_個別支援計画_20250911.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/④仕様書_個別配慮_20250911.xlsx b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/④仕様書_個別配慮_20250911.xlsx
new file mode 100644
index 0000000..f62446e
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/④仕様書_個別配慮_20250911.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑤仕様書_保育計画月案(0歳児用)_20250911.xlsx b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑤仕様書_保育計画月案(0歳児用)_20250911.xlsx
new file mode 100644
index 0000000..20ade3d
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑤仕様書_保育計画月案(0歳児用)_20250911.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑥仕様書_保育計画月案_20250911.xlsx b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑥仕様書_保育計画月案_20250911.xlsx
new file mode 100644
index 0000000..cb3387e
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑥仕様書_保育計画月案_20250911.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑦仕様書_保育計画週案_20250911.xlsx b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑦仕様書_保育計画週案_20250911.xlsx
new file mode 100644
index 0000000..415ed0a
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑦仕様書_保育計画週案_20250911.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑧仕様書_学期反省・評価_20250911.xlsx b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑧仕様書_学期反省・評価_20250911.xlsx
new file mode 100644
index 0000000..137b9e4
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑧仕様書_学期反省・評価_20250911.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑪仕様書_個別支援計画_20250911.xlsx b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑪仕様書_個別支援計画_20250911.xlsx
new file mode 100644
index 0000000..32b93bd
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/⑪仕様書_個別支援計画_20250911.xlsx differ
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/メモ.txt b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/メモ.txt
new file mode 100644
index 0000000..02e33a9
--- /dev/null
+++ b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/メモ.txt
@@ -0,0 +1,12 @@
+下記アプリについて項目等の変更があります。
+スペーステンプレートをお送りしておりますので、お手数ですが環境の差し替えをお願いいたします。
+
+■個別配慮
+・入力項目を4月~翌年3月分追加
+・システム情報にユーザー名出力用項目追加
+
+■20250911にお送りした仕様書の全アプリ
+・プロセス管理を変更
+
+また、「個別支援計画」アプリは前回までにアプリになります。
+見積もりには含めているアプリですが、私の方で標準の範囲で作成しております。
\ No newline at end of file
diff --git a/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/園児管理システム_20250911.sptpl b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/園児管理システム_20250911.sptpl
new file mode 100644
index 0000000..ee683cb
Binary files /dev/null and b/document/開発仕様書(2次開発)/横山台こども園様_開発仕様書_20250911/園児管理システム_20250911.sptpl differ
diff --git a/document/開発仕様書(2次開発)/追加情報_20250822.md b/document/開発仕様書(2次開発)/追加情報_20250822.md
new file mode 100644
index 0000000..01a7ffe
--- /dev/null
+++ b/document/開発仕様書(2次開発)/追加情報_20250822.md
@@ -0,0 +1,197 @@
+### 2025年8月22日 15:48
+**发件人:** 清水優太(PVC)
+**收件人:** 馬 小哲;薛 家豪
+**主题:** 【横山台こども園様】仕様書をお送りします
+
+アリコーン
+馬様、薛様
+
+いつもお世話になっております。
+プランニングヴィレッヂの清水です。
+
+先ほどは横山台こども園様の開発引き継ぎに
+ご参加いただきありがとうございました。
+
+画面共有していた仕様書及び
+スペーステンプレートをお送りいたしますので、
+ご確認いただけますと幸いです。
+
+現在確認中の内容については、
+固まり次第追ってご連絡いたします。
+
+何かご不明な点等ございましたらご連絡ください。
+引き続きよろしくお願いいたします。
+
+---
+
+### 2025年8月25日 16:38
+**发件人:** 馬 小哲
+**收件人:** 清水優太(PVC)
+**抄送:** 小山嘉久(PVC);薛 家豪
+**主题:** RE: 【横山台こども園様】仕様書をお送りします
+
+プランニングヴィレッヂ
+清水様
+いつもお世話になっております。
+アリコーンの馬です。
+
+先日は仕様のご説明ありがとうございました。
+ご送付いただく仕様書を拝見し、以下の点をご確認ください。
+
+1. 「園児別出欠簿入力」の「園での様子入力者」自動入力機能について:
+ 編集者による変更を許可するかご確認:
+ ・変更不可の場合、「園での様子入力者」欄を編集画面で非表示とする必要があるか?
+ ・変更可の場合、「園での様子入力者」変更がない場合のみ、保存時にログインユーザーで上書きする仕様を想定しています。
+
+2. 「個別配慮」の輸出順について:
+ 現在の仕様は「1.学年, 2出席番号」ですが、クラスが異なる園児で出席番号が重複する可能性がありますか?
+ 重複がある場合、「学年→クラス→出席番号」へのソート条件変更をご検討ください。
+
+3. 「個別配慮」の入力単位変更について:
+ ・月次から年次への変更仕様はまだ確定していない認識でよろしいでしょうか?
+ ・年次に変更する場合、Excelレイアウト変更が必要がありますか?
+ ・また、輸出件数が園児数×月数になるため、パフォーマンスへの影響も懸念されます。
+
+4. 「保育・教育日数マスタ」の休日自動取得について:
+ ・保存時に休日データのソートおよび重複除去が必要か
+ ※年間休日が120日以上のため、ソートされないと操作性に影響する可能性があります。
+
+5. 一括承認機能について:
+ 現在、仕様が未確定という認識でよろしいでしょうか?
+
+6. 現在ご提示いただいている見積工数について、下記の対応工数が含まれているかご確認ください。
+ ・「個別配慮」の年次対応
+ ・一括承認機能の追加開発
+ 含まれていない場合、追加工数として見積可能かどうかもあわせてご教示ください。
+
+以上、ご確認のほどよろしくお願いいたします。
+
+引き続きよろしくお願いいたします。
+
+---
+
+### 2025年8月25日 18:09
+**发件人:** 清水優太(PVC)
+**收件人:** 馬 小哲
+**抄送:** 小山嘉久(PVC);薛 家豪
+**主题:** Re: 【横山台こども園様】仕様書をお送りします
+
+アリコーン
+馬様
+
+いつもお世話になっております。
+プランニングヴィレッヂの清水です。
+
+仕様の方ご確認いただきありがとうございます。
+ご質問につきまして下記回答いたします。
+
+1. 「園児別出欠簿入力」の「園での様子入力者」自動入力機能について
+
+ 編集者による手修正の考慮が抜けており申し訳ございません。
+ こちらは後者の「変更可の場合~」を採用してください。
+
+2. 「個別配慮」の輸出順について
+ 同じ学年で複数のクラスは存在しないので、学年→出席番号のソート順で問題ございません。
+
+3. 「個別配慮」の入力単位変更について
+ すみません、こちらの仕様はまだお客様検討中です。
+ 年次の場合もフォーマットの変更はございません。
+
+ また、Excelの輸出件数は変わらないため、パフォーマンスはさほど影響ないと考えますが、
+ これについては私が間違っているかもしれません。
+ いずれにしても本機能は実装いただけますと助かります。
+
+4. 「保育・教育日数マスタ」の休日自動取得について
+ ソートや重複除去が可能でしたら。実装いただけると大変ありがたいです。
+
+5. 一括承認機能について
+ こちらもお客様確認中ですが、動作としては概ね以下のような形になります。
+
+ 作業者=ログインユーザーで絞りこんだ一覧にボタンを配置し、押下で一括承認する仕組みです。
+
+6. 現在ご提示いただいている見積工数について、下記の対応工数が含まれているかご確認ください
+こちらは双方とも含んだ形で見積もり工数をお出ししております。
+資料の方が曖昧な記載で申し訳ございません。
+
+以上になります。
+ご確認の程よろしくお願いいたします。
+
+清水
+
+---
+
+### 2025年8月28日 10:44
+**发件人:** 馬 小哲
+**收件人:** 清水優太(PVC)
+**抄送:** 小山嘉久(PVC);薛 家豪
+**主题:** RE: 【横山台こども園様】仕様書をお送りします
+
+プランニングヴィレッヂ
+清水様
+いつもお世話になっております。
+アリコーンの馬です。
+以下の点についてご確認させていただきたく、ご連絡いたしました。
+
+1. 教育日数の計算式について、
+ 現在は「教育日数-欠勤日数(病欠+自欠)」となっておりますが、
+ 今回の仕様変更により、欠勤日が休日の場合は除外することになっております。
+ こちらの対応に問題はございませんが、Excel表に記載されている欠勤(病欠+自欠)の合計数についても、
+ 休日分を除外する必要があるかご教示いただけますでしょうか。
+
+2. 保育・教育日数マスタについて
+ 「教育日数+休日数」がその月の月日数と一致している必要があるか、ご確認をお願いいたします。
+
+3. 台帳の園児名変更について
+ 台帳の園児名が変更された場合、園児別出欠簿入力以外に、
+ 以下のアプリの園児名も同様に変更する必要があるか、ご確認いただけますでしょうか。
+ - 0・1歳日誌出力用
+ - 2歳以上日誌出力用
+ - 個別配慮
+
+お忙しいところ恐縮ですが、ご確認のほどよろしくお願いいたします。
+
+---
+### 2025年8月29日 09:50
+**发件人:** 清水優太(PVC)
+**收件人:** 馬 小哲
+**抄送:** 小山嘉久(PVC);薛 家豪
+**主题:** Re: 【横山台こども園様】仕様書をお送りします
+
+アリコーン
+馬様
+
+いつもお世話になっております。
+プランニングヴィレッヂの清水です。
+
+ご質問いただきました件につきまして下記回答いたします。
+
+> 1.教育日数の計算式について
+
+欠勤の合計につきましては今までの計算式(病欠+自欠)で構いません。
+
+> 2.保育・教育日数マスタについて
+
+そこまでのチェックは必要ございません。
+
+> 3.台帳の園児名変更について
+
+確かに他アプリも全て変更されるのが望ましいですが、
+下記3点の理由により実装しなくて良いと考えます。
+
+①お客様の方でアプリをいくつか追加する予定があり、
+ 本開発進行中に作成されるとそれも対応しなくてはならなくなる可能性あり
+
+②日誌については再輸出してもらえばよく、
+個別配慮は数が多くないので手直しにて対応可能
+
+③そもそもそれほど費用(工数)をいただいていない。
+
+以上になります。
+
+また、お客様に確認中の事項につきまして、
+現状まだ回答をいただいておりませんため、
+未確定部分の仕様書の送付は来週になるかもしれません。
+
+ご迷惑をお掛けし申し訳ございませんが、よろしくお願いいたします。
+
+清水
\ No newline at end of file
diff --git a/src/0,1歳用日誌/main.mobile.js b/src/0,1歳用日誌/main.mobile.js
deleted file mode 100644
index c7df799..0000000
--- a/src/0,1歳用日誌/main.mobile.js
+++ /dev/null
@@ -1,6 +0,0 @@
-(function () {
- "use strict";
-
- addApproveFlowAction(true);
-
-})();
\ No newline at end of file
diff --git a/src/2歳以上日誌/main.mobile.js b/src/2歳以上日誌/main.mobile.js
deleted file mode 100644
index c7df799..0000000
--- a/src/2歳以上日誌/main.mobile.js
+++ /dev/null
@@ -1,6 +0,0 @@
-(function () {
- "use strict";
-
- addApproveFlowAction(true);
-
-})();
\ No newline at end of file
diff --git a/src/env.js b/src/env.js
index bec21a6..884bae5 100644
--- a/src/env.js
+++ b/src/env.js
@@ -1,8 +1,9 @@
"use strict";
+// https://alicorn.cybozu.com/k/#/space/15/thread/22
const env = {
"園児別出欠簿入力": {
- appId: 19,
+ appId: 250,
excelName: "出欠集計表",
view: {
linkFor0to1: 13352636,
@@ -10,28 +11,28 @@ const env = {
}
},
"0,1歳日誌出力用": {
- appId: 47,
+ appId: 255,
excelName: "ゆり・つき1視診表",
},
"2歳以上日誌出力用": {
- appId: 48,
+ appId: 256,
excelName: "幼児日誌",
},
"個別配慮": {
- appId: 23,
+ appId: 251,
excelName: "個別配慮",
},
"園児台帳": {
- appId: 16,
+ appId: 247,
},
"保育・教育日数マスタ": {
- appId: 41,
+ appId: 253,
},
"Excelテンプレート": {
- appId: 46
+ appId: 254
},
"担任マスタ": {
- appId: 52
+ appId: 259
}
};
diff --git a/src/main.mobile.css b/src/main.mobile.css
deleted file mode 100644
index 0da97be..0000000
--- a/src/main.mobile.css
+++ /dev/null
@@ -1,95 +0,0 @@
-.btn-group-area {
- display: flex;
- /* margin-left: 2.5em; */
- align-items: flex-end;
-}
-.btn-group-area .label {
- margin: 0 4px;
-}
-
-.btn-group-area .input {
- padding-left: 8px;
-}
-
-.btn-group-area .year {
- --kuc-text-input-width: calc(4em + 16px);
- --kuc-text-input-height: 48px;
-}
-.btn-group-area .year input {
- text-align: center;
-}
-
-.btn-group-area .month,
-.btn-group-area .date,
-.btn-group-area .term {
- --kuc-combobox-toggle-width: calc(2em + 16px);
- --kuc-combobox-toggle-height: 48px;
-}
-
-.btn-group-area .term {
- --kuc-combobox-toggle-width: calc(3em + 16px);
-}
-
-.btn-group-area .month input[class^='kuc-combobox'],
-.btn-group-area .date input[class^='kuc-combobox'],
-.btn-group-area .term input[class^='kuc-combobox'] {
- text-align: center;
- padding-right: 8px;
-}
-.btn-group-area .month input + div[class$="icon"],
-.btn-group-area .date input + div[class$="icon"],
-.btn-group-area .term input + div[class$="icon"] {
- display: none;
-}
-
-.action-btn {
- margin: 0 8px;
-}
-
-.customized-record-header-space {
- padding-top: 16px;
- padding-left: 8px;
-}
-.customized-record-header-space > .btn-group-area {
- padding: 0;
- margin: 0;
-}
-.kintone-app-headermenu-space {
- height: auto;
- display: inline-flex;
-}
-
-#user-js-header-clocking-btn-area {
- margin: 4px 0;
- text-align: center;
-}
-
-#user-js-header-clocking-btn-area > .action-btn {
- --kuc-button-width: 6em
-}
-
-#user-js-header-clocking-btn-area > .action-btn:first-child {
- margin-right: 1em;
-}
-
-#user-js-clock-in-btn-area > .action-btn,
-#user-js-clock-out-btn-area > .action-btn {
- --kuc-mobile-button-height: 35px;
- margin: .5em 12px;
-}
-
-.kuc--has-spinner {
- position: relative;
-}
-div[class^='kuc-spinner'][class$='__spinner'] {
- margin-top: 89px;
- height: calc(100% - 89px);
- position: absolute;
- --kuc-spinner-text-color: #3498db;
- --kuc-spinner-loader-color: #3498db;
-}
-div[class^='kuc-spinner'][class$='mask'] {
- top: 89px;
- position: absolute;
- background-color: white;
-}
diff --git a/src/pvc.ProcessBatchApprovalHandler.js b/src/pvc.ProcessBatchApprovalHandler.js
new file mode 100644
index 0000000..961b39e
--- /dev/null
+++ b/src/pvc.ProcessBatchApprovalHandler.js
@@ -0,0 +1,283 @@
+(function () {
+ "use strict";
+
+ /**
+ * 一括承認処理を管理するクラス
+ * 特定のビューでレコードの一括承認機能を提供する
+ */
+ class BatchApprovalHandler {
+ /**
+ * コンストラクタ
+ * @param {number} mineView - マイビューのID
+ * @param {string} classifyField - 分類フィールドのプレースホルダー
+ * @param {Object} btnClassifyMap - 年齢分類マッピングオブジェクト
+ * @param {Object} actionMap - アクション名マッピングオブジェクト
+ * @param {Function} getStatusPrefix - ステータス接頭辞を取得する関数
+ * @param {Object} statusFieldMap
+ * @param {string} classifyFormField
+ */
+ constructor(mineView, classifyField, btnClassifyMap, actionMap, getStatusPrefix, statusFieldMap, classifyFormField = "学年") {
+ this.mineView = mineView;
+ this.classifyField = classifyField;
+ this.btnClassifyMap = btnClassifyMap;
+ this.actionMap = actionMap;
+ this.getStatusPrefix = getStatusPrefix;
+ this.statusFieldMap = statusFieldMap;
+ this.classifyFormField = classifyFormField;
+ this.stopFlag = false;
+ }
+
+ stopProcess() {
+ this.stopFlag = true;
+ }
+
+ /**
+ * 一括承認ボタンを作成する
+ * @method
+ */
+ createApproveBtn() {
+ const headerSpace = getHeaderSpace('single-label-line');
+ const elements = createBtnGroupArea('batch-approve-area', '一括承認', this.handleApproveData.bind(this), {
+ btnElId: 'batch-btn'
+ });
+
+ if (elements && headerSpace) {
+ headerSpace.appendChild(elements['batch-approve-area']);
+ }
+ }
+
+ /**
+ * 一括承認処理を実行する
+ * @method
+ * @param {Event} e - イベントオブジェクト
+ */
+ async handleApproveData(e) {
+ this.stopFlag = false;
+ const appId = kintone.app.getId();
+ const loginUser = kintone.getLoginUser();
+
+ loading(true, '一括承認処理中...');
+ showError(false);
+
+ const api = new KintoneRestAPIClient();
+
+ // レコードを取得
+ const records = await this.getRecords(api, appId, loginUser.code);
+ if (!records || records.length === 0) {
+ loading(false);
+ return e;
+ }
+
+ // ステータスを更新
+ const result = await this.updateRecordsStatus(api, appId, records);
+
+ if (result && result.success > 0) {
+ // 承認者情報を更新
+ await this.updateRecords(api, appId, records, result.successIds, loginUser);
+ await this.showSuccessDialog(result);
+ }
+ loading(false);
+ }
+
+ /**
+ * 成功ダイアログを表示する
+ * @method
+ * @param {Object} result - 処理結果
+ */
+ async showSuccessDialog(result) {
+ const contentEl = document.createElement('div');
+ contentEl.style.fontSize = '16px';
+
+ if (result.success === result.total) {
+ contentEl.innerHTML = `✅ 全${result.total}件のレコードを承認しました`;
+ } else {
+ const successText = `✅ ${result.success}件のレコードを承認済み`;
+ const failedText = `⚠️ ${result.total - result.success}件の承認に失敗`;
+ contentEl.innerHTML = `${successText}
${failedText}
合計: ${result.total}件`;
+ }
+
+ showDialog({
+ title: '一括承認完了',
+ content: contentEl,
+ ok: '更新して確認',
+ cancel: false,
+ onClose: () => { location.reload(); }
+ });
+ }
+
+ /**
+ * アクションプロセスマップを読み込む
+ * @method
+ * @param {Object} api - Kintone REST API クライアント
+ * @param {number} appId - アプリID
+ */
+ async loadActionProcessMap(api, appId) {
+ try {
+ const result = await api.app.getProcessManagement({
+ app: appId,
+ preview: false
+ });
+
+ const actionProcessMap = {};
+ result.actions.forEach(action => {
+ actionProcessMap[action.from + ":" + action.name] = action;
+ });
+
+ return actionProcessMap;
+ } catch (error) {
+ showError(true, 'プロセス管理情報の読み取りに失敗しました\n - ' + error.message);
+ }
+ }
+
+ /**
+ * レコードを取得する
+ * @method
+ * @param {Object} api - Kintone REST API クライアント
+ * @param {number} appId - アプリID
+ * @param {string} loginUserCd - ログインユーザーコード
+ */
+ async getRecords(api, appId, loginUserCd) {
+ try {
+ return await api.record.getAllRecordsWithId({
+ app: appId,
+ condition: `作業者 in ("${loginUserCd}")`
+ });
+ } catch (error) {
+ showError(true, 'レコードの読み取りに失敗しました\n - ' + error.message);
+ return null;
+ }
+ }
+
+ /**
+ * レコードを更新する
+ * @method
+ * @param {Object} api - Kintone REST API クライアント
+ * @param {number} appId - アプリID
+ * @param {Array} oldRecords - 更新前レコード
+ * @param {Set} successIds - 成功したレコードID
+ * @param {Object} loginUser - ログインユーザー情報
+ */
+ async updateRecords(api, appId, oldRecords, successIds, loginUser) {
+ const actionProcessMap = await this.loadActionProcessMap(api, appId);
+ if (!actionProcessMap) {
+ return;
+ }
+ const updateFieldRecords = [];
+
+ for (const record of oldRecords) {
+ const updateKey = this.getRecordAutoUpdateField(record, actionProcessMap, successIds);
+ if (updateKey) {
+ updateFieldRecords.push({
+ 'id': record.$id.value,
+ 'record': {
+ [updateKey]: {
+ 'value': loginUser.name
+ }
+ }
+ });
+ }
+ }
+
+ if (updateFieldRecords.length > 0) {
+ try {
+ await api.record.updateAllRecords({
+ app: appId,
+ records: updateFieldRecords
+ });
+ } catch (error) {
+ showError(true, 'レコード更新に失敗しました\n - ' + error.message);
+ }
+ }
+ }
+
+ /**
+ * 自動更新フィールド名を取得する
+ * @method
+ * @param {Object} record - レコードオブジェクト
+ * @param {Object} actionProcessMap - アクションプロセスマップ
+ * @param {Set} successIds - 成功したレコードID
+ */
+ getRecordAutoUpdateField(record, actionProcessMap, successIds) {
+ const id = record.$id.value;
+ if (!successIds.has(id)) {
+ return null;
+ }
+
+ const oldStatus = record.ステータス.value;
+ const actionName = record.action;
+
+ const action = actionProcessMap[oldStatus + ":" + actionName];
+ return action ? this.statusFieldMap[action.to] : null;
+ }
+
+ /**
+ * レコードステータスを更新する
+ * @method
+ * @param {Object} api - Kintone REST API クライアント
+ * @param {number} appId - アプリID
+ * @param {Array} records - 更新対象レコード
+ */
+ async updateRecordsStatus(api, appId, records) {
+ const updateRecords = []
+ for (const record of records) {
+ const actionToPerform = this.getActionName(record);
+ if (this.stopFlag) {
+ return
+ }
+ if (!!actionToPerform) {
+ record.action = actionToPerform;
+ updateRecords.push({
+ id: record.$id.value,
+ action: actionToPerform,
+ revision: record.$revision.value
+ });
+ }
+ }
+
+ const result = {
+ success: 0,
+ total: records.length,
+ successIds: new Set(),
+ };
+
+ const batchSize = 100; // Kintone APIの制限
+ for (let i = 0; i < updateRecords.length; i += batchSize) {
+ const batch = updateRecords.slice(i, i + batchSize);
+
+ try {
+ const response = await api.record.updateRecordsStatus({
+ app: appId,
+ records: batch
+ });
+
+ result.success += response.records.length;
+ response.records.forEach(record => {
+ result.successIds.add(record.id);
+ });
+ } catch (error) {
+ showError(true, `レコードステータス更新エラー\n - ${error.message}`);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * アクション名を取得する
+ * @method
+ * @param {string} record - レコードオブジェクト
+ */
+ getActionName(record) {
+ const yearStr = record[this.classifyFormField]?.value || '';
+ const status = record.ステータス.value;
+ const actionTemplate = this.actionMap[this.getStatusPrefix(status)] || '';
+ const btnClassify = this.btnClassifyMap[yearStr] || '';
+ return actionTemplate.replaceAll(this.classifyField, btnClassify);
+ }
+
+ }
+
+ // グローバルにクラスを公開
+ window.BatchApprovalHandler = BatchApprovalHandler;
+
+})();
\ No newline at end of file
diff --git a/src/utils.js b/src/pvc.utils.js
similarity index 93%
rename from src/utils.js
rename to src/pvc.utils.js
index 8e64a09..6e94aaa 100644
--- a/src/utils.js
+++ b/src/pvc.utils.js
@@ -222,6 +222,18 @@ function convertToWesternYear(year, era) {
return warekiStartYear[era] + year - 1;
}
+function getYearRange() {
+ const today = new Date();
+ let year = today.getFullYear();
+ if (today.getMonth() + 1 < 4) {
+ year -= 1;
+ }
+ return {
+ 'start': getFormatDateString(year, 4, 1),
+ 'end': getFormatDateString(year + 1, 3, 31)
+ }
+}
+
function getFormatDateString(dateObjOrYear, month, date) {
let year = dateObjOrYear;
if (typeof dateObjOrYear === "object" && !month && !date) {
@@ -489,20 +501,3 @@ function groupingBySex(list) {
return [male, female];
}, [[], []]);
}
-
-const statusFieldMap = {
- '指導教諭確認中': '担任',
- '主幹確認中': '指導',
- '園長確認中': '主幹',
- '完了': '園長'
-}
-
-function addApproveFlowAction() {
- return kintone.events.on("app.record.detail.process.proceed", (event) => {
- const field = statusFieldMap[event.nextStatus.value];
- if (field) {
- event.record[field].value = kintone.getLoginUser().name;
- }
- return event;
-});
-}
\ No newline at end of file
diff --git a/src/utils-mobile.js b/src/utils-mobile.js
deleted file mode 100644
index f0ea538..0000000
--- a/src/utils-mobile.js
+++ /dev/null
@@ -1,206 +0,0 @@
-const Kuc = Kucs['1.19.0'];
-
-let notificationEl;
-function getHeaderSpace(className, isDetailPage) {
- const headerSpace = kintone.mobile.app.getHeaderSpaceElement();
- if (!headerSpace) {
- throw new Error('このページではヘッダー要素が利用できません。');
- };
-
- const _className = isDetailPage ? 'customized-record-header-space' : 'customized-header-space';
-
- headerSpace.className += (' ' + _className + ' ' + className);
- headerSpace.parentElement.className += (' ' + _className + '-wrapper ' + className);
-
- return headerSpace;
-}
-
-const classItems = [
- { label: "にじ", value: "にじ" },
- { label: "ほし", value: "ほし" },
- { label: "つき", value: "つき" },
- { label: "ゆり", value: "ゆり" },
-]
-
-const termItems = [
- { label: "0歳児", value: "0歳児" },
- { label: "1歳児", value: "1歳児" },
- { label: "2歳児", value: "2歳児" },
- { label: "3歳児", value: "3歳児" },
- { label: "4歳児", value: "4歳児" },
- { label: "5歳児", value: "5歳児" },
-]
-
-
-function createBtnGroupArea(groupId, btnLabel, btnOnClick, { btnElId = false, yearElId = false, monthElId = false, dateElId = false, termElId = false, defaultThisMonth = false, }) {
- const result = {};
-
- if (document.getElementById(groupId)) {
- return;
- }
-
- const btnGroupAreaEl = document.createElement('div');
- btnGroupAreaEl.id = groupId;
- btnGroupAreaEl.className = 'btn-group-area'
- result[groupId] = btnGroupAreaEl;
-
- if (yearElId) {
- const yearEl = new Kuc.MobileText({
- value: "" + new Date().getFullYear(),
- id: yearElId,
- label: '年',
- className: 'year input'
- });
- result[yearElId] = yearEl;
- btnGroupAreaEl.appendChild(yearEl);
- }
-
- if (monthElId) {
- const monthEl = new Kuc.MobileDropdown({
- value: defaultThisMonth ? monthItems[new Date().getMonth()].value : undefined,
- id: monthElId,
- className: 'month input',
- label: '月',
- items: monthItems,
- });
- result[monthElId] = monthEl;
- btnGroupAreaEl.appendChild(monthEl);
- }
-
- if (dateElId) {
- const dateEl = new Kuc.MobileDropdown({
- value: dateItems[new Date().getDate() - 1].value,
- id: dateElId,
- items: dateItems,
- label: '日',
- className: "date input",
- });
- result[dateElId] = dateEl;
- btnGroupAreaEl.appendChild(dateEl);
- }
-
- if (termElId) {
-
- const termEl = new Kuc.MobileDropdown({
- id: termElId,
- items: termItems,
- className: "term input",
- label: '学年',
- });
- result[termElId] = termEl;
- btnGroupAreaEl.appendChild(termEl);
- }
-
- const btnEl = new Kuc.MobileButton({
- text: btnLabel,
- type: "submit",
- className: "action-btn",
- id: btnElId,
- });
- result[btnElId] = btnEl;
- btnEl.addEventListener('click', (e) => {
- showError(false);
- const checkResult = checkInputData(result, { btnLabel, yearElId, monthElId, dateElId, termElId });
- if (checkResult) {
- btnOnClick(e, checkResult);
- }
- });
- btnGroupAreaEl.appendChild(btnEl);
-
- return result;
-}
-
-function checkInputData(map, { btnLabel, yearElId, monthElId, dateElId, termElId }) {
- const year = yearElId && map[yearElId].value;
- const month = monthElId && map[monthElId].value;
- const date = dateElId && (map[dateElId].value === 'end' ? getLastDate(year, month).getDate() : map[dateElId].value);
- const term = termElId && map[termElId].value;
-
- const errorMsgs = [];
-
- if (yearElId) {
- const yearRegex = /^\d+$/;
- if (!yearRegex.test(year)) {
- errorMsgs.push(' · 年は整数で入力してください。');
- }
- }
- if (monthElId && !month) {
- errorMsgs.push(' · 月を選択してください。');
- }
- if (dateElId && !date) {
- errorMsgs.push(' · 日を選択してください。');
- }
- if (termElId && !term) {
- errorMsgs.push(' · 学年を選択してください。');
- }
- if (errorMsgs.length > 0) {
- showError(true, btnLabel + 'エラー\n' + errorMsgs.join('\n'))
- return;
- }
-
- return {
- year,
- month,
- date,
- term,
- }
-}
-
-function createBtn(id, label, onClick) {
- const btnEl = new Kuc.MobileButton({
- text: label,
- type: "submit",
- className: "action-btn",
- id,
- });
- btnEl.addEventListener('click', onClick);
- return btnEl;
-}
-
-function hideSpaceField(ids) {
- ids.forEach(id => {
- const area = kintone.mobile.app.record.getSpaceElement(id);
- area.parentElement.style.minWidth = '0';
- area.parentElement.style.display = 'none';
- });
-}
-
-const statusFieldMap = {
- '指導教諭確認中': '担任',
- '主幹確認中': '指導',
- '園長確認中': '主幹',
- '完了': '園長'
-}
-
-function addApproveFlowAction() {
- return kintone.events.on("mobile.app.record.detail.process.proceed", (event) => {
- const field = statusFieldMap[event.nextStatus.value];
- if (field) {
- event.record[field].value = kintone.getLoginUser().name;
- }
- return event;
- });
-}
-
-function showError(show, text) {
- if (show) {
- buildNotification('danger', text);
- notificationEl.open();
- console.error(text);
- } else {
- notificationEl && notificationEl.close();
- }
-}
-
-function buildNotification(type, text, duration = -1) {
- const param = {
- type,
- text,
- duration
- }
- if (!notificationEl) {
- notificationEl = new Kuc.MobileNotification(param);
- } else {
- Object.assign(notificationEl, param);
- }
-}
diff --git a/src/保育・教育日数マスタ/main.css b/src/保育・教育日数マスタ/main.css
new file mode 100644
index 0000000..b62ae36
--- /dev/null
+++ b/src/保育・教育日数マスタ/main.css
@@ -0,0 +1,77 @@
+#legend {
+ width: 100%;
+ top: -24px;
+ position: absolute;
+ text-align: right;
+ font-size: 13px;
+}
+
+#legend .box {
+ display: inline-block;
+ width: 14px;
+ height: 14px;
+ background: #ffe3e6;
+ margin-right: 4px;
+ vertical-align: middle;
+}
+
+/* カレンダーエリア */
+#calendar {
+ width: 100%;
+ height: 100%;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(4, 1fr);
+ gap: 12px;
+ box-sizing: border-box;
+}
+
+.month {
+ display: grid;
+ grid-template-columns: repeat(7, 1fr);
+ grid-template-rows: auto repeat(6, 1fr);
+ border: 1px solid #aaa;
+ border-radius: 4px;
+}
+
+.month .title {
+ grid-column: 1/8;
+ text-align: center;
+ font-weight: bold;
+ padding: 4px 0;
+}
+
+.month .cell {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 13px;
+}
+
+#calendar:not(.readonly) .month .cell:not(.header):not(:empty) {
+ cursor: pointer;
+}
+
+.month .cell:not(:empty) {
+ padding: 2px 0;
+}
+
+.month .sun {
+ color: #e74c3c;
+}
+
+.month .sat {
+ color: #2196f3;
+}
+
+.month .cell.selected {
+ background: #ffe3e6;
+}
+
+#calendar:not(.readonly) .month .cell:not(.header):not(.selected):not(:empty):hover {
+ background: #ffe3e677;
+}
+
+#calendar:not(.readonly) .month .cell.selected:hover {
+ background: #ffd3d7;
+}
diff --git a/src/保育・教育日数マスタ/main.js b/src/保育・教育日数マスタ/main.js
new file mode 100644
index 0000000..7eb1b61
--- /dev/null
+++ b/src/保育・教育日数マスタ/main.js
@@ -0,0 +1,312 @@
+(() => {
+ 'use strict'
+ let _CALENDAR
+
+ // レコード詳細/新規作成/編集画面表示時にカレンダーを初期化
+ kintone.events.on(
+ ['app.record.detail.show', 'app.record.create.show', 'app.record.edit.show'],
+ (event) => {
+ kintone.app.record.setFieldShown('休日の生データ', false);
+ initCalendarArea(
+ event.record,
+ getHolidayMap(event.record),
+ event.type === 'app.record.detail.show'
+ )
+ return event
+ }
+ )
+
+ // 年度フィールド変更時に各月の休日をクリアしてカレンダーを再描画
+ kintone.events.on(
+ [
+ 'app.record.create.change.年度',
+ 'app.record.edit.change.年度',
+ 'app.record.index.edit.change.年度'
+ ],
+ (event) => {
+ forEachRawFields((field) => {
+ event.record[field].value = ''
+ })
+ if (event.type !== 'app.record.index.edit.change.年度') {
+ initCalendarArea(event.record)
+ }
+ return event
+ }
+ )
+
+ // 一覧編集画面では各月の休日フィールドを編集不可にする
+ kintone.events.on(
+ ['app.record.index.edit.show'],
+ (event) => {
+ forEachRawFields((field) => {
+ event.record[field].disabled = true
+ })
+ return event
+ }
+ )
+
+ // レコード保存時にカレンダーで選択した休日を各月フィールドへ反映
+ kintone.events.on(
+ ['app.record.create.submit', 'app.record.edit.submit'],
+ (event) => {
+ const resultMap = _CALENDAR.getSelectedDatesMap()
+ forEachRawFields((field, i) => {
+ event.record[field].value = resultMap[i].join(',')
+ })
+ return event
+ }
+ )
+
+ /* --------------------------------------------------
+ * 初期化・データ準備
+ * -------------------------------------------------- */
+ // カレンダー表示エリアを初期化
+ function initCalendarArea(record, map = {}, readonly = false) {
+ const calendarAreaEl = kintone.app.record.getSpaceElement('calendar-area')
+ calendarAreaEl.innerHTML = ''
+ const year = record.年度.value
+ if (isYearString(year)) {
+ _CALENDAR = createCalendar(Number(year), map, readonly)
+ calendarAreaEl.appendChild(_CALENDAR.fragment)
+ }
+ }
+
+ // 既存レコードに保存されている休日を取得
+ function getHolidayMap(record) {
+ const res = {}
+ forEachRawFields((field, i) => {
+ const str = record[field].value
+ if (!str) {
+ return
+ }
+ res[i] = new Set(str.split(','))
+ })
+ return res
+ }
+
+ /* --------------------------------------------------
+ * ユーティリティ
+ * -------------------------------------------------- */
+ // 各月フィールドをループ
+ const forEachRawFields = (callback) => {
+ for (let i = 1; i <= 12; i++) {
+ callback(`休日_${i}月`, i)
+ }
+ }
+
+ // ゼロパディング
+ const padZero = (n) => (n < 10 ? '0' + n : n)
+
+ // Date → yyyy-MM-dd
+ const toYmd = (d) => `${d.getFullYear()}-${padZero(d.getMonth() + 1)}-${padZero(d.getDate())}`
+
+ // 土日判定
+ const isWeekend = (d) => d.getDay() === 0 || d.getDay() === 6
+
+ // 年度文字列の妥当性チェック
+ function isYearString(str) {
+ // 文字列かつ空でない
+ if (typeof str !== 'string' || str.length === 0) {
+ return false
+ }
+
+ // 数字のみ
+ if (!/^\d+$/.test(str)) {
+ return false
+ }
+
+ // 4桁
+ if (str.length !== 4) {
+ return false
+ }
+
+ // 1900-3000 の範囲
+ const year = parseInt(str, 10)
+ return year >= 1900 && year <= 3000
+ }
+
+ /* --------------------------------------------------
+ * カレンダー生成
+ * -------------------------------------------------- */
+ const createCalendar = (year, highlightMap, readonly) => {
+ const fragment = document.createDocumentFragment()
+
+ /* ----- 図例 ----- */
+ const legend = document.createElement('div')
+ legend.id = 'legend'
+ legend.innerHTML = '休日'
+ fragment.appendChild(legend)
+
+ /* ----- カレンダーコンテナ ----- */
+ const calendar = document.createElement('div')
+ calendar.id = 'calendar'
+ if (readonly) {
+ calendar.classList.add('readonly')
+ }
+ fragment.appendChild(calendar)
+
+ /* ----- 内部状態 ----- */
+ const selectedSet = new Set()
+ const months = buildMonths(year)
+ months.forEach((m) => {
+ calendar.appendChild(buildMonth(m))
+ })
+
+ /* ---------- 月情報生成 ---------- */
+ function buildMonths(year) {
+ return Array.from({ length: 12 }, (_, i) => {
+ const monthIndex = 3 + i // 0 基準月で 4 月始まり
+ const date = new Date(year, monthIndex, 1)
+ return {
+ displayMonth: date.getMonth() + 1,
+ year: date.getFullYear(),
+ month: date.getMonth(),
+ label: `${date.getFullYear()}年${date.getMonth() + 1}月`
+ }
+ })
+ }
+
+ /* ---------- 月単位カレンダー生成 ---------- */
+ function buildMonth({ displayMonth, year, month, label }) {
+ const monthBox = document.createElement('div')
+ monthBox.className = 'month'
+
+ buildTitle(monthBox, label)
+ buildHeader(monthBox)
+
+ const first = new Date(year, month, 1)
+ buildPadBlocksStart(first, monthBox)
+ buildDateBlocks(year, month, displayMonth, monthBox)
+ buildPadBlocksEnd(monthBox)
+
+ return monthBox
+ }
+
+ function buildTitle(monthBox, label) {
+ const title = document.createElement('div')
+ title.className = 'title'
+ title.textContent = label
+ monthBox.appendChild(title)
+ }
+
+ function buildHeader(monthBox) {
+ ['日', '月', '火', '水', '木', '金', '土'].forEach((day, i) => {
+ const cell = document.createElement('div')
+ cell.className = 'cell header'
+ addWeekendClass(cell, i)
+ cell.textContent = day
+ monthBox.appendChild(cell)
+ })
+ }
+
+ function addWeekendClass(cell, week) {
+ if (week === 0) {
+ cell.classList.add('sun')
+ } else if (week === 6) {
+ cell.classList.add('sat')
+ }
+ }
+
+ function buildPadBlocksStart(first, monthBox) {
+ const startDayInWeek = first.getDay()
+ for (let i = 0; i < startDayInWeek; i++) {
+ const cell = document.createElement('div')
+ cell.className = 'cell'
+ monthBox.appendChild(cell)
+ }
+ }
+
+ function buildDateBlocks(year, month, displayMonth, monthBox) {
+ const last = new Date(year, month + 1, 0)
+ const highlights = highlightMap[displayMonth] || null
+
+ for (let day = 1; day <= last.getDate(); day++) {
+ const dateObj = new Date(year, month, day)
+ const ymd = toYmd(dateObj)
+ const cell = document.createElement('div')
+ cell.className = 'cell'
+ cell.textContent = day
+ cell.dataset.date = ymd
+
+ addWeekendClass(cell, dateObj.getDay())
+
+ // 初期選択判定
+ let shouldSelect = false
+ if (highlights === null) {
+ shouldSelect = isWeekend(dateObj)
+ } else if (highlights instanceof Set) {
+ shouldSelect = highlights.has(ymd)
+ }
+
+ if (shouldSelect) {
+ cell.classList.add('selected')
+ selectedSet.add(ymd)
+ }
+
+ // 編集可モードのみクリックイベントを追加
+ if (!readonly) {
+ cell.addEventListener('click', () => {
+ cell.classList.toggle('selected')
+ if (cell.classList.contains('selected')) {
+ selectedSet.add(ymd)
+ } else {
+ selectedSet.delete(ymd)
+ }
+ })
+ }
+
+ monthBox.appendChild(cell)
+ }
+ }
+
+ function buildPadBlocksEnd(monthBox) {
+ // 7×7 マスに揃えるための埋め草
+ while (monthBox.children.length < 49) {
+ const cell = document.createElement('div')
+ cell.className = 'cell'
+ monthBox.appendChild(cell)
+ }
+ }
+
+ /* ---------- 選択済み日付取得 ---------- */
+ function getSelectedDatesMap() {
+ const res = {}
+ months.forEach(({ month }) => {
+ res[month + 1] = []
+ })
+
+ // 選択済み日付を振り分け
+ selectedSet.forEach((ymd) => {
+ const d = new Date(ymd)
+ const displayMonth = d.getMonth() + 1
+ res[displayMonth].push(ymd)
+ })
+
+ // 選択が無い月は全土日を自動追加
+ Object.keys(res).forEach((monthKey) => {
+ if (res[monthKey].length === 0) {
+ const monthInfo = months.find((m) => m.displayMonth == monthKey)
+ if (monthInfo) {
+ const year = monthInfo.year
+ const month = monthInfo.month
+ const lastDay = new Date(year, month + 1, 0).getDate()
+
+ for (let day = 1; day <= lastDay; day++) {
+ const dateObj = new Date(year, month, day)
+ if (isWeekend(dateObj)) {
+ res[monthKey].push(toYmd(dateObj))
+ }
+ }
+ }
+ }
+ })
+
+ return res
+ }
+
+ return {
+ fragment,
+ getSelectedDatesMap
+ }
+ }
+})()
\ No newline at end of file
diff --git a/src/保育計画月案/env.js b/src/保育計画月案/env.js
deleted file mode 100644
index 9bce138..0000000
--- a/src/保育計画月案/env.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const statusFieldMap = {
- '主幹確認中': '指導',
- '園長確認中': '主幹',
- '完了': '園長'
-}
diff --git a/src/保育計画月案/main.mobile.js b/src/保育計画月案/main.mobile.js
deleted file mode 100644
index 4932585..0000000
--- a/src/保育計画月案/main.mobile.js
+++ /dev/null
@@ -1,12 +0,0 @@
-(function () {
- "use strict";
-
- kintone.events.on("mobile.app.record.detail.process.proceed", (event) => {
- const field = statusFieldMap[event.nextStatus.value];
- if (field) {
- event.record[field].value = kintone.getLoginUser().name;
- }
- return event;
- });
-
-})();
\ No newline at end of file
diff --git a/src/保育計画週案/env.js b/src/保育計画週案/env.js
deleted file mode 100644
index b01aacd..0000000
--- a/src/保育計画週案/env.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const statusFieldMap = {
- '主幹確認中(4週目)': '指導',
- '園長確認中(4週目)': '主幹',
- '完了(4週目)': '園長',
- '担任作成中(5週目)': '園長',
- '主幹確認中(5週目)': '指導',
- '園長確認中(5週目)': '主幹',
- '完了(5週目)': '園長',
-}
diff --git a/src/保育計画週案/main.mobile.js b/src/保育計画週案/main.mobile.js
deleted file mode 100644
index 4932585..0000000
--- a/src/保育計画週案/main.mobile.js
+++ /dev/null
@@ -1,12 +0,0 @@
-(function () {
- "use strict";
-
- kintone.events.on("mobile.app.record.detail.process.proceed", (event) => {
- const field = statusFieldMap[event.nextStatus.value];
- if (field) {
- event.record[field].value = kintone.getLoginUser().name;
- }
- return event;
- });
-
-})();
\ No newline at end of file
diff --git a/src/個別配慮/main.mobile.js b/src/個別配慮/main.mobile.js
deleted file mode 100644
index c7df799..0000000
--- a/src/個別配慮/main.mobile.js
+++ /dev/null
@@ -1,6 +0,0 @@
-(function () {
- "use strict";
-
- addApproveFlowAction(true);
-
-})();
\ No newline at end of file
diff --git a/src/園児別出欠簿入力/detail-page-desktop-mobile.js b/src/園児別出欠簿入力/detail-page-desktop-mobile.js
deleted file mode 100644
index 121634c..0000000
--- a/src/園児別出欠簿入力/detail-page-desktop-mobile.js
+++ /dev/null
@@ -1,57 +0,0 @@
-
-(function () {
- "use strict";
-
- // ------------------- 詳細画面表示時の処理 -------------------
- kintone.events.on('mobile.app.record.detail.show', function (event) {
- const area = kintone.mobile.app.record.getSpaceElement('header-clocking-btn-area');
-
- const clockIn = createBtn('clock-in', '登園', dateToFieldInDetail('登園時刻'));
- const clockOut = createBtn('clock-out', '帰園', dateToFieldInDetail('帰園時刻'));
- area.appendChild(clockIn);
- area.appendChild(clockOut);
-
- hideSpaceField(['clock-in-btn-area', 'clock-out-btn-area']);
- return event;
- });
-
- function dateToFieldInDetail(fieldCode) {
- return async function (e) {
- await new KintoneRestAPIClient().record.updateRecord({
- app: kintone.mobile.app.getId(),
- id: kintone.mobile.app.record.getId(),
- record: {
- [fieldCode]: {
- value: getCurrentTime()
- }
- }
- });
- location.reload();
- }
- }
-
-
- // ------------------- 編集画面表示時の処理 -------------------
- kintone.events.on(['mobile.app.record.create.show', 'mobile.app.record.edit.show'], function (event) {
- const clockIn = createBtn('clock-in', '登園', dateToFieldInEdit('登園時刻'));
- kintone.mobile.app.record.getSpaceElement('clock-in-btn-area').appendChild(clockIn);
- const clockOut = createBtn('clock-out', '帰園', dateToFieldInEdit('帰園時刻'));
- kintone.mobile.app.record.getSpaceElement('clock-out-btn-area').appendChild(clockOut);
- return event;
- });
-
- function dateToFieldInEdit(fieldCode) {
- return function (e) {
- var record = kintone.mobile.app.record.get();
- record['record'][fieldCode]['value'] = getCurrentTime();
- kintone.mobile.app.record.set(record);
- }
- }
-
- function getCurrentTime() {
- const now = new Date();
- const hours = String(now.getHours()).padStart(2, '0');
- const minutes = String(now.getMinutes()).padStart(2, '0');
- return `${hours}:${minutes}`;
- }
-})();
\ No newline at end of file
diff --git a/src/園児別出欠簿入力/main.mobile.js b/src/園児別出欠簿入力/main.mobile.js
deleted file mode 100644
index b87a305..0000000
--- a/src/園児別出欠簿入力/main.mobile.js
+++ /dev/null
@@ -1,21 +0,0 @@
-(function () {
- "use strict";
-
- addApproveFlowAction(true);
-
- kintone.events.on("mobile.app.record.index.show", (event) => {
- const headerSpace = getHeaderSpace('single-label-line');
-
- // if (event.viewId === APP_ENV.view.linkFor0to1) {
- // Link1Handler.getInstance(headerSpace);
- // return event;
- // }
-
- // if (event.viewId === APP_ENV.view.linkForOthers) {
- // Link2Handler.getInstance(headerSpace);
- // return event;
- // }
-
- // BatchCreateHandler.getInstance(headerSpace);
- });
-})();
\ No newline at end of file
diff --git a/src/園児台帳/main.js b/src/園児台帳/main.js
deleted file mode 100644
index a31775c..0000000
--- a/src/園児台帳/main.js
+++ /dev/null
@@ -1,41 +0,0 @@
-
-(function () {
- "use strict";
- const FIELD_CODE = "ユニークキー";
-
- // ------------------- 詳細/印刷/編集画面表示時の処理 -------------------
- kintone.events.on(['app.record.detail.show', 'app.record.print.show'], function (event) {
- hideField(FIELD_CODE);
- return event;
- });
-
- // ------------------- 編集画面表示時の処理 -------------------
- kintone.events.on(['app.record.edit.show', 'app.record.create.show'], function (event) {
- const targetFieldEl = kintone.app.record.getSpaceElement("before-unique-key").parentElement.nextSibling;
- targetFieldEl.querySelector('.input-constraints-cybozu').style.display = 'none';
-
- event.record[FIELD_CODE]['value'] = "<自動計算:出席番号+学年+クラス+名前>";
- disableField(event.record, FIELD_CODE);
- return event;
- });
-
-
- function hideField(fieldCode) {
- kintone.app.record.setFieldShown(fieldCode, false);
- }
-
- function disableField(record, fieldCode) {
- record[fieldCode]['disabled'] = true;
- }
-
- // ------------------- 編集画面保存時の処理 -------------------
- kintone.events.on(['app.record.create.submit', 'app.record.edit.submit', 'app.record.index.edit.submit'], function (event) {
- event.record[FIELD_CODE]['value'] = getUniqueKey(event.record);
- return event;
- });
-
- function getUniqueKey(record) {
- return (record['出席番号']['value'] + '_' + record['学年']['value'] + '_' + record['クラス']['value'] + '_' + record['名前']['value']).substring(0, 64);
- }
-
-})();
\ No newline at end of file
diff --git a/src/園児台帳/main.mobile.js b/src/園児台帳/main.mobile.js
deleted file mode 100644
index 2d0eaff..0000000
--- a/src/園児台帳/main.mobile.js
+++ /dev/null
@@ -1,41 +0,0 @@
-
-(function () {
- "use strict";
- const FIELD_CODE = "ユニークキー";
-
- // ------------------- 詳細/印刷/編集画面表示時の処理 -------------------
- kintone.events.on(['mobile.app.record.detail.show'], function (event) {
- hideField(FIELD_CODE);
- return event;
- });
-
- // ------------------- 編集画面表示時の処理 -------------------
- kintone.events.on(['mobile.app.record.edit.show', 'mobile.app.record.create.show'], function (event) {
- const targetFieldEl = kintone.mobile.app.record.getSpaceElement("before-unique-key").nextSibling;
- targetFieldEl.querySelector('.control-constraints-gaia').style.display = 'none';
-
- event.record[FIELD_CODE]['value'] = "<自動計算:出席番号+学年+クラス+名前>";
- disableField(event.record, FIELD_CODE);
- return event;
- });
-
-
- function hideField(fieldCode) {
- kintone.mobile.app.record.setFieldShown(fieldCode, false);
- }
-
- function disableField(record, fieldCode) {
- record[fieldCode]['disabled'] = true;
- }
-
- // ------------------- 編集画面保存時の処理 -------------------
- kintone.events.on(['mobile.app.record.create.submit', 'mobile.app.record.edit.submit'], function (event) {
- event.record[FIELD_CODE]['value'] = getUniqueKey(event.record);
- return event;
- });
-
- function getUniqueKey(record) {
- return (record['出席番号']['value'] + '_' + record['学年']['value'] + '_' + record['クラス']['value'] + '_' + record['名前']['value']).substring(0, 64);
- }
-
-})();
\ No newline at end of file
diff --git a/src/学年別保育計画/env.js b/src/学年別保育計画/env.js
deleted file mode 100644
index 0d6517b..0000000
--- a/src/学年別保育計画/env.js
+++ /dev/null
@@ -1,6 +0,0 @@
-const statusFieldMap = {
- '指導教諭確認中': '担任',
- '主幹確認中': '指導',
- '園長確認中': '主幹',
- '完了': '園長'
-}
\ No newline at end of file
diff --git a/src/学年別保育計画/main.mobile.js b/src/学年別保育計画/main.mobile.js
deleted file mode 100644
index 4932585..0000000
--- a/src/学年別保育計画/main.mobile.js
+++ /dev/null
@@ -1,12 +0,0 @@
-(function () {
- "use strict";
-
- kintone.events.on("mobile.app.record.detail.process.proceed", (event) => {
- const field = statusFieldMap[event.nextStatus.value];
- if (field) {
- event.record[field].value = kintone.getLoginUser().name;
- }
- return event;
- });
-
-})();
\ No newline at end of file
diff --git a/src/学期反省・評価/env.js b/src/学期反省・評価/env.js
deleted file mode 100644
index 32fcc62..0000000
--- a/src/学期反省・評価/env.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const statusFieldMap = {
- '主幹確認中(1学期)': '指導1',
- '園長確認中(1学期)': '主幹1',
- '完了(1学期)': '園長1',
- '担任作成中(2学期)': '園長1',
- '主幹確認中(2学期)': '指導2',
- '園長確認中(2学期)': '主幹2',
- '完了(2学期)': '園長2',
- '担任作成中(3学期)': '園長2',
- '主幹確認中(3学期)': '指導3',
- '園長確認中(3学期)': '主幹3',
- '完了(3学期)': '園長3',
-}
\ No newline at end of file
diff --git a/src/学期反省・評価/main.mobile.js b/src/学期反省・評価/main.mobile.js
deleted file mode 100644
index 4932585..0000000
--- a/src/学期反省・評価/main.mobile.js
+++ /dev/null
@@ -1,12 +0,0 @@
-(function () {
- "use strict";
-
- kintone.events.on("mobile.app.record.detail.process.proceed", (event) => {
- const field = statusFieldMap[event.nextStatus.value];
- if (field) {
- event.record[field].value = kintone.getLoginUser().name;
- }
- return event;
- });
-
-})();
\ No newline at end of file
diff --git a/src/園児別出欠簿入力/BatchCreateHandler.js b/src/1.園児別出欠簿入力/BatchCreateHandler.js
similarity index 100%
rename from src/園児別出欠簿入力/BatchCreateHandler.js
rename to src/1.園児別出欠簿入力/BatchCreateHandler.js
diff --git a/src/園児別出欠簿入力/ExtractHandler.js b/src/1.園児別出欠簿入力/ExtractHandler.js
similarity index 90%
rename from src/園児別出欠簿入力/ExtractHandler.js
rename to src/1.園児別出欠簿入力/ExtractHandler.js
index a990abc..1184be6 100644
--- a/src/園児別出欠簿入力/ExtractHandler.js
+++ b/src/1.園児別出欠簿入力/ExtractHandler.js
@@ -108,9 +108,13 @@ class ExtractHandler {
try {
const data = await api.record.getAllRecordsWithId({
app: env["保育・教育日数マスタ"].appId,
- fields: ['教育日数' + month, '保育日数' + month],
+ fields: ['教育日数' + month, '保育日数' + month, '休日_' + month + '月'],
condition: `年度 = "${year}"`
});
+ if (!data || !data[0]) {
+ showError(true, '保育・教育日数マスタのデータが存在しません。');
+ return;
+ }
return data && data[0];
} catch (e) {
showError(true, '保育・教育日数マスタのデータ読み取りエラー\n - ' + e);
@@ -124,16 +128,23 @@ class ExtractHandler {
fields: ['担任'],
condition: `学年 in ("${term}")`
});
- return data && data[0] && data[0]['担任']?.value.map((x)=>x.name).join('、') || '';
+ return data && data[0] && data[0]['担任']?.value.map((x) => x.name).join('、') || '';
} catch (e) {
showError(true, '担任マスタのデータ読み取りエラー\n - ' + e);
}
}
+ toHolidaySet = (str) => {
+ if (!str) {
+ return new Set();
+ }
+ return new Set(str.split(','))
+ }
+
writeExcel = ({ records, recordMap, childMaster, dayMaster, termTeacher }, term, { era, year, westernYear, month }) => {
const teachDays = Number(dayMaster['教育日数' + month].value);
const careDays = Number(dayMaster['保育日数' + month].value);
-
+ const holidaySet = this.toHolidaySet(dayMaster['休日_' + month + '月'].value);
return async (api, worksheet) => {
const baseCells = findCellsInfo(worksheet, ['13', '16', '19', '25', '(担 任)', '1', '番号']);
@@ -216,6 +227,7 @@ class ExtractHandler {
'出席停止': 0,
'病欠': 0,
'自欠': 0,
+ '休日欠席': 0
}
// 日
recordWrapper.list.forEach((record, i) => {
@@ -224,10 +236,18 @@ class ExtractHandler {
if (res === '出席') {
return;
}
- if (res === '出席停止' && record["出席停止理由"].value) {
- reasons.push(record["出席停止理由"].value);
+ if (res === '出席停止') {
+ if (record["出席停止理由"].value) {
+ reasons.push(record["出席停止理由"].value);
+ }
+ updateCell(row, { base, right: 2 + i }, '×');
+ return
}
- updateCell(row, { base, right: 2 + i }, res === '出席停止' ? '×' : '/');
+ // 欠席
+ if (holidaySet.has(record['登園日'].value)) {
+ sum['休日欠席']++;
+ }
+ updateCell(row, { base, right: 2 + i }, '/');
})
// 出 席
@@ -238,7 +258,7 @@ class ExtractHandler {
updateCell(row, { base, right: 36 }, sum['自欠']);
// 教育日数
// updateCell(row, { base, right: 37 }, sum['出席'] + sum['出席停止'] - sum['病欠'] - sum['自欠']);
- updateCell(row, { base, right: 37 }, teachDays - sum['病欠'] - sum['自欠']);
+ updateCell(row, { base, right: 37 }, teachDays - sum['病欠'] - sum['自欠'] + sum['休日欠席']);
// 備考
updateCell(row, { base, right: 38 }, reasons.join("\n"));
diff --git a/src/園児別出欠簿入力/Link1Handler.js b/src/1.園児別出欠簿入力/Link1Handler.js
similarity index 100%
rename from src/園児別出欠簿入力/Link1Handler.js
rename to src/1.園児別出欠簿入力/Link1Handler.js
diff --git a/src/園児別出欠簿入力/Link2Handler.js b/src/1.園児別出欠簿入力/Link2Handler.js
similarity index 100%
rename from src/園児別出欠簿入力/Link2Handler.js
rename to src/1.園児別出欠簿入力/Link2Handler.js
diff --git a/src/園児別出欠簿入力/detail-page-desktop.js b/src/1.園児別出欠簿入力/detail-page-desktop.js
similarity index 59%
rename from src/園児別出欠簿入力/detail-page-desktop.js
rename to src/1.園児別出欠簿入力/detail-page-desktop.js
index 15755db..4a1426a 100644
--- a/src/園児別出欠簿入力/detail-page-desktop.js
+++ b/src/1.園児別出欠簿入力/detail-page-desktop.js
@@ -7,8 +7,8 @@
// 「登園/帰園」ボタン
const area = kintone.app.record.getSpaceElement('header-clocking-btn-area');
- const clockIn = createBtn('clock-in', '登園', dateToFieldInDetailIn('登園時刻'));
- const clockOut = createBtn('clock-out', '帰園', dateToFieldInDetail('帰園時刻'));
+ const clockIn = createBtn('clock-in', '登園', dateToFieldInDetailIn());
+ const clockOut = createBtn('clock-out', '帰園', dateToFieldInDetailOut());
area.appendChild(clockIn);
area.appendChild(clockOut);
@@ -26,14 +26,18 @@
return grade === "0歳児" || grade === "1歳児";
}
- function dateToFieldInDetail(fieldCode) {
+ //PVC追加
+ function dateToFieldInDetailIn() {
return async function (e) {
await new KintoneRestAPIClient().record.updateRecord({
app: kintone.app.getId(),
id: kintone.app.record.getId(),
record: {
- [fieldCode]: {
+ '登園時刻': {
value: getCurrentTime()
+ },
+ "出欠": {
+ value: "出席"
}
}
});
@@ -41,18 +45,14 @@
}
}
- //PVC追加
- function dateToFieldInDetailIn(fieldCode) {
+ function dateToFieldInDetailOut() {
return async function (e) {
await new KintoneRestAPIClient().record.updateRecord({
app: kintone.app.getId(),
id: kintone.app.record.getId(),
record: {
- [fieldCode]: {
+ '帰園時刻': {
value: getCurrentTime()
- },
- 出欠: {
- value: "出席"
}
}
});
@@ -75,9 +75,9 @@
// ------------------- 編集画面表示時の処理 -------------------
kintone.events.on(['app.record.create.show', 'app.record.edit.show'], function (event) {
// 「登園/帰園」ボタン
- const clockIn = createBtn('clock-in', '登園', dateToFieldInEditIn('登園時刻','出欠'));
+ const clockIn = createBtn('clock-in', '登園', dateToFieldInEditIn());
kintone.app.record.getSpaceElement('clock-in-btn-area').appendChild(clockIn);
- const clockOut = createBtn('clock-out', '帰園', dateToFieldInEdit('帰園時刻'));
+ const clockOut = createBtn('clock-out', '帰園', dateToFieldInEditOut());
kintone.app.record.getSpaceElement('clock-out-btn-area').appendChild(clockOut);
// 「伝達事項」
@@ -87,20 +87,46 @@
return event;
});
- function dateToFieldInEdit(fieldCode) {
+ // -------------------「園での様子_入力者」の処理 -------------------
+ const _DATA_HOLDER_MAP = {}
+
+ // 「園での様子_伝達事項」はテキストエリア(複数行入力欄)であり、app.record.edit.changeイベントをサポートしていません
+ // したがって、データを事前に保存しておき、保存(submit)時のタイミングで更新を行います。
+ kintone.events.on(['app.record.index.edit.show', 'app.record.create.show', 'app.record.edit.show'], function (event) {
+ _DATA_HOLDER_MAP['isEditorChanged'] = false;
+ _DATA_HOLDER_MAP['prevSituationValue'] = event.record['園での様子_伝達事項']['value'] || '';
+ return event;
+ });
+
+ kintone.events.on(['app.record.create.change.園での様子_入力者', 'app.record.edit.change.園での様子_入力者', 'app.record.index.edit.change.園での様子_入力者'], function(event) {
+ _DATA_HOLDER_MAP['isEditorChanged'] = true;
+ return event;
+ });
+
+ kintone.events.on(['app.record.create.submit', 'app.record.edit.submit', 'app.record.index.edit.submit'], function (event) {
+ const current = event.record['園での様子_伝達事項']['value'] || '';
+
+ if (_DATA_HOLDER_MAP['prevSituationValue'] != current && !_DATA_HOLDER_MAP['isEditorChanged']) {
+ event.record['園での様子_入力者']['value'] = [kintone.getLoginUser()];
+ }
+
+ return event;
+ });
+
+ //PVC追加
+ function dateToFieldInEditIn() {
return function (e) {
var record = kintone.app.record.get();
- record['record'][fieldCode]['value'] = getCurrentTime();
+ record['record']['登園時刻']['value'] = getCurrentTime();
+ record['record']['出欠']['value'] = "出席";
kintone.app.record.set(record);
}
}
- //PVC追加
- function dateToFieldInEditIn(fieldCode1,fieldCode2) {
+ function dateToFieldInEditOut() {
return function (e) {
var record = kintone.app.record.get();
- record['record'][fieldCode1]['value'] = getCurrentTime();
- record['record'][fieldCode2]['value'] = "出席";
+ record['record']['帰園時刻']['value'] = getCurrentTime();
kintone.app.record.set(record);
}
}
diff --git a/src/0,1歳用日誌/FileSaver.min.js b/src/1.園児別出欠簿入力/lib/FileSaver.min.js
similarity index 100%
rename from src/0,1歳用日誌/FileSaver.min.js
rename to src/1.園児別出欠簿入力/lib/FileSaver.min.js
diff --git a/src/0,1歳用日誌/KintoneRestAPIClient.min.js b/src/1.園児別出欠簿入力/lib/KintoneRestAPIClient.min.js
similarity index 100%
rename from src/0,1歳用日誌/KintoneRestAPIClient.min.js
rename to src/1.園児別出欠簿入力/lib/KintoneRestAPIClient.min.js
diff --git a/src/0,1歳用日誌/exceljs.min.js b/src/1.園児別出欠簿入力/lib/exceljs.min.js
similarity index 100%
rename from src/0,1歳用日誌/exceljs.min.js
rename to src/1.園児別出欠簿入力/lib/exceljs.min.js
diff --git a/src/0,1歳用日誌/kuc.min.js b/src/1.園児別出欠簿入力/lib/kuc.min.js
similarity index 100%
rename from src/0,1歳用日誌/kuc.min.js
rename to src/1.園児別出欠簿入力/lib/kuc.min.js
diff --git a/src/0,1歳用日誌/pvc.lib.exceljsUtil.js b/src/1.園児別出欠簿入力/lib/pvc.lib.exceljsUtil.js
similarity index 100%
rename from src/0,1歳用日誌/pvc.lib.exceljsUtil.js
rename to src/1.園児別出欠簿入力/lib/pvc.lib.exceljsUtil.js
diff --git a/src/園児別出欠簿入力/main.js b/src/1.園児別出欠簿入力/pvc.main.js
similarity index 91%
rename from src/園児別出欠簿入力/main.js
rename to src/1.園児別出欠簿入力/pvc.main.js
index 4de89d2..31e32ee 100644
--- a/src/園児別出欠簿入力/main.js
+++ b/src/1.園児別出欠簿入力/pvc.main.js
@@ -2,8 +2,6 @@
"use strict";
const APP_ENV = env["園児別出欠簿入力"];
- addApproveFlowAction();
-
kintone.events.on("app.record.index.show", (event) => {
const headerSpace = getHeaderSpace('single-label-line');
diff --git a/src/学期反省・評価/main.js b/src/1.園児別出欠簿入力/pvc.processAutoUpdate.js
similarity index 55%
rename from src/学期反省・評価/main.js
rename to src/1.園児別出欠簿入力/pvc.processAutoUpdate.js
index daf0b8b..ced813b 100644
--- a/src/学期反省・評価/main.js
+++ b/src/1.園児別出欠簿入力/pvc.processAutoUpdate.js
@@ -1,6 +1,15 @@
(function () {
"use strict";
+ const statusFieldMap = {
+ '指導教諭確認中': '担任',
+ '主幹確認中': '指導',
+ '園長確認中': '主幹',
+ '完了': '園長'
+ }
+
+ window._StatusFieldMap = statusFieldMap
+
kintone.events.on("app.record.detail.process.proceed", (event) => {
const field = statusFieldMap[event.nextStatus.value];
if (field) {
diff --git a/src/2歳以上日誌/KintoneRestAPIClient.min.js b/src/10.個別支援計画/KintoneRestAPIClient.min.js
similarity index 100%
rename from src/2歳以上日誌/KintoneRestAPIClient.min.js
rename to src/10.個別支援計画/KintoneRestAPIClient.min.js
diff --git a/src/2歳以上日誌/kuc.min.js b/src/10.個別支援計画/kuc.min.js
similarity index 100%
rename from src/2歳以上日誌/kuc.min.js
rename to src/10.個別支援計画/kuc.min.js
diff --git a/src/10.個別支援計画/pvc.main.js b/src/10.個別支援計画/pvc.main.js
new file mode 100644
index 0000000..15972c0
--- /dev/null
+++ b/src/10.個別支援計画/pvc.main.js
@@ -0,0 +1,23 @@
+(function () {
+ "use strict";
+
+ kintone.events.on(["app.record.create.show","app.record.edit.show"], function(event) {
+ var record = event.record;
+ record.担当_文字列.value = record.担当.value.map(function(user) {return user.name}).join(",");
+ record.コーディネーター_文字列.value = record.コーディネーター.value.map(function(user) {return user.name}).join(",");
+ return event;
+ });
+
+ kintone.events.on(["app.record.create.change.担当","app.record.edit.change.担当", "app.record.index.edit.change.担当"], function(event) {
+ var record = event.record;
+ record.担当_文字列.value = record.担当.value.map(function(user) {return user.name}).join(",");
+ return event;
+ });
+
+ kintone.events.on(["app.record.create.change.コーディネーター","app.record.edit.change.コーディネーター", "app.record.index.edit.change.コーディネーター"], function(event) {
+ var record = event.record;
+ record.コーディネーター_文字列.value = record.コーディネーター.value.map(function(user) {return user.name}).join(",");
+ return event;
+ });
+
+})();
\ No newline at end of file
diff --git a/src/10.個別支援計画/pvc.processAutoUpdate.js b/src/10.個別支援計画/pvc.processAutoUpdate.js
new file mode 100644
index 0000000..26fd666
--- /dev/null
+++ b/src/10.個別支援計画/pvc.processAutoUpdate.js
@@ -0,0 +1,23 @@
+(function () {
+ "use strict";
+
+ const statusFieldMap = {
+ "園長確認中(1学期)": "指導1",
+ "担任作成中(2学期)": "園長1",
+ "園長確認中(2学期)": "指導2",
+ "担任作成中(3学期)": "園長2",
+ "園長確認中(3学期)": "指導3",
+ "完了": "園長3"
+ }
+
+ window._StatusFieldMap = statusFieldMap
+
+ kintone.events.on("app.record.detail.process.proceed", (event) => {
+ const field = statusFieldMap[event.nextStatus.value];
+ if (field) {
+ event.record[field].value = kintone.getLoginUser().name;
+ }
+ return event;
+ });
+
+})();
\ No newline at end of file
diff --git a/src/10.個別支援計画/pvc.processBatchApproval.js b/src/10.個別支援計画/pvc.processBatchApproval.js
new file mode 100644
index 0000000..a70a26e
--- /dev/null
+++ b/src/10.個別支援計画/pvc.processBatchApproval.js
@@ -0,0 +1,54 @@
+(function () {
+ "use strict";
+
+ // マイビューのID
+ const mineView = 13353711;
+ // 分類フィールドのプレースホルダー
+ const classifyField = "${classify}";
+
+ // ボタン分類マッピング
+ const btnClassifyMap = {
+ "0歳児": "(0~2歳)",
+ "1歳児": "(0~2歳)",
+ "2歳児": "(0~2歳)",
+ "3歳児": "(3~5歳)",
+ "4歳児": "(3~5歳)",
+ "5歳児": "(3~5歳)",
+ }
+
+ // アクションマッピング
+ const actionMap = {
+ "担任作成中": `指導教諭確認依頼${classifyField}`,
+ "指導教諭確認中": `承認する`,
+ "園長確認中": `承認する${classifyField}`
+ }
+
+ /**
+ * ステータスから接頭辞を取得する
+ * @param {string} status - ステータス文字列
+ */
+ const getStatusPrefix = (status) => {
+ return status.split("(")[0];
+ };
+
+ // kintoneイベントの登録
+ kintone.events.on("app.record.index.show", (event) => {
+ // 特定のビューの場合のみ処理を実行
+ if (event.viewId === mineView) {
+ // BatchApprovalHandlerクラスのインスタンスを作成
+ const batchApproval = new BatchApprovalHandler(
+ mineView,
+ classifyField,
+ btnClassifyMap,
+ actionMap,
+ getStatusPrefix,
+ _StatusFieldMap
+ );
+
+ // 一括承認ボタンを作成
+ batchApproval.createApproveBtn();
+ }
+ return event;
+ });
+
+})();
diff --git a/src/2歳以上日誌/FileSaver.min.js b/src/11.0,1歳日誌出力用/FileSaver.min.js
similarity index 100%
rename from src/2歳以上日誌/FileSaver.min.js
rename to src/11.0,1歳日誌出力用/FileSaver.min.js
diff --git a/src/個別配慮/KintoneRestAPIClient.min.js b/src/11.0,1歳日誌出力用/KintoneRestAPIClient.min.js
similarity index 100%
rename from src/個別配慮/KintoneRestAPIClient.min.js
rename to src/11.0,1歳日誌出力用/KintoneRestAPIClient.min.js
diff --git a/src/2歳以上日誌/exceljs.min.js b/src/11.0,1歳日誌出力用/exceljs.min.js
similarity index 100%
rename from src/2歳以上日誌/exceljs.min.js
rename to src/11.0,1歳日誌出力用/exceljs.min.js
diff --git a/src/個別配慮/kuc.min.js b/src/11.0,1歳日誌出力用/kuc.min.js
similarity index 100%
rename from src/個別配慮/kuc.min.js
rename to src/11.0,1歳日誌出力用/kuc.min.js
diff --git a/src/2歳以上日誌/pvc.lib.exceljsUtil.js b/src/11.0,1歳日誌出力用/pvc.lib.exceljsUtil.js
similarity index 100%
rename from src/2歳以上日誌/pvc.lib.exceljsUtil.js
rename to src/11.0,1歳日誌出力用/pvc.lib.exceljsUtil.js
diff --git a/src/0,1歳用日誌/main.js b/src/11.0,1歳日誌出力用/pvc.main.js
similarity index 96%
rename from src/0,1歳用日誌/main.js
rename to src/11.0,1歳日誌出力用/pvc.main.js
index c3245ce..4d1ad77 100644
--- a/src/0,1歳用日誌/main.js
+++ b/src/11.0,1歳日誌出力用/pvc.main.js
@@ -2,8 +2,6 @@
"use strict";
const APP_ENV = env["0,1歳日誌出力用"];
- addApproveFlowAction();
-
kintone.events.on("app.record.detail.show", (event) => {
const headerSpace = getHeaderSpace('', true);
diff --git a/src/保育計画月案/main.js b/src/11.0,1歳日誌出力用/pvc.processAutoUpdate.js
similarity index 58%
rename from src/保育計画月案/main.js
rename to src/11.0,1歳日誌出力用/pvc.processAutoUpdate.js
index daf0b8b..319017d 100644
--- a/src/保育計画月案/main.js
+++ b/src/11.0,1歳日誌出力用/pvc.processAutoUpdate.js
@@ -1,6 +1,14 @@
(function () {
"use strict";
+ const statusFieldMap = {
+ '指導教諭確認中(0~2歳)': '担任',
+ '園長確認中': '指導',
+ '完了': '園長'
+ }
+
+ window._StatusFieldMap = statusFieldMap
+
kintone.events.on("app.record.detail.process.proceed", (event) => {
const field = statusFieldMap[event.nextStatus.value];
if (field) {
diff --git a/src/個別配慮/FileSaver.min.js b/src/12.2歳以上日誌出力用/FileSaver.min.js
similarity index 100%
rename from src/個別配慮/FileSaver.min.js
rename to src/12.2歳以上日誌出力用/FileSaver.min.js
diff --git a/src/園児別出欠簿入力/lib/KintoneRestAPIClient.min.js b/src/12.2歳以上日誌出力用/KintoneRestAPIClient.min.js
similarity index 100%
rename from src/園児別出欠簿入力/lib/KintoneRestAPIClient.min.js
rename to src/12.2歳以上日誌出力用/KintoneRestAPIClient.min.js
diff --git a/src/個別配慮/exceljs.min.js b/src/12.2歳以上日誌出力用/exceljs.min.js
similarity index 100%
rename from src/個別配慮/exceljs.min.js
rename to src/12.2歳以上日誌出力用/exceljs.min.js
diff --git a/src/園児別出欠簿入力/lib/kuc.min.js b/src/12.2歳以上日誌出力用/kuc.min.js
similarity index 100%
rename from src/園児別出欠簿入力/lib/kuc.min.js
rename to src/12.2歳以上日誌出力用/kuc.min.js
diff --git a/src/個別配慮/pvc.lib.exceljsUtil.js b/src/12.2歳以上日誌出力用/pvc.lib.exceljsUtil.js
similarity index 100%
rename from src/個別配慮/pvc.lib.exceljsUtil.js
rename to src/12.2歳以上日誌出力用/pvc.lib.exceljsUtil.js
diff --git a/src/2歳以上日誌/main.js b/src/12.2歳以上日誌出力用/pvc.main.js
similarity index 96%
rename from src/2歳以上日誌/main.js
rename to src/12.2歳以上日誌出力用/pvc.main.js
index af8c0c9..fa8a1d4 100644
--- a/src/2歳以上日誌/main.js
+++ b/src/12.2歳以上日誌出力用/pvc.main.js
@@ -2,8 +2,6 @@
"use strict";
const APP_ENV = env["2歳以上日誌出力用"];
- addApproveFlowAction();
-
kintone.events.on("app.record.detail.show", (event) => {
const headerSpace = getHeaderSpace('', true);
diff --git a/src/12.2歳以上日誌出力用/pvc.processAutoUpdate.js b/src/12.2歳以上日誌出力用/pvc.processAutoUpdate.js
new file mode 100644
index 0000000..cd8e0c7
--- /dev/null
+++ b/src/12.2歳以上日誌出力用/pvc.processAutoUpdate.js
@@ -0,0 +1,21 @@
+(function () {
+ "use strict";
+
+ const statusFieldMap = {
+ '指導教諭確認中(0~2歳)': '担任',
+ '指導教諭確認中(3~5歳)': '担任',
+ '園長確認中': '指導',
+ '完了': '園長'
+ }
+
+ window._StatusFieldMap = statusFieldMap
+
+ kintone.events.on("app.record.detail.process.proceed", (event) => {
+ const field = statusFieldMap[event.nextStatus.value];
+ if (field) {
+ event.record[field].value = kintone.getLoginUser().name;
+ }
+ return event;
+ });
+
+})();
\ No newline at end of file
diff --git a/src/2.保育計画 月案(0歳児用)/KintoneRestAPIClient.min.js b/src/2.保育計画 月案(0歳児用)/KintoneRestAPIClient.min.js
new file mode 100644
index 0000000..dc9c93d
--- /dev/null
+++ b/src/2.保育計画 月案(0歳児用)/KintoneRestAPIClient.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.KintoneRestAPIClient=t():e.KintoneRestAPIClient=t()}(window,(function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=74)}([function(e,t,r){(function(t){var r=function(e){return e&&e.Math==Math&&e};e.exports=r("object"==typeof globalThis&&globalThis)||r("object"==typeof window&&window)||r("object"==typeof self&&self)||r("object"==typeof t&&t)||Function("return this")()}).call(this,r(40))},function(e,t,r){var n=r(0),o=r(41),i=r(4),u=r(45),s=r(46),a=r(78),c=o("wks"),f=n.Symbol,l=a?f:f&&f.withoutSetter||u;e.exports=function(e){return i(c,e)||(s&&i(f,e)?c[e]=f[e]:c[e]=l("Symbol."+e)),c[e]}},function(e,t,r){"use strict";var n=r(65),o=Object.prototype.toString;function i(e){return"[object Array]"===o.call(e)}function u(e){return void 0===e}function s(e){return null!==e&&"object"==typeof e}function a(e){return"[object Function]"===o.call(e)}function c(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),i(e))for(var r=0,n=e.length;rh;h++)if((y=f?g(n(b=e[h])[0],b[1]):g(e[h]))&&y instanceof c)return y;return new c(!1)}p=d.call(e)}for(m=p.next;!(b=m.call(p)).done;)if("object"==typeof(y=a(p,g,b.value,f))&&y&&y instanceof c)return y;return new c(!1)}).stop=function(e){return new c(!0,e)}},function(e,t){e.exports=function(e){try{return{error:!1,value:e()}}catch(e){return{error:!0,value:e}}}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.injectPlatformDeps=t.platformDeps=void 0,t.platformDeps={readFileFromPath:function(){throw new Error("not implemented")},getRequestToken:function(){throw new Error("not implemented")},buildPlatformDependentConfig:function(){throw new Error("not implemented")},buildHeaders:function(){throw new Error("not implemented")}},t.injectPlatformDeps=function(e){t.platformDeps.readFileFromPath=e.readFileFromPath,t.platformDeps.getRequestToken=e.getRequestToken,t.platformDeps.buildPlatformDependentConfig=e.buildPlatformDependentConfig,t.platformDeps.buildHeaders=e.buildHeaders}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.buildPath=void 0,t.buildPath=function(e){var t=e.endpointName,r=e.guestSpaceId;return"/k"+(void 0!==r?"/guest/"+r:"")+"/v1"+(e.preview?"/preview":"")+"/"+t+".json"}},function(e,t,r){var n={};n[r(1)("toStringTag")]="z",e.exports="[object z]"===String(n)},function(e,t,r){var n=r(0),o=r(5);e.exports=function(e,t){try{o(n,e,t)}catch(r){n[e]=t}return t}},function(e,t,r){var n=r(0),o=r(9),i=n.document,u=o(i)&&o(i.createElement);e.exports=function(e){return u?i.createElement(e):{}}},function(e,t,r){var n=r(42),o=Function.toString;"function"!=typeof n.inspectSource&&(n.inspectSource=function(e){return o.call(e)}),e.exports=n.inspectSource},function(e,t,r){var n=r(41),o=r(45),i=n("keys");e.exports=function(e){return i[e]||(i[e]=o(e))}},function(e,t){e.exports={}},function(e,t){var r=Math.ceil,n=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?n:r)(e)}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,r){var n=r(7),o=r(83),i=r(19),u=r(20),s=r(44),a=r(4),c=r(43),f=Object.getOwnPropertyDescriptor;t.f=n?f:function(e,t){if(e=u(e),t=s(t,!0),c)try{return f(e,t)}catch(e){}if(a(e,t))return i(!o.f.call(e,t),e[t])}},function(e,t){e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(e,t,r){var n=r(4),o=r(92),i=r(29),u=r(93),s=i("IE_PROTO"),a=Object.prototype;e.exports=u?Object.getPrototypeOf:function(e){return e=o(e),n(e,s)?e[s]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?a:null}},function(e,t,r){var n,o=r(3),i=r(94),u=r(34),s=r(30),a=r(54),c=r(27),f=r(29),l=f("IE_PROTO"),p=function(){},d=function(e){return"