package com.bs.jxc.controller;

import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bs.common.annotation.Log;
import com.bs.common.annotation.RepeatSubmit;
import com.bs.common.core.controller.BaseController;
import com.bs.common.core.domain.AjaxResult;
import com.bs.common.core.page.TableDataInfo;
import com.bs.common.enums.BusinessType;
import com.bs.common.utils.poi.ExcelUtil;
import com.bs.jxc.domain.*;
import com.bs.jxc.service.*;
import com.github.pagehelper.PageInfo;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 出入库单据Controller
 *
 * @author bs
 * @date 2023-07-10
 */
@Api(tags = "出入库单据")
@RestController
@RequestMapping("/jxc/ckbill")
public class CkBillController extends BaseController {
    @Resource
    private ICkBillService ckBillService;
    @Resource
    private ICkBillCargoService ckBillCargoService;
    @Resource
    private ICkCargoStockService ckCargoStockService;
    @Resource
    private ICkStockChangeService ckStockChangeService;
    @Resource
    private ICkBillStockService ckBillStockService;


    /**
     * 分页查询出入库单据列表
     */
    @ApiOperation("分页查询出入库单据列表")
    @GetMapping("/pageList")
    public TableDataInfo pageList(CkBill ckBill) {
        startPage();
        LambdaQueryWrapper<CkBill> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(CkBill::getBillStatus, "1");
        condition(queryWrapper, ckBill);
        List<CkBill> list = ckBillService.list(queryWrapper);
        return getDataTable(list);
    }


    /**
     * 分页查询出入库单据列表
     */
    @ApiOperation("分页查询出入库单据列表")
    @GetMapping("/stockPageList")
    public TableDataInfo stockPageList(CkBill ckBill) {
        startPage();
        LambdaQueryWrapper<CkBill> queryWrapper = new LambdaQueryWrapper();
        condition(queryWrapper, ckBill);
        //单据类型
        if(Validator.isNotEmpty(ckBill.getBillType())){
            if (ckBill.getBillType().equals("1")) {
                queryWrapper.ne(CkBill::getBillType, "2");
            }else if(ckBill.getBillType().equals("2")){
                queryWrapper.ne(CkBill::getBillType, "1");
            }else{
                queryWrapper.eq(CkBill::getBillType, ckBill.getBillType());
            }
        }
        List<CkBill> list = ckBillService.list(queryWrapper);
        return getDataTable(list);
    }

    /**
     * 查询出入库单据列表
     */
    @ApiOperation("查询出入库单据列表")
    @GetMapping("/list")
    public AjaxResult list(CkBill ckBill) {
        LambdaQueryWrapper<CkBill> queryWrapper = new LambdaQueryWrapper();
        condition(queryWrapper, ckBill);
        List<CkBill> list = ckBillService.list(queryWrapper);
        return success(list);
    }

    /**
     * 导出出入库单据列表
     */
    @ApiOperation("导出出入库单据列表")
    @Log(title = "出入库单据导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, CkBill ckBill) {
        LambdaQueryWrapper<CkBill> queryWrapper = new LambdaQueryWrapper();
        condition(queryWrapper, ckBill);
        List<CkBill> list = ckBillService.list(queryWrapper);
        ExcelUtil<CkBill> util = new ExcelUtil<CkBill>(CkBill.class);
        util.exportExcel(response, list, "出入库单据数据");
    }

