Browse Source

白胚布靶向预测功能

wukai 6 months ago
parent
commit
a24ebeaff4

+ 274 - 28
ruoyi-admin/src/main/java/com/ruoyi/biz/domain/TwinFormulaInfo.java

@@ -7,13 +7,13 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import java.math.BigDecimal;
+import java.util.Map;
 
 /**
  * 设备配方信息对象 twin_formula_info
  *
  * @author ruoyi
- * @date 2024-12-29
+ * @date 2025-01-03
  */
 @ApiModel(value = "ITwinFormulaInfo", description = "设备配方信息")
 @Data
@@ -21,15 +21,47 @@ import java.math.BigDecimal;
 public class TwinFormulaInfo extends BaseEntity {
     private static final long serialVersionUID = 1L;
 
-    public TwinFormulaInfo(FormulaDetail detail) {
+    public TwinFormulaInfo(Map<String, Object> map) {
+        TwinDevice twinDevice = (TwinDevice) map.get("device");
         //使用deviceId做主键
-        this.specInfoId = detail.getDeviceId();
-        this.deviceId = detail.getDeviceId();
-        this.formula = detail.getFormula_data_1();
-        this.mick = detail.getFormula_data_3();
-        this.length = BigDecimal.valueOf(detail.getFormula_data_16());
-        this.width = BigDecimal.valueOf(detail.getFormula_data_17());
-        this.weight = BigDecimal.valueOf(detail.getFormula_data_18());
+        this.specInfoId = twinDevice.getDeviceId();
+        this.deviceId = twinDevice.getDeviceId();
+        this.fd1 = (int) map.get("Formula_data_1");
+        this.fd2 = (int) map.get("Formula_data_2");
+        this.fd3 = (int) map.get("Formula_data_3");
+        this.fd4 = (int) map.get("Formula_data_4");
+        this.fd5 = (int) map.get("Formula_data_5");
+        this.fd6 = (int) map.get("Formula_data_6");
+        this.fd7 = (int) map.get("Formula_data_7");
+        this.fd8 = (int) map.get("Formula_data_8");
+        this.fd9 = (int) map.get("Formula_data_9");
+        this.fd10 = (int) map.get("Formula_data_10");
+        this.fd11 = (int) map.get("Formula_data_11");
+        this.fd12 = (int) map.get("Formula_data_12");
+        this.fd13 = (float) map.get("Formula_data_13");
+        this.fd14 = (float) map.get("Formula_data_14");
+        this.fd15 = (float) map.get("Formula_data_15");
+        this.fd16 = (float) map.get("Formula_data_16");
+        this.fd17 = (float) map.get("Formula_data_17");
+        this.fd18 = (float) map.get("Formula_data_18");
+        this.fd19 = (int) map.get("Formula_data_19");
+        this.fd20 = (int) map.get("Formula_data_20");
+        this.fd21 = (int) map.get("Formula_data_21");
+        this.fd22 = (int) map.get("Formula_data_22");
+        this.fd23 = (int) map.get("Formula_data_23");
+        this.fd24 = (float) map.get("Formula_data_24");
+        this.fd25 = (float) map.get("Formula_data_25");
+
+        this.cd10 = (float) map.get("Capacity_data_10");
+        this.cd11 = (float) map.get("Capacity_data_11");
+        this.cd12 = (float) map.get("Capacity_data_12");
+        this.cd13 = (float) map.get("Capacity_data_13");
+        this.cd14 = (float) map.get("Capacity_data_14");
+        this.cd15 = (int) map.get("Capacity_data_15");
+        this.cd16 = (int) map.get("Capacity_data_16");
+        this.cd17 = (int) map.get("Capacity_data_17");
+        this.cd18 = (int) map.get("Capacity_data_18");
+        this.cd19 = (int) map.get("Capacity_data_19");
     }
 
     /**
@@ -45,33 +77,247 @@ public class TwinFormulaInfo extends BaseEntity {
     private Long deviceId;
 
     /**
-     * 
+     * 配方号
      */
-    @Excel(name = "")
-    @ApiModelProperty("")
-    private BigDecimal length;
+    @Excel(name = "配方号")
+    @ApiModelProperty("配方号")
+    private Integer fd1;
 
     /**
-     * 
+     * 机台号
      */
-    @Excel(name = "")
-    @ApiModelProperty("")
-    private BigDecimal width;
+    @Excel(name = "机台号")
+    @ApiModelProperty("机台号")
+    private Integer fd2;
 
     /**
-     * 重
+     * 米克
      */
-    @Excel(name = "重")
-    @ApiModelProperty("重")
-    private BigDecimal weight;
+    @Excel(name = "米克重")
+    @ApiModelProperty("米克重")
+    private Integer fd3;
 
     /**
-     * 配方号
+     * L1、L5纱线规格D
      */
-    @Excel(name = "配方号")
-    @ApiModelProperty("配方号")
-    private Integer formula;
+    @Excel(name = "L1、L5纱线规格D")
+    @ApiModelProperty("L1、L5纱线规格D")
+    private Integer fd4;
 
-    @ApiModelProperty("米克重")
-    private Integer mick;
+    /**
+     * L2、L4纱线规格D
+     */
+    @Excel(name = "L2、L4纱线规格D")
+    @ApiModelProperty("L2、L4纱线规格D")
+    private Integer fd5;
+
+    /**
+     * L3纱线规格D
+     */
+    @Excel(name = "L3纱线规格D")
+    @ApiModelProperty("L3纱线规格D")
+    private Integer fd6;
+
+    /**
+     * L1、L5纱线规格F
+     */
+    @Excel(name = "L1、L5纱线规格F")
+    @ApiModelProperty("L1、L5纱线规格F")
+    private Integer fd7;
+
+    /**
+     * L2、L4纱线规格F
+     */
+    @Excel(name = "L2、L4纱线规格F")
+    @ApiModelProperty("L2、L4纱线规格F")
+    private Integer fd8;
+
+    /**
+     * L3纱线规格F
+     */
+    @Excel(name = "L3纱线规格F")
+    @ApiModelProperty("L3纱线规格F")
+    private Integer fd9;
+
+    /**
+     * L1、L5盘头根数
+     */
+    @Excel(name = "L1、L5盘头根数")
+    @ApiModelProperty("L1、L5盘头根数")
+    private Integer fd10;
+
+    /**
+     * L2、L4盘头根数
+     */
+    @Excel(name = "L2、L4盘头根数")
+    @ApiModelProperty("L2、L4盘头根数")
+    private Integer fd11;
+
+    /**
+     * L3盘头根数
+     */
+    @Excel(name = "L3盘头根数")
+    @ApiModelProperty("L3盘头根数")
+    private Integer fd12;
+
+    /**
+     * 卷曲幅宽
+     */
+    @Excel(name = "卷曲幅宽")
+    @ApiModelProperty("卷曲幅宽")
+    private Float fd13;
+
+    /**
+     * 下布长度
+     */
+    @Excel(name = "下布长度")
+    @ApiModelProperty("下布长度")
+    private Float fd14;
+
+    /**
+     * 毛高
+     */
+    @Excel(name = "毛高")
+    @ApiModelProperty("毛高")
+    private Float fd15;
+
+    /**
+     * 成品长
+     */
+    @Excel(name = "成品长")
+    @ApiModelProperty("成品长")
+    private Float fd16;
+
+    /**
+     * 成品宽
+     */
+    @Excel(name = "成品宽")
+    @ApiModelProperty("成品宽")
+    private Float fd17;
+
+    /**
+     * 成品重
+     */
+    @Excel(name = "成品重")
+    @ApiModelProperty("成品重")
+    private Float fd18;
+
+    /**
+     * GB1送经量
+     */
+    @Excel(name = "GB1送经量")
+    @ApiModelProperty("GB1送经量")
+    private Integer fd19;
+
+    /**
+     * GB2送经量
+     */
+    @Excel(name = "GB2送经量")
+    @ApiModelProperty("GB2送经量")
+    private Integer fd20;
+
+    /**
+     * GB3送经量
+     */
+    @Excel(name = "GB3送经量")
+    @ApiModelProperty("GB3送经量")
+    private Integer fd21;
+
+    /**
+     * GB4送经量
+     */
+    @Excel(name = "GB4送经量")
+    @ApiModelProperty("GB4送经量")
+    private Integer fd22;
+
+    /**
+     * GB5送经量
+     */
+    @Excel(name = "GB5送经量")
+    @ApiModelProperty("GB5送经量")
+    private Integer fd23;
+
+    /**
+     * 牵拉密度
+     */
+    @Excel(name = "牵拉密度")
+    @ApiModelProperty("牵拉密度")
+    private Float fd24;
+
+    /**
+     * 卷曲张力系数
+     */
+    @Excel(name = "卷曲张力系数")
+    @ApiModelProperty("卷曲张力系数")
+    private Float fd25;
+
+    /**
+     * GB1盘头剩余周长
+     */
+    @Excel(name = "GB1盘头剩余周长")
+    @ApiModelProperty("GB1盘头剩余周长")
+    private Float cd10;
+
+    /**
+     * GB2盘头剩余周长
+     */
+    @Excel(name = "GB2盘头剩余周长")
+    @ApiModelProperty("GB2盘头剩余周长")
+    private Float cd11;
+
+    /**
+     * GB3盘头剩余周长
+     */
+    @Excel(name = "GB3盘头剩余周长")
+    @ApiModelProperty("GB3盘头剩余周长")
+    private Float cd12;
+
+    /**
+     * GB4盘头剩余周长
+     */
+    @Excel(name = "GB4盘头剩余周长")
+    @ApiModelProperty("GB4盘头剩余周长")
+    private Float cd13;
+
+    /**
+     * GB5盘头剩余周长
+     */
+    @Excel(name = "GB5盘头剩余周长")
+    @ApiModelProperty("GB5盘头剩余周长")
+    private Float cd14;
+
+    /**
+     * GB1盘头剩余圈数
+     */
+    @Excel(name = "GB1盘头剩余圈数")
+    @ApiModelProperty("GB1盘头剩余圈数")
+    private Integer cd15;
+
+    /**
+     * GB2盘头剩余圈数
+     */
+    @Excel(name = "GB2盘头剩余圈数")
+    @ApiModelProperty("GB2盘头剩余圈数")
+    private Integer cd16;
+
+    /**
+     * GB3盘头剩余圈数
+     */
+    @Excel(name = "GB3盘头剩余圈数")
+    @ApiModelProperty("GB3盘头剩余圈数")
+    private Integer cd17;
+
+    /**
+     * GB4盘头剩余圈数
+     */
+    @Excel(name = "GB4盘头剩余圈数")
+    @ApiModelProperty("GB4盘头剩余圈数")
+    private Integer cd18;
+
+    /**
+     * GB5盘头剩余圈数
+     */
+    @Excel(name = "GB5盘头剩余圈数")
+    @ApiModelProperty("GB5盘头剩余圈数")
+    private Integer cd19;
 }

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/biz/service/impl/ApiServiceImpl.java

@@ -166,7 +166,7 @@ public class ApiServiceImpl implements IApiService {
                 FormulaDetail detail = new FormulaDetail(map);
                 formulaDetail.add(detail);
 
-                TwinFormulaInfo formulaInfo = new TwinFormulaInfo(detail);
+                TwinFormulaInfo formulaInfo = new TwinFormulaInfo(map);
                 formulaInfos.add(formulaInfo);
                 //处理送经量数据
                 WarpRunIn warpRunIn = new WarpRunIn(map);

+ 14 - 17
ruoyi-admin/src/main/java/com/ruoyi/nccloud/utils/NccloudUtils.java

@@ -12,6 +12,7 @@ import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -107,7 +108,7 @@ public class NccloudUtils {
         paramMap.put("client_id", CLIENT_ID);
         // 第三方应用secret 公钥加密
         String secret_entryption = Encryption.pubEncrypt(PUB_KEY, CLIENT_SECRET);
-        System.out.println("secret_entryption::" + secret_entryption);
+//        System.out.println("secret_entryption::" + secret_entryption);
         paramMap.put("client_secret", URLEncoder.encode(secret_entryption, "utf-8"));
         // 账套编码
         paramMap.put("biz_center", BUSI_CENTER);
@@ -117,12 +118,11 @@ public class NccloudUtils {
         // 签名
         String sign = SHA256Util.getSHA256(CLIENT_ID + CLIENT_SECRET + PUB_KEY, PUB_KEY);
         paramMap.put("signature", sign);
-        System.out.println("##gettoken sign::" + sign);
+//        System.out.println("##gettoken sign::" + sign);
 
         String url = BASE_URL + "/nccloud/opm/accesstoken";
         String mediaType = "application/x-www-form-urlencoded";
-        String token = doPost(url, paramMap, mediaType, null, "");
-        return token;
+        return doPost(url, paramMap, mediaType, null, "");
     }
 
     /**
@@ -150,7 +150,7 @@ public class NccloudUtils {
             security_key = (String) data.get("security_key");
             refresh_token = (String) data.get("refresh_token");
         }
-        System.out.println("【ACCESS_TOKEN】:" + access_token);
+//        System.out.println("【ACCESS_TOKEN】:" + access_token);
 
         // 请求路径
         String url = BASE_URL + API_URL;
@@ -159,7 +159,7 @@ public class NccloudUtils {
         headerMap.put("access_token", access_token);
         headerMap.put("client_id", CLIENT_ID);
 
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append(CLIENT_ID);
         if (StringUtils.isNotBlank(requestBody)) {
             // sb.append(requestBody.replaceAll("\\s*|\t|\r|\n", "").trim());
@@ -263,9 +263,9 @@ public class NccloudUtils {
                 for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                     String key = entry.getKey();
                     String value = entry.getValue();
-                    sb.append(key + "=" + value).append("&");
+                    sb.append(key).append("=").append(value).append("&");
                 }
-                baseUrl = sb.toString().substring(0, sb.toString().length() - 1);
+                baseUrl = sb.substring(0, sb.toString().length() - 1);
             }
 
             URL urlObj = new URL(baseUrl);
@@ -282,17 +282,17 @@ public class NccloudUtils {
                 }
             }
             out = urlConnection.getOutputStream();
-            out.write(json.getBytes("utf-8"));
+            out.write(json.getBytes(StandardCharsets.UTF_8));
             out.flush();
             int resCode = urlConnection.getResponseCode();
-            System.out.println("状态码::" + resCode);
+//            System.out.println("状态码::" + resCode);
 //			if (resCode == HttpURLConnection.HTTP_OK || resCode == HttpURLConnection.HTTP_CREATED || resCode == HttpURLConnection.HTTP_ACCEPTED) {
             in = urlConnection.getInputStream();
 //			} else {
 //				in = urlConnection.getErrorStream();
 //			}
-            bufferedReader = new BufferedReader(new InputStreamReader(in, "utf-8"));
-            StringBuffer temp = new StringBuffer();
+            bufferedReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+            StringBuilder temp = new StringBuilder();
             String line = bufferedReader.readLine();
             while (line != null) {
                 temp.append(line).append("\r\n");
@@ -300,13 +300,10 @@ public class NccloudUtils {
             }
             String ecod = urlConnection.getContentEncoding();
             if (ecod == null) {
-                ecod = Charset.forName("utf-8").name();
+                ecod = StandardCharsets.UTF_8.name();
             }
-            result = new String(temp.toString().getBytes("utf-8"), ecod);
+            result = new String(temp.toString().getBytes(StandardCharsets.UTF_8), ecod);
 //            System.out.println(result);
-        } catch (Exception e) {
-            System.out.println(e);
-            throw e;
         } finally {
             if (null != bufferedReader) {
                 try {

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/nccloud/utils/SHA256Util.java

@@ -30,7 +30,7 @@ public class SHA256Util {
             e.printStackTrace();
         }
         String salt_string = Base64Util.encryptBASE64(salt);
-        System.out.println("salt_String::" + salt_string);
+//        System.out.println("salt_String::" + salt_string);
         return getSHA256(str + salt_string.replaceAll("\r|\n", ""));
     }
 

+ 613 - 0
ruoyi-admin/src/main/java/com/ruoyi/order/controller/OrderApiController.java

@@ -0,0 +1,613 @@
+package com.ruoyi.order.controller;
+
+import com.ruoyi.biz.domain.TwinCalcDay;
+import com.ruoyi.biz.domain.TwinFormulaInfo;
+import com.ruoyi.biz.service.ITwinCalcDayService;
+import com.ruoyi.biz.service.ITwinFormulaInfoService;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.order.domain.TwinOrder;
+import com.ruoyi.order.domain.TwinOrderDetail;
+import com.ruoyi.order.domain.VmsStock;
+import com.ruoyi.order.service.ITwinOrderService;
+import com.ruoyi.order.utils.MssqlUtil;
+import com.ruoyi.order.vo.BomVO;
+import com.ruoyi.order.vo.SkuVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.chart.*;
+import org.apache.poi.xssf.usermodel.*;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTDLbls;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * @author ruoyi
+ */
+@Api("数据接口")
+@RestController
+@Slf4j
+@RequestMapping()
+public class OrderApiController extends BaseController {
+    @Resource
+    private ITwinOrderService orderService;
+    @Resource
+    private ITwinFormulaInfoService formulaInfoService;
+    @Resource
+    private ITwinCalcDayService dayService;
+    private CellStyle p2;
+    private CellStyle percentStyle;
+
+    private CellStyle bk;
+
+    @ApiOperation("查看当前库存")
+    @GetMapping("/api/stock")
+    @CrossOrigin(origins = "*")
+    @ResponseBody
+    public Map<String, Object> stock() {
+
+        Map<String, Object> result = new HashMap<>();
+        Map<String, Object> cp = new HashMap<>();
+        cp.put("d-in", 100);
+        cp.put("d-out", 101);
+        cp.put("m-in", 102);
+        cp.put("m-out", 103);
+        Map<String, Object> ycl = new HashMap<>();
+        ycl.put("d-in", 200);
+        ycl.put("d-out", 201);
+        ycl.put("m-in", 202);
+        ycl.put("m-out", 203);
+        Map<String, Object> bpb = new HashMap<>();
+        bpb.put("d-in", 300);
+        bpb.put("d-out", 301);
+        bpb.put("m-in", 302);
+        bpb.put("m-out", 303);
+        Map<String, Object> pt = new HashMap<>();
+        pt.put("d-in", 400);
+        pt.put("d-out", 401);
+        pt.put("m-in", 402);
+        pt.put("m-out", 403);
+
+        result.put("cp", cp);
+        result.put("ycl", ycl);
+        result.put("bpb", bpb);
+        result.put("pt", pt);
+
+        return result;
+    }
+
+    @ApiOperation("导出白胚预测")
+    @GetMapping("/api/export/order")
+    @CrossOrigin(origins = "*")
+    public void orderExport(String start, String end, HttpServletResponse response) {
+        //查询订单
+        List<TwinOrder> orderList = orderService.selectTwinOrderListByDate(start, end);
+        //按订单ID分组
+        Map<Long, TwinOrder> orderMap = orderList.stream().collect(Collectors.toMap(TwinOrder::getOderId, o -> o));
+        List<TwinFormulaInfo> infos = formulaInfoService.selectTwinFormulaInfoList(new TwinFormulaInfo());
+        LocalDateTime ldt = LocalDateTime.now();
+        Date sd;
+        if (ldt.getHour() > 7) {
+            sd = DateUtils.toDate(LocalDate.now().minusDays(1));
+        } else {
+            sd = DateUtils.toDate(LocalDate.now().minusDays(2));
+        }
+        List<TwinCalcDay> dayList = dayService.selectTwinCalcDayListByTime(sd, sd);
+        //按设备ID分组
+        Map<Long, TwinCalcDay> dayMap = dayList.stream().collect(Collectors.toMap(TwinCalcDay::getDeviceId, o -> o));
+        List<VmsStock> stocks = MssqlUtil.stock();
+        List<TwinOrderDetail> all = new ArrayList<>();
+        orderList.forEach(to -> all.addAll(to.getTwinOrderDetailList()));
+        //按规格分组
+        Map<String, List<TwinOrderDetail>> allMap = all.stream().collect(Collectors.groupingBy(TwinOrderDetail::getBomSpec, LinkedHashMap::new, Collectors.toList()));
+        List<BomVO> bomList = new ArrayList<>();
+        List<SkuVO> skuList = new ArrayList<>();
+        for (String spec : allMap.keySet()) {
+            List<TwinOrderDetail> todList = allMap.get(spec);
+            //匹配白胚布库存
+            Float kc = 0f;
+            VmsStock stock = matchStock(spec, stocks);
+            if (stock != null) {
+                kc = stock.getQty();
+            }
+            //匹配生产设备
+            List<TwinFormulaInfo> matchFormula = matchFormula(spec, infos);
+            BigDecimal cl = BigDecimal.ZERO;
+            String deviceIds = "";
+            for (TwinFormulaInfo match : matchFormula) {
+                if (StringUtils.isNotEmpty(deviceIds)) {
+                    deviceIds += ",";
+                }
+                deviceIds += match.getDeviceId();
+                TwinCalcDay day = dayMap.get(match.getDeviceId());
+                if (day != null) {
+                    cl = cl.add(day.getWeight());
+                }
+            }
+
+            cl = cl.multiply(BigDecimal.valueOf(1000));
+
+
+            BomVO bom = new BomVO();
+            bom.setDeviceIds(deviceIds);
+            bom.setLast(cl.doubleValue());
+            //统计订单数量
+            long orders = todList.stream().map(TwinOrderDetail::getOderId).distinct().count();
+            double totalWeight = todList.stream().mapToDouble(o -> o.getWeight().doubleValue()).sum();
+            TwinOrderDetail tod = todList.get(0);
+            bom.setBomCode(tod.getBomCode());
+            bom.setBomName(tod.getBomName());
+            bom.setBomSpec(spec);
+
+            bom.setXql(totalWeight);
+            bom.setKcl(kc);
+            bom.setOrders(orders);
+            double ycl = cl.multiply(BigDecimal.TEN).doubleValue();
+            double cz = totalWeight - kc - ycl;
+            bom.setYcl(ycl);
+            bom.setCz(cz);
+            bom.setCl(cz / totalWeight);
+
+            SkuVO sku = new SkuVO();
+            sku.setBomCode(tod.getBomCode());
+            sku.setBomName(tod.getBomName());
+            sku.setBomSpec(spec);
+            if (stock != null) {
+                sku.setSku(stock.getSku());
+                sku.setDesc(stock.getDesc());
+                sku.setNum(stock.getNum());
+                sku.setQty(stock.getQty());
+            } else {
+                sku.setSku("");
+                sku.setDesc("");
+                sku.setNum(0);
+                sku.setQty(0f);
+            }
+            sku.setXql(bom.getXql());
+            List<TwinOrder> skuOrder = new ArrayList<>();
+            //按订单分组
+            Map<Long, List<TwinOrderDetail>> map = todList.stream().collect(Collectors.groupingBy(TwinOrderDetail::getOderId, LinkedHashMap::new, Collectors.toList()));
+            for (Long oid : map.keySet()) {
+                TwinOrder to = orderMap.get(oid);
+                to.setTwinOrderDetailList(map.get(oid));
+                skuOrder.add(to);
+            }
+            sku.setOrderList(skuOrder);
+            bom.setOrderList(skuOrder);
+            bomList.add(bom);
+            skuList.add(sku);
+        }
+
+        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("tpl/order.xlsx"); XSSFWorkbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
+            CreationHelper creationHelper = wb.getCreationHelper();
+            percentStyle = wb.createCellStyle();
+            percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
+            percentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+            p2 = wb.createCellStyle();
+            p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
+            p2.setVerticalAlignment(VerticalAlignment.CENTER);
+            bk = wb.createCellStyle();
+            bk.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
+            bk.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+            XSSFSheet sheet0 = wb.getSheetAt(0);
+            Cell title = sheet0.getRow(0).getCell(0);
+            title.setCellValue("白胚布靶向生产测算-10天(" + start + " 至 " + end + ")");
+
+            sheet0(sheet0, bomList);
+            sheet1(wb.getSheetAt(1), stocks);
+            sheet2(wb.getSheetAt(2), skuList);
+            sheet3(wb.getSheetAt(3), bomList);
+            sheet4(wb.getSheetAt(4), infos);
+            response.reset();
+            // 设置response的Header
+            response.setCharacterEncoding("UTF-8");
+            //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
+            //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
+            // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
+            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("白胚布靶向预测" + start + "至" + end + ".xlsx", "UTF-8"));
+            response.setContentType("application/octet-stream");
+            wb.write(outputStream);
+            outputStream.flush();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+
+    /**
+     * 总览
+     *
+     * @param sheet   sheet
+     * @param bomList 物料列表
+     */
+    private void sheet0(XSSFSheet sheet, List<BomVO> bomList) {
+        AtomicInteger num = new AtomicInteger(3);
+        BomVO bom = new BomVO();
+        bom.setOrders(0L);
+        bom.setXql(0d);
+        bom.setKcl(0f);
+        bom.setYcl(0d);
+        bom.setCz(0d);
+        bom.setCl(0d);
+        bomList.forEach(obj -> {
+            Row row = sheet.createRow(num.getAndIncrement());
+            Cell[] cells = new Cell[10];
+            for (int i = 0; i < cells.length; i++) {
+                cells[i] = row.createCell(i);
+            }
+            cells[0].setCellValue(obj.getBomCode());
+            cells[1].setCellValue(obj.getBomName());
+            cells[2].setCellValue(obj.getBomSpec());
+            cells[3].setCellValue(obj.getOrders());
+            cells[4].setCellValue(obj.getXql());
+            cells[5].setCellValue(obj.getKcl());
+            cells[7].setCellValue(obj.getYcl());
+            cells[8].setCellValue(obj.getCz());
+            cells[9].setCellValue(obj.getCl());
+            cells[9].setCellStyle(percentStyle);
+            bom.setOrders(bom.getOrders() + obj.getOrders());
+            bom.setXql(bom.getXql() + obj.getXql());
+            bom.setKcl(bom.getKcl() + obj.getKcl());
+            bom.setYcl(bom.getYcl() + obj.getYcl());
+            bom.setCz(bom.getCz() + obj.getCz());
+            bom.setCl(bom.getCl() + obj.getCl());
+        });
+        Row row = sheet.createRow(num.getAndIncrement());
+        Cell[] cells = new Cell[10];
+        for (int i = 0; i < cells.length; i++) {
+            cells[i] = row.createCell(i);
+        }
+        cells[0].setCellValue("合计");
+//        cells[3].setCellValue(bom.getOrders());
+        cells[4].setCellValue(bom.getXql());
+        cells[5].setCellValue(bom.getKcl());
+        cells[7].setCellValue(bom.getYcl());
+        cells[8].setCellValue(bom.getCz());
+        for (int i = 4; i < 9; i++) {
+            cells[i].setCellStyle(p2);
+        }
+        cells[9].setCellValue(bom.getCl() / bomList.size());
+        cells[9].setCellStyle(percentStyle);
+        // 创建一个画布
+        XSSFDrawing drawing = sheet.createDrawingPatriarch();
+        // 前四个默认0,[0,4]:从0列4行开始;[7,20]:到7列20行结束
+        // 默认宽度(14-8)*12
+        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 11, 3, 17, 20);
+        // 创建一个chart对象
+        XSSFChart chart = drawing.createChart(anchor);
+        // 标题
+        chart.setTitleText("需求重量占比图");
+        // 标题是否覆盖图表
+        chart.setTitleOverlay(false);
+
+        // 图例位置
+        XDDFChartLegend legend = chart.getOrAddLegend();
+        legend.setPosition(LegendPosition.TOP_RIGHT);
+
+        XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(3, num.get() - 2, 2, 2));
+        // 数据1,单元格范围位置[1, 0]到[1, 6]
+        XDDFNumericalDataSource<Double> area = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(3, num.get() - 2, 4, 4));
+//         XDDFChartData data = chart.createData(ChartTypes.PIE3D, null, null);
+        XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
+        // 设置为可变颜色
+        data.setVaryColors(true);
+        // 图表加载数据
+        data.addSeries(countries, area);
+
+        // 绘制
+        chart.plot(data);
+        CTDLbls dLbls = chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDLbls();
+        dLbls.addNewShowVal().setVal(false);
+        dLbls.addNewShowLegendKey().setVal(false);
+        dLbls.addNewShowCatName().setVal(true);
+        // 类别名称
+        dLbls.addNewShowSerName().setVal(false);
+        dLbls.addNewShowPercent().setVal(true);
+        // 百分比
+        dLbls.addNewShowLeaderLines().setVal(true);
+        // 引导线
+        dLbls.setSeparator("\n");
+        // 分隔符为分行符
+
+    }
+
+    /**
+     * 白胚布全量
+     *
+     * @param sheet  sheet
+     * @param stocks 库存
+     */
+    private void sheet1(Sheet sheet, List<VmsStock> stocks) {
+        AtomicInteger num = new AtomicInteger(2);
+        stocks.forEach(stock -> {
+            Row row = sheet.createRow(num.getAndIncrement());
+            Cell[] cells = new Cell[6];
+            for (int i = 0; i < cells.length; i++) {
+                cells[i] = row.createCell(i);
+            }
+            cells[0].setCellValue(stock.getSku());
+            cells[1].setCellValue(stock.getDesc());
+            cells[2].setCellValue(stock.getNum());
+            cells[3].setCellValue(stock.getQty());
+            cells[3].setCellStyle(p2);
+//            cells[4].setCellValue();
+//            cells[5].setCellValue();
+        });
+    }
+
+    /**
+     * 白胚库存匹配
+     *
+     * @param sheet   sheet
+     * @param skuList 库存
+     */
+    private void sheet2(Sheet sheet, List<SkuVO> skuList) {
+        AtomicInteger num = new AtomicInteger(3);
+        skuList.forEach(sku -> {
+            int sr = num.get();
+            Row row = sheet.createRow(num.getAndIncrement());
+            Cell[] cells = new Cell[18];
+            for (int i = 0; i < cells.length; i++) {
+                cells[i] = row.createCell(i);
+            }
+            cells[0].setCellValue(sku.getSku());
+            cells[1].setCellValue(sku.getDesc());
+            cells[2].setCellValue(sku.getNum());
+            cells[3].setCellValue(sku.getQty());
+            cells[4].setCellValue(sku.getXql());
+            cells[3].setCellStyle(p2);
+            cells[4].setCellStyle(p2);
+            cells[5].setCellValue(sku.getBomCode());
+            cells[6].setCellValue(sku.getBomName());
+            cells[7].setCellValue(sku.getBomSpec());
+            boolean out = false;
+            for (TwinOrder order : sku.getOrderList()) {
+                if (out) {
+                    row = sheet.createRow(num.getAndIncrement());
+                    cells = new Cell[18];
+                    for (int i = 0; i < cells.length; i++) {
+                        cells[i] = row.createCell(i);
+                    }
+                }
+                cells[8].setCellValue(DateUtils.parseDateToStr(order.getOrderDate()));
+                cells[9].setCellValue(order.getOrderCode());
+                cells[10].setCellValue(order.getCustomerCode());
+                cells[11].setCellValue(order.getCustomerName());
+                boolean in = false;
+                int ssr = num.get() - 1;
+                for (TwinOrderDetail detail : order.getTwinOrderDetailList()) {
+                    if (in) {
+                        row = sheet.createRow(num.getAndIncrement());
+                        cells = new Cell[18];
+                        for (int i = 0; i < cells.length; i++) {
+                            cells[i] = row.createCell(i);
+                        }
+                    }
+                    cells[12].setCellValue(detail.getColor());
+                    cells[13].setCellValue(detail.getPrice().doubleValue());
+                    cells[14].setCellValue(detail.getTotalPrice().doubleValue());
+                    cells[15].setCellValue(detail.getUnit());
+                    cells[16].setCellValue(detail.getNum().doubleValue());
+                    cells[17].setCellValue(detail.getWeight().doubleValue());
+                    in = true;
+                }
+                out = true;
+                int eer = num.get() - 1;
+                for (int i = 8; i < 12; i++) {
+                    sheet.addMergedRegion(new CellRangeAddress(ssr, eer, i, i));
+                }
+            }
+            int er = num.get() - 1;
+            for (int i = 0; i < 8; i++) {
+                sheet.addMergedRegion(new CellRangeAddress(sr, er, i, i));
+            }
+        });
+    }
+
+    /**
+     * 经编机规格分布
+     *
+     * @param sheet   sheet
+     * @param bomList 库存
+     */
+    private void sheet3(Sheet sheet, List<BomVO> bomList) {
+        AtomicInteger num = new AtomicInteger(3);
+        bomList.forEach(obj -> {
+            int sr = num.get();
+            Row row = sheet.createRow(num.getAndIncrement());
+            Cell[] cells = new Cell[18];
+            for (int i = 0; i < cells.length; i++) {
+                cells[i] = row.createCell(i);
+            }
+            cells[0].setCellValue(obj.getBomCode());
+            cells[1].setCellValue(obj.getBomName());
+            cells[2].setCellValue(obj.getBomSpec());
+            cells[3].setCellValue(obj.getXql());
+            cells[4].setCellValue(obj.getDeviceIds());
+            cells[5].setCellValue(obj.getLast());
+            cells[6].setCellValue(obj.getYcl());
+
+            boolean out = false;
+            for (TwinOrder order : obj.getOrderList()) {
+                if (out) {
+                    row = sheet.createRow(num.getAndIncrement());
+                    cells = new Cell[18];
+                    for (int i = 0; i < cells.length; i++) {
+                        cells[i] = row.createCell(i);
+                    }
+                }
+                Cell xql = cells[7];
+                cells[8].setCellValue(DateUtils.parseDateToStr(order.getOrderDate()));
+                cells[9].setCellValue(order.getOrderCode());
+                cells[10].setCellValue(order.getCustomerCode());
+                cells[11].setCellValue(order.getCustomerName());
+                boolean in = false;
+                int ssr = num.get() - 1;
+                BigDecimal ow = BigDecimal.ZERO;
+                for (TwinOrderDetail detail : order.getTwinOrderDetailList()) {
+                    if (in) {
+                        row = sheet.createRow(num.getAndIncrement());
+                        cells = new Cell[18];
+                        for (int i = 0; i < cells.length; i++) {
+                            cells[i] = row.createCell(i);
+                        }
+                    }
+                    cells[12].setCellValue(detail.getColor());
+                    cells[13].setCellValue(detail.getPrice().doubleValue());
+                    cells[14].setCellValue(detail.getTotalPrice().doubleValue());
+                    cells[15].setCellValue(detail.getUnit());
+                    cells[16].setCellValue(detail.getNum().doubleValue());
+                    cells[17].setCellValue(detail.getWeight().doubleValue());
+                    ow = ow.add(detail.getWeight());
+                    in = true;
+                }
+                xql.setCellValue(ow.doubleValue());
+                xql.setCellStyle(p2);
+                out = true;
+                int eer = num.get() - 1;
+                for (int i = 7; i < 12; i++) {
+                    sheet.addMergedRegion(new CellRangeAddress(ssr, eer, i, i));
+                }
+            }
+            int er = num.get() - 1;
+            for (int i = 0; i < 7; i++) {
+                sheet.addMergedRegion(new CellRangeAddress(sr, er, i, i));
+            }
+        });
+    }
+
+
+    /**
+     * 白胚布库存--全量
+     *
+     * @param sheet sheet
+     * @param infos 库存
+     */
+    private void sheet4(Sheet sheet, List<TwinFormulaInfo> infos) {
+        AtomicInteger num = new AtomicInteger(3);
+        infos.sort(Comparator.comparing(TwinFormulaInfo::getFd18).reversed().thenComparing(TwinFormulaInfo::getFd16).thenComparing(TwinFormulaInfo::getFd17).thenComparing(TwinFormulaInfo::getFd3));
+        infos.forEach(info -> {
+            Row row = sheet.createRow(num.getAndIncrement());
+            Cell[] cells = new Cell[35];
+            for (int i = 0; i < cells.length; i++) {
+                cells[i] = row.createCell(i);
+            }
+            cells[0].setCellValue(info.getFd18());
+            cells[1].setCellValue(info.getFd16());
+            cells[2].setCellValue(info.getFd17());
+            cells[3].setCellValue(info.getFd3());
+            cells[4].setCellValue(info.getFd15());
+            cells[5].setCellValue(info.getFd4());
+            cells[6].setCellValue(info.getFd5());
+            cells[7].setCellValue(info.getFd6());
+            cells[8].setCellValue(info.getFd2());
+            cells[9].setCellValue(info.getFd1());
+            cells[10].setCellValue(info.getFd13());
+            cells[11].setCellValue(info.getFd14());
+            cells[12].setCellValue(info.getFd24());
+            cells[13].setCellValue(info.getFd25());
+
+            cells[14].setCellValue(info.getCd10());
+            cells[15].setCellValue(info.getCd11());
+            cells[16].setCellValue(info.getCd12());
+            cells[17].setCellValue(info.getCd13());
+            cells[18].setCellValue(info.getCd14());
+            cells[19].setCellValue(info.getCd15());
+            cells[20].setCellValue(info.getCd16());
+            cells[21].setCellValue(info.getCd17());
+            cells[22].setCellValue(info.getCd18());
+            cells[23].setCellValue(info.getCd19());
+
+            cells[24].setCellValue(info.getFd19());
+            cells[25].setCellValue(info.getFd20());
+            cells[26].setCellValue(info.getFd21());
+            cells[27].setCellValue(info.getFd22());
+            cells[28].setCellValue(info.getFd23());
+
+            cells[29].setCellValue(info.getFd7());
+            cells[30].setCellValue(info.getFd8());
+            cells[31].setCellValue(info.getFd9());
+            cells[32].setCellValue(info.getFd10());
+            cells[33].setCellValue(info.getFd11());
+            cells[34].setCellValue(info.getFd12());
+        });
+    }
+
+    /**
+     * 匹配库存
+     *
+     * @param spec   规格
+     * @param stocks 库存
+     * @return 结果
+     */
+    private VmsStock matchStock(String spec, List<VmsStock> stocks) {
+        //按重量分组
+        Map<Integer, List<VmsStock>> stockMap = stocks.stream().collect(Collectors.groupingBy(VmsStock::getWeight, LinkedHashMap::new, Collectors.toList()));
+        if (spec != null) {
+            String[] tmp = spec.split("\\*");
+            if (tmp.length == 3) {
+                Float length = Float.parseFloat(tmp[0]);
+                Float width = Float.parseFloat(tmp[1]);
+                int weight = (int) (Float.parseFloat(tmp[2]) * 1000);
+                List<VmsStock> tempList = stockMap.get(weight);
+                if (tempList != null) {
+                    for (VmsStock stock : tempList) {
+                        if (length > stock.getLength() || width > stock.getLength()) {
+                            return stock;
+                        }
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * 匹配产线
+     *
+     * @param spec 规格
+     * @param list 产线
+     * @return 结果
+     */
+    private List<TwinFormulaInfo> matchFormula(String spec, List<TwinFormulaInfo> list) {
+        List<TwinFormulaInfo> result = new ArrayList<>();
+        //按重量分组
+        Map<Float, List<TwinFormulaInfo>> formulaMap = list.stream().collect(Collectors.groupingBy(TwinFormulaInfo::getFd18, LinkedHashMap::new, Collectors.toList()));
+        if (spec != null) {
+            String[] tmp = spec.split("\\*");
+            if (tmp.length == 3) {
+                Float length = Float.parseFloat(tmp[0]);
+                Float width = Float.parseFloat(tmp[1]);
+                Float weight = Float.parseFloat(tmp[2]);
+                List<TwinFormulaInfo> infos = formulaMap.get(weight);
+                if (infos != null) {
+                    for (TwinFormulaInfo info : infos) {
+                        if (length.equals(info.getFd16()) && width.equals(info.getFd17()) ||
+                                length.equals(info.getFd17()) && width.equals(info.getFd16())) {
+                            result.add(info);
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+}

+ 2 - 0
ruoyi-admin/src/main/java/com/ruoyi/order/domain/TwinOrderDetail.java

@@ -2,6 +2,7 @@ package com.ruoyi.order.domain;
 
 import com.ruoyi.common.annotation.Excel;
 import com.ruoyi.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -13,6 +14,7 @@ import java.math.BigDecimal;
  * @date 2024-12-30
  */
 @Data
+@ApiModel(value = "TwinOrderDetail", description = "销售订单明细信息对象")
 public class TwinOrderDetail extends BaseEntity {
     private static final long serialVersionUID = 1L;
 

+ 8 - 0
ruoyi-admin/src/main/java/com/ruoyi/order/service/ITwinOrderService.java

@@ -66,4 +66,12 @@ public interface ITwinOrderService {
      * @param localDate 时间
      */
     void getOrder(LocalDate localDate);
+
+    /**
+     * 按时间获取订单信息
+     * @param start
+     * @param end
+     * @return
+     */
+    List<TwinOrder> selectTwinOrderListByDate(String start, String end);
 }

+ 18 - 0
ruoyi-admin/src/main/java/com/ruoyi/order/service/impl/TwinOrderServiceImpl.java

@@ -23,6 +23,7 @@ import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -182,6 +183,23 @@ public class TwinOrderServiceImpl implements ITwinOrderService {
     }
 
     /**
+     * 按时间获取订单信息
+     *
+     * @param start
+     * @param end
+     * @return
+     */
+    @Override
+    public List<TwinOrder> selectTwinOrderListByDate(String start, String end) {
+        TwinOrder order = new TwinOrder();
+        Map<String, Object> params = new HashMap<>(16);
+        params.put("start", start);
+        params.put("end", end);
+        order.setParams(params);
+        return selectTwinOrderList(order);
+    }
+
+    /**
      * 新增销售订单明细信息信息
      *
      * @param twinOrder 销售订单信息对象

+ 92 - 0
ruoyi-admin/src/main/java/com/ruoyi/order/utils/MssqlUtil.java

@@ -0,0 +1,92 @@
+package com.ruoyi.order.utils;
+
+import com.ruoyi.order.domain.VmsStock;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author wukai
+ */
+public class MssqlUtil {
+    /**
+     * SQLServer本地驱动的地址
+     */
+    private static final String DB_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
+    /**
+     * 连接sqlserver数据库;本地连接;通过1433号端口号连接(根据你自身数据库的端口号来),数据库名称DBMS
+     * 你需要现在Sql Server客户端上建立一个数据库
+     */
+    private static final String DB_URL = "jdbc:sqlserver://wmsdb.tlct.com.cn:1433;databaseName=WMS_V2_1";
+    /**
+     * 用户名
+     */
+    private static final String USER = "MES";
+    /**
+     * 密码
+     */
+    private static final String PASSWORD = "MES";
+
+    public static List<VmsStock> stock() {
+        List<VmsStock> stocks = new ArrayList<>();
+        try {
+            //第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
+            Class.forName(DB_DRIVER);
+            String sql = "select SKU,SKU_DESCRC,COUNT(1) NUM,SUM(QTY) QTY from V_WMS_STOCK where lot24 is not NULL and WAREHOUSE_ID='WH04-白坯仓库' and UOM='KG' group by sku,SKU_DESCRC order by sku";
+            try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD); Statement statement = conn.createStatement(); ResultSet rs = statement.executeQuery(sql)) {
+                //第二步:根据连接协议、用户名、密码连接数据库
+                //第三步:进行数据库的数据操作
+                //取得Statement对象
+                //使用ResultSet接收数据
+                while (rs.next()) {
+                    String sku = rs.getString("SKU");
+                    String desc = rs.getString("SKU_DESCRC");
+                    Integer num = rs.getInt("NUM");
+                    Float qty = rs.getFloat("QTY");
+                    VmsStock stock = new VmsStock();
+                    stock.setSku(sku);
+                    stock.setDesc(desc);
+                    stock.setNum(num);
+                    stock.setQty(qty);
+
+                    // 使用正则表达式来提取数字部分
+//                    String pattern1 = "\\d+(\\.\\d+)?\\*\\d+(\\.\\d+)?";
+//                    String pattern2 = "L(\\d+)";
+                    // 定义正则表达式模式
+                    String patternString = "([A-Za-z]+-[A-Z])(\\d+)\\(([0-9.]+\\*[0-9.]+)\\)";
+                    Pattern pattern = Pattern.compile(patternString);
+                    String weight = "";
+                    String specification = "";
+                    Matcher matcher = pattern.matcher(desc);
+                    if (matcher.find()) {
+                        // 提取重量部分,即第二组匹配的数字
+                        weight = matcher.group(2);
+                        stock.setWeight(Integer.parseInt(weight));
+                        // 提取规格部分,即第三组匹配的表达式
+                        specification = matcher.group(3);
+                        String[] tmp = specification.split("\\*");
+                        if (tmp.length > 1) {
+                            stock.setLength(Float.parseFloat(tmp[0]));
+                            stock.setMick(Integer.parseInt(tmp[1]));
+                        }
+                    }
+                    stocks.add(stock);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return stocks;
+    }
+
+    public static void main(String[] args) throws Exception {
+        List<VmsStock> list = stock();
+        System.err.println(list.size());
+    }
+}

+ 39 - 0
ruoyi-admin/src/main/java/com/ruoyi/order/vo/SkuVO.java

@@ -0,0 +1,39 @@
+package com.ruoyi.order.vo;
+
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.order.domain.TwinOrder;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 白胚布对象 twin_order_detail
+ *
+ * @author ruoyi
+ * @date 2024-12-30
+ */
+@Data
+@ApiModel(value = "BomVO", description = "白胚布视图")
+public class SkuVO extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+    @ApiModelProperty("sku")
+    private String sku;
+    @ApiModelProperty("sku描述")
+    private String desc;
+    @ApiModelProperty("数量")
+    private Integer num;
+    @ApiModelProperty("总重")
+    private Float qty;
+    @ApiModelProperty(name = "物料编码")
+    private String bomCode;
+    @ApiModelProperty(name = "物料名称")
+    private String bomName;
+    @ApiModelProperty(name = "物料规格")
+    private String bomSpec;
+    @ApiModelProperty(name = "需求总重量")
+    private Double xql;
+    @ApiModelProperty(name = "订单信息")
+    private List<TwinOrder> orderList;
+}

+ 178 - 26
ruoyi-admin/src/main/resources/mapper/biz/TwinFormulaInfoMapper.xml

@@ -7,27 +7,87 @@
     <resultMap type="TwinFormulaInfo" id="TwinFormulaInfoResult">
         <result property="specInfoId"    column="SPEC_INFO_ID"    />
         <result property="deviceId"    column="DEVICE_ID"    />
-        <result property="length"    column="LENGTH"    />
-        <result property="width"    column="WIDTH"    />
-        <result property="weight"    column="WEIGHT"    />
-        <result property="mick"    column="MICK"    />
-        <result property="formula"    column="FORMULA"    />
+        <result property="fd1"    column="FD1"    />
+        <result property="fd2"    column="FD2"    />
+        <result property="fd3"    column="FD3"    />
+        <result property="fd4"    column="FD4"    />
+        <result property="fd5"    column="FD5"    />
+        <result property="fd6"    column="FD6"    />
+        <result property="fd7"    column="FD7"    />
+        <result property="fd8"    column="FD8"    />
+        <result property="fd9"    column="FD9"    />
+        <result property="fd10"    column="FD10"    />
+        <result property="fd11"    column="FD11"    />
+        <result property="fd12"    column="FD12"    />
+        <result property="fd13"    column="FD13"    />
+        <result property="fd14"    column="FD14"    />
+        <result property="fd15"    column="FD15"    />
+        <result property="fd16"    column="FD16"    />
+        <result property="fd17"    column="FD17"    />
+        <result property="fd18"    column="FD18"    />
+        <result property="fd19"    column="FD19"    />
+        <result property="fd20"    column="FD20"    />
+        <result property="fd21"    column="FD21"    />
+        <result property="fd22"    column="FD22"    />
+        <result property="fd23"    column="FD23"    />
+        <result property="fd24"    column="FD24"    />
+        <result property="fd25"    column="FD25"    />
+        <result property="cd10"    column="CD10"    />
+        <result property="cd11"    column="CD11"    />
+        <result property="cd12"    column="CD12"    />
+        <result property="cd13"    column="CD13"    />
+        <result property="cd14"    column="CD14"    />
+        <result property="cd15"    column="CD15"    />
+        <result property="cd16"    column="CD16"    />
+        <result property="cd17"    column="CD17"    />
+        <result property="cd18"    column="CD18"    />
+        <result property="cd19"    column="CD19"    />
         <result property="remark"    column="REMARK"    />
     </resultMap>
 
     <sql id="selectTwinFormulaInfoVo">
-        select SPEC_INFO_ID, DEVICE_ID, LENGTH, WIDTH, WEIGHT, MICK, FORMULA, REMARK from twin_formula_info
+        select SPEC_INFO_ID, DEVICE_ID, FD1, FD2, FD3, FD4, FD5, FD6, FD7, FD8, FD9, FD10, FD11, FD12, FD13, FD14, FD15, FD16, FD17, FD18, FD19, FD20, FD21, FD22, FD23, FD24, FD25, CD10, CD11, CD12, CD13, CD14, CD15, CD16, CD17, CD18, CD19, REMARK from twin_formula_info
     </sql>
 
     <select id="selectTwinFormulaInfoList" parameterType="TwinFormulaInfo" resultMap="TwinFormulaInfoResult">
         <include refid="selectTwinFormulaInfoVo"/>
         <where>
             <if test="deviceId != null "> and DEVICE_ID = #{deviceId}</if>
-            <if test="length != null "> and LENGTH = #{length}</if>
-            <if test="width != null "> and WIDTH = #{width}</if>
-            <if test="weight != null "> and WEIGHT = #{weight}</if>
-            <if test="mick != null "> and MICK = #{mick}</if>
-            <if test="formula != null "> and FORMULA = #{formula}</if>
+            <if test="fd1 != null "> and FD1 = #{fd1}</if>
+            <if test="fd2 != null "> and FD2 = #{fd2}</if>
+            <if test="fd3 != null "> and FD3 = #{fd3}</if>
+            <if test="fd4 != null "> and FD4 = #{fd4}</if>
+            <if test="fd5 != null "> and FD5 = #{fd5}</if>
+            <if test="fd6 != null "> and FD6 = #{fd6}</if>
+            <if test="fd7 != null "> and FD7 = #{fd7}</if>
+            <if test="fd8 != null "> and FD8 = #{fd8}</if>
+            <if test="fd9 != null "> and FD9 = #{fd9}</if>
+            <if test="fd10 != null "> and FD10 = #{fd10}</if>
+            <if test="fd11 != null "> and FD11 = #{fd11}</if>
+            <if test="fd12 != null "> and FD12 = #{fd12}</if>
+            <if test="fd13 != null "> and FD13 = #{fd13}</if>
+            <if test="fd14 != null "> and FD14 = #{fd14}</if>
+            <if test="fd15 != null "> and FD15 = #{fd15}</if>
+            <if test="fd16 != null "> and FD16 = #{fd16}</if>
+            <if test="fd17 != null "> and FD17 = #{fd17}</if>
+            <if test="fd18 != null "> and FD18 = #{fd18}</if>
+            <if test="fd19 != null "> and FD19 = #{fd19}</if>
+            <if test="fd20 != null "> and FD20 = #{fd20}</if>
+            <if test="fd21 != null "> and FD21 = #{fd21}</if>
+            <if test="fd22 != null "> and FD22 = #{fd22}</if>
+            <if test="fd23 != null "> and FD23 = #{fd23}</if>
+            <if test="fd24 != null "> and FD24 = #{fd24}</if>
+            <if test="fd25 != null "> and FD25 = #{fd25}</if>
+            <if test="cd10 != null "> and CD10 = #{cd10}</if>
+            <if test="cd11 != null "> and CD11 = #{cd11}</if>
+            <if test="cd12 != null "> and CD12 = #{cd12}</if>
+            <if test="cd13 != null "> and CD13 = #{cd13}</if>
+            <if test="cd14 != null "> and CD14 = #{cd14}</if>
+            <if test="cd15 != null "> and CD15 = #{cd15}</if>
+            <if test="cd16 != null "> and CD16 = #{cd16}</if>
+            <if test="cd17 != null "> and CD17 = #{cd17}</if>
+            <if test="cd18 != null "> and CD18 = #{cd18}</if>
+            <if test="cd19 != null "> and CD19 = #{cd19}</if>
             <if test="remark != null  and remark != ''"> and REMARK = #{remark}</if>
         </where>
     </select>
@@ -40,21 +100,83 @@
     <insert id="insertTwinFormulaInfo" parameterType="TwinFormulaInfo" useGeneratedKeys="true" keyProperty="specInfoId">
         insert into twin_formula_info
         <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="specInfoId != null">SPEC_INFO_ID,</if>
             <if test="deviceId != null">DEVICE_ID,</if>
-            <if test="length != null">LENGTH,</if>
-            <if test="width != null">WIDTH,</if>
-            <if test="weight != null">WEIGHT,</if>
-            <if test="mick != null">MICK,</if>
-            <if test="formula != null">FORMULA,</if>
+            <if test="fd1 != null">FD1,</if>
+            <if test="fd2 != null">FD2,</if>
+            <if test="fd3 != null">FD3,</if>
+            <if test="fd4 != null">FD4,</if>
+            <if test="fd5 != null">FD5,</if>
+            <if test="fd6 != null">FD6,</if>
+            <if test="fd7 != null">FD7,</if>
+            <if test="fd8 != null">FD8,</if>
+            <if test="fd9 != null">FD9,</if>
+            <if test="fd10 != null">FD10,</if>
+            <if test="fd11 != null">FD11,</if>
+            <if test="fd12 != null">FD12,</if>
+            <if test="fd13 != null">FD13,</if>
+            <if test="fd14 != null">FD14,</if>
+            <if test="fd15 != null">FD15,</if>
+            <if test="fd16 != null">FD16,</if>
+            <if test="fd17 != null">FD17,</if>
+            <if test="fd18 != null">FD18,</if>
+            <if test="fd19 != null">FD19,</if>
+            <if test="fd20 != null">FD20,</if>
+            <if test="fd21 != null">FD21,</if>
+            <if test="fd22 != null">FD22,</if>
+            <if test="fd23 != null">FD23,</if>
+            <if test="fd24 != null">FD24,</if>
+            <if test="fd25 != null">FD25,</if>
+            <if test="cd10 != null">CD10,</if>
+            <if test="cd11 != null">CD11,</if>
+            <if test="cd12 != null">CD12,</if>
+            <if test="cd13 != null">CD13,</if>
+            <if test="cd14 != null">CD14,</if>
+            <if test="cd15 != null">CD15,</if>
+            <if test="cd16 != null">CD16,</if>
+            <if test="cd17 != null">CD17,</if>
+            <if test="cd18 != null">CD18,</if>
+            <if test="cd19 != null">CD19,</if>
             <if test="remark != null">REMARK,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="specInfoId != null">#{specInfoId},</if>
             <if test="deviceId != null">#{deviceId},</if>
-            <if test="length != null">#{length},</if>
-            <if test="width != null">#{width},</if>
-            <if test="weight != null">#{weight},</if>
-            <if test="mick != null">#{mick},</if>
-            <if test="formula != null">#{formula},</if>
+            <if test="fd1 != null">#{fd1},</if>
+            <if test="fd2 != null">#{fd2},</if>
+            <if test="fd3 != null">#{fd3},</if>
+            <if test="fd4 != null">#{fd4},</if>
+            <if test="fd5 != null">#{fd5},</if>
+            <if test="fd6 != null">#{fd6},</if>
+            <if test="fd7 != null">#{fd7},</if>
+            <if test="fd8 != null">#{fd8},</if>
+            <if test="fd9 != null">#{fd9},</if>
+            <if test="fd10 != null">#{fd10},</if>
+            <if test="fd11 != null">#{fd11},</if>
+            <if test="fd12 != null">#{fd12},</if>
+            <if test="fd13 != null">#{fd13},</if>
+            <if test="fd14 != null">#{fd14},</if>
+            <if test="fd15 != null">#{fd15},</if>
+            <if test="fd16 != null">#{fd16},</if>
+            <if test="fd17 != null">#{fd17},</if>
+            <if test="fd18 != null">#{fd18},</if>
+            <if test="fd19 != null">#{fd19},</if>
+            <if test="fd20 != null">#{fd20},</if>
+            <if test="fd21 != null">#{fd21},</if>
+            <if test="fd22 != null">#{fd22},</if>
+            <if test="fd23 != null">#{fd23},</if>
+            <if test="fd24 != null">#{fd24},</if>
+            <if test="fd25 != null">#{fd25},</if>
+            <if test="cd10 != null">#{cd10},</if>
+            <if test="cd11 != null">#{cd11},</if>
+            <if test="cd12 != null">#{cd12},</if>
+            <if test="cd13 != null">#{cd13},</if>
+            <if test="cd14 != null">#{cd14},</if>
+            <if test="cd15 != null">#{cd15},</if>
+            <if test="cd16 != null">#{cd16},</if>
+            <if test="cd17 != null">#{cd17},</if>
+            <if test="cd18 != null">#{cd18},</if>
+            <if test="cd19 != null">#{cd19},</if>
             <if test="remark != null">#{remark},</if>
         </trim>
     </insert>
@@ -63,11 +185,41 @@
         update twin_formula_info
         <trim prefix="SET" suffixOverrides=",">
             <if test="deviceId != null">DEVICE_ID = #{deviceId},</if>
-            <if test="length != null">LENGTH = #{length},</if>
-            <if test="width != null">WIDTH = #{width},</if>
-            <if test="weight != null">WEIGHT = #{weight},</if>
-            <if test="mick != null">MICK = #{mick},</if>
-            <if test="formula != null">FORMULA = #{formula},</if>
+            <if test="fd1 != null">FD1 = #{fd1},</if>
+            <if test="fd2 != null">FD2 = #{fd2},</if>
+            <if test="fd3 != null">FD3 = #{fd3},</if>
+            <if test="fd4 != null">FD4 = #{fd4},</if>
+            <if test="fd5 != null">FD5 = #{fd5},</if>
+            <if test="fd6 != null">FD6 = #{fd6},</if>
+            <if test="fd7 != null">FD7 = #{fd7},</if>
+            <if test="fd8 != null">FD8 = #{fd8},</if>
+            <if test="fd9 != null">FD9 = #{fd9},</if>
+            <if test="fd10 != null">FD10 = #{fd10},</if>
+            <if test="fd11 != null">FD11 = #{fd11},</if>
+            <if test="fd12 != null">FD12 = #{fd12},</if>
+            <if test="fd13 != null">FD13 = #{fd13},</if>
+            <if test="fd14 != null">FD14 = #{fd14},</if>
+            <if test="fd15 != null">FD15 = #{fd15},</if>
+            <if test="fd16 != null">FD16 = #{fd16},</if>
+            <if test="fd17 != null">FD17 = #{fd17},</if>
+            <if test="fd18 != null">FD18 = #{fd18},</if>
+            <if test="fd19 != null">FD19 = #{fd19},</if>
+            <if test="fd20 != null">FD20 = #{fd20},</if>
+            <if test="fd21 != null">FD21 = #{fd21},</if>
+            <if test="fd22 != null">FD22 = #{fd22},</if>
+            <if test="fd23 != null">FD23 = #{fd23},</if>
+            <if test="fd24 != null">FD24 = #{fd24},</if>
+            <if test="fd25 != null">FD25 = #{fd25},</if>
+            <if test="cd10 != null">CD10 = #{cd10},</if>
+            <if test="cd11 != null">CD11 = #{cd11},</if>
+            <if test="cd12 != null">CD12 = #{cd12},</if>
+            <if test="cd13 != null">CD13 = #{cd13},</if>
+            <if test="cd14 != null">CD14 = #{cd14},</if>
+            <if test="cd15 != null">CD15 = #{cd15},</if>
+            <if test="cd16 != null">CD16 = #{cd16},</if>
+            <if test="cd17 != null">CD17 = #{cd17},</if>
+            <if test="cd18 != null">CD18 = #{cd18},</if>
+            <if test="cd19 != null">CD19 = #{cd19},</if>
             <if test="remark != null">REMARK = #{remark},</if>
         </trim>
         where SPEC_INFO_ID = #{specInfoId}

+ 88 - 1
ruoyi-admin/src/test/java/com/jjt/OrderTest.java

@@ -1,12 +1,24 @@
 package com.jjt;
 
 import com.ruoyi.RuoYiApplication;
+import com.ruoyi.biz.domain.TwinFormulaInfo;
+import com.ruoyi.biz.service.ITwinFormulaInfoService;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.order.domain.TwinOrder;
+import com.ruoyi.order.domain.TwinOrderDetail;
+import com.ruoyi.order.domain.VmsStock;
 import com.ruoyi.order.service.ITwinOrderService;
+import com.ruoyi.order.utils.MssqlUtil;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 
 import javax.annotation.Resource;
 import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * DataProcess$
@@ -18,10 +30,13 @@ import java.time.LocalDate;
 public class OrderTest {
     @Resource
     private ITwinOrderService orderService;
+    @Resource
+    private ITwinFormulaInfoService formulaInfoService;
 
     @Test
     void test() {
-        LocalDate start = LocalDate.parse("2024-12-01");
+        String d = "2024-12-27";
+        LocalDate start = LocalDate.parse(d);
         LocalDate end = LocalDate.now().minusDays(1);
         do {
             orderService.getOrder(start);
@@ -31,6 +46,78 @@ public class OrderTest {
 
     @Test
     void match() {
+        String d = "2024-12-02";
+        TwinOrder search = new TwinOrder();
+        search.setOrderDate(DateUtils.parseDate(d));
+        List<TwinOrder> list = orderService.selectTwinOrderList(search);
+        List<TwinFormulaInfo> infos = formulaInfoService.selectTwinFormulaInfoList(new TwinFormulaInfo());
+        List<VmsStock> stocks = MssqlUtil.stock();
+        for (TwinOrder twinOrder : list) {
+
+            List<TwinOrderDetail> details = twinOrder.getTwinOrderDetailList();
+            for (TwinOrderDetail detail : details) {
+                //匹配白胚布库存
+                List<VmsStock> matchStock = matchStock(detail.getBomSpec(), stocks);
+                System.err.println();
+                for (VmsStock match : matchStock) {
+                    System.err.println(detail.getBomSpec() + "\t" + detail.getBomName() + "\t" + match.getDesc());
+                }
+                //匹配生产设备
+//                List<TwinFormulaInfo> matchFormula = matchFormula(detail.getBomSpec(), infos);
+//                for (TwinFormulaInfo match : matchFormula) {
+//                    System.err.println(detail.getBomSpec() + "\t" + detail.getBomName() + "\t" + match.getDeviceId());
+//                }
+            }
+
+        }
+
+        System.err.println(list.size());
+    }
+
+    List<VmsStock> matchStock(String spec, List<VmsStock> stocks) {
+        List<VmsStock> result = new ArrayList<>();
+        //按重量分组
+        Map<Integer, List<VmsStock>> stockMap = stocks.stream().collect(Collectors.groupingBy(VmsStock::getWeight, LinkedHashMap::new, Collectors.toList()));
+        if (spec != null) {
+            String[] tmp = spec.split("\\*");
+            if (tmp.length == 3) {
+                Float length = Float.parseFloat(tmp[0]);
+                Float width = Float.parseFloat(tmp[1]);
+                int weight = (int) (Float.parseFloat(tmp[2]) * 1000);
+                List<VmsStock> tempList = stockMap.get(weight);
+                for (VmsStock stock : tempList) {
+                    if (length > stock.getLength() || width > stock.getLength()) {
+                        result.add(stock);
+                    }
+                }
+            }
+        }
 
+        return result;
     }
+
+//    List<TwinFormulaInfo> matchFormula(String spec, List<TwinFormulaInfo> list) {
+//        List<TwinFormulaInfo> result = new ArrayList<>();
+//        //按重量分组
+//        Map<Float, List<TwinFormulaInfo>> formulaMap = list.stream().collect(Collectors.groupingBy(o -> o.getWeight().floatValue(), LinkedHashMap::new, Collectors.toList()));
+//        if (spec != null) {
+//            String[] tmp = spec.split("\\*");
+//            if (tmp.length == 3) {
+//                Float length = Float.parseFloat(tmp[0]);
+//                Float width = Float.parseFloat(tmp[1]);
+//                Float weight = Float.parseFloat(tmp[2]);
+//                List<TwinFormulaInfo> infos = formulaMap.get(weight);
+//                if (infos != null) {
+//                    for (TwinFormulaInfo info : infos) {
+//                        if (length == info.getLength().floatValue() && width == info.getWidth().floatValue() ||
+//                                length == info.getWeight().floatValue() && width == info.getLength().floatValue()) {
+//                            result.add(info);
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//        return result;
+//    }
 }
+