package com.huaheng.mobile.invenory;

import com.alibaba.fastjson.JSONException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaheng.common.constant.QuantityConstant;
import com.huaheng.common.exception.service.ServiceException;
import com.huaheng.common.support.Convert;
import com.huaheng.common.utils.DataUtils;
import com.huaheng.common.utils.StringUtils;
import com.huaheng.common.utils.Wrappers;
import com.huaheng.common.utils.security.ShiroUtils;
import com.huaheng.framework.aspectj.lang.annotation.Log;
import com.huaheng.framework.aspectj.lang.constant.BusinessType;
import com.huaheng.framework.web.domain.AjaxResult;
import com.huaheng.mobile.receipt.MaterialInfo;
import com.huaheng.mobile.receipt.ReceiptBill;
import com.huaheng.pc.config.container.domain.Container;
import com.huaheng.pc.config.container.service.ContainerService;
import com.huaheng.pc.config.location.domain.Location;
import com.huaheng.pc.config.location.service.LocationService;
import com.huaheng.pc.config.material.domain.Material;
import com.huaheng.pc.config.material.service.MaterialService;
import com.huaheng.pc.inventory.cycleCountDetail.domain.CycleCountDetail;
import com.huaheng.pc.inventory.cycleCountDetail.domain.CycleCountDetailChild;
import com.huaheng.pc.inventory.cycleCountDetail.service.CycleCountDetailChildService;
import com.huaheng.pc.inventory.cycleCountDetail.service.CycleCountDetailService;
import com.huaheng.pc.inventory.cycleCountHeader.domain.CycleCountHeader;
import com.huaheng.pc.inventory.cycleCountHeader.mapper.CycleCountHeaderMapper;
import com.huaheng.pc.inventory.cycleCountHeader.service.CycleCountHeaderService;
import com.huaheng.pc.inventory.inventoryDetail.domain.InventoryDetail;
import com.huaheng.pc.inventory.inventoryDetail.service.InventoryDetailService;
import com.huaheng.pc.inventory.inventoryHeader.domain.InventoryHeader;
import com.huaheng.pc.inventory.inventoryHeader.service.InventoryHeaderService;
import com.huaheng.pc.inventory.inventoryTransaction.domain.InventoryTransaction;
import com.huaheng.pc.inventory.inventoryTransaction.service.InventoryTransactionService;
import com.huaheng.pc.receipt.receiptContainerDetail.domain.ReceiptContainerDetail;
import com.huaheng.pc.receipt.receiptContainerDetail.service.ReceiptContainerDetailService;
import com.huaheng.pc.receipt.receiptContainerHeader.domain.ReceiptContainerHeader;
import com.huaheng.pc.receipt.receiptContainerHeader.service.ReceiptContainerHeaderService;
import com.huaheng.pc.receipt.receiptDetail.domain.ReceiptDetail;
import com.huaheng.pc.receipt.receiptDetail.service.ReceiptDetailService;
import com.huaheng.pc.receipt.receiptHeader.domain.ReceiptHeader;
import com.huaheng.pc.receipt.receiptHeader.service.ReceiptHeaderService;
import com.huaheng.pc.report.excelReport.mapper.ExcelReportMapper;
import com.huaheng.pc.task.taskDetail.domain.TaskDetail;
import com.huaheng.pc.task.taskDetail.service.TaskDetailService;
import com.huaheng.pc.task.taskHeader.domain.TaskHeader;
import com.huaheng.pc.task.taskHeader.service.TaskHeaderService;
import com.huaheng.pc.task.taskHeader.service.TransferTaskService;
import com.huaheng.pc.task.taskHeader.service.WorkTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author Enzo Cotter
 * @date 2019/12/15
 */
@CrossOrigin
@RestController
@RequestMapping("/mobile/inventory")
@Api(tags = {"手机立体库库存相关"}, value = "手机立体库库存相关MobileInventoryController")
public class MobileInventoryController {

    @Resource
    private InventoryHeaderService inventoryService;
    @Resource
    private InventoryDetailService inventoryDetailService;
    @Resource
    private InventoryTransactionService inventoryTransactionService;
    @Resource
    private TaskHeaderService taskService;
    @Resource
    private TaskDetailService taskDetailService;
    @Resource
    private TransferTaskService transferTaskService;
    @Resource
    private WorkTaskService workTaskService;

    @Resource
    private LocationService locationService;
    @Resource
    ExcelReportMapper mapper;
    @Resource
    private CycleCountDetailService cycleCountDetailService;
    @Resource
    private ContainerService containerService;
    @Resource
    private CycleCountHeaderService cycleCountHeaderService;
    @Resource
    private CycleCountDetailChildService cycleCountDetailChildService;
    @Resource
    private CycleCountHeaderMapper cycleCountHeaderMapper;
    @Resource
    private ReceiptHeaderService receiptHeaderService;
    @Resource
    private ReceiptDetailService receiptDetailService;
    @Resource
    private ReceiptContainerHeaderService receiptContainerHeaderService;
    @Resource
    private ReceiptContainerDetailService receiptContainerDetailService;
    @Resource
    private MaterialService materialService;

    @PostMapping("/getInventoryInfo")
    @ApiOperation("移动端获得库存详情")
    @Log(title = "移动端获得库存详情", action = BusinessType.OTHER)
    public AjaxResult getInventoryInfo(@RequestBody @ApiParam(value = "物料编码或者库位号") Map<String, String> param) {
        if (param.get("code") == null || param.get("code").trim().length() < 1) {
            throw new JSONException("查询码(code)不能为空");
        }
        if (param.get("companyCode") == null || param.get("companyCode").trim().length() < 1) {
            throw new JSONException("(companyCode)不能为空");
        }
        return inventoryService.getInventory(param.get("code"), param.get("companyCode"));
    }

