feat: migrate backend storage to postgres
Some checks failed
Deploy to Production / Build and Test (push) Successful in 10m51s
Deploy to Production / Deploy to Server (push) Failing after 6m41s

This commit is contained in:
你的用户名
2025-11-06 22:01:50 +08:00
parent 3646405a47
commit b68511b2e2
28 changed files with 2641 additions and 1801 deletions

View File

@@ -6,7 +6,7 @@ export default defineEventHandler(async (event) => {
const query = getQuery(event);
const currency = query.currency as string | undefined;
let accounts = listAccounts();
let accounts = await listAccounts();
if (currency) {
accounts = accounts.filter((account) => account.currency === currency);

View File

@@ -6,7 +6,7 @@ export default defineEventHandler(async (event) => {
const query = getQuery(event);
const type = query.type as 'expense' | 'income' | undefined;
const categories = fetchCategories({ type });
const categories = await fetchCategories({ type });
return useResponseSuccess(categories);
});

View File

@@ -1,20 +1,19 @@
import type { TransactionStatus } from '~/utils/finance-repository';
import { readBody } from 'h3';
import {
createTransaction,
type TransactionStatus,
} from '~/utils/finance-repository';
import { createTransaction } from '~/utils/finance-repository';
import { useResponseError, useResponseSuccess } from '~/utils/response';
import { notifyTransactionWebhook } from '~/utils/telegram-webhook';
const DEFAULT_CURRENCY = 'CNY';
const DEFAULT_STATUS: TransactionStatus = 'pending';
const ALLOWED_STATUSES: TransactionStatus[] = [
const ALLOWED_STATUSES = new Set<TransactionStatus>([
'draft',
'pending',
'approved',
'rejected',
'paid',
];
]);
export default defineEventHandler(async (event) => {
const body = await readBody(event);
@@ -33,11 +32,11 @@ export default defineEventHandler(async (event) => {
const status =
(body.status as TransactionStatus | undefined) ?? DEFAULT_STATUS;
if (!ALLOWED_STATUSES.includes(status)) {
if (!ALLOWED_STATUSES.has(status)) {
return useResponseError('状态值不合法', -1);
}
const reimbursement = createTransaction({
const reimbursement = await createTransaction({
type,
amount,
currency: body.currency ?? DEFAULT_CURRENCY,

View File

@@ -1,18 +1,19 @@
import type { TransactionStatus } from '~/utils/finance-repository';
import { getRouterParam, readBody } from 'h3';
import {
restoreTransaction,
updateTransaction,
type TransactionStatus,
} from '~/utils/finance-repository';
import { useResponseError, useResponseSuccess } from '~/utils/response';
const ALLOWED_STATUSES: TransactionStatus[] = [
const ALLOWED_STATUSES = new Set<TransactionStatus>([
'draft',
'pending',
'approved',
'rejected',
'paid',
];
]);
export default defineEventHandler(async (event) => {
const id = Number(getRouterParam(event, 'id'));
@@ -23,7 +24,7 @@ export default defineEventHandler(async (event) => {
const body = await readBody(event);
if (body?.isDeleted === false) {
const restored = restoreTransaction(id);
const restored = await restoreTransaction(id);
if (!restored) {
return useResponseError('报销单不存在', -1);
}
@@ -52,7 +53,7 @@ export default defineEventHandler(async (event) => {
if (body?.isDeleted !== undefined) payload.isDeleted = body.isDeleted;
if (body?.status !== undefined) {
const status = body.status as TransactionStatus;
if (!ALLOWED_STATUSES.includes(status)) {
if (!ALLOWED_STATUSES.has(status)) {
return useResponseError('状态值不合法', -1);
}
payload.status = status;
@@ -76,7 +77,7 @@ export default defineEventHandler(async (event) => {
payload.approvedAt = body.approvedAt ?? null;
}
const updated = updateTransaction(id, payload);
const updated = await updateTransaction(id, payload);
if (!updated) {
return useResponseError('报销单不存在', -1);
}

View File

@@ -18,7 +18,7 @@ export default defineEventHandler(async (event) => {
.map((item) => item.trim())
.filter((item) => item.length > 0) as TransactionStatus[])
: (['approved', 'paid'] satisfies TransactionStatus[]);
const transactions = fetchTransactions({
const transactions = await fetchTransactions({
type,
includeDeleted,
statuses,

View File

@@ -1,21 +1,23 @@
import type { TransactionStatus } from '~/utils/finance-repository';
import { readBody } from 'h3';
import {
createTransaction,
type TransactionStatus,
getAccountById,
getCategoryById,
} from '~/utils/finance-repository';
import { useResponseError, useResponseSuccess } from '~/utils/response';
import { notifyTransactionWebhook } from '~/utils/telegram-webhook';
import { notifyTransaction } from '~/utils/telegram-bot';
import db from '~/utils/sqlite';
import { notifyTransactionWebhook } from '~/utils/telegram-webhook';
const DEFAULT_CURRENCY = 'CNY';
const ALLOWED_STATUSES: TransactionStatus[] = [
const ALLOWED_STATUSES = new Set<TransactionStatus>([
'draft',
'pending',
'approved',
'rejected',
'paid',
];
]);
export default defineEventHandler(async (event) => {
const body = await readBody(event);
@@ -29,13 +31,12 @@ export default defineEventHandler(async (event) => {
return useResponseError('金额格式不正确', -1);
}
const status =
(body.status as TransactionStatus | undefined) ?? 'approved';
if (!ALLOWED_STATUSES.includes(status)) {
const status = (body.status as TransactionStatus | undefined) ?? 'approved';
if (!ALLOWED_STATUSES.has(status)) {
return useResponseError('状态值不合法', -1);
}
const transaction = createTransaction({
const transaction = await createTransaction({
type: body.type,
amount,
currency: body.currency ?? DEFAULT_CURRENCY,
@@ -61,23 +62,12 @@ export default defineEventHandler(async (event) => {
// 发送Telegram通知新功能
try {
// 获取分类和账户名称
let categoryName: string | undefined;
let accountName: string | undefined;
if (transaction.categoryId) {
const category = db
.prepare<{ name: string }>('SELECT name FROM finance_categories WHERE id = ?')
.get(transaction.categoryId);
categoryName = category?.name;
}
if (transaction.accountId) {
const account = db
.prepare<{ name: string }>('SELECT name FROM finance_accounts WHERE id = ?')
.get(transaction.accountId);
accountName = account?.name;
}
const category = transaction.categoryId
? await getCategoryById(transaction.categoryId)
: null;
const account = transaction.accountId
? await getAccountById(transaction.accountId)
: null;
await notifyTransaction(
{
@@ -85,8 +75,8 @@ export default defineEventHandler(async (event) => {
type: transaction.type,
amount: transaction.amount,
currency: transaction.currency,
categoryName,
accountName,
categoryName: category?.name,
accountName: account?.name,
transactionDate: transaction.transactionDate,
description: transaction.description || undefined,
status: transaction.status,

View File

@@ -9,7 +9,7 @@ export default defineEventHandler(async (event) => {
return useResponseError('参数错误', -1);
}
const updated = softDeleteTransaction(id);
const updated = await softDeleteTransaction(id);
if (!updated) {
return useResponseError('交易不存在', -1);
}

View File

@@ -1,18 +1,19 @@
import type { TransactionStatus } from '~/utils/finance-repository';
import { getRouterParam, readBody } from 'h3';
import {
restoreTransaction,
updateTransaction,
type TransactionStatus,
} from '~/utils/finance-repository';
import { useResponseError, useResponseSuccess } from '~/utils/response';
const ALLOWED_STATUSES: TransactionStatus[] = [
const ALLOWED_STATUSES = new Set<TransactionStatus>([
'draft',
'pending',
'approved',
'rejected',
'paid',
];
]);
export default defineEventHandler(async (event) => {
const id = Number(getRouterParam(event, 'id'));
@@ -23,7 +24,7 @@ export default defineEventHandler(async (event) => {
const body = await readBody(event);
if (body?.isDeleted === false) {
const restored = restoreTransaction(id);
const restored = await restoreTransaction(id);
if (!restored) {
return useResponseError('交易不存在', -1);
}
@@ -52,7 +53,7 @@ export default defineEventHandler(async (event) => {
if (body?.isDeleted !== undefined) payload.isDeleted = body.isDeleted;
if (body?.status !== undefined) {
const status = body.status as TransactionStatus;
if (!ALLOWED_STATUSES.includes(status)) {
if (!ALLOWED_STATUSES.has(status)) {
return useResponseError('状态值不合法', -1);
}
payload.status = status;
@@ -76,7 +77,7 @@ export default defineEventHandler(async (event) => {
payload.approvedAt = body.approvedAt ?? null;
}
const updated = updateTransaction(id, payload);
const updated = await updateTransaction(id, payload);
if (!updated) {
return useResponseError('交易不存在', -1);
}