chengqiang vor 2 Jahren
Ursprung
Commit
d38760bf11
56 geänderte Dateien mit 5455 neuen und 792 gelöschten Zeilen
  1. 48 0
      src/main/java/com/jeeplus/common/utils/excel/ImportExcel.java
  2. 1 17
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/liKuResourcePool/utils/ImportUtil.java
  3. 2 2
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/liKuResourcePool/web/LiKuResourcePoolController.java
  4. 89 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/entity/MaterialQuota.java
  5. 37 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/mapper/MaterialQuotaMapper.java
  6. 111 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/mapper/xml/MaterialQuotaMapper.xml
  7. 83 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/service/MaterialQuotaService.java
  8. 393 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/utils/ImportUtil.java
  9. 76 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/utils/LiKuUtils.java
  10. 177 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/utils/OptimalUtil.java
  11. 169 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/web/MaterialQuotaController.java
  12. 47 23
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/entity/MaterialReportDetails.java
  13. 561 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/utils/ExcelUtil.java
  14. 20 4
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/utils/ExportUtil.java
  15. 620 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/utils/ImportExcel.java
  16. 87 3
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/web/MaterialReportDetailsControllerTest.java
  17. 78 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/entity/PreferredMaterials.java
  18. 39 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/mapper/PreferredMaterialsMapper.java
  19. 115 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/mapper/xml/PreferredMaterialsMapper.xml
  20. 87 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/service/PreferredMaterialsService.java
  21. 393 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/utils/ImportUtil.java
  22. 76 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/utils/LiKuUtils.java
  23. 177 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/utils/OptimalUtil.java
  24. 171 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/web/PreferredMaterialsController.java
  25. 50 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/entity/StandardMaterials.java
  26. 40 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/mapper/StandardMaterialsMapper.java
  27. 100 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/mapper/xml/StandardMaterialsMapper.xml
  28. 83 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/service/StandardMaterialsService.java
  29. 175 0
      src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/web/StandardMaterialsController.java
  30. 7 0
      src/main/java/com/jeeplus/modules/sg/classification/entity/ClassificationProject.java
  31. 17 0
      src/main/java/com/jeeplus/modules/sg/classification/mapper/ClassificationMapper.java
  32. 21 0
      src/main/java/com/jeeplus/modules/sg/classification/service/ClassificationService.java
  33. 279 0
      src/main/java/com/jeeplus/modules/sg/classification/uti/ImportExcel.java
  34. 94 0
      src/main/java/com/jeeplus/modules/sg/classification/web/ClassificationController.java
  35. 9 0
      src/main/java/com/jeeplus/modules/sg/financial/erpcredit/entity/ErpAccount.java
  36. 9 0
      src/main/java/com/jeeplus/modules/sg/financial/erpcredit/entity/ErpCredit.java
  37. 10 1
      src/main/java/com/jeeplus/modules/sg/financial/erpcredit/entity/TransferOfEquipment.java
  38. 32 24
      src/main/java/com/jeeplus/modules/sg/financial/erpcredit/service/ErpCreditService.java
  39. 3 0
      src/main/java/com/jeeplus/modules/sg/financial/erpcredit/util/ErpInfo.java
  40. 596 602
      src/main/java/com/jeeplus/modules/sg/financial/erpcredit/util/ExportUtil.java
  41. 72 19
      src/main/java/com/jeeplus/modules/sg/financial/erpcredit/util/ExportUtilCalculate.java
  42. 28 0
      src/main/java/com/jeeplus/modules/sg/financial/erpcredit/util/ValidationUtils.java
  43. 1 1
      src/main/java/com/jeeplus/modules/sg/financial/settlement/mapper/CostCheckMapper.java
  44. 1 1
      src/main/java/com/jeeplus/modules/sg/financial/settlement/mapper/ProjectBudgetMapper.java
  45. 1 1
      src/main/java/com/jeeplus/modules/sg/financial/settlement/mapper/xml/CostCheckMapper.xml
  46. 1 1
      src/main/java/com/jeeplus/modules/sg/financial/settlement/mapper/xml/ProjectBudgetMapper.xml
  47. 12 36
      src/main/java/com/jeeplus/modules/sg/financial/settlement/service/CostCheckService.java
  48. 7 29
      src/main/java/com/jeeplus/modules/sg/financial/settlement/service/ProjectBudgetService.java
  49. 2 1
      src/main/java/com/jeeplus/modules/sg/financial/settlement/web/CostCheckController.java
  50. 37 19
      src/main/java/com/jeeplus/modules/sg/financial/settlement/web/ProjectBudgetController.java
  51. BIN
      src/main/resources/freemarker/excelmodel/completionModel.xlsx
  52. BIN
      src/main/resources/freemarker/excelmodel/completionModel(old).xlsx
  53. BIN
      src/main/resources/freemarker/excelmodel/requiredMaterialModel.xlsx
  54. 2 2
      src/main/resources/j2cache/j2cache.properties
  55. 6 6
      src/main/resources/properties/jeeplus.properties
  56. 103 0
      src/main/webapp/webpage/modules/sg/classification/classification.jsp

+ 48 - 0
src/main/java/com/jeeplus/common/utils/excel/ImportExcel.java

@@ -252,6 +252,54 @@ public class ImportExcel {
 		}
 		return val;
 	}
+
+	/**
+	 * 获取单元格值
+	 * @param row 获取的行
+	 * @param column 获取单元格列号
+	 * @return 单元格值
+	 */
+	public Object getCellValue(Row row, int column,Integer maxDig) {
+		Object val = "";
+		try {
+			Cell cell = row.getCell(column);
+			if (cell != null) {
+				if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+					// val = cell.getNumericCellValue();
+					// 当excel 中的数据为数值或日期是需要特殊处理
+					if (HSSFDateUtil.isCellDateFormatted(cell)) {
+						double d = cell.getNumericCellValue();
+						Date date = HSSFDateUtil.getJavaDate(d);
+						SimpleDateFormat dformat = new SimpleDateFormat(
+								"yyyy-MM-dd");
+						val = dformat.format(date);
+					} else {
+						NumberFormat nf = NumberFormat.getInstance();
+						nf.setGroupingUsed(false);// true时的格式:1,234,567,890
+						if(maxDig == null){
+							nf.setMaximumFractionDigits(4);
+						}else{
+							nf.setMaximumFractionDigits(maxDig);
+						}
+
+						val = nf.format(cell.getNumericCellValue());// 数值类型的数据为double,所以需要转换一下
+					}
+				} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
+					val = cell.getStringCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
+//					val = cell.getCellFormula();
+					val = cell.getNumericCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
+					val = cell.getBooleanCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
+					val = cell.getErrorCellValue();
+				}
+			}
+		} catch (Exception e) {
+			return val;
+		}
+		return val;
+	}
 	
 	/**
 	 * 获取导入数据列表

+ 1 - 17
src/main/java/com/jeeplus/modules/sg/balancedlibrary/liKuResourcePool/utils/ImportUtil.java

@@ -373,21 +373,5 @@ public class ImportUtil {
 		return dataList;
 	}
 
-//	/**
-//	 * 导入测试
-//	 */
-//	public static void main(String[] args) throws Throwable {
-//		
-//		ImportExcel ei = new ImportExcel("target/export.xlsx", 1);
-//		
-//		for (int i = ei.getDataRowNum(); i < ei.getLastDataRowNum(); i++) {
-//			Row row = ei.getRow(i);
-//			for (int j = 0; j < ei.getLastCellNum(); j++) {
-//				Object val = ei.getCellValue(row, j);
-//				System.out.print(val+", ");
-//			}
-//			System.out.print("\n");
-//		}
-//		
-//	}
+
 }

+ 2 - 2
src/main/java/com/jeeplus/modules/sg/balancedlibrary/liKuResourcePool/web/LiKuResourcePoolController.java

@@ -185,10 +185,10 @@ public class LiKuResourcePoolController extends BaseController {
 				pool.setRemaining(pool.getInventoryAmount());
 				pool.setNumberOfNiches(0.0);
 			}
-//			List<LiKuResourcePool> list = new ArrayList<>();
+//			List<StandardMaterials> list = new ArrayList<>();
 //			int lastDataRowNum = ei.getLastDataRowNum();
 //			for (int i = 1; i <= lastDataRowNum; i++) {
-//				LiKuResourcePool pool = new LiKuResourcePool();
+//				StandardMaterials pool = new StandardMaterials();
 //				Row row = ei.getRow(i);
 //				pool.setSerialNumber(String.valueOf(row.getCell(0)));
 //				pool.setFactory(String.valueOf(row.getCell(1)));

+ 89 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/entity/MaterialQuota.java

@@ -0,0 +1,89 @@
+package com.jeeplus.modules.sg.balancedlibrary.materialQuota.entity;
+
+import com.jeeplus.common.utils.excel.annotation.ExcelField;
+import com.jeeplus.core.persistence.DataEntity;
+
+/**
+ * 物资限额Entity
+ * @author enford
+ * @version 1.0
+ */
+public class MaterialQuota extends DataEntity<MaterialQuota> {
+
+    private String materialCode;//物料编码
+
+    private String materialDesc;//物料描述
+
+    private String materialBigClass;//物料大类
+
+    private String materialMedClass;//物料中类
+
+    private String materialLittleClass;//物料小类
+
+    private String unit;//单位
+
+    private Double quota;//最高限额
+
+    @ExcelField(title = "物料编码", align = 2, sort = 1)
+    public String getMaterialCode() {
+        return materialCode;
+    }
+
+    public void setMaterialCode(String materialCode) {
+        this.materialCode = materialCode;
+    }
+
+    @ExcelField(title = "物料描述", align = 2, sort = 2)
+    public String getMaterialDesc() {
+        return materialDesc;
+    }
+
+    public void setMaterialDesc(String materialDesc) {
+        this.materialDesc = materialDesc;
+    }
+
+    @ExcelField(title = "物料大类", align = 2, sort = 3)
+    public String getMaterialBigClass() {
+        return materialBigClass;
+    }
+
+    public void setMaterialBigClass(String materialBigClass) {
+        this.materialBigClass = materialBigClass;
+    }
+
+    @ExcelField(title = "物料中类", align = 2, sort = 4)
+    public String getMaterialMedClass() {
+        return materialMedClass;
+    }
+
+    public void setMaterialMedClass(String materialMedClass) {
+        this.materialMedClass = materialMedClass;
+    }
+
+    @ExcelField(title = "物料小类", align = 2, sort = 5)
+    public String getMaterialLittleClass() {
+        return materialLittleClass;
+    }
+
+    public void setMaterialLittleClass(String materialLittleClass) {
+        this.materialLittleClass = materialLittleClass;
+    }
+
+    @ExcelField(title = "单位", align = 2, sort = 6)
+    public String getUnit() {
+        return unit;
+    }
+
+    public void setUnit(String unit) {
+        this.unit = unit;
+    }
+
+    @ExcelField(title = "最高限额", align = 2, sort = 7)
+    public Double getQuota() {
+        return quota;
+    }
+
+    public void setQuota(Double quota) {
+        this.quota = quota;
+    }
+}

+ 37 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/mapper/MaterialQuotaMapper.java

@@ -0,0 +1,37 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.materialQuota.mapper;
+
+import com.jeeplus.core.persistence.BaseMapper;
+import com.jeeplus.core.persistence.annotation.MyBatisMapper;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.entity.MaterialQuota;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 物料限额MAPPER接口
+ * @author enford
+ * @version 1.0
+ */
+@MyBatisMapper
+public interface MaterialQuotaMapper extends BaseMapper<MaterialQuota> {
+    /**
+     *
+     * @param list 数据列表
+     * */
+    void insertList(@Param("list") List<MaterialQuota> list);
+
+    /**
+     * 清空物料限额数据
+     */
+    void clearMaterialQuota();
+
+    /**
+     * 根据id批量删除
+     * @param list
+     */
+    void delList(@Param("list") List<String> list);
+}

+ 111 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/mapper/xml/MaterialQuotaMapper.xml

@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jeeplus.modules.sg.balancedlibrary.materialQuota.mapper.MaterialQuotaMapper">
+	<sql id="resourceColumns">
+		a.id AS "id",
+		a.create_by AS "createBy.id",
+		a.create_date AS "createDate",
+		a.update_by AS "updateBy.id",
+		a.update_date AS "updateDate",
+		a.material_code AS "materialCode",
+		a.material_desc AS "materialDesc",
+		a.material_big_class AS "materialBigClass",
+		a.material_med_class AS "materialMedClass",
+		a.material_little_class AS "materialLittleClass",
+		a.unit AS "unit",
+		a.quota AS "quota"
+	</sql>
+
+
+
+	<select id="get" resultType="MaterialQuota" >
+		SELECT
+			<include refid="resourceColumns"/>
+		FROM bla_material_quota a
+		WHERE a.id = #{id}
+	</select>
+
+	<select id="findList" resultType="MaterialQuota" >
+		SELECT
+			<include refid="resourceColumns"/>
+		FROM bla_material_quota a
+		<where>
+			a.del_flag = #{DEL_FLAG_NORMAL}
+			${dataScope}
+			<if test="materialCode != null and materialCode != ''">
+				AND a.material_code = #{materialCode}
+			</if>
+		</where>
+		<choose>
+			<when test="page !=null and page.orderBy != null and page.orderBy != ''">
+				ORDER BY ${page.orderBy}
+			</when>
+			<otherwise>
+				ORDER BY a.material_code asc
+			</otherwise>
+		</choose>
+	</select>
+
+	<select id="findAllList" resultType="MaterialQuota" >
+		SELECT
+			a.material_code AS "materialCode",
+			a.unit AS "unit",
+			a.quota AS "quota"
+		FROM bla_material_quota a
+		<where>
+			a.del_flag = #{DEL_FLAG_NORMAL}
+			${dataScope}
+		</where>
+	</select>
+
+
+	<insert id="insertList">
+		insert into bla_material_quota(
+		id,
+		create_by,
+		create_date,
+		update_by,
+		update_date,
+		del_flag,
+		material_code,
+		material_desc,
+		material_big_class,
+		material_med_class,
+		material_little_class,
+		unit,
+		quota
+		)VALUES
+		<foreach collection="list" item="item" index="index" separator=",">
+			(
+			#{item.id},
+			#{item.createBy.id},
+			#{item.createDate},
+			#{item.updateBy.id},
+			#{item.updateDate},
+			#{item.delFlag},
+			#{item.materialCode},
+			#{item.materialDesc},
+			#{item.materialBigClass},
+			#{item.materialMedClass},
+			#{item.materialLittleClass},
+			#{item.unit},
+			#{item.quota}
+			)
+		</foreach>
+	</insert>
+
+	<delete id="clearMaterialQuota">
+		truncate table bla_material_quota
+	</delete>
+
+	<!--物理删除-->
+	<update id="delList">
+		DELETE FROM bla_material_quota
+		WHERE id in
+		(
+		<foreach collection="list" item="item" index="index" separator=",">
+			#{item}
+		</foreach>
+		)
+	</update>
+</mapper>

+ 83 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/service/MaterialQuotaService.java

@@ -0,0 +1,83 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.materialQuota.service;
+
+import com.jeeplus.core.persistence.Page;
+import com.jeeplus.core.service.CrudService;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.mapper.LiKuResourcePoolMapper;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.entity.MaterialQuota;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.mapper.MaterialQuotaMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * 物料限额Service
+ * @author enford
+ * @version 1.0
+ */
+@Service
+@Transactional(readOnly = true)
+public class MaterialQuotaService extends CrudService<MaterialQuotaMapper, MaterialQuota> {
+
+	@Override
+	public MaterialQuota get(String id) {
+		return super.get(id);
+	}
+
+	@Override
+	public List<MaterialQuota> findList(MaterialQuota entity) {
+		return super.findList(entity);
+	}
+
+	@Override
+	public Page<MaterialQuota> findPage(Page<MaterialQuota> page, MaterialQuota entity) {
+		return super.findPage(page, entity);
+	}
+
+
+	//
+	@Transactional(readOnly = false)
+	public void fullReplace(List<MaterialQuota> list) {
+		mapper.clearMaterialQuota();
+		for (MaterialQuota li :
+				list) {
+			li.preInsert();
+		}
+		int eachSize = 5000;//每次往数据库插入的数据量
+		if(list.size()>eachSize) {
+			int begin = 0;
+			int end = eachSize;
+			while (true) {
+				mapper.insertList(list.subList(begin, end));
+				if (end == list.size()) {
+					break;
+				}
+				begin = end;
+				if ((end + eachSize) > list.size()) {
+					end = list.size();
+				} else {
+					end = end + eachSize;
+				}
+			}
+
+		}else{
+			mapper.insertList(list);
+		}
+
+	}
+
+
+	/**
+	 * 清空物料限额数据
+	 */
+	@Transactional(readOnly = false)
+	public void deleteList(List<String> list) {
+		mapper.delList(list);
+	}
+
+
+}

+ 393 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/utils/ImportUtil.java

@@ -0,0 +1,393 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.materialQuota.utils;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.utils.Reflections;
+import com.jeeplus.common.utils.excel.annotation.ExcelField;
+import com.jeeplus.modules.sys.entity.Area;
+import com.jeeplus.modules.sys.entity.Office;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.DictUtils;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 导入Excel文件(支持“XLS”和“XLSX”格式)
+ * @author jeeplus
+ * @version 2016-03-10
+ */
+public class ImportUtil {
+
+	private static Logger log = LoggerFactory.getLogger(ImportUtil.class);
+
+	/**
+	 * 工作薄对象
+	 */
+	private Workbook wb;
+
+	/**
+	 * 工作表对象
+	 */
+	private Sheet sheet;
+
+	/**
+	 * 标题行号
+	 */
+	private int headerNum;
+
+	/**
+	 * 构造函数
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(String fileName, int headerNum)
+			throws InvalidFormatException, IOException {
+		this(new File(fileName), headerNum);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象,读取第一个工作表
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(File file, int headerNum)
+			throws InvalidFormatException, IOException {
+		this(file, headerNum, 0);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(String fileName, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(new File(fileName), headerNum, sheetIndex);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(File file, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(file.getName(), new FileInputStream(file), headerNum, sheetIndex);
+	}
+
+	/**
+	 * 构造函数
+	 * @param file 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(MultipartFile multipartFile, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(String fileName, InputStream is, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		if (StringUtils.isBlank(fileName)){
+			throw new RuntimeException("导入文档为空!");
+		}else if(fileName.toLowerCase().endsWith("xls")){    
+			this.wb = new HSSFWorkbook(is);    
+        }else if(fileName.toLowerCase().endsWith("xlsx")){  
+        	this.wb = new XSSFWorkbook(is);
+        }else{  
+        	throw new RuntimeException("文档格式不正确!");
+        }  
+		if (this.wb.getNumberOfSheets()<sheetIndex){
+			throw new RuntimeException("文档中没有工作表!");
+		}
+		this.sheet = this.wb.getSheetAt(sheetIndex);
+		this.headerNum = headerNum;
+		log.debug("Initialize success.");
+	}
+	
+	/**
+	 * 获取行对象
+	 * @param rownum
+	 * @return
+	 */
+	public Row getRow(int rownum){
+		return this.sheet.getRow(rownum);
+	}
+
+	/**
+	 * 获取数据行号
+	 * @return
+	 */
+	public int getDataRowNum(){
+		return headerNum+1;
+	}
+	
+	/**
+	 * 获取最后一个数据行号
+	 * @return
+	 */
+	public int getLastDataRowNum(){
+//		return this.sheet.getLastRowNum()+headerNum;
+		return this.sheet.getLastRowNum()+1;
+	}
+	
+	/**
+	 * 获取最后一个列号
+	 * @return
+	 */
+	public int getLastCellNum(){
+		return this.getRow(headerNum).getLastCellNum();
+	}
+	
+	/**
+	 * 获取单元格值
+	 * @param row 获取的行
+	 * @param column 获取单元格列号
+	 * @return 单元格值
+	 */
+	public Object getCellValue(Row row, int column) {
+		Object val = "";
+		try {
+			Cell cell = row.getCell(column);
+			if (cell != null) {
+				if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+					// val = cell.getNumericCellValue();
+					// 当excel 中的数据为数值或日期是需要特殊处理
+					if (HSSFDateUtil.isCellDateFormatted(cell)) {
+						double d = cell.getNumericCellValue();
+						Date date = HSSFDateUtil.getJavaDate(d);
+						SimpleDateFormat dformat = new SimpleDateFormat(
+								"yyyy-MM-dd");
+						val = dformat.format(date);
+					} else {
+						NumberFormat nf = NumberFormat.getInstance();
+						nf.setGroupingUsed(false);// true时的格式:1,234,567,890
+						val = nf.format(cell.getNumericCellValue());// 数值类型的数据为double,所以需要转换一下
+					}
+				} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
+					val = cell.getStringCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
+					val = cell.getCellFormula();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
+					val = cell.getBooleanCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
+					val = cell.getErrorCellValue();
+				}
+			}
+		} catch (Exception e) {
+			return val;
+		}
+		return val;
+	}
+	
+	/**
+	 * 获取导入数据列表
+	 * @param cls 导入对象类型
+	 * @param groups 导入分组
+	 */
+	public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{
+		List<Object[]> annotationList = Lists.newArrayList();
+		// Get annotation field 
+		Field[] fs = cls.getDeclaredFields();
+		for (Field f : fs){
+			ExcelField ef = f.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, f});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, f});
+				}
+			}
+		}
+		// Get annotation method
+		Method[] ms = cls.getDeclaredMethods();
+		for (Method m : ms){
+			ExcelField ef = m.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, m});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, m});
+				}
+			}
+		}
+		// Field sorting
+		Collections.sort(annotationList, new Comparator<Object[]>() {
+			public int compare(Object[] o1, Object[] o2) {
+				return new Integer(((ExcelField)o1[0]).sort()).compareTo(
+						new Integer(((ExcelField)o2[0]).sort()));
+			};
+		});
+		//log.debug("Import column count:"+annotationList.size());
+		// Get excel data
+		List<E> dataList = Lists.newArrayList();
+		for (int i = this.getDataRowNum(); i < this.getLastDataRowNum(); i++) {
+			E e = (E)cls.newInstance();
+			int column = 0;
+			Row row = this.getRow(i);
+			StringBuilder sb = new StringBuilder();
+			for (Object[] os : annotationList){
+				Object val = this.getCellValue(row, column++);
+				if (val != null){
+					ExcelField ef = (ExcelField)os[0];
+					// If is dict type, get dict value
+					if (StringUtils.isNotBlank(ef.dictType())){
+						val = DictUtils.getDictValue(val.toString(), ef.dictType(), "");
+						//log.debug("Dictionary type value: ["+i+","+colunm+"] " + val);
+					}
+					// Get param type and type cast
+					Class<?> valType = Class.class;
+					if (os[1] instanceof Field){
+						valType = ((Field)os[1]).getType();
+					}else if (os[1] instanceof Method){
+						Method method = ((Method)os[1]);
+						if ("get".equals(method.getName().substring(0, 3))){
+							valType = method.getReturnType();
+						}else if("set".equals(method.getName().substring(0, 3))){
+							valType = ((Method)os[1]).getParameterTypes()[0];
+						}
+					}
+					//log.debug("Import value type: ["+i+","+column+"] " + valType);
+					try {
+						//如果导入的java对象,需要在这里自己进行变换。
+						if (valType == String.class){
+							String s = String.valueOf(val.toString());
+							if(StringUtils.endsWith(s, ".0")){
+								val = StringUtils.substringBefore(s, ".0");
+							}else{
+								val = String.valueOf(val.toString());
+							}
+						}else if (valType == Integer.class){
+							val = Double.valueOf(val.toString()).intValue();
+						}else if (valType == Long.class){
+							val = Double.valueOf(val.toString()).longValue();
+						}else if (valType == Double.class){
+							val = Double.valueOf(val.toString());
+						}else if (valType == Float.class){
+							val = Float.valueOf(val.toString());
+						}else if (valType == Date.class){
+							SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
+							val=sdf.parse(val.toString()); 
+						}else if (valType == User.class){
+							val = UserUtils.getByUserName(val.toString());
+						}else if (valType == Office.class){
+							val = UserUtils.getByOfficeName(val.toString());
+						}else if (valType == Area.class){
+							val = UserUtils.getByAreaName(val.toString());
+						}else{
+							if (ef.fieldType() != Class.class){
+								val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
+							}else{
+								val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(), 
+										"fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
+							}
+						}
+					} catch (Exception ex) {
+						log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());
+						val = null;
+					}
+					// set entity value
+					if (os[1] instanceof Field){
+						Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);
+					}else if (os[1] instanceof Method){
+						String mthodName = ((Method)os[1]).getName();
+						if ("get".equals(mthodName.substring(0, 3))){
+							mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
+						}
+						Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
+					}
+				}
+				sb.append(val+", ");
+			}
+			dataList.add(e);
+			log.debug("Read success: ["+i+"] "+sb.toString());
+		}
+		return dataList;
+	}
+
+//	/**
+//	 * 导入测试
+//	 */
+//	public static void main(String[] args) throws Throwable {
+//		
+//		ImportExcel ei = new ImportExcel("target/export.xlsx", 1);
+//		
+//		for (int i = ei.getDataRowNum(); i < ei.getLastDataRowNum(); i++) {
+//			Row row = ei.getRow(i);
+//			for (int j = 0; j < ei.getLastCellNum(); j++) {
+//				Object val = ei.getCellValue(row, j);
+//				System.out.print(val+", ");
+//			}
+//			System.out.print("\n");
+//		}
+//		
+//	}
+}

