diff --git a/ssjygl-xsx-common/src/main/java/com/cowr/common/utils/poimerge/PoiDynamicMarge.java b/ssjygl-xsx-common/src/main/java/com/cowr/common/utils/poimerge/PoiDynamicMarge.java new file mode 100644 index 0000000..1ac048c --- /dev/null +++ b/ssjygl-xsx-common/src/main/java/com/cowr/common/utils/poimerge/PoiDynamicMarge.java @@ -0,0 +1,163 @@ +package com.cowr.common.utils.poimerge; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +public class PoiDynamicMarge { + + /** + * + * @param headers 标题集合headers的长度应该与list中的model的属性个数一致 + * @param title sheetName + * @param dataset 内容集合 + * @param mergeColumns 合并单元格的列 + * @param titleMap headers对应map + * @return + */ + public static Workbook createExcel(String[] headers, String title, List> dataset, String[] mergeColumns, Map titleMap) { + if (headers.length==0){ + return null; + } + /*初始化excel模板*/ + Workbook wb = new XSSFWorkbook(); + Sheet sheet = null; + try { + sheet = wb.createSheet(); + wb.setSheetName(0, title); + }catch (Exception e){ + e.printStackTrace(); + } + + /*初始化head,填值标题行(第一行)*/ + Row row0 = sheet.createRow(0); + for(int i = 0; i < headers.length; i++){ + /*创建单元格,指定类型*/ + Cell cell_1 = row0.createCell(i, CellType.STRING); + cell_1.setCellValue(titleMap.get(headers[i])); + } + + List poiModels = new ArrayList<>(); + Iterator> iterator = dataset.iterator(); + int index = 1; //这里1是从excel的第二行开始,第一行已经塞入标题了 + while (iterator.hasNext()){ + Row row = sheet.createRow(index); + // 取得当前这行的map,该map中以key,value的形式存着这一行值 + Map map = iterator.next(); + // 循环列数,给当前行塞值 + for(int i = 0; i < headers.length; i++) { + Object old = ""; + // old存的是上一行统一位置的单元的值,第一行是最上一行了,所以从第二行开始记 + if(index > 1) { + old = poiModels.get(i) == null ? "" : poiModels.get(i).getContent(); + } + Object value = map.get(headers[i]); + CellRangeAddress cra; + // 循环需要合并的列 + for(int j = 0; j < mergeColumns.length; j++){ + PoiModel poiModel; + if(index == 1) { + poiModel = new PoiModel(); + poiModel.setOldContent(value + ""); + poiModel.setContent(value + ""); + poiModel.setRowIndex(1); + poiModel.setCellIndex(i); + poiModels.add(poiModel); + old = value; + break; + } + poiModel = poiModels.get(i); + + int rowStartIndex = poiModel.getRowIndex(); + int rowEndIndex = index - 1; + int cellIndex = poiModel.getCellIndex(); + String content = poiModel.getContent(); + String preOldContent = poiModels.get(0).getOldContent(); + String preValue = map.get(headers[0]) + ""; + Boolean isHeaderEquals = mergeColumns[j].equals(headers[i]); + + if(i == 0 && isHeaderEquals && !content.equals(value)) { + if (rowStartIndex != rowEndIndex) { + cra=new CellRangeAddress(rowStartIndex, rowEndIndex, cellIndex, cellIndex); + sheet.addMergedRegion(cra); + } + // 重新记录该列的内容为当前内容,行标记改为当前行标记 + poiModel.setContent(value + ""); + poiModel.setRowIndex(index); + poiModel.setCellIndex(i); + } else if (i > 0 && isHeaderEquals) { + if(!content.equals(value) || (content.equals(value) && !preOldContent.equals(preValue))) { + if (rowStartIndex != rowEndIndex) { + cra = new CellRangeAddress(rowStartIndex, rowEndIndex, cellIndex, cellIndex); + sheet.addMergedRegion(cra); + } + poiModels.get(i).setContent(value + ""); + poiModels.get(i).setRowIndex(index); + poiModels.get(i).setCellIndex(i); + } + } + if(isHeaderEquals && index == dataset.size()) { + if (i == 0) { + if (content.equals(value)) { + cra = new CellRangeAddress(rowStartIndex, index, cellIndex, cellIndex); + sheet.addMergedRegion(cra); + } + } else if (i > 0) { + if (content.equals(value) && preOldContent.equals(preValue)) { + cra = new CellRangeAddress(rowStartIndex, index, cellIndex, cellIndex); + sheet.addMergedRegion(cra); + } + } + } + } + Cell cell = row.createCell(i, CellType.STRING); + if (value instanceof java.math.BigDecimal ) { + if ((new BigDecimal(0)).compareTo((BigDecimal)value) == 0) { + value = "0"; + } + } + cell.setCellValue(value + ""); + // 在每一个单元格处理完成后,把这个单元格内容设置为old内容 + poiModels.get(i).setOldContent(old + ""); + } + index++; + } + + // 通用单元格格式 + Font font = wb.createFont(); + CellStyle cellStyle = wb.createCellStyle(); + cellStyle.setBorderBottom(BorderStyle.THIN); + cellStyle.setBorderLeft(BorderStyle.THIN); + cellStyle.setBorderTop(BorderStyle.THIN); + cellStyle.setBorderRight(BorderStyle.THIN); + cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中 + cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中 + cellStyle.setFont(font); + + for (int r = 0; r <= dataset.size(); r++) { + Row row = sheet.getRow(r); + if (row == null) { + row = sheet.createRow(r); + } + for (int c = 0; c < headers.length; c++) { + Cell cell = row.getCell(c); + if (cell == null) { + cell = row.createCell(c); + } + cell.setCellStyle(cellStyle); + } + } + + for (int i = 1; i < 30; i++) { + sheet.setColumnWidth(i, 15 * 256); + } + + return wb; + } +} diff --git a/ssjygl-xsx-common/src/main/java/com/cowr/common/utils/poimerge/PoiModel.java b/ssjygl-xsx-common/src/main/java/com/cowr/common/utils/poimerge/PoiModel.java new file mode 100644 index 0000000..9617c31 --- /dev/null +++ b/ssjygl-xsx-common/src/main/java/com/cowr/common/utils/poimerge/PoiModel.java @@ -0,0 +1,46 @@ +package com.cowr.common.utils.poimerge; + +/** + * Created by wwx on 2021-12-29 + */ +public class PoiModel { + private String content; + + private String oldContent; + + private int rowIndex; + + private int cellIndex; + + public String getOldContent() { + return oldContent; + } + + public void setOldContent(String oldContent) { + this.oldContent = oldContent; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public int getRowIndex() { + return rowIndex; + } + + public void setRowIndex(int rowIndex) { + this.rowIndex = rowIndex; + } + + public int getCellIndex() { + return cellIndex; + } + + public void setCellIndex(int cellIndex) { + this.cellIndex = cellIndex; + } +} diff --git a/ssjygl-xsx-common/src/main/java/com/cowr/ssjygl/stat/sale/OrderStatService.java b/ssjygl-xsx-common/src/main/java/com/cowr/ssjygl/stat/sale/OrderStatService.java index 110463f..cf82b41 100644 --- a/ssjygl-xsx-common/src/main/java/com/cowr/ssjygl/stat/sale/OrderStatService.java +++ b/ssjygl-xsx-common/src/main/java/com/cowr/ssjygl/stat/sale/OrderStatService.java @@ -4,6 +4,7 @@ import com.cowr.common.enums.OrderStateEnum; import com.cowr.common.enums.OrderTypeEnum; import com.cowr.common.utils.DataUtil; import com.cowr.common.utils.DateTimeUtil; +import com.cowr.common.utils.poimerge.PoiDynamicMarge; import com.cowr.common.view.ReportExcelStyle; import com.cowr.model.Supermarket; import com.cowr.ssjygl.CacheData; @@ -679,6 +680,11 @@ public class OrderStatService { total.set("product_name", ""); dblist.add(total); + for (Record record : dblist) { + String uuid = StrKit.getRandomUUID(); + record.set("uuid", uuid); + } + return dblist; } @@ -2861,4 +2867,392 @@ public class OrderStatService { return new Record().set("data", ret).set("supermarket", sups); } + + public Workbook yearsalestatExportBySup(String tm) { + String title = tm + "年销售统计"; + String[] headers = {"name", "item_name", "product_name", "order_num", "weight", "total_price"}; + String[] regions = {"name", "item_name"}; + Map titleMap = new HashMap<>(); + titleMap.put("name", "名称"); + titleMap.put("item_name", "实(预)售"); + titleMap.put("product_name", "品类"); + titleMap.put("order_num", "订单量"); + titleMap.put("weight", "销量(吨)"); + titleMap.put("total_price", "金额(元)"); + List> listMap = new ArrayList<>(); + List list = statYearBySup(tm, 2); + for (Record r : list) { + Map map = r.getColumns(); + listMap.add(map); + } + + return PoiDynamicMarge.createExcel(headers, title, listMap, regions, titleMap); + } + + /** + * [{ + * name: '竹瓦', key: '1' + * children: [ + * {name: '实售', key: '1_sh' , + * children: [ + * {name: '黄砂', key: '1_sh_1', order_num: 45, weight: 171.11, total_price: 14855.9}, + * {name: '鹅卵石', key: '1_sh_2', order_num: 3, weight: 36, total_price: 2376}, + * {name: '机制砂', key: '1_sh_3', order_num: 0, weight: 0, total_price: 0} + * ] + * }, + * {name: '预售', key: '1_yh' , + * children: [ + * {name: '-', key: '1_yh_1', order_num: '-', weight: '-', total_price: 380}] + * } + * ] + * } + * ] + * 砂站年统计 + * @param tm + * @return + */ + public List statYearBySup(String tm, int type) { + // 砂站 + List sups = Db.find("SELECT\n" + + " t.id,\n" + + " t.`name`\n" + + "FROM\n" + + " supermarket t\n" + + "WHERE\n" + + " id <= 6\n" + + "OR id = 11"); + // 实售 + List shList = Db.find( + "select s.id, s.name, p.id product_id, p.`name` product_name, ifnull(a.orderCount, 0) as order_num, ifnull(a.totalPrice, 0) as total_price, ifnull(a.weight, 0) as weight\n" + + " from supermarket_product t\n" + + " left join (\n" + + " select t.id, t.product_id, count(*) as orderCount, sum(t.total_price) as totalPrice, sum(t.weight) as weight\n" + + " from (\n" + + " select t.supermarket_id as id, t.paid, t.total_price, t.weight, t.product_id\n" + + " from order_temp t\n" + + " where t.state = ? \n" + + " and t.create_time like ? \n" + + " ) t\n" + + " group by t.id, t.product_id\n" + + " ) a on a.id = t.supermarket_id and a.product_id = t.product_id\n" + + " left join supermarket s on s.id = t.supermarket_id\n" + + " left join product p on p.id = t.product_id", OrderStateEnum.RECEIVED.getStateid(), tm + "%"); + // 预售 + List yhList = Db.find( + "SELECT\n" + + " p.supermarket_id id,\n" + + " SUM(p.presell_amount) total_price\n" + + "FROM\n" + + " `presell_order` p\n" + + "WHERE\n" + + " del = 0\n" + + "AND p.presell_date LIKE ?\n" + + "GROUP BY\n" + + " p.supermarket_id", tm + "%"); + + List retChildren = new ArrayList<>(); + List retList = new ArrayList<>(); + List shList1 = new ArrayList<>(); + List yhList1 = new ArrayList<>(); + + int hj_hs_sh_order_num = 0; + double hj_hs_sh_weight = 0.0; + double hj_hs_sh_total_price = 0.0; + + int hj_els_sh_order_num = 0; + double hj_els_sh_weight = 0.0; + double hj_els_sh_total_price = 0.0; + + int hj_jzs_sh_order_num = 0; + double hj_jzs_sh_weight = 0.0; + double hj_jzs_sh_total_price = 0.0; + + double hj_yh_total_price = 0.0; + + // 实售合并 + if (shList.size() > 0) { + List shList2 = new ArrayList<>(); + for (Record s : shList) { + int id = s.getInt("id"); + int product_id = s.getInt("product_id"); + if ((id == 1 || id == 5 || id == 6 || id == 7 || id == 8 || id == 9) && product_id == 1) { + shList2.add(s); + } else { + shList1.add(s); + } + } + if (shList2.size() > 1) { + for (Record s1 : shList2) { + for (Record s2 : shList2) { + int s1_id = s1.getInt("id"); + int s2_id = s2.getInt("id"); + BigDecimal weight = s1.getBigDecimal("weight").add(s2.getBigDecimal("weight")); + if (weight.compareTo(new BigDecimal(0)) == 0) { + weight = new BigDecimal(0); + } + if ((s1_id == 1 && s2_id == 7) || (s1_id == 5 && s2_id == 9) ||s1_id == 6 && s2_id == 8) { + Record s3 = new Record(); + s3.set("id", s1_id); + s3.set("name", s1.getStr("name")); + s3.set("product_id", s1.getInt("product_id")); + s3.set("product_name", s1.getStr("product_name")); + s3.set("order_num", Math.addExact(s1.getInt("order_num"), s2.getInt("order_num"))); + s3.set("total_price", s1.getBigDecimal("total_price").add(s2.getBigDecimal("total_price"))); + s3.set("weight", weight); + shList1.add(s3); + break; + } + } + } + } else if (shList2.size() == 1) { + shList1.addAll(shList2); + } + } + // 预售合并 + if (yhList.size() > 0) { + List yhList2 = new ArrayList<>(); + for (Record s : yhList) { + int id = s.getInt("id"); + if (id == 1 || id == 5 || id == 6 || id == 7 || id == 8 || id == 9) { + yhList2.add(s); + } else { + yhList1.add(s); + } + } + if (yhList2.size() > 1) { + for (Record s1 : yhList2) { + for (Record s2 : yhList2) { + int s1_id = s1.getInt("id"); + int s2_id = s2.getInt("id"); + if ((s1_id == 1 && s2_id == 7) || (s1_id == 5 && s2_id == 9) ||s1_id == 6 && s2_id == 8) { + Record s3 = new Record(); + s3.set("id", s1_id); + s3.set("total_price", s1.getBigDecimal("total_price").add(s2.getBigDecimal("total_price"))); + yhList1.add(s3); + break; + } + } + } + } else if(yhList2.size() == 1) { + yhList1.addAll(yhList2); + } + } + if (sups.size() > 0) { + for (Record s : sups) { + Record p = new Record(); + int s_id = s.getInt("id"); + String name = s.getStr("name"); + p.set("key", s_id); + p.set("name", name); + Record sh = new Record(); + sh.set("key", s_id + "_sh"); + sh.set("item_name", "实售"); + List shChildren = new ArrayList<>(); + if (shList1.size() > 0) { + boolean flag = true; + for (Record sl : shList1) { + int sl_id = sl.getInt("id"); + int product_id = sl.getInt("product_id"); + if (s_id == sl_id) { + flag = false; + Record r = new Record(); + int order_num = sl.getInt("order_num"); + BigDecimal weight = sl.getBigDecimal("weight"); + BigDecimal total_price = sl.getBigDecimal("total_price"); + + if (product_id == 1) { + hj_hs_sh_order_num += order_num; + hj_hs_sh_weight += weight.doubleValue(); + hj_hs_sh_total_price += total_price.doubleValue(); + } else if (product_id == 2) { + hj_els_sh_order_num += order_num; + hj_els_sh_weight += weight.doubleValue(); + hj_els_sh_total_price += total_price.doubleValue(); + } else if (product_id == 3) { + hj_jzs_sh_order_num += order_num; + hj_jzs_sh_weight += weight.doubleValue(); + hj_jzs_sh_total_price += total_price.doubleValue(); + } + + r.set("key", s_id + "_sh_" + product_id); + r.set("id", s_id); + r.set("name", name); + r.set("item_name", "实售"); + r.set("product_id", product_id); + r.set("product_name", sl.getStr("product_name")); + r.set("order_num", order_num); + r.set("weight", weight); + r.set("total_price", total_price); + retList.add(r); + shChildren.add(new Record().setColumns(r).remove("name").remove("item_name")); + } + } + if (flag) { + Record r = new Record(); + r.set("key", s_id + "_sh_1"); + r.set("id", s_id); + r.set("name", name); + r.set("item_name", "实售"); + r.set("product_id", 1); + r.set("product_name", "-"); + r.set("order_num", "-"); + r.set("weight", "-"); + r.set("total_price", "-"); + retList.add(r); + shChildren.add(new Record().setColumns(r).remove("name").remove("item_name")); + } + } + + shChildren.sort(new Comparator() { + @Override + public int compare(Record o1, Record o2) { + return o1.getInt("product_id") - o2.getInt("product_id"); + } + }); + sh.set("children", shChildren); + + Record yh = new Record(); + yh.set("key", s.getInt("id") + "_yh"); + yh.set("item_name", "预售"); + List yhChildren = new ArrayList<>(); + if (yhList1.size() > 0) { + boolean flag = true; + for (Record yl : yhList1) { + int yl_id = yl.getInt("id"); + if (s_id == yl_id) { + flag = false; + Record r = new Record(); + + BigDecimal total_price = yl.getBigDecimal("total_price"); + hj_yh_total_price += total_price.doubleValue(); + + r.set("key", yl_id + "_yh_1"); + r.set("id", s_id); + r.set("name", name); + r.set("item_name", "预售"); + r.set("product_name", "-"); + r.set("order_num", "-"); + r.set("weight", "-"); + r.set("total_price", total_price); + retList.add(r); + yhChildren.add(new Record().setColumns(r).remove("name").remove("item_name")); + } + } + if (flag) { + Record r2 = new Record(); + r2.set("key", s_id + "_yh_1"); + r2.set("id", s_id); + r2.set("name", name); + r2.set("item_name", "预售"); + r2.set("product_name", "-"); + r2.set("order_num", "-"); + r2.set("weight", "-"); + r2.set("total_price", "-"); + retList.add(r2); + yhChildren.add(new Record().setColumns(r2).remove("name").remove("item_name")); + } + } + yh.set("children", yhChildren); + List children = new ArrayList<>(); + + children.add(sh); + children.add(yh); + p.set("children", children); + + retChildren.add(p); + } + + retList.sort(new Comparator() { + @Override + public int compare(Record o1, Record o2) { + if (o1.getInt("product_id") != null && o2.getInt("product_id") != null + && o1.getInt("id") == o2.getInt("id")) { + return o1.getInt("product_id") - o2.getInt("product_id"); + } else if (o1.getInt("id") != null && o2.getInt("id") != null) { + return o1.getInt("id") - o2.getInt("id"); + } + return 1; + } + }); + + // 合计 + Record hj = new Record(); + List hj_sh_children = new ArrayList<>(); + List hj_yh_children = new ArrayList<>(); + + Record hj_sh_hs = new Record(); + hj_sh_hs.set("key", "hj_sh_1"); + hj_sh_hs.set("name", "合计"); + hj_sh_hs.set("item_name", "实售"); + hj_sh_hs.set("product_name", "黄砂"); + hj_sh_hs.set("order_num", hj_hs_sh_order_num); + hj_sh_hs.set("weight", hj_hs_sh_weight); + hj_sh_hs.set("total_price", hj_hs_sh_total_price); + retList.add(hj_sh_hs); + hj_sh_children.add(new Record().setColumns(hj_sh_hs).remove("name").remove("item_name")); + + Record hj_sh_els = new Record(); + hj_sh_els.set("key", "hj_sh_2"); + hj_sh_els.set("name", "合计"); + hj_sh_els.set("item_name", "实售"); + hj_sh_els.set("product_name", "鹅卵石"); + hj_sh_els.set("order_num", hj_els_sh_order_num); + hj_sh_els.set("weight", hj_els_sh_weight); + hj_sh_els.set("total_price", hj_els_sh_total_price); + retList.add(hj_sh_els); + hj_sh_children.add(new Record().setColumns(hj_sh_els).remove("name").remove("item_name")); + + Record hj_sh_jzs = new Record(); + hj_sh_jzs.set("key", "hj_sh_3"); + hj_sh_jzs.set("name", "合计"); + hj_sh_jzs.set("item_name", "实售"); + hj_sh_jzs.set("product_name", "机制砂"); + hj_sh_jzs.set("order_num", hj_jzs_sh_order_num); + hj_sh_jzs.set("weight", hj_jzs_sh_weight); + hj_sh_jzs.set("total_price", hj_jzs_sh_total_price); + retList.add(hj_sh_jzs); + hj_sh_children.add(hj_sh_jzs); + + Record hj_yh_1 = new Record(); + hj_yh_1.set("key", "hj_yh_1"); + hj_yh_1.set("name", "合计"); + hj_yh_1.set("item_name", "预售"); + hj_yh_1.set("product_name", "-"); + hj_yh_1.set("order_num", "-"); + hj_yh_1.set("weight", "-"); + hj_yh_1.set("total_price", hj_yh_total_price); + retList.add(hj_yh_1); + hj_yh_children.add(hj_yh_1); + + Record hj_sh = new Record(); + hj_sh.set("key", "hj_sh"); + hj_sh.set("item_name", "实售"); + hj_sh.set("children", hj_sh_children); + + Record hj_yh = new Record(); + hj_yh.set("key", "hj_yh"); + hj_yh.set("item_name", "预售"); + hj_yh.set("children", hj_yh_children); + + List hj_children = new ArrayList<>(); + hj_children.add(hj_sh); + hj_children.add(hj_yh); + + hj.set("key", "hj").set("name", "合计").set("children", hj_children); + retChildren.add(hj); + + // 总合计 + Record total = new Record(); + total.set("key", "total").set("name", "总合计").set("item_name", "-").set("product_name", "-") + .set("order_num", hj_hs_sh_order_num + hj_els_sh_order_num + hj_jzs_sh_order_num) + .set("weight", hj_hs_sh_weight + hj_els_sh_weight + hj_els_sh_weight) + .set("total_price", hj_hs_sh_total_price + hj_els_sh_total_price + hj_jzs_sh_total_price + hj_yh_total_price); + + retList.add(total); + + retChildren.add(total); + } + + return type == 1 ? retChildren : retList; + } } diff --git a/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/stat/sale/OrderStatController.java b/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/stat/sale/OrderStatController.java index c6494bf..569bc32 100644 --- a/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/stat/sale/OrderStatController.java +++ b/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/stat/sale/OrderStatController.java @@ -379,14 +379,17 @@ public class OrderStatController extends BaseController { } } + /** + * 按砂站年统计 + */ public void statYearBySup() { String tm = get("tm"); int export = getInt("export", 0); // 是否导出为exce 0 不导出,1 导出 Boolean stat_product = getBoolean("stat_product", false); if (export == 0) { - renderJson(Result.object(OrderStatService.me.salestat(tm))); + renderJson(Result.object(OrderStatService.me.statYearBySup(tm, 2))); } else { - Workbook wb = OrderStatService.me.yearsalestatExport(tm); + Workbook wb = OrderStatService.me.yearsalestatExportBySup(tm); render(new ExcelRender("按砂站总销售汇总表_" + System.currentTimeMillis() + ".xlsx", wb)); } }