package cn.ezhizao.project.business.controller;

import cn.ezhizao.common.utils.SecurityUtils;
import cn.ezhizao.common.utils.StringUtils;
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 cn.ezhizao.project.business.domain.*;
import cn.ezhizao.project.business.service.*;
import cn.ezhizao.project.system.domain.SysDept;
import cn.ezhizao.project.system.domain.SysDeptUser;
import cn.ezhizao.project.system.domain.SysDictData;
import cn.ezhizao.project.system.domain.SysUser;
import cn.ezhizao.project.system.mapper.SysDeptMapper;
import cn.ezhizao.project.system.service.ISysDeptService;
import cn.ezhizao.project.system.service.ISysDeptUserService;
import cn.ezhizao.project.system.service.ISysDictTypeService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import java.util.List;

/**
 * 报工Controller
 *
 * @author ezhizao
 * @date 2023-11-29
 */
@RestController
@RequestMapping("/business/specialDaywork")
public class BizSpecialDayworkController extends BaseController {
    @Resource
    private IBizDayworkService bizDayworkService;

    @Resource
    private IBizProductionResourceGroupService bizProductionResourceGroupService;

    @Resource
    private IBizTurnoverService iBizTurnoverService;

    @Resource
    private IBizCarrierService iBizCarrierService;

    @Resource
    private ISysDeptService iSysDeptService;

    @Resource
    private IBizProductionResourceGroupSubPlanService bizProductionResourceGroupSubPlanService;
    @Resource
    private IBizProcessInspecionService bizProcessInspecionService;

    @Resource
    private IBizWorkshopTurnoverService iBizWorkshopTurnoverService;

    @Resource
    private SysDeptMapper sysDeptMapper;

    @Resource
    private IBizCarrierService bizCarrierService;

    @Resource
    private IBizTechnologicalProcessDetailService bizTechnologicalProcessDetailService;

    @Resource
    private IBizLotTechnologicalProcessDetailService bizTechnologicalAmendDetailService;

    @Resource
    private IBizLotTechnologicalProcessDetailService bizLotTechnologicalProcessDetailService;

    @Resource
    private IBizDayworkCarrierService bizDayworkCarrierService;

    @Resource
    private IBizProductionResourceGroupDetailService bizProductionResourceGroupDetailService;

    @Resource
    private IBizDayworkItemService bizDayworkItemService;
    @Resource
    private IBizDayworkItemRejectService bizDayworkItemRejectService;

    @Resource
    private IBizProductionPlanDetailService bizProductionPlanDetailService;
    @Resource
    private IBizFurnaceNoInfoService bizFurnaceNoInfoService;
    @Resource
    private IBizLotService bizLotService;

    @Resource
    private IBizCarrierCategoryService carrierCategoryService;

    @Resource
    private IBizDeptProcessService bizDeptProcessService;

    @Resource
    private ISysDictTypeService dictTypeService;

    @Resource
    HttpServletRequest request;
    @Resource
    private IBizTakeStockPeriodService bizTakeStockPeriodService;

    @Resource
    private ISysDeptService deptService;
    @Resource
    private IBizProcessService bizProcessService;
    @Resource
    private IBizDayworkItemExamineService bizDayworkItemExamineService;
    @Resource
    private IBizDayworkAuxiliaryItemService bizDayworkAuxiliaryItemService;
    @Resource
    private IBizDayworkAuxiliaryItemRejectService bizDayworkAuxiliaryItemRejectService;

    /**
     * 查询报工列表
     */
    @Log(title = "特殊报工列表查询", businessType = BusinessType.SELECT)
    @PreAuthorize("@ss.hasPermi('business:specialDaywork:list')")
    @GetMapping("/list")
    public TableDataInfo list(BizDayworkItem bizDayworkItem) {
        /**
         * 查询特殊报工信息，先查询所有是特殊报工(is_special=1)的明细(daywork_item)的数据查出来，查询时跟据创建时间正序排列
         */

        if (bizDayworkItem.getSpecialStartTime() != null) {
            bizDayworkItem.setSpecialStartTime(bizDayworkItem.getSpecialStartTime() + " 00:00:00");
        }
        if (bizDayworkItem.getSpecialEndTime() != null) {
            bizDayworkItem.setSpecialEndTime(bizDayworkItem.getSpecialEndTime() + " 23:59:59");
        }
        //查询出所有特殊报工的报工信息
        List<BizDayworkItem> dayworkItemList = bizDayworkItemService.getSpecialList(bizDayworkItem);

        //根据报工信息筛选出符合条件的dayworkId
        List<Long> specialIds = bizDayworkItemService.screenDayworkItem(dayworkItemList, bizDayworkItem);

        if (specialIds.isEmpty()) {
            return getDataTable(new ArrayList<>());
        }
        //分页请求
        startPage();
        //查询daywork信息
        List<BizDaywork> dayworks = bizDayworkService.selectScreenDaywork(specialIds);

        //如果没有数据则返回空
        if (dayworks.isEmpty()) {
            return getDataTable(new ArrayList<>());
        }

        //查询工序信息
        dayworks = selectDayworkProcess(dayworks);

        //查询产品信息
        dayworks = selectProductionPlanDetail(dayworks);

        //查询箱号信息
        dayworks = selectCarrierCode(dayworks);

        /*
          查询合格数和废品信息需要先查询到每条daywork对应的当前工序的报工信息daywork_item
          因为需要进行合格数计算所以只查询状态为2和3的数据
         */
        List<BizDayworkItem> dayworkItems = bizDayworkItemService.selectListOfspecial(dayworks);

        if (!dayworkItems.isEmpty()) {
            //查询合格数和投产数
            dayworks = selectNumber(dayworks, dayworkItems);
            //查询废品数
            dayworks = selectRejectsNumber(dayworks, dayworkItems);
            //将该工序所有报工人员用保存到一个字符串中用“，”分割
            for (BizDaywork daywork :dayworks) {
                Set<String> nameSet=new HashSet<>();
                for(BizDayworkItem dayworkItem:dayworkItems){
                    if(daywork.getId().equals(dayworkItem.getDayworkId())){
                        nameSet.add(dayworkItem.getNickName());
                    }
                }
                if(!nameSet.isEmpty()){
                    daywork.setItemNames(String.join(", ", nameSet));
                    daywork.setItemNames(daywork.getItemNames().trim());
                }

            }

        }

        return getDataTable(dayworks);
    }

    @Log(title = "特殊报工首序报工查询计划单", businessType = BusinessType.SELECT)
    @GetMapping("/selectProductList")
    public TableDataInfo selectProductList(BizProductionPlanDetail bizProductionPlanDetail) {
        List<BizProductionPlanDetail> planDetailList = bizProductionPlanDetailService.selectSpecialFirstProductDetail(bizProductionPlanDetail);
        return getDataTable(planDetailList);
    }

    @Log(title = "特殊报工首序报工查询可用批次", businessType = BusinessType.SELECT)
    @GetMapping("/lotList")
    public TableDataInfo list(BizLot bizLot) throws NoSuchFieldException, IllegalAccessException {
        List<BizLot> list = bizLotService.specialGetLotList(bizLot);
        return getDataTable(list);
    }


    @Log(title = "特殊报工非首序报工查询批次", businessType = BusinessType.SELECT)
    @GetMapping("/getNoFirstLotList")
    public TableDataInfo getNoFirstLotList(BizDaywork bizDaywork) throws NoSuchFieldException, IllegalAccessException {
        //根据工段查询出当前在对应工段的批次
        List<BizDaywork> dayworks = bizDayworkService.query().eq("dept_id", bizDaywork.getDeptId()).list();
        List<Long> dayworkIds = dayworks.stream().map(BizDaywork::getId).collect(Collectors.toList());
        List<BizDayworkItem> dayworkItems = bizDayworkItemService.selectBydayworkId(dayworkIds);
        //根据daywork查询出所有dayworkItem信息按照创建时间排序
        //按照daywork_id分组
        List<List<BizDayworkItem>> groupedByDayworkId = dayworkItems.stream()
                .collect(Collectors.groupingBy(BizDayworkItem::getDayworkId, LinkedHashMap::new, Collectors.toList()))
                .values()
                .stream()
                .map(ArrayList::new) // 如果需要，将分组的列表转换成 ArrayList
                .collect(Collectors.toList());
        //判断每组最新一条数据状态是否为4或者7(为4或者7表示已经周转申请或者已经送达可以加工，5和6为搬运进行周转暂不做处理)
        if (bizDaywork.getIds() == null) {
            bizDaywork.setIds(new ArrayList<>());
        }
        for (List<BizDayworkItem> group : groupedByDayworkId) {
            if (!group.isEmpty() && (group.get(0).getStatus().equals("4") || group.get(0).getStatus().equals("7"))) {

                bizDaywork.getIds().add(group.get(0).getDayworkId());
            }
        }
        if (bizDaywork.getIds().isEmpty()) {
            return getDataTable(new ArrayList<>());
        }
        List<BizDaywork> list = bizDayworkService.getNoFirstLotList(bizDaywork);

        return getDataTable(list);

    }


    /**
     * 查询deptProcess列表
     */
    @Log(title = "特殊报工首序报工查询工段内工序信息", businessType = BusinessType.SELECT)
    @PostMapping("/selectDeptProcessList")
    public AjaxResult deptProcessList(@RequestBody Map<String, Object> data) throws NoSuchFieldException, IllegalAccessException {
        List<String> statusList = Arrays.asList("0", "1", "2");
        Long deptId = Long.parseLong(data.get("deptId").toString());
        List<BizDeptProcess> deptProcesses = bizDeptProcessService.query().eq("dept_id", deptId).list();
        List<Long> deptProcessIds = deptProcesses.stream().map(BizDeptProcess::getProcessId).collect(Collectors.toList());

        long dayworkId = 0L;
        if (data.get("dayworkId") != null) {
            dayworkId = Long.parseLong(data.get("dayworkId").toString());
        }

        long planDetailId = 0L;
        if (data.get("planDetailId") != null) {
            planDetailId = Long.parseLong(data.get("planDetailId").toString());
            BizProductionPlanDetail productionPlanDetail = bizProductionPlanDetailService.getById(planDetailId);
            List<BizTechnologicalProcessDetail> technologicalProcessDetails = bizTechnologicalProcessDetailService.query()
                    .eq("technological_process_id", productionPlanDetail.getTechnologicalProcessId())
                    .ne("tenant_id", 9)
                    .in("process_id", deptProcessIds)
                    .orderByAsc("process_step_number")

                    .list();

            return success(technologicalProcessDetails);
        }
        return success(deptProcesses);
    }

