Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-csf
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-csf
Commits
b70d4af7
Commit
b70d4af7
authored
Nov 24, 2025
by
zhangxingmin
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/test' into test
parents
744d58f7
0707d9ed
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
845 additions
and
55 deletions
+845
-55
yd-csf-api/src/main/java/com/yd/csf/api/controller/ApiCommissionController.java
+32
-5
yd-csf-api/src/main/java/com/yd/csf/api/controller/ApiPolicyFollowController.java
+96
-3
yd-csf-service/pom.xml
+19
-0
yd-csf-service/src/main/java/com/yd/csf/service/dao/CommissionMapper.java
+5
-0
yd-csf-service/src/main/java/com/yd/csf/service/dto/CommissionAddRequest.java
+6
-0
yd-csf-service/src/main/java/com/yd/csf/service/dto/CommissionQueryRequest.java
+8
-0
yd-csf-service/src/main/java/com/yd/csf/service/dto/CommissionStatisticsRequest.java
+15
-0
yd-csf-service/src/main/java/com/yd/csf/service/dto/CommissionUpdateRequest.java
+6
-0
yd-csf-service/src/main/java/com/yd/csf/service/dto/PolicyReportData.java
+39
-0
yd-csf-service/src/main/java/com/yd/csf/service/enums/FortuneStatusEnum.java
+1
-0
yd-csf-service/src/main/java/com/yd/csf/service/model/Fortune.java
+5
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/CommissionService.java
+3
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/PolicyFollowService.java
+2
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/PolicyReportPdfService.java
+399
-0
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/CommissionServiceImpl.java
+94
-46
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/PolicyFollowServiceImpl.java
+41
-0
yd-csf-service/src/main/java/com/yd/csf/service/vo/CommissionStatisticsVO.java
+44
-0
yd-csf-service/src/main/java/com/yd/csf/service/vo/CommissionVO.java
+6
-0
yd-csf-service/src/main/resources/font/DFKai-SB.ttf
+0
-0
yd-csf-service/src/main/resources/mappers/CommissionMapper.xml
+22
-0
yd-csf-service/src/main/resources/mappers/FortuneMapper.xml
+2
-1
No files found.
yd-csf-api/src/main/java/com/yd/csf/api/controller/ApiCommissionController.java
View file @
b70d4af7
package
com
.
yd
.
csf
.
api
.
controller
;
import
com.alibaba.excel.EasyExcel
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.utils.SecurityUtil
;
...
...
@@ -14,6 +15,7 @@ import com.yd.csf.service.model.Commission;
import
com.yd.csf.service.model.CommissionExpected
;
import
com.yd.csf.service.service.CommissionExpectedService
;
import
com.yd.csf.service.service.CommissionService
;
import
com.yd.csf.service.vo.CommissionStatisticsVO
;
import
com.yd.csf.service.vo.CommissionVO
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
...
...
@@ -30,7 +32,9 @@ import javax.servlet.http.HttpServletRequest;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
/**
...
...
@@ -247,6 +251,19 @@ public class ApiCommissionController {
}
/**
* 计算统计数据 总金额、总入账金额、待入账金额、已入账比例(已入账金额/总金额)、总保单数
*/
@PostMapping
(
"/statistics"
)
@Operation
(
summary
=
"计算统计数据 总金额、总入账金额、待入账金额、已入账比例(已入账金额/总金额)、总保单数"
)
public
Result
<
CommissionStatisticsVO
>
getCommissionStatistics
(
@RequestBody
CommissionStatisticsRequest
commissionStatisticsRequest
)
{
if
(
commissionStatisticsRequest
==
null
)
{
return
Result
.
fail
(
ErrorCode
.
PARAMS_ERROR
.
getCode
(),
ErrorCode
.
PARAMS_ERROR
.
getMessage
());
}
return
Result
.
success
(
commissionService
.
getCommissionStatistics
(
commissionStatisticsRequest
.
getCommissionIds
()));
}
/**
* 根据 commissionBizId 获取保单来佣(封装类)
*
* @param commissionBizId
...
...
@@ -293,16 +310,26 @@ public class ApiCommissionController {
*/
@PostMapping
(
"/list/page/vo"
)
@Operation
(
summary
=
"分页获取保单来佣列表"
)
public
Result
<
Page
<
CommissionVO
>>
listPolicyFollowByPage
(
@RequestBody
CommissionQueryRequest
commissionQueryRequest
,
public
Result
<
Map
<
String
,
Object
>>
listPolicyFollowByPage
(
@RequestBody
CommissionQueryRequest
commissionQueryRequest
,
HttpServletRequest
request
)
{
long
current
=
commissionQueryRequest
.
getPageNo
();
long
size
=
commissionQueryRequest
.
getPageSize
();
// 查询数据库
// 查询列表数据
QueryWrapper
<
Commission
>
queryWrapper
=
commissionService
.
getQueryWrapper
(
commissionQueryRequest
);
Page
<
Commission
>
commissionPage
=
commissionService
.
page
(
new
Page
<>(
current
,
size
),
commissionService
.
getQueryWrapper
(
commissionQueryRequest
));
// 获取封装类
return
Result
.
success
(
commissionService
.
getCommissionVOPage
(
commissionPage
));
queryWrapper
);
// 查询统计数据
List
<
Commission
>
commissionList
=
commissionService
.
list
(
queryWrapper
);
// 计算统计数据
List
<
Long
>
commissionIds
=
commissionList
.
stream
().
map
(
Commission:
:
getId
).
collect
(
Collectors
.
toList
());
CommissionStatisticsVO
commissionStatisticsVO
=
commissionService
.
getCommissionStatistics
(
commissionIds
);
// 组装返回值
Map
<
String
,
Object
>
map
=
new
HashMap
<>();
map
.
put
(
"commissionStatisticsVO"
,
commissionStatisticsVO
);
map
.
put
(
"page"
,
commissionService
.
getCommissionVOPage
(
commissionPage
));
return
Result
.
success
(
map
);
}
}
yd-csf-api/src/main/java/com/yd/csf/api/controller/ApiPolicyFollowController.java
View file @
b70d4af7
...
...
@@ -12,19 +12,18 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.utils.SecurityUtil
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.csf.api.dto.CommissionExcelDTO
;
import
com.yd.csf.api.dto.PolicyExcelDTO
;
import
com.yd.csf.api.dto.PolicyFollowDTO
;
import
com.yd.csf.api.listener.PolicyDataListener
;
import
com.yd.csf.api.service.ApiExpectedFortuneService
;
import
com.yd.csf.service.common.ErrorCode
;
import
com.yd.csf.service.dto.*
;
import
com.yd.csf.service.enums.PolicyFollowStatusEnum
;
import
com.yd.csf.service.model.*
;
import
com.yd.csf.service.service.*
;
import
com.yd.csf.service.utils.AsyncQueryUtil
;
import
com.yd.csf.service.vo.PolicyFollowDetailVO
;
import
com.yd.csf.service.vo.PolicyFollowRecordVO
;
import
com.yd.csf.service.vo.PolicyFollowVO
;
...
...
@@ -35,13 +34,15 @@ import org.apache.commons.lang3.StringUtils;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.annotation.Resource
;
import
javax.servlet.ServletOutputStream
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.math.BigDecimal
;
import
java.text.DecimalFormat
;
import
java.text.ParseException
;
import
java.util.*
;
...
...
@@ -82,6 +83,10 @@ public class ApiPolicyFollowController {
private
PolicyFollowFileService
policyFollowFileService
;
@Resource
private
PolicyReportPdfService
policyReportPdfService
;
@PostMapping
(
"/upload/excel"
)
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Result
<
Boolean
>
uploadExcel
(
@RequestParam
(
"file"
)
MultipartFile
file
)
throws
Exception
{
...
...
@@ -258,6 +263,8 @@ public class ApiPolicyFollowController {
if
(
policyFollow
.
getEffectiveDate
()!=
null
&&
policyFollow
.
getCoolingOffDays
()
!=
null
)
{
policyFollow
.
setCoolingOffEndDate
(
DateUtil
.
offset
(
policyFollow
.
getEffectiveDate
(),
DateField
.
DAY_OF_MONTH
,
policyFollow
.
getCoolingOffDays
()));
}
// 获取币种字典值
policyFollow
.
setCurrency
(
policyFollowService
.
getCurrencyValue
(
policyExcelDTO
.
getCurrency
()));
// 转换为Policy对象
Policy
policy
=
new
Policy
();
...
...
@@ -549,4 +556,89 @@ public class ApiPolicyFollowController {
List
<
PolicyFollowRecord
>
policyFollowStatusList
=
policyFollowRecordService
.
list
(
queryWrapper
);
return
Result
.
success
(
policyFollowRecordService
.
getVOList
(
policyFollowStatusList
));
}
/**
* 生成签约单
*/
@GetMapping
(
value
=
"/report/download"
,
produces
=
"application/pdf"
)
@Operation
(
summary
=
"生成签约单"
)
public
void
previewPolicyReport
(
@RequestParam
(
"policyBizId"
)
String
policyBizId
,
HttpServletResponse
response
)
{
PolicyFollow
policyFollow
=
policyFollowService
.
getByPolicyBizId
(
policyBizId
);
if
(
policyFollow
==
null
)
{
throw
new
BusinessException
(
ErrorCode
.
NOT_FOUND_ERROR
.
getCode
(),
ErrorCode
.
NOT_FOUND_ERROR
.
getMessage
());
}
PolicyReportData
reportData
=
new
PolicyReportData
();
// 填充数据
// reportData.setStartTime("2025-10-30");
// reportData.setEndTime("2025-10-30");
// reportData.setLocation("香港");
// reportData.setServiceManager("Vickie");
// reportData.setPolicyHolder(policyFollow.getPolicyHolder());
// reportData.setPolicyNumber(policyFollow.getPolicyNo());
// reportData.setInsuranceCompany(policyFollow.getInsurer());
// reportData.setInsuredPerson(policyFollow.getInsured());
// reportData.setInsurancePlan(policyFollow.getProductName());
// reportData.setInsuredAge(0);
// reportData.setCurrency(policyFollow.getCurrency());
// reportData.setPaymentPeriod((Integer) policyFollow.getPaymentTerm());
// reportData.setAnnualAmount(policyFollow.getPaymentPremium());
// reportData.setTotalPrepayment(BigDecimal.ZERO);
// reportData.setPremiumFee(BigDecimal.ZERO);
reportData
.
setStartTime
(
"2025-10-30"
);
reportData
.
setEndTime
(
"2025-10-30"
);
reportData
.
setLocation
(
"香港"
);
reportData
.
setServiceManager
(
"Vickie"
);
reportData
.
setPolicyHolder
(
"policyHolder"
);
reportData
.
setPolicyNumber
(
"B635379588"
);
reportData
.
setInsuranceCompany
(
"友邦保险"
);
reportData
.
setInsuredPerson
(
"insuredPerson"
);
reportData
.
setInsurancePlan
(
"环宇盈活储蓄保险计划"
);
reportData
.
setInsuredAge
(
1
);
reportData
.
setCurrency
(
"HKD"
);
reportData
.
setPaymentPeriod
(
5
);
reportData
.
setAnnualAmount
(
BigDecimal
.
valueOf
(
30000.08
));
reportData
.
setTotalPrepayment
(
BigDecimal
.
valueOf
(
150064.70
));
reportData
.
setPremiumFee
(
BigDecimal
.
valueOf
(
12.86
));
try
{
log
.
info
(
"收到PDF生成请求: {}"
,
reportData
);
log
.
info
(
"PolicyReportData 内容检查:"
);
log
.
info
(
"startTime: {}"
,
reportData
.
getStartTime
());
log
.
info
(
"endTime: {}"
,
reportData
.
getEndTime
());
log
.
info
(
"location: {}"
,
reportData
.
getLocation
());
log
.
info
(
"serviceManager: {}"
,
reportData
.
getServiceManager
());
byte
[]
pdfBytes
=
policyReportPdfService
.
generatePolicyReport
(
reportData
);
if
(
pdfBytes
==
null
||
pdfBytes
.
length
==
0
)
{
log
.
error
(
"生成的PDF为空"
);
throw
new
BusinessException
(
"生成的PDF内容为空"
);
}
log
.
info
(
"PDF生成成功,大小: {} bytes"
,
pdfBytes
.
length
);
// 设置下载响应头
response
.
setContentType
(
"application/pdf"
);
response
.
setHeader
(
"Content-Disposition"
,
"attachment; filename=policy-report-"
+
reportData
.
getPolicyNumber
()
+
".pdf"
);
response
.
setContentLength
(
pdfBytes
.
length
);
// 写入响应流
ServletOutputStream
outputStream
=
response
.
getOutputStream
();
outputStream
.
write
(
pdfBytes
);
outputStream
.
flush
();
log
.
info
(
"PDF响应发送完成"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"PDF预览失败"
,
e
);
throw
new
BusinessException
(
"PDF预览失败: "
+
e
.
getMessage
());
}
}
}
\ No newline at end of file
yd-csf-service/pom.xml
View file @
b70d4af7
...
...
@@ -12,6 +12,20 @@
<artifactId>
yd-csf-service
</artifactId>
<dependencies>
<!-- 公共工具类 -->
<dependency>
<groupId>
commons-io
</groupId>
<artifactId>
commons-io
</artifactId>
<version>
2.11.0
</version>
</dependency>
<!-- itextpdf -->
<dependency>
<groupId>
com.github.librepdf
</groupId>
<artifactId>
openpdf
</artifactId>
<version>
1.3.30
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
easyexcel
</artifactId>
...
...
@@ -104,5 +118,10 @@
<artifactId>
yd-feign
</artifactId>
<version>
${project.version}
</version>
</dependency>
<!-- 添加AOP依赖 -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-aop
</artifactId>
</dependency>
</dependencies>
</project>
yd-csf-service/src/main/java/com/yd/csf/service/dao/CommissionMapper.java
View file @
b70d4af7
package
com
.
yd
.
csf
.
service
.
dao
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.yd.csf.service.dto.CommissionBindPolicyBrokerDto
;
import
com.yd.csf.service.dto.CommissionDto
;
import
com.yd.csf.service.model.Commission
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.yd.csf.service.vo.CommissionStatisticsVO
;
import
com.yd.csf.service.vo.CommissionVO
;
import
org.apache.ibatis.annotations.Param
;
import
java.util.List
;
...
...
@@ -17,6 +20,8 @@ import java.util.List;
public
interface
CommissionMapper
extends
BaseMapper
<
Commission
>
{
List
<
CommissionBindPolicyBrokerDto
>
queryCommissionBindPolicyBrokerList
(
@Param
(
"dto"
)
CommissionDto
dto
);
CommissionStatisticsVO
getCommissionStatistics
(
@Param
(
"commissionIdList"
)
List
<
Long
>
commissionIdList
);
}
...
...
yd-csf-service/src/main/java/com/yd/csf/service/dto/CommissionAddRequest.java
View file @
b70d4af7
...
...
@@ -64,6 +64,12 @@ public class CommissionAddRequest implements Serializable {
private
String
currency
;
/**
* 结算汇率
*/
@Schema
(
description
=
"结算汇率"
)
private
String
exchangeRate
;
/**
* 来佣日期
*/
@Schema
(
description
=
"来佣日期"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
format
=
"yyyy-MM-dd"
)
...
...
yd-csf-service/src/main/java/com/yd/csf/service/dto/CommissionQueryRequest.java
View file @
b70d4af7
...
...
@@ -49,5 +49,12 @@ public class CommissionQueryRequest extends PageDto implements Serializable {
@JsonFormat
(
pattern
=
"yyyy-MM-dd"
,
timezone
=
"GMT+8"
)
private
Date
commissionDateEnd
;
/**
* 预计入账日期
*/
@Schema
(
description
=
"预计入账日期 格式-yyyy-MM-dd"
,
example
=
"2023-01-01"
)
@JsonFormat
(
pattern
=
"yyyy-MM-dd"
,
timezone
=
"GMT+8"
)
private
Date
expectedDate
;
private
static
final
long
serialVersionUID
=
1L
;
}
\ No newline at end of file
yd-csf-service/src/main/java/com/yd/csf/service/dto/CommissionStatisticsRequest.java
0 → 100644
View file @
b70d4af7
package
com
.
yd
.
csf
.
service
.
dto
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
CommissionStatisticsRequest
{
/**
* 佣金ID列表
*/
@Schema
(
description
=
"佣金ID列表"
)
private
List
<
Long
>
commissionIds
;
}
yd-csf-service/src/main/java/com/yd/csf/service/dto/CommissionUpdateRequest.java
View file @
b70d4af7
...
...
@@ -75,6 +75,12 @@ public class CommissionUpdateRequest implements Serializable {
@Schema
(
description
=
"来佣币种"
)
private
String
currency
;
/**
* 结算汇率
*/
@Schema
(
description
=
"结算汇率"
)
private
String
exchangeRate
;
/**
* 来佣日期
*/
...
...
yd-csf-service/src/main/java/com/yd/csf/service/dto/PolicyReportData.java
0 → 100644
View file @
b70d4af7
package
com
.
yd
.
csf
.
service
.
dto
;
import
lombok.Data
;
import
java.math.BigDecimal
;
import
java.util.List
;
@Data
public
class
PolicyReportData
{
// 基本信息
private
String
startTime
;
private
String
endTime
;
private
String
location
;
private
String
serviceManager
;
// 保单详细信息
private
String
policyHolder
;
private
String
policyNumber
;
private
String
insuranceCompany
;
private
String
insuredPerson
;
private
String
insurancePlan
;
private
Integer
insuredAge
;
private
String
currency
;
private
Integer
paymentPeriod
;
private
BigDecimal
annualAmount
;
private
BigDecimal
totalPrepayment
;
private
BigDecimal
premiumFee
;
// 附加险信息
private
List
<
AdditionalInsurance
>
additionalInsurances
;
@Data
public
static
class
AdditionalInsurance
{
private
String
name
;
private
String
paymentTerm
;
private
String
currency
;
private
BigDecimal
firstYearAmount
;
}
}
yd-csf-service/src/main/java/com/yd/csf/service/enums/FortuneStatusEnum.java
View file @
b70d4af7
...
...
@@ -9,6 +9,7 @@ public enum FortuneStatusEnum {
WAIT
(
"待出账"
,
"0"
),
CAN_SEND
(
"可出账"
,
"1"
),
SENT
(
"已出账"
,
"2"
),
MATCH_FAIL
(
"未找到当前预计发佣对应的来佣"
,
"3"
),
;
//字典项标签(名称)
...
...
yd-csf-service/src/main/java/com/yd/csf/service/model/Fortune.java
View file @
b70d4af7
...
...
@@ -30,6 +30,11 @@ public class Fortune implements Serializable {
*/
private
String
fortuneBizId
;
/**
* 来佣保单业务id
*/
private
String
commissionBizId
;
/**
* 保单号
*/
...
...
yd-csf-service/src/main/java/com/yd/csf/service/service/CommissionService.java
View file @
b70d4af7
...
...
@@ -7,6 +7,7 @@ import com.yd.csf.service.dto.*;
import
com.yd.csf.service.model.Commission
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yd.csf.service.model.CommissionExpected
;
import
com.yd.csf.service.vo.CommissionStatisticsVO
;
import
com.yd.csf.service.vo.CommissionVO
;
import
java.util.List
;
...
...
@@ -36,4 +37,6 @@ public interface CommissionService extends IService<Commission> {
List
<
Commission
>
queryList
(
CommissionDto
dto
);
List
<
CommissionBindPolicyBrokerDto
>
queryCommissionBindPolicyBrokerList
(
CommissionDto
dto
);
CommissionStatisticsVO
getCommissionStatistics
(
List
<
Long
>
commissionIds
);
}
yd-csf-service/src/main/java/com/yd/csf/service/service/PolicyFollowService.java
View file @
b70d4af7
...
...
@@ -42,4 +42,6 @@ public interface PolicyFollowService extends IService<PolicyFollow> {
PolicyFollowAggregateDto
getPolicyFollowAggregate
(
String
policyBizId
);
Page
<
PolicyFollowDetailVO
>
getPolicyFollowDetailVOList
(
Page
<
PolicyFollow
>
policyFollowPage
);
String
getCurrencyValue
(
String
currency
);
}
yd-csf-service/src/main/java/com/yd/csf/service/service/PolicyReportPdfService.java
0 → 100644
View file @
b70d4af7
package
com
.
yd
.
csf
.
service
.
service
;
import
com.lowagie.text.Document
;
import
com.lowagie.text.DocumentException
;
import
com.lowagie.text.Font
;
import
com.lowagie.text.PageSize
;
import
com.lowagie.text.Paragraph
;
import
com.lowagie.text.pdf.BaseFont
;
import
com.lowagie.text.pdf.PdfContentByte
;
import
com.lowagie.text.pdf.PdfPTable
;
import
com.lowagie.text.pdf.PdfWriter
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.csf.service.dto.PolicyReportData
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.io.IOUtils
;
import
org.springframework.stereotype.Service
;
import
java.awt.*
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.math.BigDecimal
;
@Service
@Slf4j
public
class
PolicyReportPdfService
{
private
Font
chineseFont
;
private
Font
chineseBoldFont
;
private
Font
chineseTitleFont
;
private
Font
chineseRedTitleFont
;
// 颜色定义
private
static
final
Color
RED_TITLE_COLOR
=
new
Color
(
255
,
0
,
0
);
private
static
final
Color
TEXT_COLOR
=
new
Color
(
102
,
102
,
102
);
private
static
final
Color
FOOTNOTE_COLOR
=
new
Color
(
153
,
153
,
153
);
private
static
final
Color
LINE_COLOR
=
new
Color
(
226
,
226
,
226
);
// 调整字号常量
private
static
final
float
MAIN_TITLE_FONT_SIZE
=
28
f
;
// 增大主标题字号
private
static
final
float
SECTION_TITLE_FONT_SIZE
=
16
f
;
// 调整章节标题字号
private
static
final
float
CONTENT_FONT_SIZE
=
12
f
;
// 调整内容文字字号
private
static
final
float
FOOTNOTE_FONT_SIZE
=
10
f
;
// 调整备注文字字号
// 调整间距常量
private
static
final
float
MAIN_TITLE_MARGIN_BOTTOM
=
20
f
;
// 增大主标题下方间距
private
static
final
float
LINE_MARGIN_BOTTOM
=
18
f
;
// 调整水平线间距
private
static
final
float
ROW_SPACING
=
12
f
;
// 调整行间距
public
byte
[]
generatePolicyReport
(
PolicyReportData
reportData
)
throws
DocumentException
{
ByteArrayOutputStream
outputStream
=
new
ByteArrayOutputStream
();
try
{
Document
document
=
new
Document
(
PageSize
.
A4
,
40
,
40
,
40
,
40
);
PdfWriter
writer
=
PdfWriter
.
getInstance
(
document
,
outputStream
);
document
.
open
();
initChineseFont
();
// 1. 主标题
addMainTitle
(
document
,
"簽單完成報告"
);
// 2. 主标题下方水平线
addHorizontalLine
(
document
,
writer
);
// 3. 基本信息表格
addBasicInfo
(
document
,
reportData
);
// 4. 保单详细信息标题
addPolicyDetailTitle
(
document
,
reportData
);
// 5. 保单详细信息标题下方水平线
addHorizontalLine
(
document
,
writer
);
// 6. 保单详细字段表格(包含备注和保費徵費)
addPolicyDetailFields
(
document
,
reportData
);
// 7. 附加险表头
addAdditionalInsuranceHeader
(
document
);
// 8. 详细信息下方水平线
addHorizontalLine
(
document
,
writer
);
// 移除了原来的备注说明,因为现在备注已经整合到保单详细字段中
document
.
close
();
return
outputStream
.
toByteArray
();
}
catch
(
Exception
e
)
{
log
.
error
(
"PDF生成失败"
,
e
);
throw
new
BusinessException
(
"生成报告失败: "
+
e
.
getMessage
());
}
}
/**
* 主标题 - 放大并居中
*/
private
void
addMainTitle
(
Document
document
,
String
title
)
throws
DocumentException
{
// 创建更大的红色标题字体
Font
largeTitleFont
=
new
Font
(
chineseRedTitleFont
.
getBaseFont
(),
MAIN_TITLE_FONT_SIZE
,
Font
.
BOLD
,
RED_TITLE_COLOR
);
Paragraph
titleParagraph
=
new
Paragraph
(
title
,
largeTitleFont
);
titleParagraph
.
setAlignment
(
Paragraph
.
ALIGN_CENTER
);
// 设置为居中
titleParagraph
.
setSpacingAfter
(
MAIN_TITLE_MARGIN_BOTTOM
);
document
.
add
(
titleParagraph
);
}
/**
* 水平线 - 调整位置
*/
private
void
addHorizontalLine
(
Document
document
,
PdfWriter
writer
)
throws
DocumentException
{
// 绘制直线
PdfContentByte
canvas
=
writer
.
getDirectContent
();
canvas
.
saveState
();
canvas
.
setColorStroke
(
LINE_COLOR
);
canvas
.
setLineWidth
(
1
f
);
float
y
=
writer
.
getVerticalPosition
(
false
)
-
5
f
;
canvas
.
moveTo
(
40
,
y
);
canvas
.
lineTo
(
PageSize
.
A4
.
getWidth
()
-
40
,
y
);
canvas
.
stroke
();
canvas
.
restoreState
();
// 添加额外间距
Paragraph
extraSpacing
=
new
Paragraph
(
" "
);
extraSpacing
.
setSpacingAfter
(
8
f
);
document
.
add
(
extraSpacing
);
}
/**
* 保单详细信息标题 - 调整字体大小
*/
private
void
addPolicyDetailTitle
(
Document
document
,
PolicyReportData
data
)
throws
DocumentException
{
PdfPTable
table
=
new
PdfPTable
(
4
);
table
.
setWidthPercentage
(
100
);
table
.
setWidths
(
new
float
[]{
25
,
25
,
25
,
25
});
table
.
setSpacingBefore
(
0
f
);
table
.
setSpacingAfter
(
ROW_SPACING
);
// 使用更大的字体和红色
Font
sectionTitleFont
=
new
Font
(
chineseRedTitleFont
.
getBaseFont
(),
SECTION_TITLE_FONT_SIZE
,
Font
.
BOLD
,
RED_TITLE_COLOR
);
Paragraph
titlePara
=
new
Paragraph
(
"保單詳細信息"
,
sectionTitleFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
titleCell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
titlePara
);
titleCell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
titleCell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
// 第二列:空
com
.
lowagie
.
text
.
pdf
.
PdfPCell
emptyCell1
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
new
Paragraph
(
" "
));
emptyCell1
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
// 第三列:保單編號标签
Paragraph
numberLabelPara
=
new
Paragraph
(
"保單編號"
,
chineseFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
numberLabelCell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
numberLabelPara
);
numberLabelCell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
numberLabelCell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
// 第四列:保单编号值
Paragraph
numberValuePara
=
new
Paragraph
(
data
.
getPolicyNumber
()
!=
null
?
data
.
getPolicyNumber
()
:
""
,
chineseFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
numberValueCell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
numberValuePara
);
numberValueCell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
numberValueCell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
table
.
addCell
(
titleCell
);
table
.
addCell
(
emptyCell1
);
table
.
addCell
(
numberLabelCell
);
table
.
addCell
(
numberValueCell
);
document
.
add
(
table
);
}
/**
* 保单详细字段 - 修正保費徵費位置
*/
private
void
addPolicyDetailFields
(
Document
document
,
PolicyReportData
data
)
throws
DocumentException
{
PdfPTable
table
=
new
PdfPTable
(
4
);
table
.
setWidthPercentage
(
100
);
table
.
setWidths
(
new
float
[]{
20
,
30
,
20
,
30
});
table
.
setSpacingBefore
(
0
f
);
table
.
setSpacingAfter
(
ROW_SPACING
);
// 第一行:保單持有人 | 持有人值 | 保險公司 | 公司值
addTableHeaderCellNoBorder
(
table
,
"保單持有人"
);
addTableCellNoBorder
(
table
,
data
.
getPolicyHolder
()
!=
null
?
data
.
getPolicyHolder
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"保險公司"
);
addTableCellNoBorder
(
table
,
data
.
getInsuranceCompany
()
!=
null
?
data
.
getInsuranceCompany
()
:
""
);
// 第二行:保單受保人 | 受保人值 | 受保人年齡 | 年齡值
addTableHeaderCellNoBorder
(
table
,
"保單受保人"
);
addTableCellNoBorder
(
table
,
data
.
getInsuredPerson
()
!=
null
?
data
.
getInsuredPerson
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"受保人年齡"
);
addTableCellNoBorder
(
table
,
data
.
getInsuredAge
()
!=
null
?
String
.
valueOf
(
data
.
getInsuredAge
())
:
""
);
// 第三行:保險計劃 | 計劃值 | 繳費年期 | 年期值
addTableHeaderCellNoBorder
(
table
,
"保險計劃"
);
addTableCellNoBorder
(
table
,
data
.
getInsurancePlan
()
!=
null
?
data
.
getInsurancePlan
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"繳費年期"
);
addTableCellNoBorder
(
table
,
data
.
getPaymentPeriod
()
!=
null
?
String
.
valueOf
(
data
.
getPaymentPeriod
())
:
""
);
// 第四行:保單貨幣 | 貨幣值 | 备注 | 备注(跨列)
addTableHeaderCellNoBorder
(
table
,
"保單貨幣"
);
addTableCellNoBorder
(
table
,
data
.
getCurrency
()
!=
null
?
data
.
getCurrency
()
:
""
);
// 备注单元格 - 跨第3、4列,与保單貨幣同一行
Font
footnoteFont
=
new
Font
(
chineseFont
.
getBaseFont
(),
FOOTNOTE_FONT_SIZE
,
Font
.
NORMAL
,
FOOTNOTE_COLOR
);
Paragraph
footnotePara
=
new
Paragraph
(
"*此徵費為香港政府收取,續期時亦須繳納,但不納入本報告金額統計。澳門保單毋需繳納此費用。"
,
footnoteFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
footnoteCell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
footnotePara
);
footnoteCell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
footnoteCell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
footnoteCell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_TOP
);
footnoteCell
.
setColspan
(
2
);
// 跨2列
footnoteCell
.
setPadding
(
2
f
);
table
.
addCell
(
footnoteCell
);
// 第五行:年繳金額 | 金額值 | 保費徵費 | 費用值
addTableHeaderCellNoBorder
(
table
,
"年繳金額"
);
addTableCellNoBorder
(
table
,
formatAmount
(
data
.
getAnnualAmount
()));
addTableHeaderCellNoBorder
(
table
,
"保費徵費"
);
addTableCellNoBorder
(
table
,
formatAmount
(
data
.
getPremiumFee
()));
// 第六行:合預繳息金額 | 金額值 | (空) | (空)
addTableHeaderCellNoBorder
(
table
,
"合預繳息金額"
);
addTableCellNoBorder
(
table
,
formatAmount
(
data
.
getTotalPrepayment
()));
addTableCellNoBorder
(
table
,
""
);
addTableCellNoBorder
(
table
,
""
);
document
.
add
(
table
);
}
/**
* 添加无边框的表头单元格
*/
private
void
addTableHeaderCellNoBorder
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
cell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
para
);
cell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
cell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
cell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_MIDDLE
);
cell
.
setPadding
(
2
f
);
table
.
addCell
(
cell
);
}
/**
* 添加无边框的内容单元格
*/
private
void
addTableCellNoBorder
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
cell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
para
);
cell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
cell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
cell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_MIDDLE
);
cell
.
setPadding
(
2
f
);
table
.
addCell
(
cell
);
}
/**
* 基本信息 - 调整行间距
*/
private
void
addBasicInfo
(
Document
document
,
PolicyReportData
data
)
throws
DocumentException
{
PdfPTable
table
=
new
PdfPTable
(
4
);
table
.
setWidthPercentage
(
100
);
table
.
setWidths
(
new
float
[]{
20
,
30
,
20
,
30
});
// 调整列宽比例
table
.
setSpacingBefore
(
0
f
);
table
.
setSpacingAfter
(
ROW_SPACING
);
// 第一行
addTableHeaderCellNoBorder
(
table
,
"開始時間"
);
addTableCellNoBorder
(
table
,
data
.
getStartTime
()
!=
null
?
data
.
getStartTime
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"結束時間"
);
addTableCellNoBorder
(
table
,
data
.
getEndTime
()
!=
null
?
data
.
getEndTime
()
:
""
);
// 第二行
addTableHeaderCellNoBorder
(
table
,
"簽單地點"
);
addTableCellNoBorder
(
table
,
data
.
getLocation
()
!=
null
?
data
.
getLocation
()
:
""
);
addTableHeaderCellNoBorder
(
table
,
"服務主管"
);
addTableCellNoBorder
(
table
,
data
.
getServiceManager
()
!=
null
?
data
.
getServiceManager
()
:
""
);
document
.
add
(
table
);
}
/**
* 附加险表头 - 去掉边框
*/
private
void
addAdditionalInsuranceHeader
(
Document
document
)
throws
DocumentException
{
PdfPTable
table
=
new
PdfPTable
(
4
);
table
.
setWidthPercentage
(
100
);
table
.
setWidths
(
new
float
[]{
25
,
25
,
25
,
25
});
table
.
setSpacingBefore
(
10
f
);
table
.
setSpacingAfter
(
10
f
);
// 创建居中对齐的无边框单元格
addTableCenterHeaderCellNoBorder
(
table
,
"附加险名称"
);
addTableCenterHeaderCellNoBorder
(
table
,
"缴费期限"
);
addTableCenterHeaderCellNoBorder
(
table
,
"幣种"
);
addTableCenterHeaderCellNoBorder
(
table
,
"首年金额"
);
document
.
add
(
table
);
}
/**
* 添加居中对齐的无边框表头单元格
*/
private
void
addTableCenterHeaderCellNoBorder
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseBoldFont
);
com
.
lowagie
.
text
.
pdf
.
PdfPCell
cell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
para
);
cell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
cell
.
setHorizontalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_CENTER
);
cell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_MIDDLE
);
cell
.
setPadding
(
2
f
);
table
.
addCell
(
cell
);
}
/**
* 备注说明
*/
private
void
addFootnote
(
Document
document
)
throws
DocumentException
{
Font
footnoteFont
=
new
Font
(
chineseFont
.
getBaseFont
(),
FOOTNOTE_FONT_SIZE
,
Font
.
NORMAL
,
FOOTNOTE_COLOR
);
Paragraph
footnote
=
new
Paragraph
(
"*此徵費為香港政府收取,續期時亦須繳納,但不納入本報告金額統計。澳門保單毋需繳納此費用。"
,
footnoteFont
);
footnote
.
setAlignment
(
Paragraph
.
ALIGN_LEFT
);
footnote
.
setSpacingBefore
(
10
f
);
document
.
add
(
footnote
);
}
/**
* 添加表格表头单元格
*/
private
void
addTableHeaderCell
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseFont
);
table
.
addCell
(
createCell
(
para
,
false
));
}
/**
* 添加表格内容单元格
*/
private
void
addTableCell
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseFont
);
table
.
addCell
(
createCell
(
para
,
false
));
}
/**
* 添加居中对齐的表头单元格
*/
private
void
addTableCenterHeaderCell
(
PdfPTable
table
,
String
text
)
{
Paragraph
para
=
new
Paragraph
(
text
,
chineseBoldFont
);
table
.
addCell
(
createCell
(
para
,
true
));
}
/**
* 创建单元格
*/
private
com
.
lowagie
.
text
.
pdf
.
PdfPCell
createCell
(
Paragraph
paragraph
,
boolean
centerAlign
)
{
com
.
lowagie
.
text
.
pdf
.
PdfPCell
cell
=
new
com
.
lowagie
.
text
.
pdf
.
PdfPCell
(
paragraph
);
cell
.
setBorder
(
com
.
lowagie
.
text
.
Rectangle
.
NO_BORDER
);
cell
.
setHorizontalAlignment
(
centerAlign
?
com
.
lowagie
.
text
.
Element
.
ALIGN_CENTER
:
com
.
lowagie
.
text
.
Element
.
ALIGN_LEFT
);
cell
.
setVerticalAlignment
(
com
.
lowagie
.
text
.
Element
.
ALIGN_MIDDLE
);
cell
.
setPadding
(
5
f
);
return
cell
;
}
/**
* 初始化中文字体 - 从classpath资源加载
*/
private
void
initChineseFont
()
throws
IOException
,
DocumentException
{
try
{
BaseFont
baseFont
=
null
;
// 优先使用Classpath资源流加载
try
{
InputStream
fontStream
=
getClass
().
getClassLoader
().
getResourceAsStream
(
"font/DFKai-SB.ttf"
);
if
(
fontStream
!=
null
)
{
byte
[]
fontData
=
IOUtils
.
toByteArray
(
fontStream
);
baseFont
=
BaseFont
.
createFont
(
"DFKai-SB.ttf"
,
BaseFont
.
IDENTITY_H
,
BaseFont
.
EMBEDDED
,
BaseFont
.
CACHED
,
fontData
,
null
);
log
.
info
(
"成功从字节数组加载繁体楷体"
);
}
}
catch
(
Exception
e
)
{
log
.
warn
(
"Classpath加载失败: {}"
,
e
.
getMessage
());
}
// 如果还是失败,使用备用字体
if
(
baseFont
==
null
)
{
log
.
warn
(
"繁体楷体加载失败,使用STSong-Light"
);
baseFont
=
BaseFont
.
createFont
(
"STSong-Light"
,
"UniGB-UCS2-H"
,
BaseFont
.
EMBEDDED
);
}
// 创建字体样式
this
.
chineseFont
=
new
Font
(
baseFont
,
CONTENT_FONT_SIZE
,
Font
.
NORMAL
,
TEXT_COLOR
);
this
.
chineseBoldFont
=
new
Font
(
baseFont
,
CONTENT_FONT_SIZE
,
Font
.
BOLD
,
TEXT_COLOR
);
this
.
chineseTitleFont
=
new
Font
(
baseFont
,
SECTION_TITLE_FONT_SIZE
,
Font
.
BOLD
,
TEXT_COLOR
);
this
.
chineseRedTitleFont
=
new
Font
(
baseFont
,
MAIN_TITLE_FONT_SIZE
,
Font
.
BOLD
,
RED_TITLE_COLOR
);
// 使用主标题字号
}
catch
(
Exception
e
)
{
log
.
error
(
"字体初始化失败"
,
e
);
throw
new
DocumentException
(
"字体初始化失败: "
+
e
.
getMessage
());
}
}
/**
* 金额格式化
*/
private
String
formatAmount
(
BigDecimal
amount
)
{
if
(
amount
==
null
)
return
""
;
return
String
.
format
(
"%.2f"
,
amount
);
}
}
\ No newline at end of file
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/CommissionServiceImpl.java
View file @
b70d4af7
...
...
@@ -18,6 +18,7 @@ import com.yd.csf.service.enums.FortuneStatusEnum;
import
com.yd.csf.service.model.*
;
import
com.yd.csf.service.service.*
;
import
com.yd.csf.service.dao.CommissionMapper
;
import
com.yd.csf.service.vo.CommissionStatisticsVO
;
import
com.yd.csf.service.vo.CommissionVO
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
...
...
@@ -26,17 +27,20 @@ import org.springframework.stereotype.Service;
import
org.springframework.transaction.annotation.Transactional
;
import
javax.annotation.Resource
;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.text.NumberFormat
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* @author Zhang Jianan
* @description 针对表【commission(保单来佣表)】的数据库操作Service实现
* @createDate 2025-09-19 16:08:05
*/
* @author Zhang Jianan
* @description 针对表【commission(保单来佣表)】的数据库操作Service实现
* @createDate 2025-09-19 16:08:05
*/
@Service
public
class
CommissionServiceImpl
extends
ServiceImpl
<
CommissionMapper
,
Commission
>
implements
CommissionService
{
implements
CommissionService
{
@Resource
private
FortuneService
fortuneService
;
...
...
@@ -48,6 +52,8 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
private
PolicyService
policyService
;
@Resource
private
CommissionExpectedService
commissionExpectedService
;
@Resource
private
IExpectedFortuneService
iExpectedFortuneService
;
@Override
...
...
@@ -62,6 +68,7 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
String
reconciliationCompany
=
commissionQueryRequest
.
getReconciliationCompany
();
Date
commissionDateStart
=
commissionQueryRequest
.
getCommissionDateStart
();
Date
commissionDateEnd
=
commissionQueryRequest
.
getCommissionDateEnd
();
Date
expectedDate
=
commissionQueryRequest
.
getExpectedDate
();
queryWrapper
.
eq
(
StringUtils
.
isNotBlank
(
status
),
"status"
,
status
);
queryWrapper
.
like
(
StringUtils
.
isNotBlank
(
policyNo
),
"policy_no"
,
policyNo
);
...
...
@@ -70,6 +77,10 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
if
(
commissionDateStart
!=
null
&&
commissionDateEnd
!=
null
)
{
queryWrapper
.
between
(
"commission_date"
,
commissionDateStart
,
commissionDateEnd
);
}
// 查询预计入账日期及之前的记录
if
(
expectedDate
!=
null
)
{
queryWrapper
.
lt
(
"expected_date"
,
expectedDate
);
}
queryWrapper
.
orderByDesc
(
"id"
);
return
queryWrapper
;
...
...
@@ -132,64 +143,65 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
generateFortune
(
GenerateFortuneRequest
generateFortuneRequest
)
{
List
<
String
>
commissionBizIdList
=
generateFortuneRequest
.
getCommissionBizIdList
();
// 1. 查询选中来佣记录
List
<
Commission
>
commissionList
=
this
.
list
(
new
QueryWrapper
<
Commission
>().
in
(
"commission_biz_id"
,
commissionBizIdList
));
// 校验来佣记录状态
for
(
Commission
commission
:
commissionList
)
{
if
(
StringUtils
.
equals
(
commission
.
getStatus
(),
CommissionStatusEnum
.
WAIT
.
getItemValue
()))
{
throw
new
BusinessException
(
ResultCode
.
FAIL
.
getCode
(),
"来佣记录为未比对,不能生成出帐"
);
}
}
// 获取所有保单号
Set
<
String
>
policyNoSet
=
commissionList
.
stream
().
map
(
Commission:
:
getPolicyNo
).
collect
(
Collectors
.
toSet
());
// 根据保单号查询所有发佣记录
// 2. 查询对应的预计发佣记录
QueryWrapper
<
ExpectedFortune
>
expectedFortuneQueryWrapper
=
new
QueryWrapper
<
ExpectedFortune
>().
in
(
"policy_no"
,
policyNoSet
);
List
<
ExpectedFortune
>
expectedFortuneList
=
iExpectedFortuneService
.
list
(
expectedFortuneQueryWrapper
);
if
(
CollectionUtils
.
isEmpty
(
expectedFortuneList
))
{
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"未找到该保单对应的预计发佣记录"
);
}
else
{
Set
<
String
>
expectedPolicyNoSet
=
expectedFortuneList
.
stream
().
map
(
ExpectedFortune:
:
getPolicyNo
).
collect
(
Collectors
.
toSet
());
// 获取没有预计发佣的保单号
Set
<
String
>
notExpectedPolicyNoSet
=
policyNoSet
.
stream
().
filter
(
policyNo
->
!
expectedPolicyNoSet
.
contains
(
policyNo
)).
collect
(
Collectors
.
toSet
());
if
(!
CollectionUtils
.
isEmpty
(
notExpectedPolicyNoSet
))
{
throw
new
BusinessException
(
ResultCode
.
FAIL
.
getCode
(),
"未找到以下保单对应的预计发佣记录:"
+
String
.
join
(
","
,
notExpectedPolicyNoSet
));
}
}
// 3. 根据保单号查询所有发佣记录
List
<
Fortune
>
fortuneList
=
fortuneService
.
list
(
new
QueryWrapper
<
Fortune
>().
in
(
"policy_no"
,
policyNoSet
));
// 校验,如果有"可发放或已发并关账"的发佣记录,不能重复生成
//
4.
校验,如果有"可发放或已发并关账"的发佣记录,不能重复生成
for
(
Fortune
item
:
fortuneList
)
{
if
(
StringUtils
.
equals
(
item
.
getStatus
(),
FortuneStatusEnum
.
CAN_SEND
.
getItemValue
())
||
StringUtils
.
equals
(
item
.
getStatus
(),
FortuneStatusEnum
.
SENT
.
getItemValue
()))
{
throw
new
BusinessException
(
ResultCode
.
FAIL
.
getCode
(),
"该来佣记录已有出帐,不能
重复
生成"
);
throw
new
BusinessException
(
ResultCode
.
FAIL
.
getCode
(),
"该来佣记录已有出帐,不能生成"
);
}
}
// 1.查询所有保单号对应的保单跟进记录
List
<
PolicyFollow
>
policyFollowListList
=
policyFollowService
.
list
(
new
QueryWrapper
<
PolicyFollow
>().
in
(
"policy_no"
,
policyNoSet
));
// 5. 筛出来佣对应的预计发佣记录
List
<
ExpectedFortune
>
filteredExpectedFortuneList
=
expectedFortuneList
.
stream
()
.
filter
(
expectedFortune
->
commissionList
.
stream
()
.
anyMatch
(
commission
->
StringUtils
.
equals
(
commission
.
getPolicyNo
(),
expectedFortune
.
getPolicyNo
())
&&
commission
.
getCommissionPeriod
().
equals
(
expectedFortune
.
getFortunePeriod
())))
.
collect
(
Collectors
.
toList
());
// 2.根据保单号查询所有转介人
List
<
PolicyBroker
>
brokerList
=
policyBrokerService
.
list
(
new
QueryWrapper
<
PolicyBroker
>().
in
(
"policy_no"
,
policyNoSet
));
if
(
CollUtil
.
isEmpty
(
brokerList
))
{
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"该保单不存在转介人,请先配置转介人"
);
}
// 构建保单号到转介人的映射
Map
<
String
,
List
<
PolicyBroker
>>
brokerMap
=
brokerList
.
stream
().
collect
(
Collectors
.
groupingBy
(
PolicyBroker:
:
getPolicyNo
));
// 3.删除旧的发佣记录
// 6.删除旧的发佣记录
fortuneService
.
remove
(
new
QueryWrapper
<
Fortune
>().
in
(
"policy_no"
,
policyNoSet
));
//
4. 构建
发佣记录
//
7. 构建实际的初始
发佣记录
List
<
Fortune
>
newFortuneList
=
new
ArrayList
<>();
for
(
PolicyFollow
policyFollow
:
policyFollowListList
)
{
String
policyNo
=
policyFollow
.
getPolicyNo
();
List
<
PolicyBroker
>
policyBrokers
=
brokerMap
.
get
(
policyNo
);
if
(
CollectionUtils
.
isNotEmpty
(
policyBrokers
))
{
for
(
PolicyBroker
policyBroker
:
policyBrokers
)
{
Fortune
fortune
=
new
Fortune
();
fortune
.
setFortuneBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_FORTUNE
.
getCode
()));
fortune
.
setPolicyNo
(
policyNo
);
fortune
.
setBroker
(
policyBroker
.
getBrokerName
());
fortune
.
setStatus
(
FortuneStatusEnum
.
WAIT
.
getItemValue
());
fortune
.
setCreateTime
(
new
Date
());
fortune
.
setUpdateTime
(
new
Date
());
newFortuneList
.
add
(
fortune
);
}
}
for
(
ExpectedFortune
expectedFortune
:
filteredExpectedFortuneList
)
{
Fortune
fortune
=
new
Fortune
();
BeanUtils
.
copyProperties
(
expectedFortune
,
fortune
);
fortune
.
setFortuneBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_FORTUNE
.
getCode
()));
fortune
.
setStatus
(
FortuneStatusEnum
.
WAIT
.
getItemValue
());
// 关联来佣业务ID
matchCommission
(
fortune
,
commissionList
);
fortune
.
setCreateTime
(
new
Date
());
fortune
.
setUpdateTime
(
new
Date
());
newFortuneList
.
add
(
fortune
);
}
//
5
. 保存发佣记录
//
8
. 保存发佣记录
if
(
CollUtil
.
isNotEmpty
(
newFortuneList
))
{
boolean
saveSuccess
=
fortuneService
.
saveBatch
(
newFortuneList
);
if
(!
saveSuccess
)
{
...
...
@@ -199,6 +211,20 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
return
true
;
}
private
void
matchCommission
(
Fortune
fortune
,
List
<
Commission
>
commissionList
)
{
for
(
Commission
commission
:
commissionList
)
{
if
(
StringUtils
.
equals
(
commission
.
getPolicyNo
(),
fortune
.
getPolicyNo
())
&&
commission
.
getCommissionPeriod
().
equals
(
fortune
.
getFortunePeriod
())
&&
commission
.
getCommissionName
().
equals
(
fortune
.
getFortuneName
())
)
{
fortune
.
setCommissionBizId
(
commission
.
getCommissionBizId
());
}
else
{
fortune
.
setStatus
(
FortuneStatusEnum
.
MATCH_FAIL
.
getItemValue
());
fortune
.
setRemark
(
"未找到当前预计发佣对应的来佣"
);
}
}
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
addCommission
(
CommissionAddRequest
commissionAddRequest
)
{
...
...
@@ -263,19 +289,21 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
/**
* 查询列表
*
* @param dto
* @return
*/
@Override
public
List
<
Commission
>
queryList
(
CommissionDto
dto
)
{
List
<
Commission
>
list
=
baseMapper
.
selectList
(
new
LambdaQueryWrapper
<
Commission
>()
.
in
(
CollectionUtils
.
isNotEmpty
(
dto
.
getCommissionBizIdList
()),
Commission:
:
getCommissionBizId
,
dto
.
getCommissionBizIdList
())
.
in
(
CollectionUtils
.
isNotEmpty
(
dto
.
getCommissionBizIdList
()),
Commission:
:
getCommissionBizId
,
dto
.
getCommissionBizIdList
())
);
return
list
;
}
/**
* 查询来佣保单转介人关系信息
*
* @param dto
* @return
*/
...
...
@@ -283,6 +311,26 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
public
List
<
CommissionBindPolicyBrokerDto
>
queryCommissionBindPolicyBrokerList
(
CommissionDto
dto
)
{
return
baseMapper
.
queryCommissionBindPolicyBrokerList
(
dto
);
}
@Override
public
CommissionStatisticsVO
getCommissionStatistics
(
List
<
Long
>
commissionIds
)
{
// 自定义统计数据
CommissionStatisticsVO
commissionStatistics
=
baseMapper
.
getCommissionStatistics
(
commissionIds
);
BigDecimal
totalAmount
=
commissionStatistics
.
getTotalAmount
();
BigDecimal
totalPaidAmount
=
commissionStatistics
.
getTotalPaidAmount
();
// 计算待入账金额
commissionStatistics
.
setPendingPaidAmount
(
totalAmount
.
subtract
(
totalPaidAmount
));
// 计算已入账比例
BigDecimal
divided
=
BigDecimal
.
ZERO
;
if
(
totalAmount
.
compareTo
(
BigDecimal
.
ZERO
)
>
0
)
{
divided
=
totalPaidAmount
.
divide
(
totalAmount
,
4
,
RoundingMode
.
HALF_UP
);
}
// 格式化 %
commissionStatistics
.
setPaidAmountRatio
(
String
.
format
(
"%.2f%%"
,
divided
.
doubleValue
()
*
100
));
return
commissionStatistics
;
}
}
...
...
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/PolicyFollowServiceImpl.java
View file @
b70d4af7
...
...
@@ -157,6 +157,8 @@ public class PolicyFollowServiceImpl extends ServiceImpl<PolicyFollowMapper, Pol
if
(
policyFollowUpdateDto
.
getCoolingOffDays
()
!=
null
&&
policyFollowUpdateDto
.
getEffectiveDate
()
!=
null
)
{
policyFollow
.
setCoolingOffEndDate
(
DateUtil
.
offset
(
policyFollowUpdateDto
.
getEffectiveDate
(),
DateField
.
DAY_OF_MONTH
,
policyFollowUpdateDto
.
getCoolingOffDays
()));
}
// 获取币种字典值
policyFollow
.
setCurrency
(
this
.
getCurrencyValue
(
policyFollowUpdateDto
.
getCurrency
()));
}
// 设置核保信息
setValidPolicyInfo
(
policyFollow
,
policyFollowUpdateRequest
.
getVerifyPolicyInfo
());
...
...
@@ -248,6 +250,9 @@ public class PolicyFollowServiceImpl extends ServiceImpl<PolicyFollowMapper, Pol
if
(
policyFollowAddRequest
.
getCoolingOffDays
()
!=
null
)
{
policyFollow
.
setCoolingOffEndDate
(
DateUtil
.
offset
(
policyFollowAddRequest
.
getEffectiveDate
(),
DateField
.
DAY_OF_MONTH
,
policyFollowAddRequest
.
getCoolingOffDays
()));
}
// 获取币种字典值
policyFollow
.
setCurrency
(
this
.
getCurrencyValue
(
policyFollowAddRequest
.
getCurrency
()));
// 创建 Policy对象
Policy
policy
=
new
Policy
();
BeanUtils
.
copyProperties
(
policyFollowAddRequest
,
policy
);
...
...
@@ -527,6 +532,42 @@ public class PolicyFollowServiceImpl extends ServiceImpl<PolicyFollowMapper, Pol
}
@Override
public
String
getCurrencyValue
(
String
currency
)
{
if
(
StringUtils
.
isBlank
(
currency
))
{
return
null
;
}
switch
(
currency
)
{
case
"美元"
:
currency
=
"USD"
;
break
;
case
"人民幣"
:
currency
=
"CNY"
;
break
;
case
"港幣"
:
currency
=
"HKD"
;
break
;
case
"澳元"
:
currency
=
"AUD"
;
break
;
case
"加元"
:
currency
=
"CAD"
;
break
;
case
"欧元"
:
currency
=
"EUR"
;
break
;
case
"英鎊"
:
currency
=
"GBP"
;
break
;
case
"新加坡元"
:
currency
=
"SGD"
;
break
;
default
:
break
;
}
return
currency
;
}
@Override
public
Boolean
uploadAttachment
(
AttachmentUploadRequest
attachmentUploadRequest
)
{
String
policyBizId
=
attachmentUploadRequest
.
getPolicyBizId
();
if
(
policyBizId
==
null
)
{
...
...
yd-csf-service/src/main/java/com/yd/csf/service/vo/CommissionStatisticsVO.java
0 → 100644
View file @
b70d4af7
package
com
.
yd
.
csf
.
service
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
import
java.math.BigDecimal
;
/**
* 佣金统计VO 包含总金额、总入账金额、待入账金额、已入账比例(已入账金额/总金额)、总保单数
*/
@Data
public
class
CommissionStatisticsVO
{
/**
* 总金额
*/
@Schema
(
description
=
"总金额"
)
private
BigDecimal
totalAmount
;
/**
* 总入账金额
*/
@Schema
(
description
=
"总入账金额"
)
private
BigDecimal
totalPaidAmount
;
/**
* 待入账金额
*/
@Schema
(
description
=
"待入账金额"
)
private
BigDecimal
pendingPaidAmount
;
/**
* 已入账比例(已入账金额/总金额)
*/
@Schema
(
description
=
"已入账比例(已入账金额/总金额)"
)
private
String
paidAmountRatio
;
/**
* 总保单数
*/
@Schema
(
description
=
"总保单数"
)
private
Integer
totalPolicyCount
;
}
yd-csf-service/src/main/java/com/yd/csf/service/vo/CommissionVO.java
View file @
b70d4af7
...
...
@@ -14,6 +14,12 @@ import java.util.Date;
public
class
CommissionVO
implements
Serializable
{
/**
* commission id
*/
@Schema
(
description
=
"commission id"
)
private
Long
id
;
/**
* 保单来佣业务id
*/
@Schema
(
description
=
"保单来佣业务id"
)
...
...
yd-csf-service/src/main/resources/font/DFKai-SB.ttf
0 → 100644
View file @
b70d4af7
File added
yd-csf-service/src/main/resources/mappers/CommissionMapper.xml
View file @
b70d4af7
...
...
@@ -52,4 +52,26 @@
left join policy_broker pb on pb.policy_no = p.policy_no and pb.is_deleted = 0
</select>
<!-- 总金额:统计保单预计来佣表 已入账金额:统计来佣表-->
<select
id=
"getCommissionStatistics"
resultType=
"com.yd.csf.service.vo.CommissionStatisticsVO"
>
SELECT
COALESCE(SUM(e.amount), 0) as totalAmount,
COALESCE(SUM(c.amount), 0) as totalPaidAmount,
COUNT(DISTINCT c.policy_no) as totalPolicyCount
FROM commission c
LEFT JOIN (
SELECT policy_no, SUM(amount) as amount
FROM commission_expected
GROUP BY policy_no
) e ON c.policy_no = e.policy_no
<where>
<if
test=
"commissionIdList != null and commissionIdList.size > 0"
>
c.id IN
<foreach
collection=
"commissionIdList"
item=
"item"
open=
"("
separator=
","
close=
")"
>
#{item}
</foreach>
</if>
</where>
</select>
</mapper>
yd-csf-service/src/main/resources/mappers/FortuneMapper.xml
View file @
b70d4af7
...
...
@@ -7,6 +7,7 @@
<resultMap
id=
"BaseResultMap"
type=
"com.yd.csf.service.model.Fortune"
>
<id
property=
"id"
column=
"id"
/>
<result
property=
"fortuneBizId"
column=
"fortune_biz_id"
/>
<result
property=
"commissionBizId"
column=
"commission_biz_id"
/>
<result
property=
"policyNo"
column=
"policy_no"
/>
<result
property=
"fortunePeriod"
column=
"fortune_period"
/>
<result
property=
"fortuneTotalPeriod"
column=
"fortune_total_period"
/>
...
...
@@ -36,7 +37,7 @@
</resultMap>
<sql
id=
"Base_Column_List"
>
id,fortune_biz_id,policy_no,fortune_period,fortune_total_period,broker_biz_id,
id,fortune_biz_id,
commission_biz_id,
policy_no,fortune_period,fortune_total_period,broker_biz_id,
team_biz_id,grade_commission_rate,share_rate,fortune_name,fortune_type,
amount,currency,status,payout_date,is_tax,
tax_amount,net_amount,salary_biz_id,base_rule_biz_id,settlement_biz_id,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment