package com.goafanti.order.service.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.goafanti.admin.bo.AdminListBo;
import com.goafanti.common.bo.Error;
import com.goafanti.common.bo.OrderExamineBo;
import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.dao.AdminMapper;
import com.goafanti.common.dao.NewOrderChangeMapper;
import com.goafanti.common.dao.NewOrderDunMapper;
import com.goafanti.common.dao.NewOrderRefundMapper;
import com.goafanti.common.dao.OrderChangeLogMapper;
import com.goafanti.common.dao.OrderExamineMapper;
import com.goafanti.common.dao.OrderRefundInvoiceMapper;
import com.goafanti.common.dao.OrganizationManagementMapper;
import com.goafanti.common.dao.TChangeDunMapper;
import com.goafanti.common.dao.TChangeTaskMapper;
import com.goafanti.common.dao.TOrderBillNewMapper;
import com.goafanti.common.dao.TOrderInvoiceMapper;
import com.goafanti.common.dao.TOrderLogMapper;
import com.goafanti.common.dao.TOrderNewMapper;
import com.goafanti.common.dao.TOrderTaskMapper;
import com.goafanti.common.dao.TTaskMidMapper;
import com.goafanti.common.dao.UserLockReleaseMapper;
import com.goafanti.common.enums.NoticeStatus;
import com.goafanti.common.error.BusinessException;
import com.goafanti.common.model.OrderChangeLog;
import com.goafanti.common.model.OrderExamine;
import com.goafanti.common.model.OrderRefundInvoice;
import com.goafanti.common.model.TChangeDun;
import com.goafanti.common.model.TChangeTask;
import com.goafanti.common.model.TOrderBillNew;
import com.goafanti.common.model.TOrderNew;
import com.goafanti.common.model.TOrderTask;
import com.goafanti.common.model.TTaskMid;
import com.goafanti.common.model.Admin;
import com.goafanti.common.model.NewOrderChange;
import com.goafanti.common.model.NewOrderDun;
import com.goafanti.common.utils.DateUtils;
import com.goafanti.common.utils.ExportExcelUtil;
import com.goafanti.common.utils.StringUtils;
import com.goafanti.core.mybatis.BaseMybatisDao;
import com.goafanti.core.mybatis.JDBCIdGenerator;
import com.goafanti.core.mybatis.page.Pagination;
import com.goafanti.core.shiro.token.TokenManager;
import com.goafanti.order.bo.BillBo;
import com.goafanti.order.bo.InputNewOrderRefund;
import com.goafanti.order.bo.InputTChangeTask;
import com.goafanti.order.bo.InvoiceBo;
import com.goafanti.order.bo.NewOderCahngeListBo;
import com.goafanti.order.bo.NewOrderChangeBo;
import com.goafanti.order.bo.OrderChangeLogBo;
import com.goafanti.order.bo.OutNewOrderDunBo;
import com.goafanti.order.bo.OutNewOrderRefund;
import com.goafanti.order.bo.TChangeDunOut;
import com.goafanti.order.bo.TChangeTaskOut;
import com.goafanti.order.bo.TOrderLogBo;
import com.goafanti.order.bo.TOrderNewBo;
import com.goafanti.order.bo.TOrderTaskBo;
import com.goafanti.order.enums.OrderChangeType;
import com.goafanti.order.enums.OrderNewState;
import com.goafanti.order.enums.OrderType;
import com.goafanti.order.enums.ProcessStatus;
import com.goafanti.order.service.NewOrderDunService;
import com.goafanti.order.service.OrderChangeService;
import com.goafanti.order.service.OrderNewService;
import com.goafanti.order.service.OrderService;
import com.goafanti.techproject.enums.TaskState;

@Service
public class OrderChangeServiceImpl extends BaseMybatisDao<NewOrderChangeMapper> implements OrderChangeService {
	@Autowired
	private NewOrderChangeMapper	newOrderChangeMapper;
	@Autowired
	private OrderChangeLogMapper	orderChangeLogMapper;
	@Autowired
	private TOrderNewMapper			tOrderNewMapper;
	@Autowired
	private TOrderLogMapper 		tOrderLogMapper;  
	@Autowired
	private TOrderTaskMapper	tOrderTaskMapper;
	@Autowired
	private TOrderInvoiceMapper	tOrderInvoiceMapper;
	@Autowired
	private OrderRefundInvoiceMapper	orderRefundInvoiceMapper;
	@Autowired
	private OrganizationManagementMapper	organizationManagementMapper;
	@Autowired
	private NewOrderRefundMapper	newOrderRefundMapper;
	@Autowired
	private OrderExamineMapper	orderExamineMapper;
	@Autowired
	private OrderService	orderService;
	@Autowired
	private NewOrderDunMapper	newOrderDunMapper;
	@Autowired
	private JDBCIdGenerator	idGenerator;
	@Autowired
	private AdminMapper	adminMapper;
	@Autowired
	private OrderNewService	orderNewService;
	@Autowired
	private NewOrderDunService	newOrderDunService;
	@Autowired
	private TChangeTaskMapper	tChangeTaskMapper;
	@Autowired
	private TChangeDunMapper	tChangeDunMapper;
	@Autowired
	private TOrderBillNewMapper tOrderBillNewMapper;
	@Autowired
	private TTaskMidMapper	tTaskMidMapper;
	@Autowired
	private UserLockReleaseMapper	userLockReleaseMapper;
	
	Logger							logger	= LoggerFactory.getLogger(OrderChangeServiceImpl.class);
	
