package com.sifang.modules.supply.stock.service;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.sunshine.SystemSetting.dao.TraderWarehouseRelDao;
import com.sifang.modules.sunshine.SystemSetting.utils.StringUtil;
import com.sifang.modules.supply.order.entity.CrmSupplyMaterialDeliverOrder;
import com.sifang.modules.supply.order.entity.CrmSupplyMaterialDeliverOrderDetail;
import com.sifang.modules.supply.order.entity.CrmSupplyMaterialReturnOrder;
import com.sifang.modules.supply.order.entity.CrmSupplyMaterialReturnOrderDetail;
import com.sifang.modules.supply.setting.dao.CrmSupplyMaterialTypeDao;
import com.sifang.modules.supply.setting.dao.CrmSupplyWarehouseDao;
import com.sifang.modules.supply.setting.entity.CrmSupplyWarehouse;
import com.sifang.modules.supply.stock.KeepUnit;
import com.sifang.modules.supply.stock.entity.SupplyMaterial;
import com.sifang.modules.supply.stock.form.ExportExceptionOrderExcel;
import com.sifang.modules.supply.warehouse.constant.InventoryOrderConstants;
import com.sifang.modules.supply.warehouse.constant.MaterialKeepConstants;
import com.sifang.modules.supply.warehouse.dao.CrmSupplyMaterialKeepDao;
import com.sifang.modules.supply.warehouse.entity.*;
import com.sifang.modules.sys.common.UserUtils;
import com.sifang.modules.sys.common.entity.User;
import com.sifang.modules.sys.common.service.BaseService;
import com.sifang.modules.sys.common.utils.IdGen;
import com.sifang.modules.sys.entity.Ascription;
import com.sifang.modules.sys.common.utils.DateUtils;
import com.sifang.modules.sys.util.CrmUtils;
import com.sifang.modules.sys.util.LayuiPage;
import com.sifang.modules.sys.util.SqlBuilder;
import com.sifang.modules.sys.util.excel.ExportExcel;
import org.hibernate.service.spi.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

@Service
public class SupplyMaterialKeepService extends BaseService {

    @Autowired
    private CrmSupplyMaterialKeepDao materialKeepDao;

    @Autowired
    private CrmSupplyWarehouseDao warehouseDao;

    @Autowired
    private TraderWarehouseRelDao traderWarehouseRelDao;

    @Autowired
    private CrmSupplyMaterialTypeDao materialTypeDao;


    public void materialKeepList(LayuiPage page, Map<String, String> map) {
        User user = UserUtils.getUser();
        String userType = CrmUtils.getCurrentUserType(user);
        if (!"1".equals(userType)) {
            Ascription ascription = CrmUtils.getAscription();
            map.put("ascriptionId", ascription.getAscriptionId());
        }
        List<Record> list = listData(page, map);
        if("2".equals(map.get("type"))){  //出库记录
            for(Record rd:list){
                long durationDay=0l;
                try {
                    logger.info(">>>>>materialKeepList mergeTime:{},inputTime:{}",rd.get("mergeTime"),rd.get("inputTime"));
                    if(rd.get("mergeTime")!=null && rd.get("inputTime")!=null){
                        durationDay = DateUtils.daysBetween(rd.get("inputTime"), rd.get("mergeTime"));
                    }
                } catch (ParseException e) {
                    logger.info("日期计算错误");
                }
                rd.set("durationDay",durationDay);
            }
        }
        page.setData(list);
        page.setCount(countList(map));
    }

    public List<Record> listData(LayuiPage page, Map<String, String> map) {

        SqlBuilder builder = new SqlBuilder();
        builder.line(" SELECT k.*,w.`ascription_name`,m.material_name,m.material_specs,m.material_brand ");
                if("2".equals(map.get("type"))){  //出库记录
                    builder.line(" ,e.id,e.tenant_name,DATE_FORMAT(e.install_time,'%Y-%m-%d %H:%i:%s')as azTime, DATE_FORMAT(e.merge_time,'%Y-%m-%d %H:%i:%s')as bwTime ");
                    builder.line(",DATE_FORMAT(b.input_time,'%Y-%m-%d')as inputTime,DATE_FORMAT(e.merge_time,'%Y-%m-%d')as mergeTime ");
                }
        builder.line(" FROM `crm_supply_material_keep` k ")
                .line("LEFT JOIN `crm_supply_warehouse` w ON w.id=k.`warehouse_id` ")
                .line("LEFT JOIN `crm_supply_material` m ON m.id=k.`material_id` ");
                if("2".equals(map.get("type"))){   //出库记录
                    builder.line(" LEFT JOIN crm_customer_entry e on e.id=k.source_id ");
                    builder.line(" LEFT JOIN crm_supply_material_batch b on b.code=k.batch_code AND b.`material_id`=k.material_id ");
                }
        builder.line("where 1=1 ");
        appendCondition(builder, map);
        builder.line("order by k.create_time desc");
        if (page != null) {
            builder.limit(page.getPage(), page.getLimit());
        }
        return Db.find(builder.build(), builder.params());
    }

