from datetime import datetime from sqlalchemy import select from sqlalchemy.orm import Session from app.models.habit import Habit, HabitStatus, HabitType from app.schemas.habit import HabitCreate, HabitUpdate def list_habits( db: Session, user_id: int, habit_type: HabitType | None = None, status: HabitStatus | None = None ) -> list[Habit]: stmt = select(Habit).where(Habit.user_id == user_id) if habit_type is not None: stmt = stmt.where(Habit.habit_type == habit_type) if status is not None: stmt = stmt.where(Habit.status == status) stmt = stmt.order_by(Habit.sort_order.is_(None), Habit.sort_order, Habit.created_at) return list(db.scalars(stmt)) def list_active_habits_with_reminders(db: Session) -> list[Habit]: """스케줄러 전용: 유저 스코핑 없이 알림 시각이 설정된 전체 active 습관을 반환한다.""" stmt = select(Habit).where(Habit.status == HabitStatus.ACTIVE, Habit.reminder_time.isnot(None)) return list(db.scalars(stmt)) def list_active_user_ids(db: Session) -> list[int]: """스케줄러 전용: 유저 스코핑 없이, active 습관을 하나 이상 가진 유저 id 목록을 반환한다(주간/월간 요약 알림 대상).""" stmt = ( select(Habit.user_id) .where(Habit.status == HabitStatus.ACTIVE, Habit.user_id.isnot(None)) .distinct() ) return list(db.scalars(stmt)) def get_habit(db: Session, habit_id: int, user_id: int) -> Habit | None: return db.scalar(select(Habit).where(Habit.id == habit_id, Habit.user_id == user_id)) def create_habit(db: Session, user_id: int, data: HabitCreate) -> Habit: habit = Habit( user_id=user_id, name=data.name, habit_type=data.habit_type, weekdays_mask=data.weekdays_mask, condition_text=data.condition_text, reminder_time=data.reminder_time, status=HabitStatus.ACTIVE, ) db.add(habit) db.commit() db.refresh(habit) return habit def update_habit(db: Session, habit: Habit, data: HabitUpdate) -> Habit: habit.name = data.name habit.habit_type = data.habit_type habit.weekdays_mask = data.weekdays_mask habit.condition_text = data.condition_text habit.reminder_time = data.reminder_time db.commit() db.refresh(habit) return habit def delete_habit(db: Session, habit: Habit) -> None: db.delete(habit) db.commit() def complete_habit(db: Session, habit: Habit) -> Habit: habit.status = HabitStatus.COMPLETED habit.completed_at = datetime.now() db.commit() db.refresh(habit) return habit def abandon_habit(db: Session, habit: Habit) -> Habit: habit.status = HabitStatus.ABANDONED habit.abandoned_at = datetime.now() db.commit() db.refresh(habit) return habit def reactivate_habit(db: Session, habit: Habit) -> Habit: habit.status = HabitStatus.ACTIVE habit.completed_at = None habit.abandoned_at = None db.commit() db.refresh(habit) return habit def reorder_habits(db: Session, user_id: int, ordered_ids: list[int]) -> None: """ordered_ids에 나온 순서대로 sort_order를 다시 매긴다. 목록에 없는 id나 다른 유저의 habit은 무시한다.""" habits = db.scalars( select(Habit).where(Habit.id.in_(ordered_ids), Habit.user_id == user_id) ).all() habit_map = {h.id: h for h in habits} for index, habit_id in enumerate(ordered_ids): habit = habit_map.get(habit_id) if habit is not None: habit.sort_order = index db.commit()