	@Override
	public int addOrderChange(NewOrderChangeBo t,String startRemarks) {
		TOrderNew ton=new TOrderNew();
		ton.setOrderNo(t.getOrderNo());
		ton.setDeleteSign(2);//将订单置为锁定
		tOrderNewMapper.updateByPrimaryKeySelective(ton);
		BigDecimal invoiceAmount=tOrderInvoiceMapper.conutAmountByOrderNo(t.getOrderNo());
		t.setInvoiceAmount(invoiceAmount);//开票金额
		BigDecimal paymentAmount=tOrderBillNewMapper.conutAmountByOrderNo(t.getOrderNo());
		t.setPaymentAmount(paymentAmount);//收款金额
		//预计成本与预计退款：预计成本=项目价格*数量    预计退款=收款-预计成本
		BigDecimal estimateCost=new BigDecimal(tOrderTaskMapper.selectEstimateCost(t.getOrderNo()));
		t.setEstimateCost(estimateCost);
		t.setEstimateRefundable(paymentAmount.subtract(estimateCost));
		t.setZxsRemarks(startRemarks);
		newOrderChangeMapper.insertSelective(t);
		NewOrderChangeBo ncb=newOrderChangeMapper.selectByorderNoAndStatus(t.getOrderNo());

			List<OutNewOrderDunBo> listDun=newOrderDunMapper.selectListNewOrderDun(t.getOrderNo(),null,null);
			List<TChangeDun> listcd=new ArrayList<>();
			if (listDun!=null&&!listDun.isEmpty()) {
				for (OutNewOrderDunBo d : listDun) {
					TChangeDun cd=new TChangeDun();
					cd.setOrderNo(d.getOrderNo());
					cd.setAid(d.getAid());
					cd.setAppropriationRatio(d.getAppropriationRatio());
					cd.setCid(ncb.getId());
					cd.setDid(d.getId());
					cd.setTid(d.getTid());
					cd.setProjectType(d.getProjectType());
					cd.setDunType(d.getDunType());
					cd.setMoney(d.getMoney());
					cd.setWaitDay(d.getWaitDay());
					cd.setStartTime(d.getStartTime());
					cd.setEffectiveCount(d.getEffectiveCount());
					cd.setCustomizeTime(d.getCustomizeTime());
					cd.setCustomizeName(d.getCustomizeName());
					listcd.add(cd);
				}
				tChangeDunMapper.insertSelectiveList(listcd);
			}
			List<TChangeTask> listck=new ArrayList<>();
			List<TOrderTaskBo> listTask=tOrderTaskMapper.selectOrderTaskAll(t.getOrderNo());
			if (listTask!=null&&!listTask.isEmpty()) {
				for (TOrderTaskBo tt : listTask) {
					TChangeTask ck=new TChangeTask();
					ck.setOrderNo(tt.getOrderNo());
					ck.setCid(ncb.getId());
					ck.setCommodityId(tt.getCommodityId());
					ck.setOrderNo(tt.getOrderNo());
					ck.setCommodityName(tt.getCommodityName());
					ck.setCommodityPrice(tt.getCommodityPrice());
					ck.setCommodityQuantity(tt.getCommodityQuantity());
					ck.setTaskComment(tt.getTaskComment());
					ck.setSplitStatus(tt.getSplitStatus());
					ck.setSplitSuper(tt.getSplitSuper());
					ck.setReceiverName(tt.getReceiverName());
					ck.setMain(tt.getMain());
					ck.setTid(tt.getId());
					listck.add(ck);
				}
				tChangeTaskMapper.insertSelectiveList(listck);
			}
			if (t.getType()==OrderChangeType.TDTK.getCode()) {
				OrderChangeLog ocl=new OrderChangeLog();
				ocl.setAuditor(TokenManager.getAdminId());
				ocl.setOrderNo(t.getOrderNo());
				ocl.setRemarks(startRemarks);
				ocl.setChangeId(ncb.getId());
				ocl.setStatus(0);
				sendNotice(0, t);//设置与通过一样发送信息
				orderChangeLogMapper.insertSelective(ocl);
			}
		return 1;
	}
	
	/*
	 * 新增审核流程中的
	 */
	private void insertOrderExamine(String orderNo) {
		List<TOrderTaskBo> list=tOrderTaskMapper.selectOrderTaskAll(orderNo);
		for (TOrderTaskBo t : list) {
			if (t.getConsultantId()!=null) {
				OrderExamine o=new OrderExamine();
				o.setAid(t.getConsultantId());
				o.setOrderNo(orderNo);
				o.setCreateTime(new Date());
				o.setType(0);//咨询师
				o.setStatus(0);//正常
				orderExamineMapper.insertSelective(o);
			}
			if (t.getManagerId()!=null) {
				OrderExamine o=new OrderExamine();
				o.setAid(t.getManagerId());
				o.setOrderNo(orderNo);
				o.setCreateTime(new Date());
				o.setType(1);//咨询师经理
				o.setStatus(0);//正常
				orderExamineMapper.insertSelective(o);
			}
		}
		
		
	}