    @PostMapping("/createCheckOutTask")
    @ApiOperation("移动端创建出库查看任务")
    @ResponseBody
    public AjaxResult createCheckOutTask(@RequestBody @ApiParam(value = "库存ids") Map<String, String> param) {
        String ids = param.get("ids");
        String port = param.get("port");
        Integer companyId = DataUtils.getInteger(param.get("companyId"));
        String companyCode = param.get("companyCode");
        if (StringUtils.isEmpty(ids)) {
            return AjaxResult.error("ids不能为空");
        }
        return workTaskService.createCheckOutTaskByIds(Arrays.asList(Convert.toIntArray(ids)), port);
    }

    @PostMapping("/transfer")
    @ApiOperation("移动端创建移库任务")
    @ResponseBody
    public AjaxResult transfer(@RequestBody @ApiParam(value = "库位情况") Map<String, String> param) {
        String sourceLocation = param.get("sourceLocation");
        String destinationLocation = param.get("destinationLocation");
        return transferTaskService.createTransferTask(sourceLocation, destinationLocation, ShiroUtils.getWarehouseCode());
    }

    @PostMapping("/execute")
    @ApiOperation("执行立库任务")
    @ResponseBody
    public AjaxResult execute(@RequestBody @ApiParam(value = "任务id") Map<String, String> param) {
        String taskId = param.get("taskId");
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error("taskId不能为空");
        }

