feat(web-admin): wire fq last-period and dj deadline autofill in SamplePaymentPanel
Auto-recalculate the final installment due amount when earlier periods change (with manual override), and sync lump-sum deadline to due date. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
6ec4ec6730
commit
618d8fe21c
1 file changed
+65
-1
@@ -59,7 +59,7 @@
|
||||
placeholder="选择截止时间"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
@update:model-value="(v: string) => patchPay(pIdx, { lumpSumDeadline: v || '' })"
|
||||
@update:model-value="(v: string) => onLumpSumDeadlineChange(pIdx, v || '')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -364,12 +364,15 @@
|
||||
import {
|
||||
applyConsolidateRemainingToPayment,
|
||||
applyExpandRemainingToInstallment,
|
||||
applyLumpSumDeadlineToLastDueDate,
|
||||
availableSamplePayModes,
|
||||
calcLastPeriodDueAmount,
|
||||
parseInstallmentRatios,
|
||||
parsePreferentialPrice,
|
||||
resolvePerSamplePaymentDefaults,
|
||||
samplePaymentHasConfirmedTransfer,
|
||||
schedulePaidArrears,
|
||||
shouldAutoFillLastPeriodDue,
|
||||
shouldReplaceContractWithPreferentialPrice
|
||||
} from '@/utils/protocol-sample-payment'
|
||||
import { isMultiSchedulePayMode } from '@/utils/protocol-payment-presets'
|
||||
@@ -430,6 +433,8 @@
|
||||
const transferTypeOptions = ref<Api.Dict.DictDataOption[]>([])
|
||||
const submittingId = ref('')
|
||||
const savingKey = ref('')
|
||||
/** 按样本 key:用户手改过最后一期应缴金额则 true,前几期再变时清除 */
|
||||
const lastPeriodDueOverrideByKey = ref<Record<string, boolean>>({})
|
||||
|
||||
async function ensureTransferTypes() {
|
||||
await loadTransferTypeDict()
|
||||
@@ -442,6 +447,18 @@
|
||||
return '¥' + formatMoneyDisplay(v)
|
||||
}
|
||||
|
||||
function samplePayKey(pay: Record<string, any>, pIdx: number): string {
|
||||
return String(pay.sampleCode || pay.protocolSampleId || pIdx)
|
||||
}
|
||||
|
||||
function activeScheduleIndices(schedules: Record<string, any>[]): number[] {
|
||||
const idx: number[] = []
|
||||
schedules.forEach((s, i) => {
|
||||
if (String(s.scheduleStatus || 'open') !== 'void' && !s._deleted) idx.push(i)
|
||||
})
|
||||
return idx
|
||||
}
|
||||
|
||||
/** 仅财务已确认(yjf)锁定;付款确认中仍可改,直至财务确认 */
|
||||
function isTransferLocked(tr: Record<string, any>) {
|
||||
return tr.payStatus === 'yjf'
|
||||
@@ -458,6 +475,37 @@
|
||||
const pay = { ...list[pIdx] }
|
||||
const schedules = [...(pay.schedules || [])]
|
||||
schedules[sIdx] = { ...schedules[sIdx], ...patch }
|
||||
const mode = String(pay.payMode || '')
|
||||
const key = samplePayKey(pay, pIdx)
|
||||
const activeIdx = activeScheduleIndices(schedules)
|
||||
|
||||
if ('dueAmount' in patch && mode === 'fq' && activeIdx.length >= 2) {
|
||||
const lastIdx = activeIdx[activeIdx.length - 1]
|
||||
if (sIdx === lastIdx) {
|
||||
lastPeriodDueOverrideByKey.value = {
|
||||
...lastPeriodDueOverrideByKey.value,
|
||||
[key]: true
|
||||
}
|
||||
} else if (activeIdx.slice(0, -1).includes(sIdx)) {
|
||||
lastPeriodDueOverrideByKey.value = {
|
||||
...lastPeriodDueOverrideByKey.value,
|
||||
[key]: false
|
||||
}
|
||||
const lastSch = schedules[lastIdx]
|
||||
const canFill = shouldAutoFillLastPeriodDue({
|
||||
lastManualOverride: false,
|
||||
lastLocked: isScheduleDueLocked(lastSch)
|
||||
})
|
||||
if (canFill) {
|
||||
const priors = activeIdx.slice(0, -1).map((i) => schedules[i]?.dueAmount)
|
||||
const lastAmt = calcLastPeriodDueAmount(pay.contractAmount, priors)
|
||||
if (lastAmt != null) {
|
||||
schedules[lastIdx] = { ...schedules[lastIdx], dueAmount: lastAmt }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pay.schedules = schedules
|
||||
if ('dueAmount' in patch) {
|
||||
pay.installmentRatios = schedules.map((s: Record<string, any>) => {
|
||||
@@ -469,6 +517,22 @@
|
||||
emit('update:modelValue', list)
|
||||
}
|
||||
|
||||
function onLumpSumDeadlineChange(pIdx: number, raw: string) {
|
||||
const list = [...(props.modelValue || [])]
|
||||
const pay = { ...list[pIdx] }
|
||||
const deadline = raw || ''
|
||||
pay.lumpSumDeadline = deadline
|
||||
if (String(pay.payMode || '') === 'dj') {
|
||||
pay.schedules = applyLumpSumDeadlineToLastDueDate(
|
||||
[...(pay.schedules || [])],
|
||||
deadline,
|
||||
isScheduleDueLocked
|
||||
)
|
||||
}
|
||||
list[pIdx] = pay
|
||||
emit('update:modelValue', list)
|
||||
}
|
||||
|
||||
function sampleTitle(pay: Record<string, any>) {
|
||||
const sample = (props.samples || []).find(
|
||||
(s) => String(s.sampleCode || '') === String(pay.sampleCode || '')
|
||||
|
||||
Reference in new issue
Block a user