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

@@ -127,6 +127,33 @@ jobs:
echo "⏳ 等待服务启动..."
sleep 10
# 确认PostgreSQL已就绪
echo "⏳ 等待PostgreSQL就绪..."
POSTGRES_READY=0
for i in {1..10}; do
if sudo docker-compose exec -T postgres pg_isready -U kt_financial -d kt_financial > /dev/null 2>&1; then
echo "✅ PostgreSQL 已就绪"
POSTGRES_READY=1
break
fi
echo " 第${i}次重试..."
sleep 3
done
if [ "$POSTGRES_READY" -ne 1 ]; then
echo "❌ PostgreSQL 未在预期时间内就绪"
exit 1
fi
# 导入财务交易数据
echo "📦 导入财务数据..."
sudo docker-compose exec -T kt-financial \
bash -lc "pnpm --filter @vben/backend import:data -- --csv /app/data/finance/finance-combined.csv --year 2025"
# 验证数据条数
echo "🔢 检查交易记录条数..."
sudo docker-compose exec -T postgres \
psql -U kt_financial -d kt_financial -c "SELECT COUNT(*) AS transaction_count FROM finance_transactions;"
# 1. 检查容器状态
echo "📊 容器状态:"
sudo docker-compose ps

View File

@@ -9,6 +9,7 @@
- **功能**: Telegram Bot通知系统
#### 已完成功能:
1. ✅ 基础Telegram通知
2. ✅ 频率控制和去重
3. ✅ 失败重试机制
@@ -16,15 +17,38 @@
5. ✅ 优先级设置
#### 配置信息:
- Bot Token: 已配置
- Chat ID: 1102887169
- Bot用户名: @ktcaiwubot
#### 测试结果:
- ✅ Telegram消息发送成功
- ✅ API接口已实现
- 🚧 前端界面待完成
---
最后更新时间: 2024-11-04 23:30
## 2025-11-06 部署记录
### PostgreSQL 数据持久化与财务数据同步
- **时间**: 2025-11-06 21:30
- **版本**: main@latest
- **内容**: 后端切换 PostgreSQLCI/CD 自动导入 657 条 2025 年账目
#### 核心变更
1. `docker-compose.yml` 新增 `postgres` 服务并启用 `postgres-data` 卷持久化
2. `apps/backend/scripts/import-finance-data.js` 重写为 PostgreSQL 版本,支持新旧两种 CSV 结构
3. Gitea Workflow 部署脚本自动执行 `pnpm --filter @vben/backend import:data -- --csv /app/data/finance/finance-combined.csv --year 2025`
#### 数据校验
- `sudo docker-compose exec -T postgres psql -U kt_financial -d kt_financial -c "SELECT COUNT(*) FROM finance_transactions;"`**657**
- 前端 `/finance/transactions` 页面显示最新日期为 **2025-11-05**,历史数据保持完整
---
最后更新时间: 2025-11-06 21:30

View File

@@ -12,6 +12,7 @@ COPY apps ./apps
COPY packages ./packages
COPY internal ./internal
COPY scripts ./scripts
COPY data ./data
# 安装依赖如果存在lock文件则使用
RUN pnpm install --no-frozen-lockfile
@@ -48,6 +49,7 @@ RUN mkdir -p /app/apps
COPY --from=backend-builder /app/apps/backend /app/apps/backend
RUN ln -s /app/apps/backend /app/backend
COPY --from=backend-builder /app/node_modules /app/node_modules
COPY --from=backend-builder /app/data /app/data
# 创建nginx配置和日志目录
RUN mkdir -p /run/nginx && \

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);
}

View File

