package cn.ezhizao.project.business.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.ezhizao.common.utils.PdfUtil;
import cn.ezhizao.common.utils.SecurityUtils;
import cn.ezhizao.common.utils.uuid.SnowflakeIdWorker;
import cn.ezhizao.framework.qrCode.BarCodeDemo;
import cn.ezhizao.framework.qrCode.QrCodeDemo;
import cn.ezhizao.framework.redis.RedisCache;
import cn.ezhizao.project.business.domain.*;
import cn.ezhizao.project.business.service.*;

import cn.ezhizao.project.business.service.IBizOutsourcedRecordsService;
import cn.ezhizao.project.system.domain.SysDept;
import cn.ezhizao.project.system.domain.SysUser;
import cn.ezhizao.project.system.service.ISysConfigService;
import cn.ezhizao.project.system.service.ISysDeptService;
import cn.ezhizao.project.system.service.ISysUserService;
import cn.hutool.extra.template.TemplateException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import freemarker.template.Template;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import cn.ezhizao.framework.aspectj.lang.annotation.Log;
import cn.ezhizao.framework.aspectj.lang.enums.BusinessType;
import cn.ezhizao.framework.web.controller.BaseController;
import cn.ezhizao.framework.web.domain.AjaxResult;

import cn.ezhizao.framework.web.page.TableDataInfo;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

/**
 * 外协单主
 * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子Controller
 *
 * @author 庄德政
 * date    2024-04-26
 */
@Data
@RestController
@RequestMapping("/business/outsource")
public class BizOutsourcedOrderController extends BaseController {
    @Value("${file.upload.path}")
    private String uploadPath;
    @Resource
    private IBizOutsourcedOrderService bizOutsourcedOrderService;

    @Value("${baseUrl}")
    private String baseUrl;

    @Resource
    private IBizDayworkService bizDayworkService;

    @Resource
    private IBizDayworkItemService bizDayworkItemService;

    @Resource
    private IBizOutsourcedOrderDetailService bizOutsourcedOrderDetailService;

    @Resource
    private IBizOutsourcedOrderDetailProcessService bizOutsourcedOrderDetailProcessService;

    @Resource
    private IBizCarrierService bizCarrierService;

    @Resource
    private IBizDayworkCarrierService iBizDayworkCarrierService;
    @Resource
    private IBizOutsourcedRecordsService bizOutsourcedRecordsService;

    @Resource
    private ISysUserService userService;
    @Resource
    private SnowflakeIdWorker snowflakeIdWorker;

    /**
     * 生成pdf
     */
    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    @Resource
    private IBizCarrierRejectService iBizCarrierRejectService;

    @Resource
    private RedisCache redisCache;
    @Resource
    private IBizReturnReceiptDetailService bizReturnReceiptDetailService;
    @Resource
    private IBizProductionPlanDetailService bizProductionPlanDetailService;
    @Resource
    private ISysDeptService deptService;
    @Resource
    private IBizLotService bizLotService;
    @Resource
    private IBizFurnaceNoInfoService furnaceNoInfoService;
    @Resource
    private IBizReturnReceiptService bizReturnReceiptService;
    @Resource
    private IBizDayworkItemExamineService bizDayworkItemExamineService;
    @Resource
    HttpServletRequest request;
    @Resource
    private ISysConfigService configService;

    /**
     * 查询外协单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子列表
     */
//    @PreAuthorize("@ss.hasPermi('business:outsource:list')")
    @GetMapping("/list")
    @Log(title = "查询外协单", businessType = BusinessType.SELECT)
    public TableDataInfo list(BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(bizOutsourcedOrder);
        startPage();
        List<BizOutsourcedOrder> list = bizOutsourcedOrderService.getList(bizOutsourcedOrder);
        return getDataTable(list);
    }

    /**
     * 导出外协单主 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子列表
     */
//    @PreAuthorize("@ss.hasPermi('business:outsource:export')")
    @Log(title = "外协单导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException, IOException {
        bizOutsourcedOrder = bizOutsourcedOrderService.getById(bizOutsourcedOrder);
        BizOutsourcedOrderDetail bizOutsourcedOrderDetail = new BizOutsourcedOrderDetail();
        bizOutsourcedOrderDetail.setMasterId(bizOutsourcedOrder.getId());
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrderDetailService.getList(bizOutsourcedOrderDetail);
        bizOutsourcedOrder.setDetails(outsourcedOrderDetails);
        bizOutsourcedOrderService.exportTemplateProvinceAreaData(response, bizOutsourcedOrder);
    }

    @Log(title = "外协打印", businessType = BusinessType.EXPORT)
    @PostMapping("/printDetailPdf")
    public void SocialSecurityPdf(BizOutsourcedOrder bizOutsourcedOrder, HttpServletResponse response) throws IOException, TemplateException, freemarker.template.TemplateException {

        /** 按照产品进行区分 **/
        bizOutsourcedOrder = bizOutsourcedOrderService.getById(bizOutsourcedOrder);
        BizOutsourcedOrderDetail bizOutsourcedOrderDetail = new BizOutsourcedOrderDetail();
        bizOutsourcedOrderDetail.setMasterId(bizOutsourcedOrder.getId());
        SysUser user = userService.selectUserById(bizOutsourcedOrder.getCreatorId());
        if (user != null) {
            bizOutsourcedOrder.setNickName(user.getNickName());
        }

        //该发出单所有明细
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrderDetailService.getList(bizOutsourcedOrderDetail);
        //因为新箱子保存的时候，是用“id|code,id|code”的字符串形式存储的所以查询的时候需要进行拆分
        //如果保存的时候没有选择新箱子则会把旧箱号复制到新箱号中，所有不会有“|”所以下方需要进行判断
        outsourcedOrderDetails.forEach(detail -> {
            // 因为需要显示箱号，所以需要拆分出code重新拼接到NewCarrier
            List<String> codeList = new ArrayList<>();

            //使用 StringTokenizer 来分割字符串
            StringTokenizer tokenizer = new StringTokenizer(detail.getNewCarrier(), ",");
            while (tokenizer.hasMoreTokens()) {
                String token = tokenizer.nextToken();
                // 检查当前 token 是否包含 "|" 字符 如果没有表示不是新箱，则跳过当前 token
                if (token.contains("|")) {
                    String[] idCode = token.split("\\|"); // 安全地分割 token
                    if (idCode.length == 2) {
                        codeList.add(idCode[1]);
                        BizCarrier bizCarrier = new BizCarrier();
                        bizCarrier.setId(Long.parseLong(idCode[0]));
                        bizCarrier.setCode(idCode[1]);
                    }
                }
            }
            if (codeList.size() > 0) {
                detail.setNewCarrier(String.join(",", codeList));
            }

        });
        // 创建SimpleDateFormat对象，并设置日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        bizOutsourcedOrder.setStringDate(dateFormat.format(bizOutsourcedOrder.getFormDate()));

        // 使用 Stream API 按照 productDescription 属性进行分组，
        // 并将每个分组的元素收集到一个 List 中
        Map<String, List<BizOutsourcedOrderDetail>> groupedByProductDescription =
                outsourcedOrderDetails.stream()
                        .collect(Collectors.groupingBy(
                                BizOutsourcedOrderDetail::getProductDescription, // 分组依据的函数
                                Collectors.toList() // 指定分组内的元素收集为 List
                        ));

//        注释部分为按照炉号分组2024-9-26注释
//        List<List<BizOutsourcedOrderDetail>> groupedByFurnaceNumber = new ArrayList<>();
//        //将groupedByProductDescription数据再按照炉号FurnaceNumber再进行分组将最终的分组数据保存到groupedByFurnaceNumber中
//        for (Map.Entry<String, List<BizOutsourcedOrderDetail>> entry : groupedByProductDescription.entrySet()) {
//            List<BizOutsourcedOrderDetail> details = entry.getValue();
//            // 根据 furnaceNumber 分组
//            Map<String, List<BizOutsourcedOrderDetail>> groupedByFurnace = details.stream()
//                    .collect(Collectors.groupingBy(BizOutsourcedOrderDetail::getFurnaceNumber));
//
//            // 将分组后的结果添加到新的 List 中
//            groupedByFurnaceNumber.addAll(groupedByFurnace.values());
//        }

        List<List<BizOutsourcedOrderDetail>> list = new ArrayList<>();
        // 使用 for-each 循环遍历 groupedByProductDescription
        for ( Entry<String, List<BizOutsourcedOrderDetail>> entry : groupedByProductDescription.entrySet()) {
            List<BizOutsourcedOrderDetail> details = entry.getValue(); // 获取对应的 List，即 Map 的值
            // 用于临时存储每组数据的列表
            List<BizOutsourcedOrderDetail> group = new ArrayList<>();
            // 遍历 outsourcedOrderDetails 列表
            for (BizOutsourcedOrderDetail detail : details) {
                group.add(detail);
                // 每添加 14 个元素后，将其添加到 list 中，并重置 group
                if (group.size() == 14) {
                    list.add(new ArrayList<>(group));
                    group = new ArrayList<>();
                }
            }
            // 如果最后一组不足 14 个元素，也将其添加到 list 中
            if (!group.isEmpty()) {
                BizOutsourcedOrderDetail orderDetail = new BizOutsourcedOrderDetail();
                while (group.size() < 14) {
                    group.add(orderDetail); // 添加默认元素直到总数为14
                }
                list.add(group);
            }
        }
        for (List<BizOutsourcedOrderDetail> listItem : list) {
            // 使用流过滤出 productNum 不为空的元素，并对其 productNum 值求和
            Integer sum = listItem.stream()
                    .filter(item -> item.getProductNum() != null) // 过滤出 productNum 不为空的元素
                    .mapToInt(BizOutsourcedOrderDetail::getProductNum) // 映射到 productNum 属性
                    .sum(); // 计算总和
            // 然后，给每个对象的 sum 属性赋值
            for (BizOutsourcedOrderDetail item : listItem) {
                item.setSum(sum);
                item.setOriginalCarrierCount(item.getNewCarrierCount() != null && item.getNewCarrierCount() != 0 ? item.getNewCarrierCount() : item.getOriginalCarrierCount());
            }

        }

        bizOutsourcedOrder.setDetailLists(list);
        bizOutsourcedOrder.setQrcodeUrl2Src(baseUrl + bizOutsourcedOrder.getQrcodeUrl());
        bizOutsourcedOrder.setBarcodeUrl2Src(baseUrl + bizOutsourcedOrder.getBarcodeUrl());

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("outsourcedOrder", bizOutsourcedOrder);
        Writer out = new StringWriter();
        //获取模板地址
        Template template = freeMarkerConfigurer.getConfiguration().getTemplate("outSourcedProductPdf.html");
        template.process(paramMap, out);
        out.flush();
        out.close();
        String templateContent = out.toString();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/pdf");
        String fileName = "外协发出明细";
        response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes()));
        byte[] resources = PdfUtil.html2Pdf(templateContent);
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(resources);
        outputStream.close();
    }

    @GetMapping("/innerList")
    @Log(title = "查询内部外协单", businessType = BusinessType.SELECT)
    public TableDataInfo innerList(BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(bizOutsourcedOrder);
        startPage();
        List<BizOutsourcedOrder> list = bizOutsourcedOrderService.getInnerList(bizOutsourcedOrder);
        return getDataTable(list);
    }

//    @Log(title = "外协打印", businessType = BusinessType.EXPORT)
//    @PostMapping("/printDetailPdf")
//    public void SocialSecurityPdf(BizOutsourcedOrder bizOutsourcedOrder, HttpServletResponse response) throws IOException, TemplateException, freemarker.template.TemplateException {
//
//        /** 正常打印 **/
//        bizOutsourcedOrder = bizOutsourcedOrderService.getById(bizOutsourcedOrder);
//        BizOutsourcedOrderDetail bizOutsourcedOrderDetail = new BizOutsourcedOrderDetail();
//        bizOutsourcedOrderDetail.setMasterId(bizOutsourcedOrder.getId());
//        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrderDetailService.getList(bizOutsourcedOrderDetail);
//        // 创建SimpleDateFormat对象，并设置日期格式
//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//        bizOutsourcedOrder.setStringDate(dateFormat.format(bizOutsourcedOrder.getFormDate()));
//
//        List<List<BizOutsourcedOrderDetail> > list = new ArrayList<>();
//

//        //打印数据时每页14条
//        if(outsourcedOrderDetails.size() > 14){
//            // 用于临时存储每组数据的列表
//            List<BizOutsourcedOrderDetail> group = new ArrayList<>();
//            // 遍历 outsourcedOrderDetails 列表
//            for (BizOutsourcedOrderDetail detail : outsourcedOrderDetails) {
//                group.add(detail);
//                // 每添加 14 个元素后，将其添加到 list 中，并重置 group
//                if (group.size() == 14) {
//                    // 使用流过滤出 productNum 不为空的元素，并对其 productNum 值求和
//                    Integer sum = group.stream()
//                            .filter(item -> item.getProductNum() != null) // 过滤出 productNum 不为空的元素
//                            .mapToInt(BizOutsourcedOrderDetail::getProductNum) // 映射到 productNum 属性
//                            .sum(); // 计算总和
//                    // 然后，给每个对象的 sum 属性赋值
//                    for (BizOutsourcedOrderDetail item : group) {
//                        item.setSum(sum);
//                        item.setOriginalCarrierCount(item.getNewCarrierCount()==null?item.getOriginalCarrierCount():item.getNewCarrierCount());
//                    }
//                    list.add(new ArrayList<>(group));
//                    group = new ArrayList<>();
//                }
//            }
//            // 如果最后一组不足 14 个元素，也将其添加到 list 中
//            if (!group.isEmpty()) {
//                BizOutsourcedOrderDetail orderDetail=new BizOutsourcedOrderDetail();
//                while (group.size() < 14) {
//                    group.add(orderDetail); // 添加默认元素直到总数为14
//                }
//                list.add(group);
//            }
//        }else{
//            BizOutsourcedOrderDetail orderDetail=new BizOutsourcedOrderDetail();
//            while (outsourcedOrderDetails.size() < 14) {
//                outsourcedOrderDetails.add(orderDetail); // 添加默认元素直到总数为14
//            }
//            // 使用流过滤出 productNum 不为空的元素，并对其 productNum 值求和
//            Integer sum = outsourcedOrderDetails.stream()
//                    .filter(detail -> detail.getProductNum() != null) // 过滤出 productNum 不为空的元素
//                    .mapToInt(BizOutsourcedOrderDetail::getProductNum) // 映射到 productNum 属性
//                    .sum(); // 计算总和
//            // 然后，给每个对象的 sum 属性赋值
//            for (BizOutsourcedOrderDetail detail : outsourcedOrderDetails) {
//                detail.setSum(sum);
//                detail.setOriginalCarrierCount(detail.getNewCarrierCount()==null?detail.getOriginalCarrierCount():detail.getNewCarrierCount());
//            }
//
//            list.add(outsourcedOrderDetails);
//        }
//        bizOutsourcedOrder.setDetailLists(list);
//
//
//        Map<String, Object> paramMap = new HashMap<>();
//        paramMap.put("outsourcedOrder" , bizOutsourcedOrder);
//        Writer out = new StringWriter();
//        //获取模板地址
//        Template template = freeMarkerConfigurer.getConfiguration().getTemplate("outSourcedPdf.html");
//        template.process(paramMap, out);
//        out.flush();
//        out.close();
//        String templateContent = out.toString();
//        response.setCharacterEncoding("UTF-8");
//        response.setContentType("application/pdf");
//        String fileName ="外协发出明细";
//        response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes()));
//        byte[] resources = PdfUtil.html2Pdf(templateContent);
//        ServletOutputStream outputStream = response.getOutputStream();
//        outputStream.write(resources);
//        outputStream.close();
//    }
//

    /**
     * 获取外协单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子详细信息
     */
