import config from models import date, Category, Subcategory, Executor, TimeRange, FreeToOrder, Order, Issue from psycopg import AsyncConnection, Connection conninfo = 'dbname=%(dbname)s user=%(user)s password=%(password)s host=%(host)s port=%(port)d' % { 'dbname': config.Database.dbname, 'user': config.Database.user, 'password': config.Database.password, 'host': config.Database.host, 'port': config.Database.port, } async def read_categories() -> tuple[Category]: async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' select distinct categories.id, categories.name, categories.description from categories right join executor_specialties on categories.id = executor_specialties.category_id order by categories.id; ''' await cursor.execute(sql) records = await cursor.fetchall() return tuple( Category( id=category_id, name=name, description=description, ) for category_id, name, description, in records ) async def read_subcategories(category: Category) -> tuple[Subcategory]: async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' select distinct categories.id, categories.name, categories.description, subcategories.id, subcategories.name, subcategories.description from subcategories left join categories on subcategories.category_id = categories.id right join executor_specialties on categories.id = executor_specialties.category_id and subcategories.id = executor_specialties.subcategory_id where categories.id = %(category_id)s order by subcategories.id; ''' await cursor.execute( sql, { 'category_id': category.id, }, ) records = await cursor.fetchall() return tuple( Subcategory( category=Category( id=category_id, name=category_name, description=category_description, ), id=subcategory_id, name=subcategory_name, description=subcategory_description, ) for category_id, category_name, category_description, subcategory_id, subcategory_name, subcategory_description, in records ) async def read_free_to_order(subcategory: Subcategory) -> tuple[FreeToOrder]: async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' select sfx_read_free_to_order.date, time_ranges.id, time_ranges.start_time, time_ranges.end_time, executors.id, executors.name, sfx_read_free_to_order.busy_interval from sfx_read_free_to_order( %(category_id)s::smallint, %(subcategory_id)s::smallint ) left join time_ranges on sfx_read_free_to_order.time_range_id = time_ranges.id left join executors on sfx_read_free_to_order.executor_id = executors.id; ''' await cursor.execute( sql, { 'category_id': subcategory.category.id, 'subcategory_id': subcategory.id }, ) records = await cursor.fetchall() return tuple( FreeToOrder( date=free_to_order_date, time_range=TimeRange( id=time_range_id, start_time=time_range_start_time, end_time=time_range_end_time, ), executor=Executor( id=executor_id, name=executor_name, ), busy_interval=free_to_order_busy_interval, ) for free_to_order_date, time_range_id, time_range_start_time, time_range_end_time, executor_id, executor_name, free_to_order_busy_interval, in records ) async def create_order( subcategory: Subcategory, date: date, time_range: TimeRange, executor: Executor, telegram_id: int, email_address: str, phone_number: str, comment: str, ) -> int: async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' insert into orders ( category_id, subcategory_id, date, time_range_id, executor_id, telegram_id, email_address, phone_number, comment ) values ( %(category_id)s, %(subcategory_id)s, %(date)s, %(time_range_id)s, %(executor_id)s, %(telegram_id)s, %(email_address)s, %(phone_number)s, %(comment)s ) returning orders.id; ''' await cursor.execute( sql, { 'category_id': subcategory.category.id, 'subcategory_id': subcategory.id, 'date': date, 'time_range_id': time_range.id, 'executor_id': executor.id, 'telegram_id': telegram_id, 'email_address': email_address, 'phone_number': phone_number, 'comment': comment, }, ) record = await cursor.fetchone() return record[0] async def read_orders( telegram_id: int, ) -> tuple[Order]: async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' select orders.id, categories.id, categories.name, categories.description, subcategories.id, subcategories.name, subcategories.description, orders.date, time_ranges.id, time_ranges.start_time, time_ranges.end_time, executors.id, executors.name, orders.telegram_id, orders.email_address, orders.phone_number, orders.comment, orders.start_time, orders.end_time from orders left join categories on orders.category_id = categories.id left join subcategories on orders.category_id = subcategories.category_id and orders.subcategory_id = subcategories.id left join time_ranges on orders.time_range_id = time_ranges.id left join executors on orders.executor_id = executors.id where orders.telegram_id = %(telegram_id)s and orders.start_time is null and orders.end_time is null order by orders.id; ''' await cursor.execute( sql, { 'telegram_id': telegram_id, }, ) records = await cursor.fetchall() return tuple( Order( id=order_id, subcategory=Subcategory( category=Category( id=category_id, name=category_name, description=category_description, ), id=subcategory_id, name=subcategory_name, description=subcategory_description, ), date=order_date, time_range=TimeRange( id=time_range_id, start_time=time_range_start_time, end_time=time_range_end_time, ), executor=Executor( id=executor_id, name=executor_name, ), telegram_id=order_telegram_id, email_address=order_email_address, phone_number=order_phone_number, comment=order_comment, start_time=order_start_time, end_time=order_end_time, ) for order_id, category_id, category_name, category_description, subcategory_id, subcategory_name, subcategory_description, order_date, time_range_id, time_range_start_time, time_range_end_time, executor_id, executor_name, order_telegram_id, order_email_address, order_phone_number, order_comment, order_start_time, order_end_time, in records ) async def update_order( order_id: int, date: date, time_range: TimeRange, executor: Executor, ): async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' update orders set date = %(date)s, time_range_id = %(time_range_id)s, executor_id = %(executor_id)s where orders.id = %(order_id)s; ''' await cursor.execute( sql, { 'order_id': order_id, 'date': date, 'time_range_id': time_range.id, 'executor_id': executor.id, }, ) async def delete_order( order_id: int, ): async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' delete from orders where orders.id = %(order_id)s; ''' await cursor.execute( sql, { 'order_id': order_id, }, ) def update_statistics( k: int, ): with Connection.connect(conninfo) as connection: with connection.cursor() as cursor: sql = ''' select sfx_update_statistics( %(k)s ); ''' cursor.execute( sql, { 'k': k, }, ) async def create_issue( issue: Issue, ): async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' insert into issues ( id, key, status, telegram_id ) values ( %(issue_id)s, %(key)s, %(status)s, %(telegram_id)s ); ''' await cursor.execute( sql, { 'issue_id': issue.id, 'key': issue.key, 'status': issue.status, 'telegram_id': issue.telegram_id, }, ) async def read_issues( telegram_id: int, ) -> tuple[Issue]: async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' select issues.id, issues.key, issues.status, issues.telegram_id from issues where issues.telegram_id = %(telegram_id)s and issues.status != 'done' order by issues.id; ''' await cursor.execute( sql, { 'telegram_id': telegram_id, }, ) records = await cursor.fetchall() return tuple( Issue( id=issue_id, key=key, status=status, telegram_id=telegram_id, ) for issue_id, key, status, telegram_id, in records ) async def delete_issue( issue: Issue, ): async with await AsyncConnection.connect(conninfo) as connection: async with connection.cursor() as cursor: sql = ''' delete from issues where issues.id = %(issue_id)s ''' await cursor.execute( sql, { 'issue_id': issue.id, }, )