wukai 1 неделя назад
Родитель
Сommit
db9d995dff

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

@@ -43,23 +43,23 @@ public class TaskTest {
     @Test
     public void last() {
         iotService.setToken();
-//        String date = "2025-02-26";
-//        LocalDate localDate = LocalDate.parse(date);
+        String date = "2025-07-11";
+        LocalDate localDate = LocalDate.parse(date);
 //        dayService.day(localDate);
 //        dayService.day(LocalDate.parse("2025-02-23"));
 //        dayService.day(LocalDate.parse("2025-02-24"));
 //        dayService.day(LocalDate.parse("2025-03-16"));
-        for (int i = 1; i < 19; i++) {
-            String d = "2025-03-" + (i < 10 ? "0" + i : i);
-            dayService.day(LocalDate.parse(d));
-        }
-////        empCalcService.calc(DateUtils.toDate(localDate));
-//        LocalDateTime ldt = LocalDateTime.of(localDate, LocalTime.MIN);
-//        for (int i = 11; i < 15; i++) {
-//            LocalDateTime tt = ldt.plusHours(i);
-//            System.err.println(tt.toLocalDate().toString() + tt.getHour());
-//            calcHourService.calc(tt.toLocalDate().toString(), tt.getHour());
+//        for (int i = 1; i < 19; i++) {
+//            String d = "2025-03-" + (i < 10 ? "0" + i : i);
+//            dayService.day(LocalDate.parse(d));
 //        }
+////        empCalcService.calc(DateUtils.toDate(localDate));
+        LocalDateTime ldt = LocalDateTime.of(localDate, LocalTime.MIN);
+        for (int i = 23; i < 24; 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-24", 14);
 

+ 283 - 0
jjt-biz/src/main/java/com/jjt/biz/controller/ApiDriverController.java

@@ -0,0 +1,283 @@
+package com.jjt.biz.controller;
+
+import com.jjt.common.core.controller.BaseController;
+import com.jjt.common.core.domain.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+/**
+ * swagger 用户测试方法
+ *
+ * @author ruoyi
+ */
+@Api(tags = "全厂孪生数据接口")
+@RestController
+@RequestMapping("/api/driver")
+@Slf4j
+public class ApiDriverController extends BaseController {
+    @ApiOperation("全球营收")
+    @GetMapping("/rev")
+    @CrossOrigin(origins = "*")
+    @ResponseBody
+    public R<?> rev() {
+        // 创建全局结果Map,用于存储所有业务数据
+        Map<String, Object> result = new HashMap<>();
+        // 基础财务指标数据(单位:万元)
+        // 年度总营收
+        result.put("rev", 5800);
+        // 年度总成本
+        result.put("cogs", 4500);
+        // 年度总利润
+        result.put("gp", 1300);
+        // 年度毛利率(百分比)
+        result.put("gpm", 22.4);
+        // 总资产(单位:万元)
+        result.put("assets", 360000);
+        // 业务覆盖国家数量
+        result.put("country", 15);
+        // 年度订单总量
+        result.put("order", 90);
+
+        // 营收构成明细数据
+        List<Map<String, Object>> revList = new ArrayList<>();
+        String[] revenueTypes = {"订单销售", "售后服务", "金融业务", "其他收入"};
+        double[] revenueValues = {3800, 500, 200, 100};
+        for (int i = 0; i < revenueTypes.length; i++) {
+            Map<String, Object> revMap = new HashMap<>();
+            revMap.put("type", revenueTypes[i]);  // 收入类型
+            revMap.put("value", revenueValues[i]); // 收入金额(万元)
+            revList.add(revMap);
+        }
+        result.put("revList", revList);
+
+        // 成本构成明细数据(单位:万元)
+        List<Map<String, Object>> cogsList = new ArrayList<>();
+        String[] cogsTypes = {"直接材料", "直接人工", "制造费用", "销售费用", "管理费用"};
+        double[] cogsValues = {40, 20, 15, 5, 8};
+        for (int i = 0; i < cogsTypes.length; i++) {
+            Map<String, Object> cogsMap = new HashMap<>();
+            cogsMap.put("type", cogsTypes[i]);   // 成本类型
+            cogsMap.put("value", cogsValues[i]); // 成本金额
+            cogsList.add(cogsMap);
+        }
+        result.put("cogsList", cogsList);
+
+        // 各国业务数据
+        List<Map<String, Object>> orderList = new ArrayList<>();
+        String[] countries = {"澳大利亚", "美国", "英国", "德国", "法国", "日本", "韩国", "巴西", "印度", "俄罗斯"};
+        for (int i = 0; i < 10; i++) {
+            Map<String, Object> orderMap = new HashMap<>();
+            orderMap.put("country", countries[i]);  // 国家名称
+            orderMap.put("num", 20 + i * 5);       // 订单数量
+            orderMap.put("rev", 20 + i * 10);      // 收入(万元)
+            orderMap.put("gp", 25.2 + i * 2.5);    // 利润(万元)
+            orderList.add(orderMap);
+        }
+        result.put("orderList", orderList);
+
+        // 产品线利润数据(单位:万元)
+        List<Map<String, Object>> gpList = new ArrayList<>();
+        String[] carpetTypes = {"羊毛毯", "纯棉毯", "亚麻毯", "丝绸毯", "竹纤维毯", "涤纶毯", "腈纶毯", "混纺毯", "法兰绒毯", "珊瑚绒毯"};
+        double[] profitValues = {6.9, 7.8, 8.3, 9.1, 10.4, 11.2, 12.5, 13.5, 14.1, 15.2};
+        double[] gpmValues = {35.2, 28.3, 31.2, 26.9, 33.5, 30.4, 34.1, 27.8, 32.5, 29.1};
+        for (int i = 0; i < carpetTypes.length; i++) {
+            Map<String, Object> gpMap = new HashMap<>();
+            gpMap.put("type", carpetTypes[i]);    // 产品类型
+            gpMap.put("value", profitValues[i]);  // 利润金额
+            gpMap.put("gmp", gpmValues[i]);  // 利润金额
+            gpList.add(gpMap);
+        }
+        result.put("gpList", gpList);
+
+        // 产品线毛利率数据(百分比)
+        List<Map<String, Object>> gpmList = new ArrayList<>();
+        String[] gpmTypes ={"羊毛毯", "纯棉毯", "亚麻毯", "丝绸毯", "竹纤维毯", "涤纶毯", "腈纶毯", "混纺毯", "法兰绒毯", "珊瑚绒毯"};
+        for (int i = 0; i < gpmTypes.length; i++) {
+            Map<String, Object> gpmMap = new HashMap<>();
+            gpmMap.put("type", gpmTypes[i]);    // 产品类型
+            gpmMap.put("value", gpmValues[i]);  // 毛利率百分比
+            gpmList.add(gpmMap);
+        }
+        result.put("gpmList", gpmList);
+
+        // 月度经营数据
+        List<Map<String, Object>> tradeList = new ArrayList<>();
+        String[] months = {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
+        double[] revenue = {380, 420, 510, 490, 560, 590, 720, 670, 810, 780, 920, 940};
+        double[] cost = {310, 340, 390, 370, 420, 400, 470, 430, 480, 460, 520, 550};
+        double[] profit = {70, 80, 120, 120, 140, 190, 250, 240, 330, 320, 400, 390};
+        double[] profitRate = {18.4, 19.0, 23.5, 24.5, 25.0, 32.2, 34.7, 35.8, 40.7, 41.0, 43.5, 41.5};
+
+        for (int i = 0; i < months.length; i++) {
+            Map<String, Object> tradeMap = new HashMap<>();
+            tradeMap.put("month", months[i]);       // 月份
+            tradeMap.put("revenue", revenue[i]);    // 月度收入(万元)
+            tradeMap.put("cost", cost[i]);          // 月度成本(万元)
+            tradeMap.put("profit", profit[i]);      // 月度利润(万元)
+            tradeMap.put("profitRate", profitRate[i]); // 月度利润率(%)
+            tradeList.add(tradeMap);
+        }
+        result.put("tradeList", tradeList);
+
+        // 月度预测数据(简化版,只保留利润率、营收和资产)
+        List<Map<String, Object>> forecastList = new ArrayList<>();
+        String[] forecastMonths = {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
+        double[] forecastRevenue = {1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100};
+        double[] forecastProfitRate = {42.0, 40.9, 40.0, 39.2, 38.6, 38.0, 37.5, 37.1, 36.7, 36.3, 36.0, 35.7};
+        double[] forecastAssets = {370000, 380000, 390000, 400000, 410000, 420000, 430000, 440000, 450000, 460000, 470000, 480000};
+
+        for (int i = 0; i < forecastMonths.length; i++) {
+            Map<String, Object> forecastMap = new HashMap<>();
+            forecastMap.put("month", forecastMonths[i]);        // 预测月份
+            forecastMap.put("revenue", forecastRevenue[i]);     // 预测收入(万元)
+            forecastMap.put("profitRate", forecastProfitRate[i]); // 预测利润率(%)
+            forecastMap.put("assets", forecastAssets[i]);       // 预测资产(万元)
+            forecastList.add(forecastMap);
+        }
+        result.put("forecastList", forecastList);
+        return R.ok(result);
+    }
+
+    @ApiOperation("销售")
+    @GetMapping("/sales")
+    @CrossOrigin(origins = "*")
+    @ResponseBody
+    public R<?> sales() {
+        Map<String, Object> result = new HashMap<>();
+        // 模拟一年12个月份的销售数据
+        List<Map<String, Object>> salesData = new ArrayList<>();
+        String[] months = {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
+        double[] revenue = {380, 420, 510, 490, 560, 590, 720, 670, 810, 780, 920, 940};
+
+        for (int i = 0; i < months.length; i++) {
+            Map<String, Object> monthData = new HashMap<>();
+            monthData.put("month", months[i]);
+            monthData.put("revenue", revenue[i]);
+            salesData.add(monthData);
+        }
+
+        result.put("sales", salesData);
+
+        // 模拟TOP6渠道排名数据
+        List<Map<String, Object>> channelRanking = new ArrayList<>();
+        String[] channels = {"电商平台", "经销商", "专卖店", "大型超市", "外贸出口", "直销"};
+        double[] amounts = {3200, 2800, 1500, 1200, 800, 500};
+        double total = Arrays.stream(amounts).sum();
+
+        for (int i = 0; i < channels.length; i++) {
+            Map<String, Object> channelData = new HashMap<>();
+            channelData.put("channel", channels[i]);
+            channelData.put("amount", amounts[i]);
+            channelData.put("percentage", Math.round(amounts[i] / total * 100 * 100) / 100.0); // 保留两位小数
+            channelRanking.add(channelData);
+        }
+        result.put("channel", channelRanking);
+
+        // 模拟TOP10的花色排名数据
+        List<Map<String, Object>> patternRanking = new ArrayList<>();
+        String[] patterns = {"雪里梅花", "南韩芳摇", "如旧芳菲", "金山观月", "惊喜四座", "怡情古韵", "炫彩印象", "MT花卉", "最爱纯真", "牡丹齐放"};
+        double[] amountsP = {3200, 2800, 1500, 1200, 800, 500, 400, 300, 200, 100};
+
+        for (int i = 0; i < patterns.length; i++) {
+            Map<String, Object> patternData = new HashMap<>();
+            patternData.put("pattern", patterns[i]);
+            patternData.put("amount", amountsP[i]);
+            patternRanking.add(patternData);
+        }
+        result.put("pattern", patternRanking);
+
+        List<Map<String, Object>> regionRanking = new ArrayList<>();
+        String[] salesTypes = {"订单销售", "售后服务", "金融业务", "其他"};
+        String[] regions = {"美国", "日本", "德国", "沙特阿拉伯", "阿联酋", "卡塔尔", "法国", "韩国", "澳大利亚", "巴西"};
+        double[] amountsR = {4200, 3800, 3500, 2800, 2200, 1800, 1500, 1200, 900, 600};
+
+        for (String salesType : salesTypes) {
+            Map<String, Object> salesTypeMap = new HashMap<>();
+            salesTypeMap.put("salesType", salesType);
+
+            // 为每种销售类型生成独立的region数据,使用不同的国家组合
+            List<Map<String, Object>> typeRegions = new ArrayList<>();
+
+            // 不同的销售类型使用不同的国家组合
+            String[][] regionGroups = {
+                {"美国", "日本", "德国", "法国", "韩国"},  // 订单销售
+                {"沙特阿拉伯", "阿联酋", "卡塔尔", "澳大利亚", "巴西"},  // 售后服务
+                {"美国", "德国", "法国", "澳大利亚", "巴西"},  // 金融业务
+                {"日本", "韩国", "沙特阿拉伯", "阿联酋", "卡塔尔"}   // 其他
+            };
+
+            // 根据销售类型选择对应的国家组
+            String[] selectedRegions = regionGroups[Arrays.asList(salesTypes).indexOf(salesType)];
+
+            for (int i = 0; i < selectedRegions.length; i++) {
+                Map<String, Object> regionData = new HashMap<>();
+                String region = selectedRegions[i];
+                int originalIndex = Arrays.asList(regions).indexOf(region);
+                regionData.put("region", region);
+                // 随机调整金额
+                regionData.put("amount", Math.round(amountsR[originalIndex] * (0.8 + Math.random() * 0.4)));
+
+                // 生成12个月销售趋势数据
+                List<Map<String, Object>> monthlySales = new ArrayList<>();
+                Random random = new Random();
+                double totalV = amountsR[originalIndex];
+                double remaining = totalV;
+
+                for (int j = 0; j < 12; j++) {
+                    Map<String, Object> monthData = new HashMap<>();
+                    double amount = j == 11 ? remaining :
+                        Math.min(random.nextDouble() * (remaining / (12 - j) * 1.5), remaining);
+                    monthData.put("month", months[j]);
+                    monthData.put("amount", Math.round(amount * 100) / 100.0);
+                    monthlySales.add(monthData);
+                    remaining -= amount;
+                }
+                regionData.put("trend", monthlySales);
+                typeRegions.add(regionData);
+            }
+
+            salesTypeMap.put("regions", typeRegions);
+            regionRanking.add(salesTypeMap);
+        }
+
+        result.put("type", regionRanking);
+
+        // 模拟TOP10的规格占比数据
+        List<Map<String, Object>> specRanking = new ArrayList<>();
+        String[] specs = {"单层涤纶毯(成品)", "单层涤纶毯(面料)", "单面涤纶复合羊羔绒(成品)", "双层涤纶复合毯(成品)", "双层涤纶复合毯(面料)", "双层涤纶毯(成品)", "双层涤纶毯(面料)"};
+        double[] amountsS = {3200, 2800, 1500, 1200, 800, 500, 400};
+        double totalS = Arrays.stream(amountsS).sum();
+
+        for (int i = 0; i < specs.length; i++) {
+            Map<String, Object> specData = new HashMap<>();
+            specData.put("bom", specs[i]);
+            specData.put("amount", amountsS[i]);
+            specData.put("percentage", Math.round(amountsS[i] / totalS * 100 * 100) / 100.0); // 保留两位小数
+            specRanking.add(specData);
+        }
+        result.put("bom", specRanking);
+
+        return R.ok(result);
+    }
+
+    @ApiOperation("成本")
+    @GetMapping("/cogs")
+    @CrossOrigin(origins = "*")
+    @ResponseBody
+    public R<?> cogs() {
+        return R.ok();
+    }
+
+    @ApiOperation("采购")
+    @GetMapping("/po")
+    @CrossOrigin(origins = "*")
+    @ResponseBody
+    public R<?> po() {
+        return R.ok();
+    }
+
+}

+ 1 - 1
jjt-biz/src/main/java/com/jjt/biz/controller/ApiProductivityExportController.java

@@ -102,7 +102,7 @@ public class ApiProductivityExportController extends BaseController {
     @RequestMapping("/api/export/productivity-month")
     @CrossOrigin(origins = "*")
     public void productivityMonthExport(String date, HttpServletResponse response) {
-        date = date.substring(0, 7);
+//        date = date.substring(0, 7);
         try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("tpl/productivity-month.xlsx"); XSSFWorkbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
             CreationHelper creationHelper = wb.getCreationHelper();
             CellStyle percentStyle = wb.createCellStyle();

+ 80 - 7
jjt-biz/src/main/java/com/jjt/biz/controller/ApiThirdController.java

@@ -2,21 +2,24 @@ package com.jjt.biz.controller;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.jjt.biz.vo.KnittingEmpVO;
+import com.jjt.biz.vo.SalaryVO;
 import com.jjt.common.core.controller.BaseController;
 import com.jjt.common.core.domain.AjaxResult;
+import com.jjt.emp.domain.TwinEmpCalc;
+import com.jjt.emp.service.ITwinEmpCalcService;
 import com.jjt.wkEmp.domain.TwinWkEmpSync;
 import com.jjt.wkEmp.service.ITwinWkEmpRotaService;
 import com.jjt.wkEmp.service.ITwinWkEmpSyncService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
-import java.util.Date;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 第三方数据接口
@@ -27,12 +30,12 @@ import java.util.Date;
 @RestController
 @Slf4j
 public class ApiThirdController extends BaseController {
-
     @Resource
     ITwinWkEmpSyncService syncService;
-
     @Resource
     ITwinWkEmpRotaService rotaService;
+    @Resource
+    private ITwinEmpCalcService twinEmpCalcService;
 
     @ApiOperation("经编车间员工排班")
     @PostMapping("/api/knitting/emp/schedule")
@@ -59,4 +62,74 @@ public class ApiThirdController extends BaseController {
         }
         return AjaxResult.success();
     }
+
+    @ApiOperation("经编车间员工月度工资")
+    @GetMapping("/api/salary/monthly")
+    @CrossOrigin(origins = "*")
+    public AjaxResult monthCalc(String date) {
+        List<TwinEmpCalc> list = twinEmpCalcService.selectTwinEmpCalcListByMonth(date);
+        Map<String, String> nameMap = getNameMapping();
+        if (list.size() > 0) {
+            List<SalaryVO> salary = list.stream()
+                    .collect(Collectors.groupingBy(TwinEmpCalc::getEmpName))
+                    .entrySet().stream()
+                    .map(entry -> {
+                                List<TwinEmpCalc> group = entry.getValue();
+                                BigDecimal totalPrice = calculateTotalPrice(group);
+                                SalaryVO vo = new SalaryVO();
+                                String id = nameMap.get(entry.getKey());
+                                if (id == null) {
+                                    id = "";
+                                }
+                                vo.setEmpId(id);
+                                vo.setEmpName(entry.getKey());
+                                vo.setSalary(totalPrice.setScale(2, RoundingMode.HALF_UP));
+                                return vo;
+                            }
+                    ).collect(Collectors.toList());
+            return AjaxResult.success(salary);
+        } else {
+            return AjaxResult.error("无此月份数据");
+        }
+    }
+
+    /**
+     * 辅助方法:计算总金额
+     */
+    private BigDecimal calculateTotalPrice(List<TwinEmpCalc> group) {
+        return group.stream()
+                .map(TwinEmpCalc::getTotalPrice).filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+
+
+    public Map<String, String> getNameMapping() {
+        Map<String, String> nameMap = new LinkedHashMap<>();
+        nameMap.put("杨玉叶", "20130902001");
+        nameMap.put("裴菊芬", "20140219001");
+        nameMap.put("黄春叶", "20181102001");
+        nameMap.put("马雯鑫", "20200131002");
+        nameMap.put("余茂敏", "20200831003");
+        nameMap.put("李红子", "20200921002");
+        nameMap.put("姚虹云", "20210305003");
+        nameMap.put("马爱敏", "20211011003");
+        nameMap.put("吴亚琼", "20211101005");
+        nameMap.put("马雨欣", "20220217003");
+        nameMap.put("谭裕琴", "20220315006");
+        nameMap.put("张蓉", "20220922001");
+        nameMap.put("邓威", "20230511003");
+        nameMap.put("杨艳杰", "20230908005");
+        nameMap.put("沈让", "20231109005");
+        nameMap.put("邓丽", "20231127003");
+        nameMap.put("史杨杨", "20231204003");
+        nameMap.put("史利侠", "20240228012");
+        nameMap.put("黄浩杰", "20240626006");
+        nameMap.put("费秋容", "20250208005");
+        nameMap.put("韩忍", "20250215002");
+        nameMap.put("袁奇俊", "20250217008");
+        nameMap.put("孙秋来", "20250701004");
+        nameMap.put("伍小弟", "20250704002");
+        return nameMap;
+    }
+
 }

+ 26 - 0
jjt-biz/src/main/java/com/jjt/biz/vo/SalaryVO.java

@@ -0,0 +1,26 @@
+package com.jjt.biz.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 经编车间员工工资 SalaryVO
+ *
+ * @author wukai
+ * @date 2025-01-18
+ */
+@ApiModel(value = "SalaryVO", description = "经编车间员工工资VO")
+@Data
+public class SalaryVO {
+    private static final long serialVersionUID = 1L;
+    @ApiModelProperty("员工编号")
+    private String empId;
+    @ApiModelProperty("姓名")
+    private String empName;
+    @ApiModelProperty("工资")
+    private BigDecimal salary;
+
+}