Commit 1517e55f by 李东升

优化计费规则实现以及添加首时段计费

parent 769482ef
package com.huaching.parking.local.parking_local_general.command;
import com.huaching.parking.local.parking_local_general.domain.local.bo.ThsRequestChargeAbstract;
import com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.ThsRequestChargeAbstract;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
......
package com.huaching.parking.local.parking_local_general.domain.local.bo;
import com.alibaba.fastjson.JSON;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesPO;
import com.huaching.parking.local.parking_local_general.enums.local.RequestChargeTypeEnums;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
/**
* @program: parking_local_general
* @description: 按照时间间隔计算费用
* @author: lidongsheng
* @createData: 2020-04-26 10:31
* @updateAuthor: lidongsheng
* @updateData: 2020-04-26 10:31
* @updateContent: 按照时间间隔计算费用
* @Version: 1.0.0
* ************************************************
* Copyright @ 李东升 2020. All rights reserved
* ************************************************
*/
@Component
public class ThsIntervalPayableMoney implements ThsRequestChargeAbstract {
private static final Logger logger = LoggerFactory.getLogger(ThsIntervalPayableMoney.class);
@Override
public Integer getPayableMoney(ThsChargingRulesPO thsChargingRulesPO, Date inTime) {
String chargeDetails = thsChargingRulesPO.getChargeDetails();
return intervalPayableMoney(JSON.parseObject(chargeDetails, IntervalChargeDetail.class), inTime, thsChargingRulesPO.getFreeTime()
, thsChargingRulesPO.getMaxOneTimeMoney());
}
@Override
public Integer getType() {
return RequestChargeTypeEnums.INTERVAL.getCode();
}
/**
* 按照间隔收费
*
* @param detail
* @param inTime 计费开始时间
* @param freeTime 免费时长(分钟)
* @param maxOneTimeMoney 一次停车的最高费用(单位分)
* @return
*/
public Integer intervalPayableMoney(IntervalChargeDetail detail, Date inTime,
Integer freeTime, Integer maxOneTimeMoney) {
inTime = DateUtils.getNextMinute(inTime, freeTime);
long sumMoney = 0;
switch (detail.frameType) {
//按照分钟收费
case 0:
long minute = DateUtils.subDate(inTime, new Date(), 2);
sumMoney = (minute / detail.intervalTime) * detail.money;
break;
//按照小时收费
case 1:
long hour = DateUtils.subDate(inTime, new Date(), 3);
sumMoney = (hour / detail.intervalTime) * detail.money;
break;
//按照固定收费
default:
sumMoney = (DateUtils.subDate(inTime, new Date(), 2) / detail.intervalTime) * detail.money;
break;
}
sumMoney = sumMoney > maxOneTimeMoney ? maxOneTimeMoney : sumMoney;
return (int) sumMoney;
}
/**
* 按照间隔收费
* "frameType": 0 按分钟收费
* "frameType": 1 按小时收费
*/
static class IntervalChargeDetail {
private Integer money;
private Integer frameType;
//间隔时长
private Integer intervalTime;
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
public Integer getFrameType() {
return frameType;
}
public void setFrameType(Integer frameType) {
this.frameType = frameType;
}
public Integer getIntervalTime() {
return intervalTime;
}
public void setIntervalTime(Integer intervalTime) {
this.intervalTime = intervalTime;
}
}
}
package com.huaching.parking.local.parking_local_general.domain.local.dto.response;
import com.alibaba.fastjson.JSON;
import com.huaching.parking.local.parking_local_general.domain.local.bo.ThsRequestChargeBO;
import com.huaching.parking.local.parking_local_general.domain.local.dto.BaseDTO;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesPO;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsParkingRecordsPO;
import com.huaching.parking.local.parking_local_general.service.local.PaymentChargesServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.UUID;
/**
* @program: parking_local_general
......
package com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import java.util.Date;
/**
* @program: parking_local_general
* @description: 首时段收费
* @author: lidongsheng
* @createData: 2020-05-27 10:39
* @updateAuthor: lidongsheng
* @updateData: 2020-05-27 10:39
* @updateContent:
* @Version: 1.0.0
* ************************************************
* Copyright @ 李东升 2020. All rights reserved
* ************************************************
*/
public class BaseChargeDetailPOJO<T> {
//首时段的时间
private Integer fastTime;
//首时段类型 0 按分钟 1按小时
private Integer fastFrameType;
//首时段金额
private Integer fastMoney;
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Integer getFastTime() {
return fastTime;
}
public void setFastTime(Integer fastTime) {
this.fastTime = fastTime;
}
public Integer getFastFrameType() {
return fastFrameType;
}
public void setFastFrameType(Integer fastFrameType) {
this.fastFrameType = fastFrameType;
}
public Integer getFastMoney() {
return fastMoney;
}
public void setFastMoney(Integer fastMoney) {
this.fastMoney = fastMoney;
}
/**
* 验证是否还在首时段内
*
* @param detail
* @param inTime
* @param endTime
* @return
*/
public boolean validateFirstTime(BaseChargeDetailPOJO detail, Date inTime, Date endTime) {
Date temp = inTime;
if (detail.getFastFrameType()== null) {
detail.setFastFrameType(0);
}
int dateNum = Math.toIntExact(DateUtils.subDate(inTime, endTime, detail.getFastFrameType() + 2));
return dateNum <= detail.getFastTime();
}
}
package com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator;
/**
* @program: parking_local_general
* @description: 按照间隔收费
* @author: lidongsheng
* @createData: 2020-05-27 10:47
* @updateAuthor: lidongsheng
* @updateData: 2020-05-27 10:47
* @updateContent: 按照间隔收费
* @Version: 1.0.0
* @email: lidongshenglife@163.com
* @blog: www.b0c0.com
* ************************************************
* Copyright @ 李东升 2020. All rights reserved
* ************************************************
*/
/*
首时段:2小时10元
后续:每间隔10分钟收费10元
{
"fastTime": 2,
"frameType": 1,
"fastMoney": 100,
"data": {
//金额
"money": 100,
//时间类型
"frameType": 0,
//间隔时长
"intervalTime": 10
}
}
*/
public class IntervalChargeDetailPOJO {
private Integer money;
private Integer frameType;
//间隔时长
private Integer intervalTime;
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
public Integer getFrameType() {
return frameType;
}
public void setFrameType(Integer frameType) {
this.frameType = frameType;
}
public Integer getIntervalTime() {
return intervalTime;
}
public void setIntervalTime(Integer intervalTime) {
this.intervalTime = intervalTime;
}
}
package com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator;
/**
* @program: parking_local_general
* @description: 一次收费
* @author: lidongsheng
* @createData: 2020-05-27 11:03
* @updateAuthor: lidongsheng
* @updateData: 2020-05-27 11:03
* @updateContent: 一次收费
* @Version: 1.0.0
* @email: lidongshenglife@163.com
* @blog: www.b0c0.com
* ************************************************
* Copyright @ 李东升 2020. All rights reserved
* ************************************************
*/
public class OneTimeChargeDetailPOJO {
private Integer money;
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
}
package com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator;
import java.util.List;
/**
* @program: parking_local_general
* @description: 按照时段收费
* @author: lidongsheng
* @createData: 2020-05-27 10:53
* @updateAuthor: lidongsheng
* @updateData: 2020-05-27 10:53
* @updateContent: 按照时段收费
* @Version: 1.0.0
* @email: lidongshenglife@163.com
* @blog: www.b0c0.com
* ************************************************
* Copyright @ 李东升 2020. All rights reserved
* ************************************************
*/
/*
TimeFrameChargeDetail:
首时段:30分钟 收费5元
后续:
00:00-07:00时间端内每分钟收费2元
07:00-20:30时间端内每小时钟收费4元
20:30-00:00时间端内一共收费3元
//json数组
{
"fastTime": 30,
"frameType": 0,
"fastMoney": 50,
"data": [
{
//"frameType": 0 按分钟收费
"frameType": 0,
"beginTime": "00:00",
"endTime": "07:00",
//表示在00:00-07:00时间端内每分钟收费2元
"money": 200
},
{
//"frameType": 1 按小时收费
"frameType": 1,
"beginTime": "07:00",
"endTime": "20:30",
//表示在07:00-20:30时间端内每小时钟收费4元
"money": 400
},
{
//"frameType": 2 按固定收费
"frameType": 2,
"beginTime": "20:30",
"endTime": "00:00",
//表示在20:30-00:00时间端内一共收费3元
"money": 300
}
]
}
*/
public class TimeFrameChargeDetailPOJO {
private String beginTime;
private String endTime;
private Integer money;
private Integer frameType;
public Integer getFrameType() {
return frameType;
}
public void setFrameType(Integer frameType) {
this.frameType = frameType;
}
public String getBeginTime() {
return beginTime;
}
public void setBeginTime(String beginTime) {
this.beginTime = beginTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
}
package com.huaching.parking.local.parking_local_general.service.local;
import com.alibaba.fastjson.JSON;
import com.huaching.parking.local.parking_local_general.domain.ResponseResult;
import com.huaching.parking.local.parking_local_general.domain.local.bo.ThsRequestChargeBO;
import com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.ThsRequestChargeService;
import com.huaching.parking.local.parking_local_general.domain.local.dto.request.ManualCarOutDTO;
import com.huaching.parking.local.parking_local_general.domain.local.dto.request.ThsCarInDTO;
import com.huaching.parking.local.parking_local_general.domain.local.dto.request.ThsCarOutDTO;
......@@ -10,9 +9,7 @@ import com.huaching.parking.local.parking_local_general.domain.local.dto.request
import com.huaching.parking.local.parking_local_general.domain.local.dto.response.ThsRequestChargeDTO;
import com.huaching.parking.local.parking_local_general.domain.local.po.*;
import com.huaching.parking.local.parking_local_general.enums.local.ReasonCodeEnums;
import com.huaching.parking.local.parking_local_general.intercept.local.GeneralPrintLogAOP;
import com.huaching.parking.local.parking_local_general.service.local.base.*;
import com.huaching.parking.local.parking_local_general.service.zhaf.RemoteRequestService;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -59,7 +56,7 @@ public class LocalCarInAndOutServiceImpl implements LocalCarInAndOutService {
private PaymentChargesService paymentChargesService;
@Autowired
private ThsRequestChargeBO thsRequestChargeBO;
private ThsRequestChargeService thsRequestChargeService;
@Autowired
private PayOrderRecordsService payOrderRecordsService;
......@@ -273,7 +270,7 @@ public class LocalCarInAndOutServiceImpl implements LocalCarInAndOutService {
logger.error("未查询到 parkCode -> {} 配置收费规则", parkCode);
return null;
}
return thsRequestChargeBO.getPayableMoney(thsChargingRulesPO, carNo, thsParkingRecordsPO.getInTime());
return thsRequestChargeService.getPayableMoney(thsChargingRulesPO, carNo, thsParkingRecordsPO.getInTime());
} catch (Exception ex) {
logger.error("出场请求费用出错, parkCode -> {} ,carNo -> {}", parkCode, carNo);
return null;
......
package com.huaching.parking.local.parking_local_general.service.local;
import com.alibaba.fastjson.JSON;
import com.huaching.parking.local.parking_local_general.domain.ResponseResult;
import com.huaching.parking.local.parking_local_general.domain.local.bo.ThsRequestChargeBO;
import com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.ThsRequestChargeService;
import com.huaching.parking.local.parking_local_general.domain.local.dto.request.ThsPaySyncDTO;
import com.huaching.parking.local.parking_local_general.domain.local.dto.response.ThsRequestChargeDTO;
import com.huaching.parking.local.parking_local_general.domain.local.po.*;
......@@ -10,8 +9,7 @@ import com.huaching.parking.local.parking_local_general.enums.local.ReasonCodeEn
import com.huaching.parking.local.parking_local_general.factory.ThreadPoolFactory;
import com.huaching.parking.local.parking_local_general.intercept.local.GeneralPrintLogAOP;
import com.huaching.parking.local.parking_local_general.service.local.base.*;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import com.huaching.parking.local.parking_local_general.util.local.chargeCalculator.ChargeCalculatorUtil;
import com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.old.ChargeCalculatorUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -55,7 +53,7 @@ public class PaymentChargesServiceImpl implements PaymentChargesService {
private LocalCarInAndOutService localCarInAndOutService;
@Autowired
private ThsRequestChargeBO thsRequestChargeBO;
private ThsRequestChargeService thsRequestChargeService;
@Autowired
private ChargeCalculatorUtil chargeCalculatorUtil;
......@@ -84,7 +82,7 @@ public class PaymentChargesServiceImpl implements PaymentChargesService {
return ThsRequestChargeDTO.errorMsg("该车场未配置收费规则");
}
thsParkingRecordsId = thsParkingRecordsPO.getId();
payableMoney = thsRequestChargeBO.getPayableMoney(thsChargingRulesPO, carNo, thsParkingRecordsPO.getInTime());
payableMoney = thsRequestChargeService.getPayableMoney(thsChargingRulesPO, carNo, thsParkingRecordsPO.getInTime());
totalMoney = payableMoney < 0 ? 0 : payableMoney;
payableMoney -= thsParkingRecordsPO.getPayedMoney();
payableMoney = payableMoney < 0 ? 0 : payableMoney;
......@@ -106,6 +104,7 @@ public class PaymentChargesServiceImpl implements PaymentChargesService {
}
@Override
@GeneralPrintLogAOP(value = "场内付请求费用 old", jsonSubs = {-1})
public ThsRequestChargeDTO requestChargeOld(String parkCode, String carNo) {
Integer thsParkingRecordsId;
String orderNo;
......
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesPO;
import com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator.BaseChargeDetailPOJO;
import com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator.IntervalChargeDetailPOJO;
import com.huaching.parking.local.parking_local_general.enums.local.RequestChargeTypeEnums;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
/**
* @program: parking_local_general
* @description: 按照时间间隔计算费用
* @author: lidongsheng
* @createData: 2020-04-26 10:31
* @updateAuthor: lidongsheng
* @updateData: 2020-04-26 10:31
* @updateContent: 按照时间间隔计算费用
* @Version: 1.0.0
* ************************************************
* Copyright @ 李东升 2020. All rights reserved
* ************************************************
*/
/*
//表示每2分钟收费10元
IntervalChargeDetail:
"data":{
//金额
"money": 100,
// 0 分钟 1 小时
"frameType": 0,
// 时间
"intervalTime": 2
}
*/
@Component
public class ThsIntervalPayableMoney implements ThsRequestChargeAbstract {
private static final Logger logger = LoggerFactory.getLogger(ThsIntervalPayableMoney.class);
@Override
public Integer getPayableMoney(ThsChargingRulesPO thsChargingRulesPO, Date inTime,Date endTime) {
String chargeDetails = thsChargingRulesPO.getChargeDetails();
BaseChargeDetailPOJO<IntervalChargeDetailPOJO> baseChargeDetailPOJO =
JSON.parseObject(chargeDetails, new TypeReference<BaseChargeDetailPOJO<IntervalChargeDetailPOJO>>() {
});
return intervalPayableMoney(baseChargeDetailPOJO, inTime, endTime, thsChargingRulesPO.getFreeTime()
, thsChargingRulesPO.getMaxOneTimeMoney());
}
@Override
public Integer getType() {
return RequestChargeTypeEnums.INTERVAL.getCode();
}
/**
* 按照间隔收费
*
* @param detail
* @param inTime 计费开始时间
* @param freeTime 免费时长(分钟)
* @param maxOneTimeMoney 一次停车的最高费用(单位分)
* @return
*/
public Integer intervalPayableMoney(BaseChargeDetailPOJO<IntervalChargeDetailPOJO> detail, Date inTime, Date endTime,
Integer freeTime, Integer maxOneTimeMoney) {
inTime = DateUtils.getNextMinute(inTime, freeTime);
//1. 判断是否在免费时长内
if (inTime.after(endTime)) {
return 0;
}
long sumMoney = detail.getFastMoney();
//2. 判断是否在首时段内
if (detail.validateFirstTime(detail, inTime, endTime)) {
return Math.toIntExact(sumMoney);
}
//3. 加上首时段的时间
int[] dateType = {Calendar.MINUTE, Calendar.HOUR_OF_DAY};
inTime = DateUtils.calAddDate(inTime, detail.getFastTime(), dateType[detail.getFastFrameType()]);
//4. 计算费用
int dateNum = Math.toIntExact(DateUtils.subDate(inTime, endTime, detail.getData().getFrameType() + 2));
sumMoney += (dateNum / detail.getData().getIntervalTime()) * detail.getData().getMoney();
sumMoney = sumMoney > maxOneTimeMoney ? maxOneTimeMoney : sumMoney;
return Math.toIntExact(sumMoney);
}
public static void main(String[] args) {
ThsChargingRulesPO thsChargingRulesPO = new ThsChargingRulesPO();
thsChargingRulesPO.setFreeTime(10);
thsChargingRulesPO.setChargeType(RequestChargeTypeEnums.INTERVAL.getCode());
thsChargingRulesPO.setMaxOneTimeMoney(20000000);
thsChargingRulesPO.setChargeDetails("{\n" +
" \"fastTime\": 0,\n" +
" \"frameType\": 0,\n" +
" \"fastMoney\": 0,\n" +
" \"data\": {\n" +
" \"money\": 100,\n" +
" \"frameType\": 0,\n" +
" \"intervalTime\": 2\n" +
" }\n" +
"}");
ThsIntervalPayableMoney payableMoney = new ThsIntervalPayableMoney();
Integer money = payableMoney.getPayableMoney(thsChargingRulesPO,
DateUtils.stringConvertDate("2020-05-27 06:25:20", 3),
DateUtils.stringConvertDate("2020-05-27 15:24:20", 3));
System.out.println(money);
}
}
package com.huaching.parking.local.parking_local_general.domain.local.bo;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesPO;
import com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator.BaseChargeDetailPOJO;
import com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator.OneTimeChargeDetailPOJO;
import com.huaching.parking.local.parking_local_general.enums.local.RequestChargeTypeEnums;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
......@@ -29,13 +33,46 @@ public class ThsOneTimePayableMoney implements ThsRequestChargeAbstract {
private static final Logger logger = LoggerFactory.getLogger(ThsOneTimePayableMoney.class);
@Override
public Integer getPayableMoney(ThsChargingRulesPO thsChargingRulesPO, Date inTime) {
public Integer getPayableMoney(ThsChargingRulesPO thsChargingRulesPO, Date inTime, Date endTime) {
String chargeDetails = thsChargingRulesPO.getChargeDetails();
return (Integer) JSON.parseObject(chargeDetails).get("oneTimeMoney");
BaseChargeDetailPOJO<OneTimeChargeDetailPOJO> detail =
JSON.parseObject(chargeDetails, new TypeReference<BaseChargeDetailPOJO<OneTimeChargeDetailPOJO>>() {
});
inTime = DateUtils.getNextMinute(inTime, thsChargingRulesPO.getFreeTime());
//1. 判断是否在免费时长内
if (inTime.after(endTime)) {
return 0;
}
long sumMoney = detail.getFastMoney();
//2. 判断是否在首时段内
if (detail.validateFirstTime(detail, inTime, endTime)) {
return Math.toIntExact(sumMoney);
}
return detail.getData().getMoney();
}
@Override
public Integer getType() {
return RequestChargeTypeEnums.ONE_TIME.getCode();
}
public static void main(String[] args) {
ThsChargingRulesPO thsChargingRulesPO = new ThsChargingRulesPO();
thsChargingRulesPO.setFreeTime(10);
thsChargingRulesPO.setChargeType(RequestChargeTypeEnums.ONE_TIME.getCode());
thsChargingRulesPO.setMaxOneTimeMoney(20000000);
thsChargingRulesPO.setChargeDetails("{\n" +
" \"fastTime\": 0,\n" +
" \"frameType\": 0,\n" +
" \"fastMoney\": 0,\n" +
" \"data\": {\n" +
" \"money\": 100\n" +
" }\n" +
"}");
ThsOneTimePayableMoney payableMoney = new ThsOneTimePayableMoney();
Integer money = payableMoney.getPayableMoney(thsChargingRulesPO
, DateUtils.stringConvertDate("2020-05-27 06:25:20", 3)
, DateUtils.stringConvertDate("2020-05-27 15:20:20", 3));
System.out.println(money);
}
}
package com.huaching.parking.local.parking_local_general.domain.local.bo;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesPO;
......@@ -21,7 +21,7 @@ import java.util.Date;
public interface ThsRequestChargeAbstract {
Integer getPayableMoney(ThsChargingRulesPO thsChargingRulesPO, Date inTime);
Integer getPayableMoney(ThsChargingRulesPO thsChargingRulesPO, Date inTime,Date endTime);
Integer getType();
}
package com.huaching.parking.local.parking_local_general.domain.local.bo;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator;
import com.alibaba.fastjson.JSON;
import com.huaching.parking.local.parking_local_general.command.RequestChargeCommand;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesPO;
import com.huaching.parking.local.parking_local_general.intercept.local.GeneralPrintLogAOP;
import com.huaching.parking.local.parking_local_general.service.local.MemberCarHelperService;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* @program: parking_local_general
......@@ -31,9 +25,9 @@ import java.util.UUID;
* ************************************************
*/
@Component
public class ThsRequestChargeBO {
public class ThsRequestChargeService {
private static final Logger logger = LoggerFactory.getLogger(ThsRequestChargeBO.class);
private static final Logger logger = LoggerFactory.getLogger(ThsRequestChargeService.class);
@Autowired
private MemberCarHelperService memberCarHelperService;
......@@ -53,7 +47,7 @@ public class ThsRequestChargeBO {
if (memberCarHelperService.vaildMember(thsChargingRulesPO.getParkCode(), carNo) != null) {
return 0;
}
return requestChargeCommand.getProcessor(thsChargingRulesPO.getChargeType()).getPayableMoney(thsChargingRulesPO, inTime);
return requestChargeCommand.getProcessor(thsChargingRulesPO.getChargeType()).getPayableMoney(thsChargingRulesPO, inTime, new Date());
}
}
package com.huaching.parking.local.parking_local_general.domain.local.bo;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesPO;
import com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator.BaseChargeDetailPOJO;
import com.huaching.parking.local.parking_local_general.domain.local.pojo.chargeCalculator.TimeFrameChargeDetailPOJO;
import com.huaching.parking.local.parking_local_general.enums.local.RequestChargeTypeEnums;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
......@@ -25,16 +29,52 @@ import java.util.List;
* Copyright @ 李东升 2020. All rights reserved
* ************************************************
*/
/*
TimeFrameChargeDetail:
//json数组
"data": [
{
//"frameType": 0 按分钟收费
"frameType": 0,
"beginTime": "00:00",
"endTime": "07:00",
//表示在00:00-07:00时间端内每分钟收费2元
"money": 200
},
{
//"frameType": 1 按小时收费
"frameType": 1,
"beginTime": "07:00",
"endTime": "20:30",
//表示在07:00-20:30时间端内每小时钟收费4元
"money": 400
},
{
//"frameType": 2 按固定收费
"frameType": 2,
"beginTime": "20:30",
"endTime": "00:00",
//表示在20:30-00:00时间端内一共收费3元
"money": 300
}
]
*/
@Component
public class ThsTimeFramePayableMoney implements ThsRequestChargeAbstract {
private static final Logger logger = LoggerFactory.getLogger(ThsTimeFramePayableMoney.class);
@Override
public Integer getPayableMoney(ThsChargingRulesPO thsChargingRulesPO, Date inTime) {
public Integer getPayableMoney(ThsChargingRulesPO thsChargingRulesPO, Date inTime, Date endTime) {
String chargeDetails = thsChargingRulesPO.getChargeDetails();
List<TimeFrameChargeDetail> list = JSON.parseArray(chargeDetails, TimeFrameChargeDetail.class);
return timeFramePayableMoney(list, inTime, thsChargingRulesPO.getFreeTime()
BaseChargeDetailPOJO<List<TimeFrameChargeDetailPOJO>> detail =
JSON.parseObject(chargeDetails, new TypeReference<BaseChargeDetailPOJO<List<TimeFrameChargeDetailPOJO>>>() {
});
return timeFramePayableMoney(detail, inTime, endTime, thsChargingRulesPO.getFreeTime()
, thsChargingRulesPO.getMaxOneTimeMoney(), thsChargingRulesPO.getMaxOneDayMoney());
}
......@@ -46,27 +86,46 @@ public class ThsTimeFramePayableMoney implements ThsRequestChargeAbstract {
/**
* 按时段收费
*
* @param list 时段list
* @param detail 按时段计费detail
* @param inTime 进场时间
* @param freeTime 免费时长(分钟)
* @param maxOneTimeMoney 一次停车的最高费用(单位分)
* @param maxOneDayMoney 一天停车的最高费用(单位分)
* @return
*/
public Integer timeFramePayableMoney(List<TimeFrameChargeDetail> list, Date inTime,
Integer freeTime, Integer maxOneTimeMoney, Integer maxOneDayMoney) {
list.sort(Comparator.comparing(o -> DateUtils.stringConvertDate("2020-01-01 " + o.getBeginTime(), 3)));
public Integer timeFramePayableMoney(BaseChargeDetailPOJO<List<TimeFrameChargeDetailPOJO>> detail, Date inTime,
Date endTime, Integer freeTime, Integer maxOneTimeMoney, Integer maxOneDayMoney) {
inTime = DateUtils.getNextMinute(inTime, freeTime);
//1. 判断是否在免费时长内
if (inTime.after(endTime)) {
return 0;
}
long sumMoney = detail.getFastMoney();
//2. 判断是否在首时段内
if (detail.validateFirstTime(detail, inTime, endTime)) {
return Math.toIntExact(sumMoney);
}
//3. 加上首时段的时间
int[] dateType = {Calendar.MINUTE, Calendar.HOUR_OF_DAY};
inTime = DateUtils.calAddDate(inTime, detail.getFastTime(), dateType[detail.getFastFrameType()]);
//4. 处理时段
List<TimeFrameChargeDetailPOJO> list = detail.getData();
list.sort(Comparator.comparing(o -> DateUtils.stringConvertDate("2020-01-01 " + o.getBeginTime(), 3)));
list.stream().forEach(o -> {
o.setBeginTime(o.getBeginTime() + ":00");
o.setEndTime(o.getEndTime() + ":00");
});
//得到跨天的天数
int acrossDayNum = (int) DateUtils.subDate(DateUtils.getNextDayStart(inTime, 0),
DateUtils.getNextDayStart(new Date(), 0), 4);
DateUtils.getNextDayStart(endTime, 0), 4);
//是否存在跨天
if (acrossDayNum > 0) {
logger.info("跨天费用计算");
return acrossDayTimeFrameCharge(list, inTime, acrossDayNum, maxOneTimeMoney, maxOneDayMoney);
} else {
logger.info("非跨天费用计算");
return noAcrossDayTimeFrameCharge(list, inTime, new Date(), maxOneTimeMoney, maxOneDayMoney);
return noAcrossDayTimeFrameCharge(list, inTime, endTime, maxOneTimeMoney, maxOneDayMoney);
}
}
......@@ -80,17 +139,15 @@ public class ThsTimeFramePayableMoney implements ThsRequestChargeAbstract {
* @param maxOneDayMoney 一天停车的最高费用(单位分)
* @return
*/
private Integer noAcrossDayTimeFrameCharge(List<TimeFrameChargeDetail> list, Date inTime, Date endTime
private Integer noAcrossDayTimeFrameCharge(List<TimeFrameChargeDetailPOJO> list, Date inTime, Date endTime
, Integer maxOneTimeMoney, Integer maxOneDayMoney) {
int sumMoney = 0;
String tempInTime = DateUtils.dateFormatToString(inTime, 3) + " ";
String tempEndTime = DateUtils.dateFormatToString(endTime, 3) + " ";
for (TimeFrameChargeDetail detail : list) {
detail.beginTime = detail.beginTime + ":00";
detail.endTime = detail.endTime + ":00";
Date detailBeginTime = DateUtils.stringConvertDate(tempInTime + detail.beginTime, 3);
Date detailEndTime = DateUtils.stringConvertDate(tempEndTime + detail.endTime, 3);
for (TimeFrameChargeDetailPOJO detail : list) {
Date detailBeginTime = DateUtils.stringConvertDate(tempInTime + detail.getBeginTime(), 3);
Date detailEndTime = DateUtils.stringConvertDate(tempEndTime + detail.getEndTime(), 3);
if (inTime.compareTo(detailBeginTime) >= 0
&& endTime.compareTo(detailEndTime) <= 0) {
......@@ -130,13 +187,12 @@ public class ThsTimeFramePayableMoney implements ThsRequestChargeAbstract {
* @param maxOneDayMoney 一天停车的最高费用(单位分)
* @return
*/
private Integer acrossDayTimeFrameCharge(List<TimeFrameChargeDetail> list, Date inTime, Integer acrossDayNum
private Integer acrossDayTimeFrameCharge(List<TimeFrameChargeDetailPOJO> list, Date inTime, Integer acrossDayNum
, Integer maxOneTimeMoney, Integer maxOneDayMoney) {
int sumMoney = 0;
//是否跨多天
//是否跨多天(跨天先计算出一整天需要缴费多少。)
if (acrossDayNum > 1) {
//跨天先计算出一整天需要缴费多少。
int oneDayMoney = oneDayTimeFrameCharge(list);
logger.info("停车完整一天收费:" + oneDayMoney);
oneDayMoney = oneDayMoney > maxOneDayMoney ? maxOneDayMoney : oneDayMoney;
......@@ -149,24 +205,22 @@ public class ThsTimeFramePayableMoney implements ThsRequestChargeAbstract {
logger.info("所跨天数停车的停车收费:" + sumMoney);
}
Date nowDate = new Date();
//记录最后一个区段的计费信息
TimeFrameChargeDetail lastDetail = list.get(list.size() - 1);
// //记录最后一个区段的计费信息
// TimeFrameChargeDetail lastDetail = list.get(list.size() - 1);
long firstDayMoney = 0, endDayMoney = 0;
//第一次循环是为了计算停车当天的总费用
String tempInTime = DateUtils.dateFormatToString(inTime, 3) + " ";
String tempNowTime = DateUtils.dateFormatToString(nowDate, 3) + " ";
for (TimeFrameChargeDetail detail : list) {
detail.beginTime = detail.beginTime + ":00";
detail.endTime = detail.endTime + ":00";
Date detailBeginTime = DateUtils.stringConvertDate(tempInTime + detail.beginTime, 3);
Date detailEndTime = DateUtils.stringConvertDate(tempInTime + detail.endTime, 3);
for (TimeFrameChargeDetailPOJO detail : list) {
Date detailBeginTime = DateUtils.stringConvertDate(tempInTime + detail.getBeginTime(), 3);
Date detailEndTime = DateUtils.stringConvertDate(tempInTime + detail.getEndTime(), 3);
//最初开始区段
if (inTime.compareTo(detailBeginTime) >= 0 &&
inTime.compareTo(detailEndTime) < 0
) {
Date tempEnd = DateUtils.stringConvertDate(DateUtils.dateFormatToString(inTime, 3) + " " + detail.endTime, 3);
Date tempEnd = DateUtils.stringConvertDate(DateUtils.dateFormatToString(inTime, 3) + " " + detail.getEndTime(), 3);
firstDayMoney += frameTypeTimeFrameCharge(detail, inTime, tempEnd);
}
//最初区段内
......@@ -179,16 +233,14 @@ public class ThsTimeFramePayableMoney implements ThsRequestChargeAbstract {
logger.info("停车当天的停车收费:" + firstDayMoney);
sumMoney += firstDayMoney;
//第二次循环是为了计算停车结束当天的总费用
for (TimeFrameChargeDetail detail : list) {
detail.beginTime = detail.beginTime + ":00";
detail.endTime = detail.endTime + ":00";
Date detailNowBeginTime = DateUtils.stringConvertDate(tempNowTime + detail.beginTime, 3);
Date detailNowEndTime = DateUtils.stringConvertDate(tempNowTime + detail.endTime, 3);
for (TimeFrameChargeDetailPOJO detail : list) {
Date detailNowBeginTime = DateUtils.stringConvertDate(tempNowTime + detail.getBeginTime(), 3);
Date detailNowEndTime = DateUtils.stringConvertDate(tempNowTime + detail.getEndTime(), 3);
//最终结束区段
if (nowDate.compareTo(detailNowBeginTime) > 0 &&
nowDate.compareTo(detailNowEndTime) <= 0
) {
Date tempBegin = DateUtils.stringConvertDate(tempNowTime + " " + detail.beginTime, 3);
Date tempBegin = DateUtils.stringConvertDate(tempNowTime + " " + detail.getBeginTime(), 3);
endDayMoney += frameTypeTimeFrameCharge(detail, tempBegin, nowDate);
}
//结束区段内
......@@ -209,16 +261,14 @@ public class ThsTimeFramePayableMoney implements ThsRequestChargeAbstract {
}
/**
* 按时段收费全时段的总费用
* 停车一天的总费用
*
* @param list
* @return
*/
public Integer oneDayTimeFrameCharge(List<TimeFrameChargeDetail> list) {
public Integer oneDayTimeFrameCharge(List<TimeFrameChargeDetailPOJO> list) {
int oneDayMoney = 0;
for (TimeFrameChargeDetail detail : list) {
detail.beginTime = detail.beginTime + ":00";
detail.endTime = detail.endTime + ":00";
for (TimeFrameChargeDetailPOJO detail : list) {
oneDayMoney += frameTypeTimeFrameCharge(detail, null, null);
}
return oneDayMoney;
......@@ -232,84 +282,67 @@ public class ThsTimeFramePayableMoney implements ThsRequestChargeAbstract {
* @param endTime 如果有结束时间,就以给定的结束时间计算
* @return
*/
public long frameTypeTimeFrameCharge(TimeFrameChargeDetail detail, Date beginTime, Date endTime) {
public long frameTypeTimeFrameCharge(TimeFrameChargeDetailPOJO detail, Date beginTime, Date endTime) {
if (beginTime == null) {
beginTime = DateUtils.stringConvertDate("2020-01-01 " + detail.beginTime, 3);
beginTime = DateUtils.stringConvertDate("2020-01-01 " + detail.getBeginTime(), 3);
}
if (endTime == null) {
endTime = DateUtils.stringConvertDate("2020-01-01 " + detail.endTime, 3);
endTime = DateUtils.stringConvertDate("2020-01-01 " + detail.getEndTime(), 3);
}
switch (detail.frameType) {
switch (detail.getFrameType()) {
//按照分钟收费
case 0:
long minute = DateUtils.subDate(beginTime, endTime, 2);
return minute * detail.money;
return minute * detail.getMoney();
//按照小时收费
case 1:
long hour = DateUtils.subDate(beginTime, endTime, 3);
return hour * detail.money;
return hour * detail.getMoney();
//按照固定收费
case 2:
return detail.money;
return detail.getMoney();
}
return 0;
}
/**
* 按时段收费
* "frameType": 0
* "beginTime": "00:00",
* "endTime": "07:00",
* 表示在00:00-07:00时间端内每分钟收费2元
* "money": 200
* <p>
* "frameType": 2
* "beginTime": "00:00",
* "endTime": "07:00",
* 表示在00:00-07:00时间端内一共收费3元
* "money": 300
* <p>
* "frameType": 0 按分钟收费
* "frameType": 1 按小时收费
* "frameType": 2 按固定收费
*/
static class TimeFrameChargeDetail {
private String beginTime;
private String endTime;
private Integer money;
private Integer frameType;
public Integer getFrameType() {
return frameType;
}
public void setFrameType(Integer frameType) {
this.frameType = frameType;
}
public String getBeginTime() {
return beginTime;
}
public void setBeginTime(String beginTime) {
this.beginTime = beginTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
public static void main(String[] args) {
ThsChargingRulesPO thsChargingRulesPO = new ThsChargingRulesPO();
thsChargingRulesPO.setFreeTime(10);
thsChargingRulesPO.setChargeType(RequestChargeTypeEnums.ONE_TIME.getCode());
thsChargingRulesPO.setMaxOneTimeMoney(20000000);
thsChargingRulesPO.setMaxOneDayMoney(20000000);
thsChargingRulesPO.setChargeDetails("{\n" +
" \"fastTime\": 0,\n" +
" \"frameType\": 0,\n" +
" \"fastMoney\": 0,\n" +
" \"data\": [\n" +
" {\n" +
" \"frameType\": 0,\n" +
" \"beginTime\": \"00:00\",\n" +
" \"endTime\": \"07:00\",\n" +
" \"money\": 200\n" +
" },\n" +
" {\n" +
" \"frameType\": 1,\n" +
" \"beginTime\": \"07:00\",\n" +
" \"endTime\": \"20:30\",\n" +
" \"money\": 400\n" +
" },\n" +
" {\n" +
" \"frameType\": 2,\n" +
" \"beginTime\": \"20:30\",\n" +
" \"endTime\": \"00:00\",\n" +
" \"money\": 300\n" +
" }\n" +
" ]\n" +
"}");
ThsTimeFramePayableMoney payableMoney = new ThsTimeFramePayableMoney();
Integer money = payableMoney.getPayableMoney(thsChargingRulesPO
, DateUtils.stringConvertDate("2020-05-27 06:25:20", 3)
, DateUtils.stringConvertDate("2020-05-27 15:26:28", 3));
//期望结果:8600
//计算结果:8600 正确
System.out.println(money);
}
}
package com.huaching.parking.local.parking_local_general.util.local.chargeCalculator;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.old;
import java.util.Date;
......
package com.huaching.parking.local.parking_local_general.util.local.chargeCalculator;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.old;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRules24OldPO;
import com.huaching.parking.local.parking_local_general.service.local.base.ChargingRulesOldService;
import com.huaching.parking.local.parking_local_general.service.local.base.impl.ChargingRulesOldServiceImpl;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......
package com.huaching.parking.local.parking_local_general.util.local.chargeCalculator;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.old;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesFeeOldPO;
import com.huaching.parking.local.parking_local_general.service.local.base.ChargingRulesOldService;
import com.huaching.parking.local.parking_local_general.service.local.base.impl.ChargingRulesOldServiceImpl;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......
package com.huaching.parking.local.parking_local_general.util.local.chargeCalculator;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.old;
import org.springframework.stereotype.Service;
......
package com.huaching.parking.local.parking_local_general.util.local.chargeCalculator;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.old;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesOldPO;
import com.huaching.parking.local.parking_local_general.service.local.base.ChargingRulesOldService;
import com.huaching.parking.local.parking_local_general.service.local.base.impl.ChargingRulesOldServiceImpl;
import com.huaching.parking.local.parking_local_general.util.local.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......
package com.huaching.parking.local.parking_local_general.util.local.chargeCalculator;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.old;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRules24OldPO;
import com.huaching.parking.local.parking_local_general.domain.local.po.ThsChargingRulesOldPO;
......
package com.huaching.parking.local.parking_local_general.util.local.chargeCalculator;
package com.huaching.parking.local.parking_local_general.service.local.base.chargeCalculator.old;
/**
* Created by sunke on 2018/3/5.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment