Bladeren bron

新增手动外呼明细

lmx 1 dag geleden
bovenliggende
commit
d15f24dea8

+ 111 - 0
fs-company/src/main/java/com/fs/company/controller/crm/ManualOutboundCallLogController.java

@@ -0,0 +1,111 @@
+package com.fs.company.controller.crm;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.company.domain.CrmCustomerCallLog;
+import com.fs.company.service.ICrmCustomerCallLogService;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.security.SecurityUtils;
+import com.fs.his.utils.PhoneUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 手动外呼通话记录Controller
+ *
+ * @author MixLiu
+ * @date 2026/5/25 18:23
+ */
+@RestController
+@RequestMapping("/crm/manualOutboundCallLog")
+public class ManualOutboundCallLogController extends BaseController {
+
+    @Autowired
+    private ICrmCustomerCallLogService crmCustomerCallLogService;
+
+    /**
+     * 查询手动外呼通话记录列表(管理员-查看公司全部)
+     */
+    @PreAuthorize("@ss.hasPermi('crm:manualOutboundCall:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CrmCustomerCallLog crmCustomerCallLog) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        crmCustomerCallLog.setCompanyId(loginUser.getCompany().getCompanyId());
+        encryptCallerNum(crmCustomerCallLog);
+        startPage();
+        List<CrmCustomerCallLog> list = crmCustomerCallLogService.selectCrmCustomerCallLogList(crmCustomerCallLog);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询我的手动外呼通话记录列表(个人-只看自己)
+     */
+    @PreAuthorize("@ss.hasPermi('crm:manualOutboundCall:myList')")
+    @GetMapping("/myList")
+    public TableDataInfo myList(CrmCustomerCallLog crmCustomerCallLog) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        crmCustomerCallLog.setCompanyId(loginUser.getCompany().getCompanyId());
+        crmCustomerCallLog.setCompanyUserId(loginUser.getUser().getUserId());
+        encryptCallerNum(crmCustomerCallLog);
+        startPage();
+        List<CrmCustomerCallLog> list = crmCustomerCallLogService.selectCrmCustomerCallLogList(crmCustomerCallLog);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询手动外呼通话记录计费分钟数总和(管理员-查看公司全部)
+     */
+    @PreAuthorize("@ss.hasPermi('crm:manualOutboundCall:list')")
+    @GetMapping("/sumBillingMinute")
+    public AjaxResult sumBillingMinute(CrmCustomerCallLog crmCustomerCallLog) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        crmCustomerCallLog.setCompanyId(loginUser.getCompany().getCompanyId());
+        encryptCallerNum(crmCustomerCallLog);
+        Long sum = crmCustomerCallLogService.selectSumBillingMinute(crmCustomerCallLog);
+        Map<String, Object> result = new HashMap<>();
+        result.put("sumBillingMinute", sum);
+        return AjaxResult.success(result);
+    }
+
+    /**
+     * 查询我的手动外呼通话记录计费分钟数总和(个人-只看自己)
+     */
+    @PreAuthorize("@ss.hasPermi('crm:manualOutboundCall:myList')")
+    @GetMapping("/mySumBillingMinute")
+    public AjaxResult mySumBillingMinute(CrmCustomerCallLog crmCustomerCallLog) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        crmCustomerCallLog.setCompanyId(loginUser.getCompany().getCompanyId());
+        crmCustomerCallLog.setCompanyUserId(loginUser.getUser().getUserId());
+        encryptCallerNum(crmCustomerCallLog);
+        Long sum = crmCustomerCallLogService.selectSumBillingMinute(crmCustomerCallLog);
+        Map<String, Object> result = new HashMap<>();
+        result.put("sumBillingMinute", sum);
+        return AjaxResult.success(result);
+    }
+
+    /**
+     * 处理客户号码查询参数,区分明文和加密两种匹配方式:
+     * 1. 手机(callerNum):输入明文号码,不加密,直接匹配 caller_num 字段(匹配历史明文数据)
+     * 2. 加密手机(encryptedCallerNum):输入明文号码,加密后设为 callerNum 匹配密文数据,
+     *    同时将原始明文保留到 plainCallerNum 匹配历史明文数据(OR条件覆盖两种存储格式)
+     * Mapper SQL: AND (caller_num = #{callerNum} OR caller_num = #{plainCallerNum})
+     */
+    private void encryptCallerNum(CrmCustomerCallLog param) {
+        if (StringUtils.isNotBlank(param.getEncryptedCallerNum())) {
+            // 加密手机输入:加密后匹配密文,原始明文保留匹配历史明文(OR覆盖)
+            param.setPlainCallerNum(param.getEncryptedCallerNum());
+            param.setCallerNum(PhoneUtil.encryptPhone(param.getEncryptedCallerNum()));
+            param.setEncryptedCallerNum(null);
+        }
+        // 手机输入:不加密,直接传明文匹配历史明文数据
+    }
+}

