优化
This commit is contained in:
1 parent
8417f8d5cc
commit
693a9628bc
38 files changed
+3688
-2817
No files matched your search
@@ -0,0 +1,651 @@
|
||||
import { serviceList } from '@/sql'
|
||||
import { roundTo } from '@/lib/decimal'
|
||||
import { getBenchmarkBudgetSplitByScale, getScaleBudgetFeeSplit } from '@/lib/pricingScaleFee'
|
||||
|
||||
interface ScaleMethodRowLike {
|
||||
id: string
|
||||
majorDictId?: unknown
|
||||
amount: number | null
|
||||
landArea: number | null
|
||||
benchmarkBudgetBasicChecked?: unknown
|
||||
benchmarkBudgetOptionalChecked?: unknown
|
||||
basicFormula?: unknown
|
||||
optionalFormula?: unknown
|
||||
budgetFee?: unknown
|
||||
budgetFeeBasic?: unknown
|
||||
budgetFeeOptional?: unknown
|
||||
consultCategoryFactor?: unknown
|
||||
majorFactor?: unknown
|
||||
workStageFactor?: unknown
|
||||
workRatio?: unknown
|
||||
remark?: unknown
|
||||
}
|
||||
|
||||
interface WorkContentRowLike {
|
||||
id?: unknown
|
||||
content?: unknown
|
||||
checked?: unknown
|
||||
custom?: unknown
|
||||
serviceid?: unknown
|
||||
isAddTrigger?: unknown
|
||||
}
|
||||
|
||||
interface FactorRowLike {
|
||||
id: string
|
||||
budgetValue?: unknown
|
||||
remark?: unknown
|
||||
}
|
||||
|
||||
interface ScaleRowLike {
|
||||
id: string
|
||||
amount: number | null
|
||||
landArea: number | null
|
||||
}
|
||||
|
||||
interface WorkloadMethodRowLike {
|
||||
id: string
|
||||
budgetAdoptedUnitPrice?: unknown
|
||||
workload?: unknown
|
||||
basicFee?: unknown
|
||||
consultCategoryFactor?: unknown
|
||||
serviceFee?: unknown
|
||||
remark?: unknown
|
||||
}
|
||||
|
||||
interface HourlyMethodRowLike {
|
||||
id: string
|
||||
adoptedBudgetUnitPrice?: unknown
|
||||
personnelCount?: unknown
|
||||
workdayCount?: unknown
|
||||
serviceBudget?: unknown
|
||||
remark?: unknown
|
||||
}
|
||||
|
||||
interface ZxFwRowLike {
|
||||
id: string
|
||||
process?: unknown
|
||||
subtotal?: unknown
|
||||
finalFee?: unknown
|
||||
investScale?: unknown
|
||||
landScale?: unknown
|
||||
workload?: unknown
|
||||
hourly?: unknown
|
||||
}
|
||||
|
||||
interface RateMethodRowLike {
|
||||
rate?: unknown
|
||||
budgetFee?: unknown
|
||||
}
|
||||
|
||||
interface QuantityMethodRowLike {
|
||||
id?: unknown
|
||||
feeItem?: unknown
|
||||
unit?: unknown
|
||||
quantity?: unknown
|
||||
unitPrice?: unknown
|
||||
budgetFee?: number | null
|
||||
remark?: unknown
|
||||
}
|
||||
|
||||
interface ExportScaleRowLike {
|
||||
majorid: number
|
||||
major: number
|
||||
cost: number | null
|
||||
area: number | null
|
||||
}
|
||||
|
||||
interface ExportServiceCoeLike {
|
||||
serviceid: number
|
||||
coe: number
|
||||
remark: string
|
||||
}
|
||||
|
||||
interface ExportMajorCoeLike {
|
||||
majorid: number
|
||||
coe: number
|
||||
remark: string
|
||||
}
|
||||
|
||||
interface ExportMethod1DetailLike {
|
||||
proNum: number
|
||||
major: number
|
||||
cost: number
|
||||
basicFee: number
|
||||
basicFormula: string
|
||||
basicFee_basic: number
|
||||
optionalFormula: string
|
||||
basicFee_optional: number
|
||||
serviceCoe: number
|
||||
majorCoe: number
|
||||
processCoe: number
|
||||
proportion: number
|
||||
fee: number
|
||||
remark: string
|
||||
}
|
||||
|
||||
interface ExportMethod2DetailLike {
|
||||
proNum: number
|
||||
major: number
|
||||
area: number
|
||||
basicFee: number
|
||||
basicFormula: string
|
||||
basicFee_basic: number
|
||||
optionalFormula: string
|
||||
basicFee_optional: number
|
||||
serviceCoe: number
|
||||
majorCoe: number
|
||||
processCoe: number
|
||||
proportion: number
|
||||
fee: number
|
||||
remark: string
|
||||
}
|
||||
|
||||
interface ExportMethod3DetailLike {
|
||||
task: number
|
||||
price: number
|
||||
amount: number
|
||||
basicFee: number
|
||||
serviceCoe: number
|
||||
fee: number
|
||||
remark: string
|
||||
}
|
||||
|
||||
interface ExportMethod4DetailLike {
|
||||
expert: number
|
||||
price: number
|
||||
person_num: number
|
||||
work_day: number
|
||||
fee: number
|
||||
remark: string
|
||||
}
|
||||
|
||||
interface ExportMethod5DetailLike {
|
||||
name: string
|
||||
unit: string
|
||||
amount: number
|
||||
price: number
|
||||
fee: number
|
||||
remark: string
|
||||
}
|
||||
|
||||
export const toFiniteNumber = (value: unknown): number | null => {
|
||||
if (typeof value === 'number') {
|
||||
return Number.isFinite(value) ? value : null
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
const trimmed = value.trim()
|
||||
if (!trimmed) return null
|
||||
const num = Number(trimmed)
|
||||
return Number.isFinite(num) ? num : null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const toFiniteNumberOrZero = (value: unknown): number => toFiniteNumber(value) ?? 0
|
||||
|
||||
export const toSafeInteger = (value: unknown): number | null => {
|
||||
const num = Number(value)
|
||||
if (!Number.isInteger(num)) return null
|
||||
if (!Number.isSafeInteger(num)) return null
|
||||
return num
|
||||
}
|
||||
|
||||
export const sumNumbers = (values: Array<number | null | undefined>): number =>
|
||||
values.reduce<number>(
|
||||
(sum, value) => sum + (typeof value === 'number' && Number.isFinite(value) ? value : 0),
|
||||
0
|
||||
)
|
||||
|
||||
export const toMoney = (value: unknown): number => roundTo(toFiniteNumber(value) ?? 0, 2)
|
||||
|
||||
export const isNonEmptyString = (value: unknown): value is string =>
|
||||
typeof value === 'string' && value.trim().length > 0
|
||||
|
||||
export const getTaskIdFromRowId = (value: string): number | null => {
|
||||
const match = /^task-(\d+)-\d+$/.exec(value)
|
||||
return match ? toSafeInteger(match[1]) : null
|
||||
}
|
||||
|
||||
export const getExpertIdFromRowId = (value: string): number | null => {
|
||||
const match = /^expert-(\d+)$/.exec(value)
|
||||
return match ? toSafeInteger(match[1]) : null
|
||||
}
|
||||
|
||||
export const hasServiceId = (serviceId: string) =>
|
||||
Object.prototype.hasOwnProperty.call(serviceList as Record<string, unknown>, serviceId)
|
||||
|
||||
export const sortServiceIdsByDict = (ids: string[]) =>
|
||||
[...ids].sort((left, right) => {
|
||||
const leftOrder = Number((serviceList as Record<string, any>)[left]?.order)
|
||||
const rightOrder = Number((serviceList as Record<string, any>)[right]?.order)
|
||||
const safeLeft = Number.isFinite(leftOrder) ? leftOrder : Number.MAX_SAFE_INTEGER
|
||||
const safeRight = Number.isFinite(rightOrder) ? rightOrder : Number.MAX_SAFE_INTEGER
|
||||
return safeLeft - safeRight
|
||||
})
|
||||
|
||||
export const mapIndustryCodeToExportIndustry = (value: unknown): number => {
|
||||
const raw = typeof value === 'string' ? value.trim().toUpperCase() : ''
|
||||
if (!raw) return 0
|
||||
if (raw === '0' || raw === 'E2') return 0
|
||||
if (raw === '1' || raw === 'E3') return 1
|
||||
if (raw === '2' || raw === 'E4') return 2
|
||||
return 0
|
||||
}
|
||||
|
||||
export const parseScaleScopedRowId = (rowId: unknown) => {
|
||||
const raw = String(rowId || '').trim()
|
||||
const scopedMatch = /^(\d+)::(.+)$/.exec(raw)
|
||||
if (scopedMatch) {
|
||||
return {
|
||||
proNum: toSafeInteger(scopedMatch[1]) ?? 1,
|
||||
majorPart: String(scopedMatch[2] || '').trim()
|
||||
}
|
||||
}
|
||||
return {
|
||||
proNum: 1,
|
||||
majorPart: raw
|
||||
}
|
||||
}
|
||||
|
||||
export const toScaleMajorId = (row: ScaleMethodRowLike): number | null => {
|
||||
const direct = toSafeInteger((row as { majorDictId?: unknown }).majorDictId)
|
||||
if (direct != null) return direct
|
||||
const parsed = parseScaleScopedRowId(row.id)
|
||||
return toSafeInteger(parsed.majorPart)
|
||||
}
|
||||
|
||||
export const toScaleProNum = (row: ScaleMethodRowLike): number => {
|
||||
const parsed = parseScaleScopedRowId(row.id)
|
||||
return parsed.proNum > 0 ? parsed.proNum : 1
|
||||
}
|
||||
|
||||
export const normalizeTaskText = (value: unknown): string => String(value || '').trim()
|
||||
|
||||
export const resolveTaskRowServiceId = (row: WorkContentRowLike): number | null =>
|
||||
toSafeInteger((row as { serviceid?: unknown })?.serviceid)
|
||||
|
||||
export const resolveScaleMethodFee = (row: ScaleMethodRowLike, mode: 'cost' | 'area') => {
|
||||
const scaleValue = mode === 'cost' ? toFiniteNumber(row.amount) : toFiniteNumber(row.landArea)
|
||||
const benchmarkSplit = getBenchmarkBudgetSplitByScale(scaleValue, mode)
|
||||
const basicChecked = row.benchmarkBudgetBasicChecked !== false
|
||||
const optionalChecked = row.benchmarkBudgetOptionalChecked !== false
|
||||
const allUnchecked = !basicChecked && !optionalChecked
|
||||
const benchmarkBudgetBasic = benchmarkSplit ? (basicChecked ? benchmarkSplit.basic : 0) : null
|
||||
const benchmarkBudgetOptional = benchmarkSplit ? (optionalChecked ? benchmarkSplit.optional : 0) : null
|
||||
const computedSplit = benchmarkSplit
|
||||
? getScaleBudgetFeeSplit({
|
||||
benchmarkBudgetBasic,
|
||||
benchmarkBudgetOptional,
|
||||
majorFactor: row.majorFactor,
|
||||
consultCategoryFactor: row.consultCategoryFactor,
|
||||
workStageFactor: row.workStageFactor,
|
||||
workRatio: row.workRatio
|
||||
})
|
||||
: null
|
||||
const basicFee = allUnchecked ? null : (toFiniteNumber(row.budgetFee) ?? computedSplit?.total ?? null)
|
||||
const basicFeeBasic = allUnchecked ? null : (toFiniteNumber(row.budgetFeeBasic) ?? computedSplit?.basic ?? null)
|
||||
const basicFeeOptional = allUnchecked ? null : (toFiniteNumber(row.budgetFeeOptional) ?? computedSplit?.optional ?? null)
|
||||
const basicFormula = typeof row.basicFormula === 'string' && row.basicFormula.trim()
|
||||
? row.basicFormula
|
||||
: (basicChecked ? (benchmarkSplit?.basicFormula ?? '') : '')
|
||||
const optionalFormula = typeof row.optionalFormula === 'string' && row.optionalFormula.trim()
|
||||
? row.optionalFormula
|
||||
: (optionalChecked ? (benchmarkSplit?.optionalFormula ?? '') : '')
|
||||
return {
|
||||
basicFee,
|
||||
basicFeeBasic,
|
||||
basicFeeOptional,
|
||||
basicFormula,
|
||||
optionalFormula
|
||||
}
|
||||
}
|
||||
|
||||
export interface ExportTaskGroupLike {
|
||||
serviceid?: number
|
||||
text: string[]
|
||||
}
|
||||
|
||||
export const groupWorkContentTasks = (
|
||||
rows: WorkContentRowLike[] | undefined,
|
||||
options?: { forceUngroup?: boolean }
|
||||
): ExportTaskGroupLike[] => {
|
||||
const source = Array.isArray(rows) ? rows : []
|
||||
const selected = source.filter(item => {
|
||||
if (item && item.isAddTrigger === true) return false
|
||||
const isCustom = Boolean(item?.custom)
|
||||
const isChecked = Boolean(item?.checked)
|
||||
return isCustom || isChecked
|
||||
})
|
||||
if (selected.length === 0) return []
|
||||
|
||||
const hasGroup = !options?.forceUngroup && selected.some(item => resolveTaskRowServiceId(item) != null)
|
||||
if (!hasGroup) {
|
||||
const text = selected
|
||||
.map(item => normalizeTaskText(item?.content))
|
||||
.filter(Boolean)
|
||||
return text.length > 0 ? [{ text }] : []
|
||||
}
|
||||
|
||||
const grouped = new Map<number, string[]>()
|
||||
const orderedServiceIds: number[] = []
|
||||
const ungroupedText: string[] = []
|
||||
for (const item of selected) {
|
||||
const content = normalizeTaskText(item?.content)
|
||||
if (!content) continue
|
||||
const serviceid = resolveTaskRowServiceId(item)
|
||||
if (serviceid == null) {
|
||||
ungroupedText.push(content)
|
||||
continue
|
||||
}
|
||||
if (!grouped.has(serviceid)) {
|
||||
grouped.set(serviceid, [])
|
||||
orderedServiceIds.push(serviceid)
|
||||
}
|
||||
grouped.get(serviceid)?.push(content)
|
||||
}
|
||||
|
||||
const groupedTasks: ExportTaskGroupLike[] = []
|
||||
for (const serviceid of orderedServiceIds) {
|
||||
const text = grouped.get(serviceid) || []
|
||||
if (text.length === 0) continue
|
||||
groupedTasks.push({ serviceid, text })
|
||||
}
|
||||
|
||||
if (ungroupedText.length > 0) {
|
||||
groupedTasks.push({ text: ungroupedText })
|
||||
}
|
||||
return groupedTasks
|
||||
}
|
||||
|
||||
export const buildProjectServiceCoes = (rows: FactorRowLike[] | undefined) => {
|
||||
if (!Array.isArray(rows)) return []
|
||||
return rows
|
||||
.map(row => {
|
||||
const serviceid = toSafeInteger(row.id)
|
||||
if (serviceid == null || row.budgetValue == null) return null
|
||||
const coe = toFiniteNumber(row.budgetValue)
|
||||
return {
|
||||
serviceid,
|
||||
coe: coe ?? 0,
|
||||
remark: typeof row.remark === 'string' ? row.remark : ''
|
||||
}
|
||||
})
|
||||
.filter((item): item is ExportServiceCoeLike => Boolean(item))
|
||||
}
|
||||
|
||||
export const buildProjectMajorCoes = (rows: FactorRowLike[] | undefined) => {
|
||||
if (!Array.isArray(rows)) return []
|
||||
return rows
|
||||
.map(row => {
|
||||
const majorid = toSafeInteger(row.id)
|
||||
if (majorid == null || row.budgetValue == null) return null
|
||||
const coe = toFiniteNumber(row.budgetValue)
|
||||
return {
|
||||
majorid,
|
||||
coe: coe ?? 0,
|
||||
remark: typeof row.remark === 'string' ? row.remark : ''
|
||||
}
|
||||
})
|
||||
.filter((item): item is ExportMajorCoeLike => Boolean(item))
|
||||
}
|
||||
|
||||
export const toExportScaleRows = (rows: ScaleRowLike[] | undefined) => {
|
||||
if (!Array.isArray(rows)) return []
|
||||
return rows
|
||||
.map(row => {
|
||||
const majorid = toSafeInteger(row.id)
|
||||
if (majorid == null || (row.amount == null && row.landArea == null)) return null
|
||||
return {
|
||||
majorid,
|
||||
major: majorid,
|
||||
cost: row.amount,
|
||||
area: row.landArea
|
||||
}
|
||||
})
|
||||
.filter((item): item is ExportScaleRowLike => Boolean(item))
|
||||
}
|
||||
|
||||
export const buildMethod1 = (rows: ScaleMethodRowLike[] | undefined) => {
|
||||
if (!Array.isArray(rows)) return null
|
||||
let hasTotalValue = false
|
||||
const proSet = new Set<number>()
|
||||
const det = rows
|
||||
.map(row => {
|
||||
const major = toScaleMajorId(row)
|
||||
if (major == null) return null
|
||||
const proNum = toScaleProNum(row)
|
||||
proSet.add(proNum)
|
||||
const cost = toFiniteNumber(row.amount)
|
||||
const feeResolved = resolveScaleMethodFee(row, 'cost')
|
||||
const basicFee = feeResolved.basicFee
|
||||
if (basicFee != null) hasTotalValue = true
|
||||
const basicFeeBasic = feeResolved.basicFeeBasic
|
||||
const basicFeeOptional = feeResolved.basicFeeOptional
|
||||
const remark = typeof row.remark === 'string' ? row.remark : ''
|
||||
if (basicFee == null) return null
|
||||
return {
|
||||
proNum,
|
||||
major,
|
||||
cost: cost ?? 0,
|
||||
basicFee: toMoney(basicFee),
|
||||
basicFormula: feeResolved.basicFormula,
|
||||
basicFee_basic: toMoney(basicFeeBasic),
|
||||
optionalFormula: feeResolved.optionalFormula,
|
||||
basicFee_optional: toMoney(basicFeeOptional),
|
||||
serviceCoe: toFiniteNumberOrZero(row.consultCategoryFactor),
|
||||
majorCoe: toFiniteNumberOrZero(row.majorFactor),
|
||||
processCoe: toFiniteNumber(row.workStageFactor) ?? 1,
|
||||
proportion: toFiniteNumber(row.workRatio) ?? 1,
|
||||
fee: toMoney(basicFee),
|
||||
remark
|
||||
}
|
||||
})
|
||||
.filter((item): item is ExportMethod1DetailLike => Boolean(item))
|
||||
|
||||
if (det.length === 0 || !hasTotalValue) return null
|
||||
return {
|
||||
proAmount: proSet.size > 0 ? proSet.size : 1,
|
||||
cost: sumNumbers(det.map(item => item.cost)),
|
||||
basicFee: toMoney(sumNumbers(det.map(item => item.basicFee))),
|
||||
basicFee_basic: toMoney(sumNumbers(det.map(item => item.basicFee_basic))),
|
||||
basicFee_optional: toMoney(sumNumbers(det.map(item => item.basicFee_optional))),
|
||||
fee: toMoney(sumNumbers(det.map(item => item.fee))),
|
||||
det
|
||||
}
|
||||
}
|
||||
|
||||
export const buildMethod2 = (rows: ScaleMethodRowLike[] | undefined) => {
|
||||
if (!Array.isArray(rows)) return null
|
||||
let hasTotalValue = false
|
||||
const proSet = new Set<number>()
|
||||
const det = rows
|
||||
.map(row => {
|
||||
const major = toScaleMajorId(row)
|
||||
if (major == null) return null
|
||||
const proNum = toScaleProNum(row)
|
||||
proSet.add(proNum)
|
||||
const area = toFiniteNumber(row.landArea)
|
||||
const feeResolved = resolveScaleMethodFee(row, 'area')
|
||||
const basicFee = feeResolved.basicFee
|
||||
if (basicFee != null) hasTotalValue = true
|
||||
const basicFeeBasic = feeResolved.basicFeeBasic
|
||||
const basicFeeOptional = feeResolved.basicFeeOptional
|
||||
const remark = typeof row.remark === 'string' ? row.remark : ''
|
||||
if (basicFee == null) return null
|
||||
return {
|
||||
proNum,
|
||||
major,
|
||||
area: area ?? 0,
|
||||
basicFee: toMoney(basicFee),
|
||||
basicFormula: feeResolved.basicFormula,
|
||||
basicFee_basic: toMoney(basicFeeBasic),
|
||||
optionalFormula: feeResolved.optionalFormula,
|
||||
basicFee_optional: toMoney(basicFeeOptional),
|
||||
serviceCoe: toFiniteNumberOrZero(row.consultCategoryFactor),
|
||||
majorCoe: toFiniteNumberOrZero(row.majorFactor),
|
||||
processCoe: toFiniteNumber(row.workStageFactor) ?? 1,
|
||||
proportion: toFiniteNumber(row.workRatio) ?? 1,
|
||||
fee: toMoney(basicFee),
|
||||
remark
|
||||
}
|
||||
})
|
||||
.filter((item): item is ExportMethod2DetailLike => Boolean(item))
|
||||
|
||||
if (det.length === 0 || !hasTotalValue) return null
|
||||
return {
|
||||
proAmount: proSet.size > 0 ? proSet.size : 1,
|
||||
area: sumNumbers(det.map(item => item.area)),
|
||||
basicFee: toMoney(sumNumbers(det.map(item => item.basicFee))),
|
||||
basicFee_basic: toMoney(sumNumbers(det.map(item => item.basicFee_basic))),
|
||||
basicFee_optional: toMoney(sumNumbers(det.map(item => item.basicFee_optional))),
|
||||
fee: toMoney(sumNumbers(det.map(item => item.fee))),
|
||||
det
|
||||
}
|
||||
}
|
||||
|
||||
export const buildMethod3 = (rows: WorkloadMethodRowLike[] | undefined) => {
|
||||
if (!Array.isArray(rows)) return null
|
||||
let hasTotalValue = false
|
||||
const det = rows
|
||||
.map(row => {
|
||||
const task = getTaskIdFromRowId(row.id)
|
||||
if (task == null || row.basicFee == null) return null
|
||||
const amount = toFiniteNumber(row.workload)
|
||||
const basicFee = toFiniteNumber(row.basicFee)
|
||||
const fee = toFiniteNumber(row.serviceFee)
|
||||
if (fee != null) hasTotalValue = true
|
||||
const remark = typeof row.remark === 'string' ? row.remark : ''
|
||||
const hasValue = amount != null || basicFee != null || fee != null || isNonEmptyString(remark)
|
||||
if (!hasValue) return null
|
||||
return {
|
||||
task,
|
||||
price: toFiniteNumberOrZero(row.budgetAdoptedUnitPrice),
|
||||
amount: amount ?? 0,
|
||||
basicFee: basicFee ?? 0,
|
||||
serviceCoe: toFiniteNumberOrZero(row.consultCategoryFactor),
|
||||
fee: fee ?? 0,
|
||||
remark
|
||||
}
|
||||
})
|
||||
.filter((item): item is ExportMethod3DetailLike => Boolean(item))
|
||||
|
||||
if (det.length === 0 || !hasTotalValue) return null
|
||||
return {
|
||||
basicFee: sumNumbers(det.map(item => item.basicFee)),
|
||||
fee: sumNumbers(det.map(item => item.fee)),
|
||||
det
|
||||
}
|
||||
}
|
||||
|
||||
export const buildMethod4 = (rows: HourlyMethodRowLike[] | undefined) => {
|
||||
if (!Array.isArray(rows)) return null
|
||||
let hasTotalValue = false
|
||||
const det = rows
|
||||
.map(row => {
|
||||
const expert = getExpertIdFromRowId(row.id)
|
||||
if (expert == null || row.serviceBudget == null) return null
|
||||
const personNum = toFiniteNumber(row.personnelCount)
|
||||
const workDay = toFiniteNumber(row.workdayCount)
|
||||
const fee = toFiniteNumber(row.serviceBudget)
|
||||
if (fee != null) hasTotalValue = true
|
||||
const remark = typeof row.remark === 'string' ? row.remark : ''
|
||||
const hasValue = personNum != null || workDay != null || fee != null || isNonEmptyString(remark)
|
||||
if (!hasValue) return null
|
||||
return {
|
||||
expert,
|
||||
price: toFiniteNumberOrZero(row.adoptedBudgetUnitPrice),
|
||||
person_num: personNum ?? 0,
|
||||
work_day: workDay ?? 0,
|
||||
fee: fee ?? 0,
|
||||
remark
|
||||
}
|
||||
})
|
||||
.filter((item): item is ExportMethod4DetailLike => Boolean(item))
|
||||
|
||||
if (det.length === 0 || !hasTotalValue) return null
|
||||
return {
|
||||
person_num: sumNumbers(det.map(item => item.person_num)),
|
||||
work_day: sumNumbers(det.map(item => item.work_day)),
|
||||
fee: sumNumbers(det.map(item => item.fee)),
|
||||
det
|
||||
}
|
||||
}
|
||||
|
||||
export const buildServiceFee = (
|
||||
row: ZxFwRowLike | null | undefined,
|
||||
method1: { fee: number } | null,
|
||||
method2: { fee: number } | null,
|
||||
method3: { fee: number } | null,
|
||||
method4: { fee: number } | null
|
||||
) => {
|
||||
const subtotal = toFiniteNumber(row?.subtotal)
|
||||
if (subtotal != null) return subtotal
|
||||
|
||||
const methodSum = sumNumbers([method1?.fee, method2?.fee, method3?.fee, method4?.fee])
|
||||
if (methodSum !== 0) return methodSum
|
||||
|
||||
return sumNumbers([
|
||||
toFiniteNumber(row?.investScale),
|
||||
toFiniteNumber(row?.landScale),
|
||||
toFiniteNumber(row?.workload),
|
||||
toFiniteNumber(row?.hourly)
|
||||
])
|
||||
}
|
||||
|
||||
export const buildMethod0 = (payload: RateMethodRowLike | null | undefined) => {
|
||||
const coe = toFiniteNumber(payload?.rate)
|
||||
const fee = toFiniteNumber(payload?.budgetFee)
|
||||
if (fee == null) return null
|
||||
return {
|
||||
coe: coe ?? 0,
|
||||
fee
|
||||
}
|
||||
}
|
||||
|
||||
export const buildMethod5 = (rows: QuantityMethodRowLike[] | undefined) => {
|
||||
if (!Array.isArray(rows) || rows.length === 0) return null
|
||||
const subtotalRow = rows.find(row => String(row?.id || '') === 'fee-subtotal-fixed')
|
||||
const subtotalFee = toFiniteNumber(subtotalRow?.budgetFee)
|
||||
if (subtotalFee == null) return null
|
||||
const det = rows
|
||||
.filter(row => String(row?.id || '') !== 'fee-subtotal-fixed')
|
||||
.map(row => {
|
||||
const quantity = toFiniteNumber(row.quantity)
|
||||
const unitPrice = toFiniteNumber(row.unitPrice)
|
||||
const fee = toFiniteNumber(row.budgetFee)
|
||||
const name = typeof row.feeItem === 'string' ? row.feeItem : ''
|
||||
const unit = typeof row.unit === 'string' ? row.unit : ''
|
||||
const remark = typeof row.remark === 'string' ? row.remark : ''
|
||||
|
||||
if (row.budgetFee == null) return null
|
||||
return {
|
||||
name,
|
||||
unit,
|
||||
amount: quantity ?? 0,
|
||||
price: unitPrice ?? 0,
|
||||
fee: fee ?? 0,
|
||||
remark
|
||||
}
|
||||
})
|
||||
.filter((item): item is ExportMethod5DetailLike => Boolean(item))
|
||||
|
||||
if (det.length === 0) return null
|
||||
return {
|
||||
fee: subtotalFee,
|
||||
det
|
||||
}
|
||||
}
|
||||
|
||||
export const buildServiceFinalFee = (
|
||||
row: ZxFwRowLike | null | undefined,
|
||||
method1: { fee: number } | null,
|
||||
method2: { fee: number } | null,
|
||||
method3: { fee: number } | null,
|
||||
method4: { fee: number } | null
|
||||
) => {
|
||||
const finalFee = toFiniteNumber(row?.finalFee)
|
||||
if (finalFee != null) return finalFee
|
||||
const subtotal = toFiniteNumber(row?.subtotal)
|
||||
if (subtotal != null) return subtotal
|
||||
return sumNumbers([method1?.fee, method2?.fee, method3?.fee, method4?.fee])
|
||||
}
|
||||
Reference in new issue
Block a user