package com.goafanti.order.service.impl;


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


import javax.mail.MessagingException;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
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.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.goafanti.admin.bo.AdminListBo;
import com.goafanti.common.bo.EmailBo;
import com.goafanti.common.bo.Error;
import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.constant.ErrorConstants;
import com.goafanti.common.dao.AdminMapper;
import com.goafanti.common.dao.IdleContractNoMapper;
import com.goafanti.common.dao.NewOrderDunMapper;
import com.goafanti.common.dao.NoticeMapper;
import com.goafanti.common.dao.OrganizationContactBookMapper;
import com.goafanti.common.dao.OrganizationManagementMapper;
import com.goafanti.common.dao.OutsourceLogMapper;
import com.goafanti.common.dao.PaymentNodeMapper;
import com.goafanti.common.dao.TArrearsDunMapper;
import com.goafanti.common.dao.TDunLogMapper;
import com.goafanti.common.dao.TOrderBackMapper;
import com.goafanti.common.dao.TOrderDunMapper;
import com.goafanti.common.dao.TOrderExtendMapper;
import com.goafanti.common.dao.TOrderLogMapper;
import com.goafanti.common.dao.TOrderMidMapper;
import com.goafanti.common.dao.TOrderNewMapper;
import com.goafanti.common.dao.TOrderOutsourceMapper;
import com.goafanti.common.dao.TOrderRefundMapper;
import com.goafanti.common.dao.TOrderTaskMapper;
import com.goafanti.common.dao.TTaskMidMapper;
import com.goafanti.common.dao.ThirdPartyCompanyMapper;
import com.goafanti.common.dao.UserLockReleaseMapper;
import com.goafanti.common.dao.UserMapper;
import com.goafanti.common.enums.NoticeStatus;
import com.goafanti.common.enums.OrderLogProcess;
import com.goafanti.common.error.BusinessException;
import com.goafanti.common.model.Admin;
import com.goafanti.common.model.IdleContractNo;
import com.goafanti.common.model.NewOrderDun;
import com.goafanti.common.model.Notice;
import com.goafanti.common.model.OrganizationContactBook;
import com.goafanti.common.model.OrganizationManagement;
import com.goafanti.common.model.OutsourceLog;
import com.goafanti.common.model.PaymentNode;
import com.goafanti.common.model.TArrearsDun;
import com.goafanti.common.model.TDunLog;
import com.goafanti.common.model.TOrderBack;
import com.goafanti.common.model.TOrderDun;
import com.goafanti.common.model.TOrderExtend;
import com.goafanti.common.model.TOrderLog;
import com.goafanti.common.model.TOrderMid;
import com.goafanti.common.model.TOrderNew;
import com.goafanti.common.model.TOrderNewWithBLOBs;
import com.goafanti.common.model.TOrderOutsource;
import com.goafanti.common.model.TOrderRefundWithBLOBs;
import com.goafanti.common.model.TOrderTask;
import com.goafanti.common.model.TTaskMid;
import com.goafanti.common.model.User;
import com.goafanti.common.utils.ExportExcelUtil;
import com.goafanti.common.utils.LoggerUtils;
import com.goafanti.common.utils.SendEmailUtil;
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.customer.bo.LockingReleaseBo;
import com.goafanti.order.bo.InputArrearsDunListBo;
import com.goafanti.order.bo.OrderDunTaskBo;
import com.goafanti.order.bo.OrderRefundDetailBo;
import com.goafanti.order.bo.OutArrearsDunListBo;
import com.goafanti.order.bo.OutNewOrderDunBo;
import com.goafanti.order.bo.TDunLogListBo;
import com.goafanti.order.bo.TOrderLogBo;
import com.goafanti.order.bo.TOrderNewBo;
import com.goafanti.order.bo.TOrderRefundBo;
import com.goafanti.order.bo.TOrderTaskBo;
import com.goafanti.order.bo.outOrderDunListBo;
import com.goafanti.order.enums.ActiveState;
import com.goafanti.order.enums.ApprovalNewState;
import com.goafanti.order.enums.LiquidationNewState;
import com.goafanti.order.enums.NewDunState;
import com.goafanti.order.enums.NewOrderDunType;
import com.goafanti.order.enums.OrderDunSubject;
import com.goafanti.order.enums.OrderNewState;
import com.goafanti.order.enums.ProcessStatus;
import com.goafanti.order.enums.ProjectNewStage;
import com.goafanti.order.enums.TaskState;
import com.goafanti.order.enums.refundState;
import com.goafanti.order.service.OrderNewService;
import com.goafanti.order.service.OrderService;
import com.goafanti.organization.bo.OrganizationListOut;
import com.goafanti.organization.bo.OutPaymentNode;
import com.goafanti.organization.bo.OutThirdPartyCompany;

@Service
@EnableAsync
public class OrderNewServiceImpl extends BaseMybatisDao<TOrderNewMapper> implements OrderNewService {
	@Autowired
	private TOrderNewMapper	tOrderNewMapper;
	@Autowired
	private TOrderTaskMapper tOrderTaskMapper;
	@Autowired
	private NewOrderDunMapper	newOrderDunMapper;
	@Autowired
	private TOrderDunMapper tOrderDunMapper;
	@Autowired
	private TDunLogMapper tDunLogMapper;
	@Autowired
	private TOrderMidMapper	tOrderMidMapper;
	@Autowired
	private TOrderRefundMapper	tOrderRefundMapper;	
	@Autowired
	private TOrderBackMapper	tOrderBackMapper;
	@Autowired
	private OrganizationContactBookMapper	organizationContactBookMapper;
	@Autowired
	private OrganizationManagementMapper 	organizationManagementMapper ; 
	@Autowired
	private JDBCIdGenerator	idGenerator;
	@Autowired
	private AdminMapper	adminMapper;
	@Autowired
	private TOrderLogMapper tOrderLogMapper;
	@Autowired
	private NoticeMapper	noticeMapper;
	@Autowired
	private OrderService	orderService;
	@Autowired
	private IdleContractNoMapper	idleContractNoMapper;
	@Autowired
	private TOrderOutsourceMapper tOrderOutsourceMapper;
	@Autowired
	private UserLockReleaseMapper	userLockReleaseMapper;
	@Autowired
	private TArrearsDunMapper	tArrearsDunMapper;
	@Autowired
	private TOrderExtendMapper	tOrderExtendMapper;
	@Autowired
	private UserMapper	userMapper;
	@Autowired
	private OutsourceLogMapper	outsourceLogMapper;
	@Autowired
	private PaymentNodeMapper	paymentNodeMapper;
	@Autowired
	private ThirdPartyCompanyMapper	thirdPartyCompanyMapper;
	@Autowired
	private TTaskMidMapper	tTaskMidMapper;
	@Value(value = "${mobileRemindCodeTemplate}")
	private String					mobileRemindCodeTemplate	= null;
	@Value(value = "${upload.path}")
	private String 					uploadPath 			= null;
	
	@Value(value = "${accessKey}")
	private String					accessKey			= null;

	@Value(value = "${accessSecret}")
	private String					accessSecret		= null;
	
