38 lines
1.4 KiB
TypeScript
38 lines
1.4 KiB
TypeScript
import { setHeader } from 'h3'
|
|
import { format } from 'date-fns'
|
|
import { prisma } from '../../utils/db'
|
|
import { requireUser } from '../../utils/auth'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const user = await requireUser(event)
|
|
const rows = await prisma.transaction.findMany({
|
|
where: { userId: user.id },
|
|
include: { asset: true, category: { include: { parent: true } } },
|
|
orderBy: { occurredAt: 'desc' }
|
|
})
|
|
|
|
const escape = (value: unknown) => `"${String(value ?? '').replaceAll('"', '""')}"`
|
|
const categoryName = (row: typeof rows[number]) => row.category.name
|
|
const parentCategoryName = (row: typeof rows[number]) => row.category.parent?.name || ''
|
|
const lines = [
|
|
['날짜', '유형', '자산', '상위분류', '분류', '금액', '내용', '메모', '위도', '경도', '거래ID'].map(escape).join(','),
|
|
...rows.map(row => [
|
|
format(row.occurredAt, 'yyyy-MM-dd'),
|
|
row.type === 'income' ? '수입' : '지출',
|
|
row.asset.name,
|
|
parentCategoryName(row),
|
|
categoryName(row),
|
|
row.amount,
|
|
row.title,
|
|
row.memo,
|
|
row.latitude,
|
|
row.longitude,
|
|
row.id
|
|
].map(escape).join(','))
|
|
]
|
|
|
|
setHeader(event, 'content-type', 'text/csv; charset=utf-8')
|
|
setHeader(event, 'content-disposition', 'attachment; filename="money-transactions.csv"')
|
|
return `\uFEFF${lines.join('\n')}`
|
|
})
|