    /**
     * 周转前查询报工信息
     */
    @Log(title = "特殊报工周转前查询报工信息", businessType = BusinessType.SELECT)
    @PostMapping("/getDayWorkItemList")
    public AjaxResult getDayWorkItemList(@RequestBody List<BizDaywork> dayworkList) throws NoSuchFieldException, IllegalAccessException {
        /**
         * 周转前查询报工信息，先根据dayworkId查询出所有特殊报工信息根据创建时间和id排序，因为同一道工序的特殊报工创建时间可能相同
         * 再将报工信息按照daywork进行分组，将每组最新一条数据存到集合中
         */
        List<BizDayworkItem> dayworkItems = bizDayworkItemService.query().in("daywork_id", dayworkList.stream().map(BizDaywork::getId).collect(Collectors.toList()))
                .eq("is_special", 1).orderByDesc("create_time").orderByDesc("id").list();

        // 使用Collectors.groupingBy来分组
        Map<Long, List<BizDayworkItem>> groupedItems = dayworkItems.stream()
                .collect(Collectors.groupingBy(BizDayworkItem::getDayworkId));

        // 将分组结果转换为List<List<BizDayworkItem>>
        List<List<BizDayworkItem>> groupedByDayworkId = new ArrayList<>(groupedItems.values());

        List<BizDayworkItem> dayworkItemList = new ArrayList<>();
        for (List<BizDayworkItem> items : groupedByDayworkId) {
            dayworkItemList.add(items.get(0));
        }

        if (dayworkItemList.isEmpty()) {
            return error("报工信息错误，请检查数据");
        }
        return success(dayworkItemList);
    }

    /**
     * 查询该批次对应的工序
     */
    @Log(title = "特殊报工首序报工查询批次工序信息", businessType = BusinessType.SELECT)
    @GetMapping("/getProcessListByLot")
    public AjaxResult getProcessListByLot(BizLot bizLot) throws NoSuchFieldException, IllegalAccessException {
        //该批是否废品回用
        if (bizLot.getIsWasteRecycling() == 1 || bizLot.getIsAmend() == 1) {
            QueryWrapper<BizLotTechnologicalProcessDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("lot_technological_process_id", bizLot.getTechnologicalProcessId());
            //去掉备料的序1
            wrapper.ne("process_id", 0);
            wrapper.ne("process_id", 1);
            wrapper.orderByAsc("process_step_number");
            List<BizLotTechnologicalProcessDetail> list = bizLotTechnologicalProcessDetailService.list(wrapper);
            return success(list);
        }
        //查原始工艺工序表
        else {
            QueryWrapper<BizTechnologicalProcessDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("technological_process_id", bizLot.getTechnologicalProcessId());
            wrapper.ne("process_id", 0);
            wrapper.ne("process_id", 1);
            wrapper.ne("tenant_id", 9);
            wrapper.orderByAsc("process_step_number");
            return success(bizTechnologicalProcessDetailService.list(wrapper));
        }
    }

    @Log(title = "特殊报工非首序报工查询批次工序和炉号信息", businessType = BusinessType.SELECT)
    @GetMapping("/getDayworkItemAndFurnace")
    public AjaxResult getDayworkItemAndFurnace(BizDaywork bizDaywork) {
        //查询出所有报工数据
        List<BizDayworkItem> allBizDayworkItem = bizDayworkItemService.query().eq("daywork_id", bizDaywork.getId()).orderByDesc("create_time").list();
        //查询所有废品信息
        List<BizDayworkItemReject> rejectList = bizDayworkItemRejectService.query().in("daywork_item_id", allBizDayworkItem.stream().map(BizDayworkItem::getId).collect(Collectors.toList())).orderByDesc("create_time").list();

        for (BizDayworkItem item : allBizDayworkItem) {
            item.setRejectList(new ArrayList<>());
            for (BizDayworkItemReject reject : rejectList) {
                if (reject.getDayworkItemId().equals(item.getId())) {
                    item.getRejectList().add(reject);
                }
            }
        }
        //查询炉号信息
        List<BizFurnaceNoInfo> furnaceNoInfos = bizFurnaceNoInfoService.query().eq("daywork_id", bizDaywork.getId()).list();

        if (furnaceNoInfos.isEmpty()) {
            return error("查询不到炉号信息");
        }

        //查询箱号信息
        List<BizDayworkCarrier> carrierList = bizDayworkCarrierService.query().eq("daywork_id", bizDaywork.getId()).eq("is_changed", 0).eq("process_inspection_id", 0).list();
        bizDaywork.setFurnaceNoInfo(furnaceNoInfos.get(0));
        bizDaywork.setDayworkItemList(allBizDayworkItem);
        bizDaywork.setDayworkCarriers(carrierList);

        return success(bizDaywork);
    }

    @Log(title = "特殊报工查询箱号", businessType = BusinessType.SELECT)
    @GetMapping("/specialCarriers")
    public TableDataInfo list(BizCarrier data) throws NoSuchFieldException, IllegalAccessException, JsonProcessingException {
//        startPage();
        List<BizCarrier> list = iBizCarrierService.getSpecialList(data);
        return getDataTable(list);
    }


    @Log(title = "特殊报工周转页面查询周转工段", businessType = BusinessType.SELECT)
    @GetMapping("/listByPlanDetailsId")
    public AjaxResult listByPlanDetailsId(SysDept dept) throws NoSuchFieldException, IllegalAccessException {
        //判断该批是否是废品回用
        List<SysDept> departments = new ArrayList<>();
        if (dept.getIsAmend() == 1 || dept.getIsWasteRecycling() == 1) {
            BizLot bizLot = bizLotService.query().eq("id", dept.getLotId()).list().get(0);
            dept.setLotTechnologicalProcessId(bizLot.getTechnologicalProcessId());
            departments = deptService.selectDeptListByTechnologyWasteRecyclingId(dept);
        } else {
            departments = deptService.selectDeptListByPlanDetailsId(dept);
        }
        return success(departments);
    }

    @Log(title = "特殊报工查询工段员工", businessType = BusinessType.SELECT)
    @GetMapping("/specialUserList")
    public TableDataInfo specialUserList(BizProductionResourceGroupDetail data) throws NoSuchFieldException, IllegalAccessException, JsonProcessingException {
        startPage();
        List<BizProductionResourceGroupDetail> list = bizProductionResourceGroupDetailService.specialUserList(data);
        //对查询结果进行去重
        Map<Long, BizProductionResourceGroupDetail> map = list.stream()
                .collect(Collectors.toMap(
                        BizProductionResourceGroupDetail::getCommonId,
                        Function.identity(),
                        (existing, replacement) -> existing // 如果有重复的commonId，保留现有的记录
                ));

        List<BizProductionResourceGroupDetail> uniqueByCommonId = new ArrayList<>(map.values());
        return getDataTable(uniqueByCommonId);
    }

    @Log(title = "特殊报工查询工段设备", businessType = BusinessType.SELECT)
    @GetMapping("/specialEquipmentList")
    public TableDataInfo specialEquipmentList(BizProductionResourceGroupDetail data) throws NoSuchFieldException, IllegalAccessException, JsonProcessingException {
        //查询出所有分配了对应计划单的资源组中的设备
        List<BizProductionResourceGroupDetail> list = bizProductionResourceGroupDetailService.specialEquipmentList(data);
        //查询员工所在的所有资源组数据
        List<BizProductionResourceGroupDetail> userList = bizProductionResourceGroupDetailService.query().eq("common_id", data.getUserId()).list();

        // 将查询结果添加到Set集合中进行去重
        Set<BizProductionResourceGroupDetail> set = new HashSet<>();
        //将设备和人员资源组相同的数据取出
        for (BizProductionResourceGroupDetail equipment : list) {
            for (BizProductionResourceGroupDetail user : userList) {
                if (equipment.getProductionResourceGroupId().equals(user.getProductionResourceGroupId())) {
                    BizProductionResourceGroupDetail detail = new BizProductionResourceGroupDetail();
                    detail.setCommonCode(equipment.getCommonCode());
                    detail.setCommonId(equipment.getCommonId());
                    set.add(detail);
                }

            }
        }

        List<BizProductionResourceGroupDetail> uniqueList = new ArrayList<>(set);
        return getDataTable(uniqueList);
    }


    @Log(title = "特殊报工首序确认批次信息", businessType = BusinessType.SELECT)
    @PostMapping("/certainLotInfo")
    public AjaxResult certainLotInfo(@RequestBody BizDaywork bizDaywork) throws NoSuchFieldException, IllegalAccessException {
        //查询出该生产计划的投产总批数
        Integer lotNumber = bizDayworkService.getLotNumber(bizDaywork.getProductionPlanDetailId());
        //查询出该生产计划的当前生产批数
        Integer getdayworkNum = bizDayworkService.getdayworkNum(bizDaywork.getProductionPlanDetailId());
        int num = (getdayworkNum != null) ? getdayworkNum : 0; // 如果 dayworkNum 为 null，则赋值为默认值 0
        if (num < lotNumber || (bizDaywork.getIsWasteRecycling() != null && bizDaywork.getIsWasteRecycling() == 1) || bizDaywork.getFromId() != 0 || bizDaywork.getIsSuperaddition() != 0) {
            List<BizDaywork> lotId = bizDayworkService.query().eq("lot_id", bizDaywork.getLotId()).list();
            if (!lotId.isEmpty()) {
                return error("批次号已被领取");
            }
        } else {
            return error("当前计划单暂无新批次，请重新确认生产计划");
        }
        return success();
    }

    @Log(title = "特殊报工周转申请", businessType = BusinessType.INSERT)
    @PostMapping("/turnover")
    @Transactional
    @PreAuthorize("@ss.hasPermi('business:specialDaywork:turnaround')")
    public AjaxResult turnover(@RequestBody List<BizDayworkItem> dayworkItems) throws NoSuchFieldException, IllegalAccessException {
        //判断当前是否在盘点
        BizTakeStockPeriod bizTakeStockPeriod = bizTakeStockPeriodService.query().eq("status",1).one();
        if(bizTakeStockPeriod!=null && bizTakeStockPeriod.getStatus() == 1) {
            return error("当前在盘点，禁止周转");
        }
        /**
         * 根据传来的报工数据查询，查询是否存在一箱多批的情况，如果存在一项多批，查询是否在本次周转申请内，如果不在查询出对应的最后一条报工
         * 来进行赋值，将最后的结果放入传入的集合中。
         * 再根据下序部门的Id来查询是否需要自动分配如果自动分配则部门所有的资源组信息，根据需要保存的报工信息来查询是否已经分配了资源组如果没分配则分配对应的生产计划
         * 因为多批进行周转时肯定是同一个计划单才能一起进行周转所以自动分配的时候只需要用到第一条数据就行
         */
        // 设置工时
        // 获取箱子关联的所有批次
        boolean batch = true;
        BizDayworkItem bizDayworkItem = dayworkItems.get(0);

        //查询出所有周转批次的箱子
        List<BizDayworkCarrier> dayworkCarriers = bizDayworkCarrierService.query().eq("is_changed", 0).eq("process_inspection_id", 0L).in("daywork_id", dayworkItems.stream().map(BizDayworkItem::getDayworkId).collect(Collectors.toList())).list();
        // 再根据上面获得到的数据，通过箱子的id（carrier_id），再进行查找，有多少个批次与该箱子绑定，这是因为存在一箱多批的情况。这样就获得到了所有的批次
        List<BizDayworkCarrier> allCarries = bizDayworkCarrierService.query().eq("process_inspection_id", 0L).eq("is_changed", 0).in("carrier_id", dayworkCarriers.isEmpty() ? Collections.singletonList(0L) : dayworkCarriers.stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList())).list();

