Claude Media
労働時間の自己申告との乖離を入退館ログで見つける — Claudeで突合する手順

労働時間の自己申告との乖離を入退館ログで見つける — Claudeで突合する手順

自己申告の労働時間と入退館ログ・PCログのずれを、社員番号と日付で突き合わせて差の大きい日を出し、ヒアリング質問票まで作る手順です。ガイドラインの要請と、Claudeへの頼み方、検算用スクリプトをまとめます。

勤怠システムの退勤は18時なのに、入退館ログは21時すぎまで動いている。こうした差を人の目で一件ずつ拾うのは、対象が数十人を超えると続きません。自己申告、入退館ログ、PCの使用時間の三つを社員番号と日付でそろえ、差の大きい人と日を出す作業は、CSVの突合としてClaudeに手伝わせられます。

この記事では、厚生労働省のガイドラインが求める「実態調査」の入口になる突合表を作る手順を書きます。出した差は、未払い残業の証拠ではなく、ヒアリングの優先順位です。補正の判断と賃金の支払いは、労務担当者と社会保険労務士が行います。

ガイドラインが突合を求めているのはどの場面か

労働時間を確認し記録する方法は、原則として二つあります。使用者が自ら現認する方法と、タイムカード、ICカード、パソコンの使用時間の記録などの客観的な記録を基礎にする方法です。やむを得ず自己申告制にするときは、追加の措置が要ります。

突合に直結するのは、その追加措置の一つです。自己申告で把握した労働時間が実際と合っているかを、必要に応じて実態調査で確かめ、所要の補正をします。特に、入退場記録やパソコンの使用時間の記録のように事業場内にいた時間が分かるデータを持っているときは、申告との間に著しい乖離があれば実態調査と補正をします。

ここで注意したい点が二つあります。

  • 「著しい」の数値は決まっていません。ガイドライン本文とリーフレットのどちらにも、何分以上という基準は載っていません。閾値は社内で決めます
  • 申告より長く在社している時間の理由を本人に報告させている場合は、その報告が適正に行われているかも確認の対象です

つまり、突合は任意の工夫ではなく、自己申告制を採るなら備えておくべき確認作業の中心にあたります。

乖離が出ても、すぐに労働時間とは言えない

入退館ログが示すのは在社時間です。労働時間とは別のものです。ガイドラインは、労働時間を使用者の指揮命令下に置かれている時間と定めています。契約や就業規則の書き方ではなく、実態で決まります。

逆の方向にも線があります。休憩や自主的な研修、学習のため労働時間ではないと報告されていても、実際には使用者の指示で業務に従事していたと認められる時間は、労働時間として扱わなければなりません。

だから突合表の役割は二段階に分けます。

  1. 差の大きい日を機械的に出す(Claudeとスクリプトの仕事)
  2. その日に何をしていたかを聞き、労働時間かどうかを判断する(人の仕事)

2を飛ばして「差=残業」と決め打ちすると、私的な滞在や休憩を労働時間に積み上げてしまいます。反対に、差を見ても動かなければ、ガイドラインが想定する実態調査になりません。

用意する三つのデータと、Claudeに渡す前の下ごしらえ

必要なのは、次の三つのCSVです。列名は例で、実際のシステムの出力に合わせて直します。

ファイル中身主な列
attendance.csv中身自己申告(勤怠システム)主な列社員番号、日付、始業、終業、休憩分
gate.csv中身入退館ログ主な列社員番号、日付、入館、退館
pc.csv中身PCの起動・終了ログ主な列社員番号、日付、最初の起動、最後の終了

突合のキーは社員番号と日付の二つです。氏名は結合には使いません。ログの氏名は表記ゆれが出やすく、社員番号のほうが確実です。

Claudeに渡すファイルは、氏名の列を落とし、社員番号だけにしておくのが安全です。突合が終わったあとで、対象者の氏名は社内の名簿から引き直せます。入退館ログとPCログは従業員の行動が分かる記録なので、渡す範囲を最小にしておくと、社内説明もしやすくなります。個人情報を扱う委託先や外部サービスの点検は個人情報の委託先監督を点検表にする手順も参考になります。

ClaudeのチャットにCSVを渡す場合、サポート記事によるとCSVは対応するファイル形式です。1チャットあたり最大20ファイル、1ファイル500MBまで添付できます。XLSXを渡すときは、アカウントでコード実行とファイル作成を有効にしておく必要があります。三つのCSVなら、この範囲に収まります。

突合をClaudeに頼む指示文

チャットに三つのCSVを添付し、次のように頼みます。条件は具体的に書くほど、あとで結果を検算しやすくなります。

添付の attendance.csv(自己申告)、gate.csv(入退館)、pc.csv(PC)を、
社員番号と日付で突き合わせてください。
 
- 申告終業より退館が30分以上遅い日、PC終了が30分以上遅い日、
  申告始業より入館が30分以上早い日を「乖離大」とする
