sfx-tg-bot/database/database.py

469 строки
13 KiB
Python

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,
},
)