Quellcode durchsuchen

导出全搞定,解决一些小问题

wukai vor 3 Monaten
Ursprung
Commit
7330ecf7b5

+ 83 - 0
jjt-admin/src/main/resources/application-test1.yml

@@ -0,0 +1,83 @@
+# 数据源配置
+spring:
+  # redis 配置
+  redis:
+    # 地址
+    host: localhost
+    # 端口,默认为6379
+    port: 36379
+    # 数据库索引
+    database: 0
+    # 密码
+    password: redis@123
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
+    druid:
+      # 主库数据源
+      master:
+        url: jdbc:sqlserver://192.168.188.88:1433;DataBaseName=twin2025
+        username: sa
+        password: abcd@1234
+      # 从库数据源
+      slave:
+        # 从数据源开关/默认关闭
+        enabled: false
+        url:
+        username:
+        password:
+      # 初始连接数
+      initialSize: 5
+      # 最小连接池数量
+      minIdle: 10
+      # 最大连接池数量
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置连接超时时间
+      connectTimeout: 30000
+      # 配置网络超时时间
+      socketTimeout: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      # 配置一个连接在池中最大生存的时间,单位是毫秒
+      maxEvictableIdleTimeMillis: 900000
+      # 配置检测连接是否有效
+      validationQuery: SELECT 1
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 设置白名单,不填则允许所有访问
+        allow:
+        url-pattern: /druid/*
+        # 控制台管理用户名和密码
+        login-username: ruoyi
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 慢SQL记录
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true

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

@@ -29,7 +29,7 @@ public class OrderTest {
 
     @Test
     void test() {
-        String d = "2024-12-01";
+        String d = "2025-02-01";
         LocalDate start = LocalDate.parse(d);
         LocalDate end = LocalDate.now().minusDays(1);
         do {

+ 50 - 0
jjt-admin/src/test/java/com/jjt/task/EnergyTest.java

@@ -0,0 +1,50 @@
+package com.jjt.task;
+
+import com.jjt.JjtApplication;
+import com.jjt.calc.service.ITwinCalcHourEnergyService;
+import com.jjt.common.utils.DateUtils;
+import com.jjt.ws.service.ITwinWorkshopCalcService;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+
+/**
+ * DataProcess$
+ *
+ * @author wukai
+ * @date 2024/5/7 11:49
+ */
+@SpringBootTest(classes = JjtApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class EnergyTest {
+    @Resource
+    private ITwinCalcHourEnergyService energyService;
+    @Resource
+    private ITwinWorkshopCalcService wsCalcService;
+
+    @Test
+    public void last() {
+        String date = "2025-02-12";
+        LocalDate localDate = LocalDate.parse(date);
+        LocalDateTime ldt = LocalDateTime.of(localDate, LocalTime.MIN);
+        for (int i = 0; i < 24; i++) {
+            LocalDateTime tt = ldt.plusHours(i);
+            System.err.println(tt.toLocalDate().toString() + tt.getHour());
+            energyService.calcEnergy(tt, tt.plusHours(1));
+//            calcHourService.calc(tt.toLocalDate().toString(), tt.getHour());
+        }
+
+//        calcHourService.last();
+    }
+
+    @Test
+    public void calc() {
+        String date = "2025-02-11";
+        LocalDate localDate = LocalDate.parse(date);
+        wsCalcService.calc(DateUtils.toDate(localDate));
+    }
+}
+

+ 10 - 9
jjt-admin/src/test/java/com/jjt/task/TaskTest.java

@@ -41,17 +41,18 @@ public class TaskTest {
     @Test
     public void last() {
 
-        String date = "2025-01-17";
+        String date = "2025-02-13";
         LocalDate localDate = LocalDate.parse(date);
-        empCalcService.calc(DateUtils.toDate(localDate));
 //        dayService.day(localDate);
-//        LocalDateTime ldt = LocalDateTime.of(localDate, LocalTime.MIN);
-//        ldt = ldt.plusHours(7);
-//        for (int i = 0; i < 24; i++) {
-//            LocalDateTime tt = ldt.plusHours(i);
-//            System.err.println(tt.toLocalDate().toString() + tt.getHour());
-//            calcHourService.calc(tt.toLocalDate().toString(), tt.getHour());
-//        }
+//        empCalcService.calc(DateUtils.toDate(localDate));
+        LocalDateTime ldt = LocalDateTime.of(localDate, LocalTime.MIN);
+        for (int i = 0; i < 2; i++) {
+            LocalDateTime tt = ldt.plusHours(i);
+            System.err.println(tt.toLocalDate().toString() + tt.getHour());
+            calcHourService.calc(tt.toLocalDate().toString(), tt.getHour());
+        }
+
+//        calcHourService.calc("2025-02-12", 1);
 
 //        calcHourService.last();
     }

+ 76 - 6
jjt-biz/src/main/java/com/jjt/biz/controller/ApiController.java

@@ -4,15 +4,14 @@ import com.jjt.biz.domain.TwinDevice;
 import com.jjt.biz.service.ITwinDeviceService;
 import com.jjt.biz.vo.*;
 import com.jjt.calc.domain.TwinCalcDay;
-import com.jjt.calc.service.ITwinCalcAlarmsService;
 import com.jjt.calc.service.ITwinCalcDayService;
-import com.jjt.calc.service.ITwinCalcStopService;
 import com.jjt.common.constant.CacheConstants;
 import com.jjt.common.core.controller.BaseController;
 import com.jjt.common.core.domain.R;
 import com.jjt.common.core.redis.RedisCache;
 import com.jjt.common.utils.DateUtils;
 import com.jjt.utils.AsyncService;
+import com.jjt.utils.Tools;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -22,6 +21,8 @@ import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.text.ParseException;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
@@ -42,10 +43,6 @@ public class ApiController extends BaseController {
     @Resource
     private ITwinCalcDayService twinCalcDayService;
     @Resource
-    private ITwinCalcStopService stopService;
-    @Resource
-    private ITwinCalcAlarmsService alarmsService;
-    @Resource
     private ITwinDeviceService deviceService;
     @Resource
     private AsyncService asyncService;
@@ -137,6 +134,14 @@ public class ApiController extends BaseController {
         }
     }
 
+    @ApiOperation("送经量")
+    @GetMapping("/api/warp-run-in")
+    @CrossOrigin(origins = "*")
+    public R<List<WarpRunIn>> wri() {
+//        List<WarpRunIn> list = redisCache.getCacheObject(CacheConstants.INDEX_WARP_RUN_IN);
+        return R.success(redisCache.getCacheObject(CacheConstants.INDEX_WARP_RUN_IN));
+    }
+
     @ApiOperation("配方统计")
     @GetMapping("/api/formula/total")
     @CrossOrigin(origins = "*")
@@ -156,4 +161,69 @@ public class ApiController extends BaseController {
             return R.fail();
         }
     }
+
+    @ApiOperation("导出当前停机明细")
+    @GetMapping("/api/view/stop")
+    @CrossOrigin(origins = "*")
+    public R<Map> viewStop(HttpServletResponse response) throws ParseException {
+        String[] stopStr = {"", "停经片停机", "断纱停机", "人工停机", "断电停机", "设备故障停机", "落布米数达到停机", "叫料停机"};
+        TwinDevice searchDevice = new TwinDevice();
+        searchDevice.setOnline("1");
+        List<TwinDevice> deviceList = deviceService.selectTwinDeviceList(searchDevice);
+        Map<String, Object> result = new HashMap<>();
+        Object d = redisCache.getCacheObject(CacheConstants.STOP_DETAIL);
+        if (d != null) {
+            List<StopDetailVO> stopList = (List<StopDetailVO>) d;
+            stopList.sort(Comparator.comparing(StopDetailVO::getDeviceId));
+            int[] nums = new int[7];
+            String[] devices = new String[7];
+            List<Map<String, Object>> detailList = new ArrayList<>();
+            for (StopDetailVO vo : stopList) {
+                if (!vo.getHasData()) {
+                    Tools.comboStop(6, nums, devices, vo.getDeviceId());
+                    continue;
+                }
+                if (vo.getSpeed() > 0f || vo.getStop() == 0) {
+                    Tools.comboStop(0, nums, devices, vo.getDeviceId());
+                } else {
+                    switch (vo.getStop()) {
+                        case 0:
+                            break;
+                        case 1:
+                            Tools.comboStop(1, nums, devices, vo.getDeviceId());
+                            break;
+                        case 2:
+                            Tools.comboStop(2, nums, devices, vo.getDeviceId());
+                            break;
+                        case 6:
+                            Tools.comboStop(3, nums, devices, vo.getDeviceId());
+                            break;
+                        case 7:
+                            Tools.comboStop(4, nums, devices, vo.getDeviceId());
+                            break;
+                        default:
+                            Tools.comboStop(5, nums, devices, vo.getDeviceId());
+                    }
+                }
+
+                Map<String, Object> detailMap = new HashMap<>();
+                detailMap.put("device", vo.getDeviceId());
+                detailMap.put("speed", vo.getSpeed());
+                detailMap.put("status", vo.getStop());
+                detailMap.put("remark", stopStr[vo.getStop()]);
+
+                detailList.add(detailMap);
+            }
+            Map<String, Object> total = new HashMap<>(16);
+            total.put("n1", deviceList.size());
+
+            for (int i = 0; i < 7; i++) {
+                total.put("n" + (i + 2), nums[i]);
+                total.put("d" + (i + 2), devices[i]);
+            }
+            result.put("total", total);
+            result.put("detail", detailList);
+        }
+        return R.success(result);
+    }
 }