    public Long countList(Map<String, String> map) {
        SqlBuilder builder = new SqlBuilder();
        builder.line(" SELECT count(k.id) ")
                .line("FROM `crm_supply_material_keep` k ")
                .line("LEFT JOIN `crm_supply_warehouse` w ON w.id=k.`warehouse_id` ");
        if("2".equals(map.get("type"))){   //出库
            builder.line(" LEFT JOIN crm_customer_entry e on e.id=k.source_id ");
            builder.line(" LEFT JOIN crm_supply_material_batch b on b.code=k.batch_code AND b.`material_id`=k.material_id  ");
        }
        builder.line("where 1=1 ");
        appendCondition(builder, map);
        return Db.queryLong(builder.build(), builder.params());
    }

    public void appendCondition(SqlBuilder builder, Map<String, String> map) {
        if (StringUtil.checkParamsValid(map.get("belong"))) {
            String belong =  map.get("belong");
            builder.line(" and k.ascription_id in(" + StringUtil.joinInSql(belong.split(",")) + ") ");

        }
        if (StringUtil.checkParamsValid(map.get("code"))) {
            builder.line("and k.material_code like concat('%', ?, '%')", map.get("code").trim());
        }
        if (StringUtil.checkParamsValid(map.get("materialType"))) {
            builder.line("and k.material_type like concat('%', ?, '%')", map.get("materialType").trim());
        }

        if (StringUtil.checkParamsValid(map.get("materialRemarks"))) {
            builder.line("and k.material_remarks like concat('%', ?, '%')", map.get("materialRemarks").trim());
        }
        if (StringUtil.checkParamsValid(map.get("type"))) {
            builder.line(" and K.type=? ", map.get("type"));
        }
        if (StringUtil.checkParamsValid(map.get("source"))) {
            builder.line(" and K.source=? ", map.get("source"));
        }
        if (StringUtil.checkParamsValid(map.get("creator"))) {
            builder.line("and k.creator like concat('%', ?, '%')", map.get("creator").trim());
        }
        if (StringUtil.checkParamsValid(map.get("warehouseId"))) {
            builder.line(" and K.warehouse_id=? ", map.get("warehouseId"));
        }
        if (StringUtil.checkParamsValid(map.get("sourceCode"))) {
            builder.line("and k.source_code like concat('%', ?, '%')", map.get("sourceCode").trim());
        }
        if (StringUtil.checkParamsValid(map.get("deliveryMethod"))) {
            builder.line("and k.delivery_method like concat('%', ?, '%')", map.get("deliveryMethod").trim());
        }
        if (StringUtil.checkParamsValid(map.get("createTimeSta"))) {
            builder.line("and k.create_time >= concat(?, ' 00：00：00')", map.get("createTimeSta").trim());
        }
        if (StringUtil.checkParamsValid(map.get("createTimeEnd"))) {
            builder.line("and k.create_time <= concat(?, ' 23：59：59')", map.get("createTimeEnd").trim());
        }

        if (StringUtil.checkParamsValid(map.get("azStartTime"))) {
            builder.line("and e.install_time >= concat(?, ' 00：00：00')", map.get("azStartTime").trim());
        }
        if (StringUtil.checkParamsValid(map.get("azEndTime"))) {
            builder.line("and e.install_time <= concat(?, ' 23：59：59')", map.get("azEndTime").trim());
        }
        if (StringUtil.checkParamsValid(map.get("tentName"))) {
            builder.line("and e.tenant_name like concat('%', ?, '%')", map.get("tentName").trim());
        }
        if (StringUtil.checkParamsValid(map.get("bwStartTime"))) {
            builder.line("and e.merge_time >= concat(?, ' 00：00：00')", map.get("bwStartTime").trim());
        }
        if (StringUtil.checkParamsValid(map.get("bwEndTime"))) {
            builder.line("and e.merge_time <= concat(?, ' 23：59：59')", map.get("bwEndTime").trim());
        }
        if (StringUtil.checkParamsValid(map.get("province"))) {
            builder.line("and e.province =?", map.get("province"));
        }
        if (StringUtil.checkParamsValid(map.get("city"))) {
            builder.line("and e.city =?", map.get("city"));
        }
        if (StringUtil.checkParamsValid(map.get("area"))) {
            builder.line("and e.area =?", map.get("area"));
        }
        User user = UserUtils.getUser();
        if (Objects.equals("2", user.getTraderType())) {
            List<String> warehouseList = traderWarehouseRelDao.findByTraderId(user.getTraderId());
            builder.inst("and k.warehouse_id in", warehouseList);
        } else if (StringUtil.checkParamsValid(map.get("ascriptionId"))) {
            builder.line(" and K.ascription_id=? ", map.get("ascriptionId"));
        }
    }