+ 2 - 1
fs-service/src/main/java/com/fs/aiSipCall/service/impl/AiSipCallOutboundCdrServiceImpl.java

@@ -668,7 +668,7 @@ public class AiSipCallOutboundCdrServiceImpl extends ServiceImpl<AiSipCallOutbou
         callLog.setCreateTime(new Date());
         callLog.setCreateTime(new Date());
         callLog.setRecordPath(callPhoneRes.getRecordFilename());
         callLog.setRecordPath(callPhoneRes.getRecordFilename());
         callLog.setContentList(callPhoneRes.getChatContent());
         callLog.setContentList(callPhoneRes.getChatContent());
-        callLog.setCallerNum(callPhoneRes.getCallee());
+        callLog.setCallerNum(PhoneUtil.encryptPhone(callPhoneRes.getCallee()));
         callLog.setCalleeNum(callPhoneRes.getCaller());
         callLog.setCalleeNum(callPhoneRes.getCaller());
         callLog.setUuid(req.getUuid());
         callLog.setUuid(req.getUuid());
         callLog.setCallCreateTime(callPhoneRes.getStartTime());
         callLog.setCallCreateTime(callPhoneRes.getStartTime());
@@ -707,6 +707,7 @@ public class AiSipCallOutboundCdrServiceImpl extends ServiceImpl<AiSipCallOutbou
             BigDecimal minuteCount = callTimeSecond.divide(ONE_MINUTES_SECOND, 0, RoundingMode.CEILING);
             BigDecimal minuteCount = callTimeSecond.divide(ONE_MINUTES_SECOND, 0, RoundingMode.CEILING);
             BigDecimal cost = minuteCount.multiply(callCharge);
             BigDecimal cost = minuteCount.multiply(callCharge);
             callLog.setCost(cost);
             callLog.setCost(cost);
+            callLog.setBillingMinute(minuteCount.intValue());
         }
         }
 
 
         return crmCustomerCallLogMapper.insertCrmCustomerCallLog(callLog);
         return crmCustomerCallLogMapper.insertCrmCustomerCallLog(callLog);

+ 24 - 1
fs-service/src/main/java/com/fs/company/domain/CrmCustomerCallLog.java

@@ -152,8 +152,31 @@ public class CrmCustomerCallLog extends BaseEntity {
     private Integer callType;
     private Integer callType;
 
 
     /**
     /**
-     * 查询条件:最小通话时长(秒),仅过滤 call_time &gt; minCallTime 的记录;传 0 即可筛选“已接通”
+     * 查询条件:加密客户号码(前端输入明文手机号后,由Controller加密设置到callerNum)
+     * 非持久化字段,insert SQL 使用显式字段列表,不受影响
+     */
+    private String encryptedCallerNum;
+
+    /**
+     * 查询条件:明文客户号码(由Controller将原始输入保留到此字段,用于匹配历史明文数据)
+     * 非持久化字段,insert SQL 使用显式字段列表,不受影响
+     */
+    private String plainCallerNum;
+
+    /**
+     * 查询条件:最小通话时长(秒),SQL使用CEILING(call_time/1000)匹配
      * 非持久化字段,insert SQL 使用显式字段列表,不受影响
      * 非持久化字段,insert SQL 使用显式字段列表,不受影响
      */
      */
     private Long minCallTime;
     private Long minCallTime;
+    
+    /**
+     * 查询条件:最大通话时长(秒),SQL使用CEILING(call_time/1000)匹配
+     * 非持久化字段,insert SQL 使用显式字段列表,不受影响
+     */
+    private Long maxCallTime;
+
+    /**
+     * 计费分钟数
+     */
+    private Integer billingMinute;
 }
 }