	@Override
	public List<NewOrderChangeBo> orderChangeDetails(String orderNo) {
		List<NewOrderChangeBo> list=newOrderChangeMapper.selectByorderNo(orderNo);
		for (NewOrderChangeBo noc : list) {
			List<OrderExamineBo> consultantExamine =orderExamineMapper.selectByOrderNo(noc.getOrderNo(),0);
			List<OrderExamineBo> managerExamine=orderExamineMapper.selectByOrderNo(noc.getOrderNo(),1);
			int isExamine=orderExamineMapper.selectByOrderNoAndAid(noc.getOrderNo(),TokenManager.getAdminId());
			noc.setConsultantExamine(consultantExamine);
			noc.setManagerExamine(managerExamine);
			noc.setIsExamine(isExamine);
		}
		return list;
	}
	@Override
	public NewOrderChangeBo orderChangeDetailsById(Integer id) {
		NewOrderChangeBo nb=newOrderChangeMapper.selectById(id);
		List<OrderExamineBo> consultantExamine =orderExamineMapper.selectByOrderNo(nb.getOrderNo(),0);
		List<OrderExamineBo> managerExamine=orderExamineMapper.selectByOrderNo(nb.getOrderNo(),1);
		int isExamine=orderExamineMapper.selectByOrderNoAndAid(nb.getOrderNo(),TokenManager.getAdminId());
		nb.setConsultantExamine(consultantExamine);
		nb.setManagerExamine(managerExamine);
		nb.setIsExamine(isExamine);
		return nb;
	}
	@Override
	public int pushOrderChangeAudit(String changeId, String remarks, Integer status,Integer processState,Integer rejectState) {
		NewOrderChangeBo nb=newOrderChangeMapper.selectByChangeId(changeId);
		String orderNo=nb.getOrderNo();
		if (processState==null||(nb.getProcessState()!=9&&processState !=nb.getProcessState()) ) {
			throw new BusinessException(new Error( "变更流程与您所操作流程不匹配","变更流程与您所操作流程不匹配"));
		}
		if (nb.getStatus()==4) {
			throw new BusinessException(new Error( "变更流程已通过审核","变更流程已通过审核"));
		}
		//2通过 3驳回
		if (status==2) {
			//变更类型 0退单退款 1项目及金额变更 2仅项目变更 3仅金额变更 4重报 5赠送
			if(nb.getType() !=null){
				if (nb.getChangeAmount().compareTo(new BigDecimal("0.2"))<0) {//小于则总裁通过，大于则董事长
					if(nb.getProcessState()==7) {//总裁项目变更通过
						nb.setStatus(2);
						}
				}else {
					if(nb.getProcessState()==7) {
						nb.setProcessState(nb.getProcessState()+1);
						}else if(nb.getProcessState()==8) {//董事长项目变更通过
						nb.setStatus(2);
						}
				}
				 if(nb.getProcessState()==1){//营销管理通过则设置技术管理员通过表
					 if (orderExamineMapper.checkCountStatus(orderNo,null,null)<1) {
						 insertOrderExamine(orderNo);
					 } else {
						 orderExamineMapper.updateByOrderNo(orderNo,null);
					 }
					 nb.setProcessState(nb.getProcessState()+1);
					}
				 //必须放置在咨询师与咨询师经理前，否则会直接通过不走咨询师管理员
				 if(nb.getProcessState()==4||nb.getProcessState()==5||nb.getProcessState()==6) {
					 nb.setProcessState(nb.getProcessState()+1);
				 }
				 if(nb.getProcessState()==2){//咨询师
						//找出当时人的审核改为通过
						orderExamineMapper.updateByOrderNoAndAid(orderNo,TokenManager.getAdminId(),0);
						//全部通过了则跳下个流程
						if (orderExamineMapper.checkCountStatus(orderNo,0,0)<1) {
							nb.setProcessState(nb.getProcessState()+1);
						}
					}
				 if(nb.getProcessState()==3){//咨询师经理
						//找出当时人的审核改为通过
						orderExamineMapper.updateByOrderNoAndAid(orderNo,TokenManager.getAdminId(),1);
						//全部通过了则跳下个流程
						if (orderExamineMapper.checkCountStatus(orderNo,1,0)<1) {
							nb.setProcessState(nb.getProcessState()+1);
						}
					}
				
			}
			/*else {
				if(nb.getProcessState()==9) {
					//changgeAdopt(nb); 取消订单变更完成
					}
				//流程状态 0营销员 1营销管理员 2技术员 3技术经理 4技术总监 5财务专员(退单) 6财务总监 7总裁 8董事长 9 财务专员(非退单)
				if (nb.getProcessState()==1) nb.setProcessState(7);
				else if (nb.getProcessState()==7)nb.setProcessState(9);
			}*/ //去掉第二条线
			if(nb.getStatus()==3) {
				nb.setStatus(1);//如果驳回数据则改为正常数据
			}
			//通过订单取消记录的驳回位置
			if (processState==nb.getBackStatus()) {
				nb.setBackStatus(0);
			}
		}else {
			nb.setProcessState(rejectState);
			nb.setStatus(3);//订单变更设置为驳回
			//驳回订单记录驳回位置
			if (processState>nb.getBackStatus()) {
				nb.setBackStatus(processState);
			}
			//驳回位置查看有无审核人，没有则直接跳下一个
			if (rejectState==2) {
				if (orderExamineMapper.checkCountStatus(orderNo,0,null)<1) nb.setProcessState(nb.getProcessState()+1);
			}
			if (rejectState==3) {
				if (orderExamineMapper.checkCountStatus(orderNo,1,null)<1) nb.setProcessState(nb.getProcessState()+1);
			}
			
			//如果驳回到技术经理之前则将审核表中状态跳回
			if(nb.getProcessState()==3) {
				orderExamineMapper.updateByOrderNo(orderNo,1);
			}else if (nb.getProcessState()<3) {
				orderExamineMapper.updateByOrderNo(orderNo,null);
			}
			
		}
		OrderChangeLog ocl=new OrderChangeLog();
		ocl.setAuditor(TokenManager.getAdminId());
		ocl.setOrderNo(orderNo);
		ocl.setRemarks(remarks);
		ocl.setChangeId(nb.getId());
		ocl.setStatus(status);
		orderChangeLogMapper.insertSelective(ocl);
		sendNotice(status,nb);
		newOrderChangeMapper.updateByPrimaryKeySelective(nb);
		return 1;
	}
	
	private void sendNotice(Integer status,NewOrderChangeBo nb) {
		//0发起2通过 3驳回
		Integer type=0;
		if(status==0)type=NoticeStatus.ORDER_CHANGE_START.getCode();
		if(status==2)type=NoticeStatus.ORDER_CHANGE_YES.getCode();
		if(status==3)type=NoticeStatus.ORDER_CHANGE_NO.getCode();
		//获取发起人与发起人部门
		AdminListBo a = adminMapper.getDeptNameByAid(TokenManager.getAdminId());
		//获取接收者
		//流程状态 0营销员 1营销管理员 2技术员 3技术经理 4技术总监 5财务专员(退单) 6财务总监 7总裁 8董事长 9 财务专员(非退单)
		List<String> alist = new ArrayList<>();
		TOrderNew o=tOrderNewMapper.selectByPrimaryKey(nb.getOrderNo());
		switch (nb.getProcessState()) {
		case 0:
			alist.add(o.getSalesmanId());
			break;
		case 1:
			alist.addAll(adminMapper.listNameByDepAndName(a.getDepartmentId(), "营销管理员"));
			break;
		case 2:
			alist.addAll(tOrderTaskMapper.listNameByDepAndName(o.getOrderNo(),0));
			break;
		case 3:
			alist.addAll(tOrderTaskMapper.listNameByDepAndName(o.getOrderNo(),1));
			break;
		case 4:
			for (Admin admin : adminMapper.getAdminRoleList("咨询师管理员")) {
				alist.add(admin.getId());
			}
			break;
		case 5:
			alist.add(organizationManagementMapper.selectByPrimaryKey(o.getOrderDep()).getFinanceId());
			break;	
		case 6:
			for (Admin admin : adminMapper.getAdminRoleList("财务管理员")) {
				alist.add(admin.getId());
			}
			break;
		case 7:
			if(nb.getStatus()==2) {
				alist.add(organizationManagementMapper.selectByPrimaryKey(o.getOrderDep()).getFinanceId());
			}else {
				for (Admin admin : adminMapper.getAdminRoleList("总裁")) {
					alist.add(admin.getId());
				}
			}
			break;
		case 8:
			if(nb.getStatus()==2) {
				alist.add(organizationManagementMapper.selectByPrimaryKey(o.getOrderDep()).getFinanceId());
			}else {
				for (Admin admin : adminMapper.getAdminRoleList("运营决策者")) {
					alist.add(admin.getId());
				}
			}
			break;
		case 9:
			alist.add(organizationManagementMapper.selectByPrimaryKey(o.getOrderDep()).getFinanceId());
			break;	
		
		}
		//发送站内信息与邮件
		orderNewService.pushGeneralSendNoticeAndEmail(alist, type, o.getOrderNo(), TokenManager.getAdminId(),0);
	}
	