        //比较查询出的数据查看是否存在一箱多批次并且不在此次周转申请列表中
        List<Long> dayworkIds = allCarries.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toList());

        // 使用 Stream API 找出那些不在 dayworkItems 中的 dayworkIds
        List<Long> missingDayworkIds = dayworkIds.stream()
                .filter(id -> dayworkItems.stream()
                        .noneMatch(item -> Objects.equals(item.getDayworkId(), id)))
                .collect(Collectors.toList());

        if (!missingDayworkIds.isEmpty()) {
            // 根据获取到的所有批次的id，查询出所有批次的报工信息，并且状态是【"0", "1", "2", "3"】，按状态值倒序、创建日期的倒序，对数据进行排序，得到的数据是还未周转的数据。
            // 后续会通过该集合，获取某批次的最后一条报工信息
            List<BizDayworkItem> bizDayworkItems = bizDayworkItemService.query().in("daywork_id", missingDayworkIds).in("status", Arrays.asList("0", "1", "2", "3")).orderByDesc("status").orderByDesc("create_time").orderByDesc("id").list();

            // 根据获取到的所有批次的id，查询出所有批次的报工信息，不需要判断状态
            List<BizDayworkItem> bizDayworkItemList = bizDayworkItemService.query().in("daywork_id", allCarries.isEmpty() ? Collections.singletonList(0L) : allCarries.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toList())).list();

            // 获取所有的 daywork 数据集合
            List<BizDaywork> bizDayworks = bizDayworkService.query().in("id", allCarries.isEmpty() ? Collections.singletonList(0L) : allCarries.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toList())).list();

            // 遍历 daywork 数据集合
            for (BizDaywork v : bizDayworks) {
                // 获取该批次的最后一条报工
                BizDayworkItem lastItem = bizDayworkItems.stream().filter(l -> l.getDayworkId().equals(v.getId())).findFirst().orElse(null);
                // 如果最后一条报工信息存在
                if (lastItem != null) {
                    // 根据当前批次的id，获取该批次下的工序id与最后一条报工的工序id相同的所有报工信息
                    // 因为同一工序可能存在多次报工，所以需要获取该批次下，该工序的所有报工信息，后续会进行合格数的统计
                    List<BizDayworkItem> allItem = bizDayworkItemList.stream().filter(l -> l.getDayworkId().equals(v.getId()) && l.getTechnologicalProcessDetailId().equals(lastItem.getTechnologicalProcessDetailId())).collect(Collectors.toList());
                    // 根据获得到的某工序的报工信息，进行合格数统计
                    Integer lot = allItem.stream().mapToInt(BizDayworkItem::getQualifiedNum).sum();

                    // 实例化一个报工信息对象，用于保存【周转】的报工记录
                    BizDayworkItem bizItem = new BizDayworkItem();
                    bizItem.setDayworkId(lastItem.getDayworkId());
                    bizItem.setProcessId(lastItem.getProcessId());
                    bizItem.setTechnologicalProcessDetailId(lastItem.getTechnologicalProcessDetailId());
                    bizItem.setStatus(bizDayworkItem.getStatus());


                    // 如果是单批单改换，则设置form_daywork_item_id为1，表示没有原来的报工
                    if (v.getIsAmend() == 1) {
                        bizItem.setFormDayworkItemId(1L);
                    }
                    bizItem.setLotId(v.getLotId());
                    bizItem.setLotCode(v.getLotCode());
                    SysUser user = SecurityUtils.getLoginUser().getUser();
                    bizItem.setUserId(user.getUserId());
                    bizItem.setUserName(user.getUserName());
                    bizItem.setNickName(user.getNickName());
                    bizItem.setWorkingHours(0L);
                    bizItem.setDeptId(lastItem.getDeptId());
                    bizItem.setIsSpecial(lastItem.getIsSpecial());
                    bizItem.setSpecialIsFirst(lastItem.getSpecialIsFirst());
                    bizItem.setTenantId(lastItem.getTenantId());
                    bizItem.setProductionPlanDetailId(lastItem.getProductionPlanDetailId());
                    bizItem.setProductionPlanId(lastItem.getProductionPlanId());
                    bizItem.setProductionPlanDetailSubDetailId(lastItem.getProductionPlanDetailSubDetailId());
                    bizItem.setProductionPlanDetailSubDetailEquipmentId(lastItem.getProductionPlanDetailSubDetailEquipmentId());
                    bizItem.setQualifiedNum(lot);
                    bizItem.setTechnologicalProcessId(lastItem.getTechnologicalProcessId());
                    bizItem.setProdNum(lot);
                    bizItem.setEquipmentDetailId(lastItem.getEquipmentDetailId());
                    bizItem.setEquipmentDetailCode(lastItem.getEquipmentDetailCode());
                    bizItem.setDeptId(bizDayworkItem.getDeptId());
                    bizItem.setDeptName(bizDayworkItem.getDeptName());
                    bizItem.setStartTime(bizDayworkItem.getStartTime());
                    bizItem.setTurnoverId(bizDayworkItem.getTurnoverId());
                    bizItem.setTurnoverType(bizDayworkItem.getTurnoverType());
                    bizItem.setTurnoverArea(bizDayworkItem.getTurnoverArea());
                    bizItem.setPlaceId(bizDayworkItem.getPlaceId());
                    bizItem.setPlace(bizDayworkItem.getPlace());
                    bizItem.setProcessStepNumber(lastItem.getProcessStepNumber());
                    bizItem.setIsSortPackaging(bizDayworkItem.getIsSortPackaging());
                    dayworkItems.add(bizItem);
                }
            }
        }

        // 如果报工状态为：7（已送达）或者4（待周转），则需要设置对应的daywork的当前部门id，以及合格数
        // 这里的状态值4/7，是由前端传递过来的。

        List<BizDaywork> dayworkList = bizDayworkService.query().in("id", dayworkItems.stream().map(BizDayworkItem::getDayworkId).collect(Collectors.toList())).list();

        SysDept sysDept = sysDeptMapper.selectDeptById(bizDayworkItem.getDeptId());
        for (BizDaywork daywork : dayworkList) {
            for (BizDayworkItem item : dayworkItems) {
                if (daywork.getId().equals(item.getDayworkId())) {
                    item.setDeptId(sysDept.getDeptId());
                    item.setDeptName(sysDept.getDeptName());
                    item.setQualifiedNum(daywork.getProcessQualifiedNum());
                    item.setCreateTime(null);
                    daywork.setDeptId(item.getDeptId());
                    daywork.setTemporaryProcessQualifiedNum(daywork.getProcessQualifiedNum());
                }
            }
        }
        batch = bizDayworkItemService.saveOrUpdateBatch(dayworkItems);
        //下序批量审核
        List<BizDayworkItem> needDayworkItemExamineList = dayworkItems.stream().filter(v -> v.getIsSortPackaging() == 1).collect(Collectors.toList());
        if(!needDayworkItemExamineList.isEmpty()) {
            List<Long> productionPlanDetailIds = dayworkItems.stream().map(BizDayworkItem::getProductionPlanDetailId).collect(Collectors.toList());
            //拿到产品id
            List<BizProductionPlanDetail> productionPlanDetailList = bizProductionPlanDetailService.query().in("id", productionPlanDetailIds).list();
            //拿到申请审核的工段id
            List<Long> dayworkId = dayworkItems.stream().map(BizDayworkItem::getDayworkId).collect(Collectors.toList());
            //拿到工序名称
            List<Long> processIds = dayworkItems.stream().map(BizDayworkItem::getProcessId).collect(Collectors.toList());
            List<BizProcess> processList = bizProcessService.query().in("id", processIds).list();
            List<BizDaywork> bizDayworkList = bizDayworkService.query().in("id", dayworkId).list();
            List<BizDayworkItemExamine> addExamineList = new ArrayList<>();
            //先判断是否已经添加了，如果添加了则删除
            List<BizDayworkItemExamine> examineList = bizDayworkItemExamineService.query().in("daywork_id", dayworkId).list();
            if(!examineList.isEmpty()) {
                bizDayworkItemExamineService.removeBatchByIds(examineList);
            }
            needDayworkItemExamineList.forEach(item->{
                BizDayworkItemExamine examine = new BizDayworkItemExamine();
                examine.setDayworkId(item.getDayworkId());
                examine.setDayworkItemId(item.getId());
                examine.setDeptId(sysDept.getDeptId());
                examine.setProductionPlanDetailId(item.getProductionPlanDetailId());
                examine.setProductDescription(productionPlanDetailList.stream().filter(v->v.getId().equals(examine.getProductionPlanDetailId())).collect(Collectors.toList()).get(0).getProductDescription());
                examine.setLotId(item.getLotId());
                examine.setLotCode(bizDayworkList.stream().filter(v->v.getId().equals(examine.getDayworkId())).collect(Collectors.toList()).get(0).getLotCode());
                examine.setProductId(productionPlanDetailList.stream().filter(v->v.getId().equals(examine.getProductionPlanDetailId())).collect(Collectors.toList()).get(0).getProductId());
                examine.setTechnologicalProcessId(item.getTechnologicalProcessId());
                examine.setTechnologicalProcessDetailId(item.getTechnologicalProcessDetailId());
                examine.setProcessId(item.getProcessId());
                examine.setProcessAlias(processList.stream().filter(v->v.getId().equals(examine.getProcessId())).collect(Collectors.toList()).get(0).getProcessAlias());
                examine.setStatus(0);
                addExamineList.add(examine);
            });
            bizDayworkItemExamineService.saveBatch(addExamineList);
        }
        bizDayworkService.saveOrUpdateBatch(dayworkList);


        // 自动派活
        if (sysDept.getAutoAllocation() == 1) {
            // 查资源组
            List<BizProductionResourceGroup> productionResourceGroupList = bizProductionResourceGroupService.list(new QueryWrapper<BizProductionResourceGroup>().eq("dept_id", bizDayworkItem.getDeptId()).eq("is_deactivate", 0));

            //查询是否已经分配资源组
            BizProductionResourceGroupSubPlan groupSubPlan = new BizProductionResourceGroupSubPlan();
            groupSubPlan.setDeptId(bizDayworkItem.getDeptId());
            groupSubPlan.setProductionPlanDetailId(bizDayworkItem.getProductionPlanDetailId());

            List<BizProductionResourceGroupSubPlan> groupSubPlanList = bizProductionResourceGroupSubPlanService.getAotList(groupSubPlan);
            //如果没分配
            if (groupSubPlanList.isEmpty()) {
                //查产品id
                BizProductionPlanDetail productionPlanDetail = bizProductionPlanDetailService.getOne(new QueryWrapper<BizProductionPlanDetail>().eq("id", bizDayworkItem.getProductionPlanDetailId()));
                //存放保存的subPlanList
                List<BizProductionResourceGroupSubPlan> subPlanList = new ArrayList<>();
                for (BizProductionResourceGroup info : productionResourceGroupList) {
                    BizProductionResourceGroupSubPlan subPlan = new BizProductionResourceGroupSubPlan();
                    subPlan.setProductId(productionPlanDetail.getProductId());
                    subPlan.setProductionPlanDetailId(bizDayworkItem.getProductionPlanDetailId());
                    subPlan.setTechnologicalProcessId(bizDayworkItem.getTechnologicalProcessId());
                    subPlan.setResourceGroupId(info.getId());
                    subPlan.setDeptId(bizDayworkItem.getDeptId());
                    subPlan.setResourceGroupCode(info.getCode());
                    subPlanList.add(subPlan);
                }
                bizProductionResourceGroupSubPlanService.saveBatch(subPlanList);

            }
        }

        return success(batch);
    }

    /**
     * 判断一箱多批状态是否有未完成
     */


    @Log(title = "特殊报工周转前查询序检状态和一箱多批完成状态", businessType = BusinessType.SELECT)
    @PostMapping("/carrierFinishedCheck")
    public AjaxResult carrierFinishedCheck(@RequestBody List<BizDaywork> bizDayworks) {
        /**
         * 周转前判断是否序检完成，根据最后一条报工来查询序检状态，如果没有序检或者序检合格可以周转
         * 如果一箱多批判断是否全部完成
         */

        //查询出所有周转批次的箱子
        List<BizDayworkCarrier> dayworkCarriers = bizDayworkCarrierService.query().eq("is_changed", 0).eq("process_inspection_id", 0L).in("daywork_id", bizDayworks.stream().map(BizDaywork::getId).collect(Collectors.toList())).list();
        if(dayworkCarriers.isEmpty()){
            return AjaxResult.error("无载具，请先绑定载具");
        }
        // 再根据上面获得到的数据，通过箱子的id（carrier_id），再进行查找，有多少个批次与该箱子绑定，这是因为存在一箱多批的情况。这样就获得到了所有的批次
        List<BizDayworkCarrier> allCarries = bizDayworkCarrierService.query().eq("process_inspection_id", 0L).eq("is_changed", 0).in("carrier_id", dayworkCarriers.isEmpty() ? Collections.singletonList(0L) : dayworkCarriers.stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList())).list();

        List<Long> ids= bizDayworks.stream().map(BizDaywork::getId).collect(Collectors.toList());
        //比较查询出的数据查看是否存在一箱多批次并且不在此次周转申请列表中
        Set<Long> dayworkIds = allCarries.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toSet());

        //判断是否需要周转的批次是否都有载具信息
        boolean allPresent = dayworkIds.containsAll(ids);
        if(!allPresent){
            return AjaxResult.error("有无载具的批次，请先绑定载具");
        }

        List<BizDaywork> allDayweork=bizDayworkService.query().in("id",dayworkIds).list();

        // 使用 Stream API 找出那些不在 dayworkItems 中的 dayworkIds
        List<Long> missingDayworkIds = dayworkIds.stream()
                .filter(id -> bizDayworks.stream()
                        .noneMatch(item -> Objects.equals(item.getId(), id)))
                .collect(Collectors.toList());
        //查询出所有批次的报工信息
        List<BizDayworkItem> bizDayworkItems = bizDayworkItemService.query().in("daywork_id",dayworkIds).orderByDesc("create_time").list();

        Map<Long, List<BizDayworkItem>> groupedByDayworkId = bizDayworkItems.stream()
                .collect(Collectors.groupingBy(BizDayworkItem::getDayworkId));

        //如果不为空判断多批报工状态
        if(!missingDayworkIds.isEmpty()){
            for (Long id:missingDayworkIds){
                BizDayworkItem dayworkItem=groupedByDayworkId.get(id).get(0);
                if(!dayworkItem.getStatus().equals("3")){
                    for (BizDayworkCarrier carrier:allCarries) {
                        if(carrier.getDayworkId().equals(id))
                            return error("箱号：" + carrier.getCarrierCode() + ",中批次未全部完成。");
                    }
                }
            }
        }

        //根据报工信息查询否有已完成的序检
        List<BizProcessInspecion> processInspecions = bizProcessInspecionService.query().in("daywork_id",dayworkIds).orderByDesc("create_time").list();
        Map<Long, List<BizProcessInspecion>> groupedProcessInspecions = processInspecions.stream()
                .collect(Collectors.groupingBy(BizProcessInspecion::getDayworkId));
        //如果存在判断是是否有当前序的完成
        for(BizDaywork daywork:allDayweork){
            List<BizProcessInspecion> inspecionList=groupedProcessInspecions.get(daywork.getId());
            if(inspecionList!=null&&inspecionList.size()>0) {
                BizProcessInspecion inspection = inspecionList.get(0);
                //如果存在判断是是否有当前序的完成
                if (inspection.getStatus() != 1) {
                    if (inspection.getStatus() == 0) {
                        return AjaxResult.error(daywork.getLotCode()+"批次序检未完成，不能周转。");
                    }
                    if (inspection.getStatus() == 2) {
                        return AjaxResult.error(daywork.getLotCode()+"批次序检不合格，不能周转。");
                    }
                    return AjaxResult.error(daywork.getLotCode()+"批次序检未合格，不能周转。");
                }
            }

        }
        // 全部完成可以周转
        return AjaxResult.success();
    }

    @Log(title = "特殊报工外协周转申请", businessType = BusinessType.INSERT)
    @PostMapping("/turnoverOutsource")
    @Transactional
    @PreAuthorize("@ss.hasPermi('business:specialDaywork:turnaround')")
    public AjaxResult turnoverOutsource(@RequestBody List<BizDayworkItem> dayworkItems) throws NoSuchFieldException, IllegalAccessException {
        //判断当前是否在盘点
        BizTakeStockPeriod bizTakeStockPeriod = bizTakeStockPeriodService.query().eq("status",1).one();
        if(bizTakeStockPeriod!=null && bizTakeStockPeriod.getStatus() == 1) {
            return error("当前在盘点，禁止周转");
        }
        /**
         * 根据传来的报工数据查询，查询是否存在一箱多批的情况，如果存在一项多批，查询是否在本次周转申请内，如果不在查询出对应的最后一条报工
         * 来进行赋值，将最后的结果放入传入的集合中。
         * 再根据下序部门的Id来查询是否需要自动分配如果自动分配则部门所有的资源组信息，根据需要保存的报工信息来查询是否已经分配了资源组如果没分配则分配对应的生产计划
         * 因为多批进行周转时肯定是同一个计划单才能一起进行周转所以自动分配的时候只需要用到第一条数据就行
         */

        // 设置工时
        // 获取箱子关联的所有批次
        boolean batch = true;
        BizDayworkItem bizDayworkItem = dayworkItems.get(0);

        //查询出所有周转批次的箱子
        List<BizDayworkCarrier> dayworkCarriers = bizDayworkCarrierService.query().eq("is_changed", 0).eq("process_inspection_id", 0L).in("daywork_id", dayworkItems.stream().map(BizDayworkItem::getDayworkId).collect(Collectors.toList())).list();
        // 再根据上面获得到的数据，通过箱子的id（carrier_id），再进行查找，有多少个批次与该箱子绑定，这是因为存在一箱多批的情况。这样就获得到了所有的批次
        List<BizDayworkCarrier> allCarries = bizDayworkCarrierService.query().eq("process_inspection_id", 0L).eq("is_changed", 0).in("carrier_id", dayworkCarriers.isEmpty() ? Collections.singletonList(0L) : dayworkCarriers.stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList())).list();

        //比较查询出的数据查看是否存在一箱多批次并且不在此次周转申请列表中
        List<Long> dayworkIds = allCarries.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toList());

        // 使用 Stream API 找出那些不在 dayworkItems 中的 dayworkIds
        List<Long> missingDayworkIds = dayworkIds.stream()
                .filter(id -> dayworkItems.stream()
                        .noneMatch(item -> Objects.equals(item.getDayworkId(), id)))
                .collect(Collectors.toList());

        if (!missingDayworkIds.isEmpty()) {
            // 根据获取到的所有批次的id，查询出所有批次的报工信息，并且状态是【"0", "1", "2", "3"】，按状态值倒序、创建日期的倒序，对数据进行排序，得到的数据是还未周转的数据。
            // 后续会通过该集合，获取某批次的最后一条报工信息
            List<BizDayworkItem> bizDayworkItems = bizDayworkItemService.query().in("daywork_id", missingDayworkIds).in("status", Arrays.asList("0", "1", "2", "3")).orderByDesc("status").orderByDesc("create_time").orderByDesc("id").list();

            // 根据获取到的所有批次的id，查询出所有批次的报工信息，不需要判断状态
            List<BizDayworkItem> bizDayworkItemList = bizDayworkItemService.query().in("daywork_id", allCarries.isEmpty() ? Collections.singletonList(0L) : allCarries.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toList())).list();

            // 获取所有的 daywork 数据集合
            List<BizDaywork> bizDayworks = bizDayworkService.query().in("id", allCarries.isEmpty() ? Collections.singletonList(0L) : allCarries.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toList())).list();

            // 遍历 daywork 数据集合
            for (BizDaywork v : bizDayworks) {
                // 获取该批次的最后一条报工
                BizDayworkItem lastItem = bizDayworkItems.stream().filter(l -> l.getDayworkId().equals(v.getId())).findFirst().orElse(null);
                // 如果最后一条报工信息存在
                if (lastItem != null) {
                    // 根据当前批次的id，获取该批次下的工序id与最后一条报工的工序id相同的所有报工信息
                    // 因为同一工序可能存在多次报工，所以需要获取该批次下，该工序的所有报工信息，后续会进行合格数的统计
                    List<BizDayworkItem> allItem = bizDayworkItemList.stream().filter(l -> l.getDayworkId().equals(v.getId()) && l.getTechnologicalProcessDetailId().equals(lastItem.getTechnologicalProcessDetailId())).collect(Collectors.toList());
                    // 根据获得到的某工序的报工信息，进行合格数统计
                    Integer lot = allItem.stream().mapToInt(BizDayworkItem::getQualifiedNum).sum();

                    // 实例化一个报工信息对象，用于保存【周转】的报工记录
                    BizDayworkItem bizItem = new BizDayworkItem();
                    bizItem.setDayworkId(lastItem.getDayworkId());
                    bizItem.setProcessId(lastItem.getProcessId());
                    bizItem.setTechnologicalProcessDetailId(lastItem.getTechnologicalProcessDetailId());
                    bizItem.setStatus(bizDayworkItem.getStatus());


                    // 如果是单批单改换，则设置form_daywork_item_id为1，表示没有原来的报工
                    if (v.getIsAmend() == 1) {
                        bizItem.setFormDayworkItemId(1L);
                    }
                    bizItem.setLotId(v.getLotId());
                    bizItem.setLotCode(v.getLotCode());
                    SysUser user = SecurityUtils.getLoginUser().getUser();
                    bizItem.setUserId(user.getUserId());
                    bizItem.setUserName(user.getUserName());
                    bizItem.setNickName(user.getNickName());
                    bizItem.setWorkingHours(0L);
                    bizItem.setDeptId(lastItem.getDeptId());
                    bizItem.setIsSpecial(lastItem.getIsSpecial());
                    bizItem.setSpecialIsFirst(lastItem.getSpecialIsFirst());
                    bizItem.setTenantId(lastItem.getTenantId());
                    bizItem.setProductionPlanDetailId(lastItem.getProductionPlanDetailId());
                    bizItem.setProductionPlanId(lastItem.getProductionPlanId());
                    bizItem.setProductionPlanDetailSubDetailId(lastItem.getProductionPlanDetailSubDetailId());
                    bizItem.setProductionPlanDetailSubDetailEquipmentId(lastItem.getProductionPlanDetailSubDetailEquipmentId());
                    bizItem.setQualifiedNum(lot);
                    bizItem.setTechnologicalProcessId(lastItem.getTechnologicalProcessId());
                    bizItem.setProdNum(lot);
                    bizItem.setEquipmentDetailId(lastItem.getEquipmentDetailId());
                    bizItem.setEquipmentDetailCode(lastItem.getEquipmentDetailCode());
                    bizItem.setDeptId(bizDayworkItem.getDeptId());
                    bizItem.setDeptName(bizDayworkItem.getDeptName());
                    bizItem.setStartTime(bizDayworkItem.getStartTime());
                    bizItem.setTurnoverId(bizDayworkItem.getTurnoverId());
                    bizItem.setTurnoverType(bizDayworkItem.getTurnoverType());
                    bizItem.setTurnoverArea(bizDayworkItem.getTurnoverArea());
                    bizItem.setPlaceId(bizDayworkItem.getPlaceId());
                    bizItem.setPlace(bizDayworkItem.getPlace());
                    bizItem.setProcessStepNumber(lastItem.getProcessStepNumber());
                    bizItem.setIsSortPackaging(bizDayworkItem.getIsSortPackaging());
                    dayworkItems.add(bizItem);
                }
            }
        }
        SysDept sysDept = sysDeptMapper.selectDeptByCode(dayworkItems.get(0).getDeptCode());
        // 如果报工状态为：7（已送达）或者4（待周转），则需要设置对应的daywork的当前部门id，以及合格数
        // 这里的状态值4/7，是由前端传递过来的。

        List<BizDaywork> dayworkList = bizDayworkService.query().in("id", dayworkItems.stream().map(BizDayworkItem::getDayworkId).collect(Collectors.toList())).list();

        for (BizDaywork daywork : dayworkList) {
            for (BizDayworkItem item : dayworkItems) {
                if (daywork.getId().equals(item.getDayworkId())) {
                    item.setDeptId(sysDept.getDeptId());
                    item.setDeptName(sysDept.getDeptName());
                    item.setQualifiedNum(daywork.getProcessQualifiedNum());
                    item.setCreateTime(null);
                    daywork.setDeptId(item.getDeptId());
                    daywork.setTemporaryProcessQualifiedNum(daywork.getProcessQualifiedNum());
                }
            }
        }


        batch = bizDayworkItemService.saveOrUpdateBatch(dayworkItems);
        //下序批量审核
        List<BizDayworkItem> needDayworkItemExamineList = dayworkItems.stream().filter(v -> v.getIsSortPackaging() == 1).collect(Collectors.toList());
        if(!needDayworkItemExamineList.isEmpty()) {
            List<Long> productionPlanDetailIds = dayworkItems.stream().map(BizDayworkItem::getProductionPlanDetailId).collect(Collectors.toList());
            //拿到产品id
            List<BizProductionPlanDetail> productionPlanDetailList = bizProductionPlanDetailService.query().in("id", productionPlanDetailIds).list();
            //拿到申请审核的工段id
            List<Long> dayworkId = dayworkItems.stream().map(BizDayworkItem::getDayworkId).collect(Collectors.toList());
            //拿到工序名称
            List<Long> processIds = dayworkItems.stream().map(BizDayworkItem::getProcessId).collect(Collectors.toList());
            List<BizProcess> processList = bizProcessService.query().in("id", processIds).list();
            List<BizDaywork> bizDayworkList = bizDayworkService.query().in("id", dayworkId).list();
            List<BizDayworkItemExamine> addExamineList = new ArrayList<>();
            //先判断是否已经添加了，如果添加了则删除
            List<BizDayworkItemExamine> examineList = bizDayworkItemExamineService.query().in("daywork_id", dayworkId).list();
            if(!examineList.isEmpty()) {
                bizDayworkItemExamineService.removeBatchByIds(examineList);
            }
            needDayworkItemExamineList.forEach(item->{
                BizDayworkItemExamine examine = new BizDayworkItemExamine();
                examine.setDayworkId(item.getDayworkId());
                examine.setDayworkItemId(item.getId());
                examine.setDeptId(sysDept.getDeptId());
                examine.setProductionPlanDetailId(item.getProductionPlanDetailId());
                examine.setProductDescription(productionPlanDetailList.stream().filter(v->v.getId().equals(examine.getProductionPlanDetailId())).collect(Collectors.toList()).get(0).getProductDescription());
                examine.setLotId(item.getLotId());
                examine.setLotCode(bizDayworkList.stream().filter(v->v.getId().equals(examine.getDayworkId())).collect(Collectors.toList()).get(0).getLotCode());
                examine.setProductId(productionPlanDetailList.stream().filter(v->v.getId().equals(examine.getProductionPlanDetailId())).collect(Collectors.toList()).get(0).getProductId());
                examine.setTechnologicalProcessId(item.getTechnologicalProcessId());
                examine.setTechnologicalProcessDetailId(item.getTechnologicalProcessDetailId());
                examine.setProcessId(item.getProcessId());
                examine.setProcessAlias(processList.stream().filter(v->v.getId().equals(examine.getProcessId())).collect(Collectors.toList()).get(0).getProcessAlias());
                examine.setStatus(0);
                addExamineList.add(examine);
            });
            bizDayworkItemExamineService.saveBatch(addExamineList);
        }


        bizDayworkService.saveOrUpdateBatch(dayworkList);


        return success(batch);
    }


    @Log(title = "特殊报工取消周转", businessType = BusinessType.UPDATE)
    @PostMapping("/cancelSpecialDaywork")
    @Transactional
    @PreAuthorize("@ss.hasPermi('business:specialDaywork:cancelTurnaround')")
    public AjaxResult cancelSpecialDaywork(@RequestBody List<BizDaywork> bizDayworks) throws NoSuchFieldException, IllegalAccessException {
        /**
         *  取消周转时需要将最新一条的报工周转数据删除，删除后将原工段修改到daywork中
         */
        //判断当前是否在盘点
        BizTakeStockPeriod bizTakeStockPeriod = bizTakeStockPeriodService.query().eq("status",1).one();
        if(bizTakeStockPeriod!=null && bizTakeStockPeriod.getStatus() == 1) {
            return error("当前在盘点，禁止投产");
        }
        //查询出所有周转批次的箱子
        List<BizDayworkCarrier> dayworkCarriers = bizDayworkCarrierService.query().eq("is_changed", 0).eq("process_inspection_id", 0L).in("daywork_id",bizDayworks.stream().map(BizDaywork::getId).collect(Collectors.toList()) ).list();
        // 再根据上面获得到的数据，通过箱子的id（carrier_id），再进行查找，有多少个批次与该箱子绑定，这是因为存在一箱多批的情况。这样就获得到了所有的批次
        List<BizDayworkCarrier> allCarries = bizDayworkCarrierService.query().eq("process_inspection_id", 0L).eq("is_changed", 0).in("carrier_id", dayworkCarriers.isEmpty() ? Collections.singletonList(0L) : dayworkCarriers.stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList())).list();

        //比较查询出的数据查看是否存在一箱多批次并且不在此次周转申请列表中
        List<Long> dayworkIds = allCarries.stream().map(BizDayworkCarrier::getDayworkId).collect(Collectors.toList());
        List<BizDaywork> bizDayworkList=bizDayworkService.query().in("id",dayworkIds).list();

        //先根据dayworkId查询出所有的报工数据按照创建时间倒序排列
        List<BizDayworkItem> dayworkItems = bizDayworkItemService.query().in("daywork_id", dayworkIds).orderByDesc("create_time").list();

        Map<Long, List<BizDayworkItem>> groupedByDayworkId = dayworkItems.stream()
                .collect(Collectors.groupingBy(BizDayworkItem::getDayworkId));
        List<BizDayworkItem> cancelItems = new ArrayList<>();
        //因为周转信息只有一条且一定是最新的一条，所以直接将按照daywork分组的数据取第一条就是周转信息，将第二条数据的工段信息赋值给daywork
        for (BizDaywork daywork : bizDayworkList) {
            List<BizDayworkItem> items = groupedByDayworkId.get(daywork.getId());
            if (!items.isEmpty()) {
                daywork.setDeptId(items.get(1).getDeptId());
                cancelItems.add(items.get(0));
            }
        }
        return success(bizDayworkItemService.removeBatchByIds(cancelItems) && bizDayworkService.saveOrUpdateBatch(bizDayworkList));
    }


    @Log(title = "新增特殊报工批次信息", businessType = BusinessType.INSERT)
    @PostMapping("/specialSaveDaywork")
    @Transactional
    @PreAuthorize("@ss.hasPermi('business:specialDaywork:add')")
    public AjaxResult specialSaveDaywork(@RequestBody BizDaywork bizDaywork) throws NoSuchFieldException, IllegalAccessException {
        String tenantId = request.getHeader("tenantId");

        List<BizDayworkItem> itemList = bizDaywork.getDayworkItemList();
        if (bizDaywork.getDayworkCarriers() == null || bizDaywork.getDayworkCarriers().isEmpty()) {
            return error("请选择载具！");
        }

        //判断是否为首序报工
        if (bizDaywork.getSpecialIsFirst().equals(1)) {
            /**
             * 首序报工保存
             * 1.因为是首序报工之前没有产生dayweok信息，所以需要先保存daywork信息，daywork信息需要:批次id,批次号，子计划id，工段id，产品id，
             * 工艺id，合格数
             * 2.因为在daywork表中user_id,user_name,start_time字段从未使用，所以特殊报工用来存储特殊报工创建人id,创建人姓名，创建时间
             * 所以在保存之前需要查询当前登陆人员信息，将登录人员信息保存，在保存daywork前设置start_time为当前时间
             * 3.根据保存后的daywork信息来保存dworkitem信息，因为废品信息需要dayworkItemId所以需要先保存daywork_item
             * daywork_item信息需要：dayworkId,子计划id，批次id,投产数，合格数，工艺id,工艺明细id,工序id,设备id,设备编码
             * 工段id,工段名称，报工状态，开始时间，结束时间，总工时，工序排序，是否特殊报工，特殊报工是否首序
             * 保存报工时要注意如果是工序已完成需要将最后一条报工状态修改为工序完成
             * 4.根据保存的报工信息来保存废品信息，废品信息需要：daywerokId,userId(操作者id),子计划Id，批次号，工段id,dayworkItemId,废品原因，
             * 废品数量
             * 5.保存炉号信息，因为是首序报工所以需要将查询到的炉号信息保存
             * 6.最后保存载具，根据daywork来保存载具信息，载具信息需要：dayweokId,计划单id,批次id，产品id,载具id,载具编码
             */



            //判断载具是否有效
            Map<Boolean, String> booleanStringMap = checkCarrierValidity(bizDaywork);
            if (booleanStringMap.containsKey(false)) {
                return error(booleanStringMap.get(false));
            }

            //保存daywork信息
            bizDaywork.setStartTime(new Date());
            bizDaywork.setHasSpecial(1);
            bizDayworkService.saveOrUpdate(bizDaywork);
            long oneMillisecond = 1000;

            //保存报工信息
            for (int i = 0; i < itemList.size(); i++) {
                itemList.get(i).setDayworkId(bizDaywork.getId());
                itemList.get(i).setTechnologicalProcessDetailId(bizDaywork.getTechnologicalProcessDetailId());
                itemList.get(i).setIsSpecial(1);
                itemList.get(i).setSpecialIsFirst(1);
                itemList.get(i).setProcessStepNumber(bizDaywork.getProcessStepNumber());
                itemList.get(i).setProcessId(bizDaywork.getProcessId());
                Date startTime = itemList.get(i).getStartTime();
                Date endTime = itemList.get(i).getEndTime();
                // 计算时间差（毫秒）
                long diffInMilliSeconds = endTime.getTime() - startTime.getTime();
                itemList.get(i).setWorkingHours(diffInMilliSeconds);

                Date createTime=new Date();
                long createTimeSeconds=createTime.getTime();
                createTimeSeconds+=(oneMillisecond*i);
                Date newTime=new Date(createTimeSeconds);
                itemList.get(i).setCreateTime(newTime);

                //判断工序是否完成，如果工序完成，将最后一条报工状态修改为3
                if (bizDaywork.getItemStatus().equals(3) && i == itemList.size() - 1) {
                    itemList.get(i).setStatus("3");
                } else {
                    itemList.get(i).setStatus("2");
                }
            }
            bizDayworkItemService.saveBatch(itemList);

            //保存炉号信息
            if (bizDaywork.getFurnaceNoInfo() != null) {
                BizFurnaceNoInfo furnaceNoInfo = bizDaywork.getFurnaceNoInfo();
                furnaceNoInfo.setDayworkId(bizDaywork.getId());
                furnaceNoInfo.setProductionPlanDetailId(bizDaywork.getProductionPlanDetailId());
                bizFurnaceNoInfoService.saveOrUpdate(furnaceNoInfo);
            }

            //保存废品信息
            List<BizDayworkItemReject> saveReject = new ArrayList<>();
            for (BizDayworkItem item : itemList) {
                if (item.getRejectList() != null && !item.getRejectList().isEmpty()) {
                    for (BizDayworkItemReject reject : item.getRejectList()) {
                        reject.setDayworkItemId(item.getId());
                        reject.setDayworkId(item.getDayworkId());
                        reject.setProductionPlanDetailId(item.getProductionPlanDetailId());
                        reject.setProcessId(item.getProcessId());
                        saveReject.add(reject);
                    }
                }

            }

            if (!saveReject.isEmpty()) {
                bizDayworkItemRejectService.saveBatch(saveReject);
            }

            for (BizDayworkCarrier carrier : bizDaywork.getDayworkCarriers()) {
                carrier.setDayworkId(bizDaywork.getId());
            }

            //保存载具信息
            bizDayworkCarrierService.saveOrUpdateBatch(bizDaywork.getDayworkCarriers());
            //保存报工箱数
            bizDayworkItemService.saveCarrierNum(itemList);

        } else {
            /**
             * 非首序报工
             * 1.因为是非首序报工有daywork信息，所需不需要先保存daywork信息，先根据dayworkId查询出当前daywork信息，根据daywork信息，保存dayworkItem信息
             * daywork_item信息需要：dayworkId,子计划id，批次id,投产数，合格数，工艺id,工艺明细id,工序id,设备id,根据开始时间和结束时间计算工时
             * 2.根据保存的报工信息来保存废品信息，废品信息需要：daywerokId,userId(操作者id),子计划Id，批次号，工段id,dayworkItemId,废品原因，
             * 废品数量
             * 3.根据报工信息修改daywork信息，修改daywork的合格数，user_id(特殊报工创建人)，user_name(特殊报工创建人编码)，nick_name(特殊报工创建人姓名)，
             * start_time(特殊报工创建时间)，设备编码,has_special(是否特殊报工).
             * 保存报工时要注意如果是工序已完成需要将最后一条报工状态修改为工序完成
             * 4.最后保存载具信息，先根据dayworkId查询出所有关联的载具信息，比较当前载具信息将新增的保存起来，删除的载具信息进行解绑
             *
             */
            //查询出当前daywork信息
            BizDaywork daywork = bizDayworkService.query().eq("id", bizDaywork.getId()).one();

            //判断载具是否有效
            Map<Boolean, String> booleanStringMap = checkCarrierValidity(bizDaywork);
            if (booleanStringMap.containsKey(false)) {
                return error(booleanStringMap.get(false));
            }

            long oneMillisecond = 1000;

            //保存报工信息
            for (int i = 0; i < itemList.size(); i++) {
                itemList.get(i).setDayworkId(daywork.getId());
                itemList.get(i).setTechnologicalProcessDetailId(bizDaywork.getTechnologicalProcessDetailId());
                itemList.get(i).setIsSpecial(1);
                itemList.get(i).setTechnologicalProcessId(bizDaywork.getTechnologicalProcessId());
                itemList.get(i).setProcessStepNumber(bizDaywork.getProcessStepNumber());
                itemList.get(i).setProcessId(bizDaywork.getProcessId());
                Date startTime = itemList.get(i).getStartTime();

                Date createTime=new Date();
                long createTimeSeconds=createTime.getTime();
                createTimeSeconds+=(oneMillisecond*i);
                Date newTime=new Date(createTimeSeconds);
                itemList.get(i).setCreateTime(newTime);

                Date endTime = itemList.get(i).getEndTime();
                // 计算时间差（毫秒）
                long diffInMilliSeconds = endTime.getTime() - startTime.getTime();
                itemList.get(i).setWorkingHours(diffInMilliSeconds);

                //判断工序是否完成，如果工序完成，将最后一条报工状态修改为3
                if (bizDaywork.getItemStatus().equals(3) && i == itemList.size() - 1) {
                    itemList.get(i).setStatus("3");
                } else {
                    itemList.get(i).setStatus("2");
                }
            }

            bizDayworkItemService.saveBatch(itemList);

            //保存废品信息
            List<BizDayworkItemReject> saveReject = new ArrayList<>();
            for (BizDayworkItem item : itemList) {
                if (item.getRejectList() != null && !item.getRejectList().isEmpty()) {
                    for (BizDayworkItemReject reject : item.getRejectList()) {
                        reject.setDayworkItemId(item.getId());
                        reject.setDayworkId(item.getDayworkId());
                        reject.setProductionPlanDetailId(item.getProductionPlanDetailId());
                        reject.setProcessId(item.getProcessId());
                        saveReject.add(reject);
                    }
                }
            }
            if (!saveReject.isEmpty()) {
                bizDayworkItemRejectService.saveBatch(saveReject);
            }
            //保存载具信息
            // 因为是非首序报工，保存载具之前需要先将改批次的所有载具解绑，再进行绑定
            bizDayworkCarrierService.updateByDaywork(daywork.getId());
            for (BizDayworkCarrier carrier : bizDaywork.getDayworkCarriers()) {
                carrier.setDayworkId(daywork.getId());
            }
            bizDayworkCarrierService.saveOrUpdateBatch(bizDaywork.getDayworkCarriers());

            //保存报工箱数
            bizDayworkItemService.saveCarrierNum(itemList);

            //修改daywork信息（只修改合格数、userId、userName、neckName、特殊报工字段）
            daywork.setUserId(bizDaywork.getUserId());
            daywork.setUserName(bizDaywork.getUserName());
            daywork.setNickName(bizDaywork.getNickName());
            daywork.setStartTime(new Date());
            daywork.setHasSpecial(1);
            daywork.setProcessQualifiedNum(bizDaywork.getProcessQualifiedNum());
            daywork.setTemporaryProcessQualifiedNum(bizDaywork.getProcessQualifiedNum());
            bizDayworkService.saveOrUpdate(daywork);
        }
        return success();
    }

    @Log(title = "特殊报工批次信息修改", businessType = BusinessType.UPDATE)
    @PostMapping("/specialUpdateDaywork")
    @Transactional
    @PreAuthorize("@ss.hasPermi('business:specialDaywork:edit')")
    public AjaxResult specialUpdateDaywork(@RequestBody BizDaywork bizDaywork) throws NoSuchFieldException, IllegalAccessException {
        String tenantId = request.getHeader("tenantId");

        List<BizDayworkItem> itemList = bizDaywork.getDayworkItemList();
        //查询出当前daywork信息
        BizDaywork daywork = bizDayworkService.query().eq("id", bizDaywork.getId()).one();

        //判断载具是否有效
        Map<Boolean, String> booleanStringMap = checkCarrierValidity(bizDaywork);
        if (booleanStringMap.containsKey(false)) {
            return error(booleanStringMap.get(false));
        }

        //先找到之前的报工信息，筛选出删除的报工
        List<BizDayworkItem> oldItemList = bizDayworkItemService.query().eq("daywork_id", bizDaywork.getId()).eq("technological_process_detail_id", bizDaywork.getSpecialProcessId()).list();
        Set<Long> currentIds = itemList.stream()
                .filter(Objects::nonNull) // 提取 ID
                .map(BizDayworkItem::getId) // 确保 ID 不为空
                .collect(Collectors.toSet()); // 收集到 Set 中

        List<BizDayworkItem> filteredOldItems = oldItemList.stream()
                .filter(oldItem -> !currentIds.contains(oldItem.getId())) // 检查 ID 是否不在 currentIds 中
                .collect(Collectors.toList()); // 收集结果到新的列表


        List<Long> dayworkIds = new ArrayList<>();
        dayworkIds.add(bizDaywork.getId());
        //删除不要的报工数据和所有的废品信息
        bizDayworkItemService.removeBatchByIds(filteredOldItems);
        bizDayworkItemRejectService.removeSpecial(dayworkIds);


        long oneMillisecond = 1000;
        //保存报工信息
        for (int i = 0; i < itemList.size(); i++) {
            if (bizDaywork.getSpecialIsFirst().equals(1)) {
                itemList.get(i).setSpecialIsFirst(1);
            }
            itemList.get(i).setDayworkId(daywork.getId());
            itemList.get(i).setIsSpecial(1);
            Date startTime = itemList.get(i).getStartTime();
            Date endTime = itemList.get(i).getEndTime();
            if(itemList.get(i).getId()==null){
                 // 1毫秒
                Date createTime=new Date();
                long createTimeSeconds=createTime.getTime();
                createTimeSeconds+=(oneMillisecond*i);
                Date newTime=new Date(createTimeSeconds);
                itemList.get(i).setCreateTime(newTime);
            }
            // 计算时间差（毫秒）
            long diffInMilliSeconds = endTime.getTime() - startTime.getTime();
            itemList.get(i).setWorkingHours(diffInMilliSeconds);

            //判断工序是否完成，如果工序完成，将最后一条报工状态修改为3
            if (bizDaywork.getItemStatus().equals(3) && i == itemList.size() - 1) {
                itemList.get(i).setStatus("3");
            } else {
                itemList.get(i).setStatus("2");
            }
        }
        bizDayworkItemService.saveOrUpdateBatch(itemList);

        //保存废品信息
        List<BizDayworkItemReject> saveReject = new ArrayList<>();
        for (BizDayworkItem item : itemList) {
            if (item.getRejectList() != null && !item.getRejectList().isEmpty()) {
                for (BizDayworkItemReject reject : item.getRejectList()) {
                    reject.setDayworkItemId(item.getId());
                    reject.setDayworkId(item.getDayworkId());
                    reject.setProductionPlanDetailId(item.getProductionPlanDetailId());
                    reject.setProcessId(item.getProcessId());
                    reject.setId(null);
                    saveReject.add(reject);
                }
            }
        }
        if (!saveReject.isEmpty()) {
            bizDayworkItemRejectService.saveOrUpdateBatch(saveReject);
        }
        //保存载具信息
        //保存载具之前需要先将改批次的所有载具解绑，再进行绑定
        bizDayworkCarrierService.updateByDaywork(daywork.getId());
        for (BizDayworkCarrier carrier : bizDaywork.getDayworkCarriers()) {
            carrier.setDayworkId(daywork.getId());
        }
        bizDayworkCarrierService.saveOrUpdateBatch(bizDaywork.getDayworkCarriers());
        //保存报工箱数
        bizDayworkItemService.saveCarrierNum(itemList);
        //修改daywork信息（只修改合格数、userId、userName、neckName、特殊报工字段）
        daywork.setProcessQualifiedNum(bizDaywork.getProcessQualifiedNum());
        daywork.setTemporaryProcessQualifiedNum(bizDaywork.getProcessQualifiedNum());
        bizDayworkService.saveOrUpdate(daywork);

        return success();
    }

    /**
     * 判断载具是否有效
     */
    private Map<Boolean, String> checkCarrierValidity(BizDaywork bizDaywork) {

        Map<Boolean, String> map = new HashMap<>();
        List<BizDayworkItem> itemList = bizDaywork.getDayworkItemList();
        List<BizDayworkItem> currentItems = bizDayworkItemService.query().eq("daywork_id", bizDaywork.getId()).orderByDesc("create_time").list();
        // 校验铁箱不能不同计划单绑定同一个箱子,同一计划单不能绑定两个铁箱
        List<BizCarrier> carriers = bizCarrierService.query().in("id", bizDaywork.getDayworkCarriers().isEmpty() ? Collections.singletonList(0L) : bizDaywork.getDayworkCarriers().stream().map(BizDayworkCarrier::getCarrierId).collect(Collectors.toList())).list();
        // 判断是否同时有蓝箱和铁箱
        List<BizCarrierCategory> categories = carrierCategoryService.query().in("id", carriers.isEmpty() ? Collections.singletonList(0L) : carriers.stream().map(BizCarrier::getCategoryId).collect(Collectors.toList())).list();
        if (categories.stream().anyMatch(v -> v.getIsAllowMore().equals(1)) && categories.stream().anyMatch(v -> v.getIsAllowMore().equals(0))) {
            map.put(false, "不能同时绑定蓝箱和铁箱。");
            return (map);
        }
        int count = 0;
        for (BizDayworkCarrier item : bizDaywork.getDayworkCarriers()) {
            BizCarrier carrier = bizCarrierService.getOne(new QueryWrapper<BizCarrier>().eq("id", item.getCarrierId()));
            BizCarrierCategory carrierCategory = bizCarrierService.getCarrierCategory(carrier.getCategoryId());
            if (carrierCategory.getIsAllowMore() == 1) {
                // 如果是铁箱,查询该铁箱下绑定的批次是否是同一批次
                // 先查询该铁箱是够绑定了其他批次,并获取该批次计划单号
                List<BizDayworkCarrier> carrierList =
                        bizDayworkCarrierService.query().eq("carrier_id", item.getCarrierId())
                                .eq("is_changed", 0)
                                .eq("process_inspection_id", 0L)
                                .list();
                bizDayworkCarrierService.list(new QueryWrapper<BizDayworkCarrier>());
                if (!carrierList.isEmpty()) {
                    BizDaywork daywork = bizDayworkService.getById(carrierList.get(0).getDayworkId());
                    if (!daywork.getProductionPlanDetailId().equals(bizDaywork.getProductionPlanDetailId())) {
                        map.put(false, "当前存在绑定其他计划单/工序的铁箱，请重新选择。");
                        return map;
                    }
                    if (!daywork.getDeptId().equals(bizDaywork.getDeptId())) {
                        map.put(false, "当前存在绑定其他计划单/工序的铁箱，请重新选择。");
                        return map;
                    }
                    if (currentItems.size()==0?bizDaywork.getTechnologicalProcessDetailId().equals(itemList.get(0).getTechnologicalProcessDetailId()): !currentItems.get(0).getTechnologicalProcessDetailId().equals(itemList.get(0).getTechnologicalProcessDetailId())) {
                        map.put(false, "当前存在绑定其他计划单/工序的铁箱,请重新选择。");
                        return map;
                    }
                }
                count++;
            }
            if (count > 1) {
                map.put(false, "同一计划单不能绑定两个铁箱");
                return map;
            }
        }
        map.put(true, "");

        return map;
    }

    @Log(title = "特殊报工删除报工", businessType = BusinessType.DELETE)
    @PostMapping("/delSpecialDaywork")
    @Transactional
    @PreAuthorize("@ss.hasPermi('business:specialDaywork:remove')")
    public AjaxResult delSpecialDaywork(@RequestBody List<BizDaywork> bizDayworks) {
        /**
         * 删除报工时要删除对应工序的daywork信息、废品信息
         * 删除报工时要判断是否为首序报工，删除首序报工时需要额外删除载具信息、daywork信息、炉号信息
         */
        //判断是否为首序报工
        List<BizDaywork> first = new ArrayList<>();//首序报工集合
        List<BizDaywork> noFirst = new ArrayList<>();//非首序报工集合

        for (BizDaywork item : bizDayworks) {
            if (item.getSpecialIsFirst().equals(1)) {
                first.add(item);
            } else {
                noFirst.add(item);
            }
        }

        //首序需要删除的所有dayworkId
        List<Long> firstDayworkIds = new ArrayList<>();
        List<BizDayworkItem> noFirstDayworkItemIds = new ArrayList<>();
        /*
         *删除首序报工数据，因为是首序报工所以直接删除所有数据
         */
        if (!first.isEmpty()) {
            firstDayworkIds = first.stream().map(BizDaywork::getId).collect(Collectors.toList());
            bizDayworkItemService.removeSpecial(firstDayworkIds);
            bizDayworkCarrierService.removeSpecial(firstDayworkIds);
            bizFurnaceNoInfoService.removeSpecial(firstDayworkIds);
            bizDayworkItemRejectService.removeSpecial(firstDayworkIds);
        }
        /*
            非首序删除时需要先查询到对应的dayworkItem信息,根据dayworkItem删除废品信息
            查询时根据dayworkId和特殊报工工序查询
         */
        List<BizDayworkItemReject> rejects = new ArrayList<>();

        if (!noFirst.isEmpty()) {
            //根据dayworkId查询出所有特殊报工且不是首序报工的信息
            List<BizDayworkItem> dayworkItems = bizDayworkItemService.query().in("daywork_id", noFirst.stream().map(BizDaywork::getId).collect(Collectors.toList()))
                    .eq("is_special", 1).eq("special_is_first", 0).list();
            for (BizDaywork daywork : noFirst) {
                for (BizDayworkItem item : dayworkItems) {
                    //根据工序筛选出需要删除的数据
                    if (item.getDayworkId().equals(daywork.getId()) && item.getTechnologicalProcessDetailId().equals(daywork.getSpecialProcessId())) {
                        noFirstDayworkItemIds.add(item);
                    }
                }
            }
            rejects = bizDayworkItemRejectService.query().in("daywork_item_id", dayworkItems.stream().map(BizDayworkItem::getId).collect(Collectors.toList())).list();
            if (!rejects.isEmpty()) {
                bizDayworkItemRejectService.removeBatchByIds(rejects);
            }
            /* 删除报工数据 */
            if (!noFirstDayworkItemIds.isEmpty())
                bizDayworkItemService.removeBatchByIds(noFirstDayworkItemIds);

            //因为报工信息删除了所以要将daywork信息的合格数修改为上道序的合格数
            List<BizDayworkItem> itemList = bizDayworkItemService.query().in("daywork_id", noFirst.stream().map(BizDaywork::getId).collect(Collectors.toList())).orderByDesc("create_time").list();
            Map<Long, List<BizDayworkItem>> groupedByDayworkId = itemList.stream()
                    .collect(Collectors.groupingBy(BizDayworkItem::getDayworkId));
            for (BizDaywork daywork : noFirst) {
                List<BizDayworkItem> items = groupedByDayworkId.get(daywork.getId());
                if (items != null && !items.isEmpty()) {
                    daywork.setProcessQualifiedNum(items.get(0).getQualifiedNum());
                    daywork.setTemporaryProcessQualifiedNum(items.get(0).getQualifiedNum());
                }
            }

        }
        return success((noFirstDayworkItemIds.isEmpty() || bizDayworkService.saveOrUpdateBatch(noFirst)) && (firstDayworkIds.isEmpty() || bizDayworkService.removeByIds(firstDayworkIds)));
    }


    /**
     * 查询周转区列表
     */
    @Log(title = "周转区列表获取", businessType = BusinessType.SELECT)
    @PostMapping("/getTurnoverListByDeptId")
    public AjaxResult getTurnoverListByDeptId(@RequestBody Map<String, Object> data) throws NoSuchFieldException, IllegalAccessException {
        Integer zero = 0;
        String tenantId = request.getHeader("tenantId");
        QueryWrapper<BizTurnover> queryWrapper = new QueryWrapper<>();
        final String param1 = "deptId";
        long deptId = 0L;
        if (data.get(param1) != null) {
            deptId = Long.parseLong(data.get(param1).toString());
        }

        queryWrapper.eq("dept_id", deptId);
        queryWrapper.eq("status", 0);
        if (tenantId != null && !zero.toString().equals(tenantId)) {
            queryWrapper.eq("tenant_id", Long.valueOf(tenantId));
        }
        List<BizTurnover> list = iBizTurnoverService.list(queryWrapper);
        return success(list);
    }


    /**
     * 根据dayworkItems的id查询废品表数据，将数据按照dayworkId分组
     * 计算每组所有的废品数总和，在赋值给对应的daywork
     */
    private List<BizDaywork> selectRejectsNumber(List<BizDaywork> dayworks, List<BizDayworkItem> dayworkItems) {

        List<BizDayworkItemReject> dayworkItemRejects = bizDayworkItemRejectService.query()
                .in("daywork_item_id", dayworkItems.stream().map(BizDayworkItem::getId).collect(Collectors.toList())).list();
        // 按 dayworkId 分组并计算每组的废品数总和
        Map<Long, Long> totalRejectCountsByDayworkId = dayworkItemRejects.stream()
                .collect(Collectors.groupingBy(
                        BizDayworkItemReject::getDayworkId,
                        Collectors.summingLong(BizDayworkItemReject::getRejectNum) // 使用 summingLong 来处理 Long 类型的求和
                ));

        // 更新 dayworks 列表中的 BizDaywork 对象
        for (BizDaywork daywork : dayworks) {
            Long dayworkId = daywork.getId();
            Long totalRejectCount = totalRejectCountsByDayworkId.getOrDefault(dayworkId, 0L); // 使用 0L 作为 Long 类型的默认值
            daywork.setRejectSum(totalRejectCount);
        }

        return dayworks;

    }

    /**
     * 查询合格数和废品信息需要先查询到每条daywork对应的当前工序的报工信息daywork_item
     * 因为需要进行合格数计算所以只查询状态为2和3的数据
     */
    private List<BizDaywork> selectNumber(List<BizDaywork> dayworks, List<BizDayworkItem> dayworkItems) {

        // 使用 Stream API 来分组并计算每组的 qualifiedNum 总和以及获取每组的第一条数据的 prodNum
        Map<Long, BizDayworkItem> firstItemByDayworkId = dayworkItems.stream()
                .collect(Collectors.toMap(BizDayworkItem::getDayworkId, Function.identity(), (oldValue, newValue) -> oldValue));

        //将查询出来的数据按照dayworkId分组,计算总合格数
        Map<Long, Integer> sumOfQualifiedNums = dayworkItems.stream()
                .collect(Collectors.groupingBy(
                        BizDayworkItem::getDayworkId,
                        Collectors.summingInt(BizDayworkItem::getQualifiedNum)
                ));

        // 更新 dayworks 列表中的 BizDaywork 对象
        for (BizDaywork daywork : dayworks) {
            Long dayworkId = daywork.getId();
            Integer totalQualifiedNum = sumOfQualifiedNums.getOrDefault(dayworkId, 0); // 如果没有找到对应的分组，返回0
            daywork.setQualifiedNum(totalQualifiedNum);

            BizDayworkItem firstItem = firstItemByDayworkId.get(dayworkId);
            if (firstItem != null) {
                daywork.setProdNum(firstItem.getProdNum());
            } else {
                daywork.setProdNum(0);
            }
        }
        return dayworks;
    }

    /**
     * 根据dayworkId向biz_daywork_carrier查询绑定信息，查询is_changed=0的数据
     * 将carrier拼接起来，按”，“分割
     */
    private List<BizDaywork> selectCarrierCode(List<BizDaywork> dayworks) {

        List<BizDayworkCarrier> dayworkCarriers = bizDayworkCarrierService.query().in("daywork_id", dayworks.stream()
                .map(BizDaywork::getId).collect(Collectors.toList())).eq("is_changed", 0).list();

        // 使用 Stream API 来分组和拼接 carrierCode
        Map<Long, String> carrierCodeMap = dayworkCarriers.stream()
                .collect(Collectors.groupingBy(
                        BizDayworkCarrier::getDayworkId, // 分组的键
                        Collectors.mapping(BizDayworkCarrier::getCarrierCode, Collectors.joining(",")) // 拼接值
                ));

        // 更新 dayworks 列表
        for (BizDaywork daywork : dayworks) {
            Long dayworkId = daywork.getId();
            String carrierCodes = carrierCodeMap.getOrDefault(dayworkId, ""); // 如果没有找到对应的分组，返回空字符串
            // 假设 BizDaywork 有一个方法来设置它的 carrierCodes
            daywork.setCarrierCode(carrierCodes);
        }
        return dayworks;
    }

    /**
     * 查询产品信息
     *
     * @param dayworks
     * @return
     */
    private List<BizDaywork> selectProductionPlanDetail(List<BizDaywork> dayworks) {
        //根据生产子计划id查询biz_production_plan_detail表中数据
        List<BizProductionPlanDetail> productionPlanDetails = bizProductionPlanDetailService.query().in("id", dayworks.stream()
                .map(BizDaywork::getProductionPlanDetailId).collect(Collectors.toList())).list();

        //给daywork中productionPlanDetail赋值
        // 将productionPlanDetails转换为Map，以id为键，方便快速查找
        Map<Long, BizProductionPlanDetail> detailMap = productionPlanDetails.stream()
                .collect(Collectors.toMap(BizProductionPlanDetail::getId, Function.identity()));
        // 使用Stream API过滤dayworks中的元素，并设置对应的BizProductionPlanDetail
        dayworks.stream()
                .filter(daywork -> detailMap.containsKey(daywork.getProductionPlanDetailId()))
                .forEach(daywork -> {
                    BizProductionPlanDetail detail = detailMap.get(daywork.getProductionPlanDetailId());
                    daywork.setProductionPlanDetail(detail);
                });
        return dayworks;
    }


    /**
     * 查询工序信息
     * 根据daywork查询工序信息,判断批次是否单批单改或废品回用等非正常状态,将正常批次和非正常批次区分开
     * 正常批次上biz_technological_process_detail表中查询，非正常批次上biz_lot_technological_process_detail中查询
     */
    private List<BizDaywork> selectDayworkProcess(List<BizDaywork> dayworks) {

        //正常批次工序id
        List<Long> ids = new ArrayList<>();
        //工序修改批次工序id
        List<Long> amendIds = new ArrayList<>();
        for (BizDaywork bizDaywork : dayworks) {
            if (bizDaywork.getIsAmend().equals(1)) {
                amendIds.add(bizDaywork.getSpecialProcessId());
            } else {
                ids.add(bizDaywork.getSpecialProcessId());
            }
        }

        //集合不为空进入查询
        if (!ids.isEmpty()) {
            //根据工序id查询工序信息
            List<BizTechnologicalProcessDetail> processDetailList = bizTechnologicalProcessDetailService.query().in("id", ids).list();
            //根据工序id赋值工序信息
            for (BizTechnologicalProcessDetail processDetail : processDetailList) {
                for (BizDaywork bizDaywork : dayworks) {
                    if (processDetail.getId().equals(bizDaywork.getSpecialProcessId())) {
                        bizDaywork.setProcessAlias(processDetail.getProcessAlias());
                    }
                }
            }
        }
        if (!amendIds.isEmpty()) {
            //根据工序id查询工序信息
            List<BizLotTechnologicalProcessDetail> lotTechnologicalProcessDetails = bizTechnologicalAmendDetailService.query().in("id", amendIds).list();
            //根据工序id赋值工序信息
            for (BizLotTechnologicalProcessDetail processDetail : lotTechnologicalProcessDetails) {
                for (BizDaywork bizDaywork : dayworks) {
                    if (processDetail.getId().equals(bizDaywork.getSpecialProcessId())) {
                        bizDaywork.setProcessAlias(processDetail.getProcessAlias());
                    }
                }
            }
        }
        return dayworks;
    }

    /**
     * 根据字典类型查询字典数据信息
     */
    @GetMapping(value = "/getDictInfoByType/{dictType}")
    @Log(title = "根据字典类型查询字典数据信息", businessType = BusinessType.SELECT)
    public AjaxResult dictType(@PathVariable String dictType) {
        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
        if (StringUtils.isNull(data)) {
            data = new ArrayList<>();
        }
        return success(data);
    }

    /**
     * 查询周转区列表
     */
    @Log(title = "特殊报工车间周转区列表获取", businessType = BusinessType.SELECT)
    @PostMapping("/getTurnover")
    public AjaxResult getTurnover(@RequestBody Map<String, Object> data) throws NoSuchFieldException, IllegalAccessException {
        long deptId = Long.parseLong(data.get("deptId").toString());
        SysDept dept = iSysDeptService.specialSelectDeptById(deptId);
        List<BizWorkshopTurnover> workshopTurnovers = iBizWorkshopTurnoverService.query()
                .eq("workshop_id", dept.getWorkshopId())
                .eq("status", 0)
                .list();

        return success(workshopTurnovers);
    }


}
