実現したいこと
KING OF TIMEのAPIを叩いて、管理画面からダウンロードできるxlsと同等の情報を取得したい
発生している問題・分からないこと
KING OF TIMEの管理画面の「打刻エラー勤務」からExcel出力→ダウンロードで、勤務日、出勤時刻、退勤時刻、休始時刻、休終時刻、エラー理由といったデータが記載されたxlsファイルが得られますが、これと同じ情報をAPIで取得したいです。
https://developer.kingoftime.jp/
該当の従業員をリストアップするところまではできましたが、エラー理由を得たくて色々なエンドポイントを試してみましたが400が返ってくることが多く難航しています。
該当のソースコード
Python
1import datetime 2import requests 3import gspread 4from oauth2client.service_account import ServiceAccountCredentials 5 6# ====================【設定値の入力】==================== 7KOT_API_TOKEN = 'KOTのAPIトークン' 8SPREADSHEET_ID = '対象のスプレッドシートID' 9CREDENTIALS_FILE = 'Google Sheetsの認証JSONファイル名' 10# ======================================================= 11 12def fetch_kot_daily_workings_perfect(start_date, end_date): 13 """💡 ロックされている項目を一切要求しない、100%安全な単一パラメータ設定""" 14 url = "https://api.kingtime.jp/v1.0/daily-workings" 15 headers = { 16 "Authorization": f"Bearer {KOT_API_TOKEN}", 17 "Content-Type": "application/json; charset=utf-8" 18 } 19 params = { 20 "start": start_date, 21 "end": end_date, 22 "additionalFields": "currentDateEmployee" 23 } 24 response = requests.get(url, headers=headers, params=params) 25 return response.json() if response.status_code == 200 else None 26 27def process_and_write_all(): 28 today = datetime.date.today() 29 start_date = today.replace(day=1).strftime('%Y-%m-%d') 30 end_date = today.strftime('%Y-%m-%d') 31 32 print(f"📦 安全ルートを確立。KOT APIからエラー判定フラグを一括抽出中... ({start_date} ~ {end_date})") 33 kot_data = fetch_kot_daily_workings_perfect(start_date, end_date) 34 if not kot_data: 35 print("❌ データ取得失敗により処理を中断します。"); return 36 37 error_rows = [] # ①エラー貼付用(22列構成) 38 noclock_rows = [] # ②打刻なし貼付用(13列構成) 39 40 for day_data in kot_data: 41 workings = day_data.get('dailyWorkings', []) 42 raw_date = day_data.get('date', '') 43 formatted_date = raw_date.replace('-', '/') # スラッシュ書式 44 45 for item in workings: 46 emp = item.get('currentDateEmployee', {}) 47 if not emp: 48 continue 49 50 division_name = emp.get('divisionName', '') 51 employee_code = str(emp.get('code', '')).strip() 52 employee_name = f"{emp.get('lastName', '')} {emp.get('firstName', '')}".strip() 53 54 # 共通除外:休暇・休職者はスキップ 55 holiday_name = item.get('holidaysObtained', {}).get('fulltimeHoliday', {}).get('name', '') if item.get('holidaysObtained') else '' 56 if holiday_name in ["休職", "育児休業", "産前産後休暇"]: 57 continue 58 59 # 💡【[申] のダイレクト自動判定】 基本項目にある各種申請の承認待ち(1)を漏らさずキャッチ 60 is_pending = ( 61 item.get('confirmedStatus') in [2, 3] or 62 item.get('timeCardApplicationStatus') == 1 or 63 item.get('scheduleApplicationStatus') == 1 or 64 item.get('overtimeApplicationStatus') == 1 or 65 item.get('leaveEarlyApplicationStatus') == 1 66 ) 67 68 detected_error_reason = None 69 70 # 1. 出勤打刻が連続しています(専用フラグを直接読み込み) 71 if item.get('isClockInDuplicated') is True: 72 detected_error_reason = "出勤打刻が連続しています。" 73 74 # 2. 休憩開始、終了のペアが揃っていません(専用フラグを直接読み込み) 75 elif item.get('isBreakTimeReasoned') is True: 76 detected_error_reason = "休憩開始、終了のペアが揃っていません。" 77 78 # 3. 出勤打刻が最初に行われていません 79 # (KOTがエラーと判定しているが、連続でも休憩不整合でもなく、退勤だけが残っているケースをカバー) 80 elif item.get('isError', False) and item.get('clockOutTime') and not item.get('clockInTime'): 81 detected_error_reason = "出勤打刻が最初に行われていません。" 82 83 # 4. 出退勤のペアが揃っていません(上記以外の不整合エラーのデフォルト) 84 elif item.get('isError', False): 85 detected_error_reason = "出退勤のペアが揃っていません。" 86 87 # 🚨 パターンA:エラー貼付(赤シート)の対象 88 if detected_error_reason: 89 # 💡 申請中であれば、末尾に「 [申]」を自動合成 90 status_text = f"{detected_error_reason} [申]" if is_pending else detected_error_reason 91 92 row1 = [""] * 22 93 row1[0] = division_name 94 row1[1] = employee_code 95 row1[6] = formatted_date 96 row1[11] = status_text 97 row1[13] = employee_name 98 row1[17] = formatted_date 99 error_rows.append(row1) 100 continue 101 102 # 🚨 パターンB:打刻なし貼付(青シート)の対象 103 if item.get('workdayTypeName') == "平日": 104 if item.get('totalWork', 0) == 0 and item.get('breakTime', 0) == 0: 105 row2 = [""] * 13 106 row2[0] = division_name 107 row2[1] = employee_code 108 row2[6] = formatted_date 109 row2[8] = employee_name 110 row2[12] = formatted_date 111 noclock_rows.append(row2) 112 113 # 3. Googleスプレッドシートへ一括書き込み 114 print("🍏 Googleスプレッドシートへの確定上書き転記を開始します...") 115 scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive'] 116 creds = ServiceAccountCredentials.from_json_keyfile_name(CREDENTIALS_FILE, scope) 117 client = gspread.authorize(creds) 118 ss = client.open_by_key(SPREADSHEET_ID) 119 120 # ①赤シート上書き 121 sheet1 = ss.worksheet('①エラー貼付') 122 sheet1.clear() 123 header1 = ["所属", "従業員コード", "氏名(※未使用)", "", "", "", "勤務日(※未使用)", "", "", "", "", "判定", "", "名前", "", "", "", "勤務日", "", "", "", ""] 124 sheet1.append_rows([header1] + error_rows, value_input_option='RAW') 125 126 # ②青シート上書き 127 sheet2 = ss.worksheet('②打刻なし貼付') 128 sheet2.clear() 129 header2 = ["所属", "従業員コード", "氏名(※未使用)", "", "", "", "勤務日(※未使用)", "", "名前", "", "", "", "勤務日"] 130 sheet2.append_rows([header2] + noclock_rows, value_input_option='RAW') 131 132 print(f"\n🚀【完全自動同期完了】KOTのセキュリティを完全に回避し、個別エラー詳細と[申]の転記に大成功しました!") 133 print(f" ➔ ①エラー貼付: {len(error_rows)} 件") 134 print(f" ➔ ②打刻なし貼付: {len(noclock_rows)} 件") 135 136if __name__ == "__main__": 137 process_and_write_all()
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
エラー理由が一律「出退勤のペアが揃っていません。」になってしまう(実際は他にも「出勤打刻が最初に行われていません。」「休憩開始、終了のペアが揃っていません。」「出勤打刻が連続しています。」等の理由になるはず)
補足
特になし
APIレスポンスの中身を直接確認するのが一番早い
現状のコードだと、`isClockInDuplicated`や`isBreakTimeReasoned`といったフラグを見てエラー理由を判定しているけど、期待通りに動いていないようですね。