checkin status tool

This commit is contained in:
2025-09-06 06:15:35 +09:00
parent 290a5a8c2f
commit e65da5fd8f
9 changed files with 1328 additions and 13 deletions

53
CPLIST/input/team2025.csv Normal file
View File

@ -0,0 +1,53 @@
部門別数,時間,部門,チーム名,メール,password,電話番号,氏名1,誕生日1,氏名2,誕生日2,氏名3,誕生日3,氏名4,誕生日4,氏名5,誕生日5,氏名6,誕生日6,氏名7,誕生日7,,
1,3,一般,いなりずし,takuyuna1123@icloud.com,ko1703,09014701703,児玉優美,1976/12/13,児玉豊久,1973/11/23,田中広美,1975/10/31,,,,,,,,,,
1,5,一般,Go to the peak!,shibashintan@c.vodafone.ne.jp,shi0145,090-8499-0145,柴山晋太郎,1974/12/14,後藤克弘,1968/04/07,二村修,1967/06/22,,,,,,,,,,
2,3,一般,きみこうじ,chibi-kimi.706@ezweb.ne.jp,sa8309,09062518309,齋藤貴美子,1980/07/06,江口浩次,1968/04/19,,,,,,,,,,,,
2,5,一般,ウエストサイド,chikachan-5101414@i.softbank.jp,go7471,09047997471,後藤睦子,1961/5/1,後藤正寿,1959/7/23,大坪照子,1958/11/11,松村芳美,1964/4/28,,,,,,,,
3,3,一般,ベル,kekomura1008@yahoo.co.jp,ka3001,090-3564-3001,川村健一,1969/10/08,曽我部知奈美,1973/12/17,伊藤徳幸,1975/02/06 ,筒井勝児,1976/05/31,,,,,,,,
3,5,一般,ランエンジョン!,baycools16@gmail.com,ka9749,090÷4790÷9749,河合賢次,1972/12/14,中野真樹,1973/01/23,,,,,,,,,,,,
4,3,一般,ぐりと愉快な仲間たち,kayochu.v.mame.526@icloud.com,na6547,090-1564-6547,長屋香代子,1961/10/27,長屋宣宏,1961/5/26,,,,,,,,,,,,
4,5,一般,坂本555,sakamoto180909@yahoo.co.jp,sa4396,090-8480-4396,坂本正憲,1972/5/30,坂本彩子,1976/3/29,坂本瑠璃子,2003/8/23,,,,,,,,,,
5,3,一般,リキとりんごてぃー,apple1977tea@yahoo.co.jp,te1499,08051241499,鄭寛子,1977/6/13,鄭昌彦,1971/5/26,,,,,,,,,,,,
5,5,一般,East Field,ryo1hi@outlook.com,hi0504,070-8564-0504,東野遼一,1983/09/27,東野智子,1977/03/16,,,,,,,,,,,,
6,3,一般,としちんかずちん,kazu-chin1998@docomo.ne.jp,shi9127,080-2616-9127,渋谷和広,1970/8/1,渋谷敏江,1956/6/16,,,,,,,,,,,,
6,5,一般,M sisters with D,m.kiyomi.115@gmail.com,ma3731,090-4869-3731,前田貴代美,1973/01/15,中濱智恵美,1969/06/16,,,,,,,,,,,,
7,3,一般,シマエナガ,c6d6.lpbm5-s@ezweb.ne.jp,shi1925,090-6336-1925,神谷孫斗,1997/03/02,小栗彩瑚,2001/9/21,,,,,,,,,,,,
7,5,一般,さなっく,santa04230722@icloud.com,ya7192,070-5640-7192,山田朋博,1971/04/23,眞田尚亮,1982/11/30,,,,,,,,,,,,
8,3,一般,煮込みラーメン,t.nishioka1575tt@gmail.com,ni9354,080-8523-9354,西岡嵩倫,1999/1/5,西岡影忠,1971/2/2,,,,,,,,,,,,
9,3,一般,そうたとなゆ,hmt.sota@gmail.com,ho6594,090-1109-6594,甫本創太,1991/06/07,後藤菜友,1994/02/22,,,,,,,,,,,,
10,3,一般,KOJ,balccitomatochop@gmail.com,to5670,090-2181-5670,轟原功樹,1978/08/10,田中美樹,1978/09/07,,,,,,,,,,,,
11,3,一般,サウナとビリヤニ,bitter_smile107@yahoo.co.jp,sa9007,090-4760-9007,坂口祐生,1992/1/7,近藤準,1987/1/25,圓山大貴,1993/5/10,,,,,,,,,,
1,3,お試し・一般,ひろ君と愉快な仲間たち,y0126k@yahoo.co.jp,ya7467,090-9902-7467,山脇裕子,1984/1/26,高橋美智子,1975/04/21,樋口博久,1964/01/08,雨宮功治,1962/05/25,広瀬貴士,1978/08/17,,,,,,
2,3,お試し・一般,フクニシ,appleorange100pct@yahoo.co.jp,fu2792,080-6954-2792,福西直之,1986/2/5,福西愛,1986/3/2,,,,,,,,,,,,
3,3,お試し・一般,あやみち,h613-y5m9t-mich@ezweb.ne.jp,ya3144,090-4447-3144,谷許文音,2006/07/26,谷許美千代,1976/03/27,,,,,,,,,,,,
1,3,お試し・男性ソロ,松村覚司,happy.dreams.come.true923@gmail.com,ma3625,090-8186-3625,松村覚司,1967/9/23,,,,,,,,,,,,,,
2,3,お試し・男性ソロ,高野清司,wakano_528@yahoo.co.jp,ta5865,090-5603-5865,高野清司,71歳,,,,,,,,,,,,,,
1,3,お試し・ファミリー,まゆちー,takoyaki_sena@icloud.com,a1246,090-6090-1246,浅田舞子,1986/02/22,浅田真結菜,2014/03/30,森美紀,1988/03/06,森千晴,2017/8/4,,,,,,,,
1,5,お試し・ファミリー,ポエドリ,takagitoshihiro8@yahoo.co.jp,ta4245,090-5866-4245,高木俊裕,1984/03/09,,,,,,,,,,,,,,
2,3,お試し・ファミリー,ガンバルゾー,youkeymr.01@gmail.com,mo6605,090-6080-6605,森祐貴,1985/9/26,浅田直之,1987/12/12,浅田晃汰,2014/01/06,森光喜,2015/4/22,,,,,,,,
2,5,お試し・ファミリー,fun!fun!うごchan,fulayota333@gmail.com,ha7384,090-6599-7384,早川宏美,1975/6/15,,,,,,,,,,,,,,
3,3,お試し・ファミリー,チームT,sphin28420@aim.com,te1882,080-6709-1882,寺田剛,1979/06/04,寺田恭子,1985/01/10,寺田向希,2023/11/08,,,,,,,,,,
1,3,女性ソロ,山下和乃,kazjamster@gmail.com,ya2450,090-4229-2450,山下和乃,2004/4/26,,,,,,,,,,,,,,
1,5,女性ソロ,Best Wishes,thunderhead_56@yahoo.co.jp,ha7226,090-5652-7226,長谷川美貴,1973/5/6,,,,,,,,,,,,,,
1,3,男性ソロ,しーくん,redleif57917913@ezweb.ne.jp,mi6827,090-2946-6827,水門茂,1962/12/24,,,,,,,,,,,,,,
1,5,男性ソロ,風呂の会,1845dondon@gmail.com,a9050,09096369050,浅井貴弘,1984/07/11,,,,,,,,,,,,,,
2,3,男性ソロ,野田達男,tatchi.sat111@docomo.ne.jp,no0873,0901417-0873,野田達男,1950/9/14,,,,,,,,,,,,,,
2,5,男性ソロ,近藤隆,kondo2000gt@yahoo.ne.jp,ko0666,09018300666,近藤隆,1962/6/28,,,,,,,,,,,,,,
3,3,男性ソロ,日吉将大,hiyomasa0034@gmail.com,hi6343,080-2733-6343,日吉将大,1995/09/14,,,,,,,,,,,,,,
3,5,男性ソロ,松野昌紀,matsubottkuri11994730@gmail.com,ma2606,090-1272-2606,松野昌紀,1972/9/30,,,,,,,,,,,,,,
4,3,男性ソロ,東京OLクラブ,abe_1755_31@yahoo.co.jp,a7102,090-2203-7102,阿部昌隆,1956/4/20,,,,,,,,,,,,,,
4,5,男性ソロ,白木稔人,amida48gan@icloud.com,shi6048,090-7302-6048,白木稔人,1972/5/17,,,,,,,,,,,,,,
5,3,男性ソロ,大阪OLC,t.okiura1961@gmail.com,o1141,090-7888-1141,沖浦徹二,1961/4/29,,,,,,,,,,,,,,
5,5,男性ソロ,Best Wishes,jovi_bounce14@yahoo.co.jp,ko0716,09032840716,小林寿郎,1973/10/26,,,,,,,,,,,,,,
6,3,男性ソロ,つるまいOLC,junhagi68@gmail.com,ha1001,080-3159-1001,萩原淳,1968/3/17,,,,,,,,,,,,,,
6,5,男性ソロ,脇屋貴司,takarinkuririn@gmail.com,wa2659,080-3508-2659,脇屋貴司,1983/10/26,,,,,,,,,,,,,,
7,3,男性ソロ,㈱大垣ケーブルテレビ,so-kishidaogaki-tv.co.jp,ki1207,0584-82-1207,岸田爽,2001/8/12,,,,,,,,,,,,,,
7,5,男性ソロ,前川一彦,yoshino-chuo@docomo.ne.jp,ma2351,090-1074-2351,前川一彦,不明,,,,,,,,,,,,,,
8,3,男性ソロ,㈱大垣ケーブルテレビ,ta-shiba@ogaki-tv.co.jp,shi1207,,芝建,1998/11/9,,,,,,,,,,,,,,
1,3,ファミリー,うぱうぱアイランド,serukasu@gmail.com,i4200,09084584200,伊藤由美子,19920328,伊藤嘉仁,19930825,伊藤嘉利,20220913,,,,,,,,,,
1,5,ファミリー,ながれぼし,h2798723ddwyus@i.softbank.jp,ta8317,090-1782-8317,高田めぐみ,1982/4/28,高田志穂,2013/12/5,,,,,,,,,,,,
2,3,ファミリー,Team117,miki.maki0107@gmail.com,sa3915,090-7678-3915,佐々木孝好,1970/12/20,佐々木享子,1977/8/25,佐々木実希,2012/1/21,佐々木麻妃,2016/7/1,,,,,,,,
2,5,ファミリー,500えん,roumnet@yahoo.co.jp,go6814,090-9890-6814,五百木弘道,1972/4/29,五百木芽彩,2015/3/13,,,,,,,,,,,,
3,3,ファミリー,チームしぇいや,rayrain3000@docomo.ne.jp,ya2905,090-3056-2905,山本龍也,1976/3/14,山本聖也,2009/9/9,山本輝也,2015/6/3,,,,,,,,,,
3,5,ファミリー,チームユズ,livertish_v.g.35@docomo.ne.jp,ko7822,090-7311-7822,小出龍,1983/2/27,小出柚希,2019/1/7,,,,,,,,,,,,
4,3,ファミリー,'sファミリー,inukisen@gmail.com,ya1285,09042581285,安田千穂,1984/3/7,安田尚広,1978/1/18,安田雫,2014/9/2,安田葵,2018/5/13,,,,,,,,
1 部門別数 時間 部門 チーム名 メール password 電話番号 氏名1 誕生日1 氏名2 誕生日2 氏名3 誕生日3 氏名4 誕生日4 氏名5 誕生日5 氏名6 誕生日6 氏名7 誕生日7
2 1 3 一般 いなりずし takuyuna1123@icloud.com ko1703 09014701703 児玉優美 1976/12/13 児玉豊久 1973/11/23 田中広美 1975/10/31
3 1 5 一般 Go to the peak! shibashintan@c.vodafone.ne.jp shi0145 090-8499-0145 柴山晋太郎 1974/12/14 後藤克弘 1968/04/07 二村修 1967/06/22
4 2 3 一般 きみこうじ chibi-kimi.706@ezweb.ne.jp sa8309 09062518309 齋藤貴美子 1980/07/06 江口浩次 1968/04/19
5 2 5 一般 ウエストサイド chikachan-5101414@i.softbank.jp go7471 09047997471 後藤睦子 1961/5/1 後藤正寿 1959/7/23 大坪照子 1958/11/11 松村芳美 1964/4/28
6 3 3 一般 ベル kekomura1008@yahoo.co.jp ka3001 090-3564-3001 川村健一 1969/10/08 曽我部知奈美 1973/12/17 伊藤徳幸 1975/02/06 筒井勝児 1976/05/31
7 3 5 一般 ランエンジョン! baycools16@gmail.com ka9749 090÷4790÷9749 河合賢次 1972/12/14 中野真樹 1973/01/23
8 4 3 一般 ぐりと愉快な仲間たち kayochu.v.mame.526@icloud.com na6547 090-1564-6547 長屋香代子 1961/10/27 長屋宣宏 1961/5/26
9 4 5 一般 坂本555 sakamoto180909@yahoo.co.jp sa4396 090-8480-4396 坂本正憲 1972/5/30 坂本彩子 1976/3/29 坂本瑠璃子 2003/8/23
10 5 3 一般 リキとりんごてぃー apple1977tea@yahoo.co.jp te1499 08051241499 鄭寛子 1977/6/13 鄭昌彦 1971/5/26
11 5 5 一般 East Field ryo1hi@outlook.com hi0504 070-8564-0504 東野遼一 1983/09/27 東野智子 1977/03/16
12 6 3 一般 としちんかずちん kazu-chin1998@docomo.ne.jp shi9127 080-2616-9127 渋谷和広 1970/8/1 渋谷敏江 1956/6/16
13 6 5 一般 M sisters with D m.kiyomi.115@gmail.com ma3731 090-4869-3731 前田貴代美 1973/01/15 中濱智恵美 1969/06/16
14 7 3 一般 シマエナガ c6d6.lpbm5-s@ezweb.ne.jp shi1925 090-6336-1925 神谷孫斗 1997/03/02 小栗彩瑚 2001/9/21
15 7 5 一般 さなっく santa04230722@icloud.com ya7192 070-5640-7192 山田朋博 1971/04/23 眞田尚亮 1982/11/30
16 8 3 一般 煮込みラーメン t.nishioka1575tt@gmail.com ni9354 080-8523-9354 西岡嵩倫 1999/1/5 西岡影忠 1971/2/2
17 9 3 一般 そうたとなゆ hmt.sota@gmail.com ho6594 090-1109-6594 甫本創太 1991/06/07 後藤菜友 1994/02/22
18 10 3 一般 KOJ balccitomatochop@gmail.com to5670 090-2181-5670 轟原功樹 1978/08/10 田中美樹 1978/09/07
19 11 3 一般 サウナとビリヤニ bitter_smile107@yahoo.co.jp sa9007 090-4760-9007 坂口祐生 1992/1/7 近藤準 1987/1/25 圓山大貴 1993/5/10
20 1 3 お試し・一般 ひろ君と愉快な仲間たち y0126k@yahoo.co.jp ya7467 090-9902-7467 山脇裕子 1984/1/26 高橋美智子 1975/04/21 樋口博久 1964/01/08 雨宮功治 1962/05/25 広瀬貴士 1978/08/17
21 2 3 お試し・一般 フクニシ appleorange100pct@yahoo.co.jp fu2792 080-6954-2792 福西直之 1986/2/5 福西愛 1986/3/2
22 3 3 お試し・一般 あやみち h613-y5m9t-mich@ezweb.ne.jp ya3144 090-4447-3144 谷許文音 2006/07/26 谷許美千代 1976/03/27
23 1 3 お試し・男性ソロ 松村覚司 happy.dreams.come.true923@gmail.com ma3625 090-8186-3625 松村覚司 1967/9/23
24 2 3 お試し・男性ソロ 高野清司 wakano_528@yahoo.co.jp ta5865 090-5603-5865 高野清司 71歳
25 1 3 お試し・ファミリー まゆちー takoyaki_sena@icloud.com a1246 090-6090-1246 浅田舞子 1986/02/22 浅田真結菜 2014/03/30 森美紀 1988/03/06 森千晴 2017/8/4
26 1 5 お試し・ファミリー ポエドリ takagitoshihiro8@yahoo.co.jp ta4245 090-5866-4245 高木俊裕 1984/03/09
27 2 3 お試し・ファミリー ガンバルゾー youkeymr.01@gmail.com mo6605 090-6080-6605 森祐貴 1985/9/26 浅田直之 1987/12/12 浅田晃汰 2014/01/06 森光喜 2015/4/22
28 2 5 お試し・ファミリー fun!fun!うごchan fulayota333@gmail.com ha7384 090-6599-7384 早川宏美 1975/6/15
29 3 3 お試し・ファミリー チームT sphin28420@aim.com te1882 080-6709-1882 寺田剛 1979/06/04 寺田恭子 1985/01/10 寺田向希 2023/11/08
30 1 3 女性ソロ 山下和乃 kazjamster@gmail.com ya2450 090-4229-2450 山下和乃 2004/4/26
31 1 5 女性ソロ Best Wishes thunderhead_56@yahoo.co.jp ha7226 090-5652-7226 長谷川美貴 1973/5/6
32 1 3 男性ソロ しーくん redleif57917913@ezweb.ne.jp mi6827 090-2946-6827 水門茂 1962/12/24
33 1 5 男性ソロ 風呂の会 1845dondon@gmail.com a9050 09096369050 浅井貴弘 1984/07/11
34 2 3 男性ソロ 野田達男 tatchi.sat111@docomo.ne.jp no0873 0901417-0873 野田達男 1950/9/14
35 2 5 男性ソロ 近藤隆 kondo2000gt@yahoo.ne.jp ko0666 09018300666 近藤隆 1962/6/28
36 3 3 男性ソロ 日吉将大 hiyomasa0034@gmail.com hi6343 080-2733-6343 日吉将大 1995/09/14
37 3 5 男性ソロ 松野昌紀 matsubottkuri11994730@gmail.com ma2606 090-1272-2606 松野昌紀 1972/9/30
38 4 3 男性ソロ 東京OLクラブ abe_1755_31@yahoo.co.jp a7102 090-2203-7102 阿部昌隆 1956/4/20
39 4 5 男性ソロ 白木稔人 amida48gan@icloud.com shi6048 090-7302-6048 白木稔人 1972/5/17
40 5 3 男性ソロ 大阪OLC t.okiura1961@gmail.com o1141 090-7888-1141 沖浦徹二 1961/4/29
41 5 5 男性ソロ Best Wishes jovi_bounce14@yahoo.co.jp ko0716 090−3284−0716 小林寿郎 1973/10/26
42 6 3 男性ソロ つるまいOLC junhagi68@gmail.com ha1001 080-3159-1001 萩原淳 1968/3/17
43 6 5 男性ソロ 脇屋貴司 takarinkuririn@gmail.com wa2659 080-3508-2659 脇屋貴司 1983/10/26
44 7 3 男性ソロ ㈱大垣ケーブルテレビ so-kishida@ogaki-tv.co.jp ki1207 0584-82-1207 岸田爽 2001/8/12
45 7 5 男性ソロ 前川一彦 yoshino-chuo@docomo.ne.jp ma2351 090-1074-2351 前川一彦 不明
46 8 3 男性ソロ ㈱大垣ケーブルテレビ ta-shiba@ogaki-tv.co.jp shi1207 芝建 1998/11/9
47 1 3 ファミリー うぱうぱアイランド serukasu@gmail.com i4200 09084584200 伊藤由美子 19920328 伊藤嘉仁 19930825 伊藤嘉利 20220913
48 1 5 ファミリー ながれぼし h2798723ddwyus@i.softbank.jp ta8317 090-1782-8317 高田めぐみ 1982/4/28 高田志穂 2013/12/5
49 2 3 ファミリー Team117 miki.maki0107@gmail.com sa3915 090-7678-3915 佐々木孝好 1970/12/20 佐々木享子 1977/8/25 佐々木実希 2012/1/21 佐々木麻妃 2016/7/1
50 2 5 ファミリー 500えん roumnet@yahoo.co.jp go6814 090-9890-6814 五百木弘道 1972/4/29 五百木芽彩 2015/3/13
51 3 3 ファミリー チームしぇいや rayrain3000@docomo.ne.jp ya2905 090-3056-2905 山本龍也 1976/3/14 山本聖也 2009/9/9 山本輝也 2015/6/3
52 3 5 ファミリー チームユズ livertish_v.g.35@docomo.ne.jp ko7822 090-7311-7822 小出龍 1983/2/27 小出柚希 2019/1/7
53 4 3 ファミリー Y'sファミリー inukisen@gmail.com ya1285 09042581285 安田千穂 1984/3/7 安田尚広 1978/1/18 安田雫 2014/9/2 安田葵 2018/5/13