	/**
	 * 变更完成复制出原订单镜像
	 */
	private void changeAdopt(NewOrderChangeBo nb) {
		TOrderNew t1=tOrderNewMapper.selectByPrimaryKey(nb.getOrderNo());
		List<OutNewOrderDunBo> td2=newOrderDunMapper.selectListNewOrderDun(nb.getOrderNo(), null, null);
		List<TOrderTaskBo> tt1=tOrderTaskMapper.selectOrderTaskAll(nb.getOrderNo());
		List<TOrderLogBo> tl1=tOrderLogMapper.selectOrderByNo(nb.getOrderNo());		
		String newOrderNo=idGenerator.generateId().toString();
		t1.setOrderNo(newOrderNo);
		nb.setUsedOrder(newOrderNo);
		t1.setDeleteSign(1);//将原订单作废，只能查看
		tOrderNewMapper.insertSelective(t1);
		Map<Integer, Integer> map=new HashMap<>();
		for (TOrderTaskBo tOrderTaskBo : tt1) {
			//处理父子项目关系 将员父项目存储
			int x=tOrderTaskBo.getId();
			tOrderTaskBo.setId(null);
			tOrderTaskBo.setOrderNo(newOrderNo);
			if(tOrderTaskBo.getSplitStatus()==2) {
				tOrderTaskBo.setSplitSuper(map.get(tOrderTaskBo.getSplitSuper()));
			}
			tOrderTaskMapper.insertSelectiveGetId(tOrderTaskBo);
			int y=tOrderTaskBo.getId();
			tTaskMidMapper.insertSelective(new TTaskMid(y,new BigDecimal(0)));
			if(tOrderTaskBo.getSplitStatus()==1) {
				map.put(x, y);
			}
		}
		if (!td2.isEmpty()) {
			List<OutNewOrderDunBo> newtd2=new ArrayList<>();
			for (OutNewOrderDunBo outNewOrderDunBo : td2) {
				outNewOrderDunBo.setId(null);
				outNewOrderDunBo.setOrderNo(newOrderNo);
				newtd2.add(outNewOrderDunBo);
			}
			newOrderDunMapper.insertBatch(newtd2);
		}
		if (!tl1.isEmpty()) {
			List<TOrderLogBo> newtl1=new ArrayList<>();
			for (TOrderLogBo tOrderLogBo : tl1) {
				tOrderLogBo.setId(null);
				tOrderLogBo.setOrderNo(newOrderNo);
				newtl1.add(tOrderLogBo);
			}
			tOrderLogMapper.insertBatch(newtl1);
		}
		nb.setStatus(4);
		//将订单恢复正常
		TOrderNew orderNew =new TOrderNew();
		orderNew.setOrderNo(nb.getOrderNo());
		orderNew.setDeleteSign(0);
		orderNew.setPrimaryOrder(newOrderNo);
		tOrderNewMapper.updateByPrimaryKeySelective(orderNew);
	}
	
