package com.ssj.service.sys.fx.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ssj.bean.common.framework.core.domain.Response;
import com.ssj.bean.sys.fx.domain.Merchant;
import com.ssj.bean.sys.fx.domain.MerchantArea;
import com.ssj.bean.sys.organization.domain.Organization;
import com.ssj.bean.sys.role.domain.Admin;
import com.ssj.bean.weixin.libmy.domain.LibVip;
import com.ssj.bean.weixin.libmy.domain.TbLibJoin;
import com.ssj.bean.weixin.libmy.domain.TbLibJoinConsume;
import com.ssj.bean.weixin.push.domain.SendMailInfo;
import com.ssj.bean.weixin.push.domain.SendTemplateShort;
import com.ssj.bean.weixin.sales.domain.LibVipService;
import com.ssj.dao.sys.fx.dao.MerchantDao;
import com.ssj.framework.basic.utils.DateHelper;
import com.ssj.framework.basic.utils.MD5;
import com.ssj.framework.core.common.service.BaseServiceImpl;
import com.ssj.framework.core.persistence.DynamicSpecifications;
import com.ssj.framework.core.persistence.SearchFilter;
import com.ssj.framework.core.rabbitmq.TopicRabbitConfig;
import com.ssj.framework.core.rabbitmq.producer.BaseRabbitSend;
import com.ssj.framework.core.util.RedisUtil;
import com.ssj.framework.core.util.SystemResourceLocator;
import com.ssj.service.sys.fx.service.MerchantAreaService;
import com.ssj.service.sys.fx.service.MerchantMealService;
import com.ssj.service.sys.fx.service.MerchantService;
import com.ssj.service.sys.organization.service.OrganizationService;
import com.ssj.service.sys.role.service.AdminService;
import com.ssj.service.sys.role.service.RoleService;
import com.ssj.service.task.SyncRecordByMerchant;
import com.ssj.service.weixin.library.service.ILibJoinConsumeService;
import com.ssj.service.weixin.library.service.ILibJoinService;
import com.ssj.service.weixin.library.service.ILibVipService;
import com.ssj.service.weixin.problem.service.CnAreaService;
import com.ssj.service.weixin.push.service.PushTemplateService;
import com.ssj.service.weixin.sales.service.LibVipServiceService;
import com.ssj.taskthread.ThreadPool;


@Service
public class MerchantServiceImpl extends BaseServiceImpl<Merchant, String> implements MerchantService {

	
	private   Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private MerchantDao dao;

	@Autowired
	private AdminService adminService;
	
	@Autowired
	private OrganizationService organizationService;
	
	@Autowired
	private ILibVipService libVipService;
	
	@Autowired
	private LibVipServiceService libVipServiceService;
	
	@Autowired
	private ILibJoinConsumeService joinConsumeService;
	
	@Autowired
	private ILibJoinConsumeService libJoinConsumeService;
	
	@Autowired
	private ILibJoinService libJoinService;
	
    @Autowired
    private PushTemplateService pushTemplateService;
    
    @Autowired
    private MerchantAreaService merchantAreaService;
    
    @Autowired
    private MerchantMealService merchantMealService;
    
    @Autowired
    private CnAreaService cnAreaService;
    
	@Autowired
    private RoleService roleService;
    
	@Autowired
    private RedisUtil redisUtil;
	

    @Override
    public PagingAndSortingRepository<Merchant, String> getDao() {
        return dao;
    }

	@Override
	public String importMerchants(List<Merchant> list,Map<String,String> password) {
		Map<String,String> codeMap=new HashMap<String,String>();
		StringBuffer bb=new StringBuffer("");
		for (Merchant merchant : list) {
			merchant.setCreateTime(new Date());
			Admin admin=adminService.getByLoginName(merchant.getPosCode());
			if(admin!=null){//帐号存在
				bb.append("{\"error\":\"1\",\"posCode\":\""+merchant.getPosCode()+"\",\"msg\":\"帐号已存在\"}");
			}else{
				admin=new Admin();
				admin.setNickName(merchant.getPosCode());
				admin.setCreateTime(new Date());
				admin.setLoginName(merchant.getPosCode());
				admin.setPassword(MD5.getMD5(password.get(merchant.getPosCode()).getBytes()));
				admin.setStatus(1);
				adminService.save(admin);
				
			}
			Merchant oldMerchant =dao.getMerchantByPosCode(merchant.getPosCode());
			if(oldMerchant==null){
			
				//添加组织架构
				String fxcode="SSJ-FX";
				
				String code="";
				String pcode="";
				Organization org=new Organization();
				code=fxcode;
				pcode=fxcode;
				
				if(merchant.getLevel()==1){
					code=code+"-"+merchant.getPosCode();
				}else{
					if(StringUtils.isNotEmpty(merchant.getParentPosCode())){
						code=code+"-"+merchant.getParentPosCode()+"-"+merchant.getPosCode();
						pcode=pcode+"-"+merchant.getParentPosCode();
					}else{
						code=code+"-"+merchant.getPosCode();
					}
				}
				
				if(codeMap.containsKey(pcode)){
					org.setpId(codeMap.get(pcode));
				}else{
					Organization porg=organizationService.getByCode(pcode);
					org.setpId(porg.getId());
				}
				org.setCode(code);
				org.setName(merchant.getUnitName());
				org.setCreateTime(new Date());
				org.setArea("总部");
				org.setStatus(1);
				organizationService.save(org);
				codeMap.put(code, org.getId());
				
				merchant.setOrgCode(code);
				dao.save(merchant);
				
			}
		}
		return bb.toString();
	}
	

	@Override
	@Transactional
	public boolean bindingMerchantByUser(String userId, String posCode,String password) {
		boolean is=false;
		Admin admin=adminService.longin(posCode, password);
		if(admin!=null){
			Merchant merchant =dao.getMerchantByPosCode(posCode);
			merchant.setManageUserId(userId);
			dao.save(merchant);
			is=true;
		}else{
			is=false;
		}
		return is;
	}

	@Override
	public Merchant getMerchantByPosCode(String posCode) {
		return dao.getMerchantByPosCode(posCode);
	}

	@Override
	public List<Merchant> getMerchantByParentPosCode(String parentPosCode) {
		if(StringUtils.isNotEmpty(parentPosCode)) {
			return dao.getMerchantByParentPosCode(parentPosCode);
		}else {
			return new ArrayList<Merchant>();
		}
	}

	@Override
	public List<Merchant> findMerchantByPage() {
		return dao.findMerchantByPage();
	}

	@Override
	public Page<Merchant> findMerchantByPage(Map<String, Object> params,Pageable sp) {
		Map<String, SearchFilter> filters = SearchFilter.parse(params);
		Specification<Merchant> specification = DynamicSpecifications.bySearchFilter(filters.values(), Merchant.class);
		return dao.findAll(specification, sp);
	}

	@Override
	public List<Merchant> getMerchantByLikeOrgCode(String orgCode) {
		return dao.getMerchantByLikeOrgCode(orgCode);
	}
	
	
	@Override
	public void allotByMerchant(String fromMerchant, String toMerchant, Integer num,Integer type) {
	   Merchant fMerchant=this.getById(fromMerchant);
	   Merchant tMerchant=this.getById(toMerchant);
	   
	   if(type==1) {
		   if(fMerchant.getLibService()>=num) {
			   fMerchant.setLibService(fMerchant.getLibService()-num);
			   tMerchant.setLibService(tMerchant.getLibService()+num);
			   this.save(fMerchant);
			   this.save(tMerchant);
			   
			   libJoinConsumeService.allotMerchantConsume(fromMerchant, toMerchant, num, 0);
		   }
		   
	   }else if(type==2) {
		   if(fMerchant.getPlatformService()>=num) {
			   fMerchant.setPlatformService(fMerchant.getPlatformService()-num);
			   tMerchant.setPlatformService(tMerchant.getPlatformService()+num);
			   this.save(fMerchant);
			   this.save(tMerchant);
			   
			   libJoinConsumeService.allotMerchantConsume(fromMerchant, toMerchant, 0, num);
		   }
	   }
	}
	
	
	