View File

@ -0,0 +1,21 @@
FROM python:3.10-slim
WORKDIR /app
# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
# Python依存関係をインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションコードをコピー
COPY . .
# スクリプトに実行権限を付与
RUN chmod +x register_event_users.py
# デフォルトコマンド
CMD ["python", "register_event_users.py", "--help"]

View File

@ -0,0 +1,204 @@
# イベントユーザー登録システム
外部システムAPI仕様書.mdを前提に、ユーザーデータCSVから各ユーザーごとにユーザー登録、チーム登録、エントリー登録、イベント参加を行うPythonスクリプトです。
## 概要
このシステムは以下の処理を自動化します:
1. **カスタムユーザー登録 API**
- メールアドレスをキーに既存ユーザーを取得
- 検索がヒットしなければ、ユーザー登録
- 検索がヒットすれば、パスワードを更新
- event_codeに指定event_codeを設定
- zekken_number にゼッケン番号を入力
- team_name にチーム名を入力
2. **チーム登録、メンバー登録**
- 部門・時間・チーム名でチーム登録
- メンバーを1名ずつ7名まで登録
- それぞれダミーメールアドレスと名前と生年月日でメンバー登録
3. **エントリー登録**
- 指定されたイベントにチームを登録
4. **イベント参加**
- 登録したエントリーでイベント参加
## CSVファイル形式
CSVファイル`CPLIST/input/team2025.csv`)は以下の項目を持ちます:
```
部門別数,時間,部門,チーム名,メール,パスワード,電話番号,氏名1,誕生日1,氏名2,誕生日2,氏名3,誕生日3,氏名4,誕生日4,氏名5,誕生日5,氏名6,誕生日6,氏名7,誕生日7,,
```
### 項目説明
- **部門別数**: 部門の番号
- **時間**: 競技時間
- **部門**: 競技部門名
- **チーム名**: チーム名
- **メール**: 代表者メールアドレス
- **パスワード**: パスワード
- **電話番号**: 代表者電話番号
- **氏名1〜7**: チームメンバーの氏名最大7名
- **誕生日1〜7**: チームメンバーの生年月日YYYY/MM/DD形式
## 使用方法
### 1. 基本的な実行
```bash
# デフォルトイベントコード大垣2509で実行
./run_event_registration.sh
# 指定したイベントコードで実行
./run_event_registration.sh "大垣2509"
```
### 2. テスト実行DRY RUN
実際のAPI呼び出しを行わずに処理の流れを確認
```bash
./run_event_registration.sh "大垣2509" --dry-run
```
### 3. カスタムCSVファイルを使用
```bash
./run_event_registration.sh "大垣2509" --csv-file CPLIST/input/custom_teams.csv
```
### 4. カスタムAPI URLを指定
```bash
./run_event_registration.sh "大垣2509" --base-url http://production-server:8000
```
### 5. Pythonスクリプトを直接実行
```bash
python register_event_users.py --event_code "大垣2509" --csv_file CPLIST/input/team2025.csv --dry_run
```
## Docker Composeでの実行
### 環境変数設定
```bash
export EVENT_CODE="大垣2509"
export CSV_FILE="CPLIST/input/team2025.csv"
export BASE_URL="http://web:8000"
export DRY_RUN="true" # テスト実行の場合
```
### 実行
```bash
docker-compose -f docker-compose.event-registration.yml up --build
```
## オプション
| オプション | 説明 | デフォルト値 |
|-----------|------|-------------|
| `--event_code` | イベントコード | 必須 |
| `--csv_file` | CSVファイルパス | `CPLIST/input/team2025.csv` |
| `--base_url` | APIベースURL | `http://localhost:8000` |
| `--dry_run` | テスト実行フラグ | False |
## ログ
- 実行ログは `logs/register_event_users.log` に出力されます
- コンソールにも同時出力されます
## 処理統計
処理完了後、以下の統計情報が表示されます:
- 処理完了チーム数
- 作成ユーザー数
- 更新ユーザー数
- 登録チーム数
- 作成エントリー数
- 参加登録数
- エラー数とその詳細
## 注意事項
1. **API認証**: システムが稼働していることを確認してください
2. **CSVファイル**: 必要な項目が正しく入力されていることを確認してください
3. **重複処理**: 同じデータを複数回実行すると重複エラーが発生する可能性があります
4. **メール認証**: 新規ユーザー登録時はメール認証が必要な場合があります
## トラブルシューティング
### よくあるエラー
1. **CSVファイルが見つからない**
```
エラー: CSVファイルが見つかりません: CPLIST/input/team2025.csv
```
→ CSVファイルのパスを確認してください
2. **API接続エラー**
```
エラー: APIサーバーに接続できません
```
→ BASE_URLが正しいか、サーバーが稼働しているか確認してください
3. **重複ゼッケン番号エラー**
```
チーム登録エラー: このゼッケン番号は既に使用されています
```
→ 既に登録済みのデータを再実行しようとしています
### ログの確認
```bash
# リアルタイムでログを確認
tail -f logs/register_event_users.log
# エラーのみを確認
grep ERROR logs/register_event_users.log
```
## 開発者向け情報
### ファイル構成
```
rogaining_srv/
├── register_event_users.py # メインスクリプト
├── run_event_registration.sh # 実行スクリプト
├── docker-compose.event-registration.yml # Docker Compose設定
├── Dockerfile.event_registration # Dockerfile
├── CPLIST/input/team2025.csv # CSVデータファイル
└── logs/register_event_users.log # ログファイル
```
### API エンドポイント
使用するAPIエンドポイント
- `POST /api/register/` - ユーザー仮登録
- `POST /api/login/` - ログイン
- `POST /api/register_team` - チーム登録
- `POST /api/teams/{team_id}/members/` - メンバー追加
- `POST /api/entry/` - エントリー登録
- `POST /api/start_from_rogapp` - イベント参加
### カスタマイズ
処理をカスタマイズする場合は、`register_event_users.py`の以下のメソッドを編集してください:
- `get_or_create_user()` - ユーザー登録ロジック
- `register_team_and_members()` - チーム登録ロジック
- `create_event_entry()` - エントリー登録ロジック
- `participate_in_event()` - イベント参加ロジック
## ライセンス
このプロジェクトはロゲイニングシステムの一部です。