//    @PreAuthorize("@ss.hasPermi('business:outsource:query')")
    @GetMapping(value = "/{id}")
    @Log(title = "查询外协单详情", businessType = BusinessType.SELECT)
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        BizOutsourcedOrder bizOutsourcedOrder = bizOutsourcedOrderService.getById(id);
        BizOutsourcedOrderDetail bizOutsourcedOrderDetail = new BizOutsourcedOrderDetail();
        bizOutsourcedOrderDetail.setMasterId(id);
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrderDetailService.getList(bizOutsourcedOrderDetail);
        //因为新箱子保存的时候，是用“id|code,id|code”的字符串形式存储的所以查询的时候需要进行拆分
        //如果保存的时候没有选择新箱子则会把旧箱号复制到新箱号中，所有不会有“|”所以下方需要进行判断
        outsourcedOrderDetails.forEach(detail -> {
            // 将字符串拆分转为对象
            List<BizCarrier> carriers = new ArrayList<>();
            // 因为需要显示箱号，所以需要拆分出code重新拼接到NewCarrier
            List<String> codeList = new ArrayList<>();
            // 为了减少前段的逻辑，所以需要先将拆分后的id也拼接起来
            List<Long> carrierIds = new ArrayList<>();

            //使用 StringTokenizer 来分割字符串
            StringTokenizer tokenizer = new StringTokenizer(detail.getNewCarrier(), ",");
            while (tokenizer.hasMoreTokens()) {
                String token = tokenizer.nextToken();
                // 检查当前 token 是否包含 "|" 字符 如果没有表示不是新箱，则跳过当前 token
                if (token.contains("|")) {
                    String[] idCode = token.split("\\|"); // 安全地分割 token
                    if (idCode.length == 2) {
                        codeList.add(idCode[1]);
                        carrierIds.add(Long.parseLong(idCode[0]));
                        BizCarrier bizCarrier = new BizCarrier();
                        bizCarrier.setId(Long.parseLong(idCode[0]));
                        bizCarrier.setCode(idCode[1]);
                        carriers.add(bizCarrier);
                    }
                }
            }
            detail.setNewCarriers(carriers);
            detail.setCarrierIds(carrierIds);
            if (codeList.size() > 0) {
                detail.setNewCarrier(String.join(",", codeList));
            }

        });
        bizOutsourcedOrder.setDetails(outsourcedOrderDetails);
        return success(bizOutsourcedOrder);
    }
    @GetMapping(value = "/getInnerOrder")
    @Log(title = "查询内部外协单详情", businessType = BusinessType.SELECT)
    public AjaxResult getInnerOrder(BizOutsourcedOrder outsourcedOrder) {
        BizOutsourcedOrder bizOutsourcedOrder = bizOutsourcedOrderService.getInnerById(outsourcedOrder);
        BizOutsourcedOrderDetail bizOutsourcedOrderDetail = new BizOutsourcedOrderDetail();
        bizOutsourcedOrderDetail.setMasterId(outsourcedOrder.getId());
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrderDetailService.getInnerList(bizOutsourcedOrderDetail);
        //因为新箱子保存的时候，是用“id|code,id|code”的字符串形式存储的所以查询的时候需要进行拆分
        //如果保存的时候没有选择新箱子则会把旧箱号复制到新箱号中，所有不会有“|”所以下方需要进行判断
        outsourcedOrderDetails.forEach(detail -> {
            // 将字符串拆分转为对象
            List<BizCarrier> carriers = new ArrayList<>();
            // 因为需要显示箱号，所以需要拆分出code重新拼接到NewCarrier
            List<String> codeList = new ArrayList<>();
            // 为了减少前段的逻辑，所以需要先将拆分后的id也拼接起来
            List<Long> carrierIds = new ArrayList<>();

            //使用 StringTokenizer 来分割字符串
            StringTokenizer tokenizer = new StringTokenizer(detail.getNewCarrier(), ",");
            while (tokenizer.hasMoreTokens()) {
                String token = tokenizer.nextToken();
                // 检查当前 token 是否包含 "|" 字符 如果没有表示不是新箱，则跳过当前 token
                if (token.contains("|")) {
                    String[] idCode = token.split("\\|"); // 安全地分割 token
                    if (idCode.length == 2) {
                        codeList.add(idCode[1]);
                        carrierIds.add(Long.parseLong(idCode[0]));
                        BizCarrier bizCarrier = new BizCarrier();
                        bizCarrier.setId(Long.parseLong(idCode[0]));
                        bizCarrier.setCode(idCode[1]);
                        carriers.add(bizCarrier);
                    }
                }
            }
            detail.setNewCarriers(carriers);
            detail.setCarrierIds(carrierIds);
            if (codeList.size() > 0) {
                detail.setNewCarrier(String.join(",", codeList));
            }

        });
        bizOutsourcedOrder.setDetails(outsourcedOrderDetails);
        return success(bizOutsourcedOrder);
    }

    @GetMapping(value = "/getFirst/{id}")
    @Log(title = "查询首序外协详情", businessType = BusinessType.SELECT)
    public AjaxResult getFirstInfo(@PathVariable("id") Long id) {
        BizOutsourcedOrder bizOutsourcedOrder = bizOutsourcedOrderService.getById(id);
        BizOutsourcedOrderDetail bizOutsourcedOrderDetail = new BizOutsourcedOrderDetail();
        bizOutsourcedOrderDetail.setMasterId(id);
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrderDetailService.getList(bizOutsourcedOrderDetail);
        List<BizFurnaceNoInfo> furnaceNoInfos = furnaceNoInfoService.query().in("daywork_id", outsourcedOrderDetails.isEmpty() ? Collections.singletonList(0L) : outsourcedOrderDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList())).list();

        //因为新箱子保存的时候，是用“id|code,id|code”的字符串形式存储的所以查询的时候需要进行拆分
        //如果保存的时候没有选择新箱子则会把旧箱号复制到新箱号中，所有不会有“|”所以下方需要进行判断
        outsourcedOrderDetails.forEach(detail -> {
            // 将字符串拆分转为对象
            List<BizCarrier> carriers = new ArrayList<>();
            // 因为需要显示箱号，所以需要拆分出code重新拼接到NewCarrier
            List<String> codeList = new ArrayList<>();
            // 为了减少前段的逻辑，所以需要先将拆分后的id也拼接起来
            List<Long> carrierIds = new ArrayList<>();
            BizFurnaceNoInfo furnaceNoInfo = furnaceNoInfos.stream().filter(v -> detail.getDayworkId().equals(v.getDayworkId())).findFirst().orElse(null);
            detail.setFurnaceNoInfo(furnaceNoInfo);
            //使用 StringTokenizer 来分割字符串
            StringTokenizer tokenizer = new StringTokenizer(detail.getNewCarrier(), ",");
            while (tokenizer.hasMoreTokens()) {
                String token = tokenizer.nextToken();
                // 检查当前 token 是否包含 "|" 字符 如果没有表示不是新箱，则跳过当前 token
                if (token.contains("|")) {
                    String[] idCode = token.split("\\|"); // 安全地分割 token
                    if (idCode.length == 2) {
                        codeList.add(idCode[1]);
                        carrierIds.add(Long.parseLong(idCode[0]));
                        BizCarrier bizCarrier = new BizCarrier();
                        bizCarrier.setId(Long.parseLong(idCode[0]));
                        bizCarrier.setCode(idCode[1]);
                        carriers.add(bizCarrier);
                    }
                }
            }
            detail.setNewCarriers(carriers);
            detail.setCarrierIds(carrierIds);
//            if (codeList.size() > 0) {
//                detail.setNewCarrier(String.join(",", codeList));
//            }

        });
        bizOutsourcedOrder.setDetails(outsourcedOrderDetails);
        return success(bizOutsourcedOrder);
    }

    //    @PreAuthorize("@ss.hasPermi('business:outsource:query')")
    @PostMapping(value = "/carrierForOutsource")
    @Log(title = "获取外协箱列表", businessType = BusinessType.SELECT)
    public TableDataInfo carrierForOutsource(@RequestBody BizCarrier carrier) {
        if(carrier.getHasAddCarrierIds() != null && carrier.getHasAddCarrierIds().size() > 0){
            List<BizCarrier> notMoreCarrier = bizCarrierService.getNotMoreCarrier(carrier.getHasAddCarrierIds());
            if(!notMoreCarrier.isEmpty()){
                carrier.setHasAddCarrierIds(notMoreCarrier.stream().map(BizCarrier::getId).collect(Collectors.toList()));
            }
        }
        carrier.setNotInUse(1);
        carrier.setIsAllowMore(0);
        List<BizCarrier> list = bizCarrierService.getListFromOutsource(carrier);
        return getDataTable(list);
    }


    /**
     * 新增外协单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
//    @PreAuthorize("@ss.hasPermi('business:outsource:add')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @Transactional
    public AjaxResult add(@RequestBody BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(bizOutsourcedOrder);

        //若有id，则说将之前的明细删除不生成新的单号
        if (bizOutsourcedOrder.getId() != null) {
            List<Long> ids = new ArrayList<>();
            ids.add(bizOutsourcedOrder.getId());
            //先将之前的明细删除
            bizOutsourcedOrderDetailService.removeByMasterIds(ids);
            bizOutsourcedOrderDetailProcessService.removeByMasterIds(ids);
        } else {
            /* 生成单号 */
            SimpleDateFormat dateFormat = new SimpleDateFormat("yy"); // 定义日期格式
            String formattedDate = dateFormat.format(new Date());
            String codeValue;
            String codeType = "outsourcedOrderCode";
            //查询redis中外协单号的值
            String previous = redisCache.hasKey(codeType) ? redisCache.getCacheObject(codeType) : "";
            //若不存在，则直接存入
            if (previous.isEmpty()) {
                //如果没有数据再去数据库中查询该类型的流水号是否存在，如果存在找到最新一条，
                // 在最新一条基础上进行继续追加并存到redias中，如果数据库中也没有该类型的流水号再从00001开始
                List<BizOutsourcedOrder> outsourcedOrderDetailList = bizOutsourcedOrderService.getAllList();
                if(!outsourcedOrderDetailList.isEmpty()){
                    codeValue = outsourcedOrderDetailList.get(0).getFormCode();
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                }else{
                    previous = ("WFD" + formattedDate + "00001");
                }
            } else {
                codeValue = previous;
                String codeYear=codeValue.substring(3, 5);//取出当前外协单号年份
                //如果年份一致表示是当前年的发出单，如果不一致则表示已经进入了新的一年则重置发出单号
                if(codeYear.equals(formattedDate)){
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                }else{
                    previous = ("WFD" + formattedDate + "00001");
                }
            }
            //存到redis中
            redisCache.setCacheObject(codeType, previous);
            bizOutsourcedOrder.setFormCode(previous);
            bizOutsourcedOrder = generateQrCodeImg(bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder);
            bizOutsourcedOrder = generateBarCodeImg(bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder);
        }
        //新增明细信息
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrder.getDetails();

        bizOutsourcedOrderService.saveOrUpdate(bizOutsourcedOrder);


        outsourcedOrderDetails.forEach(detail -> {
            if (detail.getNewCarriers().size() > 0) {
                /**
                 * 因为是暂存，暂存的时候不解绑原先的箱子，所以在暂存的时候需要保存新箱号的id和code所以用新箱号id和code用‘|’分割每组用逗号分割
                 * 取出来的时候再进行拆分
                 */
                //这一步将绑定的新箱子以“id|code”一组，以英文“,”分割(例：1|A,2|B,3|C)
                String formattedString = detail.getNewCarriers().stream()
                        .map(item -> item.getId() + "|" + item.getCode())
                        .collect(Collectors.joining(","));
                //赋值给新箱号
                detail.setNewCarrier(formattedString);
            } else {
                detail.setNewCarrier("");
            }
        });
        outsourcedOrderDetails = bizOutsourcedOrderDetailService.batchSave(outsourcedOrderDetails, bizOutsourcedOrder);
        return success(bizOutsourcedOrderDetailProcessService.batchSave(outsourcedOrderDetails));
    }

    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.INSERT)
    @PostMapping("/submitDetails")
    @Transactional
    public AjaxResult submitDetails(@RequestBody BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException {
        String tenantId = request.getHeader("tenantId");
        bizOutsourcedOrder.setTenantId(Long.valueOf(tenantId));
        Boolean isFirst = true;
        //若有id，则说将之前的明细删除不生成新的单号
        if (bizOutsourcedOrder.getId() != null) {
            isFirst = false;
            List<Long> ids = new ArrayList<>();
            ids.add(bizOutsourcedOrder.getId());
//            //删除dayworkItem表
//            List<Long> detailIds = bizOutsourcedOrderDetailService.query().eq("master_id", bizOutsourcedOrder.getId()).list().stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList());
//            List<BizDayworkItem> oldItems = bizDayworkItemService.selectItemByOutsourcedDetailIds(detailIds);
//            bizDayworkItemService.removeBatchByIds(oldItems);
        } else {
            /* 生成单号 */
            SimpleDateFormat dateFormat = new SimpleDateFormat("yy"); // 定义日期格式
            String formattedDate = dateFormat.format(new Date());
            String codeValue;
            String codeType = "outsourcedOrderCode";
            //查询redis中外协单号的值
            String previous = redisCache.hasKey(codeType) ? redisCache.getCacheObject(codeType) : "";
            //若不存在，则直接存入
            if (previous.isEmpty()) {
                //如果没有数据再去数据库中查询该类型的流水号是否存在，如果存在找到最新一条，
                // 在最新一条基础上进行继续追加并存到redias中，如果数据库中也没有该类型的流水号再从00001开始
                List<BizOutsourcedOrder> outsourcedOrderDetailList = bizOutsourcedOrderService.getAllList();
                if(!outsourcedOrderDetailList.isEmpty()){
                    codeValue = outsourcedOrderDetailList.get(0).getFormCode();
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                }else{
                    previous = ("WFD" + formattedDate + "00001");
                }
            } else {
                codeValue = previous;
                String codeYear=codeValue.substring(3, 5);//取出当前外协单号年份
                //如果年份一致表示是当前年的发出单，如果不一致则表示已经进入了新的一年则重置发出单号
                if(codeYear.equals(formattedDate)){
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                }else{
                    previous = ("WFD" + formattedDate + "00001");
                }
            }
            //存到redis中
            redisCache.setCacheObject(codeType, previous);
            bizOutsourcedOrder.setFormCode(previous);
            generateQrCodeImg(bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder);
            generateBarCodeImg(bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder);
        }
        bizOutsourcedOrder.setIsSubmit(1);
        //新增明细信息
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrder.getDetails();
        //绑定的新箱子集合
        List<BizDayworkCarrier> carrierList = new ArrayList<>();
        List<String> originalCarrierCodeList = outsourcedOrderDetails.stream()
                .map(item -> Arrays.asList(item.getOriginalCarrier().split(","))) // 将每个元素的字符串拆分并封装为List
                .flatMap(List::stream) // 将所有拆分后的字符串扁平化为一个流
                .collect(Collectors.toList());
        List<Long> orginalDayworkIds = outsourcedOrderDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList());
        List<BizDayworkCarrier> orignalCarrierList = iBizDayworkCarrierService.query().eq("is_changed", 0).in("carrier_code", originalCarrierCodeList).in("daywork_id", orginalDayworkIds).list();

        //绑定新箱子
        outsourcedOrderDetails.forEach(detail -> {
            detail.setSettlementType(bizOutsourcedOrder.getSettlementType());
            detail.setPackagingMethod(bizOutsourcedOrder.getPackagingMethod());
            detail.setDeliveryMethod(bizOutsourcedOrder.getDeliveryMethod());
            /**
             * 与暂存逻辑类似，但因为是彻底保存提交了，所以需要解绑原先的箱子，并且在没有新箱子时，需要将原先箱号复制到新箱号中
             */
            if (detail.getNewCarriers().size() > 0) {
                //这一步将绑定的新箱子以“id|code”一组，以英文“,”分割(例：1|A,2|B,3|C)
                String formattedString = detail.getNewCarriers().stream()
                        .map(item -> item.getId() + "|" + item.getCode())
                        .collect(Collectors.joining(","));
                //赋值给新箱号
                detail.setNewCarrierName(detail.getNewCarriers().stream().map(BizCarrier::getCode)
                        .collect(Collectors.joining(",")));
                detail.setNewCarrier(formattedString);

                //将新箱号绑定至dayworkId
                detail.getNewCarriers().forEach(carrier -> {
                    BizDayworkCarrier bizDayworkCarrier = new BizDayworkCarrier();
                    bizDayworkCarrier.setCarrierId(carrier.getId());
                    bizDayworkCarrier.setCarrierCode(carrier.getCode());
                    bizDayworkCarrier.setDayworkId(detail.getDayworkId());
                    bizDayworkCarrier.setLotId(detail.getLotId());
                    carrierList.add(bizDayworkCarrier);
                });
            } else {
                //将原箱号复制到新新箱号
                //如果没点换箱，用的原箱，也要像新箱那种方式存，为了拿到newCarriers
                List<String> detailOriginalCarriers = Arrays.stream(detail.getOriginalCarrier().split(",")).collect(Collectors.toList());
                List<BizCarrier> orignialCarries = new ArrayList<>();
                for (int i = 0; i < detailOriginalCarriers.size(); i++) {
                    for (int j = 0; j < orignalCarrierList.size(); j++) {
                        if (detailOriginalCarriers.get(i).equals(orignalCarrierList.get(j).getCarrierCode())) {
                            BizCarrier bizCarrier = new BizCarrier();
                            bizCarrier.setCode(orignalCarrierList.get(j).getCarrierCode());
                            bizCarrier.setId(orignalCarrierList.get(j).getCarrierId());
                            orignialCarries.add(bizCarrier);
                        }
                    }
                }
                String formattedString = orignialCarries.stream()
                        .map(item -> item.getId() + "|" + item.getCode())
                        .distinct().collect(Collectors.joining(","));
                detail.setNewCarrier(formattedString);
                detail.setNewCarrierName(orignialCarries.stream()
                        .map(BizCarrier::getCode)
                        .distinct().collect(Collectors.joining(",")));
                // detail.setNewCarrier(detail.getOriginalCarrier());
            }
        });
        List<BizOutsourcedRecords> outsourcedRecordsList = new ArrayList<>();
        Date now = new Date();
        // 创建一个 SimpleDateFormat 对象，并设置所需的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 格式化 Date 对象
        String formattedDate = dateFormat.format(now);
        // 创建一个 SimpleDateFormat 对象，并设置所需的日期格式
        //保存修改记录
        outsourcedOrderDetails.forEach(detail -> {
            BizOutsourcedRecords saveRecords = new BizOutsourcedRecords();
            saveRecords.setUserName(SecurityUtils.getLoginUser().getUser().getUserName());
            saveRecords.setNickName(SecurityUtils.getLoginUser().getUser().getNickName());
            if (bizOutsourcedOrder.getId() == null) {
                saveRecords.setMethod("创建");
            } else {
                saveRecords.setMethod("修改");
            }
            saveRecords.setFormCode(bizOutsourcedOrder.getFormCode());
            saveRecords.setSupplierId(bizOutsourcedOrder.getSupplierId());
            saveRecords.setSupplierName(bizOutsourcedOrder.getSupplierName());
            saveRecords.setLotId(detail.getLotId());
            saveRecords.setLotCode(detail.getLotCode());
            saveRecords.setProductDescription(detail.getProductDescription());
            saveRecords.setProductNum(detail.getProductNum());
            if (detail.getNewCarriers().size() > 0) {
                saveRecords.setNewCarrier(detail.getNewCarriers().stream()
                        .map(BizCarrier::getCode)
                        .collect(Collectors.joining(",")));
            } else {
                saveRecords.setNewCarrier(detail.getOriginalCarrier());
            }
            saveRecords.setProcessNames(detail.getProcessNames());
            saveRecords.setStartTime(new Date());
            outsourcedRecordsList.add(saveRecords);
        });
        //修改主表信息
        bizOutsourcedOrderService.saveOrUpdate(bizOutsourcedOrder);
        outsourcedRecordsList.forEach(item -> {
            item.setMasterId(bizOutsourcedOrder.getId());
        });
        bizOutsourcedRecordsService.saveBatch(outsourcedRecordsList);


        //判断是否使用新箱子
        //根据 detail.getNewCarriers()判断是否绑定了新箱子，如果有数据表示绑定新箱子,找出对应的dayworkId，解绑对应的箱子
        List<Long> dayworkIds = outsourcedOrderDetails.stream().filter(detail -> detail.getNewCarriers().size() > 0).map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList());
        if (dayworkIds.size() > 0) {
            //解绑箱，不包括外协箱
            int i = iBizDayworkCarrierService.changedCarrierStatus(dayworkIds);
        }

        iBizDayworkCarrierService.saveBatch(carrierList);
        outsourcedOrderDetails = bizOutsourcedOrderDetailService.updateOrSave(outsourcedOrderDetails, bizOutsourcedOrder);
        List<BizOutsourcedOrderDetail> oldDetailList = bizOutsourcedOrderDetailService.query().eq("master_id", bizOutsourcedOrder.getId()).list();
        //删除或修改收回明细(通过工序判断，如果工序变了，如果已经填写了收回单，则删除收回单该批次的明细，如果只是修改了箱号，则编辑回收单该批次的明细)
        bizReturnReceiptDetailService.removeOrEditDetails(outsourcedOrderDetails, oldDetailList);
        //修改外协明细表
        saveOrUpdateBatch(bizOutsourcedOrderDetailService,outsourcedOrderDetails,oldDetailList);
        //新建发出单时，对dayworkItem保存
        if(isFirst) {
            bizDayworkItemService.saveDayworkItemForOutsource(outsourcedOrderDetails);
        }else{
            //对发出单进行编辑，则需要判断
            bizDayworkItemService.updateDayworkItemForOutsource(outsourcedOrderDetails,oldDetailList);
        }
        List<String> formCodeList = outsourcedOrderDetails.stream().map(BizOutsourcedOrderDetail::getFormCode).collect(Collectors.toList());
        List<BizOutsourcedOrderDetail> newDetaillist = bizOutsourcedOrderDetailService.query().in("form_code", formCodeList).list();
        for (int i = 0; i < newDetaillist.size(); i++) {
            for (int j = 0; j < outsourcedOrderDetails.size(); j++) {
                if (newDetaillist.get(i).getLotId().equals(outsourcedOrderDetails.get(j).getLotId())) {
                    newDetaillist.get(i).setProcesses(outsourcedOrderDetails.get(j).getProcesses());
                    newDetaillist.get(i).setPackagingMethod(bizOutsourcedOrder.getPackagingMethod());
                }
            }
        }
        //操作外协发出工序表
        bizOutsourcedOrderDetailProcessService.updateOrSave(newDetaillist);
        return success();
    }
    @Log(title = "内部外协发出单", businessType = BusinessType.INSERT)
    @PostMapping("/submitInnerDetails")
    @Transactional
    public AjaxResult submitInnerDetails(@RequestBody BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException {
        bizOutsourcedOrder.setTenantId(getTenantId());
        Boolean isFirst = true;
        //若有id，则说将之前的明细删除不生成新的单号
        if (bizOutsourcedOrder.getId() != null) {
            isFirst = false;
            List<Long> ids = new ArrayList<>();
            ids.add(bizOutsourcedOrder.getId());
//            //删除dayworkItem表
//            List<Long> detailIds = bizOutsourcedOrderDetailService.query().eq("master_id", bizOutsourcedOrder.getId()).list().stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList());
//            List<BizDayworkItem> oldItems = bizDayworkItemService.selectItemByOutsourcedDetailIds(detailIds);
//            bizDayworkItemService.removeBatchByIds(oldItems);
        } else {
            /* 生成单号 */
            SimpleDateFormat dateFormat = new SimpleDateFormat("yy"); // 定义日期格式
            String formattedDate = dateFormat.format(new Date());
            String codeValue;
            String codeType = "outsourcedOrderCode";
            //查询redis中外协单号的值
            String previous = redisCache.hasKey(codeType) ? redisCache.getCacheObject(codeType) : "";
            //若不存在，则直接存入
            if (previous.isEmpty()) {
                //如果没有数据再去数据库中查询该类型的流水号是否存在，如果存在找到最新一条，
                // 在最新一条基础上进行继续追加并存到redias中，如果数据库中也没有该类型的流水号再从00001开始
                List<BizOutsourcedOrder> outsourcedOrderDetailList = bizOutsourcedOrderService.getAllList();
                if(!outsourcedOrderDetailList.isEmpty()){
                    codeValue = outsourcedOrderDetailList.get(0).getFormCode();
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                }else{
                    previous = ("WFD" + formattedDate + "00001");
                }
            } else {
                codeValue = previous;
                int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                lastFourDigits += 1; // 加1
                codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                previous = codeValue;
            }
            //存到redis中
            redisCache.setCacheObject(codeType, previous);
            bizOutsourcedOrder.setFormCode(previous);
            generateQrCodeImg(bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder);
            generateBarCodeImg(bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder);
        }
        bizOutsourcedOrder.setIsSubmit(1);
        //新增明细信息
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrder.getDetails();
        //绑定的新箱子集合
        List<BizDayworkCarrier> carrierList = new ArrayList<>();
        List<String> originalCarrierCodeList = outsourcedOrderDetails.stream()
                .map(item -> Arrays.asList(item.getOriginalCarrier().split(","))) // 将每个元素的字符串拆分并封装为List
                .flatMap(List::stream) // 将所有拆分后的字符串扁平化为一个流
                .collect(Collectors.toList());
        List<Long> orginalDayworkIds = outsourcedOrderDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList());
        List<BizDayworkCarrier> orignalCarrierList = iBizDayworkCarrierService.query().eq("is_changed", 0).in("carrier_code", originalCarrierCodeList).in("daywork_id", orginalDayworkIds).list();

        //绑定新箱子
        outsourcedOrderDetails.forEach(detail -> {
            detail.setSettlementType(bizOutsourcedOrder.getSettlementType());
            detail.setPackagingMethod(bizOutsourcedOrder.getPackagingMethod());
            detail.setDeliveryMethod(bizOutsourcedOrder.getDeliveryMethod());
            /**
             * 与暂存逻辑类似，但因为是彻底保存提交了，所以需要解绑原先的箱子，并且在没有新箱子时，需要将原先箱号复制到新箱号中
             */
            if (detail.getNewCarriers().size() > 0) {
                //这一步将绑定的新箱子以“id|code”一组，以英文“,”分割(例：1|A,2|B,3|C)
                String formattedString = detail.getNewCarriers().stream()
                        .map(item -> item.getId() + "|" + item.getCode())
                        .collect(Collectors.joining(","));
                //赋值给新箱号
                detail.setNewCarrierName(detail.getNewCarriers().stream().map(BizCarrier::getCode)
                        .collect(Collectors.joining(",")));
                detail.setNewCarrier(formattedString);

                //将新箱号绑定至dayworkId
                detail.getNewCarriers().forEach(carrier -> {
                    BizDayworkCarrier bizDayworkCarrier = new BizDayworkCarrier();
                    bizDayworkCarrier.setCarrierId(carrier.getId());
                    bizDayworkCarrier.setCarrierCode(carrier.getCode());
                    bizDayworkCarrier.setDayworkId(detail.getDayworkId());
                    bizDayworkCarrier.setLotId(detail.getLotId());
                    carrierList.add(bizDayworkCarrier);
                });
            } else {
                //将原箱号复制到新新箱号
                //如果没点换箱，用的原箱，也要像新箱那种方式存，为了拿到newCarriers
                List<String> detailOriginalCarriers = Arrays.stream(detail.getOriginalCarrier().split(",")).collect(Collectors.toList());
                List<BizCarrier> orignialCarries = new ArrayList<>();
                for (int i = 0; i < detailOriginalCarriers.size(); i++) {
                    for (int j = 0; j < orignalCarrierList.size(); j++) {
                        if (detailOriginalCarriers.get(i).equals(orignalCarrierList.get(j).getCarrierCode())) {
                            BizCarrier bizCarrier = new BizCarrier();
                            bizCarrier.setCode(orignalCarrierList.get(j).getCarrierCode());
                            bizCarrier.setId(orignalCarrierList.get(j).getCarrierId());
                            orignialCarries.add(bizCarrier);
                        }
                    }
                }
                String formattedString = orignialCarries.stream()
                        .map(item -> item.getId() + "|" + item.getCode())
                        .distinct().collect(Collectors.joining(","));
                detail.setNewCarrier(formattedString);
                detail.setNewCarrierName(orignialCarries.stream()
                        .map(BizCarrier::getCode)
                        .distinct().collect(Collectors.joining(",")));
                // detail.setNewCarrier(detail.getOriginalCarrier());
            }
        });
        List<BizOutsourcedRecords> outsourcedRecordsList = new ArrayList<>();
        Date now = new Date();
        // 创建一个 SimpleDateFormat 对象，并设置所需的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 格式化 Date 对象
        String formattedDate = dateFormat.format(now);
        // 创建一个 SimpleDateFormat 对象，并设置所需的日期格式
        //保存修改记录
        outsourcedOrderDetails.forEach(detail -> {
            BizOutsourcedRecords saveRecords = new BizOutsourcedRecords();
            saveRecords.setUserName(SecurityUtils.getLoginUser().getUser().getUserName());
            saveRecords.setNickName(SecurityUtils.getLoginUser().getUser().getNickName());
            if (bizOutsourcedOrder.getId() == null) {
                saveRecords.setMethod("创建");
            } else {
                saveRecords.setMethod("修改");
            }
            saveRecords.setFormCode(bizOutsourcedOrder.getFormCode());
            saveRecords.setSupplierId(bizOutsourcedOrder.getSupplierId());
            saveRecords.setSupplierName(bizOutsourcedOrder.getSupplierName());
            saveRecords.setLotId(detail.getLotId());
            saveRecords.setLotCode(detail.getLotCode());
            saveRecords.setProductDescription(detail.getProductDescription());
            saveRecords.setProductNum(detail.getProductNum());
            if (detail.getNewCarriers().size() > 0) {
                saveRecords.setNewCarrier(detail.getNewCarriers().stream()
                        .map(BizCarrier::getCode)
                        .collect(Collectors.joining(",")));
            } else {
                saveRecords.setNewCarrier(detail.getOriginalCarrier());
            }
            saveRecords.setProcessNames(detail.getProcessNames());
            saveRecords.setIsPackage(detail.getIsPackage());
            saveRecords.setStartTime(new Date());
            outsourcedRecordsList.add(saveRecords);
        });
        //修改主表信息
        bizOutsourcedOrderService.saveOrUpdate(bizOutsourcedOrder);
        outsourcedRecordsList.forEach(item -> {
            item.setMasterId(bizOutsourcedOrder.getId());
        });
        bizOutsourcedRecordsService.saveBatch(outsourcedRecordsList);


        //判断是否使用新箱子
        //根据 detail.getNewCarriers()判断是否绑定了新箱子，如果有数据表示绑定新箱子,找出对应的dayworkId，解绑对应的箱子
        List<Long> dayworkIds = outsourcedOrderDetails.stream().filter(detail -> detail.getNewCarriers().size() > 0).map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList());
        if (dayworkIds.size() > 0) {
            //解绑箱，不包括外协箱
            int i = iBizDayworkCarrierService.changedCarrierStatus(dayworkIds);
        }

        iBizDayworkCarrierService.saveBatch(carrierList);
        //下序是否签票
        bizDayworkItemExamineService.updateOrSave(outsourcedOrderDetails, bizOutsourcedOrder);
        outsourcedOrderDetails = bizOutsourcedOrderDetailService.updateOrSave(outsourcedOrderDetails, bizOutsourcedOrder);
        List<BizOutsourcedOrderDetail> oldDetailList = bizOutsourcedOrderDetailService.query().eq("master_id", bizOutsourcedOrder.getId()).list();
        //删除或修改收回明细(通过工序判断，如果工序变了，如果已经填写了收回单，则删除收回单该批次的明细，如果只是修改了箱号，则编辑回收单该批次的明细)
        bizReturnReceiptDetailService.removeOrEditDetails(outsourcedOrderDetails, oldDetailList);
        //修改外协明细表
        saveOrUpdateBatch(bizOutsourcedOrderDetailService,outsourcedOrderDetails,oldDetailList);
        //新建发出单时，对dayworkItem保存
        if(isFirst) {
            List<BizDaywork> dayworkList =bizDayworkItemService.saveDayworkItemForInnerOutsource(outsourcedOrderDetails,bizOutsourcedOrder);
            if(dayworkList.size()>0){
                //修改报工工段及下序投产数
                bizDayworkService.updateBatchById(dayworkList);
            }
        }else{
            //对发出单进行编辑，则需要判断
           List<BizDaywork> dayworkList = bizDayworkItemService.updateDayworkItemForInnerOutsource(outsourcedOrderDetails,oldDetailList,bizOutsourcedOrder);
           if(dayworkList.size()>0){
               //修改报工工段及下序投产数
               bizDayworkService.updateBatchById(dayworkList);
           }
        }
        List<String> formCodeList = outsourcedOrderDetails.stream().map(BizOutsourcedOrderDetail::getFormCode).collect(Collectors.toList());
        List<BizOutsourcedOrderDetail> newDetaillist = bizOutsourcedOrderDetailService.query().in("form_code", formCodeList).list();
        for (int i = 0; i < newDetaillist.size(); i++) {
            for (int j = 0; j < outsourcedOrderDetails.size(); j++) {
                if (newDetaillist.get(i).getLotId().equals(outsourcedOrderDetails.get(j).getLotId())) {
                    newDetaillist.get(i).setProcesses(outsourcedOrderDetails.get(j).getProcesses());
                }
            }
        }
        //操作外协发出工序表
        bizOutsourcedOrderDetailProcessService.updateOrSave(newDetaillist);
        return success();
    }

    @Log(title = "首序外协保存方法", businessType = BusinessType.INSERT)
    @PostMapping("/submitDetailsOnFirst")
    @Transactional
    public AjaxResult submitDetailsOnFirst(@RequestBody BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(bizOutsourcedOrder);
        //若有id，则说将之前的明细删除不生成新的单号
//        List<BizOutsourcedOrderDetail> insertDetail = new ArrayList<>();
//        List<BizOutsourcedOrderDetail> updateDetail = new ArrayList<>();
        List<Long> removeIds = new ArrayList<>();
//        List<BizDaywork> insertDaywork = new ArrayList<>();
//        List<BizDaywork> updateDaywork = new ArrayList<>();
//        List<Long> removeDayworkIds = new ArrayList<>();
//        List<BizDayworkItem> insertDayworkItem = new ArrayList<>();
//        List<BizDayworkItem> updateDayworkItem = new ArrayList<>();
//        List<Long> removeDayworkItem = new ArrayList<>();
//        List<Long> removeDayworkCarrier = new ArrayList<>();
//        List<BizFurnaceNoInfo> insertFurnaceNoInfo = new ArrayList<>();
//        List<Long> removeFurnaceIds = new ArrayList<>();
//        List<BizOutsourcedRecords> insertRecord = new ArrayList<>();
//        List<BizOutsourcedOrderDetailProcess> insertProcess = new ArrayList<>();
//        List<BizOutsourcedOrderDetailProcess> updateProcess = new ArrayList<>();
//        List<Long> removeProcessIds = new ArrayList<>();
        if (bizOutsourcedOrder.getId() != null && !bizOutsourcedOrder.getId().equals(0L)) {
            bizOutsourcedOrder.getDetails().forEach(l -> {
                l.setFormCode(bizOutsourcedOrder.getFormCode());
                l.setFormDate(bizOutsourcedOrder.getFormDate());
                l.setSupplierName(bizOutsourcedOrder.getSupplierName());
                l.setSupplierId(bizOutsourcedOrder.getSupplierId());
                l.setDeliveryMethod(bizOutsourcedOrder.getDeliveryMethod());
                l.setPackagingMethod(bizOutsourcedOrder.getPackagingMethod());
                l.setSettlementType(bizOutsourcedOrder.getSettlementType());
            });

            SysDept condition = new SysDept();
            condition.setDeptCode("170000");
            SysDept dept = deptService.selectDeptList(condition).stream().findFirst().orElse(null);
            List<BizOutsourcedOrderDetail> oldDetails = bizOutsourcedOrderDetailService.query().eq("master_id", bizOutsourcedOrder.getId()).list();
            List<BizOutsourcedOrderDetail> removeDetails = oldDetails.stream().filter(v -> bizOutsourcedOrder.getDetails().stream().noneMatch(e -> v.getId().equals(e.getId()))).collect(Collectors.toList());
            removeIds = removeDetails.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList());
            removeAllForOutsourcedOrderDetailForFirst(removeDetails);
            bizOutsourcedOrderDetailService.removeByIds(removeIds);
            List<BizOutsourcedOrderDetail> updateDetails = bizOutsourcedOrder.getDetails().stream().filter(v -> oldDetails.stream().anyMatch(e -> e.getId().equals(v.getId()))).collect(Collectors.toList());
            updateAllForOutsourceDetailsForFirst(updateDetails, dept,bizOutsourcedOrder);
            List<BizOutsourcedOrderDetail> newDetails = bizOutsourcedOrder.getDetails().stream().filter(v -> oldDetails.stream().noneMatch(e -> e.getId().equals(v.getId()))).collect(Collectors.toList());
            insertAllForOutsourceDetailForFirst(newDetails, dept, bizOutsourcedOrder);

            bizOutsourcedOrderService.updateById(bizOutsourcedOrder);
        } else {
//            if(bizOutsourcedOrder.getDetails() != null ||!bizOutsourcedOrder.getDetails().isEmpty()) {
                saveAllForFirst(bizOutsourcedOrder);
//            }
        }
        return success();
    }
    public Boolean changeCarrierForOutsourcedOrderDetailForFirst(BizOutsourcedOrder bizOutsourcedOrder,List<BizDaywork> dayworks){
        //如果带箱方式从无箱修改正常带箱方式，不做修改
        //如果带箱方式从正常箱子修改为无箱，则未绑定的箱子进行修改
        List<Long> dayworkIds = bizOutsourcedOrder.getDetails().stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList());
        List<BizDayworkCarrier> dayworkCarrierList = iBizDayworkCarrierService.query().in("daywork_id", dayworkIds).eq("is_changed",0).list();
        List<Long> oldCarrierIds = dayworkCarrierList.stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList());
        //没有绑定箱的批次
        List<BizOutsourcedOrderDetail> needBind = new ArrayList<>();
        bizOutsourcedOrder.getDetails().forEach(l -> {
            List<BizDayworkCarrier> hasBindCarrier = dayworkCarrierList.stream().filter(v -> v.getDayworkId().equals(l.getDayworkId())).collect(Collectors.toList());
            if(hasBindCarrier.isEmpty()){
                needBind.add(l);
            }
        });
        if(!needBind.isEmpty()) {
            List<Long> carrierIds;
            //已绑定的首序外协批次是否是无箱
            if (oldCarrierIds.isEmpty()) {
                carrierIds = new ArrayList<>();
                carrierIds.add(0L); // 如果 oldCarrierIds 为空，添加 0L
            } else {
                carrierIds = oldCarrierIds; // 否则直接使用 oldCarrierIds
            }
            BizCarrier bizCarrier = bizCarrierService.selectIsNoneCarrier(carrierIds);
            //首序外协的批次都已换箱
            if (bizCarrier == null) {
                    //查询一个未使用的无箱
                    BizCarrier isNoneCarrier = bizCarrierService.getIsNoneCarrier();
                    if (isNoneCarrier == null) {
                        return false;
                    }
                    List<BizDayworkCarrier> bindCarrier = new ArrayList<>();
                    needBind.forEach(l -> {
                        BizDayworkCarrier dayworkCarrier = new BizDayworkCarrier();
                        dayworkCarrier.setCarrierId(isNoneCarrier.getId());
                        dayworkCarrier.setDayworkId(l.getDayworkId());
                        dayworkCarrier.setCarrierCode(isNoneCarrier.getCode());
                        bindCarrier.add(dayworkCarrier);
                    });
                    iBizDayworkCarrierService.saveBatch(bindCarrier);
            } else {
                    List<BizDayworkCarrier> bindCarrier = new ArrayList<>();
                    needBind.forEach(l -> {
                        BizDayworkCarrier dayworkCarrier = new BizDayworkCarrier();
                        dayworkCarrier.setCarrierId(bizCarrier.getId());
                        dayworkCarrier.setDayworkId(l.getDayworkId());
                        dayworkCarrier.setCarrierCode(bizCarrier.getCode());
                        bindCarrier.add(dayworkCarrier);
                    });
                    iBizDayworkCarrierService.saveBatch(bindCarrier);
            }
        }
        return  true;
    }

    private void insertAllForOutsourceDetailForFirst(List<BizOutsourcedOrderDetail> newDetails, SysDept dept, BizOutsourcedOrder bizOutsourcedOrder) {
        List<BizDaywork> dayworks = new ArrayList<>();
        List<BizFurnaceNoInfo> furnaceNoInfos = new ArrayList<>();
        List<BizOutsourcedOrderDetailProcess> detailProcesses = new ArrayList<>();
        List<BizLot> lots = bizLotService.query().in("id", newDetails.isEmpty() ? Collections.singletonList(0L) : newDetails.stream().map(BizOutsourcedOrderDetail::getLotId).collect(Collectors.toList())).list();
        List<BizDayworkItem> items = new ArrayList<>();
//        BizOutsourcedRecords record = new BizOutsourcedRecords();
        List<BizOutsourcedRecords> records = new ArrayList<>();
        newDetails.forEach(l -> {
            l.setMasterId(bizOutsourcedOrder.getId());
//            l.setNewCarrierCount(l.getOriginalCarrierCount());
            l.setFormCode(bizOutsourcedOrder.getFormCode());
            l.setFormDate(bizOutsourcedOrder.getFormDate());
            l.setSupplierName(bizOutsourcedOrder.getSupplierName());
            l.setSupplierId(bizOutsourcedOrder.getSupplierId());
            l.setDeliveryMethod(bizOutsourcedOrder.getDeliveryMethod());
            l.setPackagingMethod(bizOutsourcedOrder.getPackagingMethod());
            l.setSettlementType(bizOutsourcedOrder.getSettlementType());
            l.setTenantId(bizOutsourcedOrder.getTenantId());
            BizDaywork daywork = new BizDaywork();
            BizLot lot = lots.stream().filter(e -> e.getId().equals(l.getLotId())).findFirst().orElse(null);
            daywork.setProductionPlanDetailId(l.getProductionPlanDetailId());
            daywork.setProductId(l.getProductId());
            daywork.setLotId(l.getLotId());
            daywork.setLotCode(l.getLotCode());
            daywork.setDeptId(dept != null ? dept.getDeptId() : 0L);
            daywork.setProductId(l.getProductId());
            daywork.setTechnologicalProcessId(l.getTechnologicalProcessId());
            daywork.setProcessQualifiedNum(l.getProductNum());
            daywork.setIsLast(lot != null ? lot.getIsLast() : null);
            daywork.setIsWaste(lot != null ? lot.getIsWaste() : null);
            daywork.setIsAmend(lot != null ? lot.getIsAmend() : null);
            daywork.setIsWasteRecycling(lot != null ? lot.getIsWasteRecycling() : null);
            daywork.setId(snowflakeIdWorker.nextId());
            daywork.setTenantId(bizOutsourcedOrder.getTenantId());
            daywork.setStatus(1);
            dayworks.add(daywork);
            BizOutsourcedRecords record = new BizOutsourcedRecords();
            record.setMasterId(bizOutsourcedOrder.getId());
            record.setUserName(SecurityUtils.getLoginUser().getUser().getUserName());
            record.setNickName(SecurityUtils.getLoginUser().getUser().getNickName());
            record.setMethod("修改");
            record.setFormCode(bizOutsourcedOrder.getFormCode());
            record.setSupplierId(bizOutsourcedOrder.getSupplierId());
            record.setSupplierName(bizOutsourcedOrder.getSupplierName());
            record.setLotId(l.getLotId());
            record.setLotCode(l.getLotCode());
            record.setProductDescription(l.getProductDescription());
            record.setProductNum(l.getProductNum());
            record.setProcessNames(l.getProcessNames());
            record.setStartTime(new Date());
            records.add(record);
            l.setDayworkId(daywork.getId());
            BizFurnaceNoInfo furnaceNoInfo = l.getFurnaceNoInfo();
            furnaceNoInfo.setDayworkId(daywork.getId());
            furnaceNoInfo.setProductionPlanDetailId(daywork.getProductionPlanDetailId());
            furnaceNoInfos.add(furnaceNoInfo);
            l.setId(snowflakeIdWorker.nextId());
            l.getProcesses().forEach(v -> {
                v.setMasterId(l.getMasterId());
                v.setDetailId(l.getId());
                v.setLotId(l.getLotId());
                v.setLotCode(l.getLotCode());
                v.setFormDate(l.getFormDate());
                v.setDayworkId(l.getDayworkId());
                v.setFormCode(l.getFormCode());
                v.setProductDescription(l.getProductDescription());
                v.setTechnologicalProcessId(l.getTechnologicalProcessId());
                v.setSupplierId(l.getSupplierId());
                v.setSupplierName(l.getSupplierName());
                v.setDeliveryMethod(l.getDeliveryMethod());
                v.setProductId(l.getProductId());
                v.setTechnologyVersion(l.getTechnologyVersion());
                v.setPackagingMethod(l.getPackagingMethod());
                v.setProductNum(l.getProductNum());
                v.setTenantId(l.getTenantId());
                v.setTenantId(bizOutsourcedOrder.getTenantId());
                detailProcesses.add(v);
                BizDayworkItem item = new BizDayworkItem();
                item.setDayworkId(l.getDayworkId());
                item.setOutsourceDetailId(l.getId());
                item.setLotId(l.getLotId());
                item.setProcessId(v.getProcessId());
                item.setProcessStepNumber(v.getProcessStepNumber());
                item.setStatus("1");
                item.setProdNum(l.getProductNum());
                item.setDeptId(dept != null ? dept.getDeptId() : null);
                item.setDeptName(dept != null ? dept.getDeptName() : null);
                item.setStartTime(new Date());
                item.setDeptCode(dept != null ? dept.getDeptCode() : null);
                item.setProductionPlanDetailId(l.getProductionPlanDetailId());
                item.setTechnologicalProcessId(l.getTechnologicalProcessId());
                item.setTechnologicalProcessDetailId(v.getTechnologicalProcessDetailId());
                item.setIsWx(1);
                item.setNickName(bizOutsourcedOrder.getSupplierName());
                item.setTenantId(bizOutsourcedOrder.getTenantId());
                items.add(item);
            });

        });
        //新增无箱
        if(bizOutsourcedOrder.getPackagingMethod().equals("2")){
            //已经添加进来的detail，有dayworkId
            List<Long> dayworkIds = bizOutsourcedOrder.getDetails().stream()
                    .map(BizOutsourcedOrderDetail::getDayworkId) // 提取 dayworkId
                    .filter(Objects::nonNull) // 过滤掉为 null 的值
                    .collect(Collectors.toList()); // 收集结果
            List<BizDayworkCarrier> dayworkCarrierList = new ArrayList<>();
            List<Long> oldCarrierIds = new ArrayList<>();
            if(!dayworkIds.isEmpty()){
                //有dayworkId的批次绑定箱码detail
                dayworkCarrierList = iBizDayworkCarrierService.query().in("daywork_id", dayworkIds).eq("is_changed",0).list();
                oldCarrierIds = dayworkCarrierList.stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList());
            }
            List<Long> carrierIds;
            if (oldCarrierIds.isEmpty()) {
                carrierIds = new ArrayList<>();
                carrierIds.add(0L); // 如果 oldCarrierIds 为空，添加 0L
            } else {
                carrierIds = oldCarrierIds; // 否则直接使用 oldCarrierIds
            }
            BizCarrier bizCarrier = bizCarrierService.selectIsNoneCarrier(carrierIds);
            //首序外协的批次都已换箱
            if (bizCarrier == null) {
                //查询一个未使用的无箱
                BizCarrier isNoneCarrier = bizCarrierService.getIsNoneCarrier();
                if (isNoneCarrier == null) {
                    throw new RuntimeException("没有可绑定的载具，请联系管理员添加");
                }
                List<BizDayworkCarrier> bindCarrier = new ArrayList<>();
                dayworks.forEach(l -> {
                    BizDayworkCarrier dayworkCarrier = new BizDayworkCarrier();
                    dayworkCarrier.setCarrierId(isNoneCarrier.getId());
                    dayworkCarrier.setDayworkId(l.getId());
                    dayworkCarrier.setCarrierCode(isNoneCarrier.getCode());
                    bindCarrier.add(dayworkCarrier);
                });
                iBizDayworkCarrierService.saveBatch(bindCarrier);
                newDetails.forEach(item -> {
                    item.setNewCarrierName(isNoneCarrier.getCode());
                    item.setNewCarrier(isNoneCarrier.getId()+"|"+isNoneCarrier.getCode());
                    item.setNewCarrierCount(1);
                });
            } else {
                List<BizDayworkCarrier> bindCarrier = new ArrayList<>();
                dayworks.forEach(l -> {
                    BizDayworkCarrier dayworkCarrier = new BizDayworkCarrier();
                    dayworkCarrier.setCarrierId(bizCarrier.getId());
                    dayworkCarrier.setDayworkId(l.getId());
                    dayworkCarrier.setCarrierCode(bizCarrier.getCode());
                    bindCarrier.add(dayworkCarrier);
                });
                iBizDayworkCarrierService.saveBatch(bindCarrier);
                newDetails.forEach(item -> {
                    item.setNewCarrierName(bizCarrier.getCode());
                    item.setNewCarrier(bizCarrier.getId()+"|"+bizCarrier.getCode());
                    item.setNewCarrierCount(1);
                });
            }
        }
