Commit b70d4af7 by zhangxingmin

Merge remote-tracking branch 'origin/test' into test

parents 744d58f7 0707d9ed
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);
}
}
......@@ -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
......@@ -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>
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);
}
......
......@@ -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")
......
......@@ -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
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;
}
......@@ -75,6 +75,12 @@ public class CommissionUpdateRequest implements Serializable {
@Schema(description = "来佣币种")
private String currency;
/**
* 结算汇率
*/
@Schema(description = "结算汇率")
private String exchangeRate;
/**
* 来佣日期
*/
......
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;
}
}
......@@ -9,6 +9,7 @@ public enum FortuneStatusEnum {
WAIT("待出账", "0"),
CAN_SEND("可出账", "1"),
SENT("已出账", "2"),
MATCH_FAIL("未找到当前预计发佣对应的来佣", "3"),
;
//字典项标签(名称)
......
......@@ -30,6 +30,11 @@ public class Fortune implements Serializable {
*/
private String fortuneBizId;
/**
* 来佣保单业务id
*/
private String commissionBizId;
/**
* 保单号
*/
......
......@@ -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);
}
......@@ -42,4 +42,6 @@ public interface PolicyFollowService extends IService<PolicyFollow> {
PolicyFollowAggregateDto getPolicyFollowAggregate(String policyBizId);
Page<PolicyFollowDetailVO> getPolicyFollowDetailVOList(Page<PolicyFollow> policyFollowPage);
String getCurrencyValue(String currency);
}
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 = 28f; // 增大主标题字号
private static final float SECTION_TITLE_FONT_SIZE = 16f; // 调整章节标题字号
private static final float CONTENT_FONT_SIZE = 12f; // 调整内容文字字号
private static final float FOOTNOTE_FONT_SIZE = 10f; // 调整备注文字字号
// 调整间距常量
private static final float MAIN_TITLE_MARGIN_BOTTOM = 20f; // 增大主标题下方间距
private static final float LINE_MARGIN_BOTTOM = 18f; // 调整水平线间距
private static final float ROW_SPACING = 12f; // 调整行间距
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(1f);
float y = writer.getVerticalPosition(false) - 5f;
canvas.moveTo(40, y);
canvas.lineTo(PageSize.A4.getWidth() - 40, y);
canvas.stroke();
canvas.restoreState();
// 添加额外间距
Paragraph extraSpacing = new Paragraph(" ");
extraSpacing.setSpacingAfter(8f);
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(0f);
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(0f);
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(2f);
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(2f);
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(2f);
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(0f);
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(10f);
table.setSpacingAfter(10f);
// 创建居中对齐的无边框单元格
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(2f);
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(10f);
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(5f);
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
......@@ -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;
}
}
......
......@@ -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) {
......
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;
}
......@@ -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")
......
......@@ -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>
......@@ -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,
......
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