实时话费扣减

master
wujingtao 2 years ago
parent 3e94fee6d3
commit 56339598ba

@ -118,7 +118,10 @@ public class DefaultNumberConstants {
* 30
*/
public static final int THIRTY = 30;
/**
* 60
*/
public static final int SIXTY = 60;
/**
* 90
*/

@ -50,4 +50,7 @@ public class BaseCallDeduct implements Serializable {
@ApiModelProperty(value = "创建时间")
private Date createTime;
@Column(name="type")
@ApiModelProperty(value = "消费类型1 话费消耗 2 套餐充值 3 余额充值")
private Integer type;
}

@ -102,4 +102,23 @@ public class Company extends BaseEntity implements Serializable {
@ApiModelProperty("授权状态")
@Column(name = "authorization_state")
private Boolean authorizationState = Boolean.FALSE;
@ApiModelProperty("版本号")
@Column(name = "version")
private int version=0;
@Column(name = "double_call_fee")
private Double doubleCallFee;
@Column(name = "roll_call_fee")
private Double rollCallFee;
@Column(name = "tiktok_call_fee")
private Double tiktokCallFee;
@Column(name = "delivery_call_fee")
private Double deliveryCallFee;
@Column(name = "talk_call_fee")
private Double talkCallFee;
}

@ -43,6 +43,7 @@ public interface CompanyRepository extends JpaRepository<Company, Long>, JpaSpec
/**
* id
*
* @param companyId
*/
@Modifying
@ -51,6 +52,7 @@ public interface CompanyRepository extends JpaRepository<Company, Long>, JpaSpec
/**
* id
*
* @param balance
* @param companyId
*/
@ -58,8 +60,21 @@ public interface CompanyRepository extends JpaRepository<Company, Long>, JpaSpec
@Query("UPDATE Company set userBalance = ?1 where id = ?2")
void updateUserBalance(Double balance, Long companyId);
/**
* id ()
*
* @param deduct
* @param companyId id
* @param version
* @return
*/
@Modifying
@Query("UPDATE Company set userBalance = (userBalance-?1),version =(version+1) where id = ?2 and version =?3")
int updateBalanceOptimistic(Double deduct, Long companyId, Integer version);
/**
* 0
*
* @return
*/
@Query(value = "from Company where userBalance < 0")
@ -67,6 +82,7 @@ public interface CompanyRepository extends JpaRepository<Company, Long>, JpaSpec
/**
* ID
*
* @param ids
* @return
*/
@ -74,6 +90,7 @@ public interface CompanyRepository extends JpaRepository<Company, Long>, JpaSpec
/**
* ID
*
* @param templateId
* @return
*/

@ -15,29 +15,41 @@ import java.util.Map;
public interface CompanyService {
/**
*
*
* @param companyDto
* @param companyId
* @return CompanyDto
*/
CompanyDto userUpdateCompany(CompanyDto companyDto, Long companyId) ;
CompanyDto userUpdateCompany(CompanyDto companyDto, Long companyId);
/**
*
*
* @param criteria
* @param pageable
* @return
*/
Map<String,Object> queryAll(CompanyQueryCriteria criteria, Pageable pageable);
Map<String, Object> queryAll(CompanyQueryCriteria criteria, Pageable pageable);
/**
* id
*
* @param id
* @return
*/
CompanyDto findCompanyById(Long id);
/**
* id
*
* @param companyId
* @return
*/
Company findCompanyInfo(Long companyId);
/**
* id
*
* @param companyId
* @return
*/
@ -45,13 +57,15 @@ public interface CompanyService {
/**
*
* @return
*
* @param companyDto
* @return
*/
CompanyDto createCompany(CompanyDto companyDto);
/**
*
*
* @param status
* @param id
*/
@ -59,25 +73,39 @@ public interface CompanyService {
/**
*
*
* @param companyDto
*/
void updateCompany(CompanyDto companyDto);
/**
* id
*
* @param companyId
*/
void deleteCompanyByCompanyId(Long companyId);
/**
*
*
* @param balance
* @param companyId
*/
void updateUserBalanceByCompanyId(Double balance, Long companyId);
/**
* ()
*
* @param deduct
* @param companyId id
* @param version
* @return
*/
int updateBalanceOptimistic(Double deduct, Long companyId, Integer version);
/**
*
*
* @return
*/
List<Company> findByCompanyListByBalance();
@ -92,6 +120,7 @@ public interface CompanyService {
/**
*
*
* @param aTrue
* @param id
*/
@ -99,6 +128,7 @@ public interface CompanyService {
/**
*
*
* @param companyType
* @param companyId
*/
@ -106,6 +136,7 @@ public interface CompanyService {
/**
* id
*
* @param userId
* @return
*/

@ -26,9 +26,9 @@ import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
* @author Zheng Jie
* @date 2019-03-25
*/
@Getter
@Setter
@NoArgsConstructor
@ -89,7 +89,6 @@ public class CompanyDto extends BaseDTO implements Serializable {
@ApiModelProperty("是否授权成功")
private Boolean authorizationState;
private int version = 0;
}

@ -53,7 +53,7 @@ public class CompanyServiceImpl implements CompanyService {
@Override
@Transactional(rollbackFor = Exception.class)
@CacheEvict(cacheNames = "companyCache", key = "#companyId")
public CompanyDto userUpdateCompany(CompanyDto companyDto, Long companyId) {
public CompanyDto userUpdateCompany(CompanyDto companyDto, Long companyId) {
Company byUserId = companyRepository.findById(companyId).orElseGet(Company::new);
if (byUserId == null) {
throw new EntityExistException(Company.class, "companyName", companyDto.getCompanyName());
@ -82,7 +82,8 @@ public class CompanyServiceImpl implements CompanyService {
@Override
public CompanyDto findCompanyById(Long id) {
return companyMapper.toDto(companyRepository.findById(id).orElseGet(Company::new));
Company company = companyRepository.findById(id).orElseGet(Company::new);
return companyMapper.toDto(company);
}
@Override
@ -91,6 +92,11 @@ public class CompanyServiceImpl implements CompanyService {
return companyRepository.findById(companyId).orElseGet(Company::new);
}
@Override
public Company findCompanyInfo(Long companyId) {
return companyRepository.findById(companyId).orElseGet(Company::new);
}
@Override
public CompanyDto createCompany(CompanyDto companyDto) {
Company company = new Company();
@ -104,7 +110,7 @@ public class CompanyServiceImpl implements CompanyService {
if (status != null) {
Company company = companyRepository.findById(id).orElseGet(Company::new);
if (company != null) {
if (ObjectUtil.isNull(company.getBusinessLicense()) || ObjectUtil.isNull(company.getLegalPersonIdFront()) || ObjectUtil.isNull(company.getManagerIdFront())){
if (ObjectUtil.isNull(company.getBusinessLicense()) || ObjectUtil.isNull(company.getLegalPersonIdFront()) || ObjectUtil.isNull(company.getManagerIdFront())) {
throw new BadRequestException(ResponseCode.USER_INFORMATION_ERROR.getDesc());
}
userRepository.updateStatusById(Boolean.TRUE, company.getUserId());
@ -142,6 +148,12 @@ public class CompanyServiceImpl implements CompanyService {
companyRepository.updateUserBalance(balance, companyId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int updateBalanceOptimistic(Double deduct, Long companyId, Integer version) {
return companyRepository.updateBalanceOptimistic(deduct, companyId, version);
}
@Override
public List<Company> findByCompanyListByBalance() {
return companyRepository.findCompanyAndUserBalanceLessThanZero();

@ -64,6 +64,10 @@ public class TelephoneCallController {
Company byId = companyService.findById(SecurityUtils.getCompanyId());
if (organize != null && byId != null) {
//TODO 检查余额
if (byId.getUserBalance() == null || byId.getUserBalance() <= 0) {
return CommonResponse.createByErrorMessage("余额不足,请充值后使用");
}
if (organize.getCallMode() != null) {
switch (organize.getCallMode()) {
case DefaultNumberConstants.ZERO_NUMBER:

@ -0,0 +1,10 @@
package com.baiye.modules.telemarkting.dao;
import com.baiye.modules.telemarkting.entity.CallDeduct;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface CallDeductRepository extends JpaRepository<CallDeduct, Long>, JpaSpecificationExecutor<CallDeduct> {
}

@ -47,7 +47,9 @@ public class AllCallInfo implements Serializable {
@Column(name = "clue_id")
@ApiModelProperty(value = "线索id")
private Long clueId;
@Column(name = "clue_type")
@ApiModelProperty(value = "线索类型")
private Integer clueType;
@Column(name = "member_id")
@ApiModelProperty(value = "所属人id")
private Long memberId;

@ -0,0 +1,27 @@
package com.baiye.modules.telemarkting.entity;
import com.baiye.model.entity.BaseCallDeduct;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author jt
*/
@Entity
@Getter
@Setter
@Table(name = "tb_call_deduct")
@EntityListeners(AuditingEntityListener.class)
public class CallDeduct extends BaseCallDeduct implements Serializable {
@Id
@ApiModelProperty(value = "主键id自动递增")
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}

@ -8,17 +8,17 @@ import com.baiye.modules.telemarkting.entity.dto.*;
* @date 2021/12/14
*/
public interface TelephoneCallService {
/**
*
*
* @param telephoneCallReqDTO
* @return
*/
CommonResponse<String> doubleCallReq(TelephoneCallReqDTO telephoneCallReqDTO,Long companyId);
CommonResponse<String> doubleCallReq(TelephoneCallReqDTO telephoneCallReqDTO, Long companyId);
/**
*
*
* @param telephoneCallBackDTO
*/
void doubleCallBack(TelephoneCallBackDTO telephoneCallBackDTO);
@ -40,10 +40,11 @@ public interface TelephoneCallService {
/**
* axb
*
* @param telephoneCallReqDTO
* @return
*/
CommonResponse<String> axbDialNumber(TelephoneCallReqDTO telephoneCallReqDTO,Long companyId);
CommonResponse<String> axbDialNumber(TelephoneCallReqDTO telephoneCallReqDTO, Long companyId);
/**
*
@ -51,7 +52,8 @@ public interface TelephoneCallService {
* @param telephoneCallReqDTO
* @return
*/
CommonResponse<String> rollCallReq(TelephoneCallReqDTO telephoneCallReqDTO,Long companyId);
CommonResponse<String> rollCallReq(TelephoneCallReqDTO telephoneCallReqDTO, Long companyId);
/**
*
*

@ -2,6 +2,7 @@ package com.baiye.modules.telemarkting.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
@ -11,16 +12,17 @@ import com.baiye.feign.SourceClueClient;
import com.baiye.http.CommonResponse;
import com.baiye.model.enums.CallStatusEnum;
import com.baiye.modules.system.domain.Clue;
import com.baiye.modules.telemarkting.dao.AllCallInfoRepository;
import com.baiye.modules.telemarkting.dao.CallClueRepository;
import com.baiye.modules.telemarkting.dao.ExtensionDisplayRepository;
import com.baiye.modules.telemarkting.dao.ExtensionNumberRepository;
import com.baiye.modules.system.domain.Company;
import com.baiye.modules.system.repository.CompanyRepository;
import com.baiye.modules.system.service.CompanyService;
import com.baiye.modules.telemarkting.dao.*;
import com.baiye.modules.telemarkting.entity.*;
import com.baiye.modules.telemarkting.entity.dto.*;
import com.baiye.modules.telemarkting.httpRequest.AxbRequest;
import com.baiye.modules.telemarkting.httpRequest.DoubleCallReq;
import com.baiye.modules.telemarkting.httpRequest.RollCallReq;
import com.baiye.modules.telemarkting.service.TelephoneCallService;
import com.baiye.util.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
@ -56,6 +58,12 @@ public class TelephoneCallServiceImpl implements TelephoneCallService {
private ExtensionNumberRepository extensionNumberRepository;
@Resource
private ExtensionDisplayRepository extensionDisplayRepository;
@Resource
private CompanyService companyService;
@Resource
private CallDeductRepository callDeductRepository;
@Resource
private CompanyRepository companyRepository;
@Override
public CommonResponse<String> doubleCallReq(TelephoneCallReqDTO doubleCallReq, Long companyId) {
@ -80,6 +88,7 @@ public class TelephoneCallServiceImpl implements TelephoneCallService {
allCallInfo.setSessionId(sessionId);
allCallInfo.setRequestId(requestId);
allCallInfo.setClueId(Long.parseLong(doubleCallReq.getUserData()));
allCallInfo.setClueType(doubleCallReq.getClueType());
allCallInfo.setMemberId(doubleCallReq.getMemberId());
allCallInfo.setStatus(DefaultNumberConstants.ONE_NUMBER);
allCallInfo.setType(DefaultNumberConstants.ONE_NUMBER);
@ -120,7 +129,13 @@ public class TelephoneCallServiceImpl implements TelephoneCallService {
if (CallStatusEnum.ANSWER.getDescription().equals(flag)) {
int status = CallStatusEnum.ANSWER.getValue();
callClueRepository.updateByStatus(status, userDate);
allCallInfoRepository.updateByStatus(status, sessionId);
// allCallInfoRepository.updateByStatus(status, sessionId);
AllCallInfo allCallInfo = allCallInfoRepository.findBySessionId(sessionId);
allCallInfo.setStatus(status);
allCallInfoRepository.save(allCallInfo);
//实时扣费
callCostCount(allCallInfo.getMemberId(), allCallInfo.getClueId(), allCallInfo.getClueType(), allCallInfo.getDuration(), DefaultNumberConstants.TWO_NUMBER);
//更新资源通话状态
CompletableFuture.runAsync(() -> updateSourceCallStatus(userDate, DefaultNumberConstants.TWO_NUMBER));
} else {
@ -159,6 +174,7 @@ public class TelephoneCallServiceImpl implements TelephoneCallService {
allCallInfo.setSessionId(sessionId);
allCallInfo.setRequestId(randomString);
allCallInfo.setClueId(originalNumber);
allCallInfo.setClueType(doubleCallReq.getClueType());
allCallInfo.setMemberId(doubleCallReq.getMemberId());
allCallInfo.setStatus(DefaultNumberConstants.ONE_NUMBER);
allCallInfo.setType(DefaultNumberConstants.THREE_NUMBER);
@ -241,6 +257,7 @@ public class TelephoneCallServiceImpl implements TelephoneCallService {
allCallInfo.setSessionId(requestId);
allCallInfo.setRequestId(requestId);
allCallInfo.setClueId(Long.parseLong(telephoneCallReqDTO.getUserData()));
allCallInfo.setClueType(telephoneCallReqDTO.getClueType());
allCallInfo.setMemberId(telephoneCallReqDTO.getMemberId());
allCallInfo.setStatus(DefaultNumberConstants.ONE_NUMBER);
allCallInfo.setType(DefaultNumberConstants.TWO_NUMBER);
@ -286,6 +303,8 @@ public class TelephoneCallServiceImpl implements TelephoneCallService {
allCallInfoRepository.updateByDurationAndStatus(DefaultNumberConstants.TWO_NUMBER, Integer.valueOf(rollCallBackDTO.getDuration()), allCallInfo.getId());
//更新资源通话状态
CompletableFuture.runAsync(() -> updateSourceCallStatus(allCallInfo.getClueId(), DefaultNumberConstants.TWO_NUMBER));
//TODO 实时扣除话费
callCostCount(allCallInfo.getMemberId(), allCallInfo.getClueId(), allCallInfo.getClueType(), Integer.valueOf(rollCallBackDTO.getDuration()), 2);
} else {
//更新资源通话状态
CompletableFuture.runAsync(() -> updateSourceCallStatus(allCallInfo.getClueId(), DefaultNumberConstants.ONE_NUMBER));
@ -308,4 +327,81 @@ public class TelephoneCallServiceImpl implements TelephoneCallService {
clueMiddle.setNewestCallTime(new Date());
sourceClueClient.update(clueMiddle);
}
/**
*
*
* @param memberId id
* @param clueId 线id
* @param clueType 线
* @param duration
* @param callType 1- 2-
*/
public void callCostCount(Long memberId, Long clueId, Integer clueType, Integer duration, Integer callType) {
Long companyId = SecurityUtils.getCompanyId();
Company company = companyService.findCompanyInfo(companyId);
//模板费用
double fee;
if (callType == DefaultNumberConstants.ONE_NUMBER) {
//双呼
fee = company.getDoubleCallFee();
} else {
//点呼
if (clueType == DefaultNumberConstants.THREE_NUMBER) {
fee = company.getTiktokCallFee();
} else if (clueType == DefaultNumberConstants.FOUR_NUMBER) {
fee = company.getDeliveryCallFee();
} else if (clueType == DefaultNumberConstants.FIVE_NUMBER) {
fee = company.getTalkCallFee();
} else {
fee = company.getRollCallFee();
}
}
double minDuration = dealDuration(duration);
double mul = NumberUtil.mul(minDuration, fee);
CallDeduct callDeduct = new CallDeduct();
callDeduct.setDeductDuration((int) minDuration);
callDeduct.setDeductAmount(mul);
callDeduct.setClueId(clueId);
callDeduct.setMemberId(memberId);
callDeduct.setCompanyId(companyId);
callDeduct.setStatus(false);
callDeduct.setCreateTime(new Date());
callDeduct.setVersion(company.getVersion());
callDeduct.setType(DefaultNumberConstants.ONE_NUMBER);
CallDeduct save = callDeductRepository.save(callDeduct);
updateBalance(mul, companyId, company.getVersion(), save);
}
private void updateBalance(Double mul, Long companyId, Integer version, CallDeduct save) {
int num = companyService.updateBalanceOptimistic(mul, companyId, version);
if (num > 0) {
save.setVersion(version);
save.setStatus(true);
callDeductRepository.save(save);
} else {
updateBalance(mul, companyId, version + 1, save);
}
}
/**
*
*
* @param duration
* @return
*/
private Double dealDuration(int duration) {
if (duration <= DefaultNumberConstants.SIXTY) {
return 1.00;
} else {
int i = duration % 60;
double div = NumberUtil.div(duration, 60);
if (i > 0) {
return NumberUtil.add(div, 1);
} else {
return div;
}
}
}
}

@ -19,8 +19,9 @@ public class SettlementSync {
/**
* 11
* TODO 使
*/
@Scheduled(cron = "0 30 23 * * ?")
// @Scheduled(cron = "0 30 23 * * ?")
public void settlementCallDuration() {
callCostService.callCost();
}

@ -604,23 +604,22 @@ public class ClueServiceImpl implements ClueService {
@Override
public List<ClueMiddle> queryClueByCondition(String startTime, String endTime, Long memberId) {
//有意向的阶段 3已加微信 4:高意向 5:邀约中 6到场
List<Integer> stages = Arrays.asList(ClueStageEnum.ADD_WECHAT.getKey(), ClueStageEnum.INTENTION.getKey(), ClueStageEnum.INVITING.getKey(), ClueStageEnum.INTERVIEW.getKey());
//fixme 2022-11-09 加上有效
List<Integer> stages = Arrays.asList(ClueStageEnum.EFFICIENT.getKey(), ClueStageEnum.ADD_WECHAT.getKey(), ClueStageEnum.INTENTION.getKey(), ClueStageEnum.INVITING.getKey(), ClueStageEnum.INTERVIEW.getKey());
return clueMiddleRepository.queryClueByCondition(startTime, endTime, memberId, stages);
}
@Override
public Integer queryClueByAdmin(Long memberId) {
//有意向的阶段 3已加微信 4:高意向 5:邀约中 6到场
List<Integer> stages = Arrays.asList(ClueStageEnum.ADD_WECHAT.getKey(), ClueStageEnum.INTENTION.getKey(), ClueStageEnum.INVITING.getKey(), ClueStageEnum.INTERVIEW.getKey());
List<Integer> stages = Arrays.asList(ClueStageEnum.EFFICIENT.getKey(),ClueStageEnum.ADD_WECHAT.getKey(), ClueStageEnum.INTENTION.getKey(), ClueStageEnum.INVITING.getKey(), ClueStageEnum.INTERVIEW.getKey());
return clueMiddleRepository.queryClueByAdmin(memberId, DateUtil.today(), stages);
}
@Override
public Integer countClueByTaskId(Long taskId, String beginTime, String endTime) {
//有意向的阶段 3已加微信 4:高意向 5:邀约中 6到场
List<Integer> stages = Arrays.asList(ClueStageEnum.ADD_WECHAT.getKey(), ClueStageEnum.INTENTION.getKey(), ClueStageEnum.INVITING.getKey(), ClueStageEnum.INTERVIEW.getKey());
List<Integer> stages = Arrays.asList(ClueStageEnum.EFFICIENT.getKey(),ClueStageEnum.ADD_WECHAT.getKey(), ClueStageEnum.INTENTION.getKey(), ClueStageEnum.INVITING.getKey(), ClueStageEnum.INTERVIEW.getKey());
return clueMiddleRepository.countClueByTaskId(taskId, beginTime, endTime, stages);
}

Loading…
Cancel
Save