- 申告があるのにログが両方ない日は「ログなし」、
  ログがあるのに申告がない日は「申告なし」として別に出す
- 社員番号ごとに、対象日数・乖離大の日数・乖離の合計分を出す
- 結論は書かず、表だけを返す(労働時間かどうかは判断しない)
- 計算に使ったコードも見せる

最後の二行が要点です。Claudeに判断をさせず、計算根拠のコードを見せさせると、次の節のスクリプトと照らして検算できます。

検算に使えるスクリプト

Claudeが返した表が正しいか不安なときは、同じ条件を手元で動かして結果を比べます。次のPythonは標準ライブラリだけで動きます。三つのCSVが同じフォルダにある前提です。

import csv
from collections import defaultdict
 
THRESH_MIN = 30  # 「著しい乖離」の目安。社内で決める値
 
def mins(s):
    if not s:
        return None
    h, m = s.split(":")
    return int(h) * 60 + int(m)
 
def load(path):
    with open(path, encoding="utf-8-sig", newline="") as f:
        return {(r["emp_id"], r["date"]): r for r in csv.DictReader(f)}
 
att, gate, pc = load("attendance.csv"), load("gate.csv"), load("pc.csv")
rows = []
for key in sorted(set(att) | set(gate) | set(pc)):
    a, g, p = att.get(key), gate.get(key), pc.get(key)
    start, end = (mins(a["start"]), mins(a["end"])) if a else (None, None)
    gin, gout = (mins(g["in"]), mins(g["out"])) if g else (None, None)
    pon, poff = (mins(p["first_on"]), mins(p["last_off"])) if p else (None, None)
    if a is None:
        flag, gap = "申告なし(ログのみ)", None
    elif gin is None and pon is None:
        flag, gap = "ログなし", None
    else:
        gaps = []
        if end is not None and gout is not None: gaps.append(gout - end)
        if end is not None and poff is not None: gaps.append(poff - end)
        if start is not None and gin is not None: gaps.append(start - gin)
        gap = max(gaps) if gaps else None
        flag = "乖離大" if gap is not None and gap >= THRESH_MIN else ""
    rows.append({"emp_id": key[0], "date": key[1], "flag": flag,
                 "max_gap_min": gap})
 
flagged = [r for r in rows if r["flag"]]
with open("deviation.csv", "w", encoding="utf-8-sig", newline="") as f:
    w = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
    w.writeheader()
    w.writerows(flagged)
 
total = defaultdict(lambda: [0, 0, 0])
for r in rows:
    t = total[r["emp_id"]]
    t[0] += 1
    t[1] += bool(r["flag"])
    t[2] += max(r["max_gap_min"] or 0, 0)
for emp, (n, k, m) in sorted(total.items(), key=lambda x: -x[1][2]):
    print(emp, f"対象{n}日 フラグ{k}日 乖離合計{m}分")
python3 reconcile.py

架空の少人数データ(3人・計7日分)で動かすと、次の出力になります。社員番号E1001の9月2日は申告終業が18:00、退館が21:20、PC終了が21:05で、最大の差は200分です。

E1001 対象3日 フラグ2日 乖離合計375分
E1003 対象2日 フラグ0日 乖離合計20分
E1002 対象2日 フラグ0日 乖離合計10分

deviation.csv には、乖離大の2日分だけが残ります。この出力は例示用のダミーデータによるものです。実データでは、フラグの件数が多すぎるときに閾値を上げて絞り直します。

落とし穴

乖離ゼロの人が問題なしとは限らない

申告とログが一致していても、申告もログも同じ形に揃っている可能性があります。ガイドラインは、36協定の上限を超えて働いているのに、記録上は守っているように見せる慣習がないかも確認するよう求めています。申告の終業時刻が特定の時刻に張り付いていないか、月の申告時間が上限のすぐ手前に集まっていないかも、あわせて見ます。

ログの種類ごとに、乖離の出方が違う

突合表を読むときは、三つのデータのクセを頭に置いておくと、フラグの意味を取り違えません。次は一般的に起こりうる例で、自社のシステムで当てはまるかは運用担当に確かめてください。

  • 入退館ログ: 退館の記録は出口のゲートだけに残ることが多く、同行者に続いて出ると記録が欠けることがあります。昼休みの外出は入退館が二回に分かれるため、「最初の入館と最後の退館」だけを取ると休憩時間も在社に入ります
  • PCログ: 起動したままの席離れや、ロック画面の放置でも終了時刻が遅れて見えます。逆に、PCを使わない作業(現場、会議、電話)の時間は出ません
  • 自己申告: 一律の定時刻や、前日の入力の使い回しが続いていないかは、時刻の並びを見ると分かります

三つのうち二つが同じ方向にずれ、残る一つがずれていない日は、そのまま原因の手がかりになります。たとえば入退館とPCがともに21時台なのに、申告だけが18時なら、打刻漏れや記録忘れよりも、申告の仕方を見直す余地が大きい日です。反対に、PCだけが遅い日は、起動したままの帰宅を先に疑います。