//
        bizDayworkService.saveBatch(dayworks);
        furnaceNoInfoService.saveBatch(furnaceNoInfos);
        bizOutsourcedOrderDetailService.saveBatch(newDetails);
        bizOutsourcedOrderDetailProcessService.saveBatch(detailProcesses);
        bizDayworkItemService.saveBatch(items);
        bizOutsourcedRecordsService.saveBatch(records);
    }

    /**
     * 首序外协 外协明细变更
     *
     * @param updateDetails 有变更的外协明细
     */
    private void updateAllForOutsourceDetailsForFirst(List<BizOutsourcedOrderDetail> updateDetails, SysDept dept,BizOutsourcedOrder bizOutsourcedOrder) {
        // 获取所有明细对应的工序
        List<BizOutsourcedOrderDetailProcess> oldProcess = bizOutsourcedOrderDetailProcessService.query().in("detail_id", updateDetails.isEmpty() ? Collections.singletonList(0L) : updateDetails.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList())).list();
        // 获取明细对应的炉号
        List<BizFurnaceNoInfo> furnaceNoInfos = furnaceNoInfoService.query().in("daywork_id", updateDetails.isEmpty() ? Collections.singletonList(0L) : updateDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList())).list();
        List<BizOutsourcedOrderDetailProcess> newProcesses = new ArrayList<>();
        List<BizOutsourcedOrderDetailProcess> removeProcesses = new ArrayList<>();
        List<BizFurnaceNoInfo> updateFurnaceNoInfo = new ArrayList<>();
        List<BizFurnaceNoInfo> removeFurnaceNoInfo = new ArrayList<>();
        List<BizOutsourcedRecords> records = new ArrayList<>();
        updateDetails.forEach(l -> {
            l.setPackagingMethod(bizOutsourcedOrder.getPackagingMethod());
//            l.setNewCarrierCount(l.getOriginalCarrierCount());
            BizOutsourcedRecords record = new BizOutsourcedRecords();
            record.setMasterId(l.getMasterId());
            record.setUserName(SecurityUtils.getLoginUser().getUser().getUserName());
            record.setNickName(SecurityUtils.getLoginUser().getUser().getNickName());
            record.setMethod("创建");
            record.setFormCode(l.getFormCode());
            record.setSupplierId(l.getSupplierId());
            record.setSupplierName(l.getSupplierName());
            record.setLotId(l.getLotId());
            record.setLotCode(l.getLotCode());
            record.setProductDescription(l.getProductDescription());
            record.setProductNum(l.getProductNum());
            record.setProcessNames(l.getProcessNames());
            record.setStartTime(new Date());
            records.add(record);
            List<BizOutsourcedOrderDetailProcess> itemNewProcesses = l.getProcesses().stream().filter(v -> oldProcess.stream().filter(t -> t.getDetailId().equals(l.getId())).noneMatch(t -> t.getProcessStepNumber().equals(v.getProcessStepNumber()))).collect(Collectors.toList());
            itemNewProcesses.forEach(v -> {
                BizOutsourcedOrderDetail detail = new BizOutsourcedOrderDetail(l);
                v.setDetailId(l.getId());
                detail.setId(l.getId());
                v.setDetail(detail);
                v.setFormDate(l.getFormDate());
            });
            newProcesses.addAll(itemNewProcesses);
            List<BizOutsourcedOrderDetailProcess> itemRemoveProcesses = oldProcess.stream().filter(t -> t.getDetailId().equals(l.getId())).filter(t -> l.getProcesses().stream().noneMatch(e -> e.getProcessStepNumber().equals(t.getProcessStepNumber()))).collect(Collectors.toList());
            removeProcesses.addAll(itemRemoveProcesses);
            if (l.getFurnaceNoInfo().getId() == null || l.getFurnaceNoInfo().getId().equals(0L)) {
                l.getFurnaceNoInfo().setDayworkId(l.getDayworkId());
                l.getFurnaceNoInfo().setProductionPlanDetailId(l.getProductionPlanDetailId());
                updateFurnaceNoInfo.add(l.getFurnaceNoInfo());
                removeFurnaceNoInfo.addAll(furnaceNoInfos.stream().filter(v -> v.getDayworkId().equals(l.getDayworkId())).collect(Collectors.toList()));
            }
        });
        //新增无箱
        if(bizOutsourcedOrder.getPackagingMethod().equals("2")){
            //已经添加进来的detail，有dayworkId
            List<Long> dayworkIds = bizOutsourcedOrder.getDetails().stream()
                    .map(BizOutsourcedOrderDetail::getDayworkId) // 提取 dayworkId
                    .filter(Objects::nonNull) // 过滤掉为 null 的值
                    .collect(Collectors.toList()); // 收集结果
                //有dayworkId的批次绑定箱码detail
            List<BizDayworkCarrier> dayworkCarrierList = iBizDayworkCarrierService.query().in("daywork_id", dayworkIds).eq("is_changed",0).list();
            List<Long> oldCarrierIds = dayworkCarrierList.stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList());
            List<BizOutsourcedOrderDetail> needBind = new ArrayList<>();
            updateDetails.forEach(v->{
                List<BizDayworkCarrier> dayworkCarrier = dayworkCarrierList.stream().filter(l -> l.getDayworkId().equals(v.getDayworkId())).collect(Collectors.toList());
            if(dayworkCarrier.isEmpty()){
                //没有绑箱
                needBind.add(v);
            }
            });
            //存在没有绑箱的批次
            if(!needBind.isEmpty()) {
                List<Long> needBindIds = needBind.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList());
                List<Long> carrierIds;
                if (oldCarrierIds.isEmpty()) {
                    carrierIds = new ArrayList<>();
                    carrierIds.add(0L); // 如果 oldCarrierIds 为空，添加 0L
                } else {
                    carrierIds = oldCarrierIds; // 否则直接使用 oldCarrierIds
                }
                BizCarrier bizCarrier = bizCarrierService.selectIsNoneCarrier(carrierIds);
                //首序外协的批次都已换箱
                if (bizCarrier == null) {
                    //查询一个未使用的无箱
                    BizCarrier isNoneCarrier = bizCarrierService.getIsNoneCarrier();
                    if (isNoneCarrier == null) {
                        throw new RuntimeException("没有可绑定的载具，请联系管理员添加");
                    }
                    List<BizDayworkCarrier> bindCarrier = new ArrayList<>();
                    needBind.forEach(l -> {
                        BizDayworkCarrier dayworkCarrier = new BizDayworkCarrier();
                        dayworkCarrier.setCarrierId(isNoneCarrier.getId());
                        dayworkCarrier.setDayworkId(l.getDayworkId());
                        dayworkCarrier.setCarrierCode(isNoneCarrier.getCode());
                        bindCarrier.add(dayworkCarrier);
                    });
                    iBizDayworkCarrierService.saveBatch(bindCarrier);
                    //操作发出明细表
                    updateDetails.forEach(item->{
                        if(needBindIds.contains(item.getId())){
                            item.setNewCarrierName(isNoneCarrier.getCode());
                            item.setNewCarrier(isNoneCarrier.getId()+"|"+isNoneCarrier.getCode());
                            item.setNewCarrierCount(1);
                            item.setPackagingMethod(bizOutsourcedOrder.getPackagingMethod());
                        }

                    });
                } else {
                    List<BizDayworkCarrier> bindCarrier = new ArrayList<>();
                    needBind.forEach(l -> {
                        BizDayworkCarrier dayworkCarrier = new BizDayworkCarrier();
                        dayworkCarrier.setCarrierId(bizCarrier.getId());
                        dayworkCarrier.setDayworkId(l.getDayworkId());
                        dayworkCarrier.setCarrierCode(bizCarrier.getCode());
                        bindCarrier.add(dayworkCarrier);
                    });
                    iBizDayworkCarrierService.saveBatch(bindCarrier);
                    //操作发出明细表
                    updateDetails.forEach(item->{
                        if(needBindIds.contains(item.getId())){
                            item.setNewCarrierName(bizCarrier.getCode());
                            item.setNewCarrier(bizCarrier.getId()+"|"+bizCarrier.getCode());
                            item.setNewCarrierCount(1);
                            item.setPackagingMethod(bizOutsourcedOrder.getPackagingMethod());
                        }
                    });
                }
            }
        }
        // 假设工序删除
        removeAllForOutsourcedProcessForFirst(removeProcesses);
        bizOutsourcedOrderDetailProcessService.removeBatchByIds(removeProcesses);
        // 假设有新工序
        addAllForOutsourcedProcessForFirst(newProcesses, dept);
        // 假设炉号变更
        updateAllForOutsourceFurnaceNoInfoForFirst(updateFurnaceNoInfo, removeFurnaceNoInfo);
        bizOutsourcedOrderDetailService.updateBatchById(updateDetails);
        List<BizReturnReceiptDetail> returnReceiptDetails = bizReturnReceiptDetailService.query().in("outsource_detail_id", updateDetails.isEmpty() ? Collections.singletonList(0L) : updateDetails.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList())).list();
        updateAllForReturnReceiptDetailsForFirst(returnReceiptDetails, updateDetails);
    }

    private void updateAllForReturnReceiptDetailsForFirst(List<BizReturnReceiptDetail> returnReceiptDetails, List<BizOutsourcedOrderDetail> details) {
        // 目前没有发出单明细变更然后会变更回收单的。
    }

    // 有炉号变更
    private void updateAllForOutsourceFurnaceNoInfoForFirst(List<BizFurnaceNoInfo> updateFurnaceNoInfo, List<BizFurnaceNoInfo> removeFurnaceNoInfo) {
        furnaceNoInfoService.saveBatch(updateFurnaceNoInfo);
        furnaceNoInfoService.removeBatchByIds(removeFurnaceNoInfo);
    }

    private void addAllForOutsourcedProcessForFirst(List<BizOutsourcedOrderDetailProcess> newProcesses, SysDept dept) {
        List<BizDayworkItem> items = new ArrayList<>();
        // 新增报工明细表
        newProcesses.forEach(v -> {
            v.setMasterId(v.getDetail().getMasterId());
            v.setDetailId(v.getDetail().getId());
            v.setLotId(v.getDetail().getLotId());
            v.setLotCode(v.getDetail().getLotCode());
            v.setFormDate(v.getDetail().getFormDate());
            v.setDayworkId(v.getDetail().getDayworkId());
            v.setFormCode(v.getDetail().getFormCode());
            v.setProductDescription(v.getDetail().getProductDescription());
            v.setTechnologicalProcessId(v.getDetail().getTechnologicalProcessId());
            v.setSupplierId(v.getDetail().getSupplierId());
            v.setSupplierName(v.getDetail().getSupplierName());
            v.setDeliveryMethod(v.getDetail().getDeliveryMethod());
            v.setProductId(v.getDetail().getProductId());
            v.setTechnologyVersion(v.getDetail().getTechnologyVersion());
            v.setPackagingMethod(v.getDetail().getPackagingMethod());
            v.setProductNum(v.getDetail().getProductNum());
            v.setTenantId(v.getDetail().getTenantId());
            BizDayworkItem item = new BizDayworkItem();
            item.setDayworkId(v.getDayworkId());
            item.setOutsourceDetailId(v.getDetailId());
            item.setLotId(v.getLotId());
            item.setProcessId(v.getProcessId());
            item.setProcessStepNumber(v.getProcessStepNumber());
            item.setStatus("1");
            item.setProdNum(v.getProductNum());
            item.setDeptId(dept != null ? dept.getDeptId() : null);
            item.setDeptName(dept != null ? dept.getDeptName() : null);
            item.setStartTime(new Date());
            item.setDeptCode(dept != null ? dept.getDeptCode() : null);
            item.setProductionPlanDetailId(v.getDetail().getProductionPlanDetailId());
            item.setTechnologicalProcessId(v.getDetail().getTechnologicalProcessId());
            item.setTechnologicalProcessDetailId(v.getTechnologicalProcessDetailId());
            item.setTenantId(getTenantId());
            item.setIsWx(1);
            items.add(item);
        });
        bizOutsourcedOrderDetailProcessService.saveBatch(newProcesses);
        bizDayworkItemService.saveBatch(items);
    }

    /**
     * 首序外协删除外协明细
     *
     * @param removeDetails 删除的外协明细
     */
    private void removeAllForOutsourcedOrderDetailForFirst(List<BizOutsourcedOrderDetail> removeDetails) {
        // 删除对应的报工明细
        List<BizDayworkItem> removeItems = bizDayworkItemService.getListByDayworkIds(removeDetails.isEmpty() ? Collections.singletonList(0L) : removeDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList()));
        bizDayworkItemService.removeBatchByIds(removeItems);
        // 删除对应炉号
        List<BizFurnaceNoInfo> furnaceNoInfos = furnaceNoInfoService.query().in("daywork_id", removeDetails.isEmpty() ? Collections.singletonList(0L) : removeDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList())).list();
        furnaceNoInfoService.removeBatchByIds(furnaceNoInfos);
        // 删除对应报工
        List<BizDaywork> bizDayworks = bizDayworkService.query().in("id", removeDetails.isEmpty() ? Collections.singletonList(0L) : removeDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList())).list();
        bizDayworkService.removeBatchByIds(bizDayworks);
        // 删除对应工序
        List<BizOutsourcedOrderDetailProcess> processes = bizOutsourcedOrderDetailProcessService.query().in("detail_id", removeDetails.isEmpty() ? Collections.singletonList(0L) : removeDetails.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList())).list();
        bizOutsourcedOrderDetailProcessService.removeBatchByIds(processes);
        // 删除对应箱码
        List<BizDayworkCarrier> carriers = iBizDayworkCarrierService.query().in("daywork_id", removeDetails.isEmpty() ? Collections.singletonList(0L) : removeDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList())).list();
        iBizDayworkCarrierService.removeBatchByIds(carriers);
        //删除或修改收回明细(通过工序判断，如果工序变了，如果已经填写了收回单，则删除收回单该批次的明细，如果只是修改了箱号，则编辑回收单该批次的明细)
        List<BizReturnReceiptDetail> details = bizReturnReceiptDetailService.query().in("outsource_detail_id", removeDetails.isEmpty() ? Collections.singletonList(0L) :removeDetails.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList())).list();
        bizReturnReceiptDetailService.removeBatchByIds(details);
        QueryWrapper<BizReturnReceipt> returnReceiptQueryWrapper = new QueryWrapper<>();
        returnReceiptQueryWrapper.notExists("(select 1 from biz_return_receipt_detail t where t.deleted = 0 and t.master_id = biz_return_receipt.id)");
        bizReturnReceiptService.remove(returnReceiptQueryWrapper);
    }

    /**
     * 首序外协 删除工序
     *
     * @param removeProcesses 受删除的工序
     */
    private void removeAllForOutsourcedProcessForFirst(List<BizOutsourcedOrderDetailProcess> removeProcesses) {
        // 删除对应的报工明细
        List<BizDayworkItem> allItems = bizDayworkItemService.getListByDayworkIds(removeProcesses.isEmpty() ? Collections.singletonList(0L) : removeProcesses.stream().map(BizOutsourcedOrderDetailProcess::getDayworkId).collect(Collectors.toList()));
        List<BizDayworkItem> removeItems = allItems.stream().filter(v -> removeProcesses.stream().anyMatch(e -> e.getProcessStepNumber().equals(v.getProcessStepNumber()))).collect(Collectors.toList());
        // 还要删除对应的收回单明细
        List<BizReturnReceiptDetail> returnReceiptDetails = new ArrayList<>();
        removeProcesses.forEach(l -> {
            returnReceiptDetails.addAll( bizReturnReceiptDetailService.query()
                    .eq("outsource_detail_id", l.getDetailId())
                    .eq("technological_process_detail_id", l.getTechnologicalProcessDetailId()).list());
        });
//        List<BizReturnReceiptDetail> returnReceiptDetails = ;
        bizReturnReceiptDetailService.removeBatchByIds(returnReceiptDetails);
        bizDayworkItemService.removeBatchByIds(removeItems);
    }

    /**
     * 修改外协单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
//    @PreAuthorize("@ss.hasPermi('business:outsource:edit')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.UPDATE)
    @PutMapping
    @Transactional
    public AjaxResult submitOrder(@RequestBody BizOutsourcedOrder bizOutsourcedOrder) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(bizOutsourcedOrder);
        //若有id，则说将之前的明细删除不生成新的单号
        if (bizOutsourcedOrder.getId() != null) {
            List<Long> ids = new ArrayList<>();
            ids.add(bizOutsourcedOrder.getId());
            //先将之前的明细删除
            bizOutsourcedOrderDetailService.removeByMasterIds(ids);
            bizOutsourcedOrderDetailProcessService.removeByMasterIds(ids);
        } else {
            /* 生成单号 */
            SimpleDateFormat dateFormat = new SimpleDateFormat("yy"); // 定义日期格式
            String formattedDate = dateFormat.format(new Date());
            String codeValue;
            String codeType = "outsourcedOrderCode";
            //查询redis中外协单号的值
            String previous = redisCache.hasKey(codeType) ? redisCache.getCacheObject(codeType) : "";
            //若不存在，则直接存入
            if (previous.isEmpty()) {
                //如果没有数据再去数据库中查询该类型的流水号是否存在，如果存在找到最新一条，
                // 在最新一条基础上进行继续追加并存到redias中，如果数据库中也没有该类型的流水号再从00001开始
                List<BizOutsourcedOrder> outsourcedOrderDetailList = bizOutsourcedOrderService.getAllList();
                if(!outsourcedOrderDetailList.isEmpty()){
                    codeValue = outsourcedOrderDetailList.get(0).getFormCode();
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                }else{
                    previous = ("WFD" + formattedDate + "00001");
                }
            } else {
                codeValue = previous;
                String codeYear=codeValue.substring(3, 5);//取出当前外协单号年份
                //如果年份一致表示是当前年的发出单，如果不一致则表示已经进入了新的一年则重置发出单号
                if(codeYear.equals(formattedDate)){
                    int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                    lastFourDigits += 1; // 加1
                    codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                    previous = codeValue;
                }else{
                    previous = ("WFD" + formattedDate + "00001");
                }
            }
            //存到redis中
            redisCache.setCacheObject(codeType, previous);
            bizOutsourcedOrder.setFormCode(previous);
        }
        bizOutsourcedOrder.setIsSubmit(1);
        //新增明细信息
        List<BizOutsourcedOrderDetail> outsourcedOrderDetails = bizOutsourcedOrder.getDetails();

        //绑定的新箱子集合
        List<BizDayworkCarrier> carrierList = new ArrayList<>();
        //绑定新箱子
        outsourcedOrderDetails.forEach(detail -> {
            /**
             * 与暂存逻辑类似，但因为是彻底保存提交了，所以需要解绑原先的箱子，并且在没有新箱子时，需要将原先箱号复制到新箱号中
             */
            if (detail.getNewCarriers().size() > 0) {
                //这一步将绑定的新箱子以“id|code”一组，以英文“,”分割(例：1|A,2|B,3|C)
                String formattedString = detail.getNewCarriers().stream()
                        .map(item -> item.getId() + "|" + item.getCode())
                        .collect(Collectors.joining(","));
                //赋值给新箱号
                detail.setNewCarrier(formattedString);
                //将新箱号绑定至dayworkId
                detail.getNewCarriers().forEach(carrier -> {
                    BizDayworkCarrier bizDayworkCarrier = new BizDayworkCarrier();
                    bizDayworkCarrier.setCarrierId(carrier.getId());
                    bizDayworkCarrier.setCarrierCode(carrier.getCode());
                    bizDayworkCarrier.setDayworkId(detail.getDayworkId());
                    bizDayworkCarrier.setLotId(detail.getLotId());
                    carrierList.add(bizDayworkCarrier);
                });
            } else {
                //将原箱号复制到新新箱号
                detail.setNewCarrier(detail.getOriginalCarrier());
            }
        });

        //查询箱号是否已经废弃