+ 33 - 0
jjt-biz/src/main/java/com/jjt/biz/controller/DemoController.java

@@ -0,0 +1,33 @@
+package com.jjt.biz.controller;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.jjt.common.core.controller.BaseController;
+import com.jjt.common.core.domain.R;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * swagger 用户测试方法
+ *
+ * @author ruoyi
+ */
+@Api("数据接口")
+@RestController
+@Slf4j
+public class DemoController extends BaseController {
+    private R<Map> json(String data) {
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+            Map<String, Object> result = mapper.readValue(data, Map.class);
+            return R.ok(result);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return R.fail();
+    }
+
+
+}

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

@@ -342,7 +342,7 @@ public class ApiServiceImpl implements IApiService {
 //        if (bl != null && flag.equals(bl)) {
 //            return;
 //        }
-        curr();
+//        curr();
 //        today();
     }
 }

+ 6 - 3
jjt-biz/src/main/java/com/jjt/calc/service/impl/TwinCalcHourEnergyServiceImpl.java

@@ -120,7 +120,7 @@ public class TwinCalcHourEnergyServiceImpl implements ITwinCalcHourEnergyService
         Long startTime = start.toInstant(ZoneOffset.of("+8")).toEpochMilli();
         Long endTime = end.toInstant(ZoneOffset.of("+8")).toEpochMilli();
         String baseSql = "select %s from %s where time>%s and time <=%s";
