95 lines
3.5 KiB
TypeScript
95 lines
3.5 KiB
TypeScript
import type { FirstLegOrderStatus } from '@chongchong/shared'
|
|
import type { MerchantFirstLegOrderRow, MerchantUnifiedOrderRow } from '@/modules/first-leg/public'
|
|
import type { MerchantTenantStatus } from '@/modules/tenant-management/public'
|
|
|
|
export interface DashboardCompany {
|
|
tenantName: string
|
|
status: MerchantTenantStatus
|
|
}
|
|
|
|
export interface DashboardOrder {
|
|
id: string
|
|
orderNo: string | null
|
|
inboundCode: string | null
|
|
destination: string | null
|
|
channel: string | null
|
|
status: FirstLegOrderStatus
|
|
createdAt: string
|
|
requiresFeeConfirmation: boolean
|
|
}
|
|
|
|
export type DashboardSource = 'company' | 'orders' | 'drafts'
|
|
|
|
export interface DashboardOverview {
|
|
company: DashboardCompany | null
|
|
orders: DashboardOrder[]
|
|
drafts: DashboardOrder[]
|
|
errors: Partial<Record<DashboardSource, string>>
|
|
}
|
|
|
|
interface DashboardRequests {
|
|
company: () => Promise<DashboardCompany>
|
|
orders: () => Promise<{ records: MerchantUnifiedOrderRow[] }>
|
|
drafts: () => Promise<{ records: MerchantFirstLegOrderRow[] }>
|
|
}
|
|
|
|
const sourceErrorMessages: Record<DashboardSource, string> = {
|
|
company: '企业资料加载失败,请重试',
|
|
orders: '订单动态加载失败,请重试',
|
|
drafts: '订单草稿加载失败,请重试',
|
|
}
|
|
|
|
function newestFirst(records: DashboardOrder[]) {
|
|
return records.sort((left, right) => (Date.parse(right.createdAt) || 0) - (Date.parse(left.createdAt) || 0))
|
|
}
|
|
|
|
export async function loadDashboardOverview(permissions: readonly string[], requests: DashboardRequests): Promise<DashboardOverview> {
|
|
const result: DashboardOverview = { company: null, orders: [], drafts: [], errors: {} }
|
|
const allowed = new Set(permissions)
|
|
const tasks: Array<{ source: DashboardSource; run: () => Promise<void> }> = []
|
|
|
|
if (allowed.has('company:profile:view')) {
|
|
tasks.push({ source: 'company', run: async () => { result.company = await requests.company() } })
|
|
}
|
|
if (allowed.has('order:first-leg:list')) {
|
|
tasks.push({ source: 'orders', run: async () => {
|
|
const response = await requests.orders()
|
|
result.orders = newestFirst(response.records.map((order) => ({
|
|
id: String(order.orderId),
|
|
orderNo: order.orderNo ?? null,
|
|
inboundCode: order.inboundCode ?? null,
|
|
destination: order.destinationWarehouseName ?? null,
|
|
channel: order.channelName ?? null,
|
|
status: order.mainStatus,
|
|
createdAt: order.createdAt,
|
|
requiresFeeConfirmation: order.customerFeeConfirmationRequired === true,
|
|
})))
|
|
} })
|
|
if (allowed.has('order:first-leg:edit')) {
|
|
tasks.push({ source: 'drafts', run: async () => {
|
|
const response = await requests.drafts()
|
|
result.drafts = newestFirst(response.records.filter((order) => order.status === 'DRAFT').map((order) => ({
|
|
id: String(order.orderId),
|
|
orderNo: order.orderNo ?? null,
|
|
inboundCode: order.inboundCode ?? null,
|
|
destination: order.destinationWarehouseName ?? null,
|
|
channel: order.channelName ?? null,
|
|
status: 'DRAFT',
|
|
createdAt: order.createdAt,
|
|
requiresFeeConfirmation: false,
|
|
})))
|
|
} })
|
|
}
|
|
}
|
|
|
|
const settled = await Promise.allSettled(tasks.map(async (task) => task.run()))
|
|
settled.forEach((outcome, index) => {
|
|
if (outcome.status === 'fulfilled') return
|
|
const source = tasks[index]!.source
|
|
result.errors[source] = outcome.reason instanceof Error && outcome.reason.message.trim()
|
|
? outcome.reason.message
|
|
: sourceErrorMessages[source]
|
|
})
|
|
return result
|
|
}
|