	@Override
	public boolean checkOderNo(String orderNo) {
		int i=newOrderChangeMapper.checkOderNo(orderNo);
		if (i>0) {
			return true;
		}
		return false;
	}
	@Override
	public List<OrderChangeLogBo> selectOrderChangeLogList(String changeId) {
		return orderChangeLogMapper.selectOrderChangeLogList(changeId);
	}
	@SuppressWarnings("unchecked")
	@Override
	public Pagination<NewOderCahngeListBo> selectOrderChangeList(String userName,Integer  processState,Integer timeType,String startTime,String endTime,
			String depId,String salesmanName,Integer complete,String orderNo, String contractNo,Integer type,Integer pageSize, Integer pageNo) {
		Map<String, Object> parameter=new HashMap<String, Object>();
		if(pageSize==null||pageSize<0)pageSize=10;
		if(pageNo==null||pageNo<0)pageNo=1;
		parameter.put("processState", processState==null?0:processState);
		parameter.put("complete", complete==null?0:complete);
		if (StringUtils.isNotBlank(userName)) parameter.put("userName", userName);
		if (null!=processState) parameter.put("processState", processState);
		if (StringUtils.isNotBlank(orderNo)) parameter.put("orderNo", orderNo);
		if (StringUtils.isNotBlank(contractNo)) parameter.put("contractNo", contractNo);
		if (null!=type) parameter.put("type", type);
		if (null!=timeType) parameter.put("timeType", timeType);
		if (StringUtils.isNotBlank(startTime)) parameter.put("startTime", startTime);
		if (StringUtils.isNotBlank(endTime)) parameter.put("endTime", endTime+" 23:59:59");
		if (StringUtils.isNotBlank(depId)) parameter.put("depId", depId);
		if (StringUtils.isNotBlank(salesmanName)) parameter.put("salesmanName", salesmanName);
		if(processState==5&&TokenManager.hasRole(AFTConstants.FINANCE_MANAGER)) {
			parameter.put("aids", adminMapper.selectBySuperId(TokenManager.getAdminId()));
		}else {
			parameter.put("aid", TokenManager.getAdminId());
		}
		parameter.put("deps", orderService.selectMyDeps());
		Pagination<NewOderCahngeListBo> data = (Pagination<NewOderCahngeListBo>)findPage("selectOrderChangeList", "selectOrderChangeCount", parameter, pageNo, pageSize);
		return data;
	}
	@Override
	public int updateOrderChange(NewOrderChangeBo t,Integer changeType,String startRemarks) {
		NewOrderChange  noc=new NewOrderChange();
		t.setProcessState(1);
		noc.setId(t.getId());
		if (changeType==0) {
			chekeChangeTaskNumber(noc);
			noc.setRemarks(t.getRemarks());
			noc.setType(t.getType());
			noc.setVoucherUrl(t.getVoucherUrl());
			noc.setTotalAmount(t.getTotalAmount());
			noc.setSettlementAmount(t.getSettlementAmount());
			noc.setChangeAmount(t.getChangeAmount());
			noc.setApplicant(t.getApplicant());
			noc.setStatus(1);//订单置为正常
			noc.setProcessState(1);//流程置为营销管理员
			noc.setDepName(t.getDepName());
			OrderChangeLog ocl=new OrderChangeLog();
			ocl.setAuditor(TokenManager.getAdminId());
			ocl.setOrderNo(t.getOrderNo());
			ocl.setRemarks(startRemarks==null?"":startRemarks);
			ocl.setChangeId(noc.getId());
			ocl.setStatus(0);
			if(t.getType()!=0)chekeAmout(t);
			orderChangeLogMapper.insertSelective(ocl);
			TOrderNew ton=new TOrderNew();
			ton.setOrderNo(noc.getOrderNo());
			ton.setDeleteSign(3);
			tOrderNewMapper.updateByPrimaryKeySelective(ton);
			sendNotice(0, t);
		}else  if (changeType==2) {
			noc.setCwCost(t.getCwCost());
			noc.setRefundableAmount(t.getRefundableAmount());
		}
		if(changeType!=1)newOrderChangeMapper.updateByPrimaryKeySelective(noc);
		return 1; 
	}
	
	private void chekeAmout(NewOrderChangeBo t) {
		BigDecimal amout=t.getTotalAmount();
		List<TChangeTaskOut> list = selectChangeTask(t.getId());
		BigDecimal count=new BigDecimal(0);
		for (TChangeTaskOut tt : list) {
			if(tt.getType()!=3)count=count.add(tt.getCommodityPrice());
		}
		if (amout.compareTo(count)!=0) {
			throw new BusinessException("项目金额总和不等于合同总金额。");
		}
		List<TChangeDunOut> list2 = selectChangeDun(t.getId());
		count=new BigDecimal(0);
		for (TChangeDunOut td : list2) {
			if(td.getType()!=3)count=count.add(td.getMoney());
		}
		if (amout.compareTo(count)!=0) {
			throw new BusinessException("收款节点金额总和不等于合同总金额。");
		}
	}
	

	/**
	   *   判断变更项目是否拆分父子数量是否一直
	 * @param noc
	 */
	private void chekeChangeTaskNumber(NewOrderChange noc) {
		List<TChangeTaskOut> list=tChangeTaskMapper.selectByCid(noc.getId(),null);
		//x记录父值y记录子值
		int x=0;
		int y=0;
		
		for (TChangeTaskOut tcto : list) {
			if (tcto.getSplitStatus()==1&&tcto.getType()!=3) {
				x+=tcto.getCommodityQuantity();
			}else if (tcto.getSplitStatus()==2&&tcto.getType()!=3) {
				y+=tcto.getCommodityQuantity();
			}
		}
		if (x!=y) {
			throw new BusinessException("变更子项目与父项目数量不符");
		}
	}
	@Override
	public int addOrderRefundInvoice(OrderRefundInvoice o) {
		o.setCreateTime(new Date());
		newOrderChangeMapper.addRefundInvoice(o.getOrderNo(),o.getAmount());
		return orderRefundInvoiceMapper.insertSelective(o);
	}
	@Override
	public int deleteOrderRefundInvoice(Integer id) {
		OrderRefundInvoice or=orderRefundInvoiceMapper.selectByPrimaryKey(id);
		newOrderChangeMapper.subtractRefundInvoice(or.getOrderNo(),or.getAmount());
		return orderRefundInvoiceMapper.deleteByPrimaryKey(id);
	}
	@Override
	public List<OrderRefundInvoice> listOrderRefundInvoice(String orderNo) {
		return orderRefundInvoiceMapper.selectByorderNo(orderNo);
	}
	@Override
	public int pushCompleteOrderChange(NewOrderChangeBo nb) {
		//变更完成
		changeAdopt(nb);
		TOrderNew o=pushChange(nb);
		List<String> alist = new ArrayList<>();
		alist.add(o.getSalesmanId());
		newOrderChangeMapper.updateByPrimaryKeySelective(nb);
		orderNewService.pushGeneralSendNoticeAndEmail(alist,NoticeStatus.ORDER_CHANGE_END.getCode(), o.getOrderNo(), TokenManager.getAdminId(),0);
		return 1;
	}
	