申告と一致している日にも、特定の時刻へ終業が揃っている人は、質問票の対象に加えます。

閾値の決め方と、見る単位

閾値は一つに決め打ちせず、三つの単位で見るのが実務的です。

単位見るもの狙い
日見るもの1日の最大の差(分)狙い突発的な長居や打刻忘れを拾う
月見るもの乖離の合計分狙い毎日少しずつ積み上がる人を拾う
繰り返し見るもの乖離大の日が月に何日あるか狙い偶然でなく習慣になっている人を拾う

最初は30分から始め、フラグの多さを見て調整します。入館から席に着くまで、退館までの片付けなど、移動の時間は一定程度ずれます。ここまでをすべて拾うと、実態調査の対象が増えすぎて回らなくなります。

月の突合は、80時間などの基準との関係も見ておくと役に立ちます。申告の時間外が基準の手前で止まっている人の在社時間が、基準を超えていないかという見方です。基準を超えた人の抽出手順は医師面接指導の対象者を80時間超で抽出する手順に書いています。

ヒアリング質問票を作る

差の大きい日が出たら、本人に聞くための質問票を作ります。Claudeには、突合表の該当行を渡して質問票の下書きを頼みます。

deviation.csv の各行について、本人向けの確認質問票を作ってください。
 
- 責める口調にしない。「申告漏れを疑っている」ように読ませない
- 質問は次の観点に限る: その日の退館までの過ごし方、
  業務の指示の有無と指示者、休憩の取得、学習や研修が業務として
  義務づけられていたか、申告しにくい事情の有無
- 「労働時間にあたるか」は質問票では判定しない
- 日付ごとに、申告・入退館・PCの時刻を冒頭に1行で添える

質問票に入れておきたい項目は、次のとおりです。

観点質問の例ガイドライン上の意味
過ごし方質問の例この日、申告した終業時刻のあと、退館までに何をしていましたかガイドライン上の意味在社時間の中身の確認
指示の有無質問の例業務の指示や、待機の指示はありましたか。誰からですかガイドライン上の意味指揮命令下かどうかの判断材料
休憩質問の例その間に休憩を取りましたかガイドライン上の意味休憩と報告された時間の実態確認
研修・学習質問の例参加が義務づけられていた研修や、業務に必要な学習でしたかガイドライン上の意味義務や必要性があれば労働時間として扱う
申告のしにくさ質問の例残業の申告に上限を感じる事情はありましたかガイドライン上の意味申告を妨げる措置がないかの確認

最後の項目は、本人ではなく会社側の問題を探すための質問です。時間外労働の削減を促す社内通達や、定額の残業手当が、適正な申告を妨げていないかを確認するのも、ガイドラインが使用者に求める事項です。

補正したあとに残す記録

ヒアリングの結果、労働時間にあたる時間があれば、使用者が補正します。補正後の時間は賃金台帳に正しく記入します。賃金台帳には労働日数、労働時間数、休日労働の時間数、時間外労働の時間数、深夜労働の時間数といった事項を適正に記入する決まりがあり、記入しない場合や故意に虚偽の時間数を記入した場合は、30万円以下の罰金の定めがあります。

保存期間にも注意が要ります。ガイドラインは、出勤簿やタイムカード等の記録を労働基準法第109条に基づいて3年間保存するとしています。条文の本則は5年間ですが、附則第143条が「当分の間」を3年間と読み替えるため、現在も3年が適用されます。突合表とヒアリングの記録も、同じ扱いで保管しておくと、後で経緯を説明しやすくなります。

保存の対象には、突合に使ったCSVの原本、閾値の設定、ヒアリング記録を入れます。Claudeとのやりとりの履歴は、どこまで残すかを社内で決めます。

CoworkやExcelで続けるなら

月に一度の突合なら、チャットで十分です。毎週同じ条件で回したいときは、Coworkのスケジュール機能で週次に走らせる方法があります。構成の組み方はCoworkで勤怠異常検知を週次自動化する方法にあります。突合結果をExcelの表で追う場合は、フラグ列と社内の閾値セルを分けておくと、閾値を変えたときに再計算が楽になります。

宿日直の許可を前提にした医療機関の勤務記録は、労働時間の扱いが別に決まります。勤務記録と許可基準の突合は、宿日直許可申請をClaudeで点検する手順で扱っています。

まとめ

自己申告制の会社では、入退館ログやPCログのような事業場内にいた時間が分かるデータとの突合が、確認作業の中心になります。ずれの大きい日を機械的に出す部分はClaudeとスクリプトに任せ、その日の中身を聞いて労働時間かどうかを決める部分は、人が担います。

突合の前に決めておくのは、「著しい」にあたる閾値と、ヒアリングで聞く観点の二つです。この二つが決まっていれば、毎月同じ手順で回せます。

この記事を共有:XはてブLinkedIn