        AjaxResult ajaxResult = taskService.sendTaskToWcs(Convert.toIntArray(taskId));
        if (ajaxResult.hasErr()) {
            AjaxResult.success("执行失败");
        }
        return AjaxResult.success("下发执行成功");
    }

    @PostMapping("/executeList")
    @ApiOperation("执行立库任务")
    @Log(title = "执行立库任务", action = BusinessType.OTHER)
    public AjaxResult executeList(@RequestBody List<TaskIds> taskDetails) {
        Integer[] taskIds = new Integer[taskDetails.size()];
        for (int i = 0; i < taskDetails.size(); i++) {
            TaskIds taskDetail = taskDetails.get(i);
            taskIds[i] = taskDetail.getTaskId();
        }
        AjaxResult ajaxResult = taskService.sendTaskToWcs(taskIds);
        return ajaxResult;
    }

    @PostMapping("/completeTaskByWMS")
    @ApiOperation("完成立库任务")
    @ResponseBody
    public AjaxResult completeTaskByWMS(@RequestBody @ApiParam(value = "任务id") Map<String, String> param) throws Exception {
        String taskId = param.get("taskId");
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error("taskId不能为空");
        }

        AjaxResult ajaxResult = taskService.completeTaskByWMS(Convert.toIntArray(taskId), null);
        return ajaxResult;
    }

    @PostMapping("/completeTaskListByWMS")
    @ApiOperation("完成立库任务")
    @ResponseBody
    public AjaxResult completeTaskListByWMS(@RequestBody List<TaskIds> taskDetails) throws Exception {
        Integer[] taskIds = new Integer[taskDetails.size()];
        for (int i = 0; i < taskDetails.size(); i++) {
            TaskIds taskDetail = taskDetails.get(i);
            taskIds[i] = taskDetail.getTaskId();
        }
        AjaxResult ajaxResult = taskService.completeTaskByWMS(taskIds, null);
        return ajaxResult;
    }

    @PostMapping("/isLocation")
    @ApiOperation("判断是不是库位")
    @ResponseBody
    public AjaxResult isLocation(@RequestBody @ApiParam(value = "任务id") Map<String, String> param) {
        String code = param.get("code");
        if (StringUtils.isEmpty(code)) {
            return AjaxResult.error("location不能为空");
        }
        LambdaQueryWrapper<Location> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Location::getCode, code);
        Location location = locationService.getOne(queryWrapper);
        if (location == null) {
            return AjaxResult.error("没有这个库位");
        }
        return AjaxResult.success("库位存在").setData(code);
    }

    @PostMapping("/isContainer")
    @ApiOperation("判断是不是库位")
    @ResponseBody
    public AjaxResult isContainer(@RequestBody @ApiParam(value = "任务id") Map<String, String> param) {
        String code = param.get("code");
        if (StringUtils.isEmpty(code)) {
            return AjaxResult.error("location不能为空");
        }
        LambdaQueryWrapper<Container> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Container::getCode, code);
        Container container = containerService.getOne(queryWrapper);
        if (container == null) {
            return AjaxResult.error("没有这个容器");
        }
        return AjaxResult.success("容器存在").setData(code);
    }

    @PostMapping("/getLocationCode")
    @ApiOperation("移动端获得库位联想词")
    @Log(title = "移动端获得库位联想词", action = BusinessType.OTHER)
    public AjaxResult getLocationCode(@RequestBody @ApiParam(value = "库位号") Map<String, String> param) {
        if (param.get("code") == null || param.get("code").trim().length() < 1) {
            throw new JSONException("查询码(code)不能为空");
        }
        String type = param.get("type");
        if (type == null || type.trim().length() < 1) {
            throw new JSONException("type不能为空");
        }

        return inventoryService.getLocationForecast(param.get("code"), Integer.parseInt(type));
    }

    @PostMapping("/createEmptyIn")
    @ApiOperation("移动端空托入库")
    @Log(title = "移动端空托入库", action = BusinessType.OTHER)
    public AjaxResult createEmptyIn(@RequestBody Map<String, String> param) {
        if (param.get("containerCode") == null || param.get("containerCode").trim().length() < 1) {
            throw new JSONException("容器号不能为空");
        }
//        if  (param.get("destinationLocation") == null || param.get("destinationLocation").trim().length() < 1) {
//            throw new JSONException("目的库位不能为空");
//        }
        String containerCode = param.get("containerCode");
        String destinationLocation = param.get("destinationLocation");
        String companyCode = param.get("companyCode");
        return inventoryService.createEmptyIn(containerCode, destinationLocation);
    }

    @PostMapping("/createEmptyOut")
    @ApiOperation("移动端空托出库")
    @Log(title = "移动端空托出库", action = BusinessType.OTHER)
    public AjaxResult createEmptyOut(@RequestBody Map<String, String> param) {
        if (param.get("containerCode") == null || param.get("containerCode").trim().length() < 1) {
            throw new JSONException("容器号不能为空");
        }
        if (param.get("sourceLocation") == null || param.get("sourceLocation").trim().length() < 1) {
            throw new JSONException("源库位不能为空");
        }
        String containerCode = param.get("containerCode");
        String sourceLocation = param.get("sourceLocation");
        return inventoryService.createEmptyOut(containerCode, sourceLocation);
    }

    @PostMapping("/get7daysShipment")
    @ApiOperation("移动端获取7天收货和出货量")
    @Log(title = "移动端获取7天收货和出货量", action = BusinessType.OTHER)
    public AjaxResult get7daysShipment(@RequestBody Map<String, String> param) {
        String sql = "select a.click_date as date,ifnull(b.taskQty,0) as qty\n" +
                "from (\n" +
                "    SELECT curdate() as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 1 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 2 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 3 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 4 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 5 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 6 day) as click_date\n" +
                ") a left join (\n" +
                "SELECT DATE(h.created) AS created , SUM(d.qty) AS taskQty from shipment_container_detail d join shipment_container_header h on d.shippingContainerId = h.id and h.warehouseCode='" + ShiroUtils.getWarehouseCode() + "' WHERE h.created >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND h.status=30 GROUP BY DATE(h.created)\n" +
                ") b on a.click_date = b.created ORDER BY a.click_date;";
        List<LinkedHashMap<String, Object>> list = mapper.selectCommon(sql);

        sql = "select a.click_date as date,ifnull(b.taskQty,0) as qty\n" +
                "from (\n" +
                "    SELECT curdate() as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 1 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 2 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 3 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 4 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 5 day) as click_date\n" +
                "    union all\n" +
                "    SELECT date_sub(curdate(), interval 6 day) as click_date\n" +
                ") a left join (\n" +
                "SELECT DATE(h.created) AS created , SUM(d.qty) AS taskQty from receipt_container_detail d join receipt_container_header h on d.receiptContainerId = h.id and h.warehouseCode='" + ShiroUtils.getWarehouseCode() + "' WHERE h.created >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND d.status=30 GROUP BY DATE(h.created)\n" +
                ") b on a.click_date = b.created ORDER BY a.click_date;";
        List<LinkedHashMap<String, Object>> list2 = mapper.selectCommon(sql);


        List<LinkedHashMap<String, Object>> result = new ArrayList<>();
        result.addAll(list);
        result.addAll(list2);

        List<InventoryDetails> inventoryDetailList = new ArrayList<>();
        for (LinkedHashMap<String, Object> map : result) {
            Iterator iter = map.entrySet().iterator();
            String date = null;
            BigDecimal qty = new BigDecimal(0);
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry) iter.next();
                Object key = entry.getKey();
                Object val = entry.getValue();
                if (date == null) {
                    date = val.toString();
                } else {
                    qty = (BigDecimal) val;
                }
            }
            inventoryDetailList.add(newInventoryDetail(date, qty));
        }
        return AjaxResult.success(inventoryDetailList);
    }

    private InventoryDetails newInventoryDetail(String date, BigDecimal qty) {
        InventoryDetails inventoryDetail = new InventoryDetails();
        inventoryDetail.setDate(date);
        inventoryDetail.setQty(qty);
        return inventoryDetail;
    }

    @PostMapping("/getTodayShipmentDetail")
    @ApiOperation("移动端获得今天发货详情")
    @Log(title = "移动端获得今天发货详情", action = BusinessType.OTHER)
    public AjaxResult getTodayShipmentDetail(@RequestBody Map<String, String> param) {
        String sql = "select d.materialName, SUM(d.qty) as qty " +
                "from shipment_container_header h join shipment_container_detail d " +
                "on d.shippingContainerId = h.id WHERE h.created >= CURDATE() AND h.`status`>19 GROUP BY d.materialName";
        List<LinkedHashMap<String, Object>> list = mapper.selectCommon(sql);

        sql = "select m.name, b.taskQty as qty \n" +
                "from material m \n" +
                "join (\n" +
                "select d.materialCode as material, SUM(d.qty) " +
                "as taskQty from receipt_container_header h join receipt_container_detail d " +
                "on d.receiptContainerId = h.id WHERE h.created >= CURDATE() AND h.`status`>19 GROUP BY d.materialCode\n" +
                ") b on m.`code` = b.material ORDER BY m.name";
        List<LinkedHashMap<String, Object>> list2 = mapper.selectCommon(sql);
        List<com.huaheng.mobile.invenory.ShipmentDetail> shipmentDetails = getShipmentDetails(list);
        shipmentDetails.add(newShipmentDetail("delete", new BigDecimal(0)));
        shipmentDetails.addAll(getShipmentDetails(list2));

        return AjaxResult.success(shipmentDetails);
    }

    private List<com.huaheng.mobile.invenory.ShipmentDetail> getShipmentDetails(List<LinkedHashMap<String, Object>> list) {
        List<com.huaheng.mobile.invenory.ShipmentDetail> shipmentDetails = new ArrayList<>();
        for (LinkedHashMap<String, Object> map : list) {
            Iterator iter = map.entrySet().iterator();
            String materialName = null;
            BigDecimal qty = new BigDecimal(0);
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry) iter.next();
                Object key = entry.getKey();
                Object val = entry.getValue();
                if (materialName == null) {
                    materialName = val.toString();
                } else {
                    qty = (BigDecimal) val;
                }
            }
            shipmentDetails.add(newShipmentDetail(materialName, qty));
        }
        return shipmentDetails;
    }

    private com.huaheng.mobile.invenory.ShipmentDetail newShipmentDetail(String materialName, BigDecimal qty) {
        com.huaheng.mobile.invenory.ShipmentDetail shipmentDetail = new com.huaheng.mobile.invenory.ShipmentDetail();
        shipmentDetail.setMaterialName(materialName);
        shipmentDetail.setQty(qty);
        return shipmentDetail;
    }

    /**
     * 移动端根据容器编码获取盘点任务
     *
     * @param param
     * @return
     */
    @ResponseBody
    @PostMapping("/findTransferByContainerCode")
    public AjaxResult findTransferByContainerCode(@RequestBody Map<String, String> param) {
        String containCode = param.get("containCode");
        if (StringUtils.isEmpty(containCode)) {
            return AjaxResult.error("容器编码为空");
        } else {
            return AjaxResult.success(taskService.mobileFindTransferTask(containCode));
        }
    }

    /**
     * 移动端实盘登记
     *
     * @return
     */
    @ResponseBody
    @PostMapping("/confirmGapQty")
    public AjaxResult confirmGapQty(@RequestBody List<MaterialInfo> materialInfos) {
        for (MaterialInfo materialInfo : materialInfos) {
            int detailId = materialInfo.getBillDetailId();
            BigDecimal qty = new BigDecimal(materialInfo.getQty());
//            CycleCountDetail cycleCountDetail = cycleCountDetailService.getById(detailId);
            LambdaQueryWrapper<CycleCountDetailChild> cycleCountDetailChildLambdaQueryWrapper = Wrappers.lambdaQuery();
            cycleCountDetailChildLambdaQueryWrapper.eq(CycleCountDetailChild::getCycleCountDetailId, detailId)
                    .eq(CycleCountDetailChild::getMaterialCode, materialInfo.getMaterialCode());
            CycleCountDetailChild cycleCountDetailChild = cycleCountDetailChildService.getOne(cycleCountDetailChildLambdaQueryWrapper);
            AjaxResult ajaxResult = cycleCountDetailService.confirmGapQty(cycleCountDetailChild.getId(), qty);
            if (ajaxResult.hasErr()) {
                return AjaxResult.error("盘点失败");
            }
        }
        return AjaxResult.success("盘点成功");
    }

    @PostMapping("/getEmptyContainerInLocation")
    @ApiOperation("选取空托出库的库位")
    @Log(title = "选取空托出库的库位", action = BusinessType.OTHER)
    public AjaxResult getEmptyContainerInLocation(@RequestBody Map<String, String> param) {
        String warehouCOde = ShiroUtils.getWarehouseCode();
        List<Location> list = containerService.getEmptyContainerInLocation(null, null, null, null, ShiroUtils.getWarehouseCode());
        return AjaxResult.success(list);
    }

    @PostMapping("/pickLocation")
    @ApiOperation("选取补充入库的库位")
    @Log(title = "选取补充入库的库位", action = BusinessType.OTHER)
    public AjaxResult pickLocation(@RequestBody Map<String, String> param) {
        List<Location> locations = locationService.pickLocation();
        Container condition = new Container();
        condition.setWarehouseCode(ShiroUtils.getWarehouseCode());
        LambdaQueryWrapper lambda3 = Wrappers.lambdaQuery(condition);
        List<Container> containers = containerService.list(lambda3);
        for (Location location : locations) {
            for (Container container : containers) {
                if (container.getCode().equals(location.getContainerCode())) {
                    if (QuantityConstant.STATUS_CONTAINER_SOME.equals(container.getStatus())) {
                        location.setStatus(QuantityConstant.STATUS_LOCATION_LOCK);
                    }
                }
            }
        }
        return AjaxResult.success(locations);
    }

    @PostMapping("/searchInventory")
    @ApiOperation("移动端查询库存")
    @Log(title = "移动端查询库存", action = BusinessType.OTHER)
    public AjaxResult searchInventory(@RequestBody @ApiParam(value = "物料号") Map<String, String> param) {
        String companyCode = param.get("companyCode");
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String now = df.format(new Date());
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.DATE, -7);
        Date first = c.getTime();
        String start = df.format(first);//前一天
        LambdaQueryWrapper<InventoryDetail> inventoryQueryWrapper = Wrappers.lambdaQuery();
        inventoryQueryWrapper.eq(InventoryDetail::getCompanyCode, companyCode)
                .eq(InventoryDetail::getWarehouseCode, ShiroUtils.getWarehouseCode())
                .orderByDesc(InventoryDetail::getCreated);
        List<InventoryDetail> inventoryDetailList = inventoryDetailService.list(inventoryQueryWrapper);
        return AjaxResult.success(inventoryDetailList);
    }

    @PostMapping("/searchInventoryInCondition")
    @ApiOperation("移动端查询库存")
    @Log(title = "移动端查询库存", action = BusinessType.OTHER)
    public AjaxResult searchInventoryInCondition(@RequestBody @ApiParam(value = "物料号") Map<String, String> param) {
        String companyCode = param.get("companyCode");
        String containerCode = param.get("containerCode");
        String materialCode = param.get("materialCode");
        String materialName = param.get("materialName");
        String materialSpec = param.get("materialSpec");
        String startTime = param.get("startTime");
        String endTime = param.get("endTime");
        LambdaQueryWrapper<InventoryDetail> inventoryQueryWrapper = Wrappers.lambdaQuery();
        inventoryQueryWrapper.eq(InventoryDetail::getCompanyCode, companyCode)
                .eq(InventoryDetail::getWarehouseCode, ShiroUtils.getWarehouseCode())
                .eq(StringUtils.isNotEmpty(containerCode), InventoryDetail::getContainerCode, containerCode)
                .like(StringUtils.isNotEmpty(materialCode), InventoryDetail::getMaterialCode, materialCode)
                .like(StringUtils.isNotEmpty(materialName), InventoryDetail::getMaterialName, materialName)
                .like(StringUtils.isNotEmpty(materialSpec), InventoryDetail::getMaterialSpec, materialSpec)
                .gt(StringUtils.isNotEmpty(startTime), InventoryDetail::getCreated, startTime)
                .le(StringUtils.isNotEmpty(endTime), InventoryDetail::getCreated, endTime)
                .orderByDesc(InventoryDetail::getCreated);
        List<InventoryDetail> inventoryDetailList = inventoryDetailService.list(inventoryQueryWrapper);
        return AjaxResult.success(inventoryDetailList);
    }


    @PostMapping("/findInventory")
    @ApiOperation("移动端查询库存详情")
    @Log(title = "移动端查询库存详情", action = BusinessType.OTHER)
    public AjaxResult findInventory(@RequestBody @ApiParam(value = "物料号") Map<String, String> param) {
        String inventoryDetailId = param.get("inventoryDetailId");
        String companyCode = param.get("companyCode");
        if (StringUtils.isNull(inventoryDetailId)) {
            return AjaxResult.error("任务id为空");
        } else if (StringUtils.isNull(companyCode)) {
            return AjaxResult.error("公司编码为空");
        }

        /* 查询入库单,如果数据库中不存在,则调用ERP接口拉取单据,成功后再次查询返回结果*/
        LambdaQueryWrapper<InventoryDetail> inventoryQueryWrapper = Wrappers.lambdaQuery();
        inventoryQueryWrapper.eq(InventoryDetail::getId, inventoryDetailId)
                .eq(InventoryDetail::getCompanyCode, companyCode);
        InventoryDetail inventoryDetail = inventoryDetailService.getOne(inventoryQueryWrapper);
        if (inventoryDetail == null) {
            return AjaxResult.error("没有找到库存详情");
        }
        return AjaxResult.success(inventoryDetail);
    }

    @PostMapping("/searchInventoryTransactionInCondition")
    @ApiOperation("移动端查询库存交易记录")
    @Log(title = "移动端查询库存交易记录", action = BusinessType.OTHER)
    public AjaxResult searchInventoryTransactionInCondition(@RequestBody @ApiParam(value = "物料号") Map<String, String> param) {
        String companyCode = param.get("companyCode");
        String transactionType = param.get("transactionType");
        String containerCode = param.get("containerCode");
        String materialCode = param.get("materialCode");
        String materialName = param.get("materialName");
        String materialSpec = param.get("materialSpec");
        String startTime = param.get("startTime");
        String endTime = param.get("endTime");
        LambdaQueryWrapper<InventoryTransaction> inventoryTransactionLambdaQueryWrapper = Wrappers.lambdaQuery();
        inventoryTransactionLambdaQueryWrapper.eq(InventoryTransaction::getCompanyCode, companyCode)
                .eq(InventoryTransaction::getWarehouseCode, ShiroUtils.getWarehouseCode())
                .eq(StringUtils.isNotEmpty(transactionType), InventoryTransaction::getTransactionType, transactionType)
                .eq(StringUtils.isNotEmpty(containerCode), InventoryTransaction::getContainerCode, containerCode)
                .like(StringUtils.isNotEmpty(materialCode), InventoryTransaction::getMaterialCode, materialCode)
                .like(StringUtils.isNotEmpty(materialName), InventoryTransaction::getMaterialName, materialName)
                .like(StringUtils.isNotEmpty(materialSpec), InventoryTransaction::getMaterialSpec, materialSpec)
                .gt(StringUtils.isNotEmpty(startTime), InventoryTransaction::getCreated, startTime)
                .le(StringUtils.isNotEmpty(endTime), InventoryTransaction::getCreated, endTime)
                .orderByDesc(InventoryTransaction::getCreated);
        List<InventoryTransaction> inventoryDetailList = inventoryTransactionService.list(inventoryTransactionLambdaQueryWrapper);
        return AjaxResult.success(inventoryDetailList);
    }


    @PostMapping("/circleCount")
    @ApiOperation("移动端盘点库存")
    @Log(title = "移动端盘点库存", action = BusinessType.OTHER)
    public AjaxResult circleCount(@RequestBody List<CircleBean> circleBeanList) {
        String locaitonCode = circleBeanList.get(0).getLocaitonCode();
        String containerCode = circleBeanList.get(0).getContainerCode();
        String circleCode = addCircleHeader(circleBeanList);
        boolean diff = false;
        for (CircleBean circleBean : circleBeanList) {
            LambdaQueryWrapper<CycleCountDetailChild> lambdaQueryWrapper = Wrappers.lambdaQuery();
            lambdaQueryWrapper.eq(CycleCountDetailChild::getContainerCode, containerCode)
                    .eq(CycleCountDetailChild::getLocationCode, locaitonCode)
                    .eq(CycleCountDetailChild::getCycleCountHeadCode, circleCode)
                    .eq(CycleCountDetailChild::getChildStatus, 1)
                    .eq(CycleCountDetailChild::getMaterialCode, circleBean.getMaterialCode());
            CycleCountDetailChild cycleCountDetailChild = cycleCountDetailChildService.getOne(lambdaQueryWrapper);
            AjaxResult result = cycleCountDetailService.confirmGapQty(cycleCountDetailChild.getId(), new BigDecimal(circleBean.getQty()));
            cycleCountDetailChild = (CycleCountDetailChild) result.getData();
            LambdaQueryWrapper<CycleCountDetail> lambdaQueryWrapper1 = Wrappers.lambdaQuery();
            lambdaQueryWrapper1.eq(CycleCountDetail::getId, cycleCountDetailChild.getCycleCountDetailId());
            CycleCountDetail cycleCountDetail = cycleCountDetailService.getOne(lambdaQueryWrapper1);
            if (cycleCountDetailChild.getGapQty().compareTo(BigDecimal.ZERO) != 0) {
                cycleCountDetailChild.setChildStatus(QuantityConstant.CYCLECOUNT_STATUS_DIFFERENCE);
                cycleCountDetail.setEnableStatus(QuantityConstant.CYCLECOUNT_STATUS_DIFFERENCE);
                diff = true;
            } else {
                cycleCountDetailChild.setChildStatus(QuantityConstant.CYCLECOUNT_STATUS_COMPLETED);
                cycleCountDetail.setEnableStatus(QuantityConstant.CYCLECOUNT_STATUS_COMPLETED);
            }
        }
        LambdaQueryWrapper<CycleCountHeader> lambdaQueryWrapper2 = Wrappers.lambdaQuery();
        lambdaQueryWrapper2.eq(CycleCountHeader::getCode, circleCode);
        CycleCountHeader cycleCountHeader = cycleCountHeaderService.getOne(lambdaQueryWrapper2);
        if (diff) {
            cycleCountHeader.setStatusCyc(QuantityConstant.CYCLECOUNT_STATUS_DIFFERENCE);
        } else {
            cycleCountHeader.setStatusCyc(QuantityConstant.CYCLECOUNT_STATUS_COMPLETED);
        }
        cycleCountHeaderService.updateById(cycleCountHeader);
        return AjaxResult.success();
    }

    private String addCircleHeader(List<CircleBean> circleBeanList) {
        String maxCode = cycleCountHeaderMapper.getLastCode();
        LambdaQueryWrapper<CycleCountHeader> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(CycleCountHeader::getCode, maxCode)
                .le(CycleCountHeader::getStatusCyc, 105);
        CycleCountHeader cycleCountHeader = new CycleCountHeader();
        CycleCountHeader header = cycleCountHeaderService.getOne(lambdaQueryWrapper);
        if (header == null) {
            cycleCountHeader.setCreated(new Date());
            cycleCountHeader.setCreatedBy(ShiroUtils.getLoginName());
            cycleCountHeader.setCountType("static");
            cycleCountHeader.setCode(createCode());
            cycleCountHeader.setPreferenceCode("ccp2019101700001");
            cycleCountHeader.setRound(1);
            cycleCountHeader.setWarehouseCode(ShiroUtils.getWarehouseCode());
            cycleCountHeader.setStatusCyc(1);
            cycleCountHeader.setCountAttribute(1);
            cycleCountHeader.setTotalLocs(0);
            cycleCountHeader.setTotalItems(0);
            cycleCountHeader.setLastUpdated(new Date());
            cycleCountHeader.setLastUpdatedBy(ShiroUtils.getLoginName());
            cycleCountHeader.setEnable(true);
            cycleCountHeaderService.save(cycleCountHeader);
        } else {
            cycleCountHeader = header;
        }
        LambdaQueryWrapper<InventoryHeader> inventoryHeaderLambdaQueryWrapper = Wrappers.lambdaQuery();
        inventoryHeaderLambdaQueryWrapper.eq(InventoryHeader::getLocationCode, circleBeanList.get(0).getLocaitonCode());
        InventoryHeader inventoryHeader = inventoryService.getOne(inventoryHeaderLambdaQueryWrapper);
        Integer[] inventoryHeaderIds = new Integer[]{inventoryHeader.getId()};
        cycleCountDetailService.addDetails(cycleCountHeader.getCode(), inventoryHeaderIds);
        return cycleCountHeader.getCode();
    }

    /**
     * 生成盘点单主Code
     *
     * @return
     */
    public String createCode() {
        String code;
        Date now = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
        String maxCode = cycleCountHeaderMapper.getLastCode();
        ;
        //如果指定类型的最后的code存在,并且日期一致。那么 code = 单类型 + 年月日 + (排序号 + 1)
        if (maxCode != null && maxCode.substring(maxCode.length() - 13, maxCode.length() - 5).equals(df.format(now))) {
            Integer Count = Integer.valueOf(maxCode.substring(maxCode.length() - 5, maxCode.length()));
            code = "PD" + df.format(now) + String.format("%05d", Count + 1);
        } else {
            code = "PD" + df.format(now) + "00001";
        }
        return code;
    }

    @PostMapping("/callBox")
    @ResponseBody
    @ApiOperation("呼叫料盒")
    @Log(title = "呼叫料盒", action = BusinessType.OTHER)
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult callBox(@RequestBody @ApiParam(value = "物料号") Map<String, String> param) {
        String containerCode = param.get("containerCode");
        String destinationLocation = param.get("destinationLocation");
        LambdaQueryWrapper<Container> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(Container::getCode, containerCode).eq(Container::getWarehouseCode, ShiroUtils.getWarehouseCode());
        Container container = containerService.getOne(lambdaQueryWrapper);
        if (container == null) {
            return AjaxResult.error("容器不存在");
        }
        if (!StringUtils.isNotEmpty(container.getLocationCode())) {
            return AjaxResult.error("容器不在库位[" + container.getLocationCode() + "]上");
        }
        if (!container.getLocationCode().equals(destinationLocation)) {
            return AjaxResult.error("容器不在目的库位上");
        }
        Location temp = new Location();
        temp.setCode(destinationLocation);
        temp.setWarehouseCode(ShiroUtils.getWarehouseCode());
        Location location = locationService.selectFirstEntity(temp);
        if (StringUtils.isNotEmpty(destinationLocation)) {
            //校验目标地址
            if (location == null) {
                return AjaxResult.error("目标库位不存在");
            }
            if (!QuantityConstant.STATUS_LOCATION_EMPTY.equals(location.getStatus())) {
                return AjaxResult.error("目标库位非空闲");
            }
        }
        //判断托盘是否已经存在任务
        List<TaskHeader> list = taskService.list(new LambdaQueryWrapper<TaskHeader>()
                .eq(TaskHeader::getContainerCode, containerCode)
                .ne(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_COMPLETED)
                .eq(TaskHeader::getWarehouseCode, ShiroUtils.getWarehouseCode())
        );
        if (CollectionUtils.isNotEmpty(list)) {
            return AjaxResult.error("容器已存在任务");
        }

        //创建主任务
        TaskHeader taskHeader = new TaskHeader();
        taskHeader.setId(null);
        taskHeader.setWarehouseCode(ShiroUtils.getWarehouseCode());
        taskHeader.setCompanyCode(ShiroUtils.getCompanyCode());//货主
        taskHeader.setType(QuantityConstant.TASK_TYPE_SUPPLEMENTRECEIPT);
        taskHeader.setInternalTaskType(QuantityConstant.TASK_INTENERTYPE_RECEIPT);
        taskHeader.setContainerCode(container.getCode());
        taskHeader.setStatus(QuantityConstant.TASK_STATUS_BUILD);
        taskHeader.setZoneCode(location.getZoneCode());
        taskHeader.setFromLocation(location.getCode());
        taskHeader.setToLocation(location.getCode());
        taskHeader.setCreated(new Date());
        taskHeader.setCreatedBy(ShiroUtils.getUserName());
        taskHeader.setLastUpdatedBy(ShiroUtils.getLoginName());
        taskHeader.setLastUpdated(new Date());
        if (taskService.save(taskHeader)) {
            //锁定库位状态
            TaskDetail taskDetail = new TaskDetail();
            taskDetail.setTaskId(taskHeader.getId());
            taskDetail.setTaskType(QuantityConstant.TASK_TYPE_SUPPLEMENTRECEIPT);
            taskDetail.setInternalTaskType(QuantityConstant.TASK_INTENERTYPE_RECEIPT);
            taskDetail.setWarehouseCode(ShiroUtils.getWarehouseCode());
            taskDetail.setCompanyCode(ShiroUtils.getCompanyCode());
            taskDetail.setStatus(QuantityConstant.TASK_STATUS_BUILD);
            taskDetail.setFromLocation(location.getCode());
            taskDetail.setToLocation(location.getCode());
            taskDetail.setContainerCode(containerCode);
            taskDetail.setCreated(new Date());
            taskDetail.setLastUpdated(new Date());
            taskDetailService.save(taskDetail);
            locationService.updateStatus(location.getCode(), QuantityConstant.STATUS_LOCATION_LOCK);
        } else {
            throw new ServiceException("补充入库主表生成失败!");
        }

        return AjaxResult.success(taskHeader.getId());
    }

    @PostMapping("/quickReceipt")
    @ResponseBody
    @ApiOperation("呼叫料盒收货保存")
    @Log(title = "呼叫料盒收货保存", action = BusinessType.OTHER)
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult quickReceipt(@RequestBody @ApiParam(value = "收货单") List<ReceiptBill> receiptBills) throws Exception {
        if (receiptBills == null || receiptBills.size() <= 0) {
            throw new JSONException("没有收货信息");
        }
        boolean flag = true;
        for (ReceiptBill receiptBill : receiptBills) {
            //String companyCode = receiptBill.getCompanyCode();
            String containerCode = receiptBill.getReceiptContainerCode();
            String locationCode = receiptBill.getLocationCode();
            String receiptDetailId = receiptBill.getReceiptDetailId();
            LambdaQueryWrapper<Container> lambdaQueryWrapper = Wrappers.lambdaQuery();
            lambdaQueryWrapper.eq(Container::getCode, containerCode).eq(Container::getWarehouseCode, ShiroUtils.getWarehouseCode());
            Container container = containerService.getOne(lambdaQueryWrapper);
            if (container == null) {
                throw new JSONException("不存在这个托盘");
            }
            if (locationCode != null && locationCode.equals(container.getLocationCode())) {
                //查询未完成的入库任务
                List<TaskHeader> list = taskService.list(new LambdaQueryWrapper<TaskHeader>()
                        .eq(TaskHeader::getContainerCode, containerCode)
                        .ne(TaskHeader::getTaskType, QuantityConstant.TASK_TYPE_SUPPLEMENTRECEIPT)
                        .eq(TaskHeader::getWarehouseCode, ShiroUtils.getWarehouseCode())
                        .ne(TaskHeader::getStatus, QuantityConstant.TASK_STATUS_COMPLETED)
                );
                if (CollectionUtils.isNotEmpty(list)) {
                    throw new JSONException("没有找到托盘对应的任务");
                }
                ReceiptDetail receiptDetail = receiptDetailService.getById(Integer.valueOf(receiptDetailId));
                if (receiptDetail == null) {
                    throw new JSONException("没有找到入库单详情");
                }

                ReceiptHeader receiptHeader = receiptHeaderService.getById(receiptDetail.getReceiptId());
                if (receiptHeader == null) {
                    throw new JSONException("没有找到入库单");
                }

                /* *
                 * select * from receipt_container_header where containerCode =#{containerCode} and status &lt; 20
                 */
                ReceiptContainerHeader receiptContainerHeader = new ReceiptContainerHeader();
                receiptContainerHeader.setContainerCode(containerCode);
           /* List<ReceiptContainerHeader> list = receiptContainerHeaderMapper.selectUnCompletedReceiptContainer(receiptContainerHeader);
            if (list.size() >= 1){
                throw new ServiceException("容器已经生成任务,不能放物料了!");
            }*/
                //如果不存在记录则新建记录
                receiptContainerHeader.setWarehouseCode(ShiroUtils.getWarehouseCode());
                receiptContainerHeader.setTaskType(QuantityConstant.TASK_TYPE_SUPPLEMENTRECEIPT);
                receiptContainerHeader.setCompanyCode(ShiroUtils.getCompanyCode());
                receiptContainerHeader.setFromLocation(container.getLocationCode());
                receiptContainerHeader.setToLocation(container.getLocationCode());
                receiptContainerHeader.setCreatedBy(ShiroUtils.getLoginName());
                receiptContainerHeader.setStatus(QuantityConstant.RECEIPT_CONTAINER_TASK);
                if (receiptContainerHeaderService.save(receiptContainerHeader)) {
                    throw new ServiceException("入库组盘头表保存失败");
                }
                receiptHeader.setFirstStatus(200);
                receiptHeader.setLastStatus(200);
                receiptHeaderService.updateById(receiptHeader);
                TaskHeader taskHeader = list.get(0);
                taskHeader.setAllocationHeadId(receiptContainerHeader.getId());
                taskService.updateById(taskHeader);
                ReceiptDetail receiptDetail2 = receiptDetailService.getById(Integer.valueOf(receiptBill.getReceiptDetailId()));
                if (receiptDetail2 == null) {
                    throw new JSONException("没有找到入库单详情");
                }

                BigDecimal openQty = receiptDetail2.getTaskQty();
                BigDecimal totalQty = receiptDetail2.getQty();
                BigDecimal qty = openQty.add(receiptBill.getQty());
                if (totalQty.subtract(qty).compareTo(BigDecimal.ZERO) < 0) {
                    throw new Exception("配盘数量大于表单数量");
                }

                receiptDetail2.setTaskQty(qty);
                receiptDetailService.updateById(receiptDetail2);

                ReceiptContainerDetail receiptContainerDetail = new ReceiptContainerDetail();
                receiptContainerDetail.setReceiptContainerId(receiptContainerHeader.getId());
                receiptContainerDetail.setReceiptId(receiptHeader.getId());
                receiptContainerDetail.setReceiptDetailId(receiptDetail2.getId());
                receiptContainerDetail.setReceiptCode(receiptHeader.getCode());

                Material material = materialService.getOne(new LambdaQueryWrapper<Material>().eq(Material::getCode, receiptDetail2.getMaterialCode()).eq(Material::getWarehouseCode, ShiroUtils.getWarehouseCode()));

                receiptContainerDetail.setMaterialCode(material.getCode());
                receiptContainerDetail.setMaterialName(material.getName());
                receiptContainerDetail.setMaterialSpec(material.getSpec());
                receiptContainerDetail.setQty(receiptBill.getQty());
                receiptContainerDetail.setCreatedBy(ShiroUtils.getLoginName());
                receiptContainerDetailService.save(receiptContainerDetail);

                List<TaskDetail> taskDetailList = taskDetailService.list(new LambdaQueryWrapper<TaskDetail>().eq(TaskDetail::getTaskId, taskHeader.getId()));
                if (flag) {
                    if (taskDetailList.size() == 1 && taskDetailList != null) {
                        TaskDetail taskDetail = taskDetailList.get(0);
                        taskDetail.setContainerCode(containerCode);
                        taskDetail.setWarehouseCode(ShiroUtils.getWarehouseCode());
                        taskDetail.setCompanyCode(ShiroUtils.getCompanyCode());
                        taskDetail.setMaterialCode(material.getCode());
                        taskDetail.setMaterialName(material.getName());
                        taskDetail.setBillCode(receiptHeader.getCode());
                        taskDetail.setBillId(receiptHeader.getId());
                        taskDetail.setBillDetailId(Integer.parseInt(receiptBill.getReceiptDetailId()));
                        taskDetail.setQty(receiptBill.getQty());
                        taskDetail.setFromLocation(taskHeader.getFromLocation());
                        taskDetail.setToLocation(taskHeader.getToLocation());
                        taskDetail.setAllocationId(receiptContainerDetail.getId());
                        taskDetailService.updateById(taskDetail);
                        flag = false;
                    }
                } else {
                    TaskDetail taskDetail = new TaskDetail();
                    taskDetail.setContainerCode(containerCode);
                    taskDetail.setWarehouseCode(ShiroUtils.getWarehouseCode());
                    taskDetail.setCompanyCode(ShiroUtils.getCompanyCode());
                    taskDetail.setMaterialCode(material.getCode());
                    taskDetail.setMaterialName(material.getName());
                    taskDetail.setBillCode(receiptHeader.getCode());
                    taskDetail.setBillId(receiptHeader.getId());
                    taskDetail.setBillDetailId(Integer.parseInt(receiptBill.getReceiptDetailId()));
                    taskDetail.setQty(receiptBill.getQty());
                    taskDetail.setFromLocation(taskHeader.getFromLocation());
                    taskDetail.setToLocation(taskHeader.getToLocation());
                    taskDetail.setAllocationId(receiptContainerDetail.getId());
                    taskDetailService.save(taskDetail);
                }
            }
        }
        return AjaxResult.success("收货成功");
    }
}