LeaseChangeBillExValidator.java 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. package fi.fa.opplugin;
  2. import java.math.BigDecimal;
  3. import java.util.ArrayList;
  4. import java.util.Comparator;
  5. import java.util.Date;
  6. import java.util.HashSet;
  7. import java.util.Iterator;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Objects;
  11. import java.util.Set;
  12. import java.util.stream.Collectors;
  13. import kd.bos.dataentity.entity.DynamicObject;
  14. import kd.bos.dataentity.entity.DynamicObjectCollection;
  15. import kd.bos.dataentity.metadata.dynamicobject.DynamicProperty;
  16. import kd.bos.dataentity.resource.ResManager;
  17. import kd.bos.dataentity.utils.StringUtils;
  18. import kd.bos.entity.EntityMetadataCache;
  19. import kd.bos.entity.MainEntityType;
  20. import kd.bos.entity.property.BasedataProp;
  21. import kd.bos.entity.property.DateProp;
  22. import kd.bos.entity.property.DecimalProp;
  23. import kd.bos.entity.property.EntryProp;
  24. import kd.bos.entity.property.LongProp;
  25. import kd.bos.entity.property.TextProp;
  26. import kd.bos.entity.validate.BillStatus;
  27. import kd.bos.exception.KDBizException;
  28. import kd.bos.logging.Log;
  29. import kd.bos.logging.LogFactory;
  30. import kd.bos.orm.query.QFilter;
  31. import kd.bos.servicehelper.BusinessDataServiceHelper;
  32. import kd.bos.servicehelper.QueryServiceHelper;
  33. import kd.bos.servicehelper.botp.BFTrackerServiceHelper;
  34. import kd.fi.fa.business.calc.DynamicObjectWrapper;
  35. import kd.fi.fa.business.enums.lease.InterestAmortizeSchema;
  36. import kd.fi.fa.business.enums.lease.LeaseContractBizStatus;
  37. import kd.fi.fa.business.enums.lease.LeaseContractRentSettleStatus;
  38. import kd.fi.fa.business.enums.lease.LeaseContractSourceType;
  39. import kd.fi.fa.business.enums.lease.PayFrequency;
  40. import kd.fi.fa.business.lease.LeaseContractCal;
  41. import kd.fi.fa.business.lease.LeaseFutureBizChecker;
  42. import kd.fi.fa.business.lease.model.PayRuleCompareResult;
  43. import kd.fi.fa.business.lease.utils.LeaseChangeUtil;
  44. import kd.fi.fa.business.lease.utils.LeaseUtil;
  45. import kd.fi.fa.business.utils.FaBizUtils;
  46. import kd.fi.fa.business.utils.FaDepreUtil;
  47. import kd.fi.fa.business.utils.FaUtils;
  48. import kd.fi.fa.business.utils.SystemParamHelper;
  49. import kd.fi.fa.common.util.DateUtil;
  50. import kd.fi.fa.common.util.Fa;
  51. public class LeaseChangeBillExValidator {
  52. private static final Log logger = LogFactory.getLog(LeaseChangeBillExValidator.class);
  53. private static final Set<String> EFFECTIVE_FIN_ITEMS = new HashSet<String>() {
  54. {
  55. this.add("payruleentryentity");
  56. this.add("leaseenddate");
  57. this.add("discountrate");
  58. this.add("leaser");
  59. }
  60. };
  61. public LeaseChangeBillExValidator() {
  62. }
  63. public static List<String> validate4Save(DynamicObject bill) {
  64. List<String> errorInfo = new ArrayList(2);
  65. String billNo = bill.getString("billno");
  66. if (StringUtils.isBlank(billNo)) {
  67. errorInfo.add(ResManager.loadKDString("“单据编号”不能为空。", "LeaseChangeBillValidator_0", "fi-fa-business", new Object[0]));
  68. }
  69. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  70. if (leaseContract == null) {
  71. errorInfo.add(ResManager.loadKDString("“原合同”不能为空。", "LeaseChangeBillValidator_1", "fi-fa-business", new Object[0]));
  72. } else {
  73. String bizStatus = leaseContract.getString("bizstatus");
  74. boolean fromDatabase = bill.getDataEntityState().getFromDatabase();
  75. if (!fromDatabase && !LeaseContractBizStatus.A.name().equals(bizStatus)) {
  76. errorInfo.add(ResManager.loadKDString("“原合同”业务状态不是“正常”,不允许变更。", "LeaseChangeBillValidator_2", "fi-fa-business", new Object[0]));
  77. }
  78. }
  79. DynamicObjectCollection changeItems = bill.getDynamicObjectCollection("changeitems");
  80. if (changeItems.isEmpty()) {
  81. errorInfo.add(ResManager.loadKDString("“变更项目”不能为空。", "LeaseChangeBillValidator_3", "fi-fa-business", new Object[0]));
  82. }
  83. vadateChangeItemInDbIsChanged(bill, errorInfo);
  84. return errorInfo;
  85. }
  86. private static void vadateChangeItemInDbIsChanged(DynamicObject bill, List<String> errorInfo) {
  87. if (bill != null) {
  88. Object id = bill.getPkValue();
  89. if (id != null && (Long)id != 0L) {
  90. boolean isExistedBill = QueryServiceHelper.exists("fa_lease_change_bill", id);
  91. if (isExistedBill) {
  92. DynamicObject changeBillInDb = BusinessDataServiceHelper.loadSingle(id, "fa_lease_change_bill", "changeitems");
  93. Set<Object> itemsSetInDb = new HashSet(8);
  94. DynamicObjectCollection itemsInDb = changeBillInDb.getDynamicObjectCollection("changeitems");
  95. Iterator var7 = itemsInDb.iterator();
  96. while(var7.hasNext()) {
  97. DynamicObject items1 = (DynamicObject)var7.next();
  98. DynamicObject item = items1.getDynamicObject("fbasedataid");
  99. itemsSetInDb.add(item.getPkValue());
  100. }
  101. DynamicObjectCollection items = bill.getDynamicObjectCollection("changeitems");
  102. Set<Object> itemsSet = new HashSet(8);
  103. Iterator var14 = items.iterator();
  104. while(var14.hasNext()) {
  105. DynamicObject item1 = (DynamicObject)var14.next();
  106. DynamicObject item = item1.getDynamicObject("fbasedataid");
  107. itemsSet.add(item.getPkValue());
  108. }
  109. itemsSetInDb.removeAll(itemsSet);
  110. if (itemsSetInDb.size() > 0) {
  111. Map<Object, DynamicObject> changItemsDyMap = BusinessDataServiceHelper.loadFromCache(itemsSetInDb.toArray(new Object[1]), "fa_change_item");
  112. Set<String> alsterSet = (Set)changItemsDyMap.values().stream().map((t) -> {
  113. return t.getString("name");
  114. }).collect(Collectors.toSet());
  115. errorInfo.add(String.format(ResManager.loadKDString("已保存的变更单不能删除变更项%1$s。", "LeaseChangeBillValidator_4", "fi-fa-business", new Object[0]), alsterSet.toString()));
  116. }
  117. }
  118. }
  119. }
  120. }
  121. public static List<String> validate4Submit(DynamicObject bill, DynamicObject aftContract, DynamicObject oriLeaseContract) {
  122. List<String> errorInfo = validate4Save(bill);
  123. if (!errorInfo.isEmpty()) {
  124. return errorInfo;
  125. } else {
  126. if (aftContract == null) {
  127. aftContract = bill.getDynamicObject("changebakcontract");
  128. aftContract = reloadContractFromCache(aftContract.getPkValue());
  129. }
  130. errorInfo.addAll(checkLeaseInitEnable(bill));
  131. errorInfo.addAll(checkLeaseContactAllowsChange(bill));
  132. errorInfo.addAll(checkContractChangeInfo(bill, aftContract, oriLeaseContract));
  133. errorInfo.addAll(checkForFinChanged(bill));
  134. errorInfo.addAll(checkAmortizationPeriodIsNull(bill));
  135. errorInfo.addAll(checkAmortizeDateAftEffectiveDate(bill));
  136. return errorInfo;
  137. }
  138. }
  139. public static List<String> validate4Audit(DynamicObject bill) {
  140. List<String> errorInfo = checkLeaseInitEnable(bill);
  141. errorInfo.addAll(checkForFinChanged(bill));
  142. return errorInfo;
  143. }
  144. public static List<String> validate4Push(DynamicObject bill) {
  145. List<String> errorInfo = new ArrayList(8);
  146. String leaseChangeBillNo = bill.getString("billno");
  147. String billStatus = bill.getString("billstatus");
  148. if (!"C".equals(billStatus)) {
  149. return errorInfo;
  150. } else {
  151. String pushStatus = bill.getString("pushstatus");
  152. if ("C".equals(pushStatus)) {
  153. errorInfo.add(String.format(ResManager.loadKDString("租赁变更单编号:%s 存在关联单据,不能重复下推。", "LeaseChangeBillValidator_5", "fi-fa-business", new Object[0]), leaseChangeBillNo));
  154. return errorInfo;
  155. } else if ("B".equals(pushStatus)) {
  156. errorInfo.add(String.format(ResManager.loadKDString("租赁变更单编号:%s 下推标识为无需下推,不能下推。", "LeaseChangeBillValidator_6", "fi-fa-business", new Object[0]), leaseChangeBillNo));
  157. return errorInfo;
  158. } else {
  159. long leaseContractId = bill.getLong(Fa.id("leasecontract"));
  160. Date effectiveDate = bill.getDate("effectivedate");
  161. Date audiDate = bill.getDate("auditdate");
  162. QFilter[] qFilters = new QFilter[]{new QFilter("leasecontract", "=", leaseContractId), new QFilter("auditdate", "<", audiDate), new QFilter("pushstatus", "=", "A")};
  163. boolean existsNeedPush = QueryServiceHelper.exists("fa_lease_change_bill", qFilters);
  164. if (existsNeedPush) {
  165. errorInfo.add(String.format(ResManager.loadKDString("租赁变更单编号:%s 对应的合同存在历史变更生效的租赁变更单未下推。", "LeaseChangeBillValidator_7", "fi-fa-business", new Object[0]), leaseChangeBillNo));
  166. }
  167. DynamicObject aftContract = bill.getDynamicObject("aftcontract");
  168. Long orgId = aftContract.getLong(Fa.id("org"));
  169. DynamicObject mainBookByOrg = FaUtils.getMainBookByOrg(orgId);
  170. if (mainBookByOrg == null) {
  171. errorInfo.add(ResManager.loadKDString("请先创建核算组织对应的主账簿。", "LeaseChangeBillValidator_8", "fi-fa-business", new Object[0]));
  172. return errorInfo;
  173. } else if ("B".equals(mainBookByOrg.get("status"))) {
  174. errorInfo.add(ResManager.loadKDString("核算组织对应的主账簿未启用。", "LeaseChangeBillValidator_9", "fi-fa-business", new Object[0]));
  175. return errorInfo;
  176. } else {
  177. Long periodId = mainBookByOrg.getLong("curperiod");
  178. DynamicObject mainBookNext;
  179. if (periodId > 0L) {
  180. mainBookNext = BusinessDataServiceHelper.loadSingleFromCache("bd_period", "enddate", (new QFilter("id", "=", periodId)).toArray());
  181. long leaseContractMasterId = aftContract.getLong("masterid");
  182. DynamicObject realCard = QueryServiceHelper.queryOne("fa_card_real", "masterid", new QFilter[]{new QFilter("isbak", "in", false), new QFilter("srcbillid", "=", leaseContractMasterId)});
  183. if (realCard == null) {
  184. throw new KDBizException(ResManager.loadKDString("租赁合同关联的资产卡片丢失,请联系系统管理员。", "LeaseChangeBillValidator_10", "fi-fa-business", new Object[0]));
  185. }
  186. Long masterId = realCard.getLong("masterid");
  187. Date endDate = mainBookNext.getDate("enddate");
  188. QFilter[] qFinFilter = new QFilter[]{new QFilter("finaccountdate", ">", endDate), new QFilter("realcardmasterid", "=", masterId)};
  189. boolean exists = QueryServiceHelper.exists("fa_card_fin", qFinFilter);
  190. if (exists) {
  191. errorInfo.add(String.format(ResManager.loadKDString("租赁变更单编号:%s 对应的财务卡片是未来期间入账卡片,不能下推。", "LeaseChangeBillValidator_11", "fi-fa-business", new Object[0]), leaseChangeBillNo));
  192. return errorInfo;
  193. }
  194. }
  195. mainBookNext = FaBizUtils.queryNeighborPeriod(periodId, 1);
  196. if (mainBookNext == null) {
  197. errorInfo.add(ResManager.loadKDString("未找到主账簿的下一期间,请先维护期间数据。", "LeaseChangeBillValidator_12", "fi-fa-business", new Object[0]));
  198. return errorInfo;
  199. } else {
  200. Date mainBookEndDateNext = mainBookNext.getDate("enddate");
  201. if (mainBookEndDateNext.before(effectiveDate)) {
  202. errorInfo.add(String.format(ResManager.loadKDString("租赁变更单编号:%s 变更生效日超过主账簿的下期结束日,不能下推。", "LeaseChangeBillValidator_13", "fi-fa-business", new Object[0]), leaseChangeBillNo));
  203. }
  204. return errorInfo;
  205. }
  206. }
  207. }
  208. }
  209. }
  210. public static List<String> validate4UnAudit(DynamicObject bill) {
  211. List<String> errorInfo = new ArrayList(4);
  212. if (!checkContractBizStatus(bill)) {
  213. errorInfo.add(ResManager.loadKDString("合同业务状态不是“正常”,不允许反审核。", "LeaseChangeBillValidator_14", "fi-fa-business", new Object[0]));
  214. }
  215. if (checkLeaseChangeBillIsPush(bill)) {
  216. errorInfo.add(ResManager.loadKDString("存在下游单据,不允许反审核。", "LeaseChangeBillValidator_15", "fi-fa-business", new Object[0]));
  217. }
  218. if (isEffectiveFinInfo(bill)) {
  219. if (checkRentSettleHasVoucherAfterAmortizationDate(bill)) {
  220. errorInfo.add(ResManager.loadKDString("变更生效日后摊销与计息已经生成凭证,不允许反审核。", "LeaseChangeBillValidator_16", "fi-fa-business", new Object[0]));
  221. }
  222. errorInfo.addAll(checkPayPlanIsPushOrPaid(bill));
  223. }
  224. if (checkFutureLeaseChange(bill)) {
  225. errorInfo.add(ResManager.loadKDString("已存在未来生效的租赁变更单,不允许反审核。", "LeaseChangeBillValidator_17", "fi-fa-business", new Object[0]));
  226. }
  227. return errorInfo;
  228. }
  229. private static List<String> checkLeaseContactAllowsChange(DynamicObject bill) {
  230. List<String> errorInfo = new ArrayList(8);
  231. errorInfo.addAll(checkEffectiveDateRange(bill));
  232. errorInfo.addAll(checkChangeItems(bill));
  233. if (checkFutureLeaseChange(bill)) {
  234. errorInfo.add(ResManager.loadKDString("已存在当天或未来生效的租赁变更单,不允许变更。", "LeaseChangeBillValidator_18", "fi-fa-business", new Object[0]));
  235. }
  236. errorInfo.addAll(checkContractIsPushAndCardStatus(bill));
  237. return errorInfo;
  238. }
  239. private static List<String> checkContractChangeInfo(DynamicObject bill, DynamicObject aftContract, DynamicObject oriLeaseContract) {
  240. List<String> errorInfo = new ArrayList(8);
  241. if (checkIsExemptChanged(bill, aftContract)) {
  242. errorInfo.add(ResManager.loadKDString("合同是否豁免发生变化,不允许变更。", "LeaseChangeBillValidator_19", "fi-fa-business", new Object[0]));
  243. }
  244. if (checkExemptPropertyError(aftContract, oriLeaseContract)) {
  245. errorInfo.add(ResManager.loadKDString("原合同为豁免合同,不能变更为适用租赁期(月)大于12个月。", "LeaseChangeBillValidator_43", "fi-fa-business", new Object[0]));
  246. }
  247. List<String> contractSubmitValidateResult = LeaseContractExValidator.validateContractForSubmit(aftContract);
  248. if (!contractSubmitValidateResult.isEmpty()) {
  249. errorInfo.add(String.format(ResManager.loadKDString("变更后的合同信息存在以下问题,请修改:%s", "LeaseChangeBillValidator_20", "fi-fa-business", new Object[0]), String.join("", contractSubmitValidateResult)));
  250. } else {
  251. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  252. String rentStatus = leaseContract.getString("rentsettlestatus");
  253. if (LeaseContractRentSettleStatus.A.name().equals(rentStatus)) {
  254. errorInfo.add(ResManager.loadKDString("合同未计息,不允许变更。", "LeaseChangeBillValidator_21", "fi-fa-business", new Object[0]));
  255. }
  256. if (LeaseChangeUtil.isEffectPayPlan(bill)) {
  257. LeaseUtil.generatePayPlan4Chg(aftContract, oriLeaseContract);
  258. LeaseUtil.calLeaseContractAmount4Submit(aftContract);
  259. errorInfo.addAll(isPayRuleChangedBeforeEffectiveDate(bill, aftContract, oriLeaseContract));
  260. errorInfo.addAll(checkRentSettleStatusChanged(bill, aftContract));
  261. }
  262. errorInfo.addAll(checkHasChanged(bill, aftContract));
  263. }
  264. return errorInfo;
  265. }
  266. private static List<String> checkForFinChanged(DynamicObject bill) {
  267. List<String> errorInfo = new ArrayList(4);
  268. if (!isEffectiveFinInfo(bill)) {
  269. return errorInfo;
  270. } else {
  271. errorInfo.addAll(checkRentSettleHasVoucher4Submit(bill));
  272. errorInfo.addAll(checkPayPlanIsPushOrPaid(bill));
  273. return errorInfo;
  274. }
  275. }
  276. private static boolean isEffectiveFinInfo(DynamicObject bill) {
  277. Set<String> changeFields = LeaseChangeUtil.getChangeFields(bill);
  278. changeFields.retainAll(EFFECTIVE_FIN_ITEMS);
  279. return !changeFields.isEmpty();
  280. }
  281. private static List<String> checkAmortizeDateAftEffectiveDate(DynamicObject bill) {
  282. List<String> errorInfo = new ArrayList(1);
  283. Date effectiveDate = bill.getDate("effectivedate");
  284. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  285. leaseContract = BusinessDataServiceHelper.loadSingleFromCache(leaseContract.getPkValue(), "fa_lease_contract");
  286. DynamicObject org = leaseContract.getDynamicObject("org");
  287. String interestAmortizeSchema = SystemParamHelper.getStringParam("interest_amortize_schema", (Long)org.getPkValue(), InterestAmortizeSchema.A.name());
  288. if (InterestAmortizeSchema.A.name().equals(interestAmortizeSchema)) {
  289. return errorInfo;
  290. } else {
  291. List<Date> payDateList = new ArrayList();
  292. DynamicObjectCollection payPlanEntry = leaseContract.getDynamicObjectCollection("payplanentryentity");
  293. Iterator var8 = payPlanEntry.iterator();
  294. while(true) {
  295. Date planStartDate;
  296. Date planEndDate;
  297. DynamicObject payRuleRow;
  298. String frequency;
  299. do {
  300. DynamicObject row;
  301. DynamicObject payItem;
  302. String acctClass;
  303. do {
  304. Date planPayDate;
  305. do {
  306. if (!var8.hasNext()) {
  307. if (!payDateList.isEmpty()) {
  308. Date lastAmortizeDate = (Date)payDateList.stream().max(DateUtil::compareDate).get();
  309. errorInfo.add(String.format(ResManager.loadKDString("存在计划付款日在变更生效日之前,但摊销到变更生效日之后的付款计划,请调整变更生效日到[%s]之后。", "LeaseChangeBillValidator_22", "fi-fa-business", new Object[0]), DateUtil.getShortDate().format(lastAmortizeDate)));
  310. }
  311. return errorInfo;
  312. }
  313. row = (DynamicObject)var8.next();
  314. planPayDate = row.getDate("planpaydate");
  315. } while(DateUtil.compareDate(planPayDate, effectiveDate) >= 0);
  316. payItem = row.getDynamicObject("plan_payitem");
  317. acctClass = payItem.getString("accountingclass");
  318. } while(!"A".equals(acctClass));
  319. planStartDate = row.getDate("plan_startdate");
  320. planEndDate = row.getDate("plan_enddate");
  321. payRuleRow = LeaseUtil.getPayRuleRow(leaseContract, payItem.getLong("id"), planStartDate);
  322. frequency = payRuleRow.getString("frequency");
  323. } while(PayFrequency.F.name().equals(frequency));
  324. String payPoint = payRuleRow.getString("paypoint");
  325. int relativePayDate = payRuleRow.getInt("relativepaydate");
  326. Date startDate = planStartDate;
  327. while(DateUtil.compareDate(startDate, planEndDate) <= 0) {
  328. Date endDate = DateUtil.addNaturalMonth(startDate, 1);
  329. endDate = DateUtil.addDay(endDate, -1);
  330. if (DateUtil.compareDate(endDate, planEndDate) > 0) {
  331. endDate = planEndDate;
  332. }
  333. Date payDate = LeaseUtil.calPlanPayDate(startDate, endDate, payPoint, relativePayDate);
  334. startDate = DateUtil.addDay(endDate, 1);
  335. if (DateUtil.compareDate(payDate, effectiveDate) >= 0) {
  336. payDateList.add(payDate);
  337. }
  338. }
  339. }
  340. }
  341. }
  342. private static List<String> checkLeaseInitEnable(DynamicObject bill) {
  343. List<String> errorInfo = new ArrayList(1);
  344. DynamicObject leaseInit = getLeaseInitFromCache(bill);
  345. if (leaseInit == null) {
  346. errorInfo.add(ResManager.loadKDString("请先创建核算组织对应的租赁初始化。", "LeaseChangeBillValidator_23", "fi-fa-business", new Object[0]));
  347. return errorInfo;
  348. } else {
  349. String status = leaseInit.getString("status");
  350. boolean enable = leaseInit.getBoolean("enable");
  351. if (!BillStatus.C.name().equals(status) || !enable) {
  352. errorInfo.add(ResManager.loadKDString("请先启用核算组织的租赁初始化。", "LeaseChangeBillValidator_24", "fi-fa-business", new Object[0]));
  353. }
  354. return errorInfo;
  355. }
  356. }
  357. private static List<String> checkEffectiveDateRange(DynamicObject bill) {
  358. List<String> errorInfo = new ArrayList(1);
  359. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  360. String sourceType = leaseContract.getString("sourcetype");
  361. Date sysSwitchDate = leaseContract.getDate("sysswitchdate");
  362. Date initConfirmDate = leaseContract.getDate("initconfirmdate");
  363. Date leaseEndDate = leaseContract.getDate("leaseenddate");
  364. Date effectiveDate = bill.getDate("effectivedate");
  365. if (LeaseContractSourceType.A.name().equals(sourceType)) {
  366. if (effectiveDate.compareTo(initConfirmDate) < 0 || effectiveDate.compareTo(leaseEndDate) > 0) {
  367. errorInfo.add(ResManager.loadKDString("“变更生效日”必须大于等于原合同“初始确认日”且小于等于原合同“租赁结束日”。", "LeaseChangeBillValidator_25", "fi-fa-business", new Object[0]));
  368. }
  369. } else if (effectiveDate.compareTo(sysSwitchDate) < 0 || effectiveDate.compareTo(leaseEndDate) > 0) {
  370. errorInfo.add(ResManager.loadKDString("“变更生效日”必须大于等于原合同“系统切换日”且小于等于原合同“租赁结束日”。", "LeaseChangeBillValidator_26", "fi-fa-business", new Object[0]));
  371. }
  372. return errorInfo;
  373. }
  374. private static List<String> checkChangeItems(DynamicObject bill) {
  375. List<String> errorInfo = new ArrayList(1);
  376. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  377. boolean isExempt = leaseContract.getBoolean("isexempt");
  378. Set<String> changeFields = LeaseChangeUtil.getChangeFields(bill);
  379. if (isExempt && changeFields.contains("discountrate")) {
  380. errorInfo.add(ResManager.loadKDString("豁免合同不允许变更年折现率。", "LeaseChangeBillValidator_27", "fi-fa-business", new Object[0]));
  381. }
  382. return errorInfo;
  383. }
  384. private static boolean checkFutureLeaseChange(DynamicObject bill) {
  385. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  386. Date effectiveDate = bill.getDate("effectivedate");
  387. return LeaseFutureBizChecker.existFutureLeaseChangeBill(bill.getPkValue(), leaseContract.getPkValue(), effectiveDate);
  388. }
  389. private static List<String> checkContractIsPushAndCardStatus(DynamicObject bill) {
  390. List<String> errorInfo = new ArrayList(1);
  391. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  392. boolean isExempt = leaseContract.getBoolean("isexempt");
  393. if (isExempt) {
  394. return errorInfo;
  395. } else {
  396. QFilter[] realCardFilters = new QFilter[]{new QFilter("srcbillid", "=", leaseContract.getPkValue()), new QFilter("isbak", "=", Boolean.FALSE)};
  397. DynamicObject realCard = QueryServiceHelper.queryOne("fa_card_real", "id", realCardFilters);
  398. if (realCard == null) {
  399. errorInfo.add(ResManager.loadKDString("合同未下推生成卡片,不允许变更。", "LeaseChangeBillValidator_28", "fi-fa-business", new Object[0]));
  400. return errorInfo;
  401. } else {
  402. QFilter finCardFilter = new QFilter("realcard", "=", realCard.getLong("id"));
  403. DynamicObject finCard = QueryServiceHelper.queryOne("fa_card_fin", "billstatus", finCardFilter.toArray());
  404. if (finCard == null) {
  405. errorInfo.add(ResManager.loadKDString("合同下推的实物卡片未生成财务卡片,不允许变更。", "LeaseChangeBillValidator_29", "fi-fa-business", new Object[0]));
  406. return errorInfo;
  407. } else {
  408. String billStatus = finCard.getString("billstatus");
  409. if (!BillStatus.C.name().equals(billStatus)) {
  410. errorInfo.add(ResManager.loadKDString("合同下推的财务卡片未审核,不允许变更。", "LeaseChangeBillValidator_30", "fi-fa-business", new Object[0]));
  411. return errorInfo;
  412. } else {
  413. return errorInfo;
  414. }
  415. }
  416. }
  417. }
  418. }
  419. private static boolean checkIsExemptChanged(DynamicObject bill, DynamicObject aftContract) {
  420. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  421. boolean isExempt = leaseContract.getBoolean("isexempt");
  422. boolean aftIsExempt = aftContract.getBoolean("isexempt");
  423. return isExempt ^ aftIsExempt;
  424. }
  425. private static List<String> checkHasChanged(DynamicObject bill, DynamicObject aftContract) {
  426. List<String> errorInfo = new ArrayList(1);
  427. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  428. leaseContract = reloadContractFromCache(leaseContract.getPkValue());
  429. Set<String> changeFields = LeaseChangeUtil.getChangeFields(bill);
  430. MainEntityType entityType = EntityMetadataCache.getDataEntityType("fa_lease_contract");
  431. List<String> noChangedFields = new ArrayList(changeFields.size());
  432. Iterator var7 = changeFields.iterator();
  433. while(var7.hasNext()) {
  434. String field = (String)var7.next();
  435. DynamicProperty property = entityType.getProperty(field);
  436. if (!(property instanceof EntryProp)) {
  437. boolean isDiff = false;
  438. if (property instanceof DateProp) {
  439. Date befDate = leaseContract.getDate(field);
  440. Date aftDate = aftContract.getDate(field);
  441. isDiff = DateUtil.compareDate(befDate, aftDate) == 0;
  442. } else {
  443. long aft;
  444. long bef;
  445. if (property instanceof BasedataProp) {
  446. bef = leaseContract.getLong(field + "_id");
  447. aft = aftContract.getLong(field + "_id");
  448. isDiff = bef == aft;
  449. } else if (property instanceof TextProp) {
  450. String befString = leaseContract.getString(field);
  451. String aftString = aftContract.getString(field);
  452. isDiff = Objects.equals(befString, aftString);
  453. } else if (property instanceof DecimalProp) {
  454. BigDecimal befDecimal = leaseContract.getBigDecimal(field);
  455. befDecimal = befDecimal == null ? BigDecimal.ZERO : befDecimal;
  456. BigDecimal aftDecimal = aftContract.getBigDecimal(field);
  457. aftDecimal = aftDecimal == null ? BigDecimal.ZERO : aftDecimal;
  458. isDiff = befDecimal.compareTo(aftDecimal) == 0;
  459. } else if (property instanceof LongProp) {
  460. bef = leaseContract.getLong(field);
  461. aft = aftContract.getLong(field);
  462. isDiff = bef == aft;
  463. }
  464. }
  465. if (isDiff) {
  466. noChangedFields.add(property.getDisplayName().getLocaleValue());
  467. }
  468. }
  469. }
  470. if (changeFields.contains("payruleentryentity")) {
  471. Date effectiveDate = bill.getDate("effectivedate");
  472. PayRuleCompareResult compareResult = LeaseChangeUtil.comparePayRule(leaseContract, aftContract, effectiveDate);
  473. if (compareResult.getChangedPayItemIds().isEmpty()) {
  474. noChangedFields.add(ResManager.loadKDString("付款规则", "LeaseChangeBillValidator_31", "fi-fa-business", new Object[0]));
  475. }
  476. }
  477. if (!noChangedFields.isEmpty()) {
  478. errorInfo.add(String.format(ResManager.loadKDString("以下变更项没有发生变更,请修改对应的字段或移除该变更项:%s。", "LeaseChangeBillValidator_32", "fi-fa-business", new Object[0]), String.join(", ", noChangedFields)));
  479. }
  480. return errorInfo;
  481. }
  482. private static List<String> isPayRuleChangedBeforeEffectiveDate(DynamicObject bill, DynamicObject aftContract, DynamicObject oriLeaseContract) {
  483. List<String> errorInfo = new ArrayList(1);
  484. Date effectiveDate = bill.getDate("effectivedate");
  485. PayRuleCompareResult compareResult = LeaseChangeUtil.comparePayRule(oriLeaseContract, aftContract, effectiveDate);
  486. if (compareResult.isChangedBeforeEffective()) {
  487. Set<String> planNumberSet = compareResult.getChangedPlanNumberBeforeEffective();
  488. String planNumbers = (String)planNumberSet.stream().sorted(Comparator.naturalOrder()).collect(Collectors.joining(", "));
  489. errorInfo.add(String.format(ResManager.loadKDString("变更生效日之前的付款规则发生变化,不允许变更,请核对具体的付款计划:%s。", "LeaseChangeBillValidator_33", "fi-fa-business", new Object[0]), planNumbers));
  490. }
  491. return errorInfo;
  492. }
  493. private static List<String> checkRentSettleStatusChanged(DynamicObject bill, DynamicObject aftContract) {
  494. List<String> errorInfo = new ArrayList(1);
  495. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  496. leaseContract = reloadContractFromCache(leaseContract.getPkValue());
  497. boolean befNeedRentSettle = LeaseUtil.isNeedRentSettle(leaseContract);
  498. boolean aftNeedRentSettle = LeaseUtil.isNeedRentSettle(aftContract);
  499. if (befNeedRentSettle && !aftNeedRentSettle) {
  500. errorInfo.add(ResManager.loadKDString("变更前合同需要计息,不能变更为无需计息的合同。", "LeaseChangeBillValidator_34", "fi-fa-business", new Object[0]));
  501. }
  502. return errorInfo;
  503. }
  504. private static List<String> checkRentSettleHasVoucher4Submit(DynamicObject bill) {
  505. List<String> errorInfo = new ArrayList(1);
  506. DynamicObject leaseInit = getLeaseInitFromCache(bill);
  507. Date endDate = leaseInit.getDate("curperiod.enddate");
  508. Date beginDate = leaseInit.getDate("curperiod.begindate");
  509. Date effectiveDate = bill.getDate("effectivedate");
  510. boolean isFutureEffective = DateUtil.compareShortDate(effectiveDate, endDate) > 0;
  511. Date checkStartDate = isFutureEffective ? effectiveDate : beginDate;
  512. long leaseContractId = bill.getLong(Fa.id("leasecontract"));
  513. boolean hasVoucher = checkRentSettleHasVoucherAfterDate(leaseContractId, checkStartDate);
  514. if (hasVoucher) {
  515. if (isFutureEffective) {
  516. errorInfo.add(ResManager.loadKDString("变更生效日所在期间及后续期间的计息与摊销已生成凭证,不允许变更。", "LeaseChangeBillValidator_36", "fi-fa-business", new Object[0]));
  517. } else {
  518. errorInfo.add(ResManager.loadKDString("主账簿当前期间及后续期间的计息与摊销已生成凭证,不允许变更。", "LeaseChangeBillValidator_37", "fi-fa-business", new Object[0]));
  519. }
  520. }
  521. return errorInfo;
  522. }
  523. private static boolean checkRentSettleHasVoucherAfterDate(long leaseContractId, Date date) {
  524. QFilter[] filters = new QFilter[]{new QFilter("leasecontract", "=", leaseContractId), new QFilter("settledate", ">=", date)};
  525. DynamicObjectCollection rentSettle = QueryServiceHelper.query("fa_lease_rent_settle", "id", filters);
  526. List<Object> rentSettleIds = (List)rentSettle.stream().map((v) -> {
  527. return v.get("id");
  528. }).collect(Collectors.toList());
  529. return FaDepreUtil.hashVouncherV2(rentSettleIds, "fa_lease_rent_settle");
  530. }
  531. private static List<String> checkPayPlanIsPushOrPaid(DynamicObject bill) {
  532. List<String> errorInfo = new ArrayList(1);
  533. Date effectiveDate = bill.getDate("effectivedate");
  534. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  535. leaseContract = reloadContractFromCache(leaseContract.getPkValue());
  536. DynamicObjectCollection planEntry = leaseContract.getDynamicObjectCollection("payplanentryentity");
  537. boolean findErrData = false;
  538. Iterator var6 = planEntry.iterator();
  539. while(var6.hasNext()) {
  540. DynamicObject row = (DynamicObject)var6.next();
  541. Date planPayDate = row.getDate("planpaydate");
  542. if (DateUtil.compareDate(planPayDate, effectiveDate) >= 0) {
  543. BigDecimal realPayAmount = row.getBigDecimal("realpayamount");
  544. if (BigDecimal.ZERO.compareTo(realPayAmount) != 0) {
  545. findErrData = true;
  546. break;
  547. }
  548. boolean isPush = BFTrackerServiceHelper.isPush("fa_lease_pay_plan", (Long)row.getPkValue());
  549. if (isPush) {
  550. findErrData = true;
  551. break;
  552. }
  553. }
  554. }
  555. if (findErrData) {
  556. errorInfo.add(ResManager.loadKDString("变更生效日后付款计划存在下游单据或实际付款金额不为0。", "LeaseChangeBillValidator_38", "fi-fa-business", new Object[0]));
  557. }
  558. return errorInfo;
  559. }
  560. private static boolean checkContractBizStatus(DynamicObject bill) {
  561. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  562. String bizStatus = leaseContract.getString("bizstatus");
  563. return LeaseContractBizStatus.A.name().equals(bizStatus);
  564. }
  565. private static boolean checkLeaseChangeBillIsPush(DynamicObject bill) {
  566. return "C".equals(bill.getString("pushstatus"));
  567. }
  568. private static boolean checkRentSettleHasVoucherAfterAmortizationDate(DynamicObject bill) {
  569. Date amortizationDate = bill.getDate("amortizationdate");
  570. long leaseContractId = bill.getLong(Fa.id("leasecontract"));
  571. return checkRentSettleHasVoucherAfterDate(leaseContractId, amortizationDate);
  572. }
  573. private static List<String> checkAmortizationPeriodIsNull(DynamicObject bill) {
  574. List<String> errorInfo = new ArrayList(1);
  575. long leaseContractId = bill.getLong(Fa.id("leasecontract"));
  576. QFilter[] rentSettleFilters = new QFilter[]{new QFilter("leasecontract", "=", leaseContractId), new QFilter("amortizationperiod", "=", 0L)};
  577. boolean existsRentSettle = QueryServiceHelper.exists("fa_lease_rent_settle", rentSettleFilters);
  578. if (existsRentSettle) {
  579. errorInfo.add(ResManager.loadKDString("存在摊销与计息的“摊销期间”为空,请先维护会计期间并升级数据。", "LeaseChangeBillValidator_39", "fi-fa-business", new Object[0]));
  580. return errorInfo;
  581. } else {
  582. QFilter[] interestDetailFilters = new QFilter[]{new QFilter("leasecontract", "=", leaseContractId), new QFilter(Fa.dot(new String[]{"detailentry", "amortizationperiod"}), "=", 0L)};
  583. boolean existsInterestDetail = QueryServiceHelper.exists("fa_interest_detail", interestDetailFilters);
  584. if (existsInterestDetail) {
  585. errorInfo.add(ResManager.loadKDString("存在计息明细的“摊销期间”为空,请先维护会计期间并升级数据。", "LeaseChangeBillValidator_40", "fi-fa-business", new Object[0]));
  586. return errorInfo;
  587. } else {
  588. return errorInfo;
  589. }
  590. }
  591. }
  592. private static DynamicObject getLeaseInitFromCache(DynamicObject bill) {
  593. DynamicObject leaseContract = bill.getDynamicObject("leasecontract");
  594. long orgId = leaseContract.getLong(Fa.id("org"));
  595. QFilter[] filter = new QFilter[]{new QFilter("org", "=", orgId)};
  596. String fields = Fa.comma(new String[]{"enable", "status", "curperiod.begindate", "curperiod.enddate"});
  597. return BusinessDataServiceHelper.loadSingleFromCache("fa_lease_init", fields, filter);
  598. }
  599. private static DynamicObject reloadContractFromCache(Object pk) {
  600. return BusinessDataServiceHelper.loadSingleFromCache(pk, "fa_lease_contract");
  601. }
  602. private static boolean checkExemptPropertyError(DynamicObject aftContract, DynamicObject oriLeaseContract) {
  603. boolean oriLeaseIsExempt = oriLeaseContract.getBoolean("isexempt");
  604. if (oriLeaseIsExempt) {
  605. DynamicObjectWrapper wrapper = new DynamicObjectWrapper(aftContract);
  606. Boolean isExempt4Cal = LeaseContractCal.getIsExempt(wrapper);
  607. if (!isExempt4Cal) {
  608. return true;
  609. }
  610. }
  611. return false;
  612. }
  613. }