Skip to content

Commit

Permalink
refactor: Add table size check for Google API. Optimize codebase.
Browse files Browse the repository at this point in the history
  • Loading branch information
mign0n committed Feb 27, 2024
1 parent 6a14056 commit c3b12d6
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 44 deletions.
18 changes: 10 additions & 8 deletions app/api/endpoints/google_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from app.core.google_client import get_service
from app.core.user import current_superuser
from app.crud.charity_project import charity_project_crud
from app.schemas.charity_project import CharityProjectDB
from app.services.report import (
set_user_permissions,
spreadsheets_create,
Expand All @@ -18,18 +17,21 @@

@router.post(
'/',
response_model=list[CharityProjectDB],
response_model=str,
dependencies=[Depends(current_superuser)],
)
async def get_report(
session: AsyncSession = Depends(get_async_session),
wrapper_services: Aiogoogle = Depends(get_service),
):
"""Только для суперюзеров."""
projects = await charity_project_crud.get_projects_by_completion_rate(
session,
spreadsheet_id, spreadsheet_url = await spreadsheets_create(
wrapper_services
)
spreadsheetid = await spreadsheets_create(wrapper_services)
await set_user_permissions(spreadsheetid, wrapper_services)
await spreadsheets_update_value(spreadsheetid, projects, wrapper_services)
return projects
await set_user_permissions(spreadsheet_id, wrapper_services)
await spreadsheets_update_value(
spreadsheet_id,
(await charity_project_crud.get_projects_by_completion_rate(session)),
wrapper_services,
)
return spreadsheet_url
15 changes: 15 additions & 0 deletions app/api/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,18 @@ async def check_project_full_amount_less_invested(
status_code=status.HTTP_400_BAD_REQUEST,
detail='Нельзя установить требуемую сумму меньше внесённой.',
)


async def check_data_fits_table_grid(
table_in: list[list[str]],
row_count: int,
column_count: int,
) -> None:
if (
len(table_in) > row_count
or max(len(row) for row in table_in) > column_count
):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail='Передаваемые данные не поместятся в созданной таблице.',
)
87 changes: 51 additions & 36 deletions app/services/report.py
Original file line number Diff line number Diff line change
@@ -1,91 +1,106 @@
from copy import deepcopy
from datetime import datetime

from aiogoogle import Aiogoogle

from app.api.validators import check_data_fits_table_grid
from app.core.config import settings
from app.models import CharityProject

FORMAT = '%Y/%m/%d %H:%M:%S'
LOCALE = 'ru_RU'
SPREADSHEET_TITLE = 'Отчёт от {date}'
TITLE = 'Отчёт от'
SPREADSHEET_PERMISSIONS = {
'type': 'user',
'role': 'writer',
'emailAddress': settings.email,
}
ROW_COUNT = 100
COLUMN_COUNT = 11
SHEETS = [
{
'properties': {
'sheetType': 'GRID',
'sheetId': 0,
'title': 'Лист1',
'gridProperties': {
'rowCount': 100,
'columnCount': 11,
'rowCount': ROW_COUNT,
'columnCount': COLUMN_COUNT,
},
},
},
]
DATA_RANGE = 'A1:C{rows_number}'

TABLE_HEADER = [
['Топ проектов по скорости закрытия'],
['Название проекта', 'Время сбора', 'Описание'],
]
SPREADSHEET_PROPERTIES = {
'properties': {
'title': TITLE,
'locale': LOCALE,
},
'sheets': SHEETS,
}


async def spreadsheets_create(wrapper_services: Aiogoogle) -> str:
return (
await wrapper_services.as_service_account(
(
await wrapper_services.discover('sheets', 'v4')
).spreadsheets.create(
json={
'properties': {
'title': SPREADSHEET_TITLE.format(
date=datetime.now().strftime(FORMAT)
),
'locale': LOCALE,
},
'sheets': SHEETS,
},
),
)
)['spreadsheetId']
async def spreadsheets_create(
wrapper_services: Aiogoogle,
properties=deepcopy(SPREADSHEET_PROPERTIES),
) -> tuple[str, str]:
properties['properties']['title'] += ' {}'.format(
datetime.now().strftime(FORMAT)
)
response = await wrapper_services.as_service_account(
(await wrapper_services.discover('sheets', 'v4')).spreadsheets.create(
json=properties
),
)
return response['spreadsheetId'], response['spreadsheetUrl']


async def set_user_permissions(
spreadsheetid: str,
spreadsheet_id: str,
wrapper_services: Aiogoogle,
) -> None:
await wrapper_services.as_service_account(
(await wrapper_services.discover('drive', 'v3')).permissions.create(
fileId=spreadsheetid,
fileId=spreadsheet_id,
json=SPREADSHEET_PERMISSIONS,
fields='id',
),
)


async def spreadsheets_update_value(
spreadsheetid: str,
spreadsheet_id: str,
projects: list[CharityProject],
wrapper_services: Aiogoogle,
) -> None:
table_values = TABLE_HEADER
for project in projects:
table_values.append(
[
project.name,
str(project.close_date - project.create_date),
project.description,
]
)
table_values = [
[TITLE, datetime.now().strftime(FORMAT)],
*TABLE_HEADER,
*[
list(
map(
str,
[
project.name,
project.close_date - project.create_date,
project.description,
],
)
)
for project in projects
],
]
await check_data_fits_table_grid(table_values, ROW_COUNT, COLUMN_COUNT)
await wrapper_services.as_service_account(
(
await wrapper_services.discover('sheets', 'v4')
).spreadsheets.values.update(
spreadsheetId=spreadsheetid,
range=DATA_RANGE.format(rows_number=len(table_values)),
spreadsheetId=spreadsheet_id,
range='R1C1:R{}C{}'.format(ROW_COUNT, COLUMN_COUNT),
valueInputOption='USER_ENTERED',
json={'majorDimension': 'ROWS', 'values': table_values},
)
Expand Down

0 comments on commit c3b12d6

Please sign in to comment.