grosze
This commit is contained in:
+48
-2
@@ -190,17 +190,63 @@ async def nbp_rate():
|
||||
)
|
||||
|
||||
|
||||
CSV_MONEY_FIELDS = {
|
||||
"rata",
|
||||
"kapital",
|
||||
"odsetki",
|
||||
"nadplata",
|
||||
"prowizja_nadplaty",
|
||||
"saldo",
|
||||
"odsetki_narastajaco",
|
||||
"koszt_narastajaco",
|
||||
"nadplaty_narastajaco",
|
||||
}
|
||||
CSV_SUMMARY_MONEY_FIELDS = {
|
||||
"total_paid",
|
||||
"total_interest",
|
||||
"total_overpayment",
|
||||
"total_overpayment_fees",
|
||||
"interest_saved",
|
||||
"baseline_interest",
|
||||
"average_payment",
|
||||
"max_payment",
|
||||
}
|
||||
|
||||
|
||||
def _csv_money(value: float) -> str:
|
||||
return f"{float(value):.2f}".replace(".", ",")
|
||||
|
||||
|
||||
@app.post("/api/export/csv")
|
||||
def export_csv(req: SimulationRequest):
|
||||
result = simulate(req)
|
||||
buf = io.StringIO()
|
||||
writer = csv.writer(buf, delimiter=";")
|
||||
writer.writerow(["miesiac", "data_splaty", "dni", "oprocentowanie", "rata", "kapital", "odsetki", "nadplata", "prowizja_nadplaty", "saldo", "karencja", "odsetki_narastajaco", "koszt_narastajaco", "nadplaty_narastajaco"])
|
||||
headers = ["miesiac", "data_splaty", "dni", "oprocentowanie", "rata", "kapital", "odsetki", "nadplata", "prowizja_nadplaty", "saldo", "karencja", "odsetki_narastajaco", "koszt_narastajaco", "nadplaty_narastajaco"]
|
||||
writer.writerow(headers)
|
||||
for row in result.schedule:
|
||||
writer.writerow([row.month, row.due_date, row.days, row.rate, row.payment, row.principal_part, row.interest_part, row.overpayment, row.overpayment_fee, row.remaining, row.grace_type.value, row.cumulative_interest, row.cumulative_cost, row.cumulative_overpayment])
|
||||
values = {
|
||||
"miesiac": row.month,
|
||||
"data_splaty": row.due_date,
|
||||
"dni": row.days,
|
||||
"oprocentowanie": row.rate,
|
||||
"rata": row.payment,
|
||||
"kapital": row.principal_part,
|
||||
"odsetki": row.interest_part,
|
||||
"nadplata": row.overpayment,
|
||||
"prowizja_nadplaty": row.overpayment_fee,
|
||||
"saldo": row.remaining,
|
||||
"karencja": row.grace_type.value,
|
||||
"odsetki_narastajaco": row.cumulative_interest,
|
||||
"koszt_narastajaco": row.cumulative_cost,
|
||||
"nadplaty_narastajaco": row.cumulative_overpayment,
|
||||
}
|
||||
writer.writerow([_csv_money(values[h]) if h in CSV_MONEY_FIELDS else values[h] for h in headers])
|
||||
writer.writerow([])
|
||||
writer.writerow(["Podsumowanie"])
|
||||
for key, value in result.summary.model_dump().items():
|
||||
if key in CSV_SUMMARY_MONEY_FIELDS:
|
||||
value = _csv_money(value)
|
||||
writer.writerow([key, value])
|
||||
data = buf.getvalue().encode("utf-8-sig")
|
||||
return StreamingResponse(
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const money = (v) => new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN', maximumFractionDigits: 0 }).format(v || 0);
|
||||
const money = (v) => new Intl.NumberFormat('pl-PL', { style: 'currency', currency: 'PLN', minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(Number(v) || 0);
|
||||
const num = (id) => Number($(id).value || 0);
|
||||
|
||||
let lineChart, pieChart, barChart, detailChart;
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
<div class="card-body d-flex flex-wrap align-items-center justify-content-between gap-3">
|
||||
<div>
|
||||
<h1 class="h3 mb-1">Symulator kredytu hipotecznego</h1>
|
||||
<p class="text-muted mb-0">@linuxiarz.pl</p>
|
||||
<p class="text-muted mb-0">Dane liczone są w backendzie ale nie są przechowywane na serwerze, może swoje wyliczenia eksportować na na swój dysk</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap justify-content-end">
|
||||
<button id="themeToggle" class="btn btn-outline-secondary btn-sm" type="button" aria-label="Przełącz motyw">☀️ Jasny</button>
|
||||
<button id="loadNbp" class="btn btn-outline-primary btn-sm">Pobierz stopę NBP</button>
|
||||
<button id="exportJson" class="btn btn-outline-secondary btn-sm">Eksport JSON</button>
|
||||
<button id="importJson" class="btn btn-outline-secondary btn-sm">Import JSON</button>
|
||||
<button id="exportJson" class="btn btn-outline-secondary btn-sm">Eksport</button>
|
||||
<button id="importJson" class="btn btn-outline-secondary btn-sm">Import </button>
|
||||
<button id="exportCsv" class="btn btn-outline-secondary btn-sm">CSV</button>
|
||||
<button id="exportPdf" class="btn btn-primary btn-sm">PDF</button>
|
||||
<input id="jsonFile" type="file" accept="application/json,.json" hidden>
|
||||
|
||||
Reference in New Issue
Block a user