系数字段修改

This commit is contained in:
zwgczx committed 2026-03-07 17:52:33 +08:00
1 parent 21d3f0379c
commit fc26a87bee
12 files changed
+782 -105

No files matched your search

+152 -2
View File
@@ -121,6 +121,20 @@ const getDefaultMajorFactorById = (id: string) => {
return toFiniteNumberOrNull(major?.defCoe)
}
const isCostMajorById = (id: string) => {
const resolvedId = majorById.has(id) ? id : majorIdAliasMap.get(id) || id
const major = majorById.get(resolvedId)
if (!major) return false
return major.hasCost !== false
}
const isAreaMajorById = (id: string) => {
const resolvedId = majorById.has(id) ? id : majorIdAliasMap.get(id) || id
const major = majorById.get(resolvedId)
if (!major) return false
return major.hasArea !== false
}
const isDualScaleMajorById = (id: string) => {
const resolvedId = majorById.has(id) ? id : majorIdAliasMap.get(id) || id
const major = majorById.get(resolvedId)
@@ -299,6 +313,44 @@ const getOnlyCostScaleBudgetFee = (
})
}
const buildOnlyCostScaleDetailRows = (
serviceId: string,
rowsFromDb: Array<Record<string, unknown>> | undefined,
consultCategoryFactorMap?: Map<string, number | null>,
majorFactorMap?: Map<string, number | null>,
industryId?: string | null
) => {
const totalAmount = sumByNumber(rowsFromDb || [], row =>
typeof row?.amount === 'number' && Number.isFinite(row.amount) ? row.amount : null
)
const onlyRow = (rowsFromDb || []).find(row => String(row?.id || '') === ONLY_COST_SCALE_ROW_ID)
const consultCategoryFactor =
toFiniteNumberOrNull(onlyRow?.consultCategoryFactor) ??
consultCategoryFactorMap?.get(String(serviceId)) ??
getDefaultConsultCategoryFactor(serviceId)
const industryMajorEntry = getIndustryMajorEntryByIndustryId(industryId)
const majorFactor =
toFiniteNumberOrNull(onlyRow?.majorFactor) ??
(industryMajorEntry ? majorFactorMap?.get(industryMajorEntry.id) ?? null : null) ??
toFiniteNumberOrNull(industryMajorEntry?.item?.defCoe) ??
1
const workStageFactor = toFiniteNumberOrNull(onlyRow?.workStageFactor) ?? 1
const workRatio = toFiniteNumberOrNull(onlyRow?.workRatio) ?? 100
return [
{
id: ONLY_COST_SCALE_ROW_ID,
amount: totalAmount,
consultCategoryFactor,
majorFactor,
workStageFactor,
workRatio,
benchmarkBudgetBasicChecked: typeof onlyRow?.benchmarkBudgetBasicChecked === 'boolean' ? onlyRow.benchmarkBudgetBasicChecked : true,
benchmarkBudgetOptionalChecked: typeof onlyRow?.benchmarkBudgetOptionalChecked === 'boolean' ? onlyRow.benchmarkBudgetOptionalChecked : true
}
]
}
const getLandBudgetFee = (row: ScaleRow) => {
return getScaleBudgetFee({
benchmarkBudget: getBenchmarkBudgetByLandArea(row.landArea),
@@ -484,7 +536,7 @@ export const getPricingMethodTotalsForService = async (params: {
majorFactorMap,
industryId
)
: (() => {
: (() => {
const investRows = resolveScaleRows(
serviceId,
investData,
@@ -493,6 +545,7 @@ export const getPricingMethodTotalsForService = async (params: {
majorFactorMap
)
return sumByNumber(investRows, row => {
if (!isCostMajorById(row.id)) return null
if (excludeInvestmentCostAndAreaRows && isDualScaleMajorById(row.id)) return null
return getInvestmentBudgetFee(row)
})
@@ -505,7 +558,7 @@ export const getPricingMethodTotalsForService = async (params: {
consultCategoryFactorMap,
majorFactorMap
)
const landScale = sumByNumber(landRows, row => getLandBudgetFee(row))
const landScale = sumByNumber(landRows, row => (isAreaMajorById(row.id) ? getLandBudgetFee(row) : null))
const defaultWorkloadRows = buildDefaultWorkloadRows(serviceId, consultCategoryFactorMap)
const workload =
@@ -532,6 +585,103 @@ export const getPricingMethodTotalsForService = async (params: {
}
}
export const ensurePricingMethodDetailRowsForServices = async (params: {
contractId: string
serviceIds: Array<string | number>
options?: PricingMethodTotalsOptions
}) => {
const uniqueServiceIds = Array.from(new Set(params.serviceIds.map(serviceId => String(serviceId))))
if (uniqueServiceIds.length === 0) return
const htDbKey = `ht-info-v3-${params.contractId}`
const consultFactorDbKey = `ht-consult-category-factor-v1-${params.contractId}`
const majorFactorDbKey = `ht-major-factor-v1-${params.contractId}`
const baseInfoDbKey = 'xm-base-info-v1'
const [htData, consultFactorData, majorFactorData, baseInfo] = await Promise.all([
localforage.getItem<StoredDetailRowsState>(htDbKey),
localforage.getItem<StoredFactorState>(consultFactorDbKey),
localforage.getItem<StoredFactorState>(majorFactorDbKey),
localforage.getItem<XmBaseInfoState>(baseInfoDbKey)
])
const consultCategoryFactorMap = buildConsultCategoryFactorMap(consultFactorData)
const majorFactorMap = buildMajorFactorMap(majorFactorData)
const industryId = typeof baseInfo?.projectIndustry === 'string' ? baseInfo.projectIndustry.trim() : ''
const excludeInvestmentCostAndAreaRows = params.options?.excludeInvestmentCostAndAreaRows === true
await Promise.all(
uniqueServiceIds.map(async serviceId => {
const investDbKey = `tzGMF-${params.contractId}-${serviceId}`
const landDbKey = `ydGMF-${params.contractId}-${serviceId}`
const workloadDbKey = `gzlF-${params.contractId}-${serviceId}`
const hourlyDbKey = `hourlyPricing-${params.contractId}-${serviceId}`
const [investData, landData, workloadData, hourlyData] = await Promise.all([
localforage.getItem<StoredDetailRowsState>(investDbKey),
localforage.getItem<StoredDetailRowsState>(landDbKey),
localforage.getItem<StoredDetailRowsState>(workloadDbKey),
localforage.getItem<StoredDetailRowsState>(hourlyDbKey)
])
const shouldInitInvest = !Array.isArray(investData?.detailRows) || investData!.detailRows!.length === 0
const shouldInitLand = !Array.isArray(landData?.detailRows) || landData!.detailRows!.length === 0
const shouldInitWorkload = !Array.isArray(workloadData?.detailRows) || workloadData!.detailRows!.length === 0
const shouldInitHourly = !Array.isArray(hourlyData?.detailRows) || hourlyData!.detailRows!.length === 0
const writeTasks: Promise<unknown>[] = []
if (shouldInitInvest) {
const onlyCostScale = isOnlyCostScaleService(serviceId)
const investRows = onlyCostScale
? buildOnlyCostScaleDetailRows(
serviceId,
(htData?.detailRows as Array<Record<string, unknown>> | undefined),
consultCategoryFactorMap,
majorFactorMap,
industryId
)
: resolveScaleRows(
serviceId,
null,
htData,
consultCategoryFactorMap,
majorFactorMap
).filter(row => {
if (!isCostMajorById(row.id)) return false
if (excludeInvestmentCostAndAreaRows && isDualScaleMajorById(row.id)) return false
return true
})
writeTasks.push(localforage.setItem(investDbKey, { detailRows: investRows }))
}
if (shouldInitLand) {
const landRows = resolveScaleRows(
serviceId,
null,
htData,
consultCategoryFactorMap,
majorFactorMap
).filter(row => isAreaMajorById(row.id))
writeTasks.push(localforage.setItem(landDbKey, { detailRows: landRows }))
}
if (shouldInitWorkload) {
const workloadRows = buildDefaultWorkloadRows(serviceId, consultCategoryFactorMap)
writeTasks.push(localforage.setItem(workloadDbKey, { detailRows: workloadRows }))
}
if (shouldInitHourly) {
const hourlyRows = buildDefaultHourlyRows()
writeTasks.push(localforage.setItem(hourlyDbKey, { detailRows: hourlyRows }))
}
if (writeTasks.length > 0) {
await Promise.all(writeTasks)
}
})
)
}
export const getPricingMethodTotalsForServices = async (params: {
contractId: string
serviceIds: Array<string | number>