	/**
	 * 修改订单数据
	 * @param nb
	 */
	private TOrderNew pushChange(NewOrderChangeBo nb) {
		TOrderNew o=tOrderNewMapper.selectByPrimaryKey(nb.getOrderNo());
		NewOrderChangeBo nob=newOrderChangeMapper.selectById(nb.getId());
//		变更类型 0退单退款 1项目及金额变更 2仅项目变更 3仅金额变更 4重报 5赠送
		//退单退款不需改变内容
		if (nob.getType()==OrderChangeType.XMJJEBG.getCode()) {
			o.setTotalAmount(nob.getTotalAmount());
			//处理项目及催款
			pushTaskAndDun(nob.getId(),nob.getOrderNo());
		}else if (nob.getType()==OrderChangeType.JXMBG.getCode()) {
			pushTaskAndDun(nob.getId(),nob.getOrderNo());
		}else if (nob.getType()==OrderChangeType.JJEBG.getCode()) {
			o.setTotalAmount(nob.getTotalAmount());
			pushTaskAndDun(nob.getId(),nob.getOrderNo());
		}else if (nob.getType()==OrderChangeType.CB.getCode()){
			o.setTotalAmount(nob.getTotalAmount());
			pushTaskAndDun(nob.getId(),nob.getOrderNo());
		}else if (nob.getType()==OrderChangeType.ZS.getCode()) {
			pushTaskAndDun(nob.getId(),nob.getOrderNo());
		}else if(nob.getType()==OrderChangeType.TDTK.getCode()) {
			//先将业务锁关闭
			List<String> list=tOrderTaskMapper.getLockId(nb.getOrderNo(),o.getSalesmanId(),o.getBuyerId());
			if(!list.isEmpty())userLockReleaseMapper.updateReleaseList(list);
			int i=userLockReleaseMapper.selectByUidGetCount(o.getSalesmanId(),o.getBuyerId());
			if (i<1) userLockReleaseMapper.updateReleaseUser(o.getOrderNo());
		}
		//
		List<TOrderTaskBo> taskBos=tOrderTaskMapper.selectOrderTask(nb.getOrderNo());
		int i=0;
		for (TOrderTaskBo to : taskBos) {
			if (to.getTaskStatus()>TaskState.UN_DISTRIBUTION.getCode()&&to.getTaskStatus()<TaskState.INVALID.getCode()) {
				i++;
			}
			
		}
		if (i==taskBos.size()) {
			o.setProcessStatus(ProcessStatus.YQBFPZXSGLY.getCode());
		}else if(i>0&&i<taskBos.size()){
			o.setProcessStatus(ProcessStatus.YBFPZXSGLY.getCode());
		}else if(i==0){
			o.setProcessStatus(ProcessStatus.YPZXSGLY.getCode());
		}
		o.setDeleteSign(0);
		tOrderNewMapper.updateByPrimaryKeySelective(o);
		return o; 
	}

	private void pushTaskAndDun(Integer id,String orderNo) {
		List<TChangeTaskOut> listct=tChangeTaskMapper.selectByCid(id,null);
		for (TChangeTaskOut cd : listct) {
			TOrderTask ot=new TOrderTask();
			if (cd.getType()==1) {
			ot.setOrderNo(cd.getOrderNo());
			ot.setCommodityId(cd.getCommodityId());
			ot.setOrderNo(cd.getOrderNo());
			ot.setCommodityName(cd.getCommodityName());
			ot.setCommodityPrice(cd.getCommodityPrice());
			ot.setCommodityQuantity(cd.getCommodityQuantity());
			ot.setTaskComment(cd.getTaskComment());
			ot.setMain(cd.getMain());
			ot.setTaskStatus(0);
			tOrderTaskMapper.insertSelectiveGetId(ot);
			cd.setTid(ot.getId());
			tChangeTaskMapper.updateByPrimaryKeySelective(cd);
			tChangeDunMapper.updateByCTid(cd.getId(), ot.getId());
			}else if (cd.getType()==2) {
				ot.setId(cd.getTid());
				ot.setCommodityPrice(cd.getCommodityPrice());
				ot.setCommodityQuantity(cd.getCommodityQuantity());
				tOrderTaskMapper.updateByPrimaryKeySelective(ot);
				
			}else if(cd.getType()==3) {
				tOrderTaskMapper.deleteByPrimaryKey(cd.getTid());
			}
		}
		List<TChangeDunOut> listcd=tChangeDunMapper.selectByCid(id);
		for (TChangeDunOut cd : listcd) {
			NewOrderDun nd=new NewOrderDun();
			if (cd.getType()==1) {
			nd.setOrderNo(cd.getOrderNo());
			nd.setAid(cd.getAid());
			nd.setAppropriationRatio(cd.getAppropriationRatio());
			nd.setTid(cd.getTid());
			nd.setProjectType(cd.getProjectType());
			nd.setDunType(cd.getDunType());
			nd.setMoney(cd.getMoney());
			nd.setWaitDay(cd.getWaitDay());
			nd.setStartTime(cd.getStartTime());
			nd.setEffectiveCount(cd.getEffectiveCount());
			nd.setCustomizeTime(cd.getCustomizeTime());
			nd.setCustomizeName(cd.getCustomizeName());
			if (cd.getDunType()==1) {
				nd.setStatus(1);
				nd.setStartTime(new Date());
			}
			newOrderDunMapper.insertSelective(nd);
			}else if (cd.getType()==2) {
				nd.setId(cd.getDid());
				nd.setMoney(cd.getMoney());
				newOrderDunMapper.updateByPrimaryKeySelective(nd);
			}else if(cd.getType()==3) {
				newOrderDunMapper.deleteByPrimaryKey(cd.getDid());
			}
		}
	}

	
	