    /**
     * 周转率分析 统计
     */
    public List<Record> fingTurnoverRateStatistics(LayuiPage page, Map<String, String> map) {

        SqlBuilder sql = new SqlBuilder();

        sql.line(" SELECT   k.material_id,any_value(k.material_remarks) material_remarks,any_value(k.material_type) material_type,any_value(k.material_code) material_code,any_value(k.warehouse_name) warehouse_name ,any_value(k.ascription_name) ascription_name,any_value(k.material_unit) material_unit,");
        sql.line("SUM(CASE WHEN k.type = '2' AND k.create_time<= CONCAT(?, ' 23:59:59') AND k.create_time>=CONCAT(?, ' 00:00:00')  THEN k.amount  ELSE 0 END) AS bqCostCount,", map.get("endcreateTime"), map.get("startCreateTime"));
        sql.line(" SUM(CASE WHEN k.type = '1' AND k.create_time<= CONCAT(?, ' 23:59:59') AND k.create_time>=CONCAT(?, ' 00:00:00')  THEN k.amount  ELSE 0 END) AS bqInCostCount,", map.get("endcreateTime"), map.get("startCreateTime"));
        sql.line(" SUM(CASE WHEN k.type = '1' AND k.create_time<=CONCAT(?, ' 00:00:00') THEN k.amount  ELSE 0 END ) AS qcInCostAmount,", map.get("startCreateTime"));
        sql.line(" SUM(CASE WHEN k.type = '2' AND k.create_time<=CONCAT(?, ' 00:00:00') THEN k.amount  ELSE 0 END ) AS qcOutCostAmount ", map.get("startCreateTime"));
        sql.line(" ,any_value(m.material_specs) material_specs, any_value(m.material_brand) material_brand, any_value(m.material_name) material_name ");
        /* sql.line(" SUM(CASE WHEN k.type = '1' AND k.create_time>=CONCAT(?, ' 23:59:59') THEN k.amount  ELSE 0 END ) AS qmInCostAmount,", map.get("endcreateTime"));
        sql.line(" SUM(CASE WHEN k.type = '2' AND k.create_time>=CONCAT(?, ' 23:59:59') THEN k.amount  ELSE 0 END ) AS qmOutCostAmount", map.get("endcreateTime"));*/
        sql.line(" FROM `crm_supply_material_keep` k ");
        sql.line(" LEFT JOIN `crm_supply_warehouse` w ON w.id=k.warehouse_id");
        sql.line(" left join crm_supply_material m on m.id=k.material_id ");
        sql.line(" WHERE  1=1 ");
        appendCondition(sql, map);
        sql.line("GROUP BY k.material_id,k.warehouse_id,k.ascription_id");
        if (page != null) {
            sql.limit(page.getPage(), page.getLimit());
        }
        return Db.find(sql.build(), sql.params());
    }

    private long listDataCount(Map<String, String> map) {
        SqlBuilder sb = new SqlBuilder()
                .line("select count(*) from (select k.material_id ")
                .line(" FROM `crm_supply_material_keep` k  ")
                .line("where 1=1");
        sb.line("GROUP BY k.material_id,k.warehouse_id,k.ascription_id ) a");

        return Db.queryLong(sb.toString());
    }


    public CrmSupplyMaterialKeep createMaterialKeepForAllot(CrmSupplyInventoryOrder order, CrmSupplyInventoryOrderDetail detail, BigDecimal amount, BigDecimal curBgNum, User user, String type,SupplyMaterialBatch batch,String keepId) {
        CrmSupplyMaterialKeep keep = new CrmSupplyMaterialKeep();
        keep.setCreator(order.getAuditName());
        keep.setMaterialId(detail.getMaterialId());
        keep.setMaterialCode(detail.getMaterialCode());
        keep.setMaterialType(detail.getMaterialType());
        keep.setMaterialRemarks(detail.getMaterialRemarks());
        keep.setMaterialUnit(detail.getMaterialUnit());
        keep.setAmount(amount);
        keep.setSourceId(order.getId());
        keep.setSourceCode(order.getCode());
        keep.setRemarks(order.getRemarks());
        keep.setCostPrice(detail.getCostPrice());
        keep.setBdSalePrice(detail.getBdSalePrice());
        // curBgNum记录的是批次记录当前剩余库存 如果是盘盈 则为0
        addMaterialKeep(keep,MaterialKeepConstants.INVENTORY,curBgNum,user,type,batch,keepId,order.getWarehouseId());
        materialKeepDao.save(keep);
        return keep;
    }

