Spaces:
Sleeping
Sleeping
feat: フィールド仕様変更(ActivityFrequency・hasNoFee削除・新フィールド追加)
Browse files- ActivityFrequency Enumを追加(WEEKLY_5_PLUS/WEEKLY_3_4/WEEKLY_1_2/MONTHLY_1_3/LESS_THAN_MONTHLY)
- hasNoFeeフィールドを削除(annualFee=0で代替)
- activityFrequencyNote, memberNote, otherCosts フィールドを追加
- データ変換スクリプトに旧→新Enum値マッピングを追加
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- app/main.py +3 -1
- schemas/circles.py +19 -3
- scripts/2_create_circles_data.py +23 -2
app/main.py
CHANGED
|
@@ -144,9 +144,11 @@ def get_summary_data():
|
|
| 144 |
description=circle.description,
|
| 145 |
mainImage=image,
|
| 146 |
memberCount=circle.memberCount,
|
|
|
|
| 147 |
annualFee=circle.annualFee,
|
| 148 |
-
|
| 149 |
activityFrequency=circle.activityFrequency,
|
|
|
|
| 150 |
activityLocation=circle.activityLocation,
|
| 151 |
tags=circle.tags,
|
| 152 |
featureTags=circle.featureTags,
|
|
|
|
| 144 |
description=circle.description,
|
| 145 |
mainImage=image,
|
| 146 |
memberCount=circle.memberCount,
|
| 147 |
+
memberNote=circle.memberNote,
|
| 148 |
annualFee=circle.annualFee,
|
| 149 |
+
otherCosts=circle.otherCosts,
|
| 150 |
activityFrequency=circle.activityFrequency,
|
| 151 |
+
activityFrequencyNote=circle.activityFrequencyNote,
|
| 152 |
activityLocation=circle.activityLocation,
|
| 153 |
tags=circle.tags,
|
| 154 |
featureTags=circle.featureTags,
|
schemas/circles.py
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
|
|
| 1 |
from typing import Literal
|
| 2 |
from pydantic import BaseModel
|
| 3 |
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
class Image(BaseModel):
|
| 6 |
"""画像情報"""
|
| 7 |
url: str
|
|
@@ -56,6 +66,7 @@ class Circle(BaseModel):
|
|
| 56 |
|
| 57 |
# メンバー情報
|
| 58 |
memberCount: int | None = None
|
|
|
|
| 59 |
genderRatioMale: float | None = None
|
| 60 |
genderRatioFemale: float | None = None
|
| 61 |
|
|
@@ -64,7 +75,7 @@ class Circle(BaseModel):
|
|
| 64 |
|
| 65 |
# 金銭情報
|
| 66 |
annualFee: int | None = None
|
| 67 |
-
|
| 68 |
|
| 69 |
# タグ
|
| 70 |
tags: list[str] = []
|
|
@@ -72,6 +83,7 @@ class Circle(BaseModel):
|
|
| 72 |
|
| 73 |
# 活動情報
|
| 74 |
activityFrequency: str | None = None
|
|
|
|
| 75 |
activityTimeSlot: str | None = None
|
| 76 |
activityLocation: str | None = None # 活動場所
|
| 77 |
annualSchedule: list[AnnualScheduleItem] | None = None # 年間予定
|
|
@@ -106,9 +118,11 @@ class CircleSummary(BaseModel):
|
|
| 106 |
description: str | None = None
|
| 107 |
mainImage: Image | None = None
|
| 108 |
memberCount: int | None = None
|
|
|
|
| 109 |
annualFee: int | None = None
|
| 110 |
-
|
| 111 |
activityFrequency: str | None = None
|
|
|
|
| 112 |
activityLocation: str | None = None
|
| 113 |
tags: list[str] = []
|
| 114 |
featureTags: list[str] = []
|
|
@@ -135,9 +149,11 @@ class CircleDetail(BaseModel):
|
|
| 135 |
images: list[Image] = []
|
| 136 |
sns: list[Sns] = []
|
| 137 |
memberCount: int | None = None
|
|
|
|
| 138 |
annualFee: int | None = None
|
| 139 |
-
|
| 140 |
activityFrequency: str | None = None
|
|
|
|
| 141 |
activityLocation: str | None = None
|
| 142 |
annualSchedule: list[AnnualScheduleItem] | None = None
|
| 143 |
contactInfo: str | None = None
|
|
|
|
| 1 |
+
from enum import Enum
|
| 2 |
from typing import Literal
|
| 3 |
from pydantic import BaseModel
|
| 4 |
|
| 5 |
|
| 6 |
+
class ActivityFrequency(str, Enum):
|
| 7 |
+
"""活動頻度"""
|
| 8 |
+
WEEKLY_5_PLUS = "WEEKLY_5_PLUS" # 週5回以上
|
| 9 |
+
WEEKLY_3_4 = "WEEKLY_3_4" # 週3-4回
|
| 10 |
+
WEEKLY_1_2 = "WEEKLY_1_2" # 週1-2回
|
| 11 |
+
MONTHLY_1_3 = "MONTHLY_1_3" # 月1-3回
|
| 12 |
+
LESS_THAN_MONTHLY = "LESS_THAN_MONTHLY" # 月1回未満
|
| 13 |
+
|
| 14 |
+
|
| 15 |
class Image(BaseModel):
|
| 16 |
"""画像情報"""
|
| 17 |
url: str
|
|
|
|
| 66 |
|
| 67 |
# メンバー情報
|
| 68 |
memberCount: int | None = None
|
| 69 |
+
memberNote: str | None = None # メンバー数に関する備考
|
| 70 |
genderRatioMale: float | None = None
|
| 71 |
genderRatioFemale: float | None = None
|
| 72 |
|
|
|
|
| 75 |
|
| 76 |
# 金銭情報
|
| 77 |
annualFee: int | None = None
|
| 78 |
+
otherCosts: str | None = None # その他費用の説明
|
| 79 |
|
| 80 |
# タグ
|
| 81 |
tags: list[str] = []
|
|
|
|
| 83 |
|
| 84 |
# 活動情報
|
| 85 |
activityFrequency: str | None = None
|
| 86 |
+
activityFrequencyNote: str | None = None # 活動頻度に関する自由記述
|
| 87 |
activityTimeSlot: str | None = None
|
| 88 |
activityLocation: str | None = None # 活動場所
|
| 89 |
annualSchedule: list[AnnualScheduleItem] | None = None # 年間予定
|
|
|
|
| 118 |
description: str | None = None
|
| 119 |
mainImage: Image | None = None
|
| 120 |
memberCount: int | None = None
|
| 121 |
+
memberNote: str | None = None # メンバー数に関する備考
|
| 122 |
annualFee: int | None = None
|
| 123 |
+
otherCosts: str | None = None # その他費用の説明
|
| 124 |
activityFrequency: str | None = None
|
| 125 |
+
activityFrequencyNote: str | None = None # 活動頻度に関する自由記述
|
| 126 |
activityLocation: str | None = None
|
| 127 |
tags: list[str] = []
|
| 128 |
featureTags: list[str] = []
|
|
|
|
| 149 |
images: list[Image] = []
|
| 150 |
sns: list[Sns] = []
|
| 151 |
memberCount: int | None = None
|
| 152 |
+
memberNote: str | None = None # メンバー数に関する備考
|
| 153 |
annualFee: int | None = None
|
| 154 |
+
otherCosts: str | None = None # その他費用の説明
|
| 155 |
activityFrequency: str | None = None
|
| 156 |
+
activityFrequencyNote: str | None = None # 活動頻度に関する自由記述
|
| 157 |
activityLocation: str | None = None
|
| 158 |
annualSchedule: list[AnnualScheduleItem] | None = None
|
| 159 |
contactInfo: str | None = None
|
scripts/2_create_circles_data.py
CHANGED
|
@@ -50,6 +50,25 @@ def parse_json(value: str) -> list | dict | None:
|
|
| 50 |
return []
|
| 51 |
|
| 52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
def main():
|
| 54 |
"""CSVからサークルデータを読み込み circles.json を生成する。"""
|
| 55 |
|
|
@@ -105,10 +124,12 @@ def main():
|
|
| 105 |
"description": row.get("description") or None,
|
| 106 |
"detailDescription": row.get("detailDescription") or None,
|
| 107 |
"memberCount": parse_int(row.get("memberCount", "")),
|
| 108 |
-
"
|
|
|
|
|
|
|
| 109 |
"activityLocation": row.get("activityLocation") or None,
|
| 110 |
"annualFee": parse_int(row.get("annualFee", "")),
|
| 111 |
-
"
|
| 112 |
"annualSchedule": annual_schedule,
|
| 113 |
"contactInfo": row.get("contactInfo") or None,
|
| 114 |
"websiteUrl": row.get("websiteUrl") or None,
|
|
|
|
| 50 |
return []
|
| 51 |
|
| 52 |
|
| 53 |
+
# 旧activityFrequencyから新activityFrequencyへのマッピング
|
| 54 |
+
ACTIVITY_FREQUENCY_MAP = {
|
| 55 |
+
"DAILY": "WEEKLY_5_PLUS",
|
| 56 |
+
"WEEKLY_3_4": "WEEKLY_3_4",
|
| 57 |
+
"WEEKLY_1_2": "WEEKLY_1_2",
|
| 58 |
+
"MONTHLY_1_2": "MONTHLY_1_3",
|
| 59 |
+
"IRREGULAR": "LESS_THAN_MONTHLY",
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def convert_activity_frequency(value: str | None) -> str | None:
|
| 64 |
+
"""旧activityFrequency値を新値に変換"""
|
| 65 |
+
if not value or value.strip() == "":
|
| 66 |
+
return None
|
| 67 |
+
value = value.strip()
|
| 68 |
+
# 旧値であればマッピング、そうでなければそのまま返す
|
| 69 |
+
return ACTIVITY_FREQUENCY_MAP.get(value, value)
|
| 70 |
+
|
| 71 |
+
|
| 72 |
def main():
|
| 73 |
"""CSVからサークルデータを読み込み circles.json を生成する。"""
|
| 74 |
|
|
|
|
| 124 |
"description": row.get("description") or None,
|
| 125 |
"detailDescription": row.get("detailDescription") or None,
|
| 126 |
"memberCount": parse_int(row.get("memberCount", "")),
|
| 127 |
+
"memberNote": row.get("memberNote") or None,
|
| 128 |
+
"activityFrequency": convert_activity_frequency(row.get("activityFrequency")),
|
| 129 |
+
"activityFrequencyNote": row.get("activityFrequencyNote") or None,
|
| 130 |
"activityLocation": row.get("activityLocation") or None,
|
| 131 |
"annualFee": parse_int(row.get("annualFee", "")),
|
| 132 |
+
"otherCosts": row.get("otherCosts") or None,
|
| 133 |
"annualSchedule": annual_schedule,
|
| 134 |
"contactInfo": row.get("contactInfo") or None,
|
| 135 |
"websiteUrl": row.get("websiteUrl") or None,
|