feat: 补充积分和账务 API 客户端

- 新增 src/api/points.ts - 积分 API 客户端
- 新增 src/api/ledger.ts - 账务 API 客户端
- 新增 src/types/points.ts - 积分类型定义
- 新增 src/types/ledger.ts - 账务类型定义
- 更新 src/api/index.ts - 导出新增模块
This commit is contained in:
tangweijie 2026-01-05 18:13:12 +08:00
parent 5099f2e87e
commit ae2653f9dd
5 changed files with 475 additions and 0 deletions

View File

@ -3,8 +3,12 @@ export { apiClient, ApiClient } from './client'
export { AccountAPI } from './account'
export { TransactionAPI } from './transaction'
export { ReconciliationAPI } from './reconciliation'
export { PointsAPI } from './points'
export { LedgerAPI } from './ledger'
// 类型重新导出
export type * from '@/types/api'
export type * from '@/types/account'
export type * from '@/types/transaction'
export type * from '@/types/points'
export type * from '@/types/ledger'

141
src/api/ledger.ts Normal file
View File

@ -0,0 +1,141 @@
/**
* API
*
*/
import apiClient from './client'
import type {
AccountingSubject,
LedgerEntry,
LedgerEntryQuery,
} from '@/types/ledger'
import type { PageResponse } from '@/types/api'
export class LedgerAPI {
/**
*
* @returns
*/
static async getSubjects(): Promise<AccountingSubject[]> {
return apiClient.get('/ledger/subjects')
}
/**
*
* @param code
* @returns
*/
static async getSubject(code: string): Promise<AccountingSubject> {
return apiClient.get(`/ledger/subjects/${code}`)
}
/**
*
* @param id ID
* @returns
*/
static async getEntry(id: number): Promise<LedgerEntry> {
return apiClient.get(`/ledger/entries/${id}`)
}
/**
*
* @param accountId ID
* @param accountType (physical/virtual)
* @param query
* @returns
*/
static async getAccountEntries(
accountId: number,
accountType: 'physical' | 'virtual',
query?: LedgerEntryQuery
): Promise<PageResponse<LedgerEntry>> {
return apiClient.get(`/ledger/accounts/${accountId}/entries`, {
params: { account_type: accountType, ...query }
})
}
/**
*
* @param txnNo
* @returns
*/
static async getEntryByTxnNo(txnNo: string): Promise<LedgerEntry> {
return apiClient.get(`/ledger/entries/by-txn/${txnNo}`)
}
/**
*
* @param accountId ID
* @param accountType
* @param query
* @returns
*/
static async getBalanceHistory(
accountId: number,
accountType: 'physical' | 'virtual',
query?: BalanceHistoryQuery
): Promise<PageResponse<BalanceChange>> {
return apiClient.get(`/ledger/accounts/${accountId}/balance-history`, {
params: { account_type: accountType, ...query }
})
}
/**
*
* @param query
* @returns
*/
static async getSubjectSummary(query: SubjectSummaryQuery): Promise<SubjectSummary[]> {
return apiClient.get('/ledger/reports/subject-summary', { params: query })
}
}
/**
*
*/
export interface BalanceHistoryQuery {
start_date?: string
end_date?: string
page?: number
page_size?: number
}
/**
*
*/
export interface BalanceChange {
id: number
account_id: number
account_type: string
change_type: string
amount: string
balance_before: string
balance_after: string
txn_no?: string
description?: string
created_at: string
}
/**
*
*/
export interface SubjectSummaryQuery {
start_date: string
end_date: string
subject_code?: string
}
/**
*
*/
export interface SubjectSummary {
subject_code: string
subject_name: string
debit_total: string
credit_total: string
balance: string
transaction_count: number
}
export default LedgerAPI

100
src/api/points.ts Normal file
View File

@ -0,0 +1,100 @@
/**
* API
* //
*/
import apiClient from './client'
import type {
PointsAccount,
PointsTransaction,
PointsTransactionQuery,
EarnPointsRequest,
SpendPointsRequest,
TransferPointsRequest,
} from '@/types/points'
import type { PageResponse } from '@/types/api'
export class PointsAPI {
/**
*
* @param subAccountId ID
* @returns
*/
static async getAccounts(subAccountId: number): Promise<PointsAccount[]> {
return apiClient.get(`/points/accounts/${subAccountId}`)
}
/**
*
* @param accountId ID
* @returns
*/
static async getAccount(accountId: number): Promise<PointsAccount> {
return apiClient.get(`/points/accounts/detail/${accountId}`)
}
/**
* ()
* @param data
* @returns
*/
static async earnPoints(data: EarnPointsRequest): Promise<PointsTransaction> {
return apiClient.post('/points/earn', data)
}
/**
*
* @param data
* @returns
*/
static async spendPoints(data: SpendPointsRequest): Promise<PointsTransaction> {
return apiClient.post('/points/spend', data)
}
/**
*
* @param data
* @returns
*/
static async transferPoints(data: TransferPointsRequest): Promise<{
from_transaction: PointsTransaction
to_transaction: PointsTransaction
}> {
return apiClient.post('/points/transfer', data)
}
/**
*
* @param query
* @returns
*/
static async getTransactions(query: PointsTransactionQuery): Promise<PageResponse<PointsTransaction>> {
return apiClient.get('/points/transactions', { params: query })
}
/**
*
* @param accountId ID
* @returns
*/
static async getStatistics(accountId: number): Promise<PointsStatistics> {
return apiClient.get(`/points/accounts/${accountId}/statistics`)
}
}
/**
*
*/
export interface PointsStatistics {
account_id: number
balance: string
total_earned: string
total_spent: string
total_expired: string
earn_count: number
spend_count: number
transfer_in_count: number
transfer_out_count: number
}
export default PointsAPI