    public CrmSupplyMaterialKeep createMaterialKeepForInit(SupplyMaterial material, CrmSupplyWarehouse warehouse, BigDecimal amount,
                                                           BigDecimal curBgNum, User user, String type, SupplyMaterialBatch batch, String keepId) {
        CrmSupplyMaterialKeep keep = new CrmSupplyMaterialKeep();
        keep.setCreator(user.getUserName());//最新审批人名称
        keep.setMaterialId(material.getId());
        keep.setMaterialCode(material.getCode());
        keep.setMaterialType(materialTypeDao.get(material.getMaterialTypeId()).getName());
        keep.setMaterialRemarks(material.getRemarks());
        keep.setMaterialUnit(material.getMaterialAttribute());
        keep.setAmount(amount);
        keep.setMaterialUnit(material.getUnitName());
        keep.setSourceId(batch.getBizId());  //业务单id
        keep.setSourceCode(batch.getBizCode()); //业务单号
        keep.setRemarks(warehouse.getRemarks());//
        keep.setCostPrice(BigDecimal.ZERO);
        keep.setBdSalePrice(batch.getBdSalePrice());
        // curBgNum记录的是批次记录当前剩余库存 如果是盘盈 则为0
        addMaterialKeep(keep,MaterialKeepConstants.IN_RETURN_INIT,curBgNum,user,type,batch,keepId,warehouse.getId());
        materialKeepDao.newSave(keep);
        return keep;
    }
    public CrmSupplyMaterialKeep createMaterialKeepForDeliver(CrmSupplyMaterialDeliverOrder order,
                                                              CrmSupplyMaterialDeliverOrderDetail detail,
                                                              BigDecimal curBgNum, User user, String type,
                                                              SupplyMaterialBatch batch, String keepId,
                                                              SupplyMaterial material) {
        CrmSupplyMaterialKeep keep = new CrmSupplyMaterialKeep();
        keep.setCreator(user.getUserName());
        keep.setMaterialId(detail.getMaterialId());
        keep.setMaterialCode(material.getCode());
        keep.setMaterialType(detail.getMaterialType());
        keep.setMaterialRemarks("");
        keep.setMaterialUnit(material.getUnitName());
        keep.setAmount(detail.getInAmount());
        keep.setSourceId(detail.getId());
        keep.setSourceCode(order.getNumber());
        keep.setRemarks(order.getRemarks());
        keep.setCostPrice(detail.getPurchasePrice());
        keep.setBdSalePrice(detail.getPurchasePrice());
        addMaterialKeep(keep,MaterialKeepConstants.IN_RETURN_QQ,curBgNum,user,type,batch,keepId,order.getInWarehouseId());
        materialKeepDao.save(keep);
        return keep;
    }
    /**
     * 调拨出库
    */
    public CrmSupplyMaterialKeep createAllocationMatKeep(CrmSupplyAllocationOrder order,CrmSupplyAllocationOrderDetail detail, BigDecimal outNum,
                                                         BigDecimal curBgNum, User user, String type,SupplyMaterialBatch batch,String keepId){
        CrmSupplyMaterialKeep keep = new CrmSupplyMaterialKeep();
        keep.setCreator(CrmUtils.getUserXM(user));
        keep.setMaterialId(detail.getMaterialId());
        keep.setMaterialCode(detail.getMaterialCode());
        keep.setMaterialType(detail.getMaterialType());
        keep.setMaterialRemarks(detail.getMaterialRemarks());
        keep.setMaterialUnit(detail.getMaterialUnit());
        keep.setAmount(outNum);
        keep.setSourceId(order.getId());
        keep.setSourceCode(order.getCode());
        keep.setRemarks(order.getRemarks());
        keep.setCostPrice(batch.getCostPrice());
        keep.setBdSalePrice(batch.getBdSalePrice());
        keep.setDeliveryMethod(order.getDeliveryMethod());
        addMaterialKeep(keep,MaterialKeepConstants.ALLOT_OUT,curBgNum,user,type,batch,keepId,order.getWarehouseId());
        materialKeepDao.save(keep);
        return keep;
    }