+ 76 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/utils/LiKuUtils.java

@@ -0,0 +1,76 @@
+package com.jeeplus.modules.sg.balancedlibrary.materialQuota.utils;
+
+public class LiKuUtils {
+    /**
+     * 判断是否是段长数据
+     * YES-是 NO-不是
+     */
+    public static final Integer YES = 1;
+    public static final Integer NO = 0;
+
+    /**
+     * 地区编号值
+     * HLA2-市公司 HLD1-扬中 HLB1-丹阳 句容-HLC1 未知地区-NO_PLACE
+     */
+    public static final String HLA2 = "HLA2";
+    public static final String HLD1 = "HLD1";
+    public static final String HLB1 = "HLB1";
+    public static final String HLC1 = "HLC1";
+
+    /**
+     * 上报地区所属值
+     */
+    public static final String BB_PLACE = "市公司";
+    public static final String YZ_PLACE = "扬中";
+    public static final String DY_PLACE = "丹阳";
+    public static final String JR_PLACE = "句容";
+
+    /**
+     * 判断库存地所属标记
+     * BB_FLAG-市公司 YZ_FLAG-扬中 DY_FLAG-丹阳 JR_FLAG-句容 NO_FLAG-未知地区
+     * */
+    public static final Integer BB_FLAG = 1;
+    public static final Integer YZ_FLAG = 2;
+    public static final Integer DY_FLAG = 3;
+    public static final Integer JR_FLAG = 4;
+    public static final Integer NO_FLAG = 0;
+
+    /**
+     * 判断单位
+     * */
+    public static final String METER = "米";
+    public static final String Kilometer = "千米";
+
+
+    /**
+     * 根据单位判断物资是否为段长
+     * @param unit
+     * @return
+     */
+    public static Integer isTheUnitMeter(String unit) {
+        if (METER.equals(unit) || Kilometer.equals(unit)) {
+            return YES;
+        } else {
+            return NO;
+        }
+    }
+
+    /**
+     * 判断物资或利库所属地区
+     * @param area
+     * @return
+     */
+    public static Integer judgmentArea(String area) {
+        if (HLA2.equals(area) || area.contains(BB_PLACE)) {
+            return BB_FLAG;
+        } else if (HLD1.equals(area) || area.contains(YZ_PLACE)) {
+            return YZ_FLAG;
+        } else if (HLB1.equals(area) || area.contains(DY_PLACE)) {
+            return DY_FLAG;
+        } else if (HLC1.equals(area) || area.contains(JR_PLACE)) {
+            return JR_FLAG;
+        } else {
+            return NO_FLAG;
+        }
+    }
+}

+ 177 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/utils/OptimalUtil.java

@@ -0,0 +1,177 @@
+package com.jeeplus.modules.sg.balancedlibrary.materialQuota.utils;
+
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.entity.MaterialReportDetails;
+import com.jeeplus.modules.sys.utils.DictUtils;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+public class OptimalUtil {
+    //是否有“元素组合的和”与“待比对值”相同的情况,true为有
+    private boolean getEqual = false;
+    //所有可能的元素组合列表
+    private List<List<MaterialReportDetails>> result = new ArrayList<>();
+    //由物资上报方开始匹配时所有可能的元素组合列表
+    private List<List<LiKuResourcePool>> resultReverse = new ArrayList<>();
+    //最大浪费量
+    private BigDecimal maxiNun = new BigDecimal(DictUtils.getDictValue("maxWaste", "maximum_waste", ""));
+    //由物资上报方开始匹配时最大差额
+    private BigDecimal maxiNunReverse = new BigDecimal(DictUtils.getDictValue("maxWasteReverse", "maximum_waste", ""));
+
+    /**
+     *
+     * @param total 待比对的值
+     * @param elements  所有元素集合
+     * @return
+     */
+    public List<MaterialReportDetails> getOptimal(double total, List<MaterialReportDetails> elements){
+        //list降序排列
+        Collections.sort(elements, Comparator.comparing(MaterialReportDetails::getLengthOfMetre));
+        Collections.reverse(elements);
+        solve(0,0,new ArrayList<>(),total,elements);
+
+        //找到差值最小组合返回
+        List<MaterialReportDetails> returnList = new ArrayList<>();
+        BigDecimal currMax = BigDecimal.valueOf(0.0);//当前总和最大
+        for (List<MaterialReportDetails> detailsList :result) {
+            BigDecimal listSum = BigDecimal.valueOf(0.0);
+            for (MaterialReportDetails details :detailsList) {
+                listSum = listSum.add(BigDecimal.valueOf(details.getLengthOfMetre()));
+            }
+            if (listSum.compareTo(currMax) > 0) {
+                currMax = listSum;
+                returnList = detailsList;
+//                returnList.clear();
+//                returnList.addAll(detailsList);
+            }
+        }
+
+
+        return returnList;
+    }
+
+    /**
+     *
+     * @param total 待比对的值
+     * @param elements  利库所有元素集合
+     * @return
+     */
+    public List<LiKuResourcePool> getOptimalReverse(double total, List<LiKuResourcePool> elements){
+        //list降序排列
+        Collections.sort(elements, Comparator.comparing(LiKuResourcePool::getLengthOfMetre));
+        solveReverse(0,0,new ArrayList<>(),total,elements);
+
+        //找到差值最小组合返回
+        List<LiKuResourcePool> returnList = new ArrayList<>();
+        BigDecimal currMin = BigDecimal.valueOf(total).add(maxiNunReverse);//当前最小值
+        for (List<LiKuResourcePool> poolList : resultReverse) {
+            BigDecimal listSum = BigDecimal.valueOf(0.0);
+            for (LiKuResourcePool pool : poolList) {
+                listSum = listSum.add(BigDecimal.valueOf(pool.getLengthOfMetre()));
+            }
+            if (listSum.compareTo(currMin) < 0) {
+                currMin = listSum;
+                returnList = poolList;
+//                returnList.clear();
+//                returnList.addAll(detailsList);
+            }
+        }
+
+
+        return returnList;
+    }
+
+    /**
+     *
+     * @param index 当前集合下标
+     * @param sum   当前组合元素和
+     * @param curr  当前组合元素集合
+     * @param total 待比对的值
+     * @param elements 所有元素集合
+     */
+    public void solve(int index, double sum, List<MaterialReportDetails> curr, double total, List<MaterialReportDetails> elements ){
+        //如果找到元素组合的和与待比对值一样,则不往下继续查找
+        if(getEqual == true){
+            return;
+        }
+        //走到这一步,所有最后一个元素也参考过(可能加入组合也可能不加入),最终还是组合值小于待比对值。则放入到result中
+        if(index == elements.size()){
+            BigDecimal allSum = BigDecimal.valueOf(sum);
+            BigDecimal allTotal = BigDecimal.valueOf(total);
+            BigDecimal subtract = allTotal.subtract(allSum).setScale(2, BigDecimal.ROUND_HALF_UP);
+            if (subtract.compareTo(maxiNun) <= 0) {
+                result.add(curr);
+            }
+            return;
+        }
+        MaterialReportDetails next = elements.get(index);
+        //处理单位不同,所有都以米作为单位计算
+        Double nextNeed = next.getLengthOfMetre();
+
+        index++;
+        //如果将当前值加上已有元素组合的值等于待比对值,得到结果
+        if((sum+nextNeed)==total){
+            curr.add(next);
+            result = new ArrayList<>();
+            result.add(curr);
+            getEqual = true;
+        //如果将当前值加上已有元素组合的值大于待比对值,则不考虑这种组合的后续可能性
+        }else if((sum+nextNeed) > total){
+            solve(index,sum,curr,total,elements);
+        }else if((sum+nextNeed) < total){
+            List newCurr = new ArrayList(curr);
+            newCurr.add(next);
+            solve(index,sum+nextNeed,newCurr,total,elements);
+//            solve(index,sum,curr,total,elements);
+        }
+    }
+
+    /**
+     *
+     * @param index 当前集合下标
+     * @param sum   当前组合元素和
+     * @param curr  当前组合元素集合
+     * @param total 待比对的值
+     * @param elements 所有元素集合
+     */
+    public void solveReverse(int index, double sum, List<LiKuResourcePool> curr, double total, List<LiKuResourcePool> elements ){
+        //如果找到元素组合的和与待比对值一样,则不往下继续查找
+        if(getEqual == true){
+            return;
+        }
+        //走到这一步,说明总和比total少,不放入
+        if(index == elements.size()){
+            return;
+        }
+        LiKuResourcePool next = elements.get(index);
+        //处理单位不同,所有都以米作为单位计算
+        Double cableLength = next.getLengthOfMetre();
+
+        index++;
+        //如果将当前值加上已有元素组合的值等于待比对值,得到结果
+        if((sum+cableLength)==total){
+            curr.add(next);
+            resultReverse = new ArrayList<>();
+            resultReverse.add(curr);
+            getEqual = true;
+            //如果将当前值加上已有元素组合的值大于待比对值,则不考虑这种组合的后续可能性
+        }else if((sum+cableLength) > total){
+            BigDecimal bigSum = BigDecimal.valueOf(sum);
+            BigDecimal bigLength = BigDecimal.valueOf(cableLength);
+            BigDecimal bigTotal = BigDecimal.valueOf(total);
+            BigDecimal subtract = bigSum.add(bigLength).subtract(bigTotal).setScale(2,BigDecimal.ROUND_HALF_UP);
+            if(subtract.compareTo(maxiNunReverse)<=0){
+                curr.add(next);
+                resultReverse.add(curr);
+            }
+            //由于资源池是由小到大排序,所以后面的一定不会比这条更接近最优解,则下面的代码不需要
+//            solveReverse(index,sum,curr,total,elements);
+        }else if((sum+cableLength) < total){
+            List newCurr = new ArrayList(curr);
+            newCurr.add(next);
+            solveReverse(index,sum+cableLength,newCurr,total,elements);
+            solveReverse(index,sum,curr,total,elements);
+        }
+    }
+}

+ 169 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialQuota/web/MaterialQuotaController.java

@@ -0,0 +1,169 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.materialQuota.web;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.json.AjaxJson;
+import com.jeeplus.common.utils.DateUtils;
+import com.jeeplus.common.utils.StringUtils;
+import com.jeeplus.common.utils.excel.ExportExcel;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.utils.ImportUtil;
+import com.jeeplus.core.persistence.Page;
+import com.jeeplus.core.web.BaseController;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.service.LiKuResourcePoolService;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.utils.LiKuUtils;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.entity.MaterialQuota;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.service.MaterialQuotaService;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.shiro.authz.annotation.Logical;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.ConstraintViolationException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 物料限额Controller
+ * @author lgf
+ * @version 2018-06-12
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/materialQuota")
+public class MaterialQuotaController extends BaseController {
+
+	@Autowired
+	private MaterialQuotaService service;
+
+
+
+	@ModelAttribute
+	public MaterialQuota get(@RequestParam(required=false) String id) {
+		MaterialQuota entity = null;
+		if (StringUtils.isNotBlank(id)){
+			entity = service.get(id);
+		}
+		if (entity == null){
+			entity = new MaterialQuota();
+		}
+		return entity;
+	}
+	
+	/**
+	 * 物料限额列表页面
+	 */
+	@RequiresPermissions("sg:balancedlibrary:materialQuota:list")
+	@RequestMapping(value = "list")
+	public String list(MaterialQuota entity, Model model) {
+		model.addAttribute("entity", entity);
+		return "modules/sg/balancedlibrary/materialQuota/materialQuotaList";
+	}
+	
+		/**
+	 * 物料限额列表数据
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:materialQuota:list")
+	@RequestMapping(value = "data")
+	public Map<String, Object> data(MaterialQuota entity, HttpServletRequest request, HttpServletResponse response, Model model) {
+		Page<MaterialQuota> page = service.findPage(new Page<MaterialQuota>(request, response), entity);
+		return getBootstrapData(page);
+	}
+
+	
+	/**
+	 * 批量删除物料限额
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:materialQuota:del")
+	@RequestMapping(value = "deleteAll")
+	public AjaxJson deleteAll(String ids) {
+		AjaxJson j = new AjaxJson();
+		String idArr[] =ids.split(",");
+		List<String> idList = Arrays.asList(idArr);
+		service.deleteList(idList);
+		j.setMsg("删除物料限额成功");
+		return j;
+	}
+	
+	/**
+	 * 导出excel文件
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:materialQuota:export")
+    @RequestMapping(value = "export")
+    public AjaxJson exportFile(MaterialQuota entity, HttpServletRequest request, HttpServletResponse response) {
+		AjaxJson j = new AjaxJson();
+		try {
+            String fileName = "物料限额表"+DateUtils.getDate("yyyyMMddHHmmss")+".xlsx";
+            Page<MaterialQuota> page = service.findPage(new Page<MaterialQuota>(request, response, -1), entity);
+    		new ExportExcel("", MaterialQuota.class).setDataList(page.getList()).write(response, fileName).dispose();
+    		j.setSuccess(true);
+    		j.setMsg("导出成功!");
+    		return j;
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg("导出物料限额表失败!失败信息:"+e.getMessage());
+		}
+			return j;
+    }
+
+	/**
+	 * 物料限额-导入Excel数据
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:materialQuota:import")
+    @RequestMapping(value = "import")
+   	public AjaxJson importFile(@RequestParam("file")MultipartFile file, HttpServletResponse response, HttpServletRequest request) {
+		AjaxJson j = new AjaxJson();
+		try {
+			ImportUtil ei = new ImportUtil(file,0,0);
+			List<MaterialQuota> list = ei.getDataList(MaterialQuota.class);
+			if (list.size() > 0) {
+				//物资限额每次重新导入数据,将原有数据清空
+				service.fullReplace(list);
+				j.setMsg("已成功导入 " + list.size() + " 条物料限额记录");
+			}
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg("导入物料限额失败!失败信息:"+e.getMessage());
+		}
+		return j;
+    }
+
+
+
+	/**
+	 * 下载导入物料限额数据模板
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:materialQuota:import")
+    @RequestMapping(value = "import/template")
+     public AjaxJson importFileTemplate(HttpServletResponse response) {
+		AjaxJson j = new AjaxJson();
+		try {
+            String fileName = "物料限额数据导入模板.xlsx";
+    		List<MaterialQuota> list = Lists.newArrayList();
+    		new ExportExcel("", MaterialQuota.class, 1).setDataList(list).write(response, fileName).dispose();
+    		return null;
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg( "导入模板下载失败!失败信息:"+e.getMessage());
+		}
+		return j;
+    }
+
+}

+ 47 - 23
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/entity/MaterialReportDetails.java

@@ -56,6 +56,12 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
      * */
     private String supplied;
 
+    //提报人
+    private String reportPerson;
+
+    //提报部门
+    private String reportDepartment;
+
     /**
      * 利库数量
      * */
@@ -294,6 +300,24 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.supplied = supplied;
     }
 
+    @ExcelField(title = "提报人", align = 2, sort = 12)
+    public String getReportPerson() {
+        return reportPerson;
+    }
+
+    public void setReportPerson(String reportPerson) {
+        this.reportPerson = reportPerson;
+    }
+
+    @ExcelField(title = "提报部门", align = 2, sort = 13)
+    public String getReportDepartment() {
+        return reportDepartment;
+    }
+
+    public void setReportDepartment(String reportDepartment) {
+        this.reportDepartment = reportDepartment;
+    }
+
     @Override
     public String getRemarks() {
         return super.getRemarks();
@@ -304,7 +328,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         super.setRemarks(remarks);
     }
 
-    @ExcelField(title = "利库数量", align = 2, sort = 12)
+    @ExcelField(title = "利库数量", align = 2, sort = 14)
     public Double getNumberOfNiches() {
         return numberOfNiches;
     }
@@ -313,7 +337,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.numberOfNiches = numberOfNiches;
     }
 
-    @ExcelField(title = "申请数量", align = 2, sort = 13)
+    @ExcelField(title = "申请数量", align = 2, sort = 15)
     public Double getNumberOfApplications() {
         return numberOfApplications;
     }
@@ -370,7 +394,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.replaceExCode = replaceExCode;
     }
 
-    @ExcelField(title = "本地利库批次号", align = 2, sort = 14)
+    @ExcelField(title = "本地利库批次号", align = 2, sort = 16)
     public String getLocalWareBatch() {
         return localWareBatch;
     }
@@ -379,7 +403,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.localWareBatch = localWareBatch;
     }
 
-    @ExcelField(title = "本地利库库存地", align = 2, sort = 15)
+    @ExcelField(title = "本地利库库存地", align = 2, sort = 17)
     public String getLocalWareHouse() {
         return localWareHouse;
     }
@@ -388,7 +412,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.localWareHouse = localWareHouse;
     }
 
-    @ExcelField(title = "本地利库数量", align = 2, sort = 16)
+    @ExcelField(title = "本地利库数量", align = 2, sort = 18)
     public String getNumberOfLocal() {
         return numberOfLocal;
     }
@@ -397,7 +421,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.numberOfLocal = numberOfLocal;
     }
 
-    @ExcelField(title = "跨区利库批次号", align = 2, sort = 17)
+    @ExcelField(title = "跨区利库批次号", align = 2, sort = 19)
     public String getRegionalBatch() {
         return regionalBatch;
     }
@@ -406,7 +430,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.regionalBatch = regionalBatch;
     }
 
-    @ExcelField(title = "跨区利库库存地", align = 2, sort = 18)
+    @ExcelField(title = "跨区利库库存地", align = 2, sort = 20)
     public String getRegionalHouse() {
         return regionalHouse;
     }
@@ -415,7 +439,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.regionalHouse = regionalHouse;
     }
 
-    @ExcelField(title = "跨区利库数量", align = 2, sort = 19)
+    @ExcelField(title = "跨区利库数量", align = 2, sort = 21)
     public String getNumberOfRegional() {
         return numberOfRegional;
     }
@@ -424,7 +448,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.numberOfRegional = numberOfRegional;
     }
 
-    @ExcelField(title = "合并规划利库批次号", align = 2, sort = 20)
+    @ExcelField(title = "合并规划利库批次号", align = 2, sort = 22)
     public String getConsolidatedBatch() {
         return consolidatedBatch;
     }
@@ -433,7 +457,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.consolidatedBatch = consolidatedBatch;
     }
 
-    @ExcelField(title = "合并规划利库库存地", align = 2, sort = 21)
+    @ExcelField(title = "合并规划利库库存地", align = 2, sort = 23)
     public String getConsolidatedWareHouse() {
         return consolidatedWareHouse;
     }
@@ -442,7 +466,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.consolidatedWareHouse = consolidatedWareHouse;
     }
 
-    @ExcelField(title = "合并规划利库数量", align = 2, sort = 22)
+    @ExcelField(title = "合并规划利库数量", align = 2, sort = 24)
     public String getNumberOfConsolidated() {
         return numberOfConsolidated;
     }
@@ -451,7 +475,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.numberOfConsolidated = numberOfConsolidated;
     }
 
-    @ExcelField(title = "本地以大代小利库型号", align = 2, sort = 23)
+    @ExcelField(title = "本地以大代小利库型号", align = 2, sort = 25)
     public String getLocalLiKuModel() {
         return localLiKuModel;
     }
@@ -460,7 +484,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.localLiKuModel = localLiKuModel;
     }
 
-    @ExcelField(title = "本地以大代小利库批次号", align = 2, sort = 24)
+    @ExcelField(title = "本地以大代小利库批次号", align = 2, sort = 26)
     public String getLocalLiKuBatch() {
         return localLiKuBatch;
     }
@@ -469,7 +493,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.localLiKuBatch = localLiKuBatch;
     }
 
-    @ExcelField(title = "本地以大代小利库库存地", align = 2, sort = 25)
+    @ExcelField(title = "本地以大代小利库库存地", align = 2, sort = 27)
     public String getLocalLiKuWareHouse() {
         return localLiKuWareHouse;
     }
@@ -478,7 +502,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.localLiKuWareHouse = localLiKuWareHouse;
     }
 
-    @ExcelField(title = "本地以大代小利库数量", align = 2, sort = 26)
+    @ExcelField(title = "本地以大代小利库数量", align = 2, sort = 28)
     public String getNumberOfLocalLiKu() {
         return numberOfLocalLiKu;
     }
@@ -487,7 +511,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.numberOfLocalLiKu = numberOfLocalLiKu;
     }
 
-    @ExcelField(title = "跨区以大代小利库型号", align = 2, sort = 27)
+    @ExcelField(title = "跨区以大代小利库型号", align = 2, sort = 29)
     public String getRegionLiKuModel() {
         return regionLiKuModel;
     }
@@ -496,7 +520,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.regionLiKuModel = regionLiKuModel;
     }
 