	/**
	 * 2020年1月14日16:48:39
	 *   自营  结算扣币定时任务，00点启动
	 */
	@Override
	public void runSummaryByMerchant() {
		
		List<Merchant> merchants=dao.findMerchantByType(new int[]{1,2});//查出所以自营的商户列表
		
		for (Merchant merchant : merchants) {
			try {
				if(merchant.getPortNum()!=null && merchant.getPortNum()>0) {//是否有端口，无端口，直接跳出
					continue;
				}
				if(StringUtils.isEmpty(merchant.getLibId())) {//是否是关联了馆，不是，直接跳出
					continue;
				}
				if(!reckonGTMonth(merchant.getSignTime(), 3)) {//是否大于3个月，未大于3个月，直接跳出
					continue;
				}
				if(merchant.getCurIsSummary()!=null && merchant.getCurIsSummary()>0) {//上一次结算是否正常，正常=1，不正常0
					continue;
				}
				String libId=merchant.getLibId();
				
				//服务过期的 ：  查询所有的 “激活时间在签约时间后”   学生列表,，返回最大的结束服务时间
				List<Map<String, Object>> libVips=libVipService.findVipByLibIdMaxActivateTime(libId,merchant.getSignTime(),"S003");
				if(merchant.getLibService()<=libVips.size()) {//塾币数小于当前的过期会员数量，不做处理，直接跳出
					continue;
				}
				
				//添加服务，扣除塾币，记录消费塾币
				for (Map<String, Object> libVip : libVips) {
					String vipId=String.valueOf(libVip.get("id"));
					
					Date startTime=new Date();
					Date endTime=DateHelper.getMonthDate(startTime,1);
					LibVipService libVipService = new LibVipService();
					libVipService.setBorrowDay(0);
					libVipService.setBorrowNum(0);
					libVipService.setDeposit(0);
					libVipService.setLibId(libId);
					libVipService.setOutMoney(new BigDecimal(0));
					libVipService.setSpecies("S003");
					libVipService.setStartTime(startTime);
					libVipService.setEndTime(endTime);
					libVipService.setStat(1);
					libVipService.setType("C004");
					libVipService.setVipId(vipId);
					libVipService.setOrderDetailsId("zyb");
					libVipService.setIsJia(0);
					libVipService.setCourseCount(0);
					libVipService.setCorrectType(2);
					libVipService=libVipServiceService.save(libVipService);
					
					endTime=libVipServiceService.getEndTimeSkipHoliday(libVipService.getStartTime(), libVipService.getEndTime(), libVipService.getLibId(), 
							libVipService.getVipId(), true, libVipService.getId());
					
					libVipService.setEndTime(endTime);
					libVipServiceService.save(libVipService);
					
					
					merchant.setLibService(merchant.getLibService()-1);
					this.save(merchant);
					this.syncMerchantByLibJoin(merchant.getId());
					
					TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
					tbLibJoinConsume.setFromLibId(libId);
					tbLibJoinConsume.setFromMerchantId(merchant.getId());
					tbLibJoinConsume.setVipId(vipId);
					tbLibJoinConsume.setLibService(1);
					tbLibJoinConsume.setPlatformService(0);
					tbLibJoinConsume.setRemarks("会员服务过期，自动续费扣币");
					tbLibJoinConsume.setType(2);
					tbLibJoinConsume.setSignType(0);
					tbLibJoinConsume.setCreateTime(new Date());
					joinConsumeService.save(tbLibJoinConsume);
					
					
				}
				
			} catch (Exception e) {
				logger.error("自营  结算扣币定时任务，00点启动任务异常...");
				e.printStackTrace();
			}
			
		}
		
		
		//结算
		for (Merchant merchant : merchants) {
			try {
				if(StringUtils.isEmpty(merchant.getLibId())) {//是否是关联了馆，不是，直接跳出
					continue;
				}
				String libId=merchant.getLibId();
				
				//不足扣币的币，保留3天，第4天开始清0
				if(merchant.getCurSummaryTime()!=null && reckonEQMonth(DateHelper.getNextDay(merchant.getCurSummaryTime(), 4), new Date())) {
					if(merchant.getCurIsSummary()>0 && merchant.getLibService()>0) {
						Integer deduNum=merchant.getLibService();
						merchant.setLibService(0);
						merchant.setPortNum(0);
						merchant.setCurIsSummary(0);
						this.save(merchant);
						this.syncMerchantByLibJoin(merchant.getId());
						
						TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
						tbLibJoinConsume.setFromMerchantId(merchant.getId());
						tbLibJoinConsume.setLibService(deduNum);
						tbLibJoinConsume.setPlatformService(0);
						tbLibJoinConsume.setRemarks("统计续币不足端口数量，保留3天，过期清空币，端口也清空");
						tbLibJoinConsume.setType(3);
						tbLibJoinConsume.setCreateTime(new Date());
						joinConsumeService.save(tbLibJoinConsume);
					}
				}
				
				//当天是否是结算日，如果是直接处理结算，结算成功后，计算保存下一个结算日。
				if(reckonEQMonth(merchant.getNextSummaryTime(), new Date())) {
					//统计这个月消费了几个币，不足的端口的，扣足端口的。
					Integer consumeNum=joinConsumeService.countTbLibJoinConsumeByConsumeTime(new String[] {libId}, merchant.getCurSummaryTime(), merchant.getNextSummaryTime());
					
					if(merchant.getPortNum()>consumeNum) {
						
						//统计分配给下一级的数量,分配的不算消费
						Integer distributionNum=joinConsumeService.countTbLibJoinDistributionByConsumeTime(new String[] {libId}, merchant.getCurSummaryTime(), merchant.getNextSummaryTime());
						
						Integer deduNum=merchant.getPortNum()-consumeNum+distributionNum;
						
						if(merchant.getLibService()-deduNum>=0) {
							merchant.setLibService(merchant.getLibService()-deduNum);
							this.save(merchant);
							this.syncMerchantByLibJoin(merchant.getId());
							
							TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
							tbLibJoinConsume.setFromMerchantId(merchant.getId());
							tbLibJoinConsume.setLibService(deduNum);
							tbLibJoinConsume.setPlatformService(0);
							tbLibJoinConsume.setRemarks("统计续币不足端口数量，自动扣币");
							tbLibJoinConsume.setType(3);
							tbLibJoinConsume.setCreateTime(new Date());
							joinConsumeService.save(tbLibJoinConsume);
							merchant.setCurIsSummary(0);
						}else {
							merchant.setCurIsSummary(deduNum-merchant.getLibService());
						}
					}
				
					merchant.setCurSummaryTime(new Date());
					merchant.setNextSummaryTime(DateHelper.getMonthDate(merchant.getCurSummaryTime(),1));
					dao.save(merchant);
				}
			} catch (Exception e) {
				logger.error("自营  结算扣币定时任务，00点启动任务异常...");
				e.printStackTrace();
			}
		}
		
		
	}
	
	
	
	/**
	 * 2020年1月14日16:48:39
	 *   代理  结算扣币定时任务，00点启动
	 */
	@Override
	public void runSummaryByMerchant_Agent() {
		
		List<Merchant> merchants=dao.findMerchantByType(new int[]{3});
		
		for (Merchant merchant : merchants) {
			
			try {
				if(merchant.getPortNum()!=null && merchant.getPortNum()>0) {//是否有端口，无端口，直接跳出
					continue;
				}
				if(StringUtils.isEmpty(merchant.getLibId())) {//是否是关联了馆，不是，直接跳出
					continue;
				}
				if(!reckonGTMonth(merchant.getSignTime(), 3)) {//是否大于3个月，未大于3个月，直接跳出
					continue;
				}
				
				if(merchant.getCurIsSummary()!=null && merchant.getCurIsSummary()>0) {//上一次结算是否正常，正常==0，不正常>0
					continue;
				}
				
				String libId=merchant.getLibId();
				
				//服务过期的 ：  查询所有的 “激活时间在签约时间后”   学生列表,，返回最大的结束服务时间
				List<Map<String, Object>> libVips=libVipService.findVipByLibIdMaxActivateTime(libId,merchant.getSignTime(),"S003");
				
				Integer countNum=10;
				countNum=merchant.getLibService();
				
				//塾币数小于当前的过期会员数量，一直查询上一级塾币数，直到够数量，到第一级还是不够，直接跳出
				if(countNum<libVips.size()) {
					
					if(StringUtils.isNotEmpty(merchant.getParentPosCode())) {//上一级
						Merchant parentMerchant=this.getMerchantByPosCode(merchant.getParentPosCode());
						countNum=countNum+parentMerchant.getLibService();
						
						if(countNum<libVips.size()) {
							if(StringUtils.isNotEmpty(parentMerchant.getParentPosCode())) {//上二级
								parentMerchant=this.getMerchantByPosCode(parentMerchant.getParentPosCode());
								countNum=countNum+parentMerchant.getLibService();
								
								
								if(countNum<libVips.size()) {
									if(StringUtils.isNotEmpty(parentMerchant.getParentPosCode())) {//上三级
										parentMerchant=this.getMerchantByPosCode(parentMerchant.getParentPosCode());
										countNum=countNum+parentMerchant.getLibService();
										
									}
								}//--
								
							}
						}//--
						
					}
				}//--
				
				//全部加起来也不够，就直接跳出
				if(countNum<libVips.size()) {
					continue;
				}
				
				//添加服务，扣除塾币，记录消费塾币
				for (Map<String, Object> libVip : libVips) {
					String vipId=String.valueOf(libVip.get("id"));
					
					Date startTime=new Date();
					Date endTime=DateHelper.getMonthDate(startTime,1);
					LibVipService libVipService = new LibVipService();
					libVipService.setBorrowDay(0);
					libVipService.setBorrowNum(0);
					libVipService.setDeposit(0);
					libVipService.setLibId(libId);
					libVipService.setOutMoney(new BigDecimal(0));
					libVipService.setSpecies("S003");
					libVipService.setStartTime(startTime);
					libVipService.setEndTime(endTime);
					libVipService.setStat(1);
					libVipService.setType("C004");
					libVipService.setVipId(vipId);
					libVipService.setOrderDetailsId("zyb");
					libVipService.setIsJia(0);
					libVipService.setCourseCount(0);
					libVipService.setCorrectType(2);
					libVipService=libVipServiceService.save(libVipService);
					
					endTime=libVipServiceService.getEndTimeSkipHoliday(libVipService.getStartTime(), libVipService.getEndTime(), libVipService.getLibId(), 
							libVipService.getVipId(), true, libVipService.getId());
					
					libVipService.setEndTime(endTime);
					libVipServiceService.save(libVipService);
					
					if(merchant.getLibService()>0) {//当前商户有币，自己扣
						merchant.setLibService(merchant.getLibService()-1);
						this.save(merchant);
						this.syncMerchantByLibJoin(merchant.getId());
						
					}else {
						
						if(StringUtils.isNotEmpty(merchant.getParentPosCode())) {//上一级
							Merchant parentMerchant=this.getMerchantByPosCode(merchant.getParentPosCode());
							
							if(parentMerchant.getLibService()>0) {//当前商户有币，上一级扣
								parentMerchant.setLibService(parentMerchant.getLibService()-1);
								this.save(parentMerchant);
								this.syncMerchantByLibJoin(parentMerchant.getId());
								
								TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
								tbLibJoinConsume.setFromLibId(parentMerchant.getLibId());
								tbLibJoinConsume.setFromMerchantId(parentMerchant.getId());
								tbLibJoinConsume.setVipId(vipId);
								tbLibJoinConsume.setLibService(1);
								tbLibJoinConsume.setPlatformService(0);
								tbLibJoinConsume.setRemarks("会员服务过期，自动续费扣币，"+merchant.getUnitName()+" 商户币不足，扣上一级");
								tbLibJoinConsume.setType(2);
								tbLibJoinConsume.setSignType(0);
								tbLibJoinConsume.setCreateTime(new Date());
								joinConsumeService.save(tbLibJoinConsume);
							}else {
								
								if(StringUtils.isNotEmpty(parentMerchant.getParentPosCode())) {//上二级
									parentMerchant=this.getMerchantByPosCode(parentMerchant.getParentPosCode());
									
									if(parentMerchant.getLibService()>0) {//当前商户有币，上二级扣
										parentMerchant.setLibService(parentMerchant.getLibService()-1);
										this.save(parentMerchant);
										this.syncMerchantByLibJoin(parentMerchant.getId());
										
										TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
										tbLibJoinConsume.setFromLibId(parentMerchant.getLibId());
										tbLibJoinConsume.setFromMerchantId(parentMerchant.getId());
										tbLibJoinConsume.setVipId(vipId);
										tbLibJoinConsume.setLibService(1);
										tbLibJoinConsume.setPlatformService(0);
										tbLibJoinConsume.setRemarks("会员服务过期，自动续费扣币，"+merchant.getUnitName()+" 商户币不足，扣上二级");
										tbLibJoinConsume.setType(2);
										tbLibJoinConsume.setSignType(0);
										tbLibJoinConsume.setCreateTime(new Date());
										joinConsumeService.save(tbLibJoinConsume);
									}else {
										
										if(StringUtils.isNotEmpty(parentMerchant.getParentPosCode())) {//上三级
											parentMerchant=this.getMerchantByPosCode(merchant.getParentPosCode());
											
											if(parentMerchant.getLibService()>0) {//当前商户有币，上三级扣
												parentMerchant.setLibService(parentMerchant.getLibService()-1);
												this.save(parentMerchant);
												this.syncMerchantByLibJoin(parentMerchant.getId());
												
												TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
												tbLibJoinConsume.setFromLibId(parentMerchant.getLibId());
												tbLibJoinConsume.setFromMerchantId(parentMerchant.getId());
												tbLibJoinConsume.setVipId(vipId);
												tbLibJoinConsume.setLibService(1);
												tbLibJoinConsume.setPlatformService(0);
												tbLibJoinConsume.setRemarks("会员服务过期，自动续费扣币，"+merchant.getUnitName()+" 商户币不足，扣上三级");
												tbLibJoinConsume.setType(2);
												tbLibJoinConsume.setCreateTime(new Date());
												joinConsumeService.save(tbLibJoinConsume);
											}
	
										}
										
									}
		
								}
								
							}
							
						}
						
					}
					
					
					TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
					tbLibJoinConsume.setFromLibId(libId);
					tbLibJoinConsume.setFromMerchantId(merchant.getId());
					tbLibJoinConsume.setVipId(vipId);
					tbLibJoinConsume.setLibService(1);
					tbLibJoinConsume.setPlatformService(0);
					tbLibJoinConsume.setRemarks("会员服务过期，自动续费扣币");
					tbLibJoinConsume.setType(2);
					tbLibJoinConsume.setCreateTime(new Date());
					joinConsumeService.save(tbLibJoinConsume);
					
				}
						
			} catch (Exception e) {
				logger.error("代理  结算扣币定时任务，00点启动任务异常...");
				e.printStackTrace();
			}
			
		}
		
		//结算
		for (Merchant merchant : merchants) {
			try {
				//不足扣币的币，保留3天，第4天开始清0
				if(merchant.getCurSummaryTime()!=null && reckonEQMonth(DateHelper.getNextDay(merchant.getCurSummaryTime(), 4), new Date())) {
					if(merchant.getCurIsSummary()>0 && merchant.getLibService()>0) {
						Integer deduNum=merchant.getLibService();
						merchant.setLibService(0);
						merchant.setPortNum(0);
						merchant.setCurIsSummary(0);
						this.save(merchant);
						this.syncMerchantByLibJoin(merchant.getId());
						
						TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
						tbLibJoinConsume.setFromMerchantId(merchant.getId());
						tbLibJoinConsume.setLibService(deduNum);
						tbLibJoinConsume.setPlatformService(0);
						tbLibJoinConsume.setRemarks("统计续币不足端口数量，保留3天，过期清空币，端口也清空");
						tbLibJoinConsume.setType(3);
						tbLibJoinConsume.setCreateTime(new Date());
						joinConsumeService.save(tbLibJoinConsume);
					}
				}
				
				//当天是否是结算日，如果是直接处理结算，结算成功后，计算保存下一个结算日。
				if(reckonEQMonth(merchant.getNextSummaryTime(), new Date())) {
					List<String> libIds=new ArrayList<String>();
					if(StringUtils.isNotEmpty(merchant.getLibId())) {
						String libId=merchant.getLibId();
						libIds.add(libId);
					}else {
						//查出下一级所有的机构
						List<Merchant>  likeMerchants =this.getMerchantByLikeOrgCode(merchant.getOrgCode());
						for (Merchant likeMerchant : likeMerchants) {
							if(StringUtils.isNotEmpty(likeMerchant.getLibId())) {
								String libId=likeMerchant.getLibId();
								libIds.add(libId);
							}
						}
					}
					
					//统计这个月消费了几个币，不足的端口的，扣足端口的。
					Integer countlibJoinConsumes=0;
					Integer distributionNum=0;
					if(libIds.size()>0) {
						String[] array = new String[libIds.size()];
						countlibJoinConsumes=joinConsumeService.countTbLibJoinConsumeByConsumeTime(libIds.toArray(array), merchant.getCurSummaryTime(), merchant.getNextSummaryTime());
						//统计分配给下一级的数量,分配的不算消费
						distributionNum=joinConsumeService.countTbLibJoinDistributionByConsumeTime(libIds.toArray(array), merchant.getCurSummaryTime(), merchant.getNextSummaryTime());
					}
					
					if(merchant.getPortNum()>countlibJoinConsumes) {
						
						Integer deduNum=merchant.getPortNum()-countlibJoinConsumes+distributionNum;
						
						if(merchant.getLibService()-deduNum>=0) {
							merchant.setLibService(merchant.getLibService()-deduNum);
							this.save(merchant);
							this.syncMerchantByLibJoin(merchant.getId());
							
							TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
							tbLibJoinConsume.setFromMerchantId(merchant.getId());
							tbLibJoinConsume.setLibService(deduNum);
							tbLibJoinConsume.setPlatformService(0);
							tbLibJoinConsume.setRemarks("统计续币不足端口数量，自动扣币");
							tbLibJoinConsume.setType(3);
							tbLibJoinConsume.setCreateTime(new Date());
							joinConsumeService.save(tbLibJoinConsume);
							merchant.setCurIsSummary(0);
						}else {
							merchant.setCurIsSummary(deduNum-merchant.getLibService());
						}
					}
				
					merchant.setCurSummaryTime(new Date());
					merchant.setNextSummaryTime(DateHelper.getMonthDate(merchant.getCurSummaryTime(),1));
					this.save(merchant);
				}
			} catch (Exception e) {
				logger.error("代理  结算扣币定时任务，00点启动任务异常...");
				e.printStackTrace();
			}
		}
			
		
	}
	

	//日期加上月份，是否小于当前时间
	private static boolean reckonGTMonth(Date date,Integer monthNum) {
		if(date==null) {
			return false;
		}
		Calendar cal = Calendar.getInstance();
	    cal.setTime(date);//设置起时间
	    cal.add(Calendar.MONTH, monthNum);//增加一个月   
	    
	    if(cal.getTime().getTime()<=new Date().getTime()) {
	    	return true;
	    }
	    return false;
	}
	