+ 2 - 0
fs-service/src/main/java/com/fs/company/mapper/CrmCustomerCallLogMapper.java

@@ -16,4 +16,6 @@ public interface CrmCustomerCallLogMapper extends BaseMapper<CrmCustomerCallLog>
     int insertCrmCustomerCallLog(CrmCustomerCallLog callLog);
     int insertCrmCustomerCallLog(CrmCustomerCallLog callLog);
 
 
     List<CrmCustomerCallLog> selectCrmCustomerCallLogList(CrmCustomerCallLog crmCustomerCallLog);
     List<CrmCustomerCallLog> selectCrmCustomerCallLogList(CrmCustomerCallLog crmCustomerCallLog);
+
+    Long selectSumBillingMinute(CrmCustomerCallLog crmCustomerCallLog);
 }
 }

+ 8 - 0
fs-service/src/main/java/com/fs/company/service/ICrmCustomerCallLogService.java

@@ -19,4 +19,12 @@ public interface ICrmCustomerCallLogService {
      * @return 客户通话记录集合
      * @return 客户通话记录集合
      */
      */
     List<CrmCustomerCallLog> selectCrmCustomerCallLogList(CrmCustomerCallLog crmCustomerCallLog);
     List<CrmCustomerCallLog> selectCrmCustomerCallLogList(CrmCustomerCallLog crmCustomerCallLog);
+
+    /**
+     * 查询客户通话记录计费分钟数总和
+     *
+     * @param crmCustomerCallLog 客户通话记录查询条件
+     * @return 计费分钟数总和
+     */
+    Long selectSumBillingMinute(CrmCustomerCallLog crmCustomerCallLog);
 }
 }

+ 5 - 0
fs-service/src/main/java/com/fs/company/service/impl/CrmCustomerCallLogServiceImpl.java

@@ -30,4 +30,9 @@ public class CrmCustomerCallLogServiceImpl implements ICrmCustomerCallLogService
     public List<CrmCustomerCallLog> selectCrmCustomerCallLogList(CrmCustomerCallLog crmCustomerCallLog) {
     public List<CrmCustomerCallLog> selectCrmCustomerCallLogList(CrmCustomerCallLog crmCustomerCallLog) {
         return crmCustomerCallLogMapper.selectCrmCustomerCallLogList(crmCustomerCallLog);
         return crmCustomerCallLogMapper.selectCrmCustomerCallLogList(crmCustomerCallLog);
     }
     }
+
+    @Override
+    public Long selectSumBillingMinute(CrmCustomerCallLog crmCustomerCallLog) {
+        return crmCustomerCallLogMapper.selectSumBillingMinute(crmCustomerCallLog);
+    }
 }
 }

+ 29 - 2
fs-service/src/main/resources/mapper/company/CrmCustomerCallLogMapper.xml

@@ -22,19 +22,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="callType" column="call_type" />
         <result property="callType" column="call_type" />
         <result property="createTime" column="create_time" />
         <result property="createTime" column="create_time" />
         <result property="contentList" column="content_list" />
         <result property="contentList" column="content_list" />