    /**
     * 调拨入库
     */
    public CrmSupplyMaterialKeep createAllocationInKeep(CrmSupplyAllocationOrder order,CrmSupplyAllocationOrderDetail detail, BigDecimal curBgNum, User user, String type,SupplyMaterialBatch batch,String keepId){
        CrmSupplyMaterialKeep keep = new CrmSupplyMaterialKeep();
        keep.setCreator(CrmUtils.getUserXM(user));
        keep.setMaterialId(detail.getMaterialId());
        keep.setMaterialCode(detail.getMaterialCode());
        keep.setMaterialType(detail.getMaterialType());
        keep.setMaterialRemarks(detail.getMaterialRemarks());
        keep.setMaterialUnit(detail.getMaterialUnit());
        keep.setAmount(detail.getInoutAmount());
        keep.setSourceId(order.getId());
        keep.setSourceCode(order.getCode());
        keep.setRemarks(order.getRemarks());
        keep.setCostPrice(batch.getCostPrice());
        keep.setBdSalePrice(batch.getBdSalePrice());
        keep.setDeliveryMethod(order.getDeliveryMethod());
        addMaterialKeep(keep,MaterialKeepConstants.ALLOT_IN,curBgNum,user,type,batch,keepId,order.getInWarehouseId());
        materialKeepDao.save(keep);
        return keep;
    }


    public void addMaterialKeep(CrmSupplyMaterialKeep keep,String source, BigDecimal curBgNum, User user, String type,SupplyMaterialBatch batch,String keepId,String warehouseId){
        CrmSupplyWarehouse warehouse =  warehouseDao.get(warehouseId);
        keep.setBatchId(batch.getId());
        keep.setBatchCode(batch.getCode());
        keep.setBatchRemaining(batch.getRemaining());
        keep.setId(keepId);
        keep.setCurBgNum(curBgNum);
        keep.setWarehouseId(warehouse.getId());
        keep.setWarehouseName(warehouse.getName());
        keep.setAscriptionId(warehouse.getAscriptionId());
        keep.setAscriptionName(warehouse.getAscriptionName());
        keep.setCreateBy(user.getId());
        keep.setCreateTime(new Date());
        keep.setSource(source);
        String belongingType = warehouse.getType();
        keep.setBelongingType(belongingType);
        keep.setType(type);
    }

    public CrmSupplyMaterialKeep createKeep(KeepUnit unit, SupplyMaterialBatch batch,String deliveryMethodName) {
        CrmSupplyWarehouse warehouse =  warehouseDao.get(unit.getWarehouseId());

        CrmSupplyMaterialKeep keep = new CrmSupplyMaterialKeep();
        String belongingType = InventoryOrderConstants.DISTRIBUTOR.equals(warehouse.getType()) ?
                InventoryOrderConstants.SUPPLIER :
                (InventoryOrderConstants.SUPPLIER.equals(warehouse.getType()) ?
                        InventoryOrderConstants.DISTRIBUTOR : warehouse.getType());
        keep.setBelongingType(belongingType);
        keep.setMaterialId(unit.getMaterialId());
        keep.setMaterialCode(unit.getMaterialCode());
        keep.setMaterialType(unit.getMaterialType());
        keep.setMaterialRemarks(unit.getMaterialRemarks());
        keep.setMaterialUnit(unit.getMaterialUnit());
        keep.setType(unit.getType());
        keep.setAmount(unit.getAmount());
        keep.setCurBgNum(batch.getRemaining());
        keep.setWarehouseId(warehouse.getId());
        keep.setWarehouseName(warehouse.getName());
        keep.setAscriptionId(warehouse.getAscriptionId());
        keep.setAscriptionName(warehouse.getAscriptionName());
        keep.setCreateBy(unit.getUserId());
        keep.setCreator(unit.getUserName());
        keep.setCreateTime(new Date());
        keep.setSource(unit.getSource());
        keep.setSourceId(unit.getSourceId());
        keep.setSourceCode(unit.getSourceCode());
        keep.setRemarks(unit.getRemarks());
        keep.setCostPrice(batch.getCostPrice());
        keep.setBdSalePrice(batch.getBdSalePrice());
        keep.setBatchId(batch.getId());
        keep.setBatchCode(batch.getCode());
        keep.setBatchRemaining(batch.getRemaining());
        keep.setProjectCode(unit.getProjectCode());
        keep.setAccountFlag("0");
        keep.setId(IdGen.uuid());
        keep.setDeliveryMethod(deliveryMethodName);
        materialKeepDao.save(keep);
        return keep;
    }

