|
|
@@ -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 || '')
|