package com.usky.vpp.util; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.usky.vpp.domain.VppContract; import java.time.LocalDate; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * 合同状态工具:根据生效/到期日期自动解析生命周期状态 */ public final class VppContractStatusHelper { public static final int DRAFT = 0; public static final int AUDITING = 1; public static final int PENDING = 2; public static final int EFFECTIVE = 3; public static final int REJECTED = 4; public static final int EXPIRED = 5; public static final int TERMINATED = 6; /** 查询专用:即将到期(近三个月内过期,非落库状态) */ public static final int UPCOMING_EXPIRE = 7; private static final Set MANUAL_STATUSES = new HashSet<>(Arrays.asList( DRAFT, AUDITING, REJECTED, TERMINATED )); private VppContractStatusHelper() { } /** * 根据生效/到期日期解析合同状态;草稿、审核中、已驳回、已终止保持原状态不变。 */ public static Integer resolve(Integer storedStatus, LocalDate effectiveDate, LocalDate expireDate) { if (storedStatus != null && MANUAL_STATUSES.contains(storedStatus)) { return storedStatus; } return resolveByDates(effectiveDate, expireDate, storedStatus); } /** * 创建/更新时根据日期计算应写入的状态;未提供日期时回退为待生效。 */ public static Integer resolveForPersist(Integer requestedStatus, LocalDate effectiveDate, LocalDate expireDate) { if (requestedStatus != null && MANUAL_STATUSES.contains(requestedStatus)) { return requestedStatus; } Integer resolved = resolveByDates(effectiveDate, expireDate, requestedStatus); return resolved != null ? resolved : PENDING; } private static Integer resolveByDates(LocalDate effectiveDate, LocalDate expireDate, Integer fallback) { LocalDate today = LocalDate.now(); if (expireDate != null && today.isAfter(expireDate)) { return EXPIRED; } if (effectiveDate != null) { return today.isBefore(effectiveDate) ? PENDING : EFFECTIVE; } return fallback; } /** * 分页筛选:将生命周期状态(待生效/已生效/已到期/即将到期)转换为日期条件。 *

其中 {@link #UPCOMING_EXPIRE} 仅用于查询,不会写入数据库。

*/ public static void applyStatusFilter(LambdaQueryWrapper wrapper, Integer contractStatus) { if (contractStatus == null) { return; } LocalDate today = LocalDate.now(); if (contractStatus == PENDING) { wrapper.and(w -> w.in(VppContract::getContractStatus, PENDING, EFFECTIVE, EXPIRED) .gt(VppContract::getEffectiveDate, today) .and(inner -> inner.isNull(VppContract::getExpireDate) .or().ge(VppContract::getExpireDate, today))); return; } if (contractStatus == EFFECTIVE) { wrapper.and(w -> w.in(VppContract::getContractStatus, PENDING, EFFECTIVE, EXPIRED) .le(VppContract::getEffectiveDate, today) .and(inner -> inner.isNull(VppContract::getExpireDate) .or().ge(VppContract::getExpireDate, today))); return; } if (contractStatus == EXPIRED) { wrapper.and(w -> w.in(VppContract::getContractStatus, PENDING, EFFECTIVE, EXPIRED) .lt(VppContract::getExpireDate, today)); return; } if (contractStatus == UPCOMING_EXPIRE) { LocalDate upcomingDeadline = today.plusMonths(3); wrapper.and(w -> w.in(VppContract::getContractStatus, PENDING, EFFECTIVE, EXPIRED) .ge(VppContract::getExpireDate, today) .le(VppContract::getExpireDate, upcomingDeadline)); return; } wrapper.eq(VppContract::getContractStatus, contractStatus); } }