-    @ExcelField(title = "跨区以大代小利库批次号", align = 2, sort = 28)
+    @ExcelField(title = "跨区以大代小利库批次号", align = 2, sort = 30)
     public String getRegionLiKuBatch() {
         return regionLiKuBatch;
     }
@@ -505,7 +529,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.regionLiKuBatch = regionLiKuBatch;
     }
 
-    @ExcelField(title = "跨区以大代小利库库存地", align = 2, sort = 29)
+    @ExcelField(title = "跨区以大代小利库库存地", align = 2, sort = 31)
     public String getRegionLiKuWareHouse() {
         return regionLiKuWareHouse;
     }
@@ -514,7 +538,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.regionLiKuWareHouse = regionLiKuWareHouse;
     }
 
-    @ExcelField(title = "跨区以大代小利库数量", align = 2, sort = 30)
+    @ExcelField(title = "跨区以大代小利库数量", align = 2, sort = 32)
     public String getNumberOfRegionalLiKu() {
         return numberOfRegionalLiKu;
     }
@@ -523,7 +547,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.numberOfRegionalLiKu = numberOfRegionalLiKu;
     }
 
-    @ExcelField(title = "合并以大代小规划利库型号", align = 2, sort = 31)
+    @ExcelField(title = "合并以大代小规划利库型号", align = 2, sort = 33)
     public String getConLocalModel() {
         return conLocalModel;
     }
@@ -532,7 +556,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.conLocalModel = conLocalModel;
     }
 
-    @ExcelField(title = "合并以大代小规划利库批次号", align = 2, sort = 32)
+    @ExcelField(title = "合并以大代小规划利库批次号", align = 2, sort = 34)
     public String getConLocalBatch() {
         return conLocalBatch;
     }
@@ -541,7 +565,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.conLocalBatch = conLocalBatch;
     }
 
-    @ExcelField(title = "合并以大代小规划利库库存地", align = 2, sort = 33)
+    @ExcelField(title = "合并以大代小规划利库库存地", align = 2, sort = 35)
     public String getConLocalWareHouse() {
         return conLocalWareHouse;
     }
@@ -550,7 +574,7 @@ public class MaterialReportDetails extends DataEntity<MaterialReportDetails> {
         this.conLocalWareHouse = conLocalWareHouse;
     }
 
-    @ExcelField(title = "合并以大代小规划利库数量", align = 2, sort = 34)
+    @ExcelField(title = "合并以大代小规划利库数量", align = 2, sort = 36)
     public String getNumberOfConLocal() {
         return numberOfConLocal;
     }

+ 561 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/utils/ExcelUtil.java

@@ -0,0 +1,561 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.utils;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.utils.Reflections;
+import com.jeeplus.common.utils.excel.annotation.ExcelField;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.entity.MaterialQuota;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.entity.StandardMaterials;
+import com.jeeplus.modules.sys.entity.Area;
+import com.jeeplus.modules.sys.entity.Office;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.DictUtils;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URLEncoder;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * 专门处理导入项目物资后验证问题
+ */
+public class ExcelUtil {
+
+	private static Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+
+	/**
+	 * 工作薄对象
+	 */
+	private Workbook wb;
+
+	/**
+	 * 工作表对象
+	 */
+	private Sheet sheet;
+
+	/**
+	 * 标题行号
+	 */
+	private int headerNum;
+
+	/**
+	 * 构造函数
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ExcelUtil(String fileName, int headerNum)
+			throws InvalidFormatException, IOException {
+		this(new File(fileName), headerNum);
+	}
+
+	public ExcelUtil(){
+	}
+
+	/**
+	 * 构造函数
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ExcelUtil(File file, int headerNum)
+			throws InvalidFormatException, IOException {
+		this(file, headerNum, 0);
+	}
+
+	/**
+	 * 构造函数
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ExcelUtil(String fileName, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(new File(fileName), headerNum, sheetIndex);
+	}
+
+	/**
+	 * 构造函数
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ExcelUtil(File file, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(file.getName(), new FileInputStream(file), headerNum, sheetIndex);
+	}
+
+	/**
+	 * 构造函数
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ExcelUtil(MultipartFile multipartFile, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex);
+	}
+
+	public ExcelUtil(MultipartFile multipartFile, int headerNum, String sheetName)
+			throws InvalidFormatException, IOException {
+		this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetName);
+	}
+
+	/**
+	 * 构造函数
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ExcelUtil(String fileName, InputStream is, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		if (StringUtils.isBlank(fileName)){
+			throw new RuntimeException("导入文档为空!");
+		}else if(fileName.toLowerCase().endsWith("xls")){
+			this.wb = new HSSFWorkbook(is);
+        }else if(fileName.toLowerCase().endsWith("xlsx")){
+        	this.wb = new XSSFWorkbook(is);
+        }else{
+        	throw new RuntimeException("文档格式不正确!");
+        }
+		if (this.wb.getNumberOfSheets()<sheetIndex){
+			throw new RuntimeException("文档中没有工作表!");
+		}
+		this.sheet = this.wb.getSheetAt(sheetIndex);
+		this.headerNum = headerNum;
+		log.debug("Initialize success.");
+	}
+
+	public ExcelUtil(String fileName, InputStream is, int headerNum, String sheetName)
+			throws InvalidFormatException, IOException {
+		if (StringUtils.isBlank(fileName)){
+			throw new RuntimeException("导入文档为空!");
+		}else if(fileName.toLowerCase().endsWith("xls")){
+			this.wb = new HSSFWorkbook(is);
+		}else if(fileName.toLowerCase().endsWith("xlsx")){
+			this.wb = new XSSFWorkbook(is);
+		}else{
+			throw new RuntimeException("文档格式不正确!");
+		}
+		if (this.wb.getSheet(sheetName) == null) {
+			throw new RuntimeException("缺少" + sheetName);
+		}
+		this.sheet = this.wb.getSheet(sheetName);
+		this.headerNum = headerNum;
+		log.debug("Initialize success.");
+	}
+	
+	/**
+	 * 获取行对象
+	 * @param rownum
+	 * @return
+	 */
+	public Row getRow(int rownum){
+		return this.sheet.getRow(rownum);
+	}
+
+	/**
+	 * 获取数据行号
+	 * @return
+	 */
+	public int getDataRowNum(){
+		return headerNum+1;
+	}
+	
+	/**
+	 * 获取最后一个数据行号
+	 * @return
+	 */
+	public int getLastDataRowNum(){
+		return this.sheet.getLastRowNum()+headerNum;
+	}
+	
+	/**
+	 * 获取最后一个列号
+	 * @return
+	 */
+	public int getLastCellNum(){
+		return this.getRow(headerNum).getLastCellNum();
+	}
+	
+	/**
+	 * 获取单元格值
+	 * @param row 获取的行
+	 * @param column 获取单元格列号
+	 * @return 单元格值
+	 */
+	public Object getCellValue(Row row, int column) {
+		Object val = "";
+		try {
+			Cell cell = row.getCell(column);
+			if (cell != null) {
+				if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+					// val = cell.getNumericCellValue();
+					// 当excel 中的数据为数值或日期是需要特殊处理
+					if (HSSFDateUtil.isCellDateFormatted(cell)) {
+						double d = cell.getNumericCellValue();
+						Date date = HSSFDateUtil.getJavaDate(d);
+						SimpleDateFormat dformat = new SimpleDateFormat(
+								"yyyy-MM-dd");
+						val = dformat.format(date);
+					} else {
+						NumberFormat nf = NumberFormat.getInstance();
+						nf.setGroupingUsed(false);// true时的格式:1,234,567,890
+						nf.setMaximumFractionDigits(4);
+						val = nf.format(cell.getNumericCellValue());// 数值类型的数据为double,所以需要转换一下
+					}
+				} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
+					val = cell.getStringCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
+//					val = cell.getCellFormula();
+					val = cell.getNumericCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
+					val = cell.getBooleanCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
+					val = cell.getErrorCellValue();
+				}
+			}
+		} catch (Exception e) {
+			return val;
+		}
+		return val;
+	}
+
+	/**
+	 * 获取单元格值
+	 * @param row 获取的行
+	 * @param column 获取单元格列号
+	 * @return 单元格值
+	 */
+	public Object getCellValue(Row row, int column,Integer maxDig) {
+		Object val = "";
+		try {
+			Cell cell = row.getCell(column);
+			if (cell != null) {
+				if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+					// val = cell.getNumericCellValue();
+					// 当excel 中的数据为数值或日期是需要特殊处理
+					if (HSSFDateUtil.isCellDateFormatted(cell)) {
+						double d = cell.getNumericCellValue();
+						Date date = HSSFDateUtil.getJavaDate(d);
+						SimpleDateFormat dformat = new SimpleDateFormat(
+								"yyyy-MM-dd");
+						val = dformat.format(date);
+					} else {
+						NumberFormat nf = NumberFormat.getInstance();
+						nf.setGroupingUsed(false);// true时的格式:1,234,567,890
+						if(maxDig == null){
+							nf.setMaximumFractionDigits(4);
+						}else{
+							nf.setMaximumFractionDigits(maxDig);
+						}
+
+						val = nf.format(cell.getNumericCellValue());// 数值类型的数据为double,所以需要转换一下
+					}
+				} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
+					val = cell.getStringCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
+//					val = cell.getCellFormula();
+					val = cell.getNumericCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
+					val = cell.getBooleanCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
+					val = cell.getErrorCellValue();
+				}
+			}
+		} catch (Exception e) {
+			return val;
+		}
+		return val;
+	}
+	
+	/**
+	 * 获取导入数据列表
+	 * @param cls 导入对象类型
+	 * @param groups 导入分组
+	 */
+	public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{
+		List<Object[]> annotationList = Lists.newArrayList();
+		// Get annotation field 
+		Field[] fs = cls.getDeclaredFields();
+		for (Field f : fs){
+			ExcelField ef = f.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, f});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, f});
+				}
+			}
+		}
+		// Get annotation method
+		Method[] ms = cls.getDeclaredMethods();
+		for (Method m : ms){
+			ExcelField ef = m.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, m});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, m});
+				}
+			}
+		}
+		// Field sorting
+		Collections.sort(annotationList, new Comparator<Object[]>() {
+			public int compare(Object[] o1, Object[] o2) {
+				return new Integer(((ExcelField)o1[0]).sort()).compareTo(
+						new Integer(((ExcelField)o2[0]).sort()));
+			};
+		});
+		//log.debug("Import column count:"+annotationList.size());
+		// Get excel data
+		List<E> dataList = Lists.newArrayList();
+		for (int i = this.getDataRowNum(); i < this.getLastDataRowNum(); i++) {
+			E e = (E)cls.newInstance();
+			int column = 0;
+			Row row = this.getRow(i);
+			StringBuilder sb = new StringBuilder();
+			for (Object[] os : annotationList){
+				Object val = this.getCellValue(row, column++);
+				if (val != null){
+					ExcelField ef = (ExcelField)os[0];
+					// If is dict type, get dict value
+					if (StringUtils.isNotBlank(ef.dictType())){
+						val = DictUtils.getDictValue(val.toString(), ef.dictType(), "");
+						//log.debug("Dictionary type value: ["+i+","+colunm+"] " + val);
+					}
+					// Get param type and type cast
+					Class<?> valType = Class.class;
+					if (os[1] instanceof Field){
+						valType = ((Field)os[1]).getType();
+					}else if (os[1] instanceof Method){
+						Method method = ((Method)os[1]);
+						if ("get".equals(method.getName().substring(0, 3))){
+							valType = method.getReturnType();
+						}else if("set".equals(method.getName().substring(0, 3))){
+							valType = ((Method)os[1]).getParameterTypes()[0];
+						}
+					}
+					//log.debug("Import value type: ["+i+","+column+"] " + valType);
+					try {
+						//如果导入的java对象,需要在这里自己进行变换。
+						if (valType == String.class){
+							String s = String.valueOf(val.toString());
+							if(StringUtils.endsWith(s, ".0")){
+								val = StringUtils.substringBefore(s, ".0");
+							}else{
+								val = String.valueOf(val.toString());
+							}
+						}else if (valType == Integer.class){
+							val = Double.valueOf(val.toString()).intValue();
+						}else if (valType == Long.class){
+							val = Double.valueOf(val.toString()).longValue();
+						}else if (valType == Double.class){
+							val = Double.valueOf(val.toString());
+						}else if (valType == Float.class){
+							val = Float.valueOf(val.toString());
+						}else if (valType == Date.class){
+							SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
+							val=sdf.parse(val.toString()); 
+						}else if (valType == User.class){
+							val = UserUtils.getByUserName(val.toString());
+						}else if (valType == Office.class){
+							val = UserUtils.getByOfficeName(val.toString());
+						}else if (valType == Area.class){
+							val = UserUtils.getByAreaName(val.toString());
+						}else{
+							if (ef.fieldType() != Class.class){
+								val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
+							}else{
+								val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(), 
+										"fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
+							}
+						}
+					} catch (Exception ex) {
+						log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());
+						val = null;
+					}
+					// set entity value
+					if (os[1] instanceof Field){
+						Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);
+					}else if (os[1] instanceof Method){
+						String mthodName = ((Method)os[1]).getName();
+						if ("get".equals(mthodName.substring(0, 3))){
+							mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
+						}
+						Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
+					}
+				}
+				sb.append(val+", ");
+			}
+			dataList.add(e);
+			log.debug("Read success: ["+i+"] "+sb.toString());
+		}
+		return dataList;
+	}
+
+
+
+	public Sheet getSheet(){
+		return this.sheet;
+	}
+
+	public Workbook getWb(){
+		return this.wb;
+	}
+
+	/**
+	 * 验证项目需求物资
+	 * @param standardList
+	 * @param preferredCodes
+	 * @param quotaList
+	 */
+	public void dealVerify(List<StandardMaterials> standardList, List<String> preferredCodes,
+						   List<MaterialQuota> quotaList){
+		Map<String,StandardMaterials> standardMap = new HashMap<>();
+		for(StandardMaterials standard:standardList){
+			standardMap.put(standard.getMaterialCode(),standard);
+		}
+		Map<String,MaterialQuota> quotaMap = new HashMap<>();
+		for(MaterialQuota quota:quotaList){
+			quotaMap.put(quota.getMaterialCode(),quota);
+		}
+		//处理标题行
+		Row title = sheet.getRow(1);
+		Cell cell14 = title.createCell(14);
+		Cell cell15 = title.createCell(15);
+		Cell cell16 = title.createCell(16);
+		cell14.setCellValue("采购标准标识");
+		cell15.setCellValue("三级清单物料");
+		cell16.setCellValue("物资数量校验");
+		CellStyle cellStyle = title.getCell(13).getCellStyle();
+		cell14.setCellStyle(cellStyle);
+		cell15.setCellStyle(cellStyle);
+		cell16.setCellStyle(cellStyle);
+		//处理数据行
+		for(int i=2;i<=sheet.getLastRowNum();i++){
+			Row row = sheet.getRow(i);
+			String materialCode = row.getCell(2).getStringCellValue();
+			if(materialCode!=null&&!materialCode.isEmpty()){
+				Cell standardCell = row.createCell(14);
+				standardCell.setCellValue(standardMap.get(materialCode).getPurchaseStandardId());
+				Cell preferredCell = row.createCell(15);
+				if(preferredCodes.contains(materialCode)){
+					preferredCell.setCellValue("优选");
+				}else{
+					preferredCell.setCellValue("非优选");
+				}
+				Cell quotaCell = row.createCell(16);
+				Double number = row.getCell(7).getNumericCellValue();//物资需求数量
+				MaterialQuota quota = quotaMap.get(materialCode);
+				if(quota!=null){
+					Double quotaNum = quota.getQuota();
+					if(quotaNum!=null){
+						if(number!=null&& number>quotaNum){
+							quotaCell.setCellValue("超限额");
+						}
+					}
+				}
+
+			}
+		}
+	}
+
+	/**
+	 * 将处理好的excel表保存到服务器上
+	 * @param sessionId
+	 * @throws IOException
+	 */
+	public void saveToServer(String sessionId) throws IOException {
+		String path = this.getClass().getResource("/").getPath()+ "temp"+sessionId;
+		File file = new File(path);
+		if(!file.exists()){
+			file.createNewFile();
+		}
+		OutputStream inputStream = new FileOutputStream(file);// 将excel文件转为输入流
+		wb.write(inputStream);
+	}
+
+	/**
+	 * d导出excel
+	 * @param response
+	 */
+	public void exportFile(HttpServletResponse response, String fileName, String  sessionId){
+		OutputStream outputStream = null;
+		File file = null;
+		try {
+			String path = this.getClass().getResource("/").getPath()+ "temp"+sessionId;
+			file = new File(path);
+			InputStream inputStream = new FileInputStream(file);// 将excel文件转为输入流
+			if (StringUtils.isBlank(fileName)){
+				throw new RuntimeException("导出失败!");
+			}else if(fileName.toLowerCase().endsWith("xls")){
+				this.wb = new HSSFWorkbook(inputStream);
+			}else if(fileName.toLowerCase().endsWith("xlsx")){
+				this.wb = new XSSFWorkbook(inputStream);
+			}else{
+				throw new RuntimeException("文档格式不正确!");
+			}
+			String str = URLEncoder.encode(fileName, "UTF8");
+			response.setHeader("Content-Disposition", "attachment;filename="+str);
+			response.setContentType("application/vnd.ms-excel;charset=UTF-8");
+			outputStream = response.getOutputStream();
+			wb.write(outputStream);
+			outputStream.flush();
+			outputStream.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}finally {
+			if(file != null&&file.exists()){
+				file.delete();
+			}
+		}
+	}
+
+
+}

+ 20 - 4
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/utils/ExportUtil.java

@@ -7,10 +7,7 @@ import com.jeeplus.modules.sg.financial.settlement.entity.CostCheck;
 import com.jeeplus.modules.sg.financial.settlement.entity.ProjectBudget;
 import com.jeeplus.modules.sg.financial.settlement.util.MyExportUtil;
 import org.apache.poi.hssf.usermodel.HSSFFont;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFCellStyle;
 import org.apache.poi.xssf.usermodel.XSSFFont;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@@ -160,6 +157,25 @@ public class ExportUtil {
         }
     }
 
