c0b114efeb
- kategori formunda grup ve banka maliyeti; listede grup rozeti ve grupsuz uyarısı - işlem formunda "Kategoriden: …" önerili grup seçimi, bölünmüş kalem başına - /raporlar/kakeibo (yığılmış pay çubuğu, grup kartları, banka maliyeti, grupsuzlar, CSV) - bütçe sayfasında Kakeibo özeti Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
25 lines
1.1 KiB
TypeScript
25 lines
1.1 KiB
TypeScript
import { csvContext, csvResponse, forbidden, unauthorized } from "@/features/reports/csv";
|
||
import { getKakeiboReport } from "@/features/reports/kakeibo";
|
||
import { tr } from "@/i18n/tr";
|
||
import { csvMoney, toCsv } from "@/shared/csv";
|
||
import { KAKEIBO_GROUPS, type SpendingClass } from "@/shared/kakeibo";
|
||
|
||
/** GET /raporlar/kakeibo/csv?ay=YYYY-MM — sınıf × kategori tutarları. */
|
||
export async function GET(request: Request) {
|
||
const c = await csvContext(request);
|
||
if (!c) return unauthorized();
|
||
const r = await getKakeiboReport(c.userId, c.householdId, c.month);
|
||
if (!r) return forbidden();
|
||
const k = tr.kakeibo;
|
||
const label = (cls: SpendingClass) =>
|
||
cls === "BANK_COST" ? k.bankCost : cls === "UNGROUPED" ? k.ungrouped : k.groups[cls];
|
||
const order: SpendingClass[] = [...KAKEIBO_GROUPS, "UNGROUPED", "BANK_COST"];
|
||
const rows = order.flatMap((cls) =>
|
||
r.now.byClass[cls].map((x) => [label(cls), x.path, csvMoney(x.amountMinor)]),
|
||
);
|
||
return csvResponse(
|
||
toCsv(tr.reports.kakeiboReport.csvHeader, rows),
|
||
tr.reports.kakeiboReport.csvFile(r.month),
|
||
);
|
||
}
|