//        List<BizCarrierReject> bizCarrierRejects =  iBizCarrierRejectService.query().in("carrier_id",carrierList.stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList())).eq("is_abandoned",1).list();
//        if(bizCarrierRejects.size()>0){
//            List<Long> categoryIds = bizCarrierRejects.stream().map(BizCarrierReject::getCategoryId).collect(Collectors.toList());
//
//            // 使用 Stream API 来筛选出 id 存在于 categoryIds 集合中的 Carrier 对象
//            List<BizDayworkCarrier> filteredCarrierList = carrierList.stream()
//                    .filter(carrier -> categoryIds.contains(carrier.getCarrierId())) // 假设 getCategoryId() 返回 Carrier 对象的 categoryId
//                    .collect(Collectors.toList());
//
//            String codesAsString = filteredCarrierList.stream()
//                    .map(BizDayworkCarrier::getCarrierCode) // 假设 getCode() 返回 Carrier 对象的 code 属性
//                    .collect(Collectors.joining(", "));
//            throw new RuntimeException("《"+codesAsString+"》箱号已被废弃，请重新选择！");
//        }

        //修改主表信息
        bizOutsourcedOrderService.saveOrUpdate(bizOutsourcedOrder);


        //判断是否使用新箱子
        //根据 detail.getNewCarriers()判断是否绑定了新箱子，如果有数据表示绑定新箱子,找出对应的dayworkId，解绑对应的箱子
        List<Long> dayworkIds = outsourcedOrderDetails.stream().filter(detail -> detail.getNewCarriers().size() > 0).map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList());
        if (dayworkIds.size() > 0) {
            iBizDayworkCarrierService.removeByDayworkIds(dayworkIds);
        }

        iBizDayworkCarrierService.saveBatch(carrierList);
        outsourcedOrderDetails = bizOutsourcedOrderDetailService.batchSave(outsourcedOrderDetails, bizOutsourcedOrder);
        //将周转信息修改为7，添加外协报工信息
        //bizDayworkItemService.updateDayworkItemForOutsource(outsourcedOrderDetails);
        return toAjax(bizOutsourcedOrderDetailProcessService.batchSave(outsourcedOrderDetails));
    }

    /**
     * 删除外协单主
     * 带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子
     */