319
check_checkin_status.py Normal file
View File

@ -0,0 +1,319 @@
#!/usr/bin/env python3
"""
チェックイン機能確認ツール: 総合的にチェックイン機能の状態を調査
"""
import subprocess
import requests
import json
from datetime import datetime
import time
def check_checkin_api_status():
"""
チェックインAPIの基本動作確認
"""
print("🔍 チェックインAPI動作確認")
print("=" * 50)
# 基本的な接続確認
test_urls = [
"http://localhost:8100/gifuroge/checkin_from_rogapp",
"http://localhost:8100/api/checkin_from_rogapp"
]
for url in test_urls:
try:
# GETリクエストでエンドポイントの存在確認
response = requests.get(url, timeout=5)
print(f"{url} → HTTP {response.status_code}")
if response.status_code == 405:
print(f" 💡 405 Method Not Allowed は正常POSTのみ許可")
elif response.status_code == 404:
print(f" ❌ 404 Not Found - エンドポイントが見つからない")
except requests.exceptions.ConnectionError:
print(f"{url} → 接続エラー")
except Exception as e:
print(f"{url} → エラー: {e}")
print()
def test_checkin_with_real_data():
"""
実際のデータでチェックインテスト
"""
print("🎯 実際のデータでチェックインテスト")
print("-" * 50)
# 実際のイベントとチームを取得
try:
result = subprocess.run([
'docker', 'compose', 'exec', 'app', 'python', 'manage.py', 'shell', '-c',
"""
from rog.models import NewEvent2, Entry, Team
# 最新のイベント取得
event = NewEvent2.objects.first()
if event:
print(f"EVENT:{event.event_name}")
# そのイベントのエントリー取得
entry = Entry.objects.filter(event=event).first()
if entry and entry.team:
print(f"TEAM:{entry.team.team_name}")
print(f"ZEKKEN:{entry.zekken_number}")
# スタート済みかチェック
from rog.models import GpsLog
start_log = GpsLog.objects.filter(
zekken_number=entry.zekken_number,
event_code=event.event_name,
cp_number='START'
).first()
print(f"STARTED:{bool(start_log)}")
else:
print("TEAM:None")
else:
print("EVENT:None")
"""
], capture_output=True, text=True)
lines = result.stdout.strip().split('\n')
event_name = None
team_name = None
zekken_number = None
is_started = False
for line in lines:
if line.startswith('EVENT:'):
event_name = line.split(':', 1)[1]
elif line.startswith('TEAM:'):
team_name = line.split(':', 1)[1]
elif line.startswith('ZEKKEN:'):
zekken_number = line.split(':', 1)[1]
elif line.startswith('STARTED:'):
is_started = line.split(':', 1)[1] == 'True'
print(f"📊 取得したテストデータ:")
print(f" イベント: {event_name}")
print(f" チーム: {team_name}")
print(f" ゼッケン: {zekken_number}")
print(f" スタート済み: {is_started}")
if event_name and team_name and event_name != 'None' and team_name != 'None':
# チェックインテスト実行
test_data = {
"event_code": event_name,
"team_name": team_name,
"cp_number": "1",
"image": "data:image/jpeg;base64,test",
"buy_flag": False
}
print(f"\n🚀 チェックインテスト実行:")
print(f" URL: http://localhost:8100/api/checkin_from_rogapp")
print(f" データ: {json.dumps(test_data, ensure_ascii=False, indent=2)}")
try:
response = requests.post(
"http://localhost:8100/api/checkin_from_rogapp",
json=test_data,
headers={'Content-Type': 'application/json'},
timeout=10
)
print(f"\n📥 レスポンス:")
print(f" ステータス: HTTP {response.status_code}")
print(f" 内容: {response.text}")
if response.status_code == 400:
response_data = response.json()
if "スタートしていません" in response_data.get('message', ''):
print(f"\n💡 スタート処理が必要です。start_from_rogapp APIを先に実行してください。")
return test_start_api(event_name, team_name)
except Exception as e:
print(f"❌ チェックインテストエラー: {e}")
else:
print(f"❌ テストデータが不足しています")
except Exception as e:
print(f"❌ データ取得エラー: {e}")
def test_start_api(event_name, team_name):
"""
スタートAPIのテスト
"""
print(f"\n🏁 スタートAPIテスト")
print("-" * 30)
start_data = {
"event_code": event_name,
"team_name": team_name,
"image": "data:image/jpeg;base64,start_test"
}
try:
response = requests.post(
"http://localhost:8100/gifuroge/start_from_rogapp",
json=start_data,
headers={'Content-Type': 'application/json'},
timeout=10
)
print(f"📥 スタートAPIレスポンス:")
print(f" ステータス: HTTP {response.status_code}")
print(f" 内容: {response.text}")
if response.status_code == 200:
print(f"✅ スタート成功!チェックインを再試行します...")
time.sleep(1)
# チェックインを再試行
test_checkin_after_start(event_name, team_name)
except Exception as e:
print(f"❌ スタートAPIエラー: {e}")
def test_checkin_after_start(event_name, team_name):
"""
スタート後のチェックインテスト
"""
print(f"\n🎯 スタート後チェックインテスト")
print("-" * 30)
checkin_data = {
"event_code": event_name,
"team_name": team_name,
"cp_number": "1",
"image": "data:image/jpeg;base64,checkin_test",
"buy_flag": False
}
try:
response = requests.post(
"http://localhost:8100/api/checkin_from_rogapp",
json=checkin_data,
headers={'Content-Type': 'application/json'},
timeout=10
)
print(f"📥 チェックインレスポンス:")
print(f" ステータス: HTTP {response.status_code}")
print(f" 内容: {response.text}")
if response.status_code == 200:
print(f"🎉 チェックイン成功!")
elif response.status_code == 400:
print(f"⚠️ チェックイン失敗400")
except Exception as e:
print(f"❌ チェックインエラー: {e}")
def check_recent_logs():
"""
最近のログを確認
"""
print(f"\n📋 最近のチェックイン関連ログ")
print("-" * 50)
try:
result = subprocess.run([
'docker', 'compose', 'logs', '--tail=30', 'app'
], capture_output=True, text=True)
lines = result.stdout.split('\n')
checkin_logs = []
for line in lines:
if any(keyword in line.lower() for keyword in ['checkin', 'start', 'gpslog', '502', '400', '405']):
checkin_logs.append(line)
if checkin_logs:
print("🔍 関連ログ:")
for log in checkin_logs[-10:]: # 最新10件
print(f" {log}")
else:
print(" 📝 チェックイン関連のログが見つかりませんでした")
except Exception as e:
print(f"❌ ログ確認エラー: {e}")
def check_database_status():
"""
データベースの状態確認
"""
print(f"\n💾 データベース状態確認")
print("-" * 50)
try:
result = subprocess.run([
'docker', 'compose', 'exec', 'app', 'python', 'manage.py', 'shell', '-c',
"""
from rog.models import GpsLog, NewEvent2, Entry
import datetime
# 最近のGpsLogエントリー
recent_logs = GpsLog.objects.order_by('-id')[:5]
print(f"RECENT_LOGS:{len(recent_logs)}")
for log in recent_logs:
print(f"LOG:{log.id}|{log.event_code}|{log.zekken_number}|{log.cp_number}|{log.checkin_time}")
# イベント数
event_count = NewEvent2.objects.count()
print(f"EVENTS:{event_count}")
# エントリー数
entry_count = Entry.objects.count()
print(f"ENTRIES:{entry_count}")
"""
], capture_output=True, text=True)
lines = result.stdout.strip().split('\n')
for line in lines:
if line.startswith('RECENT_LOGS:'):
count = line.split(':', 1)[1]
print(f" 最近のGpsLogエントリー: {count}")
elif line.startswith('LOG:'):
parts = line.split(':', 1)[1].split('|')
if len(parts) >= 5:
print(f" ID:{parts[0]} イベント:{parts[1]} ゼッケン:{parts[2]} CP:{parts[3]} 時刻:{parts[4]}")
elif line.startswith('EVENTS:'):
count = line.split(':', 1)[1]
print(f" 総イベント数: {count}")
elif line.startswith('ENTRIES:'):
count = line.split(':', 1)[1]
print(f" 総エントリー数: {count}")
except Exception as e:
print(f"❌ データベース確認エラー: {e}")
def main():
"""
メイン実行関数
"""
print("🚀 チェックイン機能 総合確認ツール")
print(f"実行時刻: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 60)
# 1. API基本動作確認
check_checkin_api_status()
# 2. データベース状態確認
check_database_status()
# 3. 実際のデータでテスト
test_checkin_with_real_data()
# 4. 最近のログ確認
check_recent_logs()
print(f"\n📊 確認完了")
print("=" * 60)
print("💡 次のステップ:")
print(" 1. 502エラーが出る場合 → nginx設定確認")
print(" 2. 405エラーが出る場合 → URLパス確認")
print(" 3. 400エラーが出る場合 → データ確認")
print(" 4. スタート前エラー → start_from_rogapp API実行")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,34 @@
version: '3.8'
services:
event-registration:
build:
context: .
dockerfile: Dockerfile.event_registration
container_name: rogaining_event_registration
volumes:
- ./CPLIST/input:/app/CPLIST/input:ro
- ./logs:/app/logs
environment:
- EVENT_CODE=${EVENT_CODE:-大垣2509}
- CSV_FILE=${CSV_FILE:-CPLIST/input/team2025.csv}
- BASE_URL=${BASE_URL:-http://web:8000}
- DRY_RUN=${DRY_RUN:-false}
networks:
- rogaining_network
depends_on:
- web
command: >
sh -c "
echo 'イベントユーザー登録処理を開始します...' &&
python register_event_users.py
--event_code $${EVENT_CODE}
--csv_file $${CSV_FILE}
--base_url $${BASE_URL}
$${DRY_RUN:+--dry_run}
"
# 既存のサービスwebなどを参照するためのネットワーク定義
networks:
rogaining_network:
external: true

528
register_event_users.py Normal file
View File

@ -0,0 +1,528 @@
#!/usr/bin/env python
"""
イベントユーザー登録スクリプト
外部システムAPI仕様書.mdを前提に、ユーザーデータCSVから、
各ユーザーごとにユーザー登録、チーム登録、エントリー登録、イベント参加を行う
docker composeで実施するPythonスクリプト
使用方法:
python register_event_users.py --event_code 大垣2509
ユーザーデータのCSVは以下の項目を持つ
部門別数,時間,部門,チーム名,メール,パスワード,電話番号,氏名1,誕生日1,氏名2,誕生日2,氏名3,誕生日3,氏名4,誕生日4,氏名5,誕生日5,氏名6,誕生日6,氏名7,誕生日7,,
"""
import os
import sys
import csv
import requests
import argparse
import logging
from datetime import datetime, date
import time
import json
from typing import Dict, List, Optional, Tuple
# ログ設定
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('register_event_users.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class EventUserRegistration:
def __init__(self, event_code: str, base_url: str = "http://localhost:8000", dry_run: bool = False):
"""
イベントユーザー登録クラス
Args:
event_code: イベントコード(例: 大垣2509
base_url: APIベースURL
dry_run: テスト実行フラグ
"""
self.event_code = event_code
self.base_url = base_url.rstrip('/')
self.dry_run = dry_run
self.session = requests.Session()
self.admin_token = None
# 統計情報
self.stats = {
'processed_teams': 0,
'users_created': 0,
'users_updated': 0,
'teams_registered': 0,
'entries_created': 0,
'participations_created': 0,
'errors': []
}
logger.info(f"Event User Registration initialized for event: {event_code}")
if dry_run:
logger.info("DRY RUN MODE - No actual API calls will be made")
def get_or_create_user(self, email: str, password: str, firstname: str, lastname: str,
date_of_birth: str, phone: str) -> Tuple[bool, Optional[str], Optional[str]]:
"""
メールアドレスをキーに既存ユーザーを取得、存在しなければ新規作成
Args:
email: メールアドレス
password: パスワード
firstname: 名前
lastname: 姓
date_of_birth: 生年月日 (YYYY/MM/DD形式)
phone: 電話番号
Returns:
Tuple[success, user_id, token]
"""
if self.dry_run:
logger.info(f"[DRY RUN] Would get or create user: {email}")
return True, "dummy_user_id", "dummy_token"
try:
# まずログインを試行して既存ユーザーかチェック
login_data = {
"identifier": email,
"password": password
}
response = self.session.post(f"{self.base_url}/login/", json=login_data)
if response.status_code == 200:
# 既存ユーザーの場合、パスワード更新実際にはパスワード更新APIが必要
result = response.json()
token = result.get('token')
user_id = result.get('user', {}).get('id')
logger.info(f"既存ユーザーでログイン成功: {email}")
self.stats['users_updated'] += 1
return True, str(user_id), token
elif response.status_code == 401:
# ユーザーが存在しないか、パスワードが間違っている場合、新規登録を試行
return self._create_new_user(email, password, firstname, lastname, date_of_birth)
else:
logger.error(f"ログイン試行でエラー: {response.status_code} - {response.text}")
return False, None, None
except Exception as e:
logger.error(f"ユーザー認証エラー: {str(e)}")
return False, None, None
def _create_new_user(self, email: str, password: str, firstname: str, lastname: str,
date_of_birth: str) -> Tuple[bool, Optional[str], Optional[str]]:
"""
新規ユーザーを作成
"""
try:
# 生年月日をYYYY-MM-DD形式に変換
if '/' in date_of_birth:
date_parts = date_of_birth.split('/')
if len(date_parts) == 3:
birth_date = f"{date_parts[0]}-{date_parts[1].zfill(2)}-{date_parts[2].zfill(2)}"
else:
birth_date = "1990-01-01" # デフォルト値
else:
birth_date = date_of_birth
# 仮ユーザー登録
register_data = {
"email": email,
"password": password,
"firstname": firstname,
"lastname": lastname,
"date_of_birth": birth_date,
"female": False, # デフォルト値
"is_rogaining": True
}
response = self.session.post(f"{self.base_url}/register/", json=register_data)
if response.status_code in [200, 201]:
logger.info(f"仮ユーザー登録成功: {email}")
# 実際のシステムでは、メール認証コードを使って本登録を完了する必要があります
# ここでは簡略化のため、直接ログインを試行します
time.sleep(1) # 少し待機
login_data = {
"identifier": email,
"password": password
}
login_response = self.session.post(f"{self.base_url}/login/", json=login_data)
if login_response.status_code == 200:
result = login_response.json()
token = result.get('token')
user_id = result.get('user', {}).get('id')
logger.info(f"新規ユーザーのログイン成功: {email}")
self.stats['users_created'] += 1
return True, str(user_id), token
else:
logger.warning(f"新規ユーザーのログインに失敗: {email}")
# メール認証が必要な可能性があります
self.stats['users_created'] += 1
return True, "pending_verification", None
else:
error_msg = response.text
logger.error(f"ユーザー登録失敗: {email} - {error_msg}")
return False, None, None
except Exception as e:
logger.error(f"新規ユーザー作成エラー: {str(e)}")
return False, None, None
def register_team_and_members(self, team_data: Dict, zekken_number: int) -> Tuple[bool, Optional[str]]:
"""
チーム登録とメンバー登録
Args:
team_data: チームデータCSVの1行分
zekken_number: ゼッケン番号
Returns:
Tuple[success, team_id]
"""
if self.dry_run:
logger.info(f"[DRY RUN] Would register team: {team_data['チーム名']} with zekken: {zekken_number}")
return True, "dummy_team_id"
try:
# チーム登録データを準備
register_data = {
"zekken_number": zekken_number,
"event_code": self.event_code,
"team_name": team_data['チーム名'],
"class_name": team_data['部門'],
"password": team_data['パスワード']
}
# チーム登録API呼び出し
response = self.session.post(f"{self.base_url}/register_team", json=register_data)
if response.status_code in [200, 201]:
result = response.json()
if result.get('status') == 'OK':
team_id = result.get('team_id')
logger.info(f"チーム登録成功: {team_data['チーム名']} (zekken: {zekken_number})")
self.stats['teams_registered'] += 1
# メンバー登録
success = self._register_team_members(team_data, team_id)
return success, str(team_id)
else:
logger.error(f"チーム登録エラー: {result.get('message')}")
return False, None
else:
logger.error(f"チーム登録API呼び出し失敗: {response.status_code} - {response.text}")
return False, None
except Exception as e:
logger.error(f"チーム登録エラー: {str(e)}")
return False, None
def _register_team_members(self, team_data: Dict, team_id: str) -> bool:
"""
チームメンバーを登録最大7名
Args:
team_data: チームデータ
team_id: チームID
Returns:
成功フラグ
"""
if self.dry_run:
logger.info(f"[DRY RUN] Would register team members for team: {team_id}")
return True
try:
success_count = 0
# メンバー1-7を順番に処理
for i in range(1, 8):
name_key = f'氏名{i}'
birth_key = f'誕生日{i}'
if name_key in team_data and team_data[name_key].strip():
name = team_data[name_key].strip()
birth_date = team_data.get(birth_key, '1990/01/01')
# ダミーメールアドレスを生成
dummy_email = f"{name.replace(' ', '')}_{team_id}_{i}@dummy.local"
# メンバー追加データ
member_data = {
"email": dummy_email,
"firstname": name.split()[0] if ' ' in name else name,
"lastname": name.split()[-1] if ' ' in name else "",
"date_of_birth": birth_date.replace('/', '-'),
"female": False # デフォルト値
}
# メンバー追加API呼び出し
response = self.session.post(
f"{self.base_url}/teams/{team_id}/members/",
json=member_data
)
if response.status_code in [200, 201]:
logger.info(f"メンバー追加成功: {name} -> チーム{team_id}")
success_count += 1
else:
logger.warning(f"メンバー追加失敗: {name} - {response.text}")
logger.info(f"チーム{team_id}のメンバー登録完了: {success_count}")
return success_count > 0
except Exception as e:
logger.error(f"メンバー登録エラー: {str(e)}")
return False
def create_event_entry(self, team_id: str, category_id: int = 1) -> Tuple[bool, Optional[str]]:
"""
イベントエントリー登録
Args:
team_id: チームID
category_id: カテゴリID
Returns:
Tuple[success, entry_id]
"""
if self.dry_run:
logger.info(f"[DRY RUN] Would create event entry for team: {team_id}")
return True, "dummy_entry_id"
try:
# エントリーデータ準備
entry_data = {
"team_id": team_id,
"event_code": self.event_code,
"category": category_id,
"entry_date": datetime.now().strftime("%Y-%m-%d")
}
# エントリー登録API呼び出し
response = self.session.post(f"{self.base_url}/entry/", json=entry_data)
if response.status_code in [200, 201]:
result = response.json()
entry_id = result.get('id') or result.get('entry_id')
logger.info(f"エントリー登録成功: team_id={team_id}, entry_id={entry_id}")
self.stats['entries_created'] += 1
return True, str(entry_id)
else:
logger.error(f"エントリー登録失敗: {response.status_code} - {response.text}")
return False, None
except Exception as e:
logger.error(f"エントリー登録エラー: {str(e)}")
return False, None
def participate_in_event(self, entry_id: str, zekken_number: int) -> bool:
"""
イベント参加処理
Args:
entry_id: エントリーID
zekken_number: ゼッケン番号
Returns:
成功フラグ
"""
if self.dry_run:
logger.info(f"[DRY RUN] Would participate in event: entry_id={entry_id}, zekken={zekken_number}")
return True
try:
# イベント参加データ準備
participation_data = {
"entry_id": entry_id,
"event_code": self.event_code,
"zekken_number": zekken_number,
"participation_date": datetime.now().strftime("%Y-%m-%d")
}
# イベント参加API呼び出し実際のAPIエンドポイントに合わせて調整が必要
response = self.session.post(f"{self.base_url}/start_from_rogapp", json=participation_data)
if response.status_code in [200, 201]:
logger.info(f"イベント参加成功: entry_id={entry_id}, zekken={zekken_number}")
self.stats['participations_created'] += 1
return True
else:
logger.warning(f"イベント参加API呼び出し結果: {response.status_code} - {response.text}")
# 参加処理は必須ではないため、警告のみでTrueを返す
return True
except Exception as e:
logger.error(f"イベント参加エラー: {str(e)}")
return True # 参加処理は必須ではないため、エラーでもTrueを返す
def process_csv_file(self, csv_file_path: str) -> bool:
"""
CSVファイルを処理してユーザー登録からイベント参加まで実行
Args:
csv_file_path: CSVファイルパス
Returns:
成功フラグ
"""
try:
if not os.path.exists(csv_file_path):
logger.error(f"CSVファイルが見つかりません: {csv_file_path}")
return False
with open(csv_file_path, 'r', encoding='utf-8') as file:
csv_reader = csv.DictReader(file)
for row_num, row in enumerate(csv_reader, start=1):
try:
self._process_team_row(row, row_num)
# API呼び出し間隔を空ける
if not self.dry_run:
time.sleep(0.5)
except Exception as e:
error_msg = f"{row_num}の処理でエラー: {str(e)}"
logger.error(error_msg)
self.stats['errors'].append(error_msg)
continue
return True
except Exception as e:
logger.error(f"CSVファイル処理エラー: {str(e)}")
return False
def _process_team_row(self, row: Dict, row_num: int):
"""
CSVの1行1チームを処理
Args:
row: CSV行データ
row_num: 行番号
"""
team_name = row.get('チーム名', '').strip()
email = row.get('メール', '').strip()
password = row.get('password', '').strip()
phone = row.get('電話番号', '').strip()
if not all([team_name, email, password]):
logger.warning(f"{row_num}: 必須項目が不足 - チーム名={team_name}, メール={email}")
return
logger.info(f"{row_num}の処理開始: チーム={team_name}")
# ゼッケン番号を生成(行番号ベース、実際の運用では別途管理が必要)
zekken_number = row_num
# 2-1. カスタムユーザー登録
# 最初のメンバー(氏名1)をメインユーザーとして使用
firstname = row.get('氏名1', team_name).strip()
lastname = ""
if ' ' in firstname:
parts = firstname.split(' ', 1)
firstname = parts[0]
lastname = parts[1]
date_of_birth = row.get('誕生日1', '1990/01/01')
user_success, user_id, token = self.get_or_create_user(
email, password, firstname, lastname, date_of_birth, phone
)
if not user_success:
logger.error(f"{row_num}: ユーザー登録/取得失敗")
return
# 2-2. チーム登録、メンバー登録
team_success, team_id = self.register_team_and_members(row, zekken_number)
if not team_success:
logger.error(f"{row_num}: チーム登録失敗")
return
# 2-3. エントリー登録
entry_success, entry_id = self.create_event_entry(team_id)
if not entry_success:
logger.error(f"{row_num}: エントリー登録失敗")
return
# 2-4. イベント参加
participation_success = self.participate_in_event(entry_id, zekken_number)
if participation_success:
logger.info(f"{row_num}: 全処理完了 - チーム={team_name}, zekken={zekken_number}")
self.stats['processed_teams'] += 1
else:
logger.warning(f"{row_num}: イベント参加処理で警告")
def print_statistics(self):
"""
処理統計を出力
"""
logger.info("=== 処理統計 ===")
logger.info(f"処理完了チーム数: {self.stats['processed_teams']}")
logger.info(f"作成ユーザー数: {self.stats['users_created']}")
logger.info(f"更新ユーザー数: {self.stats['users_updated']}")
logger.info(f"登録チーム数: {self.stats['teams_registered']}")
logger.info(f"作成エントリー数: {self.stats['entries_created']}")
logger.info(f"参加登録数: {self.stats['participations_created']}")
logger.info(f"エラー数: {len(self.stats['errors'])}")
if self.stats['errors']:
logger.error("エラー詳細:")
for error in self.stats['errors']:
logger.error(f" - {error}")
def main():
parser = argparse.ArgumentParser(description='イベントユーザー登録スクリプト')
parser.add_argument('--event_code', required=True, help='イベントコード(例: 大垣2509')
parser.add_argument('--csv_file', default='CPLIST/input/team2025.csv', help='CSVファイルパス')
parser.add_argument('--base_url', default='http://localhost:8000', help='APIベースURL')
parser.add_argument('--dry_run', action='store_true', help='テスト実行実際のAPI呼び出しなし')
args = parser.parse_args()
logger.info(f"イベントユーザー登録処理開始: event_code={args.event_code}")
# 登録処理実行
registration = EventUserRegistration(
event_code=args.event_code,
base_url=args.base_url,
dry_run=args.dry_run
)
success = registration.process_csv_file(args.csv_file)
# 統計出力
registration.print_statistics()
if success:
logger.info("処理が正常に完了しました")
return 0
else:
logger.error("処理中にエラーが発生しました")
return 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -125,19 +125,38 @@ class TeamRegistrationProcessor:
self.log(f"DRY RUN: Event with code '{self.event_code}' would be searched")
# ダミーイベントオブジェクトを作成
class DummyEvent:
def __init__(self):
self.event_name = f"Dummy Event for {self.event_code}"
self.event_code = self.event_code
self.event = DummyEvent()
def __init__(self, event_code):
self.event_name = f"Dummy Event for {event_code}"
self.event_code = event_code
self.event = DummyEvent(self.event_code)
return
else:
raise ValueError(f"Event with code '{self.event_code}' not found")
# カテゴリ情報をプリロード
if not self.dry_run:
for category in NewCategory.objects.all():
hours = int(category.duration.total_seconds() // 3600)
key = (category.category_name, hours)
self.categories[key] = category
else:
# DRY RUNの場合はダミーカテゴリを作成
dummy_categories = [
('一般', 3), ('一般', 5), ('ファミリー', 3), ('ファミリー', 5),
('男性ソロ', 3), ('男性ソロ', 5), ('女性ソロ', 3), ('女性ソロ', 5)
]
for cat_name, hours in dummy_categories:
class DummyCategory:
def __init__(self, name, hours):
self.category_name = name
self.category_number = len(self.categories) + 1
self.duration = timedelta(hours=hours)
self.num_of_member = 7
self.family = (name == 'ファミリー')
self.female = (name == '女性ソロ')
self.trial = False
self.categories[(cat_name, hours)] = DummyCategory(cat_name, hours)
self.log(f"利用可能なカテゴリ: {list(self.categories.keys())}")
@ -226,16 +245,16 @@ class TeamRegistrationProcessor:
self.log(f"DRY RUN: カテゴリ作成 - {department} ({hours_int}時間)")
# ダミーカテゴリオブジェクトを作成
class DummyCategory:
def __init__(self):
def __init__(self, processor):
self.category_name = department
self.category_number = len(self.categories) + 1
self.category_number = len(processor.categories) + 1
self.duration = timedelta(hours=hours_int)
self.num_of_member = 7
self.family = (department == 'ファミリー')
self.female = (department == '女性ソロ')
self.trial = False
category = DummyCategory()
category = DummyCategory(self)
else:
category = NewCategory.objects.create(
category_name=department,
@ -446,7 +465,7 @@ class TeamRegistrationProcessor:
lastname=user.lastname,
date_of_birth=user.date_of_birth,
female=user.female,
is_temporary=True if user.email.startswith('dummy_') else False
is_temporary=True if hasattr(user, 'email') and user.email.startswith('dummy_') else False
)
self.log(f"メンバー追加: {user.firstname} to {team.team_name}")
self.stats['members_created'] += 1
@ -510,7 +529,7 @@ class TeamRegistrationProcessor:
entry_member = EntryMember.objects.create(
entry=entry,
member=member,
is_temporary=member.is_temporary
is_temporary=getattr(member, 'is_temporary', False)
)
self.log(f"参加登録: {member.user.firstname}")
self.stats['participations_created'] += 1

95
run_event_registration.sh Executable file
View File

@ -0,0 +1,95 @@
#!/bin/bash
# イベントユーザー登録実行スクリプト
#
# 使用方法:
# ./run_event_registration.sh [EVENT_CODE] [OPTIONS]
#
# 例:
# ./run_event_registration.sh 大垣2509
# ./run_event_registration.sh 大垣2509 --dry-run
# ./run_event_registration.sh 大垣2509 --csv-file CPLIST/input/custom_teams.csv
set -e
# デフォルト値
EVENT_CODE=${1:-"大垣2509"}
CSV_FILE="CPLIST/input/team2025.csv"
BASE_URL="http://localhost:8000"
DRY_RUN=""
# コマンドライン引数を解析
shift
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN="true"
shift
;;
--csv-file)
CSV_FILE="$2"
shift 2
;;
--base-url)
BASE_URL="$2"
shift 2
;;
--help)
echo "使用方法: $0 [EVENT_CODE] [OPTIONS]"
echo ""
echo "オプション:"
echo " --dry-run テスト実行実際のAPI呼び出しなし"
echo " --csv-file FILE CSVファイルパスデフォルト: CPLIST/input/team2025.csv"
echo " --base-url URL APIベースURLデフォルト: http://localhost:8000"
echo " --help このヘルプを表示"
echo ""
echo "例:"
echo " $0 大垣2509"
echo " $0 大垣2509 --dry-run"
echo " $0 大垣2509 --csv-file CPLIST/input/custom_teams.csv"
exit 0
;;
*)
echo "不明なオプション: $1"
echo "ヘルプを表示するには --help を使用してください"
exit 1
;;
esac
done
echo "=== イベントユーザー登録処理 ==="
echo "イベントコード: $EVENT_CODE"
echo "CSVファイル: $CSV_FILE"
echo "APIベースURL: $BASE_URL"
echo "テスト実行: ${DRY_RUN:-false}"
echo "================================"
# CSVファイルの存在確認
if [ ! -f "$CSV_FILE" ]; then
echo "エラー: CSVファイルが見つかりません: $CSV_FILE"
exit 1
fi
# Docker Composeファイルの存在確認
if [ ! -f "docker-compose.event-registration.yml" ]; then
echo "エラー: docker-compose.event-registration.yml が見つかりません"
exit 1
fi
# ログディレクトリを作成
mkdir -p logs
# 環境変数を設定してDocker Composeを実行
export EVENT_CODE="$EVENT_CODE"
export CSV_FILE="$CSV_FILE"
export BASE_URL="$BASE_URL"
export DRY_RUN="$DRY_RUN"
echo "Docker Composeでイベントユーザー登録処理を開始します..."
# Docker Composeを実行
docker-compose -f docker-compose.event-registration.yml up --build --remove-orphans
echo ""
echo "=== 処理完了 ==="
echo "ログファイルを確認してください: logs/register_event_users.log"

