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 "⏳ 等待服务启动..." echo "⏳ 等待服务启动..."
sleep 10 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. 检查容器状态 # 1. 检查容器状态
echo "📊 容器状态:" echo "📊 容器状态:"
sudo docker-compose ps sudo docker-compose ps

View File

@@ -9,6 +9,7 @@
- **功能**: Telegram Bot通知系统 - **功能**: Telegram Bot通知系统
#### 已完成功能: #### 已完成功能:
1. ✅ 基础Telegram通知 1. ✅ 基础Telegram通知
2. ✅ 频率控制和去重 2. ✅ 频率控制和去重
3. ✅ 失败重试机制 3. ✅ 失败重试机制
@@ -16,15 +17,38 @@
5. ✅ 优先级设置 5. ✅ 优先级设置
#### 配置信息: #### 配置信息:
- Bot Token: 已配置 - Bot Token: 已配置
- Chat ID: 1102887169 - Chat ID: 1102887169
- Bot用户名: @ktcaiwubot - Bot用户名: @ktcaiwubot
#### 测试结果: #### 测试结果:
- ✅ Telegram消息发送成功 - ✅ Telegram消息发送成功
- ✅ API接口已实现 - ✅ 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 packages ./packages
COPY internal ./internal COPY internal ./internal
COPY scripts ./scripts COPY scripts ./scripts
COPY data ./data
# 安装依赖如果存在lock文件则使用 # 安装依赖如果存在lock文件则使用
RUN pnpm install --no-frozen-lockfile 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 COPY --from=backend-builder /app/apps/backend /app/apps/backend
RUN ln -s /app/apps/backend /app/backend RUN ln -s /app/apps/backend /app/backend
COPY --from=backend-builder /app/node_modules /app/node_modules COPY --from=backend-builder /app/node_modules /app/node_modules
COPY --from=backend-builder /app/data /app/data
# 创建nginx配置和日志目录 # 创建nginx配置和日志目录
RUN mkdir -p /run/nginx && \ RUN mkdir -p /run/nginx && \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
import { readBody } from 'h3'; import { readBody } from 'h3';
import db from '~/utils/sqlite'; import { query } from '~/utils/db';
import { useResponseError, useResponseSuccess } from '~/utils/response'; import { useResponseError, useResponseSuccess } from '~/utils/response';
import { testTelegramConfig } from '~/utils/telegram-bot'; import { testTelegramConfig } from '~/utils/telegram-bot';
@@ -25,31 +25,48 @@ export default defineEventHandler(async (event) => {
const now = new Date().toISOString(); const now = new Date().toISOString();
const result = db const { rows } = await query<{
.prepare<unknown, [string, string, string, string, number, string, string]>( id: number;
` name: string;
INSERT INTO telegram_notification_configs (name, bot_token, chat_id, notification_types, is_enabled, created_at, updated_at) bot_token: string;
VALUES (?, ?, ?, ?, ?, ?, ?) 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
) )
.run( 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.name,
body.botToken, body.botToken,
body.chatId, body.chatId,
JSON.stringify(notificationTypes), JSON.stringify(notificationTypes),
body.isEnabled !== false ? 1 : 0, body.isEnabled !== false,
now, now,
now, now,
],
); );
const row = rows[0];
return useResponseSuccess({ return useResponseSuccess({
id: result.lastInsertRowid, id: row.id,
name: body.name, name: row.name,
botToken: body.botToken, botToken: row.bot_token,
chatId: body.chatId, chatId: row.chat_id,
notificationTypes, notificationTypes,
isEnabled: body.isEnabled !== false, isEnabled: row.is_enabled,
createdAt: now, createdAt: row.created_at,
updatedAt: now, 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'; import { useResponseError, useResponseSuccess } from '~/utils/response';
export default defineEventHandler((event) => { export default defineEventHandler(async (event) => {
const id = event.context.params?.id; const idParam = event.context.params?.id;
if (!id) { const id = Number(idParam);
if (!idParam || Number.isNaN(id)) {
return useResponseError('缺少ID参数', -1); return useResponseError('缺少ID参数', -1);
} }
const result = db const result = await query(
.prepare('DELETE FROM telegram_notification_configs WHERE id = ?') 'DELETE FROM telegram_notification_configs WHERE id = $1',
.run(id); [id],
);
if (result.changes === 0) { if (result.rowCount === 0) {
return useResponseError('配置不存在或删除失败', -1); return useResponseError('配置不存在或删除失败', -1);
} }

View File

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

View File

@@ -12,9 +12,9 @@
}, },
"dependencies": { "dependencies": {
"@faker-js/faker": "catalog:", "@faker-js/faker": "catalog:",
"better-sqlite3": "9.5.0",
"jsonwebtoken": "catalog:", "jsonwebtoken": "catalog:",
"nitropack": "catalog:" "nitropack": "catalog:",
"pg": "^8.12.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jsonwebtoken": "catalog:", "@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 { import {
MOCK_ACCOUNTS, MOCK_ACCOUNTS,
MOCK_BUDGETS, MOCK_BUDGETS,
@@ -5,37 +6,87 @@ import {
MOCK_CURRENCIES, MOCK_CURRENCIES,
MOCK_EXCHANGE_RATES, MOCK_EXCHANGE_RATES,
} from './mock-data'; } from './mock-data';
import db from './sqlite';
export function listAccounts() { interface AccountRow {
return MOCK_ACCOUNTS; 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;
try { name: string;
const stmt = db.prepare(` type: string;
SELECT id, name, type, icon, color, user_id as userId, is_active as isActive icon: null | string;
FROM finance_categories color: null | string;
WHERE is_active = 1 user_id: null | number;
ORDER BY type, id is_active: boolean;
`); }
const categories = stmt.all() as any[];
// 转换为前端需要的格式 function mapAccount(row: AccountRow) {
return categories.map(cat => ({ return {
id: cat.id, id: row.id,
userId: cat.userId, userId: row.user_id ?? 1,
name: cat.name, name: row.name,
type: cat.type, type: row.type,
icon: cat.icon, currency: row.currency,
color: cat.color, balance: 0,
sortOrder: cat.id, icon: row.icon ?? '💳',
isSystem: true, color: row.color ?? '#1677ff',
isActive: Boolean(cat.isActive), isActive: Boolean(row.is_active),
})); };
}
function mapCategory(row: CategoryRow) {
return {
id: row.id,
userId: row.user_id ?? 1,
name: row.name,
type: row.type as 'expense' | 'income',
icon: row.icon ?? '📝',
color: row.color ?? '#dfe4ea',
sortOrder: row.id,
isSystem: row.user_id === null,
isActive: Boolean(row.is_active),
};
}
export async function listAccounts() {
try {
const { rows } = await query<AccountRow>(
`SELECT id, name, type, currency, icon, color, user_id, is_active
FROM finance_accounts
ORDER BY id`,
);
if (rows.length === 0) {
return MOCK_ACCOUNTS;
}
return rows.map((row) => mapAccount(row));
} catch (error) { } 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; return MOCK_CATEGORIES;
} }
} }
@@ -52,76 +103,80 @@ export function listExchangeRates() {
return MOCK_EXCHANGE_RATES; return MOCK_EXCHANGE_RATES;
} }
export function createCategoryRecord(category: any) { export async function createCategoryRecord(category: any) {
try { try {
const stmt = db.prepare(` const { rows } = await query<CategoryRow>(
INSERT INTO finance_categories (name, type, icon, color, user_id, is_active) `INSERT INTO finance_categories (name, type, icon, color, user_id, is_active)
VALUES (?, ?, ?, ?, ?, 1) VALUES ($1, $2, $3, $4, $5, TRUE)
`); RETURNING id, name, type, icon, color, user_id, is_active`,
const result = stmt.run( [
category.name, category.name,
category.type, category.type,
category.icon || '📝', category.icon || '📝',
category.color || '#dfe4ea', category.color || '#dfe4ea',
category.userId || 1 category.userId || 1,
],
); );
return { const row = rows[0];
id: result.lastInsertRowid, return row
...category, ? {
...mapCategory(row),
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
}; }
: null;
} catch (error) { } catch (error) {
console.error('创建分类失败:', error); console.error('创建分类失败:', error);
return null; return null;
} }
} }
export function updateCategoryRecord(id: number, category: any) { export async function updateCategoryRecord(id: number, category: any) {
try { try {
const updates: string[] = []; const updates: string[] = [];
const params: any[] = []; const params: any[] = [];
if (category.name) { if (category.name) {
updates.push('name = ?');
params.push(category.name); params.push(category.name);
updates.push(`name = $${params.length}`);
} }
if (category.icon) { if (category.icon) {
updates.push('icon = ?');
params.push(category.icon); params.push(category.icon);
updates.push(`icon = $${params.length}`);
} }
if (category.color) { if (category.color) {
updates.push('color = ?');
params.push(category.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); params.push(id);
const stmt = db.prepare(` const setClause = updates.join(', ');
UPDATE finance_categories const { rows } = await query<CategoryRow>(
SET ${updates.join(', ')} `UPDATE finance_categories
WHERE id = ? SET ${setClause}
`); WHERE id = $${params.length}
stmt.run(...params); RETURNING id, name, type, icon, color, user_id, is_active`,
params,
// 返回更新后的分类 );
const selectStmt = db.prepare('SELECT * FROM finance_categories WHERE id = ?'); const row = rows[0];
return selectStmt.get(id); return row ? mapCategory(row) : null;
} catch (error) { } catch (error) {
console.error('更新分类失败:', error); console.error('更新分类失败:', error);
return null; return null;
} }
} }
export function deleteCategoryRecord(id: number) { export async function deleteCategoryRecord(id: number) {
try { try {
// 软删除 await query(
const stmt = db.prepare(` `UPDATE finance_categories
UPDATE finance_categories SET is_active = FALSE
SET is_active = 0 WHERE id = $1`,
WHERE id = ? [id],
`); );
stmt.run(id);
return true; return true;
} catch (error) { } catch (error) {
console.error('删除分类失败:', 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'; const BASE_CURRENCY = 'CNY';
interface TransactionRow { interface TransactionRow {
id: number; id: number;
type: string; type: string;
amount: number; amount: number | string;
currency: string; currency: string;
exchange_rate_to_base: number; exchange_rate_to_base: number | string;
amount_in_base: number; amount_in_base: number | string;
category_id: null | number; category_id: null | number;
account_id: null | number; account_id: null | number;
transaction_date: string; transaction_date: string;
@@ -23,7 +25,7 @@ interface TransactionRow {
submitted_by: null | string; submitted_by: null | string;
approved_by: null | string; approved_by: null | string;
approved_at: null | string; approved_at: null | string;
is_deleted: number; is_deleted: boolean;
deleted_at: null | string; deleted_at: null | string;
} }
@@ -49,32 +51,24 @@ interface TransactionPayload {
} }
export type TransactionStatus = export type TransactionStatus =
| 'draft'
| 'pending'
| 'approved' | 'approved'
| 'rejected' | 'draft'
| 'paid'; | 'paid'
| 'pending'
function getExchangeRateToBase(currency: string) { | 'rejected';
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;
}
function mapTransaction(row: TransactionRow) { 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 { return {
id: row.id, id: row.id,
userId: 1, userId: 1,
type: 'expense' as const, type: row.type as 'expense' | 'income' | 'transfer',
amount: Math.abs(row.amount), amount: Math.abs(amount),
currency: row.currency, currency: row.currency,
exchangeRateToBase: row.exchange_rate_to_base, exchangeRateToBase,
amountInBase: Math.abs(row.amount_in_base), amountInBase: Math.abs(amountInBase),
categoryId: row.category_id ?? undefined, categoryId: row.category_id ?? undefined,
accountId: row.account_id ?? undefined, accountId: row.account_id ?? undefined,
transactionDate: row.transaction_date, transactionDate: row.transaction_date,
@@ -94,51 +88,114 @@ 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: { options: {
includeDeleted?: boolean; includeDeleted?: boolean;
type?: string;
statuses?: TransactionStatus[]; statuses?: TransactionStatus[];
type?: string;
} = {}, } = {},
) { ) {
const clauses: string[] = []; const clauses: string[] = [];
const params: Record<string, unknown> = {}; const params: any[] = [];
if (!options.includeDeleted) { if (!options.includeDeleted) {
clauses.push('is_deleted = 0'); clauses.push('is_deleted = FALSE');
} }
if (options.type) { if (options.type) {
clauses.push('type = @type'); params.push(options.type);
params.type = options.type; clauses.push(`type = $${params.length}`);
} }
if (options.statuses && options.statuses.length > 0) { if (options.statuses && options.statuses.length > 0) {
clauses.push( const statusPlaceholders = options.statuses.map((status) => {
`status IN (${options.statuses.map((_, index) => `@status${index}`).join(', ')})`, params.push(status);
); return `$${params.length}`;
options.statuses.forEach((status, index) => {
params[`status${index}`] = status;
}); });
clauses.push(`status IN (${statusPlaceholders.join(', ')})`);
} }
const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : ''; const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : '';
const { rows } = await query<TransactionRow>(
const stmt = db.prepare<TransactionRow>( `SELECT id,
`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`, 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 rows.map((row) => mapTransaction(row));
return stmt.all(params).map(mapTransaction);
} }
export function getTransactionById(id: number) { export async function getTransactionById(id: number) {
const stmt = db.prepare<TransactionRow>( 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 = ?`, `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; return row ? mapTransaction(row) : null;
} }
export function createTransaction(payload: TransactionPayload) { export async function createTransaction(payload: TransactionPayload) {
const exchangeRate = getExchangeRateToBase(payload.currency); return withTransaction(async (client) => {
const exchangeRate = await getExchangeRateToBase(client, payload.currency);
const amountInBase = +(payload.amount * exchangeRate).toFixed(2); const amountInBase = +(payload.amount * exchangeRate).toFixed(2);
const createdAt = const createdAt =
payload.createdAt && payload.createdAt.length > 0 payload.createdAt && payload.createdAt.length > 0
@@ -149,62 +206,95 @@ export function createTransaction(payload: TransactionPayload) {
payload.statusUpdatedAt && payload.statusUpdatedAt.length > 0 payload.statusUpdatedAt && payload.statusUpdatedAt.length > 0
? payload.statusUpdatedAt ? payload.statusUpdatedAt
: createdAt; : createdAt;
const approvedAt = let approvedAt: string | null = null;
payload.approvedAt && payload.approvedAt.length > 0 if (payload.approvedAt && payload.approvedAt.length > 0) {
? payload.approvedAt approvedAt = payload.approvedAt;
: status === 'approved' || status === 'paid' } else if (status === 'approved' || status === 'paid') {
? statusUpdatedAt approvedAt = statusUpdatedAt;
: null; }
const stmt = db.prepare( 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 (@type, @amount, @currency, @exchangeRateToBase, @amountInBase, @categoryId, @accountId, @transactionDate, @description, @project, @memo, @createdAt, @status, @statusUpdatedAt, @reimbursementBatch, @reviewNotes, @submittedBy, @approvedBy, @approvedAt, 0)`, `INSERT INTO finance_transactions (
); type,
amount,
const info = stmt.run({ currency,
type: payload.type, exchange_rate_to_base,
amount: payload.amount, amount_in_base,
currency: payload.currency, category_id,
exchangeRateToBase: exchangeRate, 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, amountInBase,
categoryId: payload.categoryId ?? null, payload.categoryId ?? null,
accountId: payload.accountId ?? null, payload.accountId ?? null,
transactionDate: payload.transactionDate, payload.transactionDate,
description: payload.description ?? '', payload.description ?? '',
project: payload.project ?? null, payload.project ?? null,
memo: payload.memo ?? null, payload.memo ?? null,
createdAt, createdAt,
status, status,
statusUpdatedAt, statusUpdatedAt,
reimbursementBatch: payload.reimbursementBatch ?? null, payload.reimbursementBatch ?? null,
reviewNotes: payload.reviewNotes ?? null, payload.reviewNotes ?? null,
submittedBy: payload.submittedBy ?? null, payload.submittedBy ?? null,
approvedBy: payload.approvedBy ?? null, payload.approvedBy ?? null,
approvedAt, approvedAt,
],
);
return mapTransaction(rows[0]);
}); });
return getTransactionById(Number(info.lastInsertRowid));
} }
export function updateTransaction(id: number, payload: TransactionPayload) { export async function updateTransaction(
const current = getTransactionById(id); id: number,
payload: TransactionPayload,
) {
const current = await getTransactionById(id);
if (!current) { if (!current) {
return null; return null;
} }
const nextStatus = (payload.status ?? current.status ?? 'approved') as TransactionStatus; return withTransaction(async (client) => {
const nextStatus = (payload.status ??
current.status ??
'approved') as TransactionStatus;
const statusChanged = nextStatus !== current.status; const statusChanged = nextStatus !== current.status;
const statusUpdatedAt = let statusUpdatedAt: string;
payload.statusUpdatedAt && payload.statusUpdatedAt.length > 0 if (payload.statusUpdatedAt && payload.statusUpdatedAt.length > 0) {
? payload.statusUpdatedAt statusUpdatedAt = payload.statusUpdatedAt;
: statusChanged } else if (statusChanged) {
? new Date().toISOString() statusUpdatedAt = new Date().toISOString();
: current.statusUpdatedAt ?? current.createdAt; } else {
const approvedAt = statusUpdatedAt = current.statusUpdatedAt ?? current.createdAt;
payload.approvedAt && payload.approvedAt.length > 0 }
? payload.approvedAt let approvedAt: string | null = null;
: nextStatus === 'approved' || nextStatus === 'paid' if (payload.approvedAt && payload.approvedAt.length > 0) {
? current.approvedAt ?? (statusChanged ? statusUpdatedAt : null) approvedAt = payload.approvedAt;
: null; } else if (nextStatus === 'approved' || nextStatus === 'paid') {
approvedAt = current.approvedAt ?? (statusChanged ? statusUpdatedAt : null);
}
const approvedBy = const approvedBy =
nextStatus === 'approved' || nextStatus === 'paid' nextStatus === 'approved' || nextStatus === 'paid'
? payload.approvedBy ?? current.approvedBy ?? null ? payload.approvedBy ?? current.approvedBy ?? null
@@ -231,94 +321,117 @@ export function updateTransaction(id: number, payload: TransactionPayload) {
approvedAt, approvedAt,
}; };
const exchangeRate = getExchangeRateToBase(next.currency); const exchangeRate = await getExchangeRateToBase(client, next.currency);
const amountInBase = +(next.amount * exchangeRate).toFixed(2); const amountInBase = +(next.amount * exchangeRate).toFixed(2);
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 deletedAt = next.isDeleted ? new Date().toISOString() : null; const deletedAt = next.isDeleted ? new Date().toISOString() : null;
stmt.run({ const { rows } = await client.query<TransactionRow>(
id, `UPDATE finance_transactions
type: next.type, SET type = $1,
amount: next.amount, amount = $2,
currency: next.currency, currency = $3,
exchangeRateToBase: exchangeRate, 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, amountInBase,
categoryId: next.categoryId, next.categoryId,
accountId: next.accountId, next.accountId,
transactionDate: next.transactionDate, next.transactionDate,
description: next.description, next.description,
project: next.project, next.project,
memo: next.memo, next.memo,
status: next.status, next.status,
statusUpdatedAt: next.statusUpdatedAt, next.statusUpdatedAt,
reimbursementBatch: next.reimbursementBatch, next.reimbursementBatch,
reviewNotes: next.reviewNotes, next.reviewNotes,
submittedBy: next.submittedBy, next.submittedBy,
approvedBy: next.approvedBy, next.approvedBy,
approvedAt: next.approvedAt, next.approvedAt,
isDeleted: next.isDeleted ? 1 : 0, next.isDeleted,
deletedAt, deletedAt,
id,
],
);
return mapTransaction(rows[0]);
}); });
return getTransactionById(id);
} }
export function softDeleteTransaction(id: number) { export async function softDeleteTransaction(id: number) {
const stmt = db.prepare( const deletedAt = new Date().toISOString();
`UPDATE finance_transactions SET is_deleted = 1, deleted_at = @deletedAt WHERE id = @id`, 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() }); const row = rows[0];
return getTransactionById(id); return row ? mapTransaction(row) : null;
} }
export function restoreTransaction(id: number) { export async function restoreTransaction(id: number) {
const stmt = db.prepare( const { rows } = await query<TransactionRow>(
`UPDATE finance_transactions SET is_deleted = 0, deleted_at = NULL WHERE id = @id`, `UPDATE finance_transactions
SET is_deleted = FALSE, deleted_at = NULL
WHERE id = $1
RETURNING *`,
[id],
); );
stmt.run({ id }); const row = rows[0];
return getTransactionById(id); return row ? mapTransaction(row) : null;
} }
export function replaceAllTransactions( export async function replaceAllTransactions(
rows: Array<{ rows: Array<{
accountId: null | number; accountId: null | number;
amount: number; amount: number;
approvedAt?: null | string;
approvedBy?: null | string;
categoryId: null | number; categoryId: null | number;
createdAt?: string; createdAt?: string;
currency: string; currency: string;
description: string; description: string;
isDeleted?: boolean;
memo?: null | string; memo?: null | string;
project?: null | string; project?: null | string;
transactionDate: string;
type: string;
status?: TransactionStatus;
statusUpdatedAt?: string;
reimbursementBatch?: null | string; reimbursementBatch?: null | string;
reviewNotes?: null | string; reviewNotes?: null | string;
status?: TransactionStatus;
statusUpdatedAt?: string;
submittedBy?: null | string; submittedBy?: null | string;
approvedBy?: null | string; transactionDate: string;
approvedAt?: null | string; type: string;
isDeleted?: boolean;
}>, }>,
) { ) {
db.prepare('DELETE FROM finance_transactions').run(); await withTransaction(async (client) => {
await client.query(
const insert = db.prepare( 'TRUNCATE TABLE finance_transactions RESTART IDENTITY CASCADE',
`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( for (const item of rows) {
`SELECT rate FROM finance_exchange_rates WHERE from_currency = ? AND to_currency = 'CNY' ORDER BY date DESC LIMIT 1`, const rate = await getExchangeRateToBase(client, item.currency);
);
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;
const amountInBase = +(item.amount * rate).toFixed(2); const amountInBase = +(item.amount * rate).toFixed(2);
const createdAt = const createdAt =
item.createdAt ?? item.createdAt ??
@@ -326,38 +439,67 @@ export function replaceAllTransactions(
const status = item.status ?? 'approved'; const status = item.status ?? 'approved';
const statusUpdatedAt = const statusUpdatedAt =
item.statusUpdatedAt ?? item.statusUpdatedAt ??
new Date( new Date(`${item.transactionDate}T00:00:00Z`).toISOString();
`${item.transactionDate}T00:00:00Z`,
).toISOString();
const approvedAt = const approvedAt =
item.approvedAt ?? item.approvedAt ??
(status === 'approved' || status === 'paid' ? statusUpdatedAt : null); (status === 'approved' || status === 'paid' ? statusUpdatedAt : null);
insert.run({
...item, await client.query(
exchangeRateToBase: rate, `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, amountInBase,
project: item.project ?? null, item.categoryId ?? null,
memo: item.memo ?? null, item.accountId ?? null,
item.transactionDate,
item.description ?? '',
item.project ?? null,
item.memo ?? null,
createdAt, createdAt,
status, status,
statusUpdatedAt, statusUpdatedAt,
reimbursementBatch: item.reimbursementBatch ?? null, item.reimbursementBatch ?? null,
reviewNotes: item.reviewNotes ?? null, item.reviewNotes ?? null,
submittedBy: item.submittedBy ?? null, item.submittedBy ?? null,
approvedBy:
status === 'approved' || status === 'paid' status === 'approved' || status === 'paid'
? item.approvedBy ?? null ? (item.approvedBy ?? null)
: null, : null,
approvedAt, approvedAt,
isDeleted: item.isDeleted ? 1 : 0, item.isDeleted ?? false,
}); ],
);
} }
}); });
insertMany(rows);
} }
// 分类相关函数
interface CategoryRow { interface CategoryRow {
id: number; id: number;
name: string; name: string;
@@ -365,7 +507,7 @@ interface CategoryRow {
icon: null | string; icon: null | string;
color: null | string; color: null | string;
user_id: null | number; user_id: null | number;
is_active: number; is_active: boolean;
} }
function mapCategory(row: CategoryRow) { function mapCategory(row: CategoryRow) {
@@ -382,15 +524,53 @@ function mapCategory(row: CategoryRow) {
}; };
} }
export function fetchCategories(options: { type?: 'expense' | 'income' } = {}) { export async function fetchCategories(
const where = options.type options: { type?: 'expense' | 'income' } = {},
? `WHERE type = @type AND is_active = 1` ) {
: 'WHERE is_active = 1'; const params: any[] = [];
const params = options.type ? { type: options.type } : {}; const clauses: string[] = ['is_active = TRUE'];
if (options.type) {
const stmt = db.prepare<CategoryRow>( params.push(options.type);
`SELECT id, name, type, icon, color, user_id, is_active FROM finance_categories ${where} ORDER BY id ASC`, 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 rows.map((row) => mapCategory(row));
return stmt.all(params).map(mapCategory); }
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 { existsSync } from 'node:fs';
import db from './sqlite'; import { query } from './db';
interface MediaRow { interface MediaRow {
id: number; id: number;
@@ -47,7 +47,7 @@ export interface MediaMessage {
createdAt: string; createdAt: string;
updatedAt: string; updatedAt: string;
available: boolean; available: boolean;
downloadUrl: string | null; downloadUrl: null | string;
} }
function mapMediaRow(row: MediaRow): MediaMessage { function mapMediaRow(row: MediaRow): MediaMessage {
@@ -78,40 +78,85 @@ function mapMediaRow(row: MediaRow): MediaMessage {
}; };
} }
export function fetchMediaMessages(params: { export async function fetchMediaMessages(
limit?: number; params: {
fileTypes?: string[]; fileTypes?: string[];
} = {}) { limit?: number;
const clauses: string[] = []; } = {},
const bindParams: Record<string, unknown> = {}; ) {
const whereClauses: string[] = [];
const queryParams: any[] = [];
if (params.fileTypes && params.fileTypes.length > 0) { if (params.fileTypes && params.fileTypes.length > 0) {
clauses.push( const placeholders = params.fileTypes.map((type) => {
`file_type IN (${params.fileTypes.map((_, index) => `@type${index}`).join(', ')})`, queryParams.push(type);
); return `$${queryParams.length}`;
params.fileTypes.forEach((type, index) => {
bindParams[`type${index}`] = type;
}); });
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 = const limitClause =
params.limit && params.limit > 0 ? `LIMIT ${Number(params.limit)}` : ''; params.limit && params.limit > 0 ? `LIMIT ${Number(params.limit)}` : '';
const stmt = db.prepare<MediaRow>( 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 datetime(created_at) DESC, id DESC ${limitClause}`, `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) { export async function getMediaMessageById(id: number) {
const stmt = db.prepare<MediaRow>( 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 = ?`, `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 = rows[0];
const row = stmt.get(id);
return row ? mapMediaRow(row) : null; 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 {
import db from './sqlite'; getEnabledNotificationConfigs,
notifyTransaction,
testTelegramConfig,
} from './telegram-bot';
interface TelegramNotificationConfig { export { getEnabledNotificationConfigs, testTelegramConfig };
id: number;
name: string;
botToken: string;
chatId: string;
notificationTypes: string[];
isEnabled: boolean;
priority: string;
rateLimitSeconds: number;
batchEnabled: boolean;
batchIntervalMinutes: number;
retryEnabled: boolean;
retryMaxAttempts: number;
}
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( export async function notifyTransactionEnhanced(
transaction: TransactionNotificationData, ...args: Parameters<typeof notifyTransaction>
action: string = 'created', ) {
): Promise<void> { await notifyTransaction(...args);
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}`,
);
}
}
} }
/**
* 重试失败的通知
*/
export async function retryFailedNotifications(): Promise<void> { export async function retryFailedNotifications(): Promise<void> {
const pending = getPendingRetries(); // Retrying logic is not yet implemented for the PostgreSQL data source.
// The SQLite-specific implementation relied on synchronous database access.
if (pending.length === 0) { // If this functionality becomes necessary, please implement it using the
return; // telegram_notification_history table with pool-based transactions.
} console.warn('[telegram-bot-enhanced] retryFailedNotifications is not implemented.');
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);
} }

View File

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

View File

@@ -1,23 +1,54 @@
version: '3.8' version: '3.8'
services: 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: kt-financial:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: kt-financial-system container_name: kt-financial-system
restart: unless-stopped restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
ports: ports:
- "8080:80" - "8080:80"
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- TZ=Asia/Shanghai - TZ=Asia/Shanghai
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
- POSTGRES_DB=kt_financial
- POSTGRES_USER=kt_financial
- POSTGRES_PASSWORD=kt_financial_pwd
volumes: volumes:
- ./logs:/var/log - ./logs:/var/log
- ./storage/backend:/app/apps/backend/storage - ./storage/backend:/app/apps/backend/storage
- ./data:/app/data:ro
networks: networks:
- kt-network - kt-network
networks: networks:
kt-network: kt-network:
driver: bridge driver: bridge
volumes:
postgres-data:

144
pnpm-lock.yaml generated
View File

@@ -631,15 +631,15 @@ importers:
'@faker-js/faker': '@faker-js/faker':
specifier: 'catalog:' specifier: 'catalog:'
version: 9.9.0 version: 9.9.0
better-sqlite3:
specifier: 9.5.0
version: 9.5.0
jsonwebtoken: jsonwebtoken:
specifier: 'catalog:' specifier: 'catalog:'
version: 9.0.2 version: 9.0.2
nitropack: nitropack:
specifier: 'catalog:' specifier: 'catalog:'
version: 2.12.9(better-sqlite3@9.5.0) version: 2.12.9(better-sqlite3@9.5.0)
pg:
specifier: ^8.12.0
version: 8.16.3
devDependencies: devDependencies:
'@types/jsonwebtoken': '@types/jsonwebtoken':
specifier: 'catalog:' specifier: 'catalog:'
@@ -8247,6 +8247,40 @@ packages:
perfect-debounce@2.0.0: perfect-debounce@2.0.0:
resolution: {integrity: sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==} 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: picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -8758,6 +8792,22 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14} 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: preact@10.27.2:
resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==}
@@ -10612,6 +10662,10 @@ packages:
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
engines: {node: '>=12'} engines: {node: '>=12'}
xtend@4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
y18n@4.0.3: y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
@@ -14433,6 +14487,7 @@ snapshots:
dependencies: dependencies:
bindings: 1.5.0 bindings: 1.5.0
prebuild-install: 7.1.3 prebuild-install: 7.1.3
optional: true
bignumber.js@9.3.1: {} bignumber.js@9.3.1: {}
@@ -14451,6 +14506,7 @@ snapshots:
buffer: 5.7.1 buffer: 5.7.1
inherits: 2.0.4 inherits: 2.0.4
readable-stream: 3.6.2 readable-stream: 3.6.2
optional: true
boolbase@1.0.0: {} boolbase@1.0.0: {}
@@ -14496,6 +14552,7 @@ snapshots:
dependencies: dependencies:
base64-js: 1.5.1 base64-js: 1.5.1
ieee754: 1.2.1 ieee754: 1.2.1
optional: true
buffer@6.0.3: buffer@6.0.3:
dependencies: dependencies:
@@ -14666,7 +14723,8 @@ snapshots:
dependencies: dependencies:
readdirp: 4.1.2 readdirp: 4.1.2
chownr@1.1.4: {} chownr@1.1.4:
optional: true
chownr@3.0.0: {} chownr@3.0.0: {}
@@ -15186,6 +15244,7 @@ snapshots:
decompress-response@6.0.0: decompress-response@6.0.0:
dependencies: dependencies:
mimic-response: 3.1.0 mimic-response: 3.1.0
optional: true
deep-eql@5.0.2: {} deep-eql@5.0.2: {}
@@ -15427,6 +15486,7 @@ snapshots:
end-of-stream@1.4.5: end-of-stream@1.4.5:
dependencies: dependencies:
once: 1.4.0 once: 1.4.0
optional: true
enhanced-resolve@5.18.3: enhanced-resolve@5.18.3:
dependencies: dependencies:
@@ -15922,7 +15982,8 @@ snapshots:
strip-final-newline: 4.0.0 strip-final-newline: 4.0.0
yoctocolors: 2.1.2 yoctocolors: 2.1.2
expand-template@2.0.3: {} expand-template@2.0.3:
optional: true
expand-tilde@2.0.2: expand-tilde@2.0.2:
dependencies: dependencies:
@@ -16091,7 +16152,8 @@ snapshots:
fresh@2.0.0: {} fresh@2.0.0: {}
fs-constants@1.0.0: {} fs-constants@1.0.0:
optional: true
fs-extra@10.1.0: fs-extra@10.1.0:
dependencies: dependencies:
@@ -16215,7 +16277,8 @@ snapshots:
meow: 12.1.1 meow: 12.1.1
split2: 4.2.0 split2: 4.2.0
github-from-package@0.0.0: {} github-from-package@0.0.0:
optional: true
glob-parent@5.1.2: glob-parent@5.1.2:
dependencies: dependencies:
@@ -17235,7 +17298,8 @@ snapshots:
mimic-function@5.0.1: {} mimic-function@5.0.1: {}
mimic-response@3.1.0: {} mimic-response@3.1.0:
optional: true
minimatch@10.0.3: minimatch@10.0.3:
dependencies: dependencies:
@@ -17293,7 +17357,8 @@ snapshots:
mitt@3.0.1: {} 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)): 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: dependencies:
@@ -17374,7 +17439,8 @@ snapshots:
nanopop@2.4.2: {} nanopop@2.4.2: {}
napi-build-utils@2.0.0: {} napi-build-utils@2.0.0:
optional: true
napi-postinstall@0.3.4: {} napi-postinstall@0.3.4: {}
@@ -17498,6 +17564,7 @@ snapshots:
node-abi@3.80.0: node-abi@3.80.0:
dependencies: dependencies:
semver: 7.7.3 semver: 7.7.3
optional: true
node-addon-api@7.1.1: {} node-addon-api@7.1.1: {}
@@ -17806,6 +17873,41 @@ snapshots:
perfect-debounce@2.0.0: {} 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: {} picocolors@1.1.1: {}
picomatch@2.3.1: {} picomatch@2.3.1: {}
@@ -18334,6 +18436,16 @@ snapshots:
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.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: {} preact@10.27.2: {}
prebuild-install@7.1.3: prebuild-install@7.1.3:
@@ -18350,6 +18462,7 @@ snapshots:
simple-get: 4.0.1 simple-get: 4.0.1
tar-fs: 2.1.4 tar-fs: 2.1.4
tunnel-agent: 0.6.0 tunnel-agent: 0.6.0
optional: true
prelude-ls@1.2.1: {} prelude-ls@1.2.1: {}
@@ -18399,6 +18512,7 @@ snapshots:
dependencies: dependencies:
end-of-stream: 1.4.5 end-of-stream: 1.4.5
once: 1.4.0 once: 1.4.0
optional: true
punycode@2.3.1: {} punycode@2.3.1: {}
@@ -18492,6 +18606,7 @@ snapshots:
inherits: 2.0.4 inherits: 2.0.4
string_decoder: 1.3.0 string_decoder: 1.3.0
util-deprecate: 1.0.2 util-deprecate: 1.0.2
optional: true
readable-stream@4.7.0: readable-stream@4.7.0:
dependencies: dependencies:
@@ -18897,13 +19012,15 @@ snapshots:
signal-exit@4.1.0: {} signal-exit@4.1.0: {}
simple-concat@1.0.1: {} simple-concat@1.0.1:
optional: true
simple-get@4.0.1: simple-get@4.0.1:
dependencies: dependencies:
decompress-response: 6.0.0 decompress-response: 6.0.0
once: 1.4.0 once: 1.4.0
simple-concat: 1.0.1 simple-concat: 1.0.1
optional: true
sirv@3.0.2: sirv@3.0.2:
dependencies: dependencies:
@@ -19362,6 +19479,7 @@ snapshots:
mkdirp-classic: 0.5.3 mkdirp-classic: 0.5.3
pump: 3.0.3 pump: 3.0.3
tar-stream: 2.2.0 tar-stream: 2.2.0
optional: true
tar-stream@2.2.0: tar-stream@2.2.0:
dependencies: dependencies:
@@ -19370,6 +19488,7 @@ snapshots:
fs-constants: 1.0.0 fs-constants: 1.0.0
inherits: 2.0.4 inherits: 2.0.4
readable-stream: 3.6.2 readable-stream: 3.6.2
optional: true
tar-stream@3.1.7: tar-stream@3.1.7:
dependencies: dependencies:
@@ -19493,6 +19612,7 @@ snapshots:
tunnel-agent@0.6.0: tunnel-agent@0.6.0:
dependencies: dependencies:
safe-buffer: 5.2.1 safe-buffer: 5.2.1
optional: true
turbo-darwin-64@2.6.0: turbo-darwin-64@2.6.0:
optional: true optional: true
@@ -20567,6 +20687,8 @@ snapshots:
xml-name-validator@4.0.0: {} xml-name-validator@4.0.0: {}
xtend@4.0.2: {}
y18n@4.0.3: {} y18n@4.0.3: {}
y18n@5.0.8: {} y18n@5.0.8: {}