    /**
     * 获取出入库单据详细信息
     */
    @ApiOperation("获取出入库单据详细信息")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(ckBillService.getById(id));
    }

    /**
     * 新增出入库单据
     */
    @ApiOperation("新增出入库单据")
    @Log(title = "出入库单据新增", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody CkBill ckBill) {
        return toAjax(ckBillService.save(ckBill));
    }


    /**
     * 新增混配矿单据（生成混配矿，入库、信息）
     */
    @ApiOperation("新增混配矿单据")
    @Log(title = "新增混配矿单据", businessType = BusinessType.INSERT)
    @PostMapping("/addMixture")
    @RepeatSubmit
    public AjaxResult addMixture(@RequestBody CkBill ckBill) {
        AjaxResult ajaxResult = verifyMixture(ckBill);
        if (ajaxResult.isFail()) {
            return ajaxResult;
        }
        return ckBillService.mixtureCargo(ckBill);
    }

    /**
     * 撤回出库单据
     */
    @ApiOperation("撤回混配矿单据")
    @Log(title = "撤回混配矿单据", businessType = BusinessType.INSERT)
    @GetMapping(value = "/recallMixture/{id}")
    @RepeatSubmit
    public AjaxResult recallMixture(@PathVariable("id") Long id) {
        CkBill ckBill = ckBillService.getById(id);
        if (!ckBill.getSourceType().equals("3")) {
            return error("非本页面操作出库，不能撤回");
        }
        if (ckBill.getBillStatus().equals("0")) {
            return error("未提交的出库单不允许做撤回操作");
        }
        return ckBillService.warehouseWork(ckBill, true);
    }

    /**
     * 获取混配矿详细信息
     */
    @ApiOperation("获取混配矿详细信息")
    @GetMapping(value = "/getMixtureInfo/{id}")
    public AjaxResult getMixtureInfo(@PathVariable("id") Long id) {
        MPJLambdaWrapper<CkBill> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(CkBill.class)
                .selectCollection(CkBillCargo.class, CkBill::getCkBillCargos, billCargo -> billCargo.collection(
                        CkBillStock.class, CkBillCargo::getCkBillStocks)).
                leftJoin(CkBillCargo.class, CkBillCargo::getBillId, CkBill::getId).
                leftJoin(CkBillStock.class, CkBillStock::getBillCargoId, CkBillCargo::getId);
        queryWrapper.eq(CkBill::getBillType, "4");
        queryWrapper.eq(CkBill::getId, id);
        CkBill ckBill = ckBillService.selectJoinOne(CkBill.class, queryWrapper);
        List<CkBillCargo> ckBillCargos = ckBill.getCkBillCargos();
        List<CkBillStock> oldCargo = new ArrayList<>();
        List<CkBillStock> newCargo = new ArrayList<>();
        ckBillCargos.forEach(ele -> {
            List<CkBillStock> ckBillStocks = ele.getCkBillStocks();
            ckBillStocks.forEach(stock -> {
                stock.setExpiryDate(ele.getExpiryDate());
                stock.setCargoNumber(ele.getCargoNumber());
                stock.setItemNumber(ele.getItemNumber());
                stock.setBookNumber(ele.getBookNumber());
                stock.setCustomsNo(ele.getCustomsNo());
                stock.setListNumber(ele.getListNumber());
                stock.setCargoId(ele.getCargoId());
                if (ele.getInoutType().equals("1")) {//入库
                    MPJLambdaWrapper<CkCargoStock> mpjWrapper = new MPJLambdaWrapper();
                    mpjWrapper.select("sum(cargo_num) as cargo_num",
                            "sum(cargo_wt) as cargo_wt",
                            "sum(cargo_vol) as cargo_vol",
                            "sum(cargo_value) as cargo_value"
                    ).select(CkCargoStock::getCargoId,
                            CkCargoStock::getCargoName,
                            CkCargoStock::getCustId,
                            CkCargoStock::getCustName,
                            CkCargoStock::getCargoSpec,
                            CkCargoStock::getOriginCountry,
                            CkCargoStock::getHsCode);
                    mpjWrapper.eq(CkCargoStock::getCargoId, ele.getCargoId());
                    mpjWrapper.eq(CkCargoStock::getCustId, ele.getCustId());
                    mpjWrapper.eq(CkCargoStock::getStockId, stock.getStockId());
                    mpjWrapper.and(wp -> {
                        wp.gt("cargo_num", 0).or().
                                gt("cargo_num", 0).or().
                                gt("cargo_num", 0);
                    });
                    CkCargoStock ckCargoStock = ckCargoStockService.getOne(mpjWrapper);
                    if(ckCargoStock==null){
                        ckCargoStock = new CkCargoStock();
                        stock.setNowStockWt(BigDecimal.ZERO);
                        stock.setNowStockVol(BigDecimal.ZERO);
                        stock.setNowStockNum(BigDecimal.ZERO);
                        stock.setNowCargoValue(BigDecimal.ZERO);
                    }else{
                        stock.setNowStockWt(ckCargoStock.getCargoWt());
                        stock.setNowStockVol(ckCargoStock.getCargoVol());
                        stock.setNowStockNum(ckCargoStock.getCargoNum());
                        stock.setNowCargoValue(ckCargoStock.getCargoValue());
                    }
                    newCargo.add(stock);
                } else {//出库
                    LambdaQueryWrapper<CkCargoStock> wrapper = new LambdaQueryWrapper();
                    wrapper.eq(CkCargoStock::getCargoId, ele.getCargoId());
                    wrapper.eq(CkCargoStock::getCustId, ele.getCustId());
                    wrapper.eq(CkCargoStock::getStockId, stock.getStockId());
                    wrapper.eq(CkCargoStock::getBillNumber, stock.getBillNumber());
                    CkCargoStock ckCargoStock = ckCargoStockService.getOne(wrapper);
                    if (ckCargoStock != null) {
                        stock.setNowStockWt(ckCargoStock.getCargoWt());
                        stock.setNowStockVol(ckCargoStock.getCargoVol());
                        stock.setNowStockNum(ckCargoStock.getCargoNum());
                        stock.setNowCargoValue(ckCargoStock.getCargoValue());
                    } else {
                        stock.setNowStockWt(new BigDecimal(0));
                        stock.setNowStockVol(new BigDecimal(0));
                        stock.setNowStockNum(new BigDecimal(0));
                    }
                    //未提交查询
                    if (ckBill.getBillStatus().equals("0")) {
                        MPJLambdaWrapper<CkCargoStock> stockWrapper = new MPJLambdaWrapper();
                        stockWrapper.eq(CkCargoStock::getCargoId, stock.getCargoId());
                        stockWrapper.eq(CkCargoStock::getCustId, ele.getCustId());
                        stockWrapper.and(qw -> {
                            qw.gt(CkCargoStock::getCargoNum, "0")
                                    .or().gt(CkCargoStock::getCargoWt, "0")
                                    .or().gt(CkCargoStock::getCargoValue, "0")
                                    .or().gt(CkCargoStock::getCargoVol, "0");
                        });
                        List<CkCargoStock> list = ckCargoStockService.list(stockWrapper);
                        Map<Long, List<CkCargoStock>> listMap = list.stream().collect(Collectors.groupingBy(CkCargoStock::getStockId));
                        List<CkCargoStock> stockList = new ArrayList<>();
                        listMap.keySet().forEach(key -> {
                            stockList.add(listMap.get(key).get(0));
                        });
                        stock.setStockList(stockList);
                        stock.setListMap(listMap);
                    }
                    oldCargo.add(stock);
                }
            });

        });
        ckBill.setOldCargos(oldCargo);
        ckBill.setNewCargos(newCargo);
        ckBill.setCustId(ckBillCargos.get(0).getCustId());
        return success(ckBill);
    }

    /**
     * 分页查询出混配矿列表
     */
    @ApiOperation("分页查询出混配矿列表")
    @GetMapping("/mixtureList")
    public TableDataInfo mixtureList(CkBill ckBill) {
        startPage();
        MPJLambdaWrapper<CkBill> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(CkBill.class)
                .selectCollection(CkBillCargo.class, CkBill::getCkBillCargos, billCargo -> billCargo.collection(
                        CkBillStock.class, CkBillCargo::getCkBillStocks)).
                leftJoin(CkBillCargo.class, CkBillCargo::getBillId, CkBill::getId).
                leftJoin(CkBillStock.class, CkBillStock::getBillCargoId, CkBillCargo::getId);
        queryWrapper.eq(CkBill::getBillType, "4");
        queryWrapper.eq(StringUtils.isNotBlank(ckBill.getBillNumber()), CkBill::getBillNumber,ckBill.getBillNumber());
        queryWrapper.like(StringUtils.isNotBlank(ckBill.getCargoName()), CkBillCargo::getCargoName,ckBill.getCargoName());
        queryWrapper.like(StringUtils.isNotBlank(ckBill.getCustName()), CkBillCargo::getCustName,ckBill.getCustName());
        queryWrapper.like(StringUtils.isNotBlank(ckBill.getStockName()), CkBillStock::getStockName,ckBill.getStockName());
        List<CkBill> list = ckBillService.selectJoinList(CkBill.class, queryWrapper);
        List<CkBillStock> ckBillStocks = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            CkBill ele = list.get(i);
            List<CkBillCargo> ckBillCargos = ele.getCkBillCargos();
            List<CkBillStock> childStock = new ArrayList<>();
            ckBillCargos.forEach(ckBillCargo -> {
                List<CkBillStock> stocks = ckBillCargo.getCkBillStocks();
                stocks.forEach(stock -> {
                    stock.setBillStatus(ckBillCargo.getBillStatus());
                    stock.setCargoName(ckBillCargo.getCargoName());
                    stock.setCargoId(ckBillCargo.getCargoId());
                    stock.setCustName(ckBillCargo.getCustName());
                    stock.setCustId(ckBillCargo.getCustId());
                    stock.setProportion(ele.getProportion());
                    stock.setBillDate(ele.getBillDate());
                    stock.setInoutType("原货物");
                    stock.setIsChildren(true);
                });
                if (ckBillCargo.getInoutType().equals("1")) {
                    stocks.get(0).setId(ele.getId());
                    stocks.get(0).setInoutType("混配矿");
                    stocks.get(0).setIsChildren(false);
                    ckBillStocks.add(stocks.get(0));
                } else {
                    childStock.addAll(stocks);
                }
            });
            ckBillStocks.get(i).setChildren(childStock);
        }
        return getDataTable(ckBillStocks, new PageInfo(list).getTotal());
    }

    /**
     * 新增货物转移单据（生成转移，出库，入库、信息）
     */
    @ApiOperation("新增、修改、提交货物转场单据")
    @Log(title = "新增、修改、提交货物转场单据", businessType = BusinessType.INSERT)
    @PostMapping("/addTransfer")
    @RepeatSubmit
    public AjaxResult addTransfer(@RequestBody CkBill ckBill) {
        AjaxResult ajaxResult = verifyTransfer(ckBill);
        if (ajaxResult.isFail()) {
            return ajaxResult;
        }
        return ckBillService.transferCargo(ckBill);
    }


    /**
     * 删除单据
     */
    @ApiOperation("删除单据")
    @Log(title = "删除单据", businessType = BusinessType.INSERT)
    @GetMapping(value = "/deleteBill/{id}")
    @RepeatSubmit
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteBill(@PathVariable("id") Long id) {
        CkBill ckBill = ckBillService.getById(id);
        if (ckBill.getBillStatus().equals("1")) {
            return error("此单据已经提交，不允许删除");
        }
        LambdaQueryWrapper<CkBillCargo> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(CkBillCargo::getId);
        wrapper.eq(CkBillCargo::getBillId,id);
        List<Object> list = ckBillCargoService.listObjs(wrapper);
        ckBillCargoService.removeBatchByIds(list);
        //删除入库记录
        ckStockChangeService.remove(new LambdaQueryWrapper<CkStockChange>().eq(CkStockChange::getBillId,id));
        //单据明细下出入库信息
        LambdaQueryWrapper<CkBillStock> stockWapper = new LambdaQueryWrapper<>();
        stockWapper.in(CkBillStock::getBillCargoId,list);
        ckBillStockService.remove(stockWapper);
        ckBillService.removeById(id);
        return success("删除成功");
    }

    /**
     * 撤回货物转场单据
     */
    @ApiOperation("撤回货物转场单据")
    @Log(title = "撤回货物转场单据", businessType = BusinessType.INSERT)
    @GetMapping(value = "/recallTransfer/{id}")
    @RepeatSubmit
    public AjaxResult recallTransfer(@PathVariable("id") Long id) {
        CkBill ckBill = ckBillService.getById(id);
        if (!ckBill.getSourceType().equals("2")) {
            return error("非本页面操作出库，不能撤回");
        }
        if (ckBill.getBillStatus().equals("0")) {
            return error("未提交的出库单不允许做撤回操作");
        }
        return ckBillService.warehouseWork(ckBill, true);
    }


    /**
     * 获取转场详细信息
     */
    @ApiOperation("获取转场详细信息")
    @GetMapping(value = "/getTransferInfo/{id}")
    public AjaxResult getTransferInfo(@PathVariable("id") Long id) {
        MPJLambdaWrapper<CkBill> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(CkBill.class)
                .selectCollection(CkBillCargo.class, CkBill::getCkBillCargos, billCargo -> billCargo.collection(
                        CkBillStock.class, CkBillCargo::getCkBillStocks)).
                leftJoin(CkBillCargo.class, CkBillCargo::getBillId, CkBill::getId).
                leftJoin(CkBillStock.class, CkBillStock::getBillCargoId, CkBillCargo::getId);
        queryWrapper.eq(CkBill::getBillType, "3");
        queryWrapper.eq(CkBill::getId, id);
        CkBill ckBill = ckBillService.selectJoinOne(CkBill.class, queryWrapper);
        List<CkBillCargo> ckBillCargos = ckBill.getCkBillCargos();
        List<CkBillStock> oldCargo = new ArrayList<>();
        List<CkBillStock> newCargo = new ArrayList<>();
        ckBillCargos.forEach(ele -> {
            List<CkBillStock> ckBillStocks = ele.getCkBillStocks();
            ckBillStocks.forEach(stock -> {
                LambdaQueryWrapper<CkCargoStock> wrapper = new LambdaQueryWrapper();
                wrapper.eq(CkCargoStock::getCargoId, ele.getCargoId());
                wrapper.eq(CkCargoStock::getCustId, ele.getCustId());
                wrapper.eq(CkCargoStock::getStockId, stock.getStockId());
                //if(ele.getInoutType().equals("2")){
                wrapper.eq(CkCargoStock::getBillNumber, stock.getBillNumber());
                //}
                CkCargoStock ckCargoStock = ckCargoStockService.getOne(wrapper);
                if (ckCargoStock != null) {
                    stock.setNowStockWt(ckCargoStock.getCargoWt());
                    stock.setNowStockVol(ckCargoStock.getCargoVol());
                    stock.setNowStockNum(ckCargoStock.getCargoNum());
                    stock.setNowCargoValue(ckCargoStock.getCargoValue());
                } else {
                    stock.setNowStockWt(new BigDecimal(0));
                    stock.setNowStockVol(new BigDecimal(0));
                    stock.setNowStockNum(new BigDecimal(0));
                    stock.setNowCargoValue(new BigDecimal(0));
                }
                stock.setCargoId(ele.getCargoId());
                stock.setCargoName(ele.getCargoName());
                stock.setHsCode(ele.getHsCode());
                stock.setCargoNumber(ele.getCargoNumber());
                stock.setItemNumber(ele.getItemNumber());
                stock.setCargoSpec(ele.getCargoSpec());
                stock.setOriginCountry(ele.getOriginCountry());
                if (stock.getInoutType().equals("1")) {
                    CkBillCargo billCargoById = ckBillCargoService.getById(stock.getBillCargoId());
                    stock.setBookNumber(billCargoById.getBookNumber());
                    stock.setCustomsNo(billCargoById.getCustomsNo());
                    stock.setListNumber(billCargoById.getListNumber());
                    stock.setExpiryDate(billCargoById.getExpiryDate());
                    stock.setCargoFlow(billCargoById.getCargoFlow());
                    newCargo.add(stock);
                } else {
                    oldCargo.add(stock);
                }
            });
        });
        ckBill.setOldCargo(oldCargo.get(0));
        ckBill.setNewCargos(newCargo);
        ckBill.setCustId(ckBillCargos.get(0).getCustId());
        ckBill.setCkBillCargos(null);
        return success(ckBill);
    }


    /**
     * 分页查询转场列表
     */
    @ApiOperation("分页查询转场列表")
    @GetMapping("/transferList")
    public TableDataInfo transferList(CkBill ckBill) {
        startPage();
        MPJLambdaWrapper<CkBill> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(CkBill.class)
                .selectCollection(CkBillCargo.class, CkBill::getCkBillCargos, billCargo -> billCargo.collection(
                        CkBillStock.class, CkBillCargo::getCkBillStocks)).
                leftJoin(CkBillCargo.class, CkBillCargo::getBillId, CkBill::getId).
                leftJoin(CkBillStock.class, CkBillStock::getBillCargoId, CkBillCargo::getId);
        queryWrapper.eq(CkBill::getBillType, "3");

        queryWrapper.eq(StringUtils.isNotBlank(ckBill.getBillNumber()), CkBillCargo::getBillNumber,ckBill.getBillNumber());
        queryWrapper.like(StringUtils.isNotBlank(ckBill.getCargoName()), CkBillCargo::getCargoName,ckBill.getCargoName());
        queryWrapper.like(StringUtils.isNotBlank(ckBill.getCustName()), CkBillCargo::getCustName,ckBill.getCustName());
        queryWrapper.like(StringUtils.isNotBlank(ckBill.getStockName()), CkBillStock::getStockName,ckBill.getStockName());
        queryWrapper.eq(StringUtils.isNotBlank(ckBill.getStockCode()), CkBillStock::getStockCode,ckBill.getStockCode());
        List<CkBill> list = ckBillService.selectJoinList(CkBill.class, queryWrapper);
        List<CkBillStock> ckBillStocks = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            CkBill ele = list.get(i);
            List<CkBillCargo> ckBillCargos = ele.getCkBillCargos();
            List<CkBillStock> childStock = new ArrayList<>();
            ckBillCargos.forEach(ckBillCargo -> {
                List<CkBillStock> stocks = ckBillCargo.getCkBillStocks();
                stocks.forEach(stock -> {
                    stock.setBillStatus(ckBillCargo.getBillStatus());
                    stock.setCargoName(ckBillCargo.getCargoName());
                    stock.setCargoId(ckBillCargo.getCargoId());
                    stock.setCustName(ckBillCargo.getCustName());
                    stock.setProportion(ele.getProportion());
                    stock.setBillDate(ele.getBillDate());
                    if (stock.getInoutType().equals("2")) {
                        stock.setId(ele.getId());
                        stock.setInoutType("转出");
                        ckBillStocks.add(stock);
                    } else {
                        stock.setInoutType("转入");
                        stock.setIsChildren(true);
                        childStock.add(stock);
                    }
                    //ckBillStocks.add(stock);
                });
            });
            ckBillStocks.get(i).setChildren(childStock);
        }
        return getDataTable(ckBillStocks, new PageInfo(list).getTotal());
    }

    /**
     * 新增货物出库单据（生成出库信息）
     */
    @ApiOperation("新增货物出库单据")
    @Log(title = "新增货物出库单据", businessType = BusinessType.INSERT)
    @PostMapping("/outBill")
    @RepeatSubmit
    public AjaxResult outBill(@RequestBody CkBill ckBill) {
        AjaxResult ajaxResult = verifyOutBill(ckBill);
        if (ajaxResult.isFail()) {
            return ajaxResult;
        }
        return ckBillService.outCargo(ckBill);
    }

    /**
     * 撤回出库单据
     */
    @ApiOperation("撤回出库单据")
    @Log(title = "撤回出库单据", businessType = BusinessType.INSERT)
    @GetMapping(value = "/recallOutBill/{id}")
    @RepeatSubmit
    public AjaxResult recallOutBill(@PathVariable("id") Long id) {
        CkBill ckBill = ckBillService.getById(id);
        if (!ckBill.getSourceType().equals("1")) {
            return error("非本页面操作出库，不能撤回");
        }
        if (ckBill.getBillStatus().equals("0")) {
            return error("未提交的出库单不允许做撤回操作");
        }
        return ckBillService.recallOutBill(id);
    }


    /**
     * 确认入库单据（列表页面确认）
     */
    @ApiOperation("确认入库单据")
    @Log(title = "确认入库单据", businessType = BusinessType.INSERT)
    @GetMapping(value = "/confirmOutBill/{id}")
    @RepeatSubmit
    public AjaxResult confirmOutBill(@PathVariable("id") Long id) {
        CkBill ckBill = ckBillService.getById(id);
        if (!ckBill.getSourceType().equals("1")) {
            return error("非人工操作入库，不能撤回");
        }
        if (ckBill.getBillStatus().equals("1")) {
            return error("此单据已经确认，不允许再次操作");
        }
        return ckBillService.warehouseWork(ckBill,false);
    }

    /**
     * 新增货物入库单据（生成入库信息）
     */
    @ApiOperation("新增货物入库单据")
    @Log(title = "新增货物入库单据", businessType = BusinessType.INSERT)
    @PostMapping("/putBill")
    @RepeatSubmit
    public AjaxResult putBill(@RequestBody CkBill ckBill) {
        AjaxResult ajaxResult = verifyPutBill(ckBill);
        if (ajaxResult.isFail()) {
            return ajaxResult;
        }
        return ckBillService.putCargo(ckBill);
    }

    /**
     * 撤回入库单据
     */
    @ApiOperation("撤回入库单据")
    @Log(title = "撤回入库单据", businessType = BusinessType.INSERT)
    @GetMapping(value = "/recallPutBill/{id}")
    @RepeatSubmit
    public AjaxResult recallPutBill(@PathVariable("id") Long id) {
        CkBill ckBill = ckBillService.getById(id);
        if (!ckBill.getSourceType().equals("1")) {
            return error("非人工操作入库，不能撤回");
        }
        if (ckBill.getBillStatus().equals("0")) {
            return error("未提交的出库单不允许做撤回操作");
        }
        return ckBillService.recallPutBill(id);
    }

    /**
     * 确认入库单据（列表页面确认）
     */
    @ApiOperation("确认入库单据")
    @Log(title = "确认入库单据", businessType = BusinessType.INSERT)
    @GetMapping(value = "/confirmPutBill/{id}")
    @RepeatSubmit
    public AjaxResult confirmPutBill(@PathVariable("id") Long id) {
        CkBill ckBill = ckBillService.getById(id);
        if (!ckBill.getSourceType().equals("1")) {
            return error("非人工操作入库，不能撤回");
        }
        if (ckBill.getBillStatus().equals("1")) {
            return error("此单据已经确认，不允许再次操作");
        }
        return ckBillService.warehouseWork(ckBill,false);
    }

    /**
     * 获取出入库单据明细详细信息(出入库页面)
     */
    @ApiOperation("获取出入库单据明细详细信息")
    @GetMapping(value = "/getBillInfo/{id}")
    public AjaxResult getOutBillInfo(@PathVariable("id") Long id) {
        CkBill ckBill = ckBillService.getById(id);
        MPJLambdaWrapper<CkBillCargo> queryWrapper = new MPJLambdaWrapper();
        queryWrapper.selectAll(CkBillCargo.class)
                .select(CkBillStock::getStockName, CkBillStock::getStockCode)
                .selectAs(CkBillStock::getStockId, CkBillCargo::getInStockId)
                .selectAs(CkBillStock::getBillNumber, CkBillCargo::getOutBillNumber)
                .selectAs(CkBillStock::getCargoNum, CkBillCargo::getCargoNum)
                .selectAs(CkBillStock::getCargoWt, CkBillCargo::getCargoWt)
                .selectAs(CkBillStock::getCargoVol, CkBillCargo::getCargoVol)
                .selectAs(CkBillStock::getCargoValue, CkBillCargo::getCargoValue)
                .leftJoin(CkBillStock.class, CkBillStock::getBillCargoId, CkBillCargo::getId);
        queryWrapper.eq(CkBillCargo::getBillId, id);
        queryWrapper.orderByDesc(CkBillCargo::getCreateTime);
        List<CkBillCargo> ckBillCargos = ckBillCargoService.selectJoinList(CkBillCargo.class, queryWrapper);
        ckBillCargos.forEach(ckBillCargo -> {
            if (ckBillCargo.getInoutType().equals("2")) {
                ckBillCargo.setOutStockId(ckBillCargo.getInStockId());
                LambdaQueryWrapper<CkCargoStock> wrapper = new LambdaQueryWrapper();
                wrapper.eq(CkCargoStock::getCargoId, ckBillCargo.getCargoId());
                wrapper.eq(CkCargoStock::getCustId, ckBillCargo.getCustId());
                wrapper.eq(CkCargoStock::getStockId, ckBillCargo.getOutStockId());
                wrapper.eq(CkCargoStock::getBillNumber, ckBillCargo.getOutBillNumber());
                CkCargoStock ckCargoStock = ckCargoStockService.getOne(wrapper);
                if (ckCargoStock != null) {
                    ckBillCargo.setNowStockWt(ckCargoStock.getCargoWt());
                    ckBillCargo.setNowStockVol(ckCargoStock.getCargoVol());
                    ckBillCargo.setNowStockNum(ckCargoStock.getCargoNum());
                    ckBillCargo.setNowCargoValue(ckCargoStock.getCargoValue());
                } else {
                    ckBillCargo.setNowStockWt(new BigDecimal(0));
                    ckBillCargo.setNowStockVol(new BigDecimal(0));
                    ckBillCargo.setNowStockNum(new BigDecimal(0));
                    ckBillCargo.setNowCargoValue(new BigDecimal(0));
                }
            }
        });
        ckBill.setCkBillCargos(ckBillCargos);
        return success(ckBill);
    }

    /**
     * 修改出入库单据
     */
    @ApiOperation("修改出入库单据")
    @Log(title = "出入库单据修改", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody CkBill ckBill) {
        return toAjax(ckBillService.updateById(ckBill));
    }

    /**
     * 删除出入库单据
     */
    @ApiOperation("删除出入库单据")
    @Log(title = "出入库单据删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @RepeatSubmit
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult remove(@PathVariable List<Long> ids) {
        for (int i = 0; i < ids.size(); i++) {
            Long id = ids.get(i);
            CkBill ckBill = ckBillService.getById(id);
            if (ckBill.getBillStatus().equals("1")) {
                return error("此单据已经提交，不允许删除");
            }
            LambdaQueryWrapper<CkBillCargo> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CkBillCargo::getId);
            wrapper.eq(CkBillCargo::getBillId,id);
            List<Object> list = ckBillCargoService.listObjs(wrapper);
            ckBillCargoService.removeBatchByIds(list);
            //删除入库记录
            ckStockChangeService.remove(new LambdaQueryWrapper<CkStockChange>().eq(CkStockChange::getBillId,id));
            //单据明细下出入库信息
            if (!list.isEmpty()) {
                LambdaQueryWrapper<CkBillStock> stockWapper = new LambdaQueryWrapper<>();
                stockWapper.in(CkBillStock::getBillCargoId,list);
                ckBillStockService.remove(stockWapper);
            }
            ckBillService.removeById(id);
        }
        return success("删除成功");
    }


    /**
     * 条件设置
     */
    private void condition(LambdaQueryWrapper<CkBill> queryWrapper, CkBill ckBill) {



        if (Validator.isNotEmpty(ckBill.getCargoName())) {
            queryWrapper.inSql(CkBill::getId, "select bill_id from ck_bill_cargo where cargo_name like '%"+ ckBill.getCargoName() +"%'");
        }

        if (Validator.isNotEmpty(ckBill.getCustName())) {
            queryWrapper.inSql(CkBill::getId, "select bill_id from ck_bill_cargo where cust_name like '%"+ ckBill.getCustName() +"%'");
        }

        if (Validator.isNotEmpty(ckBill.getBillNumber())) {
            queryWrapper.like(CkBill::getBillNumber, ckBill.getBillNumber());
        }

        if (Validator.isNotEmpty(ckBill.getStockCode())) {
            queryWrapper.inSql(CkBill::getId, "select a.bill_id from ck_bill_cargo a, ck_bill_stock b where a.id = b.bill_cargo_id and b.stock_code = '"+ ckBill.getStockCode() +"'");
        }

        if (Validator.isNotEmpty(ckBill.getOutBillNumber())) {
            queryWrapper.inSql(CkBill::getId, "select a.bill_id from ck_bill_cargo a, ck_bill_stock b where a.id = b.bill_cargo_id and b.bill_number like '%"+ ckBill.getOutBillNumber() +"%'");
        }

        if (Validator.isNotEmpty(ckBill.getStockName())) {
            queryWrapper.inSql(CkBill::getId, "select a.bill_id from ck_bill_cargo a, ck_bill_stock b where a.id = b.bill_cargo_id and b.stock_name like '%"+ ckBill.getStockName() +"%'");
        }

        if (Validator.isNotEmpty(ckBill.getCustomsNo())) {
            queryWrapper.inSql(CkBill::getId, "select bill_id from ck_bill_cargo where customs_no like '%"+ ckBill.getCustomsNo() +"%'");
        }

        if (Validator.isNotEmpty(ckBill.getListNumber())) {
            queryWrapper.inSql(CkBill::getId, "select bill_id from ck_bill_cargo where list_number like '%"+ ckBill.getListNumber() +"%'");
        }
        //单据日期
//        if (ckBill.getBillDate() != null) {
//            queryWrapper.eq(CkBill::getBillDate, ckBill.getBillDate());
//        }

        if (null != ckBill.getBeginDate()) {
            queryWrapper.between(CkBill::getBillDate, ckBill.getBeginDate(), ckBill.getEndDate());
        }


        //单据编号
        if (Validator.isNotEmpty(ckBill.getBillNo())) {
            queryWrapper.like(CkBill::getBillNo, ckBill.getBillNo());
        }

        if (Validator.isNotEmpty(ckBill.getWtNumber())) {
            queryWrapper.like(CkBill::getWtNumber, ckBill.getWtNumber());
        }

        if (Validator.isNotEmpty(ckBill.getBatchNumber())) {
            queryWrapper.like(CkBill::getBatchNumber, ckBill.getBatchNumber());
        }

        //船舶航次ID
        if (ckBill.getVoyageId() != null) {
            queryWrapper.eq(CkBill::getVoyageId, ckBill.getVoyageId());
        }

        //航次号
        if (Validator.isNotEmpty(ckBill.getVoyageNo())) {
            queryWrapper.like(CkBill::getVoyageNo, ckBill.getVoyageNo());
        }

        //船舶ID
        if (ckBill.getVesselId() != null) {
            queryWrapper.eq(CkBill::getVesselId, ckBill.getVesselId());
        }

        //船舶名称
        if (Validator.isNotEmpty(ckBill.getVesselName())) {
            queryWrapper.like(CkBill::getVesselName, ckBill.getVesselName());
        }

        //状态
        if (Validator.isNotEmpty(ckBill.getStatus())) {
            queryWrapper.eq(CkBill::getStatus, ckBill.getStatus());
        }

        //备注
        if (Validator.isNotEmpty(ckBill.getRemark())) {
            queryWrapper.eq(CkBill::getRemark, ckBill.getRemark());
        }

        //删除标志（0代表存在 2代表删除）
        if (Validator.isNotEmpty(ckBill.getDelFlag())) {
            queryWrapper.eq(CkBill::getDelFlag, ckBill.getDelFlag());
        }

        //租户ID
        if (Validator.isNotEmpty(ckBill.getTenantId())) {
            queryWrapper.eq(CkBill::getTenantId, ckBill.getTenantId());
        }

    }


    public AjaxResult verifyPutBill(CkBill ckBill) {
        if (StringUtils.isEmpty(ckBill.getBillNumber())) {
            return error("单据编号不能为空");
        }
        CkBill tmpCkBill = ckBillService.getOne(new LambdaQueryWrapper<CkBill>().eq(CkBill::getBillNumber, ckBill.getBillNumber()));
        if (ckBill.getId() == null) {
            if (tmpCkBill != null) {
                return error("单据编号已经存在，请重新输入");
            }
        } else {
            if (tmpCkBill != null && !tmpCkBill.getId().equals(ckBill.getId())) {
                return error("单据编号已经存在，请重新输入");
            }
            if (!ckBill.getSourceType().equals("1")) {
                return error("非本页面操作入库，不能撤回");
            }
        }
        if (ckBill.getBillDate() == null) {
            return error("单据日期不能为空");
        }
        List<CkBillCargo> ckBillCargos = ckBill.getCkBillCargos();
        for (int i = 0; i < ckBillCargos.size(); i++) {
            CkBillCargo ckBillCargo = ckBillCargos.get(i);
            if (ckBillCargo.getCustId() == null) {
                return error("货主不能为空");
            }
            if (ckBillCargo.getCargoNum() == null) {
                return error("货物件数不能为空");
            }
            if (ckBillCargo.getCargoWt() == null) {
                return error("货物重量不能为空");
            }
            if (ckBillCargo.getCargoVol() == null) {
                return error("货物体积不能为空");
            }
            if (ckBillCargo.getCargoId() == null) {
                return error("货物不能为空");
            }
            if (ckBillCargo.getInStockId() == null) {
                return error("库场不能为空");
            }
        }
        return success();
    }

    public AjaxResult verifyBillCargo(List<CkBillStock> newCargos) {
        for (int i = 0; i < newCargos.size(); i++) {
            CkBillStock ckBillStock = newCargos.get(i);
            if (ckBillStock.getCargoNum() == null) {
                return error("货物件数不能为空");
            }
            if (ckBillStock.getCargoWt() == null) {
                return error("货物重量不能为空");
            }
            if (ckBillStock.getCargoVol() == null) {
                return error("货物体积不能为空");
            }
        }
        return success();
    }

    public AjaxResult verifyBill(CkBill ckBill) {
        if (StringUtils.isEmpty(ckBill.getBillNumber())) {
            return error("单据编号不能为空");
        }
        CkBill tmpCkBill = ckBillService.getOne(new LambdaQueryWrapper<CkBill>().eq(CkBill::getBillNumber, ckBill.getBillNumber()));
        if (ckBill.getId() == null) {
            if (tmpCkBill != null) {
                return error("单据编号已经存在，请重新输入");
            }
        } else {
            if (tmpCkBill != null && !tmpCkBill.getId().equals(ckBill.getId())) {
                return error("单据编号已经存在，请重新输入");
            }
        }
        if (ckBill.getBillDate() == null) {
            return error("单据日期不能为空");
        }
        if (ckBill.getCustId() == null) {
            return error("货主不能为空");
        }
        return success();
    }

    public AjaxResult verifyOutBill(CkBill ckBill) {
        if (StringUtils.isEmpty(ckBill.getBillNumber())) {
            return error("单据编号不能为空");
        }
        CkBill tmpCkBill = ckBillService.getOne(new LambdaQueryWrapper<CkBill>().eq(CkBill::getBillNumber, ckBill.getBillNumber()));
        if (ckBill.getId() == null) {
            if (tmpCkBill != null) {
                return error("单据编号已经存在，请重新输入");
            }
        } else {
            if (tmpCkBill != null && !tmpCkBill.getId().equals(ckBill.getId())) {
                return error("单据编号已经存在，请重新输入");
            }
            if (!ckBill.getSourceType().equals("1")) {
                return error("非本页面操作出库，不能撤回");
            }
        }

        if (ckBill.getBillDate() == null) {
            return error("单据日期不能为空");
        }
        List<CkBillCargo> ckBillCargos = ckBill.getCkBillCargos();
        for (int i = 0; i < ckBillCargos.size(); i++) {
            CkBillCargo ckBillCargo = ckBillCargos.get(i);
            if (ckBillCargo.getCustId() == null) {
                return error("货主不能为空");
            }
            if (ckBillCargo.getCargoNum() == null) {
                return error("货物件数不能为空");
            }
            if (ckBillCargo.getCargoWt() == null) {
                return error("货物重量不能为空");
            }
            if (ckBillCargo.getCargoVol() == null) {
                return error("货物体积不能为空");
            }
            if (ckBillCargo.getOutStockId() == null) {
                return error("货物的出库库场不能为空");
            }
        }
        return success();
    }

    public AjaxResult verifyTransfer(CkBill ckBill) {
        AjaxResult ajaxResult = verifyBill(ckBill);
        if (ajaxResult.isFail()) {
            return ajaxResult;
        }
        CkBillStock oldCargo = ckBill.getOldCargo();
        List<CkBillStock> newCargos = ckBill.getNewCargos();
        if (ckBill.getNewCargos().isEmpty() || ckBill.getNewCargos().size() == 0) {
            return error("入库库场不能为空");
        }

        if (oldCargo.getCargoId() == null) {
            return error("货物不能为空");
        }
        if (oldCargo.getStockId() == null) {
            return error("出库库场不能为空");
        }
        AjaxResult ajaxBillCargoResult = verifyBillCargo(newCargos);
        if (ajaxBillCargoResult.isFail()) {
            return ajaxResult;
        }
        return success();
    }


    public AjaxResult verifyMixture(CkBill ckBill) {
        AjaxResult ajaxResult = verifyBill(ckBill);
        if (ajaxResult.isFail()) {
            return ajaxResult;
        }
        if (ckBill.getOldCargos().isEmpty() || ckBill.getOldCargos().size() == 0) {
            return error("原货物不能为空");
        }
        if (ckBill.getNewCargos().isEmpty() || ckBill.getNewCargos().size() != 1) {
            return error("混配矿不能为空或不能生成多种货物");
        }
        return success();
    }

}
