186 lines
4.2 KiB
TypeScript
186 lines
4.2 KiB
TypeScript
import { query } from './db';
|
|
import {
|
|
MOCK_ACCOUNTS,
|
|
MOCK_BUDGETS,
|
|
MOCK_CATEGORIES,
|
|
MOCK_CURRENCIES,
|
|
MOCK_EXCHANGE_RATES,
|
|
} from './mock-data';
|
|
|
|
interface AccountRow {
|
|
id: number;
|
|
name: string;
|
|
type: string;
|
|
currency: string;
|
|
icon: null | string;
|
|
color: null | string;
|
|
user_id: null | number;
|
|
is_active: boolean;
|
|
}
|
|
|
|
interface CategoryRow {
|
|
id: number;
|
|
name: string;
|
|
type: string;
|
|
icon: null | string;
|
|
color: null | string;
|
|
user_id: null | number;
|
|
is_active: boolean;
|
|
}
|
|
|
|
function mapAccount(row: AccountRow) {
|
|
return {
|
|
id: row.id,
|
|
userId: row.user_id ?? 1,
|
|
name: row.name,
|
|
type: row.type,
|
|
currency: row.currency,
|
|
balance: 0,
|
|
icon: row.icon ?? '💳',
|
|
color: row.color ?? '#1677ff',
|
|
isActive: Boolean(row.is_active),
|
|
};
|
|
}
|
|
|
|
function mapCategory(row: CategoryRow) {
|
|
return {
|
|
id: row.id,
|
|
userId: row.user_id ?? 1,
|
|
name: row.name,
|
|
type: row.type as 'expense' | 'income',
|
|
icon: row.icon ?? '📝',
|
|
color: row.color ?? '#dfe4ea',
|
|
sortOrder: row.id,
|
|
isSystem: row.user_id === null,
|
|
isActive: Boolean(row.is_active),
|
|
};
|
|
}
|
|
|
|
export async function listAccounts() {
|
|
try {
|
|
const { rows } = await query<AccountRow>(
|
|
`SELECT id, name, type, currency, icon, color, user_id, is_active
|
|
FROM finance_accounts
|
|
ORDER BY id`,
|
|
);
|
|
if (rows.length === 0) {
|
|
return MOCK_ACCOUNTS;
|
|
}
|
|
return rows.map((row) => mapAccount(row));
|
|
} catch (error) {
|
|
console.error('从数据库读取账户失败,使用 MOCK 数据:', error);
|
|
return MOCK_ACCOUNTS;
|
|
}
|
|
}
|
|
|
|
export async function listCategories() {
|
|
try {
|
|
const { rows } = await query<CategoryRow>(
|
|
`SELECT id, name, type, icon, color, user_id, is_active
|
|
FROM finance_categories
|
|
WHERE is_active = TRUE
|
|
ORDER BY type, id`,
|
|
);
|
|
if (rows.length === 0) {
|
|
return MOCK_CATEGORIES;
|
|
}
|
|
return rows.map((row) => mapCategory(row));
|
|
} catch (error) {
|
|
console.error('从数据库读取分类失败,使用 MOCK 数据:', error);
|
|
return MOCK_CATEGORIES;
|
|
}
|
|
}
|
|
|
|
export function listBudgets() {
|
|
return MOCK_BUDGETS;
|
|
}
|
|
|
|
export function listCurrencies() {
|
|
return MOCK_CURRENCIES;
|
|
}
|
|
|
|
export function listExchangeRates() {
|
|
return MOCK_EXCHANGE_RATES;
|
|
}
|
|
|
|
export async function createCategoryRecord(category: any) {
|
|
try {
|
|
const { rows } = await query<CategoryRow>(
|
|
`INSERT INTO finance_categories (name, type, icon, color, user_id, is_active)
|
|
VALUES ($1, $2, $3, $4, $5, TRUE)
|
|
RETURNING id, name, type, icon, color, user_id, is_active`,
|
|
[
|
|
category.name,
|
|
category.type,
|
|
category.icon || '📝',
|
|
category.color || '#dfe4ea',
|
|
category.userId || 1,
|
|
],
|
|
);
|
|
const row = rows[0];
|
|
return row
|
|
? {
|
|
...mapCategory(row),
|
|
createdAt: new Date().toISOString(),
|
|
}
|
|
: null;
|
|
} catch (error) {
|
|
console.error('创建分类失败:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function updateCategoryRecord(id: number, category: any) {
|
|
try {
|
|
const updates: string[] = [];
|
|
const params: any[] = [];
|
|
|
|
if (category.name) {
|
|
params.push(category.name);
|
|
updates.push(`name = $${params.length}`);
|
|
}
|
|
if (category.icon) {
|
|
params.push(category.icon);
|
|
updates.push(`icon = $${params.length}`);
|
|
}
|
|
if (category.color) {
|
|
params.push(category.color);
|
|
updates.push(`color = $${params.length}`);
|
|
}
|
|
|
|
if (updates.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
params.push(id);
|
|
const setClause = updates.join(', ');
|
|
const { rows } = await query<CategoryRow>(
|
|
`UPDATE finance_categories
|
|
SET ${setClause}
|
|
WHERE id = $${params.length}
|
|
RETURNING id, name, type, icon, color, user_id, is_active`,
|
|
params,
|
|
);
|
|
const row = rows[0];
|
|
return row ? mapCategory(row) : null;
|
|
} catch (error) {
|
|
console.error('更新分类失败:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function deleteCategoryRecord(id: number) {
|
|
try {
|
|
await query(
|
|
`UPDATE finance_categories
|
|
SET is_active = FALSE
|
|
WHERE id = $1`,
|
|
[id],
|
|
);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('删除分类失败:', error);
|
|
return false;
|
|
}
|
|
}
|