Dbmaxwell's picture
feat: deploy FinReport Agent with LightOnOCR review
9703837 verified
Raw
History Blame Contribute Delete
31.4 kB
from __future__ import annotations
from datetime import datetime, time
from decimal import Decimal
from pathlib import Path
import xlsxwriter
from .models import FundPortfolioReport, Severity, ValidationResult
NAVY = "#11233F"
BLUE = "#246BFE"
PALE_BLUE = "#EAF1FF"
TEAL = "#0F9D8A"
PALE_TEAL = "#E5F7F3"
AMBER = "#D98E04"
PALE_AMBER = "#FFF4D6"
RED = "#C83C3C"
PALE_RED = "#FDECEC"
SLATE = "#526173"
LIGHT = "#F5F7FA"
WHITE = "#FFFFFF"
BORDER = "#D9E0E8"
def _number(value: Decimal) -> float:
return float(value)
def _as_datetime(value):
return datetime.combine(value, time.min)
def _formats(workbook: xlsxwriter.Workbook) -> dict[str, xlsxwriter.format.Format]:
return {
"title": workbook.add_format(
{
"bold": True,
"font_size": 18,
"font_color": WHITE,
"bg_color": NAVY,
"align": "left",
"valign": "vcenter",
}
),
"subtitle": workbook.add_format(
{
"font_size": 10,
"font_color": SLATE,
"bg_color": LIGHT,
"align": "left",
"valign": "vcenter",
}
),
"section": workbook.add_format(
{
"bold": True,
"font_size": 11,
"font_color": WHITE,
"bg_color": BLUE,
"align": "left",
"valign": "vcenter",
}
),
"table_header": workbook.add_format(
{
"bold": True,
"font_color": WHITE,
"bg_color": NAVY,
"border": 1,
"border_color": NAVY,
"align": "center",
"valign": "vcenter",
"text_wrap": True,
}
),
"label": workbook.add_format(
{"bold": True, "font_color": NAVY, "bg_color": LIGHT}
),
"text": workbook.add_format({"font_color": NAVY}),
"text_border": workbook.add_format(
{"font_color": NAVY, "border": 1, "border_color": BORDER}
),
"wrapped_text": workbook.add_format(
{
"font_color": NAVY,
"border": 1,
"border_color": BORDER,
"text_wrap": True,
"valign": "top",
}
),
"integer": workbook.add_format(
{"num_format": "#,##0", "border": 1, "border_color": BORDER}
),
"decimal": workbook.add_format(
{"num_format": "#,##0.00", "border": 1, "border_color": BORDER}
),
"price": workbook.add_format(
{"num_format": "#,##0.000000", "border": 1, "border_color": BORDER}
),
"money": workbook.add_format(
{
"num_format": '#,##0.00;[Red]-#,##0.00',
"border": 1,
"border_color": BORDER,
}
),
"percent": workbook.add_format(
{
"num_format": "0.00%;[Red]-0.00%",
"border": 1,
"border_color": BORDER,
}
),
"date": workbook.add_format(
{"num_format": "dd/mm/yyyy", "border": 1, "border_color": BORDER}
),
"total_label": workbook.add_format(
{
"bold": True,
"font_color": WHITE,
"bg_color": NAVY,
"border": 1,
"border_color": NAVY,
}
),
"total_number": workbook.add_format(
{
"bold": True,
"font_color": WHITE,
"bg_color": NAVY,
"num_format": "#,##0.00",
"border": 1,
"border_color": NAVY,
}
),
"total_percent": workbook.add_format(
{
"bold": True,
"font_color": WHITE,
"bg_color": NAVY,
"num_format": "0.00%",
"border": 1,
"border_color": NAVY,
}
),
"declared_label": workbook.add_format(
{
"bold": True,
"font_color": NAVY,
"bg_color": PALE_BLUE,
"border": 1,
"border_color": BORDER,
}
),
"declared_number": workbook.add_format(
{
"bold": True,
"font_color": NAVY,
"bg_color": PALE_BLUE,
"num_format": "#,##0.00",
"border": 1,
"border_color": BORDER,
}
),
"declared_percent": workbook.add_format(
{
"bold": True,
"font_color": NAVY,
"bg_color": PALE_BLUE,
"num_format": "0.00%",
"border": 1,
"border_color": BORDER,
}
),
"status_ok": workbook.add_format(
{"bold": True, "font_color": TEAL, "bg_color": PALE_TEAL}
),
"status_warning": workbook.add_format(
{"bold": True, "font_color": AMBER, "bg_color": PALE_AMBER}
),
"status_error": workbook.add_format(
{"bold": True, "font_color": RED, "bg_color": PALE_RED}
),
"small": workbook.add_format({"font_size": 8, "font_color": SLATE}),
"hash": workbook.add_format(
{"font_name": "Consolas", "font_size": 8, "font_color": SLATE}
),
}
def _status_format(formats, validation: ValidationResult):
if validation.error_count:
return formats["status_error"]
if validation.warning_count:
return formats["status_warning"]
return formats["status_ok"]
def _add_title(
sheet,
title: str,
subtitle: str,
last_column: int,
formats,
) -> None:
sheet.merge_range(0, 0, 0, last_column, title, formats["title"])
sheet.merge_range(1, 0, 1, last_column, subtitle, formats["subtitle"])
sheet.set_row(0, 30)
sheet.set_row(1, 22)
sheet.hide_gridlines(2)
def _configure_print(sheet, *, repeat_header_row: int | None = None) -> None:
sheet.set_landscape()
sheet.set_paper(9)
sheet.fit_to_pages(1, 0)
sheet.center_horizontally()
sheet.set_margins(left=0.25, right=0.25, top=0.45, bottom=0.45)
sheet.set_header("&LFinReport Agent&C&F&R&P / &N", {"margin": 0.2})
sheet.set_footer(
"&LKaynak belgeye göre otomatik oluşturulmuştur.&R&D &T",
{"margin": 0.2},
)
if repeat_header_row is not None:
sheet.repeat_rows(repeat_header_row, repeat_header_row)
def _write_summary(workbook, report, validation, formats) -> None:
sheet = workbook.add_worksheet("Özet")
_add_title(
sheet,
"FinReport Agent · Doğrulanmış Portföy Özeti",
f"{report.metadata.fund_name} · {report.metadata.period}",
5,
formats,
)
sheet.set_column("A:A", 25)
sheet.set_column("B:B", 24)
sheet.set_column("C:E", 20)
sheet.set_column("F:F", 15)
sheet.freeze_panes(8, 0)
sheet.write("A3", "Doğrulama durumu", formats["label"])
sheet.write("B3", validation.status, _status_format(formats, validation))
sheet.write("A4", "Kaynak dosya", formats["label"])
sheet.write("B4", report.metadata.source_filename, formats["text"])
sheet.write("D3", "Fon kodu", formats["label"])
sheet.write("E3", report.metadata.fund_code or "-", formats["text"])
sheet.write("D4", "Dönem", formats["label"])
sheet.write("E4", report.metadata.period, formats["text"])
sheet.write("A6", "Portföy uzlaştırması", formats["section"])
sheet.merge_range("B6:F6", "", formats["section"])
headers = [
"Kalem",
"Muhasebesel Sınıf",
"PDF Beyanı (TL)",
"Detay Hesabı (TL)",
"Fark (TL)",
"FPD (%)",
]
for column, header in enumerate(headers):
sheet.write(7, column, header)
totals = report.declared_totals
equity_calc = sum(row.total_value for row in report.equities)
repo_calc = sum(row.total_value for row in report.repos)
collateral_calc = sum(row.total_value for row in report.cash_collaterals)
rows = [
(
"Hisse Senetleri",
"Portföye dahil",
totals.equity_value,
equity_calc,
totals.equity_fpd_pct,
),
(
"T. Repo",
"Portföye dahil",
totals.repo_value,
repo_calc,
totals.repo_fpd_pct,
),
(
"VİOP Nakit Teminatı",
"Portföye dahil",
totals.cash_collateral_value,
collateral_calc,
totals.cash_collateral_fpd_pct,
),
(
"FON PORTFÖY DEĞERİ",
"Uzlaştırılmış toplam",
totals.fund_portfolio_value,
equity_calc + repo_calc + collateral_calc,
Decimal("1"),
),
(
"Futures Pozisyon Değeri",
"Bilgi / maruziyet",
totals.derivative_exposure,
sum(row.total_value for row in report.derivatives),
Decimal("0"),
),
]
for row_index, (name, classification, declared, calculated, percentage) in enumerate(
rows, start=8
):
sheet.write(row_index, 0, name, formats["text_border"])
sheet.write(row_index, 1, classification, formats["text_border"])
sheet.write_number(row_index, 2, _number(declared), formats["money"])
sheet.write_number(row_index, 3, _number(calculated), formats["money"])
sheet.write_formula(
row_index,
4,
f"=D{row_index + 1}-C{row_index + 1}",
formats["money"],
_number(calculated - declared),
)
sheet.write_number(row_index, 5, _number(percentage), formats["percent"])
sheet.add_table(
7,
0,
12,
5,
{
"name": "PortfolioSummary",
"style": "Table Style Medium 2",
"columns": [
{"header": header, "header_format": formats["table_header"]}
for header in headers
],
},
)
sheet.conditional_format(
"E9:E13",
{
"type": "cell",
"criteria": "not between",
"minimum": -0.01,
"maximum": 0.01,
"format": formats["status_error"],
},
)
sheet.write("A15", "Not", formats["label"])
sheet.merge_range(
"B15:F15",
(
"Futures pozisyon değeri maruziyettir; fon portföy değeri toplamına "
"eklenmez. VİOP nakit teminatı portföy uzlaştırmasına dahildir."
),
formats["subtitle"],
)
sheet.set_row(7, 28)
_configure_print(sheet)
def _write_equities(workbook, report, formats) -> None:
sheet = workbook.add_worksheet("Hisse Senetleri")
_add_title(
sheet,
"Hisse Senetleri",
f"{len(report.equities)} pozisyon · Kaynak koordinatları korunmuştur",
13,
formats,
)
headers = [
"Kod",
"İhraççı Kurum",
"Döviz",
"ISIN",
"Nominal Değer",
"Birim Alış Fiyatı",
"Satın Alış Tarihi",
"Borsa Sözleşme No",
"Güncel Birim Fiyat",
"Toplam Değer (TL)",
"Grup (%)",
"FPD (%)",
"FTD (%)",
"Kaynak Sayfa",
]
header_row = 3
for column, header in enumerate(headers):
sheet.write(header_row, column, header)
for row_index, row in enumerate(report.equities, start=header_row + 1):
sheet.write(row_index, 0, row.code, formats["text_border"])
issuer_format = (
formats["wrapped_text"] if len(row.issuer) > 42 else formats["text_border"]
)
sheet.write(row_index, 1, row.issuer, issuer_format)
if len(row.issuer) > 42:
sheet.set_row(row_index, 30)
sheet.write(row_index, 2, row.currency, formats["text_border"])
sheet.write(row_index, 3, row.isin, formats["text_border"])
sheet.write_number(row_index, 4, _number(row.nominal), formats["decimal"])
sheet.write_number(row_index, 5, _number(row.purchase_price), formats["price"])
sheet.write_datetime(
row_index, 6, _as_datetime(row.purchase_date), formats["date"]
)
sheet.write(row_index, 7, row.contract_no or "", formats["text_border"])
sheet.write_number(row_index, 8, _number(row.current_price), formats["price"])
sheet.write_number(row_index, 9, _number(row.total_value), formats["money"])
sheet.write_number(row_index, 10, _number(row.group_pct), formats["percent"])
sheet.write_number(row_index, 11, _number(row.fpd_pct), formats["percent"])
sheet.write_number(row_index, 12, _number(row.ftd_pct), formats["percent"])
sheet.write_number(row_index, 13, row.source.page, formats["integer"])
last_data_row = header_row + len(report.equities)
sheet.add_table(
header_row,
0,
last_data_row,
len(headers) - 1,
{
"name": "EquityPositions",
"style": "Table Style Medium 2",
"columns": [
{"header": header, "header_format": formats["table_header"]}
for header in headers
],
},
)
calculated_row = last_data_row + 1
declared_row = last_data_row + 2
sheet.write(calculated_row, 0, "HESAPLANAN TOPLAM", formats["total_label"])
sheet.write_formula(
calculated_row,
4,
f"=SUM(E{header_row + 2}:E{last_data_row + 1})",
formats["total_number"],
_number(sum(row.nominal for row in report.equities)),
)
sheet.write_formula(
calculated_row,
9,
f"=SUM(J{header_row + 2}:J{last_data_row + 1})",
formats["total_number"],
_number(sum(row.total_value for row in report.equities)),
)
for column, attr in ((10, "group_pct"), (11, "fpd_pct"), (12, "ftd_pct")):
sheet.write_formula(
calculated_row,
column,
f"=SUM({xlsxwriter.utility.xl_col_to_name(column)}"
f"{header_row + 2}:{xlsxwriter.utility.xl_col_to_name(column)}"
f"{last_data_row + 1})",
formats["total_percent"],
_number(sum(getattr(row, attr) for row in report.equities)),
)
for column in range(1, len(headers)):
if column not in {4, 9, 10, 11, 12}:
sheet.write_blank(calculated_row, column, None, formats["total_label"])
totals = report.declared_totals
sheet.write(declared_row, 0, "PDF BEYAN TOPLAMI", formats["declared_label"])
sheet.write_number(
declared_row, 4, _number(totals.equity_nominal), formats["declared_number"]
)
sheet.write_number(
declared_row, 9, _number(totals.equity_value), formats["declared_number"]
)
sheet.write_number(declared_row, 10, 1, formats["declared_percent"])
sheet.write_number(
declared_row, 11, _number(totals.equity_fpd_pct), formats["declared_percent"]
)
sheet.write_number(
declared_row, 12, _number(totals.equity_ftd_pct), formats["declared_percent"]
)
for column in range(1, len(headers)):
if column not in {4, 9, 10, 11, 12}:
sheet.write_blank(declared_row, column, None, formats["declared_label"])
sheet.freeze_panes(header_row + 1, 2)
sheet.set_column("A:A", 12)
sheet.set_column("B:B", 38)
sheet.set_column("C:C", 9)
sheet.set_column("D:D", 17)
sheet.set_column("E:F", 17)
sheet.set_column("G:G", 15)
sheet.set_column("H:H", 20)
sheet.set_column("I:J", 18)
sheet.set_column("K:M", 12)
sheet.set_column("N:N", 13)
sheet.set_row(header_row, 34)
_configure_print(sheet, repeat_header_row=header_row)
def _write_repos(workbook, report, formats) -> None:
sheet = workbook.add_worksheet("T. Repo")
_add_title(
sheet,
"Ters Repo Pozisyonları",
f"{len(report.repos)} pozisyon",
19,
formats,
)
headers = [
"Kod",
"Döviz",
"İhraççı",
"Vade Tarihi",
"Kalan Gün",
"ISIN",
"İç İskonto (%)",
"Faiz Ödeme Sayısı",
"Nominal Değer",
"Birim Alış Fiyatı",
"Satın Alış Tarihi",
"Repo Teminatı",
"Borsa Sözleşme No",
"Net Dönüş",
"Günlük Br Değer",
"Toplam Değer (TL)",
"Grup (%)",
"FPD (%)",
"FTD (%)",
"Kaynak Sayfa",
]
header_row = 3
for column, header in enumerate(headers):
sheet.write(header_row, column, header)
for row_index, row in enumerate(report.repos, start=header_row + 1):
values = [row.code, row.currency, row.issuer]
for column, value in enumerate(values):
sheet.write(row_index, column, value, formats["text_border"])
sheet.write_datetime(
row_index, 3, _as_datetime(row.maturity_date), formats["date"]
)
sheet.write_number(row_index, 4, row.days_to_maturity, formats["integer"])
sheet.write(row_index, 5, row.isin, formats["text_border"])
sheet.write_number(
row_index, 6, _number(row.discount_rate / 100), formats["percent"]
)
sheet.write_number(
row_index, 7, row.interest_payment_count, formats["integer"]
)
sheet.write_number(row_index, 8, _number(row.nominal), formats["money"])
sheet.write_number(row_index, 9, _number(row.purchase_price), formats["price"])
sheet.write_datetime(
row_index, 10, _as_datetime(row.purchase_date), formats["date"]
)
sheet.write_number(
row_index, 11, _number(row.collateral_amount), formats["money"]
)
sheet.write(row_index, 12, row.contract_no, formats["text_border"])
sheet.write_number(row_index, 13, _number(row.net_return), formats["money"])
sheet.write_number(row_index, 14, _number(row.daily_value), formats["price"])
sheet.write_number(row_index, 15, _number(row.total_value), formats["money"])
sheet.write_number(row_index, 16, _number(row.group_pct), formats["percent"])
sheet.write_number(row_index, 17, _number(row.fpd_pct), formats["percent"])
sheet.write_number(row_index, 18, _number(row.ftd_pct), formats["percent"])
sheet.write_number(row_index, 19, row.source.page, formats["integer"])
last_data_row = header_row + len(report.repos)
sheet.add_table(
header_row,
0,
last_data_row,
len(headers) - 1,
{
"name": "RepoPositions",
"style": "Table Style Medium 2",
"columns": [
{"header": header, "header_format": formats["table_header"]}
for header in headers
],
},
)
total_row = last_data_row + 1
sheet.write(total_row, 0, "HESAPLANAN TOPLAM", formats["total_label"])
sheet.write_formula(
total_row,
15,
f"=SUM(P{header_row + 2}:P{last_data_row + 1})",
formats["total_number"],
_number(sum(row.total_value for row in report.repos)),
)
for column, attr in ((16, "group_pct"), (17, "fpd_pct"), (18, "ftd_pct")):
letter = xlsxwriter.utility.xl_col_to_name(column)
sheet.write_formula(
total_row,
column,
f"=SUM({letter}{header_row + 2}:{letter}{last_data_row + 1})",
formats["total_percent"],
_number(sum(getattr(row, attr) for row in report.repos)),
)
for column in range(1, len(headers)):
if column not in {15, 16, 17, 18}:
sheet.write_blank(total_row, column, None, formats["total_label"])
sheet.freeze_panes(header_row + 1, 2)
sheet.set_column(0, 19, 15)
sheet.set_column("C:C", 18)
sheet.set_column("F:F", 17)
sheet.set_column("M:M", 20)
sheet.set_row(header_row, 34)
_configure_print(sheet, repeat_header_row=header_row)
def _write_derivatives(workbook, report, formats) -> None:
sheet = workbook.add_worksheet("Türev")
_add_title(
sheet,
"Türev Pozisyonlar ve Nakit Teminatlar",
"Maruziyet ile portföye dahil nakit teminatı ayrı sunulur",
13,
formats,
)
headers = [
"Tür",
"Kod",
"Döviz",
"Vade Tarihi",
"Nominal",
"Birim Alış Fiyatı",
"Satın Alış Tarihi",
"Borsa Sözleşme No",
"Güncel Fiyat",
"Pozisyon Değeri (TL)",
"Grup (%)",
"FPD (%)",
"FTD (%)",
"Kaynak Sayfa",
]
header_row = 3
for column, header in enumerate(headers):
sheet.write(header_row, column, header)
for row_index, row in enumerate(report.derivatives, start=header_row + 1):
sheet.write(row_index, 0, row.position_type, formats["text_border"])
sheet.write(row_index, 1, row.code, formats["text_border"])
sheet.write(row_index, 2, row.currency, formats["text_border"])
if row.maturity_date:
sheet.write_datetime(
row_index, 3, _as_datetime(row.maturity_date), formats["date"]
)
else:
sheet.write(row_index, 3, "-", formats["text_border"])
sheet.write_number(row_index, 4, _number(row.nominal), formats["decimal"])
sheet.write_number(row_index, 5, _number(row.purchase_price), formats["price"])
sheet.write_datetime(
row_index, 6, _as_datetime(row.purchase_date), formats["date"]
)
sheet.write(row_index, 7, row.contract_no or "", formats["text_border"])
sheet.write_number(row_index, 8, _number(row.current_price), formats["price"])
sheet.write_number(row_index, 9, _number(row.total_value), formats["money"])
sheet.write_number(row_index, 10, _number(row.group_pct), formats["percent"])
sheet.write_number(row_index, 11, _number(row.fpd_pct), formats["percent"])
sheet.write_number(row_index, 12, _number(row.ftd_pct), formats["percent"])
sheet.write_number(row_index, 13, row.source.page, formats["integer"])
last_derivative_row = header_row + len(report.derivatives)
sheet.add_table(
header_row,
0,
last_derivative_row,
len(headers) - 1,
{
"name": "DerivativePositions",
"style": "Table Style Medium 2",
"columns": [
{"header": header, "header_format": formats["table_header"]}
for header in headers
],
},
)
cash_header = last_derivative_row + 3
sheet.merge_range(
cash_header - 1,
0,
cash_header - 1,
5,
"Portföye Dahil Nakit Teminatlar",
formats["section"],
)
cash_headers = [
"Kalem",
"Döviz",
"Nominal",
"Toplam Değer (TL)",
"Grup (%)",
"FPD (%)",
"Kaynak Sayfa",
]
for column, header in enumerate(cash_headers):
sheet.write(cash_header, column, header)
for row_index, row in enumerate(report.cash_collaterals, start=cash_header + 1):
sheet.write(row_index, 0, row.name, formats["text_border"])
sheet.write(row_index, 1, row.currency, formats["text_border"])
sheet.write_number(row_index, 2, _number(row.nominal), formats["money"])
sheet.write_number(row_index, 3, _number(row.total_value), formats["money"])
sheet.write_number(row_index, 4, _number(row.group_pct), formats["percent"])
sheet.write_number(row_index, 5, _number(row.fpd_pct), formats["percent"])
sheet.write_number(row_index, 6, row.source.page, formats["integer"])
if report.cash_collaterals:
sheet.add_table(
cash_header,
0,
cash_header + len(report.cash_collaterals),
len(cash_headers) - 1,
{
"name": "CashCollaterals",
"style": "Table Style Medium 4",
"columns": [
{"header": header, "header_format": formats["table_header"]}
for header in cash_headers
],
},
)
sheet.freeze_panes(header_row + 1, 2)
sheet.set_column("A:B", 20)
sheet.set_column("C:C", 10)
sheet.set_column("D:J", 18)
sheet.set_column("K:N", 13)
sheet.set_row(header_row, 34)
sheet.set_row(cash_header, 30)
_configure_print(sheet, repeat_header_row=header_row)
def _write_findings(workbook, report, validation, formats) -> None:
sheet = workbook.add_worksheet("Kontroller")
_add_title(
sheet,
"Finansal Doğrulama ve Denetim İzi",
(
f"{validation.error_count} hata · {validation.warning_count} uyarı · "
f"{validation.info_count} bilgi"
),
8,
formats,
)
sheet.write("A3", "Durum", formats["label"])
sheet.write("B3", validation.status, _status_format(formats, validation))
sheet.write("A4", "SHA-256", formats["label"])
sheet.merge_range("B4:I4", report.metadata.source_sha256, formats["hash"])
headers = [
"Seviye",
"Kontrol Kodu",
"Açıklama",
"Sayfa",
"Kayıt",
"Beklenen",
"Gerçekleşen",
"Çalışma Sayfası",
"Sonuç",
]
header_row = 6
for column, header in enumerate(headers):
sheet.write(header_row, column, header)
for row_index, finding in enumerate(validation.findings, start=header_row + 1):
severity_label = {
Severity.ERROR: "Hata",
Severity.WARNING: "Uyarı",
Severity.INFO: "Bilgi",
}[finding.severity]
severity_format = {
Severity.ERROR: formats["status_error"],
Severity.WARNING: formats["status_warning"],
Severity.INFO: formats["status_ok"],
}[finding.severity]
sheet.write(row_index, 0, severity_label, severity_format)
sheet.write(row_index, 1, finding.code, formats["text_border"])
sheet.write(row_index, 2, finding.message, formats["text_border"])
sheet.write(row_index, 3, finding.page or "", formats["text_border"])
sheet.write(row_index, 4, finding.record_key or "", formats["text_border"])
sheet.write(row_index, 5, finding.expected or "", formats["text_border"])
sheet.write(row_index, 6, finding.actual or "", formats["text_border"])
sheet.write(row_index, 7, finding.sheet or "", formats["text_border"])
result = "İncele" if finding.severity != Severity.INFO else "Bilgilendirme"
sheet.write(row_index, 8, result, severity_format)
last_row = header_row + max(1, len(validation.findings))
if validation.findings:
sheet.add_table(
header_row,
0,
last_row,
len(headers) - 1,
{
"name": "ValidationFindings",
"style": "Table Style Medium 2",
"columns": [
{"header": header, "header_format": formats["table_header"]}
for header in headers
],
},
)
sheet.freeze_panes(header_row + 1, 0)
sheet.set_column("A:B", 22)
sheet.set_column("C:C", 72)
sheet.set_column("D:E", 13)
sheet.set_column("F:G", 22)
sheet.set_column("H:I", 20)
sheet.set_row(header_row + 1, 38)
sheet.set_row(header_row, 30)
_configure_print(sheet, repeat_header_row=header_row)
def _write_provenance(workbook, report, formats) -> None:
sheet = workbook.add_worksheet("Kaynak İzleri")
_add_title(
sheet,
"Hücre Kaynak İzleri",
"Her kayıt PDF sayfası ve koordinat kutusuyla eşleştirilir",
8,
formats,
)
headers = [
"Çalışma Sayfası",
"Kayıt Türü",
"Kayıt Anahtarı",
"PDF Sayfası",
"X0",
"Y0",
"X1",
"Y1",
"Çıkarım Yöntemi",
]
header_row = 3
for column, header in enumerate(headers):
sheet.write(header_row, column, header)
records = []
records.extend(
("Hisse Senetleri", "Hisse", row.code, row.source)
for row in report.equities
)
records.extend(("T. Repo", "Repo", row.code, row.source) for row in report.repos)
records.extend(
("Türev", "Türev", row.code, row.source) for row in report.derivatives
)
records.extend(
("Türev", "Nakit Teminat", row.name, row.source)
for row in report.cash_collaterals
)
for row_index, (sheet_name, record_type, key, source) in enumerate(
records, start=header_row + 1
):
sheet.write(row_index, 0, sheet_name, formats["text_border"])
sheet.write(row_index, 1, record_type, formats["text_border"])
sheet.write(row_index, 2, key, formats["text_border"])
sheet.write_number(row_index, 3, source.page, formats["integer"])
for offset, coordinate in enumerate(source.bbox):
sheet.write_number(
row_index, 4 + offset, coordinate, formats["decimal"]
)
sheet.write(row_index, 8, source.method.value, formats["text_border"])
sheet.add_table(
header_row,
0,
header_row + len(records),
len(headers) - 1,
{
"name": "SourceProvenance",
"style": "Table Style Medium 2",
"columns": [
{"header": header, "header_format": formats["table_header"]}
for header in headers
],
},
)
sheet.freeze_panes(header_row + 1, 0)
sheet.set_column("A:C", 22)
sheet.set_column("D:I", 15)
sheet.set_row(header_row, 30)
_configure_print(sheet, repeat_header_row=header_row)
def write_workbook(
report: FundPortfolioReport,
validation: ValidationResult,
output_path: str | Path,
) -> Path:
path = Path(output_path).expanduser().resolve()
path.parent.mkdir(parents=True, exist_ok=True)
workbook = xlsxwriter.Workbook(
path,
{
"constant_memory": False,
"nan_inf_to_errors": True,
},
)
workbook.set_properties(
{
"title": f"{report.metadata.fund_code or ''} Fon Portföy Raporu",
"subject": "FinReport Agent tarafından kaynak PDF'den oluşturuldu",
"author": "FinReport Agent",
"company": "FinReport Agent",
"comments": (
f"Kaynak SHA-256: {report.metadata.source_sha256}. "
"Kontroller sayfasını inceleyin."
),
}
)
formats = _formats(workbook)
_write_summary(workbook, report, validation, formats)
_write_equities(workbook, report, formats)
_write_repos(workbook, report, formats)
_write_derivatives(workbook, report, formats)
_write_findings(workbook, report, validation, formats)
_write_provenance(workbook, report, formats)
workbook.close()
return path