    /**
     * 退货单发货——出库
     */
    public CrmSupplyMaterialKeep createReturnOrderOutMatKeep(CrmSupplyMaterialReturnOrder order, CrmSupplyMaterialReturnOrderDetail detail,
                  BigDecimal curBgNum, User user, String type, SupplyMaterialBatch batch, String keepId) {
        CrmSupplyMaterialKeep keep = new CrmSupplyMaterialKeep();
        keep.setCreator(order.getConfirmName());
        keep.setMaterialId(detail.getMaterialId());
        keep.setMaterialCode(detail.getMaterialCode());
        keep.setMaterialType(detail.getMaterialType());
        keep.setMaterialRemarks(detail.getMaterialRemarks());
        keep.setMaterialUnit(detail.getMaterialUnit());
        keep.setAmount(curBgNum);
        keep.setSourceId(order.getId());
        keep.setSourceCode(order.getNumber());
        keep.setRemarks(order.getReturnRemark());
        keep.setCostPrice(detail.getCostPrice());
        keep.setBdSalePrice(detail.getSalesPrice());
        keep.setDeliveryMethod(order.getReturnMethodName());
        addMaterialKeep(keep,MaterialKeepConstants.OUT_RETURN_ORDER,curBgNum,user,type,batch,keepId,order.getWarehouseId());
        materialKeepDao.save(keep);
        return keep;
    }

    /**
     * 退货单发货——入库
     */
    public CrmSupplyMaterialKeep createReturnOrderInMatKeep(CrmSupplyMaterialReturnOrder order, CrmSupplyMaterialReturnOrderDetail detail,
                                                             User user, String type, SupplyMaterialBatch batch, String keepId) {
        CrmSupplyMaterialKeep keep = new CrmSupplyMaterialKeep();
        keep.setCreator(order.getConfirmName());
        keep.setMaterialId(detail.getMaterialId());
        keep.setMaterialCode(detail.getMaterialCode());
        keep.setMaterialType(detail.getMaterialType());
        keep.setMaterialUnit(detail.getMaterialUnit());
        keep.setMaterialRemarks(detail.getMaterialRemarks());
        keep.setAmount(detail.getReturnNum());
        keep.setSourceId(order.getId());
        keep.setSourceCode(order.getNumber());
        keep.setRemarks(order.getReturnRemark());
        keep.setCostPrice(detail.getCostPrice());
        keep.setBdSalePrice(detail.getSalesPrice());
        keep.setDeliveryMethod(order.getReturnMethodName());
        addMaterialKeep(keep,MaterialKeepConstants.IN_RETURN_ORDER,detail.getReturnNum(),user,type,batch,keepId,order.getInWarehouseId());
        materialKeepDao.save(keep);
        return keep;
    }


    /**
     *期初库存=开始时间之前总入库-总出库量
     * 期中出库=期中各类型总出库量
     * 期中入库=期中各类型总入库量
     * 期末库存=期初库存+期中总入库量-期中总出库量
     */

    public LayuiPage fittingTurnOverStatistics(LayuiPage page, Map<String, String> map) {
        if (!StringUtil.checkParamsValid(map.get("startCreateTime")) || !StringUtil.checkParamsValid(map.get("endcreateTime"))) {
            return page;
        }
        List<Record> list = fingTurnoverRateStatistics(page, map);
        for (Record rd : list) {
            BigDecimal qcInCostAmount = rd.getBigDecimal("qcInCostAmount"); //期初入库数量
            BigDecimal qcOutCostAmount = rd.getBigDecimal("qcOutCostAmount"); //期初出库数量
            BigDecimal bqInCostCount = rd.getBigDecimal("bqInCostCount"); //本期入库数量
            BigDecimal bqOutCostCount = rd.getBigDecimal("bqCostCount"); //本期出库数量

            BigDecimal qcchCostPrice = qcInCostAmount.subtract(qcOutCostAmount); //期初存货数量
            BigDecimal qmchCostPrice = qcchCostPrice.add(bqInCostCount).subtract(bqOutCostCount); //期末存货数量

            rd.set("qcchCostPrice", qcchCostPrice);
            rd.set("qmchCostPrice", qmchCostPrice);
            //存货周转次数：本期出库成本/平均存货成本
            BigDecimal sum = qcchCostPrice.add(qmchCostPrice);
            BigDecimal chzzDays = BigDecimal.ZERO;
            BigDecimal chzzCount = BigDecimal.ZERO;
            if (sum.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal bqCostCount = rd.getBigDecimal("bqCostCount");
                chzzCount = bqCostCount.divide(sum.divide(new BigDecimal(2), BigDecimal.ROUND_HALF_UP), BigDecimal.ROUND_HALF_UP);
                //存货周转天数：统计时间段（按天计算）/存货周转次数
                long days;
                try {
                    days = DateUtils.daysBetween(map.get("startCreateTime"), map.get("endcreateTime"));
                } catch (ParseException e) {
                    throw new ServiceException("日期计算错误");
                }
                if (chzzCount.compareTo(BigDecimal.ZERO) > 0) {
                    chzzDays = new BigDecimal(days).divide(chzzCount, BigDecimal.ROUND_HALF_UP);
                }
            }
            rd.set("chzzCount", chzzCount);
            rd.set("chzzDays", chzzDays);
        }
        ;
        page.setData(list);
        page.setCount(listDataCount(map));
        return page;
    }


