diff --git a/apps/backend/src/services/cost-center/platform-credit-service.ts b/apps/backend/src/services/cost-center/platform-credit-service.ts
index 2278c679..c26e54ba 100644
--- a/apps/backend/src/services/cost-center/platform-credit-service.ts
+++ b/apps/backend/src/services/cost-center/platform-credit-service.ts
@@ -419,8 +419,8 @@ export async function listPlatformCreditOwners() {
SELECT
au.id, au.username, COALESCE(NULLIF(au.display_name, ''), au.username) AS display_name
FROM admin_users au
- WHERE au.status = 'active'
- ORDER BY au.id
+ WHERE au.status = 'active' AND au.role = 'support'
+ ORDER BY display_name, au.id
`,
)
return {
diff --git a/apps/backend/src/services/finance/manual-fulfillment-note.test.ts b/apps/backend/src/services/finance/manual-fulfillment-note.test.ts
new file mode 100644
index 00000000..d6d90dbd
--- /dev/null
+++ b/apps/backend/src/services/finance/manual-fulfillment-note.test.ts
@@ -0,0 +1,63 @@
+import assert from 'node:assert/strict'
+import test from 'node:test'
+
+import {
+ buildManualFulfillmentNote,
+ buildManualFulfillmentReference,
+} from './manual-fulfillment-note.js'
+
+test('人工履约编号同时带工单号与平台单号', () => {
+ assert.equal(
+ buildManualFulfillmentReference({
+ workOrderNo: 'WK26102414033739',
+ platformOrderId: '2628501763808879',
+ orderItemId: 10,
+ }),
+ '工单 WK26102414033739 · 平台单号 2628501763808879',
+ )
+})
+
+test('人工履约编号在没有工单号时回退平台单号', () => {
+ assert.equal(
+ buildManualFulfillmentReference({
+ workOrderNo: null,
+ platformOrderId: '2628501763808879',
+ orderItemId: 10,
+ }),
+ '平台单号 2628501763808879',
+ )
+})
+
+test('人工履约编号完全没有单号时回退订单项', () => {
+ assert.equal(
+ buildManualFulfillmentReference({
+ workOrderNo: null,
+ platformOrderId: '',
+ orderItemId: 10,
+ }),
+ '订单项 #10',
+ )
+})
+
+test('人工履约备注包含商品、编号与客服备注并按上限截断', () => {
+ const note = buildManualFulfillmentNote({
+ skuName: '幸运币2个',
+ reference: '工单 WK26102414033739 · 平台单号 2628501763808879',
+ note: '已发放',
+ maxLength: 300,
+ })
+ assert.equal(
+ note,
+ '人工履约 幸运币2个 · 工单 WK26102414033739 · 平台单号 2628501763808879 · 已发放',
+ )
+
+ assert.equal(
+ buildManualFulfillmentNote({
+ skuName: '幸运币2个',
+ reference: '工单 WK26102414033739',
+ note: '',
+ maxLength: 12,
+ }),
+ '人工履约 幸运币2个 ·',
+ )
+})
diff --git a/apps/backend/src/services/finance/manual-fulfillment-note.ts b/apps/backend/src/services/finance/manual-fulfillment-note.ts
new file mode 100644
index 00000000..674f1c71
--- /dev/null
+++ b/apps/backend/src/services/finance/manual-fulfillment-note.ts
@@ -0,0 +1,23 @@
+/** 人工履约流水备注:商品、可追溯编号与客服备注。 */
+export function buildManualFulfillmentReference(input: {
+ workOrderNo: string | null
+ platformOrderId: string
+ orderItemId: number
+}) {
+ const parts: string[] = []
+ if (input.workOrderNo) parts.push(`工单 ${input.workOrderNo}`)
+ if (input.platformOrderId) parts.push(`平台单号 ${input.platformOrderId}`)
+ if (parts.length === 0) parts.push(`订单项 #${input.orderItemId}`)
+ return parts.join(' · ')
+}
+
+export function buildManualFulfillmentNote(input: {
+ skuName: string
+ reference: string
+ note: string
+ maxLength: number
+}) {
+ const parts = [`人工履约 ${input.skuName}`.trim(), input.reference]
+ if (input.note) parts.push(input.note)
+ return parts.filter(Boolean).join(' · ').slice(0, input.maxLength)
+}
diff --git a/apps/backend/src/services/finance/manual-fulfillment-service.ts b/apps/backend/src/services/finance/manual-fulfillment-service.ts
index dc870484..4a7d5896 100644
--- a/apps/backend/src/services/finance/manual-fulfillment-service.ts
+++ b/apps/backend/src/services/finance/manual-fulfillment-service.ts
@@ -3,6 +3,10 @@ import type { JsonObject } from '../../types/json.js'
import { createHttpError } from '../../utils/http.js'
import { nowIso } from '../../utils/time.js'
import type { AdminSession } from '../admin/admin-auth-service.js'
+import {
+ buildManualFulfillmentNote,
+ buildManualFulfillmentReference,
+} from './manual-fulfillment-note.js'
import {
consumePlatformCredit,
type PlatformCreditKey,
@@ -175,6 +179,7 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm
cost_mode: string
credit_unit_price_fen: string
work_order_id: number | null
+ work_order_no: string | null
work_product_rule_id: number | null
fulfilled_at: string | null
}>(
@@ -203,6 +208,7 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm
COALESCE(cfg.cost_mode, 'variable') AS cost_mode,
COALESCE((fp.config_json->>'rechargeUnitPriceFen')::bigint, 1) AS credit_unit_price_fen,
wo.id AS work_order_id,
+ wo.work_order_no,
wo.product_rule_id AS work_product_rule_id,
fulfilled.fulfilled_at
FROM order_items oi
@@ -210,7 +216,7 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm
LEFT JOIN manual_fulfillment_configs cfg ON cfg.id = oi.fulfillment_config_id
LEFT JOIN fulfillment_profiles fp ON fp.profile_key = 'manual_' || cfg.platform_key
LEFT JOIN LATERAL (
- SELECT id, product_rule_id FROM work_orders
+ SELECT id, product_rule_id, work_order_no FROM work_orders
WHERE order_item_id = oi.id ORDER BY id DESC LIMIT 1
) wo ON TRUE
LEFT JOIN fulfilled ON fulfilled.order_item_id = oi.id
@@ -267,6 +273,11 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm
const note = optionalText(payload.note, 300)
const payeeName = optionalText(payload.payeeName ?? payload.payee_name, 120)
+ const fulfillmentReference = buildManualFulfillmentReference({
+ workOrderNo: row.work_order_no,
+ platformOrderId: row.platform_order_id,
+ orderItemId,
+ })
// 1. 先扣额度(积分平台走积分钱包;备用金现金走现有 fund_* 链路)。
let creditEntryId: number | null = null
@@ -288,7 +299,12 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm
orderItemId,
paidAt: now,
evidence: [],
- note: buildFundNote(row.sku_name, note),
+ note: buildManualFulfillmentNote({
+ skuName: row.sku_name,
+ reference: fulfillmentReference,
+ note,
+ maxLength: 500,
+ }),
actorUserId: session.userId,
})
})
@@ -300,7 +316,13 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm
platformKey: platformKey as PlatformCreditKey,
quantity: creditQuantity,
relatedTaskId: null,
- note: buildCreditNote(row.sku_name, note),
+ platformRef: row.work_order_no || row.platform_order_id,
+ note: buildManualFulfillmentNote({
+ skuName: row.sku_name,
+ reference: fulfillmentReference,
+ note,
+ maxLength: 300,
+ }),
})
creditEntryId = consumed.entryId
balanceAfter = consumed.balanceAfter
@@ -500,18 +522,6 @@ function mapPending(row: PendingRow) {
}
}
-function buildFundNote(skuName: string, note: string) {
- const parts = [`人工履约 ${skuName}`.trim()]
- if (note) parts.push(note)
- return parts.join(' · ').slice(0, 500)
-}
-
-function buildCreditNote(skuName: string, note: string) {
- const parts = [`人工履约 ${skuName}`.trim()]
- if (note) parts.push(note)
- return parts.join(' · ').slice(0, 300)
-}
-
function normalizeCostFen(value: unknown) {
const parsed = Number(value)
if (!Number.isFinite(parsed) || parsed < 0) {
diff --git a/apps/frontend/src/layouts/AdminLayout.tsx b/apps/frontend/src/layouts/AdminLayout.tsx
index a041b7c3..7accd7a8 100644
--- a/apps/frontend/src/layouts/AdminLayout.tsx
+++ b/apps/frontend/src/layouts/AdminLayout.tsx
@@ -136,7 +136,7 @@ export default function AdminLayout() {
{ key: '/admin/finance', icon: , label: '财务' },
{ key: '/admin/sales-profit', icon: , label: '销售毛利' },
{ key: '/admin/cost-center', icon: , label: '商品与成本' },
- { key: '/admin/fund', icon: , label: '备用金' },
+ { key: '/admin/fund', icon: , label: '钱包管理' },
{ key: '/admin/worker-platform', icon: , label: '资金审核' },
]
: [
@@ -145,7 +145,7 @@ export default function AdminLayout() {
{
key: '/admin/fund',
icon: ,
- label: role === 'support' ? '我的钱包' : '备用金',
+ label: role === 'support' ? '我的钱包' : '钱包管理',
},
...(role === 'support'
? []
diff --git a/apps/frontend/src/pages/admin/AdminManualFulfillmentPage.tsx b/apps/frontend/src/pages/admin/AdminManualFulfillmentPage.tsx
index 83143b40..14408991 100644
--- a/apps/frontend/src/pages/admin/AdminManualFulfillmentPage.tsx
+++ b/apps/frontend/src/pages/admin/AdminManualFulfillmentPage.tsx
@@ -87,7 +87,10 @@ export default function AdminManualFulfillmentPage() {
void queryClient.invalidateQueries({
queryKey: ['admin-manual-fulfillment-pending'],
})
+ void queryClient.invalidateQueries({ queryKey: ['admin-fund-my'] })
+ void queryClient.invalidateQueries({ queryKey: ['admin-fund-accounts'] })
void queryClient.invalidateQueries({ queryKey: ['admin-platform-credit-accounts'] })
+ void queryClient.invalidateQueries({ queryKey: ['admin-platform-credit-entries'] })
},
onError: (error) => {
message.error(error instanceof Error ? error.message : '确认履约失败')
diff --git a/apps/frontend/src/pages/admin/fund/FundManagementView.tsx b/apps/frontend/src/pages/admin/fund/FundManagementView.tsx
index 8f7a2454..5fa3a07a 100644
--- a/apps/frontend/src/pages/admin/fund/FundManagementView.tsx
+++ b/apps/frontend/src/pages/admin/fund/FundManagementView.tsx
@@ -156,6 +156,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
const canIssue = role === 'admin' || role === 'operator'
const canReconcile = role === 'admin' || role === 'operator' || role === 'finance'
const canExpense = role === 'admin'
+ const canManageCredits = role === 'admin' || role === 'finance'
const [activeTab, setActiveTab] = useState('overview')
const [submitting, setSubmitting] = useState(false)
@@ -875,8 +876,8 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
return (
} loading={overviewQuery.isFetching} onClick={refreshAll}>
刷新
@@ -902,7 +903,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
items={[
{
key: 'overview',
- label: '总览',
+ label: '钱包总览',
children: (
@@ -997,14 +998,25 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
发放备用金
) : null}
+ {canManageCredits ? (
+ }
+ onClick={() => setActiveTab('platform-credits')}
+ >
+ 分配客服积分
+
+ ) : null}
{canExpense ? (
} onClick={() => openExpense()}>
登记支出
) : null}
{canReconcile ? (
- } onClick={() => openReconcile()}>
- 发起对账
+ }
+ onClick={() => setActiveTab('reconciliations')}
+ >
+ 对账中心
) : null}
{isAdmin ? : null}
@@ -1024,7 +1036,7 @@ export default function FundManagementView({ role }: { role: ManagementRole }) {
},
{
key: 'agents',
- label: '客服余额',
+ label: '客服现金钱包',
children: (
,
},
{
key: 'expenses',
- label: '支出明细',
+ label: '现金支出',
children: (
openReconcile()}>
diff --git a/apps/frontend/src/pages/admin/fund/FundSupportView.tsx b/apps/frontend/src/pages/admin/fund/FundSupportView.tsx
index 25576884..584ca31a 100644
--- a/apps/frontend/src/pages/admin/fund/FundSupportView.tsx
+++ b/apps/frontend/src/pages/admin/fund/FundSupportView.tsx
@@ -96,13 +96,18 @@ export default function FundSupportView() {
const entries = data?.entries || []
const expenses = data?.expenses || []
+ // 全局 staleTime=Infinity:钱包页每次进入都重新拉取,停留期间也轮询最新流水。
const creditAccountsQuery = useQuery({
queryKey: ['admin-platform-credit-accounts'],
queryFn: fetchAdminPlatformCreditAccounts,
+ refetchOnMount: 'always',
+ refetchInterval: 15_000,
})
const creditEntriesQuery = useQuery({
queryKey: ['admin-platform-credit-entries', 'mine'],
queryFn: () => fetchAdminPlatformCreditEntries({ pageSize: 50 }),
+ refetchOnMount: 'always',
+ refetchInterval: 15_000,
})
const creditAccounts = creditAccountsQuery.data?.data.items || []
const creditEntries = creditEntriesQuery.data?.data.items || []
@@ -247,7 +252,8 @@ export default function FundSupportView() {
{
title: '平台',
dataIndex: 'platformKey',
- width: 100,
+ width: 110,
+ align: 'center',
render: (value: string, row) => (
{row.platformLabel}
@@ -257,7 +263,8 @@ export default function FundSupportView() {
{
title: '类型',
dataIndex: 'entryType',
- width: 80,
+ width: 88,
+ align: 'center',
render: (value: string) => (
{value === 'grant'
@@ -273,8 +280,8 @@ export default function FundSupportView() {
{
title: '变动',
dataIndex: 'quantityDelta',
- width: 100,
- align: 'right',
+ width: 110,
+ align: 'center',
render: (value: number) =>
value > 0 ? (
+{value}
@@ -285,26 +292,32 @@ export default function FundSupportView() {
{
title: '余额',
dataIndex: 'balanceAfter',
- width: 100,
- align: 'right',
+ width: 120,
+ align: 'center',
},
{
title: '折合金额',
dataIndex: 'amountFen',
- width: 110,
- align: 'right',
+ width: 120,
+ align: 'center',
render: (value: number) => `¥${(Number(value || 0) / 100).toFixed(2)}`,
},
{
title: '备注',
dataIndex: 'note',
+ width: 320,
+ align: 'center',
+ ellipsis: true,
render: (value: string) => value || '-',
},
{
title: '时间',
dataIndex: 'createdAt',
- width: 150,
- render: (value: string) => formatAdminDateTime(value),
+ width: 180,
+ align: 'center',
+ render: (value: string) => (
+ {formatAdminDateTime(value)}
+ ),
},
]
@@ -378,7 +391,9 @@ export default function FundSupportView() {
extra={
}
- loading={myQuery.isFetching || creditAccountsQuery.isFetching}
+ loading={
+ myQuery.isFetching || creditAccountsQuery.isFetching || creditEntriesQuery.isFetching
+ }
onClick={refresh}
>
刷新
@@ -489,7 +504,8 @@ export default function FundSupportView() {
dataSource={creditEntries}
loading={creditEntriesQuery.isLoading}
pagination={false}
- scroll={{ x: 900 }}
+ scroll={{ x: 1048 }}
+ tableLayout="fixed"
locale={{ emptyText: '还没有积分流水' }}
/>
),
diff --git a/apps/frontend/src/pages/admin/fund/PlatformCreditPanel.tsx b/apps/frontend/src/pages/admin/fund/PlatformCreditPanel.tsx
index dddd7cda..0fa088d6 100644
--- a/apps/frontend/src/pages/admin/fund/PlatformCreditPanel.tsx
+++ b/apps/frontend/src/pages/admin/fund/PlatformCreditPanel.tsx
@@ -35,9 +35,10 @@ import {
adjustAdminPlatformCredit,
fetchAdminPlatformCreditAccounts,
fetchAdminPlatformCreditEntries,
+ fetchAdminPlatformCreditOwners,
grantAdminPlatformCredit,
} from '@/services/admin'
-import type { PlatformCreditAccount, PlatformCreditEntry } from '@/types/admin'
+import type { PlatformCreditAccount, PlatformCreditEntry, PlatformCreditOwner } from '@/types/admin'
import { hasAdminPermission } from '@/utils/admin-auth'
import { formatAdminDateTime } from '@/utils/admin-time'
@@ -88,9 +89,16 @@ export function PlatformCreditPanel() {
const canManage = hasAdminPermission('finance.config')
+ const ownersQuery = useQuery({
+ queryKey: ['admin-platform-credit-owners'],
+ queryFn: fetchAdminPlatformCreditOwners,
+ enabled: canManage,
+ })
const accountsQuery = useQuery({
queryKey: ['admin-platform-credit-accounts'],
queryFn: fetchAdminPlatformCreditAccounts,
+ refetchOnMount: 'always',
+ refetchInterval: 30_000,
})
const entriesQuery = useQuery({
queryKey: ['admin-platform-credit-entries', platformFilter],
@@ -99,6 +107,8 @@ export function PlatformCreditPanel() {
platformKey: platformFilter || undefined,
pageSize: 50,
}),
+ refetchOnMount: 'always',
+ refetchInterval: 30_000,
})
const grantMutation = useMutation({
@@ -113,14 +123,14 @@ export function PlatformCreditPanel() {
onSuccess: (response) => {
const result = response.data
message.success(
- `已充值 ${result.quantity} 积分,折合 ¥${(result.amountFen / 100).toFixed(2)}`,
+ `已分配 ${result.quantity} 积分,折合 ¥${(result.amountFen / 100).toFixed(2)}`,
)
setGrantOpen(false)
void queryClient.invalidateQueries({ queryKey: ['admin-platform-credit-accounts'] })
void queryClient.invalidateQueries({ queryKey: ['admin-platform-credit-entries'] })
},
onError: (error) => {
- message.error(error instanceof Error ? error.message : '充值失败')
+ message.error(error instanceof Error ? error.message : '分配失败')
},
})
@@ -147,18 +157,128 @@ export function PlatformCreditPanel() {
const accounts = accountsQuery.data?.data.items || []
const platforms = accountsQuery.data?.data.platforms || []
const entries = entriesQuery.data?.data.items || []
+ const owners: PlatformCreditOwner[] = ownersQuery.data?.data.items || []
+ const ownerOptions = owners.map((owner) => ({
+ value: owner.id,
+ label:
+ owner.displayName && owner.displayName !== owner.username
+ ? `${owner.displayName}(${owner.username})`
+ : owner.username,
+ }))
+ const visibleAccounts = (
+ platformFilter ? accounts.filter((item) => item.platformKey === platformFilter) : accounts
+ )
+ .slice()
+ .sort(
+ (left, right) =>
+ left.ownerName.localeCompare(right.ownerName, 'zh-CN') ||
+ left.platformKey.localeCompare(right.platformKey),
+ )
+
+ function openGrant(account?: PlatformCreditAccount) {
+ grantForm.resetFields()
+ if (account) {
+ grantForm.setFieldsValue({
+ ownerAdminUserId: account.ownerAdminUserId,
+ platformKey: account.platformKey,
+ })
+ }
+ setGrantOpen(true)
+ }
+
+ function openAdjust(account?: PlatformCreditAccount) {
+ adjustForm.resetFields()
+ if (account) {
+ adjustForm.setFieldsValue({
+ ownerAdminUserId: account.ownerAdminUserId,
+ platformKey: account.platformKey,
+ })
+ }
+ setAdjustOpen(true)
+ }
+
+ const accountColumns: TableColumnsType = [
+ {
+ title: '客服',
+ dataIndex: 'ownerName',
+ width: 160,
+ align: 'center',
+ render: (value: string) => value || '-',
+ },
+ {
+ title: '平台',
+ dataIndex: 'platformKey',
+ width: 130,
+ align: 'center',
+ render: (value: string, row) => (
+ {row.platformLabel}
+ ),
+ },
+ {
+ title: '积分余额',
+ dataIndex: 'balanceQuantity',
+ width: 140,
+ align: 'center',
+ render: (value: number, row) => `${value} ${row.unitName}`,
+ },
+ {
+ title: '折合金额',
+ dataIndex: 'balanceAmountFen',
+ width: 130,
+ align: 'center',
+ render: (value: number) => `¥${(Number(value || 0) / 100).toFixed(2)}`,
+ },
+ {
+ title: '状态',
+ dataIndex: 'status',
+ width: 100,
+ align: 'center',
+ render: (value: string) =>
+ value === 'active' ? 正常 : {value},
+ },
+ {
+ title: '更新时间',
+ dataIndex: 'updatedAt',
+ width: 180,
+ align: 'center',
+ render: (value: string) => (
+ {formatAdminDateTime(value)}
+ ),
+ },
+ {
+ title: '操作',
+ key: 'actions',
+ width: 150,
+ align: 'center',
+ render: (_, account) =>
+ canManage ? (
+
+
+
+
+ ) : (
+ '-'
+ ),
+ },
+ ]
const entryColumns: TableColumnsType = [
{
title: '客服',
dataIndex: 'ownerName',
width: 110,
+ align: 'center',
render: (value: string) => value || '-',
},
{
title: '平台',
dataIndex: 'platformKey',
width: 100,
+ align: 'center',
render: (value: string, row) => (
{row.platformLabel}
),
@@ -167,6 +287,7 @@ export function PlatformCreditPanel() {
title: '类型',
dataIndex: 'entryType',
width: 80,
+ align: 'center',
render: (value: string) => (
{ENTRY_TYPE_LABELS[value] || value}
),
@@ -175,7 +296,7 @@ export function PlatformCreditPanel() {
title: '变动',
dataIndex: 'quantityDelta',
width: 100,
- align: 'right',
+ align: 'center',
render: (value: number) =>
value > 0 ? (
+{value}
@@ -187,45 +308,49 @@ export function PlatformCreditPanel() {
title: '余额',
dataIndex: 'balanceAfter',
width: 100,
- align: 'right',
+ align: 'center',
},
{
title: '金额',
dataIndex: 'amountFen',
width: 110,
- align: 'right',
+ align: 'center',
render: (value: number) => `¥${(Number(value || 0) / 100).toFixed(2)}`,
},
{
title: '备注',
dataIndex: 'note',
+ align: 'center',
render: (value: string) => value || '-',
},
{
title: '时间',
dataIndex: 'createdAt',
- width: 150,
- render: (value: string) => formatAdminDateTime(value),
+ width: 180,
+ align: 'center',
+ render: (value: string) => (
+ {formatAdminDateTime(value)}
+ ),
},
]
return (
-
+
-
+
{platforms.map((platform) => {
const total = accounts
.filter((item) => item.platformKey === platform.key)
.reduce((sum, item) => sum + item.balanceQuantity, 0)
return (
-
+
{canManage ? (
<>
- }
- onClick={() => {
- grantForm.resetFields()
- setGrantOpen(true)
- }}
- >
- 充值积分
-
-
+ openAdjust()}>调整余额
>
) : null}
+
+ 客服积分余额
+
+
+ rowKey="id"
+ size="small"
+ columns={accountColumns}
+ dataSource={visibleAccounts}
+ loading={accountsQuery.isLoading}
+ scroll={{ x: 1080 }}
+ pagination={{ pageSize: 20, showSizeChanger: true }}
+ locale={{ emptyText: '还没有客服积分账户' }}
+ />
+
+
+ 积分流水
+
{
@@ -313,9 +441,14 @@ export function PlatformCreditPanel() {
name="ownerAdminUserId"
label="客服"
rules={[{ required: true, message: '请选择客服' }]}
- extra="客服 ID(管理员用户 id)"
>
-
+
@@ -347,7 +480,7 @@ export function PlatformCreditPanel() {
-
+
('/api/v1/admin/cost-center/platform-credits/owners')
+}
+
export function fetchAdminPlatformCreditEntries(
params: {
page?: number
diff --git a/apps/frontend/src/types/admin/cost-center.ts b/apps/frontend/src/types/admin/cost-center.ts
index c3614ed9..665d108c 100644
--- a/apps/frontend/src/types/admin/cost-center.ts
+++ b/apps/frontend/src/types/admin/cost-center.ts
@@ -418,6 +418,16 @@ export interface PlatformCreditAccountListResult {
}>
}
+export interface PlatformCreditOwner {
+ id: number
+ username: string
+ displayName: string
+}
+
+export interface PlatformCreditOwnerListResult {
+ items: PlatformCreditOwner[]
+}
+
export interface PlatformCreditEntry {
id: number
accountId: number