-        TwinWorkshop ws = workshopService.selectTwinWorkshopByWsId(3L);
+        TwinWorkshop ws = workshopService.selectTwinWorkshopByWsCode("WS_01");
         List<TwinWorkshopEnergy> energyList = ws.getTwinWorkshopEnergyList();
         List<TwinCalcHourEnergy> list = new ArrayList<>();
         for (TwinWorkshopEnergy energy : energyList) {
@@ -128,6 +128,9 @@ public class TwinCalcHourEnergyServiceImpl implements ITwinCalcHourEnergyService
             JSONObject jsonObject = iotService.query(sql);
             JSONObject data = jsonObject.getJSONObject("data");
             JSONArray values = data.getJSONArray("values");
+            if (values.size() == 0) {
+                continue;
+            }
             JSONArray first = values.getJSONArray(0);
             JSONArray last = values.getJSONArray(values.size() - 1);
             int res = last.getInt(0) - first.getInt(0);
@@ -177,8 +180,8 @@ public class TwinCalcHourEnergyServiceImpl implements ITwinCalcHourEnergyService
         Date eTime = pair.getValue();
         TwinCalcHourEnergy hour = new TwinCalcHourEnergy();
         Map<String, Object> params = new HashMap<>(16);
-        params.put("sTime", sTime);
-        params.put("eTime", eTime);
+        params.put("sTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,sTime));
+        params.put("eTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, eTime));
         hour.setParams(params);
         return selectTwinCalcHourEnergyList(hour);
     }

+ 26 - 32
jjt-biz/src/main/java/com/jjt/emp/controller/TwinEmpCalcController.java

@@ -1,28 +1,22 @@
 package com.jjt.emp.controller;
 
-import java.util.List;
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.jjt.common.annotation.Log;
 import com.jjt.common.core.controller.BaseController;
 import com.jjt.common.core.domain.AjaxResult;
+import com.jjt.common.core.page.TableDataInfo;
 import com.jjt.common.enums.BusinessType;
+import com.jjt.common.utils.DateUtils;
+import com.jjt.common.utils.poi.ExcelUtil;
 import com.jjt.emp.domain.TwinEmpCalc;
 import com.jjt.emp.service.ITwinEmpCalcService;
-import com.jjt.common.utils.poi.ExcelUtil;
-import com.jjt.common.core.page.TableDataInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
 
 /**
  * 员工产量统计Controller
@@ -30,21 +24,26 @@ import com.jjt.common.core.page.TableDataInfo;
  * @author wukai
  * @date 2025-01-18
  */
-@Api(tags="员工产量统计")
+@Api(tags = "员工产量统计")
 @RestController
 @RequestMapping("/emp/empCalc")
-public class TwinEmpCalcController extends BaseController{
+public class TwinEmpCalcController extends BaseController {
     @Resource
     private ITwinEmpCalcService twinEmpCalcService;
 
+    @GetMapping("/calc")
+    @ResponseBody
+    public AjaxResult calc(String date) {
+        return toAjax(twinEmpCalcService.calc(DateUtils.parseDate(date)));
+    }
+
     /**
      * 查询员工产量统计列表
      */
     @ApiOperation("查询员工产量统计列表")
     @PreAuthorize("@ss.hasPermi('emp:empCalc:list')")
     @GetMapping("/list")
-    public TableDataInfo list(TwinEmpCalc twinEmpCalc)
-    {
+    public TableDataInfo list(TwinEmpCalc twinEmpCalc) {
         startPage();
         List<TwinEmpCalc> list = twinEmpCalcService.selectTwinEmpCalcList(twinEmpCalc);
         return getDataTable(list);
@@ -57,8 +56,7 @@ public class TwinEmpCalcController extends BaseController{
     @PreAuthorize("@ss.hasPermi('emp:empCalc:export')")
     @Log(title = "员工产量统计", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    public void export(HttpServletResponse response, TwinEmpCalc twinEmpCalc)
-    {
+    public void export(HttpServletResponse response, TwinEmpCalc twinEmpCalc) {
         List<TwinEmpCalc> list = twinEmpCalcService.selectTwinEmpCalcList(twinEmpCalc);
         ExcelUtil<TwinEmpCalc> util = new ExcelUtil<TwinEmpCalc>(TwinEmpCalc.class);
         util.exportExcel(response, list, "员工产量统计数据");
@@ -70,8 +68,7 @@ public class TwinEmpCalcController extends BaseController{
     @ApiOperation("获取员工产量统计详细信息")
     @PreAuthorize("@ss.hasPermi('emp:empCalc:query')")
     @GetMapping(value = "/{calcId}")
-    public AjaxResult getInfo(@PathVariable("calcId") Long calcId)
-    {
+    public AjaxResult getInfo(@PathVariable("calcId") Long calcId) {
         return success(twinEmpCalcService.selectTwinEmpCalcByCalcId(calcId));
     }
 
@@ -82,8 +79,7 @@ public class TwinEmpCalcController extends BaseController{
     @PreAuthorize("@ss.hasPermi('emp:empCalc:add')")
     @Log(title = "员工产量统计", businessType = BusinessType.INSERT)
     @PostMapping
-    public AjaxResult add(@RequestBody TwinEmpCalc twinEmpCalc)
-    {
+    public AjaxResult add(@RequestBody TwinEmpCalc twinEmpCalc) {
         return toAjax(twinEmpCalcService.insertTwinEmpCalc(twinEmpCalc));
     }
 
@@ -94,8 +90,7 @@ public class TwinEmpCalcController extends BaseController{
     @PreAuthorize("@ss.hasPermi('emp:empCalc:edit')")
     @Log(title = "员工产量统计", businessType = BusinessType.UPDATE)
     @PutMapping
-    public AjaxResult edit(@RequestBody TwinEmpCalc twinEmpCalc)
-    {
+    public AjaxResult edit(@RequestBody TwinEmpCalc twinEmpCalc) {
         return toAjax(twinEmpCalcService.updateTwinEmpCalc(twinEmpCalc));
     }
 
@@ -105,9 +100,8 @@ public class TwinEmpCalcController extends BaseController{
     @ApiOperation("删除员工产量统计")
     @PreAuthorize("@ss.hasPermi('emp:empCalc:remove')")
     @Log(title = "员工产量统计", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{calcIds}")
-    public AjaxResult remove(@PathVariable Long[] calcIds)
-    {
+    @DeleteMapping("/{calcIds}")
+    public AjaxResult remove(@PathVariable Long[] calcIds) {
         return toAjax(twinEmpCalcService.deleteTwinEmpCalcByCalcIds(calcIds));
     }
 }

+ 221 - 1
jjt-biz/src/main/java/com/jjt/order/controller/OrderApiController.java

@@ -1,15 +1,42 @@
 package com.jjt.order.controller;
 
+import com.jjt.calc.domain.TwinCalcDay;
+import com.jjt.calc.domain.TwinFormulaInfo;
+import com.jjt.calc.service.ITwinCalcDayService;
+import com.jjt.calc.service.ITwinFormulaInfoService;
 import com.jjt.common.constant.CacheConstants;
 import com.jjt.common.core.controller.BaseController;
 import com.jjt.common.core.redis.RedisCache;
+import com.jjt.common.utils.DateUtils;
+import com.jjt.order.domain.TwinOrder;
+import com.jjt.order.domain.TwinOrderDetail;
+import com.jjt.order.domain.VmsStock;
+import com.jjt.order.service.ITwinOrderService;
+import com.jjt.order.utils.OrderExportUtil;
+import com.jjt.order.vo.BomVO;
+import com.jjt.order.vo.SkuVO;
+import com.jjt.utils.MssqlUtil;
 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.Cell;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
-import java.util.Map;
+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.stream.Collectors;
 
 /**
  * @author ruoyi
@@ -21,6 +48,12 @@ import java.util.Map;
 public class OrderApiController extends BaseController {
     @Resource
     private RedisCache redisCache;
+    @Resource
+    private ITwinOrderService orderService;
+    @Resource
+    private ITwinFormulaInfoService formulaInfoService;
+    @Resource
+    private ITwinCalcDayService dayService;
 
     @ApiOperation("查看当前库存")
     @GetMapping("/api/stock")
@@ -29,4 +62,191 @@ public class OrderApiController extends BaseController {
     public Map<String, Object> mesStock() {
         return redisCache.getCacheObject(CacheConstants.VMS_STOCK);
     }
+
+    @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 = DateUtils.toDate(LocalDate.now().minusDays(2));
+        if (ldt.getHour() > 7) {
+            sd = DateUtils.toDate(LocalDate.now().minusDays(1));
+        }
+        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.vmsStock();
+        List<TwinOrderDetail> all = new ArrayList<>();
+        orderList.forEach(to -> all.addAll(to.getTwinOrderDetailList().stream().filter(tod -> tod.getBomSpec() != null).collect(Collectors.toList())));
+        //按规格分组
+        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())) {
+            OrderExportUtil oe = new OrderExportUtil(wb);
+
+            XSSFSheet sheet0 = wb.getSheetAt(0);
+            Cell title = sheet0.getRow(0).getCell(0);
+            title.setCellValue("白坯布靶向生产测算-10天(" + start + " 至 " + end + ")");
+
+            oe.sheet0(sheet0, bomList);
+            oe.sheet1(wb.getSheetAt(1), stocks);
+            oe.sheet2(wb.getSheetAt(2), skuList);
+            oe.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 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;
+    }
 }

+ 10 - 1
jjt-biz/src/main/java/com/jjt/order/service/impl/TwinOrderServiceImpl.java

@@ -12,6 +12,7 @@ import com.jjt.order.domain.TwinOrder;
 import com.jjt.order.domain.TwinOrderDetail;
 import com.jjt.order.mapper.TwinOrderMapper;
 import com.jjt.order.service.ITwinBomService;
+import com.jjt.order.service.ITwinOrderDetailService;
 import com.jjt.order.service.ITwinOrderService;
 import org.springframework.stereotype.Service;
 
@@ -39,6 +40,8 @@ public class TwinOrderServiceImpl implements ITwinOrderService {
     private TwinOrderMapper twinOrderMapper;
     @Resource
     private ITwinBomService bomService;
+    @Resource
+    private ITwinOrderDetailService detailService;
 
     /**
      * 查询销售订单信息
@@ -190,7 +193,13 @@ public class TwinOrderServiceImpl implements ITwinOrderService {
         params.put("start", start);
         params.put("end", end);
         order.setParams(params);
-        return selectTwinOrderList(order);
+        List<TwinOrder> list = selectTwinOrderList(order);
+        list.forEach(to -> {
+            TwinOrderDetail tod = new TwinOrderDetail();
+            tod.setOderId(to.getOderId());
+            to.setTwinOrderDetailList(detailService.selectTwinOrderDetailList(tod));
+        });
+        return list;
     }
 
     /**

+ 359 - 0
jjt-biz/src/main/java/com/jjt/order/utils/OrderExportUtil.java

@@ -0,0 +1,359 @@
+package com.jjt.order.utils;
+
+import com.jjt.calc.domain.TwinFormulaInfo;
+import com.jjt.common.utils.DateUtils;
+import com.jjt.order.domain.TwinOrder;
+import com.jjt.order.domain.TwinOrderDetail;
+import com.jjt.order.domain.VmsStock;
+import com.jjt.order.vo.BomVO;
+import com.jjt.order.vo.SkuVO;
+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 java.math.BigDecimal;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * OrderExportUtils$
+ *
+ * @author wukai
+ * @date 2025/2/12 02:27
+ */
+public class OrderExportUtil {
+    private CellStyle p2;
+    private CellStyle percentStyle;
+
+    public OrderExportUtil(XSSFWorkbook wb) {
+        CreationHelper creationHelper = wb.getCreationHelper();
+        this.percentStyle = wb.createCellStyle();
+        percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
+        percentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        this.p2 = wb.createCellStyle();
+        p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
+        p2.setVerticalAlignment(VerticalAlignment.CENTER);
+    }
+
+    /**
+     * 总览
+     *
+     * @param sheet   sheet
+     * @param bomList 物料列表
+     */
+    public 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 库存
+     */
+    public 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 库存
+     */
+    public 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 库存
+     */
+    public 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 库存
+     */
+    public 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());
+        });
+    }
+}

+ 58 - 0
jjt-biz/src/main/java/com/jjt/order/vo/BomVO.java

@@ -0,0 +1,58 @@
+package com.jjt.order.vo;
+
+import com.jjt.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 BomVO{
+    private static final long serialVersionUID = 1L;
+    @ApiModelProperty(name = "物料编码")
+    private String bomCode;
+
+    @ApiModelProperty(name = "物料名称")
+    private String bomName;
+
+    @ApiModelProperty(name = "物料规格")
+    private String bomSpec;
+
+    @ApiModelProperty(name = "订单量")
+    private Long orders;
+
+    @ApiModelProperty(name = "需求总重量")
+    private Double xql;
+
+    @ApiModelProperty(name = "库存量")
+    private Float kcl;
+
+    @ApiModelProperty(name = "印染量")
+    private Float yrl;
+
+    @ApiModelProperty(name = "预测量")
+    private Double ycl;
+
+    @ApiModelProperty(name = "差值")
+    private Double cz;
+
+    @ApiModelProperty(name = "差率")
+    private Double cl;
+
+    @ApiModelProperty(name = "机台号")
+    private String deviceIds;
+
+    @ApiModelProperty(name = "最近日产量")
+    private Double last;
+
+    @ApiModelProperty(name = "订单信息")
+    private List<TwinOrder> orderList;
+}

+ 38 - 0
jjt-biz/src/main/java/com/jjt/order/vo/SkuVO.java

@@ -0,0 +1,38 @@
+package com.jjt.order.vo;
+
+import com.jjt.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 {
+    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;
+}

+ 15 - 0
jjt-biz/src/main/java/com/jjt/utils/Tools.java

@@ -1,6 +1,7 @@
 package com.jjt.utils;
 
 import cn.hutool.json.JSONArray;
+import com.jjt.common.utils.StringUtils;
 import javafx.util.Pair;
 import org.apache.poi.ss.usermodel.*;
 
@@ -374,4 +375,18 @@ public class Tools {
         return res;
     }
 
+
+    /**
+     * 组装设备ID
+     */
+    public static void comboStop(int i, int[] nums, String[] devices, long id) {
+        nums[i]++;
+        if (StringUtils.isNotEmpty(devices[i])) {
+            devices[i] += ",";
+        } else {
+            devices[i] = "";
+        }
+        devices[i] += id;
+    }
+
 }

+ 3 - 0
jjt-biz/src/main/resources/mapper/order/TwinOrderMapper.xml

@@ -28,6 +28,9 @@
             </if>
             <if test="orderDate != null ">and ORDER_DATE = #{orderDate}</if>
             <if test="remark != null  and remark != ''">and REMARK = #{remark}</if>
+            <if test="params.start != null and params.end != null">
+                and FORMAT(ORDER_DATE,'yyyy-MM-dd') between #{params.start} and #{params.end}
+            </if>
         </where>
     </select>
 

+ 1 - 1
jjt-biz/src/main/resources/mapper/ws/TwinWorkshopCalcMapper.xml

@@ -37,7 +37,7 @@
         order by DATA_DATE
     </select>
 
-    <insert id="insertTwinWorkshopCalc" parameterType="TwinWorkshopCalc" useGeneratedKeys="true" keyProperty="calcId">
+    <insert id="insertTwinWorkshopCalc" parameterType="TwinWorkshopCalc">
         insert into TWIN_WORKSHOP_CALC
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="dataDate != null">DATA_DATE,</if>