calculator2026/src/lib/xmFactorDefaults.ts

101 lines
3.0 KiB
TypeScript

import { getMajorDictById, getMajorIdAliasMap, getServiceDictById } from '@/sql'
import { toFiniteNumberOrNull } from '@/lib/decimal'
import { useKvStore } from '@/pinia/kv'
import { useZxFwPricingStore } from '@/pinia/zxFwPricing'
const CONSULT_CATEGORY_FACTOR_KEY = 'xm-consult-category-factor-v1'
const MAJOR_FACTOR_KEY = 'xm-major-factor-v1'
type XmFactorRow = {
id: string
standardFactor: number | null
budgetValue: number | null
}
type XmFactorState = {
detailRows?: XmFactorRow[]
}
type FactorDictItem = {
defCoe?: number | null
}
type FactorDict = Record<string, FactorDictItem>
const hasUsableFactorRows = (state: XmFactorState | null | undefined) =>
Array.isArray(state?.detailRows) &&
state.detailRows.some(row => {
const hasFactor =
toFiniteNumberOrNull(row?.budgetValue) != null ||
toFiniteNumberOrNull(row?.standardFactor) != null
return hasFactor || String(row?.id || '').trim() !== ''
})
const buildStandardFactorMap = (dict: FactorDict): Map<string, number | null> => {
const map = new Map<string, number | null>()
for (const [id, item] of Object.entries(dict)) {
map.set(String(id), toFiniteNumberOrNull(item?.defCoe))
}
return map
}
const resolveFactorValue = (
row: Partial<XmFactorRow> | undefined,
fallbackStandard: number | null
): number | null => {
if (!row) return null
if (Object.prototype.hasOwnProperty.call(row, 'budgetValue')) {
return toFiniteNumberOrNull(row.budgetValue)
}
if (Object.prototype.hasOwnProperty.call(row, 'standardFactor')) {
return toFiniteNumberOrNull(row.standardFactor)
}
return fallbackStandard
}
const getKvStoreSafely = () => {
try {
return useKvStore()
} catch {
return null
}
}
const getZxFwPricingStoreSafely = () => {
try {
return useZxFwPricingStore()
} catch {
return null
}
}
const loadFactorMap = async (
storageKey: string,
dict: FactorDict,
aliases?: Map<string, string>
): Promise<Map<string, number | null>> => {
const zxFwPricingStore = getZxFwPricingStoreSafely()
const kvStore = getKvStoreSafely()
const piniaData = zxFwPricingStore ? await zxFwPricingStore.loadKeyState<XmFactorState>(storageKey) : null
const kvData = kvStore ? await kvStore.getItem<XmFactorState>(storageKey) : null
const data = hasUsableFactorRows(piniaData)
? piniaData
: hasUsableFactorRows(kvData)
? kvData
: (piniaData ?? kvData)
const map = buildStandardFactorMap(dict)
for (const row of data?.detailRows || []) {
if (!row?.id) continue
const rowId = String(row.id)
const id = map.has(rowId) ? rowId : aliases?.get(rowId) || rowId
map.set(id, resolveFactorValue(row, map.get(id) ?? null))
}
return map
}
export const loadConsultCategoryFactorMap = async (storageKey = CONSULT_CATEGORY_FACTOR_KEY) =>
loadFactorMap(storageKey, getServiceDictById() as FactorDict)
export const loadMajorFactorMap = async (storageKey = MAJOR_FACTOR_KEY) =>
loadFactorMap(storageKey, getMajorDictById() as FactorDict, getMajorIdAliasMap())