from collections.abc import Mapping from datetime import date from typing import Optional from sqlalchemy import text from app.dao import BaseDAO from app.db_compat import inserted_primary_key class ChildDAO(BaseDAO): def _create_relation(self, user_id: int, child_id: int) -> None: self.db.execute( text( """ INSERT INTO parent_child_relations (user_id, child_id, relation_type, is_primary, status) VALUES (:user_id, :child_id, 9, 0, 1) """ ), {"user_id": user_id, "child_id": child_id}, ) def create( self, user_id: int, child_name: str, child_gender: int = 2, child_birthday: Optional[date] = None, ) -> int: result = self.db.execute( text( """ INSERT INTO children (child_name, child_gender, child_birthday, status) VALUES (:child_name, :child_gender, :child_birthday, 1) """ ), {"child_name": child_name, "child_gender": child_gender, "child_birthday": child_birthday}, ) child_id = inserted_primary_key(result) self._create_relation(user_id, child_id) self.commit() return child_id def get_by_id(self, child_id: int) -> Optional[Mapping]: return ( self.db.execute( text("SELECT * FROM children WHERE child_id = :child_id"), {"child_id": child_id}, ) .mappings() .first() ) def list_by_parent(self, user_id: int, limit: int = 20, cursor: int = None) -> list[Mapping]: params = {"user_id": user_id, "limit": limit + 1} where = "pcr.user_id = :user_id AND pcr.status = 1 AND c.status = 1" if cursor is not None: where += " AND c.child_id < :cursor" params["cursor"] = cursor rows = ( self.db.execute( text( f""" SELECT c.* FROM children AS c JOIN parent_child_relations AS pcr ON pcr.child_id = c.child_id WHERE {where} ORDER BY c.child_id DESC LIMIT :limit """ ), params, ) .mappings() .all() ) return rows def update( self, child_id: int, child_name: Optional[str] = None, child_gender: Optional[int] = None, child_birthday: Optional[date] = None, ) -> None: self.db.execute( text( """ UPDATE children SET child_name = COALESCE(:child_name, child_name), child_gender = COALESCE(:child_gender, child_gender), child_birthday = COALESCE(:child_birthday, child_birthday) WHERE child_id = :child_id """ ), {"child_id": child_id, "child_name": child_name, "child_gender": child_gender, "child_birthday": child_birthday}, ) self.commit() def has_access(self, child_id: int, user_id: int) -> bool: return ( self.db.execute( text( """ SELECT 1 FROM children AS c JOIN parent_child_relations AS pcr ON pcr.child_id = c.child_id WHERE c.child_id = :child_id AND pcr.user_id = :user_id AND c.status = 1 AND pcr.status = 1 """ ), {"child_id": child_id, "user_id": user_id}, ).scalar_one_or_none() is not None )