+    /**
+     * d导出excel
+     * @param response
+     */
+    public static void exportFile(HttpServletResponse response, String fileName, Workbook workbook){
+        OutputStream outputStream = null;
+        try {
+            String str = URLEncoder.encode(fileName, "UTF8");
+            response.setHeader("Content-Disposition", "attachment;filename="+str);
+            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
+            outputStream = response.getOutputStream();
+            workbook.write(outputStream);
+            outputStream.flush();
+            outputStream.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
 
 
     /**

+ 620 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/utils/ImportExcel.java

@@ -0,0 +1,620 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.utils;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.utils.Reflections;
+import com.jeeplus.common.utils.excel.annotation.ExcelField;
+import com.jeeplus.modules.sys.entity.Area;
+import com.jeeplus.modules.sys.entity.Office;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.DictUtils;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 导入Excel文件(支持“XLS”和“XLSX”格式)
+ * @author jeeplus
+ * @version 2016-03-10
+ */
+public class ImportExcel {
+	
+	private static Logger log = LoggerFactory.getLogger(ImportExcel.class);
+			
+	/**
+	 * 工作薄对象
+	 */
+	private Workbook wb;
+	
+	/**
+	 * 工作表对象
+	 */
+	private Sheet sheet;
+	
+	/**
+	 * 标题行号
+	 */
+	private int headerNum;
+	
+	/**
+	 * 构造函数
+	 * @param path 导入文件,读取第一个工作表
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @throws InvalidFormatException 
+	 * @throws IOException 
+	 */
+	public ImportExcel(String fileName, int headerNum) 
+			throws InvalidFormatException, IOException {
+		this(new File(fileName), headerNum);
+	}
+	
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象,读取第一个工作表
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @throws InvalidFormatException 
+	 * @throws IOException 
+	 */
+	public ImportExcel(File file, int headerNum) 
+			throws InvalidFormatException, IOException {
+		this(file, headerNum, 0);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException 
+	 * @throws IOException 
+	 */
+	public ImportExcel(String fileName, int headerNum, int sheetIndex) 
+			throws InvalidFormatException, IOException {
+		this(new File(fileName), headerNum, sheetIndex);
+	}
+	
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException 
+	 * @throws IOException 
+	 */
+	public ImportExcel(File file, int headerNum, int sheetIndex) 
+			throws InvalidFormatException, IOException {
+		this(file.getName(), new FileInputStream(file), headerNum, sheetIndex);
+	}
+	
+	/**
+	 * 构造函数
+	 * @param file 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException 
+	 * @throws IOException 
+	 */
+	public ImportExcel(MultipartFile multipartFile, int headerNum, int sheetIndex) 
+			throws InvalidFormatException, IOException {
+		this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex);
+	}
+
+	public ImportExcel(MultipartFile multipartFile, int headerNum, String sheetName)
+			throws InvalidFormatException, IOException {
+		this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetName);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException 
+	 * @throws IOException 
+	 */
+	public ImportExcel(String fileName, InputStream is, int headerNum, int sheetIndex) 
+			throws InvalidFormatException, IOException {
+		if (StringUtils.isBlank(fileName)){
+			throw new RuntimeException("导入文档为空!");
+		}else if(fileName.toLowerCase().endsWith("xls")){    
+			this.wb = new HSSFWorkbook(is);    
+        }else if(fileName.toLowerCase().endsWith("xlsx")){  
+        	this.wb = new XSSFWorkbook(is);
+        }else{  
+        	throw new RuntimeException("文档格式不正确!");
+        }  
+		if (this.wb.getNumberOfSheets()<sheetIndex){
+			throw new RuntimeException("文档中没有工作表!");
+		}
+		this.sheet = this.wb.getSheetAt(sheetIndex);
+		this.headerNum = headerNum;
+		log.debug("Initialize success.");
+	}
+
+	public ImportExcel(String fileName, InputStream is, int headerNum, String sheetName)
+			throws InvalidFormatException, IOException {
+		if (StringUtils.isBlank(fileName)){
+			throw new RuntimeException("导入文档为空!");
+		}else if(fileName.toLowerCase().endsWith("xls")){
+			this.wb = new HSSFWorkbook(is);
+		}else if(fileName.toLowerCase().endsWith("xlsx")){
+			this.wb = new XSSFWorkbook(is);
+		}else{
+			throw new RuntimeException("文档格式不正确!");
+		}
+		if (this.wb.getSheet(sheetName) == null) {
+			throw new RuntimeException("缺少" + sheetName);
+		}
+		this.sheet = this.wb.getSheet(sheetName);
+		this.headerNum = headerNum;
+		log.debug("Initialize success.");
+	}
+	
+	/**
+	 * 获取行对象
+	 * @param rownum
+	 * @return
+	 */
+	public Row getRow(int rownum){
+		return this.sheet.getRow(rownum);
+	}
+
+	/**
+	 * 获取数据行号
+	 * @return
+	 */
+	public int getDataRowNum(){
+		return headerNum+1;
+	}
+	
+	/**
+	 * 获取最后一个数据行号
+	 * @return
+	 */
+	public int getLastDataRowNum(){
+		return this.sheet.getLastRowNum()+headerNum;
+	}
+	
+	/**
+	 * 获取最后一个列号
+	 * @return
+	 */
+	public int getLastCellNum(){
+		return this.getRow(headerNum).getLastCellNum();
+	}
+	
+	/**
+	 * 获取单元格值
+	 * @param row 获取的行
+	 * @param column 获取单元格列号
+	 * @return 单元格值
+	 */
+	public Object getCellValue(Row row, int column) {
+		Object val = "";
+		try {
+			Cell cell = row.getCell(column);
+			if (cell != null) {
+				if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+					// val = cell.getNumericCellValue();
+					// 当excel 中的数据为数值或日期是需要特殊处理
+					if (HSSFDateUtil.isCellDateFormatted(cell)) {
+						double d = cell.getNumericCellValue();
+						Date date = HSSFDateUtil.getJavaDate(d);
+						SimpleDateFormat dformat = new SimpleDateFormat(
+								"yyyy-MM-dd");
+						val = dformat.format(date);
+					} else {
+						NumberFormat nf = NumberFormat.getInstance();
+						nf.setGroupingUsed(false);// true时的格式:1,234,567,890
+						nf.setMaximumFractionDigits(4);
+						val = nf.format(cell.getNumericCellValue());// 数值类型的数据为double,所以需要转换一下
+					}
+				} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
+					val = cell.getStringCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
+//					val = cell.getCellFormula();
+					val = cell.getNumericCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
+					val = cell.getBooleanCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
+					val = cell.getErrorCellValue();
+				}
+			}
+		} catch (Exception e) {
+			return val;
+		}
+		return val;
+	}
+
+	/**
+	 * 获取单元格值
+	 * @param row 获取的行
+	 * @param column 获取单元格列号
+	 * @return 单元格值
+	 */
+	public Object getCellValue(Row row, int column,Integer maxDig) {
+		Object val = "";
+		try {
+			Cell cell = row.getCell(column);
+			if (cell != null) {
+				if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+					// val = cell.getNumericCellValue();
+					// 当excel 中的数据为数值或日期是需要特殊处理
+					if (HSSFDateUtil.isCellDateFormatted(cell)) {
+						double d = cell.getNumericCellValue();
+						Date date = HSSFDateUtil.getJavaDate(d);
+						SimpleDateFormat dformat = new SimpleDateFormat(
+								"yyyy-MM-dd");
+						val = dformat.format(date);
+					} else {
+						NumberFormat nf = NumberFormat.getInstance();
+						nf.setGroupingUsed(false);// true时的格式:1,234,567,890
+						if(maxDig == null){
+							nf.setMaximumFractionDigits(4);
+						}else{
+							nf.setMaximumFractionDigits(maxDig);
+						}
+
+						val = nf.format(cell.getNumericCellValue());// 数值类型的数据为double,所以需要转换一下
+					}
+				} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
+					val = cell.getStringCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
+//					val = cell.getCellFormula();
+					val = cell.getNumericCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
+					val = cell.getBooleanCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
+					val = cell.getErrorCellValue();
+				}
+			}
+		} catch (Exception e) {
+			return val;
+		}
+		return val;
+	}
+	
+	/**
+	 * 获取导入数据列表
+	 * @param cls 导入对象类型
+	 * @param groups 导入分组
+	 */
+	public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{
+		List<Object[]> annotationList = Lists.newArrayList();
+		// Get annotation field 
+		Field[] fs = cls.getDeclaredFields();
+		for (Field f : fs){
+			ExcelField ef = f.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, f});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, f});
+				}
+			}
+		}
+		// Get annotation method
+		Method[] ms = cls.getDeclaredMethods();
+		for (Method m : ms){
+			ExcelField ef = m.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, m});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, m});
+				}
+			}
+		}
+		// Field sorting
+		Collections.sort(annotationList, new Comparator<Object[]>() {
+			public int compare(Object[] o1, Object[] o2) {
+				return new Integer(((ExcelField)o1[0]).sort()).compareTo(
+						new Integer(((ExcelField)o2[0]).sort()));
+			};
+		});
+		//log.debug("Import column count:"+annotationList.size());
+		// Get excel data
+		List<E> dataList = Lists.newArrayList();
+		for (int i = this.getDataRowNum(); i < this.getLastDataRowNum(); i++) {
+			E e = (E)cls.newInstance();
+			int column = 0;
+			Row row = this.getRow(i);
+			StringBuilder sb = new StringBuilder();
+			for (Object[] os : annotationList){
+				Object val = this.getCellValue(row, column++);
+				if (val != null){
+					ExcelField ef = (ExcelField)os[0];
+					// If is dict type, get dict value
+					if (StringUtils.isNotBlank(ef.dictType())){
+						val = DictUtils.getDictValue(val.toString(), ef.dictType(), "");
+						//log.debug("Dictionary type value: ["+i+","+colunm+"] " + val);
+					}
+					// Get param type and type cast
+					Class<?> valType = Class.class;
+					if (os[1] instanceof Field){
+						valType = ((Field)os[1]).getType();
+					}else if (os[1] instanceof Method){
+						Method method = ((Method)os[1]);
+						if ("get".equals(method.getName().substring(0, 3))){
+							valType = method.getReturnType();
+						}else if("set".equals(method.getName().substring(0, 3))){
+							valType = ((Method)os[1]).getParameterTypes()[0];
+						}
+					}
+					//log.debug("Import value type: ["+i+","+column+"] " + valType);
+					try {
+						//如果导入的java对象,需要在这里自己进行变换。
+						if (valType == String.class){
+							String s = String.valueOf(val.toString());
+							if(StringUtils.endsWith(s, ".0")){
+								val = StringUtils.substringBefore(s, ".0");
+							}else{
+								val = String.valueOf(val.toString());
+							}
+						}else if (valType == Integer.class){
+							val = Double.valueOf(val.toString()).intValue();
+						}else if (valType == Long.class){
+							val = Double.valueOf(val.toString()).longValue();
+						}else if (valType == Double.class){
+							val = Double.valueOf(val.toString());
+						}else if (valType == Float.class){
+							val = Float.valueOf(val.toString());
+						}else if (valType == Date.class){
+							SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
+							val=sdf.parse(val.toString()); 
+						}else if (valType == User.class){
+							val = UserUtils.getByUserName(val.toString());
+						}else if (valType == Office.class){
+							val = UserUtils.getByOfficeName(val.toString());
+						}else if (valType == Area.class){
+							val = UserUtils.getByAreaName(val.toString());
+						}else{
+							if (ef.fieldType() != Class.class){
+								val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
+							}else{
+								val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(), 
+										"fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
+							}
+						}
+					} catch (Exception ex) {
+						log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());
+						val = null;
+					}
+					// set entity value
+					if (os[1] instanceof Field){
+						Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);
+					}else if (os[1] instanceof Method){
+						String mthodName = ((Method)os[1]).getName();
+						if ("get".equals(mthodName.substring(0, 3))){
+							mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
+						}
+						Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
+					}
+				}
+				sb.append(val+", ");
+			}
+			dataList.add(e);
+			log.debug("Read success: ["+i+"] "+sb.toString());
+		}
+		return dataList;
+	}
+
+	/**
+	 * 获取导入数据列表,470行小于号改为小于等于,用于处理读取行数问题
+	 * @param cls 导入对象类型
+	 * @param groups 导入分组
+	 */
+	public <E> List<E> getDataListNew(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{
+		List<Object[]> annotationList = Lists.newArrayList();
+		// Get annotation field
+		Field[] fs = cls.getDeclaredFields();
+		for (Field f : fs){
+			ExcelField ef = f.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, f});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, f});
+				}
+			}
+		}
+		// Get annotation method
+		Method[] ms = cls.getDeclaredMethods();
+		for (Method m : ms){
+			ExcelField ef = m.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, m});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, m});
+				}
+			}
+		}
+		// Field sorting
+		Collections.sort(annotationList, new Comparator<Object[]>() {
+			public int compare(Object[] o1, Object[] o2) {
+				return new Integer(((ExcelField)o1[0]).sort()).compareTo(
+						new Integer(((ExcelField)o2[0]).sort()));
+			};
+		});
+		//log.debug("Import column count:"+annotationList.size());
+		// Get excel data
+		List<E> dataList = Lists.newArrayList();
+		int a = this.getDataRowNum();
+		int b = this.getLastDataRowNum();
+		for (int i = this.getDataRowNum(); i <= this.sheet.getLastRowNum(); i++) {
+			E e = (E)cls.newInstance();
+			int column = 0;
+			Row row = this.getRow(i);
+			StringBuilder sb = new StringBuilder();
+			for (Object[] os : annotationList){
+				Object val = this.getCellValue(row, column++);
+				if (val != null){
+					ExcelField ef = (ExcelField)os[0];
+					// If is dict type, get dict value
+					if (StringUtils.isNotBlank(ef.dictType())){
+						val = DictUtils.getDictValue(val.toString(), ef.dictType(), "");
+						//log.debug("Dictionary type value: ["+i+","+colunm+"] " + val);
+					}
+					// Get param type and type cast
+					Class<?> valType = Class.class;
+					if (os[1] instanceof Field){
+						valType = ((Field)os[1]).getType();
+					}else if (os[1] instanceof Method){
+						Method method = ((Method)os[1]);
+						if ("get".equals(method.getName().substring(0, 3))){
+							valType = method.getReturnType();
+						}else if("set".equals(method.getName().substring(0, 3))){
+							valType = ((Method)os[1]).getParameterTypes()[0];
+						}
+					}
+					//log.debug("Import value type: ["+i+","+column+"] " + valType);
+					try {
+						//如果导入的java对象,需要在这里自己进行变换。
+						if (valType == String.class){
+							String s = String.valueOf(val.toString());
+							if(StringUtils.endsWith(s, ".0")){
+								val = StringUtils.substringBefore(s, ".0");
+							}else{
+								val = String.valueOf(val.toString());
+							}
+						}else if (valType == Integer.class){
+							val = Double.valueOf(val.toString()).intValue();
+						}else if (valType == Long.class){
+							val = Double.valueOf(val.toString()).longValue();
+						}else if (valType == Double.class){
+							val = Double.valueOf(val.toString());
+						}else if (valType == Float.class){
+							val = Float.valueOf(val.toString());
+						}else if (valType == Date.class){
+							SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
+							val=sdf.parse(val.toString());
+						}else if (valType == User.class){
+							val = UserUtils.getByUserName(val.toString());
+						}else if (valType == Office.class){
+							val = UserUtils.getByOfficeName(val.toString());
+						}else if (valType == Area.class){
+							val = UserUtils.getByAreaName(val.toString());
+						}else{
+							if (ef.fieldType() != Class.class){
+								val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
+							}else{
+								val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
+										"fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
+							}
+						}
+					} catch (Exception ex) {
+						log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());
+						val = null;
+					}
+					// set entity value
+					if (os[1] instanceof Field){
+						Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);
+					}else if (os[1] instanceof Method){
+						String mthodName = ((Method)os[1]).getName();
+						if ("get".equals(mthodName.substring(0, 3))){
+							mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
+						}
+						Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
+					}
+				}
+				sb.append(val+", ");
+			}
+			dataList.add(e);
+			log.debug("Read success: ["+i+"] "+sb.toString());
+		}
+		return dataList;
+	}
+
+//	/**
+//	 * 导入测试
+//	 */
+//	public static void main(String[] args) throws Throwable {
+//		
+//		ImportExcel ei = new ImportExcel("target/export.xlsx", 1);
+//		
+//		for (int i = ei.getDataRowNum(); i < ei.getLastDataRowNum(); i++) {
+//			Row row = ei.getRow(i);
+//			for (int j = 0; j < ei.getLastCellNum(); j++) {
+//				Object val = ei.getCellValue(row, j);
+//				System.out.print(val+", ");
+//			}
+//			System.out.print("\n");
+//		}
+//		
+//	}
+
+}

+ 87 - 3
src/main/java/com/jeeplus/modules/sg/balancedlibrary/materialReportDetails/web/MaterialReportDetailsControllerTest.java

@@ -5,16 +5,15 @@ package com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.web;
 
 import com.google.common.collect.Lists;
 import com.jeeplus.common.json.AjaxJson;
-import com.jeeplus.common.utils.DateUtils;
 import com.jeeplus.common.utils.StringUtils;
 import com.jeeplus.common.utils.excel.ExportExcel;
-import com.jeeplus.common.utils.excel.ImportExcel;
 import com.jeeplus.core.persistence.Page;
 import com.jeeplus.core.web.BaseController;
 import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
 import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.service.LiKuResourcePoolService;
 import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.utils.LiKuUtils;
-import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.utils.OptimalUtil;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.entity.MaterialQuota;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.service.MaterialQuotaService;
 import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.entity.CompareHistory;
 import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.entity.LikuDetail;
 import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.entity.MaterialDetails;
@@ -22,10 +21,21 @@ import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.entity.Mater
 import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.service.CompareHistoryService;
 import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.service.MaterialReportDetailsService;
 import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.utils.AdjustUtil;
+import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.utils.ExcelUtil;
 import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.utils.ExportUtil;
+import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.utils.ImportExcel;
+import com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.service.PreferredMaterialsService;
 import com.jeeplus.modules.sg.balancedlibrary.replaceMaterial.entity.ReplaceMaterial;
 import com.jeeplus.modules.sg.balancedlibrary.replaceMaterial.service.ReplaceMaterialService;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.entity.StandardMaterials;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.service.StandardMaterialsService;
+import com.jeeplus.modules.sg.financial.erpcredit.util.ValidationUtils;
 import com.jeeplus.modules.sg.managementcenter.materialproject.entity.MaterialProject;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.apache.shiro.authz.annotation.Logical;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -37,9 +47,11 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.resource.spi.work.Work;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
+import java.io.*;
 import java.math.BigDecimal;
 import java.util.*;
 
@@ -67,6 +79,15 @@ public class MaterialReportDetailsControllerTest extends BaseController {
     @Autowired
     private CompareHistoryService compareHistoryService;
 
+    @Autowired
+    private PreferredMaterialsService preferredMaterialsService;
+
+    @Autowired
+    private MaterialQuotaService materialQuotaService;
+
+    @Autowired
+    private StandardMaterialsService standardMaterialsService;
+
     @ModelAttribute
     public MaterialReportDetails get(@RequestParam(required = false) String id) {
         MaterialReportDetails entity = null;
@@ -911,4 +932,67 @@ public class MaterialReportDetailsControllerTest extends BaseController {
         return j;
     }
 
+    /**
+     * 下载物资上报明细导入模板 新的直接从模板文件中获取
+     */
+    @ResponseBody
+    @RequestMapping(value = "import/templateNew")
+    public void  importFileTemplateNew(HttpServletResponse response) throws IOException {
+        String fileName = "项目物资需求.xlsx";
+        String path = this.getClass().getResource("/").getPath()+ "freemarker/excelmodel/requiredMaterialModel.xlsx";
+        File file = new File(path);
+        InputStream inputStream = new FileInputStream(file);// 将excel文件转为输入流
+        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);// 创建个workbook,
+        ExportUtil.exportFile(response,fileName,workbook);
+    }
+
+    /**
+     * 对项目需求物资做验证
+     */
+    @ResponseBody
+    @RequestMapping(value = "importVerify")
+    public AjaxJson importFileAndVerify(@RequestParam("file") MultipartFile file, HttpServletResponse response, HttpServletRequest request) throws IOException, InvalidFormatException {
+        AjaxJson j = new AjaxJson();
+        try {
+            ExcelUtil util = new ExcelUtil(file,1,0);
+
+            List<StandardMaterials> standardList = standardMaterialsService.findAllList(new StandardMaterials());
+            List<String> preferredCodes = preferredMaterialsService.findAllCodes();
+            List<MaterialQuota> quotaList = materialQuotaService.findAllList(new MaterialQuota());
+            util.dealVerify(standardList,preferredCodes,quotaList);
+
+            HttpSession session = request.getSession();
+            session.setAttribute(ValidationUtils.REQUIRED_MATERIAL_VERIFY,file.getOriginalFilename());
+            util.saveToServer(session.getId());
+//
+//            ValidationUtils.storeObjToRedis(request,workbook,ValidationUtils.REQUIRED_MATERIAL_VERIFY);
+
+            j.setSuccess(true);
+            j.setMsg("导入成功,马上下载!");
+            return j;
+        } catch (Exception e) {
+            j.setSuccess(false);
+            j.setMsg("导入项目需求物资失败!失败信息:" + e.getMessage());
+        }
+        return j;
+
+
+    }
+
+    @ResponseBody
+    @RequestMapping(value = "exportVerify")
+    public void exportVerify(HttpServletResponse response, HttpServletRequest request) throws IOException, InvalidFormatException {
+//        ExcelUtil util = new ExcelUtil(file,1,0);
+
+//        Workbook workbook = ValidationUtils.getSessionRedisObj(request,ValidationUtils.REQUIRED_MATERIAL_VERIFY,Workbook.class);
+        HttpSession session = request.getSession();
+        String  fileName = (String)session.getAttribute(ValidationUtils.REQUIRED_MATERIAL_VERIFY);
+        ExcelUtil util = new ExcelUtil();
+        util.exportFile(response,fileName,session.getId());
+
+
+
+    }
+
+
 }

+ 78 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/entity/PreferredMaterials.java

@@ -0,0 +1,78 @@
+package com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.entity;
+
+import com.jeeplus.common.utils.excel.annotation.ExcelField;
+import com.jeeplus.core.persistence.DataEntity;
+
+/**
+ * 优选物资Entity
+ * @author enford
+ * @version 1.0
+ */
+public class PreferredMaterials extends DataEntity<PreferredMaterials> {
+
+    private String materialCode;//物料编码
+
+    private String materialDesc;//物料描述
+
+    private String extendCode;//扩展编码
+
+    private String extendDesc;//扩展描述
+
+    private String thirdClassList;//三级清单物料(是否优选)
+
+    private String subclassDesc;//小类描述
+
+    @ExcelField(title = "物料编码", align = 2, sort = 1)
+    public String getMaterialCode() {
+        return materialCode;
+    }
+
+    public void setMaterialCode(String materialCode) {
+        this.materialCode = materialCode;
+    }
+
+    @ExcelField(title = "物料描述", align = 2, sort = 2)
+    public String getMaterialDesc() {
+        return materialDesc;
+    }
+
+    public void setMaterialDesc(String materialDesc) {
+        this.materialDesc = materialDesc;
+    }
+
+    @ExcelField(title = "扩展编码", align = 2, sort = 3)
+    public String getExtendCode() {
+        return extendCode;
+    }
+
+    public void setExtendCode(String extendCode) {
+        this.extendCode = extendCode;
+    }
+
+    @ExcelField(title = "扩展描述", align = 2, sort = 4)
+    public String getExtendDesc() {
+        return extendDesc;
+    }
+
+    public void setExtendDesc(String extendDesc) {
+        this.extendDesc = extendDesc;
+    }
+
+    @ExcelField(title = "三级清单物料", align = 2, sort = 5)
+    public String getThirdClassList() {
+        return thirdClassList;
+    }
+
+    public void setThirdClassList(String thirdClassList) {
+        this.thirdClassList = thirdClassList;
+    }
+
+    @ExcelField(title = "小类描述", align = 2, sort = 6)
+    public String getSubclassDesc() {
+        return subclassDesc;
+    }
+
+    public void setSubclassDesc(String subclassDesc) {
+        this.subclassDesc = subclassDesc;
+    }
+}

+ 39 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/mapper/PreferredMaterialsMapper.java

@@ -0,0 +1,39 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.mapper;
+
+import com.jeeplus.core.persistence.BaseMapper;
+import com.jeeplus.core.persistence.annotation.MyBatisMapper;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.entity.PreferredMaterials;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 优选物料MAPPER接口
+ * @author enford
+ * @version 1.0
+ */
+@MyBatisMapper
+public interface PreferredMaterialsMapper extends BaseMapper<PreferredMaterials> {
+    /**
+     *
+     * @param list 数据列表
+     * */
+    void insertList(@Param("list") List<PreferredMaterials> list);
+
+    /**
+     * 清空优选物料数据
+     */
+    void clearPreferredMaterials();
+
+    /**
+     * 根据id批量删除
+     * @param list
+     */
+    void delList(@Param("list") List<String> list);
+
+    List<String> findAllCodes();
+}

+ 115 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/mapper/xml/PreferredMaterialsMapper.xml

@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.mapper.PreferredMaterialsMapper">
+	<sql id="resourceColumns">
+		a.id AS "id",
+		a.create_by AS "createBy.id",
+		a.create_date AS "createDate",
+		a.update_by AS "updateBy.id",
+		a.update_date AS "updateDate",
+		a.material_code AS "materialCode",
+		a.material_desc AS "materialDesc",
+		a.extend_code AS "extendCode",
+		a.extend_desc AS "extendDesc",
+		a.third_class_list AS "thirdClassList",
+		a.subclass_desc AS "subclassDesc"
+	</sql>
+
+	<sql id="leftJoins">
+		LEFT JOIN sys_office office ON office.id = a.office_id
+		LEFT JOIN sys_user tuser ON tuser.id = a.user_id
+	</sql>
+
+
+	<select id="get" resultType="PreferredMaterials" >
+		SELECT
+			<include refid="resourceColumns"/>
+		FROM bla_preferred_materials a
+		WHERE a.id = #{id}
+	</select>
+
+	<select id="findList" resultType="PreferredMaterials" >
+		SELECT
+			<include refid="resourceColumns"/>
+		FROM bla_preferred_materials a
+		<where>
+			a.del_flag = #{DEL_FLAG_NORMAL}
+			${dataScope}
+			<if test="materialCode != null and materialCode != ''">
+				AND a.material_code = #{materialCode}
+			</if>
+		</where>
+		<choose>
+			<when test="page !=null and page.orderBy != null and page.orderBy != ''">
+				ORDER BY ${page.orderBy}
+			</when>
+			<otherwise>
+				ORDER BY a.material_code asc
+			</otherwise>
+		</choose>
+	</select>
+
+	<select id="findAllCodes" resultType="String" >
+		SELECT
+			a.material_code
+		FROM bla_preferred_materials a
+		<where>
+			a.del_flag = #{DEL_FLAG_NORMAL}
+			${dataScope}
+		</where>
+	</select>
+
+	
+	<insert id="insertList">
+		insert into bla_preferred_materials(
+		id,
+		create_by,
+		create_date,
+		update_by,
+		update_date,
+		del_flag,
+		material_code,
+		material_desc,
+		extend_code,
+		extend_desc,
+		third_class_list,
+		subclass_desc
+		)VALUES
+		<foreach collection="list" item="item" index="index" separator=",">
+			(
+			#{item.id},
+			#{item.createBy.id},
+			#{item.createDate},
+			#{item.updateBy.id},
+			#{item.updateDate},
+			#{item.delFlag},
+			#{item.materialCode},
+			#{item.materialDesc},
+			#{item.extendCode},
+			#{item.extendDesc},
+			#{item.thirdClassList},
+			#{item.subclassDesc}
+			)
+		</foreach>
+	</insert>
+
+	<delete id="clearPreferredMaterials">
+		truncate table bla_preferred_materials
+	</delete>
+
+
+
+	<!--物理删除-->
+	<update id="delList">
+		DELETE FROM bla_preferred_materials
+		WHERE id in
+		(
+		<foreach collection="list" item="item" index="index" separator=",">
+			#{item}
+		</foreach>
+		)
+	</update>
+
+
+
+</mapper>

