-
Notifications
You must be signed in to change notification settings - Fork 0
hotfix #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
hotfix #13
Changes from all commits
229e6ac
7d91d41
054a25a
da8c05d
b5801d6
25e8ff1
3eefe17
d010073
dbb1a6f
5b8199a
a5616e5
b8669b4
238845e
b06aaa8
20fd47e
0773930
bb0c4a6
82ab22a
cf8daa7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -155,4 +155,3 @@ restart_systemd.sh | |
| SERVERS.md | ||
|
|
||
| *.json | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| from app.database import engine | ||
| from sqlalchemy import text | ||
|
|
||
|
|
||
| def ensure_surprise_column() -> None: | ||
| with engine.connect() as conn: | ||
| res = conn.execute(text("SHOW COLUMNS FROM voice_analyze LIKE 'surprise_bps'")) | ||
| row = res.fetchone() | ||
| if row is None: | ||
| print("Adding surprise_bps column...") | ||
| conn.execute(text("ALTER TABLE voice_analyze ADD COLUMN surprise_bps SMALLINT NOT NULL DEFAULT 0")) | ||
| print("Added surprise_bps") | ||
| else: | ||
| print("surprise_bps exists") | ||
| conn.commit() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| ensure_surprise_column() | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| from sqlalchemy import func, extract | ||
| from .models import User, Voice, VoiceAnalyze | ||
| from .auth_service import get_auth_service | ||
| from datetime import datetime, timedelta | ||
| from collections import Counter, defaultdict | ||
|
|
||
| class CareService: | ||
| def __init__(self, db): | ||
| self.db = db | ||
| self.auth_service = get_auth_service(db) | ||
|
|
||
| def get_emotion_monthly_frequency(self, care_username: str, month: str) -> dict: | ||
| """ | ||
| 보νΈμ νμ΄μ§: μ°κ²° μ μ μ νλ¬κ° top_emotion μ§κ³ λ°ν | ||
| :param care_username: 보νΈμ μμ΄λ | ||
| :param month: 'YYYY-MM' | ||
| :return: {success, frequency: {emotion: count, ...}} | ||
| """ | ||
| try: | ||
| care = self.auth_service.get_user_by_username(care_username) | ||
| if not care or care.role != 'CARE' or not care.connecting_user_code: | ||
| return {"success": False, "frequency": {}, "message": "Care user not found or no connection."} | ||
| user = self.db.query(User).filter(User.user_code == care.connecting_user_code).first() | ||
| if not user: | ||
| return {"success": False, "frequency": {}, "message": "Connected user not found."} | ||
| try: | ||
| y, m = map(int, month.split("-")) | ||
| except Exception: | ||
| return {"success": False, "frequency": {}, "message": "month format YYYY-MM required"} | ||
| results = ( | ||
| self.db.query(VoiceAnalyze.top_emotion, func.count()) | ||
| .join(Voice, Voice.voice_id == VoiceAnalyze.voice_id) | ||
| .filter( | ||
| Voice.user_id == user.user_id, | ||
| extract('year', Voice.created_at) == y, | ||
| extract('month', Voice.created_at) == m | ||
| ) | ||
| .group_by(VoiceAnalyze.top_emotion) | ||
| .all() | ||
| ) | ||
| freq = {str(emotion): count for emotion, count in results if emotion} | ||
| return {"success": True, "frequency": freq} | ||
| except Exception as e: | ||
| return {"success": False, "frequency": {}, "message": f"error: {str(e)}"} | ||
|
|
||
| def get_emotion_weekly_summary(self, care_username: str, month: str, week: int) -> dict: | ||
| """ | ||
| 보νΈμ νμ΄μ§: μ°κ²° μ μ μ μ/μ£Όμ°¨λ³ μμΌλ³ top κ°μ μμ½ λ°ν | ||
| :param care_username: 보νΈμ μμ΄λ | ||
| :param month: YYYY-MM | ||
| :param week: 1~5 (1μ£Όμ°¨~5μ£Όμ°¨) | ||
| :return: {success, weekly: [{day: "2025-10-02", weekday: "Thu", top_emotion: "happy"}, ...]} | ||
| """ | ||
| try: | ||
| care = self.auth_service.get_user_by_username(care_username) | ||
| if not care or care.role != 'CARE' or not care.connecting_user_code: | ||
| return {"success": False, "weekly": [], "message": "Care user not found or no connection."} | ||
| user = self.db.query(User).filter(User.user_code == care.connecting_user_code).first() | ||
| if not user: | ||
| return {"success": False, "weekly": [], "message": "Connected user not found."} | ||
| try: | ||
| y, m = map(int, month.split("-")) | ||
| except Exception: | ||
| return {"success": False, "weekly": [], "message": "month format YYYY-MM required"} | ||
| # μ£Όμ°¨ κ΅¬κ° κ³μ° | ||
| from calendar import monthrange | ||
| start_day = (week-1)*7+1 | ||
| end_day = min(week*7, monthrange(y, m)[1]) | ||
| start_date = datetime(y, m, start_day) | ||
| end_date = datetime(y, m, end_day, 23, 59, 59) | ||
| # μμΌλ³ group | ||
| q = ( | ||
| self.db.query(Voice, VoiceAnalyze) | ||
| .join(VoiceAnalyze, Voice.voice_id == VoiceAnalyze.voice_id) | ||
| .filter( | ||
| Voice.user_id == user.user_id, | ||
| Voice.created_at >= start_date, | ||
| Voice.created_at <= end_date, | ||
| ).order_by(Voice.created_at.asc()) | ||
| ) | ||
| days = defaultdict(list) # day: [emotion, ...] | ||
| day_first = {} | ||
| for v, va in q: | ||
| d = v.created_at.date() | ||
| em = va.top_emotion | ||
| days[d].append(em) | ||
| if d not in day_first: | ||
| day_first[d] = em # μ λ‘λ λΉ λ₯Έ κ°μ 미리 κΈ°μ΅ | ||
| result = [] | ||
| for d in sorted(days.keys()): | ||
| cnt = Counter(days[d]) | ||
| top, val = cnt.most_common(1)[0] | ||
| # λλ₯ λ§μΆκΈ°(λμ μ κ°μ₯ λ¨Όμ μ λ‘λν κ°μ μ topμΌλ‘) | ||
| top_emotions = [e for e, c in cnt.items() if c == val] | ||
| selected = day_first[d] if len(top_emotions) > 1 and day_first[d] in top_emotions else top | ||
| result.append({ | ||
| "date": d.isoformat(), | ||
| "weekday": d.strftime("%a"), | ||
| "top_emotion": selected | ||
| }) | ||
| return {"success": True, "weekly": result} | ||
| except Exception as e: | ||
| return {"success": False, "weekly": [], "message": f"error: {str(e)}"} |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -36,6 +36,10 @@ def get_user_by_username(self, username: str) -> Optional[User]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_users(self, skip: int = 0, limit: int = 100) -> List[User]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """μ¬μ©μ λͺ©λ‘ μ‘°ν""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self.db.query(User).offset(skip).limit(limit).all() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_user_by_user_code(self, user_code: str) -> Optional[User]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """user_codeλ‘ μ¬μ©μ μ‘°ν""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self.db.query(User).filter(User.user_code == user_code).first() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Voice κ΄λ ¨ λ©μλ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def create_voice(self, voice_key: str, voice_name: str, duration_ms: int, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -58,6 +62,21 @@ def create_voice(self, voice_key: str, voice_name: str, duration_ms: int, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_voice_by_id(self, voice_id: int) -> Optional[Voice]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """IDλ‘ μμ± νμΌ μ‘°ν""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self.db.query(Voice).filter(Voice.voice_id == voice_id).first() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_voice_detail_for_username(self, voice_id: int, username: str) -> Optional[Voice]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """usernameμΌλ‘ μμ κΆμ κ²μ¦νλ©° μμΈλ₯Ό λ‘λ(joinedload)""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sqlalchemy.orm import joinedload | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.db.query(Voice) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .join(User, Voice.user_id == User.user_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter(Voice.voice_id == voice_id, User.username == username) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .options( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| joinedload(Voice.questions), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| joinedload(Voice.voice_content), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| joinedload(Voice.voice_analyze), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .first() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_voice_by_key(self, voice_key: str) -> Optional[Voice]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """S3 ν€λ‘ μμ± νμΌ μ‘°ν""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -69,6 +88,29 @@ def get_voices_by_user(self, user_id: int, skip: int = 0, limit: int = 50) -> Li | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self.db.query(Voice).filter(Voice.user_id == user_id)\ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .options(joinedload(Voice.questions))\ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .order_by(Voice.created_at.desc()).offset(skip).limit(limit).all() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_care_voices(self, care_username: str, skip: int = 0, limit: int = 20) -> List[Voice]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """보νΈμ(care)μ μ°κ²° μ¬μ©μ μμ± μ€ voice_analyzeκ° μ‘΄μ¬νλ νλͺ©λ§ μ΅μ μ μ‘°ν""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sqlalchemy.orm import joinedload | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 1) 보νΈμ μ‘°ν | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| care = self.get_user_by_username(care_username) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not care or not care.connecting_user_code: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 2) μ°κ²°λ μ¬μ©μ μ‘°ν | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| linked_user = self.get_user_by_user_code(care.connecting_user_code) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not linked_user: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 3) μ°κ²° μ¬μ©μ μμ± μ€ λΆμ μλ£λ§(join) νμ΄μ§ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| q = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.db.query(Voice) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .join(VoiceAnalyze, VoiceAnalyze.voice_id == Voice.voice_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter(Voice.user_id == linked_user.user_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .options(joinedload(Voice.questions), joinedload(Voice.voice_analyze)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .order_by(Voice.created_at.desc()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .offset(skip) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .limit(limit) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return q.all() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_all_voices(self, skip: int = 0, limit: int = 50) -> List[Voice]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """μ 체 μμ± νμΌ λͺ©λ‘ μ‘°ν""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -126,7 +168,7 @@ def update_voice_content(self, voice_id: int, content: str, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # VoiceAnalyze κ΄λ ¨ λ©μλ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def create_voice_analyze(self, voice_id: int, happy_bps: int, sad_bps: int, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| neutral_bps: int, angry_bps: int, fear_bps: int, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| neutral_bps: int, angry_bps: int, fear_bps: int, surprise_bps: int = 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| top_emotion: Optional[str] = None, top_confidence_bps: Optional[int] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model_version: Optional[str] = None) -> VoiceAnalyze: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """μμ± κ°μ λΆμ λ°μ΄ν° μμ±""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -137,6 +179,7 @@ def create_voice_analyze(self, voice_id: int, happy_bps: int, sad_bps: int, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| neutral_bps=neutral_bps, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| angry_bps=angry_bps, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fear_bps=fear_bps, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| surprise_bps=surprise_bps, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| top_emotion=top_emotion, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| top_confidence_bps=top_confidence_bps, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model_version=model_version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -151,7 +194,7 @@ def get_voice_analyze_by_voice_id(self, voice_id: int) -> Optional[VoiceAnalyze] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self.db.query(VoiceAnalyze).filter(VoiceAnalyze.voice_id == voice_id).first() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def update_voice_analyze(self, voice_id: int, happy_bps: int, sad_bps: int, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| neutral_bps: int, angry_bps: int, fear_bps: int, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| neutral_bps: int, angry_bps: int, fear_bps: int, surprise_bps: Optional[int] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| top_emotion: Optional[str] = None, top_confidence_bps: Optional[int] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model_version: Optional[str] = None) -> Optional[VoiceAnalyze]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """μμ± κ°μ λΆμ κ²°κ³Ό μ λ°μ΄νΈ""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -162,6 +205,8 @@ def update_voice_analyze(self, voice_id: int, happy_bps: int, sad_bps: int, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| voice_analyze.neutral_bps = neutral_bps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| voice_analyze.angry_bps = angry_bps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| voice_analyze.fear_bps = fear_bps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if surprise_bps is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| voice_analyze.surprise_bps = surprise_bps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if top_emotion is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| voice_analyze.top_emotion = top_emotion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if top_confidence_bps is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -229,6 +274,29 @@ def unlink_voice_question(self, voice_id: int, question_id: int) -> bool: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # μμ κ΄λ ¨ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_voice_owned_by_username(self, voice_id: int, username: str) -> Optional[Voice]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """username μμ μ voice μ‘°ν""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.db.query(Voice) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .join(User, Voice.user_id == User.user_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter(Voice.voice_id == voice_id, User.username == username) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .first() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def delete_voice_with_relations(self, voice_id: int) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """μ°κ΄ λ°μ΄ν°(voice_question, voice_content, voice_analyze) μμ ν voice μμ """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # voice_question | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.db.query(VoiceQuestion).filter(VoiceQuestion.voice_id == voice_id).delete(synchronize_session=False) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # voice_content | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.db.query(VoiceContent).filter(VoiceContent.voice_id == voice_id).delete(synchronize_session=False) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # voice_analyze | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.db.query(VoiceAnalyze).filter(VoiceAnalyze.voice_id == voice_id).delete(synchronize_session=False) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # voice | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| deleted = self.db.query(Voice).filter(Voice.voice_id == voice_id).delete(synchronize_session=False) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.db.commit() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return deleted > 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+287
to
+298
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. λΆλΆ μμ κ°λ₯μ±μ λν νΈλμμ μ²λ¦¬λ₯Ό κ²ν νμΈμ. νμ¬ κ΅¬νμ μ¬λ¬ ν μ΄λΈμμ μμ°¨μ μΌλ‘ μμ λ₯Ό μννμ§λ§, μ€κ°μ μ€ν¨ μ λΆλΆ μμ κ° λ°μν μ μμ΅λλ€. λͺ μμ μΈ νΈλμμ 컨ν μ€νΈλ₯Ό μ¬μ©νκ±°λ μμΈ λ°μ μ λ‘€λ°± μ²λ¦¬λ₯Ό μΆκ°νλ κ²μ κΆμ₯ν©λλ€. μμ: def delete_voice_with_relations(self, voice_id: int) -> bool:
"""μ°κ΄ λ°μ΄ν°(voice_question, voice_content, voice_analyze) μμ ν voice μμ """
- # voice_question
- self.db.query(VoiceQuestion).filter(VoiceQuestion.voice_id == voice_id).delete(synchronize_session=False)
- # voice_content
- self.db.query(VoiceContent).filter(VoiceContent.voice_id == voice_id).delete(synchronize_session=False)
- # voice_analyze
- self.db.query(VoiceAnalyze).filter(VoiceAnalyze.voice_id == voice_id).delete(synchronize_session=False)
- # voice
- deleted = self.db.query(Voice).filter(Voice.voice_id == voice_id).delete(synchronize_session=False)
- self.db.commit()
- return deleted > 0
+ try:
+ # voice_question
+ self.db.query(VoiceQuestion).filter(VoiceQuestion.voice_id == voice_id).delete(synchronize_session=False)
+ # voice_content
+ self.db.query(VoiceContent).filter(VoiceContent.voice_id == voice_id).delete(synchronize_session=False)
+ # voice_analyze
+ self.db.query(VoiceAnalyze).filter(VoiceAnalyze.voice_id == voice_id).delete(synchronize_session=False)
+ # voice
+ deleted = self.db.query(Voice).filter(Voice.voice_id == voice_id).delete(synchronize_session=False)
+ self.db.commit()
+ return deleted > 0
+ except Exception as e:
+ self.db.rollback()
+ raiseπ Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_db_service(db: Session) -> DatabaseService: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """λ°μ΄ν°λ² μ΄μ€ μλΉμ€ μΈμ€ν΄μ€ μμ±""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alembic λ§μ΄κ·Έλ μ΄μ μ¬μ©μ κΆμ₯ν©λλ€.
μ΄ μ€ν¬λ¦½νΈλ μλμΌλ‘ μ€ν€λ§λ₯Ό λ³κ²½νμ§λ§, README.mdμ Alembic λ§μ΄κ·Έλ μ΄μ κ°μ΄λκ° μ΄λ―Έ μμ΅λλ€. λͺ κ°μ§ λ¬Έμ μ :
SHOW COLUMNS)μΌλ‘ λ€λ₯Έ DBμ νΈν λΆκ°λμ Alembicμ μ¬μ©νμΈμ:
alembic revision --autogenerate -m "Add surprise_bps to VoiceAnalyze" alembic upgrade headπ€ Prompt for AI Agents