diff --git a/code/db/建表/电销坐席车非渗透统计表.sql b/code/db/建表/电销坐席车非渗透统计表.sql
new file mode 100644
index 0000000..5c3500c
--- /dev/null
+++ b/code/db/建表/电销坐席车非渗透统计表.sql
@@ -0,0 +1,33 @@
+-- Create table
+create table 电销坐席车非渗透统计表
+(
+ summary_date DATE default sysdate not null,
+ telsaler_name VARCHAR2(20) not null,
+ moto_premium NUMBER default 0 not null,
+ nomoto_premium NUMBER default 0 not null,
+ moto_premium_proportion NUMBER default 0 not null,
+ attaching_rate NUMBER default 0 not null,
+ attaching_rate_change NUMBER default 0 not null
+)
+tablespace DESKTOP_ARCHIEVEMENT
+ pctfree 10
+ initrans 1
+ maxtrans 255;
+-- Add comments to the table
+comment on table 电销坐席车非渗透统计表
+ is '用于存放BI导出每日电销坐席车险非车险保费和车非渗透率数据。';
+-- Add comments to the columns
+comment on column 电销坐席车非渗透统计表.summary_date
+ is '统计日期';
+comment on column 电销坐席车非渗透统计表.telsaler_name
+ is '坐席名称';
+comment on column 电销坐席车非渗透统计表.moto_premium
+ is '车险保费';
+comment on column 电销坐席车非渗透统计表.nomoto_premium
+ is '非车险保费';
+comment on column 电销坐席车非渗透统计表.moto_premium_proportion
+ is '车险保费占比';
+comment on column 电销坐席车非渗透统计表.attaching_rate
+ is '渗透率';
+comment on column 电销坐席车非渗透统计表.attaching_rate_change
+ is '渗透率环比上月';
diff --git a/code/后端/desktop_archievement_backend/pom.xml b/code/后端/desktop_archievement_backend/pom.xml
index cd7b3b8..40689cc 100644
--- a/code/后端/desktop_archievement_backend/pom.xml
+++ b/code/后端/desktop_archievement_backend/pom.xml
@@ -14,6 +14,7 @@
17
17
5.3.24
+ 2.20.0
@@ -116,19 +117,26 @@
log4j-slf4j2-impl
2.20.0
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.20.0
+
+
org.apache.poi
poi
- 5.2.4
+ 5.2.3
org.apache.poi
poi-ooxml
- 5.2.4
+ 5.2.3
diff --git a/code/后端/desktop_archievement_backend/src/main/java/com/cpic/xim/mybatis/pojo/TelsalerAttachingRateRecord.java b/code/后端/desktop_archievement_backend/src/main/java/com/cpic/xim/mybatis/pojo/TelsalerAttachingRateRecord.java
new file mode 100644
index 0000000..8a35eb7
--- /dev/null
+++ b/code/后端/desktop_archievement_backend/src/main/java/com/cpic/xim/mybatis/pojo/TelsalerAttachingRateRecord.java
@@ -0,0 +1,188 @@
+/*
+ * @Author: Kane
+ * @Date: 2023-10-08 14:45:13
+ * @LastEditors: Kane
+ * @FilePath: /desktop_archievement_backend/src/main/java/com/cpic/xim/mybatis/pojo/TelsalerAttachingRateRecord.java
+ * @Description: 用于存放BI导出每日电销坐席车险非车险保费和车非渗透率数据.
+ *
+ * Copyright (c) ${2023} by Kane, All Rights Reserved.
+ */
+package com.cpic.xim.mybatis.pojo;
+
+import java.time.LocalDate;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class TelsalerAttachingRateRecord
+{
+ // 统计日期
+ @JsonProperty("summaryDate")
+ private LocalDate summaryDate;
+
+ // 坐席名称
+ @JsonProperty("telsalerName")
+ private String telsalerName;
+
+ // 车险保费
+ @JsonProperty("motoPremium")
+ private double motoPremium;
+
+ // 非车险保费
+ @JsonProperty("nomotoPremium")
+ private double nomotoPremium;
+
+ // 车险保费占比
+ @JsonProperty("motoPremiumProportion")
+ private double motoPremiumProportion;
+
+ // 渗透率
+ @JsonProperty("attachingRate")
+ private double attachingRate;
+
+ // 渗透率环比上月
+ @JsonProperty("attachingRateChange")
+ private double attachingRateChange;
+
+ public TelsalerAttachingRateRecord() {}
+
+ @Override
+ public String toString()
+ {
+ return "TelsalerAttachingRateRecord [summaryDate=" + summaryDate + ", telsalerName="
+ + telsalerName + ", motoPremium=" + motoPremium + ", nomotoPremium=" + nomotoPremium
+ + ", motoPremiumProportion=" + motoPremiumProportion + ", attachingRate="
+ + attachingRate + ", attachingRateChange=" + attachingRateChange + "]";
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((summaryDate == null) ? 0 : summaryDate.hashCode());
+ result = prime * result + ((telsalerName == null) ? 0 : telsalerName.hashCode());
+ long temp;
+ temp = Double.doubleToLongBits( motoPremium );
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits( nomotoPremium );
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits( motoPremiumProportion );
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits( attachingRate );
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits( attachingRateChange );
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ TelsalerAttachingRateRecord other = (TelsalerAttachingRateRecord) obj;
+ if ( summaryDate == null )
+ {
+ if ( other.summaryDate != null )
+ return false;
+ }
+ else if ( !summaryDate.equals( other.summaryDate ) )
+ return false;
+ if ( telsalerName == null )
+ {
+ if ( other.telsalerName != null )
+ return false;
+ }
+ else if ( !telsalerName.equals( other.telsalerName ) )
+ return false;
+ if ( Double.doubleToLongBits( motoPremium ) != Double
+ .doubleToLongBits( other.motoPremium ) )
+ return false;
+ if ( Double.doubleToLongBits( nomotoPremium ) != Double
+ .doubleToLongBits( other.nomotoPremium ) )
+ return false;
+ if ( Double.doubleToLongBits( motoPremiumProportion ) != Double
+ .doubleToLongBits( other.motoPremiumProportion ) )
+ return false;
+ if ( Double.doubleToLongBits( attachingRate ) != Double
+ .doubleToLongBits( other.attachingRate ) )
+ return false;
+ if ( Double.doubleToLongBits( attachingRateChange ) != Double
+ .doubleToLongBits( other.attachingRateChange ) )
+ return false;
+ return true;
+ }
+
+ public LocalDate getSummaryDate()
+ {
+ return summaryDate;
+ }
+
+ public void setSummaryDate( LocalDate summaryDate )
+ {
+ this.summaryDate = summaryDate;
+ }
+
+ public String getTelsalerName()
+ {
+ return telsalerName;
+ }
+
+ public void setTelsalerName( String telsalerName )
+ {
+ this.telsalerName = telsalerName;
+ }
+
+ public double getMotoPremium()
+ {
+ return motoPremium;
+ }
+
+ public void setMotoPremium( double motoPremium )
+ {
+ this.motoPremium = motoPremium;
+ }
+
+ public double getNomotoPremium()
+ {
+ return nomotoPremium;
+ }
+
+ public void setNomotoPremium( double nomotoPremium )
+ {
+ this.nomotoPremium = nomotoPremium;
+ }
+
+ public double getMotoPremiumProportion()
+ {
+ return motoPremiumProportion;
+ }
+
+ public void setMotoPremiumProportion( double motoPremiumProportion )
+ {
+ this.motoPremiumProportion = motoPremiumProportion;
+ }
+
+ public double getAttachingRate()
+ {
+ return attachingRate;
+ }
+
+ public void setAttachingRate( double attachingRate )
+ {
+ this.attachingRate = attachingRate;
+ }
+
+ public double getAttachingRateChange()
+ {
+ return attachingRateChange;
+ }
+
+ public void setAttachingRateChange( double attachingRateChange )
+ {
+ this.attachingRateChange = attachingRateChange;
+ }
+}
diff --git a/code/后端/desktop_archievement_backend/src/main/java/com/cpic/xim/utils/data/TelsalerArchievementData.java b/code/后端/desktop_archievement_backend/src/main/java/com/cpic/xim/utils/data/TelsalerArchievementData.java
new file mode 100644
index 0000000..9d1ead9
--- /dev/null
+++ b/code/后端/desktop_archievement_backend/src/main/java/com/cpic/xim/utils/data/TelsalerArchievementData.java
@@ -0,0 +1,58 @@
+/*
+ * @Author: Kane
+ * @Date: 2023-10-08 15:02:15
+ * @LastEditors: Kane
+ * @FilePath: /desktop_archievement_backend/src/main/java/com/cpic/xim/utils/data/TelsalerArchievementData.java
+ * @Description: 坐席业绩相关的数据操作方法。
+ *
+ * Copyright (c) ${2023} by Kane, All Rights Reserved.
+ */
+package com.cpic.xim.utils.data;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import com.cpic.xim.mybatis.pojo.TelsalerAttachingRateRecord;
+
+/**
+ * 坐席业绩相关的数据操作方法。
+ */
+public class TelsalerArchievementData
+{
+ public static ArrayList importTelsalerAttachingRateRecordFromXlsx(
+ String filePath ) throws IOException, InvalidFormatException
+ {
+ ArrayList records = new ArrayList<>( 200 );
+
+ Workbook wb = null;
+ Sheet sheet = null;
+
+ try
+ {
+ wb = WorkbookFactory.create( new File(filePath));
+ sheet = wb.getSheet("经办");
+ }
+ finally
+ {
+ try
+ {
+ if ( wb != null )
+ {
+ wb.close();
+ }
+ }
+ catch ( IOException error )
+ {
+ error.printStackTrace();
+ }
+ }
+
+ return records;
+ }
+}
diff --git a/数据/测试用/TWr业务员人力查询 - 坐席清单.xlsx b/数据/测试用/TWr业务员人力查询 - 坐席清单.xlsx
new file mode 100644
index 0000000..1156b23
Binary files /dev/null and b/数据/测试用/TWr业务员人力查询 - 坐席清单.xlsx differ
diff --git a/数据/测试用/坐席清单.xlsx b/数据/测试用/坐席清单.xlsx
new file mode 100644
index 0000000..f5420d2
Binary files /dev/null and b/数据/测试用/坐席清单.xlsx differ
diff --git a/数据/测试用/坐席续保率 - 当月个车续保率跟踪报表【机构】.xlsx b/数据/测试用/坐席续保率 - 当月个车续保率跟踪报表【机构】.xlsx
new file mode 100644
index 0000000..add431b
Binary files /dev/null and b/数据/测试用/坐席续保率 - 当月个车续保率跟踪报表【机构】.xlsx differ
diff --git a/数据/测试用/坐席车非渗透 - 副本.xlsx b/数据/测试用/坐席车非渗透 - 副本.xlsx
new file mode 100644
index 0000000..bf78dd6
Binary files /dev/null and b/数据/测试用/坐席车非渗透 - 副本.xlsx differ
diff --git a/数据/测试用/坐席车非渗透.xlsx b/数据/测试用/坐席车非渗透.xlsx
new file mode 100644
index 0000000..bf78dd6
Binary files /dev/null and b/数据/测试用/坐席车非渗透.xlsx differ