	@Override
	public Map<String, Object> listOrderInvoiceAndBill(String orderNo) {
		Map<String, Object> map=new HashMap<>();
		List<BillBo>list=tOrderBillNewMapper.selectByOrderNo(orderNo);
		List<InvoiceBo>list2=tOrderInvoiceMapper.selectByOrderNo(orderNo);
		map.put("bill", list);
		map.put("invoice", list2);
		return map;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void exportMyChange(HttpServletResponse response, String userName, Integer processState, Integer timeType,
			String startTime, String endTime, String depId, String salesmanName, Integer complete,String orderNo, String contractNo,Integer type,Integer pageSize,Integer pageNo) throws IOException {
		OutputStream out = response.getOutputStream();
		List<NewOderCahngeListBo>list=(List<NewOderCahngeListBo>) selectOrderChangeList( userName,  processState, timeType, startTime, endTime,
				 depId, salesmanName, complete, orderNo,  contractNo, type, pageSize,  pageNo).getList();
		try {
    		//设计表头  String[] comment = {"合同编号","订单编号","客户名称","订单部门","订单类型","下单时间","订单状态","合同额(万元)","已付额(万元)","欠款(万元)","订单负责人","变更类型","变更审核状态","变更提交时间"}
    		String[] comment = {"合同编号","订单编号","客户名称","订单部门","订单类型","下单时间","订单状态","合同额(万元)","已付额(万元)","欠款(万元)","订单负责人","变更类型","变更审核状态","变更提交时间"};
    		String fileName ="开票变更记录表" + new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date()) + ".xls";
    		//type 0 变更
    		XSSFWorkbook wb =ExportExcelUtil.exportTemplateInfoS(comment,"开票变更记录");
    		//根据列表编写文档
    		XSSFSheet sheet =wb.getSheetAt(0);
    		for (NewOderCahngeListBo ob : (List<NewOderCahngeListBo>)list) {
    			//新增一行
    			XSSFRow r = sheet.createRow(sheet.getLastRowNum()+1);
    			for (int i = 0; i < comment.length; i++) {
    				//当前列的只
    				String o = "";
    				switch (comment[i]) {
//    				String[] comment = {"合同编号","订单编号","客户名称","订单部门","订单类型","下单时间",
//    				"订单状态","合同额(万元)","已付额(万元)","欠款(万元)","订单负责人","变更类型","变更审核状态","变更提交时间"};
    				case "合同编号": o = ob.getContractNo(); break;
    				case "订单编号": o = ob.getOrderNo().toString(); break;
    				case "客户名称": o = ob.getNickname(); break;
    				case "订单部门": o = ob.getDepName(); break;
    				case "订单类型": o = OrderType.getValueByCode(ob.getOrderType()); break;
    				case "下单时间": o = ob.getEstablishTimes(); break;
    				case "订单状态": o = OrderNewState.getValueByCode(ob.getOrderStatus()); break;
    				case "合同额(万元)": o = ob.getTotalAmount().toString(); break;
    				case "已付额(万元)": o = ob.getSettlementAmount().toString(); break;
    				case "欠款(万元)": o = ob.getArrears().toString(); break;
    				case "订单负责人": o = ob.getSalesmanName(); break;
    				case "变更类型": o = OrderChangeType.getValueByCode(ob.getType()); break;
    				case "变更审核状态": o = getProcessState(ob.getProcessState(),ob.getStatus()); break;
    				case "变更提交时间": o = ob.getCreateTimes(); break;
    				default: o = ""; break;
    				}
    				XSSFCell c = r.createCell(i);
    				c.setCellValue(o);
    			}
    		}
    		//返回名称及参数
			 response.addHeader("Content-Disposition", "attachment;filename="  + new String(fileName.getBytes(),"iso-8859-1"));  
			 response.setContentType("application/octet-stream;charset=utf-8");
    		 // 返回数据流
			 wb.write(out); 
			 out.flush();
			 out.close();
		} catch (Exception e) {
			throw new BusinessException(new Error("表格生成错误。"));
		}finally {
			out.flush(); 
			 out.close(); 
		}
	}
	
	
			public static String getProcessState(Integer processState,Integer status) {
				String str="";
				if (processState == 0) {
				      str = "营销员";
				    } else if (processState == 1) {
				      str = "营销管理员";
				    } else if (processState == 2) {
				      str = "咨询师";
				    } else if (processState == 3) {
				      str = "咨询师经理";
				    } else if (processState == 4) {
				      str = "咨询师总监";
				    } else if (processState == 5) {
				      str = "财务专员";
				    } else if (processState == 6) {
				      str = "财务总监";
				    } else if (processState == 7) {
				      str = "总裁";
				    } else if (processState == 8) {
				      str = "董事长";
				    }
					String num = "";
				    if (status == 0) {
				      num = "发起";
				    } else if (status == 1) {
				      num = "审核中";
				    } else if (status == 2) {
				      num = "通过";
				    } else if (status == 3) {
				      num = "驳回";
				      return num + "到" + str;
				    } else if (status == 4) {
				      num = "完成";
				    }
				    if (processState == 7 && status == 2) {
				      return "订单变更退票中";
				    } else if (processState == 8 && status == 2) {
				      return "订单变更退票中";
				    } else if (processState >= 7 && status == 4) {
				      return "订单变更已完成";
				    } else {
				      return str + num;
				    }
			}


			@Override
			public int addChangeTask(TChangeTask t) {
				t.setType(1);
				return tChangeTaskMapper.insertSelective(t);
			}

			@Override
			public int addChangeDun(TChangeDun d) {
				d.setAid(TokenManager.getAdminId());
				d.setType(1);
				if(d.getCustomizeTimes()!=null)d.setCustomizeTime(DateUtils.StringToDate(d.getCustomizeTimes(), AFTConstants.YYYYMMDD));
				return tChangeDunMapper.insertSelective(d);
			}

			@Override
			public int deleteChangeTask(Integer id) {
				return tChangeTaskMapper.deleteByPrimaryKey(id);
			}

			@Override
			public int deleteChangeDun(Integer id) {
				return tChangeDunMapper.deleteByPrimaryKey(id);
			}

			@Override
			public List<TChangeTaskOut> selectChangeTask(Integer cid) {
				List<TChangeTaskOut> list=tChangeTaskMapper.selectByCid(cid,3);//3设置不等于2
				for (TChangeTaskOut tChangeTaskOut : list) {
					List<TChangeTask> list2=tChangeTaskMapper.selectBySuper(tChangeTaskOut.getTid(),cid);
					tChangeTaskOut.setList(list2);
				}
				return list;
			}

			@Override
			public List<TChangeDunOut> selectChangeDun(Integer cid) {
				return tChangeDunMapper.selectByCid(cid);
			}

