120 lines
4.0 KiB
TypeScript
120 lines
4.0 KiB
TypeScript
import { getBasicFeeFromScale } from '@/sql'
|
|
import { addNumbers, roundTo, toDecimal } from '@/lib/decimal'
|
|
import { toFiniteNumberOrNull } from '@/lib/number'
|
|
|
|
type ScaleMode = 'cost' | 'area'
|
|
|
|
export interface ScaleFeeSplitResult {
|
|
basic: number
|
|
optional: number
|
|
total: number
|
|
basicFormula: string
|
|
optionalFormula: string
|
|
}
|
|
|
|
export const getBenchmarkBudgetSplitByScale = (
|
|
value: unknown,
|
|
mode: ScaleMode
|
|
): ScaleFeeSplitResult | null => {
|
|
const scaleValue = toFiniteNumberOrNull(value)
|
|
const result = getBasicFeeFromScale(scaleValue, mode)
|
|
if (!result) return null
|
|
|
|
const basic = roundTo(result.basic, 2)
|
|
const optional = roundTo(result.optional, 2)
|
|
const basicFormula = typeof result.basicFormula === 'string' ? result.basicFormula : ''
|
|
const optionalFormula = typeof result.optionalFormula === 'string' ? result.optionalFormula : ''
|
|
return {
|
|
basic,
|
|
optional,
|
|
total: roundTo(addNumbers(basic, optional), 2),
|
|
basicFormula,
|
|
optionalFormula
|
|
}
|
|
}
|
|
|
|
export const getBenchmarkBudgetByScale = (value: unknown, mode: ScaleMode) => {
|
|
const splitResult = getBenchmarkBudgetSplitByScale(value, mode)
|
|
return splitResult ? splitResult.total : null
|
|
}
|
|
|
|
export const getScaleBudgetFeeSplit = (params: {
|
|
benchmarkBudgetBasic: unknown
|
|
benchmarkBudgetOptional: unknown
|
|
majorFactor: unknown
|
|
consultCategoryFactor: unknown
|
|
workStageFactor?: unknown
|
|
workRatio?: unknown
|
|
}): ScaleFeeSplitResult | null => {
|
|
const hasWorkStageFactor = Object.prototype.hasOwnProperty.call(params, 'workStageFactor')
|
|
const hasWorkRatio = Object.prototype.hasOwnProperty.call(params, 'workRatio')
|
|
const benchmarkBudgetBasic = toFiniteNumberOrNull(params.benchmarkBudgetBasic)
|
|
const benchmarkBudgetOptional = toFiniteNumberOrNull(params.benchmarkBudgetOptional)
|
|
const majorFactor = toFiniteNumberOrNull(params.majorFactor)
|
|
const consultCategoryFactor = toFiniteNumberOrNull(params.consultCategoryFactor)
|
|
const workStageFactor = hasWorkStageFactor ? toFiniteNumberOrNull(params.workStageFactor) : 1
|
|
const workRatio = hasWorkRatio ? toFiniteNumberOrNull(params.workRatio) : 100
|
|
|
|
if (
|
|
benchmarkBudgetBasic == null ||
|
|
benchmarkBudgetOptional == null ||
|
|
majorFactor == null ||
|
|
consultCategoryFactor == null ||
|
|
workStageFactor == null ||
|
|
workRatio == null
|
|
) {
|
|
return null
|
|
}
|
|
|
|
const multiplier = toDecimal(consultCategoryFactor)
|
|
.mul(majorFactor)
|
|
.mul(workStageFactor)
|
|
.mul(workRatio)
|
|
.div(100)
|
|
const roundedBenchmarkBudget = roundTo(addNumbers(benchmarkBudgetBasic, benchmarkBudgetOptional), 2)
|
|
const basic = roundTo(toDecimal(benchmarkBudgetBasic).mul(multiplier), 2)
|
|
const optional = roundTo(toDecimal(benchmarkBudgetOptional).mul(multiplier), 2)
|
|
|
|
return {
|
|
basic,
|
|
optional,
|
|
total: roundTo(toDecimal(roundedBenchmarkBudget).mul(multiplier), 2),
|
|
basicFormula: '',
|
|
optionalFormula: ''
|
|
}
|
|
}
|
|
|
|
export const getScaleBudgetFee = (params: {
|
|
benchmarkBudget: unknown
|
|
majorFactor: unknown
|
|
consultCategoryFactor: unknown
|
|
workStageFactor?: unknown
|
|
workRatio?: unknown
|
|
}) => {
|
|
const hasWorkStageFactor = Object.prototype.hasOwnProperty.call(params, 'workStageFactor')
|
|
const hasWorkRatio = Object.prototype.hasOwnProperty.call(params, 'workRatio')
|
|
const benchmarkBudget = toFiniteNumberOrNull(params.benchmarkBudget)
|
|
const majorFactor = toFiniteNumberOrNull(params.majorFactor)
|
|
const consultCategoryFactor = toFiniteNumberOrNull(params.consultCategoryFactor)
|
|
const workStageFactor = hasWorkStageFactor ? toFiniteNumberOrNull(params.workStageFactor) : 1
|
|
const workRatio = hasWorkRatio ? toFiniteNumberOrNull(params.workRatio) : 100
|
|
|
|
if (
|
|
benchmarkBudget == null ||
|
|
majorFactor == null ||
|
|
consultCategoryFactor == null ||
|
|
workStageFactor == null ||
|
|
workRatio == null
|
|
) {
|
|
return null
|
|
}
|
|
|
|
const roundedBenchmarkBudget = roundTo(benchmarkBudget, 2)
|
|
const multiplier = toDecimal(consultCategoryFactor)
|
|
.mul(majorFactor)
|
|
.mul(workStageFactor)
|
|
.mul(workRatio)
|
|
.div(100)
|
|
return roundTo(toDecimal(roundedBenchmarkBudget).mul(multiplier), 2)
|
|
}
|