QueryOweFeeImpl.java 28 KB

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