//    @PreAuthorize("@ss.hasPermi('business:outsource:remove')")
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @Transactional
    public AjaxResult remove(@PathVariable List<Long> ids) {
        /**
         *删除工能暂时不可删除已经提交的数据，如果后续想要删除，将下方代码解开
         *解开后要加上：如果使用的是新箱子，则需要解绑箱子并将对应的周转报工删除
         *不删除只解绑箱子会出现错误，删除后可在手机端重新绑定箱子进行周转（也可使用别的方式进行绑定）
         */

        //查找需要删除的从表信息
//        List<BizOutsourcedOrderDetail> outsourcedOrderDetails =bizOutsourcedOrderDetailService.query().in("master_id",ids).list();
//        List<Long> dayworkIds=outsourcedOrderDetails.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList());
//
//        /*查询需要删除的外协工序信息，因为可能出现二次外协周转不能删除所有的外协报工,所以要查询当前外协需要加工的工序*/
//        List<BizOutsourcedOrderDetailProcess> bizOutsourcedOrderDetailProcessList=bizOutsourcedOrderDetailProcessService.query().in("master_id",ids).list();
//
//        //判断是否已经报工，如果存在投入数则表示已经报工不能删除
//        for (BizOutsourcedOrderDetailProcess process : bizOutsourcedOrderDetailProcessList) {
//            if(process.getProductionNum()>0){
//                throw new RuntimeException("【"+process.getLotCode()+"】批次存在已报工的工序，不能删除");
//            }
//        }
//
//        List<Long> processIds=bizOutsourcedOrderDetailProcessList.stream().map(BizOutsourcedOrderDetailProcess::getTechnologicalProcessDetailId).collect(Collectors.toList());
//        //找到对应的外协所有报工信息
//        List<BizDayworkItem> bizDayworkItemList=bizDayworkItemService.getListByDayworkIdsForOutsourced(dayworkIds);
//
//        // 使用流来筛选出当前的信息
//        List<BizDayworkItem> filteredList = bizDayworkItemList.stream()
//                .filter(item -> processIds.contains(item.getTechnologicalProcessDetailId()))
//                .collect(Collectors.toList());
//        //删除报工信息
//        List<Long> dayworkItemIds= filteredList.stream().map(BizDayworkItem::getId).collect(Collectors.toList());
//        bizDayworkItemService.removeBatchByIds(dayworkItemIds);
//
//        //修改对应的周转信息,将周转信息改为待周转
//        bizDayworkItemList= bizDayworkItemService.selectLatestItemByDayworkIds(dayworkIds);
//
//        bizDayworkItemList.forEach(item->{
//            item.setStatus("4");
//        });
//
//        List<Long> removeIds=outsourcedOrderDetails.stream().filter(detail -> detail.getPackagingMethod().equals("1")).map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList());
//        if(removeIds.size()>0) {
//            iBizDayworkCarrierService.removeByDayworkIds(removeIds);
//        }
//
//        //此方法待定
//        iBizDayworkCarrierService.updateByDaywork(outsourcedOrderDetails);
//
//
//        //修改周转信息
//        bizDayworkItemService.saveOrUpdateBatch(bizDayworkItemList);
        //删除表，如果有收回明细，则不能删除
        Boolean flag = false;
        List<BizOutsourcedOrderDetail> outsourcedDetailList = bizOutsourcedOrderDetailService.query().in("master_id", ids).list();
        List<Long> outsourcedDetailIds = outsourcedDetailList.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList());
        //德迈仕审核，flag为true
        flag = bizReturnReceiptDetailService.query().in("outsource_detail_id", outsourcedDetailIds).list().isEmpty()?false:true;
        if(flag) {
            return error("发出单内的批次存在收回明细，不能删除！");
        }
        //删除收回单明细及收回单主表信息
        bizReturnReceiptDetailService.removeByMasterIds(ids);
        //删除明细信息
        bizOutsourcedOrderDetailService.removeByMasterIds(ids);
        //删除报工信息
        bizDayworkItemService.removeByOutsourceIds(outsourcedDetailIds);
        //删除明细对应的工序
        bizOutsourcedOrderDetailProcessService.removeByMasterIds(ids);
        //删除主表信息
        return toAjax(bizOutsourcedOrderService.removeBatchByIds(ids));
    }
    @Log(title = "外协单主带箱方式，是整单的。如果换新箱子，明细中，都需要更换箱子", businessType = BusinessType.DELETE)
    @DeleteMapping("/delInnerOrder/{ids}")
    @Transactional
    public AjaxResult delInnerOrder(@PathVariable List<Long> ids) {
        //删除表，如果有报工数据，则不能删除
        Boolean flag = false;
        List<BizOutsourcedOrderDetail> outsourcedDetailList = bizOutsourcedOrderDetailService.query().in("master_id", ids).list();
        List<Long> outsourcedDetailIds = outsourcedDetailList.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList());
        //德迈仕审核，flag为true
        List<BizDayworkItem> dayworkItemList = bizDayworkItemService.query().in("outsource_detail_id", outsourcedDetailIds).list();
        flag = dayworkItemList.stream().filter(v->v.getStatus().equals("0")||v.getStatus().equals("1") || v.getStatus().equals("2")||v.getStatus().equals("3")).collect(Collectors.toList()).isEmpty()?false:true;
        if(flag) {
            return error("发出单内的批次存在报工数据，不能删除！");
        }
        //删除收回单明细及收回单主表信息
        bizReturnReceiptDetailService.removeByMasterIds(ids);
        //删除明细信息
        bizOutsourcedOrderDetailService.removeByMasterIds(ids);
        //删除报工信息
        bizDayworkItemService.removeByOutsourceIds(outsourcedDetailIds);
        //修改daywork的工段数据及合格数
        List<Long> dayworkIds = dayworkItemList.stream().map(BizDayworkItem::getDayworkId).distinct().collect(Collectors.toList());
        List<BizDaywork> dayworkList = bizDayworkService.query().in("id", dayworkIds).list();
        List<BizDayworkItem> bizDayworkItemList = bizDayworkItemService.query().in("daywork_id", dayworkIds).list();
        for(BizDaywork daywork:dayworkList) {
            BizDayworkItem lastDayworkItem = bizDayworkItemList.stream()
                    .filter(v -> v.getDayworkId().equals(daywork.getId()))
                    .sorted(Comparator.comparing(BizDayworkItem::getProcessStepNumber).reversed())
                    .sorted(Comparator.comparing(BizDayworkItem::getCreateTime).reversed()).findFirst().orElse(null);
            daywork.setDeptId(lastDayworkItem.getDeptId());
            List<BizDayworkItem> lastDayworkItemList = bizDayworkItemList.stream()
                    .filter(v -> v.getDayworkId().equals(daywork.getId()) && v.getProcessStepNumber().equals(lastDayworkItem.getProcessStepNumber()) && (v.getStatus().equals("2") || v.getStatus().equals("3"))).collect(Collectors.toList());
            int sum = lastDayworkItemList.stream().mapToInt(BizDayworkItem::getQualifiedNum).sum();
            daywork.setProcessQualifiedNum(sum);
            daywork.setTemporaryProcessQualifiedNum(sum);
        }
        bizDayworkService.updateBatchById(dayworkList);
        //删除明细对应的工序
        bizOutsourcedOrderDetailProcessService.removeByMasterIds(ids);

        //删除主表信息
        return toAjax(bizOutsourcedOrderService.removeBatchByIds(ids));
    }

    @Log(title="删除外协首序外协的外协单", businessType = BusinessType.DELETE)
    @DeleteMapping("/removeForFirst/{ids}")
    @Transactional
    public AjaxResult removeForFirst(@PathVariable List<Long> ids) {
        Boolean flag = false;
        List<BizOutsourcedOrderDetail> outsourcedDetailList = bizOutsourcedOrderDetailService.query().in("master_id", ids).list();
        List<Long> outsourcedDetailIds = outsourcedDetailList.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList());
        //德迈仕审核，flag为true
        flag = bizReturnReceiptDetailService.query().in("outsource_detail_id", outsourcedDetailIds).list().isEmpty()?false:true;
        if(flag) {
            return error("发出单内的批次存在收回明细，不能删除！");
        }
        //删除收回单明细及收回单主表信息
        bizReturnReceiptDetailService.removeByMasterIds(ids);
        //删除明细信息
        bizOutsourcedOrderDetailService.removeByMasterIds(ids);
        //删除报工信息
        bizDayworkItemService.removeByOutsourceIds(outsourcedDetailIds);
        //删除明细对应的工序
        bizOutsourcedOrderDetailProcessService.removeByMasterIds(ids);
        // 删除报工
        QueryWrapper<BizDaywork> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", outsourcedDetailList.isEmpty() ? Collections.singletonList(0L) : outsourcedDetailList.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList()));
        bizDayworkService.remove(queryWrapper);
        // 删除外协箱
        QueryWrapper<BizDayworkCarrier> carrierQueryWrapper = new QueryWrapper<>();
        carrierQueryWrapper.in("daywork_id", outsourcedDetailList.isEmpty() ? Collections.singletonList(0L) : outsourcedDetailList.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList()));
        iBizDayworkCarrierService.remove(carrierQueryWrapper);
        // 删除原料
        QueryWrapper<BizFurnaceNoInfo> furnaceNoInfoQueryWrapper = new QueryWrapper<>();
        furnaceNoInfoQueryWrapper.in("daywork_id", outsourcedDetailList.isEmpty() ? Collections.singletonList(0L) : outsourcedDetailList.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList()));
        furnaceNoInfoService.remove(furnaceNoInfoQueryWrapper);
        // 删除主表信息
        return toAjax(bizOutsourcedOrderService.removeBatchByIds(ids));
    }

    @PostMapping("getCarrierInfo")
    public AjaxResult getCarrierInfo(@RequestBody List<Long> orderIds) {
        List<BizOutsourcedOrder> orders = bizOutsourcedOrderService.query().in("id", orderIds).list();
        // 获取所有明细
        List<BizOutsourcedOrderDetail> details = bizOutsourcedOrderDetailService.query().in("master_id", orders.stream().map(BizOutsourcedOrder::getId).collect(Collectors.toList())).list();
        // 获取明细中的所有的载具code
        List<String> codes = new ArrayList<>();
        details.forEach(l -> {
            codes.addAll(Arrays.stream(l.getNewCarrierName().split(",")).collect(Collectors.toList()));
        });
        // 获取载具列表
        List<BizCarrier> carriers = bizCarrierService.query().in("code", codes.isEmpty() ? Collections.singletonList("") : codes).exists("(select 1 from biz_carrier_category t where t.id = biz_carrier.category_id and t.deleted = 0 and t.name = '外协箱')").list();

        return success(carriers);
    }

    @Log(title = "首序外协产品明细", businessType = BusinessType.SELECT)
    @GetMapping("/getProductionPlan")
    public TableDataInfo getProductionPlan(BizProductionPlanDetail bizProductionPlanDetail) throws NoSuchFieldException, IllegalAccessException {
        SysDept condition = new SysDept();
        condition.setDeptCode("170000");
        SysDept dept = deptService.getDeptList(condition).stream().findFirst().orElse(null);
        bizProductionPlanDetail.setDeptId(dept != null ? dept.getValue() : null);
        startPage();
        bizProductionPlanDetail.setRemainLot(true);
        String config = configService.selectConfigByKey("switch_data_source");
        if ("true".equals(config)) {
            setTenantId(bizProductionPlanDetail);
        }
        List<BizProductionPlanDetail> list = bizProductionPlanDetailService.getListForOutsource(bizProductionPlanDetail);
        return getDataTable(list);
    }

    @Log(title = "根据生产计划明细子计划获取对应批次")
    @PostMapping("/getLotByProductionPlanSub")
    public AjaxResult getLotByProductionPlanSub(@RequestBody BizOutsourcedOrderDetail detail) {
        // 获取该外协单的所有批次
        // 获取对应子计划的所有批次
//        List<BizLot> lots =
        List<BizLot> allLots = bizLotService.query().in("production_plan_detail_id", detail.getPlanDetails() == null || detail.getPlanDetails().isEmpty() ? Collections.singletonList(0L) : detail.getPlanDetails().stream().map(BizProductionPlanDetail::getId).collect(Collectors.toList())).list();
        // 已开始生产的所有批次
        List<BizLot> workedLots = bizLotService.query().in("id", allLots.isEmpty() ? Collections.singletonList(0L) : allLots.stream().map(BizLot::getId).collect(Collectors.toList())).exists("(select 1 from biz_daywork t where t.deleted = 0 and t.lot_id = biz_lot.id)").list();
        List<BizOutsourcedOrderDetail> details = bizOutsourcedOrderDetailService.query().eq("master_id", detail.getMasterId()).in("lot_id", allLots.isEmpty() ? Collections.singletonList(0L) : allLots.stream().map(BizLot::getId).collect(Collectors.toList())).list();
        List<BizFurnaceNoInfo> furnaceNoInfos = furnaceNoInfoService.query().in("daywork_id", details.isEmpty() ? Collections.singletonList(0L) : details.stream().map(BizOutsourcedOrderDetail::getDayworkId).collect(Collectors.toList())).list();
        List<BizOutsourcedOrderDetailProcess> processes = bizOutsourcedOrderDetailProcessService.query().in("detail_id", details.isEmpty() ? Collections.singletonList(0L) : details.stream().map(BizOutsourcedOrderDetail::getId).collect(Collectors.toList())).list();
        details.forEach(e -> {
            e.setFurnaceNoInfo(furnaceNoInfos.stream().filter(t -> t.getDayworkId().equals(e.getDayworkId())).findFirst().orElse(null));
            e.setProcesses(processes.stream().filter(v -> v.getDetailId().equals(e.getId())).collect(Collectors.toList()));

        });
        List<BizLot> currentLots = bizLotService.query().eq("id", details.isEmpty() ? Collections.singletonList(0L) : details.stream().map(BizOutsourcedOrderDetail::getLotId).collect(Collectors.toList())).list();
        List<BizOutsourcedOrderDetail> result = new ArrayList<>();
        detail.getPlanDetails().forEach(l -> {
            // 获取当前计划单所有已开始的批次
            List<BizLot> itemWorkLot = workedLots.stream().filter(v -> v.getProductionPlanDetailId().equals(l.getId())).collect(Collectors.toList());
            // 获取当前计划单已开始批次中在当前外协单上的批次。
            List<BizLot> detailWorkLot = itemWorkLot.stream().filter(e -> currentLots.stream().anyMatch(v -> v.getId().equals(e.getId()))).collect(Collectors.toList());
            // 根据已开始批次获取所有未开始批次
            List<BizLot> allItemLot = allLots.stream().filter(v -> v.getProductionPlanDetailId().equals(l.getId()) && itemWorkLot.stream().noneMatch(t -> t.getId().equals(v.getId()))).collect(Collectors.toList());
            int remainLotNumber = (int) (l.getLotTotalNumber() - itemWorkLot.size());
            allItemLot = allItemLot.subList(0, remainLotNumber);
            // 将所有未开始批次和所有当前外协单中已开始批次插入到result表中
            allItemLot.forEach(v -> {
                BizOutsourcedOrderDetail item = new BizOutsourcedOrderDetail();
                item.setLotCode(v.getLotCode());
                item.setLotId(v.getId());
                item.setMasterId(detail.getMasterId());
                item.setSupplierId(detail.getSupplierId());
                item.setSupplierName(detail.getSupplierName());
                item.setProductId(l.getProductId());
                item.setProductDescription(l.getProductDescription());
                item.setProductCode(l.getProductCode());
                item.setProductNum(v.getProductionQuantity());
                item.setTechnologicalProcessId(v.getTechnologicalProcessId());
                item.setTechnologyVersion(v.getTechnologyVersion());
                item.setProductionPlanNo(l.getProductionPlanNo());
                item.setLineNumber(l.getLineNumber());
                item.setProductionPlanDetailId(l.getId());
                item.setIsAmend(v.getIsAmend());
                item.setIsWasteRecycling(Integer.parseInt (v.getIsWasteRecycling().toString()));
                item.setIsSuperaddition(v.getIsSuperaddition());
                item.setIsWaste(v.getIsWaste());
                item.setPlanType(l.getPlanType());
                result.add(item);
            });
            List<BizOutsourcedOrderDetail> currentDetails = details.stream().filter(v -> detailWorkLot.stream().anyMatch(t -> t.getId().equals(v.getLotId()))).collect(Collectors.toList());
            result.addAll(currentDetails);
        });
        return success(result);
    }

    private void saveAllForFirst(BizOutsourcedOrder bizOutsourcedOrder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yy"); // 定义日期格式
        String formattedDate = dateFormat.format(new Date());
        String codeValue;
        String codeType = "outsourcedOrderCode";
        //查询redis中外协单号的值
        String previous = redisCache.hasKey(codeType) ? redisCache.getCacheObject(codeType) : "";
        //若不存在，则直接存入
        if (previous.isEmpty()) {
            //如果没有数据再去数据库中查询该类型的流水号是否存在，如果存在找到最新一条，
            // 在最新一条基础上进行继续追加并存到redias中，如果数据库中也没有该类型的流水号再从00001开始
            List<BizOutsourcedOrder> outsourcedOrderDetailList = bizOutsourcedOrderService.getAllList();
            if(!outsourcedOrderDetailList.isEmpty()){
                codeValue = outsourcedOrderDetailList.get(0).getFormCode();
                int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                lastFourDigits += 1; // 加1
                codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                previous = codeValue;
            }else{
                previous = ("WFD" + formattedDate + "00001");
            }
        } else {
            codeValue = previous;
            String codeYear=codeValue.substring(3, 5);//取出当前外协单号年份
            //如果年份一致表示是当前年的发出单，如果不一致则表示已经进入了新的一年则重置发出单号
            if(codeYear.equals(formattedDate)){
                int lastFourDigits = Integer.parseInt(codeValue.substring(5, 10));
                lastFourDigits += 1; // 加1
                codeValue = codeValue.substring(0, 5) + String.format("%05d", lastFourDigits);
                previous = codeValue;
            }else{
                previous = ("WFD" + formattedDate + "00001");
            }
        }

        //存到redis中
        redisCache.setCacheObject(codeType, previous);
        bizOutsourcedOrder.setFormCode(previous);
        bizOutsourcedOrder = generateQrCodeImg(bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder);
        bizOutsourcedOrder = generateBarCodeImg(bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder.getFormCode(), bizOutsourcedOrder);
        bizOutsourcedOrder.setIsSubmit(1);
        bizOutsourcedOrder.setIsFirstProcess(1);

        bizOutsourcedOrderService.save(bizOutsourcedOrder);
        List<BizOutsourcedOrderDetail> details = bizOutsourcedOrder.getDetails();
        SysDept condition = new SysDept();
        condition.setDeptCode("170000");
        SysDept dept = deptService.selectDeptList(condition).stream().findFirst().orElse(null);
        List<BizDaywork> dayworks = new ArrayList<>();
        List<BizFurnaceNoInfo> furnaceNoInfos = new ArrayList<>();
        List<BizOutsourcedOrderDetailProcess> detailProcesses = new ArrayList<>();
        List<BizLot> lots = bizLotService.query().in("id", details.isEmpty() ? Collections.singletonList(0L) : details.stream().map(BizOutsourcedOrderDetail::getLotId).collect(Collectors.toList())).list();
        List<BizDayworkItem> items = new ArrayList<>();
//        BizOutsourcedRecords record = new BizOutsourcedRecords();
        List<BizOutsourcedRecords> records = new ArrayList<>();
        BizOutsourcedOrder finalBizOutsourcedOrder = bizOutsourcedOrder;
        details.forEach(l -> {
            l.setMasterId(finalBizOutsourcedOrder.getId());
//            l.setNewCarrierCount(l.getOriginalCarrierCount());
            l.setFormCode(finalBizOutsourcedOrder.getFormCode());
            l.setFormDate(finalBizOutsourcedOrder.getFormDate());
            l.setSupplierName(finalBizOutsourcedOrder.getSupplierName());
            l.setSupplierId(finalBizOutsourcedOrder.getSupplierId());
            l.setDeliveryMethod(finalBizOutsourcedOrder.getDeliveryMethod());
            l.setPackagingMethod(finalBizOutsourcedOrder.getPackagingMethod());
            l.setSettlementType(finalBizOutsourcedOrder.getSettlementType());
            BizDaywork daywork = new BizDaywork();
            BizLot lot = lots.stream().filter(e -> e.getId().equals(l.getLotId())).findFirst().orElse(null);
            daywork.setProductionPlanDetailId(l.getProductionPlanDetailId());
            daywork.setProductId(l.getProductId());
            daywork.setLotId(l.getLotId());
            daywork.setLotCode(l.getLotCode());
            daywork.setDeptId(dept != null ? dept.getDeptId() : 0L);
            daywork.setProductId(l.getProductId());
            daywork.setTechnologicalProcessId(l.getTechnologicalProcessId());
            daywork.setProcessQualifiedNum(l.getProductNum());
            daywork.setIsLast(lot != null ? lot.getIsLast() : null);
            daywork.setIsWaste(lot != null ? lot.getIsWaste() : null);
            daywork.setIsAmend(lot != null ? lot.getIsAmend() : null);
            daywork.setIsWasteRecycling(lot != null ? lot.getIsWasteRecycling() : null);
            daywork.setTenantId(getTenantId());
            daywork.setId(snowflakeIdWorker.nextId());
            daywork.setStatus(1);
            dayworks.add(daywork);
            BizOutsourcedRecords record = new BizOutsourcedRecords();
            record.setMasterId(finalBizOutsourcedOrder.getId());
            record.setUserName(SecurityUtils.getLoginUser().getUser().getUserName());
            record.setNickName(SecurityUtils.getLoginUser().getUser().getNickName());
            record.setMethod("创建");
            record.setFormCode(finalBizOutsourcedOrder.getFormCode());
            record.setSupplierId(finalBizOutsourcedOrder.getSupplierId());
            record.setSupplierName(finalBizOutsourcedOrder.getSupplierName());
            record.setLotId(l.getLotId());
            record.setLotCode(l.getLotCode());
            record.setProductDescription(l.getProductDescription());
            record.setProductNum(l.getProductNum());
            record.setProcessNames(l.getProcessNames());
            record.setStartTime(new Date());
            records.add(record);
            l.setDayworkId(daywork.getId());
            BizFurnaceNoInfo furnaceNoInfo = l.getFurnaceNoInfo();
            furnaceNoInfo.setDayworkId(daywork.getId());
            furnaceNoInfo.setProductionPlanDetailId(daywork.getProductionPlanDetailId());
            furnaceNoInfos.add(furnaceNoInfo);
            l.setId(snowflakeIdWorker.nextId());
            l.getProcesses().forEach(v -> {
                v.setMasterId(l.getMasterId());
                v.setDetailId(l.getId());
                v.setLotId(l.getLotId());
                v.setLotCode(l.getLotCode());
                v.setFormDate(l.getFormDate());
                v.setDayworkId(l.getDayworkId());
                v.setFormCode(l.getFormCode());
                v.setProductDescription(l.getProductDescription());
                v.setTechnologicalProcessId(l.getTechnologicalProcessId());
                v.setSupplierId(l.getSupplierId());
                v.setSupplierName(l.getSupplierName());
                v.setDeliveryMethod(l.getDeliveryMethod());
                v.setProductId(l.getProductId());
                v.setTechnologyVersion(l.getTechnologyVersion());
                v.setPackagingMethod(l.getPackagingMethod());
                v.setProductNum(l.getProductNum());
                v.setTenantId(l.getTenantId());
                detailProcesses.add(v);
                BizDayworkItem item = new BizDayworkItem();
                item.setDayworkId(l.getDayworkId());
                item.setOutsourceDetailId(l.getId());
                item.setLotId(l.getLotId());
                item.setProcessId(v.getProcessId());
                item.setProcessStepNumber(v.getProcessStepNumber());
                item.setStatus("1");
                item.setProdNum(l.getProductNum());
                item.setDeptId(dept != null ? dept.getDeptId() : null);
                item.setDeptName(dept != null ? dept.getDeptName() : null);
                item.setStartTime(new Date());
                item.setDeptCode(dept != null ? dept.getDeptCode() : null);
                item.setProductionPlanDetailId(l.getProductionPlanDetailId());
                item.setTechnologicalProcessId(l.getTechnologicalProcessId());
                item.setTechnologicalProcessDetailId(v.getTechnologicalProcessDetailId());
                item.setIsWx(1);
                item.setTenantId(getTenantId());
                item.setNickName(finalBizOutsourcedOrder.getSupplierName());
                items.add(item);
            });

        });
        if(bizOutsourcedOrder.getPackagingMethod().equals("2")){
            //查询一个未使用的无箱
            BizCarrier isNoneCarrier = bizCarrierService.getIsNoneCarrier();
            if (isNoneCarrier == null) {
                bizOutsourcedOrderService.removeById(finalBizOutsourcedOrder);
                throw new RuntimeException("没有可绑定的载具，请联系管理员添加");
            }
            List<BizDayworkCarrier> bindCarrierList = new ArrayList<>();
            dayworks.forEach(l -> {
                BizDayworkCarrier dayworkCarrier = new BizDayworkCarrier();
                dayworkCarrier.setCarrierId(isNoneCarrier.getId());
                dayworkCarrier.setDayworkId(l.getId());
                dayworkCarrier.setCarrierCode(isNoneCarrier.getCode());
                bindCarrierList.add(dayworkCarrier);
            });
            iBizDayworkCarrierService.saveBatch(bindCarrierList);
            details.forEach(item->{
                    item.setNewCarrierName(isNoneCarrier.getCode());
                    item.setNewCarrier(isNoneCarrier.getId()+"|"+isNoneCarrier.getCode());
                    item.setNewCarrierCount(1);
            });
        }
        bizDayworkService.saveBatch(dayworks);
        furnaceNoInfoService.saveBatch(furnaceNoInfos);
        bizOutsourcedOrderDetailService.saveBatch(details);
        bizOutsourcedOrderDetailProcessService.saveBatch(detailProcesses);
        bizDayworkItemService.saveBatch(items);
        bizOutsourcedRecordsService.saveBatch(records);
    }

    private BizOutsourcedOrder generateQrCodeImg(String content, String fileName, BizOutsourcedOrder outsourcedOrder) {
        BufferedImage qrImage = QrCodeDemo.createQrCode(null, "二维码", content, "" );
        String dir = uploadPath + "qcCode/outsourcedOrder/qrcode/";
        // 判断文件夹是否存在，假设不存在创建你文件夹
        File file = new File(dir);
        if (!file.exists()) {
            file.mkdirs();
        }
        String path = uploadPath + "qcCode/outsourcedOrder/qrcode/" + fileName + ".png";
        outsourcedOrder.setQrcode(content);
        outsourcedOrder.setQrcodeUrl("/profile/upload/qcCode/outsourcedOrder/qrcode/" + fileName + ".png");
        QrCodeDemo.createImage(qrImage, path);
        return outsourcedOrder;
    }

    private BizOutsourcedOrder generateBarCodeImg(String content, String fileName, BizOutsourcedOrder outsourcedOrder) {
        BufferedImage qrImage = BarCodeDemo.createQrCode(null, "二维码", content, "" );
        String dir = uploadPath + "qcCode/outsourcedOrder/barcode/";
        // 判断文件夹是否存在，假设不存在创建你文件夹
        File file = new File(dir);
        if (!file.exists()) {
            file.mkdirs();
        }
        String path = uploadPath + "qcCode/outsourcedOrder/barcode/" + fileName + ".png";
        outsourcedOrder.setBarcodeUrl("/profile/upload/qcCode/outsourcedOrder/barcode/" + fileName + ".png");
        outsourcedOrder.setBarcode(content);
        BarCodeDemo.createImage(qrImage, path);
        return outsourcedOrder;
    }

}
