1+ from __future__ import annotations
2+
13from datetime import datetime
4+ from typing import Dict , Any
25
36from sqlalchemy import (DDL , Boolean , Column , DateTime , ForeignKey , Index ,
4- Integer , String , event )
7+ Integer , String , event , UniqueConstraint )
58from sqlalchemy .dialects .postgresql import TSVECTOR
6- from sqlalchemy .orm import relationship
9+ from sqlalchemy .exc import IntegrityError , SQLAlchemyError
10+ from sqlalchemy .orm import relationship , Session
711
812from app .config import PSQL_ENVIRONMENT
913from app .database .database import Base
14+ from app .dependencies import logger
1015
1116
1217class UserEvent (Base ):
@@ -52,11 +57,12 @@ class Event(Base):
5257 end = Column (DateTime , nullable = False )
5358 content = Column (String )
5459 location = Column (String )
60+ color = Column (String , nullable = True )
5561
56- owner = relationship ("User" )
5762 owner_id = Column (Integer , ForeignKey ("users.id" ))
58- color = Column (String , nullable = True )
63+ category_id = Column (Integer , ForeignKey ( "categories.id" ) )
5964
65+ owner = relationship ("User" )
6066 participants = relationship ("UserEvent" , back_populates = "events" )
6167
6268 # PostgreSQL
@@ -66,12 +72,45 @@ class Event(Base):
6672 'events_tsv_idx' ,
6773 'events_tsv' ,
6874 postgresql_using = 'gin' ),
69- )
75+ )
7076
7177 def __repr__ (self ):
7278 return f'<Event { self .id } >'
7379
7480
81+ class Category (Base ):
82+ __tablename__ = "categories"
83+
84+ __table_args__ = (
85+ UniqueConstraint ('user_id' , 'name' , 'color' ),
86+ )
87+ id = Column (Integer , primary_key = True , index = True )
88+ name = Column (String , nullable = False )
89+ color = Column (String , nullable = False )
90+ user_id = Column (Integer , ForeignKey ("users.id" ), nullable = False )
91+
92+ @staticmethod
93+ def create (db_session : Session , name : str , color : str ,
94+ user_id : int ) -> Category :
95+ try :
96+ category = Category (name = name , color = color , user_id = user_id )
97+ db_session .add (category )
98+ db_session .flush ()
99+ db_session .commit ()
100+ db_session .refresh (category )
101+ except (SQLAlchemyError , IntegrityError ) as e :
102+ logger .error (f"Failed to create category: { e } " )
103+ raise e
104+ else :
105+ return category
106+
107+ def to_dict (self ) -> Dict [str , Any ]:
108+ return {c .name : getattr (self , c .name ) for c in self .__table__ .columns }
109+
110+ def __repr__ (self ) -> str :
111+ return f'<Category { self .id } { self .name } { self .color } >'
112+
113+
75114class PSQLEnvironmentError (Exception ):
76115 pass
77116
@@ -89,7 +128,7 @@ class PSQLEnvironmentError(Exception):
89128 Event .__table__ ,
90129 'after_create' ,
91130 trigger_snippet .execute_if (dialect = 'postgresql' )
92- )
131+ )
93132
94133
95134class Invitation (Base ):
0 commit comments