QueryOweFeeImpl.java 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. package com.java110.fee.bmo.impl;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.java110.core.factory.CommunitySettingFactory;
  4. import com.java110.core.factory.Java110ThreadPoolFactory;
  5. import com.java110.core.log.LoggerFactory;
  6. import com.java110.core.smo.IComputeFeeSMO;
  7. import com.java110.dto.RoomDto;
  8. import com.java110.dto.fee.FeeConfigDto;
  9. import com.java110.dto.fee.FeeDto;
  10. import com.java110.dto.owner.OwnerCarDto;
  11. import com.java110.dto.owner.OwnerDto;
  12. import com.java110.dto.parking.ParkingSpaceDto;
  13. import com.java110.fee.bmo.IQueryOweFee;
  14. import com.java110.intf.community.IParkingSpaceInnerServiceSMO;
  15. import com.java110.intf.community.IRoomInnerServiceSMO;
  16. import com.java110.intf.fee.IFeeConfigInnerServiceSMO;
  17. import com.java110.intf.fee.IFeeInnerServiceSMO;
  18. import com.java110.intf.user.IOwnerCarInnerServiceSMO;
  19. import com.java110.intf.user.IOwnerInnerServiceSMO;
  20. import com.java110.utils.cache.MappingCache;
  21. import com.java110.utils.constant.ResponseConstant;
  22. import com.java110.utils.exception.ListenerExecuteException;
  23. import com.java110.utils.util.Assert;
  24. import com.java110.utils.util.DateUtil;
  25. import com.java110.utils.util.StringUtil;
  26. import com.java110.vo.ResultVo;
  27. import org.slf4j.Logger;
  28. import org.springframework.beans.factory.annotation.Autowired;
  29. import org.springframework.http.ResponseEntity;
  30. import org.springframework.stereotype.Service;
  31. import java.math.BigDecimal;
  32. import java.math.RoundingMode;
  33. import java.util.*;
  34. @Service
  35. public class QueryOweFeeImpl implements IQueryOweFee {
  36. private final static Logger logger = LoggerFactory.getLogger(QueryOweFeeImpl.class);
  37. @Autowired
  38. private IFeeInnerServiceSMO feeInnerServiceSMOImpl;
  39. @Autowired
  40. private IOwnerCarInnerServiceSMO ownerCarInnerServiceSMOImpl;
  41. @Autowired
  42. private IFeeConfigInnerServiceSMO feeConfigInnerServiceSMOImpl;
  43. @Autowired
  44. private IParkingSpaceInnerServiceSMO parkingSpaceInnerServiceSMOImpl;
  45. @Autowired
  46. private IRoomInnerServiceSMO roomInnerServiceSMOImpl;
  47. @Autowired
  48. private IOwnerInnerServiceSMO ownerInnerServiceSMOImpl;
  49. @Autowired
  50. private IComputeFeeSMO computeFeeSMOImpl;
  51. //域
  52. public static final String DOMAIN_COMMON = "DOMAIN.COMMON";
  53. //键
  54. public static final String TOTAL_FEE_PRICE = "TOTAL_FEE_PRICE";
  55. //键
  56. public static final String RECEIVED_AMOUNT_SWITCH = "RECEIVED_AMOUNT_SWITCH";
  57. //禁用电脑端提交收费按钮
  58. public static final String OFFLINE_PAY_FEE_SWITCH = "OFFLINE_PAY_FEE_SWITCH";
  59. @Override
  60. public ResponseEntity<String> query(FeeDto feeDto) {
  61. //查询费用信息arrearsEndTime
  62. feeDto.setArrearsEndTime(DateUtil.getCurrentDate());
  63. feeDto.setState(FeeDto.STATE_DOING);
  64. List<FeeDto> feeDtos = feeInnerServiceSMOImpl.queryFees(feeDto);
  65. if (feeDtos == null || feeDtos.size() < 1) {
  66. feeDtos = new ArrayList<>();
  67. return ResultVo.createResponseEntity(feeDtos);
  68. }
  69. List<FeeDto> tmpFeeDtos = new ArrayList<>();
  70. for (FeeDto tmpFeeDto : feeDtos) {
  71. try {
  72. computeFeeSMOImpl.computeEveryOweFee(tmpFeeDto);//计算欠费金额
  73. //如果金额为0 就排除
  74. //if (tmpFeeDto.getFeePrice() > 0 && tmpFeeDto.getEndTime().getTime() <= DateUtil.getCurrentDate().getTime()) {
  75. if (tmpFeeDto.getFeePrice() > 0) {
  76. tmpFeeDtos.add(tmpFeeDto);
  77. }
  78. } catch (Exception e) {
  79. logger.error("可能费用资料有问题导致算费失败", e);
  80. }
  81. }
  82. return ResultVo.createResponseEntity(tmpFeeDtos);
  83. }
  84. @Override
  85. public ResponseEntity<String> queryAllOwneFee(FeeDto feeDto) {
  86. ResponseEntity<String> responseEntity = null;
  87. if (!freshFeeDtoParam(feeDto)) {
  88. return ResultVo.createResponseEntity(1, 0, new JSONArray());
  89. }
  90. if (FeeConfigDto.BILL_TYPE_EVERY.equals(feeDto.getBillType())) {
  91. responseEntity = computeEveryOweFee(feeDto);
  92. } else {
  93. responseEntity = computeBillOweFee(feeDto);
  94. }
  95. return responseEntity;
  96. }
  97. @Override
  98. public ResponseEntity<String> listFeeObj(FeeDto feeDto) {
  99. List<FeeDto> feeDtos = feeInnerServiceSMOImpl.queryFees(feeDto);
  100. if (feeDtos == null || feeDtos.size() < 1) {
  101. return ResultVo.success();
  102. }
  103. String cycel = null;
  104. if (!StringUtil.isEmpty(feeDto.getCycle())) {
  105. cycel = feeDto.getCycle();
  106. }
  107. feeDto = feeDtos.get(0);
  108. if (!StringUtil.isEmpty(cycel)) {
  109. feeDto.setCycle(cycel);
  110. }
  111. if (FeeDto.PAYER_OBJ_TYPE_ROOM.equals(feeDto.getPayerObjType())) { //房屋相关
  112. RoomDto roomDto = new RoomDto();
  113. roomDto.setRoomId(feeDto.getPayerObjId());
  114. roomDto.setCommunityId(feeDto.getCommunityId());
  115. List<RoomDto> roomDtos = roomInnerServiceSMOImpl.queryRooms(roomDto);
  116. if (roomDtos == null || roomDtos.size() != 1) {
  117. throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR, "未查到房屋信息,查询多条数据");
  118. }
  119. roomDto = roomDtos.get(0);
  120. feeDto.setPayerObjName(roomDto.getFloorNum() + "栋" + roomDto.getUnitNum() + "单元" + roomDto.getRoomNum() + "室");
  121. feeDto.setBuiltUpArea(roomDto.getBuiltUpArea());
  122. } else if (FeeDto.PAYER_OBJ_TYPE_CAR.equals(feeDto.getPayerObjType())) {//车位相关
  123. OwnerCarDto ownerCarDto = new OwnerCarDto();
  124. ownerCarDto.setCarTypeCd("1001"); //业主车辆
  125. ownerCarDto.setCommunityId(feeDto.getCommunityId());
  126. ownerCarDto.setCarId(feeDto.getPayerObjId());
  127. List<OwnerCarDto> ownerCarDtos = ownerCarInnerServiceSMOImpl.queryOwnerCars(ownerCarDto);
  128. Assert.listOnlyOne(ownerCarDtos, "未找到车辆信息");
  129. ParkingSpaceDto parkingSpaceDto = new ParkingSpaceDto();
  130. parkingSpaceDto.setCommunityId(feeDto.getCommunityId());
  131. parkingSpaceDto.setPsId(ownerCarDtos.get(0).getPsId());
  132. List<ParkingSpaceDto> parkingSpaceDtos = parkingSpaceInnerServiceSMOImpl.queryParkingSpaces(parkingSpaceDto);
  133. if (parkingSpaceDtos == null || parkingSpaceDtos.size() < 1) { //数据有问题
  134. throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR, "未查到停车位信息,查询多条数据");
  135. }
  136. ownerCarDto = ownerCarDtos.get(0);
  137. parkingSpaceDto = parkingSpaceDtos.get(0);
  138. feeDto.setPayerObjName(ownerCarDto.getCarNum() + "(" + parkingSpaceDto.getAreaNum() + "停车场" + parkingSpaceDto.getNum() + "车位)");
  139. feeDto.setBuiltUpArea(parkingSpaceDto.getArea());
  140. }
  141. Map feePriceAll = computeFeeSMOImpl.getFeePrice(feeDto);
  142. feeDto.setFeePrice(Double.parseDouble(feePriceAll.get("feePrice").toString()));
  143. feeDto.setFeeTotalPrice(Double.parseDouble(feePriceAll.get("feeTotalPrice").toString()));
  144. //应收款取值
  145. //先取单小区的如果没有配置 取 全局的
  146. String val = CommunitySettingFactory.getValue(feeDto.getCommunityId(), TOTAL_FEE_PRICE);
  147. if (StringUtil.isEmpty(val)) {
  148. val = MappingCache.getValue(DOMAIN_COMMON, TOTAL_FEE_PRICE);
  149. }
  150. feeDto.setVal(val);
  151. //先取单小区的如果没有配置 取 全局的
  152. String received_amount_switch = CommunitySettingFactory.getValue(feeDto.getCommunityId(), RECEIVED_AMOUNT_SWITCH);
  153. if (StringUtil.isEmpty(received_amount_switch)) {
  154. received_amount_switch = MappingCache.getValue(DOMAIN_COMMON, RECEIVED_AMOUNT_SWITCH);
  155. }
  156. //关闭 线下收银功能
  157. if (StringUtil.isEmpty(received_amount_switch)) {
  158. feeDto.setReceivedAmountSwitch("1");//默认启用实收款输入框
  159. } else {
  160. feeDto.setReceivedAmountSwitch(received_amount_switch);
  161. }
  162. //先取单小区的如果没有配置 取 全局的
  163. String offlinePayFeeSwitch = CommunitySettingFactory.getValue(feeDto.getCommunityId(), OFFLINE_PAY_FEE_SWITCH);
  164. if (StringUtil.isEmpty(offlinePayFeeSwitch)) {
  165. offlinePayFeeSwitch = MappingCache.getValue(DOMAIN_COMMON, OFFLINE_PAY_FEE_SWITCH);
  166. }
  167. feeDto.setOfflinePayFeeSwitch(offlinePayFeeSwitch);
  168. return ResultVo.createResponseEntity(feeDto);
  169. }
  170. @Override
  171. public ResponseEntity<String> querys(FeeDto feeDto) {
  172. RoomDto roomDto = new RoomDto();
  173. roomDto.setCommunityId(feeDto.getCommunityId());
  174. roomDto.setRoomId(feeDto.getPayerObjId());
  175. List<RoomDto> roomDtos = roomInnerServiceSMOImpl.queryRooms(roomDto);
  176. if (roomDtos == null || roomDtos.size() < 1) {
  177. return ResultVo.createResponseEntity(ResultVo.CODE_OK, "成功", new JSONArray());
  178. }
  179. //查询费用信息arrearsEndTime
  180. List<RoomDto> tmpRoomDtos = new ArrayList<>();
  181. List<RoomDto> tempRooms = new ArrayList<>();
  182. int threadNum = Java110ThreadPoolFactory.JAVA110_DEFAULT_THREAD_NUM;
  183. tempRooms.addAll(doGetTmpRoomDto(roomDtos, feeDto, threadNum));
  184. for (RoomDto tmpRoomDto : tempRooms) {
  185. if (tmpRoomDto == null) {
  186. continue;
  187. }
  188. tmpRoomDtos.add(tmpRoomDto);
  189. }
  190. return ResultVo.createResponseEntity(tmpRoomDtos);
  191. }
  192. private List<RoomDto> doGetTmpRoomDto(List<RoomDto> roomDtos, FeeDto feeDto, int threadNum) {
  193. Java110ThreadPoolFactory java110ThreadPoolFactory = null;
  194. try {
  195. java110ThreadPoolFactory = Java110ThreadPoolFactory.getInstance().createThreadPool(threadNum);
  196. for (RoomDto roomDto1 : roomDtos) {
  197. java110ThreadPoolFactory.submit(() -> {
  198. return getTmpRoomDtos(roomDto1, feeDto);
  199. });
  200. }
  201. return java110ThreadPoolFactory.get();
  202. } finally {
  203. if (java110ThreadPoolFactory != null) {
  204. java110ThreadPoolFactory.stop();
  205. }
  206. }
  207. }
  208. private RoomDto getTmpRoomDtos(RoomDto tmpRoomDto, FeeDto feeDto) {
  209. FeeDto tmpFeeDto = null;
  210. tmpFeeDto = new FeeDto();
  211. tmpFeeDto.setArrearsEndTime(DateUtil.getCurrentDate());
  212. tmpFeeDto.setState(FeeDto.STATE_DOING);
  213. tmpFeeDto.setPayerObjId(tmpRoomDto.getRoomId());
  214. tmpFeeDto.setPayerObjType(FeeDto.PAYER_OBJ_TYPE_ROOM);
  215. List<FeeDto> feeDtos = feeInnerServiceSMOImpl.querySimpleFees(tmpFeeDto);
  216. if (feeDtos == null || feeDtos.size() < 1) {
  217. return null;
  218. }
  219. List<FeeDto> tmpFeeDtos = new ArrayList<>();
  220. for (FeeDto tempFeeDto : feeDtos) {
  221. computeFeeSMOImpl.computeEveryOweFee(tempFeeDto, tmpRoomDto);//计算欠费金额
  222. //如果金额为0 就排除
  223. //if (tempFeeDto.getFeePrice() > 0 && tempFeeDto.getEndTime().getTime() <= DateUtil.getCurrentDate().getTime()) {
  224. if (tempFeeDto.getFeePrice() > 0) {
  225. tmpFeeDtos.add(tempFeeDto);
  226. }
  227. }
  228. if (tmpFeeDtos.size() < 1) {
  229. return null;
  230. }
  231. tmpRoomDto.setFees(tmpFeeDtos);
  232. return tmpRoomDto;
  233. }
  234. private boolean freshFeeDtoParam(FeeDto feeDto) {
  235. if (StringUtil.isEmpty(feeDto.getPayerObjId())) {
  236. return true;
  237. }
  238. if (!feeDto.getPayerObjId().contains("-")) {
  239. return false;
  240. }
  241. if (FeeDto.PAYER_OBJ_TYPE_ROOM.equals(feeDto.getPayerObjType())) {
  242. String[] nums = feeDto.getPayerObjId().split("-");
  243. if (nums.length != 3) {
  244. return false;
  245. }
  246. RoomDto roomDto = new RoomDto();
  247. roomDto.setFloorNum(nums[0]);
  248. roomDto.setUnitNum(nums[1]);
  249. roomDto.setRoomNum(nums[2]);
  250. roomDto.setCommunityId(feeDto.getCommunityId());
  251. List<RoomDto> roomDtos = roomInnerServiceSMOImpl.queryRooms(roomDto);
  252. if (roomDtos == null || roomDtos.size() < 1) {
  253. return false;
  254. }
  255. feeDto.setPayerObjId(roomDtos.get(0).getRoomId());
  256. } else {
  257. String[] nums = feeDto.getPayerObjId().split("-");
  258. if (nums.length != 2) {
  259. return false;
  260. }
  261. ParkingSpaceDto parkingSpaceDto = new ParkingSpaceDto();
  262. parkingSpaceDto.setAreaNum(nums[0]);
  263. parkingSpaceDto.setNum(nums[1]);
  264. parkingSpaceDto.setCommunityId(feeDto.getCommunityId());
  265. List<ParkingSpaceDto> parkingSpaceDtos = parkingSpaceInnerServiceSMOImpl.queryParkingSpaces(parkingSpaceDto);
  266. if (parkingSpaceDtos == null || parkingSpaceDtos.size() < 1) {
  267. return false;
  268. }
  269. feeDto.setPayerObjId(parkingSpaceDtos.get(0).getPsId());
  270. }
  271. return true;
  272. }
  273. /**
  274. * 账单费用
  275. *
  276. * @param feeDto
  277. * @return
  278. */
  279. private ResponseEntity<String> computeBillOweFee(FeeDto feeDto) {
  280. int count = feeInnerServiceSMOImpl.computeBillOweFeeCount(feeDto);
  281. List<FeeDto> feeDtos = null;
  282. if (count > 0) {
  283. feeDtos = feeInnerServiceSMOImpl.computeBillOweFee(feeDto);
  284. } else {
  285. feeDtos = new ArrayList<>();
  286. }
  287. return ResultVo.createResponseEntity((int) Math.ceil((double) count / (double) feeDto.getRow()), count, feeDtos);
  288. }
  289. /**
  290. * 实时费用
  291. *
  292. * @param feeDto
  293. * @return
  294. */
  295. private ResponseEntity<String> computeEveryOweFee(FeeDto feeDto) {
  296. int count = feeInnerServiceSMOImpl.computeEveryOweFeeCount(feeDto);
  297. List<FeeDto> feeDtos = null;
  298. if (count > 0) {
  299. feeDtos = feeInnerServiceSMOImpl.computeEveryOweFee(feeDto);
  300. computeFeePrices(feeDtos);
  301. } else {
  302. feeDtos = new ArrayList<>();
  303. }
  304. return ResultVo.createResponseEntity((int) Math.ceil((double) count / (double) feeDto.getRow()), count, feeDtos);
  305. }
  306. private void computeFeePrices(List<FeeDto> feeDtos) {
  307. List<FeeDto> roomFees = new ArrayList<>();
  308. List<FeeDto> psFees = new ArrayList<>();
  309. List<String> roomIds = new ArrayList<>();
  310. List<String> psIds = new ArrayList<>();
  311. for (FeeDto fee : feeDtos) {
  312. // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间
  313. if ("3333".equals(fee.getPayerObjType())) { //房屋相关
  314. roomFees.add(fee);
  315. roomIds.add(fee.getPayerObjId());
  316. } else if ("6666".equals(fee.getPayerObjType())) {//车位相关
  317. psFees.add(fee);
  318. psIds.add(fee.getPayerObjId());
  319. }
  320. }
  321. if (roomFees.size() > 0) {
  322. computeRoomFee(roomFees, roomIds);
  323. }
  324. if (psFees.size() > 0) {
  325. computePsFee(psFees, psIds);
  326. }
  327. }
  328. /**
  329. * 计算停车费
  330. *
  331. * @param psFees
  332. */
  333. private void computePsFee(List<FeeDto> psFees, List<String> psIds) {
  334. ParkingSpaceDto parkingSpaceDto = new ParkingSpaceDto();
  335. parkingSpaceDto.setCommunityId(psFees.get(0).getCommunityId());
  336. parkingSpaceDto.setPsIds(psIds.toArray(new String[psIds.size()]));
  337. List<ParkingSpaceDto> parkingSpaceDtos = parkingSpaceInnerServiceSMOImpl.queryParkingSpaces(parkingSpaceDto);
  338. if (parkingSpaceDtos == null || parkingSpaceDtos.size() < 1) { //数据有问题
  339. return;
  340. }
  341. for (ParkingSpaceDto tmpParkingSpaceDto : parkingSpaceDtos) {
  342. for (FeeDto feeDto : psFees) {
  343. dealFeePs(tmpParkingSpaceDto, feeDto);
  344. }
  345. }
  346. OwnerDto ownerDto = new OwnerDto();
  347. ownerDto.setOwnerIds(psIds.toArray(new String[psIds.size()]));
  348. ownerDto.setCommunityId(psFees.get(0).getCommunityId());
  349. List<OwnerDto> ownerDtos = ownerInnerServiceSMOImpl.queryOwnersByParkingSpace(ownerDto);
  350. for (OwnerDto tmpOwnerDto : ownerDtos) {
  351. for (FeeDto feeDto : psFees) {
  352. dealFeeOwner(tmpOwnerDto, feeDto);
  353. }
  354. }
  355. }
  356. private void dealFeePs(ParkingSpaceDto tmpParkingSpaceDto, FeeDto feeDto) {
  357. // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间
  358. Map<String, Object> targetEndDateAndOweMonth = getTargetEndDateAndOweMonth(feeDto);
  359. Date targetEndDate = (Date) targetEndDateAndOweMonth.get("targetEndDate");
  360. double oweMonth = (double) targetEndDateAndOweMonth.get("oweMonth");
  361. if (!tmpParkingSpaceDto.getPsId().equals(feeDto.getPayerObjId())) {
  362. return;
  363. }
  364. feeDto.setRoomName(tmpParkingSpaceDto.getAreaNum() + "停车场" + tmpParkingSpaceDto.getNum() + "车位");
  365. String computingFormula = feeDto.getComputingFormula();
  366. double feePrice = 0.00;
  367. if ("1001".equals(computingFormula)) { //面积*单价+附加费
  368. BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getSquarePrice()));
  369. BigDecimal builtUpArea = new BigDecimal(Double.parseDouble(tmpParkingSpaceDto.getArea()));
  370. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  371. feePrice = squarePrice.multiply(builtUpArea).add(additionalAmount).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  372. } else if ("2002".equals(computingFormula)) { // 固定费用
  373. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  374. feePrice = additionalAmount.setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  375. } else if ("3003".equals(computingFormula)) { // 固定费用
  376. feePrice = 0.0;
  377. } else if ("1101".equals(computingFormula)) { // 租金
  378. feePrice = 0.0;
  379. } else if ("4004".equals(computingFormula)) {
  380. feePrice = Double.parseDouble(feeDto.getAmount());
  381. } else if ("5005".equals(computingFormula)) {
  382. if (StringUtil.isEmpty(feeDto.getCurDegrees())) {
  383. feePrice = -1.00;
  384. } else {
  385. BigDecimal curDegree = new BigDecimal(Double.parseDouble(feeDto.getCurDegrees()));
  386. BigDecimal preDegree = new BigDecimal(Double.parseDouble(feeDto.getPreDegrees()));
  387. BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getSquarePrice()));
  388. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  389. BigDecimal sub = curDegree.subtract(preDegree);
  390. feePrice = sub.multiply(squarePrice)
  391. .add(additionalAmount)
  392. .setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  393. }
  394. } else if ("9009".equals(computingFormula)) { //(本期度数-上期度数)*动态单价+附加费
  395. if (StringUtil.isEmpty(feeDto.getCurDegrees())) {
  396. feePrice = -1.00;
  397. } else {
  398. BigDecimal curDegree = new BigDecimal(Double.parseDouble(feeDto.getCurDegrees()));
  399. BigDecimal preDegree = new BigDecimal(Double.parseDouble(feeDto.getPreDegrees()));
  400. BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getMwPrice()));
  401. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  402. BigDecimal sub = curDegree.subtract(preDegree);
  403. feePrice = sub.multiply(squarePrice)
  404. .add(additionalAmount)
  405. .setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  406. }
  407. } else {
  408. feePrice = 0.00;
  409. }
  410. feeDto.setFeePrice(feePrice);
  411. // double month = dayCompare(feeDto.getEndTime(), DateUtil.getCurrentDate());
  412. BigDecimal price = new BigDecimal(feeDto.getFeePrice());
  413. price = price.multiply(new BigDecimal(oweMonth));
  414. feeDto.setAmountOwed(price.setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue() + "");
  415. feeDto.setDeadlineTime(targetEndDate);
  416. //动态费用
  417. if ("4004".equals(computingFormula)
  418. && FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag())
  419. ) {
  420. feeDto.setAmountOwed(feeDto.getFeePrice() + "");
  421. feeDto.setDeadlineTime(DateUtil.getCurrentDate());
  422. }
  423. }
  424. /**
  425. * 计算房屋费
  426. *
  427. * @param roomFees
  428. */
  429. private void computeRoomFee(List<FeeDto> roomFees, List<String> roomIds) {
  430. RoomDto roomDto = new RoomDto();
  431. roomDto.setCommunityId(roomFees.get(0).getCommunityId());
  432. roomDto.setRoomIds(roomIds.toArray(new String[roomIds.size()]));
  433. List<RoomDto> roomDtos = roomInnerServiceSMOImpl.queryRooms(roomDto);
  434. if (roomDtos == null || roomDtos.size() < 1) { //数据有问题
  435. return;
  436. }
  437. for (RoomDto tmpRoomDto : roomDtos) {
  438. for (FeeDto feeDto : roomFees) {
  439. dealFeeRoom(tmpRoomDto, feeDto);
  440. }
  441. }
  442. OwnerDto ownerDto = new OwnerDto();
  443. ownerDto.setRoomIds(roomIds.toArray(new String[roomIds.size()]));
  444. ownerDto.setCommunityId(roomFees.get(0).getCommunityId());
  445. List<OwnerDto> ownerDtos = ownerInnerServiceSMOImpl.queryOwners(ownerDto);
  446. for (OwnerDto tmpOwnerDto : ownerDtos) {
  447. for (FeeDto feeDto : roomFees) {
  448. dealFeeOwner(tmpOwnerDto, feeDto);
  449. }
  450. }
  451. }
  452. private void dealFeeOwner(OwnerDto tmpOwnerDto, FeeDto feeDto) {
  453. if (!tmpOwnerDto.getRoomId().equals(feeDto.getPayerObjId())) {
  454. return;
  455. }
  456. feeDto.setOwnerName(tmpOwnerDto.getName());
  457. feeDto.setOwnerTel(tmpOwnerDto.getLink());
  458. }
  459. private void dealFeeRoom(RoomDto tmpRoomDto, FeeDto feeDto) {
  460. Map<String, Object> targetEndDateAndOweMonth = getTargetEndDateAndOweMonth(feeDto);
  461. Date targetEndDate = (Date) targetEndDateAndOweMonth.get("targetEndDate");
  462. double oweMonth = (double) targetEndDateAndOweMonth.get("oweMonth");
  463. if (!tmpRoomDto.getRoomId().equals(feeDto.getPayerObjId())) {
  464. return;
  465. }
  466. feeDto.setRoomName(tmpRoomDto.getFloorNum() + "栋" + tmpRoomDto.getUnitNum() + "单元" + tmpRoomDto.getRoomNum() + "室");
  467. String computingFormula = feeDto.getComputingFormula();
  468. double feePrice = 0.00;
  469. if ("1001".equals(computingFormula)) { //面积*单价+附加费
  470. BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getSquarePrice()));
  471. BigDecimal builtUpArea = new BigDecimal(Double.parseDouble(tmpRoomDto.getBuiltUpArea()));
  472. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  473. feePrice = squarePrice.multiply(builtUpArea).add(additionalAmount).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  474. } else if ("2002".equals(computingFormula)) { // 固定费用
  475. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  476. feePrice = additionalAmount.setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  477. } else if ("3003".equals(computingFormula)) { // 固定费用
  478. BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getSquarePrice()));
  479. BigDecimal builtUpArea = new BigDecimal(Double.parseDouble(tmpRoomDto.getRoomArea()));
  480. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  481. feePrice = squarePrice.multiply(builtUpArea).add(additionalAmount).setScale(3, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  482. } else if ("1101".equals(computingFormula)) { // 租金
  483. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(tmpRoomDto.getRoomRent()));
  484. feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  485. } else if ("4004".equals(computingFormula)) {
  486. feePrice = Double.parseDouble(feeDto.getAmount());
  487. } else if ("5005".equals(computingFormula)) {
  488. if (StringUtil.isEmpty(feeDto.getCurDegrees())) {
  489. feePrice = -1.00;
  490. } else {
  491. BigDecimal curDegree = new BigDecimal(Double.parseDouble(feeDto.getCurDegrees()));
  492. BigDecimal preDegree = new BigDecimal(Double.parseDouble(feeDto.getPreDegrees()));
  493. BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getSquarePrice()));
  494. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  495. BigDecimal sub = curDegree.subtract(preDegree);
  496. feePrice = sub.multiply(squarePrice)
  497. .add(additionalAmount)
  498. .setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  499. }
  500. } else if ("9009".equals(computingFormula)) {
  501. if (StringUtil.isEmpty(feeDto.getCurDegrees())) {
  502. feePrice = -1.00;
  503. } else {
  504. BigDecimal curDegree = new BigDecimal(Double.parseDouble(feeDto.getCurDegrees()));
  505. BigDecimal preDegree = new BigDecimal(Double.parseDouble(feeDto.getPreDegrees()));
  506. BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getMwPrice()));
  507. BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
  508. BigDecimal sub = curDegree.subtract(preDegree);
  509. feePrice = sub.multiply(squarePrice)
  510. .add(additionalAmount)
  511. .setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
  512. }
  513. } else {
  514. feePrice = 0.00;
  515. }
  516. feeDto.setFeePrice(feePrice);
  517. //double month = dayCompare(feeDto.getEndTime(), DateUtil.getCurrentDate());
  518. BigDecimal price = new BigDecimal(feeDto.getFeePrice());
  519. price = price.multiply(new BigDecimal(oweMonth));
  520. feeDto.setAmountOwed(price.setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue() + "");
  521. feeDto.setDeadlineTime(targetEndDate);
  522. //动态费用
  523. if ("4004".equals(computingFormula)) {
  524. feeDto.setAmountOwed(feeDto.getFeePrice() + "");
  525. feeDto.setDeadlineTime(DateUtil.getCurrentDate());
  526. }
  527. }
  528. /**
  529. * 计算2个日期之间相差的 以年、月、日为单位,各自计算结果是多少
  530. * 比如:2011-02-02 到 2017-03-02
  531. * 以年为单位相差为:6年
  532. * 以月为单位相差为:73个月
  533. * 以日为单位相差为:2220天
  534. *
  535. * @param fromDate
  536. * @param toDate
  537. * @return
  538. */
  539. public static double dayCompare(Date fromDate, Date toDate) {
  540. Calendar from = Calendar.getInstance();
  541. from.setTime(fromDate);
  542. Calendar to = Calendar.getInstance();
  543. to.setTime(toDate);
  544. long t1 = from.getTimeInMillis();
  545. long t2 = to.getTimeInMillis();
  546. double days = (t2 - t1) * 1.00 / (24 * 60 * 60 * 1000);
  547. BigDecimal tmpDays = new BigDecimal(days);
  548. BigDecimal monthDay = new BigDecimal(30);
  549. return tmpDays.divide(monthDay, 2, RoundingMode.HALF_UP).doubleValue();
  550. }
  551. private Map getTargetEndDateAndOweMonth(FeeDto feeDto) {
  552. Date targetEndDate = null;
  553. double oweMonth = 0.0;
  554. Map<String, Object> targetEndDateAndOweMonth = new HashMap<>();
  555. if (FeeDto.STATE_FINISH.equals(feeDto.getState())) {
  556. targetEndDate = feeDto.getEndTime();
  557. targetEndDateAndOweMonth.put("oweMonth", oweMonth);
  558. targetEndDateAndOweMonth.put("targetEndDate", targetEndDate);
  559. return targetEndDateAndOweMonth;
  560. }
  561. if (FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag())) {
  562. if (feeDto.getDeadlineTime() != null) {
  563. targetEndDate = feeDto.getDeadlineTime();
  564. } else if (!StringUtil.isEmpty(feeDto.getCurDegrees())) {
  565. targetEndDate = feeDto.getCurReadingTime();
  566. } else if (feeDto.getImportFeeEndTime() == null) {
  567. targetEndDate = feeDto.getConfigEndTime();
  568. } else {
  569. targetEndDate = feeDto.getImportFeeEndTime();
  570. }
  571. //判断当前费用是不是导入费用
  572. oweMonth = 1.0;
  573. } else {
  574. //当前时间
  575. Date billEndTime = DateUtil.getCurrentDate();
  576. //开始时间
  577. Date startDate = feeDto.getStartTime();
  578. //到期时间
  579. Date endDate = feeDto.getEndTime();
  580. if (FeeDto.PAYER_OBJ_TYPE_CAR.equals(feeDto.getPayerObjType())) {
  581. OwnerCarDto ownerCarDto = new OwnerCarDto();
  582. ownerCarDto.setCommunityId(feeDto.getCommunityId());
  583. ownerCarDto.setCarId(feeDto.getPayerObjId());
  584. List<OwnerCarDto> ownerCarDtos = ownerCarInnerServiceSMOImpl.queryOwnerCars(ownerCarDto);
  585. if (ownerCarDtos == null || ownerCarDtos.size() != 1) {
  586. targetEndDateAndOweMonth.put("oweMonth", 0);
  587. targetEndDateAndOweMonth.put("targetEndDate", "");
  588. return targetEndDateAndOweMonth;
  589. }
  590. targetEndDate = ownerCarDtos.get(0).getEndTime();
  591. //说明没有欠费
  592. if (endDate.getTime() >= targetEndDate.getTime()) {
  593. // 目标到期时间 - 到期时间 = 欠费月份
  594. oweMonth = 0;
  595. targetEndDateAndOweMonth.put("oweMonth", oweMonth);
  596. targetEndDateAndOweMonth.put("targetEndDate", targetEndDate);
  597. return targetEndDateAndOweMonth;
  598. }
  599. }
  600. //缴费周期
  601. long paymentCycle = Long.parseLong(feeDto.getPaymentCycle());
  602. // 当前时间 - 开始时间 = 月份
  603. double mulMonth = 0.0;
  604. mulMonth = dayCompare(startDate, billEndTime);
  605. // 月份/ 周期 = 轮数(向上取整)
  606. double round = 0.0;
  607. if ("1200".equals(feeDto.getPaymentCd())) { // 预付费
  608. round = Math.floor(mulMonth / paymentCycle) + 1;
  609. } else { //后付费
  610. round = Math.floor(mulMonth / paymentCycle);
  611. }
  612. // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间
  613. targetEndDate = getTargetEndTime(round * paymentCycle, startDate);
  614. //费用 快结束了
  615. if (feeDto.getConfigEndTime().getTime() < targetEndDate.getTime()) {
  616. targetEndDate = feeDto.getConfigEndTime();
  617. }
  618. //说明没有欠费
  619. if (endDate.getTime() < targetEndDate.getTime()) {
  620. // 目标到期时间 - 到期时间 = 欠费月份
  621. oweMonth = dayCompare(endDate, targetEndDate);
  622. }
  623. if (feeDto.getEndTime().getTime() > targetEndDate.getTime()) {
  624. targetEndDate = feeDto.getEndTime();
  625. }
  626. }
  627. targetEndDateAndOweMonth.put("oweMonth", oweMonth);
  628. targetEndDateAndOweMonth.put("targetEndDate", targetEndDate);
  629. return targetEndDateAndOweMonth;
  630. }
  631. private Date getTargetEndTime(double v, Date startDate) {
  632. Calendar endDate = Calendar.getInstance();
  633. endDate.setTime(startDate);
  634. endDate.add(Calendar.MONTH, (int) v);
  635. return endDate.getTime();
  636. }
  637. }