@@ -1,24 +1,29 @@
import db from '~/utils/sqlite';
import { query } from '~/utils/db';
import { useResponseSuccess } from '~/utils/response';
export default defineEventHandler(() => {
const configs = db
.prepare<{ id: number; name: string; bot_token: string; chat_id: string; notification_types: string; is_enabled: number; created_at: string; updated_at: string }>(
`
SELECT id, name, bot_token, chat_id, notification_types, is_enabled, created_at, updated_at
FROM telegram_notification_configs
ORDER BY created_at DESC
`,
)
.all();
export default defineEventHandler(async () => {
const { rows } = await query<{
id: number;
name: string;
bot_token: string;
chat_id: string;
notification_types: string;
is_enabled: boolean;
created_at: string;
updated_at: string;
}>(
`SELECT id, name, bot_token, chat_id, notification_types, is_enabled, created_at, updated_at
FROM telegram_notification_configs
ORDER BY created_at DESC`,
);
const result = configs.map((row) => ({
const result = rows.map((row) => ({
id: row.id,
name: row.name,
botToken: row.bot_token,
chatId: row.chat_id,
notificationTypes: JSON.parse(row.notification_types) as string[],
isEnabled: row.is_enabled === 1,
isEnabled: row.is_enabled,
createdAt: row.created_at,
updatedAt: row.updated_at,
}));

View File

@@ -1,5 +1,5 @@
import { readBody } from 'h3';
import db from '~/utils/sqlite';
import { query } from '~/utils/db';
import { useResponseError, useResponseSuccess } from '~/utils/response';
import { testTelegramConfig } from '~/utils/telegram-bot';
@@ -25,31 +25,48 @@ export default defineEventHandler(async (event) => {
const now = new Date().toISOString();
const result = db
.prepare<unknown, [string, string, string, string, number, string, string]>(
`
INSERT INTO telegram_notification_configs (name, bot_token, chat_id, notification_types, is_enabled, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`,
)
.run(
const { rows } = await query<{
id: number;
name: string;
bot_token: string;
chat_id: string;
notification_types: string;
is_enabled: boolean;
created_at: string;
updated_at: string;
}>(
`INSERT INTO telegram_notification_configs (
name,
bot_token,
chat_id,
notification_types,
is_enabled,
created_at,
updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, name, bot_token, chat_id, notification_types, is_enabled, created_at, updated_at`,
[
body.name,
body.botToken,
body.chatId,
JSON.stringify(notificationTypes),
body.isEnabled !== false ? 1 : 0,
body.isEnabled !== false,
now,
now,
);
],
);
const row = rows[0];
return useResponseSuccess({
id: result.lastInsertRowid,
name: body.name,
botToken: body.botToken,
chatId: body.chatId,
id: row.id,
name: row.name,
botToken: row.bot_token,
chatId: row.chat_id,
notificationTypes,
isEnabled: body.isEnabled !== false,
createdAt: now,
updatedAt: now,
isEnabled: row.is_enabled,
createdAt: row.created_at,
updatedAt: row.updated_at,
});
});

View File

@@ -1,17 +1,19 @@
import db from '~/utils/sqlite';
import { query } from '~/utils/db';
import { useResponseError, useResponseSuccess } from '~/utils/response';
export default defineEventHandler((event) => {
const id = event.context.params?.id;
if (!id) {
export default defineEventHandler(async (event) => {
const idParam = event.context.params?.id;
const id = Number(idParam);
if (!idParam || Number.isNaN(id)) {
return useResponseError('缺少ID参数', -1);
}
const result = db
.prepare('DELETE FROM telegram_notification_configs WHERE id = ?')
.run(id);
const result = await query(
'DELETE FROM telegram_notification_configs WHERE id = $1',
[id],
);
if (result.changes === 0) {
if (result.rowCount === 0) {
return useResponseError('配置不存在或删除失败', -1);
}

View File

@@ -1,28 +1,34 @@
import { readBody } from 'h3';
import db from '~/utils/sqlite';
import { query } from '~/utils/db';
import { useResponseError, useResponseSuccess } from '~/utils/response';
import { testTelegramConfig } from '~/utils/telegram-bot';
export default defineEventHandler(async (event) => {
const id = event.context.params?.id;
if (!id) {
const idParam = event.context.params?.id;
const id = Number(idParam);
if (!idParam || Number.isNaN(id)) {
return useResponseError('缺少ID参数', -1);
}
const body = await readBody(event);
// 如果更新了botToken或chatId需要测试配置
if (body.botToken || body.chatId) {
const existing = db
.prepare<{ bot_token: string; chat_id: string }>('SELECT bot_token, chat_id FROM telegram_notification_configs WHERE id = ?')
.get(id);
if (body.botToken !== undefined || body.chatId !== undefined) {
const { rows } = await query<{
bot_token: string;
chat_id: string;
}>(
'SELECT bot_token, chat_id FROM telegram_notification_configs WHERE id = $1',
[id],
);
const existing = rows[0];
if (!existing) {
return useResponseError('配置不存在', -1);
}
const tokenToTest = body.botToken || existing.bot_token;
const chatIdToTest = body.chatId || existing.chat_id;
const tokenToTest = body.botToken ?? existing.bot_token;
const chatIdToTest = body.chatId ?? existing.chat_id;
const testResult = await testTelegramConfig(tokenToTest, chatIdToTest);
if (!testResult.success) {
@@ -34,51 +40,65 @@ export default defineEventHandler(async (event) => {
}
const updates: string[] = [];
const values: (string | number)[] = [];
const values: any[] = [];
if (body.name !== undefined) {
updates.push('name = ?');
values.push(body.name);
updates.push(`name = $${values.length}`);
}
if (body.botToken !== undefined) {
updates.push('bot_token = ?');
values.push(body.botToken);
updates.push(`bot_token = $${values.length}`);
}
if (body.chatId !== undefined) {
updates.push('chat_id = ?');
values.push(body.chatId);
updates.push(`chat_id = $${values.length}`);
}
if (body.notificationTypes !== undefined) {
updates.push('notification_types = ?');
values.push(JSON.stringify(body.notificationTypes));
updates.push(`notification_types = $${values.length}`);
}
if (body.isEnabled !== undefined) {
updates.push('is_enabled = ?');
values.push(body.isEnabled ? 1 : 0);
values.push(body.isEnabled !== false);
updates.push(`is_enabled = $${values.length}`);
}
if (updates.length === 0) {
return useResponseError('没有可更新的字段', -1);
}
updates.push('updated_at = ?');
values.push(new Date().toISOString());
updates.push(`updated_at = $${values.length}`);
values.push(id);
const idPosition = values.length;
db.prepare(`UPDATE telegram_notification_configs SET ${updates.join(', ')} WHERE id = ?`).run(
...values,
const updateResult = await query(
`UPDATE telegram_notification_configs
SET ${updates.join(', ')}
WHERE id = $${idPosition}`,
values,
);
const updated = db
.prepare<{ id: number; name: string; bot_token: string; chat_id: string; notification_types: string; is_enabled: number; created_at: string; updated_at: string }>(
'SELECT * FROM telegram_notification_configs WHERE id = ?',
)
.get(id);
if (updateResult.rowCount === 0) {
return useResponseError('配置不存在', -1);
}
const { rows: updatedRows } = await query<{
id: number;
name: string;
bot_token: string;
chat_id: string;
notification_types: string;
is_enabled: boolean;
created_at: string;
updated_at: string;
}>('SELECT * FROM telegram_notification_configs WHERE id = $1', [id]);
const updated = updatedRows[0];
if (!updated) {
return useResponseError('更新失败', -1);
}
@@ -89,7 +109,7 @@ export default defineEventHandler(async (event) => {
botToken: updated.bot_token,
chatId: updated.chat_id,
notificationTypes: JSON.parse(updated.notification_types) as string[],
isEnabled: updated.is_enabled === 1,
isEnabled: updated.is_enabled,
createdAt: updated.created_at,
updatedAt: updated.updated_at,
});

View File

@@ -12,9 +12,9 @@
},
"dependencies": {
"@faker-js/faker": "catalog:",
"better-sqlite3": "9.5.0",
"jsonwebtoken": "catalog:",
"nitropack": "catalog:"
"nitropack": "catalog:",
"pg": "^8.12.0"
},
"devDependencies": {
"@types/jsonwebtoken": "catalog:",

File diff suppressed because it is too large Load Diff

314
apps/backend/utils/db.ts Normal file
View File

@@ -0,0 +1,314 @@
import process from 'node:process';
import type { PoolClient } from 'pg';
import { Pool } from 'pg';
import {
MOCK_ACCOUNTS,
MOCK_CATEGORIES,
MOCK_CURRENCIES,
MOCK_EXCHANGE_RATES,
} from './mock-data';
const DEFAULT_HOST = process.env.POSTGRES_HOST ?? 'postgres';
const DEFAULT_PORT = Number.parseInt(process.env.POSTGRES_PORT ?? '5432', 10);
const DEFAULT_DB = process.env.POSTGRES_DB ?? 'kt_financial';
const DEFAULT_USER = process.env.POSTGRES_USER ?? 'kt_financial';
const DEFAULT_PASSWORD = process.env.POSTGRES_PASSWORD ?? 'kt_financial_pwd';
const connectionString =
process.env.POSTGRES_URL ??
`postgresql://${DEFAULT_USER}:${DEFAULT_PASSWORD}@${DEFAULT_HOST}:${DEFAULT_PORT}/${DEFAULT_DB}`;
const pool = new Pool({
connectionString,
max: 10,
});
let initPromise: null | Promise<void> = null;
async function seedCurrencies(client: PoolClient) {
await Promise.all(
MOCK_CURRENCIES.map((currency) =>
client.query(
`INSERT INTO finance_currencies (code, name, symbol, is_base, is_active)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (code) DO NOTHING`,
[
currency.code,
currency.name,
currency.symbol,
currency.isBase,
currency.isActive,
],
),
),
);
}
async function seedExchangeRates(client: PoolClient) {
await Promise.all(
MOCK_EXCHANGE_RATES.map((rate) =>
client.query(
`INSERT INTO finance_exchange_rates (from_currency, to_currency, rate, date, source)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT DO NOTHING`,
[
rate.fromCurrency,
rate.toCurrency,
rate.rate,
rate.date,
rate.source ?? 'manual',
],
),
),
);
}
async function seedAccounts(client: PoolClient) {
await Promise.all(
MOCK_ACCOUNTS.map((account) =>
client.query(
`INSERT INTO finance_accounts (id, name, currency, type, icon, color, user_id, is_active)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT (id) DO NOTHING`,
[
account.id,
account.name,
account.currency,
account.type,
account.icon,
account.color,
account.userId ?? 1,
account.isActive,
],
),
),
);
}
async function seedCategories(client: PoolClient) {
await Promise.all(
MOCK_CATEGORIES.map((category) =>
client.query(
`INSERT INTO finance_categories (id, name, type, icon, color, user_id, is_active)
VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (id) DO NOTHING`,
[
category.id,
category.name,
category.type,
category.icon,
category.color,
category.userId,
category.isActive,
],
),
),
);
}
async function initializeSchema() {
const client = await pool.connect();
try {
await client.query('BEGIN');
await client.query(`
CREATE TABLE IF NOT EXISTS finance_currencies (
code TEXT PRIMARY KEY,
name TEXT NOT NULL,
symbol TEXT NOT NULL,
is_base BOOLEAN NOT NULL DEFAULT FALSE,
is_active BOOLEAN NOT NULL DEFAULT TRUE
);
`);
await client.query(`
CREATE TABLE IF NOT EXISTS finance_exchange_rates (
id SERIAL PRIMARY KEY,
from_currency TEXT NOT NULL REFERENCES finance_currencies(code),
to_currency TEXT NOT NULL REFERENCES finance_currencies(code),
rate NUMERIC NOT NULL,
date DATE NOT NULL,
source TEXT DEFAULT 'manual'
);
`);
await client.query(`
CREATE TABLE IF NOT EXISTS finance_accounts (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
currency TEXT NOT NULL REFERENCES finance_currencies(code),
type TEXT DEFAULT 'cash',
icon TEXT,
color TEXT,
user_id INTEGER DEFAULT 1,
is_active BOOLEAN DEFAULT TRUE
);
`);
await client.query(`
CREATE TABLE IF NOT EXISTS finance_categories (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
type TEXT NOT NULL,
icon TEXT,
color TEXT,
user_id INTEGER,
is_active BOOLEAN DEFAULT TRUE
);
`);
await client.query(`
CREATE TABLE IF NOT EXISTS finance_transactions (
id SERIAL PRIMARY KEY,
type TEXT NOT NULL,
amount NUMERIC NOT NULL,
currency TEXT NOT NULL REFERENCES finance_currencies(code),
exchange_rate_to_base NUMERIC NOT NULL,
amount_in_base NUMERIC NOT NULL,
category_id INTEGER REFERENCES finance_categories(id),
account_id INTEGER REFERENCES finance_accounts(id),
transaction_date DATE NOT NULL,
description TEXT,
project TEXT,
memo TEXT,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
status TEXT NOT NULL DEFAULT 'approved',
status_updated_at TIMESTAMP WITH TIME ZONE,
reimbursement_batch TEXT,
review_notes TEXT,
submitted_by TEXT,
approved_by TEXT,
approved_at TIMESTAMP WITH TIME ZONE,
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
deleted_at TIMESTAMP WITH TIME ZONE
);
`);
await client.query(`
CREATE TABLE IF NOT EXISTS finance_media_messages (
id SERIAL PRIMARY KEY,
chat_id BIGINT NOT NULL,
message_id BIGINT NOT NULL,
user_id INTEGER NOT NULL,
username TEXT,
display_name TEXT,
file_type TEXT NOT NULL,
file_id TEXT NOT NULL,
file_unique_id TEXT,
caption TEXT,
file_name TEXT,
file_path TEXT NOT NULL,
file_size INTEGER,
mime_type TEXT,
duration INTEGER,
width INTEGER,
height INTEGER,
forwarded_to INTEGER,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
UNIQUE(chat_id, message_id)
);
`);
await client.query(`
CREATE TABLE IF NOT EXISTS telegram_notification_configs (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
bot_token TEXT NOT NULL,
chat_id TEXT NOT NULL,
notification_types TEXT NOT NULL,
is_enabled BOOLEAN NOT NULL DEFAULT TRUE,
priority TEXT DEFAULT 'normal',
rate_limit_seconds INTEGER DEFAULT 0,
batch_enabled BOOLEAN DEFAULT FALSE,
batch_interval_minutes INTEGER DEFAULT 60,
retry_enabled BOOLEAN DEFAULT TRUE,
retry_max_attempts INTEGER DEFAULT 3,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
`);
await client.query(`
CREATE TABLE IF NOT EXISTS telegram_notification_history (
id SERIAL PRIMARY KEY,
config_id INTEGER NOT NULL REFERENCES telegram_notification_configs(id),
notification_type TEXT NOT NULL,
content_hash TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
retry_count INTEGER DEFAULT 0,
sent_at TIMESTAMP WITH TIME ZONE,
error_message TEXT,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
`);
await client.query(`
CREATE INDEX IF NOT EXISTS idx_finance_media_messages_created_at
ON finance_media_messages (created_at DESC);
`);
await client.query(`
CREATE INDEX IF NOT EXISTS idx_finance_media_messages_user_id
ON finance_media_messages (user_id);
`);
await client.query(`
CREATE INDEX IF NOT EXISTS idx_telegram_notification_configs_enabled
ON telegram_notification_configs (is_enabled);
`);
await client.query(`
CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_config
ON telegram_notification_history (config_id, created_at DESC);
`);
await client.query(`
CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_hash
ON telegram_notification_history (content_hash, created_at DESC);
`);
await client.query(`
CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_status
ON telegram_notification_history (status, retry_count);
`);
await seedCurrencies(client);
await seedExchangeRates(client);
await seedAccounts(client);
await seedCategories(client);
await client.query('COMMIT');
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}
}
export async function getPool() {
if (!initPromise) {
initPromise = initializeSchema();
}
await initPromise;
return pool;
}
export async function query<T = any>(text: string, params?: any[]) {
const client = await getPool();
const result = await client.query<T>(text, params);
return result;
}
export async function withTransaction<T>(
handler: (client: PoolClient) => Promise<T>,
) {
const client = await pool.connect();
try {
await client.query('BEGIN');
const result = await handler(client);
await client.query('COMMIT');
return result;
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}
}

View File

@@ -1,3 +1,4 @@
import { query } from './db';
import {
MOCK_ACCOUNTS,
MOCK_BUDGETS,
@@ -5,37 +6,87 @@ import {
MOCK_CURRENCIES,
MOCK_EXCHANGE_RATES,
} from './mock-data';
import db from './sqlite';
export function listAccounts() {
return MOCK_ACCOUNTS;
interface AccountRow {
id: number;
name: string;
type: string;
currency: string;
icon: null | string;
color: null | string;
user_id: null | number;
is_active: boolean;
}
export function listCategories() {
// 从数据库读取分类
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 stmt = db.prepare(`
SELECT id, name, type, icon, color, user_id as userId, is_active as isActive
FROM finance_categories
WHERE is_active = 1
ORDER BY type, id
`);
const categories = stmt.all() as any[];
// 转换为前端需要的格式
return categories.map(cat => ({
id: cat.id,
userId: cat.userId,
name: cat.name,
type: cat.type,
icon: cat.icon,
color: cat.color,
sortOrder: cat.id,
isSystem: true,
isActive: Boolean(cat.isActive),
}));
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);
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;
}
}
@@ -52,76 +103,80 @@ export function listExchangeRates() {
return MOCK_EXCHANGE_RATES;
}
export function createCategoryRecord(category: any) {
export async function createCategoryRecord(category: any) {
try {
const stmt = db.prepare(`
INSERT INTO finance_categories (name, type, icon, color, user_id, is_active)
VALUES (?, ?, ?, ?, ?, 1)
`);
const result = stmt.run(
category.name,
category.type,
category.icon || '📝',
category.color || '#dfe4ea',
category.userId || 1
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,
],
);
return {
id: result.lastInsertRowid,
...category,
createdAt: new Date().toISOString(),
};
const row = rows[0];
return row
? {
...mapCategory(row),
createdAt: new Date().toISOString(),
}
: null;
} catch (error) {
console.error('创建分类失败:', error);
return null;
}
}
export function updateCategoryRecord(id: number, category: any) {
export async function updateCategoryRecord(id: number, category: any) {
try {
const updates: string[] = [];
const params: any[] = [];
if (category.name) {
updates.push('name = ?');
params.push(category.name);
updates.push(`name = $${params.length}`);
}
if (category.icon) {
updates.push('icon = ?');
params.push(category.icon);
updates.push(`icon = $${params.length}`);
}
if (category.color) {
updates.push('color = ?');
params.push(category.color);
updates.push(`color = $${params.length}`);
}
if (updates.length === 0) return null;
if (updates.length === 0) {
return null;
}
params.push(id);
const stmt = db.prepare(`
UPDATE finance_categories
SET ${updates.join(', ')}
WHERE id = ?
`);
stmt.run(...params);
// 返回更新后的分类
const selectStmt = db.prepare('SELECT * FROM finance_categories WHERE id = ?');
return selectStmt.get(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 function deleteCategoryRecord(id: number) {
export async function deleteCategoryRecord(id: number) {
try {
// 软删除
const stmt = db.prepare(`
UPDATE finance_categories
SET is_active = 0
WHERE id = ?
`);
stmt.run(id);
await query(
`UPDATE finance_categories
SET is_active = FALSE
WHERE id = $1`,
[id],
);
return true;
} catch (error) {
console.error('删除分类失败:', error);

View File

@@ -1,14 +1,16 @@
import db from './sqlite';
import type { PoolClient } from 'pg';
import { query, withTransaction } from './db';
const BASE_CURRENCY = 'CNY';
interface TransactionRow {
id: number;
type: string;
amount: number;
amount: number | string;
currency: string;
exchange_rate_to_base: number;
amount_in_base: number;
exchange_rate_to_base: number | string;
amount_in_base: number | string;
category_id: null | number;
account_id: null | number;
transaction_date: string;
@@ -23,7 +25,7 @@ interface TransactionRow {
submitted_by: null | string;
approved_by: null | string;
approved_at: null | string;
is_deleted: number;
is_deleted: boolean;
deleted_at: null | string;
}
@@ -49,32 +51,24 @@ interface TransactionPayload {
}
export type TransactionStatus =
| 'draft'
| 'pending'
| 'approved'
| 'rejected'
| 'paid';
function getExchangeRateToBase(currency: string) {
if (currency === BASE_CURRENCY) {
return 1;
}
const stmt = db.prepare(
`SELECT rate FROM finance_exchange_rates WHERE from_currency = ? AND to_currency = ? ORDER BY date DESC LIMIT 1`,
);
const row = stmt.get(currency, BASE_CURRENCY) as undefined | { rate: number };
return row?.rate ?? 1;
}
| 'draft'
| 'paid'
| 'pending'
| 'rejected';
function mapTransaction(row: TransactionRow) {
const amount = Number(row.amount);
const exchangeRateToBase = Number(row.exchange_rate_to_base);
const amountInBase = Number(row.amount_in_base);
return {
id: row.id,
userId: 1,
type: 'expense' as const,
amount: Math.abs(row.amount),
type: row.type as 'expense' | 'income' | 'transfer',
amount: Math.abs(amount),
currency: row.currency,
exchangeRateToBase: row.exchange_rate_to_base,
amountInBase: Math.abs(row.amount_in_base),
exchangeRateToBase,
amountInBase: Math.abs(amountInBase),
categoryId: row.category_id ?? undefined,
accountId: row.account_id ?? undefined,
transactionDate: row.transaction_date,
@@ -94,231 +88,350 @@ function mapTransaction(row: TransactionRow) {
};
}
export function fetchTransactions(
async function getExchangeRateToBase(client: PoolClient, currency: string) {
if (currency === BASE_CURRENCY) {
return 1;
}
const result = await client.query<{ rate: number | string }>(
`SELECT rate
FROM finance_exchange_rates
WHERE from_currency = $1 AND to_currency = $2
ORDER BY date DESC
LIMIT 1`,
[currency, BASE_CURRENCY],
);
const raw = result.rows[0]?.rate;
return raw ? Number(raw) : 1;
}
export async function fetchTransactions(
options: {
includeDeleted?: boolean;
type?: string;
statuses?: TransactionStatus[];
type?: string;
} = {},
) {
const clauses: string[] = [];
const params: Record<string, unknown> = {};
const params: any[] = [];
if (!options.includeDeleted) {
clauses.push('is_deleted = 0');
clauses.push('is_deleted = FALSE');
}
if (options.type) {
clauses.push('type = @type');
params.type = options.type;
params.push(options.type);
clauses.push(`type = $${params.length}`);
}
if (options.statuses && options.statuses.length > 0) {
clauses.push(
`status IN (${options.statuses.map((_, index) => `@status${index}`).join(', ')})`,
);
options.statuses.forEach((status, index) => {
params[`status${index}`] = status;
const statusPlaceholders = options.statuses.map((status) => {
params.push(status);
return `$${params.length}`;
});
clauses.push(`status IN (${statusPlaceholders.join(', ')})`);
}
const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : '';
const stmt = db.prepare<TransactionRow>(
`SELECT id, type, amount, currency, exchange_rate_to_base, amount_in_base, category_id, account_id, transaction_date, description, project, memo, created_at, status, status_updated_at, reimbursement_batch, review_notes, submitted_by, approved_by, approved_at, is_deleted, deleted_at FROM finance_transactions ${where} ORDER BY transaction_date DESC, id DESC`,
const { rows } = await query<TransactionRow>(
`SELECT id,
type,
amount,
currency,
exchange_rate_to_base,
amount_in_base,
category_id,
account_id,
transaction_date,
description,
project,
memo,
created_at,
status,
status_updated_at,
reimbursement_batch,
review_notes,
submitted_by,
approved_by,
approved_at,
is_deleted,
deleted_at
FROM finance_transactions
${where}
ORDER BY transaction_date DESC, id DESC`,
params,
);
return stmt.all(params).map(mapTransaction);
return rows.map((row) => mapTransaction(row));
}
export function getTransactionById(id: number) {
const stmt = db.prepare<TransactionRow>(
`SELECT id, type, amount, currency, exchange_rate_to_base, amount_in_base, category_id, account_id, transaction_date, description, project, memo, created_at, status, status_updated_at, reimbursement_batch, review_notes, submitted_by, approved_by, approved_at, is_deleted, deleted_at FROM finance_transactions WHERE id = ?`,
export async function getTransactionById(id: number) {
const { rows } = await query<TransactionRow>(
`SELECT id,
type,
amount,
currency,
exchange_rate_to_base,
amount_in_base,
category_id,
account_id,
transaction_date,
description,
project,
memo,
created_at,
status,
status_updated_at,
reimbursement_batch,
review_notes,
submitted_by,
approved_by,
approved_at,
is_deleted,
deleted_at
FROM finance_transactions
WHERE id = $1`,
[id],
);
const row = stmt.get(id);
const row = rows[0];
return row ? mapTransaction(row) : null;
}
export function createTransaction(payload: TransactionPayload) {
const exchangeRate = getExchangeRateToBase(payload.currency);
const amountInBase = +(payload.amount * exchangeRate).toFixed(2);
const createdAt =
payload.createdAt && payload.createdAt.length > 0
? payload.createdAt
: new Date().toISOString();
const status: TransactionStatus = payload.status ?? 'approved';
const statusUpdatedAt =
payload.statusUpdatedAt && payload.statusUpdatedAt.length > 0
? payload.statusUpdatedAt
: createdAt;
const approvedAt =
payload.approvedAt && payload.approvedAt.length > 0
? payload.approvedAt
: status === 'approved' || status === 'paid'
? statusUpdatedAt
: null;
export async function createTransaction(payload: TransactionPayload) {
return withTransaction(async (client) => {
const exchangeRate = await getExchangeRateToBase(client, payload.currency);
const amountInBase = +(payload.amount * exchangeRate).toFixed(2);
const createdAt =
payload.createdAt && payload.createdAt.length > 0
? payload.createdAt
: new Date().toISOString();
const status: TransactionStatus = payload.status ?? 'approved';
const statusUpdatedAt =
payload.statusUpdatedAt && payload.statusUpdatedAt.length > 0
? payload.statusUpdatedAt
: createdAt;
let approvedAt: string | null = null;
if (payload.approvedAt && payload.approvedAt.length > 0) {
approvedAt = payload.approvedAt;
} else if (status === 'approved' || status === 'paid') {
approvedAt = statusUpdatedAt;
}
const stmt = db.prepare(
`INSERT INTO finance_transactions (type, amount, currency, exchange_rate_to_base, amount_in_base, category_id, account_id, transaction_date, description, project, memo, created_at, status, status_updated_at, reimbursement_batch, review_notes, submitted_by, approved_by, approved_at, is_deleted) VALUES (@type, @amount, @currency, @exchangeRateToBase, @amountInBase, @categoryId, @accountId, @transactionDate, @description, @project, @memo, @createdAt, @status, @statusUpdatedAt, @reimbursementBatch, @reviewNotes, @submittedBy, @approvedBy, @approvedAt, 0)`,
);
const info = stmt.run({
type: payload.type,
amount: payload.amount,
currency: payload.currency,
exchangeRateToBase: exchangeRate,
amountInBase,
categoryId: payload.categoryId ?? null,
accountId: payload.accountId ?? null,
transactionDate: payload.transactionDate,
description: payload.description ?? '',
project: payload.project ?? null,
memo: payload.memo ?? null,
createdAt,
status,
statusUpdatedAt,
reimbursementBatch: payload.reimbursementBatch ?? null,
reviewNotes: payload.reviewNotes ?? null,
submittedBy: payload.submittedBy ?? null,
approvedBy: payload.approvedBy ?? null,
approvedAt,
const { rows } = await client.query<TransactionRow>(
`INSERT INTO finance_transactions (
type,
amount,
currency,
exchange_rate_to_base,
amount_in_base,
category_id,
account_id,
transaction_date,
description,
project,
memo,
created_at,
status,
status_updated_at,
reimbursement_batch,
review_notes,
submitted_by,
approved_by,
approved_at,
is_deleted
)
VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11,
$12, $13, $14, $15, $16, $17, $18, $19, FALSE
)
RETURNING *`,
[
payload.type,
payload.amount,
payload.currency,
exchangeRate,
amountInBase,
payload.categoryId ?? null,
payload.accountId ?? null,
payload.transactionDate,
payload.description ?? '',
payload.project ?? null,
payload.memo ?? null,
createdAt,
status,
statusUpdatedAt,
payload.reimbursementBatch ?? null,
payload.reviewNotes ?? null,
payload.submittedBy ?? null,
payload.approvedBy ?? null,
approvedAt,
],
);
return mapTransaction(rows[0]);
});
return getTransactionById(Number(info.lastInsertRowid));
}
export function updateTransaction(id: number, payload: TransactionPayload) {
const current = getTransactionById(id);
export async function updateTransaction(
id: number,
payload: TransactionPayload,
) {
const current = await getTransactionById(id);
if (!current) {
return null;
}
const nextStatus = (payload.status ?? current.status ?? 'approved') as TransactionStatus;
const statusChanged = nextStatus !== current.status;
const statusUpdatedAt =
payload.statusUpdatedAt && payload.statusUpdatedAt.length > 0
? payload.statusUpdatedAt
: statusChanged
? new Date().toISOString()
: current.statusUpdatedAt ?? current.createdAt;
const approvedAt =
payload.approvedAt && payload.approvedAt.length > 0
? payload.approvedAt
: nextStatus === 'approved' || nextStatus === 'paid'
? current.approvedAt ?? (statusChanged ? statusUpdatedAt : null)
: null;
const approvedBy =
nextStatus === 'approved' || nextStatus === 'paid'
? payload.approvedBy ?? current.approvedBy ?? null
: payload.approvedBy ?? null;
return withTransaction(async (client) => {
const nextStatus = (payload.status ??
current.status ??
'approved') as TransactionStatus;
const statusChanged = nextStatus !== current.status;
let statusUpdatedAt: string;
if (payload.statusUpdatedAt && payload.statusUpdatedAt.length > 0) {
statusUpdatedAt = payload.statusUpdatedAt;
} else if (statusChanged) {
statusUpdatedAt = new Date().toISOString();
} else {
statusUpdatedAt = current.statusUpdatedAt ?? current.createdAt;
}
let approvedAt: string | null = null;
if (payload.approvedAt && payload.approvedAt.length > 0) {
approvedAt = payload.approvedAt;
} else if (nextStatus === 'approved' || nextStatus === 'paid') {
approvedAt = current.approvedAt ?? (statusChanged ? statusUpdatedAt : null);
}
const approvedBy =
nextStatus === 'approved' || nextStatus === 'paid'
? payload.approvedBy ?? current.approvedBy ?? null
: payload.approvedBy ?? null;
const next = {
type: payload.type ?? current.type,
amount: payload.amount ?? current.amount,
currency: payload.currency ?? current.currency,
categoryId: payload.categoryId ?? current.categoryId ?? null,
accountId: payload.accountId ?? current.accountId ?? null,
transactionDate: payload.transactionDate ?? current.transactionDate,
description: payload.description ?? current.description ?? '',
project: payload.project ?? current.project ?? null,
memo: payload.memo ?? current.memo ?? null,
isDeleted: payload.isDeleted ?? current.isDeleted,
status: nextStatus,
statusUpdatedAt,
reimbursementBatch:
payload.reimbursementBatch ?? current.reimbursementBatch ?? null,
reviewNotes: payload.reviewNotes ?? current.reviewNotes ?? null,
submittedBy: payload.submittedBy ?? current.submittedBy ?? null,
approvedBy,
approvedAt,
};
const next = {
type: payload.type ?? current.type,
amount: payload.amount ?? current.amount,
currency: payload.currency ?? current.currency,
categoryId: payload.categoryId ?? current.categoryId ?? null,
accountId: payload.accountId ?? current.accountId ?? null,
transactionDate: payload.transactionDate ?? current.transactionDate,
description: payload.description ?? current.description ?? '',
project: payload.project ?? current.project ?? null,
memo: payload.memo ?? current.memo ?? null,
isDeleted: payload.isDeleted ?? current.isDeleted,
status: nextStatus,
statusUpdatedAt,
reimbursementBatch:
payload.reimbursementBatch ?? current.reimbursementBatch ?? null,
reviewNotes: payload.reviewNotes ?? current.reviewNotes ?? null,
submittedBy: payload.submittedBy ?? current.submittedBy ?? null,
approvedBy,
approvedAt,
};
const exchangeRate = getExchangeRateToBase(next.currency);
const amountInBase = +(next.amount * exchangeRate).toFixed(2);
const exchangeRate = await getExchangeRateToBase(client, next.currency);
const amountInBase = +(next.amount * exchangeRate).toFixed(2);
const deletedAt = next.isDeleted ? new Date().toISOString() : null;
const stmt = db.prepare(
`UPDATE finance_transactions SET type = @type, amount = @amount, currency = @currency, exchange_rate_to_base = @exchangeRateToBase, amount_in_base = @amountInBase, category_id = @categoryId, account_id = @accountId, transaction_date = @transactionDate, description = @description, project = @project, memo = @memo, status = @status, status_updated_at = @statusUpdatedAt, reimbursement_batch = @reimbursementBatch, review_notes = @reviewNotes, submitted_by = @submittedBy, approved_by = @approvedBy, approved_at = @approvedAt, is_deleted = @isDeleted, deleted_at = @deletedAt WHERE id = @id`,
);
const { rows } = await client.query<TransactionRow>(
`UPDATE finance_transactions
SET type = $1,
amount = $2,
currency = $3,
exchange_rate_to_base = $4,
amount_in_base = $5,
category_id = $6,
account_id = $7,
transaction_date = $8,
description = $9,
project = $10,
memo = $11,
status = $12,
status_updated_at = $13,
reimbursement_batch = $14,
review_notes = $15,
submitted_by = $16,
approved_by = $17,
approved_at = $18,
is_deleted = $19,
deleted_at = $20
WHERE id = $21
RETURNING *`,
[
next.type,
next.amount,
next.currency,
exchangeRate,
amountInBase,
next.categoryId,
next.accountId,
next.transactionDate,
next.description,
next.project,
next.memo,
next.status,
next.statusUpdatedAt,
next.reimbursementBatch,
next.reviewNotes,
next.submittedBy,
next.approvedBy,
next.approvedAt,
next.isDeleted,
deletedAt,
id,
],
);
const deletedAt = next.isDeleted ? new Date().toISOString() : null;
stmt.run({
id,
type: next.type,
amount: next.amount,
currency: next.currency,
exchangeRateToBase: exchangeRate,
amountInBase,
categoryId: next.categoryId,
accountId: next.accountId,
transactionDate: next.transactionDate,
description: next.description,
project: next.project,
memo: next.memo,
status: next.status,
statusUpdatedAt: next.statusUpdatedAt,
reimbursementBatch: next.reimbursementBatch,
reviewNotes: next.reviewNotes,
submittedBy: next.submittedBy,
approvedBy: next.approvedBy,
approvedAt: next.approvedAt,
isDeleted: next.isDeleted ? 1 : 0,
deletedAt,
return mapTransaction(rows[0]);
});
return getTransactionById(id);
}
export function softDeleteTransaction(id: number) {
const stmt = db.prepare(
`UPDATE finance_transactions SET is_deleted = 1, deleted_at = @deletedAt WHERE id = @id`,
export async function softDeleteTransaction(id: number) {
const deletedAt = new Date().toISOString();
const { rows } = await query<TransactionRow>(
`UPDATE finance_transactions
SET is_deleted = TRUE, deleted_at = $1
WHERE id = $2
RETURNING *`,
[deletedAt, id],
);
stmt.run({ id, deletedAt: new Date().toISOString() });
return getTransactionById(id);
const row = rows[0];
return row ? mapTransaction(row) : null;
}
export function restoreTransaction(id: number) {
const stmt = db.prepare(
`UPDATE finance_transactions SET is_deleted = 0, deleted_at = NULL WHERE id = @id`,
export async function restoreTransaction(id: number) {
const { rows } = await query<TransactionRow>(
`UPDATE finance_transactions
SET is_deleted = FALSE, deleted_at = NULL
WHERE id = $1
RETURNING *`,
[id],
);
stmt.run({ id });
return getTransactionById(id);
const row = rows[0];
return row ? mapTransaction(row) : null;
}
export function replaceAllTransactions(
export async function replaceAllTransactions(
rows: Array<{
accountId: null | number;
amount: number;
approvedAt?: null | string;
approvedBy?: null | string;
categoryId: null | number;
createdAt?: string;
currency: string;
description: string;
isDeleted?: boolean;
memo?: null | string;
project?: null | string;
transactionDate: string;
type: string;
status?: TransactionStatus;
statusUpdatedAt?: string;
reimbursementBatch?: null | string;
reviewNotes?: null | string;
status?: TransactionStatus;
statusUpdatedAt?: string;
submittedBy?: null | string;
approvedBy?: null | string;
approvedAt?: null | string;
isDeleted?: boolean;
transactionDate: string;
type: string;
}>,
) {
db.prepare('DELETE FROM finance_transactions').run();
await withTransaction(async (client) => {
await client.query(
'TRUNCATE TABLE finance_transactions RESTART IDENTITY CASCADE',
);
const insert = db.prepare(
`INSERT INTO finance_transactions (type, amount, currency, exchange_rate_to_base, amount_in_base, category_id, account_id, transaction_date, description, project, memo, created_at, status, status_updated_at, reimbursement_batch, review_notes, submitted_by, approved_by, approved_at, is_deleted) VALUES (@type, @amount, @currency, @exchangeRateToBase, @amountInBase, @categoryId, @accountId, @transactionDate, @description, @project, @memo, @createdAt, @status, @statusUpdatedAt, @reimbursementBatch, @reviewNotes, @submittedBy, @approvedBy, @approvedAt, @isDeleted)`,
);
const getRate = db.prepare(
`SELECT rate FROM finance_exchange_rates WHERE from_currency = ? AND to_currency = 'CNY' ORDER BY date DESC LIMIT 1`,
);
const insertMany = db.transaction((items: Array<any>) => {
for (const item of items) {
const row = getRate.get(item.currency) as undefined | { rate: number };
const rate = row?.rate ?? 1;
for (const item of rows) {
const rate = await getExchangeRateToBase(client, item.currency);
const amountInBase = +(item.amount * rate).toFixed(2);
const createdAt =
item.createdAt ??
@@ -326,38 +439,67 @@ export function replaceAllTransactions(
const status = item.status ?? 'approved';
const statusUpdatedAt =
item.statusUpdatedAt ??
new Date(
`${item.transactionDate}T00:00:00Z`,
).toISOString();
new Date(`${item.transactionDate}T00:00:00Z`).toISOString();
const approvedAt =
item.approvedAt ??
(status === 'approved' || status === 'paid' ? statusUpdatedAt : null);
insert.run({
...item,
exchangeRateToBase: rate,
amountInBase,
project: item.project ?? null,
memo: item.memo ?? null,
createdAt,
status,
statusUpdatedAt,
reimbursementBatch: item.reimbursementBatch ?? null,
reviewNotes: item.reviewNotes ?? null,
submittedBy: item.submittedBy ?? null,
approvedBy:
await client.query(
`INSERT INTO finance_transactions (
type,
amount,
currency,
exchange_rate_to_base,
amount_in_base,
category_id,
account_id,
transaction_date,
description,
project,
memo,
created_at,
status,
status_updated_at,
reimbursement_batch,
review_notes,
submitted_by,
approved_by,
approved_at,
is_deleted
)
VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10,
$11, $12, $13, $14, $15, $16, $17, $18, $19, $20
)`,
[
item.type,
item.amount,
item.currency,
rate,
amountInBase,
item.categoryId ?? null,
item.accountId ?? null,
item.transactionDate,
item.description ?? '',
item.project ?? null,
item.memo ?? null,
createdAt,
status,
statusUpdatedAt,
item.reimbursementBatch ?? null,
item.reviewNotes ?? null,
item.submittedBy ?? null,
status === 'approved' || status === 'paid'
? item.approvedBy ?? null
? (item.approvedBy ?? null)
: null,
approvedAt,
isDeleted: item.isDeleted ? 1 : 0,
});
approvedAt,
item.isDeleted ?? false,
],
);
}
});
insertMany(rows);
}
// 分类相关函数
interface CategoryRow {
id: number;
name: string;
@@ -365,7 +507,7 @@ interface CategoryRow {
icon: null | string;
color: null | string;
user_id: null | number;
is_active: number;
is_active: boolean;
}
function mapCategory(row: CategoryRow) {
@@ -382,15 +524,53 @@ function mapCategory(row: CategoryRow) {
};
}
export function fetchCategories(options: { type?: 'expense' | 'income' } = {}) {
const where = options.type
? `WHERE type = @type AND is_active = 1`
: 'WHERE is_active = 1';
const params = options.type ? { type: options.type } : {};
const stmt = db.prepare<CategoryRow>(
`SELECT id, name, type, icon, color, user_id, is_active FROM finance_categories ${where} ORDER BY id ASC`,
export async function fetchCategories(
options: { type?: 'expense' | 'income' } = {},
) {
const params: any[] = [];
const clauses: string[] = ['is_active = TRUE'];
if (options.type) {
params.push(options.type);
clauses.push(`type = $${params.length}`);
}
const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : '';
const { rows } = await query<CategoryRow>(
`SELECT id,
name,
type,
icon,
color,
user_id,
is_active
FROM finance_categories
${where}
ORDER BY id ASC`,
params,
);
return stmt.all(params).map(mapCategory);
return rows.map((row) => mapCategory(row));
}
export async function getAccountById(id: number) {
const { rows } = await query<{
currency: string;
id: number;
name: string;
}>(
`SELECT id, name, currency
FROM finance_accounts
WHERE id = $1`,
[id],
);
return rows[0] ?? null;
}
export async function getCategoryById(id: number) {
const { rows } = await query<CategoryRow>(
`SELECT id, name, type, icon, color, user_id, is_active
FROM finance_categories
WHERE id = $1`,
[id],
);
const row = rows[0];
return row ? mapCategory(row) : null;
}

View File

@@ -1,6 +1,6 @@
import { existsSync } from 'node:fs';
import db from './sqlite';
import { query } from './db';
interface MediaRow {
id: number;
@@ -47,7 +47,7 @@ export interface MediaMessage {
createdAt: string;
updatedAt: string;
available: boolean;
downloadUrl: string | null;
downloadUrl: null | string;
}
function mapMediaRow(row: MediaRow): MediaMessage {
@@ -78,40 +78,85 @@ function mapMediaRow(row: MediaRow): MediaMessage {
};
}
export function fetchMediaMessages(params: {
limit?: number;
fileTypes?: string[];
} = {}) {
const clauses: string[] = [];
const bindParams: Record<string, unknown> = {};
export async function fetchMediaMessages(
params: {
fileTypes?: string[];
limit?: number;
} = {},
) {
const whereClauses: string[] = [];
const queryParams: any[] = [];
if (params.fileTypes && params.fileTypes.length > 0) {
clauses.push(
`file_type IN (${params.fileTypes.map((_, index) => `@type${index}`).join(', ')})`,
);
params.fileTypes.forEach((type, index) => {
bindParams[`type${index}`] = type;
const placeholders = params.fileTypes.map((type) => {
queryParams.push(type);
return `$${queryParams.length}`;
});
whereClauses.push(`file_type IN (${placeholders.join(', ')})`);
}
const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : '';
const where =
whereClauses.length > 0 ? `WHERE ${whereClauses.join(' AND ')}` : '';
const limitClause =
params.limit && params.limit > 0 ? `LIMIT ${Number(params.limit)}` : '';
const stmt = db.prepare<MediaRow>(
`SELECT id, chat_id, message_id, user_id, username, display_name, file_type, file_id, file_unique_id, caption, file_name, file_path, file_size, mime_type, duration, width, height, forwarded_to, created_at, updated_at FROM finance_media_messages ${where} ORDER BY datetime(created_at) DESC, id DESC ${limitClause}`,
const { rows } = await query<MediaRow>(
`SELECT id,
chat_id,
message_id,
user_id,
username,
display_name,
file_type,
file_id,
file_unique_id,
caption,
file_name,
file_path,
file_size,
mime_type,
duration,
width,
height,
forwarded_to,
created_at,
updated_at
FROM finance_media_messages
${where}
ORDER BY created_at DESC, id DESC
${limitClause}`,
queryParams,
);
return stmt.all(bindParams).map(mapMediaRow);
return rows.map((row) => mapMediaRow(row));
}
export function getMediaMessageById(id: number) {
const stmt = db.prepare<MediaRow>(
`SELECT id, chat_id, message_id, user_id, username, display_name, file_type, file_id, file_unique_id, caption, file_name, file_path, file_size, mime_type, duration, width, height, forwarded_to, created_at, updated_at FROM finance_media_messages WHERE id = ?`,
export async function getMediaMessageById(id: number) {
const { rows } = await query<MediaRow>(
`SELECT id,
chat_id,
message_id,
user_id,
username,
display_name,
file_type,
file_id,
file_unique_id,
caption,
file_name,
file_path,
file_size,
mime_type,
duration,
width,
height,
forwarded_to,
created_at,
updated_at
FROM finance_media_messages
WHERE id = $1`,
[id],
);
const row = stmt.get(id);
const row = rows[0];
return row ? mapMediaRow(row) : null;
}

View File

@@ -1,248 +0,0 @@
import { mkdirSync } from 'node:fs';
import Database from 'better-sqlite3';
import { dirname, join } from 'pathe';
const dbFile = join(process.cwd(), 'storage', 'finance.db');
mkdirSync(dirname(dbFile), { recursive: true });
const database = new Database(dbFile);
function assertIdentifier(name: string) {
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
throw new Error(`Invalid identifier: ${name}`);
}
return name;
}
function ensureColumn(table: string, column: string, definition: string) {
const safeTable = assertIdentifier(table);
const safeColumn = assertIdentifier(column);
const columns = database
.prepare<{ name: string }>(`PRAGMA table_info(${safeTable})`)
.all();
if (!columns.some((item) => item.name === safeColumn)) {
database.exec(`ALTER TABLE ${safeTable} ADD COLUMN ${definition}`);
}
}
database.pragma('journal_mode = WAL');
database.exec(`
CREATE TABLE IF NOT EXISTS finance_currencies (
code TEXT PRIMARY KEY,
name TEXT NOT NULL,
symbol TEXT NOT NULL,
is_base INTEGER NOT NULL DEFAULT 0,
is_active INTEGER NOT NULL DEFAULT 1
);
`);
database.exec(`
CREATE TABLE IF NOT EXISTS finance_exchange_rates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
from_currency TEXT NOT NULL,
to_currency TEXT NOT NULL,
rate REAL NOT NULL,
date TEXT NOT NULL,
source TEXT DEFAULT 'manual'
);
`);
database.exec(`
CREATE TABLE IF NOT EXISTS finance_accounts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
currency TEXT NOT NULL,
type TEXT DEFAULT 'cash',
icon TEXT,
color TEXT,
user_id INTEGER DEFAULT 1,
is_active INTEGER DEFAULT 1
);
`);
database.exec(`
CREATE TABLE IF NOT EXISTS finance_categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
type TEXT NOT NULL,
icon TEXT,
color TEXT,
user_id INTEGER DEFAULT 1,
is_active INTEGER DEFAULT 1
);
`);
database.exec(`
CREATE TABLE IF NOT EXISTS finance_transactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL,
amount REAL NOT NULL,
currency TEXT NOT NULL,
exchange_rate_to_base REAL NOT NULL,
amount_in_base REAL NOT NULL,
category_id INTEGER,
account_id INTEGER,
transaction_date TEXT NOT NULL,
description TEXT,
project TEXT,
memo TEXT,
created_at TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'approved',
status_updated_at TEXT,
reimbursement_batch TEXT,
review_notes TEXT,
submitted_by TEXT,
approved_by TEXT,
approved_at TEXT,
is_deleted INTEGER NOT NULL DEFAULT 0,
deleted_at TEXT,
FOREIGN KEY (currency) REFERENCES finance_currencies(code),
FOREIGN KEY (category_id) REFERENCES finance_categories(id),
FOREIGN KEY (account_id) REFERENCES finance_accounts(id)
);
`);
ensureColumn(
'finance_transactions',
'status',
"status TEXT NOT NULL DEFAULT 'approved'",
);
ensureColumn('finance_transactions', 'status_updated_at', 'status_updated_at TEXT');
ensureColumn(
'finance_transactions',
'reimbursement_batch',
'reimbursement_batch TEXT',
);
ensureColumn('finance_transactions', 'review_notes', 'review_notes TEXT');
ensureColumn('finance_transactions', 'submitted_by', 'submitted_by TEXT');
ensureColumn('finance_transactions', 'approved_by', 'approved_by TEXT');
ensureColumn('finance_transactions', 'approved_at', 'approved_at TEXT');
database.exec(`
CREATE TABLE IF NOT EXISTS finance_media_messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
chat_id INTEGER NOT NULL,
message_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
username TEXT,
display_name TEXT,
file_type TEXT NOT NULL,
file_id TEXT NOT NULL,
file_unique_id TEXT,
caption TEXT,
file_name TEXT,
file_path TEXT NOT NULL,
file_size INTEGER,
mime_type TEXT,
duration INTEGER,
width INTEGER,
height INTEGER,
forwarded_to INTEGER,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(chat_id, message_id)
);
`);
database.exec(`
CREATE INDEX IF NOT EXISTS idx_finance_media_messages_created_at
ON finance_media_messages (created_at DESC);
`);
database.exec(`
CREATE INDEX IF NOT EXISTS idx_finance_media_messages_user_id
ON finance_media_messages (user_id);
`);
// Telegram通知配置表
database.exec(`
CREATE TABLE IF NOT EXISTS telegram_notification_configs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
bot_token TEXT NOT NULL,
chat_id TEXT NOT NULL,
notification_types TEXT NOT NULL,
is_enabled INTEGER NOT NULL DEFAULT 1,
priority TEXT DEFAULT 'normal',
rate_limit_seconds INTEGER DEFAULT 0,
batch_enabled INTEGER DEFAULT 0,
batch_interval_minutes INTEGER DEFAULT 60,
retry_enabled INTEGER DEFAULT 1,
retry_max_attempts INTEGER DEFAULT 3,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
`);
database.exec(`
CREATE INDEX IF NOT EXISTS idx_telegram_notification_configs_enabled
ON telegram_notification_configs (is_enabled);
`);
// 通知发送历史表(用于频率控制和去重)
database.exec(`
CREATE TABLE IF NOT EXISTS telegram_notification_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
config_id INTEGER NOT NULL,
notification_type TEXT NOT NULL,
content_hash TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
retry_count INTEGER DEFAULT 0,
sent_at TEXT,
error_message TEXT,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (config_id) REFERENCES telegram_notification_configs(id)
);
`);
database.exec(`
CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_config
ON telegram_notification_history (config_id, created_at DESC);
`);
database.exec(`
CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_hash
ON telegram_notification_history (content_hash, created_at DESC);
`);
database.exec(`
CREATE INDEX IF NOT EXISTS idx_telegram_notification_history_status
ON telegram_notification_history (status, retry_count);
`);
// 确保添加新列到已存在的表
ensureColumn(
'telegram_notification_configs',
'priority',
"priority TEXT DEFAULT 'normal'",
);
ensureColumn(
'telegram_notification_configs',
'rate_limit_seconds',
'rate_limit_seconds INTEGER DEFAULT 0',
);
ensureColumn(
'telegram_notification_configs',
'batch_enabled',
'batch_enabled INTEGER DEFAULT 0',
);
ensureColumn(
'telegram_notification_configs',
'batch_interval_minutes',
'batch_interval_minutes INTEGER DEFAULT 60',
);
ensureColumn(
'telegram_notification_configs',
'retry_enabled',
'retry_enabled INTEGER DEFAULT 1',
);
ensureColumn(
'telegram_notification_configs',
'retry_max_attempts',
'retry_max_attempts INTEGER DEFAULT 3',
);
export default database;

View File

@@ -1,491 +1,21 @@
import crypto from 'node:crypto';
import db from './sqlite';
import {
getEnabledNotificationConfigs,
notifyTransaction,
testTelegramConfig,
} from './telegram-bot';
interface TelegramNotificationConfig {
id: number;
name: string;
botToken: string;
chatId: string;
notificationTypes: string[];
isEnabled: boolean;
priority: string;
rateLimitSeconds: number;
batchEnabled: boolean;
batchIntervalMinutes: number;
retryEnabled: boolean;
retryMaxAttempts: number;
}
export { getEnabledNotificationConfigs, testTelegramConfig };
interface TransactionNotificationData {
id: number;
type: string;
amount: number;
currency: string;
categoryName?: string;
accountName?: string;
transactionDate: string;
description?: string;
status: string;
}
/**
* 生成消息内容hash用于去重
*/
function generateContentHash(content: string): string {
return crypto.createHash('md5').update(content).digest('hex');
}
/**
* 检查频率限制
*/
function checkRateLimit(configId: number, rateLimitSeconds: number): boolean {
if (rateLimitSeconds <= 0) {
return true; // 无限制
}
const cutoffTime = new Date(
Date.now() - rateLimitSeconds * 1000,
).toISOString();
const recent = db
.prepare<{ count: number }>(
`
SELECT COUNT(*) as count
FROM telegram_notification_history
WHERE config_id = ? AND status = 'sent' AND sent_at > ?
`,
)
.get(configId, cutoffTime);
return (recent?.count || 0) === 0;
}
/**
* 检查是否为重复消息
*/
function isDuplicateMessage(
configId: number,
contentHash: string,
withinMinutes: number = 5,
): boolean {
const cutoffTime = new Date(Date.now() - withinMinutes * 60 * 1000).toISOString();
const duplicate = db
.prepare<{ count: number }>(
`
SELECT COUNT(*) as count
FROM telegram_notification_history
WHERE config_id = ? AND content_hash = ? AND created_at > ?
`,
)
.get(configId, contentHash, cutoffTime);
return (duplicate?.count || 0) > 0;
}
/**
* 记录通知历史
*/
function recordNotification(
configId: number,
notificationType: string,
contentHash: string,
status: 'pending' | 'sent' | 'failed',
errorMessage?: string,
): number {
const now = new Date().toISOString();
const result = db
.prepare<unknown, [number, string, string, string, string | null, string | null, string]>(
`
INSERT INTO telegram_notification_history
(config_id, notification_type, content_hash, status, sent_at, error_message, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`,
)
.run(
configId,
notificationType,
contentHash,
status,
status === 'sent' ? now : null,
errorMessage || null,
now,
);
return result.lastInsertRowid as number;
}
/**
* 更新通知状态
*/
function updateNotificationStatus(
historyId: number,
status: 'sent' | 'failed',
retryCount: number = 0,
errorMessage?: string,
): void {
const now = new Date().toISOString();
db.prepare(
`
UPDATE telegram_notification_history
SET status = ?, retry_count = ?, sent_at = ?, error_message = ?
WHERE id = ?
`,
).run(status, retryCount, status === 'sent' ? now : null, errorMessage || null, historyId);
}
/**
* 获取待重试的通知
*/
function getPendingRetries(): Array<{
id: number;
configId: number;
contentHash: string;
retryCount: number;
}> {
return db
.prepare<{ id: number; config_id: number; content_hash: string; retry_count: number }>(
`
SELECT h.id, h.config_id, h.content_hash, h.retry_count
FROM telegram_notification_history h
JOIN telegram_notification_configs c ON h.config_id = c.id
WHERE h.status = 'failed'
AND c.retry_enabled = 1
AND h.retry_count < c.retry_max_attempts
AND h.created_at > datetime('now', '-24 hours')
ORDER BY h.created_at ASC
LIMIT 10
`,
)
.all()
.map((row) => ({
id: row.id,
configId: row.config_id,
contentHash: row.content_hash,
retryCount: row.retry_count,
}));
}
/**
* 获取所有启用的Telegram通知配置增强版
*/
export function getEnabledNotificationConfigs(
notificationType: string = 'transaction',
): TelegramNotificationConfig[] {
const rows = db
.prepare<{
id: number;
name: string;
bot_token: string;
chat_id: string;
notification_types: string;
is_enabled: number;
priority: string;
rate_limit_seconds: number;
batch_enabled: number;
batch_interval_minutes: number;
retry_enabled: number;
retry_max_attempts: number;
}>(
`
SELECT id, name, bot_token, chat_id, notification_types, is_enabled,
priority, rate_limit_seconds, batch_enabled, batch_interval_minutes,
retry_enabled, retry_max_attempts
FROM telegram_notification_configs
WHERE is_enabled = 1
`,
)
.all();
return rows
.map((row) => ({
id: row.id,
name: row.name,
botToken: row.bot_token,
chatId: row.chat_id,
notificationTypes: JSON.parse(row.notification_types) as string[],
isEnabled: row.is_enabled === 1,
priority: row.priority || 'normal',
rateLimitSeconds: row.rate_limit_seconds || 0,
batchEnabled: (row.batch_enabled || 0) === 1,
batchIntervalMinutes: row.batch_interval_minutes || 60,
retryEnabled: (row.retry_enabled || 1) === 1,
retryMaxAttempts: row.retry_max_attempts || 3,
}))
.filter((config) => config.notificationTypes.includes(notificationType));
}
/**
* 格式化交易金额
*/
function formatAmount(amount: number, currency: string): string {
const formatted = amount.toLocaleString('zh-CN', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
return `${currency} ${formatted}`;
}
/**
* 格式化交易类型
*/
function formatTransactionType(type: string): string {
const typeMap: Record<string, string> = {
income: '💰 收入',
expense: '💸 支出',
transfer: '🔄 转账',
};
return typeMap[type] || type;
}
/**
* 格式化交易状态
*/
function formatTransactionStatus(status: string): string {
const statusMap: Record<string, string> = {
draft: '📝 草稿',
pending: '⏳ 待审核',
approved: '✅ 已批准',
rejected: '❌ 已拒绝',
paid: '💵 已支付',
};
return statusMap[status] || status;
}
/**
* 格式化优先级标识
*/
function formatPriority(priority: string): string {
const priorityMap: Record<string, string> = {
low: '🔵',
normal: '⚪',
high: '🟡',
urgent: '🔴',
};
return priorityMap[priority] || '⚪';
}
/**
* 构建交易通知消息
*/
function buildTransactionMessage(
transaction: TransactionNotificationData,
action: string = 'created',
priority: string = 'normal',
): string {
const actionMap: Record<string, string> = {
created: '📋 新增账目记录',
updated: '✏️ 更新账目记录',
deleted: '🗑️ 删除账目记录',
};
const priorityIcon = formatPriority(priority);
const lines: string[] = [
`${priorityIcon} ${actionMap[action] || '📋 账目记录'}`,
'',
`类型:${formatTransactionType(transaction.type)}`,
`金额:${formatAmount(transaction.amount, transaction.currency)}`,
`日期:${transaction.transactionDate}`,
];
if (transaction.categoryName) {
lines.push(`分类:${transaction.categoryName}`);
}
if (transaction.accountName) {
lines.push(`账户:${transaction.accountName}`);
}
lines.push(`状态:${formatTransactionStatus(transaction.status)}`);
if (transaction.description) {
lines.push(``, `备注:${transaction.description}`);
}
lines.push(
``,
`🕐 记录时间:${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`,
);
return lines.join('\n');
}
/**
* 发送Telegram消息带重试
*/
async function sendTelegramMessage(
botToken: string,
chatId: string,
message: string,
retryCount: number = 0,
): Promise<{ success: boolean; error?: string }> {
try {
const url = `https://api.telegram.org/bot${botToken}/sendMessage`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
chat_id: chatId,
text: message,
parse_mode: 'HTML',
}),
});
if (!response.ok) {
const error = await response.json().catch(() => ({ description: 'Unknown error' }));
const errorMsg = error.description || `HTTP ${response.status}`;
console.error(
'[telegram-bot-enhanced] Failed to send message:',
response.status,
errorMsg,
);
return { success: false, error: errorMsg };
}
return { success: true };
} catch (error: unknown) {
const errorMsg = error instanceof Error ? error.message : 'Unknown error';
console.error('[telegram-bot-enhanced] Error sending message:', errorMsg);
return { success: false, error: errorMsg };
}
}
/**
* 通知交易记录(增强版 - 带频率控制、去重、重试)
*/
export async function notifyTransactionEnhanced(
transaction: TransactionNotificationData,
action: string = 'created',
): Promise<void> {
const configs = getEnabledNotificationConfigs('transaction');
if (configs.length === 0) {
console.log('[telegram-bot-enhanced] No enabled notification configs found');
return;
}
for (const config of configs) {
// 1. 检查频率限制
if (!checkRateLimit(config.id, config.rateLimitSeconds)) {
console.log(
`[telegram-bot-enhanced] Rate limit exceeded for config: ${config.name}`,
);
continue;
}
// 2. 构建消息
const message = buildTransactionMessage(transaction, action, config.priority);
const contentHash = generateContentHash(message);
// 3. 检查重复消息
if (isDuplicateMessage(config.id, contentHash)) {
console.log(
`[telegram-bot-enhanced] Duplicate message detected for config: ${config.name}`,
);
continue;
}
// 4. 记录通知历史
const historyId = recordNotification(
config.id,
'transaction',
contentHash,
'pending',
);
// 5. 发送消息
const result = await sendTelegramMessage(
config.botToken,
config.chatId,
message,
);
// 6. 更新状态
if (result.success) {
updateNotificationStatus(historyId, 'sent');
console.log(
`[telegram-bot-enhanced] Sent notification via config: ${config.name}`,
);
} else {
updateNotificationStatus(historyId, 'failed', 0, result.error);
console.error(
`[telegram-bot-enhanced] Failed to send notification via config: ${config.name}, error: ${result.error}`,
);
}
}
...args: Parameters<typeof notifyTransaction>
) {
await notifyTransaction(...args);
}
/**
* 重试失败的通知
*/
export async function retryFailedNotifications(): Promise<void> {
const pending = getPendingRetries();
if (pending.length === 0) {
return;
}
console.log(
`[telegram-bot-enhanced] Retrying ${pending.length} failed notifications`,
);
for (const item of pending) {
// 获取配置
const config = db
.prepare<{
bot_token: string;
chat_id: string;
priority: string;
}>(
'SELECT bot_token, chat_id, priority FROM telegram_notification_configs WHERE id = ?',
)
.get(item.configId);
if (!config) {
continue;
}
// 注意:这里需要重新构建消息或从历史中获取
// 简化处理:发送重试通知
const retryMessage = `🔄 通知重试 (尝试 ${item.retryCount + 1})`;
const result = await sendTelegramMessage(
config.bot_token,
config.chat_id,
retryMessage,
item.retryCount,
);
if (result.success) {
updateNotificationStatus(item.id, 'sent', item.retryCount + 1);
console.log(`[telegram-bot-enhanced] Retry successful for history ID: ${item.id}`);
} else {
updateNotificationStatus(
item.id,
'failed',
item.retryCount + 1,
result.error,
);
console.error(
`[telegram-bot-enhanced] Retry failed for history ID: ${item.id}`,
);
}
}
}
/**
* 测试Telegram Bot配置
*/
export async function testTelegramConfig(
botToken: string,
chatId: string,
): Promise<{ success: boolean; error?: string }> {
const testMessage = `🤖 KT财务系统\n\n✅ Telegram通知配置测试成功\n\n🕐 ${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`;
return await sendTelegramMessage(botToken, chatId, testMessage);
// Retrying logic is not yet implemented for the PostgreSQL data source.
// The SQLite-specific implementation relied on synchronous database access.
// If this functionality becomes necessary, please implement it using the
// telegram_notification_history table with pool-based transactions.
console.warn('[telegram-bot-enhanced] retryFailedNotifications is not implemented.');
}

View File

@@ -1,4 +1,4 @@
import db from './sqlite';
import { query } from './db';
interface TelegramNotificationConfig {
id: number;
@@ -24,18 +24,21 @@ interface TransactionNotificationData {
/**
* 获取所有启用的Telegram通知配置
*/
export function getEnabledNotificationConfigs(
export async function getEnabledNotificationConfigs(
notificationType: string = 'transaction',
): TelegramNotificationConfig[] {
const rows = db
.prepare<{ id: number; name: string; bot_token: string; chat_id: string; notification_types: string; is_enabled: number }>(
`
SELECT id, name, bot_token, chat_id, notification_types, is_enabled
FROM telegram_notification_configs
WHERE is_enabled = 1
`,
)
.all();
): Promise<TelegramNotificationConfig[]> {
const { rows } = await query<{
bot_token: string;
chat_id: string;
id: number;
is_enabled: boolean;
name: string;
notification_types: string;
}>(
`SELECT id, name, bot_token, chat_id, notification_types, is_enabled
FROM telegram_notification_configs
WHERE is_enabled = TRUE`,
);
return rows
.map((row) => ({
@@ -44,7 +47,7 @@ export function getEnabledNotificationConfigs(
botToken: row.bot_token,
chatId: row.chat_id,
notificationTypes: JSON.parse(row.notification_types) as string[],
isEnabled: row.is_enabled === 1,
isEnabled: row.is_enabled,
}))
.filter((config) => config.notificationTypes.includes(notificationType));
}
@@ -175,10 +178,10 @@ export async function notifyTransaction(
transaction: TransactionNotificationData,
action: string = 'created',
): Promise<void> {
const configs = getEnabledNotificationConfigs('transaction');
const configs = await getEnabledNotificationConfigs('transaction');
if (configs.length === 0) {
console.log('[telegram-bot] No enabled notification configs found');
console.warn('[telegram-bot] No enabled notification configs found');
return;
}
@@ -192,7 +195,7 @@ export async function notifyTransaction(
results.forEach((result, index) => {
if (result.status === 'fulfilled' && result.value) {
console.log(
console.warn(
`[telegram-bot] Sent notification via config: ${configs[index].name}`,
);
} else {
@@ -209,17 +212,18 @@ export async function notifyTransaction(
export async function testTelegramConfig(
botToken: string,
chatId: string,
): Promise<{ success: boolean; error?: string }> {
): Promise<{ error?: string; success: boolean }> {
try {
const testMessage = `🤖 KT财务系统\n\n✅ Telegram通知配置测试成功\n\n🕐 ${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`;
const success = await sendTelegramMessage(botToken, chatId, testMessage);
if (success) {
return { success: true };
} else {
return { success: false, error: '发送消息失败请检查Bot Token和Chat ID' };
}
return success
? { success: true }
: {
success: false,
error: '发送消息失败请检查Bot Token和Chat ID',
};
} catch (error: unknown) {
return {
success: false,

View File

@@ -0,0 +1,658 @@
日期,类型,分类,项目名称,金额,币种,账户
2025-10-27,支出,🏷️ 广告推广,谷歌广告,1000,USDT,未知账户
2025-10-27,支出,🏷️ 其他支出,爱拼才会赢 退款,273,USDT,未知账户
2025-10-27,支出,🏷️ 其他支出,鼎胜国际退款,140,USDT,未知账户
2025-10-24,支出,🏷️ 其他支出,买飞机票,142,USDT,未知账户
2025-10-23,支出,🏷️ 广告推广,谷歌广告费,50,USDT,未知账户
2025-10-22,支出,🏷️ 佣金/返佣,阿宏返佣9月,896,USDT,未知账户
2025-10-22,支出,🏷️ 其他支出,泰国支出,30700,USDT,未知账户
2025-10-20,支出,🏷️ 工资,煮饭阿姨工资,3000,USDT,未知账户
2025-10-18,支出,🏷️ 服务器/技术,Open AI服务器续费预存,5000,USDT,未知账户
2025-10-17,支出,🏷️ 服务器/技术,购买域名地址,201.61,USDT,未知账户
2025-10-07,支出,🏷️ 工资,虚拟卡一张,11,USDT,未知账户
2025-10-07,支出,🏷️ 分红,皇雨工资,11364,USDT,未知账户
2025-10-07,支出,🏷️ 分红,代理ip小哥工资,994,USDT,未知账户
2025-10-07,支出,🏷️ 分红,SY工资,4761,USDT,未知账户
2025-10-07,支出,🏷️ 分红,菲菲,1918,USDT,未知账户
2025-10-07,支出,🏷️ 分红,cp工资,1000,USDT,未知账户
2025-10-07,支出,🏷️ 未分类支出,羽琦返佣,2960,USDT,未知账户
2025-10-07,支出,🏷️ 未分类支出,666返佣,230,USDT,未知账户
2025-10-06,支出,🏷️ 未分类支出,金返佣,815,USDT,未知账户
2025-10-05,支出,🏷️ 工资,5张esim卡续费预充值,203,USDT,未知账户
2025-10-04,支出,🏷️ 未分类支出,合鑫返佣,285,USDT,未知账户
2025-10-04,支出,🏷️ 未分类支出,无名返佣,2023,USDT,未知账户
2025-10-04,支出,🏷️ 未分类支出,胖兔返佣,3134,USDT,未知账户
2025-10-04,支出,🏷️ 未分类支出,恋哥返佣,271,USDT,未知账户
2025-10-04,支出,🏷️ 未分类支出,方向返佣,162,USDT,未知账户
2025-10-03,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2025-10-03,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2025-10-03,支出,🏷️ 分红,香缇卡工资,1122,USDT,未知账户
2025-10-03,支出,🏷️ 分红,龙腾集团转给天天,11560,USDT,未知账户
2025-10-03,支出,🏷️ 服务器/技术,龙腾借走,7000,USDT,未知账户
2025-10-03,支出,🏷️ 借款/转账,泰国支出的费用,6221,USDT,未知账户
2025-10-03,支出,🏷️ 未分类支出,杰夫返佣,1476,USDT,未知账户
2025-10-03,支出,🏷️ 分红,天天8月报销,4649,USDT,未知账户
2025-10-03,支出,🏷️ 分红,天天9月报销,931,USDT,未知账户
2025-10-03,支出,🏷️ 未分类支出,国哥返佣8月和9月,60,USDT,未知账户
2025-10-03,支出,🏷️ 未分类支出,市场经理返佣,1388,USDT,未知账户
2025-10-03,支出,🏷️ 未分类支出,天龙返佣,8530,USDT,未知账户
2025-10-02,支出,🏷️ 借款/转账,后勤大叔一个半月薪资,710,USDT,未知账户
2025-10-02,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2025-10-02,支出,🏷️ 分红,助理OAC工资,1500,USDT,未知账户
2025-10-02,支出,🏷️ 借款/转账,小江江,500,USDT,未知账户
2025-10-02,支出,🏷️ 借款/转账,程程,500,USDT,未知账户
2025-10-02,支出,🏷️ 未分类支出,绿豆汤返佣,849,USDT,未知账户
2025-10-02,支出,🏷️ 未分类支出,OAC返佣,1000,USDT,未知账户
2025-09-30,支出,🏷️ 其他支出,合源公司退款,247,USDT,未知账户
2025-09-30,支出,🏷️ 未分类支出,Jack帅哥返佣,536,USDT,未知账户
2025-09-28,支出,🏷️ 其他支出,三喜团队退款,500,USDT,未知账户
2025-09-28,支出,🏷️ 其他支出,爱拼才会赢 退款,265,USDT,未知账户
2025-09-27,支出,🏷️ 分红,龙腾转给天天,1100,USDT,未知账户
2025-09-25,支出,🏷️ 服务器/技术,马来西亚(龙腾月底转回来),1500,USDT,未知账户
2025-09-23,支出,🏷️ 佣金/返佣,服务器续费,169.01,USDT,未知账户
2025-09-20,支出,🏷️ 退款,电脑 3550*2=7100 显示器3600*7=25200 笔记本电脑 78500*1=78500 合计110800元,15873,USDT,未知账户
2025-09-20,支出,🏷️ 佣金/返佣,服务器续费预存,5000,USDT,未知账户
2025-09-17,支出,🏷️ 借款/转账,买2000TRX,737.424,USDT,未知账户
2025-09-17,支出,🏷️ 借款/转账,自动激活地址购买TRX,171,USDT,未知账户
2025-09-12,支出,🏷️ 未分类支出,阿宏返佣,384,USDT,未知账户
2025-09-06,支出,🏷️ 佣金/返佣,cursor,40,USDT,未知账户
2025-09-06,支出,🏷️ 佣金/返佣,服务器59u+128u,187,USDT,未知账户
2025-09-06,支出,🏷️ 佣金/返佣,google翻译,957,USDT,未知账户
2025-09-06,支出,🏷️ 佣金/返佣,openrouter 210u+210u,420,USDT,未知账户
2025-09-06,支出,🏷️ 佣金/返佣,Claude code,250,USDT,未知账户
2025-09-06,支出,🏷️ 借款/转账,泰国支出的费用,6289,USDT,未知账户
2025-09-06,支出,🏷️ 借款/转账,Funstat 开通镜像,4.11,USDT,未知账户
2025-09-06,支出,🏷️ 未分类支出,666返佣,233,USDT,未知账户
2025-09-06,支出,🏷️ 未分类支出,合鑫返佣,375,USDT,未知账户
2025-09-06,支出,🏷️ 未分类支出,恋哥返佣,309,USDT,未知账户
2025-09-06,支出,🏷️ 未分类支出,方向返佣,214,USDT,未知账户
2025-09-06,支出,🏷️ 未分类支出,市场经理返佣,708,USDT,未知账户
2025-09-06,支出,🏷️ 分红,皇雨返佣,1208,USDT,未知账户
2025-09-06,支出,🏷️ 未分类支出,乐乐返佣,166,USDT,未知账户
2025-09-06,支出,🏷️ 未分类支出,pt返佣,965,USDT,未知账户
2025-09-05,支出,🏷️ 佣金/返佣,Open Ai服务器续费预存,5000,USDT,未知账户
2025-09-05,支出,🏷️ 其他支出,星链宇宙退款,77,USDT,未知账户
2025-09-04,支出,🏷️ 分红,超鹏工资,452,USDT,未知账户
2025-09-04,支出,🏷️ 分红,小白工资,387,USDT,未知账户
2025-09-04,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2025-09-04,支出,🏷️ 分红,助理OAC工资,1500,USDT,未知账户
2025-09-04,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2025-09-04,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2025-09-04,支出,🏷️ 分红,香缇卡工资,1122,USDT,未知账户
2025-09-04,支出,🏷️ 借款/转账,小江江,500,USDT,未知账户
2025-09-04,支出,🏷️ 借款/转账,程程,500,USDT,未知账户
2025-09-04,支出,🏷️ 分红,皇雨工资,11332,USDT,未知账户
2025-09-04,支出,🏷️ 分红,代理ip小哥工资,992,USDT,未知账户
2025-09-04,支出,🏷️ 分红,SY工资,4750,USDT,未知账户
2025-09-04,支出,🏷️ 未分类支出,杰夫返佣,845,USDT,未知账户
2025-09-04,支出,🏷️ 未分类支出,老虎返佣,46,USDT,未知账户
2025-08-31,支出,🏷️ 分红,龙腾集团转给天天,14265,USDT,未知账户
2025-08-31,支出,🏷️ 其他支出,Jack帅哥退款,320,USDT,未知账户
2025-08-31,支出,🏷️ 未分类支出,Jack帅哥返佣,380,USDT,未知账户
2025-08-31,支出,🏷️ 未分类支出,绿豆汤返佣,460,USDT,未知账户
2025-08-31,支出,🏷️ 其他支出,英才团队退款,569,USDT,未知账户
2025-08-31,支出,🏷️ 其他支出,天一退款,21,USDT,未知账户
2025-08-31,支出,🏷️ 未分类支出,OAC返佣,538,USDT,未知账户
2025-08-31,支出,🏷️ 未分类支出,金返佣,470,USDT,未知账户
2025-08-31,支出,🏷️ 未分类支出,天龙返佣,11261,USDT,未知账户
2025-08-31,支出,🏷️ 未分类支出,胖兔返佣,3225,USDT,未知账户
2025-08-31,支出,🏷️ 未分类支出,羽琦返佣,2620,USDT,未知账户
2025-08-31,支出,🏷️ 未分类支出,无名返佣,2531,USDT,未知账户
2025-08-30,支出,🏷️ 其他支出,三喜团队退款,1000,USDT,未知账户
2025-08-28,支出,🏷️ 服务器/技术,柬埔寨出差费用,3000,USDT,未知账户
2025-08-24,支出,🏷️ 佣金/返佣,服务器续费,169,USDT,未知账户
2025-08-22,支出,🏷️ 其他支出,爱拼才会赢 退款,103,USDT,未知账户
2025-08-21,支出,🏷️ 佣金/返佣,新OpenAi充值,1028,USDT,未知账户
2025-08-14,支出,🏷️ 佣金/返佣,7月 服务器 59u + 128u,187,USDT,未知账户
2025-08-14,支出,🏷️ 佣金/返佣,7月 google 翻译 1051u,1051,USDT,未知账户
2025-08-14,支出,🏷️ 佣金/返佣,7月 openrouter 105u + 105u + 105u,315,USDT,未知账户
2025-08-14,支出,🏷️ 佣金/返佣,7月 Claude code 250u,250,USDT,未知账户
2025-08-14,支出,🏷️ 佣金/返佣,7月 cursor 131u,131,USDT,未知账户
2025-08-14,支出,🏷️ 分红,代理ip小哥工资,990,USDT,未知账户
2025-08-14,支出,🏷️ 分红,SY工资,4744,USDT,未知账户
2025-08-14,支出,🏷️ 分红,皇雨工资,11316,USDT,未知账户
2025-08-14,支出,🏷️ 分红,7月 皇雨返佣,847,USDT,未知账户
2025-08-14,支出,🏷️ 其他支出,新阿金公司退款,232,USDT,未知账户
2025-08-12,支出,🏷️ 服务器/技术,转给阿寒,16199,USDT,未知账户
2025-08-10,支出,🏷️ 佣金/返佣,Open AI,5000,USDT,未知账户
2025-08-07,支出,🏷️ 未分类支出,金返佣6月和7月,305,USDT,未知账户
2025-08-07,支出,🏷️ 其他支出,兰博基尼退款,76,USDT,未知账户
2025-08-06,支出,🏷️ 未分类支出,乐乐返佣,166,USDT,未知账户
2025-08-06,支出,🏷️ 未分类支出,阿宏返佣6月和7月,2290,USDT,未知账户
2025-08-06,支出,🏷️ 未分类支出,恋哥返佣,326,USDT,未知账户
2025-08-02,支出,🏷️ 借款/转账,泰国的费用,6400,USDT,未知账户
2025-08-02,支出,🏷️ 未分类支出,市场经理返佣,390,USDT,未知账户
2025-08-02,支出,🏷️ 未分类支出,无名返佣,2267,USDT,未知账户
2025-08-02,支出,🏷️ 未分类支出,兔子返佣,112,USDT,未知账户
2025-08-01,支出,🏷️ 服务器/技术,龙腾集团,9792,USDT,未知账户
2025-08-01,支出,🏷️ 佣金/返佣,服务器续费预存,5000,USDT,未知账户
2025-08-01,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2025-08-01,支出,🏷️ 分红,助理OAC工资,1000,USDT,未知账户
2025-08-01,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2025-08-01,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2025-08-01,支出,🏷️ 分红,香缇卡工资,1122,USDT,未知账户
2025-08-01,支出,🏷️ 其他支出,盛天退款,130,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,Jack帅哥佣金,1297,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,OAC00返佣,550,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,方向返佣,199,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,天龙返佣,10263,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,合鑫返佣,315,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,绿豆汤返佣,826,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,胖兔返佣,3646,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,羽琦返佣,2400,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,国哥返佣,60,USDT,未知账户
2025-08-01,支出,🏷️ 未分类支出,杰夫返佣,1551,USDT,未知账户
2025-07-20,支出,🏷️ 佣金/返佣,服务器续费人民币1200,168.3,USDT,未知账户
2025-07-16,支出,🏷️ 其他支出,左岸退款,34.7,USDT,未知账户
2025-07-12,支出,🏷️ 佣金/返佣,Open Ai服务器续费预存,5000,USDT,未知账户
2025-07-09,支出,🏷️ 未分类支出,方向返佣,383,USDT,未知账户
2025-07-07,支出,🏷️ 借款/转账,鑫晟公司5月3600u 6月2880u,6480,USDT,未知账户
2025-07-05,支出,🏷️ 借款/转账,买trx 2000,610.2,USDT,未知账户
2025-07-05,支出,🏷️ 分红,代理ip小哥工资,990,USDT,未知账户
2025-07-05,支出,🏷️ 分红,SY工资,4743,USDT,未知账户
2025-07-05,支出,🏷️ 分红,皇雨工资,11316,USDT,未知账户
2025-07-05,支出,💰 未分类收入,蚊子分红,30000,USDT,未知账户
2025-07-05,支出,💰 未分类收入,阿寒分红,30000,USDT,未知账户
2025-07-04,支出,🏷️ 未分类支出,胖兔返佣,2760,USDT,未知账户
2025-07-04,支出,🏷️ 未分类支出,羽琦返佣,2220,USDT,未知账户
2025-07-03,支出,🏷️ 服务器/技术,龙腾集团15077,12397,USDT,未知账户
2025-07-03,支出,🏷️ 未分类支出,乐乐返佣,83,USDT,未知账户
2025-07-03,支出,🏷️ 未分类支出,合鑫返佣,420,USDT,未知账户
2025-07-01,支出,🏷️ 佣金/返佣,服务器58u+128u,186,USDT,未知账户
2025-07-01,支出,🏷️ 佣金/返佣,google 翻译,1032,USDT,未知账户
2025-07-01,支出,🏷️ 佣金/返佣,openRouter 105u + 50u,155,USDT,未知账户
2025-07-01,支出,🏷️ 佣金/返佣,Claude code 250u + 5% 手续费,262.5,USDT,未知账户
2025-07-01,支出,🏷️ 佣金/返佣,cursor 40u + 13.8u + 3.7u,57.5,USDT,未知账户
2025-07-01,支出,🏷️ 佣金/返佣,iphone16 pro max 工作机,1676,USDT,未知账户
2025-07-01,支出,🏷️ 未分类支出,无名返佣,1790,USDT,未知账户
2025-07-01,支出,🏷️ 未分类支出,恋哥返佣,366,USDT,未知账户
2025-07-01,支出,🏷️ 未分类支出,OAC00返佣,350,USDT,未知账户
2025-07-01,支出,🏷️ 未分类支出,天龙返佣,6293,USDT,未知账户
2025-07-01,支出,🏷️ 未分类支出,绿豆汤返佣,723,USDT,未知账户
2025-07-01,支出,🏷️ 分红,皇雨返佣,656,USDT,未知账户
2025-06-30,支出,🏷️ 佣金/返佣,chatgpt 1个23u开5个,115,USDT,未知账户
2025-06-30,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2025-06-30,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2025-06-30,支出,🏷️ 分红,香缇卡工资,1122,USDT,未知账户
2025-06-30,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2025-06-30,支出,🏷️ 分红,助理OAC工资,1000,USDT,未知账户
2025-06-30,支出,🏷️ 未分类支出,Jack帅哥佣金,947,USDT,未知账户
2025-06-30,支出,🏷️ 未分类支出,杰夫返佣,1095,USDT,未知账户
2025-06-23,支出,🏷️ 佣金/返佣,服务器续费人民币1200,167.59,USDT,未知账户
2025-06-21,支出,🏷️ 其他支出,达摩团队退,390,USDT,未知账户
2025-06-21,支出,🏷️ 佣金/返佣,服务器续费,5000,USDT,未知账户
2025-06-16,支出,🏷️ 未分类支出,胖兔返佣,1764,USDT,未知账户
2025-06-16,支出,🏷️ 未分类支出,羽琦返佣,1580,USDT,未知账户
2025-06-09,支出,🏷️ 分红,皇雨买号测试软件,102,USDT,未知账户
2025-06-09,支出,🏷️ 分红,香缇卡买号测试软件,65,USDT,未知账户
2025-06-09,支出,🏷️ 未分类支出,阿宏返佣,1846,USDT,未知账户
2025-06-08,支出,🏷️ 服务器/技术,测试买控的,50,USDT,未知账户
2025-06-08,支出,🏷️ 未分类支出,金返佣,220,USDT,未知账户
2025-06-07,支出,🏷️ 分红,皇雨工资,11300,USDT,未知账户
2025-06-07,支出,🏷️ 分红,代理ip小哥工资,989,USDT,未知账户
2025-06-07,支出,🏷️ 分红,SY工资,4738,USDT,未知账户
2025-06-07,支出,🏷️ 服务器/技术,泰国房租和换现金,9290,USDT,未知账户
2025-06-05,支出,🏷️ 佣金/返佣,openai,1250,USDT,未知账户
2025-06-04,支出,🏷️ 分红,皇雨返佣,850,USDT,未知账户
2025-06-04,支出,🏷️ 未分类支出,4月 小树返佣,36,USDT,未知账户
2025-06-03,支出,🏷️ 服务器/技术,龙腾集团计14295u+3400=17695,14095,USDT,未知账户
2025-06-03,支出,🏷️ 佣金/返佣,开通企业版chatgpt,1652,USDT,未知账户
2025-06-03,支出,💰 未分类收入,蚊子分红,15000,USDT,未知账户
2025-06-03,支出,💰 未分类收入,阿寒分红,15000,USDT,未知账户
2025-06-02,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2025-06-02,支出,🏷️ 分红,香缇卡工资,1101,USDT,未知账户
2025-06-02,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2025-06-02,支出,🏷️ 分红,助理OAC工资,1000,USDT,未知账户
2025-06-02,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2025-06-02,支出,🏷️ 佣金/返佣,google翻译接口的费用 (取整),1013,USDT,未知账户
2025-06-02,支出,🏷️ 佣金/返佣,openRouter 充值,100,USDT,未知账户
2025-06-02,支出,🏷️ 佣金/返佣,服务器费用,188,USDT,未知账户
2025-06-02,支出,🏷️ 佣金/返佣,cursor费用,64,USDT,未知账户
2025-06-02,支出,🏷️ 未分类支出,杰夫返佣,330,USDT,未知账户
2025-06-02,支出,🏷️ 未分类支出,天龙返佣,8542,USDT,未知账户
2025-06-02,支出,🏷️ 未分类支出,无名返佣,2103,USDT,未知账户
2025-06-02,支出,🏷️ 未分类支出,恋哥返佣,480,USDT,未知账户
2025-06-02,支出,🏷️ 未分类支出,OAC00返佣,586,USDT,未知账户
2025-06-02,支出,🏷️ 未分类支出,乐乐返佣,291,USDT,未知账户
2025-06-02,支出,🏷️ 未分类支出,国哥返佣,30,USDT,未知账户
2025-06-02,支出,🏷️ 未分类支出,合鑫返佣,360,USDT,未知账户
2025-06-01,支出,🏷️ 未分类支出,绿豆汤返佣,973,USDT,未知账户
2025-05-31,支出,🏷️ 其他支出,Jack帅哥余额退,619,USDT,未知账户
2025-05-31,支出,🏷️ 未分类支出,Jack帅哥返佣,1033,USDT,未知账户
2025-05-24,支出,🏷️ 服务器/技术,投资款,20000,USDT,未知账户
2025-05-21,支出,🏷️ 服务器/技术,小树保关,165,USDT,未知账户
2025-05-21,支出,🏷️ 佣金/返佣,服务器续费人民币1200,167,USDT,未知账户
2025-05-17,支出,🏷️ 佣金/返佣,硅基流动 ai 重排序接口充值 2000人民币,278,USDT,未知账户
2025-05-13,支出,🏷️ 未分类支出,羽琦返佣3月 1395u+4月 1260u,2655,USDT,未知账户
2025-05-13,支出,🏷️ 未分类支出,金返佣,200,USDT,未知账户
2025-05-12,支出,🏷️ 佣金/返佣,服务器续费,5000,USDT,未知账户
2025-05-09,支出,🏷️ 借款/转账,换泰珠,3058,USDT,未知账户
2025-05-08,支出,🏷️ 分红,天天返佣,2191.5,USDT,未知账户
2025-05-08,支出,🏷️ 分红,天天投流报销,1488,USDT,未知账户
2025-05-08,支出,🏷️ 未分类支出,胖兔返佣,2062.5,USDT,未知账户
2025-05-05,支出,🏷️ 其他支出,KM 退款,71,USDT,未知账户
2025-05-04,支出,🏷️ 未分类支出,合鑫返佣,435,USDT,未知账户
2025-05-04,支出,🏷️ 未分类支出,乐乐返佣,177,USDT,未知账户
2025-05-03,支出,🏷️ 工资,cloudflare 防火墙,165.5,USDT,未知账户
2025-05-03,支出,🏷️ 佣金/返佣,chatgpt pro,200,USDT,未知账户
2025-05-03,支出,🏷️ 佣金/返佣,cursor,320,USDT,未知账户
2025-05-03,支出,🏷️ 佣金/返佣,openrouter,121,USDT,未知账户
2025-05-03,支出,🏷️ 佣金/返佣,bolt.new,500,USDT,未知账户
2025-05-03,支出,🏷️ 佣金/返佣,openai,911.8,USDT,未知账户
2025-05-03,支出,🏷️ 工资,tg会员,36,USDT,未知账户
2025-05-03,支出,🏷️ 分红,chatwoot客服,19,USDT,未知账户
2025-05-03,支出,🏷️ 工资,uizard,19,USDT,未知账户
2025-05-03,支出,💰 未分类收入,蚊子分红,20000,USDT,未知账户
2025-05-03,支出,💰 未分类收入,阿寒分红,20000,USDT,未知账户
2025-05-02,支出,🏷️ 服务器/技术,租办公室,500,USDT,未知账户
2025-05-02,支出,🏷️ 分红,SY工资,4127,USDT,未知账户
2025-05-02,支出,🏷️ 分红,皇雨工资,11005,USDT,未知账户
2025-05-02,支出,🏷️ 分红,代理ip小哥工资,963,USDT,未知账户
2025-05-02,支出,🏷️ 佣金/返佣,google 翻译接口,903,USDT,未知账户
2025-05-02,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2025-05-02,支出,🏷️ 分红,香缇卡工资,1101,USDT,未知账户
2025-05-02,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2025-05-02,支出,🏷️ 分红,助理OAC工资,1000,USDT,未知账户
2025-05-02,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2025-05-02,支出,🏷️ 未分类支出,绿豆汤返佣,540,USDT,未知账户
2025-05-02,支出,🏷️ 未分类支出,国哥返佣,60,USDT,未知账户
2025-05-02,支出,🏷️ 未分类支出,杰夫返佣,778,USDT,未知账户
2025-05-02,支出,🏷️ 未分类支出,恋哥返佣,273,USDT,未知账户
2025-05-02,支出,🏷️ 未分类支出,天龙返佣,10531,USDT,未知账户
2025-05-02,支出,🏷️ 未分类支出,无名返佣,1819,USDT,未知账户
2025-05-02,支出,🏷️ 未分类支出,OAC00返佣,744,USDT,未知账户
2025-05-02,支出,🏷️ 分红,皇雨返佣,91,USDT,未知账户
2025-05-02,支出,🏷️ 未分类支出,杰夫返佣,778,USDT,未知账户
2025-05-01,支出,🏷️ 未分类支出,Jack帅哥返佣,1111,USDT,未知账户
2025-04-30,支出,🏷️ 借款/转账,买trx 2000,531,USDT,未知账户
2025-04-30,支出,🏷️ 固定资产,打流量,500,USDT,未知账户
2025-04-28,支出,🏷️ 服务器/技术,泰国生活换泰铢,6033,USDT,未知账户
2025-04-25,支出,🏷️ 服务器/技术,做 whatsapp 云控测试的,110,USDT,未知账户
2025-04-25,支出,🏷️ 其他支出,啊Qmeidusha001退款,150,USDT,未知账户
2025-04-22,支出,🏷️ 佣金/返佣,服务器续费人民币1200,165,USDT,未知账户
2025-04-20,支出,🏷️ 分红,阿寒 皇雨 碧桂园 天天 4个人会员续费,120,USDT,未知账户
2025-04-19,支出,🏷️ 其他支出,致胜退款,184,USDT,未知账户
2025-04-14,支出,🏷️ 未分类支出,金返佣,267,USDT,未知账户
2025-04-13,支出,🏷️ 分红,皇雨返佣,1080,USDT,未知账户
2025-04-11,支出,🏷️ 佣金/返佣,服务器续费和防护扣款,5000,USDT,未知账户
2025-04-11,支出,🏷️ 服务器/技术,换美金,448,USDT,未知账户
2025-04-10,支出,🏷️ 服务器/技术,保关,360,USDT,未知账户
2025-04-07,支出,🏷️ 服务器/技术,泰国换泰铢,5874,USDT,未知账户
2025-04-07,支出,🏷️ 工资,esim plus 手机号续费预充值,204,USDT,未知账户
2025-04-07,支出,🏷️ 未分类支出,恋哥返佣,293,USDT,未知账户
2025-04-03,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2025-04-03,支出,🏷️ 分红,香缇卡工资,1101,USDT,未知账户
2025-04-03,支出,🏷️ 未分类支出,杰夫返佣,390,USDT,未知账户
2025-04-03,支出,🏷️ 分红,天天返佣,1492,USDT,未知账户
2025-04-03,支出,💰 未分类收入,紫气东来充值18995%分红,95,USDT,未知账户
2025-04-01,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2025-04-01,支出,🏷️ 分红,助理OAC工资,1000,USDT,未知账户
2025-04-01,支出,🏷️ 退款,路由器费用(硬件+物流),53,USDT,未知账户
2025-04-01,支出,🏷️ 佣金/返佣,google翻译接口的费用,973,USDT,未知账户
2025-04-01,支出,🏷️ 佣金/返佣,openRouter 充值,106,USDT,未知账户
2025-04-01,支出,🏷️ 佣金/返佣,2个服务器费用,188,USDT,未知账户
2025-04-01,支出,🏷️ 分红,SY工资,4110,USDT,未知账户
2025-04-01,支出,🏷️ 分红,皇雨工资,10959,USDT,未知账户
2025-04-01,支出,🏷️ 分红,代理ip小哥工资,959,USDT,未知账户
2025-04-01,支出,🏷️ 服务器/技术,租办公室,500,USDT,未知账户
2025-04-01,支出,🏷️ 借款/转账,买trx 2000,510,USDT,未知账户
2025-04-01,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2025-04-01,支出,🏷️ 分红,龙腾集团费用转给天天,16867,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,Jack帅哥返佣,725,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,天龙返佣,11398,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,闲聊返佣,420,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,OAC00返佣,229,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,无名返佣,1787,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,绿豆汤返佣,371,USDT,未知账户
2025-04-01,支出,💰 未分类收入,蚊子分红,5520,USDT,未知账户
2025-04-01,支出,💰 未分类收入,阿寒分红,5520,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,合鑫返佣,330,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,A Feng 返佣,100,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,胖兔返佣,2659,USDT,未知账户
2025-04-01,支出,🏷️ 未分类支出,乐乐返佣,151,USDT,未知账户
2025-03-29,支出,🏷️ 借款/转账,机器人续费,19,USDT,未知账户
2025-03-29,支出,💰 未分类收入,蚊子分红,10000,USDT,未知账户
2025-03-29,支出,💰 未分类收入,阿寒分红,10000,USDT,未知账户
2025-03-28,支出,🏷️ 佣金/返佣,阿里云主服务器,2100,USDT,未知账户
2025-03-28,支出,🏷️ 分红,皇雨买 007 测试系统,110,USDT,未知账户
2025-03-23,支出,🏷️ 佣金/返佣,服务器续费人民币1200,165.28,USDT,未知账户
2025-03-18,支出,🏷️ 其他支出,老莫8688 退款,44,USDT,未知账户
2025-03-18,支出,🏷️ 其他支出,月入10w美金 退款,480,USDT,未知账户
2025-03-12,支出,🏷️ 佣金/返佣,11月 open Ai 接口费用,1500,USDT,未知账户
2025-03-12,支出,🏷️ 佣金/返佣,2月 open Ai 接口费用,1163,USDT,未知账户
2025-03-12,支出,🏷️ 佣金/返佣,3月 open Ai 接口费用,713,USDT,未知账户
2025-03-12,支出,🏷️ 未分类支出,乐乐返佣,120,USDT,未知账户
2025-03-12,支出,🏷️ 分红,天天紫气东来分红5%,114,USDT,未知账户
2025-03-12,支出,🏷️ 未分类支出,1月阿宏返佣,1213,USDT,未知账户
2025-03-12,支出,🏷️ 未分类支出,2月阿宏返佣,480,USDT,未知账户
2025-03-08,支出,🏷️ 未分类支出,金返佣,200,USDT,未知账户
2025-03-06,支出,🏷️ 未分类支出,合鑫返佣,315,USDT,未知账户
2025-03-04,支出,🏷️ 分红,龙腾集团费用转给天天,16321,USDT,未知账户
2025-03-03,支出,🏷️ 未分类支出,羽琦返佣,783,USDT,未知账户
2025-03-02,支出,🏷️ 佣金/返佣,服务器两台,188,USDT,未知账户
2025-03-02,支出,🏷️ 佣金/返佣,google 翻译api的 费用 截止到 2025.02.28,1074,USDT,未知账户
2025-03-02,支出,🏷️ 佣金/返佣,openrouter 充值,60,USDT,未知账户
2025-03-02,支出,🏷️ 佣金/返佣,deepseek,52,USDT,未知账户
2025-03-02,支出,🏷️ 服务器/技术,租办公室,500,USDT,未知账户
2025-03-02,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2025-03-02,支出,🏷️ 分红,香缇卡工资,1102,USDT,未知账户
2025-03-02,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2025-03-02,支出,🏷️ 分红,助理OAC工资,786,USDT,未知账户
2025-03-02,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2025-03-02,支出,🏷️ 分红,SY工资,2032,USDT,未知账户
2025-03-02,支出,🏷️ 分红,皇雨工资,8517,USDT,未知账户
2025-03-02,支出,🏷️ 分红,代理ip小哥工资,746,USDT,未知账户
2025-03-02,支出,🏷️ 佣金/返佣,广州技术,733,USDT,未知账户
2025-03-02,支出,🏷️ 未分类支出,绿豆汤返佣,700,USDT,未知账户
2025-03-01,支出,🏷️ 借款/转账,买trx 2000,502,USDT,未知账户
2025-03-01,支出,🏷️ 工资,小红卡续费余额不足,400,USDT,未知账户
2025-03-01,支出,🏷️ 未分类支出,闲聊返佣,330,USDT,未知账户
2025-03-01,支出,🏷️ 未分类支出,国哥返佣,150,USDT,未知账户
2025-03-01,支出,🏷️ 未分类支出,胖兔返佣,3129,USDT,未知账户
2025-03-01,支出,🏷️ 未分类支出,OAC00返佣,157,USDT,未知账户
2025-03-01,支出,🏷️ 未分类支出,无名返佣,1146,USDT,未知账户
2025-03-01,支出,🏷️ 未分类支出,辞辞返佣,181,USDT,未知账户
2025-03-01,支出,🏷️ 未分类支出,恋哥返佣,440,USDT,未知账户
2025-03-01,支出,💰 未分类收入,蚊子分红,30000,USDT,未知账户
2025-03-01,支出,💰 未分类收入,阿寒分红,30000,USDT,未知账户
2025-02-28,支出,🏷️ 借款/转账,A Feng,110,USDT,未知账户
2025-02-28,支出,🏷️ 未分类支出,Jack帅哥返佣,1276,USDT,未知账户
2025-02-28,支出,🏷️ 未分类支出,天龙返佣,9757,USDT,未知账户
2025-02-26,支出,🏷️ 工资,小红卡买虚拟卡,10,USDT,未知账户
2025-02-26,支出,🏷️ 佣金/返佣,阿里云主服务器,1980,USDT,未知账户
2025-02-23,支出,🏷️ 佣金/返佣,服务器续费,165,USDT,未知账户
2025-02-18,支出,🏷️ 其他支出,一路发 多充退款,2500,USDT,未知账户
2025-02-15,支出,🏷️ 服务器/技术,转给阿寒在泰国租房等等,8982,USDT,未知账户
2025-02-15,支出,🏷️ 未分类支出,A Feng 1月返佣,158,USDT,未知账户
2025-02-15,支出,🏷️ 其他支出,众彩公司退款,52,USDT,未知账户
2025-02-11,支出,🏷️ 佣金/返佣,1月open Ai费用,782,USDT,未知账户
2025-02-11,支出,🏷️ 未分类支出,乐乐1月返佣,200,USDT,未知账户
2025-02-10,支出,🏷️ 佣金/返佣,10月服务器续费,874.47,USDT,未知账户
2025-02-10,支出,🏷️ 佣金/返佣,11月服务器续费,923.42,USDT,未知账户
2025-02-10,支出,🏷️ 佣金/返佣,12月服务器续费,936.34,USDT,未知账户
2025-02-10,支出,🏷️ 佣金/返佣,2025年1月服务器续费,956,USDT,未知账户
2025-02-10,支出,🏷️ 分红,1月chatwoot 客服,57,USDT,未知账户
2025-02-10,支出,🏷️ 分红,2月chatwoot 客服,57,USDT,未知账户
2025-02-10,支出,🏷️ 佣金/返佣,bolt.new ai 写代码套餐开通,181.7,USDT,未知账户
2025-02-10,支出,🏷️ 退款,三星硬盘1579rmb,215.4,USDT,未知账户
2025-02-10,支出,🏷️ 退款,西部数据企业级氦气硬盘(12732rmb),1737,USDT,未知账户
2025-02-10,支出,🏷️ 退款,绿联DXP8800Pro云硬盘7039.72rmb,960.4,USDT,未知账户
2025-02-10,支出,🏷️ 分红,香缇卡笔记本电脑(9436.49rmb),1287.4,USDT,未知账户
2025-02-10,支出,🏷️ 佣金/返佣,双路渲染服务器40核(10499rmb),1432.3,USDT,未知账户
2025-02-10,支出,🏷️ 借款/转账,A Feng补12月漏,50,USDT,未知账户
2025-02-10,支出,🏷️ 借款/转账,辞辞补1月漏,203,USDT,未知账户
2025-02-10,支出,🏷️ 未分类支出,羽琦返佣,770,USDT,未知账户
2025-02-10,支出,🏷️ 未分类支出,绿豆汤返佣,520,USDT,未知账户
2025-02-07,支出,🏷️ 分红,天天开工红包,257,USDT,未知账户
2025-02-07,支出,🏷️ 分红,碧桂园开工红包,257,USDT,未知账户
2025-02-07,支出,🏷️ 分红,香缇卡开工红包,257,USDT,未知账户
2025-02-07,支出,🏷️ 分红,财务amy开工红包,257,USDT,未知账户
2025-02-07,支出,🏷️ 服务器/技术,助理oac开工红包,257,USDT,未知账户
2025-02-07,支出,🏷️ 分红,代理小哥开工红包,257,USDT,未知账户
2025-02-07,支出,🏷️ 分红,皇雨开工红包,529,USDT,未知账户
2025-02-06,支出,🏷️ 佣金/返佣,服务器临时配置升级 充值,1000,USDT,未知账户
2025-02-05,支出,🏷️ 未分类支出,合鑫返佣,600,USDT,未知账户
2025-02-04,支出,🏷️ 其他支出,众发退款,900,USDT,未知账户
2025-02-04,支出,🏷️ 未分类支出,无名返佣,752,USDT,未知账户
2025-02-04,支出,🏷️ 未分类支出,闲聊返佣,763,USDT,未知账户
2025-02-03,支出,🏷️ 未分类支出,辞辞返佣,1033,USDT,未知账户
2025-02-03,支出,🏷️ 分红,天天紫气东来分红5%,186,USDT,未知账户
2025-02-02,支出,🏷️ 服务器/技术,龙腾集团,4202,USDT,未知账户
2025-02-02,支出,🏷️ 未分类支出,胖兔返佣,2128,USDT,未知账户
2025-02-02,支出,🏷️ 其他支出,启运退款,88,USDT,未知账户
2025-02-01,支出,🏷️ 未分类支出,天龙返佣,5632,USDT,未知账户
2025-01-28,支出,🏷️ 未分类支出,Jack帅哥返佣,723,USDT,未知账户
2025-01-25,支出,🏷️ 佣金/返佣,xiaohai0000 鸿图,20,USDT,未知账户
2025-01-24,支出,🏷️ 分红,amy买香港信用卡虚拟卡,10,USDT,未知账户
2025-01-24,支出,🏷️ 服务器/技术,蚊子 阿寒在泰国两人生活费,2497,USDT,未知账户
2025-01-24,支出,💰 未分类收入,蚊子分红,10000,USDT,未知账户
2025-01-24,支出,💰 未分类收入,阿寒分红,10000,USDT,未知账户
2025-01-21,支出,🏷️ 分红,皇雨工资5517 年终奖5517,11034,USDT,未知账户
2025-01-21,支出,🏷️ 分红,代理ip 小哥工资965 年终奖965,1930,USDT,未知账户
2025-01-21,支出,🏷️ 分红,天天工资1500年终奖750,2250,USDT,未知账户
2025-01-21,支出,🏷️ 分红,碧桂园工资1000 年终奖500,1500,USDT,未知账户
2025-01-21,支出,🏷️ 分红,香缇卡工资1103年终奖552,1655,USDT,未知账户
2025-01-21,支出,🏷️ 分红,财务amy 1500年终奖750,2250,USDT,未知账户
2025-01-21,支出,🏷️ 分红,助理OAC工资1000年终奖500,1500,USDT,未知账户
2025-01-21,支出,🏷️ 佣金/返佣,服务器续费,165.97,USDT,未知账户
2025-01-18,支出,🏷️ 借款/转账,买trx 2000,527.904,USDT,未知账户
2025-01-15,支出,🏷️ 分红,转给香缇卡买账户备用金,300,USDT,未知账户
2025-01-14,支出,🏷️ 分红,香缇卡买小红卡,50,USDT,未知账户
2025-01-14,支出,🏷️ 工资,OAC买小红卡实体卡,100,USDT,未知账户
2025-01-13,支出,🏷️ 分红,amy买小红卡,50,USDT,未知账户
2025-01-11,支出,🏷️ 分红,小哥两个月开发费用,1000,USDT,未知账户
2025-01-11,支出,🏷️ 借款/转账,老表对接,300,USDT,未知账户
2025-01-09,支出,🏷️ 分红,转给香缇卡买账户备用金,200,USDT,未知账户
2025-01-08,支出,🏷️ 退款,泰国买车,39358.6,USDT,未知账户
2025-01-03,支出,🏷️ 分红,转给天天,9000,USDT,未知账户
2025-01-01,支出,🏷️ 借款/转账,合鑫,570,USDT,未知账户
2025-01-01,支出,🏷️ 借款/转账,金鑫,26,USDT,未知账户
2025-01-01,支出,🏷️ 佣金/返佣,xiaohai0000 鸿图,380,USDT,未知账户
2025-01-01,支出,🏷️ 借款/转账,阿宏11月 1147Uu+12月1892,3039,USDT,未知账户
2025-01-01,支出,💰 未分类收入,蚊子分红,10000,USDT,未知账户
2025-01-01,支出,💰 未分类收入,阿寒分红,10000,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,A Feng返佣,180,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,绿豆汤返佣,500,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,天龙返佣,8795,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,胖兔返佣,2622.7,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,无名返佣,800,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,闲聊返佣,1043,USDT,未知账户
2025-01-01,支出,🏷️ 分红,天天散户分红,198,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,乐乐返佣,414,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,知青返佣,135,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,恋哥返佣,526.7,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,长青返佣,77,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,国哥返佣,150,USDT,未知账户
2025-01-01,支出,🏷️ 未分类支出,羽琦返佣,419,USDT,未知账户
2024-12-31,支出,🏷️ 分红,皇雨工资 代理ip小哥 服务器续费128,6638,USDT,未知账户
2024-12-31,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2024-12-31,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2024-12-31,支出,🏷️ 分红,香缇卡工资,1000,USDT,未知账户
2024-12-31,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2024-12-31,支出,🏷️ 分红,助理OAC工资,1000,USDT,未知账户
2024-12-31,支出,💰 未分类收入,蚊子分红,20000,USDT,未知账户
2024-12-31,支出,💰 未分类收入,阿寒分红,20000,USDT,未知账户
2024-12-31,支出,🏷️ 未分类支出,Jack帅哥返佣,842,USDT,未知账户
2024-12-31,支出,🏷️ 其他支出,金鑫 退款,800,USDT,未知账户
2024-12-30,支出,🏷️ 其他支出,金鑫退款,800,USDT,未知账户
2024-12-21,支出,🏷️ 服务器/技术,转龙腾,3000,USDT,未知账户
2024-12-21,支出,🏷️ 佣金/返佣,服务器续费,164,USDT,未知账户
2024-12-19,支出,🏷️ 分红,转给天天,7000,USDT,未知账户
2024-12-15,支出,💰 未分类收入,蚊子分红,20000,USDT,未知账户
2024-12-15,支出,💰 未分类收入,阿寒分红,20000,USDT,未知账户
2024-12-06,支出,🏷️ 分红,转给天天,5000,USDT,未知账户
2024-12-06,支出,🏷️ 退款,硬盘费用,1769,USDT,未知账户
2024-12-01,支出,🏷️ 分红,香缇卡工资,1000,USDT,未知账户
2024-12-01,支出,🏷️ 分红,财务Amy工资,1500,USDT,未知账户
2024-12-01,支出,🏷️ 分红,助理OAC工资,1000,USDT,未知账户
2024-12-01,支出,🏷️ 服务器/技术,龙腾集团鑫晟公司,6102,USDT,未知账户
2024-12-01,支出,🏷️ 分红,皇雨5579 代理ip小哥976,6555,USDT,未知账户
2024-12-01,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2024-12-01,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2024-12-01,支出,🏷️ 分红,龙腾集团转给天天,6073,USDT,未知账户
2024-12-01,支出,🏷️ 佣金/返佣,服务器续费专用小红卡,50,USDT,未知账户
2024-12-01,支出,🏷️ 分红,天天散户,172,USDT,未知账户
2024-12-01,支出,🏷️ 佣金/返佣,服务器续费2个月,256,USDT,未知账户
2024-12-01,支出,🏷️ 佣金/返佣,流量测试服务器,500,USDT,未知账户
2024-12-01,支出,🏷️ 退款,展示屏,805,USDT,未知账户
2024-12-01,支出,🏷️ 佣金/返佣,openai 12 月份接口费用,1768,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,天龙返佣,9738,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,绿豆汤返佣,500,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,貔貅返佣,300,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,恋哥返佣713+367补10月,1080,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,无名返佣1107+635,1742,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,知青返佣,768,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,乐乐返佣,494,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,合鑫返佣,615,USDT,未知账户
2024-12-01,支出,🏷️ 未分类支出,胖兔返佣,2601,USDT,未知账户
2024-11-30,支出,🏷️ 未分类支出,Jack帅哥返佣,649,USDT,未知账户
2024-11-29,支出,🏷️ 工资,开飞机会员,38,USDT,未知账户
2024-11-16,支出,🏷️ 借款/转账,3000 trx自动归集的手续费购买609.444 usdt,609.444,USDT,未知账户
2024-11-15,支出,🏷️ 佣金/返佣,oac 40 ai机器人40,80,USDT,未知账户
2024-11-10,支出,🏷️ 借款/转账,买trx,85,USDT,未知账户
2024-11-10,支出,🏷️ 佣金/返佣,人工智能接口费用,1590,USDT,未知账户
2024-11-10,支出,🏷️ 佣金/返佣,服务器费用,1326,USDT,未知账户
2024-11-10,支出,🏷️ 未分类支出,阿宏佣金,2505,USDT,未知账户
2024-11-10,支出,🏷️ 借款/转账,买自动到账地址(用于质押获得手续费),2000,USDT,未知账户
2024-11-07,支出,🏷️ 服务器/技术,投资款项6006+32934,38940,USDT,未知账户
2024-11-05,支出,🏷️ 分红,转给啊寒3000美金用于天天买电脑,3000,USDT,未知账户
2024-11-05,支出,🏷️ 分红,给财务买苹果电脑,1499,USDT,未知账户
2024-11-05,支出,🏷️ 退款,蚊子工作苹果电脑,8433,USDT,未知账户
2024-11-04,支出,🏷️ 未分类支出,大白菜佣金,1290.5,USDT,未知账户
2024-11-04,支出,🏷️ 未分类支出,胖兔佣金,2942,USDT,未知账户
2024-11-04,支出,🏷️ 未分类支出,恋哥佣金,660,USDT,未知账户
2024-11-02,支出,🏷️ 未分类支出,貔貅佣金,900,USDT,未知账户
2024-11-01,支出,🏷️ 借款/转账,买trx,700,USDT,未知账户
2024-11-01,支出,🏷️ 分红,龙腾集团转给天天,9797,USDT,未知账户
2024-11-01,支出,🏷️ 分红,天天虚拟信用卡,50,USDT,未知账户
2024-11-01,支出,🏷️ 未分类支出,乐乐佣金,225,USDT,未知账户
2024-11-01,支出,🏷️ 未分类支出,国哥佣金,450,USDT,未知账户
2024-10-31,支出,🏷️ 分红,代理ip小哥,1000,USDT,未知账户
2024-10-31,支出,🏷️ 分红,黄雨工资,5673,USDT,未知账户
2024-10-31,支出,🏷️ 分红,财务,1500,USDT,未知账户
2024-10-31,支出,🏷️ 分红,天天,1500,USDT,未知账户
2024-10-31,支出,🏷️ 分红,碧桂园,1000,USDT,未知账户
2024-10-31,支出,🏷️ 借款/转账,卡卡提,500,USDT,未知账户
2024-10-31,支出,🏷️ 未分类支出,天龙佣金,9292,USDT,未知账户
2024-10-31,支出,🏷️ 未分类支出,核心佣金,2349,USDT,未知账户
2024-10-31,支出,💰 未分类收入,蚊子分红,10000,USDT,未知账户
2024-10-31,支出,💰 未分类收入,阿寒分红,10000,USDT,未知账户
2024-10-31,支出,🏷️ 未分类支出,知青佣金,818,USDT,未知账户
2024-10-31,支出,🏷️ 未分类支出,合鑫佣金,420,USDT,未知账户
2024-10-31,支出,🏷️ 分红,天天 紫气东来散户分红5%,146,USDT,未知账户
2024-10-30,支出,🏷️ 未分类支出,Jack帅哥佣金,700,USDT,未知账户
2024-10-28,支出,💰 未分类收入,阿寒分红,1000,USDT,未知账户
2024-10-28,支出,💰 未分类收入,蚊子分红,1000,USDT,未知账户
2024-10-25,支出,🏷️ 其他支出,七月退,100,USDT,未知账户
2024-10-22,支出,🏷️ 服务器/技术,接待,3000,USDT,未知账户
2024-10-19,支出,🏷️ 工资,2t u盘两个。每个203u,406,USDT,未知账户
2024-10-19,支出,💰 未分类收入,阿寒分红,3000,USDT,未知账户
2024-10-19,支出,💰 未分类收入,蚊子分红,3000,USDT,未知账户
2024-10-16,支出,🏷️ 工资,007购买,125,USDT,未知账户
2024-10-11,支出,🏷️ 未分类支出,大卫佣金,1875,USDT,未知账户
2024-10-09,支出,🏷️ 借款/转账,购买 trx质押产生能量,2000,USDT,未知账户
2024-10-09,支出,🏷️ 固定资产,汉城广告费,1000,USDT,未知账户
2024-10-06,支出,🏷️ 其他支出,大秦退费,310,USDT,未知账户
2024-10-05,支出,🏷️ 佣金/返佣,技术公司鸿泰,1768,USDT,未知账户
2024-10-05,支出,🏷️ 佣金/返佣,ChatGPT自建服务器半年付,479.88,USDT,未知账户
2024-10-05,支出,🏷️ 借款/转账,交友五个阶段提示词编写和优化外包,700,USDT,未知账户
2024-10-04,支出,🏷️ 佣金/返佣,ChatGPT接口费用,869,USDT,未知账户
2024-10-04,支出,🏷️ 佣金/返佣,备用OpenAI预充值,200,USDT,未知账户
2024-10-04,支出,🏷️ 佣金/返佣,备用转发接口充值,100,USDT,未知账户
2024-10-04,支出,🏷️ 佣金/返佣,Kt主服务器。分流服务器。自动到账服务器。oss服务器,1143,USDT,未知账户
2024-10-04,支出,🏷️ 未分类支出,胖兔佣金,2821,USDT,未知账户
2024-10-03,支出,🏷️ 分红,皇工资35000rmb,5022,USDT,未知账户
2024-10-03,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2024-10-03,支出,🏷️ 分红,碧桂园,1000,USDT,未知账户
2024-10-03,支出,🏷️ 分红,amy,1500,USDT,未知账户
2024-10-03,支出,🏷️ 分红,代理ip小哥,1000,USDT,未知账户
2024-10-03,支出,🏷️ 借款/转账,截图,100,USDT,未知账户
2024-10-03,支出,🏷️ 佣金/返佣,技术公司,3815,USDT,未知账户
2024-10-03,支出,🏷️ 未分类支出,乐乐佣金,483,USDT,未知账户
2024-10-03,支出,💰 未分类收入,蚊子分红,593,USDT,未知账户
2024-10-02,支出,🏷️ 未分类支出,长青佣金,240,USDT,未知账户
2024-10-02,支出,🏷️ 未分类支出,合鑫佣金,450,USDT,未知账户
2024-10-01,支出,🏷️ 未分类支出,天龙佣金,5815,USDT,未知账户
2024-10-01,支出,🏷️ 未分类支出,核心佣金,2413,USDT,未知账户
2024-10-01,支出,🏷️ 未分类支出,三七公司佣金,189,USDT,未知账户
2024-09-26,支出,🏷️ 分红,天天控天费用,593,USDT,未知账户
2024-09-26,支出,🏷️ 借款/转账,自动到账购买2000trx,329,USDT,未知账户
2024-09-25,支出,🏷️ 固定资产,亚太地推开支,1550,USDT,未知账户
2024-09-24,支出,🏷️ 固定资产,亚太小助手投放,1500,USDT,未知账户
2024-09-22,支出,🏷️ 工资,processon流程图终身会员,185,USDT,未知账户
2024-09-21,支出,🏷️ 佣金/返佣,服务器续费,1210,USDT,未知账户
2024-09-20,支出,🏷️ 借款/转账,截图制作,338,USDT,未知账户
2024-09-19,支出,🏷️ 未分类支出,Jack帅哥佣金,276,USDT,未知账户
2024-09-18,支出,🏷️ 固定资产,广告费用,450,USDT,未知账户
2024-09-18,支出,🏷️ 工资,开飞机会员,38,USDT,未知账户
2024-09-13,支出,🏷️ 服务器/技术,阿鹏借出35000rmb,4943.5,USDT,未知账户
2024-09-13,支出,🏷️ 退款,rog电脑购买,5659,USDT,未知账户
2024-09-11,支出,🏷️ 未分类支出,羽琦佣金,154,USDT,未知账户
2024-09-10,支出,🏷️ 固定资产,广告费,1000,USDT,未知账户
2024-09-03,支出,🏷️ 其他支出,大秦退费,300,USDT,未知账户
2024-09-03,支出,🏷️ 工资,飞机会员续费,35,USDT,未知账户
2024-09-01,支出,🏷️ 未分类支出,老外 大卫佣金,2250,USDT,未知账户
2024-09-01,支出,🏷️ 未分类支出,天龙佣金,6943.9,USDT,未知账户
2024-09-01,支出,🏷️ 未分类支出,大卫5月的佣金,900,USDT,未知账户
2024-08-31,支出,🏷️ 分红,天天控天费用,2207,USDT,未知账户
2024-08-31,支出,🏷️ 佣金/返佣,nat转发包年,280,USDT,未知账户
2024-08-31,支出,🏷️ 未分类支出,长青佣金,377,USDT,未知账户
2024-08-31,支出,💰 未分类收入,蚊子同比例分红,2207,USDT,未知账户
2024-08-31,支出,🏷️ 未分类支出,Jack帅哥佣金,456,USDT,未知账户
2024-08-31,支出,🏷️ 未分类支出,乐乐佣金,440,USDT,未知账户
2024-08-30,支出,🏷️ 佣金/返佣,宝塔会员,203,USDT,未知账户
2024-08-30,支出,🏷️ 未分类支出,核心佣金,3103,USDT,未知账户
2024-08-27,支出,🏷️ 退款,买车定金,2000,USDT,未知账户
2024-08-27,支出,🏷️ 退款,买车尾款,16562,USDT,未知账户
2024-08-27,支出,🏷️ 佣金/返佣,技术信用卡,50,USDT,未知账户
2024-08-27,支出,🏷️ 分红,天天工资,1500,USDT,未知账户
2024-08-27,支出,🏷️ 分红,碧桂园工资,1000,USDT,未知账户
2024-08-27,支出,🏷️ 分红,皇工资,5000,USDT,未知账户
2024-08-27,支出,🏷️ 分红,财务客服,1500,USDT,未知账户
2024-08-27,支出,🏷️ 分红,代理ip技术,1000,USDT,未知账户
2024-08-27,支出,🏷️ 佣金/返佣,人工智能接口,700,USDT,未知账户
2024-08-27,支出,🏷️ 借款/转账,处理员工一起出,10000,USDT,未知账户
2024-08-27,支出,🏷️ 借款/转账,外星人一起出4.8w,6571,USDT,未知账户
2024-08-27,支出,🏷️ 服务器/技术,啊杰借的10000,1404,USDT,未知账户
2024-08-27,支出,🏷️ 固定资产,群发广告,300,USDT,未知账户
2024-08-27,支出,🏷️ 借款/转账,网络攻击买服务,800,USDT,未知账户
2024-08-27,支出,🏷️ 未分类支出,老练几个月佣金,1586,USDT,未知账户
2024-08-27,支出,🏷️ 未分类支出,胖兔佣金,3597,USDT,未知账户
2024-08-07,支出,🏷️ 借款/转账,攻击,60,USDT,未知账户
2024-08-07,支出,🏷️ 佣金/返佣,其他翻译测试,58,USDT,未知账户
2024-08-07,支出,🏷️ 佣金/返佣,佣金,80,USDT,未知账户
2024-08-07,支出,🏷️ 佣金/返佣,乐乐佣金,343,USDT,未知账户
2024-08-07,支出,🏷️ 佣金/返佣,佣金,823.5,USDT,未知账户
2024-08-07,支出,🏷️ 退款,退款,170.71,USDT,未知账户
2024-08-07,支出,🏷️ 退款,退款,70,USDT,未知账户
2024-08-03,支出,🏷️ 分红,啊寒分红,3000,USDT,未知账户
2024-08-03,支出,🏷️ 分红,蚊子分红,3000,USDT,未知账户
2024-08-03,支出,🏷️ 佣金/返佣,长青佣金,326,USDT,未知账户
2024-08-03,支出,🏷️ 佣金/返佣,阿宏佣金,311,USDT,未知账户
2024-06-15,支出,未分类,6月测试交易,50,USDT,未知账户
2024-06-15,支出,未分类,6月测试交易,50,USDT,未知账户
2024-06-15,支出,未分类,6月测试交易,50,USDT,未知账户
2024-06-15,支出,未分类,6月测试交易,50,USDT,未知账户
2025-10-30,支出,🏷️ 未分类,买飞机号,213,USDT,乐乐用
2025-10-31,支出,🏷️ 未分类,公司的外网专线费用,211,USDT,cp
2025-10-31,支出,🏷️ 未分类,强耀科技退款,19,USDT,未知账户
2025-11-01,支出,🏷️ 未分类,阿金公司退款,186,USDT,未知账户
2025-11-01,支出,🏷️ 未分类,小白工资,1000,USDT,未知账户
2025-11-01,支出,🏷️ 未分类,cp工资,1000,USDT,未知账户
2025-11-01,支出,🏷️ 未分类,菲菲工资,2344,USDT,16500按7.04
2025-11-02,支出,🏷️ 未分类,绿豆汤返佣,99,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,OAC返佣,972,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,天龙返佣,10556,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,Jack帅哥返佣,506,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,无名返佣,1655,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,方向返佣,89,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,阿泰会员,30,USDT,天天
2025-11-02,支出,🏷️ 未分类,香缇卡会员,30,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,虚拟卡,100,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,代理ip,15,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,服务器,540,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,域名,15,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,宝金出海会员,30,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,网盘会员,42.5,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,水电宽带,65,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,硬盘,68,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,cpcc会员,253.5,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,香缇卡流量卡,153,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,杰夫返佣,1055,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,天天工资,1500,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,碧桂园工资,1000,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,香缇卡工资,1146,USDT,未知账户
2025-11-02,支出,🏷️ 未分类,龙腾集团,7700,USDT,14700扣10月龙腾借7000 鑫晟公司2480未结算
2025-11-04,支出,🏷️ 未分类,羽琦返佣,2960,USDT,未知账户
2025-11-04,支出,🏷️ 未分类,皇雨工资,11364,USDT,80000元按7.04
2025-11-04,支出,🏷️ 未分类,代理ip小哥工资,994,USDT,7000元按7.04
2025-11-04,支出,🏷️ 未分类,SY工资,4761,USDT,4261+50030000元按7.04
2025-11-04,支出,🏷️ 未分类,财务Amy工资,1500,USDT,未知账户
2025-11-04,支出,🏷️ 未分类,助理OAC工资,1500,USDT,未知账户
2025-11-04,支出,🏷️ 未分类,煮饭阿姨工资,426,USDT,未知账户
2025-11-04,支出,🏷️ 未分类,李涛工资,578,USDT,未知账户
2025-11-04,支出,🏷️ 未分类,胖兔返佣,3414,USDT,未知账户
2025-11-04,支出,🏷️ 未分类,合鑫返佣,105,USDT,未知账户
2025-11-04,支出,🏷️ 未分类,恋哥返佣,187,USDT,未知账户
2025-11-05,支出,🏷️ 未分类,阿宏返佣,815,USDT,825u (10u换trx)
2025-11-05,支出,🏷️ 未分类,666返佣,270,USDT,未知账户
1 日期 类型 分类 项目名称 金额 币种 账户
2 2025-10-27 支出 🏷️ 广告推广 谷歌广告 1000 USDT 未知账户
3 2025-10-27 支出 🏷️ 其他支出 爱拼才会赢 退款 273 USDT 未知账户
4 2025-10-27 支出 🏷️ 其他支出 鼎胜国际退款 140 USDT 未知账户
5 2025-10-24 支出 🏷️ 其他支出 买飞机票 142 USDT 未知账户
6 2025-10-23 支出 🏷️ 广告推广 谷歌广告费 50 USDT 未知账户
7 2025-10-22 支出 🏷️ 佣金/返佣 阿宏返佣9月 896 USDT 未知账户
8 2025-10-22 支出 🏷️ 其他支出 泰国支出 30700 USDT 未知账户
9 2025-10-20 支出 🏷️ 工资 煮饭阿姨工资 3000 USDT 未知账户
10 2025-10-18 支出 🏷️ 服务器/技术 Open AI服务器续费预存 5000 USDT 未知账户
11 2025-10-17 支出 🏷️ 服务器/技术 购买域名地址 201.61 USDT 未知账户
12 2025-10-07 支出 🏷️ 工资 虚拟卡一张 11 USDT 未知账户
13 2025-10-07 支出 🏷️ 分红 皇雨工资 11364 USDT 未知账户
14 2025-10-07 支出 🏷️ 分红 代理ip小哥工资 994 USDT 未知账户
15 2025-10-07 支出 🏷️ 分红 SY工资 4761 USDT 未知账户
16 2025-10-07 支出 🏷️ 分红 菲菲 1918 USDT 未知账户
17 2025-10-07 支出 🏷️ 分红 cp工资 1000 USDT 未知账户
18 2025-10-07 支出 🏷️ 未分类支出 羽琦返佣 2960 USDT 未知账户
19 2025-10-07 支出 🏷️ 未分类支出 666返佣 230 USDT 未知账户
20 2025-10-06 支出 🏷️ 未分类支出 金返佣 815 USDT 未知账户
21 2025-10-05 支出 🏷️ 工资 5张esim卡续费预充值 203 USDT 未知账户
22 2025-10-04 支出 🏷️ 未分类支出 合鑫返佣 285 USDT 未知账户
23 2025-10-04 支出 🏷️ 未分类支出 无名返佣 2023 USDT 未知账户
24 2025-10-04 支出 🏷️ 未分类支出 胖兔返佣 3134 USDT 未知账户
25 2025-10-04 支出 🏷️ 未分类支出 恋哥返佣 271 USDT 未知账户
26 2025-10-04 支出 🏷️ 未分类支出 方向返佣 162 USDT 未知账户
27 2025-10-03 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
28 2025-10-03 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
29 2025-10-03 支出 🏷️ 分红 香缇卡工资 1122 USDT 未知账户
30 2025-10-03 支出 🏷️ 分红 龙腾集团转给天天 11560 USDT 未知账户
31 2025-10-03 支出 🏷️ 服务器/技术 龙腾借走 7000 USDT 未知账户
32 2025-10-03 支出 🏷️ 借款/转账 泰国支出的费用 6221 USDT 未知账户
33 2025-10-03 支出 🏷️ 未分类支出 杰夫返佣 1476 USDT 未知账户
34 2025-10-03 支出 🏷️ 分红 天天8月报销 4649 USDT 未知账户
35 2025-10-03 支出 🏷️ 分红 天天9月报销 931 USDT 未知账户
36 2025-10-03 支出 🏷️ 未分类支出 国哥返佣(8月和9月) 60 USDT 未知账户
37 2025-10-03 支出 🏷️ 未分类支出 市场经理返佣 1388 USDT 未知账户
38 2025-10-03 支出 🏷️ 未分类支出 天龙返佣 8530 USDT 未知账户
39 2025-10-02 支出 🏷️ 借款/转账 后勤大叔一个半月薪资 710 USDT 未知账户
40 2025-10-02 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
41 2025-10-02 支出 🏷️ 分红 助理OAC工资 1500 USDT 未知账户
42 2025-10-02 支出 🏷️ 借款/转账 小江江 500 USDT 未知账户
43 2025-10-02 支出 🏷️ 借款/转账 程程 500 USDT 未知账户
44 2025-10-02 支出 🏷️ 未分类支出 绿豆汤返佣 849 USDT 未知账户
45 2025-10-02 支出 🏷️ 未分类支出 OAC返佣 1000 USDT 未知账户
46 2025-09-30 支出 🏷️ 其他支出 合源公司退款 247 USDT 未知账户
47 2025-09-30 支出 🏷️ 未分类支出 Jack帅哥返佣 536 USDT 未知账户
48 2025-09-28 支出 🏷️ 其他支出 三喜团队退款 500 USDT 未知账户
49 2025-09-28 支出 🏷️ 其他支出 爱拼才会赢 退款 265 USDT 未知账户
50 2025-09-27 支出 🏷️ 分红 龙腾转给天天 1100 USDT 未知账户
51 2025-09-25 支出 🏷️ 服务器/技术 马来西亚(龙腾月底转回来) 1500 USDT 未知账户
52 2025-09-23 支出 🏷️ 佣金/返佣 服务器续费 169.01 USDT 未知账户
53 2025-09-20 支出 🏷️ 退款 电脑 3550*2=7100 显示器3600*7=25200 笔记本电脑 78500*1=78500 合计:110800元 15873 USDT 未知账户
54 2025-09-20 支出 🏷️ 佣金/返佣 服务器续费预存 5000 USDT 未知账户
55 2025-09-17 支出 🏷️ 借款/转账 买2000TRX 737.424 USDT 未知账户
56 2025-09-17 支出 🏷️ 借款/转账 自动激活地址购买TRX 171 USDT 未知账户
57 2025-09-12 支出 🏷️ 未分类支出 阿宏返佣 384 USDT 未知账户
58 2025-09-06 支出 🏷️ 佣金/返佣 cursor 40 USDT 未知账户
59 2025-09-06 支出 🏷️ 佣金/返佣 服务器59u+128u 187 USDT 未知账户
60 2025-09-06 支出 🏷️ 佣金/返佣 google翻译 957 USDT 未知账户
61 2025-09-06 支出 🏷️ 佣金/返佣 openrouter 210u+210u 420 USDT 未知账户
62 2025-09-06 支出 🏷️ 佣金/返佣 Claude code 250 USDT 未知账户
63 2025-09-06 支出 🏷️ 借款/转账 泰国支出的费用 6289 USDT 未知账户
64 2025-09-06 支出 🏷️ 借款/转账 Funstat 开通镜像 4.11 USDT 未知账户
65 2025-09-06 支出 🏷️ 未分类支出 666返佣 233 USDT 未知账户
66 2025-09-06 支出 🏷️ 未分类支出 合鑫返佣 375 USDT 未知账户
67 2025-09-06 支出 🏷️ 未分类支出 恋哥返佣 309 USDT 未知账户
68 2025-09-06 支出 🏷️ 未分类支出 方向返佣 214 USDT 未知账户
69 2025-09-06 支出 🏷️ 未分类支出 市场经理返佣 708 USDT 未知账户
70 2025-09-06 支出 🏷️ 分红 皇雨返佣 1208 USDT 未知账户
71 2025-09-06 支出 🏷️ 未分类支出 乐乐返佣 166 USDT 未知账户
72 2025-09-06 支出 🏷️ 未分类支出 pt返佣 965 USDT 未知账户
73 2025-09-05 支出 🏷️ 佣金/返佣 Open Ai服务器续费预存 5000 USDT 未知账户
74 2025-09-05 支出 🏷️ 其他支出 星链宇宙退款 77 USDT 未知账户
75 2025-09-04 支出 🏷️ 分红 超鹏工资 452 USDT 未知账户
76 2025-09-04 支出 🏷️ 分红 小白工资 387 USDT 未知账户
77 2025-09-04 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
78 2025-09-04 支出 🏷️ 分红 助理OAC工资 1500 USDT 未知账户
79 2025-09-04 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
80 2025-09-04 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
81 2025-09-04 支出 🏷️ 分红 香缇卡工资 1122 USDT 未知账户
82 2025-09-04 支出 🏷️ 借款/转账 小江江 500 USDT 未知账户
83 2025-09-04 支出 🏷️ 借款/转账 程程 500 USDT 未知账户
84 2025-09-04 支出 🏷️ 分红 皇雨工资 11332 USDT 未知账户
85 2025-09-04 支出 🏷️ 分红 代理ip小哥工资 992 USDT 未知账户
86 2025-09-04 支出 🏷️ 分红 SY工资 4750 USDT 未知账户
87 2025-09-04 支出 🏷️ 未分类支出 杰夫返佣 845 USDT 未知账户
88 2025-09-04 支出 🏷️ 未分类支出 老虎返佣 46 USDT 未知账户
89 2025-08-31 支出 🏷️ 分红 龙腾集团转给天天 14265 USDT 未知账户
90 2025-08-31 支出 🏷️ 其他支出 Jack帅哥退款 320 USDT 未知账户
91 2025-08-31 支出 🏷️ 未分类支出 Jack帅哥返佣 380 USDT 未知账户
92 2025-08-31 支出 🏷️ 未分类支出 绿豆汤返佣 460 USDT 未知账户
93 2025-08-31 支出 🏷️ 其他支出 英才团队退款 569 USDT 未知账户
94 2025-08-31 支出 🏷️ 其他支出 天一退款 21 USDT 未知账户
95 2025-08-31 支出 🏷️ 未分类支出 OAC返佣 538 USDT 未知账户
96 2025-08-31 支出 🏷️ 未分类支出 金返佣 470 USDT 未知账户
97 2025-08-31 支出 🏷️ 未分类支出 天龙返佣 11261 USDT 未知账户
98 2025-08-31 支出 🏷️ 未分类支出 胖兔返佣 3225 USDT 未知账户
99 2025-08-31 支出 🏷️ 未分类支出 羽琦返佣 2620 USDT 未知账户
100 2025-08-31 支出 🏷️ 未分类支出 无名返佣 2531 USDT 未知账户
101 2025-08-30 支出 🏷️ 其他支出 三喜团队退款 1000 USDT 未知账户
102 2025-08-28 支出 🏷️ 服务器/技术 柬埔寨出差费用 3000 USDT 未知账户
103 2025-08-24 支出 🏷️ 佣金/返佣 服务器续费 169 USDT 未知账户
104 2025-08-22 支出 🏷️ 其他支出 爱拼才会赢 退款 103 USDT 未知账户
105 2025-08-21 支出 🏷️ 佣金/返佣 新OpenAi充值 1028 USDT 未知账户
106 2025-08-14 支出 🏷️ 佣金/返佣 7月 服务器 59u + 128u 187 USDT 未知账户
107 2025-08-14 支出 🏷️ 佣金/返佣 7月 google 翻译 1051u 1051 USDT 未知账户
108 2025-08-14 支出 🏷️ 佣金/返佣 7月 openrouter 105u + 105u + 105u 315 USDT 未知账户
109 2025-08-14 支出 🏷️ 佣金/返佣 7月 Claude code 250u 250 USDT 未知账户
110 2025-08-14 支出 🏷️ 佣金/返佣 7月 cursor 131u 131 USDT 未知账户
111 2025-08-14 支出 🏷️ 分红 代理ip小哥工资 990 USDT 未知账户
112 2025-08-14 支出 🏷️ 分红 SY工资 4744 USDT 未知账户
113 2025-08-14 支出 🏷️ 分红 皇雨工资 11316 USDT 未知账户
114 2025-08-14 支出 🏷️ 分红 7月 皇雨返佣 847 USDT 未知账户
115 2025-08-14 支出 🏷️ 其他支出 新阿金公司退款 232 USDT 未知账户
116 2025-08-12 支出 🏷️ 服务器/技术 转给阿寒 16199 USDT 未知账户
117 2025-08-10 支出 🏷️ 佣金/返佣 Open AI 5000 USDT 未知账户
118 2025-08-07 支出 🏷️ 未分类支出 金返佣(6月和7月) 305 USDT 未知账户
119 2025-08-07 支出 🏷️ 其他支出 兰博基尼退款 76 USDT 未知账户
120 2025-08-06 支出 🏷️ 未分类支出 乐乐返佣 166 USDT 未知账户
121 2025-08-06 支出 🏷️ 未分类支出 阿宏返佣(6月和7月) 2290 USDT 未知账户
122 2025-08-06 支出 🏷️ 未分类支出 恋哥返佣 326 USDT 未知账户
123 2025-08-02 支出 🏷️ 借款/转账 泰国的费用 6400 USDT 未知账户
124 2025-08-02 支出 🏷️ 未分类支出 市场经理返佣 390 USDT 未知账户
125 2025-08-02 支出 🏷️ 未分类支出 无名返佣 2267 USDT 未知账户
126 2025-08-02 支出 🏷️ 未分类支出 兔子返佣 112 USDT 未知账户
127 2025-08-01 支出 🏷️ 服务器/技术 龙腾集团 9792 USDT 未知账户
128 2025-08-01 支出 🏷️ 佣金/返佣 服务器续费预存 5000 USDT 未知账户
129 2025-08-01 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
130 2025-08-01 支出 🏷️ 分红 助理OAC工资 1000 USDT 未知账户
131 2025-08-01 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
132 2025-08-01 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
133 2025-08-01 支出 🏷️ 分红 香缇卡工资 1122 USDT 未知账户
134 2025-08-01 支出 🏷️ 其他支出 盛天退款 130 USDT 未知账户
135 2025-08-01 支出 🏷️ 未分类支出 Jack帅哥佣金 1297 USDT 未知账户
136 2025-08-01 支出 🏷️ 未分类支出 OAC00返佣 550 USDT 未知账户
137 2025-08-01 支出 🏷️ 未分类支出 方向返佣 199 USDT 未知账户
138 2025-08-01 支出 🏷️ 未分类支出 天龙返佣 10263 USDT 未知账户
139 2025-08-01 支出 🏷️ 未分类支出 合鑫返佣 315 USDT 未知账户
140 2025-08-01 支出 🏷️ 未分类支出 绿豆汤返佣 826 USDT 未知账户
141 2025-08-01 支出 🏷️ 未分类支出 胖兔返佣 3646 USDT 未知账户
142 2025-08-01 支出 🏷️ 未分类支出 羽琦返佣 2400 USDT 未知账户
143 2025-08-01 支出 🏷️ 未分类支出 国哥返佣 60 USDT 未知账户
144 2025-08-01 支出 🏷️ 未分类支出 杰夫返佣 1551 USDT 未知账户
145 2025-07-20 支出 🏷️ 佣金/返佣 服务器续费(人民币1200) 168.3 USDT 未知账户
146 2025-07-16 支出 🏷️ 其他支出 左岸退款 34.7 USDT 未知账户
147 2025-07-12 支出 🏷️ 佣金/返佣 Open Ai服务器续费预存 5000 USDT 未知账户
148 2025-07-09 支出 🏷️ 未分类支出 方向返佣 383 USDT 未知账户
149 2025-07-07 支出 🏷️ 借款/转账 鑫晟公司5月3600u ,6月2880u 6480 USDT 未知账户
150 2025-07-05 支出 🏷️ 借款/转账 买trx 2000 610.2 USDT 未知账户
151 2025-07-05 支出 🏷️ 分红 代理ip小哥工资 990 USDT 未知账户
152 2025-07-05 支出 🏷️ 分红 SY工资 4743 USDT 未知账户
153 2025-07-05 支出 🏷️ 分红 皇雨工资 11316 USDT 未知账户
154 2025-07-05 支出 💰 未分类收入 蚊子分红 30000 USDT 未知账户
155 2025-07-05 支出 💰 未分类收入 阿寒分红 30000 USDT 未知账户
156 2025-07-04 支出 🏷️ 未分类支出 胖兔返佣 2760 USDT 未知账户
157 2025-07-04 支出 🏷️ 未分类支出 羽琦返佣 2220 USDT 未知账户
158 2025-07-03 支出 🏷️ 服务器/技术 龙腾集团(15077) 12397 USDT 未知账户
159 2025-07-03 支出 🏷️ 未分类支出 乐乐返佣 83 USDT 未知账户
160 2025-07-03 支出 🏷️ 未分类支出 合鑫返佣 420 USDT 未知账户
161 2025-07-01 支出 🏷️ 佣金/返佣 服务器(58u+128u) 186 USDT 未知账户
162 2025-07-01 支出 🏷️ 佣金/返佣 google 翻译 1032 USDT 未知账户
163 2025-07-01 支出 🏷️ 佣金/返佣 openRouter 105u + 50u 155 USDT 未知账户
164 2025-07-01 支出 🏷️ 佣金/返佣 Claude code 250u + 5% 手续费 262.5 USDT 未知账户
165 2025-07-01 支出 🏷️ 佣金/返佣 cursor 40u + 13.8u + 3.7u 57.5 USDT 未知账户
166 2025-07-01 支出 🏷️ 佣金/返佣 iphone16 pro max 工作机 1676 USDT 未知账户
167 2025-07-01 支出 🏷️ 未分类支出 无名返佣 1790 USDT 未知账户
168 2025-07-01 支出 🏷️ 未分类支出 恋哥返佣 366 USDT 未知账户
169 2025-07-01 支出 🏷️ 未分类支出 OAC00返佣 350 USDT 未知账户
170 2025-07-01 支出 🏷️ 未分类支出 天龙返佣 6293 USDT 未知账户
171 2025-07-01 支出 🏷️ 未分类支出 绿豆汤返佣 723 USDT 未知账户
172 2025-07-01 支出 🏷️ 分红 皇雨返佣 656 USDT 未知账户
173 2025-06-30 支出 🏷️ 佣金/返佣 chatgpt 1个23u开5个 115 USDT 未知账户
174 2025-06-30 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
175 2025-06-30 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
176 2025-06-30 支出 🏷️ 分红 香缇卡工资 1122 USDT 未知账户
177 2025-06-30 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
178 2025-06-30 支出 🏷️ 分红 助理OAC工资 1000 USDT 未知账户
179 2025-06-30 支出 🏷️ 未分类支出 Jack帅哥佣金 947 USDT 未知账户
180 2025-06-30 支出 🏷️ 未分类支出 杰夫返佣 1095 USDT 未知账户
181 2025-06-23 支出 🏷️ 佣金/返佣 服务器续费(人民币1200) 167.59 USDT 未知账户
182 2025-06-21 支出 🏷️ 其他支出 达摩团队退 390 USDT 未知账户
183 2025-06-21 支出 🏷️ 佣金/返佣 服务器续费 5000 USDT 未知账户
184 2025-06-16 支出 🏷️ 未分类支出 胖兔返佣 1764 USDT 未知账户
185 2025-06-16 支出 🏷️ 未分类支出 羽琦返佣 1580 USDT 未知账户
186 2025-06-09 支出 🏷️ 分红 皇雨买号测试软件 102 USDT 未知账户
187 2025-06-09 支出 🏷️ 分红 香缇卡买号测试软件 65 USDT 未知账户
188 2025-06-09 支出 🏷️ 未分类支出 阿宏返佣 1846 USDT 未知账户
189 2025-06-08 支出 🏷️ 服务器/技术 测试买控的 50 USDT 未知账户
190 2025-06-08 支出 🏷️ 未分类支出 金返佣 220 USDT 未知账户
191 2025-06-07 支出 🏷️ 分红 皇雨工资 11300 USDT 未知账户
192 2025-06-07 支出 🏷️ 分红 代理ip小哥工资 989 USDT 未知账户
193 2025-06-07 支出 🏷️ 分红 SY工资 4738 USDT 未知账户
194 2025-06-07 支出 🏷️ 服务器/技术 泰国房租和换现金 9290 USDT 未知账户
195 2025-06-05 支出 🏷️ 佣金/返佣 openai 1250 USDT 未知账户
196 2025-06-04 支出 🏷️ 分红 皇雨返佣 850 USDT 未知账户
197 2025-06-04 支出 🏷️ 未分类支出 4月 小树返佣 36 USDT 未知账户
198 2025-06-03 支出 🏷️ 服务器/技术 龙腾集团(计14295u)+3400=17695 14095 USDT 未知账户
199 2025-06-03 支出 🏷️ 佣金/返佣 开通企业版chatgpt 1652 USDT 未知账户
200 2025-06-03 支出 💰 未分类收入 蚊子分红 15000 USDT 未知账户
201 2025-06-03 支出 💰 未分类收入 阿寒分红 15000 USDT 未知账户
202 2025-06-02 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
203 2025-06-02 支出 🏷️ 分红 香缇卡工资 1101 USDT 未知账户
204 2025-06-02 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
205 2025-06-02 支出 🏷️ 分红 助理OAC工资 1000 USDT 未知账户
206 2025-06-02 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
207 2025-06-02 支出 🏷️ 佣金/返佣 google翻译接口的费用 (取整) 1013 USDT 未知账户
208 2025-06-02 支出 🏷️ 佣金/返佣 openRouter 充值 100 USDT 未知账户
209 2025-06-02 支出 🏷️ 佣金/返佣 服务器费用 188 USDT 未知账户
210 2025-06-02 支出 🏷️ 佣金/返佣 cursor费用 64 USDT 未知账户
211 2025-06-02 支出 🏷️ 未分类支出 杰夫返佣 330 USDT 未知账户
212 2025-06-02 支出 🏷️ 未分类支出 天龙返佣 8542 USDT 未知账户
213 2025-06-02 支出 🏷️ 未分类支出 无名返佣 2103 USDT 未知账户
214 2025-06-02 支出 🏷️ 未分类支出 恋哥返佣 480 USDT 未知账户
215 2025-06-02 支出 🏷️ 未分类支出 OAC00返佣 586 USDT 未知账户
216 2025-06-02 支出 🏷️ 未分类支出 乐乐返佣 291 USDT 未知账户
217 2025-06-02 支出 🏷️ 未分类支出 国哥返佣 30 USDT 未知账户
218 2025-06-02 支出 🏷️ 未分类支出 合鑫返佣 360 USDT 未知账户
219 2025-06-01 支出 🏷️ 未分类支出 绿豆汤返佣 973 USDT 未知账户
220 2025-05-31 支出 🏷️ 其他支出 Jack帅哥余额退 619 USDT 未知账户
221 2025-05-31 支出 🏷️ 未分类支出 Jack帅哥返佣 1033 USDT 未知账户
222 2025-05-24 支出 🏷️ 服务器/技术 投资款 20000 USDT 未知账户
223 2025-05-21 支出 🏷️ 服务器/技术 小树保关 165 USDT 未知账户
224 2025-05-21 支出 🏷️ 佣金/返佣 服务器续费(人民币1200) 167 USDT 未知账户
225 2025-05-17 支出 🏷️ 佣金/返佣 硅基流动 ai 重排序接口充值 2000人民币 278 USDT 未知账户
226 2025-05-13 支出 🏷️ 未分类支出 羽琦返佣(3月 1395u+4月 1260u) 2655 USDT 未知账户
227 2025-05-13 支出 🏷️ 未分类支出 金返佣 200 USDT 未知账户
228 2025-05-12 支出 🏷️ 佣金/返佣 服务器续费 5000 USDT 未知账户
229 2025-05-09 支出 🏷️ 借款/转账 换泰珠 3058 USDT 未知账户
230 2025-05-08 支出 🏷️ 分红 天天返佣 2191.5 USDT 未知账户
231 2025-05-08 支出 🏷️ 分红 天天投流报销 1488 USDT 未知账户
232 2025-05-08 支出 🏷️ 未分类支出 胖兔返佣 2062.5 USDT 未知账户
233 2025-05-05 支出 🏷️ 其他支出 KM 退款 71 USDT 未知账户
234 2025-05-04 支出 🏷️ 未分类支出 合鑫返佣 435 USDT 未知账户
235 2025-05-04 支出 🏷️ 未分类支出 乐乐返佣 177 USDT 未知账户
236 2025-05-03 支出 🏷️ 工资 cloudflare 防火墙 165.5 USDT 未知账户
237 2025-05-03 支出 🏷️ 佣金/返佣 chatgpt pro 200 USDT 未知账户
238 2025-05-03 支出 🏷️ 佣金/返佣 cursor 320 USDT 未知账户
239 2025-05-03 支出 🏷️ 佣金/返佣 openrouter 121 USDT 未知账户
240 2025-05-03 支出 🏷️ 佣金/返佣 bolt.new 500 USDT 未知账户
241 2025-05-03 支出 🏷️ 佣金/返佣 openai 911.8 USDT 未知账户
242 2025-05-03 支出 🏷️ 工资 tg会员 36 USDT 未知账户
243 2025-05-03 支出 🏷️ 分红 chatwoot客服 19 USDT 未知账户
244 2025-05-03 支出 🏷️ 工资 uizard 19 USDT 未知账户
245 2025-05-03 支出 💰 未分类收入 蚊子分红 20000 USDT 未知账户
246 2025-05-03 支出 💰 未分类收入 阿寒分红 20000 USDT 未知账户
247 2025-05-02 支出 🏷️ 服务器/技术 租办公室 500 USDT 未知账户
248 2025-05-02 支出 🏷️ 分红 SY工资 4127 USDT 未知账户
249 2025-05-02 支出 🏷️ 分红 皇雨工资 11005 USDT 未知账户
250 2025-05-02 支出 🏷️ 分红 代理ip小哥工资 963 USDT 未知账户
251 2025-05-02 支出 🏷️ 佣金/返佣 google 翻译接口 903 USDT 未知账户
252 2025-05-02 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
253 2025-05-02 支出 🏷️ 分红 香缇卡工资 1101 USDT 未知账户
254 2025-05-02 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
255 2025-05-02 支出 🏷️ 分红 助理OAC工资 1000 USDT 未知账户
256 2025-05-02 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
257 2025-05-02 支出 🏷️ 未分类支出 绿豆汤返佣 540 USDT 未知账户
258 2025-05-02 支出 🏷️ 未分类支出 国哥返佣 60 USDT 未知账户
259 2025-05-02 支出 🏷️ 未分类支出 杰夫返佣 778 USDT 未知账户
260 2025-05-02 支出 🏷️ 未分类支出 恋哥返佣 273 USDT 未知账户
261 2025-05-02 支出 🏷️ 未分类支出 天龙返佣 10531 USDT 未知账户
262 2025-05-02 支出 🏷️ 未分类支出 无名返佣 1819 USDT 未知账户
263 2025-05-02 支出 🏷️ 未分类支出 OAC00返佣 744 USDT 未知账户
264 2025-05-02 支出 🏷️ 分红 皇雨返佣 91 USDT 未知账户
265 2025-05-02 支出 🏷️ 未分类支出 杰夫返佣 778 USDT 未知账户
266 2025-05-01 支出 🏷️ 未分类支出 Jack帅哥返佣 1111 USDT 未知账户
267 2025-04-30 支出 🏷️ 借款/转账 买trx 2000 531 USDT 未知账户
268 2025-04-30 支出 🏷️ 固定资产 打流量 500 USDT 未知账户
269 2025-04-28 支出 🏷️ 服务器/技术 泰国生活换泰铢 6033 USDT 未知账户
270 2025-04-25 支出 🏷️ 服务器/技术 做 whatsapp 云控测试的 110 USDT 未知账户
271 2025-04-25 支出 🏷️ 其他支出 啊Q(meidusha001)退款 150 USDT 未知账户
272 2025-04-22 支出 🏷️ 佣金/返佣 服务器续费(人民币1200) 165 USDT 未知账户
273 2025-04-20 支出 🏷️ 分红 阿寒 皇雨 碧桂园 天天 4个人会员续费 120 USDT 未知账户
274 2025-04-19 支出 🏷️ 其他支出 致胜退款 184 USDT 未知账户
275 2025-04-14 支出 🏷️ 未分类支出 金返佣 267 USDT 未知账户
276 2025-04-13 支出 🏷️ 分红 皇雨返佣 1080 USDT 未知账户
277 2025-04-11 支出 🏷️ 佣金/返佣 服务器续费和防护扣款 5000 USDT 未知账户
278 2025-04-11 支出 🏷️ 服务器/技术 换美金 448 USDT 未知账户
279 2025-04-10 支出 🏷️ 服务器/技术 保关 360 USDT 未知账户
280 2025-04-07 支出 🏷️ 服务器/技术 泰国换泰铢 5874 USDT 未知账户
281 2025-04-07 支出 🏷️ 工资 esim plus 手机号续费预充值 204 USDT 未知账户
282 2025-04-07 支出 🏷️ 未分类支出 恋哥返佣 293 USDT 未知账户
283 2025-04-03 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
284 2025-04-03 支出 🏷️ 分红 香缇卡工资 1101 USDT 未知账户
285 2025-04-03 支出 🏷️ 未分类支出 杰夫返佣 390 USDT 未知账户
286 2025-04-03 支出 🏷️ 分红 天天返佣 1492 USDT 未知账户
287 2025-04-03 支出 💰 未分类收入 紫气东来充值(1899)5%分红 95 USDT 未知账户
288 2025-04-01 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
289 2025-04-01 支出 🏷️ 分红 助理OAC工资 1000 USDT 未知账户
290 2025-04-01 支出 🏷️ 退款 路由器费用(硬件+物流) 53 USDT 未知账户
291 2025-04-01 支出 🏷️ 佣金/返佣 google翻译接口的费用 973 USDT 未知账户
292 2025-04-01 支出 🏷️ 佣金/返佣 openRouter 充值 106 USDT 未知账户
293 2025-04-01 支出 🏷️ 佣金/返佣 2个服务器费用 188 USDT 未知账户
294 2025-04-01 支出 🏷️ 分红 SY工资 4110 USDT 未知账户
295 2025-04-01 支出 🏷️ 分红 皇雨工资 10959 USDT 未知账户
296 2025-04-01 支出 🏷️ 分红 代理ip小哥工资 959 USDT 未知账户
297 2025-04-01 支出 🏷️ 服务器/技术 租办公室 500 USDT 未知账户
298 2025-04-01 支出 🏷️ 借款/转账 买trx 2000 510 USDT 未知账户
299 2025-04-01 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
300 2025-04-01 支出 🏷️ 分红 龙腾集团费用转给天天 16867 USDT 未知账户
301 2025-04-01 支出 🏷️ 未分类支出 Jack帅哥返佣 725 USDT 未知账户
302 2025-04-01 支出 🏷️ 未分类支出 天龙返佣 11398 USDT 未知账户
303 2025-04-01 支出 🏷️ 未分类支出 闲聊返佣 420 USDT 未知账户
304 2025-04-01 支出 🏷️ 未分类支出 OAC00返佣 229 USDT 未知账户
305 2025-04-01 支出 🏷️ 未分类支出 无名返佣 1787 USDT 未知账户
306 2025-04-01 支出 🏷️ 未分类支出 绿豆汤返佣 371 USDT 未知账户
307 2025-04-01 支出 💰 未分类收入 蚊子分红 5520 USDT 未知账户
308 2025-04-01 支出 💰 未分类收入 阿寒分红 5520 USDT 未知账户
309 2025-04-01 支出 🏷️ 未分类支出 合鑫返佣 330 USDT 未知账户
310 2025-04-01 支出 🏷️ 未分类支出 A Feng 返佣 100 USDT 未知账户
311 2025-04-01 支出 🏷️ 未分类支出 胖兔返佣 2659 USDT 未知账户
312 2025-04-01 支出 🏷️ 未分类支出 乐乐返佣 151 USDT 未知账户
313 2025-03-29 支出 🏷️ 借款/转账 机器人续费 19 USDT 未知账户
314 2025-03-29 支出 💰 未分类收入 蚊子分红 10000 USDT 未知账户
315 2025-03-29 支出 💰 未分类收入 阿寒分红 10000 USDT 未知账户
316 2025-03-28 支出 🏷️ 佣金/返佣 阿里云主服务器 2100 USDT 未知账户
317 2025-03-28 支出 🏷️ 分红 皇雨买 007 测试系统 110 USDT 未知账户
318 2025-03-23 支出 🏷️ 佣金/返佣 服务器续费(人民币1200) 165.28 USDT 未知账户
319 2025-03-18 支出 🏷️ 其他支出 老莫8688 退款 44 USDT 未知账户
320 2025-03-18 支出 🏷️ 其他支出 月入10w美金 退款 480 USDT 未知账户
321 2025-03-12 支出 🏷️ 佣金/返佣 11月 open Ai 接口费用 1500 USDT 未知账户
322 2025-03-12 支出 🏷️ 佣金/返佣 2月 open Ai 接口费用 1163 USDT 未知账户
323 2025-03-12 支出 🏷️ 佣金/返佣 3月 open Ai 接口费用 713 USDT 未知账户
324 2025-03-12 支出 🏷️ 未分类支出 乐乐返佣 120 USDT 未知账户
325 2025-03-12 支出 🏷️ 分红 天天紫气东来分红5% 114 USDT 未知账户
326 2025-03-12 支出 🏷️ 未分类支出 1月阿宏返佣 1213 USDT 未知账户
327 2025-03-12 支出 🏷️ 未分类支出 2月阿宏返佣 480 USDT 未知账户
328 2025-03-08 支出 🏷️ 未分类支出 金返佣 200 USDT 未知账户
329 2025-03-06 支出 🏷️ 未分类支出 合鑫返佣 315 USDT 未知账户
330 2025-03-04 支出 🏷️ 分红 龙腾集团费用转给天天 16321 USDT 未知账户
331 2025-03-03 支出 🏷️ 未分类支出 羽琦返佣 783 USDT 未知账户
332 2025-03-02 支出 🏷️ 佣金/返佣 服务器两台 188 USDT 未知账户
333 2025-03-02 支出 🏷️ 佣金/返佣 google 翻译api的 费用 截止到 2025.02.28 1074 USDT 未知账户
334 2025-03-02 支出 🏷️ 佣金/返佣 openrouter 充值 60 USDT 未知账户
335 2025-03-02 支出 🏷️ 佣金/返佣 deepseek 52 USDT 未知账户
336 2025-03-02 支出 🏷️ 服务器/技术 租办公室 500 USDT 未知账户
337 2025-03-02 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
338 2025-03-02 支出 🏷️ 分红 香缇卡工资 1102 USDT 未知账户
339 2025-03-02 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
340 2025-03-02 支出 🏷️ 分红 助理OAC工资 786 USDT 未知账户
341 2025-03-02 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
342 2025-03-02 支出 🏷️ 分红 SY工资 2032 USDT 未知账户
343 2025-03-02 支出 🏷️ 分红 皇雨工资 8517 USDT 未知账户
344 2025-03-02 支出 🏷️ 分红 代理ip小哥工资 746 USDT 未知账户
345 2025-03-02 支出 🏷️ 佣金/返佣 广州技术 733 USDT 未知账户
346 2025-03-02 支出 🏷️ 未分类支出 绿豆汤返佣 700 USDT 未知账户
347 2025-03-01 支出 🏷️ 借款/转账 买trx 2000 502 USDT 未知账户
348 2025-03-01 支出 🏷️ 工资 小红卡续费余额不足 400 USDT 未知账户
349 2025-03-01 支出 🏷️ 未分类支出 闲聊返佣 330 USDT 未知账户
350 2025-03-01 支出 🏷️ 未分类支出 国哥返佣 150 USDT 未知账户
351 2025-03-01 支出 🏷️ 未分类支出 胖兔返佣 3129 USDT 未知账户
352 2025-03-01 支出 🏷️ 未分类支出 OAC00返佣 157 USDT 未知账户
353 2025-03-01 支出 🏷️ 未分类支出 无名返佣 1146 USDT 未知账户
354 2025-03-01 支出 🏷️ 未分类支出 辞辞返佣 181 USDT 未知账户
355 2025-03-01 支出 🏷️ 未分类支出 恋哥返佣 440 USDT 未知账户
356 2025-03-01 支出 💰 未分类收入 蚊子分红 30000 USDT 未知账户
357 2025-03-01 支出 💰 未分类收入 阿寒分红 30000 USDT 未知账户
358 2025-02-28 支出 🏷️ 借款/转账 A Feng 110 USDT 未知账户
359 2025-02-28 支出 🏷️ 未分类支出 Jack帅哥返佣 1276 USDT 未知账户
360 2025-02-28 支出 🏷️ 未分类支出 天龙返佣 9757 USDT 未知账户
361 2025-02-26 支出 🏷️ 工资 小红卡买虚拟卡 10 USDT 未知账户
362 2025-02-26 支出 🏷️ 佣金/返佣 阿里云主服务器 1980 USDT 未知账户
363 2025-02-23 支出 🏷️ 佣金/返佣 服务器续费 165 USDT 未知账户
364 2025-02-18 支出 🏷️ 其他支出 一路发 多充退款 2500 USDT 未知账户
365 2025-02-15 支出 🏷️ 服务器/技术 转给阿寒在泰国租房等等 8982 USDT 未知账户
366 2025-02-15 支出 🏷️ 未分类支出 A Feng 1月返佣 158 USDT 未知账户
367 2025-02-15 支出 🏷️ 其他支出 众彩公司退款 52 USDT 未知账户
368 2025-02-11 支出 🏷️ 佣金/返佣 1月open Ai费用 782 USDT 未知账户
369 2025-02-11 支出 🏷️ 未分类支出 乐乐1月返佣 200 USDT 未知账户
370 2025-02-10 支出 🏷️ 佣金/返佣 10月服务器续费 874.47 USDT 未知账户
371 2025-02-10 支出 🏷️ 佣金/返佣 11月服务器续费 923.42 USDT 未知账户
372 2025-02-10 支出 🏷️ 佣金/返佣 12月服务器续费 936.34 USDT 未知账户
373 2025-02-10 支出 🏷️ 佣金/返佣 2025年1月服务器续费 956 USDT 未知账户
374 2025-02-10 支出 🏷️ 分红 1月chatwoot 客服 57 USDT 未知账户
375 2025-02-10 支出 🏷️ 分红 2月chatwoot 客服 57 USDT 未知账户
376 2025-02-10 支出 🏷️ 佣金/返佣 bolt.new ai 写代码套餐开通 181.7 USDT 未知账户
377 2025-02-10 支出 🏷️ 退款 三星硬盘(1579rmb) 215.4 USDT 未知账户
378 2025-02-10 支出 🏷️ 退款 西部数据企业级氦气硬盘(12732rmb) 1737 USDT 未知账户
379 2025-02-10 支出 🏷️ 退款 绿联DXP8800Pro云硬盘(7039.72rmb) 960.4 USDT 未知账户
380 2025-02-10 支出 🏷️ 分红 香缇卡笔记本电脑(9436.49rmb) 1287.4 USDT 未知账户
381 2025-02-10 支出 🏷️ 佣金/返佣 双路渲染服务器40核(10499rmb) 1432.3 USDT 未知账户
382 2025-02-10 支出 🏷️ 借款/转账 A Feng补12月漏 50 USDT 未知账户
383 2025-02-10 支出 🏷️ 借款/转账 辞辞补1月漏 203 USDT 未知账户
384 2025-02-10 支出 🏷️ 未分类支出 羽琦返佣 770 USDT 未知账户
385 2025-02-10 支出 🏷️ 未分类支出 绿豆汤返佣 520 USDT 未知账户
386 2025-02-07 支出 🏷️ 分红 天天开工红包 257 USDT 未知账户
387 2025-02-07 支出 🏷️ 分红 碧桂园开工红包 257 USDT 未知账户
388 2025-02-07 支出 🏷️ 分红 香缇卡开工红包 257 USDT 未知账户
389 2025-02-07 支出 🏷️ 分红 财务amy开工红包 257 USDT 未知账户
390 2025-02-07 支出 🏷️ 服务器/技术 助理oac开工红包 257 USDT 未知账户
391 2025-02-07 支出 🏷️ 分红 代理小哥开工红包 257 USDT 未知账户
392 2025-02-07 支出 🏷️ 分红 皇雨开工红包 529 USDT 未知账户
393 2025-02-06 支出 🏷️ 佣金/返佣 服务器临时配置升级 充值 1000 USDT 未知账户
394 2025-02-05 支出 🏷️ 未分类支出 合鑫返佣 600 USDT 未知账户
395 2025-02-04 支出 🏷️ 其他支出 众发退款 900 USDT 未知账户
396 2025-02-04 支出 🏷️ 未分类支出 无名返佣 752 USDT 未知账户
397 2025-02-04 支出 🏷️ 未分类支出 闲聊返佣 763 USDT 未知账户
398 2025-02-03 支出 🏷️ 未分类支出 辞辞返佣 1033 USDT 未知账户
399 2025-02-03 支出 🏷️ 分红 天天紫气东来分红5% 186 USDT 未知账户
400 2025-02-02 支出 🏷️ 服务器/技术 龙腾集团 4202 USDT 未知账户
401 2025-02-02 支出 🏷️ 未分类支出 胖兔返佣 2128 USDT 未知账户
402 2025-02-02 支出 🏷️ 其他支出 启运退款 88 USDT 未知账户
403 2025-02-01 支出 🏷️ 未分类支出 天龙返佣 5632 USDT 未知账户
404 2025-01-28 支出 🏷️ 未分类支出 Jack帅哥返佣 723 USDT 未知账户
405 2025-01-25 支出 🏷️ 佣金/返佣 xiaohai0000 鸿图 20 USDT 未知账户
406 2025-01-24 支出 🏷️ 分红 amy买香港信用卡虚拟卡 10 USDT 未知账户
407 2025-01-24 支出 🏷️ 服务器/技术 蚊子 阿寒在泰国两人生活费 2497 USDT 未知账户
408 2025-01-24 支出 💰 未分类收入 蚊子分红 10000 USDT 未知账户
409 2025-01-24 支出 💰 未分类收入 阿寒分红 10000 USDT 未知账户
410 2025-01-21 支出 🏷️ 分红 皇雨工资5517 年终奖5517 11034 USDT 未知账户
411 2025-01-21 支出 🏷️ 分红 代理ip 小哥工资965 年终奖965 1930 USDT 未知账户
412 2025-01-21 支出 🏷️ 分红 天天工资1500年终奖750 2250 USDT 未知账户
413 2025-01-21 支出 🏷️ 分红 碧桂园工资1000 年终奖500 1500 USDT 未知账户
414 2025-01-21 支出 🏷️ 分红 香缇卡工资1103年终奖552 1655 USDT 未知账户
415 2025-01-21 支出 🏷️ 分红 财务amy 1500年终奖750 2250 USDT 未知账户
416 2025-01-21 支出 🏷️ 分红 助理OAC工资1000年终奖500 1500 USDT 未知账户
417 2025-01-21 支出 🏷️ 佣金/返佣 服务器续费 165.97 USDT 未知账户
418 2025-01-18 支出 🏷️ 借款/转账 买trx 2000 527.904 USDT 未知账户
419 2025-01-15 支出 🏷️ 分红 转给香缇卡买账户备用金 300 USDT 未知账户
420 2025-01-14 支出 🏷️ 分红 香缇卡买小红卡 50 USDT 未知账户
421 2025-01-14 支出 🏷️ 工资 OAC买小红卡实体卡 100 USDT 未知账户
422 2025-01-13 支出 🏷️ 分红 amy买小红卡 50 USDT 未知账户
423 2025-01-11 支出 🏷️ 分红 小哥两个月开发费用 1000 USDT 未知账户
424 2025-01-11 支出 🏷️ 借款/转账 老表对接 300 USDT 未知账户
425 2025-01-09 支出 🏷️ 分红 转给香缇卡买账户备用金 200 USDT 未知账户
426 2025-01-08 支出 🏷️ 退款 泰国买车 39358.6 USDT 未知账户
427 2025-01-03 支出 🏷️ 分红 转给天天 9000 USDT 未知账户
428 2025-01-01 支出 🏷️ 借款/转账 合鑫 570 USDT 未知账户
429 2025-01-01 支出 🏷️ 借款/转账 金鑫 26 USDT 未知账户
430 2025-01-01 支出 🏷️ 佣金/返佣 xiaohai0000 鸿图 380 USDT 未知账户
431 2025-01-01 支出 🏷️ 借款/转账 阿宏11月 1147Uu+12月1892 3039 USDT 未知账户
432 2025-01-01 支出 💰 未分类收入 蚊子分红 10000 USDT 未知账户
433 2025-01-01 支出 💰 未分类收入 阿寒分红 10000 USDT 未知账户
434 2025-01-01 支出 🏷️ 未分类支出 A Feng返佣 180 USDT 未知账户
435 2025-01-01 支出 🏷️ 未分类支出 绿豆汤返佣 500 USDT 未知账户
436 2025-01-01 支出 🏷️ 未分类支出 天龙返佣 8795 USDT 未知账户
437 2025-01-01 支出 🏷️ 未分类支出 胖兔返佣 2622.7 USDT 未知账户
438 2025-01-01 支出 🏷️ 未分类支出 无名返佣 800 USDT 未知账户
439 2025-01-01 支出 🏷️ 未分类支出 闲聊返佣 1043 USDT 未知账户
440 2025-01-01 支出 🏷️ 分红 天天散户分红 198 USDT 未知账户
441 2025-01-01 支出 🏷️ 未分类支出 乐乐返佣 414 USDT 未知账户
442 2025-01-01 支出 🏷️ 未分类支出 知青返佣 135 USDT 未知账户
443 2025-01-01 支出 🏷️ 未分类支出 恋哥返佣 526.7 USDT 未知账户
444 2025-01-01 支出 🏷️ 未分类支出 长青返佣 77 USDT 未知账户
445 2025-01-01 支出 🏷️ 未分类支出 国哥返佣 150 USDT 未知账户
446 2025-01-01 支出 🏷️ 未分类支出 羽琦返佣 419 USDT 未知账户
447 2024-12-31 支出 🏷️ 分红 皇雨工资 代理ip小哥 服务器续费128 6638 USDT 未知账户
448 2024-12-31 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
449 2024-12-31 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
450 2024-12-31 支出 🏷️ 分红 香缇卡工资 1000 USDT 未知账户
451 2024-12-31 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
452 2024-12-31 支出 🏷️ 分红 助理OAC工资 1000 USDT 未知账户
453 2024-12-31 支出 💰 未分类收入 蚊子分红 20000 USDT 未知账户
454 2024-12-31 支出 💰 未分类收入 阿寒分红 20000 USDT 未知账户
455 2024-12-31 支出 🏷️ 未分类支出 Jack帅哥返佣 842 USDT 未知账户
456 2024-12-31 支出 🏷️ 其他支出 金鑫 退款 800 USDT 未知账户
457 2024-12-30 支出 🏷️ 其他支出 金鑫退款 800 USDT 未知账户
458 2024-12-21 支出 🏷️ 服务器/技术 转龙腾 3000 USDT 未知账户
459 2024-12-21 支出 🏷️ 佣金/返佣 服务器续费 164 USDT 未知账户
460 2024-12-19 支出 🏷️ 分红 转给天天 7000 USDT 未知账户
461 2024-12-15 支出 💰 未分类收入 蚊子分红 20000 USDT 未知账户
462 2024-12-15 支出 💰 未分类收入 阿寒分红 20000 USDT 未知账户
463 2024-12-06 支出 🏷️ 分红 转给天天 5000 USDT 未知账户
464 2024-12-06 支出 🏷️ 退款 硬盘费用 1769 USDT 未知账户
465 2024-12-01 支出 🏷️ 分红 香缇卡工资 1000 USDT 未知账户
466 2024-12-01 支出 🏷️ 分红 财务Amy工资 1500 USDT 未知账户
467 2024-12-01 支出 🏷️ 分红 助理OAC工资 1000 USDT 未知账户
468 2024-12-01 支出 🏷️ 服务器/技术 龙腾集团鑫晟公司 6102 USDT 未知账户
469 2024-12-01 支出 🏷️ 分红 皇雨5579 代理ip小哥976 6555 USDT 未知账户
470 2024-12-01 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
471 2024-12-01 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
472 2024-12-01 支出 🏷️ 分红 龙腾集团转给天天 6073 USDT 未知账户
473 2024-12-01 支出 🏷️ 佣金/返佣 服务器续费专用小红卡 50 USDT 未知账户
474 2024-12-01 支出 🏷️ 分红 天天散户 172 USDT 未知账户
475 2024-12-01 支出 🏷️ 佣金/返佣 服务器续费2个月 256 USDT 未知账户
476 2024-12-01 支出 🏷️ 佣金/返佣 流量测试服务器 500 USDT 未知账户
477 2024-12-01 支出 🏷️ 退款 展示屏 805 USDT 未知账户
478 2024-12-01 支出 🏷️ 佣金/返佣 openai 12 月份接口费用 1768 USDT 未知账户
479 2024-12-01 支出 🏷️ 未分类支出 天龙返佣 9738 USDT 未知账户
480 2024-12-01 支出 🏷️ 未分类支出 绿豆汤返佣 500 USDT 未知账户
481 2024-12-01 支出 🏷️ 未分类支出 貔貅返佣 300 USDT 未知账户
482 2024-12-01 支出 🏷️ 未分类支出 恋哥返佣(713+367补10月) 1080 USDT 未知账户
483 2024-12-01 支出 🏷️ 未分类支出 无名返佣(1107+635) 1742 USDT 未知账户
484 2024-12-01 支出 🏷️ 未分类支出 知青返佣 768 USDT 未知账户
485 2024-12-01 支出 🏷️ 未分类支出 乐乐返佣 494 USDT 未知账户
486 2024-12-01 支出 🏷️ 未分类支出 合鑫返佣 615 USDT 未知账户
487 2024-12-01 支出 🏷️ 未分类支出 胖兔返佣 2601 USDT 未知账户
488 2024-11-30 支出 🏷️ 未分类支出 Jack帅哥返佣 649 USDT 未知账户
489 2024-11-29 支出 🏷️ 工资 开飞机会员 38 USDT 未知账户
490 2024-11-16 支出 🏷️ 借款/转账 3000 trx自动归集的手续费购买609.444 usdt 609.444 USDT 未知账户
491 2024-11-15 支出 🏷️ 佣金/返佣 oac 40 ai机器人40 80 USDT 未知账户
492 2024-11-10 支出 🏷️ 借款/转账 买trx 85 USDT 未知账户
493 2024-11-10 支出 🏷️ 佣金/返佣 人工智能接口费用 1590 USDT 未知账户
494 2024-11-10 支出 🏷️ 佣金/返佣 服务器费用 1326 USDT 未知账户
495 2024-11-10 支出 🏷️ 未分类支出 阿宏佣金 2505 USDT 未知账户
496 2024-11-10 支出 🏷️ 借款/转账 买自动到账地址(用于质押获得手续费) 2000 USDT 未知账户
497 2024-11-07 支出 🏷️ 服务器/技术 投资款项(6006+32934) 38940 USDT 未知账户
498 2024-11-05 支出 🏷️ 分红 转给啊寒3000美金用于天天买电脑 3000 USDT 未知账户
499 2024-11-05 支出 🏷️ 分红 给财务买苹果电脑 1499 USDT 未知账户
500 2024-11-05 支出 🏷️ 退款 蚊子工作苹果电脑 8433 USDT 未知账户
501 2024-11-04 支出 🏷️ 未分类支出 大白菜佣金 1290.5 USDT 未知账户
502 2024-11-04 支出 🏷️ 未分类支出 胖兔佣金 2942 USDT 未知账户
503 2024-11-04 支出 🏷️ 未分类支出 恋哥佣金 660 USDT 未知账户
504 2024-11-02 支出 🏷️ 未分类支出 貔貅佣金 900 USDT 未知账户
505 2024-11-01 支出 🏷️ 借款/转账 买trx 700 USDT 未知账户
506 2024-11-01 支出 🏷️ 分红 龙腾集团转给天天 9797 USDT 未知账户
507 2024-11-01 支出 🏷️ 分红 天天虚拟信用卡 50 USDT 未知账户
508 2024-11-01 支出 🏷️ 未分类支出 乐乐佣金 225 USDT 未知账户
509 2024-11-01 支出 🏷️ 未分类支出 国哥佣金 450 USDT 未知账户
510 2024-10-31 支出 🏷️ 分红 代理ip小哥 1000 USDT 未知账户
511 2024-10-31 支出 🏷️ 分红 黄雨工资 5673 USDT 未知账户
512 2024-10-31 支出 🏷️ 分红 财务 1500 USDT 未知账户
513 2024-10-31 支出 🏷️ 分红 天天 1500 USDT 未知账户
514 2024-10-31 支出 🏷️ 分红 碧桂园 1000 USDT 未知账户
515 2024-10-31 支出 🏷️ 借款/转账 卡卡提 500 USDT 未知账户
516 2024-10-31 支出 🏷️ 未分类支出 天龙佣金 9292 USDT 未知账户
517 2024-10-31 支出 🏷️ 未分类支出 核心佣金 2349 USDT 未知账户
518 2024-10-31 支出 💰 未分类收入 蚊子分红 10000 USDT 未知账户
519 2024-10-31 支出 💰 未分类收入 阿寒分红 10000 USDT 未知账户
520 2024-10-31 支出 🏷️ 未分类支出 知青佣金 818 USDT 未知账户
521 2024-10-31 支出 🏷️ 未分类支出 合鑫佣金 420 USDT 未知账户
522 2024-10-31 支出 🏷️ 分红 天天 紫气东来散户分红5% 146 USDT 未知账户
523 2024-10-30 支出 🏷️ 未分类支出 Jack帅哥佣金 700 USDT 未知账户
524 2024-10-28 支出 💰 未分类收入 阿寒分红 1000 USDT 未知账户
525 2024-10-28 支出 💰 未分类收入 蚊子分红 1000 USDT 未知账户
526 2024-10-25 支出 🏷️ 其他支出 七月退 100 USDT 未知账户
527 2024-10-22 支出 🏷️ 服务器/技术 接待 3000 USDT 未知账户
528 2024-10-19 支出 🏷️ 工资 2t u盘两个。每个203u 406 USDT 未知账户
529 2024-10-19 支出 💰 未分类收入 阿寒分红 3000 USDT 未知账户
530 2024-10-19 支出 💰 未分类收入 蚊子分红 3000 USDT 未知账户
531 2024-10-16 支出 🏷️ 工资 007购买 125 USDT 未知账户
532 2024-10-11 支出 🏷️ 未分类支出 大卫佣金 1875 USDT 未知账户
533 2024-10-09 支出 🏷️ 借款/转账 购买 trx质押产生能量 2000 USDT 未知账户
534 2024-10-09 支出 🏷️ 固定资产 汉城广告费 1000 USDT 未知账户
535 2024-10-06 支出 🏷️ 其他支出 大秦退费 310 USDT 未知账户
536 2024-10-05 支出 🏷️ 佣金/返佣 技术公司鸿泰 1768 USDT 未知账户
537 2024-10-05 支出 🏷️ 佣金/返佣 ChatGPT自建服务器半年付 479.88 USDT 未知账户
538 2024-10-05 支出 🏷️ 借款/转账 交友五个阶段提示词编写和优化外包 700 USDT 未知账户
539 2024-10-04 支出 🏷️ 佣金/返佣 ChatGPT接口费用 869 USDT 未知账户
540 2024-10-04 支出 🏷️ 佣金/返佣 备用OpenAI预充值 200 USDT 未知账户
541 2024-10-04 支出 🏷️ 佣金/返佣 备用转发接口充值 100 USDT 未知账户
542 2024-10-04 支出 🏷️ 佣金/返佣 Kt主服务器。分流服务器。自动到账服务器。oss服务器 1143 USDT 未知账户
543 2024-10-04 支出 🏷️ 未分类支出 胖兔佣金 2821 USDT 未知账户
544 2024-10-03 支出 🏷️ 分红 皇工资35000rmb 5022 USDT 未知账户
545 2024-10-03 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
546 2024-10-03 支出 🏷️ 分红 碧桂园 1000 USDT 未知账户
547 2024-10-03 支出 🏷️ 分红 amy 1500 USDT 未知账户
548 2024-10-03 支出 🏷️ 分红 代理ip小哥 1000 USDT 未知账户
549 2024-10-03 支出 🏷️ 借款/转账 截图 100 USDT 未知账户
550 2024-10-03 支出 🏷️ 佣金/返佣 技术公司 3815 USDT 未知账户
551 2024-10-03 支出 🏷️ 未分类支出 乐乐佣金 483 USDT 未知账户
552 2024-10-03 支出 💰 未分类收入 蚊子分红 593 USDT 未知账户
553 2024-10-02 支出 🏷️ 未分类支出 长青佣金 240 USDT 未知账户
554 2024-10-02 支出 🏷️ 未分类支出 合鑫佣金 450 USDT 未知账户
555 2024-10-01 支出 🏷️ 未分类支出 天龙佣金 5815 USDT 未知账户
556 2024-10-01 支出 🏷️ 未分类支出 核心佣金 2413 USDT 未知账户
557 2024-10-01 支出 🏷️ 未分类支出 三七公司佣金 189 USDT 未知账户
558 2024-09-26 支出 🏷️ 分红 天天控天费用 593 USDT 未知账户
559 2024-09-26 支出 🏷️ 借款/转账 自动到账购买2000trx 329 USDT 未知账户
560 2024-09-25 支出 🏷️ 固定资产 亚太地推开支 1550 USDT 未知账户
561 2024-09-24 支出 🏷️ 固定资产 亚太小助手投放 1500 USDT 未知账户
562 2024-09-22 支出 🏷️ 工资 processon流程图终身会员 185 USDT 未知账户
563 2024-09-21 支出 🏷️ 佣金/返佣 服务器续费 1210 USDT 未知账户
564 2024-09-20 支出 🏷️ 借款/转账 截图制作 338 USDT 未知账户
565 2024-09-19 支出 🏷️ 未分类支出 Jack帅哥佣金 276 USDT 未知账户
566 2024-09-18 支出 🏷️ 固定资产 广告费用 450 USDT 未知账户
567 2024-09-18 支出 🏷️ 工资 开飞机会员 38 USDT 未知账户
568 2024-09-13 支出 🏷️ 服务器/技术 阿鹏借出35000rmb 4943.5 USDT 未知账户
569 2024-09-13 支出 🏷️ 退款 rog电脑购买 5659 USDT 未知账户
570 2024-09-11 支出 🏷️ 未分类支出 羽琦佣金 154 USDT 未知账户
571 2024-09-10 支出 🏷️ 固定资产 广告费 1000 USDT 未知账户
572 2024-09-03 支出 🏷️ 其他支出 大秦退费 300 USDT 未知账户
573 2024-09-03 支出 🏷️ 工资 飞机会员续费 35 USDT 未知账户
574 2024-09-01 支出 🏷️ 未分类支出 老外 大卫佣金 2250 USDT 未知账户
575 2024-09-01 支出 🏷️ 未分类支出 天龙佣金 6943.9 USDT 未知账户
576 2024-09-01 支出 🏷️ 未分类支出 大卫5月的佣金 900 USDT 未知账户
577 2024-08-31 支出 🏷️ 分红 天天控天费用 2207 USDT 未知账户
578 2024-08-31 支出 🏷️ 佣金/返佣 nat转发包年 280 USDT 未知账户
579 2024-08-31 支出 🏷️ 未分类支出 长青佣金 377 USDT 未知账户
580 2024-08-31 支出 💰 未分类收入 蚊子同比例分红 2207 USDT 未知账户
581 2024-08-31 支出 🏷️ 未分类支出 Jack帅哥佣金 456 USDT 未知账户
582 2024-08-31 支出 🏷️ 未分类支出 乐乐佣金 440 USDT 未知账户
583 2024-08-30 支出 🏷️ 佣金/返佣 宝塔会员 203 USDT 未知账户
584 2024-08-30 支出 🏷️ 未分类支出 核心佣金 3103 USDT 未知账户
585 2024-08-27 支出 🏷️ 退款 买车定金 2000 USDT 未知账户
586 2024-08-27 支出 🏷️ 退款 买车尾款 16562 USDT 未知账户
587 2024-08-27 支出 🏷️ 佣金/返佣 技术信用卡 50 USDT 未知账户
588 2024-08-27 支出 🏷️ 分红 天天工资 1500 USDT 未知账户
589 2024-08-27 支出 🏷️ 分红 碧桂园工资 1000 USDT 未知账户
590 2024-08-27 支出 🏷️ 分红 皇工资 5000 USDT 未知账户
591 2024-08-27 支出 🏷️ 分红 财务客服 1500 USDT 未知账户
592 2024-08-27 支出 🏷️ 分红 代理ip技术 1000 USDT 未知账户
593 2024-08-27 支出 🏷️ 佣金/返佣 人工智能接口 700 USDT 未知账户
594 2024-08-27 支出 🏷️ 借款/转账 处理员工一起出 10000 USDT 未知账户
595 2024-08-27 支出 🏷️ 借款/转账 外星人一起出4.8w 6571 USDT 未知账户
596 2024-08-27 支出 🏷️ 服务器/技术 啊杰借的10000 1404 USDT 未知账户
597 2024-08-27 支出 🏷️ 固定资产 群发广告 300 USDT 未知账户
598 2024-08-27 支出 🏷️ 借款/转账 网络攻击买服务 800 USDT 未知账户
599 2024-08-27 支出 🏷️ 未分类支出 老练几个月佣金 1586 USDT 未知账户
600 2024-08-27 支出 🏷️ 未分类支出 胖兔佣金 3597 USDT 未知账户
601 2024-08-07 支出 🏷️ 借款/转账 攻击 60 USDT 未知账户
602 2024-08-07 支出 🏷️ 佣金/返佣 其他翻译测试 58 USDT 未知账户
603 2024-08-07 支出 🏷️ 佣金/返佣 佣金 80 USDT 未知账户
604 2024-08-07 支出 🏷️ 佣金/返佣 乐乐佣金 343 USDT 未知账户
605 2024-08-07 支出 🏷️ 佣金/返佣 佣金 823.5 USDT 未知账户
606 2024-08-07 支出 🏷️ 退款 退款 170.71 USDT 未知账户
607 2024-08-07 支出 🏷️ 退款 退款 70 USDT 未知账户
608 2024-08-03 支出 🏷️ 分红 啊寒分红 3000 USDT 未知账户
609 2024-08-03 支出 🏷️ 分红 蚊子分红 3000 USDT 未知账户
610 2024-08-03 支出 🏷️ 佣金/返佣 长青佣金 326 USDT 未知账户
611 2024-08-03 支出 🏷️ 佣金/返佣 阿宏佣金 311 USDT 未知账户
612 2024-06-15 支出 未分类 6月测试交易 50 USDT 未知账户
613 2024-06-15 支出 未分类 6月测试交易 50 USDT 未知账户
614 2024-06-15 支出 未分类 6月测试交易 50 USDT 未知账户
615 2024-06-15 支出 未分类 6月测试交易 50 USDT 未知账户
616 2025-10-30 支出 🏷️ 未分类 买飞机号 213 USDT 乐乐用
617 2025-10-31 支出 🏷️ 未分类 公司的外网专线费用 211 USDT cp
618 2025-10-31 支出 🏷️ 未分类 强耀科技退款 19 USDT 未知账户
619 2025-11-01 支出 🏷️ 未分类 阿金公司退款 186 USDT 未知账户
620 2025-11-01 支出 🏷️ 未分类 小白工资 1000 USDT 未知账户
621 2025-11-01 支出 🏷️ 未分类 cp工资 1000 USDT 未知账户
622 2025-11-01 支出 🏷️ 未分类 菲菲工资 2344 USDT 16500按7.04
623 2025-11-02 支出 🏷️ 未分类 绿豆汤返佣 99 USDT 未知账户
624 2025-11-02 支出 🏷️ 未分类 OAC返佣 972 USDT 未知账户
625 2025-11-02 支出 🏷️ 未分类 天龙返佣 10556 USDT 未知账户
626 2025-11-02 支出 🏷️ 未分类 Jack帅哥返佣 506 USDT 未知账户
627 2025-11-02 支出 🏷️ 未分类 无名返佣 1655 USDT 未知账户
628 2025-11-02 支出 🏷️ 未分类 方向返佣 89 USDT 未知账户
629 2025-11-02 支出 🏷️ 未分类 阿泰会员 30 USDT 天天
630 2025-11-02 支出 🏷️ 未分类 香缇卡会员 30 USDT 未知账户
631 2025-11-02 支出 🏷️ 未分类 虚拟卡 100 USDT 未知账户
632 2025-11-02 支出 🏷️ 未分类 代理ip 15 USDT 未知账户
633 2025-11-02 支出 🏷️ 未分类 服务器 540 USDT 未知账户
634 2025-11-02 支出 🏷️ 未分类 域名 15 USDT 未知账户
635 2025-11-02 支出 🏷️ 未分类 宝金出海会员 30 USDT 未知账户
636 2025-11-02 支出 🏷️ 未分类 网盘会员 42.5 USDT 未知账户
637 2025-11-02 支出 🏷️ 未分类 水电宽带 65 USDT 未知账户
638 2025-11-02 支出 🏷️ 未分类 硬盘 68 USDT 未知账户
639 2025-11-02 支出 🏷️ 未分类 cpcc会员 253.5 USDT 未知账户
640 2025-11-02 支出 🏷️ 未分类 香缇卡流量卡 153 USDT 未知账户
641 2025-11-02 支出 🏷️ 未分类 杰夫返佣 1055 USDT 未知账户
642 2025-11-02 支出 🏷️ 未分类 天天工资 1500 USDT 未知账户
643 2025-11-02 支出 🏷️ 未分类 碧桂园工资 1000 USDT 未知账户
644 2025-11-02 支出 🏷️ 未分类 香缇卡工资 1146 USDT 未知账户
645 2025-11-02 支出 🏷️ 未分类 龙腾集团 7700 USDT 14700扣10月龙腾借7000 鑫晟公司2480未结算
646 2025-11-04 支出 🏷️ 未分类 羽琦返佣 2960 USDT 未知账户
647 2025-11-04 支出 🏷️ 未分类 皇雨工资 11364 USDT 80000元按7.04
648 2025-11-04 支出 🏷️ 未分类 代理ip小哥工资 994 USDT 7000元按7.04
649 2025-11-04 支出 🏷️ 未分类 SY工资 4761 USDT (4261+500)30000元按7.04
650 2025-11-04 支出 🏷️ 未分类 财务Amy工资 1500 USDT 未知账户
651 2025-11-04 支出 🏷️ 未分类 助理OAC工资 1500 USDT 未知账户
652 2025-11-04 支出 🏷️ 未分类 煮饭阿姨工资 426 USDT 未知账户
653 2025-11-04 支出 🏷️ 未分类 李涛工资 578 USDT 未知账户
654 2025-11-04 支出 🏷️ 未分类 胖兔返佣 3414 USDT 未知账户
655 2025-11-04 支出 🏷️ 未分类 合鑫返佣 105 USDT 未知账户
656 2025-11-04 支出 🏷️ 未分类 恋哥返佣 187 USDT 未知账户
657 2025-11-05 支出 🏷️ 未分类 阿宏返佣 815 USDT 825u (10u换trx)
658 2025-11-05 支出 🏷️ 未分类 666返佣 270 USDT 未知账户

View File

@@ -69,6 +69,33 @@ sudo docker-compose down || true
echo "🚀 构建并启动新容器..."
sudo docker-compose up -d --build
# 等待PostgreSQL就绪
echo "⏳ 等待PostgreSQL就绪..."
POSTGRES_READY=0
for i in {1..10}; do
if sudo docker-compose exec -T postgres pg_isready -U kt_financial -d kt_financial > /dev/null 2>&1; then
echo "✅ PostgreSQL 已就绪"
POSTGRES_READY=1
break
fi
echo " 第${i}次重试..."
sleep 3
done
if [ "$POSTGRES_READY" -ne 1 ]; then
echo "❌ PostgreSQL 未在预期时间内就绪"
exit 1
fi
# 导入数据
echo "📦 导入财务数据..."
sudo docker-compose exec -T kt-financial \
bash -lc "pnpm --filter @vben/backend import:data -- --csv /app/data/finance/finance-combined.csv --year 2025"
# 验证数据条数
echo "🔢 检查交易记录条数..."
sudo docker-compose exec -T postgres \
psql -U kt_financial -d kt_financial -c "SELECT COUNT(*) AS transaction_count FROM finance_transactions;"
# 清理旧镜像
echo "🧹 清理旧镜像..."
sudo docker image prune -f

View File

@@ -1,23 +1,54 @@
version: '3.8'
services:
postgres:
image: postgres:16-alpine
container_name: kt-financial-postgres
restart: unless-stopped
environment:
- POSTGRES_DB=kt_financial
- POSTGRES_USER=kt_financial
- POSTGRES_PASSWORD=kt_financial_pwd
- TZ=Asia/Shanghai
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U kt_financial -d kt_financial']
interval: 10s
timeout: 5s
retries: 6
networks:
- kt-network
kt-financial:
build:
context: .
dockerfile: Dockerfile
container_name: kt-financial-system
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
ports:
- "8080:80"
environment:
- NODE_ENV=production
- TZ=Asia/Shanghai
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
- POSTGRES_DB=kt_financial
- POSTGRES_USER=kt_financial
- POSTGRES_PASSWORD=kt_financial_pwd
volumes:
- ./logs:/var/log
- ./storage/backend:/app/apps/backend/storage
- ./data:/app/data:ro
networks:
- kt-network
networks:
kt-network:
driver: bridge
volumes:
postgres-data:

144
pnpm-lock.yaml generated
View File

@@ -631,15 +631,15 @@ importers:
'@faker-js/faker':
specifier: 'catalog:'
version: 9.9.0
better-sqlite3:
specifier: 9.5.0
version: 9.5.0
jsonwebtoken:
specifier: 'catalog:'
version: 9.0.2
nitropack:
specifier: 'catalog:'
version: 2.12.9(better-sqlite3@9.5.0)
pg:
specifier: ^8.12.0
version: 8.16.3
devDependencies:
'@types/jsonwebtoken':
specifier: 'catalog:'
@@ -8247,6 +8247,40 @@ packages:
perfect-debounce@2.0.0:
resolution: {integrity: sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==}
pg-cloudflare@1.2.7:
resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==}
pg-connection-string@2.9.1:
resolution: {integrity: sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==}
pg-int8@1.0.1:
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
engines: {node: '>=4.0.0'}
pg-pool@3.10.1:
resolution: {integrity: sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==}
peerDependencies:
pg: '>=8.0'
pg-protocol@1.10.3:
resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==}
pg-types@2.2.0:
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
engines: {node: '>=4'}
pg@8.16.3:
resolution: {integrity: sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==}
engines: {node: '>= 16.0.0'}
peerDependencies:
pg-native: '>=3.0.1'
peerDependenciesMeta:
pg-native:
optional: true
pgpass@1.0.5:
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -8758,6 +8792,22 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
postgres-array@2.0.0:
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
engines: {node: '>=4'}
postgres-bytea@1.0.0:
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
engines: {node: '>=0.10.0'}
postgres-date@1.0.7:
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
engines: {node: '>=0.10.0'}
postgres-interval@1.2.0:
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
engines: {node: '>=0.10.0'}
preact@10.27.2:
resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==}
@@ -10612,6 +10662,10 @@ packages:
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
engines: {node: '>=12'}
xtend@4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
@@ -14433,6 +14487,7 @@ snapshots:
dependencies:
bindings: 1.5.0
prebuild-install: 7.1.3
optional: true
bignumber.js@9.3.1: {}
@@ -14451,6 +14506,7 @@ snapshots:
buffer: 5.7.1
inherits: 2.0.4
readable-stream: 3.6.2
optional: true
boolbase@1.0.0: {}
@@ -14496,6 +14552,7 @@ snapshots:
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
optional: true
buffer@6.0.3:
dependencies:
@@ -14666,7 +14723,8 @@ snapshots:
dependencies:
readdirp: 4.1.2
chownr@1.1.4: {}
chownr@1.1.4:
optional: true
chownr@3.0.0: {}
@@ -15186,6 +15244,7 @@ snapshots:
decompress-response@6.0.0:
dependencies:
mimic-response: 3.1.0
optional: true
deep-eql@5.0.2: {}
@@ -15427,6 +15486,7 @@ snapshots:
end-of-stream@1.4.5:
dependencies:
once: 1.4.0
optional: true
enhanced-resolve@5.18.3:
dependencies:
@@ -15922,7 +15982,8 @@ snapshots:
strip-final-newline: 4.0.0
yoctocolors: 2.1.2
expand-template@2.0.3: {}
expand-template@2.0.3:
optional: true
expand-tilde@2.0.2:
dependencies:
@@ -16091,7 +16152,8 @@ snapshots:
fresh@2.0.0: {}
fs-constants@1.0.0: {}
fs-constants@1.0.0:
optional: true
fs-extra@10.1.0:
dependencies:
@@ -16215,7 +16277,8 @@ snapshots:
meow: 12.1.1
split2: 4.2.0
github-from-package@0.0.0: {}
github-from-package@0.0.0:
optional: true
glob-parent@5.1.2:
dependencies:
@@ -17235,7 +17298,8 @@ snapshots:
mimic-function@5.0.1: {}
mimic-response@3.1.0: {}
mimic-response@3.1.0:
optional: true
minimatch@10.0.3:
dependencies:
@@ -17293,7 +17357,8 @@ snapshots:
mitt@3.0.1: {}
mkdirp-classic@0.5.3: {}
mkdirp-classic@0.5.3:
optional: true
mkdist@2.4.1(sass@1.93.3)(typescript@5.9.3)(vue-tsc@2.2.10(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)):
dependencies:
@@ -17374,7 +17439,8 @@ snapshots:
nanopop@2.4.2: {}
napi-build-utils@2.0.0: {}
napi-build-utils@2.0.0:
optional: true
napi-postinstall@0.3.4: {}
@@ -17498,6 +17564,7 @@ snapshots:
node-abi@3.80.0:
dependencies:
semver: 7.7.3
optional: true
node-addon-api@7.1.1: {}
@@ -17806,6 +17873,41 @@ snapshots:
perfect-debounce@2.0.0: {}
pg-cloudflare@1.2.7:
optional: true
pg-connection-string@2.9.1: {}
pg-int8@1.0.1: {}
pg-pool@3.10.1(pg@8.16.3):
dependencies:
pg: 8.16.3
pg-protocol@1.10.3: {}
pg-types@2.2.0:
dependencies:
pg-int8: 1.0.1
postgres-array: 2.0.0
postgres-bytea: 1.0.0
postgres-date: 1.0.7
postgres-interval: 1.2.0
pg@8.16.3:
dependencies:
pg-connection-string: 2.9.1
pg-pool: 3.10.1(pg@8.16.3)
pg-protocol: 1.10.3
pg-types: 2.2.0
pgpass: 1.0.5
optionalDependencies:
pg-cloudflare: 1.2.7
pgpass@1.0.5:
dependencies:
split2: 4.2.0
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -18334,6 +18436,16 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
postgres-array@2.0.0: {}
postgres-bytea@1.0.0: {}
postgres-date@1.0.7: {}
postgres-interval@1.2.0:
dependencies:
xtend: 4.0.2
preact@10.27.2: {}
prebuild-install@7.1.3:
@@ -18350,6 +18462,7 @@ snapshots:
simple-get: 4.0.1
tar-fs: 2.1.4
tunnel-agent: 0.6.0
optional: true
prelude-ls@1.2.1: {}
@@ -18399,6 +18512,7 @@ snapshots:
dependencies:
end-of-stream: 1.4.5
once: 1.4.0
optional: true
punycode@2.3.1: {}
@@ -18492,6 +18606,7 @@ snapshots:
inherits: 2.0.4
string_decoder: 1.3.0
util-deprecate: 1.0.2
optional: true
readable-stream@4.7.0:
dependencies:
@@ -18897,13 +19012,15 @@ snapshots:
signal-exit@4.1.0: {}
simple-concat@1.0.1: {}
simple-concat@1.0.1:
optional: true
simple-get@4.0.1:
dependencies:
decompress-response: 6.0.0
once: 1.4.0
simple-concat: 1.0.1
optional: true
sirv@3.0.2:
dependencies:
@@ -19362,6 +19479,7 @@ snapshots:
mkdirp-classic: 0.5.3
pump: 3.0.3
tar-stream: 2.2.0
optional: true
tar-stream@2.2.0:
dependencies:
@@ -19370,6 +19488,7 @@ snapshots:
fs-constants: 1.0.0
inherits: 2.0.4
readable-stream: 3.6.2
optional: true
tar-stream@3.1.7:
dependencies:
@@ -19493,6 +19612,7 @@ snapshots:
tunnel-agent@0.6.0:
dependencies:
safe-buffer: 5.2.1
optional: true
turbo-darwin-64@2.6.0:
optional: true
@@ -20567,6 +20687,8 @@ snapshots:
xml-name-validator@4.0.0: {}
xtend@4.0.2: {}
y18n@4.0.3: {}
y18n@5.0.8: {}