			@Override
			public int updateChangeTask(InputTChangeTask t) {
				//有tid是订单复制项目
				if(t.getTid()!=null) {
					//type 0正常 1新增 2修改 3删除
					TChangeTask tt=tChangeTaskMapper.selectByPrimaryKey(t.getId());
					if (t.getType()==3) {
						//删除首先将项目删除，然后将所属催款做删除
						tChangeTaskMapper.updateByTid(t.getTid(),null,tt.getCid(),3);
						if (tt.getSplitStatus()==0) {
							tChangeDunMapper.updateByTid(tt.getTid(),tt.getCid(),3);
						}else if (tt.getSplitStatus()==1) {
							//删除父类下所有的子类	
							tChangeTaskMapper.updateByTid(null,tt.getTid(),tt.getCid(),3);
							tChangeDunMapper.updateByTid(tt.getTid(),tt.getCid(),3);
						}else if(tt.getSplitStatus()==2) {
							List<TChangeTask> list=tChangeTaskMapper.selectBySuper(tt.getSplitSuper(),tt.getCid());
							boolean flag=true;
							for (TChangeTask tc : list) {
								if (tc.getType()!=3) {
									flag=false;
									break;
								}
							}
							if (flag) {
								//如果所有子类删除判断删除父类
								tChangeTaskMapper.updateByTid(tt.getSplitSuper(),null,tt.getCid(),3);
								tChangeDunMapper.updateByTid(tt.getSplitSuper(),tt.getCid(),3);
							}
						}
					}else if(t.getType()==2){
						tChangeTaskMapper.updateByTid(t.getTid(),null,tt.getCid(),2);
						if (tt.getSplitStatus()==1) {
							tChangeTaskMapper.updateByTid(null,tt.getTid(),tt.getCid(),2);
						}else if(tt.getSplitStatus()==2) {
								tChangeTaskMapper.updateByTid(tt.getSplitSuper(),null,tt.getCid(),2);
						}
					}
				}else {
					if (t.getType()==3) {
						tChangeTaskMapper.deleteByPrimaryKey(t.getId());
						tChangeDunMapper.deleteByCtid(t.getId());
					}
				}
				return tChangeTaskMapper.updateByPrimaryKeySelective(t);
			}

			@Override
			public int updateChangeDun(TChangeDun t) {
				if(t.getCustomizeTimes()!=null)t.setCustomizeTime(DateUtils.StringToDate(t.getCustomizeTimes(), AFTConstants.YYYYMMDD));
				if (t.getType()==1||t.getType()==2) {
					return tChangeDunMapper.updateByPrimaryKeySelective(t);
				}else if(t.getType()==3){
					if (t.getDid()!=null) {
						return tChangeDunMapper.updateByPrimaryKeySelective(t);	
					}else {
						return tChangeDunMapper.deleteByPrimaryKey(t.getId());
					}
					
				}else {
					return 0;
				}
				
			}

			@Override
			public List<TOrderNewBo> orderChangeUsed(String orderNo) {
				List<TOrderNewBo> list=tOrderNewMapper.selectUsedOrderByOrder(orderNo);
				for (TOrderNewBo t : list) {
					t.setDunList(newOrderDunService.selectListNewOrderDun(orderNo));
					t.setTaskList(orderNewService.selectOrderTask(orderNo));
				}
				return list;
			}

			@Override
			public List<Map<String, String>> getOrderChange(String orderNo) {
				List<Map<String, String>> list=new ArrayList<>();
				list =newOrderChangeMapper.getOrderChange(orderNo);
				return list;
			}

			@Override
			public int addOrderRefund(InputNewOrderRefund or) {
				or.setRefundTime(DateUtils.StringToDate(or.getRefundDate(), AFTConstants.YYYYMMDD));
				return newOrderRefundMapper.insertSelective(or);
			}

			@Override
			public int deleteRefund(Integer id) {
				return newOrderRefundMapper.deleteByPrimaryKey(id);
			}

			@Override
			public List<OutNewOrderRefund> listRefund(Integer id) {
				return newOrderRefundMapper.listRefund(id);
			}

			@Override
			public int pushRefund(Integer id,String refundUrl) {
				NewOrderChange noc=newOrderChangeMapper.selectByPrimaryKey(id);
				if (noc.getRefundStatus()!=1) {
					List<OutNewOrderRefund> list=listRefund(id);
					BigDecimal bd=new BigDecimal(0);
					TOrderNew order=tOrderNewMapper.selectByPrimaryKey(noc.getOrderNo());
					for (OutNewOrderRefund o : list) {
						TOrderBillNew tbn =new TOrderBillNew();
						tbn.setOrderNo(o.getOrderNo());
						tbn.setTransactionAmount(o.getRefundAmount().negate());// 取负数
						tbn.setBillNo(UUID.randomUUID().toString().replaceAll("-", ""));
						tbn.setCreater(TokenManager.getAdminId());
						tbn.setPayeeId(order.getBuyerId());
						tbn.setPayerId("0");
						tbn.setRemarks(o.getRemarks());
						tbn.setTransactionSubject(2);
						tbn.setTransactionChannel(2);
						tbn.setConfirmSign(1);
						tbn.setRefundTime(o.getRefundTime());
						bd=bd.add(o.getRefundAmount());
						tOrderBillNewMapper.insertSelective(tbn);
					}
					TOrderNew o=new TOrderNew();
					o.setOrderNo(noc.getOrderNo());
					o.setRefundAmount(bd);
					tOrderNewMapper.updaterefund(o);
					NewOrderChange n=new NewOrderChange();
					n.setId(id);
					n.setRefundStatus(1);
					n.setRefundUrl(refundUrl);
					newOrderChangeMapper.updateByPrimaryKeySelective(n);
				}
				return 1;
			}

			@Override
			public boolean checkrefund(InputNewOrderRefund or) {
				if (or.getOrderNo()!=null) {
					TOrderNew o=tOrderNewMapper.selectByPrimaryKey(or.getOrderNo());
					BigDecimal refund=new BigDecimal(0);
					List<OutNewOrderRefund> list=listRefund(or.getCid());
					refund=refund.add(or.getRefundAmount());
					for (OutNewOrderRefund oor : list) {
						refund=refund.add(oor.getRefundAmount());
					}
					if (o.getSettlementAmount().compareTo(refund)!=-1) {
						return false;
					}else {
						return true;
					}	
				}
				return true;
			}

			@Override
			public int updateCancelOrderChange(NewOrderChangeBo nb) {
				NewOrderChange noc=new NewOrderChange();
				noc.setId(nb.getId());
				noc.setStatus(5);
				newOrderChangeMapper.updateByPrimaryKeySelective(noc);
				TOrderNew t=new TOrderNew();
				t.setOrderNo(nb.getOrderNo());
				t.setDeleteSign(0);
				tOrderNewMapper.updateByPrimaryKeySelective(t);
				return 1;
			}
}