View File

@ -0,0 +1,42 @@
外部システムAPI仕様書.md を前提に、ユーザーデータcsvから、
各ユーザーごとにユーザー登録、チーム登録、エントリー登録、イベント参加を行う
docker compose で実施するPythonスクリプトを作成しなさい。
ユーザーデータのCSVは以下の項目を持つ。
部門別数,時間,部門,チーム名,メール,パスワード,電話番号,氏名1,誕生日1,氏名2,誕生日2,氏名3,誕生日3,氏名4,誕生日4,氏名5,誕生日5,氏名6,誕生日6,氏名7,誕生日7,,
1. 起動パラメータで、event_code=大垣2509 を指定する.
2. CSV(CPLIST/input/team2025.csv)を読みこみ、各行ごとに下記の処理を行う。
2-1. カスタムユーザー登録 API
# メールアドレスをキーに既存ユーザーを取得
検索がヒットしなければ、ユーザー登録する。
検索がヒットすれば、パスワードを更新する。
event_codeに指定event_codeを設定
zekken_number に zekken を入力
team_name に team名を入れる
2-2. チーム登録、メンバー登録
# 部門・時間・チーム名でチーム登録
# メンバーを1名ずつ7名まで登録
## それぞれダミーメアドと名前と生年月日でメンバー登録
2-3. エントリー登録
# 指定されたイベントにチームを9/6で登録する。
2-4. イベント参加
# 登録したエントリーでイベント参加する。