checkin status tool
This commit is contained in:
53
CPLIST/input/team2025.csv
Normal file
53
CPLIST/input/team2025.csv
Normal 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,090−3284−0716,小林寿郎,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-kishida@ogaki-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,ファミリー,Y'sファミリー,inukisen@gmail.com,ya1285,09042581285,安田千穂,1984/3/7,安田尚広,1978/1/18,安田雫,2014/9/2,安田葵,2018/5/13,,,,,,,,
|
||||||
|
21
Dockerfile.event_registration
Normal file
21
Dockerfile.event_registration
Normal 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"]
|
||||||
204
EVENT_REGISTRATION_README.md
Normal file
204
EVENT_REGISTRATION_README.md
Normal 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
319
check_checkin_status.py
Normal 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()
|
||||||
34
docker-compose.event-registration.yml
Normal file
34
docker-compose.event-registration.yml
Normal 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
528
register_event_users.py
Normal 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())
|
||||||
@ -125,19 +125,38 @@ class TeamRegistrationProcessor:
|
|||||||
self.log(f"DRY RUN: Event with code '{self.event_code}' would be searched")
|
self.log(f"DRY RUN: Event with code '{self.event_code}' would be searched")
|
||||||
# ダミーイベントオブジェクトを作成
|
# ダミーイベントオブジェクトを作成
|
||||||
class DummyEvent:
|
class DummyEvent:
|
||||||
def __init__(self):
|
def __init__(self, event_code):
|
||||||
self.event_name = f"Dummy Event for {self.event_code}"
|
self.event_name = f"Dummy Event for {event_code}"
|
||||||
self.event_code = self.event_code
|
self.event_code = event_code
|
||||||
self.event = DummyEvent()
|
self.event = DummyEvent(self.event_code)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Event with code '{self.event_code}' not found")
|
raise ValueError(f"Event with code '{self.event_code}' not found")
|
||||||
|
|
||||||
# カテゴリ情報をプリロード
|
# カテゴリ情報をプリロード
|
||||||
for category in NewCategory.objects.all():
|
if not self.dry_run:
|
||||||
hours = int(category.duration.total_seconds() // 3600)
|
for category in NewCategory.objects.all():
|
||||||
key = (category.category_name, hours)
|
hours = int(category.duration.total_seconds() // 3600)
|
||||||
self.categories[key] = category
|
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())}")
|
self.log(f"利用可能なカテゴリ: {list(self.categories.keys())}")
|
||||||
|
|
||||||
@ -226,16 +245,16 @@ class TeamRegistrationProcessor:
|
|||||||
self.log(f"DRY RUN: カテゴリ作成 - {department} ({hours_int}時間)")
|
self.log(f"DRY RUN: カテゴリ作成 - {department} ({hours_int}時間)")
|
||||||
# ダミーカテゴリオブジェクトを作成
|
# ダミーカテゴリオブジェクトを作成
|
||||||
class DummyCategory:
|
class DummyCategory:
|
||||||
def __init__(self):
|
def __init__(self, processor):
|
||||||
self.category_name = department
|
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.duration = timedelta(hours=hours_int)
|
||||||
self.num_of_member = 7
|
self.num_of_member = 7
|
||||||
self.family = (department == 'ファミリー')
|
self.family = (department == 'ファミリー')
|
||||||
self.female = (department == '女性ソロ')
|
self.female = (department == '女性ソロ')
|
||||||
self.trial = False
|
self.trial = False
|
||||||
|
|
||||||
category = DummyCategory()
|
category = DummyCategory(self)
|
||||||
else:
|
else:
|
||||||
category = NewCategory.objects.create(
|
category = NewCategory.objects.create(
|
||||||
category_name=department,
|
category_name=department,
|
||||||
@ -446,7 +465,7 @@ class TeamRegistrationProcessor:
|
|||||||
lastname=user.lastname,
|
lastname=user.lastname,
|
||||||
date_of_birth=user.date_of_birth,
|
date_of_birth=user.date_of_birth,
|
||||||
female=user.female,
|
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.log(f"メンバー追加: {user.firstname} to {team.team_name}")
|
||||||
self.stats['members_created'] += 1
|
self.stats['members_created'] += 1
|
||||||
@ -510,7 +529,7 @@ class TeamRegistrationProcessor:
|
|||||||
entry_member = EntryMember.objects.create(
|
entry_member = EntryMember.objects.create(
|
||||||
entry=entry,
|
entry=entry,
|
||||||
member=member,
|
member=member,
|
||||||
is_temporary=member.is_temporary
|
is_temporary=getattr(member, 'is_temporary', False)
|
||||||
)
|
)
|
||||||
self.log(f"参加登録: {member.user.firstname}")
|
self.log(f"参加登録: {member.user.firstname}")
|
||||||
self.stats['participations_created'] += 1
|
self.stats['participations_created'] += 1
|
||||||
|
|||||||
95
run_event_registration.sh
Executable file
95
run_event_registration.sh
Executable 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"
|
||||||
42
イベントユーザー登録
Normal file
42
イベントユーザー登録
Normal 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. イベント参加
|
||||||
|
|
||||||
|
# 登録したエントリーでイベント参加する。
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user