+ 87 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/service/PreferredMaterialsService.java

@@ -0,0 +1,87 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.service;
+
+import com.jeeplus.core.persistence.Page;
+import com.jeeplus.core.service.CrudService;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.mapper.LiKuResourcePoolMapper;
+import com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.entity.PreferredMaterials;
+import com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.mapper.PreferredMaterialsMapper;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.entity.StandardMaterials;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * 优选物料Service
+ * @author enford
+ * @version 1.0
+ */
+@Service
+@Transactional(readOnly = true)
+public class PreferredMaterialsService extends CrudService<PreferredMaterialsMapper, PreferredMaterials> {
+
+	@Override
+	public PreferredMaterials get(String id) {
+		return super.get(id);
+	}
+
+	@Override
+	public List<PreferredMaterials> findList(PreferredMaterials entity) {
+		return super.findList(entity);
+	}
+
+	@Override
+	public Page<PreferredMaterials> findPage(Page<PreferredMaterials> page, PreferredMaterials entity) {
+		return super.findPage(page, entity);
+	}
+
+
+	//数据库全量替换
+	@Transactional(readOnly = false)
+	public void fullReplace(List<PreferredMaterials> list) {
+		mapper.clearPreferredMaterials();
+		for (PreferredMaterials li :
+				list) {
+			li.preInsert();
+		}
+		int eachSize = 5000;//每次往数据库插入的数据量
+		if(list.size()>eachSize) {
+			int begin = 0;
+			int end = eachSize;
+			while (true) {
+				mapper.insertList(list.subList(begin, end));
+				if (end == list.size()) {
+					break;
+				}
+				begin = end;
+				if ((end + eachSize) > list.size()) {
+					end = list.size();
+				} else {
+					end = end + eachSize;
+				}
+			}
+
+		}else{
+			mapper.insertList(list);
+		}
+	}
+
+
+	/**
+	 * 清空优选物料数据
+	 */
+	@Transactional(readOnly = false)
+	public void deleteList(List<String> list) {
+		mapper.delList(list);
+	}
+
+
+	public List<String> findAllCodes(){
+		return mapper.findAllCodes();
+	}
+
+}

+ 393 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/utils/ImportUtil.java

@@ -0,0 +1,393 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.utils;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.utils.Reflections;
+import com.jeeplus.common.utils.excel.annotation.ExcelField;
+import com.jeeplus.modules.sys.entity.Area;
+import com.jeeplus.modules.sys.entity.Office;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.DictUtils;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 导入Excel文件(支持“XLS”和“XLSX”格式)
+ * @author jeeplus
+ * @version 2016-03-10
+ */
+public class ImportUtil {
+
+	private static Logger log = LoggerFactory.getLogger(ImportUtil.class);
+
+	/**
+	 * 工作薄对象
+	 */
+	private Workbook wb;
+
+	/**
+	 * 工作表对象
+	 */
+	private Sheet sheet;
+
+	/**
+	 * 标题行号
+	 */
+	private int headerNum;
+
+	/**
+	 * 构造函数
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(String fileName, int headerNum)
+			throws InvalidFormatException, IOException {
+		this(new File(fileName), headerNum);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象,读取第一个工作表
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(File file, int headerNum)
+			throws InvalidFormatException, IOException {
+		this(file, headerNum, 0);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(String fileName, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(new File(fileName), headerNum, sheetIndex);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(File file, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(file.getName(), new FileInputStream(file), headerNum, sheetIndex);
+	}
+
+	/**
+	 * 构造函数
+	 * @param file 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(MultipartFile multipartFile, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex);
+	}
+
+	/**
+	 * 构造函数
+	 * @param path 导入文件对象
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportUtil(String fileName, InputStream is, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		if (StringUtils.isBlank(fileName)){
+			throw new RuntimeException("导入文档为空!");
+		}else if(fileName.toLowerCase().endsWith("xls")){    
+			this.wb = new HSSFWorkbook(is);    
+        }else if(fileName.toLowerCase().endsWith("xlsx")){  
+        	this.wb = new XSSFWorkbook(is);
+        }else{  
+        	throw new RuntimeException("文档格式不正确!");
+        }  
+		if (this.wb.getNumberOfSheets()<sheetIndex){
+			throw new RuntimeException("文档中没有工作表!");
+		}
+		this.sheet = this.wb.getSheetAt(sheetIndex);
+		this.headerNum = headerNum;
+		log.debug("Initialize success.");
+	}
+	
+	/**
+	 * 获取行对象
+	 * @param rownum
+	 * @return
+	 */
+	public Row getRow(int rownum){
+		return this.sheet.getRow(rownum);
+	}
+
+	/**
+	 * 获取数据行号
+	 * @return
+	 */
+	public int getDataRowNum(){
+		return headerNum+1;
+	}
+	
+	/**
+	 * 获取最后一个数据行号
+	 * @return
+	 */
+	public int getLastDataRowNum(){
+//		return this.sheet.getLastRowNum()+headerNum;
+		return this.sheet.getLastRowNum()+1;
+	}
+	
+	/**
+	 * 获取最后一个列号
+	 * @return
+	 */
+	public int getLastCellNum(){
+		return this.getRow(headerNum).getLastCellNum();
+	}
+	
+	/**
+	 * 获取单元格值
+	 * @param row 获取的行
+	 * @param column 获取单元格列号
+	 * @return 单元格值
+	 */
+	public Object getCellValue(Row row, int column) {
+		Object val = "";
+		try {
+			Cell cell = row.getCell(column);
+			if (cell != null) {
+				if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+					// val = cell.getNumericCellValue();
+					// 当excel 中的数据为数值或日期是需要特殊处理
+					if (HSSFDateUtil.isCellDateFormatted(cell)) {
+						double d = cell.getNumericCellValue();
+						Date date = HSSFDateUtil.getJavaDate(d);
+						SimpleDateFormat dformat = new SimpleDateFormat(
+								"yyyy-MM-dd");
+						val = dformat.format(date);
+					} else {
+						NumberFormat nf = NumberFormat.getInstance();
+						nf.setGroupingUsed(false);// true时的格式:1,234,567,890
+						val = nf.format(cell.getNumericCellValue());// 数值类型的数据为double,所以需要转换一下
+					}
+				} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
+					val = cell.getStringCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
+					val = cell.getCellFormula();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
+					val = cell.getBooleanCellValue();
+				} else if (cell.getCellType() == Cell.CELL_TYPE_ERROR) {
+					val = cell.getErrorCellValue();
+				}
+			}
+		} catch (Exception e) {
+			return val;
+		}
+		return val;
+	}
+	
+	/**
+	 * 获取导入数据列表
+	 * @param cls 导入对象类型
+	 * @param groups 导入分组
+	 */
+	public <E> List<E> getDataList(Class<E> cls, int... groups) throws InstantiationException, IllegalAccessException{
+		List<Object[]> annotationList = Lists.newArrayList();
+		// Get annotation field 
+		Field[] fs = cls.getDeclaredFields();
+		for (Field f : fs){
+			ExcelField ef = f.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, f});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, f});
+				}
+			}
+		}
+		// Get annotation method
+		Method[] ms = cls.getDeclaredMethods();
+		for (Method m : ms){
+			ExcelField ef = m.getAnnotation(ExcelField.class);
+			if (ef != null && (ef.type()==0 || ef.type()==2)){
+				if (groups!=null && groups.length>0){
+					boolean inGroup = false;
+					for (int g : groups){
+						if (inGroup){
+							break;
+						}
+						for (int efg : ef.groups()){
+							if (g == efg){
+								inGroup = true;
+								annotationList.add(new Object[]{ef, m});
+								break;
+							}
+						}
+					}
+				}else{
+					annotationList.add(new Object[]{ef, m});
+				}
+			}
+		}
+		// Field sorting
+		Collections.sort(annotationList, new Comparator<Object[]>() {
+			public int compare(Object[] o1, Object[] o2) {
+				return new Integer(((ExcelField)o1[0]).sort()).compareTo(
+						new Integer(((ExcelField)o2[0]).sort()));
+			};
+		});
+		//log.debug("Import column count:"+annotationList.size());
+		// Get excel data
+		List<E> dataList = Lists.newArrayList();
+		for (int i = this.getDataRowNum(); i < this.getLastDataRowNum(); i++) {
+			E e = (E)cls.newInstance();
+			int column = 0;
+			Row row = this.getRow(i);
+			StringBuilder sb = new StringBuilder();
+			for (Object[] os : annotationList){
+				Object val = this.getCellValue(row, column++);
+				if (val != null){
+					ExcelField ef = (ExcelField)os[0];
+					// If is dict type, get dict value
+					if (StringUtils.isNotBlank(ef.dictType())){
+						val = DictUtils.getDictValue(val.toString(), ef.dictType(), "");
+						//log.debug("Dictionary type value: ["+i+","+colunm+"] " + val);
+					}
+					// Get param type and type cast
+					Class<?> valType = Class.class;
+					if (os[1] instanceof Field){
+						valType = ((Field)os[1]).getType();
+					}else if (os[1] instanceof Method){
+						Method method = ((Method)os[1]);
+						if ("get".equals(method.getName().substring(0, 3))){
+							valType = method.getReturnType();
+						}else if("set".equals(method.getName().substring(0, 3))){
+							valType = ((Method)os[1]).getParameterTypes()[0];
+						}
+					}
+					//log.debug("Import value type: ["+i+","+column+"] " + valType);
+					try {
+						//如果导入的java对象,需要在这里自己进行变换。
+						if (valType == String.class){
+							String s = String.valueOf(val.toString());
+							if(StringUtils.endsWith(s, ".0")){
+								val = StringUtils.substringBefore(s, ".0");
+							}else{
+								val = String.valueOf(val.toString());
+							}
+						}else if (valType == Integer.class){
+							val = Double.valueOf(val.toString()).intValue();
+						}else if (valType == Long.class){
+							val = Double.valueOf(val.toString()).longValue();
+						}else if (valType == Double.class){
+							val = Double.valueOf(val.toString());
+						}else if (valType == Float.class){
+							val = Float.valueOf(val.toString());
+						}else if (valType == Date.class){
+							SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
+							val=sdf.parse(val.toString()); 
+						}else if (valType == User.class){
+							val = UserUtils.getByUserName(val.toString());
+						}else if (valType == Office.class){
+							val = UserUtils.getByOfficeName(val.toString());
+						}else if (valType == Area.class){
+							val = UserUtils.getByAreaName(val.toString());
+						}else{
+							if (ef.fieldType() != Class.class){
+								val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
+							}else{
+								val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(), 
+										"fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
+							}
+						}
+					} catch (Exception ex) {
+						log.info("Get cell value ["+i+","+column+"] error: " + ex.toString());
+						val = null;
+					}
+					// set entity value
+					if (os[1] instanceof Field){
+						Reflections.invokeSetter(e, ((Field)os[1]).getName(), val);
+					}else if (os[1] instanceof Method){
+						String mthodName = ((Method)os[1]).getName();
+						if ("get".equals(mthodName.substring(0, 3))){
+							mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
+						}
+						Reflections.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
+					}
+				}
+				sb.append(val+", ");
+			}
+			dataList.add(e);
+			log.debug("Read success: ["+i+"] "+sb.toString());
+		}
+		return dataList;
+	}
+
+//	/**
+//	 * 导入测试
+//	 */
+//	public static void main(String[] args) throws Throwable {
+//		
+//		ImportExcel ei = new ImportExcel("target/export.xlsx", 1);
+//		
+//		for (int i = ei.getDataRowNum(); i < ei.getLastDataRowNum(); i++) {
+//			Row row = ei.getRow(i);
+//			for (int j = 0; j < ei.getLastCellNum(); j++) {
+//				Object val = ei.getCellValue(row, j);
+//				System.out.print(val+", ");
+//			}
+//			System.out.print("\n");
+//		}
+//		
+//	}
+}

+ 76 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/utils/LiKuUtils.java

@@ -0,0 +1,76 @@
+package com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.utils;
+
+public class LiKuUtils {
+    /**
+     * 判断是否是段长数据
+     * YES-是 NO-不是
+     */
+    public static final Integer YES = 1;
+    public static final Integer NO = 0;
+
+    /**
+     * 地区编号值
+     * HLA2-市公司 HLD1-扬中 HLB1-丹阳 句容-HLC1 未知地区-NO_PLACE
+     */
+    public static final String HLA2 = "HLA2";
+    public static final String HLD1 = "HLD1";
+    public static final String HLB1 = "HLB1";
+    public static final String HLC1 = "HLC1";
+
+    /**
+     * 上报地区所属值
+     */
+    public static final String BB_PLACE = "市公司";
+    public static final String YZ_PLACE = "扬中";
+    public static final String DY_PLACE = "丹阳";
+    public static final String JR_PLACE = "句容";
+
+    /**
+     * 判断库存地所属标记
+     * BB_FLAG-市公司 YZ_FLAG-扬中 DY_FLAG-丹阳 JR_FLAG-句容 NO_FLAG-未知地区
+     * */
+    public static final Integer BB_FLAG = 1;
+    public static final Integer YZ_FLAG = 2;
+    public static final Integer DY_FLAG = 3;
+    public static final Integer JR_FLAG = 4;
+    public static final Integer NO_FLAG = 0;
+
+    /**
+     * 判断单位
+     * */
+    public static final String METER = "米";
+    public static final String Kilometer = "千米";
+
+
+    /**
+     * 根据单位判断物资是否为段长
+     * @param unit
+     * @return
+     */
+    public static Integer isTheUnitMeter(String unit) {
+        if (METER.equals(unit) || Kilometer.equals(unit)) {
+            return YES;
+        } else {
+            return NO;
+        }
+    }
+
+    /**
+     * 判断物资或利库所属地区
+     * @param area
+     * @return
+     */
+    public static Integer judgmentArea(String area) {
+        if (HLA2.equals(area) || area.contains(BB_PLACE)) {
+            return BB_FLAG;
+        } else if (HLD1.equals(area) || area.contains(YZ_PLACE)) {
+            return YZ_FLAG;
+        } else if (HLB1.equals(area) || area.contains(DY_PLACE)) {
+            return DY_FLAG;
+        } else if (HLC1.equals(area) || area.contains(JR_PLACE)) {
+            return JR_FLAG;
+        } else {
+            return NO_FLAG;
+        }
+    }
+}

+ 177 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/utils/OptimalUtil.java

@@ -0,0 +1,177 @@
+package com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.utils;
+
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.materialReportDetails.entity.MaterialReportDetails;
+import com.jeeplus.modules.sys.utils.DictUtils;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+public class OptimalUtil {
+    //是否有“元素组合的和”与“待比对值”相同的情况,true为有
+    private boolean getEqual = false;
+    //所有可能的元素组合列表
+    private List<List<MaterialReportDetails>> result = new ArrayList<>();
+    //由物资上报方开始匹配时所有可能的元素组合列表
+    private List<List<LiKuResourcePool>> resultReverse = new ArrayList<>();
+    //最大浪费量
+    private BigDecimal maxiNun = new BigDecimal(DictUtils.getDictValue("maxWaste", "maximum_waste", ""));
+    //由物资上报方开始匹配时最大差额
+    private BigDecimal maxiNunReverse = new BigDecimal(DictUtils.getDictValue("maxWasteReverse", "maximum_waste", ""));
+
+    /**
+     *
+     * @param total 待比对的值
+     * @param elements  所有元素集合
+     * @return
+     */
+    public List<MaterialReportDetails> getOptimal(double total, List<MaterialReportDetails> elements){
+        //list降序排列
+        Collections.sort(elements, Comparator.comparing(MaterialReportDetails::getLengthOfMetre));
+        Collections.reverse(elements);
+        solve(0,0,new ArrayList<>(),total,elements);
+
+        //找到差值最小组合返回
+        List<MaterialReportDetails> returnList = new ArrayList<>();
+        BigDecimal currMax = BigDecimal.valueOf(0.0);//当前总和最大
+        for (List<MaterialReportDetails> detailsList :result) {
+            BigDecimal listSum = BigDecimal.valueOf(0.0);
+            for (MaterialReportDetails details :detailsList) {
+                listSum = listSum.add(BigDecimal.valueOf(details.getLengthOfMetre()));
+            }
+            if (listSum.compareTo(currMax) > 0) {
+                currMax = listSum;
+                returnList = detailsList;
+//                returnList.clear();
+//                returnList.addAll(detailsList);
+            }
+        }
+
+
+        return returnList;
+    }
+
+    /**
+     *
+     * @param total 待比对的值
+     * @param elements  利库所有元素集合
+     * @return
+     */
+    public List<LiKuResourcePool> getOptimalReverse(double total, List<LiKuResourcePool> elements){
+        //list降序排列
+        Collections.sort(elements, Comparator.comparing(LiKuResourcePool::getLengthOfMetre));
+        solveReverse(0,0,new ArrayList<>(),total,elements);
+
+        //找到差值最小组合返回
+        List<LiKuResourcePool> returnList = new ArrayList<>();
+        BigDecimal currMin = BigDecimal.valueOf(total).add(maxiNunReverse);//当前最小值
+        for (List<LiKuResourcePool> poolList : resultReverse) {
+            BigDecimal listSum = BigDecimal.valueOf(0.0);
+            for (LiKuResourcePool pool : poolList) {
+                listSum = listSum.add(BigDecimal.valueOf(pool.getLengthOfMetre()));
+            }
+            if (listSum.compareTo(currMin) < 0) {
+                currMin = listSum;
+                returnList = poolList;
+//                returnList.clear();
+//                returnList.addAll(detailsList);
+            }
+        }
+
+
+        return returnList;
+    }
+
+    /**
+     *
+     * @param index 当前集合下标
+     * @param sum   当前组合元素和
+     * @param curr  当前组合元素集合
+     * @param total 待比对的值
+     * @param elements 所有元素集合
+     */
+    public void solve(int index, double sum, List<MaterialReportDetails> curr, double total, List<MaterialReportDetails> elements ){
+        //如果找到元素组合的和与待比对值一样,则不往下继续查找
+        if(getEqual == true){
+            return;
+        }
+        //走到这一步,所有最后一个元素也参考过(可能加入组合也可能不加入),最终还是组合值小于待比对值。则放入到result中
+        if(index == elements.size()){
+            BigDecimal allSum = BigDecimal.valueOf(sum);
+            BigDecimal allTotal = BigDecimal.valueOf(total);
+            BigDecimal subtract = allTotal.subtract(allSum).setScale(2, BigDecimal.ROUND_HALF_UP);
+            if (subtract.compareTo(maxiNun) <= 0) {
+                result.add(curr);
+            }
+            return;
+        }
+        MaterialReportDetails next = elements.get(index);
+        //处理单位不同,所有都以米作为单位计算
+        Double nextNeed = next.getLengthOfMetre();
+
+        index++;
+        //如果将当前值加上已有元素组合的值等于待比对值,得到结果
+        if((sum+nextNeed)==total){
+            curr.add(next);
+            result = new ArrayList<>();
+            result.add(curr);
+            getEqual = true;
+        //如果将当前值加上已有元素组合的值大于待比对值,则不考虑这种组合的后续可能性
+        }else if((sum+nextNeed) > total){
+            solve(index,sum,curr,total,elements);
+        }else if((sum+nextNeed) < total){
+            List newCurr = new ArrayList(curr);
+            newCurr.add(next);
+            solve(index,sum+nextNeed,newCurr,total,elements);
+//            solve(index,sum,curr,total,elements);
+        }
+    }
+
+    /**
+     *
+     * @param index 当前集合下标
+     * @param sum   当前组合元素和
+     * @param curr  当前组合元素集合
+     * @param total 待比对的值
+     * @param elements 所有元素集合
+     */
+    public void solveReverse(int index, double sum, List<LiKuResourcePool> curr, double total, List<LiKuResourcePool> elements ){
+        //如果找到元素组合的和与待比对值一样,则不往下继续查找
+        if(getEqual == true){
+            return;
+        }
+        //走到这一步,说明总和比total少,不放入
+        if(index == elements.size()){
+            return;
+        }
+        LiKuResourcePool next = elements.get(index);
+        //处理单位不同,所有都以米作为单位计算
+        Double cableLength = next.getLengthOfMetre();
+
+        index++;
+        //如果将当前值加上已有元素组合的值等于待比对值,得到结果
+        if((sum+cableLength)==total){
+            curr.add(next);
+            resultReverse = new ArrayList<>();
+            resultReverse.add(curr);
+            getEqual = true;
+            //如果将当前值加上已有元素组合的值大于待比对值,则不考虑这种组合的后续可能性
+        }else if((sum+cableLength) > total){
+            BigDecimal bigSum = BigDecimal.valueOf(sum);
+            BigDecimal bigLength = BigDecimal.valueOf(cableLength);
+            BigDecimal bigTotal = BigDecimal.valueOf(total);
+            BigDecimal subtract = bigSum.add(bigLength).subtract(bigTotal).setScale(2,BigDecimal.ROUND_HALF_UP);
+            if(subtract.compareTo(maxiNunReverse)<=0){
+                curr.add(next);
+                resultReverse.add(curr);
+            }
+            //由于资源池是由小到大排序,所以后面的一定不会比这条更接近最优解,则下面的代码不需要
+//            solveReverse(index,sum,curr,total,elements);
+        }else if((sum+cableLength) < total){
+            List newCurr = new ArrayList(curr);
+            newCurr.add(next);
+            solveReverse(index,sum+cableLength,newCurr,total,elements);
+            solveReverse(index,sum,curr,total,elements);
+        }
+    }
+}

+ 171 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/preferredMaterials/web/PreferredMaterialsController.java