+        <result property="billingMinute" column="billing_minute" />
     </resultMap>
     </resultMap>
 
 
     <select id="selectCrmCustomerCallLogList" parameterType="CrmCustomerCallLog" resultMap="CrmCustomerCallLogResult">
     <select id="selectCrmCustomerCallLogList" parameterType="CrmCustomerCallLog" resultMap="CrmCustomerCallLogResult">
         select log_id, uuid, customer_id, company_id, company_user_id, caller_num, callee_num,
         select log_id, uuid, customer_id, company_id, company_user_id, caller_num, callee_num,
                call_create_time, call_answer_time, call_time, record_path, status, intention,
                call_create_time, call_answer_time, call_time, record_path, status, intention,
-               cost, call_type, create_time, content_list
+               cost, call_type, create_time, content_list, billing_minute
         from crm_customer_call_log
         from crm_customer_call_log
         <where>
         <where>
             <if test="customerId != null">AND customer_id = #{customerId}</if>
             <if test="customerId != null">AND customer_id = #{customerId}</if>
             <if test="companyId != null">AND company_id = #{companyId}</if>
             <if test="companyId != null">AND company_id = #{companyId}</if>
             <if test="companyUserId != null">AND company_user_id = #{companyUserId}</if>
             <if test="companyUserId != null">AND company_user_id = #{companyUserId}</if>
             <if test="status != null">AND status = #{status}</if>
             <if test="status != null">AND status = #{status}</if>
-            <if test="minCallTime != null">AND call_time &gt; #{minCallTime}</if>
+            <if test="minCallTime != null">AND CEILING(call_time/1000) &gt;= #{minCallTime}</if>
+            <if test="maxCallTime != null">AND CEILING(call_time/1000) &lt;= #{maxCallTime}</if>
+            <if test="callerNum != null and callerNum != ''">AND (caller_num = #{callerNum} OR caller_num = #{plainCallerNum})</if>
+            <if test="beginTime != null and beginTime != '' and endTime != null and endTime != ''">
+                AND date_format(create_time,'%Y-%m-%d') &gt;= #{beginTime}
+                AND date_format(create_time,'%Y-%m-%d') &lt;= #{endTime}
+            </if>
         </where>
         </where>
         order by create_time desc
         order by create_time desc
     </select>
     </select>
@@ -67,6 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="updateBy != null">update_by,</if>
             <if test="updateBy != null">update_by,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="callType != null">call_type,</if>
             <if test="callType != null">call_type,</if>
+            <if test="billingMinute != null">billing_minute,</if>
         </trim>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="runTime != null">#{runTime},</if>
             <if test="runTime != null">#{runTime},</if>
@@ -91,8 +99,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateBy != null">#{updateBy},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="callType != null">#{callType},</if>
             <if test="callType != null">#{callType},</if>
+            <if test="billingMinute != null">#{billingMinute},</if>
         </trim>
         </trim>
     </insert>
     </insert>
 
 
+    <select id="selectSumBillingMinute" parameterType="CrmCustomerCallLog" resultType="java.lang.Long">
+        select IFNULL(SUM(billing_minute), 0)
+        from crm_customer_call_log
+        <where>
+            <if test="customerId != null">AND customer_id = #{customerId}</if>
+            <if test="companyId != null">AND company_id = #{companyId}</if>
+            <if test="companyUserId != null">AND company_user_id = #{companyUserId}</if>
+            <if test="status != null">AND status = #{status}</if>
+            <if test="minCallTime != null">AND CEILING(call_time/1000) &gt;= #{minCallTime}</if>
+            <if test="maxCallTime != null">AND CEILING(call_time/1000) &lt;= #{maxCallTime}</if>
+            <if test="callerNum != null and callerNum != ''">AND (caller_num = #{callerNum} OR caller_num = #{plainCallerNum})</if>
+            <if test="beginTime != null and beginTime != '' and endTime != null and endTime != ''">
+                AND date_format(create_time,'%Y-%m-%d') &gt;= #{beginTime}
+                AND date_format(create_time,'%Y-%m-%d') &lt;= #{endTime}
+            </if>
+        </where>
+    </select>
+
 
 
 </mapper>
 </mapper>