This commit is contained in:
2026-03-01 15:32:25 +03:00
parent 8b05a2d512
commit 1110d89bb0
17 changed files with 150 additions and 59 deletions
+42 -10
View File
@@ -1,4 +1,4 @@
from datetime import date
from datetime import date, timedelta, timezone
from io import BytesIO
from openpyxl import Workbook
@@ -16,6 +16,11 @@ from dutylog.infrastructure.database.repositories.residents_repository import (
from dutylog.infrastructure.database.repositories.rooms_repository import (
RoomsRepository,
)
from dutylog.infrastructure.database.repositories.users_repository import (
UsersRepository,
)
MSK_TZ = timezone(timedelta(hours=3))
class ReportService:
@@ -25,11 +30,13 @@ class ReportService:
residents_repository: ResidentsRepository,
rooms_repository: RoomsRepository,
floors_repository: FloorsRepository,
users_repository: UsersRepository,
):
self.hours_transactions_repository = hours_transactions_repository
self.residents_repository = residents_repository
self.rooms_repository = rooms_repository
self.floors_repository = floors_repository
self.users_repository = users_repository
async def generate_period_report(self, start_date: date, end_date: date) -> BytesIO:
transactions = await self.hours_transactions_repository.get_by_period(
@@ -69,7 +76,7 @@ class ReportService:
title_text = f"Отчет по начислениям часов за период {start_date.strftime('%d.%m.%Y')} - {end_date.strftime('%d.%m.%Y')}"
ws.cell(row=1, column=1, value=title_text)
ws.merge_cells("A1:E1")
ws.merge_cells("A1:F1")
title_cell = ws.cell(row=1, column=1)
title_cell.font = Font(bold=True, size=14)
title_cell.alignment = Alignment(horizontal="center", vertical="center")
@@ -79,10 +86,10 @@ class ReportService:
ws.cell(row=row_num, column=1, value="НАЧИСЛЕНИЯ")
ws.cell(row=row_num, column=1).font = Font(bold=True, size=12)
ws.merge_cells(f"A{row_num}:E{row_num}")
ws.merge_cells(f"A{row_num}:F{row_num}")
row_num += 1
headers = ["Дата", "Резидент", "Комната", "Часы", "Примечание"]
headers = ["Дата", "Резидент", "Комната", "Часы", "Админ", "Примечание"]
for col_num, header in enumerate(headers, 1):
cell = ws.cell(row=row_num, column=col_num)
cell.value = header
@@ -105,9 +112,17 @@ class ReportService:
room = await self.rooms_repository.get_by_id(resident.room)
room_number = room.number if room else ""
admin_username = ""
if transaction.admin_id:
admin = await self.users_repository.get_user_by_id(transaction.admin_id)
if admin and admin.username:
admin_username = f"@{admin.username}"
msk_time = transaction.created_at.astimezone(MSK_TZ).replace(tzinfo=None)
ws.cell(
row=row_num, column=1, value=transaction.created_at.replace(tzinfo=None)
row=row_num, column=1, value=msk_time
).border = border
ws.cell(row=row_num, column=1).number_format = "DD.MM.YYYY HH:MM"
ws.cell(
@@ -115,8 +130,9 @@ class ReportService:
).border = border
ws.cell(row=row_num, column=3, value=room_number).border = border
ws.cell(row=row_num, column=4, value=transaction.amount).border = border
ws.cell(row=row_num, column=5, value=admin_username).border = border
ws.cell(
row=row_num, column=5, value=transaction.remark or ""
row=row_num, column=6, value=transaction.remark or ""
).border = border
ws.cell(row=row_num, column=1).alignment = Alignment(horizontal="center")
@@ -142,12 +158,15 @@ class ReportService:
ws.cell(row=summary_row, column=5, value="").fill = summary_fill
ws.cell(row=summary_row, column=5).border = border
ws.cell(row=summary_row, column=6, value="").fill = summary_fill
ws.cell(row=summary_row, column=6).border = border
row_num += 3
ws.cell(row=row_num, column=1, value="СПИСАНИЯ")
ws.cell(row=row_num, column=1).font = Font(bold=True, size=12)
ws.merge_cells(f"A{row_num}:E{row_num}")
ws.merge_cells(f"A{row_num}:F{row_num}")
row_num += 1
for col_num, header in enumerate(headers, 1):
@@ -172,9 +191,17 @@ class ReportService:
room = await self.rooms_repository.get_by_id(resident.room)
room_number = room.number if room else ""
admin_username = ""
if transaction.admin_id:
admin = await self.users_repository.get_user_by_id(transaction.admin_id)
if admin and admin.username:
admin_username = f"@{admin.username}"
msk_time = transaction.created_at.astimezone(MSK_TZ).replace(tzinfo=None)
ws.cell(
row=row_num, column=1, value=transaction.created_at.replace(tzinfo=None)
row=row_num, column=1, value=msk_time
).border = border
ws.cell(row=row_num, column=1).number_format = "DD.MM.YYYY HH:MM"
ws.cell(
@@ -182,8 +209,9 @@ class ReportService:
).border = border
ws.cell(row=row_num, column=3, value=room_number).border = border
ws.cell(row=row_num, column=4, value=transaction.amount).border = border
ws.cell(row=row_num, column=5, value=admin_username).border = border
ws.cell(
row=row_num, column=5, value=transaction.remark or ""
row=row_num, column=6, value=transaction.remark or ""
).border = border
ws.cell(row=row_num, column=1).alignment = Alignment(horizontal="center")
@@ -209,12 +237,16 @@ class ReportService:
ws.cell(row=summary_row, column=5, value="").fill = summary_fill
ws.cell(row=summary_row, column=5).border = border
ws.cell(row=summary_row, column=6, value="").fill = summary_fill
ws.cell(row=summary_row, column=6).border = border
ws.column_dimensions["A"].width = 18
ws.column_dimensions["B"].width = 25
ws.column_dimensions["C"].width = 10
ws.column_dimensions["D"].width = 10
ws.column_dimensions["E"].width = 30
ws.column_dimensions["E"].width = 15
ws.column_dimensions["F"].width = 30
output = BytesIO()
wb.save(output)