飲食店のアルバイトが紙に書いたシフト希望表を読み取り、日ごと・時間帯ごとの希望の一覧にそろえて、未提出と書き漏れと18歳未満の深夜の希望を拾ってからシフト作成に渡す
アルバイトが紙に書いたシフト希望表を写真で読み取り、日ごとの出勤の可否と入れる時刻をそろえて、店の希望の一覧に入れます。あわせて、未提出の人、書き漏れの日、18歳未満のスタッフの午後10時以降の希望を拾い、店長に渡します。
- 生成AI
- ChatGPT/Claude
- AIサービス
- Azure AI/Google Document AI
- 連携・自動化
- Google Apps Script/Python
- 対象業界
- 宿泊/小売/飲食
- 対象部門
- 人事
- 対象業務
- データ入力・転記/内容確認・チェック
- 主な課題
- 人手が足りない/入力作業が多い/確認ミスが多い
- AIで行う処理
- 読み取り(OCR)
- 主な効果
- 入力漏れ削減/対応スピード向上/工数削減
- 導入難易度
- ★★☆☆☆
- 実装レベル
- 本格構成
- 費用感
- API連携(中)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 締め切りの翌日、店長が休憩室の箱から希望表を集める
- スタッフの名簿と見比べ、出していない人を探して声をかける
- 希望表を1枚ずつ見て、表計算のシフト表の希望の欄に日ごとに打ち直す
- 空欄や読めない字の日に付箋を貼り、次に会ったときに本人に聞く
- 高校生の希望で、22時を過ぎる時刻が書かれているものを直す
- 打ち直した希望をもとに、シフトを組む
- 人アルバイトがこれまでどおり紙の希望表に書き、箱に戻す
- 人締め切りの日の閉店時に、店長かシフトリーダーが箱の希望表を店のタブレットで1枚ずつ撮る
- 自動写真の保存をきっかけにプログラムが動き、店と対象の半月を写真の名前から決める
- 自動OCRが希望表を表として読み、日付ごとのセルの文字と読み取りの信頼度を返す
- 自動生成AIがスタッフの名前と日ごとの可否・時刻を、決まった形にそろえる
- 自動名簿と突き合わせて未提出の人を挙げ、書き漏れの日と18歳未満の深夜の希望を規則で拾う
- 自動問題の無い希望はシフト表の希望の欄に入れ、問題のあるものは確認の一覧に出す
- 人店長が確認の一覧だけを見て、本人に聞くものを決める。シフトは店長が組む
各工程の詳しい説明を読む
- 締め切りの翌日、店長が休憩室の箱から希望表を集める
- スタッフの名簿と見比べ、出していない人を探して声をかける
- 希望表を1枚ずつ見て、表計算のシフト表の希望の欄に日ごとに打ち直す
- 空欄や読めない字の日に付箋を貼り、次に会ったときに本人に聞く
- 高校生の希望で、22時を過ぎる時刻が書かれているものを直す
- 打ち直した希望をもとに、シフトを組む
(a)打ち直しが店長の休みに回る。 3番目は、1枚に半月分の日付が並ぶ希望表を、日ごとに打ち直す作業です。営業中にはできないので、閉店後か休みの日にやることになります。 店長の時間が、シフトを考えることではなく打ち直しに消えます。
(b)書き漏れの日に気づくのがシフトを作る時になる。 4番目の付箋は、打ち直しのときに貼ります。シフトを組み始めてから「この日はどっちだったか」と止まり、本人に聞くまで決まりません。 本人の次の出勤が数日後なら、シフトの公開がそのぶん遅れます。
(c)書き方がそろっていない。 ある人は「○」と時刻、ある人は「17-L」、ある人は「OK」、ある人は「F」(フリー)と書きます。「L」がラストか17時台の何かかは、店長がその人の癖を知っていないと分かりません。 新しい店長に引き継ぐと、読み違いが出ます。
(d)高校生の深夜の希望を見落とす。 5番目は、店長がスタッフの年齢を覚えていることが前提です。名簿を見ればわかることでも、打ち直しの最中に名簿を開き直すことはまずありません。
- 【人】 アルバイトがこれまでどおり紙の希望表に書き、箱に戻す
- 【人】 締め切りの日の閉店時に、店長かシフトリーダーが箱の希望表を店のタブレットで1枚ずつ撮る
- 【自動】 写真の保存をきっかけにプログラムが動き、店と対象の半月を写真の名前から決める
- 【自動】 OCRが希望表を表として読み、日付ごとのセルの文字と読み取りの信頼度を返す
- 【自動】 生成AIがスタッフの名前と日ごとの可否・時刻を、決まった形にそろえる
- 【自動】 名簿と突き合わせて未提出の人を挙げ、書き漏れの日と18歳未満の深夜の希望を規則で拾う
- 【自動】 問題の無い希望はシフト表の希望の欄に入れ、問題のあるものは確認の一覧に出す
- 【人】 店長が確認の一覧だけを見て、本人に聞くものを決める。シフトは店長が組む
8番目が、この設計の分かれ目です。人が見るのは全件ではありません。 書き方がそろっていて、空欄も読めない欄も無い希望表は、シフト表に入るだけです。店長が見るのは、確認の一覧に出た日と、その希望表の写真だけです。
2番目を締め切りの日の閉店時にしているのは、(b)の確認を早めるためです。 翌朝には未提出の人と書き漏れの日の一覧ができているので、その日に出勤するスタッフに、その場で聞けます。 シフトを組み始める前に、聞くことが片づきます。
02今回想定するシステム構成
紙のシフト希望表(1人1枚、半月分の日付ごとの行) │ 締め切りの日の閉店時に、店のタブレットで1枚ずつ撮影 ▼【トリガー】共有フォルダへの写真の保存 Python ── 写真の名前から店と対象の半月を決める、形式と向きの確認 ▼ Google Document AI(Form Parser) │ 表のセル(日付の行と、可否・開始・終了・備考の列)、名前の欄、信頼度 ▼ Claude API ── 日ごとの可否と時刻をそろえる │ available/unavailable/blank/unreadable、開始と終了の時刻 ▼ Python ── 名簿と突き合わせて未提出の人を挙げる │ 書き漏れの日、18歳未満の22時以降の希望を規則で拾う ▼ シフト表の希望の欄(問題の無い日を追加) ▼ 確認の一覧 ──▶【店長が写真と見比べ、本人に聞くものを決める】
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| OCR | Google Document AI(Form Parser) | Azure AI Document Intelligence |
| 生成AI | Claude API(日ごとの可否と時刻のそろえ) | OpenAI API |
| 連携 | Python(写真の受け取り、名簿との照合、規則の判定、シフト表への書き出し) | Google Apps Script |
| 保管 | 共有のスプレッドシート(シフト表の希望の欄と確認の一覧) | シフト管理のシステム |
シフト表とスタッフの名簿は、新しく足すものではありません。 足すのは、希望表を撮る手順と、写真を読んで希望の欄に入れる小さなプログラムです。最初の準備は、希望表の様式を作り直すことです(第7章の前処理)。
生成AIの代替候補から Gemini API を外しているのは、意図してのことです。 Gemini API の利用規約は、API の利用者が18歳以上であることを求め、18歳未満に向けた、または18歳未満がアクセスしうるサービスでの利用を認めていません。 この構成を使うのは店長ですが、高校生のスタッフの情報を扱うので、念のため候補から外しています。
土台は Document AI の Form Parser です。 公式のプロセッサ一覧では、OCRのテキストに加えてキーと値のペア、チェックボックス、表を抽出するとされ、言語の一覧で日本語(ja)は手書きに対応する言語として示されています。希望表は日付ごとの行が並んだ表なので、1行が1日の希望として読めることが、この題材にいちばん効きます。
表の中の印の扱いに、注意点があります。 応答の扱いの説明では、表の中にあるチェック欄は、項目と値としてではなく文字として返るとされています。また、Form Parser の表の抽出は行や列をまたぐセルの無い、ふつうの表だけを認識し、返るセルの rowSpan と colSpan は常に1です。可否は四角の印ではなく、「○」「×」の文字で書く欄にし、結合したセルを作りません。
処理する場所に日本はありません。 プロセッサ一覧の Form Parser の対応リージョンは、us、eu、asia-southeast1、asia-south1、australia-southeast1 などで、日本のリージョンは一覧にありません。 希望表にはスタッフの名前が書かれているので、国外で処理してよいかを導入前に会社として決めます(第13章)。
03どうやって実装するのか
処理の起点を決める
共有フォルダに希望表の写真が保存されたことを起点にします。 撮るのは締め切りの日の閉店時で、店長かシフトリーダーが箱の希望表を店のタブレットで1枚ずつ撮ります。Python のプログラムが5分おきにフォルダを見て、新しい写真を処理します。
写真の名前は、撮影アプリで「店番号_対象の半月」を選んでから撮る形にします。 例えば「03_2026-11前半」です。対象の半月を希望表の見出しから読ませないのは、見出しの日付を書かない人がいるからです。 半月を読み違えると、その人の希望が丸ごと別の半月に入ります。
締め切りの後に遅れて出された希望表も、同じ手順で撮ります。 同じ人の同じ半月の写真が後から来たら、後の写真で前の希望を置き換える候補として確認の一覧に出します。 黙って上書きしません。処理が終わった写真は処理済みのフォルダへ移し、移すのは成功したときだけにします。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 希望表の写真 | 1人1枚。店番号、対象の半月、撮影日時 | 共有フォルダ |
| 読み取り結果 | 表のセル(行・列)、名前の欄、全文、セルごとの信頼度 | Google Document AI |
| スタッフの名簿 | スタッフ番号、名前と呼び名、所属店、18歳未満かどうか、在籍の状態 | 名簿(スプレッドシート) |
| 店の時間帯の決まり | 営業時間、ランチとディナーの時間帯の区切り、ラストの時刻 | 店の一覧 |
| 書き方の対応表 | 「L」「ラスト」「F」「OK」「〜」などの書き方と意味 | 店長が作る一覧 |
質を決めるのは、名簿の「18歳未満かどうか」の欄です。 生年月日をそのまま渡さず、半月の初日の時点で18歳未満かどうかを名簿の側で計算した印だけを使います。誕生日を迎えて18歳になった人は、その半月から印が外れます。印の計算はプログラムの側で行い、生成AIには渡しません。
書き方の対応表は、店長が最初に作ります。 「L」は閉店時刻(ラスト)、「F」は終日入れる、のような店ごとの決まりを一覧にします。一覧に無い書き方は、意味を推し量らずに確認に回します。 第3章の(c)は、ここで解きます。
データの取得方法を決める
読み取りは、Python から Form Parser のプロセッサを呼ぶだけです。オンラインの処理は1回の要求で最大15ページで、希望表は1枚ずつ送るので上限に届きません。
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 表のセル | 各ページの tables の headerRows/bodyRows の cells | 1行を1日の希望として扱う |
| 名前の欄 | 各ページの formFields(「氏名」の項目と値) | 名簿のスタッフと突き合わせる |
| 全文 | 応答の text と各セルの textAnchor | セルの文字を取り出す |
| 信頼度 | 各要素の layout の confidence | 読めたセルと読めなかったセルの区別 |
| 位置 | layout の boundingPoly | 確認の画面で、写真の該当の行に枠を出す |
表の見出しの行で、列の意味を決めます。 headerRows のセルに「日付」「○×」「入り」「上がり」「備考」と書かれていれば、その列番号を覚えておき、bodyRows の各セルを列の意味で読みます。見出しは印刷なので、手書きの欄より読み取りが安定します。
日付の列は、印刷しておきます。 様式の日付の列に、対象の半月の日付と曜日をあらかじめ印刷すれば、手書きの日付を読む必要がなくなります。 月の前半と後半で2種類の様式を、毎月刷ります。
AIへ渡す前に整形する
- 様式を作り直す … 日付(印刷)・○×・入り・上がり・備考の5列の罫線の表にします。セルを結合した欄を作りません
- 書き方を決める … 可否は「○」か「×」、時刻は「17:00」の形、ラストは「L」と決め、用紙の上に書き方の見本を印刷します
- 名前の欄を表の外に置く … 用紙の上に「氏名」の欄を、表とは別に置きます
- 形式の確認 … 公式の対応形式は PDF、GIF、TIFF、JPEG、PNG、BMP、WebP などです。タブレットの写真は JPEG で保存し、撮影後に圧縮し直さない設定にします
- 解像度の確認 … 公式の説明では、スキャンは最低200dpiが望ましく、300dpi以上が一般に最もよいとされています。写真では、用紙の4隅が画面いっぱいに入る距離で撮ります
- 向きの確認 … 横向きの写真は回転させ、4隅が写っていない写真は撮り直しに回します
1番目と2番目を省くと、この構成は動きません。 自由に書ける白紙のカレンダーの用紙では、表として読めず、書き方もそろいません。様式を作り直すのは、AIのためというより、店長が読みやすい紙にするためでもあります。
2番目で「×」を決めるのが、第1章の「入れない」と「書いていない」を分ける土台です。 「入れない日は空けておく」決まりのままだと、空欄が「入れない」と「書き忘れ」の両方を意味します。入れない日は「×」を書く、と決めれば、空欄は書き忘れだけになります。
AIに処理させる
させるのは、表の1行を1日の希望の形にそろえることだけです。 行ごとのセルの文字を受け取り、可否・入りの時刻・上がりの時刻・備考に直して返させます。未提出の判定と、18歳未満の深夜の判定はさせません。
| 項目 | そろえ方 | 判断できないときの扱い |
|---|---|---|
| 可否 | 「○」「OK」「F」は available、「×」は unavailable | 空欄なら blank、読めなければ unreadable |
| 入りの時刻 | 「5時」「17」「17:00」を24時間表記の HH:MM に | 午前か午後か決まらなければ ambiguous |
| 上がりの時刻 | 「L」は対応表のラストの時刻に。「F」は営業の終わりに | 対応表に無い書き方は原文のまま ambiguous |
| 備考 | 「テスト期間」「19時以降なら可」などを原文で写す | - |
| 名前 | 氏名の欄の文字をそのまま写す | 読めなければ unreadable |
いちばん大事な区別は、unavailable と blank と unreadable の3つです。 unavailable は本人が入れないと書いたということ、blank は本人が何も書かなかったということ、unreadable は字はあるが確定できないということです。分ける材料は、セルに「×」の文字が検出されたか、文字が検出されなかったか、検出されたが信頼度が低いかの3つです。
時刻と可否が食い違う行も、そのまま返させます。 「×」なのに入りの時刻が書かれている、「○」なのに時刻が空、という行です。どちらかに寄せて直させず、両方を写して確認に回します。
| させないこと | 理由 |
|---|---|
| 空欄を「入れない」と扱う | 空欄は書き忘れ。店長が本人に聞く |
| 対応表に無い書き方の意味の推測 | 「L」「F」以外の略記は店ごとに違う |
| 18歳未満の深夜の希望の書き換え | 規則で拾い、店長が本人と話す |
| 備考の要約 | 「テスト期間」の一言に事情が詰まっている |
| シフトに入れるかの判断 | 店長の仕事 |
いちばん起きやすい失敗は、1行目です。 半月分のうち数日だけ空欄の希望表を渡すと、生成AIは「記入のない日は出勤不可と解釈しました」と書き添えて unavailable にすることがあります。空欄が「×」に変わった瞬間、店長は本人に聞く機会を失います。
指示内容を固定する
あなたは飲食店の店長の補助として、アルバイトが紙に書いたシフト希望表を
希望の一覧に写す立場です。OCRが返した表のセルだけを見て、
1行を1日の希望の形にそろえてください。推測で埋めないでください。
【列の意味】
date(日付・印刷)/mark(○×)/start(入り)/end(上がり)/note(備考)
【そろえ方】
- mark が「○」「OK」「F」なら status を available、「×」なら unavailable にしてください。
- start と end は 24時間表記の HH:MM にしてください。店の営業時間の内側で
午前か午後かを決め、それでも決まらなければ time_status を ambiguous に
してください。
- 「L」「ラスト」は対応表のラストの時刻に、「F」は start を開店、
end を閉店にしてください。対応表に無い書き方は、原文を raw に写し、
time_status を ambiguous にしてください。
- note は原文のまま写してください。
【厳守事項】
- 何も書かれていない行は status を blank にしてください。
空欄を unavailable にしないでください。
- 文字はあるが読めないセルは「(判読不能)」とし、status を unreadable に
してください。空欄と読めないセルを混ぜないでください。
- mark と時刻が食い違う行は、どちらかに直さず、両方を写して
conflict を true にしてください。
- 取り消し線や塗りつぶしで消された文字は読まず、消されていることを
struck に true で記録してください。
- シフトに入れるべきか、年齢による制限について書かないでください。
【店の営業時間とラストの時刻】{store_hours}
【書き方の対応表】{notation_map}
【表のセル(行ごと・列ごと、信頼度つき)】{table_cells}
【氏名の欄】{name_field}
「年齢による制限について書かない」と入れているのは、判定を規則の側に集めるためです。 生成AIに年齢の情報を渡さないので、書かせても根拠がありません。18歳未満の深夜の判定は、名簿の印と時刻からプログラムが決めます。
「消された文字は読まない」は、書き直しの多い希望表のためです。 「○」を消して「×」に書き直した欄で、消された「○」を読むと可否が逆になります。消されたことだけを記録させ、残った文字で可否を決めます。
出力形式を固定する
次の形のJSONで受け取ります。 Claude API の構造化出力(output_config.format に JSON スキーマを渡す方式)を使い、形を固定します。
{
"store_id": "",
"period": "",
"name_raw": "", "name_status": "ok | unreadable",
"days": [
{
"date": "",
"status": "available | unavailable | blank | unreadable",
"start": "", "end": "",
"time_status": "ok | ambiguous | blank",
"raw": "", "note": "",
"conflict": false, "struck": false,
"min_confidence": 0
}
]
}
1つ目の理由は、名簿との突き合わせをプログラムで行えることです。 name_raw を名簿の名前と呼び名で引き、1人に決まればスタッフ番号を付けます。名簿の在籍者のうち、その半月の希望表が1枚も無い人が、未提出の人です。
2つ目は、確認の一覧に出す条件を、AIでなくプログラムが決められることです。
| 条件 | 確認の一覧に出す理由 |
|---|---|
名簿で18歳未満の印があり、end が22:00より後 | 深夜の希望。店長が本人と時間を決め直す |
status が blank | 書き漏れ。本人に聞く |
status が unreadable か time_status が ambiguous | 写真で確かめる |
conflict が true | 可否と時刻の食い違い。本人に聞く |
name_status が unreadable、または名簿の1人に決まらない | 誰の希望表か分からない |
| 同じ人の同じ半月の希望表が2枚 | 遅れて出された分。どちらを使うか店長が決める |
| その半月の希望表が1枚も無い在籍者 | 未提出。声をかける |
3つ目は、days からそのままシフト表の希望の欄を埋められることです。 確認の一覧に出なかった日は、可否と時刻をシフト表の該当の日の欄に書き込みます。確認に出た日は、シフト表の欄を空けたまま「確認中」の印を付けます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 共有フォルダ | Python の定期の確認 | 新しい写真を見つける |
| Google Document AI | API呼び出し | 表のセル・名前の欄・信頼度 |
| Claude API | API呼び出し | 日ごとの可否と時刻をそろえる |
| スタッフの名簿 | 読み取り | 名前の照合、18歳未満の印、在籍の状態 |
| シフト表 | スプレッドシートの希望の欄への書き込み | 問題の無い日の可否と時刻 |
| 確認の一覧 | スプレッドシートへの追記 | 確認の条件に当たった日と、写真へのリンク |
シフト表には、希望の欄だけを書きます。 店長が組むシフトの欄には触れません。希望の欄を書き直すのも、新しい希望表が来たときだけで、店長が手で直した欄は上書きしません。 手で直した欄には印を付け、プログラムはその欄を飛ばします。
人が確認する
- 18歳未満の深夜の希望を最初に見る … 本人と時間を決め直します。希望表の書き直しを頼むのではなく、店長が話して決めます
- 未提出の人に声をかける … 翌朝の時点の一覧を見て、その日に出勤する人から聞きます
- 書き漏れと食い違いを本人に聞く … 写真の該当の行を見せて聞くと早く済みます
- 読めない欄と時刻のあいまいな欄を写真で確かめる … 写真で決まらなければ本人に聞きます
- 直したら記録する … どの日の何を何から何に変えたかを残します
1番目を急ぐのは、シフトを組み始める前に片づけたいからです。 深夜に入れる人の数がシフトの組み方を決めるので、後から外すと、組んだシフトを崩すことになります。
目標は、240件をならして1件2分です。 確認の一覧に1日でも出る希望表は2割前後という想定で、それより多い半月は、書き方の見本が守られていないか、撮り方が崩れています。
例外に対処する
| 起きること | 対応 |
|---|---|
| 表として読まれない(セルが返らない) | 様式の外に書かれている。全文だけを渡し、日の判定をせずに確認へ |
| 日付の行がずれる(2日分を1行に書く) | 様式の使い方を本人に伝え直す。届いたものは確認へ |
| 白紙の用紙やメモ用紙に書かれた希望 | 様式の外。写真を確認の一覧に出し、店長が手で入れる |
| 対象の半月が写真の名前と違う用紙 | 印刷された日付と食い違えば処理を止め、撮り直しに回す |
| 名簿に無い名前 | 新しく入った人か、呼び名の違い。名簿を確かめる |
| 退職した人の希望表 | 名簿の在籍の状態で除き、確認の一覧に出す |
| 備考に「この週は全部×」のように書かれている | 行の可否は書かれたとおりに写し、備考と食い違う行は conflict で確認へ |
| OCRが応答しない | 写真を元のフォルダに残し、次の回にやり直す |
上から3行目までが、運用の最初の1か月にいちばん多く出ます。 どれもAIの問題ではなく、様式の使い方の問題です。 人ごとに件数を数え、多い人にだけ書き方を伝え直します。
記録を残す
- 希望表の写真と、店番号・対象の半月・撮影日時
- OCRが返したJSONの全文(表のセル、全文、信頼度)
- AIが返した日ごとの希望と、そのとき照合した名簿の行(18歳未満の印を含む)
- 確認の一覧に出した理由と、店長が直した記録(日、項目、変更前、変更後)
- 未提出の人に声をかけた日時と、提出された日時
- 人ごとの、
blankとunreadableと様式外の件数
3つ目で「照合した名簿の行」を残すのは、深夜の判定を後から説明するためです。 誕生日の前後で印が変わった人について、その半月にどちらの扱いで判定したかを示せます。
04実装レベルの3段階
半自動化で、1件8分が4分程度になります。 読み取りは自動になりますが、未提出の人を探すことと、シフト表に写すことが手で残ります。本格構成で2分になり、この段階が本記事の想定です。 段階を飛ばさないでください。 半自動化の一覧を1か月見ると、書き方の見本を守らない人と、撮り方の崩れが先に分かります。そこを直してからシフト表への書き込みを足すほうが、確認の一覧の空振りが減ります。
05工数削減シミュレーション
導入後 240件 × 2分 ÷ 60 = 8 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- アルバイトのシフト希望を、休憩室に置いた紙の希望表で月2回集めている飲食店。店長が締め切りの後に希望表を1枚ずつ見て、表計算のシフト表に打ち直しており、その時間が営業後や休みの日に回っている場合。高校生のアルバイトがいて、午後10時以降に入れないことを店長の記憶で守っている場合。店の希望表の様式を、日付ごとの罫線の表に作り直せる場合。
- シフトの希望をすでにアプリや勤怠のシステムで集めており、紙の希望表が残っていない店。アルバイトが数名で、店長が口頭で希望を聞いて足りている店。アルバイトの名前と希望の時刻を国外のリージョンで処理することを、会社として認められない場合。なお、誰をどの時間に入れるか、希望に応えられないときにどう伝えるかの判断は、この構成では代替できません。
07最小構成で試す方法
- 前の半月の希望表から10枚を選ぶ(空欄の日がある人と、高校生の人を入れる)
- スマートフォンで、明るい場所で真上から撮る
- 手元の生成AIのサービスの画面に1枚ずつ貼り付ける
- 「この希望表を1日ずつ読み、可否・入りの時刻・上がりの時刻・備考を表にしてください。空欄の日と、×の日と、読めない日を分けてください。空欄の日を出勤不可にしないでください」と指示する
- 出てきた表を、シフト表に打ち直した内容と突き合わせる
10枚は必ずやってください。 プログラムを組む前に、「この店の書き方で、日ごとの希望が読めるのか」を確かめます。
| 出てきた内容 | 判断 |
|---|---|
| シフト表とほぼ同じ表が出た | Form Parser とプログラムの連携に進む |
| 空欄を不可にした、「L」を読み違えた | 指示と対応表で直る。構成は有効 |
| 行がずれる、2日分が1日にまとまる | 希望表の様式が先。 AIの問題ではない |
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 空欄が「入れない」になる | 入れない日は「×」と決め、空欄は blank として確認へ |
| 行がずれる、2日分が1行になる | 表の抽出は結合したセルの無い表だけ。 日付を印刷した様式にする |
| 「L」「F」を読み違える | 書き方の対応表を作り、無い書き方は ambiguous |
| 18歳未満の深夜の希望を見落とす | 名簿の印と上がりの時刻で規則で拾う |
| 誕生日の前後で判定がずれる | 半月の初日の時点で印を計算する |
| 消した「○」を読む | 消された文字を読ませず、struck を記録させる |
| 遅れて出た希望表で前の希望が消える | 黙って上書きせず、確認の一覧に出す |
| 店長が直した欄が上書きされる | 手で直した欄に印を付け、プログラムは飛ばす |
上の2行が、この構成の失敗のほとんどです。 どちらも、紙に書かれた希望を、書かれたとおりの日に、書かれたとおりの意味で入れるという同じことから来ています。「×」の決まりと、日付を印刷した様式の2つで、ほぼ防げます。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: アルバイトの名前、半月分の出勤の希望と時刻、備考に書かれた事情(「テスト期間」「通院」など)、名簿の18歳未満の印です。
- 国外で処理してよいかを先に決める … Form Parser の対応リージョンに日本はありません。スタッフの名前と希望が国外のリージョンで処理されることを、会社として認めるかを導入前に決めます
- 18歳未満のスタッフの情報を扱う前提で製品を選ぶ … 高校生のスタッフの名前と希望を扱うので、利用規約で18歳未満に関わる利用を制限している生成AIのAPIは候補から外します。仕組みを高校生のスタッフ自身に使わせることもしません
- 生年月日を外に出さない … 生成AIには年齢の情報を渡さず、18歳未満かどうかの印も名簿の側のプログラムだけで使います
- 備考の事情を広げない … 「通院」のような備考は、シフト表の希望の欄の備考にだけ写し、確認の一覧以外に出しません
- シフトの決定は人が行う … この構成が出すのは希望の一覧と確認の一覧までです。誰をどの時間に入れるかは店長が決めます
- 写真を残す期間を決める … 撮影したタブレットの側は送ったら消し、共有フォルダの写真も、シフトの確定から一定の期間がたったら消す期間を先に決めます
誤りが起きた場合のリスクは、書き漏れの日を「入れない」と扱って人手が足りなくなることと、18歳未満のスタッフを深夜に入れてしまうことの2つです。 前者は空欄の扱いで、後者は名簿の印の計算で起きます。どちらも、空欄を blank で確認に回すことと、深夜の判定を規則で行うことで防ぎます。
10まず何から始めるか
1週目:様式を作り直す
日付(印刷)・○×・入り・上がり・備考の5列の希望表を作り、用紙の上に書き方の見本を印刷します。入れない日は「×」を書くことを、スタッフに伝えます。
2週目:10枚で試す
新しい様式で書かれた希望表を10枚撮り、手元の生成AIの画面に貼り付けて表にさせます。空欄を不可にしていないか、「L」を読み違えていないかを最優先で見ます。
3週目:名簿と対応表をそろえる
名簿に、半月の初日の時点で18歳未満かどうかの印を計算する列を足します。店ごとの書き方の対応表とラストの時刻も決めます。
4週目:撮影から確認の一覧までをつなぐ
Python で共有フォルダを見て Form Parser を呼び、日ごとの希望を確認の一覧に書き出すところまで作ります。この時点ではシフト表に書き込まず、確認の一覧だけを店長が見ます。
2か月目: 名簿との照合と未提出の人の洗い出し、18歳未満の深夜の判定を足し、問題の無い日をシフト表の希望の欄に入れます。3か月目以降: 5店舗に広げ、1件8分が何分になったかを実測します。確認の一覧に出る希望表が2割前後で落ち着き、店長の休みの日の打ち直しがなくなった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
| 使用者は満18歳に満たない者を午後10時から午前5時までの間において使用してはならないこと(第61条第1項)と、その例外の規定(法令APIで条文を取得して確認) | e-Gov 法令API: 労働基準法 | 2026-10-08 |
Form Parser がOCRのテキストに加えてキーと値のペア、チェックボックス、表を抽出すること。日本語(ja)が手書きに対応する言語として示されていること。オンラインの処理が最大15ページであること。対応リージョンに日本が含まれていないこと(HTMLを取得して確認) | Google Cloud: Processor list | 2026-10-08 |
| 表の抽出が行や列をまたぐセルの無い表を対象とすること。チェック欄がラジオボタンに対応しないこと | Google Cloud: Form Parser | 2026-10-08 |
表が headerRows/bodyRows の cells で返り、Form Parser では rowSpan/colSpan が常に1であること。表の中のチェック欄が項目と値ではなく文字として返ること。textAnchor、boundingPoly | Google Cloud: Handle the processing response | 2026-10-08 |
| 対応形式と、スキャンは最低200dpiが望ましく300dpi以上が一般に最もよいこと。非可逆の形式で小さくすると精度が落ちうること | Google Cloud: Supported files | 2026-10-08 |
output_config.format に JSON スキーマを渡して応答の形を固定できること。列挙の値の大文字・小文字は保証されないこと。max_tokens で打ち切られるとスキーマに合わない出力になりうること | Claude API: Structured outputs | 2026-10-08 |
| API の利用者が18歳以上であることを求め、18歳未満に向けた、または18歳未満がアクセスしうるサービスでの利用を認めていないこと | Gemini API: Additional Terms of Service | 2026-10-08 |
誰をどの時間に入れるか、18歳未満のスタッフの勤務時間の扱いは、店長と労務の担当で決めてください。 本記事は確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-1132)についてのご相談はこちらから。
