fix
This commit is contained in:
1 parent
ad4e9cdee0
commit
043e1fc879
8 files changed
+529
-112
No files matched your search
@@ -53,10 +53,13 @@ interface HourlyRow {
|
||||
interface MajorLite {
|
||||
code: string
|
||||
defCoe: number | null
|
||||
hasCost?: boolean
|
||||
hasArea?: boolean
|
||||
}
|
||||
|
||||
interface ServiceLite {
|
||||
defCoe: number | null
|
||||
onlyCostScale?: boolean | null
|
||||
}
|
||||
|
||||
interface TaskLite {
|
||||
@@ -77,6 +80,12 @@ export interface PricingMethodTotals {
|
||||
hourly: number | null
|
||||
}
|
||||
|
||||
interface PricingMethodTotalsOptions {
|
||||
excludeInvestmentCostAndAreaRows?: boolean
|
||||
}
|
||||
|
||||
const ONLY_COST_SCALE_ROW_ID = '__only-cost-scale-total__'
|
||||
|
||||
const hasOwn = (obj: unknown, key: string) =>
|
||||
Object.prototype.hasOwnProperty.call(obj || {}, key)
|
||||
|
||||
@@ -93,6 +102,11 @@ const getDefaultConsultCategoryFactor = (serviceId: string | number) => {
|
||||
return toFiniteNumberOrNull(service?.defCoe)
|
||||
}
|
||||
|
||||
const isOnlyCostScaleService = (serviceId: string | number) => {
|
||||
const service = (getServiceDictById() as Record<string, ServiceLite | undefined>)[String(serviceId)]
|
||||
return service?.onlyCostScale === true
|
||||
}
|
||||
|
||||
const majorById = new Map(getMajorDictEntries().map(({ id, item }) => [id, item as MajorLite]))
|
||||
const majorIdAliasMap = getMajorIdAliasMap()
|
||||
|
||||
@@ -102,6 +116,15 @@ const getDefaultMajorFactorById = (id: string) => {
|
||||
return toFiniteNumberOrNull(major?.defCoe)
|
||||
}
|
||||
|
||||
const isDualScaleMajorById = (id: string) => {
|
||||
const resolvedId = majorById.has(id) ? id : majorIdAliasMap.get(id) || id
|
||||
const major = majorById.get(resolvedId)
|
||||
if (!major) return false
|
||||
const hasCost = major.hasCost !== false
|
||||
const hasArea = major.hasArea !== false
|
||||
return hasCost && hasArea
|
||||
}
|
||||
|
||||
const resolveFactorValue = (
|
||||
row: { budgetValue?: number | null; standardFactor?: number | null } | undefined,
|
||||
fallback: number | null
|
||||
@@ -227,6 +250,31 @@ const getInvestmentBudgetFee = (row: ScaleRow) => {
|
||||
})
|
||||
}
|
||||
|
||||
const getOnlyCostScaleBudgetFee = (
|
||||
serviceId: string,
|
||||
rowsFromDb: Array<Record<string, unknown>> | undefined,
|
||||
consultCategoryFactorMap?: Map<string, number | 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 majorFactor = toFiniteNumberOrNull(onlyRow?.majorFactor) ?? 1
|
||||
const workStageFactor = toFiniteNumberOrNull(onlyRow?.workStageFactor) ?? 1
|
||||
const workRatio = toFiniteNumberOrNull(onlyRow?.workRatio) ?? 100
|
||||
return getScaleBudgetFee({
|
||||
benchmarkBudget: getBenchmarkBudgetByAmount(totalAmount),
|
||||
majorFactor,
|
||||
consultCategoryFactor,
|
||||
workStageFactor,
|
||||
workRatio
|
||||
})
|
||||
}
|
||||
|
||||
const getLandBudgetFee = (row: ScaleRow) => {
|
||||
return getScaleBudgetFee({
|
||||
benchmarkBudget: getBenchmarkBudgetByLandArea(row.landArea),
|
||||
@@ -373,6 +421,7 @@ const resolveScaleRows = (
|
||||
export const getPricingMethodTotalsForService = async (params: {
|
||||
contractId: string
|
||||
serviceId: string | number
|
||||
options?: PricingMethodTotalsOptions
|
||||
}): Promise<PricingMethodTotals> => {
|
||||
const serviceId = String(params.serviceId)
|
||||
const htDbKey = `ht-info-v3-${params.contractId}`
|
||||
@@ -395,16 +444,30 @@ export const getPricingMethodTotalsForService = async (params: {
|
||||
|
||||
const consultCategoryFactorMap = buildConsultCategoryFactorMap(consultFactorData)
|
||||
const majorFactorMap = buildMajorFactorMap(majorFactorData)
|
||||
const onlyCostScale = isOnlyCostScaleService(serviceId)
|
||||
|
||||
// 优先使用对应计费页的数据;不存在时回退合同段规模信息,再回退默认字典行。
|
||||
const investRows = resolveScaleRows(
|
||||
serviceId,
|
||||
investData,
|
||||
htData,
|
||||
consultCategoryFactorMap,
|
||||
majorFactorMap
|
||||
)
|
||||
const investScale = sumByNumber(investRows, row => getInvestmentBudgetFee(row))
|
||||
const excludeInvestmentCostAndAreaRows = params.options?.excludeInvestmentCostAndAreaRows === true
|
||||
const investScale = onlyCostScale
|
||||
? getOnlyCostScaleBudgetFee(
|
||||
serviceId,
|
||||
(investData?.detailRows as Array<Record<string, unknown>> | undefined) ||
|
||||
(htData?.detailRows as Array<Record<string, unknown>> | undefined),
|
||||
consultCategoryFactorMap
|
||||
)
|
||||
: (() => {
|
||||
const investRows = resolveScaleRows(
|
||||
serviceId,
|
||||
investData,
|
||||
htData,
|
||||
consultCategoryFactorMap,
|
||||
majorFactorMap
|
||||
)
|
||||
return sumByNumber(investRows, row => {
|
||||
if (excludeInvestmentCostAndAreaRows && isDualScaleMajorById(row.id)) return null
|
||||
return getInvestmentBudgetFee(row)
|
||||
})
|
||||
})()
|
||||
|
||||
const landRows = resolveScaleRows(
|
||||
serviceId,
|
||||
@@ -443,13 +506,15 @@ export const getPricingMethodTotalsForService = async (params: {
|
||||
export const getPricingMethodTotalsForServices = async (params: {
|
||||
contractId: string
|
||||
serviceIds: Array<string | number>
|
||||
options?: PricingMethodTotalsOptions
|
||||
}) => {
|
||||
const result = new Map<string, PricingMethodTotals>()
|
||||
await Promise.all(
|
||||
params.serviceIds.map(async serviceId => {
|
||||
const totals = await getPricingMethodTotalsForService({
|
||||
contractId: params.contractId,
|
||||
serviceId
|
||||
serviceId,
|
||||
options: params.options
|
||||
})
|
||||
result.set(String(serviceId), totals)
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user