110
src/types/ledger.ts Normal file
View File

@ -0,0 +1,110 @@
/**
*
*/
/**
*
*/
export type SubjectCategory = 'asset' | 'liability' | 'income' | 'expense'
/**
*
*/
export type Direction = 'debit' | 'credit'
/**
*
*/
export type EntryStatus = 'pending' | 'posted' | 'reversed'
/**
*
*/
export interface AccountingSubject {
code: string
name: string
category: SubjectCategory
direction_default: number
parent_code?: string
level: number
}
/**
*
*/
export interface LedgerLine {
id: number
entry_id: number
account_id: number
account_type: string
subject_code: string
direction: Direction
amount: string
}
/**
*
*/
export interface LedgerEntry {
id: number
entry_no: string
txn_no: string
post_date: string
post_time: string
description?: string
status: EntryStatus
created_at: string
lines: LedgerLine[]
}
/**
*
*/
export interface LedgerEntryQuery {
subject_code?: string
start_date?: string
end_date?: string
status?: EntryStatus
page?: number
page_size?: number
}
/**
*
*/
export const SubjectCategoryLabels: Record<SubjectCategory, string> = {
asset: '资产类',
liability: '负债类',
income: '收入类',
expense: '支出类',
}
/**
*
*/
export const DirectionLabels: Record<Direction, string> = {
debit: '借方',
credit: '贷方',
}
/**
*
*/
export const EntryStatusLabels: Record<EntryStatus, string> = {
pending: '待确认',
posted: '已过账',
reversed: '已冲销',
}
/**
*
*/
export const PredefinedSubjects: AccountingSubject[] = [
{ code: '1002', name: '银行存款', category: 'asset', direction_default: 1, level: 1 },
{ code: '1003', name: '在途资金', category: 'asset', direction_default: 1, level: 1 },
{ code: '2001', name: '客户存款', category: 'liability', direction_default: -1, level: 1 },
{ code: '2002', name: '待清算款项', category: 'liability', direction_default: -1, level: 1 },
{ code: '3001', name: '手续费收入', category: 'income', direction_default: -1, level: 1 },
{ code: '4001', name: '利息支出', category: 'expense', direction_default: 1, level: 1 },
]

120
src/types/points.ts Normal file
View File

@ -0,0 +1,120 @@
/**
*
*/
/**
*
*/
export type PointsType = 'production' | 'management' | 'other'
/**
*
*/
export type PointsTransactionType = 'earn' | 'spend' | 'transfer' | 'expire' | 'adjust'
/**
*
*/
export interface PointsAccount {
id: number
sub_account_id: number
points_type: PointsType
balance: string
total_earned: string
total_spent: string
total_expired: string
created_at: string
updated_at: string
}
/**
*
*/
export interface PointsTransaction {
id: number
txn_no: string
points_account_id: number
txn_type: PointsTransactionType
amount: string
balance_before: string
balance_after: string
related_business_id?: string
remark?: string
created_at: string
}
/**
*
*/
export interface EarnPointsRequest {
points_account_id: number
amount: string
related_business_id?: string
remark?: string
}
/**
*
*/
export interface SpendPointsRequest {
points_account_id: number
amount: string
related_business_id?: string
remark?: string
}
/**
*
*/
export interface TransferPointsRequest {
from_account_id: number
to_account_id: number
amount: string
remark?: string
}
/**
*
*/
export interface PointsTransactionQuery {
points_account_id?: number
txn_type?: PointsTransactionType
start_date?: string
end_date?: string
page?: number
page_size?: number
}
/**
*
*/
export interface PointsRule {
id: number
name: string
points_type: PointsType
rule_type: string
config: Record<string, unknown>
enabled: boolean
created_at: string
}
/**
*
*/
export const PointsTypeLabels: Record<PointsType, string> = {
production: '生产积分',
management: '管理积分',
other: '其他积分',
}
/**
*
*/
export const PointsTransactionTypeLabels: Record<PointsTransactionType, string> = {
earn: '获取',
spend: '消费',
transfer: '转移',
expire: '过期',
adjust: '调整',
}