    /**
     * 进销存统计
     * 期初库存=开始时间之前总入库-总出库量
     * 期中出库=期中各类型总出库量
     * 期中入库=期中各类型总入库量
     * 期末库存=期初库存+期中总入库量-期中总出库量
     */
    public LayuiPage fittingInventoryStatisticsData(LayuiPage page, Map<String, String> map) {
        if (!StringUtil.checkParamsValid(map.get("startCreateTime")) || !StringUtil.checkParamsValid(map.get("endCreateTime"))) {
            return page;
        }
        List<Record> list = inventoryStatisticsList(page, map);
        for (Record record : list) {
            BigDecimal qcInCostAmount = record.getBigDecimal("qcInCostAmount");
            BigDecimal qcOutCostAmount = record.getBigDecimal("qcOutCostAmount");
            BigDecimal bqInAmount = record.getBigDecimal("bqInAmount");
            BigDecimal bqOutAmount = record.getBigDecimal("bqOutAmount");

            BigDecimal qcJcAmount = qcInCostAmount.subtract(qcOutCostAmount);   //期初结存库存
            BigDecimal qmJcAmount = qcJcAmount.add(bqInAmount).subtract(bqOutAmount);   //期末结存数量

            record.set("qcJcAmount", qcJcAmount);
            record.set("qmJcAmount", qmJcAmount);
        }
        page.setData(list);
        page.setCount(listDataCount(map));
        return page;
    }

    public List<Record> inventoryStatisticsList(LayuiPage page, Map<String, String> map) {
        SqlBuilder sql = new SqlBuilder();
        sql.line("  SELECT  k.material_id,any_value(k.material_remarks) as material_remarks,any_value(k.material_type) as material_type,any_value(k.material_code) as material_code,any_value(k.warehouse_name) as warehouse_name ,any_value(k.ascription_name) as ascription_name, any_value(k.material_unit) as material_unit,")
                .line(" SUM(CASE WHEN k.type = '1' AND k.create_time<= CONCAT(?, ' 00:00:00') THEN k.amount  ELSE 0 END) AS qcInCostAmount,", map.get("startCreateTime"))
                .line(" SUM(CASE WHEN k.type = '2' AND k.create_time<= CONCAT(?, ' 00:00:00') THEN k.amount  ELSE 0 END) AS qcOutCostAmount, ", map.get("startCreateTime"))
                .line(" any_value(m.material_specs) as material_specs, any_value(m.material_brand) as  material_brand, any_value(m.material_name) as  material_name ,")
              /*  .line(" SUM(CASE WHEN k.type = '1' AND k.create_time>=CONCAT(?, ' 23:59:59') THEN k.amount ELSE 0 END ) AS qmInCostAmount,", map.get("endCreateTime"))
                .line(" SUM(CASE WHEN k.type = '2' AND k.create_time>=CONCAT(?, ' 23:59:59') THEN k.amount ELSE 0 END ) AS qmOutCostAmount,", map.get("endCreateTime"))*/
                .line(" SUM(CASE WHEN k.type = '1' AND k.create_time>=CONCAT(?, ' 00:00:00') AND k.create_time<=CONCAT(?, ' 23:59:59') THEN k.amount ELSE 0 END ) AS bqInAmount, ", map.get("startCreateTime"), map.get("endCreateTime"))
                .line(" SUM(CASE WHEN k.type = '2' AND k.create_time>=CONCAT(?, ' 00:00:00') AND k.create_time<=CONCAT(?, ' 23:59:59') THEN k.amount ELSE 0 END ) AS bqOutAmount ", map.get("startCreateTime"), map.get("endCreateTime"))
                .line(" FROM    `crm_supply_material_keep` k  ")
                .line(" left join crm_supply_material m on m.id=k.material_id where 1=1  ");
        appendCondition(sql, map);
        sql.line("GROUP BY k.material_id,k.warehouse_id,k.ascription_id");
        if (page != null) {
            sql.limit(page.getPage(), page.getLimit());
        }
        return Db.find(sql.build(), sql.params());
    }