	Logger							logger	= LoggerFactory.getLogger(OrderNewServiceImpl.class);

	
	@Override
	public int createServiceOrder(String uid, Integer orderType) {
		BigDecimal initial = new BigDecimal(0);
		TOrderNew t=new TOrderNew();
		String orderNo=idGenerator.generateId().toString();
		t.setOrderNo(orderNo);
		t.setOrderType(orderType);
		t.setOrderStatus(OrderNewState.DQD.getCode());
		t.setFirstAmount(initial);
		t.setTotalAmount(initial);
		t.setSettlementAmount(initial);
		t.setLiquidationStatus(LiquidationNewState.WAIT_PAY_FIRST_BALANCE.getCode());
		t.setProcessStatus(ProcessStatus.YPYXY.getCode());
		t.setProjectStatus(ProjectNewStage.DTJ.getCode());
		t.setApproval(ApprovalNewState.FTP.getCode());
		t.setDeleteSign(0);//0-正常，1-作废，2-锁定
		t.setSalesmanId(TokenManager.getAdminId());
		t.setCreater(TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
		t.setOrderDep(adminMapper.selectByPrimaryKey(TokenManager.getAdminId()).getDepartmentId());
		t.setCreateTime(new Date());
		t.setUpdateTime(new Date());
		t.setBuyerId(uid);
		TOrderExtend te=new TOrderExtend();
		te.setOrderNo(orderNo);
		te.setServiceStatus(0);
		tOrderExtendMapper.insertSelective(te);
		return tOrderNewMapper.insertSelective(t); 
	}



	@Override
	public int addOrderTask(TOrderTask t) {
		TOrderNew order=tOrderNewMapper.selectByPrimaryKey(t.getOrderNo());
		checkOrder(order,t);
		t.setTaskStatus(TaskState.WFP.getCode());
		t.setProjectStatus(ProjectNewStage.DTJ.getCode());
		if(t.getCommodityPrice()!=null)order.setTotalAmount(order.getTotalAmount());
		String str=tOrderTaskMapper.selectByidGetCname(t.getCommodityId());
		t.setCname(str);
		tOrderTaskMapper.insertSelectiveGetId(t);
		TTaskMid tm=new TTaskMid(t.getId(),null);
		tTaskMidMapper.insertSelective(tm);
		return 1;
	}

	public void checkOrder(TOrderNew order,TOrderTask t){
		if(order == null) 
			 throw new BusinessException(new Error(ErrorConstants.ORDER_NOT_EXIST, "" ,""));
		if(order.getDeleteSign() == ActiveState.ABOLISH.getCode())
			 throw new BusinessException(new Error(ErrorConstants.ORDER_ALREADY_FREEZE, order.getOrderNo(),""));
		if(order.getDeleteSign() == ActiveState.LOCKING.getCode())
			 throw new BusinessException(new Error(ErrorConstants.ORDER_ALREADY_REVOKE, order.getOrderNo(),""));
		List<LockingReleaseBo> list=userLockReleaseMapper.checkTask(order.getBuyerId(),t.getCommodityId());
		if (list.size()>0) {
			for (LockingReleaseBo lockingReleaseBo : list) {
				System.out.println(lockingReleaseBo.getAid() +"======="+order.getSalesmanId());
				if (!lockingReleaseBo.getAid().equals(order.getSalesmanId())) {
					throw new BusinessException(new Error( "该业务已经被其他人锁定","该业务已经被其他人锁定"));
				}
			}
			
		}
		
	}


	@Override
	public int updateOrderTask(TOrderTask t) {
		return tOrderTaskMapper.updateByPrimaryKeySelective(t);
	}



	@Override
	public int delectOrderTask(Integer id) {
		//连带催款一起删除
		newOrderDunMapper.deleteByTid(id);
		return tOrderTaskMapper.deleteByPrimaryKey(id);
	}



	@Override
	public List<TOrderTaskBo> selectOrderTask(String orderNo) {
		List<TOrderTaskBo> list=tOrderTaskMapper.selectOrderTask(orderNo);
			for (TOrderTaskBo t : list) {
				if (TokenManager.hasRole(AFTConstants.SALESMAN)) {
				t.setOutsourceName("****");
				t.setOutsourcePrice(new BigDecimal(0));
				t.setDeclareUser("****");
				t.setDeclarePwd("****");
				t.setCertificateNumber("****");
				}
				if (TokenManager.hasRole(AFTConstants.TECH)) {
					//设置隐藏金额
					t.setCommodityPrice(new BigDecimal(-1));
					}
		}
		return list;
	}





	@Override
	public int updateServiceOrder(TOrderNewWithBLOBs t, Integer isSubmit) {
		TOrderNew t2=tOrderNewMapper.selectByPrimaryKey(t.getOrderNo());
		//判断手机号码是否存在
		if (StringUtils.isNotBlank(t.getContacts())&&StringUtils.isNotBlank(t.getContactMobile())&&
				organizationContactBookMapper.checkContacts(t2.getBuyerId(), t2.getContactMobile(),TokenManager.getAdminId()==null?"1":TokenManager.getAdminId() )>0) {
			OrganizationContactBook contactBook=new OrganizationContactBook();
			contactBook.setId(UUID.randomUUID().toString());
			contactBook.setAid(TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
			contactBook.setUid(t2.getBuyerId());
			contactBook.setName(t.getContacts());
			contactBook.setMobile(t.getContactMobile());
			organizationContactBookMapper.insertSelective(contactBook);
		}
		if (StringUtils.isBlank(t.getOrderDep())) {
			t.setOrderDep(adminMapper.selectByPrimaryKey(TokenManager.getAdminId()).getDepartmentId());
		}
		if (isSubmit==1) {//订单提交
			if(t2.getProcessStatus()<ProcessStatus.YPYXGLY.getCode()) {
				t.setOrderStatus(OrderNewState.QDDS.getCode());
				t.setProcessStatus(ProcessStatus.YPYXGLY.getCode());
			}else {
				t.setOrderStatus(OrderNewState.QDSHTG.getCode());
			}
			if (t2.getApproval()==ApprovalNewState.BH.getCode()){
				t.setApproval(ApprovalNewState.DSH.getCode());
			}
			//生成流转
			TOrderLog tl=new TOrderLog();
			tl.setOrderNo(t.getOrderNo());
			tl.setProcess(OrderLogProcess.TJ.getCode());
			tl.setAid(TokenManager.getAdminId());
			addOrderLog(tl,null);
			if (StringUtils.isBlank(t2.getContractNo())) {
				//没有合同编号则生成
				createContractNo(t);
			}else if(!t.getOrderDep().equals(t2.getOrderDep())) {
				contractNoReplace(t.getOrderNo(), t2.getContractNo(),t2.getOrderDep());
				createContractNo(t);
			}
			//修改订单中间表信息
			t.setBuyerId(t2.getBuyerId());
			updateOrderMid(t);
			List<String> aids = new ArrayList<>();
			Integer type=null;
			AdminListBo a = adminMapper.getDeptNameByAid(TokenManager.getAdminId());
			aids.addAll(adminMapper.listNameByDepAndName(a.getDepartmentId(), "营销管理员"));
			type=NoticeStatus.ORDER_START.getCode();
			pushGeneralSendNoticeAndEmail(aids, type,t2.getOrderNo(), TokenManager.getAdminId(),t.getApproval());
		}
		if (t2.getApproval()==ApprovalNewState.BH.getCode()||
				t2.getOrderStatus()==OrderNewState.QDSHJJ.getCode()||
					t2.getOrderStatus()==OrderNewState.YBH.getCode()) {
			t.setCreateTime(new Date());
			tOrderBackMapper.updateByOrderNoAndBackStatus(t.getOrderNo());
		}
		// 0 相等
		// -1 小于 
		// 1 大于
		//liquidation_status 清算状态 0-首付待付请，1-尾款待付清，2-已付请，3-部分退款，4-全部退款
		//settlement_amount 已付  total_amount 总价格   first_amount首付
		if(t2.getLiquidationStatus()!=LiquidationNewState.FULL_REFUND.getCode()) {
			if(t2.getSettlementAmount().compareTo(t.getTotalAmount()) == 0){//如果已付等于总价
				t.setLiquidationStatus(LiquidationNewState.ALREADY_PAY.getCode());
			}else if(t2.getSettlementAmount().compareTo(t.getFirstAmount()) >= 0){//如果大于等于首付
				t.setLiquidationStatus(LiquidationNewState.WAIT_PAY_LAST_BALANCE.getCode());
			} else if(t2.getSettlementAmount().compareTo(t.getFirstAmount()) < 0){//如果小于首付
				t.setLiquidationStatus(LiquidationNewState.WAIT_PAY_FIRST_BALANCE.getCode());
			}
			
		}
		return tOrderNewMapper.updateByPrimaryKeySelective(t);
	}


	private void updateOrderMid(TOrderNew t) {
		TOrderMid tm=tOrderMidMapper.selectByOrderNo(t.getOrderNo());
		Admin admin=adminMapper.selectFinanceAdminByOrderDep(t.getOrderDep());
		Admin a=adminMapper.selectAllByid(TokenManager.getAdminId());
		User u=userMapper.selectByPrimaryKey(t.getBuyerId());
		if (tm==null) tm=new TOrderMid();
			tm.setOrderNo(t.getOrderNo());
		if (u!=null&&u.getNickname()!=null) {
			tm.setBuyerName(u.getNickname());
		}
		if (admin!=null&&admin.getName()!=null) {
			tm.setFinanceId(admin.getId());
			tm.setFinanceName(admin.getName());
		}
		if(a.getId()!=null&&a.getName()!=null) {
			tm.setSalesmanId(a.getId());
			tm.setSalesmanName(a.getName());
		}
		tm.setDepName(tOrderMidMapper.selectDepNameByDepid(t.getOrderDep()));
		if (tm.getId()!=null) {
			tOrderMidMapper.updateByPrimaryKeySelective(tm);
		}else {
			tOrderMidMapper.insertSelective(tm);
		}
		
	}



	/**
	 * 		新建合同编号，优先获取闲置合同编号，否则按年份生成编号
	 * @param t
	 */
	private void createContractNo(TOrderNew t) {
		//根据订单部门或许合同编号前缀
		OrganizationManagement dep=organizationManagementMapper.selectByPrimaryKey(t.getOrderDep());
		//获取日期年份
		Calendar c=Calendar.getInstance();
		int y=c.get(Calendar.YEAR);
		if (dep==null||StringUtils.isBlank(dep.getAbbreviation())) {
			throw new BusinessException(new Error( "该部门缩写不存在","该部门缩写不存在"));
		}
		IdleContractNo i=idleContractNoMapper.selectByAbbreviation(dep.getAbbreviation(),y);
		if (i!=null&&i.getContractNo()!=null) {
			t.setContractNo(i.getContractNo());
			idleContractNoMapper.deleteByPrimaryKey(i.getId());
		}else {
			//根据前缀查询最大编号
			String max=organizationManagementMapper.getMaxAbbreviation(dep.getAbbreviation()+"-");
			
			String sno=null;
			if (StringUtils.isBlank(max)||max.length()<13) {
				String cn=""+dep.getAbbreviation()+"-"+y+"0001";
				cn=iterationNo(cn,dep.getAbbreviation(),y,1);
				t.setContractNo(cn);
			}else {
				int ty=Integer.parseInt(max.substring(max.indexOf("-")+1, max.length()-4));
				int no=Integer.parseInt(max.substring(max.length()-4, max.length()));
				
				//得出字符串
				sno = countNo(dep.getAbbreviation(), sno, ty, no);
				//迭代得出最后编码
				sno=iterationNo(sno,dep.getAbbreviation(),ty,no);
				//年份小于等于则获取最大值加1，大于则获取最新年份
				if (y<=ty) {
					t.setContractNo(sno);
				}else {
					t.setContractNo(""+dep.getAbbreviation()+"-"+y+"0001");
				}
			}
		}
	}
		
	
	

	private String iterationNo(String sno ,Object mp, int ty, int no) {
		if (tOrderNewMapper.checkContractNo(sno)>0) {
			int i=Integer.parseInt(sno.substring(sno.indexOf("-")+5, sno.length()));
			sno=countNo(mp, sno, ty, i);
			sno=iterationNo(sno,mp,ty,i);
		}
		return sno;
	}



	private String countNo(Object object, String sno, int ty, int no) {
		no++;
		if (no>0&&no<10) {
			sno=object+"-"+ty+"000"+no;
		}else if (no>9&&no<100) {
			sno=object+"-"+ty+"00"+no;
		} else if (no>99&&no<1000) {
			sno=object+"-"+ty+"0"+no;
		} else if(no>1000){
			sno=object+"-"+ty+no;
		}
		return sno;
	}
	

	public void addOrderLog(TOrderLog tl, String reason) {
		tl.setAid(TokenManager.getAdminId());
		if(reason!=null)tl.setRemarks(reason);
		tOrderLogMapper.insertSelective(tl);
		
	}



	@Override
	public TOrderNewBo getOrderNewDetail(String orderNo) {
		TOrderNewBo tOrder= tOrderNewMapper.getOrderNewDetail(orderNo);
		return tOrder;
	}



	@Override
	public int createOrderDun(String orderDun,String orderNo) {
		List<TOrderDun> l=  JSON.parseArray(orderDun, TOrderDun.class);
		List<TOrderDun> l2=tOrderDunMapper.selectByOrderNoDunSubject(orderNo);
		if (l!=null&&!l.isEmpty()) {
			for (TOrderDun t : l) {
				if (t.getId()==null||t.getId().equals("")) {//Id为空新增
					if (tOrderDunMapper.checkOrderDun(t.getDunSubject(),orderNo)>0) {
						throw new BusinessException(new Error( "该截点已经存在","该截点已经存在"));
					}
					t.setId(UUID.randomUUID().toString());
					t.setDunBy(TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
					t.setDunStatus(0);//未启动
					tOrderDunMapper.insertSelective(t);
				}else {
					tOrderDunMapper.updateByPrimaryKeySelective(t);
				}
				
			}
		}
		boolean flag=true;
		for (TOrderDun t2 : l2) {
			if (l.isEmpty()) {
				tOrderDunMapper.deleteByPrimaryKey(t2.getId());
			}else {
				for (TOrderDun t : l) {
					if (t2.getId().equals(t.getId())) {//查询集合与返回集合比较查出删除项
						flag=false;
					}
				}
				if (t2.getId()!=null&&flag) {
					tOrderDunMapper.deleteByPrimaryKey(t2.getId());
				}
				flag=true;
			}
			
		}
		return 1;
	}



	@SuppressWarnings("unchecked")
	@Override
	public Pagination<TOrderNewBo> orderNewList(String name, String orderNo, String starTime, String endTime,Integer specially,Integer approval,
			Integer distribution,String depId,String contractNo,Integer outsource,Integer liquidationStatus, Integer amountStatus, Integer pageNo, Integer pageSize) {
		Map<String, Object> params = new HashMap<String, Object>();
		if(pageSize==null||pageSize<0)pageSize=10;
		if(pageNo==null||pageNo<0)pageNo=1;
		if (specially!=null&&(specially==0||specially==1||specially==2||specially==4||specially==5)) {
			//0 个人 1 营销员管理 2 驳回 3 特批 4 咨询师管理 5部门订单查询
			if (specially!=3&&specially!=4) {
				params.put("aid", TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
			}
			//（咨询师管理列表 0 未分配 1部分   2全部）
			if(specially==4) params.put("distribution",distribution);
			// 计算出所有本部门及所属部门的ID
			if(specially==1||specially==5) params.put("deps", orderService.selectMyDeps());
		}
			params.put("specially",specially);
		if (StringUtils.isNotBlank(name)) params.put("name", name);
		if (StringUtils.isNotBlank(depId)) params.put("depId", depId);
		if (StringUtils.isNotBlank(contractNo)) params.put("contractNo", contractNo);
		if (null!=liquidationStatus) params.put("liquidationStatus", liquidationStatus);
		if (null !=approval)params.put("approval", approval);
		if(null != amountStatus) params.put("amountStatus", amountStatus);
		if (StringUtils.isNotBlank(orderNo)) params.put("orderNo", orderNo);
		if (StringUtils.isNotBlank(starTime)) params.put("starTime", starTime);
		if (StringUtils.isNotBlank(endTime)) params.put("endTime", endTime+" 23:59:59");
		params.put("outsource", outsource);
		Pagination<TOrderNewBo> p = (Pagination<TOrderNewBo>)findPage("selectOrderNewListByPage", "selectOrderNewListCount", params, pageNo, pageSize);
		return p;
	}

	

	@Override
	public int updateOrderNew(String orderNo, Integer orderStatus,String reason,Integer outsource, TOrderOutsource o) {
		TOrderNew t= new TOrderNew();
		TOrderNew t2= checkDeleteSign(orderNo);
		t.setOrderNo(orderNo);
		List<String> aids = new ArrayList<>();
		Integer type=null;
		TOrderLog tl=new TOrderLog();
		tl.setAid(TokenManager.getAdminId());
		if (orderStatus==OrderNewState.QDSHTG.getCode()) {
			t.setOutsource(outsource);
			//外包单给外包审核员 否则给财务专员
				if(outsource==0) {
					t.setProcessStatus(ProcessStatus.YPCWZY.getCode());
					//如果是转的暂时不删除外包信息
					aids.add(organizationManagementMapper.selectByPrimaryKey(t2.getOrderDep()).getFinanceId());
				} else if(outsource==1) {
					for (Admin admin : adminMapper.getAdminRoleList("外包审核员")) {
						aids.add(admin.getId());
					}
					t.setProcessStatus(ProcessStatus.YPWBSH.getCode());
					tl.setOrderNo(orderNo);
					tl.setProcess(OrderLogProcess.FQWB.getCode());
					addOrderLog(tl,reason);
					
				}
			
			type=NoticeStatus.ORDER_YES.getCode();
			tl.setOrderNo(orderNo);
			tl.setProcess(OrderLogProcess.SH.getCode());
			//增加日志
			addOrderLog(tl,reason);
			//非特批增加催款信息
			//外包
			 if(outsource==1) {
				 o.setRefundStatus(0);
				if(o.getId()==null) {
				o.setCreateTime(new Date());
				tOrderOutsourceMapper.insertSelective(o);
				}else {
				tOrderOutsourceMapper.updateByPrimaryKeySelective(o);
				}
				//修改项目为外包项目
				tOrderTaskMapper.updateByOutsourceToOrderNo(orderNo,1);
			}
//			pushOrderDun(t2);
		}else if (orderStatus==OrderNewState.QDSHJJ.getCode()) {//如果不通过新增驳回
				if (outsource==0) {//非外包
				t.setProcessStatus(ProcessStatus.YPYXY.getCode());
				addBackOrder(orderNo, reason);
			}
				aids.add(t2.getSalesmanId());
				type=NoticeStatus.ORDER_NO.getCode();
		}
		t.setOrderStatus(orderStatus);
		tOrderNewMapper.updateByPrimaryKeySelective(t);
		if (aids.isEmpty()) {
			throw new BusinessException(new Error( "邮件发送失败，对方设置邮箱错误","邮件发送失败，对方设置邮箱错误")); 
		}
		pushGeneralSendNoticeAndEmail(aids, type,t2.getOrderNo(), TokenManager.getAdminId(),t2.getApproval());
		return 1; 
	}



	public void pushOrderDun(String orderNo) {
			List<OutNewOrderDunBo> list=newOrderDunMapper.selectListNewOrderDun(orderNo,null,0);
			for (OutNewOrderDunBo o : list) {
				if (o.getDunType()==1) {	
					o.setStatus(1);
					o.setStartTime(new Date());
					newOrderDunMapper.updateByPrimaryKeySelective(o);
					tOrderMidMapper.addOrderReceivables(o.getOrderNo(),o.getMoney());
					TOrderMid tm=tOrderMidMapper.selectByOrderNo(orderNo);
						TArrearsDun t=new TArrearsDun();
						t.setOrderArrears(tm.getOrderArrears());
						t.setOrderReceivables(tm.getOrderReceivables());
						if (tArrearsDunMapper.checkOrderNo(orderNo,null)<1) {
							t.setOrderNo(orderNo);
							tArrearsDunMapper.insertSelective(t);
						}else if(tArrearsDunMapper.checkOrderNo(orderNo,0)>0){
							Integer i=tArrearsDunMapper.selectByStatus(orderNo, 0);
							t.setId(i);
							tArrearsDunMapper.updateByPrimaryKeySelective(t);
						}
					addNewDunNoticAndSendEmail(orderNo,o);
				}
			}
	}



	public void addNewDunNoticAndSendEmail(String  orderNo, OutNewOrderDunBo o) {
		AdminListBo a = adminMapper.getDeptNameByAid(TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
		TOrderNewBo b  = tOrderNewMapper.getSaleIdByOno(orderNo);
		addNotic(orderNo,NoticeStatus.ORDER_DUN.getCode(),a, b);
		try {
			NewDunsendEmail(orderNo,o.getId(), a, b);
		} catch (UnsupportedEncodingException | MessagingException e) {
			throw new BusinessException(new Error("邮件发送错误。"));
		}
	}
	public void addTimingTaskNewDunNoticAndSendEmail(TOrderNew t2, OutNewOrderDunBo o) {
		AdminListBo a = adminMapper.getDeptNameByAid("1");
		TOrderNewBo b  = tOrderNewMapper.getSaleIdByOno(t2.getOrderNo());
		addNotic(t2.getOrderNo(),NoticeStatus.ORDER_DUN.getCode(),a, b);
		try {
			NewDunsendEmail(t2.getOrderNo(),o.getId(), a, b);
		} catch (UnsupportedEncodingException | MessagingException e) {
			throw new BusinessException(new Error("邮件发送错误。"));
		}
	}
	
	
	public void  NewDunsendEmail(String orderNo,Integer dunId,AdminListBo a,TOrderNewBo b) throws UnsupportedEncodingException, MessagingException{
		LoggerUtils.debug(logger, "======================邮件信息发送===================");
		NewOrderDun ob=newOrderDunMapper.selectByPrimaryKey(dunId);
		AdminListBo a2 = adminMapper.getDeptNameByAid(b.getSalesmanId());
		String dunTypeName="";
		if(ob.getDunType()!=null&&ob.getProjectType()!=null&&ob.getDunType()!=0) {
			dunTypeName= NewOrderDunType.getValueByCode(Integer.valueOf(""+ob.getProjectType()+ob.getDunType()));
		}else if(ob.getDunType()!=null&&ob.getProjectType()!=null&&ob.getDunType()==0){
			dunTypeName= NewOrderDunType.getValueByCode(Integer.valueOf(""+ob.getProjectType()+ob.getDunType()))+ob.getCustomizeName();
		}
			//发送驳回邮件
		if(SendEmailUtil.isEmail(b.getEmail())) {
	    	 EmailBo bo = new EmailBo("催收通知", b.getEmail(), a.getDepartmentName(), a.getName(),
						"", orderNo,new SimpleDateFormat("yyyy-MM-dd").format(ob.getCreateTime()),dunTypeName,a2.getName(),b.getUserName(),1,0);
				if(StringUtils.isNotBlank(b.getEmail())) {
					SendEmailUtil.getInstance().patentSend(bo);
				}
				LoggerUtils.debug(logger, "=========================================发送邮件成功"); 
	     }
			

	}

	private void addBackOrder(String orderNo, String reason) {
		TOrderBack ob=new TOrderBack();
		TOrderNew tOrder= tOrderNewMapper.selectByPrimaryKey(orderNo);
		ob.setCreateTime(new Date());
		ob.setOrderNo(orderNo);
		ob.setReason(reason);
		ob.setBackStatus(0);//待处理
		ob.setInitiate(TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
		ob.setAccept(tOrder.getSalesmanId());
		TOrderLog tl=new TOrderLog();
		tl.setOrderNo(orderNo);
		tl.setProcess(OrderLogProcess.BH.getCode());
		addOrderLog(tl,reason);
		tOrderBackMapper.insertSelective(ob);
	}


	@SuppressWarnings("unchecked")
	@Override
	public Pagination<outOrderDunListBo> dunOrderNewList(String name, String orderNo, String starTime, String endTime,
			Integer specially, String adminName,String depId,Integer newStatus,Integer pageNo, Integer pageSize) {
		Map<String, Object> params = new HashMap<String, Object>();
		if(pageSize==null||pageSize<0)pageSize=10;
		if(pageNo==null||pageNo<0)pageNo=1;
		if(newStatus!=null&&newStatus==0)params.put("newStatus", 0);
		else params.put("newStatus", tOrderDunMapper.selectByOrderNo(orderNo).isEmpty()?1:0);
		if (StringUtils.isNotBlank(name)) params.put("name", name);
		if (StringUtils.isNotBlank(depId)) params.put("depId", depId);
		if (StringUtils.isNotBlank(adminName)) params.put("adminName", adminName);
		if (StringUtils.isNotBlank(orderNo)) params.put("orderNo", orderNo);
		if (StringUtils.isNotBlank(starTime)) params.put("starTime", starTime);
		if (StringUtils.isNotBlank(endTime)) params.put("endTime", endTime+" 23:59:59");
		Integer i=null;
		if(TokenManager.hasRole(AFTConstants.SALESMAN)) {
			params.put("aid", TokenManager.getAdminId());
		} else if (TokenManager.hasRole(AFTConstants.FINANCE)) {
			i=1;
			params.put("fid", TokenManager.getAdminId());
		}else if (TokenManager.hasRole(AFTConstants.FINANCE_MANAGER)) {
			i=2;
			params.put("fid", TokenManager.getAdminId());
		}
		if (TokenManager.hasRole(AFTConstants.FINANCE_ADMIN)||TokenManager.hasRole(AFTConstants.VICE_CEO)||
				TokenManager.hasRole(AFTConstants.SUPERADMIN)||TokenManager.hasRole(AFTConstants.CED)||
				TokenManager.hasRole(AFTConstants.APPROVAL_DECISION))i=3;
		if(i!=null)params.put("shiroType", i);
		Pagination<outOrderDunListBo> p = (Pagination<outOrderDunListBo>)findPage("selectDunOrderNewListByPage", "selectDunOrderNewListCount", params, pageNo, pageSize);
		return p;
	}



	@Override
	public int createDunLog(String dunId,String dumTime,String remarks) {
		TDunLog d=new TDunLog();
		d.setId(UUID.randomUUID().toString());
		d.setDunId(dunId);
		d.setDumBy(TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			d.setDumTime(sdf.parse(dumTime));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		d.setRemarks(remarks);
		return tDunLogMapper.insertSelective(d);
	}



	@Override
	public List<TDunLogListBo> selectDunLogList(String dunId) {
		return tDunLogMapper.selectByDunId(dunId);
	}



	@Override
	public int addOrderRefund(TOrderRefundWithBLOBs t) {
		TOrderNew order =checkDeleteSign(t.getOrderNo());
		if(order.getDeleteSign()!=0)throw new BusinessException(new Error( "订单变更锁定中","订单变更锁定中"));
		t.setRefundStatus(refundState.DSH.getCode());
		t.setCreateTime(new Date());
		t.setInitiate(TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
		//t.setAccept("1");
		t.setAccept(order.getFinanceId());
		t.setResult("");
		TOrderNew tOrder=new TOrderNew(); 
		tOrder.setOrderNo(t.getOrderNo());
		tOrder.setOrderStatus(OrderNewState.TDZ.getCode());
		tOrderNewMapper.updateByPrimaryKeySelective(tOrder);
		TOrderLog tl=new TOrderLog();
		tl.setOrderNo(t.getOrderNo());
		tl.setProcess(OrderLogProcess.FQTD.getCode());
		addOrderLog(tl,null);
		return tOrderRefundMapper.insertSelective(t);
	}



	@Override
	public int updateApprovalOrder(String orderNo,Integer confirm,String reason) {
		TOrderNew t=new TOrderNew();
		TOrderNew t2=checkDeleteSign(orderNo);
		t.setOrderNo(orderNo);
		List<String> aids = new ArrayList<>();
		Integer type=null;
		TOrderLog tl=new TOrderLog();
		tl.setOrderNo(orderNo);
		if (confirm==2) {
			t.setApproval(2);
				t.setProcessStatus(ProcessStatus.YPZXSGLY.getCode());
				OrganizationListOut oo=organizationManagementMapper.selectAllById(t2.getOrderDep());
				t.setFinanceId(oo.getFinanceId());
				for (Admin admin : adminMapper.getAdminRoleList("咨询师管理员")) {
					aids.add(admin.getId());
				}
			type=NoticeStatus.ORDER_APPROVA_YES.getCode();
			tl.setProcess(OrderLogProcess.TP.getCode());
		} else {
			t.setApproval(3);
			t.setOrderStatus(OrderNewState.YBH.getCode());
			t.setProcessStatus(ProcessStatus.YPYXY.getCode());
			addBackOrder(orderNo, reason);
			tl.setProcess(OrderLogProcess.BH.getCode());
			aids.add(t2.getSalesmanId());
			type=NoticeStatus.ORDER_APPROVA_NO.getCode();
		}
		addOrderLog(tl,reason);
		pushGeneralSendNoticeAndEmail(aids, type,t2.getOrderNo(), TokenManager.getAdminId(),t2.getApproval());
		//新增特批催款信息
		
		return tOrderNewMapper.updateByPrimaryKeySelective(t);
	}



	@Override
	public List<TOrderDun> selectOrderDun(String orderNo) {
		return tOrderDunMapper.selectByOrderNoDunSubject(orderNo);
	}



	@Override
	public boolean checkOrderMain(TOrderTask t) {
		List<TOrderTaskBo> list=tOrderTaskMapper.selectOrderTask(t.getOrderNo());
		int flag=0;
		if(t.getMain()==1)flag++;
		for (TOrderTask t2 : list) {
			if(t2.getMain()==1&&t.getId()==null) {
				flag++;
			}else if (t2.getMain()==1&&(!t.getId().equals(t2.getId()))) {
				flag++;
			}
		}
		if (flag>1) {
			return true;
		}
		return false;
	}



	@Override
	public boolean chekeOrderStatus(String orderNo) {
		TOrderNew tOrder= tOrderNewMapper.selectByPrimaryKey(orderNo);
		if (tOrder.getOrderStatus()==OrderNewState.QDDS.getCode()||tOrder.getOrderStatus()==OrderNewState.QDSHTG.getCode()) {
			return false;
		}
		return true;
	}



	@Override
	public boolean chekeApprovalOrderStatus(String orderNo) {
		TOrderNew tOrder= tOrderNewMapper.selectByPrimaryKey(orderNo);
		if (tOrder.getApproval()==ApprovalNewState.FTP.getCode()||
				tOrder.getOrderStatus()==OrderNewState.QDSHJJ.getCode()||
					tOrder.getOrderStatus()==OrderNewState.YBH.getCode()) {
			return true;
		}
		return false;
	}



	@Override
	public int deleteOrderNew(String orderNo) {
		TOrderNew t=tOrderNewMapper.selectByPrimaryKey(orderNo);
		if (t.getOrderStatus()==OrderNewState.YBH.getCode()||t.getOrderStatus()==OrderNewState.YTD.getCode()||
				t.getOrderStatus()==OrderNewState.DQD.getCode()||t.getOrderStatus()==OrderNewState.QDSHJJ.getCode()) {
			t.setOrderNo(orderNo);
			t.setDeleteSign(1);//作废
			contractNoReplace(orderNo, t.getContractNo(),t.getOrderDep());
			t.setContractNo("");
			return tOrderNewMapper.updateByPrimaryKeySelective(t);
		}
		return -1;
	}


	/**
	 *  	将合同编号置为闲置编号
	 * @param orderNo
	 * @param t
	 */
	private void contractNoReplace(String orderNo, String  contractNo,String orderDep) {
		Calendar c=Calendar.getInstance();
		int y=c.get(Calendar.YEAR);
		String ys="-"+y;
		//判断编号是否类似‘-2019’，是则为有效编号
		if (contractNo.contains(ys)) {
			IdleContractNo i=new IdleContractNo();
			i.setAid(TokenManager.getAdminId());
			i.setContractNo(contractNo);
			i.setUsedOrderNo(orderNo);
			i.setYear(y);
			//如果找不到订单部门，则取订单编号-前面的缩写
			if(StringUtils.isNotBlank(orderDep)) {
				OrganizationManagement o=organizationManagementMapper.selectByPrimaryKey(orderDep);
				i.setAbbreviation(o.getAbbreviation());
			}else {
				i.setAbbreviation(contractNo.substring(0, contractNo.indexOf("-")));
			}
			idleContractNoMapper.insertSelective(i);
		}
	}

	@Override
	public boolean checkOderSettlementAmount(String orderNo) {
		TOrderNew tOrder= tOrderNewMapper.selectByPrimaryKey(orderNo);
		if (tOrder.getSettlementAmount()==null||
				tOrder.getSettlementAmount().doubleValue()==0||
					tOrder.getOrderStatus()==OrderNewState.TDZ.getCode()){
				return true;
		}
		return false;
	}


	@SuppressWarnings("unchecked")
	@Override
	public Pagination<TOrderRefundBo> orderRefundList(String name, String orderNo, String starTime, String endTime, Integer specially,
			Integer pageNo, Integer pageSize) {
			Map<String, Object> params = new HashMap<String, Object>();
			if(pageSize==null||pageSize<0)pageSize=10;
			if(pageNo==null||pageNo<0)pageNo=1;
			params.put("aid", TokenManager.getAdminId()==null?"1":TokenManager.getAdminId());
			if (StringUtils.isNotBlank(name)) params.put("name", name);
			if (StringUtils.isNotBlank(orderNo)) params.put("orderNo", orderNo);
			if (StringUtils.isNotBlank(starTime)) params.put("starTime", starTime);
			if (StringUtils.isNotBlank(endTime)) params.put("endTime", endTime+" 23:59:59");
			Pagination<TOrderRefundBo> p = (Pagination<TOrderRefundBo>)findPage("selectOrderRefundListByPage", "selectOrderRefundListCount", params, pageNo, pageSize);
			return p;
		
	}



	@Override
	public boolean checkORderTask(String orderNo) {
		List<TOrderTaskBo> list=tOrderTaskMapper.selectOrderTask(orderNo);
		for (TOrderTaskBo t : list) {
			if (t.getMain()==1) {
				return false;
			}
		}
		return true;
	}
	@Override
	public boolean checkORderDun(String orderNo) {
		List<OutNewOrderDunBo> list=newOrderDunMapper.selectListNewOrderDun(orderNo, null, null);
		if (list==null||list.size()<1) {
			return true;
		}else {
			return false;
		}
		
	}
	


	/**
	 * 获取催款数据
	 * @throws IOException 
	 */
	@Override
	public void exportOrderDunData(String name,String orderNo,String starTime,String endTime,Integer specially,String adminName,
			String depId,Integer newStatus,Integer pageNo,Integer pageSize,HttpServletResponse response) throws Exception  {
		OutputStream out = response.getOutputStream();
		try {
			@SuppressWarnings("unchecked")
			List<outOrderDunListBo> list=(List<outOrderDunListBo>) dunOrderNewList( name,  orderNo,  starTime,  endTime,
					 specially,  adminName, depId,newStatus, pageNo,  pageSize).getList();
			
    		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);
    		System.out.println(list.get(0).getAccountsReceivable());
    		for (outOrderDunListBo ob : list) {
    			//新增一行
    			XSSFRow r = sheet.createRow(sheet.getLastRowNum()+1);
    			for (int i = 0; i < comment.length; i++) {
    				//当前列的只
    				String o = "";
    				switch (comment[i]) {
//    "合同编号","订单编号","客户名称","订单负责人","订单部门","订单状态","项目负责人","签单金额","结算状态","已收款","应收款","项目状态","催收科目","催款启动时间"
    				case "合同编号": o = ob.getContractNo(); break;
    				case "订单编号": o = ob.getOrderNo().toString(); break;
    				case "客户名称": o = ob.getUserName(); break;
    				case "订单负责人": o = ob.getSalesmanName(); break;
    				case "订单部门": o = ob.getDepName(); break;
    				case "订单状态": o = OrderNewState.getValueByCode(ob.getOrderStatus());break;
    				case "签单金额": o = ob.getTotalAmount().toString(); break;
    				case "结算状态": o = LiquidationNewState.getValueByCode(ob.getLiquidationStatus()); break;
    				case "应收款": o = ob.getAccountsReceivable().toString(); break;
    				case "已收款": o = ob.getSettlementAmount().toString(); break;
    				case "未收款": o = ob.getUncollectedAmount().toString(); break;
    				case "项目状态": o = ProjectNewStage.getValueByCode(ob.getProjectStatus()); break;
    				case "催收科目": o = ob.getDunSubject(); break;
    				case "催款状态": o = ob.getDunStatus()==0?"未启动":"已启动"; break;
    				case "催款启动时间": o = ob.getStartDate(); break;
    				case "签单时间": o = ob.getSignDate(); 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(); 
		}
		
	}



	@Override
	public int updateOrderOver(String orderNo) {
		TOrderNew t=tOrderNewMapper.selectByPrimaryKey(orderNo);
		if (t.getLiquidationStatus()!=LiquidationNewState.ALREADY_PAY.getCode()||
				t.getProcessStatus()!=ProcessStatus.YQBFPZXSGLY.getCode()) {
			return -1;
		}
		List<TOrderTaskBo> list=tOrderTaskMapper.selectOrderTask(orderNo);
		for (TOrderTaskBo task : list) {
			if (task.getTaskStatus()!=TaskState.CLYWC.getCode()) {
				return -1;
			}
		}
		t.setOrderStatus(OrderNewState.YJX.getCode());
		t.setSettlementTime(new Date());
		return tOrderNewMapper.updateByPrimaryKeySelective(t);
	}
	
	@Override
	public OrderRefundDetailBo orderRefundDetail(String id) {
		return tOrderNewMapper.orderRefundDetail(id);
	}



	@Override
	public int updateOrderRefund(TOrderRefundWithBLOBs t) {
		checkDeleteSign(t.getOrderNo());
		return tOrderRefundMapper.updateByPrimaryKeySelective(t);
	}



	@Override
	public int updatetechnicianBackOrder(String orderNo,String reason) {
		TOrderNew t = checkDeleteSign(orderNo);
		if (t.getSettlementAmount().compareTo(new BigDecimal(0))!=0) {
			return -1;
		}
		t.setOrderStatus(OrderNewState.YBH.getCode());
		t.setProcessStatus(ProcessStatus.YPYXY.getCode());
		t.setFinanceId("");
		addBackOrder(orderNo, reason);
		List<String> aids = new ArrayList<>();
		aids.add(t.getSalesmanId());
		pushGeneralSendNoticeAndEmail(aids, NoticeStatus.ORDER_NO.getCode(),t.getOrderNo(), TokenManager.getAdminId(),t.getApproval());
		return tOrderNewMapper.updateByPrimaryKeySelective(t);
	}



	private TOrderNew checkDeleteSign(String orderNo) {
		TOrderNew t=tOrderNewMapper.selectByPrimaryKey(orderNo);
		//if(t.getDeleteSign()==2) throw new BusinessException(new Error(ErrorConstants.ORDER_ALREADY_REVOKE, t.getOrderNo(),""));
		return t;
	}
	
	@Override
	public List<OrderDunTaskBo> selectAllOrderDun() {
		return tOrderDunMapper.getTaskAllOrderDun();
	}



	@Override
	public void updateOrderDun(TOrderDun tDun) {
		 tOrderDunMapper.updateByPrimaryKeySelective(tDun);
	}
	


	
	
	@Override
	public void addNoticAndSendEmail(String orderNo,OrderDunTaskBo t,Integer type)
			throws UnsupportedEncodingException, MessagingException {
		TOrderNewBo b  = tOrderNewMapper.getSaleIdByOno(type==NoticeStatus.ORDER_DUN.getCode()?t.getOrderNo():orderNo);
		 String id="1";
		if (type==NoticeStatus.ORDER_DUN.getCode())  id=b.getSalesmanId();
		if (type==NoticeStatus.ORDER_BACK.getCode())  id=TokenManager.getAdminId()==null?"1":TokenManager.getAdminId();
		if (type==NoticeStatus.ORDER_APPROVA_NO.getCode())  id=TokenManager.getAdminId()==null?"1":TokenManager.getAdminId();
		AdminListBo a = adminMapper.getDeptNameByAid(id);
		 sendEmail(type==NoticeStatus.ORDER_DUN.getCode()?t.getOrderNo():orderNo, t==null?null:t.getId(), a, b);
		 
		 addNotic(type==NoticeStatus.ORDER_DUN.getCode()?t.getOrderNo():orderNo,type,a, b);
	}
	public void addNotic(String orderNo,Integer type,AdminListBo a,TOrderNewBo b) {
		String str=NoticeStatus.getValueByCode(type)+": 订单编号 -"+orderNo+"， 操作人:"+a.getDepartmentName()+"-"+a.getName()+"。";
		Notice n =new Notice();
		n.setId(UUID.randomUUID().toString());
		n.setAid(b.getSalesmanId());
		n.setNoticeType(type);
		n.setContent(str);
		n.setReaded(0);//未读
		noticeMapper.insertSelective(n);
	}
	public void  sendEmail(String orderNo,String dunId,AdminListBo a,TOrderNewBo b) throws UnsupportedEncodingException, MessagingException{
		LoggerUtils.debug(logger, "======================邮件信息发送===================");
		String content = "<div>客户名称: "+ b.getUserName() +"</div><div>订单编号: " + orderNo + "</div>";
		String tite="订单驳回";
			if(StringUtils.isNotBlank(dunId)) {
				TOrderDun tDun=tOrderDunMapper.selectByPrimaryKey(dunId);
				content +="<div>催收时间: " +  new SimpleDateFormat("yyyy-MM-dd").format(tDun.getCreateTime()) +
						"</div><div>催收科目: " + OrderDunSubject.getValueByCode(tDun.getDunSubject()) +
						"</div><div>催收情况: " + (tDun.getDunStatus()==2?"已完成":"已启动") +"</div>";
				tite="催收通知";
			}
			//发送驳回邮件
			EmailBo bo = new EmailBo(tite, b.getEmail(), b.getSalesmanName(), a.getDepartmentName(), a.getName(), content);
			if(StringUtils.isNotBlank(b.getEmail())) {
				SendEmailUtil.getInstance().send(bo);
			}
			LoggerUtils.debug(logger, "=========================================发送邮件成功");
	}


	@Override
	public int updateFinance(String orderNo, String newFinance) {
		String aid=TokenManager.getAdminId();
			String[] l=orderNo.split(",");
			List<String> orderNos=new ArrayList<>(Arrays.asList(l));
			tOrderNewMapper.updateFinance(aid,orderNos,newFinance);
			return 1;
		
	}
	



	@Override
	public List<TOrderLogBo> selectOrderLog(String orderNo) {
		return tOrderLogMapper.selectOrderByNo(orderNo);
	}

	


    @Async
	public  void pushGeneralSendNoticeAndEmail(List<String> alist, Integer type,String orderNo,String adminId,Integer approval) {
    	
		AdminListBo a = adminMapper.getDeptNameByAid(adminId);
		String approvalType="";
		if (approval!=ApprovalNewState.FTP.getCode()) approvalType="[特批]";
		String str=approvalType+NoticeStatus.getValueByCode(type)+": 订单编号 -"+orderNo+"， 操作人:"+a.getDepartmentName()+"-"+a.getName()+"。";
		String adminIds="";
		List<Notice> nlist=new  ArrayList<>();
		for (String string : alist) {
			Notice n =new Notice();
			n.setId(UUID.randomUUID().toString());
			n.setNoticeType(type);
			n.setContent(str);
			n.setCreateTime(new Date());
			n.setReaded(0);//未读
			n.setAid(string);
			nlist.add(n);
			Admin admin = adminMapper.selectAllByid(string);
			if(admin!=null&&SendEmailUtil.isEmail(admin.getEmail().trim()))adminIds+=admin.getEmail()+",";
		}
		noticeMapper.insertBatch(nlist);
		if (!nlist.isEmpty()&&StringUtils.isNotBlank(adminIds)) {
			adminIds=adminIds.substring(0, adminIds.length()-1);
			EmailBo bo = new EmailBo(NoticeStatus.getValueByCode(type), adminIds, a.getDepartmentName(), a.getName(), "请登录查看"
					,null,null,null,null,null,0,approval);
			try {
				//使用专利邮件模板
				SendEmailUtil.getInstance().patentSend(bo);
			} catch (UnsupportedEncodingException | MessagingException e) {
				throw new BusinessException(new Error( "邮件发送错误","邮件发送错误"));
			}
		}
	}
    



	@Override
	public void exportOrderTaskData(String orderNo, HttpServletResponse response) throws IOException,BusinessException {
		OutputStream out = response.getOutputStream();
		try {
			List<TOrderTaskBo> list=selectOrderTask(orderNo);
    		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 (TOrderTaskBo ob : list) {
    			//新增一行
    			XSSFRow r = sheet.createRow(sheet.getLastRowNum()+1);
    			for (int i = 0; i < comment.length; i++) {
    				//当前列的只
    				String o = "";
    				switch (comment[i]) {
//    "合同编号","订单编号","客户名称","订单负责人","订单部门","订单状态","项目负责人","是否主项目","项目别类","项目名称","项目数量",
//    				"服务市价","证书編号","项目状态","项目说明"
    				case "合同编号": o = ob.getContractNo(); break;
    				case "订单编号": o = ob.getOrderNo().toString(); break;
    				case "客户名称": o = ob.getUserName(); break;
    				case "订单负责人": o = ob.getSalesmanName(); break;
    				case "订单部门": o = ob.getDepName(); break;
    				case "订单状态": o = OrderNewState.getValueByCode(ob.getOrderStatus());break;
    				case "项目负责人": o = ob.getSalesmanName(); break;
    				case "是否主项目": o = ob.getMain()==0?"否":"是"; break;
    				case "项目别类": o = ob.getCname(); break;
    				case "项目名称": o = ob.getCommodityName(); break;
    				case "项目数量": o = ob.getCommodityQuantity().toString(); break;
    				case "服务市价": o = ob.getCommodityPrice()!=null?ob.getCommodityPrice().toString():""; break;
    				case "证书編号": o = ob.getCertificateNumber(); break;
    				case "项目状态": o = ProjectNewStage.getValueByCode(ob.getProjectStatus()); break;
    				case "项目说明": o = ob.getTaskComment(); break;
    				case "外包（内部）公司": o = ob.getOutsourceName(); break;
    				case "外包（内部）价格": o = ob.getOutsourcePrice()!=null?ob.getOutsourcePrice().toString():""; 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(); 
		}
		
	
		
	}



	@Override
	public int pushOutsourceProjectAudit(TOrderOutsource o) {
		o.setRefundStatus(0);
		o.setCreateTime(new Date());
		if(o.getAmount()==null)o.setAmount(new BigDecimal(0));
		if(o.getStartType()==null)o.setStartType(0);
		if (o.getStartType()==0) {
			List<String> aids = new ArrayList<>();
			for (Admin admin : adminMapper.getAdminRoleList("外包审核员")) {
				aids.add(admin.getId());
			}
			TOrderNew t2= checkDeleteSign(o.getOrderNo());
			Admin a =adminMapper.selectByPrimaryKey(TokenManager.getAdminId());
			OutsourceLog ol=new OutsourceLog(o.getTid(),0,o.getReason(), TokenManager.getAdminId(),a.getName());
			outsourceLogMapper.insertSelective(ol);
			pushGeneralSendNoticeAndEmail(aids, NoticeStatus.PROJECT_OUTSOURCE_START.getCode(),o.getOrderNo(), TokenManager.getAdminId(),t2.getApproval());
		}
		List<OutPaymentNode> list=paymentNodeMapper.selectByStatus(0);
		for (OutPaymentNode outPaymentNode : list) {
			if (outPaymentNode.getDunType()==1) {
				PaymentNode pn=new PaymentNode();
				pn.setId(outPaymentNode.getId());
				pn.setDunStatus(1);
				paymentNodeMapper.updateByPrimaryKeySelective(pn);
			}
		}
		if (o.getStartType()==1) {//供应商无需审核
			o.setRefundStatus(1);
		}
		if (o.getId()==null) {
			 tOrderOutsourceMapper.insertSelective(o);
		}else {
			tOrderOutsourceMapper.updateByPrimaryKeySelective(o);
			//旧项目变更，如果驳回修改成新的项目变更
			if(o.getUnitNumber()!=null)tOrderOutsourceMapper.updateByidNull(o.getId());
		}
		updateOrderCostAmount(o.getTid(),o.getStartType(),o.getActualOfficial());
		return 1;
	}

	/**
	 * 发起外包时，通过计算获取项目的成本，订单的成本
	 * @param tid
	 */
	private void updateOrderCostAmount(Integer tid,Integer startType,Integer actualOfficial) {
		//计算项目成本
		List<OutThirdPartyCompany>list=thirdPartyCompanyMapper.selectByTid(tid);
		BigDecimal tCount=new BigDecimal(0);
		for (OutThirdPartyCompany op : list) {
			tCount=tCount.add(new BigDecimal(op.getTotalAmount()));
			if(op.getOfficialCost()==1 && startType==1 && actualOfficial==0) {
				BigDecimal sum= new BigDecimal(0);
				if (op.getCostReduction()==0) {
					sum= new BigDecimal(op.getOfficialUnitPrice()).multiply(new BigDecimal(op.getQuantity()));
					tCount=tCount.add(sum);
				}else if (op.getCostReduction()==1) {
					sum= new BigDecimal(op.getReductionAmount()).multiply(new BigDecimal(op.getQuantity()));
					tCount=tCount.add(sum);
				}
			}
		}
		tTaskMidMapper.updateCostAmount(tid,tCount);
		//计算订单成本
		BigDecimal oCount=new BigDecimal(0);
		List <TTaskMid> tlist=tTaskMidMapper.selectByTid(tid);
		for (TTaskMid tm : tlist) {
			if (tm!=null&&tm.getCostAmount()!=null)oCount=oCount.add(tm.getCostAmount()==null?new BigDecimal(0):tm.getCostAmount());
		}
		tOrderMidMapper.updateCostAmount(tid,oCount);
	}

	@SuppressWarnings("unchecked")
	@Override
	public Pagination<OutArrearsDunListBo> arrearsDunList(InputArrearsDunListBo in) {

		Map<String, Object> params = new HashMap<String, Object>();
		if(in.getPageSize()==null||in.getPageSize()<0)in.setPageSize(10);
		if(in.getPageNo()==null||in.getPageNo()<0)in.setPageNo(1);
		if (StringUtils.isNotBlank(in.getName())) params.put("name", in.getName());
		if (StringUtils.isNotBlank(in.getDepId())) params.put("depId", in.getDepId());
		if (StringUtils.isNotBlank(in.getAdminName())) params.put("adminName", in.getAdminName());
		if (StringUtils.isNotBlank(in.getOrderNo())) params.put("orderNo", in.getOrderNo());
		if (StringUtils.isNotBlank(in.getStarTime())) params.put("starTime", in.getStarTime());
		if (StringUtils.isNotBlank(in.getEndTime())) params.put("endTime", in.getEndTime()+" 23:59:59");
		if (StringUtils.isNotBlank(in.gettStarTime())) params.put("tStarTime", in.gettStarTime());
		if (StringUtils.isNotBlank(in.gettEndTime())) params.put("tEndTime", in.gettEndTime()+" 23:59:59");
		Integer i=null;
		if(TokenManager.hasRole(AFTConstants.SALESMAN)) {
			params.put("aid", TokenManager.getAdminId());
		} else if (TokenManager.hasRole(AFTConstants.FINANCE)) {
			i=1;
			params.put("fid", TokenManager.getAdminId());
		}else if (TokenManager.hasRole(AFTConstants.FINANCE_MANAGER)) {
			i=2;
			params.put("fid", TokenManager.getAdminId());
		}
		if (TokenManager.hasRole(AFTConstants.FINANCE_ADMIN)||TokenManager.hasRole(AFTConstants.VICE_CEO)||
				TokenManager.hasRole(AFTConstants.SUPERADMIN)||TokenManager.hasRole(AFTConstants.CED)||
				TokenManager.hasRole(AFTConstants.APPROVAL_DECISION))i=3;
		if(i!=null)params.put("shiroType", i);
		Pagination<OutArrearsDunListBo> p = (Pagination<OutArrearsDunListBo>)findPage("selectArrearsDunListByPage", "selectArrearsDunListByCount", params, in.getPageNo(), in.getPageSize());
		return p;
	}



	@SuppressWarnings("unchecked")
	@Override
	public void exportArrearsDunListData(InputArrearsDunListBo in, HttpServletResponse response) throws IOException {
		OutputStream out = response.getOutputStream();
		try {
			List<OutArrearsDunListBo> list=(List<OutArrearsDunListBo>) arrearsDunList(in).getList();
    		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 (OutArrearsDunListBo ob : list) {
    			//新增一行
    			XSSFRow r = sheet.createRow(sheet.getLastRowNum()+1);
    			for (int i = 0; i < comment.length; i++) {
    				//当前列的只
    				String o = "";
    				switch (comment[i]) {
//    "合同编号","订单编号","客户名称","订单负责人","订单部门","订单状态","项目状态","签单金额（万元）","已收款（万元）
//    				","结算状态","催收科目","欠款催收","催款状态","催款启动时间",
    				case "合同编号": o = ob.getContractNo(); break;
    				case "订单编号": o = ob.getOrderNo().toString(); break;
    				case "客户名称": o = ob.getUserName(); break;
    				case "订单负责人": o = ob.getSalesmanName(); break;
    				case "订单部门": o = ob.getDepName(); break;
    				case "订单状态": o = OrderNewState.getValueByCode(ob.getOrderStatus());break;
    				case "项目状态": o = ProjectNewStage.getValueByCode(ob.getOrderStatus());break;
    				case "签单金额（万元）": o = ob.getTotalAmount().toString();break;
    				case "已收款（万元）": o = ob.getSettlementAmount().toString();break;
    				case "结算状态": o = LiquidationNewState.getValueByCode(ob.getLiquidationStatus());break;
    				case "催收科目": o = ob.getType()==0?"按时触发应收款":"未知";break;
    				case "欠款催收": o = ob.getOrderArrears().toString();break;
    				case "催款状态": o = NewDunState.getValueByCode(ob.getDunStatus());break;
    				case "催款启动时间": o = ob.getStartDate();break;
    				case "下单时间": o = ob.getSignDate();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(); 
		}
		
	
		
	}



	@Override
	public int checkOutAudit(Integer id) {
		List<OutThirdPartyCompany> list=thirdPartyCompanyMapper.selectByTid(id);
		if (list.isEmpty())return 1;
//		OrderOutsourceDtails o=tOrderOutsourceMapper.selectByOrderNo(null,String.valueOf(id));
//		if (o==null)return 2;
		return 0;
	}




	
}