	//两个时间是否是同一天
	private static boolean reckonEQMonth(Date date1,Date date2) {
		if(date1==null) {
			return false;
		}
		if(date2==null) {
			return false;
		}
		return DateUtils.isSameDay(date1, date2);
	}
	

	@Override
	public Merchant getMerchantByLibId(String libId) {
		return dao.getMerchantByLibId(libId);
	}

	
	@Override
	public void syncMerchantByLibJoin(String merchantId) {
		Merchant  merchant = this.getById(merchantId);
		if(merchant!=null && StringUtils.isNotEmpty(merchant.getLibId())) {
			TbLibJoin libJoin = libJoinService.getById(merchant.getLibId());
			libJoin.setLibService(merchant.getLibService());
			libJoin.setPlatformService(merchant.getPlatformService());
			libJoinService.save(libJoin);
		}
	}

	@Override
	public void syncLibJoinByMerchant(String libId) {
		TbLibJoin libJoin = libJoinService.getById(libId);
		if(libJoin!=null) {
			Merchant  merchant = this.getMerchantByLibId(libId);
			merchant.setLibService(libJoin.getLibService());
			merchant.setPlatformService(libJoin.getPlatformService());
			this.save(merchant);
		}
		
	}

	@Override
	public void syncRecordByMerchant(String loginName, String id,String ip,String title) {
		try {
			ThreadPool.getInstance().addTask(new SyncRecordByMerchant(loginName,id, ip, title));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//上次结算日，无法扣除的币量>=0
	@Override
	public boolean isBuckleLibServiceByLibId(String libId) {
		Merchant merchant = this.getMerchantByLibId(libId);
		if(merchant!=null && merchant.getCurIsSummary()>0) {
			return false;
		}
		return true;
	}

	
	@Override
	public List<Merchant> findMerchantByNotParent() {
		return dao.findMerchantByNotParent();
	}
	
	
//	各位老师：
//	关于代理扣币规则建议方案如下：
//	1、扣币原则：①从下级往上倒推扣减，多不退少要补；②各级扣币时间统一；
//	2、具体说明：
//	①级数限定：与旧方案一致，代理到渠道终端级数限定为3级即（市代——区代——学校独家/普通）；
//	②总有效激活期限定：从旧方案市代到学校独家/普通总有效期不超过4个月延长至5个月；
//	具体举例：
//	A市代签约1000塾币，端口800；签约日期为1.1日，则市代激活有效期为1.1——3.31为3个月，结算日为4.1日；
//	在此有效期内下发一级则结算日在原来的基础上自动延长一个月；
//	2.1日下发给B区代端口600，塾币600，则B区代激活有效期为2.1——4.30为3个月，结算日为5.1日，A市代照此日期顺延结算；
//	照此类推，下发到非代理，则
//	3.1日下发给C机构（学校独家）端口200，塾币200，，则C机构激活有效期为3.1——5.31为3个月，计算日为6.1日，A市代、B区代照此日期顺延结算；
//	6.1日结算时，A市代需要按端口数量扣减塾币800个，先从最下级扣去C机构塾币200，扣去B区代600—200=400，倒推补扣减A市代塾币200，A市代剩余塾币200。
//	若其中有一级未能往下分发，则按该级别原定结算日期扣币。
// 	下级满足扣币，上级代理不符合的情况，
	
	@Override
	public void runSummaryByMerchant_new() {
		
		//先从最下级开始结算。
		List<Merchant> merchants=this.findMerchantBySubListAndLevelNum(3);
		runBalanceMerchantByLevelNum(merchants);
		
		merchants=this.findMerchantBySubListAndLevelNum(2);
		runBalanceMerchantByLevelNum(merchants);
		
		merchants=this.findMerchantBySubListAndLevelNum(1);
		runBalanceMerchantByLevelNum(merchants);

	}
	
	//结算指定级别的商户
	private void  runBalanceMerchantByLevelNum(List<Merchant> merchants) {
		if(merchants==null) {
			return;
		}
		for (Merchant merchant : merchants) {
			
			if(merchant.getSignType()!=0) {
				continue;
			}
			//没有签约时间的,不进行结算
			if(merchant.getNextSummaryTime()==null) {
				continue;
			}
			
			//提前3天推送提醒信息
			if(reckonEQMonth(new Date(),DateHelper.getNextDay(merchant.getNextSummaryTime(), -1))) {
				if(merchant.getEndSignTime()!=null && new Date().getTime()<=merchant.getEndSignTime().getTime()) {
					runBalancePushWarn(merchant);
				}
			}
			
			//当天是否是结算日，如果是直接处理结算，结算成功后，计算保存下一个结算日。
			if(reckonEQMonth(merchant.getNextSummaryTime(), new Date())) {
				
				//上一个结算日不正常结算的，不再结算。
				if(merchant.getCurIsSummary()>0) {
					merchant.setCurSummaryTime(new Date());
					merchant.setNextSummaryTime(DateHelper.getMonthDate(merchant.getCurSummaryTime(),1));
					this.save(merchant);
					break;
				}
				
				//查出子级的所有商户
				List<String> merchantIds=new ArrayList<String>();
				List<Merchant> subMerchants=this.getMerchantByParentPosCode(merchant.getPosCode());
				for (Merchant subMerchant : subMerchants) {
					merchantIds.add(subMerchant.getId());
				}
				
				//查出自己与和直子级机构消费的币总量
				merchantIds.add(merchant.getId());
				String[] array = new String[merchantIds.size()];
				
				Integer consumeNum=joinConsumeService.countMerchantConsumeByConsumeTime(merchantIds.toArray(array),  merchant.getCurSummaryTime(), merchant.getNextSummaryTime());
				Integer libService=merchant.getLibService();//当前商户的币量
				Integer portNum=merchant.getPortNum();//当前商户端口数
				Integer needNum=portNum-consumeNum;//当前商户还需的扣币数。
				
				//机构消费的币总量>=端口，不需要再扣币,小于的话就需要扣币。
				if(needNum>0) {
					
					//商户余的币>=还需扣的币时，扣除现有的。
					if(libService>=needNum) {
						merchant.setLibService(libService-needNum);
						
						//记录扣币情况
						syncMerchantByLibJoinAndConsume(merchant, needNum, "当前商户 [ "+merchant.getUnitName()+" ] 扣币，结算日服务扣币-商户端口："+portNum+"-商户现存币数："+libService+"-商户与子级消费币数："+consumeNum+"-商户需扣币数："+needNum);
						needNum=0;
					}else {
						//不够的，先扣完自己的，再向上级扣,统一查出所有上级的列表。先从反向上开始扣，不够再向上扣。
						merchant.setLibService(libService);
						needNum=needNum-libService;
						//记录扣币情况
						syncMerchantByLibJoinAndConsume(merchant, libService, "当前商户 [ "+merchant.getUnitName()+" ] 扣币，结算日服务扣币-商户端口："+portNum+"-商户现存币数："+libService+"-商户与子级消费币数："+consumeNum+"-商户需扣币数："+needNum);

						List<Merchant> parentMerchants=new ArrayList<Merchant>();
						findParentMerchantList(parentMerchants, merchant);
						for (Merchant parentMerchant : parentMerchants) {
							
							//够扣了，跳出for,else不够扣，再向上扣。
							if(parentMerchant.getLibService()>=needNum) {
								parentMerchant.setLibService(parentMerchant.getLibService()-needNum);
								//记录扣币情况
								syncMerchantByLibJoinAndConsume(parentMerchant, needNum, "商户 [ "+merchant.getUnitName()+" ] 向上级扣币，结算日服务扣币-商户需扣币数："+needNum);
								needNum=0;
								break;
							}else {
								parentMerchant.setLibService(parentMerchant.getLibService());
								needNum=needNum-parentMerchant.getLibService();
								//记录扣币情况
								syncMerchantByLibJoinAndConsume(parentMerchant, needNum, "商户 [ "+merchant.getUnitName()+" ] 向上级扣币，结算日服务扣币-商户需扣币数："+needNum);
							}
						}
					
					}
				}
				
				//一直到最后，扣完所有上级了，needNum还是大于0,那就证明全级的币都不够扣，那就停止当前商户的服务,并且记录这次还差多少币。
				if(needNum>0) {
					merchant.setCurIsSummary(needNum);
				}

				merchant.setCurSummaryTime(new Date());
				merchant.setNextSummaryTime(DateHelper.getMonthDate(merchant.getCurSummaryTime(),1));
				this.save(merchant);
			}
			
		}
	}
	
	
	//保存扣币，并且记录扣币。
	private void syncMerchantByLibJoinAndConsume(Merchant merchant,Integer deduNum,String remarks){
		try {
			this.save(merchant);
			this.syncMerchantByLibJoin(merchant.getId());
			
			TbLibJoinConsume tbLibJoinConsume=new TbLibJoinConsume();
			tbLibJoinConsume.setFromMerchantId(merchant.getId());
			tbLibJoinConsume.setFromLibId(merchant.getLibId());
			tbLibJoinConsume.setLibService(deduNum);
			tbLibJoinConsume.setPlatformService(0);
			tbLibJoinConsume.setRemarks(remarks);
			tbLibJoinConsume.setType(3);
			tbLibJoinConsume.setSignType(0);
			tbLibJoinConsume.setCreateTime(new Date());
			joinConsumeService.save(tbLibJoinConsume);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	//查出所有上级，列表中排序返回，上级--》上上级--》上上上级--》....。直到总部的”广州指点商户“的下级为终点。
	@Override
	public void findParentMerchantList(List<Merchant> parentMerchants,Merchant merchant){
		if(merchant!=null && StringUtils.isNotEmpty(merchant.getParentPosCode())) {
			merchant=this.getMerchantByPosCode(merchant.getParentPosCode());
			if(merchant!=null && !"ssj001".equals(merchant.getPosCode())) {
				parentMerchants.add(merchant);
				this.findParentMerchantList(parentMerchants, merchant);
			}else {
				return;
			}
		}else {
			return;
		}
	}
	
	

	
	//直接查出指定下层级的所有商户
	//为了数据的完整性，还是取一次查一次数据库，保证数据各层的数据是和数据库是一致。
	private List<Merchant> findMerchantBySubListAndLevelNum(Integer levelNum){
		List<Merchant>  levelMerchants=new ArrayList<Merchant>();
		List<Merchant>  merchants=this.findMerchantBySubList();
		
		if(levelNum==1) {
			levelMerchants=merchants;
		}else if(levelNum==2) {
			for (Merchant merchant1 : merchants) {
				List<Merchant> subMerchants2=merchant1.getSubMerchants();
				levelMerchants.addAll(subMerchants2);
			}
		}else if(levelNum==3) {
			for (Merchant merchant1 : merchants) {
				List<Merchant> subMerchants2=merchant1.getSubMerchants();
				for (Merchant merchant2 : subMerchants2) {
					List<Merchant> subMerchants3=merchant2.getSubMerchants();
					levelMerchants.addAll(subMerchants3);
				}
			}
		}else if(levelNum==4) {
			for (Merchant merchant1 : merchants) {
				List<Merchant> subMerchants2=merchant1.getSubMerchants();
				for (Merchant merchant2 : subMerchants2) {
					List<Merchant> subMerchants3=merchant2.getSubMerchants();
					for (Merchant merchant3 : subMerchants3) {
						List<Merchant> subMerchants4=merchant3.getSubMerchants();
						levelMerchants.addAll(subMerchants4);
					}
				}
			}
		}
		return levelMerchants;
	}
	
	
	//查出总部下的所有商户，包含了层子级列表的数据,总共查询保留到4级商户，现需求是3级。
	//为什么要for去得到下下级呢，而不是添加层级字段呢,因为有可能商户的数据改动了，只有这样查才能100%保证商户与商户之间的层级关系。
	private List<Merchant> findMerchantBySubList() {
		//总部code
		String headPosCode="ssj001";
		
		//查出一级商户
		List<Merchant> merchants=this.getMerchantByParentPosCode(headPosCode);
		
		//查出二级商户
		for (Merchant merchant2 : merchants) {
			List<Merchant> subMerchants2=this.getMerchantByParentPosCode(merchant2.getPosCode());
			if(subMerchants2!=null) {
				merchant2.setSubMerchants(subMerchants2);
			}else {
				merchant2.setSubMerchants(new ArrayList<Merchant>());
			}
			
			//查出三级商户
			for (Merchant merchant3 : subMerchants2) {
				List<Merchant> subMerchants3=this.getMerchantByParentPosCode(merchant3.getPosCode());
				if(subMerchants3!=null) {
					merchant3.setSubMerchants(subMerchants3);
				}else {
					merchant3.setSubMerchants(new ArrayList<Merchant>());
				}
				
				
				//查出四级商户
				for (Merchant merchant4 : subMerchants3) {
					List<Merchant> subMerchants4=this.getMerchantByParentPosCode(merchant4.getPosCode());
					if(subMerchants4!=null) {
						merchant4.setSubMerchants(subMerchants4);
					}else {
						merchant4.setSubMerchants(new ArrayList<Merchant>());
					}
					
				}
			}
		}
		return merchants;
	}
	
	
	
	//结算推送提醒
	private void runBalancePushWarn(Merchant merchant) {
		try {
			Object balanceOpenIds=SystemResourceLocator.getValue("BalanceOpenID");
			if(balanceOpenIds!=null) {
				String balanceOpenId=String.valueOf(balanceOpenIds);
				if(StringUtils.isNotEmpty(balanceOpenId)) {
					Map<String, String> data=new LinkedHashMap<String, String>();
					data.put("first","您有新的商户结算提醒，请注意提醒商户充值币喔。");
		            data.put("keyword1", "商户名称_"+merchant.getUnitName());
		            data.put("keyword2", "结算日期_"+DateHelper.formatDateByFormat(merchant.getNextSummaryTime(), "yyyy-MM-dd"));
					String[] openIds=balanceOpenId.split(";");
					for (String openId : openIds) {
						try {
				            SendTemplateShort sendTemplateShort = new SendTemplateShort(openId, "OPENTM413117392", null, data);
				            pushTemplateService.saveAndSendPushWxTemplate(sendTemplateShort);
						} catch (Exception e) {
						}
					}
				}
			}
		} catch (Exception e) {
			
		}
		
		try {
			Object balanceMails=SystemResourceLocator.getValue("BalanceMails");
			if(balanceMails!=null) {
				String balanceMail=String.valueOf(balanceMails);
				if(StringUtils.isNotEmpty(balanceMail)) {
					List<String> tos=new ArrayList<String>();
					String[] mails=balanceMail.split(";");
					for (String mail : mails) {
						tos.add(mail);
					}
					SendMailInfo sendMailInfo=new SendMailInfo();
					sendMailInfo.setSubject("您有新的商户结算提醒，请注意提醒商户充值币喔。");
			        sendMailInfo.setContent("商户名称_"+merchant.getUnitName()+"    "+"结算日期_"+DateHelper.formatDateByFormat(merchant.getNextSummaryTime(), "yyyy-MM-dd"));
					sendMailInfo.setTos(tos);
			        BaseRabbitSend.convertAndTopicSend(
							TopicRabbitConfig.exchange_task,
							TopicRabbitConfig.topic_push_messages_mail, 
							sendMailInfo);
				}
			}
		} catch (Exception e) {
			
		}
	}

	
	//计算最上级的结算时间
	//如果大于等于3个月表示，是第一次结算，如果大于5个月，就不可以再添加月份，下面的商户统一和最上级的一致。
	//如果等于1个月，表示，第一次结算了，后面所有的子商户时间都定为和最上级的一致。
	@Override
	public void computeMerchantSummaryTime(Merchant merchant) {
		List<Merchant> parentMerchants=new ArrayList<Merchant>();
		this.findParentMerchantList(parentMerchants, merchant);
		Merchant maxParentMerchant=null;
		
		merchant.setCurSummaryTime(merchant.getSignTime());
		merchant.setNextSummaryTime(DateHelper.getMonthDate(merchant.getCurSummaryTime(),3));
		
		//得到最上级,如果没有，它就是最上级了。
		if(parentMerchants.size()>0) {
			maxParentMerchant=parentMerchants.get(parentMerchants.size()-1);
			
			Calendar begin = Calendar.getInstance();
			begin.setTime(maxParentMerchant.getCurSummaryTime());
			Calendar end = Calendar.getInstance();
			end.setTime(maxParentMerchant.getNextSummaryTime());
			int months=(end.get(Calendar.YEAR)-begin.get(Calendar.YEAR))*12+(end.get(Calendar.MONTH)-begin.get(Calendar.MONTH));
			
			if(months>=3 && months<5) {
				maxParentMerchant.setNextSummaryTime(DateHelper.getMonthDate(maxParentMerchant.getNextSummaryTime(),1));
				merchant.setNextSummaryTime(maxParentMerchant.getNextSummaryTime());
			}else {
				merchant.setNextSummaryTime(maxParentMerchant.getNextSummaryTime());
			}
		}
		
		this.save(merchant);
		if(maxParentMerchant!=null) {
			this.save(maxParentMerchant);
			//同步它下级所有的商户时间。
			updateSubMerchantSummaryTime(maxParentMerchant);
		}
	}

	@Override
	public void updateSubMerchantSummaryTime(Merchant merchant) {
		//查出下级商户
		List<Merchant> merchants=this.getMerchantByParentPosCode(merchant.getPosCode());
		//查出再下级商户
		for (Merchant merchant2 : merchants) {
			merchant2.setNextSummaryTime(merchant.getNextSummaryTime());
			
			List<Merchant> subMerchants2=this.getMerchantByParentPosCode(merchant2.getPosCode());
			//查出再下级商户
			for (Merchant merchant3 : subMerchants2) {
				merchant3.setNextSummaryTime(merchant.getNextSummaryTime());
				
				List<Merchant> subMerchants3=this.getMerchantByParentPosCode(merchant2.getPosCode());
				//查出再下级商户
				for (Merchant merchant4 : subMerchants3) {
					merchant4.setNextSummaryTime(merchant.getNextSummaryTime());
				}
				this.save(subMerchants3);
			}
			this.save(subMerchants2);
		}
		this.save(merchants);
	}

	@Override
	public List<Merchant> getMerchantByLikePosCode(String posCode) {
		return dao.getMerchantByLikePosCode(posCode);
	}

	@Override
	public Merchant getMerchantByVipId(String vipId) {
		return dao.getMerchantByVipId(vipId);
	}


	@Override
	public boolean unboundVipIdByLibIdToRedis(String vipId,String libId) {
		//两个月
		try {
			String key="AWARD:";
			redisUtil.set(key+vipId, libId, 5184000);
			return true;
		} catch (Exception e) {
		}
		//三个月
		try {
			String key="invalid_";
			redisUtil.set(key+vipId, String.valueOf(System.currentTimeMillis()));
			return true;
		} catch (Exception e) {
		}
		return false;
	}
	
	@Override
	public Merchant getDefaultMerchantByVipId(String vipId) {
		LibVip libVip=libVipService.getById(vipId);
		//绑定校区
		if(StringUtils.isNotEmpty(libVip.getLibId())) {
			Merchant merchant=this.getMerchantByLibId(libVip.getLibId());
			return merchant;
		}else {
			String key="AWARD:";
			//没绑定校区了，查redis厉害记录
			String libId=redisUtil.get(key+vipId);
			if(StringUtils.isNotEmpty(libId)) {
				Merchant merchant=this.getMerchantByLibId(libId);
				return merchant;
			}
		}
		return null;
	}

	@Override
	public List<Merchant> findMerchantByType(int[] type) {
		return dao.findMerchantByType(type);
	}


	@Override
	public List<Merchant> findMerchantSignBySummaryTime() {
		return dao.findMerchantSignBySummaryTime();
	}

	
	@Override
	public List<Merchant> findMerchantSignByAll() {
		return dao.findMerchantSignByAll();
	}

	@Override
	public List<Merchant> findMerchantSignByActiveTime() {
		return dao.findMerchantSignByActiveTime();
	}

	@Override
	public List<Merchant> findMerchantSignByComputeTime() {
		return dao.findMerchantSignByComputeTime();
	}

	
	//保存旧模式商户
	@Override
	@Transactional
	public Response saveMerchantByUsed(
			Merchant merchant,String startTime,String endTime,String contractTimeStr,String password,String province,String city,String area,String schoollist,String location,
			Admin curadmin) {
		
		Response response=new Response();
		
		if(StringUtils.isNotEmpty(merchant.getId())){
			
				Merchant oldmerchant =this.getById(merchant.getId());
				
				if(StringUtils.isNotEmpty(merchant.getLibId())) {
					Merchant libMerchant=this.getMerchantByLibId(merchant.getLibId());
					if(libMerchant!=null && !libMerchant.getId().equals(merchant.getId())) {
						response.failure("您选择的机构已绑定其它商户，不可重复绑定。");
				        return response;
					}
				}
				
				oldmerchant.setDeputyName(merchant.getDeputyName());
				oldmerchant.setDeputyPhone(merchant.getDeputyPhone());
				oldmerchant.setLegalPerson(merchant.getLegalPerson());
				oldmerchant.setLevel(merchant.getLevel());
				oldmerchant.setPhone(merchant.getPhone());
				oldmerchant.setPrice(merchant.getPrice());
				oldmerchant.setStatus(merchant.getStatus());
				oldmerchant.setRemarks(merchant.getRemarks());
				oldmerchant.setUnitName(merchant.getUnitName());
				oldmerchant.setType(merchant.getType());
				oldmerchant.setAddress(merchant.getAddress());
				oldmerchant.setLocation(location);
				
				oldmerchant.setSignerPerson(merchant.getSignerPerson());
				oldmerchant.setContractNo(merchant.getContractNo());
				//合同签约时间
				if(StringUtils.isNotEmpty(contractTimeStr)) {
					oldmerchant.setContractTime(DateHelper.parseDate(contractTimeStr, "yyyy-MM-dd"));
				}
				
				//删除所有关联的学校
				List<MerchantArea> merchantAreas=merchantAreaService.findSchoolByMerchantList(merchant.getId());
				for (MerchantArea merchantArea : merchantAreas) {
					merchantAreaService.delete(merchantArea);
				}
				//重新关联学校
				if(StringUtils.isNotEmpty(schoollist)) {
					merchantAreas=new ArrayList<MerchantArea>();
					String[] areaIds=schoollist.split(";");
					for (String areaId : areaIds) {
						MerchantArea merchantArea=new MerchantArea();
						merchantArea.setCnAreaId(areaId);
						merchantArea.setCreateTime(new Date());
						merchantArea.setMerchantId(merchant.getId());
						merchantArea.setSchoolName(cnAreaService.getById(areaId).getName());
						merchantAreas.add(merchantArea);
					}
					merchantAreaService.save(merchantAreas);
				}
				
				//是旧模式兼容，修改了签约的时间，重新计算结算时间
				if(oldmerchant.getSignTime()==null || DateHelper.parseDate(startTime, "yyyy-MM-dd").getTime()!=oldmerchant.getSignTime().getTime()) {
					oldmerchant.setSignTime(DateHelper.parseDate(startTime, "yyyy-MM-dd"));
					oldmerchant.setEndSignTime(DateHelper.parseDate(endTime, "yyyy-MM-dd"));
					//如果是总部直签的商户，才会更新结算日期，同时更新所有下级的结算日期
					if("ssj001".equals(oldmerchant.getParentPosCode())) {
						oldmerchant.setCurSummaryTime(oldmerchant.getSignTime());
						oldmerchant.setNextSummaryTime(DateHelper.getMonthDate(oldmerchant.getCurSummaryTime(),3));
						//计算结算日期。
						this.updateSubMerchantSummaryTime(oldmerchant);
					}
				}
		
				
				//商户同步学币/人数 到机构 / 时间
				if(StringUtils.isNotEmpty(merchant.getLibId())) {
					oldmerchant.setLibId(merchant.getLibId());
					TbLibJoin  libJoin= libJoinService.getById(oldmerchant.getLibId());
					if(libJoin!=null) {
						libJoin.setLibService(oldmerchant.getLibService());
						libJoin.setPlatformService(oldmerchant.getPlatformService());
						
						libJoin.setSignType(oldmerchant.getSignType());
						libJoin.setSignTime(oldmerchant.getSignTime());
						libJoin.setEndSignTime(oldmerchant.getEndSignTime());
						libJoinService.save(libJoin);
					}	
				}
				
				this.save(oldmerchant);
				this.syncRecordByMerchant(curadmin.getLoginName(), oldmerchant.getId(),"", "修改签约商户");
				
		}else{
				Merchant posMerchant =this.getMerchantByPosCode(merchant.getPosCode());
				if(posMerchant!=null) {
					response.failure("商户账号不得包含已经创建的商户账号，请重新填写账号。");
			        return response;
				}
				List<Merchant> posCodeMerchants=this.getMerchantByLikePosCode(merchant.getPosCode());
				if(posCodeMerchants!=null && posCodeMerchants.size()>0){
					response.failure("商户账号不得包含已经创建的商户账号，请重新填写账号。");
			        return response;
				}
				if(StringUtils.isNotEmpty(merchant.getLibId())) {
					Merchant libMerchant=this.getMerchantByLibId(merchant.getLibId());
					if(libMerchant!=null) {
						response.failure("您选择的机构已绑定其它商户，不可重复绑定。");
				        return response;
					}
				}			
				Admin admin=adminService.getByLoginName(merchant.getPosCode());
				if(admin!=null){
					response.failure("商户账号已存在");
			        return response;
				}
				merchant.setLocation(location);
				merchant.setPortNum(0);
				merchant.setLibService(0);
				merchant.setPlatformService(0);
				merchant.setHardwareService(0);
				merchant.setSignService(0);
				merchant.setHardwarePrice((double)0);
				merchant.setOutPrice((double)0);
				merchant.setCurIsSummary(0);
				
				merchant.setContractTime(startTime!=null ? DateHelper.parseDate(contractTimeStr, "yyyy-MM-dd") : null);
				merchant.setSignTime(startTime!=null ? DateHelper.parseDate(startTime, "yyyy-MM-dd"): null);
				merchant.setEndSignTime(endTime!=null ? DateHelper.parseDate(endTime, "yyyy-MM-dd"): null);
				merchant.setCreateTime(new Date());
				merchant.setSaleLoginName(curadmin.getLoginName());
				
				String code="SSJ-FX";
				if(StringUtils.isNotEmpty(merchant.getParentPosCode())){
					Merchant pMerchant =this.getMerchantByPosCode(merchant.getParentPosCode());
					code=pMerchant.getOrgCode()+"-"+merchant.getPosCode();
				}else{
					code=code+"-"+merchant.getPosCode(); 
				}
				merchant.setOrgCode(code);
				
				//添加admin用户信息
				admin=new Admin();
				admin.setLoginName(merchant.getPosCode());
				admin.setNickName(merchant.getPosCode());
				admin.setCreateTime(new Date());
				admin.setPassword(MD5.getMD5(password.getBytes()));
				admin.setStatus(1);
				admin=adminService.save(admin);
				
				//添加商户的权限
				roleService.saveAdminRole(admin.getId(), "eadc6389-6a29-4864-bce6-a18b30e0a998");
				
				//保存商户信息
				merchant=this.save(merchant);
				
				if(StringUtils.isNotEmpty(schoollist)) {
					List<MerchantArea> merchantAreas=new ArrayList<MerchantArea>();
					String[] areaIds=schoollist.split(";");
					for (String areaId : areaIds) {
						MerchantArea merchantArea=new MerchantArea();
						merchantArea.setCnAreaId(areaId);
						merchantArea.setCreateTime(new Date());
						merchantArea.setMerchantId(merchant.getId());
						merchantAreas.add(merchantArea);
					}
					merchantAreaService.save(merchantAreas);
				}
				
				//商户同步学币/人数 到机构 / 时间
				if(StringUtils.isNotEmpty(merchant.getLibId())) {
					TbLibJoin  libJoin= libJoinService.getById(merchant.getLibId());
					if(libJoin!=null) {
						libJoin.setLibService(merchant.getLibService());
						libJoin.setPlatformService(merchant.getPlatformService());
						
						libJoin.setSignType(merchant.getSignType());
						libJoin.setSignTime(merchant.getSignTime());
						libJoin.setEndSignTime(merchant.getEndSignTime());
						
						libJoinService.save(libJoin);
					}	
				}
	
				//判断的是否是旧模式兼容，修改了签约的时间，重新计算结算时间
				this.computeMerchantSummaryTime(merchant);
				this.syncRecordByMerchant(curadmin.getLoginName(), merchant.getId(),"", "新增签约商户");
					
		}
		
		response.success();
		return response;
	}

	//保存新模式商户
	@Override
	@Transactional
	public Response saveMerchantByNew(
				Merchant merchant,
				String startTime,String endTime,String startActiveTimeStr,String activeTimeStr,String computeTimeStr,String contractTimeStr,String password,String province,String city,String area,String schoollist,String location,
				Admin curadmin) {
		Response response=new Response();
		
		if(StringUtils.isNotEmpty(merchant.getId())){
				Merchant oldmerchant =this.getById(merchant.getId());
				
				if(StringUtils.isNotEmpty(merchant.getLibId())) {
					Merchant libMerchant=this.getMerchantByLibId(merchant.getLibId());
					if(libMerchant!=null && !libMerchant.getId().equals(merchant.getId())) {
						response.failure("您选择的机构已绑定其它商户，不可重复绑定。");
				        return response;
					}
				}
				
				oldmerchant.setLibId(merchant.getLibId());
				oldmerchant.setDeputyName(merchant.getDeputyName());
				oldmerchant.setDeputyPhone(merchant.getDeputyPhone());
				oldmerchant.setLegalPerson(merchant.getLegalPerson());
				oldmerchant.setLevel(merchant.getLevel());
				oldmerchant.setPhone(merchant.getPhone());
				oldmerchant.setStatus(merchant.getStatus());
				oldmerchant.setRemarks(merchant.getRemarks());
				oldmerchant.setUnitName(merchant.getUnitName());
				oldmerchant.setType(merchant.getType());
				oldmerchant.setHardwareService(merchant.getHardwareService());
				oldmerchant.setHardwarePrice(merchant.getHardwarePrice());
				oldmerchant.setAddress(merchant.getAddress());
				oldmerchant.setMealType(merchant.getMealType());
				oldmerchant.setLocation(location);
				oldmerchant.setSignerPerson(merchant.getSignerPerson());
				oldmerchant.setContractNo(merchant.getContractNo());
				
				//合同签约时间
				if(StringUtils.isNotEmpty(contractTimeStr)) {
					oldmerchant.setContractTime(DateHelper.parseDate(contractTimeStr, "yyyy-MM-dd"));
				}
				//合同日期
				if(StringUtils.isNotEmpty(startTime)) {
					oldmerchant.setSignTime(DateHelper.parseDate(startTime, "yyyy-MM-dd"));
				}
				//合同日期
				if(StringUtils.isNotEmpty(endTime)) {
					oldmerchant.setEndSignTime(DateHelper.parseDate(endTime, "yyyy-MM-dd"));
				}
				
				//激活开始日期
				if(StringUtils.isNotEmpty(startActiveTimeStr)) {
					oldmerchant.setStartActiveTime(DateHelper.parseDate(startActiveTimeStr, "yyyy-MM-dd"));
				}
				
				//激活结束日期
				if(StringUtils.isNotEmpty(activeTimeStr)) {
					oldmerchant.setActiveTime(DateHelper.parseDate(activeTimeStr, "yyyy-MM-dd"));
				}
				
				//计费开始日期也可设为空
				if(StringUtils.isNotEmpty(computeTimeStr)) {
					oldmerchant.setComputeTime(DateHelper.parseDate(computeTimeStr, "yyyy-MM-dd"));
				}else {
					oldmerchant.setComputeTime(null);
				}
				
				this.save(oldmerchant);
				
			    //重新关联学校
				if(StringUtils.isNotEmpty(schoollist)) {
					//删除所有关联的学校
					List<MerchantArea> merchantAreas=merchantAreaService.findSchoolByMerchantList(merchant.getId());
					for (MerchantArea merchantArea : merchantAreas) {
						merchantAreaService.delete(merchantArea);
					}
					merchantAreas=new ArrayList<MerchantArea>();
					String[] areaIds=schoollist.split(";");
					for (String areaId : areaIds) {
						MerchantArea merchantArea=new MerchantArea();
						merchantArea.setCnAreaId(areaId);
						merchantArea.setCreateTime(new Date());
						merchantArea.setMerchantId(merchant.getId());
						merchantArea.setSchoolName(cnAreaService.getById(areaId).getName());
						merchantAreas.add(merchantArea);
					}
					merchantAreaService.save(merchantAreas);
				}
				
				//重新同步套餐的数据信息
				if(StringUtils.isNotEmpty(oldmerchant.getLibId())) {
					merchantMealService.updateMerchantByMeal(oldmerchant.getId());
				}
				
				this.syncRecordByMerchant(curadmin.getLoginName(), oldmerchant.getId(),"", "修改套餐商户");
				
		}else{
				Merchant posMerchant =this.getMerchantByPosCode(merchant.getPosCode());
				if(posMerchant!=null) {
					response.failure("商户账号不得包含已经创建的商户账号，请重新填写账号。");
			        return response;
				}
				List<Merchant> posCodeMerchants=this.getMerchantByLikePosCode(merchant.getPosCode());
				if(posCodeMerchants!=null && posCodeMerchants.size()>0){
					response.failure("商户账号不得包含已经创建的商户账号，请重新填写账号。");
			        return response;
				}
				if(StringUtils.isNotEmpty(merchant.getLibId())) {
					Merchant libMerchant=this.getMerchantByLibId(merchant.getLibId());
					if(libMerchant!=null) {
						response.failure("您选择的机构已绑定其它商户，不可重复绑定。");
				        return response;
					}
				}			
				Admin admin=adminService.getByLoginName(merchant.getPosCode());
				if(admin!=null){
					response.failure("商户账号已存在");
			        return response;
				}
				
				merchant.setLocation(location);
				merchant.setPortNum(0);
				merchant.setPrice((double) 0);
				merchant.setOutPrice((double) 0);
				merchant.setLibService(0);
				merchant.setPlatformService(0);
				merchant.setHardwareService(0);
				merchant.setHardwarePrice((double)0);
				merchant.setCreateTime(new Date());
				merchant.setSaleLoginName(curadmin.getLoginName());
				merchant.setCurIsSummary(0);
				
				//合同签约时间
				if(StringUtils.isNotEmpty(contractTimeStr)) {
					merchant.setContractTime(DateHelper.parseDate(contractTimeStr, "yyyy-MM-dd"));
				}
				//合同开始日期
				if(StringUtils.isNotEmpty(startTime)) {
					merchant.setSignTime(DateHelper.parseDate(startTime, "yyyy-MM-dd"));
				}
				//合同结束日期
				if(StringUtils.isNotEmpty(endTime)) {
					merchant.setEndSignTime(DateHelper.parseDate(endTime, "yyyy-MM-dd"));
				}
				//激活开始日期
				if(StringUtils.isNotEmpty(startActiveTimeStr)) {
					merchant.setStartActiveTime(DateHelper.parseDate(startActiveTimeStr, "yyyy-MM-dd"));
				}
				//激活结束日期
				if(StringUtils.isNotEmpty(activeTimeStr)) {
					merchant.setActiveTime(DateHelper.parseDate(activeTimeStr, "yyyy-MM-dd"));
				}
				//计费开始日期也可设为空
				if(StringUtils.isNotEmpty(computeTimeStr)) {
					merchant.setComputeTime(DateHelper.parseDate(computeTimeStr, "yyyy-MM-dd"));
				}else {
					merchant.setComputeTime(null);
				}
				
				
				String code="SSJ-FX";
				if(StringUtils.isNotEmpty(merchant.getParentPosCode())){
					Merchant pMerchant =this.getMerchantByPosCode(merchant.getParentPosCode());
					code=pMerchant.getOrgCode()+"-"+merchant.getPosCode();
				}else{
					code=code+"-"+merchant.getPosCode(); 
				}
				merchant.setOrgCode(code);
				
				//添加admin用户信息
				admin=new Admin();
				admin.setLoginName(merchant.getPosCode());
				admin.setNickName(merchant.getPosCode());
				admin.setCreateTime(new Date());
				admin.setPassword(MD5.getMD5(password.getBytes()));
				admin.setStatus(1);
				admin=adminService.save(admin);
				
				//添加商户的权限
				roleService.saveAdminRole(admin.getId(), "eadc6389-6a29-4864-bce6-a18b30e0a998");
				
				//保存商户信息
				merchant=this.save(merchant);
				
				if(StringUtils.isNotEmpty(schoollist)) {
					List<MerchantArea> merchantAreas=new ArrayList<MerchantArea>();
					String[] areaIds=schoollist.split(";");
					for (String areaId : areaIds) {
						MerchantArea merchantArea=new MerchantArea();
						merchantArea.setCnAreaId(areaId);
						merchantArea.setCreateTime(new Date());
						merchantArea.setMerchantId(merchant.getId());
						merchantAreas.add(merchantArea);
					}
					merchantAreaService.save(merchantAreas);
				}
				
				this.syncRecordByMerchant(curadmin.getLoginName(), merchant.getId(),"", "新增套餐商户");
		}
		
		response.success();
		return response;
	}
	
	

	//保存学校模式商户
	@Override
	public Response saveMerchantByNew_Sc(Merchant merchant, String startTime, String endTime,
			String activeTimeStr, String endActiveTimeStr,String contractTimeStr, String password, String province, String city, String area,
			String schoollist, String location, Admin curadmin) {
		Response response=new Response();
		
		if(StringUtils.isNotEmpty(merchant.getId())){
			
				Merchant oldmerchant =this.getById(merchant.getId());
				
				if(StringUtils.isNotEmpty(merchant.getLibId())) {
					Merchant libMerchant=this.getMerchantByLibId(merchant.getLibId());
					if(libMerchant!=null && !libMerchant.getId().equals(merchant.getId())) {
						response.failure("您选择的机构已绑定其它商户，不可重复绑定。");
				        return response;
					}
				}
				
				oldmerchant.setLibId(merchant.getLibId());
				oldmerchant.setDeputyName(merchant.getDeputyName());
				oldmerchant.setDeputyPhone(merchant.getDeputyPhone());
				oldmerchant.setLegalPerson(merchant.getLegalPerson());
				oldmerchant.setLevel(merchant.getLevel());
				oldmerchant.setPhone(merchant.getPhone());
				oldmerchant.setStatus(merchant.getStatus());
				oldmerchant.setRemarks(merchant.getRemarks());
				oldmerchant.setUnitName(merchant.getUnitName());
				oldmerchant.setSignService(merchant.getSignService());
				oldmerchant.setType(merchant.getType());
				oldmerchant.setHardwareService(merchant.getHardwareService());
				oldmerchant.setHardwarePrice(merchant.getHardwarePrice());
				oldmerchant.setAddress(merchant.getAddress());
				oldmerchant.setMealType(merchant.getMealType());
				oldmerchant.setLocation(location);
				oldmerchant.setSignerPerson(merchant.getSignerPerson());
				oldmerchant.setContractNo(merchant.getContractNo());
				
				//合同签约时间
				if(StringUtils.isNotEmpty(contractTimeStr)) {
					oldmerchant.setContractTime(DateHelper.parseDate(contractTimeStr, "yyyy-MM-dd"));
				}
				
				//合同日期
				if(StringUtils.isNotEmpty(startTime)) {
					oldmerchant.setSignTime(DateHelper.parseDate(startTime, "yyyy-MM-dd"));
				}
				
				//合同日期
				if(StringUtils.isNotEmpty(endTime)) {
					oldmerchant.setEndSignTime(DateHelper.parseDate(endTime, "yyyy-MM-dd"));
				}
				
				this.save(oldmerchant);
				
				//重新关联学校
				if(StringUtils.isNotEmpty(schoollist)) {
					//删除所有关联的学校
					List<MerchantArea> merchantAreas=merchantAreaService.findSchoolByMerchantList(merchant.getId());
					for (MerchantArea merchantArea : merchantAreas) {
						merchantAreaService.delete(merchantArea);
					}
					merchantAreas=new ArrayList<MerchantArea>();
					String[] areaIds=schoollist.split(";");
					for (String areaId : areaIds) {
						MerchantArea merchantArea=new MerchantArea();
						merchantArea.setCnAreaId(areaId);
						merchantArea.setCreateTime(new Date());
						merchantArea.setMerchantId(merchant.getId());
						merchantArea.setSchoolName(cnAreaService.getById(areaId).getName());
						merchantAreas.add(merchantArea);
					}
					merchantAreaService.save(merchantAreas);
				}

				//同步套餐的数据信息
				if(StringUtils.isNotEmpty(oldmerchant.getLibId())) {
					merchantMealService.updateMerchantByMeal(oldmerchant.getId());
				}
				
				this.syncRecordByMerchant(curadmin.getLoginName(), oldmerchant.getId(),"", "修改套餐商户");
				
		}else{
				Merchant posMerchant =this.getMerchantByPosCode(merchant.getPosCode());
				if(posMerchant!=null) {
					response.failure("商户账号不得包含已经创建的商户账号，请重新填写账号。");
			        return response;
				}
				List<Merchant> posCodeMerchants=this.getMerchantByLikePosCode(merchant.getPosCode());
				if(posCodeMerchants!=null && posCodeMerchants.size()>0){
					response.failure("商户账号不得包含已经创建的商户账号，请重新填写账号。");
			        return response;
				}
				if(StringUtils.isNotEmpty(merchant.getLibId())) {
					Merchant libMerchant=this.getMerchantByLibId(merchant.getLibId());
					if(libMerchant!=null) {
						response.failure("您选择的机构已绑定其它商户，不可重复绑定。");
				        return response;
					}
				}			
				Admin admin=adminService.getByLoginName(merchant.getPosCode());
				if(admin!=null){
					response.failure("商户账号已存在");
			        return response;
				}
				
				merchant.setLocation(location);
				merchant.setPortNum(0);
				merchant.setLibService(0);
				merchant.setPlatformService(0);
				merchant.setCreateTime(new Date());
				merchant.setSaleLoginName(curadmin.getLoginName());
				merchant.setCurIsSummary(0);
				merchant.setPrice((double) 0);
				merchant.setOutPrice((double) 0);
				
				
				if(StringUtils.isNotEmpty(contractTimeStr)) {
					merchant.setContractTime(DateHelper.parseDate(contractTimeStr, "yyyy-MM-dd"));
				}
				
				if(StringUtils.isNotEmpty(startTime)) {
					merchant.setSignTime(DateHelper.parseDate(startTime, "yyyy-MM-dd"));
				}
				if(StringUtils.isNotEmpty(endTime)) {
					merchant.setEndSignTime(DateHelper.parseDate(endTime, "yyyy-MM-dd"));
				}
				
				String code="SSJ-FX";
				if(StringUtils.isNotEmpty(merchant.getParentPosCode())){
					Merchant pMerchant =this.getMerchantByPosCode(merchant.getParentPosCode());
					code=pMerchant.getOrgCode()+"-"+merchant.getPosCode();
				}else{
					code=code+"-"+merchant.getPosCode(); 
				}
				merchant.setOrgCode(code);
				
				//添加admin用户信息
				admin=new Admin();
				admin.setLoginName(merchant.getPosCode());
				admin.setNickName(merchant.getPosCode());
				admin.setCreateTime(new Date());
				admin.setPassword(MD5.getMD5(password.getBytes()));
				admin.setStatus(1);
				admin=adminService.save(admin);
				
				//添加商户的权限
				roleService.saveAdminRole(admin.getId(), "eadc6389-6a29-4864-bce6-a18b30e0a998");
				
				//保存商户信息
				merchant=this.save(merchant);
				
				if(StringUtils.isNotEmpty(schoollist)) {
					List<MerchantArea> merchantAreas=new ArrayList<MerchantArea>();
					String[] areaIds=schoollist.split(";");
					for (String areaId : areaIds) {
						MerchantArea merchantArea=new MerchantArea();
						merchantArea.setCnAreaId(areaId);
						merchantArea.setCreateTime(new Date());
						merchantArea.setMerchantId(merchant.getId());
						merchantAreas.add(merchantArea);
					}
					merchantAreaService.save(merchantAreas);
				}
				this.syncRecordByMerchant(curadmin.getLoginName(), merchant.getId(),"", "新增套餐商户");
		}
		
		response.success();
		return response;
	}

	@Override
	public Merchant updateMerchantByLibService(Merchant merchant) {
		
		
		
		
		
		
		return null;
	}
	
	
	
	

	

}


