Commit 9a1e5de5ac844a8360446d0e1b5b44b8309f0b47

Authored by chenhang4442024
1 parent 74490ef0

1.优化邮件发送

2.测试结果自动更新到产品意见
3.创建生产科时不重复自动添加到字典中
Showing 23 changed files with 1375 additions and 96 deletions
src/main/java/com/order/erp/common/utils/EasyPdfUtils.java 0 → 100644
  1 +package com.order.erp.common.utils;
  2 +
  3 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4 +import com.order.erp.common.constant.Constant;
  5 +import com.order.erp.common.exception.BusinessException;
  6 +import com.order.erp.domain.dto.BaseDO;
  7 +import com.order.erp.domain.dto.order.OrderBaseInfoDO;
  8 +import com.order.erp.domain.dto.order.OrderProfitAnalysisDO;
  9 +import com.order.erp.domain.pdf.OrderProducePdfVO;
  10 +import com.order.erp.domain.vo.FileRespVO;
  11 +import com.order.erp.domain.vo.ProducePdfVO;
  12 +import com.order.erp.service.LocalStorageService;
  13 +import com.order.erp.service.order.OrderBaseInfoService;
  14 +import com.order.erp.service.order.OrderProfitAnalysisService;
  15 +import lombok.extern.slf4j.Slf4j;
  16 +import org.springframework.beans.BeanUtils;
  17 +import org.springframework.beans.factory.annotation.Value;
  18 +import org.springframework.stereotype.Service;
  19 +import wiki.xsx.core.pdf.component.image.XEasyPdfImage;
  20 +import wiki.xsx.core.pdf.component.table.XEasyPdfCell;
  21 +import wiki.xsx.core.pdf.component.table.XEasyPdfRow;
  22 +import wiki.xsx.core.pdf.component.table.XEasyPdfTable;
  23 +import wiki.xsx.core.pdf.doc.*;
  24 +import wiki.xsx.core.pdf.handler.XEasyPdfHandler;
  25 +
  26 +import javax.annotation.Resource;
  27 +import java.io.File;
  28 +import java.io.InputStream;
  29 +import java.io.OutputStream;
  30 +import java.math.BigDecimal;
  31 +import java.math.RoundingMode;
  32 +import java.net.URL;
  33 +import java.util.*;
  34 +import java.util.function.Function;
  35 +import java.util.stream.Collectors;
  36 +//待拷贝start。
  37 +
  38 +/**
  39 + * @author: xms
  40 + * @description: TODO
  41 + * @date: 2024/7/17 16:30
  42 + * @version: 1.0
  43 + */
  44 +@Slf4j
  45 +@Service
  46 +public class EasyPdfUtils {
  47 +
  48 + @Resource
  49 + private OrderBaseInfoService orderBaseInfoService;
  50 +
  51 + @Resource
  52 + private OrderProfitAnalysisService profitAnalysisService;
  53 + @Resource
  54 + private LocalStorageService localStorageService;
  55 +
  56 + @Value("${file.path}")
  57 + private String path;
  58 +
  59 + public List<OrderProducePdfVO> build(List<Long> ids) {
  60 + List<OrderBaseInfoDO> orderBaseInfoDOList = orderBaseInfoService.list(new LambdaQueryWrapper<OrderBaseInfoDO>()
  61 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  62 + .in(OrderBaseInfoDO::getId, ids));
  63 + Set<String> productionDepartments = orderBaseInfoDOList.stream().map(OrderBaseInfoDO::getProductionDepartment).filter(Objects::nonNull)
  64 + .filter(department -> !department.trim().isEmpty()).collect(Collectors.toSet());
  65 + if (productionDepartments.size() > 1) {
  66 + throw new BusinessException("订单中包含多个不同生产科,请重新选择!");
  67 + }
  68 + //得到所选订单的创建人。
  69 + Set<String> createByList = orderBaseInfoDOList.stream().map(OrderBaseInfoDO::getCreateBy).collect(Collectors.toSet());
  70 + //得到所选订单的业务员。
  71 + Set<String> businessPersonList=orderBaseInfoDOList.stream().map(OrderBaseInfoDO::getBusinessPerson).collect(Collectors.toSet());
  72 + //去重。
  73 + HashSet<String> setPerson = new HashSet<>(createByList);
  74 + setPerson.addAll(businessPersonList);
  75 + List<String> personList= new ArrayList<>(setPerson);
  76 + Set<Long> orderIds = orderBaseInfoDOList.stream().map(OrderBaseInfoDO::getId).collect(Collectors.toSet());
  77 + List<OrderProfitAnalysisDO> profitAnalysisDOS = profitAnalysisService.list(new LambdaQueryWrapper<OrderProfitAnalysisDO>().in(OrderProfitAnalysisDO::getOrderId, orderIds));
  78 + Map<Long, OrderProfitAnalysisDO> profitAnalysisDOMap = profitAnalysisDOS.stream().collect(Collectors.toMap(OrderProfitAnalysisDO::getOrderId, Function.identity()));
  79 + return orderBaseInfoDOList.stream().map(x -> {
  80 + OrderProducePdfVO producePdfVO = new OrderProducePdfVO();
  81 + BeanUtils.copyProperties(x, producePdfVO);
  82 + OrderProfitAnalysisDO profitAnalysisDO = profitAnalysisDOMap.get(x.getId());
  83 + if (Objects.nonNull(profitAnalysisDO)) {
  84 + producePdfVO.setProductionDepartmentPrice(profitAnalysisDO.getProductionDepartmentPrice());
  85 + producePdfVO.setProductionDepartmentTotalPrice(profitAnalysisDO.getProductionDepartmentTotalPrice());
  86 + }
  87 + producePdfVO.setPersonList(personList);
  88 + return producePdfVO;
  89 + }).collect(Collectors.toList());
  90 + }
  91 +
  92 + /**
  93 + * @param pdfVOList
  94 + * @param fileName
  95 + * @return
  96 + */
  97 + public ProducePdfVO createProducePdf(List<OrderProducePdfVO> pdfVOList, String fileName, String companyName) {
  98 + Set<String> productionDepartments = pdfVOList.stream().map(OrderProducePdfVO::getProductionDepartment).filter(Objects::nonNull)
  99 + .filter(department -> !department.trim().isEmpty())
  100 + .collect(Collectors.toSet());
  101 + if (productionDepartments.size() > 1) {
  102 + throw new BusinessException("订单中包含多个不同生产科,请重新选择!");
  103 + }
  104 + String pathUri = path + "pdfs" + File.separator + AliOssUtil.getUniqueFileName(companyName);
  105 + OutputStream os = FileUtil.getOutputStream(pathUri);
  106 + XEasyPdfDocument document = createProducePdf(pdfVOList, companyName);
  107 + document.save(os);
  108 + File file = FileUtil.file(pathUri);
  109 + FileRespVO fileRespVO = localStorageService.getFilePath(file,companyName);
  110 + ProducePdfVO producePdfVO = new ProducePdfVO();
  111 + producePdfVO.setProductionUrl(fileRespVO.getFileUrl());
  112 + producePdfVO.setProductionDepartment(productionDepartments.iterator().next());
  113 + //得到订单的创建人和业务员。
  114 + producePdfVO.setProductionDepartment(productionDepartments.iterator().next());
  115 + Optional<List<String>> firstElementFromSet1 = pdfVOList.stream().findFirst().map(OrderProducePdfVO::getPersonList);
  116 + List<String> personList = firstElementFromSet1.orElse(Collections.emptyList());
  117 + producePdfVO.setPersonList(personList);
  118 + return producePdfVO;
  119 + }
  120 +
  121 + /**
  122 + * @param pdfVOList
  123 + * @return
  124 + */
  125 + public XEasyPdfDocument createProducePdf(List<OrderProducePdfVO> pdfVOList, String companyName) {
  126 + // 构建文档
  127 + XEasyPdfDocument document = XEasyPdfHandler.Document.build();
  128 + /* try {
  129 + // 表格
  130 + XEasyPdfTable table = createTable(pdfVOList, companyName);
  131 + XEasyPdfPage page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 500F), table);
  132 + if(pdfVOList.size()==1){
  133 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 1000F), table);
  134 + }else if(pdfVOList.size()==2){
  135 + // 创建页面
  136 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 500F), table);
  137 + } else if (pdfVOList.size()==3) {
  138 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 333F), table);
  139 + } else if (pdfVOList.size()==4) {
  140 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 250F), table);
  141 + } else if (pdfVOList.size()==5) {
  142 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 200F), table);
  143 + } else if (pdfVOList.size()==6) {
  144 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 166F), table);
  145 + } else if (pdfVOList.size()==7) {
  146 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 142F), table);
  147 + } else if (pdfVOList.size()==8) {
  148 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 125F), table);
  149 + } else if (pdfVOList.size()==9) {
  150 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 111F), table);
  151 + } else {
  152 + page = XEasyPdfHandler.Page.build(XEasyPdfPageRectangle.create(1700F, pdfVOList.size() * 100F), table);
  153 + }
  154 + // 将页面添加到文档
  155 + document.addPage(page);
  156 + // 添加页脚
  157 + document.setGlobalFooter(XEasyPdfHandler.Footer.build(
  158 + //构建文本(使用当前页占位符)
  159 + XEasyPdfHandler.Text.build(
  160 + XEasyPdfHandler.Page.getCurrentPagePlaceholder() +
  161 + "/" +
  162 + XEasyPdfHandler.Page.getTotalPagePlaceholder()).
  163 + setFontSize(10F).setHorizontalStyle(XEasyPdfPositionStyle.CENTER).
  164 + setDefaultFontStyle(XEasyPdfDefaultFontStyle.LIGHT)
  165 + ));
  166 + // 开启总页码占位符替换
  167 + document.enableReplaceTotalPagePlaceholder();
  168 + return document;
  169 + } catch (Exception e) {
  170 + return null;
  171 + }*/
  172 +
  173 + //第二版 线上版。
  174 + try {
  175 + // 每页最大行数
  176 + int rowsPerPage = 10;
  177 + int totalRows = pdfVOList.size();
  178 + int totalPages = (int) Math.ceil((double) totalRows / rowsPerPage);
  179 +
  180 + // 固定页面大小 (1700F 宽, 1000F 高)
  181 + XEasyPdfPageRectangle pageSize = XEasyPdfPageRectangle.create(1700F, 1000F);
  182 +
  183 + // 计算总计
  184 + Integer totalOrderCount = 0;
  185 + BigDecimal totalPrice = new BigDecimal(Constant.ZERO);
  186 +
  187 + for (OrderProducePdfVO producePdfVO : pdfVOList) {
  188 + totalOrderCount += Objects.nonNull(producePdfVO.getOrderCount()) ? producePdfVO.getOrderCount() : Constant.ZERO;
  189 + totalPrice = totalPrice.add(new BigDecimal(Objects.nonNull(producePdfVO.getProductionDepartmentTotalPrice()) ? producePdfVO.getProductionDepartmentTotalPrice() : Constant.ZERO).setScale(2, RoundingMode.HALF_UP));
  190 + }
  191 +
  192 + int currentIndex = 1; // 初始化当前编号
  193 +
  194 + for (int page = 0; page < totalPages; page++) {
  195 + // 计算当前页的数据
  196 + int startRow = page * rowsPerPage;
  197 + int endRow = Math.min(startRow + rowsPerPage, totalRows);
  198 + List<OrderProducePdfVO> pageData = pdfVOList.subList(startRow, endRow);
  199 + boolean isLastPage = (page == totalPages - 1);
  200 + // 创建表格并填充数据
  201 + XEasyPdfTable table = createTable(pageData, companyName, currentIndex, isLastPage, totalOrderCount, totalPrice);
  202 + currentIndex += pageData.size(); // 更新编号
  203 +
  204 + // 创建页面
  205 + XEasyPdfPage pdfPage = XEasyPdfHandler.Page.build(pageSize, table);
  206 + document.addPage(pdfPage);
  207 + }
  208 +
  209 + // 添加页脚
  210 + document.setGlobalFooter(XEasyPdfHandler.Footer.build(
  211 + XEasyPdfHandler.Text.build(
  212 + XEasyPdfHandler.Page.getCurrentPagePlaceholder() +
  213 + "/" +
  214 + XEasyPdfHandler.Page.getTotalPagePlaceholder())
  215 + .setFontSize(10F)
  216 + .setHorizontalStyle(XEasyPdfPositionStyle.CENTER)
  217 + .setDefaultFontStyle(XEasyPdfDefaultFontStyle.LIGHT)
  218 + ));
  219 +
  220 + // 开启总页码占位符替换
  221 + document.enableReplaceTotalPagePlaceholder();
  222 +
  223 + return document;
  224 + } catch (Exception e) {
  225 + e.printStackTrace();
  226 + return null;
  227 + }
  228 +
  229 + }
  230 +
  231 + /**
  232 + * @param imageFile
  233 + * @param width
  234 + * @return
  235 + */
  236 + private XEasyPdfCell createImageCell(File imageFile, float width) {
  237 + XEasyPdfImage image = XEasyPdfHandler.Image.build(imageFile).
  238 + setHeight(40F).setWidth(80F).
  239 + setMarginTop(0F).setMarginLeft(0F).
  240 + setVerticalStyle(XEasyPdfPositionStyle.CENTER).setHorizontalStyle(XEasyPdfPositionStyle.CENTER);
  241 +
  242 + XEasyPdfCell cell = XEasyPdfHandler.Table.Row.Cell.build(width, 60F).
  243 + addContent(image).
  244 + setVerticalStyle(XEasyPdfPositionStyle.CENTER).
  245 + setHorizontalStyle(XEasyPdfPositionStyle.CENTER).
  246 + enableCenterStyle().enableComponentSelfStyle();
  247 + return cell;
  248 + }
  249 +
  250 + /**
  251 + * @param text
  252 + * @param width
  253 + * @return
  254 + */
  255 + private XEasyPdfCell createCell(String text, float width, float fontSize) {
  256 + XEasyPdfCell cell = XEasyPdfHandler.Table.Row.Cell.build(width, 50F).
  257 + addContent(XEasyPdfHandler.Text.build(text).
  258 + setVerticalStyle(XEasyPdfPositionStyle.CENTER).
  259 + setHorizontalStyle(XEasyPdfPositionStyle.CENTER).
  260 + setDefaultFontStyle(XEasyPdfDefaultFontStyle.LIGHT).setFontSize(fontSize)).
  261 + enableCenterStyle().enableComponentSelfStyle();
  262 + return cell;
  263 + }
  264 +
  265 + /**
  266 + * @param text
  267 + * @param width
  268 + * @return
  269 + */
  270 + private XEasyPdfCell createCell(String text, float width, float height, float fontSize, XEasyPdfDefaultFontStyle fontStyle) {
  271 + XEasyPdfCell cell = XEasyPdfHandler.Table.Row.Cell.build(width, height).
  272 + addContent(XEasyPdfHandler.Text.build(text).
  273 + setVerticalStyle(XEasyPdfPositionStyle.CENTER).
  274 + setHorizontalStyle(XEasyPdfPositionStyle.CENTER).
  275 + setDefaultFontStyle(fontStyle).setFontSize(fontSize)).
  276 + enableCenterStyle().enableComponentSelfStyle();
  277 + return cell;
  278 + }
  279 +
  280 + /**
  281 + * @param text
  282 + * @param width
  283 + * @return
  284 + */
  285 + private XEasyPdfCell createCell(String text, float width) {
  286 + XEasyPdfCell cell = XEasyPdfHandler.Table.Row.Cell.build(width).
  287 + addContent(XEasyPdfHandler.Text.build(text).
  288 + setVerticalStyle(XEasyPdfPositionStyle.CENTER).
  289 + setHorizontalStyle(XEasyPdfPositionStyle.CENTER).
  290 + setDefaultFontStyle(XEasyPdfDefaultFontStyle.LIGHT).setFontSize(16)).
  291 + enableCenterStyle().enableComponentSelfStyle();
  292 + return cell;
  293 + }
  294 +
  295 + /**
  296 + * @param text
  297 + * @param width
  298 + * @return
  299 + */
  300 + private XEasyPdfCell createCell(String text, float width, float height, float fontSize,
  301 + XEasyPdfDefaultFontStyle fontStyle,
  302 + XEasyPdfPositionStyle verticalStyle,
  303 + XEasyPdfPositionStyle horizontalStyle) {
  304 + XEasyPdfCell cell = XEasyPdfHandler.Table.Row.Cell.build(width, height).
  305 + addContent(XEasyPdfHandler.Text.build(text).
  306 + setVerticalStyle(verticalStyle).
  307 + setHorizontalStyle(horizontalStyle).
  308 + setDefaultFontStyle(fontStyle).setFontSize(fontSize)).
  309 + enableCenterStyle().enableComponentSelfStyle();
  310 + return cell;
  311 + }
  312 +
  313 + /**
  314 + * @return
  315 + */
  316 + private XEasyPdfTable createTable(List<OrderProducePdfVO> pdfVOList, String companyName, int startIndex,boolean isLastPage,Integer totalOrderCount, BigDecimal totalPrice) throws Exception {
  317 + XEasyPdfTable table = XEasyPdfHandler.Table.build();
  318 + List<XEasyPdfRow> rowList = new ArrayList<>();
  319 + List<XEasyPdfCell> cellList = new ArrayList<>(15);
  320 + List<XEasyPdfCell> header = new ArrayList<>(1);
  321 + if ("青岛吉庆天成饰品有限公司".equals(companyName)) {
  322 + header.add(createCell("青岛吉庆天成生产订单", 1660F, 70F, 24F, XEasyPdfDefaultFontStyle.BOLD));
  323 + } else {
  324 + header.add(createCell("青岛翱特逸格生产订单", 1660F, 70F, 24F, XEasyPdfDefaultFontStyle.BOLD));
  325 + }
  326 + rowList.add(XEasyPdfHandler.Table.Row.build(header));
  327 + // 第一行设置表头,默认标题
  328 + cellList.add(createCell("编号", 90F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  329 + cellList.add(createCell("项目号", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  330 + cellList.add(createCell("生产科", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  331 + cellList.add(createCell("内部编号", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  332 + cellList.add(createCell("客户订单号", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  333 + cellList.add(createCell("客户款号", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  334 + cellList.add(createCell("订单颜色", 140F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  335 + cellList.add(createCell("颜色中文", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  336 + cellList.add(createCell("订单图片", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  337 + cellList.add(createCell("产品意见", 150F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  338 + cellList.add(createCell("订单数量", 90F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  339 + cellList.add(createCell("生产科交期", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  340 + cellList.add(createCell("包装类型", 90F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  341 + cellList.add(createCell("生产科单价", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  342 + cellList.add(createCell("生产科总价", 110F, 60F, 16F, XEasyPdfDefaultFontStyle.BOLD));
  343 + rowList.add(XEasyPdfHandler.Table.Row.build(cellList));
  344 +
  345 + for (int i = 0; i < pdfVOList.size(); i++) {
  346 + OrderProducePdfVO producePdfVO = pdfVOList.get(i);
  347 + String productionDepartmentConsignTime = StringUtils.isNotBlank(producePdfVO.getProductionDepartmentConsignTime()) ?
  348 + DateUtils.format(DateUtils.parseDate(producePdfVO.getProductionDepartmentConsignTime(), DateUtils.DATE_TIME), DateUtils.DATE) : "";
  349 +
  350 + List<XEasyPdfCell> dataCellList = new ArrayList<>(15);
  351 + dataCellList.add(createCell("" + (startIndex + i), 90F)); // 使用连续编号
  352 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getProjectNo()) ? producePdfVO.getProjectNo() : "", 110F));
  353 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getProductionDepartment()) ? producePdfVO.getProductionDepartment() : "", 110F));
  354 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getInnerNo()) ? producePdfVO.getInnerNo() : "", 110F));
  355 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getCustomerPo()) ? producePdfVO.getCustomerPo() : "", 110F));
  356 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getCustomerStyle()) ? producePdfVO.getCustomerStyle() : "", 110F));
  357 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getPoColor()) ? producePdfVO.getPoColor() : "", 140F));
  358 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getCnColor()) ? producePdfVO.getCnColor() : "", 110F));
  359 + if (StringUtils.isNotBlank(producePdfVO.getPicUrl())) {
  360 + URL url = new URL(producePdfVO.getPicUrl());
  361 + InputStream inputStream = url.openStream();
  362 + File imageFile = FileUtil.inputStreamToFile(inputStream, "order" + System.currentTimeMillis() + ".png");
  363 +
  364 + dataCellList.add(createImageCell(imageFile, 110F));
  365 + } else {
  366 + dataCellList.add(createCell("", 110F));
  367 + }
  368 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getProductionComment()) ? producePdfVO.getProductionComment() : "", 150F));
  369 + if (Constant.ZERO == producePdfVO.getOrderCount()) {
  370 + dataCellList.add(createCell("", 90F));
  371 + } else {
  372 + dataCellList.add(createCell("" + producePdfVO.getOrderCount(), 90F));
  373 + }
  374 + dataCellList.add(createCell(productionDepartmentConsignTime, 110F));
  375 + dataCellList.add(createCell(StringUtils.isNotEmpty(producePdfVO.getPacketType()) ? producePdfVO.getPacketType() : "", 90F));
  376 + dataCellList.add(createCell(Objects.nonNull(producePdfVO.getProductionDepartmentPrice()) ? "" + producePdfVO.getProductionDepartmentPrice() : "", 110F));
  377 + dataCellList.add(createCell(Objects.nonNull(producePdfVO.getProductionDepartmentTotalPrice()) ? "" + producePdfVO.getProductionDepartmentTotalPrice() : "", 110F));
  378 + rowList.add(XEasyPdfHandler.Table.Row.build(dataCellList));
  379 + }
  380 +
  381 + if (isLastPage) {
  382 + List<XEasyPdfCell> endCellList = new ArrayList<>(15);
  383 + endCellList.add(createCell("合计", 90F, 16F));
  384 + endCellList.add(createCell("", 110F));
  385 + endCellList.add(createCell("", 110F));
  386 + endCellList.add(createCell("", 110F));
  387 + endCellList.add(createCell("", 110F));
  388 + endCellList.add(createCell("", 110F));
  389 + endCellList.add(createCell("", 140F));
  390 + endCellList.add(createCell("", 110F));
  391 + endCellList.add(createCell("", 110F));
  392 + endCellList.add(createCell("", 150F));
  393 + endCellList.add(createCell("" + totalOrderCount, 90F, 16F));
  394 + endCellList.add(createCell("", 110F));
  395 + endCellList.add(createCell("", 90F));
  396 + endCellList.add(createCell("", 110F));
  397 + endCellList.add(createCell("" + totalPrice, 110F, 16F));
  398 + rowList.add(XEasyPdfHandler.Table.Row.build(endCellList));
  399 + }
  400 +
  401 + List<XEasyPdfCell> signList = new ArrayList<>(2);
  402 + if ("青岛吉庆天成饰品有限公司".equals(companyName)) {
  403 + signList.add(createCell("吉庆天成签字+日期:", 640F, 80F, 20F, XEasyPdfDefaultFontStyle.BOLD, XEasyPdfPositionStyle.CENTER, XEasyPdfPositionStyle.LEFT));
  404 + } else {
  405 + signList.add(createCell("翱特逸格签字+日期:", 640F, 80F, 20F, XEasyPdfDefaultFontStyle.BOLD, XEasyPdfPositionStyle.CENTER, XEasyPdfPositionStyle.LEFT));
  406 + }
  407 + signList.add(createCell("外加工签字+日期:", 1020F, 80F, 20F, XEasyPdfDefaultFontStyle.BOLD, XEasyPdfPositionStyle.CENTER, XEasyPdfPositionStyle.LEFT));
  408 + rowList.add(XEasyPdfHandler.Table.Row.build(signList));
  409 +
  410 + table.addRow(rowList);
  411 + table.setHorizontalStyle(XEasyPdfPositionStyle.CENTER).setMarginLeft(10F).setMarginTop(60F).setMarginBottom(10F);
  412 + return table;
  413 + }
  414 +
  415 +
  416 +}
  417 +//待拷贝end。
0 418 \ No newline at end of file
... ...
src/main/java/com/order/erp/common/utils/OrderFieldUtils.java
... ... @@ -309,6 +309,9 @@ public class OrderFieldUtils {
309 309 if (OrderLockFieldEnum.UN_LOCKED.getStatus().equals(baseFields.getBusinessPerson())) {
310 310 return true;
311 311 }
  312 + if (OrderLockFieldEnum.UN_LOCKED.getStatus().equals(baseFields.getReturnOrder())) {
  313 + return true;
  314 + }
312 315  
313 316 return false;
314 317 }
... ... @@ -358,6 +361,7 @@ public class OrderFieldUtils {
358 361 .productStyle(locked)
359 362 .projectNo(locked)
360 363 .businessPerson(locked)
  364 + .returnOrder(locked)
361 365 .build();
362 366 }
363 367  
... ...
src/main/java/com/order/erp/controller/OrderController.java
... ... @@ -4,6 +4,7 @@ import com.order.erp.common.annotation.AnonymousAccess;
4 4 import com.order.erp.common.constant.ServerResult;
5 5 import com.order.erp.common.excel4j.exceptions.Excel4JException;
6 6 import com.order.erp.common.exception.BusinessException;
  7 +import com.order.erp.domain.vo.ProducePdfVO;
7 8 import com.order.erp.domain.vo.order.*;
8 9 import com.order.erp.mapper.order.OrderBaseInfoMapper;
9 10 import com.order.erp.service.order.OrderBaseInfoService;
... ... @@ -157,6 +158,28 @@ public class OrderController {
157 158 return orderBaseInfoService.check(orderBaseInfoQueryVO);
158 159 }
159 160  
  161 + /**
  162 + * 一次性通过率
  163 + *
  164 + * @param orderOpinionLogVO 查询条件
  165 + * @return 查询结果
  166 + */
  167 + @PostMapping("/passRate")
  168 + @AnonymousAccess
  169 + public ServerResult oneTimePassRate(@RequestBody OrderOpinionLogVO orderOpinionLogVO) {
  170 + return orderBaseInfoService.passRate(orderOpinionLogVO);
  171 + }
  172 +
  173 + @PostMapping("/produceReport")
  174 + public ServerResult produceReport(@RequestBody ProducePdfVO producePdfVO) {
  175 + return orderBaseInfoService.produceReport(producePdfVO);
  176 + }
  177 +
  178 + @PostMapping("/send")
  179 + public ServerResult send(@RequestBody ProducePdfVO producePdfVO) throws Exception {
  180 + return orderBaseInfoService.send(producePdfVO);
  181 + }
  182 +
160 183  
161 184 }
162 185  
... ...
src/main/java/com/order/erp/controller/OrderOpinionLonController.java 0 → 100644
  1 +package com.order.erp.controller;
  2 +
  3 +import com.order.erp.common.annotation.AnonymousAccess;
  4 +import com.order.erp.common.constant.ServerResult;
  5 +import com.order.erp.domain.vo.order.OrderOpinionLogVO;
  6 +import com.order.erp.service.order.OrderOpinionLogService;
  7 +import io.swagger.annotations.Api;
  8 +import io.swagger.annotations.ApiOperation;
  9 +import org.springframework.validation.annotation.Validated;
  10 +import org.springframework.web.bind.annotation.PostMapping;
  11 +import org.springframework.web.bind.annotation.RequestBody;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RestController;
  14 +
  15 +import javax.annotation.Resource;
  16 +
  17 +/**
  18 + *
  19 + * 订单跟单结果记录日志表(OrderOpinionLogDO)表控制层
  20 + * @Author:ch
  21 + * @createTime:2024-08-05
  22 + */
  23 +@Api(tags = "订单跟单结果记录")
  24 +@RestController
  25 +@RequestMapping("/order/erp/opinion/log")
  26 +public class OrderOpinionLonController {
  27 +
  28 + @Resource
  29 + private OrderOpinionLogService orderOpinionLogService;
  30 +
  31 + @PostMapping("/query_by_id")
  32 + @ApiOperation("查询订单的跟单结果记录")
  33 + @AnonymousAccess
  34 + public ServerResult queryById(@RequestBody @Validated OrderOpinionLogVO orderOpinionLogVo){
  35 + return orderOpinionLogService.queryById(orderOpinionLogVo);
  36 + }
  37 +
  38 +}
... ...
src/main/java/com/order/erp/domain/EmailTemplateEnum.java
... ... @@ -33,6 +33,8 @@ public enum EmailTemplateEnum {
33 33  
34 34 PRODUCE_INDICATE_REPORT("生产指示书报告","你好,请查收附件生产订单",10L),
35 35  
  36 + PRODUCE_IDEA("产品意见信息","你好,请查收产品意见信息",11L),
  37 +
36 38 ;
37 39  
38 40 private String title;
... ...
src/main/java/com/order/erp/domain/OrderOpinionLogEnum.java 0 → 100644
  1 +package com.order.erp.domain;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +//待拷贝START。
  6 +
  7 +/**
  8 + * @Author:ch
  9 + * @createTime:2024-08-05
  10 + */
  11 +
  12 +@Getter
  13 +@AllArgsConstructor
  14 +public enum OrderOpinionLogEnum {
  15 + ORDER_PRODUCTION_COMMENT("productionComment","产品意见"),
  16 + ORDER_PP_CONFIRRM_RESULT("ppConfirmResult","pp样品确认意见"),
  17 + ORDER_SHIPMENT_SAMPLE_CONFIRM_RESULT("shippmentSampleConfirmResult","shipment sample确认意见"),
  18 + ORDER_AITEX_TEST_FINISH_RESULT("aitexTestResult","Altex测试结果"),
  19 + ORDER_SGS_TEST_FINISH_RESULT("sgsTestFinishResult","SGS测试结果"),
  20 + ;
  21 + private String type;
  22 +
  23 + private String desc;
  24 +}
  25 +//待拷贝END。
0 26 \ No newline at end of file
... ...
src/main/java/com/order/erp/domain/dto/order/OrderBaseInfoDO.java
... ... @@ -115,4 +115,9 @@ public class OrderBaseInfoDO extends BaseDO implements Serializable {
115 115 * 业务员
116 116 */
117 117 private String businessPerson;
  118 +
  119 + /**
  120 + * 是否返单
  121 + */
  122 + private String returnOrder;
118 123 }
... ...
src/main/java/com/order/erp/domain/dto/order/OrderOpinionLogDO.java 0 → 100644
  1 +package com.order.erp.domain.dto.order;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableName;
  4 +import com.order.erp.domain.dto.BaseDO;
  5 +import lombok.*;
  6 +import lombok.experimental.SuperBuilder;
  7 +
  8 +import java.io.Serializable;
  9 +
  10 +/**
  11 + * @Author:ch
  12 + * @createTime:2024-08-05
  13 + * @Description:订单跟单结果记录日志表。
  14 + */
  15 +//待拷贝start。
  16 +@TableName("order_opinion_log")
  17 +@Data
  18 +@AllArgsConstructor
  19 +@ToString
  20 +@NoArgsConstructor
  21 +@EqualsAndHashCode(callSuper = false)
  22 +@SuperBuilder
  23 +public class OrderOpinionLogDO extends BaseDO implements Serializable {
  24 + private Long id;
  25 +
  26 + /**
  27 + * 订单id
  28 + */
  29 + private Long orderId;
  30 + /**
  31 + * 意见类型(SGS/Aitex/SHIPPMENT/PP/产品意见)
  32 + */
  33 + private String opinionType;
  34 +
  35 + /**
  36 + * 更新字段
  37 + */
  38 + private String field;
  39 +}
  40 +//待拷贝end。
0 41 \ No newline at end of file
... ...
src/main/java/com/order/erp/domain/pdf/OrderProducePdfVO.java 0 → 100644
  1 +package com.order.erp.domain.pdf;
  2 +
  3 +import lombok.*;
  4 +import lombok.experimental.SuperBuilder;
  5 +
  6 +import java.io.Serializable;
  7 +import java.util.List;
  8 +//待拷贝start。
  9 +
  10 +/**
  11 + * 生产指示书pdf
  12 + *
  13 + * @author makejava
  14 + * @since 2023-09-08 15:26:43
  15 + */
  16 +@Data
  17 +@AllArgsConstructor
  18 +@ToString
  19 +@NoArgsConstructor
  20 +@EqualsAndHashCode(callSuper = false)
  21 +@SuperBuilder
  22 +public class OrderProducePdfVO implements Serializable {
  23 +
  24 + /**
  25 + * 项目号
  26 + */
  27 + private String projectNo;
  28 +
  29 + /**
  30 + * 生产科
  31 + */
  32 + private String productionDepartment;
  33 +
  34 + /**
  35 + * 内部编号
  36 + */
  37 + private String innerNo;
  38 +
  39 + /**
  40 + * 客户po号(客户订单号)
  41 + */
  42 + private String customerPo;
  43 +
  44 + /**
  45 + * 客户STYLE#(客户款号)
  46 + */
  47 + private String customerStyle;
  48 +
  49 + /**
  50 + * PO COLOR (订单颜色)
  51 + */
  52 + private String poColor;
  53 +
  54 + /**
  55 + * 颜色中文
  56 + */
  57 + private String cnColor;
  58 +
  59 + /**
  60 + * pic图片地址(订单图片)
  61 + */
  62 + private String picUrl;
  63 +
  64 + /**
  65 + * 产品意见
  66 + */
  67 + private String productionComment;
  68 +
  69 + /**
  70 + * 订单数量
  71 + */
  72 + private Integer orderCount;
  73 +
  74 + /**
  75 + * 生成科拖货时间(生产科交期)
  76 + */
  77 + private String productionDepartmentConsignTime;
  78 +
  79 + /**
  80 + * 包装类型
  81 + */
  82 + private String packetType;
  83 +
  84 + /**
  85 + * 生成科单价¥
  86 + */
  87 + private Double productionDepartmentPrice;
  88 +
  89 + /**
  90 + * 生成科总价¥
  91 + */
  92 + private Double productionDepartmentTotalPrice;
  93 + /**
  94 + * 注意:创建订单的用户以及订单对应的业务员 这个不需要导出
  95 + */
  96 + private List<String> personList;
  97 +
  98 +}
  99 +//待拷贝end。
0 100 \ No newline at end of file
... ...
src/main/java/com/order/erp/domain/vo/ProducePdfVO.java 0 → 100644
  1 +package com.order.erp.domain.vo;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.ToString;
  7 +
  8 +import java.util.List;
  9 +
  10 +@Data
  11 +@AllArgsConstructor
  12 +@NoArgsConstructor
  13 +@ToString
  14 +public class ProducePdfVO {
  15 +
  16 + private List<Long> ids;
  17 +
  18 + private String companyName;
  19 + /**
  20 + * 生产科
  21 + */
  22 + private String productionDepartment;
  23 +
  24 + private String productionUrl;
  25 +
  26 + private Boolean isSend;
  27 + private List<String> personList;
  28 +
  29 +}
... ...
src/main/java/com/order/erp/domain/vo/order/OrderBaseFieldVO.java
... ... @@ -106,4 +106,9 @@ public class OrderBaseFieldVO implements Serializable {
106 106 */
107 107 private String businessPerson = OrderLockFieldEnum.LOCKED.getStatus();
108 108  
  109 + /**
  110 + * 是否返单
  111 + */
  112 + private String returnOrder = OrderLockFieldEnum.LOCKED.getStatus();
  113 +
109 114 }
... ...
src/main/java/com/order/erp/domain/vo/order/OrderBaseInfoVO.java
... ... @@ -117,4 +117,9 @@ public class OrderBaseInfoVO implements Serializable {
117 117 */
118 118 private String businessPerson;
119 119  
  120 + /**
  121 + * 是否返单
  122 + */
  123 + private String returnOrder;
  124 +
120 125 }
121 126 \ No newline at end of file
... ...
src/main/java/com/order/erp/domain/vo/order/OrderOpinionLogVO.java 0 → 100644
  1 +package com.order.erp.domain.vo.order;
  2 +
  3 +import lombok.*;
  4 +import lombok.experimental.SuperBuilder;
  5 +
  6 +import java.util.List;
  7 +//待拷贝start。
  8 +
  9 +/**
  10 + * @Author:ch
  11 + * @createTime:2024-08-07
  12 + */
  13 +@Data
  14 +@AllArgsConstructor
  15 +@ToString
  16 +@NoArgsConstructor
  17 +@EqualsAndHashCode(callSuper = false)
  18 +@SuperBuilder
  19 +public class OrderOpinionLogVO {
  20 + private List<Long> ids;
  21 +
  22 + /**
  23 + * 订单id
  24 + */
  25 + private Long orderId;
  26 + /**
  27 + * 意见类型(SGS/Aitex/SHIPPMENT/PP/产品意见)
  28 + */
  29 + private String opinionType;
  30 +
  31 + /**
  32 + * 更新字段
  33 + */
  34 + private String field;
  35 +}
  36 +//待拷贝end。
0 37 \ No newline at end of file
... ...
src/main/java/com/order/erp/job/OrderOverTimeEventJob.java
... ... @@ -20,8 +20,11 @@ import com.order.erp.service.order.*;
20 20 import lombok.extern.slf4j.Slf4j;
21 21 import org.springframework.scheduling.annotation.Scheduled;
22 22 import org.springframework.stereotype.Component;
  23 +import org.w3c.dom.events.Event;
  24 +
23 25 import javax.annotation.Resource;
24 26 import java.time.LocalDate;
  27 +import java.time.format.DateTimeFormatter;
25 28 import java.time.temporal.ChronoUnit;
26 29 import java.util.*;
27 30 import java.util.concurrent.TimeUnit;
... ... @@ -63,10 +66,11 @@ public class OrderOverTimeEventJob {
63 66 private AdminUserService adminUserService;
64 67  
65 68 /**
66   - * 凌晨5点执行,一天一次
  69 + * 凌晨1点执行,一天一次
67 70 */
68 71  
69 72 @Scheduled(cron = "0 0 5 * * ?")
  73 +
70 74 //存储的日期都必须为yyyy-MM-dd HH:mm:ss。
71 75 public void checkOverTimeExecuteV2() {
72 76 List<OrderBaseInfoDO> orderBaseInfoDOList = orderBaseInfoService.getEventList();
... ... @@ -120,7 +124,7 @@ public class OrderOverTimeEventJob {
120 124 }).filter(Objects::nonNull)
121 125 .collect(Collectors.toList());
122 126 //如果为尾期验货事件的话,需要从订单中的生产科角色中得到邮箱。而不是从邮件配置中得到邮箱。
123   - if (OrderEventEnum.END_CHECK_DATE_EVENT.equals(eventEnum) ) {
  127 + if (OrderEventEnum.END_CHECK_DATE_EVENT.equals(eventEnum)) {
124 128 for (OrderEventJobVO orderEventJob : eventJobVOS) {
125 129 if (!redisUtils.hasKey(EmailTemplateEnum.byTemplate(
126 130 eventEnum.getTemplateId()) + Constant.CROSS_BAR_CHARACTER + orderEventJob.getBaseInfo().getId())) {
... ... @@ -133,17 +137,44 @@ public class OrderOverTimeEventJob {
133 137 AdminUserDO productionDepartmentUser = adminUserService.getOne(new LambdaQueryWrapper<AdminUserDO>()
134 138 .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
135 139 .eq(AdminUserDO::getUserName, productionDepartment));
136   - if(Objects.nonNull(productionDepartmentUser) && StringUtils.isNotBlank(productionDepartmentUser.getEmail())){
  140 + log.info("------------------------------------------------------------------------------------");
  141 + //得到订单的尾期验货日期的邮件配置中的邮箱。
  142 + LambdaQueryWrapper<ReceiveEmailMappingDO> receiveEmailMappingDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
  143 + receiveEmailMappingDOLambdaQueryWrapper.eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN);
  144 + if(!orderEventJob.getBaseInfo().getCustomerCode().contains("-") && !orderEventJob.getBaseInfo().getCustomerCode().contains("——")){
  145 + receiveEmailMappingDOLambdaQueryWrapper.eq(ReceiveEmailMappingDO::getTypeValue, orderEventJob.getBaseInfo().getCustomerCode())
  146 + .last("limit 1");
  147 + }else{
  148 + receiveEmailMappingDOLambdaQueryWrapper.like(ReceiveEmailMappingDO::getTypeValue, orderEventJob.getBaseInfo().getCustomerCode().split("-")[0])
  149 + .last("limit 1");
  150 + }
  151 + ReceiveEmailMappingDO receiveEmailMappingDO = receiveEmailMappingService.getOne( receiveEmailMappingDOLambdaQueryWrapper);
  152 + List<String> emailList = new ArrayList<>();
  153 + if (Objects.nonNull(receiveEmailMappingDO)) {
  154 + List<ReceiveEmailConfigItemVO> receiveEmailConfigItemVOList = JSON.parseObject(
  155 + receiveEmailMappingDO.getConfigInfos(), new TypeReference<List<ReceiveEmailConfigItemVO>>() {
  156 + });
  157 + for (ReceiveEmailConfigItemVO item : receiveEmailConfigItemVOList) {
  158 + if (eventEnum.getEvent().equals(item.getEvent())) {
  159 + emailList = item.getEmails();
  160 + }
  161 + }
  162 + }
  163 + if (Objects.nonNull(productionDepartmentUser) && CollectionUtils.isNotEmpty(emailList)) {
  164 + List<String> emails = emailList.stream().flatMap(email -> Arrays.stream(email.split("[,,]+"))).collect(Collectors.toList());
137 165 List<String> productionEmail = Arrays.asList(productionDepartmentUser.getEmail().split("[,,]+"))
138 166 .stream().map(String::trim)
  167 + .filter(Objects::nonNull)
139 168 .collect(Collectors.toList());
  169 + List<String> combineEmail = new ArrayList<>(emails);
  170 + combineEmail.addAll(productionEmail);
140 171 emailSendUtils.sendEmail(EmailTemplateEnum.byTemplate(eventEnum.getTemplateId()),
141   - productionEmail, orderEventJob);
  172 + combineEmail, orderEventJob);
142 173 redisUtils.set(EmailTemplateEnum.byTemplate(
143   - eventEnum.getTemplateId()) + Constant.CROSS_BAR_CHARACTER +orderEventJob.getBaseInfo().getId(),
  174 + eventEnum.getTemplateId()) + Constant.CROSS_BAR_CHARACTER + orderEventJob.getBaseInfo().getId(),
144 175 orderEventJob, 90, TimeUnit.DAYS);
145 176 }
146   -
  177 + log.info("------------------------------------------------------------------------------------");
147 178 }
148 179 }
149 180 } else {
... ... @@ -281,7 +312,13 @@ public class OrderOverTimeEventJob {
281 312 String ppConfirmResult = eventJobVO.getTrackStageInfo().getPpConfirmResult();
282 313 if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(ppConfirmResult) && StringUtils.isNotBlank(ppConfirmTime)) {
283 314 int daysBetween = getDaysBetween(ppConfirmResult, ppConfirmTime, orderHodTime);
284   - if (daysBetween == Constant.TWENTY_FIRST || daysBetween == Constant.NEGATIVE_ONE) {
  315 + if (Constant.TWENTY_FIRST == daysBetween|| Constant.NEGATIVE_ONE ==daysBetween) {
  316 + return true;
  317 + }
  318 + } else {
  319 + LocalDate today = LocalDate.now();
  320 + LocalDate localDate = DateUtils.parseDate(orderHodTime);
  321 + if (Constant.TWENTY_FIRST == (int) ChronoUnit.DAYS.between(today, localDate) && StringUtils.isEmpty(ppConfirmResult)) {
285 322 return true;
286 323 }
287 324 }
... ... @@ -290,15 +327,11 @@ public class OrderOverTimeEventJob {
290 327  
291 328 private Boolean filterOtherSampleEvent(OrderEventJobVO eventJobVO) {
292 329 String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
293   - String esoSampleSendTime = eventJobVO.getTrackStageInfo().getEsoSampleSendTime();
294   - if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(esoSampleSendTime)) {
295   - LocalDate orderHodTimelocalDate = DateUtils.parseDate(orderHodTime);
296   - LocalDate esoSampleSendTimelocalDate = DateUtils.parseDate(esoSampleSendTime);
297   - if (ChronoUnit.DAYS.between(esoSampleSendTimelocalDate, orderHodTimelocalDate) == Constant.FOURTEEN) {
  330 + LocalDate today = LocalDate.now();
  331 + LocalDate localDate = DateUtils.parseDate(orderHodTime);
  332 + if ( Constant.FOURTEEN==(int) ChronoUnit.DAYS.between(today, localDate) && StringUtils.isBlank(eventJobVO.getTrackStageInfo().getEsoSampleSendTime())) {
298 333 return true;
299 334 }
300   -
301   - }
302 335 return false;
303 336 }
304 337  
... ... @@ -308,7 +341,13 @@ public class OrderOverTimeEventJob {
308 341 String shippmentSampleConfirmTime = eventJobVO.getTrackStageInfo().getShippmentSampleConfirmTime();
309 342 if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(shippmentSampleConfirmResult) && StringUtils.isNotBlank(shippmentSampleConfirmTime)) {
310 343 int daysBetween = getDaysBetween(shippmentSampleConfirmResult, shippmentSampleConfirmTime, orderHodTime);
311   - if (daysBetween == Constant.SEVEN || daysBetween == Constant.NEGATIVE_ONE) {
  344 + if ( Constant.SEVEN ==daysBetween || Constant.NEGATIVE_ONE==daysBetween ) {
  345 + return true;
  346 + }
  347 + } else {
  348 + LocalDate today = LocalDate.now();
  349 + LocalDate localDate = DateUtils.parseDate(orderHodTime);
  350 + if ( Constant.SEVEN ==(int) ChronoUnit.DAYS.between(today, localDate) && StringUtils.isBlank(shippmentSampleConfirmResult)) {
312 351 return true;
313 352 }
314 353 }
... ... @@ -317,20 +356,27 @@ public class OrderOverTimeEventJob {
317 356  
318 357  
319 358 private Boolean filterAITEXSGSTestEvent(OrderEventJobVO eventJobVO) {
320   - int aitextestDaysBetween=0;
321   - int sgstestDaysBetween=0;
  359 + int aitextestDaysBetween = 0;
  360 + int sgstestDaysBetween = 0;
322 361 String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
323 362 String aitexTestFinishResult = eventJobVO.getTrackStageInfo().getAitexTestFinishResult();
324 363 String sgsTestFinishResult = eventJobVO.getTrackStageInfo().getSgsTestFinishResult();
325 364 String sgsTestFinishTime = eventJobVO.getTrackStageInfo().getSgsTestFinishTime();
326 365 String aitexTestFinishTime = eventJobVO.getTrackStageInfo().getAitexTestFinishTime();
327   - if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(aitexTestFinishResult) && StringUtils.isNotBlank(aitexTestFinishTime)){
  366 + if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(aitexTestFinishResult) && StringUtils.isNotBlank(aitexTestFinishTime)) {
328 367 aitextestDaysBetween = getDaysBetween(aitexTestFinishResult, aitexTestFinishTime, orderHodTime);
329 368 }
330   - if(StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(sgsTestFinishResult) && StringUtils.isNotBlank(sgsTestFinishTime)){
  369 + if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(sgsTestFinishResult) && StringUtils.isNotBlank(sgsTestFinishTime)) {
331 370 sgstestDaysBetween = getDaysBetween(sgsTestFinishResult, sgsTestFinishTime, orderHodTime);
332 371 }
333   - if (Constant.THREE == aitextestDaysBetween || Constant.THREE == sgstestDaysBetween || Constant.NEGATIVE_ONE == aitextestDaysBetween || Constant.NEGATIVE_ONE == sgstestDaysBetween ) {
  372 + if ((StringUtils.isEmpty(aitexTestFinishResult) && StringUtils.isEmpty(sgsTestFinishResult)) || (StringUtils.isEmpty(aitexTestFinishResult) && StringUtils.isEmpty(sgsTestFinishResult))){
  373 + LocalDate today = LocalDate.now();
  374 + LocalDate localDate = DateUtils.parseDate(orderHodTime);
  375 + if(Constant.THREE == (int) ChronoUnit.DAYS.between(today, localDate)){
  376 + return true;
  377 + }
  378 + }
  379 + if (Constant.THREE == aitextestDaysBetween || Constant.THREE == sgstestDaysBetween || Constant.NEGATIVE_ONE == aitextestDaysBetween || Constant.NEGATIVE_ONE == sgstestDaysBetween) {
334 380 return true;
335 381 }
336 382 return false;
... ... @@ -340,41 +386,31 @@ public class OrderOverTimeEventJob {
340 386  
341 387 private Boolean filterBarcodeArrivalEvent(OrderEventJobVO eventJobVO) {
342 388 String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
343   - String lastArrivalTime = eventJobVO.getTrackStageInfo().getLatestArrivalTime();
344   - if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(lastArrivalTime) && !(lastArrivalTime.contains("ok"))) {
345   - LocalDate orderHodTimelocalDate = DateUtils.parseDate(orderHodTime);
346   - LocalDate lastArrivalTimelocalDate = DateUtils.parseDate(lastArrivalTime);
347   - if (ChronoUnit.DAYS.between(lastArrivalTimelocalDate, orderHodTimelocalDate) == Constant.SEVEN) {
  389 + LocalDate today = LocalDate.now();
  390 + LocalDate localDate = DateUtils.parseDate(orderHodTime);
  391 + if ( Constant.SEVEN ==(int) ChronoUnit.DAYS.between(today, localDate) && StringUtils.isBlank(eventJobVO.getTrackStageInfo().getLatestArrivalTime())) {
348 392 return true;
349 393 }
350   - }
351 394 return false;
352 395 }
353 396  
354 397 private Boolean filterLatestDCEvent(OrderEventJobVO eventJobVO) {
355 398 String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
356   - String latestBkTime = eventJobVO.getTrackStageInfo().getLatestBkTime();
357   - if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(latestBkTime) && !(latestBkTime.contains("ok"))) {
358   - LocalDate latestBkTimelocalDate = DateUtils.parseDate(latestBkTime);
359   - LocalDate orderHodTimelocalDate = DateUtils.parseDate(orderHodTime);
360   - if (ChronoUnit.DAYS.between(latestBkTimelocalDate, orderHodTimelocalDate) == Constant.ENABLE_TEN) {
  399 + LocalDate today = LocalDate.now();
  400 + LocalDate localDate = DateUtils.parseDate(orderHodTime);
  401 + if ( Constant.ENABLE_TEN ==(int) ChronoUnit.DAYS.between(today, localDate) && StringUtils.isBlank(eventJobVO.getTrackStageInfo().getLatestBkTime())) {
361 402 return true;
362 403 }
363   - }
364 404 return false;
365   -
366 405 }
367 406  
368 407 private Boolean filterEndCheckDateEvent(OrderEventJobVO eventJobVO) {
369 408 String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime();
370   - String endCheckApplyTime = eventJobVO.getInspectionStageInfo().getEndCheckApplyTime();
371   - if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(endCheckApplyTime)) {
372   - LocalDate endCheckApplyTimelocalDate = DateUtils.parseDate(endCheckApplyTime);
373   - LocalDate orderHodTimelocalDate = DateUtils.parseDate(orderHodTime);
374   - if (ChronoUnit.DAYS.between(endCheckApplyTimelocalDate, orderHodTimelocalDate) == Constant.TWO) {
  409 + LocalDate today = LocalDate.now();
  410 + LocalDate localDate = DateUtils.parseDate(orderHodTime);
  411 + if ( Constant.TWO ==(int) ChronoUnit.DAYS.between(today, localDate) && StringUtils.isBlank(eventJobVO.getInspectionStageInfo().getEndCheckApplyTime())) {
375 412 return true;
376 413 }
377   - }
378 414 return false;
379 415 }
380 416  
... ... @@ -390,14 +426,14 @@ public class OrderOverTimeEventJob {
390 426 return Constant.ZERO;
391 427 }
392 428  
393   - public OrderBaseInfoVO getDateFormat(String productionDepartmentConsignTime,String orderHodTime){
  429 + public OrderBaseInfoVO getDateFormat(String productionDepartmentConsignTime, String orderHodTime) {
394 430 String substring = productionDepartmentConsignTime.substring(0, 10);
395 431 String substring1 = orderHodTime.substring(0, 10);
396 432 String productionDepartmentConsignTimeFormat = DateUtils.format(DateUtils.parseDate(substring, DATE), DateUtils.DATE);
397   - String orderHodTimeFormat = DateUtils.format(DateUtils.parseDate(substring1,DATE), DateUtils.DATE);
  433 + String orderHodTimeFormat = DateUtils.format(DateUtils.parseDate(substring1, DATE), DateUtils.DATE);
398 434 OrderBaseInfoVO orderBaseInfoVO = new OrderBaseInfoVO();
399 435 orderBaseInfoVO.setProductionDepartmentConsignTime(productionDepartmentConsignTimeFormat);
400 436 orderBaseInfoVO.setOrderHodTime(orderHodTimeFormat);
401 437 return orderBaseInfoVO;
402 438 }
403   -}
404 439 \ No newline at end of file
  440 +}
... ...
src/main/java/com/order/erp/mapper/order/OrderOpinionLogMapper.java 0 → 100644
  1 +package com.order.erp.mapper.order;
  2 +
  3 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4 +import com.order.erp.domain.dto.order.OrderOpinionLogDO;
  5 +
  6 +public interface OrderOpinionLogMapper extends BaseMapper<OrderOpinionLogDO> {
  7 +}
... ...
src/main/java/com/order/erp/service/LocalStorageService.java
... ... @@ -3,10 +3,13 @@ package com.order.erp.service;
3 3 import com.baomidou.mybatisplus.extension.service.IService;
4 4 import com.order.erp.common.constant.ServerResult;
5 5 import com.order.erp.domain.dto.LocalStorageDO;
  6 +import com.order.erp.domain.vo.FileRespVO;
6 7 import com.order.erp.domain.vo.LocalStorageQueryVO;
7 8 import com.order.erp.domain.vo.LocalStorageVO;
8 9 import org.springframework.web.multipart.MultipartFile;
9 10  
  11 +import java.io.File;
  12 +
10 13 /**
11 14 * 本地存储(LocalStorage)表服务接口
12 15 *
... ... @@ -33,6 +36,7 @@ public interface LocalStorageService extends IService&lt;LocalStorageDO&gt; {
33 36 ServerResult uploadFileByAliOss(String name, MultipartFile file);
34 37  
35 38 ServerResult create(String name, MultipartFile file);
  39 + FileRespVO getFilePath(File file, String companyName);
36 40  
37 41 /**
38 42 * 通过ID查询单条数据
... ...
src/main/java/com/order/erp/service/admin/impl/AdminUserServiceImpl.java
... ... @@ -197,6 +197,11 @@ public class AdminUserServiceImpl extends ServiceImpl&lt;AdminUserMapper, AdminUser
197 197 if(StringUtils.isNotBlank(adminUserVO.getEmail())){
198 198 adminUserDo.setEmail(adminUserVO.getEmail());
199 199 }
  200 + List<AdminUserDO> byNickNameUserDOS = list(new LambdaQueryWrapper<AdminUserDO>().eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  201 + .eq(AdminUserDO::getUserName, adminUserVO.getNickName()));
  202 + if (CollectionUtils.isNotEmpty(byNickNameUserDOS)) {
  203 + throw new BusinessException("用户名已存在");
  204 + }
200 205 if (StringUtils.isNotBlank(adminUserVO.getNickName())) {
201 206 adminUserDo.setUserName(adminUserVO.getNickName());
202 207 }
... ... @@ -219,7 +224,7 @@ public class AdminUserServiceImpl extends ServiceImpl&lt;AdminUserMapper, AdminUser
219 224 .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
220 225 .eq(DictionaryDO::getDictName,RoleEnum.PRODUCE_USER.getName()));
221 226 if(CollectionUtils.isNotEmpty(dictionaryDOList)){
222   - Set<String> dictionaryNames = dictionaryDOList.stream().map(DictionaryDO::getDictName).collect(Collectors.toSet());
  227 + Set<String> dictionaryNames = dictionaryDOList.stream().map(DictionaryDO::getDictValue).collect(Collectors.toSet());
223 228 if(!dictionaryNames.contains(adminUserVO.getNickName())){
224 229 DictionaryVO dictionaryVO = new DictionaryVO();
225 230 dictionaryVO.setRemark("生产科");
... ... @@ -337,6 +342,9 @@ public class AdminUserServiceImpl extends ServiceImpl&lt;AdminUserMapper, AdminUser
337 342 if (RoleEnum.INSPECT_USER.getId().equals(x.getRoleId())) {
338 343 result.set(RoleEnum.INSPECT_USER);
339 344 }
  345 + if(RoleEnum.PRODUCE_USER.getId().equals(x.getRoleId())){
  346 + result.set(RoleEnum.PRODUCE_USER);
  347 + }
340 348 });
341 349 return ServerResult.success(result.get());
342 350 }
... ...
src/main/java/com/order/erp/service/impl/LocalStorageServiceImpl.java
... ... @@ -28,6 +28,7 @@ import org.springframework.stereotype.Service;
28 28 import org.springframework.web.multipart.MultipartFile;
29 29  
30 30 import java.io.File;
  31 +import java.nio.file.Files;
31 32 import java.util.List;
32 33 import java.util.Objects;
33 34  
... ... @@ -80,27 +81,49 @@ public class LocalStorageServiceImpl extends ServiceImpl&lt;LocalStorageMapper, Loc
80 81 try {
81 82 File tempFile = new File(path + "images" + File.separator + tempFileName);
82 83 if (AliOssUtil.upload(AliOssConfig.ALIYUN_BUCKET, fileName, file.getBytes())) {
83   - log.info("--------uploadByAliOss success----------");
84 84 String originImageUrl = AliOssUtil.createUrl(AliOssConfig.ALIYUN_BUCKET, fileName, new DateTime().plusYears(Constant.ENABLE_TEN).toDate());
85 85 imageRespVO.setPicUrl(originImageUrl);
86 86 // 生成缩略图
87 87 Thumbnails.of(file.getInputStream()).size(100, 100).toFile(tempFile);
88 88 if (AliOssUtil.upload(AliOssConfig.ALIYUN_BUCKET, tempFileName, FileUtil.readBytes(tempFile))) {
89   - log.info("--------uploadByAliOss 缩略图 success----------");
90 89 String thumbnailImageUrl = AliOssUtil.createUrl(AliOssConfig.ALIYUN_BUCKET, tempFileName, new DateTime().plusYears(Constant.ENABLE_TEN).toDate());
91 90 imageRespVO.setSmallPicUrl(thumbnailImageUrl);
92 91 }
93   - log.info("--------uploadByAliOss end ----------");
94 92 FileUtil.del(tempFile);
95   - log.info("--------uploadByAliOss del success ----------");
96 93 }
97 94 return ServerResult.success(imageRespVO);
98 95 } catch (Exception e) {
99   - log.error("上传图片异常:{}", e.getMessage());
  96 + log.error("上传图片异常{}", e.getMessage());
100 97 throw new BusinessException(ServerResultCode.UPLOAD_IMAGES_ERROR);
101 98 }
102 99 }
103 100  
  101 +
  102 +
  103 + public FileRespVO getFilePath(File file,String companyName) {
  104 + FileUtil.checkSize(maxSize, file.length()); // 使用文件长度检查大小
  105 + String fileName = AliOssUtil.getUniqueFileName(companyName+"生产指示书.pdf");
  106 + String tempFileName = "Thumbnails" + Constant.CROSS_BAR_CHARACTER + fileName;
  107 + FileRespVO fileRespVO = new FileRespVO();
  108 + try {
  109 + // 文件路径生成(如果需要保存临时文件)
  110 + File tempFile = new File(path + "files" + File.separator + tempFileName);
  111 +
  112 + // 使用文件的字节数组上传到阿里云 OSS
  113 + byte[] fileBytes = Files.readAllBytes(file.toPath()); // 将 File 转换为字节数组
  114 + if (AliOssUtil.upload(AliOssConfig.ALIYUN_BUCKET, fileName, fileBytes)) {
  115 + String fileUrl = AliOssUtil.createUrl(AliOssConfig.ALIYUN_BUCKET, fileName, new DateTime().plusYears(Constant.ENABLE_TEN).toDate());
  116 + fileRespVO.setFileUrl(fileUrl);
  117 + FileUtil.del(tempFile); // 删除临时文件
  118 + }
  119 + return fileRespVO;
  120 + } catch (Exception e) {
  121 + log.error("上传文件异常:{}", e.getMessage());
  122 + throw new BusinessException(ServerResultCode.UPLOAD_IMAGES_ERROR);
  123 + }
  124 + }
  125 +
  126 +
104 127 @Override
105 128 public ServerResult create(String name, MultipartFile multipartFile) {
106 129 FileUtil.checkSize(maxSize, multipartFile.getSize());
... ... @@ -127,6 +150,7 @@ public class LocalStorageServiceImpl extends ServiceImpl&lt;LocalStorageMapper, Loc
127 150 }
128 151 }
129 152  
  153 +
130 154 /**
131 155 * 通过ID查询单条数据
132 156 * <p>
... ...
src/main/java/com/order/erp/service/order/OrderBaseInfoService.java
... ... @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
5 5 import com.order.erp.common.constant.ServerResult;
6 6 import com.order.erp.common.excel4j.exceptions.Excel4JException;
7 7 import com.order.erp.domain.dto.order.OrderBaseInfoDO;
  8 +import com.order.erp.domain.vo.ProducePdfVO;
8 9 import com.order.erp.domain.vo.order.*;
9 10 import freemarker.template.TemplateException;
10 11  
... ... @@ -100,6 +101,9 @@ public interface OrderBaseInfoService extends IService&lt;OrderBaseInfoDO&gt; {
100 101 * @return 是否成功
101 102 */
102 103 ServerResult deleteById(OrderBaseInfoQueryVO orderBaseInfoQueryVO);
  104 + ServerResult passRate(OrderOpinionLogVO orderOpinionLogVO);
  105 +
  106 + ServerResult produceReport(ProducePdfVO producePdfVO);
103 107  
104 108  
105 109 long countByOrderStatus(Integer orderFinish);
... ... @@ -117,4 +121,6 @@ public interface OrderBaseInfoService extends IService&lt;OrderBaseInfoDO&gt; {
117 121  
118 122 List<OrderBaseInfoDO> getEventList();
119 123  
  124 + ServerResult send(ProducePdfVO producePdfVO) throws Exception;
  125 +
120 126 }
... ...
src/main/java/com/order/erp/service/order/OrderOpinionLogService.java 0 → 100644
  1 +package com.order.erp.service.order;
  2 +
  3 +import com.baomidou.mybatisplus.extension.service.IService;
  4 +import com.order.erp.common.constant.ServerResult;
  5 +import com.order.erp.domain.dto.order.OrderOpinionLogDO;
  6 +import com.order.erp.domain.vo.order.OrderOpinionLogVO;
  7 +
  8 +public interface OrderOpinionLogService extends IService<OrderOpinionLogDO> {
  9 +
  10 + ServerResult queryById(OrderOpinionLogVO orderOpinionLogVo);
  11 +}
... ...
src/main/java/com/order/erp/service/order/impl/OrderBaseInfoServiceImpl.java
... ... @@ -3,7 +3,9 @@ package com.order.erp.service.order.impl;
3 3 import cn.hutool.core.bean.BeanUtil;
4 4 import cn.hutool.core.collection.CollUtil;
5 5 import cn.hutool.core.collection.CollectionUtil;
  6 +import com.alibaba.fastjson.JSON;
6 7 import com.alibaba.fastjson.JSONObject;
  8 +import com.alibaba.fastjson.TypeReference;
7 9 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8 10 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
9 11 import com.baomidou.mybatisplus.core.metadata.IPage;
... ... @@ -26,6 +28,7 @@ import com.order.erp.domain.dto.BaseDO;
26 28 import com.order.erp.domain.dto.SystemSettingDO;
27 29 import com.order.erp.domain.dto.admin.AdminUserDO;
28 30 import com.order.erp.domain.dto.order.*;
  31 +import com.order.erp.domain.vo.ProducePdfVO;
29 32 import com.order.erp.domain.vo.order.*;
30 33 import com.order.erp.job.OrderOverTimeEventJob;
31 34 import com.order.erp.mapper.order.OrderBaseInfoMapper;
... ... @@ -43,13 +46,16 @@ import org.springframework.transaction.annotation.Transactional;
43 46 import javax.annotation.Resource;
44 47 import javax.mail.MessagingException;
45 48 import javax.servlet.http.HttpServletResponse;
  49 +import java.io.File;
46 50 import java.io.IOException;
47 51 import java.io.InputStream;
48 52 import java.math.BigDecimal;
49 53 import java.math.RoundingMode;
50 54 import java.net.URL;
51 55 import java.text.DecimalFormat;
  56 +import java.time.LocalDate;
52 57 import java.time.LocalDateTime;
  58 +import java.time.Month;
53 59 import java.util.*;
54 60 import java.util.function.Function;
55 61 import java.util.stream.Collectors;
... ... @@ -118,6 +124,17 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
118 124 @Resource
119 125 private EmailSendUtils emailSendUtils;
120 126  
  127 + @Resource
  128 + private OrderOpinionLogService orderOpinionLogService;
  129 +
  130 + @Resource
  131 + private EasyPdfUtils pdfUtils;
  132 +
  133 + @Resource
  134 + private AdminUserService adminUserService;
  135 +
  136 + @Resource
  137 + private ReceiveEmailMappingService receiveEmailMappingService;
121 138  
122 139  
123 140 /**
... ... @@ -232,6 +249,12 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
232 249  
233 250 if (CollectionUtils.isNotEmpty(orderBaseInfoDOList)) {
234 251 List<OrderInfoResultVO> resultVOList = orderBaseInfoDOList.stream().map(x -> {
  252 + //在导出时只导出产品意见的最后一行。
  253 + if(x.getProductionComment().contains("\n")){
  254 + String[] productionCommentS = x.getProductionComment().split("\n");
  255 + String productionComment = productionCommentS[productionCommentS.length - 1];
  256 + x.setProductionComment(productionComment);
  257 + }
235 258 OrderInfoResultVO resultVO = new OrderInfoResultVO();
236 259 BeanUtils.copyProperties(x, resultVO);
237 260 return resultVO;
... ... @@ -342,7 +365,7 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
342 365 }
343 366 if (StringUtils.isNotBlank(baseFields.getProductionComment()) &&
344 367 OrderLockFieldEnum.SELECTED.getStatus().equals(baseFields.getProductionComment())) {
345   - map.put("生产要求", orderInfoResultVO.getProductionComment());
  368 + map.put("产品意见", orderInfoResultVO.getProductionComment());
346 369 }
347 370 if (StringUtils.isNotBlank(baseFields.getOrderCount()) &&
348 371 OrderLockFieldEnum.SELECTED.getStatus().equals(baseFields.getOrderCount())) {
... ... @@ -1261,7 +1284,7 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1261 1284 queryVO.setBusinessPerson(Arrays.asList(dataScope.getUser().getNickName()));
1262 1285 }
1263 1286 // 生产科
1264   - if(Objects.nonNull(roleEnum) && roleEnum.getId().equals(RoleEnum.PRODUCE_USER.getId())){
  1287 + if (Objects.nonNull(roleEnum) && roleEnum.getId().equals(RoleEnum.PRODUCE_USER.getId())) {
1265 1288 queryVO.setProductionDepartment(Arrays.asList(dataScope.getUser().getNickName()));
1266 1289 }
1267 1290 if (StringUtils.isNotBlank(queryVO.getCommitUserPhone())) {
... ... @@ -1430,11 +1453,29 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1430 1453 if (Objects.isNull(baseInfoVO)) {
1431 1454 throw new BusinessException(ServerResultCode.ORDER_BASE_INFO_EMPTY);
1432 1455 }
  1456 + LocalDate currentDate = LocalDate.now();
  1457 + Month month = currentDate.getMonth();
  1458 + int currentMonth = month.getValue();
  1459 + int dayOfMonth = currentDate.getDayOfMonth();
  1460 + String originProductionComment = baseInfoVO.getProductionComment();
  1461 + if (StringUtils.isNotBlank(baseInfoVO.getProductionComment())) {
  1462 + String date = currentMonth + "/" + dayOfMonth + ": ";
  1463 + String productionComment = baseInfoVO.getProductionComment();
  1464 + productionComment = date + productionComment;
  1465 + baseInfoVO.setProductionComment(productionComment);
  1466 +
  1467 + }
1433 1468 Long userId = dataScope.getLoginUserId();
1434 1469 OrderBaseInfoDO baseInfoDO = new OrderBaseInfoDO();
1435 1470 BeanUtils.copyProperties(baseInfoVO, baseInfoDO);
1436 1471 baseInfoDO.setOrderStatus(OrderStatusEnum.CREATE_FINISH.getStatus());
1437 1472 save(baseInfoDO);
  1473 +
  1474 + OrderOpinionLogDO orderOpinionLogDO = buildOrderOpinionLogDo(baseInfoDO.getId(),
  1475 + OrderOpinionLogEnum.ORDER_PRODUCTION_COMMENT.getDesc(),
  1476 + originProductionComment);
  1477 + orderOpinionLogService.save(orderOpinionLogDO);
  1478 +
1438 1479 OrderTrackStageDO orderTrackStageDO = new OrderTrackStageDO();
1439 1480 orderTrackStageDO.setOrderId(baseInfoDO.getId());
1440 1481 orderTrackStageDO.setOrderStatus(OrderStatusEnum.CREATE_FINISH.getStatus());
... ... @@ -1507,8 +1548,9 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1507 1548 return OrderOptLogDO.builder().orderId(orderId).userId(userId).fields(jsonString).optType(optType).build();
1508 1549 }
1509 1550  
1510   -
1511   -
  1551 + private OrderOpinionLogDO buildOrderOpinionLogDo(Long orderId, String type, String field) {
  1552 + return OrderOpinionLogDO.builder().orderId(orderId).opinionType(type).field(field).build();
  1553 + }
1512 1554 /**
1513 1555 * @param updateVO
1514 1556 */
... ... @@ -1597,14 +1639,48 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1597 1639 if (Objects.isNull(orderBaseInfoDo)) {
1598 1640 throw new BusinessException(ServerResultCode.ORDER_BASE_INFO_EMPTY);
1599 1641 }
  1642 + LocalDate currentDate = LocalDate.now();
  1643 + Month month = currentDate.getMonth();
  1644 + int currentMonth = month.getValue();
  1645 + int dayOfMonth = currentDate.getDayOfMonth();
1600 1646 OrderOptLogDO optLogDO = new OrderOptLogDO();
  1647 + List<OrderOpinionLogDO> orderOpinionLogDOList = new ArrayList<>();
1601 1648 if (Objects.nonNull(updateVO.getBaseInfo())) {
1602   -
  1649 + //用户编辑时,产品意见与这个订单的上一次产品意见内容不一样。
  1650 + if (StringUtils.isNotBlank(updateVO.getBaseInfo().getProductionComment()) && !(updateVO.getBaseInfo().getProductionComment().equals(orderBaseInfoDo.getProductionComment()))) {
  1651 + //说明用户第一次填写产品意见,这一步其实没必要,因为在add中会添加。
  1652 + if (org.apache.commons.lang3.StringUtils.isEmpty(orderBaseInfoDo.getProductionComment())) {
  1653 + OrderOpinionLogDO orderOpinionLogDO = buildOrderOpinionLogDo(updateVO.getOrderId(), OrderOpinionLogEnum.ORDER_PRODUCTION_COMMENT.getDesc(), updateVO.getBaseInfo().getProductionComment());
  1654 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1655 + } else {
  1656 + //说明用户不是第一次填写产品意见,并且填写的内容与上一次的产品意见不一样。
  1657 + String[] parts = updateVO.getBaseInfo().getProductionComment().split("\n");
  1658 + //取最后一条的数据。
  1659 + String lastPart = parts[parts.length - 1].trim();
  1660 + OrderOpinionLogDO orderOpinionLogDO = buildOrderOpinionLogDo(updateVO.getOrderId(), OrderOpinionLogEnum.ORDER_PRODUCTION_COMMENT.getDesc(), lastPart);
  1661 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1662 + }
  1663 + String date = currentMonth + "/" + dayOfMonth;
  1664 + String productionComment = orderBaseInfoDo.getProductionComment();
  1665 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1666 + String[] newProductionComment = updateVO.getBaseInfo().getProductionComment().split("\n");
  1667 + //对于四个结果,并且当前输入产品意见文字小于上一次的产品意见后续填写不需要换行。
  1668 + if((!newProductionComment[newProductionComment.length - 1].trim().contains("确认通过") &&
  1669 + !newProductionComment[newProductionComment.length - 1].trim().contains("确认未通过")) && updateVO.getBaseInfo().getProductionComment().length() > orderBaseInfoDo.getProductionComment().length()){
  1670 + stringBuilder.append("\n").append(date + ": " + newProductionComment[newProductionComment.length - 1].trim());
  1671 + updateVO.getBaseInfo().setProductionComment(stringBuilder.toString());
  1672 + sendProductionCommentEmail(orderBaseInfoDo, stringBuilder.toString());
  1673 + }else{
  1674 + sendProductionCommentEmail(orderBaseInfoDo,updateVO.getBaseInfo().getProductionComment());
  1675 + }
  1676 + }
1603 1677 buildUpdateVO(updateVO.getBaseInfo(), orderBaseInfoDo);
1604 1678 orderBaseInfoDo.setId(updateVO.getOrderId());
1605 1679 optLogDO = buildOrderOptLogDo(updateVO.getOrderId(), userId, OrderOptTypeEnum.ORDER_EDIT.getDesc(), JSONObject.toJSONString(updateVO));
1606 1680 clearLockedField(updateVO.getOrderId(), userId, LockedFieldTypeEnum.ORDER_BASE);
1607 1681 }
  1682 +
  1683 +
1608 1684 if (Objects.nonNull(updateVO.getProfitAnalysisInfo())) {
1609 1685 checkApply(updateVO.getOrderId(), userId, ApplyTypeEnum.ORDER_PROFIT_APPLY);
1610 1686 OrderFieldLockApplyDO orderFieldLockApplyDO = handlerProfitRate(updateVO.getProfitAnalysisInfo(), orderBaseInfoDo, userId);
... ... @@ -1635,7 +1711,22 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1635 1711 trackStageDO.setPpTime(trackStageInfo.getPpTime());
1636 1712 }
1637 1713 if (StringUtils.isNotBlank(trackStageInfo.getPpConfirmResult())) {
  1714 + if (!(trackStageInfo.getPpConfirmResult().equals(trackStageDO.getPpConfirmResult()))) {
  1715 + String resultText = trackStageInfo.getPpConfirmResult().contains("ok")
  1716 + ? "PP样品确认通过"
  1717 + : "PP样品确认未通过";
  1718 + //用于在跟单记录中展示。
  1719 + OrderOpinionLogDO orderOpinionLogDO = buildOrderOpinionLogDo(updateVO.getOrderId(), OrderOpinionLogEnum.ORDER_PP_CONFIRRM_RESULT.getDesc(), trackStageInfo.getPpConfirmResult());
  1720 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1721 + //添加到产品意见中去。
  1722 + String date = currentMonth + "/" + dayOfMonth;
  1723 + String productionComment = orderBaseInfoDo.getProductionComment();
  1724 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1725 + stringBuilder.append("\n").append(date + ":" + resultText);
  1726 + orderBaseInfoDo.setProductionComment(stringBuilder.toString());
  1727 + sendProductionCommentEmail(orderBaseInfoDo, stringBuilder.toString());
1638 1728  
  1729 + }
1639 1730 trackStageDO.setPpConfirmResult(trackStageInfo.getPpConfirmResult());
1640 1731 }
1641 1732 if (StringUtils.isNotBlank(trackStageInfo.getEsoSampleSendTime())) {
... ... @@ -1645,7 +1736,21 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1645 1736 trackStageDO.setShippmentSampleSendTime(trackStageInfo.getShippmentSampleSendTime());
1646 1737 }
1647 1738 if (StringUtils.isNotBlank(trackStageInfo.getShippmentSampleConfirmResult())) {
1648   - trackStageDO.setShippmentSampleConfirmResult(trackStageInfo.getShippmentSampleConfirmResult());
  1739 + if (!(trackStageInfo.getShippmentSampleConfirmResult().equals(trackStageDO.getShippmentSampleConfirmResult()))) {
  1740 + String resultText = trackStageInfo.getShippmentSampleConfirmResult().contains("ok")
  1741 + ? "大货样确认通过"
  1742 + : "大货样确认未通过";
  1743 + OrderOpinionLogDO orderOpinionLogDO = buildOrderOpinionLogDo(updateVO.getOrderId(), OrderOpinionLogEnum.ORDER_SHIPMENT_SAMPLE_CONFIRM_RESULT.getDesc(), trackStageInfo.getShippmentSampleConfirmResult());
  1744 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1745 + //添加到产品意见中去。
  1746 + String date = currentMonth + "/" + dayOfMonth;
  1747 + String productionComment = orderBaseInfoDo.getProductionComment();
  1748 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1749 + stringBuilder.append("\n").append(date + ": " + resultText);
  1750 + orderBaseInfoDo.setProductionComment(stringBuilder.toString());
  1751 + sendProductionCommentEmail(orderBaseInfoDo, stringBuilder.toString());
  1752 + }
  1753 + trackStageDO.setShippmentSampleConfirmResult(trackStageInfo.getShippmentSampleConfirmResult());
1649 1754 }
1650 1755 if (StringUtils.isNotBlank(trackStageInfo.getSelfTestPassTime())) {
1651 1756 trackStageDO.setSelfTestPassTime(trackStageInfo.getSelfTestPassTime());
... ... @@ -1654,13 +1759,40 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1654 1759 trackStageDO.setAitexTestSendTime(trackStageInfo.getAitexTestSendTime());
1655 1760 }
1656 1761 if (StringUtils.isNotBlank(trackStageInfo.getAitexTestFinishResult())) {
1657   -
  1762 + if (!(trackStageInfo.getAitexTestFinishResult().equals(trackStageDO.getAitexTestFinishResult()))) {
  1763 + String resultText = trackStageInfo.getAitexTestFinishResult().contains("ok")
  1764 + ? "Aitex测试确认通过"
  1765 + : "Aitex测试确认未通过";
  1766 + OrderOpinionLogDO orderOpinionLogDO = buildOrderOpinionLogDo(updateVO.getOrderId(), OrderOpinionLogEnum.ORDER_AITEX_TEST_FINISH_RESULT.getDesc(), trackStageInfo.getAitexTestFinishResult());
  1767 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1768 + //添加到产品意见中去。
  1769 + String date = currentMonth + "/" + dayOfMonth;
  1770 + String productionComment = orderBaseInfoDo.getProductionComment();
  1771 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1772 + stringBuilder.append("\n").append(date + ": " + resultText);
  1773 + orderBaseInfoDo.setProductionComment(stringBuilder.toString());
  1774 + sendProductionCommentEmail(orderBaseInfoDo, stringBuilder.toString());
  1775 + }
1658 1776 trackStageDO.setAitexTestFinishResult(trackStageInfo.getAitexTestFinishResult());
1659 1777 }
1660 1778 if (StringUtils.isNotBlank(trackStageInfo.getSgsTestSendTime())) {
1661 1779 trackStageDO.setSgsTestSendTime(trackStageInfo.getSgsTestSendTime());
1662 1780 }
1663 1781 if (StringUtils.isNotBlank(trackStageInfo.getSgsTestFinishResult())) {
  1782 + if (!(trackStageInfo.getSgsTestFinishResult().equals(trackStageDO.getSgsTestFinishResult()))) {
  1783 + String resultText = trackStageInfo.getSgsTestFinishResult().contains("ok")
  1784 + ? "SGS测试确认通过"
  1785 + : "SGS测试确认未通过";
  1786 + OrderOpinionLogDO orderOpinionLogDO = buildOrderOpinionLogDo(updateVO.getOrderId(), OrderOpinionLogEnum.ORDER_SGS_TEST_FINISH_RESULT.getDesc(), trackStageInfo.getSgsTestFinishResult());
  1787 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1788 + //添加到产品意见中去。
  1789 + String date = currentMonth + "/" + dayOfMonth;
  1790 + String productionComment = orderBaseInfoDo.getProductionComment();
  1791 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1792 + stringBuilder.append("\n").append(date + ": " + resultText);
  1793 + orderBaseInfoDo.setProductionComment(stringBuilder.toString());
  1794 + sendProductionCommentEmail(orderBaseInfoDo, stringBuilder.toString());
  1795 + }
1664 1796  
1665 1797 trackStageDO.setSgsTestFinishResult(trackStageInfo.getSgsTestFinishResult());
1666 1798 }
... ... @@ -1694,6 +1826,58 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1694 1826 trackStageDO.setOrderId(updateVO.getOrderId());
1695 1827 trackStageDO.setOrderStatus(OrderStatusEnum.TRACK_ING.getStatus());
1696 1828 trackStageService.save(trackStageDO);
  1829 + if(StringUtils.isNotBlank(updateVO.getTrackStageInfo().getPpConfirmResult())){
  1830 + String resultText = updateVO.getTrackStageInfo().getPpConfirmResult().contains("ok")
  1831 + ? "PP样品确认通过"
  1832 + : "PP样品确认未通过";
  1833 + OrderOpinionLogDO orderOpinionLogDO =buildOrderOpinionLogDo(updateVO.getOrderId(),OrderOpinionLogEnum.ORDER_PP_CONFIRRM_RESULT.getDesc(),trackStageInfo.getPpConfirmResult());
  1834 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1835 + String date=currentMonth+"/"+dayOfMonth;
  1836 + String productionComment = orderBaseInfoDo.getProductionComment();
  1837 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1838 + stringBuilder.append("\n").append(date+": "+resultText);
  1839 + orderBaseInfoDo.setProductionComment(stringBuilder.toString());
  1840 + sendProductionCommentEmail(orderBaseInfoDo,stringBuilder.toString());
  1841 + }
  1842 + if(StringUtils.isNotBlank(updateVO.getTrackStageInfo().getShippmentSampleConfirmResult())) {
  1843 + String resultText = updateVO.getTrackStageInfo().getShippmentSampleConfirmResult().contains("ok")
  1844 + ? "大货样确认通过"
  1845 + : "大货样确认未通过";
  1846 + OrderOpinionLogDO orderOpinionLogDO = buildOrderOpinionLogDo(updateVO.getOrderId(), OrderOpinionLogEnum.ORDER_SHIPMENT_SAMPLE_CONFIRM_RESULT.getDesc(), trackStageInfo.getShippmentSampleConfirmResult());
  1847 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1848 + String date=currentMonth+"/"+dayOfMonth;
  1849 + String productionComment = orderBaseInfoDo.getProductionComment();
  1850 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1851 + stringBuilder.append("\n").append(date+": "+resultText);
  1852 + orderBaseInfoDo.setProductionComment(stringBuilder.toString());
  1853 + sendProductionCommentEmail(orderBaseInfoDo,stringBuilder.toString());
  1854 + }
  1855 + if(StringUtils.isNotBlank(updateVO.getTrackStageInfo().getAitexTestFinishResult())){
  1856 + String resultText =updateVO.getTrackStageInfo().getAitexTestFinishResult().contains("ok")
  1857 + ? "Aitex测试确认通过"
  1858 + : "Aitex测试确认未通过";
  1859 + OrderOpinionLogDO orderOpinionLogDO =buildOrderOpinionLogDo(updateVO.getOrderId(),OrderOpinionLogEnum.ORDER_AITEX_TEST_FINISH_RESULT.getDesc(),trackStageInfo.getAitexTestFinishResult());
  1860 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1861 + String date=currentMonth+"/"+dayOfMonth;
  1862 + String productionComment = orderBaseInfoDo.getProductionComment();
  1863 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1864 + stringBuilder.append("\n").append(date+": "+resultText);
  1865 + orderBaseInfoDo.setProductionComment(stringBuilder.toString());
  1866 + sendProductionCommentEmail(orderBaseInfoDo,stringBuilder.toString());
  1867 + }
  1868 + if(StringUtils.isNotBlank(updateVO.getTrackStageInfo().getSgsTestFinishResult())){
  1869 + String resultText = updateVO.getTrackStageInfo().getSgsTestFinishResult().contains("ok")
  1870 + ? "SGS测试确认通过"
  1871 + : "SGS测试确认未通过";
  1872 + OrderOpinionLogDO orderOpinionLogDO =buildOrderOpinionLogDo(updateVO.getOrderId(),OrderOpinionLogEnum.ORDER_SGS_TEST_FINISH_RESULT.getDesc(),trackStageInfo.getSgsTestFinishResult());
  1873 + orderOpinionLogDOList.add(orderOpinionLogDO);
  1874 + String date=currentMonth+"/"+dayOfMonth;
  1875 + String productionComment = orderBaseInfoDo.getProductionComment();
  1876 + StringBuilder stringBuilder = new StringBuilder(productionComment);
  1877 + stringBuilder.append("\n").append(date+": "+resultText);
  1878 + orderBaseInfoDo.setProductionComment(stringBuilder.toString());
  1879 + sendProductionCommentEmail(orderBaseInfoDo,stringBuilder.toString());
  1880 + }
1697 1881 }
1698 1882 orderBaseInfoDo.setOrderStatus(OrderStatusEnum.TRACK_ING.getStatus());
1699 1883 optLogDO = buildOrderOptLogDo(updateVO.getOrderId(), userId, OrderOptTypeEnum.ORDER_TRACKER_EDIT_APPLY.getDesc(), JSONObject.toJSONString(updateVO));
... ... @@ -1705,11 +1889,11 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1705 1889 .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
1706 1890 .eq(OrderInspectionStageDO::getOrderId, updateVO.getOrderId()));
1707 1891 OrderInspectionStageVO inspectionStageInfo = updateVO.getInspectionStageInfo();
1708   - String midCheckResult=inspectionStageInfo.getMidCheckResult();
1709   - String endCheckResult=inspectionStageInfo.getEndCheckResult();
  1892 + String midCheckResult = inspectionStageInfo.getMidCheckResult();
  1893 + String endCheckResult = inspectionStageInfo.getEndCheckResult();
1710 1894 if (Objects.nonNull(inspectionStageDO)) {
1711   - midCheckResult=inspectionStageDO.getMidCheckResult();
1712   - endCheckResult=inspectionStageDO.getEndCheckResult();
  1895 + midCheckResult = inspectionStageDO.getMidCheckResult();
  1896 + endCheckResult = inspectionStageDO.getEndCheckResult();
1713 1897 if (StringUtils.isNotBlank(inspectionStageInfo.getMidCheckApplyTime())) {
1714 1898 inspectionStageDO.setMidCheckApplyTime(inspectionStageInfo.getMidCheckApplyTime());
1715 1899 }
... ... @@ -1753,8 +1937,8 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1753 1937 AdminUserDO ProductionDepartmentUserDO = userService.getOne(new LambdaQueryWrapper<AdminUserDO>()
1754 1938 .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
1755 1939 .eq(AdminUserDO::getUserName, orderBaseInfoDO.getProductionDepartment()));
1756   - if( Objects.nonNull(ProductionDepartmentUserDO) && StringUtils.isNotBlank(ProductionDepartmentUserDO.getEmail())){
1757   - sendOrderInspectionStage(updateVO,midCheckResult,endCheckResult);
  1940 + if (Objects.nonNull(ProductionDepartmentUserDO) && StringUtils.isNotBlank(ProductionDepartmentUserDO.getEmail())) {
  1941 + sendOrderInspectionStage(updateVO, midCheckResult, endCheckResult);
1758 1942 }
1759 1943 } else {
1760 1944 inspectionStageDO = new OrderInspectionStageDO();
... ... @@ -1766,10 +1950,10 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1766 1950 AdminUserDO ProductionDepartmentUserDO = userService.getOne(new LambdaQueryWrapper<AdminUserDO>()
1767 1951 .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
1768 1952 .eq(AdminUserDO::getUserName, orderBaseInfoDO.getProductionDepartment()));
1769   - if( Objects.nonNull(ProductionDepartmentUserDO) && StringUtils.isNotBlank(ProductionDepartmentUserDO.getEmail())){
1770   - midCheckResult="1";
1771   - endCheckResult="1";
1772   - sendOrderInspectionStage(updateVO,midCheckResult,endCheckResult);
  1953 + if (Objects.nonNull(ProductionDepartmentUserDO) && StringUtils.isNotBlank(ProductionDepartmentUserDO.getEmail())) {
  1954 + midCheckResult = "1";
  1955 + endCheckResult = "1";
  1956 + sendOrderInspectionStage(updateVO, midCheckResult, endCheckResult);
1773 1957 }
1774 1958  
1775 1959 }
... ... @@ -1779,6 +1963,7 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1779 1963 }
1780 1964 updateById(orderBaseInfoDo);
1781 1965 orderOptLogService.save(optLogDO);
  1966 + orderOpinionLogService.saveBatch(orderOpinionLogDOList);
1782 1967 return ServerResult.success();
1783 1968 }
1784 1969  
... ... @@ -1887,6 +2072,9 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1887 2072 if (StringUtils.isNotBlank(baseInfoVO.getBusinessPerson())) {
1888 2073 baseInfoDO.setBusinessPerson(baseInfoVO.getBusinessPerson());
1889 2074 }
  2075 + if (Objects.nonNull(baseInfoVO.getReturnOrder())){
  2076 + baseInfoDO.setReturnOrder(baseInfoVO.getReturnOrder());
  2077 + }
1890 2078 }
1891 2079  
1892 2080 /**
... ... @@ -1954,7 +2142,70 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
1954 2142 * @return
1955 2143 */
1956 2144  
  2145 + @Override
  2146 + public ServerResult passRate(OrderOpinionLogVO orderOpinionLogVO) {
  2147 + if (CollectionUtils.isEmpty(orderOpinionLogVO.getIds())) {
  2148 + return ServerResult.fail("OrderId 参数不能为空");
  2149 + }
  2150 + //过滤掉返单的数据。
  2151 + List<OrderBaseInfoDO> orderBaseInfoDOList = baseInfoService.list(new LambdaQueryWrapper<OrderBaseInfoDO>()
  2152 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  2153 + .in(OrderBaseInfoDO::getId, orderOpinionLogVO.getIds())
  2154 + .and(wrapper -> wrapper.ne(OrderBaseInfoDO::getReturnOrder, Constant.STRING_ONE).or().isNull(OrderBaseInfoDO::getReturnOrder)));
  2155 + List<Long> orderBaseInfoList = orderBaseInfoDOList.stream().map(OrderBaseInfoDO::getId).filter(Objects::nonNull).collect(Collectors.toList());
  2156 + //过滤完返单的数据。
  2157 + if(CollectionUtils.isNotEmpty(orderBaseInfoList)){
  2158 + LambdaQueryWrapper<OrderOpinionLogDO> orderOpinionWrapper = new LambdaQueryWrapper<OrderOpinionLogDO>()
  2159 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  2160 + .in(OrderOpinionLogDO::getOrderId, orderBaseInfoList);
  2161 + if (!OrderOpinionLogEnum.ORDER_SGS_TEST_FINISH_RESULT.getDesc().equals(orderOpinionLogVO.getOpinionType()) &&
  2162 + !OrderOpinionLogEnum.ORDER_AITEX_TEST_FINISH_RESULT.getDesc().equals(orderOpinionLogVO.getOpinionType())) {
  2163 + //不等于sgs和ailtex
  2164 + orderOpinionWrapper.eq(OrderOpinionLogDO::getOpinionType, orderOpinionLogVO.getOpinionType());
  2165 + } else {
  2166 + orderOpinionWrapper.and(wrapper ->
  2167 + wrapper.eq(OrderOpinionLogDO::getOpinionType, OrderOpinionLogEnum.ORDER_SGS_TEST_FINISH_RESULT.getDesc())
  2168 + .or()
  2169 + .eq(OrderOpinionLogDO::getOpinionType, OrderOpinionLogEnum.ORDER_AITEX_TEST_FINISH_RESULT.getDesc())
  2170 + );
  2171 + }
  2172 + List<OrderOpinionLogDO> orderOpinionLogDOList = orderOpinionLogService.list(orderOpinionWrapper);
  2173 + if (CollectionUtils.isEmpty(orderOpinionLogDOList)) {
  2174 + return ServerResult.fail("订单跟单信息" + orderOpinionLogVO.getOpinionType() + "未填写");
  2175 + }
  2176 + List<Integer> okCountList = new ArrayList();
  2177 + List<Integer> FailCountList = new ArrayList();
  2178 + orderOpinionLogDOList.stream().forEach(x -> {
  2179 + if (x.getField().contains("ok") || x.getField().contains("OK")) {
  2180 + okCountList.add(Constant.ONE);
  2181 + } else if(x.getField().contains("Fail") || x.getField().contains("FAIL") ) {
  2182 + FailCountList.add(Constant.ZERO);
  2183 + }
  2184 + });
  2185 + int sum = okCountList.size() + FailCountList.size();
  2186 + double rate = ((double) okCountList.size() / sum) * Constant.HUNDRED;
  2187 + DecimalFormat decimalFormat = new DecimalFormat("0.00");
  2188 + String resultrate = decimalFormat.format(rate);
  2189 + return ServerResult.success(resultrate + "%");
  2190 + }
  2191 + return ServerResult.fail("返单订单不进行统计!");
  2192 + }
1957 2193  
  2194 + @Override
  2195 + public ServerResult produceReport(ProducePdfVO producePdfVO) {
  2196 + if (CollectionUtils.isEmpty(producePdfVO.getIds()) && org.apache.commons.lang3.StringUtils.isBlank(producePdfVO.getCompanyName())) {
  2197 + return ServerResult.fail("订单id或者公司名称为空");
  2198 + }
  2199 + List<OrderProfitAnalysisDO> orderProfitAnalysisList = profitAnalysisService.list(new LambdaQueryWrapper<OrderProfitAnalysisDO>()
  2200 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  2201 + .in(OrderProfitAnalysisDO::getOrderId, producePdfVO.getIds()));
  2202 + //必须要求每一个订单的利润分析信息都存在,才能生成生产指标书。
  2203 + if (CollectionUtils.isEmpty(orderProfitAnalysisList) || producePdfVO.getIds().size() != orderProfitAnalysisList.size()) {
  2204 + return ServerResult.fail("利润分析未填写,无法进行生成!");
  2205 + }
  2206 + ProducePdfVO producePdf = pdfUtils.createProducePdf(pdfUtils.build(producePdfVO.getIds()), "生产指示书.pdf", producePdfVO.getCompanyName());
  2207 + return ServerResult.success(producePdf);
  2208 + }
1958 2209  
1959 2210  
1960 2211 /**
... ... @@ -2053,36 +2304,179 @@ public class OrderBaseInfoServiceImpl extends ServiceImpl&lt;OrderBaseInfoMapper, O
2053 2304 return orderBaseInfoDOList;
2054 2305 }
2055 2306  
2056   - private void sendOrderInspectionStage(OrderUpdateVO updateVO,String midCheckResult,String endCheckResult){
  2307 + @Override
  2308 + public ServerResult send(ProducePdfVO producePdfVO) throws Exception {
  2309 + if (producePdfVO.getIsSend()) {
  2310 + if (StringUtils.isNotBlank(producePdfVO.getProductionUrl()) && StringUtils.isNotBlank(producePdfVO.getProductionDepartment())) {
  2311 + AdminUserDO produceUser = adminUserService.getOne(new LambdaQueryWrapper<AdminUserDO>()
  2312 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  2313 + .eq(AdminUserDO::getNickName, producePdfVO.getProductionDepartment()));
  2314 + if (Objects.nonNull(produceUser) && org.apache.commons.lang3.StringUtils.isNotBlank(produceUser.getEmail())) {
  2315 + List<String> emails = Arrays.asList(produceUser.getEmail().split("[,,]+"))
  2316 + .stream().map(String::trim)
  2317 + .filter(Objects::nonNull)
  2318 + .collect(Collectors.toList());
  2319 + if(CollectionUtils.isNotEmpty(producePdfVO.getPersonList())){
  2320 + List<AdminUserDO> personUser = adminUserService.list(new LambdaQueryWrapper<AdminUserDO>()
  2321 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  2322 + .in(AdminUserDO::getNickName, producePdfVO.getPersonList()));
  2323 + if(CollectionUtils.isNotEmpty(personUser)){
  2324 + List<String> personList = personUser.stream().map(AdminUserDO::getEmail).filter(Objects::nonNull)
  2325 + .flatMap(email -> Arrays.asList(email.split("[,,]+")).stream())
  2326 + .map(String::trim)
  2327 + .filter(s -> !s.isEmpty())
  2328 + .collect(Collectors.toList());
  2329 + if(CollectionUtils.isNotEmpty(personList)){
  2330 + emails.addAll(personList);
  2331 + }
  2332 + }
  2333 + }
  2334 + URL url1 = new URL(producePdfVO.getProductionUrl());
  2335 + InputStream inputStream = url1.openStream();
  2336 + File file = FileUtil.inputStreamToFile(inputStream, "生产指示书_" + System.currentTimeMillis() + ".pdf");
  2337 + try {
  2338 + emailSendUtils.sendEmail(EmailTemplateEnum.PRODUCE_INDICATE_REPORT, emails, file);
  2339 + } finally {
  2340 + if (file.exists()) {
  2341 + file.delete();
  2342 + System.out.println(file.delete());
  2343 + }
  2344 + }
  2345 + return ServerResult.success("已发送给" + producePdfVO.getProductionDepartment() + "生产科");
  2346 + } else {
  2347 + return ServerResult.fail("生产科邮箱不存在!");
  2348 + }
  2349 + } else {
  2350 + return ServerResult.fail("发送失败!");
  2351 + }
  2352 + }
  2353 + return ServerResult.fail("取消发送!");
  2354 + }
  2355 +
  2356 + private void sendOrderInspectionStage(OrderUpdateVO updateVO, String midCheckResult, String endCheckResult) {
2057 2357 OrderBaseInfoDO orderBaseInfoDO = baseInfoService.getById(updateVO.getOrderId());
2058 2358 AdminUserDO ProductionDepartmentUserDO = userService.getOne(new LambdaQueryWrapper<AdminUserDO>()
2059 2359 .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
2060 2360 .eq(AdminUserDO::getUserName, orderBaseInfoDO.getProductionDepartment()));
2061   - if(Objects.nonNull(ProductionDepartmentUserDO)){
  2361 + if (Objects.nonNull(ProductionDepartmentUserDO)) {
2062 2362 OrderEventJobVO orderEventJobVO = new OrderEventJobVO();
2063 2363 orderEventJobVO.setInspectionStageInfo(updateVO.getInspectionStageInfo());
2064 2364 OrderBaseInfoVO orderBaseInfoVo = BeanUtil.copyProperties(orderBaseInfoDO, OrderBaseInfoVO.class);
2065 2365 orderEventJobVO.setBaseInfo(orderBaseInfoVo);
2066   - List<String> emails = Arrays.asList(ProductionDepartmentUserDO.getEmail().split( "[,,]+"))
  2366 + List<String> emails = Arrays.asList(ProductionDepartmentUserDO.getEmail().split("[,,]+"))
2067 2367 .stream().map(String::trim)
  2368 + .filter(Objects::nonNull)
2068 2369 .collect(Collectors.toList());
2069 2370 //一旦修改完质检信息就自动发送邮件对应的生产科。多次编辑保存多次发送。
2070   - if (StringUtils.isNotBlank(updateVO.getInspectionStageInfo().getEndCheckResult()) && !(updateVO.getInspectionStageInfo().getEndCheckResult().equals(endCheckResult))) {
2071   - String EndCheckApplyTime= updateVO.getInspectionStageInfo().getEndCheckApplyTime().substring(0, 10);
2072   - String ProductionDepartmentConsignTime =orderBaseInfoDO.getProductionDepartmentConsignTime().substring(0, 10);
  2371 + if (StringUtils.isNotBlank(updateVO.getInspectionStageInfo().getEndCheckResult()) && !(updateVO.getInspectionStageInfo().getEndCheckResult().equals(endCheckResult))) {
  2372 + String EndCheckApplyTime = "";
  2373 + if (StringUtils.isNotBlank(updateVO.getInspectionStageInfo().getEndCheckApplyTime())) {
  2374 + EndCheckApplyTime = updateVO.getInspectionStageInfo().getEndCheckApplyTime().substring(0, 10);
  2375 + }
  2376 + String ProductionDepartmentConsignTime = orderBaseInfoDO.getProductionDepartmentConsignTime().substring(0, 10);
2073 2377 orderEventJobVO.getInspectionStageInfo().setEndCheckApplyTime(EndCheckApplyTime);
2074 2378 orderEventJobVO.getBaseInfo().setProductionDepartmentConsignTime(ProductionDepartmentConsignTime);
2075   - //尾期验货报告。
2076   - emailSendUtils.sendEmail(EmailTemplateEnum.END_CHECK_REPORT_TEMPLATE, emails, orderEventJobVO);
2077   - }else if(StringUtils.isNotBlank(updateVO.getInspectionStageInfo().getMidCheckResult()) && !(updateVO.getInspectionStageInfo().getMidCheckResult().equals(midCheckResult))){
2078   - String MidCheckApplyTime= updateVO.getInspectionStageInfo().getMidCheckApplyTime().substring(0, 10);
2079   - String ProductionDepartmentConsignTime =orderBaseInfoDO.getProductionDepartmentConsignTime().substring(0, 10);
2080   - String MidCheckApply = DateUtils.format(DateUtils.parseDate(MidCheckApplyTime, DATE), DATE);
2081   - String ProductionDepartmentConsign = DateUtils.format(DateUtils.parseDate(ProductionDepartmentConsignTime,DATE), DATE);
2082   - orderEventJobVO.getInspectionStageInfo().setMidCheckApplyTime(MidCheckApply);
2083   - orderEventJobVO.getBaseInfo().setProductionDepartmentConsignTime(ProductionDepartmentConsign);
2084   - //中期验货报告。
2085   - emailSendUtils.sendEmail(EmailTemplateEnum.MID_CHECK_REPORT_TEMPLATE, emails, orderEventJobVO);
  2379 + LambdaQueryWrapper<ReceiveEmailMappingDO> receiveEmailMappingDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
  2380 + receiveEmailMappingDOLambdaQueryWrapper.eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN);
  2381 + if(!orderBaseInfoDO.getCustomerCode().contains("-") && !orderBaseInfoDO.getCustomerCode().contains("——")){
  2382 + receiveEmailMappingDOLambdaQueryWrapper.eq(ReceiveEmailMappingDO::getTypeValue, orderBaseInfoDO.getCustomerCode())
  2383 + .last("limit 1");
  2384 + }else{
  2385 + receiveEmailMappingDOLambdaQueryWrapper.like(ReceiveEmailMappingDO::getTypeValue,orderBaseInfoDO.getCustomerCode().split("-")[0])
  2386 + .last("limit 1");
  2387 + }
  2388 + ReceiveEmailMappingDO receiveEmailMappingDO = receiveEmailMappingService.getOne( receiveEmailMappingDOLambdaQueryWrapper);
  2389 +
  2390 + List<String> emailList = new ArrayList<>();
  2391 + if (Objects.nonNull(receiveEmailMappingDO)) {
  2392 + List<ReceiveEmailConfigItemVO> receiveEmailConfigItemVOList = JSON.parseObject(
  2393 + receiveEmailMappingDO.getConfigInfos(), new TypeReference<List<ReceiveEmailConfigItemVO>>() {
  2394 + });
  2395 + for (ReceiveEmailConfigItemVO item : receiveEmailConfigItemVOList) {
  2396 + if (OrderEventEnum.END_CHECK_REPORT_EVENT.getEvent().equals(item.getEvent())) {
  2397 + emailList = item.getEmails();
  2398 + }
  2399 + }
  2400 + }
  2401 + if (CollectionUtils.isNotEmpty(emails) && CollectionUtils.isNotEmpty(emailList)) {
  2402 + List<String> emailLists = emailList.stream().flatMap(email -> Arrays.stream(email.split("[,,]+"))).collect(Collectors.toList());
  2403 + List<String> combineEmail = new ArrayList<>(emails);
  2404 + combineEmail.addAll(emailLists);
  2405 +
  2406 + //尾期验货报告。
  2407 + emailSendUtils.sendEmail(EmailTemplateEnum.END_CHECK_REPORT_TEMPLATE, combineEmail, orderEventJobVO);
  2408 + }
  2409 + } else if (StringUtils.isNotBlank(updateVO.getInspectionStageInfo().getMidCheckResult()) && !(updateVO.getInspectionStageInfo().getMidCheckResult().equals(midCheckResult))) {
  2410 + String MidCheckApplyTime = "";
  2411 + if (StringUtils.isNotBlank(updateVO.getInspectionStageInfo().getMidCheckApplyTime())) {
  2412 + MidCheckApplyTime = updateVO.getInspectionStageInfo().getMidCheckApplyTime().substring(0, 10);
  2413 + }
  2414 + String ProductionDepartmentConsignTime = orderBaseInfoDO.getProductionDepartmentConsignTime().substring(0, 10);
  2415 + orderEventJobVO.getInspectionStageInfo().setMidCheckApplyTime(MidCheckApplyTime);
  2416 + orderEventJobVO.getBaseInfo().setProductionDepartmentConsignTime(ProductionDepartmentConsignTime);
  2417 + LambdaQueryWrapper<ReceiveEmailMappingDO> receiveEmailMappingDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
  2418 + receiveEmailMappingDOLambdaQueryWrapper.eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN);
  2419 + if(!orderBaseInfoDO.getCustomerCode().contains("-") && !orderBaseInfoDO.getCustomerCode().contains("——")){
  2420 + receiveEmailMappingDOLambdaQueryWrapper.eq(ReceiveEmailMappingDO::getTypeValue, orderBaseInfoDO.getCustomerCode())
  2421 + .last("limit 1");
  2422 + }else{
  2423 + receiveEmailMappingDOLambdaQueryWrapper.like(ReceiveEmailMappingDO::getTypeValue,orderBaseInfoDO.getCustomerCode().split("-")[0])
  2424 + .last("limit 1");
  2425 + }
  2426 + ReceiveEmailMappingDO receiveEmailMappingDO = receiveEmailMappingService.getOne( receiveEmailMappingDOLambdaQueryWrapper);
  2427 + List<String> emailList = new ArrayList<>();
  2428 + if (Objects.nonNull(receiveEmailMappingDO)) {
  2429 + List<ReceiveEmailConfigItemVO> receiveEmailConfigItemVOList = JSON.parseObject(
  2430 + receiveEmailMappingDO.getConfigInfos(), new TypeReference<List<ReceiveEmailConfigItemVO>>() {
  2431 + });
  2432 + for (ReceiveEmailConfigItemVO item : receiveEmailConfigItemVOList) {
  2433 + if (OrderEventEnum.END_CHECK_REPORT_EVENT.getEvent().equals(item.getEvent())) {
  2434 + emailList = item.getEmails();
  2435 + }
  2436 + }
  2437 + }
  2438 + if (CollectionUtils.isNotEmpty(emails) && CollectionUtils.isNotEmpty(emailList)) {
  2439 + List<String> emailLists = emailList.stream().flatMap(email -> Arrays.stream(email.split("[,,]+"))).collect(Collectors.toList());
  2440 + List<String> combineEmail = new ArrayList<>(emails);
  2441 + combineEmail.addAll(emailLists);
  2442 + //中期验货报告。
  2443 + emailSendUtils.sendEmail(EmailTemplateEnum.MID_CHECK_REPORT_TEMPLATE, combineEmail, orderEventJobVO);
  2444 +
  2445 + }
  2446 + }
  2447 + }
  2448 + }
  2449 +
  2450 + private void sendProductionCommentEmail(OrderBaseInfoDO orderBaseInfoDo, String productionComment) {
  2451 + List<AdminUserDO> adminList = adminUserService.list(new LambdaQueryWrapper<AdminUserDO>()
  2452 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  2453 + .in(AdminUserDO::getUserName, Arrays.asList(orderBaseInfoDo.getBusinessPerson(), orderBaseInfoDo.getCreateBy(), orderBaseInfoDo.getProductionDepartment())));
  2454 + if (CollectionUtils.isNotEmpty(adminList)) {
  2455 + List<String> emailsList = adminList.stream().map(AdminUserDO::getEmail).filter(Objects::nonNull).collect(Collectors.toList());
  2456 + if (CollectionUtils.isNotEmpty(emailsList)) {
  2457 + List<String> emailList = emailsList.stream()
  2458 + .flatMap(email -> Arrays.stream(email.split("[,,]+")))
  2459 + .collect(Collectors.toList());
  2460 + if (CollectionUtils.isNotEmpty(emailList)) {
  2461 + OrderEventJobVO orderEventJobVO = new OrderEventJobVO();
  2462 + orderEventJobVO.setBaseInfo(new OrderBaseInfoVO());
  2463 +
  2464 + orderEventJobVO.getBaseInfo().setProjectNo(orderBaseInfoDo.getProjectNo());
  2465 + orderEventJobVO.getBaseInfo().setProductionDepartment(orderBaseInfoDo.getProductionDepartment());
  2466 + orderEventJobVO.getBaseInfo().setInnerNo(orderBaseInfoDo.getInnerNo());
  2467 + orderEventJobVO.getBaseInfo().setCustomerPo(orderBaseInfoDo.getCustomerPo());
  2468 + orderEventJobVO.getBaseInfo().setCustomerStyle(orderBaseInfoDo.getCustomerStyle());
  2469 + orderEventJobVO.getBaseInfo().setPoColor(orderBaseInfoDo.getPoColor());
  2470 + orderEventJobVO.getBaseInfo().setSmallPicUrl(orderBaseInfoDo.getSmallPicUrl());
  2471 + orderEventJobVO.getBaseInfo().setOrderCount(orderBaseInfoDo.getOrderCount());
  2472 + String[] split = productionComment.split("\n");
  2473 + String[] split1 = split[split.length - 1].split("[::]+");
  2474 + String lastProductionComment = split1[split1.length - 1];
  2475 + orderEventJobVO.getBaseInfo().setProductionComment(lastProductionComment);
  2476 + orderEventJobVO.getBaseInfo().setProductionDepartmentConsignTime(orderBaseInfoDo.getProductionDepartmentConsignTime().substring(0, 10));
  2477 + //目前是选择的是跟单员邮箱和业务员邮箱。
  2478 + emailSendUtils.sendEmail(EmailTemplateEnum.PRODUCE_IDEA, emailList, orderEventJobVO);
  2479 + }
2086 2480 }
2087 2481 }
2088 2482 }
... ...
src/main/java/com/order/erp/service/order/impl/OrderOpinionLogServiceImpl.java 0 → 100644
  1 +package com.order.erp.service.order.impl;
  2 +
  3 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  5 +import com.order.erp.common.constant.Constant;
  6 +import com.order.erp.common.constant.ServerResult;
  7 +import com.order.erp.domain.dto.BaseDO;
  8 +import com.order.erp.domain.dto.order.OrderOpinionLogDO;
  9 +import com.order.erp.domain.vo.order.OrderOpinionLogVO;
  10 +import com.order.erp.mapper.order.OrderOpinionLogMapper;
  11 +import com.order.erp.service.order.OrderOpinionLogService;
  12 +import lombok.extern.slf4j.Slf4j;
  13 +import org.springframework.stereotype.Service;
  14 +
  15 +import java.util.List;
  16 +import java.util.Objects;
  17 +
  18 +
  19 +/**
  20 + * @Author:ch
  21 + * @createTime:2024-08-05
  22 + */
  23 +@Slf4j
  24 +@Service
  25 +public class OrderOpinionLogServiceImpl extends ServiceImpl<OrderOpinionLogMapper, OrderOpinionLogDO> implements OrderOpinionLogService {
  26 + @Override
  27 + public ServerResult queryById(OrderOpinionLogVO orderOpinionLogVo) {
  28 + log.info("orderId"+orderOpinionLogVo.getOrderId());
  29 + System.out.println(orderOpinionLogVo);
  30 + if (Objects.isNull(orderOpinionLogVo.getOrderId())) {
  31 + return ServerResult.fail("OrderId 不能为空");
  32 + }
  33 + List<OrderOpinionLogDO> orderOpinionLogDOList = list(new LambdaQueryWrapper<OrderOpinionLogDO>()
  34 + .eq(BaseDO::getEnableFlag, Constant.ENABLE_TEN)
  35 + .eq(OrderOpinionLogDO::getOrderId, orderOpinionLogVo.getOrderId())
  36 + .orderByDesc(OrderOpinionLogDO::getId));
  37 + return ServerResult.success(orderOpinionLogDOList);
  38 + }
  39 +}
... ...
src/main/resources/templates/mail.ftl
... ... @@ -70,7 +70,7 @@
70 70 <td> 不良2 </td>
71 71 <td> 不良3 </td>
72 72 <td> 包装:卡片、条码、箱贴、箱单 </td>
73   - <td> 期验货结果PASS/FALL </td>
  73 + <td> 期验货结果PASS/FALL </td>
74 74 <#elseif title=="尾期验货日期">
75 75 <td> 客户编码</td>
76 76 <td> 项目号</td>
... ... @@ -83,20 +83,31 @@
83 83 <td> 生产要求</td>
84 84 <td> 数量</td>
85 85 <td> 生产科拖货时间</td>
  86 + <#elseif title=="产品意见信息" >
  87 + <td> 项目号</td>
  88 + <td> 生产科</td>
  89 + <td> 内部编号</td>
  90 + <td> 客户PO号</td>
  91 + <td> 客户SYSTEM</td>
  92 + <td> PO COLOR</td>
  93 + <td> 订单图片</td>
  94 + <td> 生产要求</td>
  95 + <td> 数量</td>
  96 + <td> 生产科拖货时间</td>
86 97 <#else>
87   - <td> 客户编码</td>
88   - <td> 项目号</td>
89   - <td> 生产科</td>
90   - <td> 内部编号</td>
91   - <td> 客户PO号</td>
92   - <td> 客户SYSTEM</td>
93   - <td> PO COLOR</td>
94   - <td> 订单图片</td>
95   - <td> 生产要求</td>
96   - <td> 数量</td>
97   - <td> 生产科拖货时间</td>
98   - <td> 订单上的HOD时间</td>
99   - <td> 出库类型</td>
  98 + <td> 客户编码</td>
  99 + <td> 项目号</td>
  100 + <td> 生产科</td>
  101 + <td> 内部编号</td>
  102 + <td> 客户PO号</td>
  103 + <td> 客户SYSTEM</td>
  104 + <td> PO COLOR</td>
  105 + <td> 订单图片</td>
  106 + <td> 生产要求</td>
  107 + <td> 数量</td>
  108 + <td> 生产科拖货时间</td>
  109 + <td> 订单上的HOD时间</td>
  110 + <td> 出库类型</td>
100 111 </#if>
101 112 </tr>
102 113 <tr id="title2">
... ... @@ -148,6 +159,17 @@
148 159 <td>${data.baseInfo.productionComment!" "}</td>
149 160 <td>${data.baseInfo.orderCount! " "}</td>
150 161 <td>${data.baseInfo.productionDepartmentConsignTime! " "}</td>
  162 + <#elseif title=="产品意见信息">
  163 + <td>${data.baseInfo.projectNo! " "}</td>
  164 + <td>${data.baseInfo.productionDepartment! " "}</td>
  165 + <td>${data.baseInfo.innerNo!" "}</td>
  166 + <td>${data.baseInfo.customerPo!" "}</td>
  167 + <td>${data.baseInfo.customerStyle!" "}</td>
  168 + <td>${data.baseInfo.poColor!" "}</td>
  169 + <td><img src="${data.baseInfo.smallPicUrl! " "}" alt="Image"></td>
  170 + <td>${data.baseInfo.productionComment!" "}</td>
  171 + <td>${data.baseInfo.orderCount! " "}</td>
  172 + <td>${data.baseInfo.productionDepartmentConsignTime! " "}</td>
151 173 <#else>
152 174 <td>${data.baseInfo.customerCode! " "}</td>
153 175 <td>${data.baseInfo.projectNo! " "}</td>
... ...