@@ -0,0 +1,171 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.web;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.json.AjaxJson;
+import com.jeeplus.common.utils.DateUtils;
+import com.jeeplus.common.utils.StringUtils;
+import com.jeeplus.common.utils.excel.ExportExcel;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.utils.ImportUtil;
+import com.jeeplus.core.persistence.Page;
+import com.jeeplus.core.web.BaseController;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.service.LiKuResourcePoolService;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.utils.LiKuUtils;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.entity.MaterialQuota;
+import com.jeeplus.modules.sg.balancedlibrary.materialQuota.service.MaterialQuotaService;
+import com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.entity.PreferredMaterials;
+import com.jeeplus.modules.sg.balancedlibrary.preferredMaterials.service.PreferredMaterialsService;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.shiro.authz.annotation.Logical;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.ConstraintViolationException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 优选物料Controller
+ * @author lgf
+ * @version 2018-06-12
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/preferredMaterials")
+public class PreferredMaterialsController extends BaseController {
+
+	@Autowired
+	private PreferredMaterialsService service;
+
+
+
+	@ModelAttribute
+	public PreferredMaterials get(@RequestParam(required=false) String id) {
+		PreferredMaterials entity = null;
+		if (StringUtils.isNotBlank(id)){
+			entity = service.get(id);
+		}
+		if (entity == null){
+			entity = new PreferredMaterials();
+		}
+		return entity;
+	}
+	
+	/**
+	 * 优选物料列表页面
+	 */
+	@RequiresPermissions("sg:balancedlibrary:preferredMaterials:list")
+	@RequestMapping(value = "list")
+	public String list(PreferredMaterials entity, Model model) {
+		model.addAttribute("entity", entity);
+		return "modules/sg/balancedlibrary/preferredMaterials/preferredMaterialsList";
+	}
+	
+		/**
+	 * 优选物料列表数据
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:preferredMaterials:list")
+	@RequestMapping(value = "data")
+	public Map<String, Object> data(PreferredMaterials entity, HttpServletRequest request, HttpServletResponse response, Model model) {
+		Page<PreferredMaterials> page = service.findPage(new Page<PreferredMaterials>(request, response), entity);
+		return getBootstrapData(page);
+	}
+
+
+	/**
+	 * 批量删除优选物料
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:preferredMaterials:del")
+	@RequestMapping(value = "deleteAll")
+	public AjaxJson deleteAll(String ids) {
+		AjaxJson j = new AjaxJson();
+		String idArr[] =ids.split(",");
+		List<String> idList = Arrays.asList(idArr);
+		service.deleteList(idList);
+		j.setMsg("删除优选物料成功");
+		return j;
+	}
+	
+	/**
+	 * 导出excel文件
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:preferredMaterials:export")
+    @RequestMapping(value = "export")
+    public AjaxJson exportFile(PreferredMaterials entity, HttpServletRequest request, HttpServletResponse response) {
+		AjaxJson j = new AjaxJson();
+		try {
+            String fileName = "优选物料表"+DateUtils.getDate("yyyyMMddHHmmss")+".xlsx";
+            Page<PreferredMaterials> page = service.findPage(new Page<PreferredMaterials>(request, response, -1), entity);
+    		new ExportExcel("", PreferredMaterials.class).setDataList(page.getList()).write(response, fileName).dispose();
+    		j.setSuccess(true);
+    		j.setMsg("导出成功!");
+    		return j;
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg("导出优选物料表失败!失败信息:"+e.getMessage());
+		}
+			return j;
+    }
+
+	/**
+	 * 优选物料-导入Excel数据
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:preferredMaterials:import")
+    @RequestMapping(value = "import")
+   	public AjaxJson importFile(@RequestParam("file")MultipartFile file, HttpServletResponse response, HttpServletRequest request) {
+		AjaxJson j = new AjaxJson();
+		try {
+			ImportUtil ei = new ImportUtil(file,0,0);
+			List<PreferredMaterials> list = ei.getDataList(PreferredMaterials.class);
+			if (list.size() > 0) {
+				//优选物资每次重新导入数据,将原有数据清空
+				service.fullReplace(list);
+				j.setMsg("已成功导入 " + list.size() + " 条优选物料记录");
+			}
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg("导入优选物料失败!失败信息:"+e.getMessage());
+		}
+		return j;
+    }
+
+
+
+	/**
+	 * 下载导入优选物料数据模板
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:preferredMaterials:import")
+    @RequestMapping(value = "import/template")
+     public AjaxJson importFileTemplate(HttpServletResponse response) {
+		AjaxJson j = new AjaxJson();
+		try {
+            String fileName = "优选物料数据导入模板.xlsx";
+    		List<PreferredMaterials> list = Lists.newArrayList();
+    		new ExportExcel("", PreferredMaterials.class, 1).setDataList(list).write(response, fileName).dispose();
+    		return null;
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg( "导入模板下载失败!失败信息:"+e.getMessage());
+		}
+		return j;
+    }
+
+}

+ 50 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/entity/StandardMaterials.java

@@ -0,0 +1,50 @@
+package com.jeeplus.modules.sg.balancedlibrary.standardMaterials.entity;
+
+import com.jeeplus.common.utils.excel.annotation.ExcelField;
+import com.jeeplus.core.persistence.DataEntity;
+
+/**
+ * 标准物资Entity
+ * @author enford
+ * @version 1.0
+ */
+public class StandardMaterials extends DataEntity<StandardMaterials> {
+
+    //物料编码
+    private String materialCode;
+
+    //物料描述
+    private String materialDesc;
+
+    //采购标准标识
+    private String purchaseStandardId;
+
+    @ExcelField(title = "物料编码", align = 2, sort = 1)
+    public String getMaterialCode() {
+        return materialCode;
+    }
+
+    public void setMaterialCode(String materialCode) {
+        this.materialCode = materialCode;
+    }
+
+    @ExcelField(title = "物料描述", align = 2, sort = 2)
+    public String getMaterialDesc() {
+        return materialDesc;
+    }
+
+    public void setMaterialDesc(String materialDesc) {
+        this.materialDesc = materialDesc;
+    }
+
+    @ExcelField(title = "采购标准标识", align = 2, sort = 3)
+    public String getPurchaseStandardId() {
+        return purchaseStandardId;
+    }
+
+    public void setPurchaseStandardId(String purchaseStandardId) {
+        this.purchaseStandardId = purchaseStandardId;
+    }
+
+
+}

+ 40 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/mapper/StandardMaterialsMapper.java

@@ -0,0 +1,40 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.standardMaterials.mapper;
+
+import com.jeeplus.core.persistence.BaseMapper;
+import com.jeeplus.core.persistence.annotation.MyBatisMapper;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.entity.StandardMaterials;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 标准物资MAPPER接口
+ * @author enford
+ * @version 1.0
+ */
+@MyBatisMapper
+public interface StandardMaterialsMapper extends BaseMapper<StandardMaterials> {
+    /**
+     *
+     * @param list 数据列表
+     * */
+    void insertList(@Param("list") List<StandardMaterials> list);
+
+    /**
+     * 清空利库资源池数据
+     */
+    void clearStandardMaterials();
+
+    /**
+     * 根据id批量删除
+     * @param list
+     */
+    void delList(@Param("list") List<String> list);
+
+
+
+}

+ 100 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/mapper/xml/StandardMaterialsMapper.xml

@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jeeplus.modules.sg.balancedlibrary.standardMaterials.mapper.StandardMaterialsMapper">
+	<sql id="resourceColumns">
+		a.material_code AS "materialCode",
+		a.material_desc AS "materialDesc",
+		a.purchase_standard_id AS "purchaseStandardId",
+		a.id AS "id",
+		a.create_by AS "createBy.id",
+		a.create_date AS "createDate",
+		a.update_by AS "updateBy.id",
+		a.update_date AS "updateDate"
+	</sql>
+
+
+	<select id="get" resultType="StandardMaterials" >
+		SELECT
+			<include refid="resourceColumns"/>
+		FROM bla_standard_materials a
+		WHERE a.id = #{id}
+	</select>
+
+	<select id="findList" resultType="StandardMaterials" >
+		SELECT
+			<include refid="resourceColumns"/>
+		FROM bla_standard_materials a
+		<where>
+			a.del_flag = #{DEL_FLAG_NORMAL}
+			${dataScope}
+			<if test="materialCode != null and materialCode != ''">
+				AND a.material_code = #{materialCode}
+			</if>
+		</where>
+		<choose>
+			<when test="page !=null and page.orderBy != null and page.orderBy != ''">
+				ORDER BY ${page.orderBy}
+			</when>
+			<otherwise>
+				ORDER BY a.material_code asc
+			</otherwise>
+		</choose>
+	</select>
+
+	<select id="findAllList" resultType="StandardMaterials" >
+		SELECT
+			a.material_code AS "materialCode",
+			a.purchase_standard_id AS "purchaseStandardId"
+		FROM bla_standard_materials a
+		<where>
+			a.del_flag = #{DEL_FLAG_NORMAL}
+			${dataScope}
+		</where>
+	</select>
+
+
+
+	<insert id="insertList">
+		insert into bla_standard_materials(
+		id,
+		material_code,
+		material_desc,
+		purchase_standard_id,
+		create_by,
+		create_date,
+		update_by,
+		update_date,
+		del_flag
+		)VALUES
+		<foreach collection="list" item="item" index="index" separator=",">
+			(
+			#{item.id},
+			#{item.materialCode},
+			#{item.materialDesc},
+			#{item.purchaseStandardId},
+			#{item.createBy.id},
+			#{item.createDate},
+			#{item.updateBy.id},
+			#{item.updateDate},
+			#{item.delFlag}
+			)
+		</foreach>
+	</insert>
+
+	<delete id="clearStandardMaterials">
+		truncate table bla_standard_materials
+	</delete>
+
+	<!--物理删除-->
+	<update id="delList">
+		DELETE FROM bla_standard_materials
+		WHERE id in
+		(
+		<foreach collection="list" item="item" index="index" separator=",">
+			#{item}
+		</foreach>
+		)
+	</update>
+
+
+</mapper>

+ 83 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/service/StandardMaterialsService.java

@@ -0,0 +1,83 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.standardMaterials.service;
+
+import com.jeeplus.core.persistence.Page;
+import com.jeeplus.core.service.CrudService;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.mapper.LiKuResourcePoolMapper;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.entity.StandardMaterials;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.mapper.StandardMaterialsMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * 标准物资Service
+ * @author enford
+ * @version 1.0
+ */
+@Service
+@Transactional(readOnly = true)
+public class StandardMaterialsService extends CrudService<StandardMaterialsMapper, StandardMaterials> {
+
+	@Override
+	public StandardMaterials get(String id) {
+		return super.get(id);
+	}
+
+	@Override
+	public List<StandardMaterials> findList(StandardMaterials entity) {
+		return super.findList(entity);
+	}
+
+	@Override
+	public Page<StandardMaterials> findPage(Page<StandardMaterials> page, StandardMaterials entity) {
+		return super.findPage(page, entity);
+	}
+
+
+	//
+	@Transactional(readOnly = false)
+	public void fullReplace(List<StandardMaterials> list) {
+		mapper.clearStandardMaterials();
+		for (StandardMaterials li :
+				list) {
+			li.preInsert();
+		}
+		int eachSize = 10000;//每次往数据库插入的数据量
+		if(list.size()>eachSize) {
+			int begin = 0;
+			int end = eachSize;
+			while (true) {
+				mapper.insertList(list.subList(begin, end));
+				if (end == list.size()) {
+					break;
+				}
+				begin = end;
+				if ((end + eachSize) > list.size()) {
+					end = list.size();
+				} else {
+					end = end + eachSize;
+				}
+			}
+
+		}else{
+			mapper.insertList(list);
+		}
+	}
+
+
+	/**
+	 * 清空利库资源池数据
+	 */
+	@Transactional(readOnly = false)
+	public void deleteList(List<String> list) {
+		mapper.delList(list);
+	}
+
+
+
+}

+ 175 - 0
src/main/java/com/jeeplus/modules/sg/balancedlibrary/standardMaterials/web/StandardMaterialsController.java

@@ -0,0 +1,175 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.balancedlibrary.standardMaterials.web;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.json.AjaxJson;
+import com.jeeplus.common.utils.DateUtils;
+import com.jeeplus.common.utils.StringUtils;
+import com.jeeplus.common.utils.excel.ExportExcel;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.utils.ImportUtil;
+import com.jeeplus.core.persistence.Page;
+import com.jeeplus.core.web.BaseController;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.entity.LiKuResourcePool;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.service.LiKuResourcePoolService;
+import com.jeeplus.modules.sg.balancedlibrary.liKuResourcePool.utils.LiKuUtils;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.entity.StandardMaterials;
+import com.jeeplus.modules.sg.balancedlibrary.standardMaterials.service.StandardMaterialsService;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.shiro.authz.annotation.Logical;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.ConstraintViolationException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 标准物资Controller
+ * @author lgf
+ * @version 2018-06-12
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/standardMaterials")
+public class StandardMaterialsController extends BaseController {
+
+	@Autowired
+	private StandardMaterialsService service;
+
+
+
+	@ModelAttribute
+	public StandardMaterials get(@RequestParam(required=false) String id) {
+		StandardMaterials entity = null;
+		if (StringUtils.isNotBlank(id)){
+			entity = service.get(id);
+		}
+		if (entity == null){
+			entity = new StandardMaterials();
+		}
+		return entity;
+	}
+	
+	/**
+	 * 标准物资列表页面
+	 */
+	@RequiresPermissions("sg:balancedlibrary:standardMaterials:list")
+	@RequestMapping(value = "list")
+	public String list(StandardMaterials entity, Model model) {
+		model.addAttribute("entity", entity);
+		return "modules/sg/balancedlibrary/standardMaterials/standardMaterialsList";
+	}
+	
+	/**
+	 * 标准物资列表数据
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:standardMaterials:list")
+	@RequestMapping(value = "data")
+	public Map<String, Object> data(StandardMaterials entity, HttpServletRequest request, HttpServletResponse response, Model model) {
+		Page<StandardMaterials> page = service.findPage(new Page<StandardMaterials>(request, response), entity);
+		return getBootstrapData(page);
+	}
+
+
+	
+	/**
+	 * 批量删除标准物资
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:standardMaterials:del")
+	@RequestMapping(value = "deleteAll")
+	public AjaxJson deleteAll(String ids) {
+		AjaxJson j = new AjaxJson();
+		String idArr[] =ids.split(",");
+		List<String> idList = Arrays.asList(idArr);
+		service.deleteList(idList);
+		j.setMsg("删除标准物资成功");
+		return j;
+	}
+	
+	/**
+	 * 导出excel文件
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:standardMaterials:export")
+    @RequestMapping(value = "export")
+    public AjaxJson exportFile(StandardMaterials entity, HttpServletRequest request, HttpServletResponse response) {
+		AjaxJson j = new AjaxJson();
+		try {
+            String fileName = "标准物资情况表"+DateUtils.getDate("yyyyMMddHHmmss")+".xlsx";
+            Page<StandardMaterials> page = service.findPage(new Page<StandardMaterials>(request, response, -1), entity);
+    		new ExportExcel("", StandardMaterials.class).setDataList(page.getList()).write(response, fileName).dispose();
+    		j.setSuccess(true);
+    		j.setMsg("导出成功!");
+    		return j;
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg("导出标准物资表失败!失败信息:"+e.getMessage());
+		}
+			return j;
+    }
+
+	/**
+	 * 标准物资-导入Excel数据
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:standardMaterials:import")
+    @RequestMapping(value = "import")
+   	public AjaxJson importFile(@RequestParam("file")MultipartFile file, HttpServletResponse response, HttpServletRequest request) {
+		AjaxJson j = new AjaxJson();
+		try {
+			ImportUtil ei = new ImportUtil(file,0,0);
+			List<StandardMaterials> list = ei.getDataList(StandardMaterials.class);
+			for(StandardMaterials material:list){
+				if("非国网采购标准物料".equals(material.getPurchaseStandardId())){
+					material.setPurchaseStandardId("非标物料");
+				}
+			}
+			if (list.size() > 0) {
+				//标准物资每次重新导入数据,将原有数据清空
+				service.fullReplace(list);
+				j.setMsg("已成功导入 " + list.size() + " 条标准物资记录");
+			}
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg("导入标准物资失败!失败信息:"+e.getMessage());
+		}
+		return j;
+    }
+
+
+
+	/**
+	 * 下载导入标准物资数据模板
+	 */
+	@ResponseBody
+	@RequiresPermissions("sg:balancedlibrary:standardMaterials:import")
+    @RequestMapping(value = "import/template")
+     public AjaxJson importFileTemplate(HttpServletResponse response) {
+		AjaxJson j = new AjaxJson();
+		try {
+            String fileName = "标准物资数据导入模板.xlsx";
+    		List<StandardMaterials> list = Lists.newArrayList();
+    		new ExportExcel("", StandardMaterials.class, 1).setDataList(list).write(response, fileName).dispose();
+    		return null;
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg( "导入模板下载失败!失败信息:"+e.getMessage());
+		}
+		return j;
+    }
+
+}

+ 7 - 0
src/main/java/com/jeeplus/modules/sg/classification/entity/ClassificationProject.java

@@ -0,0 +1,7 @@
+package com.jeeplus.modules.sg.classification.entity;
+
+import com.jeeplus.core.persistence.DataEntity;
+
+public class ClassificationProject  extends DataEntity<ClassificationProject> {
+
+}

+ 17 - 0
src/main/java/com/jeeplus/modules/sg/classification/mapper/ClassificationMapper.java

@@ -0,0 +1,17 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.classification.mapper;
+
+import com.jeeplus.core.persistence.BaseMapper;
+import com.jeeplus.core.persistence.annotation.MyBatisMapper;
+import com.jeeplus.modules.sg.classification.entity.ClassificationProject;
+
+
+/**
+ *
+
+ */
+@MyBatisMapper
+public interface ClassificationMapper extends BaseMapper<ClassificationProject> {
+}

+ 21 - 0
src/main/java/com/jeeplus/modules/sg/classification/service/ClassificationService.java

@@ -0,0 +1,21 @@
+package com.jeeplus.modules.sg.classification.service;
+
+import com.jeeplus.core.service.CrudService;
+import com.jeeplus.modules.sg.classification.entity.ClassificationProject;
+import com.jeeplus.modules.sg.classification.mapper.ClassificationMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@Transactional(readOnly = true)
+public class ClassificationService extends CrudService<ClassificationMapper, ClassificationProject> {
+
+
+    @Transactional(readOnly = false)
+    public void save(ClassificationProject project) {
+        super.save(project);
+    }
+
+}

+ 279 - 0
src/main/java/com/jeeplus/modules/sg/classification/uti/ImportExcel.java

@@ -0,0 +1,279 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.classification.uti;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+import com.jeeplus.common.utils.Encodes;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.utils.Reflections;
+import com.jeeplus.common.utils.excel.annotation.ExcelField;
+import com.jeeplus.modules.sys.entity.Area;
+import com.jeeplus.modules.sys.entity.Office;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.utils.DictUtils;
+import com.jeeplus.modules.sys.utils.UserUtils;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 导入Excel文件(支持“XLS”和“XLSX”格式)
+ * @author jeeplus
+ * @version 2016-03-10
+ */
+public class ImportExcel {
+
+	private static Logger log = LoggerFactory.getLogger(ImportExcel.class);
+
+	/**
+	 * 工作薄对象
+	 */
+	private Workbook wb;
+
+	/**
+	 * 工作表对象
+	 */
+	private Sheet sheet;
+
+	/**
+	 * 标题行号
+	 */
+	private int headerNum;
+
+
+
+
+	public ImportExcel(MultipartFile multipartFile, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		this(multipartFile.getOriginalFilename(), multipartFile.getInputStream(), headerNum, sheetIndex);
+	}
+
+
+	/**
+	 * 构造函数
+	 * @param headerNum 标题行号,数据行号=标题行号+1
+	 * @param sheetIndex 工作表编号
+	 * @throws InvalidFormatException
+	 * @throws IOException
+	 */
+	public ImportExcel(String fileName, InputStream is, int headerNum, int sheetIndex)
+			throws InvalidFormatException, IOException {
+		if (StringUtils.isBlank(fileName)){
+			throw new RuntimeException("导入文档为空!");
+		}else if(fileName.toLowerCase().endsWith("xls")){
+			this.wb = new HSSFWorkbook(is);
+		}else if(fileName.toLowerCase().endsWith("xlsx")){
+			this.wb = new XSSFWorkbook(is);
+		}else{
+			throw new RuntimeException("文档格式不正确!");
+		}
+		if (this.wb.getNumberOfSheets()<sheetIndex){
+			throw new RuntimeException("文档中没有工作表!");
+		}
+		this.sheet = this.wb.getSheetAt(sheetIndex);
+		this.headerNum = headerNum;
+		log.debug("Initialize success.");
+	}
+
+
+	/**
+	 * 获取行对象
+	 * @param rownum
+	 * @return
+	 */
+	public Row getRow(int rownum){
+		return this.sheet.getRow(rownum);
+	}
+
+	/**
+	 * 获取数据行号
+	 * @return
+	 */
+	public int getDataRowNum(){
+		return headerNum+1;
+	}
+
+	/**
+	 * 获取最后一个数据行号
+	 * @return
+	 */
+	public int getLastDataRowNum(){
+		return this.sheet.getLastRowNum();
+	}
+
+	/**
+	 * 获取最后一个列号
+	 * @return
+	 */
+	public int getLastCellNum(){
+		return this.getRow(headerNum).getLastCellNum();
+	}
+
+
+	public void classify() throws Exception {
+		int firstLine = headerNum;
+		int lastLine = this.sheet.getLastRowNum();
+		if(lastLine<=firstLine)
+			throw new Exception("no data!");
+		for(int i= firstLine;i<=lastLine;i++){
+			Row row = sheet.getRow(i);
+			String reason = getStringValue(row,30);
+			Double num1 = getDoubleValue(row,47);//变压器
+			Double num2 = getDoubleValue(row,39);//环网柜
+			Double num3 = getDoubleValue(row,51);//低压分支箱
+			Double num4 = getDoubleValue(row,62);//高压分支箱
+			Double num5 = getDoubleValue(row,45);//箱变
+			Double num6 = getDoubleValue(row,37);//电缆
+			Double num7 = getDoubleValue(row,50);//低压电缆
+			String classfilation = "";
+			if((reason.contains("移位")||reason.contains("迁移")||reason.contains("变压器")||reason.contains("配变"))&&
+					(num1==null||num1==0)){
+				classfilation = "配变移位:将变压器进行移位";
+			}else if((reason.contains("移位")||reason.contains("迁移")||reason.contains("变压器")||reason.contains("配变"))&&
+					(num1 !=null&&num1>0)){
+				classfilation = "配变移位改造:将配变进行移位改造新建";
+			}else if((reason.contains("新增")||reason.contains("新设")||reason.contains("新上"))&&
+					(num2 !=null&&num2>0)){
+				classfilation = "环网柜新建:新设环网柜,并对基础进行改造";
+			}else if((reason.contains("更换"))&&
+					(num2 !=null&&num2>0)){
+				classfilation = "环网柜改造:更换环网柜,同时进行自动化改造";
+			}else if((reason.contains("更换或维修")&&reason.contains("低压分支箱"))&&
+					(num3 !=null&&num3>0)){
+				classfilation = "低压分支箱:更换低压分支箱";
+			}else if((reason.contains("更换或维修")&&reason.contains("高压分支箱"))&&
+					(num4 !=null&&num4>0)){
+				classfilation = "分支箱更换:更换高压分支箱";
+			}else if((reason.contains("分支箱改"))&&
+					(num2 !=null&&num2>0)){
+				classfilation = "分支箱换环网柜:分支箱换环网柜";
+			}else if(reason.contains("更换")&&
+					(num5 !=null&&num5>0)){
+				classfilation = "箱变更换:更换箱变";
+			}else if((reason.contains("下地"))&&
+					(num6 !=null&&num6>0)){
+				classfilation = "电缆项目:杆线进行下地改造";
+			}else if((reason.contains("电缆老"))&&
+					((num6 !=null&&num6>0)||(num7 !=null&&num7>0))){
+				classfilation = "电缆项目:电缆严重老化,线经过小,将原电缆更换";
+			}else if(reason.contains("更换电缆")){
+				classfilation = "电缆项目:环网柜电缆维修";
+			}else if(reason.contains("更换开关")||reason.contains("开关改造")||reason.contains("改造开关")){
+				classfilation = "线路开关维修:对开关进行自动化改造,改造为集中型、三遥自动化装置,通信方式优先光纤,不满足条件时可采用无线专网";
+			}else if(reason.contains("新上开关")||reason.contains("新设开关")||reason.contains("增加开关")){
+				classfilation = "用户分界开关:用户开关加装为智能分界开关,二遥,接入调度主站。";
+			}else if(reason.contains("裸线")||reason.contains("裸导线")){
+				classfilation = "杆线项目:拆除裸线,新设绝缘线,更换杆塔,提高该段线路运行安全";
+			}else if(reason.contains("线树")||reason.contains("树线")){
+				classfilation = "杆线项目:更换原绝缘线,更换杆塔,项目实施后,该段架空线路通道位置合理,运行巡视、抢修便利。";
+			}else if(reason.contains("改接")){
+				classfilation = "杆线项目:新建联络,拆除现有联络";
+			}else if((reason.contains("开关站")&&reason.contains("分支箱"))||(reason.contains("电房")&&reason.contains("分支箱"))){
+				classfilation = "开关站改造:开闭所内新设高压分支箱,拆除不利用设备";
+			}else if(reason.contains("FA")||reason.contains("DTU")||reason.contains("二遥")||reason.contains("三遥")){
+				classfilation = "自动化改造";
+			}
+			Cell cell = row.createCell(1);
+			cell.setCellValue(classfilation);
+		}
+
+	}
+
+	public String getStringValue(Row row,int column) throws Exception {
+		Cell cell = row.getCell(column);
+		if(cell !=null){
+			return cell.getStringCellValue();
+		}else{
+			int line = row.getRowNum()+1;
+			throw new Exception("找不到单元格第 "+line+" 行,第 "+(column+1)+" 列!");
+		}
+	}
+
+	public Double getDoubleValue(Row row,int column) throws Exception {
+		Cell cell = row.getCell(column);
+		if(cell !=null){
+			if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
+				return cell.getNumericCellValue();
+			}else if(cell.getCellType() == Cell.CELL_TYPE_STRING){
+				return Double.parseDouble(cell.getStringCellValue());
+			}else{
+				String temp = cell.getStringCellValue();
+				if(StringUtils.isBlank(temp)){
+					return 0.0;
+				}else{
+					int line = row.getRowNum()+1;
+					throw new Exception("单元格格式错误第 "+line+" 行,第 "+(column+1)+" 列!");
+				}
+			}
+		}else{
+			int line = row.getRowNum()+1;
+			throw new Exception("找不到单元格第 "+line+" 行,第 "+(column+1)+" 列!");
+		}
+
+	}
+
+
+	public ImportExcel writeFile(String name) throws FileNotFoundException, IOException{
+		File file = new File(name);
+		FileOutputStream os = new FileOutputStream(file);
+		this.write(os);
+		return this;
+	}
+	public ImportExcel write(OutputStream os) throws IOException{
+		wb.write(os);
+		os.close();
+		return this;
+	}
+	/**
+	 * 输出到客户端
+	 * @param fileName 输出文件名
+	 */
+	public ImportExcel write(HttpServletResponse response, String fileName) throws IOException{
+		response.reset();
+		response.setContentType("application/octet-stream; charset=utf-8");
+		response.setHeader("Content-Disposition", "attachment; filename="+Encodes.urlEncode(fileName));
+		write(response.getOutputStream());
+		return this;
+	}
+
+	public ImportExcel(InputStream is){
+		try {
+			wb = new XSSFWorkbook(is);
+			sheet = wb.getSheetAt(0);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}finally {
+			if(is!=null){
+				try {
+					is.close();
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}
+
+}

+ 94 - 0
src/main/java/com/jeeplus/modules/sg/classification/web/ClassificationController.java

@@ -0,0 +1,94 @@
+/**
+ * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
+ */
+package com.jeeplus.modules.sg.classification.web;
+
+import com.jeeplus.common.json.AjaxJson;
+import com.jeeplus.core.web.BaseController;
+import com.jeeplus.modules.sg.classification.service.ClassificationService;
+import com.jeeplus.modules.sg.classification.uti.ImportExcel;
+import com.jeeplus.modules.test.one.dialog.entity.Leave1;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.util.UUID;
+
+/**
+ * 考勤数据转换工具类
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/sg/classification")
+public class ClassificationController extends BaseController {
+
+	private static final String TEMP_PATH = ClassificationController.class.getResource("/").getPath()+"/temp/";
+
+	@Autowired
+	private ClassificationService classificationService;
+
+
+
+	/**
+	 * 考勤数据转换页面
+	 */
+	@RequestMapping(value = {"list", ""})
+	public String list(Leave1 leave1, Model model) {
+		model.addAttribute("leave1", leave1);
+		return "modules/sg/classification/classification";
+	}
+	
+
+	/**
+	 *
+	 */
+	@ResponseBody
+    @RequestMapping(value = "classify")
+   	public AjaxJson importFile(@RequestParam("classificationFile")MultipartFile classficationFile) {
+		AjaxJson j = new AjaxJson();
+		try {
+			ImportExcel excel = new ImportExcel(classficationFile,1,0);
+			excel.classify();
+			String tempFileName = UUID.randomUUID().toString();
+			if(classficationFile.getOriginalFilename().toLowerCase().endsWith("xls")){
+				tempFileName = tempFileName + ".xls";
+			}else{
+				tempFileName = tempFileName + ".xlsx";
+			}
+			excel.writeFile(TEMP_PATH+tempFileName);
+
+			j.put("tempFileName",tempFileName);
+			j.setSuccess(true);
+		} catch (Exception e) {
+			j.setSuccess(false);
+			j.setMsg("匹配失败:"+e.getMessage());
+		}
+		return j;
+    }
+
+	@ResponseBody
+	@RequestMapping(value = "download")
+	public void importFile(String tempFileName,HttpServletResponse response) {
+		try {
+			File file = new File(TEMP_PATH+"/"+tempFileName);
+			InputStream is = new FileInputStream(file);
+			ImportExcel util = new ImportExcel(is);
+			util.write(response,"匹配结果.xlsx");
+//			下载完将临时文件删除
+			if(file.exists()){
+				file.delete();
+			}
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+
+}

+ 9 - 0
src/main/java/com/jeeplus/modules/sg/financial/erpcredit/entity/ErpAccount.java

@@ -11,6 +11,7 @@ import java.io.Serializable;
 public class ErpAccount implements Serializable {
     private static final long serialVersionUID = 1L;
 
+    private String profitCenter;//利润中心
     private String WbsDetails;//WBS描述
     private String ProjectDefinitionCode;//项目定义编码
     private String ProjectDefinitionDetails;//项目定义描述
@@ -23,6 +24,14 @@ public class ErpAccount implements Serializable {
     private Double theInputTax;//进项税额
     private String supplierName;//供应商名称
 
+    public String getProfitCenter() {
+        return profitCenter;
+    }
+
+    public void setProfitCenter(String profitCenter) {
+        this.profitCenter = profitCenter;
+    }
+
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }

+ 9 - 0
src/main/java/com/jeeplus/modules/sg/financial/erpcredit/entity/ErpCredit.java

@@ -14,6 +14,7 @@ import java.util.Map;
 public class ErpCredit extends DataEntity<ErpCredit>{
     private static final long serialVersionUID = 1L;
 
+    private String profitCenter;//利润中心
     private String itemId;//项目定义编码
     private String itemName;//项目名称
     private Double actualInvestment;//实际投资
@@ -54,6 +55,14 @@ public class ErpCredit extends DataEntity<ErpCredit>{
     private String supervisorStatus;
 
 
+    public String getProfitCenter() {
+        return profitCenter;
+    }
+
+    public void setProfitCenter(String profitCenter) {
+        this.profitCenter = profitCenter;
+    }
+
     public Map<String, ErpCreditEquipment> getEquipmentMap() {
         return equipmentMap;
     }

+ 10 - 1
src/main/java/com/jeeplus/modules/sg/financial/erpcredit/entity/TransferOfEquipment.java

@@ -6,7 +6,8 @@ package com.jeeplus.modules.sg.financial.erpcredit.entity;
 public class TransferOfEquipment {
     private String powerId;//配电网项目编号
     private String powerName;//配电网资产名称
-    private String powerAssetClass;//资产类别
+    private String powerAssetName;//资产名称
+    private String powerAssetClass;//资产类别(代码)
     private String powerArea;//线路起止地点或配变所在滴
     private String powerDepartment;//保管部门
     private String powerNumber;//配变数量
@@ -18,6 +19,14 @@ public class TransferOfEquipment {
     private String powerDeliveredAssets;//交付使用资产价值
     private String poweRequipmentFee;//其中:附属设备价值
 
+    public String getPowerAssetName() {
+        return powerAssetName;
+    }
+
+    public void setPowerAssetName(String powerAssetName) {
+        this.powerAssetName = powerAssetName;
+    }
+
     public String getPowerInstallFee() {
         return powerInstallFee;
     }

+ 32 - 24
src/main/java/com/jeeplus/modules/sg/financial/erpcredit/service/ErpCreditService.java

@@ -239,8 +239,9 @@ public class ErpCreditService extends CrudService<ErpCreditMapper,ErpCredit> {
         InputStream inputStream = null;
         XSSFWorkbook workbook = null;
         XSSFFont font=null;
-        XSSFSheet sheetOverView = null;
-        XSSFSheet sheetView = null;
+        XSSFSheet sheetCover = null; //封面
+        XSSFSheet sheetOverView = null; //概述表
+        XSSFSheet sheetView = null; //一览表
         XSSFSheet sheetOtherFee = null;//定义其他费用明细表费用
         XSSFSheet sheetAssetsTotal= null;//资产总表
         XSSFSheet sheetLine1 = null;//移交生产总值一览表
@@ -254,34 +255,41 @@ public class ErpCreditService extends CrudService<ErpCreditMapper,ErpCredit> {
             inputStream = new FileInputStream(newFile);// 将excel文件转为输入流
             workbook = new XSSFWorkbook(inputStream);// 创建个workbook,
             font = workbook.createFont();
-            sheetOverView =workbook.getSheetAt(0);//概述表
-            sheetView = workbook.getSheetAt(1);//定义一览表
-            sheetOtherFee = workbook.getSheetAt(2);//其他费用表
-            sheetAssetsTotal = workbook.getSheetAt(4);//移交生产总值
-            sheetLine1=workbook.getSheetAt(7);//线路1
-            sheetEquip=workbook.getSheetAt(8);//设备1
-            sheetEquipMaterial=workbook.getSheetAt(9);//设备材料清单表
-            sheetSettlement=workbook.getSheetAt(10);//结算表
-            sheetLine2=workbook.getSheetAt(5);//线路2
-            sheetEquip2=workbook.getSheetAt(6);//设备2
-            newForm=workbook.getSheetAt(3);//新表
+            sheetCover = workbook.getSheetAt(0);//封面
+            sheetOverView =workbook.getSheetAt(1);//概述表 01
+            sheetView = workbook.getSheetAt(2);//一览表 02
+//            sheetOtherFee = workbook.getSheetAt(2);//其他费用表
+            newForm=workbook.getSheetAt(3);//其他费用表新 03
+            sheetAssetsTotal = workbook.getSheetAt(4);//移交生产总值 04
+//            sheetLine1=workbook.getSheetAt(5);//线路1
+//            sheetEquip=workbook.getSheetAt(6);//设备1
+            sheetLine2=workbook.getSheetAt(5);//04-1
+            sheetEquip2=workbook.getSheetAt(6);//04-2
+            sheetEquipMaterial=workbook.getSheetAt(7);//设备材料清单表
+            sheetSettlement=workbook.getSheetAt(8);//结算表05
+
+
         } catch (Exception e1) {
             e1.printStackTrace();
         }
         try {
             // 写数据
             FileOutputStream fos = new FileOutputStream(newFile);
-            ExportUtil.getSheetOverView(sheetOverView,erpCreditList,maintainDatas);
-            ExportUtil.getSheetView(sheetView,erpCreditList,maintainDatas,workbook);//调用一览表写入方法
-            ExportUtil.getSheetOtherFee(sheetOtherFee,erpCreditList,maintainDatas);
-            ExportUtil.getSheetAssetsTotal(sheetAssetsTotal,erpCreditList,maintainDatas);
-            ExportUtil.getSheetLine1(sheetLine1,erpCreditList,workbook);
-            ExportUtil.getSheetEquip(sheetEquip,erpCreditList,maintainDatas,workbook);
-            ExportUtil.getSheetEquipMaterial(sheetEquipMaterial,erpCreditList,workbook);
-            ExportUtil.getSheetSettlement(sheetSettlement,erpCreditList,maintainDatas);
-            ExportUtil.getSheetLine2(sheetLine2,erpCreditList,workbook);
-            ExportUtil.getSheetEquip2(sheetEquip2,erpCreditList,maintainDatas,workbook);
-            ExportUtil.getOtherExpenses(newForm,erpCreditList,maintainDatas,workbook);
+            ExportUtil.getSheetCover(sheetCover,erpCreditList,maintainDatas); //封面写入数据
+            ExportUtil.getSheetOverView(sheetOverView,erpCreditList,maintainDatas);//概况表写入数据 01
+            ExportUtil.getSheetView(sheetView,erpCreditList,maintainDatas,workbook);//一览表写入数据 02
+//            ExportUtil.getSheetOtherFee(sheetOtherFee,erpCreditList,maintainDatas);//其他费用明细表 不用
+            ExportUtil.getOtherExpenses(newForm,erpCreditList,maintainDatas,workbook);//其他费用表写入数据 03
+            ExportUtil.getSheetAssetsTotal(sheetAssetsTotal,erpCreditList,maintainDatas);//移交资产总表 04
+            ExportUtil.getSheetLine2(sheetLine2,erpCreditList,workbook);//04-1
+            ExportUtil.getSheetEquip2(sheetEquip2,erpCreditList,maintainDatas,workbook);//04-2
+//            ExportUtil.getSheetLine1(sheetLine1,erpCreditList,workbook);
+//            ExportUtil.getSheetEquip(sheetEquip,erpCreditList,maintainDatas,workbook);
+            ExportUtil.getSheetEquipMaterial(sheetEquipMaterial,erpCreditList,workbook);//设备材料清册
+            ExportUtil.getSheetSettlement(sheetSettlement,erpCreditList,maintainDatas);//竣工工程决算表 05
+
+
+
             workbook.write(fos);
             fos.flush();
             fos.close();

+ 3 - 0
src/main/java/com/jeeplus/modules/sg/financial/erpcredit/util/ErpInfo.java

@@ -103,6 +103,7 @@ public  class ErpInfo {
             String erpCode = (String) importUtil.getCellValue(row,10);
             if(StringUtils.isNotBlank(erpCode)) {
                 erpAccount.setProjectDefinitionCode(erpCode);
+                erpAccount.setProfitCenter((String)importUtil.getCellValue(row,1));
                 erpAccount.setProjectDefinitionDetails((String)importUtil.getCellValue(row,11));
                 erpAccount.setSubjectName((String)importUtil.getCellValue(row,13));
                 erpAccount.setLineItemAmount(Double.parseDouble((String) importUtil.getCellValue(row,19)));
@@ -213,6 +214,7 @@ public  class ErpInfo {
                 map.put(projectId,erpCredit);
                 erpCredit.setItemId(erpAccount.getProjectDefinitionCode());//添加项目定义编号
                 erpCredit.setItemName(erpAccount.getProjectDefinitionDetails());//项目名称
+                erpCredit.setProfitCenter(erpAccount.getProfitCenter());//利润中心
             }
 
             //处理进项税额
@@ -388,6 +390,7 @@ public  class ErpInfo {
                 map.put(projectId,erpCredit);
                 erpCredit.setItemId(erpAccount.getProjectDefinitionCode());//添加项目定义编号
                 erpCredit.setItemName(erpAccount.getProjectDefinitionDetails());//项目名称
+                erpCredit.setProfitCenter(erpAccount.getProfitCenter());//利润中心
             }
 
             //成本项目施工费对应供应商

Datei-Diff unterdrückt, da er zu groß ist
+ 596 - 602
src/main/java/com/jeeplus/modules/sg/financial/erpcredit/util/ExportUtil.java


+ 72 - 19
src/main/java/com/jeeplus/modules/sg/financial/erpcredit/util/ExportUtilCalculate.java

@@ -1,7 +1,10 @@
 package com.jeeplus.modules.sg.financial.erpcredit.util;
 
+import com.jeeplus.common.utils.StringUtils;
 import com.jeeplus.modules.sg.financial.erpcredit.entity.*;
 import com.jeeplus.modules.sg.financial.settlement.entity.MaintainData;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFRow;
 
 import java.io.*;
 import java.math.BigDecimal;
@@ -30,7 +33,7 @@ public class ExportUtilCalculate {
     public static String POWER_YU = "有";
 
     /**
-     * 一览表汇总
+     * 获取一览表所有数据及汇总
      * @param erpCreditList
      * @param maintainDataList
      * @return
@@ -106,15 +109,19 @@ public class ExportUtilCalculate {
                 addSubtractionLinesAll+=Double.parseDouble(s.getAddSubtractionLines());
                 scheduletotal.setAddSubtractionLines(decimalFormat.format(addSubtractionLinesAll));
             }
-            if (null!=s.getAddSubtractionRate()&&!"∞".equals(s.getAddSubtractionRate())){
-                addSubtractionRateAll+=Double.parseDouble(s.getAddSubtractionRate());
-                scheduletotal.setAddSubtractionRate(decimalFormat.format(addSubtractionRateAll));
-            }
+//            if (null!=s.getAddSubtractionRate()&&!"∞".equals(s.getAddSubtractionRate())){
+//                addSubtractionRateAll+=Double.parseDouble(s.getAddSubtractionRate());
+//                scheduletotal.setAddSubtractionRate(decimalFormat.format(addSubtractionRateAll));
+//            }
             if (null!=s.getListDeduction()) {
                 listDeduction += Double.parseDouble(s.getListDeduction());
                 scheduletotal.setListDeduction(decimalFormat.format(listDeduction));
             }
         }
+        //合计行增减率
+        scheduletotal.setAddSubtractionRate(decimalFormat.format(
+                Double.parseDouble(schedule.getAddSubtractionLines())/Double.parseDouble(schedule.getBudgetTotalFee())*100
+        ));
         scheduletotal.setItemName(itemNameAll);
         schedules.add(scheduletotal);
         return schedules;
@@ -796,16 +803,21 @@ public class ExportUtilCalculate {
                     //添加资产类别
                     if (transferOfPower2.getPowerCapacity().contains(POWER_BDZ)){
                         transferOfPower2.setPowerAssetClass(POWER_BDZCOUNT);
+                        transferOfPower2.setPowerAssetName(POWER_BDZ);
                     }
                     if (transferOfPower2.getPowerCapacity().contains(POWER_BOXBDZ)){
                         transferOfPower2.setPowerAssetClass(POWER_BOXCOUNT);
+                        transferOfPower2.setPowerAssetName(POWER_BOXBDZ);
                     }
                     if (transferOfPower2.getPowerCapacity().contains(POWER_HGW)&&!transferOfPower2.getPowerCapacity().contains(POWER_WU)
                         &&!transferOfPower2.getPowerCapacity().contains(POWER_YU)){
                         transferOfPower2.setPowerAssetClass(POWER_HGWCOUNT);
+                        transferOfPower2.setPowerAssetName("环网柜");
+
                     }
                     if (transferOfPower2.getPowerCapacity().contains(POWER_KGG)){
                         transferOfPower2.setPowerAssetClass(POWER_KGGCOUNT);
+                        transferOfPower2.setPowerAssetName(POWER_KGG);
                     }
                     transferOfPower2s.add(transferOfPower2);
                 }
@@ -876,7 +888,13 @@ public class ExportUtilCalculate {
         transferOfEquipments.add(transferOfEquipment1);
         return transferOfEquipments;
     }
-    //概况表
+
+    /**
+     * 生成概况表数据
+     * @param erpCredits
+     * @param maintainDataList
+     * @return
+     */
     public static GeneralSituation getFeneraSituation(List<ErpCredit> erpCredits, List<MaintainData> maintainDataList){
         DecimalFormat decimalFormat   = new DecimalFormat("#0.00");
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
@@ -884,15 +902,34 @@ public class ExportUtilCalculate {
         Double lineLength=0.0;//线路长度
         Double tenKvLength=0.0;//其中:10kv线路
         Double fourKvLength=0.0;//400v及以下
+        Set<String> designUnitSet = new HashSet<>();//设计单位
+        Set<String> consUnitSet = new HashSet<>();//施工单位
+        Set<String> organDataSet = new HashSet<>();//文号
         List<String> organDataList = new ArrayList<String>();//预算批准机关、日期、文号
         TreeSet<Date>  commencementDateSet =new TreeSet<Date>();//开工日期
         TreeSet<Date> completionDateSet = new TreeSet<Date>();//竣工时间
         Date beforeDate=null;
         Date endDate = null;
+
+        String designUnit = "";//设计单位
+        String conUnit = "";//施工单位
         String organData = "";//文号
         Double investmentBudget=0.0;//预算投资
         Double actualInvestment=0.0;//实际投资
         if (null!=erpCredits&&erpCredits.size()>0){
+            //项目名称
+            ErpCredit credit = erpCredits.get(0);
+            String profitCenter = credit.getProfitCenter();
+            String projectDefinitionCode = credit.getItemId();
+            String projectName = "";
+            if("L010010501".equals(profitCenter)){
+                projectName = "20"+projectDefinitionCode.substring(6,8)+"年国网江苏省电力有限公司常州供电分公司配网"
+                        +erpCredits.size()+"个项目";
+            }else{
+
+            }
+            generalSituation.setProjectName(projectName);
+
             for (ErpCredit erpCredit:erpCredits){
                 //如果线路长度不为空
                 if (null!=erpCredit.getTenKvLineLength()){
@@ -920,8 +957,17 @@ public class ExportUtilCalculate {
         }
         if (null!=maintainDataList&&maintainDataList.size()>0){
             for (MaintainData maintainData:maintainDataList){
-                if (null!=maintainData.getApprovalNumber()){//如果审批文号不为空
-                    organDataList.add(maintainData.getApprovalNumber());
+//                if (null!=maintainData.getApprovalNumber()){//如果审批文号不为空
+//                    organDataList.add(maintainData.getApprovalNumber());
+//                }
+                if(StringUtils.isNotEmpty(maintainData.getDesignUnits())){
+                    designUnitSet.add(maintainData.getDesignUnits());
+                }
+                if(StringUtils.isNotEmpty(maintainData.getConstructionUnits())){
+                    consUnitSet.add(maintainData.getConstructionUnits());
+                }
+                if(StringUtils.isNotEmpty(maintainData.getApprovalNumber())){
+                    organDataSet.add(maintainData.getApprovalNumber());
                 }
                 if (null!=maintainData.getStartDate()&&maintainData.getStartDate().toString().length()>0){
                     commencementDateSet.add(maintainData.getStartDate());
@@ -933,20 +979,27 @@ public class ExportUtilCalculate {
                         +maintainData.getDamages()+maintainData.getManagementFee()+maintainData.getBuildingFee()+maintainData.getInstallFee()
                         +maintainData.getEquipmentFee()+maintainData.getMaterialFee();
             }
-            if (null!=organDataList&&organDataList.size()>0){
-                Set set1 = new HashSet();
-                List<String> newList1 = new ArrayList();
-                for (String string:organDataList) {
-                    if(set1.add(string)) {
-                        newList1.add(string);
-                    }
+            if(designUnitSet.size()>0){
+                for(String unit:designUnitSet){
+                    designUnit = designUnit+unit+"、";
+                }
+                designUnit = designUnit.substring(0,designUnit.length()-1);
+            }
+            if(consUnitSet.size()>0){
+                for(String unit:consUnitSet){
+                    conUnit = conUnit+unit+"、";
                 }
-                for (String str:newList1){
-                    organData+=str+"、";
+                conUnit = conUnit.substring(0,conUnit.length()-1);
+            }
+            if(organDataSet.size()>0){
+                for(String unit:organDataSet){
+                    organData = organData+unit+"、";
                 }
-                String substring = organData.substring(0, organData.length() - 1);
-                generalSituation.setOrganDataNumber(substring);
+                organData = organData.substring(0,organData.length()-1);
             }
+            generalSituation.setDesignUnit(designUnit);
+            generalSituation.setBuildUnit(conUnit);
+            generalSituation.setOrganDataNumber(organData);
             if (null!=commencementDateSet&&commencementDateSet.size()>0){
                 generalSituation.setCommencementDate(sdf.format(commencementDateSet.first()));
             }

+ 28 - 0
src/main/java/com/jeeplus/modules/sg/financial/erpcredit/util/ValidationUtils.java

@@ -27,6 +27,7 @@ public class ValidationUtils {
     public static final String CREDIT_KEY_PREFIX = "erpcredit:";//明细账转化中间数据存储key
     public static final String EXPENSE_KEY_PREFIX = "erpexpense:";//实付大于应付数据对象 存储key
     public static final String ARTIFICIAL_KEY_PREFIX = "erpartificial";//应付金额大于实付金额数据对象 存储key
+    public static final String REQUIRED_MATERIAL_VERIFY = "requiredMaterialVarify";//项目需求物资验证中间量
 
     //验证概预算信息是否存在
     public static String getDataMainJudge(List<ErpCredit> erpCredits, List<MaintainData> maintainDatas){
@@ -541,6 +542,18 @@ public class ValidationUtils {
         }
     }
 
+    public static  void storeObjToRedis(HttpServletRequest request,Object obj,String prefix){
+        HttpSession session = request.getSession();
+        String key = prefix+session.getId();
+        CacheChannel channel = J2Cache.getChannel();
+        RedisClient client = ((RedisCacheProvider)channel.getL2Provider()).getRedisClient();
+        try {
+            client.get().setex(key.getBytes(),120, SerializeUtil.serizlize(obj));
+        } finally {
+            client.release();
+        }
+    }
+
     public static <T> List<T> getSessionRedisList(HttpServletRequest request,String prefix,Class T){
         List<T> list = null;
         HttpSession session = request.getSession();
@@ -554,4 +567,19 @@ public class ValidationUtils {
         }
         return list;
     }
+
+    public static <T> T getSessionRedisObj(HttpServletRequest request,String prefix,Class T){
+        T obj = null;
+        HttpSession session = request.getSession();
+        String key = prefix + session.getId();
+        CacheChannel channel = J2Cache.getChannel();
+        RedisClient client = ((RedisCacheProvider)channel.getL2Provider()).getRedisClient();
+        try {
+            obj  = (T) SerializeUtil.deserialize(client.get().get(key.getBytes()));
+        } finally {
+            client.release();
+
+        }
+        return obj;
+    }
 }

+ 1 - 1
src/main/java/com/jeeplus/modules/sg/financial/settlement/mapper/CostCheckMapper.java

@@ -39,7 +39,7 @@ public interface CostCheckMapper extends BaseMapper<CostCheck> {
      * 查询库中所有的项目编号,用于比对插入时是否修改
      * @return 所有项目编号
      * */
-    List<CostCheck> findAllProjectId();
+    List<String> findAllProjectId();
 
     /**
      * 费用检查单挑更新

+ 1 - 1
src/main/java/com/jeeplus/modules/sg/financial/settlement/mapper/ProjectBudgetMapper.java

@@ -36,7 +36,7 @@ public interface ProjectBudgetMapper extends BaseMapper<ProjectBudget> {
 	 * 查询库中所有的项目编号,用于比对插入时是否修改
 	 * @return 所有项目编号
 	 * */
-	List<ProjectBudget> findAllProjectId();
+	List<String> findAllProjectId();
 
 
 	/**

+ 1 - 1
src/main/java/com/jeeplus/modules/sg/financial/settlement/mapper/xml/CostCheckMapper.xml

@@ -215,7 +215,7 @@
 		select * FROM finance_project_cost_check  where ${propertyName} = '${value}'
 	</select>
 
-	<select id="findAllProjectId" resultType="com.jeeplus.modules.sg.financial.settlement.entity.CostCheck">
+	<select id="findAllProjectId" resultType="String">
 		select project_id
 		from finance_project_cost_check;
 	</select>

+ 1 - 1
src/main/java/com/jeeplus/modules/sg/financial/settlement/mapper/xml/ProjectBudgetMapper.xml

@@ -93,7 +93,7 @@
 		</choose>
 	</select>
 
-	<select id="findAllProjectId" resultType="com.jeeplus.modules.sg.financial.settlement.entity.ProjectBudget">
+	<select id="findAllProjectId" resultType="String">
 		select project_id
 		from finance_project_budget;
 	</select>

+ 12 - 36
src/main/java/com/jeeplus/modules/sg/financial/settlement/service/CostCheckService.java

@@ -83,37 +83,15 @@ public class CostCheckService extends CrudService<CostCheckMapper, CostCheck> {
 		List<ProjectBudget> insertList = new ArrayList<>();
 		List<ProjectBudget> updateList = new ArrayList<>();
 		//查找所有的费用检查信息
-		List<CostCheck> allList = costCheckMapper.findAllProjectId();
+		List<String> allList = costCheckMapper.findAllProjectId();
 		if (allList.size() > 0) {
 			for (ProjectBudget b : list) {
-				for (CostCheck a : allList) {
-					if (a.getProjectId().equals(b.getProjectId())) {
-						b.preInsert();
-						updateList.add(b);
-					}
-				}
-			}
-			//获得需要更新的项目信息,其它项目信息则插入
-			Iterator<ProjectBudget> iterator = list.iterator();
-			while (iterator.hasNext()) {
-				ProjectBudget next = iterator.next();
-				for (ProjectBudget u :
-						updateList) {
-					if (next.getProjectId().equals(u.getProjectId())) {
-						iterator.remove();
-					}
-				}
-			}
-			if (list.size() > 0) {
-				for (ProjectBudget a :
-						list) {
-					insertList.add(a);
-				}
-			}
-			if (insertList.size() > 0) {
-				for (ProjectBudget p :
-						insertList) {
-					p.preInsert();
+				if(allList.contains(b.getProjectId())){
+					b.preInsert();
+					updateList.add(b);
+				}else{
+					b.preInsert();
+					insertList.add(b);
 				}
 			}
 		} else {
@@ -139,13 +117,11 @@ public class CostCheckService extends CrudService<CostCheckMapper, CostCheck> {
 	public String insertConstructionList(@Param("list") List<CostCheck> list) {
 		String str = "";
 		List<CostCheck> updateList = new ArrayList<>();
-		List<CostCheck> allList = costCheckMapper.findAllProjectId();
-		for (CostCheck costCheck : allList) {
-			for (CostCheck c : list) {
-				if (costCheck.getProjectId().equals(c.getProjectId())) {
-					c.preInsert();
-					updateList.add(c);
-				}
+		List<String> allList = costCheckMapper.findAllProjectId();
+		for (CostCheck costCheck : list) {
+			if(allList.contains(costCheck.getProjectId())){
+				costCheck.preInsert();
+				updateList.add(costCheck);
 			}
 		}
 		if (updateList.size() > 0) {

+ 7 - 29
src/main/java/com/jeeplus/modules/sg/financial/settlement/service/ProjectBudgetService.java

@@ -86,37 +86,15 @@ public class ProjectBudgetService extends CrudService<ProjectBudgetMapper, Proje
 		List<ProjectBudget> insertList = new ArrayList<>();
 		List<ProjectBudget> updateList = new ArrayList<>();
 		//查询出所有现在存在的项目概预算信息,判断项目编号是否存在,存在的更新,不存在的插入
-		List<ProjectBudget> allList = projectBudgetMapper.findAllProjectId();
+		List<String> allList = projectBudgetMapper.findAllProjectId();
 		if (allList.size() > 0) {
 			for(ProjectBudget b : list){
-				for (ProjectBudget a : allList) {
-					if (a.getProjectId().equals(b.getProjectId())) {
-						b.preInsert();
-						updateList.add(b);
-					}
-				}
-			}
-			//获得需要更新的项目信息,其它项目信息则插入
-			Iterator<ProjectBudget> iterator = list.iterator();
-			while (iterator.hasNext()) {
-				ProjectBudget next = iterator.next();
-				for (ProjectBudget u :
-						updateList) {
-					if (next.getProjectId().equals(u.getProjectId())) {
-						iterator.remove();
-					}
-				}
-			}
-			if (list.size() > 0) {
-				for (ProjectBudget a :
-						list) {
-					insertList.add(a);
-				}
-			}
-			if (insertList.size() > 0) {
-				for (ProjectBudget p :
-						insertList) {
-					p.preInsert();
+				if(allList.contains(b.getProjectId())){
+					b.preInsert();
+					updateList.add(b);
+				}else{
+					b.preInsert();
+					insertList.add(b);
 				}
 			}
 		}else {

+ 2 - 1
src/main/java/com/jeeplus/modules/sg/financial/settlement/web/CostCheckController.java

@@ -238,7 +238,8 @@ public class CostCheckController extends BaseController {
             String projectId = (String) importExcel.getCellValue(row, 1);
             if (StringUtils.isNotBlank(projectId)) {
                 costCheck.setProjectId(projectId);
-                double aDouble = getDouble(importExcel, row, 34);
+//                double aDouble = getDouble(importExcel, row, 34);
+                double aDouble = getDouble(importExcel, row, 36); //模板变动 建议结算款从AI列变成AK列
                 BigDecimal bigDecimal = new BigDecimal(aDouble);
                 BigDecimal setScale = bigDecimal.divide(rates, 2, BigDecimal.ROUND_HALF_UP);
                 costCheck.setConstructionAmountDue(Double.valueOf(setScale.toString()));

+ 37 - 19
src/main/java/com/jeeplus/modules/sg/financial/settlement/web/ProjectBudgetController.java

@@ -432,11 +432,11 @@ public class ProjectBudgetController extends BaseController {
                 projectBudget.setPreliminaryWorkCost(getDouble(importExcel, row, 16));
                 projectBudget.setCompensationCost(getDouble(importExcel, row, 17));
                 projectBudget.setAdministrationCost(getDouble(importExcel, row, 18));
-                double designContractDiscount = getDisCount(importExcel, row, 19);
-                double designTypicalDiscount = getDisCount(importExcel, row, 20);
-                double designTaxRate = getDisCount(importExcel, row, 21);
-                double supervisorContractDiscount = getDisCount(importExcel, row, 22);
-                double supervisorTaxRate = getDisCount(importExcel, row, 23);
+                double designContractDiscount = getDisCount(importExcel, row, 19,6);
+                double designTypicalDiscount = getDisCount(importExcel, row, 20,6);
+                double designTaxRate = getDisCount(importExcel, row, 21,6);
+                double supervisorContractDiscount = getDisCount(importExcel, row, 22,6);
+                double supervisorTaxRate = getDisCount(importExcel, row, 23,6);
                 projectBudget.setDesignContractDiscount(designContractDiscount);
                 projectBudget.setDesignTaxRate(designTaxRate);
                 projectBudget.setDesignTypicalDiscount(designTypicalDiscount);
@@ -452,37 +452,43 @@ public class ProjectBudgetController extends BaseController {
                 //使用bigDecimal初始化数值,计算防止精度丢失问题
                 //设计费
                 BigDecimal bigDecimal = new BigDecimal(designCost);
-                BigDecimal designCostDecimal = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP);
+                BigDecimal designCostDecimal = bigDecimal.setScale(4, BigDecimal.ROUND_HALF_UP);
                 //监理费
                 BigDecimal bigDecimal1 = new BigDecimal(supervisorCost);
-                BigDecimal supervisorCostDecimal = bigDecimal1.setScale(2, BigDecimal.ROUND_HALF_UP);
+                BigDecimal supervisorCostDecimal = bigDecimal1.setScale(4, BigDecimal.ROUND_HALF_UP);
                 //设计合同折扣
                 BigDecimal bigDecimal2 = new BigDecimal(designContractDiscount);
-                BigDecimal desConDecimal = bigDecimal2.setScale(4, BigDecimal.ROUND_HALF_UP);
+                BigDecimal desConDecimal = bigDecimal2.setScale(6, BigDecimal.ROUND_HALF_UP);
                 //设计典设折扣
                 BigDecimal bigDecimal3 = new BigDecimal(designTypicalDiscount);
-                BigDecimal desTypeDecimal = bigDecimal3.setScale(4, BigDecimal.ROUND_HALF_UP);
+                BigDecimal desTypeDecimal = bigDecimal3.setScale(6, BigDecimal.ROUND_HALF_UP);
                 //设计含税税率
                 BigDecimal bigDecimal5 = new BigDecimal(designTaxRate);
-                BigDecimal desTaxRateDecimal = bigDecimal5.setScale(4, BigDecimal.ROUND_HALF_UP);
+                BigDecimal desTaxRateDecimal = bigDecimal5.setScale(6, BigDecimal.ROUND_HALF_UP);
 
                 //监理费合同折扣
                 BigDecimal bigDecimal4 = new BigDecimal(supervisorContractDiscount);
-                BigDecimal supervisorDecimal = bigDecimal4.setScale(4, BigDecimal.ROUND_HALF_UP);
+                BigDecimal supervisorDecimal = bigDecimal4.setScale(6, BigDecimal.ROUND_HALF_UP);
                 //监理含税税率
                 BigDecimal bigDecimal6 = new BigDecimal(supervisorTaxRate);
-                BigDecimal supTaxRateDecimal = bigDecimal6.setScale(4, BigDecimal.ROUND_HALF_UP);
+                BigDecimal supTaxRateDecimal = bigDecimal6.setScale(6, BigDecimal.ROUND_HALF_UP);
 
 
                 //计算项目设计费应付金额(设计费*设计合同折扣*设计典设折扣/设计含税税率)两位小数
-                BigDecimal firResult = designCostDecimal.multiply(desConDecimal).setScale(2, BigDecimal.ROUND_HALF_UP);
-                BigDecimal secResult = firResult.multiply(desTypeDecimal).setScale(2, BigDecimal.ROUND_HALF_UP);
-                BigDecimal thirdResult = secResult.divide(desTaxRateDecimal,4,BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP);
-                projectBudget.setDesignFeePayable(thirdResult.toString());
+//                BigDecimal firResult = designCostDecimal.multiply(desConDecimal).setScale(2, BigDecimal.ROUND_HALF_UP);
+//                BigDecimal secResult = firResult.multiply(desTypeDecimal).setScale(2, BigDecimal.ROUND_HALF_UP);
+//                BigDecimal thirdResult = secResult.divide(desTaxRateDecimal,4,BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP);
+//                projectBudget.setDesignFeePayable(thirdResult.toString());
+                BigDecimal designFeePayable = designCostDecimal.multiply(desConDecimal).multiply(desTypeDecimal)
+                        .divide(desTaxRateDecimal,6,BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP);
+                projectBudget.setDesignFeePayable(designFeePayable.toString());
                 //计算项目监理费应付金额(监理费*监理费合同折扣/监理含税税率)两位小数
-                BigDecimal fourResult = supervisorCostDecimal.multiply(supervisorDecimal).setScale(2, BigDecimal.ROUND_HALF_UP);
-                BigDecimal fivResult = fourResult.divide(supTaxRateDecimal,4,BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP);
-                projectBudget.setSupervisionFeePayable(fivResult.toString());
+//                BigDecimal fourResult = supervisorCostDecimal.multiply(supervisorDecimal).setScale(2, BigDecimal.ROUND_HALF_UP);
+//                BigDecimal fivResult = fourResult.divide(supTaxRateDecimal,4,BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP);
+//                projectBudget.setSupervisionFeePayable(fivResult.toString());
+                BigDecimal supervisionFeePayable = supervisorCostDecimal.multiply(supervisorDecimal)
+                        .divide(supTaxRateDecimal,6,BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP);
+                projectBudget.setSupervisionFeePayable(supervisionFeePayable.toString());
 
                 list.add(projectBudget);
             }
@@ -515,6 +521,18 @@ public class ProjectBudgetController extends BaseController {
     }
 
     /**
+     * 获取excel double类型的值,
+     */
+    private double getDisCount(ImportExcel importExcel, Row row, int col,Integer maxDig) {
+        double d = 1.00;
+        Object o = importExcel.getCellValue(row, col,maxDig);
+        if (!o.equals("")) {
+            d = Double.parseDouble(o.toString());
+        }
+        return d;
+    }
+
+    /**
      * 获取excel date类型的值
      */
     private Date getDate(ImportExcel importExcel, Row row, int col) throws ParseException {

BIN
src/main/resources/freemarker/excelmodel/completionModel.xlsx


BIN
src/main/resources/freemarker/excelmodel/completionModel(old).xlsx


BIN
src/main/resources/freemarker/excelmodel/requiredMaterialModel.xlsx


+ 2 - 2
src/main/resources/j2cache/j2cache.properties

@@ -88,8 +88,8 @@ redis.cluster_name = j2cache
 redis.namespace = 
 
 ## connection
-redis.hosts = 127.0.0.1:6382
-#redis.hosts = 192.168.2.4:6380
+#redis.hosts = 127.0.0.1:6382
+redis.hosts = 127.0.0.1:6379
 redis.timeout = 2000
 #192.168.2.4\u73AF\u5883
 #redis.password = 123456

+ 6 - 6
src/main/resources/properties/jeeplus.properties

@@ -14,21 +14,22 @@
 #mysql database setting
 jdbc.type=mysql
 jdbc.driver=com.mysql.jdbc.Driver
-#jdbc.url=jdbc:mysql://192.168.2.4:3306/sg_audit_0916?useUnicode=true&amp;characterEncoding=utf-8&allowMultiQueries=true
+jdbc.url=jdbc:mysql://192.168.2.4:3306/sg_audit_0916?useUnicode=true&amp;characterEncoding=utf-8&allowMultiQueries=true
 #\u9547\u6C5F\u73B0\u573A
 #jdbc.url=jdbc:mysql://localhost:3307/sg_audit_0925?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
 #103\u79C1\u670D\u73AF\u5883
 #jdbc.url=jdbc:mysql://106.12.212.98:3306/sg_test?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
 #\u9547\u6C5F\u6D4B\u8BD5\u73AF\u5883
 #jdbc.url=jdbc:mysql://localhost:3306/sg_audit_0924?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
-jdbc.url=jdbc:mysql://localhost:3306/sg_audit_changzhou?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
+#jdbc.url=jdbc:mysql://localhost:3306/sg_audit_zhenj?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
+#jdbc.url=jdbc:mysql://localhost:3306/sg_audit_changzhou?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
 #jdbc.url=jdbc:mysql://106.12.212.98:3306/sg_audit_0924?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
 jdbc.username=root
 #\u9547\u6C5F\u73B0\u573A
 #jdbc.password=Zjsh5182!
 #103\u79C1\u670D\u73AF\u5883\u3001\u9547\u6C5F\u6D4B\u8BD5\u73AF\u5883
-jdbc.password=Xgxx1234!
-#jdbc.password=root
+#jdbc.password=Xgxx1234!
+jdbc.password=root
 jdbc.testSql=SELECT 'x'
 jdbc.dual =
 
@@ -137,5 +138,4 @@ spring.http.multipart.max-request-size=100MB
 domain.url=
 #\u6587\u4EF6\u4E0A\u4F20\u524D\u7F00\u8BBE\u7F6E
 #linux.file.store.prefix=/data/nginx/file
-linux.file.store.prefix=/home/nginx/file
-
+linux.file.store.prefix=/home/nginx/file

+ 103 - 0
src/main/webapp/webpage/modules/sg/classification/classification.jsp

@@ -0,0 +1,103 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+    <title>导入Excel</title>
+    <meta name="decorator" content="ani"/>
+    <style type="text/css">
+        .common-style {
+            width:80%;
+            display: inline-block;
+            height: 34px;
+            padding: 6px 12px;
+            margin: 0px 2px;
+            font-size: 14px;
+            line-height: 1.42857143;
+            color: #555;
+            background-color: #fff;
+            background-image: none;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+            box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+            -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+            transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+        }
+        .btn-style {
+            display: inline-block;
+            height: 34px;
+            margin-left: 105px;
+            font-size: 14px;
+            line-height: 1.42857143;
+            color: #555;
+            background-image: none;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+            box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+            -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+            transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+        }
+
+    </style>
+    <script>
+
+        $(document).ready(function() {
+
+        });
+
+
+
+        function importExcel() {
+            if($('#classificationFile').val()==null || $('#classificationFile').val()==''){
+                jp.warning("请上传待匹配文件!");
+                return;
+            }
+            var url = '${ctx}/sg/classification/classify';
+            var importForm =$("#importForm")[0];
+            jp.loading('  正在匹配,请稍等...');
+            jp.uploadFile(importForm, url,function (data){
+                if(data.success){
+                    var address = '${ctx}/sg/classification/download?tempFileName='+data.body.tempFileName;
+                    jp.downloadFile(address);
+                    jp.close();
+                }else{
+                    jp.error(data.msg);
+                }
+            });//调用保存事件
+        }
+    </script>
+</head>
+<body class="bg-white">
+<div class="wrapper wrapper-content">
+    <div class="row">
+        <div class="col-md-12">
+            <div class="panel panel-primary">
+                <div class="panel-body">
+                    <form id="importForm"  action="${url}" method="post"  enctype="multipart/form-data" class="form-horizontal">
+                        <div class="form-group" style="margin:15px 25%">
+                            <label class="col-sm-4 control-label">待匹配文件:</label>
+                            <div class="col-sm-8">
+                                <div class=" input-group" style=" width: 100%;">
+                                    <input id="classificationFile" class="common-style" name="classificationFile" type="file" />
+                                </div>
+                            </div>
+                        </div>
+
+
+                    </form>
+                    <div class="col-lg-6" style="margin:15px 25%">
+                        <div class="form-group text-center" >
+                            <div>
+                                <button class="btn btn-primary  btn-lg btn-parsley" onclick="importExcel()">开始匹配</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+</body>
+</html>