    public LayuiPage exceptionOrderStatisticsData(LayuiPage page, Map<String, String> map) {
        if (!StringUtil.checkParamsValid(map.get("startCreateTime")) || !StringUtil.checkParamsValid(map.get("endCreateTime"))) {
            return page;
        }
        List<Record> list = exceptionOrderStatisticsList(page, map);
        page.setData(list);
        page.setCount(countExceptionOrderStatistics(map));
        return page;
    }

    public List<Record> exceptionOrderStatisticsList(LayuiPage page, Map<String, String> map) {
        SqlBuilder sql = new SqlBuilder();
        sql.line("  SELECT any_value(e.ascription_name) ascription_name,e.ascription_id,COUNT(e.id) AS number ")
                .line("FROM `crm_supply_exception` e ")
                .line("WHERE 1=1 and e.ascription_id <>'a'");
        getCondition(sql, map);
        sql.line("GROUP BY e.`ascription_id` ");
        if (page != null) {
            sql.limit(page.getPage(), page.getLimit());
        }
        return Db.find(sql.build(), sql.params());
    }

    public Long countExceptionOrderStatistics(Map<String, String> map) {
        SqlBuilder sql = new SqlBuilder();
        sql.line("  SELECT COUNT(*) FROM ")
                .line(" ( SELECT e.ascription_id ")
                .line(" FROM `crm_supply_exception` e ")
                .line(" WHERE 1=1 and e.ascription_id <>'a' ");
        getCondition(sql, map);
        sql.line(" GROUP BY e.`ascription_id`)a ");
        return Db.queryLong(sql.build(), sql.params());
    }

    public void getCondition(SqlBuilder builder, Map<String, String> map) {
        if (StringUtil.checkParamsValid(map.get("belong"))) {
            String belong = (String) map.get("belong");
            builder.line(" and e.ascription_id in(" + StringUtil.joinInSql(belong.split(",")) + ") ");
        }
        if (StringUtil.checkParamsValid(map.get("startCreateTime"))) {
            builder.line("and e.create_time >= concat(?, ' 00：00：00')", map.get("startCreateTime").trim());
        }
        if (StringUtil.checkParamsValid(map.get("endCreateTime"))) {
            builder.line("and e.create_time <= concat(?, ' 23：59：59')", map.get("endCreateTime").trim());
        }

        if (StringUtil.checkParamsValid(map.get("ascriptionId"))) {
            builder.line(" and e.ascription_id=? ", map.get("ascriptionId"));
        }

    }


    public List<Record> exceptionOrderStaticList(Map<String, String> map){
        SqlBuilder sql = new SqlBuilder();
          sql.line(" select e.* ")
                  .line(" FROM `crm_supply_exception` e ")
                  .line(" where 1=1 and e.ascription_id <>'a' ");
        getCondition(sql, map);
        return Db.find(sql.build(), sql.params());
    }

    public List<Record> getExportExceptionOrderList(Map<String, String> map){
        if (!StringUtil.checkParamsValid(map.get("startCreateTime")) || !StringUtil.checkParamsValid(map.get("endCreateTime"))) {
            return new ArrayList<>();
        }
        SqlBuilder sql = new SqlBuilder();
        sql.line("  SELECT e.* ")
                .line("FROM `crm_supply_exception` e ")
                .line("WHERE 1=1 and e.ascription_id <>'a'");
        getCondition(sql, map);
        return Db.find(sql.build(), sql.params());
    }

    public void exportExceptionOrder(Map<String, String> map, HttpServletResponse response) throws IOException {
        List<Record> list=getExportExceptionOrderList(map);
        List<ExportExceptionOrderExcel> excelList=new ArrayList<>();
        int sort = 1;
        for(Record record:list){
            ExportExceptionOrderExcel excel=new ExportExceptionOrderExcel();
            excel.setSort(String.valueOf(sort));
            excel.setCode(record.getStr("code"));
            excel.setStatus(record.getStr("status"));
            excel.setOperator_name(record.getStr("operator_name"));
            excel.setRemarks(record.getStr("remarks"));
            excel.setOperator_time(record.getDate("operator_time"));
            excel.setPlace_order_time(record.getDate("place_order_time"));
            excelList.add(excel);
            sort++;
        }
        String fileName = map.get("name") + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
        new ExportExcel(map.get("name"), ExportExceptionOrderExcel.class)
                .setDataList(excelList)
                .write(response, fileName)
                .dispose();
    }

}
