/**
 * Copyright &copy; 2012-2014 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.cku.oa.finance.service;

import static com.cku.oa.statistics.strategy.InitSplitStrategy.PAYMENT_TYPE_CAB;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.cku.oa.handler.dao.HandlerRegisterDao;
import com.cku.oa.handler.entity.HandlerRegister;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.cku.config.WxPayConfig;
import com.cku.core.ZAErrorCode;
import com.cku.core.ZAException;
import com.cku.logUtil.JSONObjectUtils;
import com.cku.oa.dog.dao.DogActivationDao;
import com.cku.oa.dog.dao.DogAppraisalDao;
import com.cku.oa.dog.dao.DogBirthCertificateDao;
import com.cku.oa.dog.dao.DogBloodSaveDao;
import com.cku.oa.dog.dao.DogChipDao;
import com.cku.oa.dog.dao.DogDnaArchiveDao;
import com.cku.oa.dog.dao.DogNewbornDao;
import com.cku.oa.dog.dao.DogPedigreeCertifiedRedoDao;
import com.cku.oa.dog.dao.DogSecondBreederDao;
import com.cku.oa.dog.dao.DogVideoAppraisalDao;
import com.cku.oa.dog.entity.DogActivation;
import com.cku.oa.dog.entity.DogAppraisal;
import com.cku.oa.dog.entity.DogBirthCertificate;
import com.cku.oa.dog.entity.DogBloodSave;
import com.cku.oa.dog.entity.DogChip;
import com.cku.oa.dog.entity.DogDnaArchive;
import com.cku.oa.dog.entity.DogPedigreeCertifiedRedo;
import com.cku.oa.dog.entity.DogSecondBreeder;
import com.cku.oa.dog.entity.DogVideoAppraisal;
import com.cku.oa.dog.service.DogActivationService;
import com.cku.oa.dog.service.DogFrozenSemenService;
import com.cku.oa.finance.cab.dao.CABFinanceStatisticsDao;
import com.cku.oa.finance.dao.PaymentChargingItemDao;
import com.cku.oa.finance.dao.PaymentOrderDao;
import com.cku.oa.finance.dao.PaymentOrderDetailDao;
import com.cku.oa.finance.dao.PaymentProjectCartDao;
import com.cku.oa.finance.dao.SaPaymentDetailTotalDao;
import com.cku.oa.finance.entity.PaymentCart;
import com.cku.oa.finance.entity.PaymentChargingItem;
import com.cku.oa.finance.entity.PaymentOrder;
import com.cku.oa.finance.entity.PaymentOrderDetail;
import com.cku.oa.finance.entity.PaymentPayLog;
import com.cku.oa.finance.entity.PaymentProjectCart;
import com.cku.oa.finance.entity.PaymentRecord;
import com.cku.oa.finance.entity.SaFinanceSubjectMapping;
import com.cku.oa.finance.entity.SaPaymentDetailTotal;
import com.cku.oa.finance.vo.PaymentOrderDetailQueryVO;
import com.cku.oa.finance.vo.PaymentRefundOrderVO;
import com.cku.oa.groomer.dao.GroomerRegisterDao;
import com.cku.oa.groomer.entity.GroomerRegister;
import com.cku.oa.kennel.entity.Kennel;
import com.cku.oa.kennel.service.KennelService;
import com.cku.oa.order.service.BusinessOrderService;
import com.cku.oa.sampling.service.SamplingService;
import com.cku.oa.show.dao.ChampionLoginDao;
import com.cku.oa.show.dao.ShowApplyDao;
import com.cku.oa.show.entity.ChampionLogin;
import com.cku.oa.show.entity.ShowApply;
import com.cku.oa.statistics.service.SplitOrderService;
import com.cku.oa.sys.code.SysCodeUtil;
import com.cku.oa.sys.coupon.dao.SysCouponDao;
import com.cku.oa.sys.coupon.entity.SysCoupon;
import com.cku.oa.sys.dao.user.MemberDao;
import com.cku.oa.sys.entity.user.KennelType;
import com.cku.oa.sys.entity.user.Member;
import com.cku.oa.sys.entity.user.MemberType;
import com.cku.oa.sys.service.ExpressQueueService;
import com.cku.oa.sys.service.user.MemberService;
import com.cku.oa.sys.util.MemberUtil;
import com.cku.partner.club.service.ClubDogChipDeleteService;
import com.cku.restful.v1.finance.service.DogChipDeleteService;
import com.cku.restful.v1.finance.service.DogNewbornDeleteService;
import com.cku.restful.v1.finance.service.KennelRegisterDeleteService;
import com.cku.restful.v1.sys.model.Unifiedorder;
import com.cku.restful.v1.sys.utils.HttpXmlUtils;
import com.cku.restful.v1.sys.utils.RandCharsUtils;
import com.cku.restful.v1.sys.utils.WXSignUtils;
import com.thinkgem.jeesite.common.persistence.BaseEntity;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.service.CrudService;
import com.thinkgem.jeesite.common.utils.Collections3;
import com.thinkgem.jeesite.common.utils.DateUtils;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;

import edu.emory.mathcs.backport.java.util.Arrays;
import io.netty.util.internal.StringUtil;

/**
 * 订单Service
 *
 * @author lyy
 * @version 2016-08-04
 */
@Service
@Transactional(readOnly = true)
public class PaymentOrderService extends CrudService<PaymentOrderDao, PaymentOrder> {
	@Autowired
	private PaymentOrderDetailDao paymentOrderDetailDao;
	@Autowired
	private PaymentProjectCartDao paymentProjectCartDao;
	@Autowired
	private MemberService memberService;
	@Autowired
	private KennelService kennelService;
	@Autowired
	private PaymentRecordService paymentRecordService;
	@Autowired
	private PaymentChargingItemService paymentChargingItemService;
	@Autowired
	private PaymentCartService paymentCartService;
	@Autowired
	private ClubDogChipDeleteService clubDogChipDeleteService;
	@Autowired
	private KennelRegisterDeleteService kennelRegisterDeleteService;
	@Autowired
	private DogChipDeleteService dogChipDeleteService;
	@Autowired
	private DogNewbornDeleteService dogNewbornDeleteService;
	@Autowired
	private DogFrozenSemenService dogFrozenSemenService;
	@Autowired
	private DogActivationService dogActivationService;
	@Autowired
	private PaymentOrderDao paymentOrderDao;
	@Autowired
	private SplitOrderService splitOrderService;
	@Autowired
	private SaPaymentDetailTotalDao saPaymentDetailTotalDao;
	@Autowired
	private MemberDao memberDao;
	@Autowired
	private PaymentPayLogService paymentPayLogService;
	@Autowired
	private PaymentChargingItemDao paymentChargingItemDao;
	@Autowired
	private DogBirthCertificateDao dogbirthcertificatedao;
	@Autowired
	private ChampionLoginDao championLoginDao;
	@Autowired
	private GroomerRegisterDao groomerRegisterDao;
	@Autowired
	private DogBloodSaveDao dogBloodSaveDao;
	@Autowired
	private DogChipDao dogChipDao;
	@Autowired
	private DogNewbornDao dogNewbornDao;
	@Autowired
	private SysCouponDao sysCouponDao;
	@Autowired
	private DogPedigreeCertifiedRedoDao dogpedigreecertifiedredodao;
	@Autowired
	private ShowApplyDao showApplyDao;
	@Autowired
	private DogActivationDao dogActivationDao;
	@Autowired
	private CABFinanceStatisticsDao cabFinanceStatisticsDao;
	@Autowired
	private DogVideoAppraisalDao dogVideoAppraisalDao;
	@Autowired
	private DogAppraisalDao dogAppraisalDao;
	@Autowired
	private DogSecondBreederDao dogSecondBreederDao;
	@Autowired
	private SaFinanceSubjectMappingService saFinanceSubjectMappingService;
	@Autowired
	private WxPayConfig config;
	@Autowired
	private DogDnaArchiveDao dogDnaArchiveDao;
	@Autowired
	private SamplingService samplingService;
	@Autowired
	private BusinessOrderService businessOrderService;
	@Autowired
	private ExpressQueueService expressQueueService;
	@Autowired
	private HandlerRegisterDao handlerRegisterDao;

	private Logger logger = LoggerFactory.getLogger(PaymentOrderService.class);

	public PaymentOrder get(String id, String getByorderCode) {
		PaymentOrder paymentOrder = null;
		if (!StringUtils.isBlank(id)) {
			paymentOrder = super.get(id);
		} else {
			paymentOrder = paymentOrderDao.getByorderCode(getByorderCode);
		}
		if (paymentOrder != null && paymentOrder.getOrderCode() != null && !paymentOrder.getOrderCode().equals("")) {
			List<PaymentOrderDetail> orderDetailList = paymentOrderDetailDao
					.findList(new PaymentOrderDetail(paymentOrder));
			if (orderDetailList != null && orderDetailList.size() > 0) {
				orderDetailList.forEach(item -> {
					String chargingItemId = item.getChargingItemId();
					item.setPaymentChargingItem(
							paymentChargingItemService.get(new PaymentChargingItem(chargingItemId)));
				});
			}
			paymentOrder.setOrderDetailList(orderDetailList);
		}
		return paymentOrder;
	}

	public List<PaymentOrder> findList(PaymentOrder paymentOrder) {
		return super.findList(paymentOrder);
	}

	public String getOrderCount(PaymentOrder paymentOrder) {
		return dao.getOrderCount(paymentOrder);
	}

	public Page<PaymentOrder> findPage(Page<PaymentOrder> page, PaymentOrder paymentOrder) {
		return super.findPage(page, paymentOrder);
	}

	public Page<PaymentOrder> findPages(Page<PaymentOrder> page, PaymentOrder paymentOrder) {
		return super.findPages(page, paymentOrder);
	}

	/**
	 * 后台OA用户使用的订单提交
	 *
	 * @param paymentOrder
	 */
	@Transactional(readOnly = false)
	public void save(PaymentOrder paymentOrder) throws ZAException {
		String runningNumber = SysCodeUtil.getPayRunningNumber();
		Double orderTotal = Double.valueOf("0");
		Date addTime = new Date();
		// 是否相同
		List<PaymentOrderDetail> orderDetailList = paymentOrder.getOrderDetailList();
		// 是否有会员缴费收费项
		boolean memberbFlag = false;
		boolean memberpFlag = false;
		// 专业会员初次注册费标记位
		boolean memberfFlag = false;
		if (orderDetailList != null && orderDetailList.size() > 1) {
			List<PaymentOrderDetail> subli = orderDetailList.subList(1, orderDetailList.size() - 1);
			for (int i = 0; i < subli.size(); i++) {
				if (!orderDetailList.get(0).equalsme(subli.get(i))) {
					throw new ZAException(-1, "同一标识、同一凭证号、同一会员的订单才能支付!");
				}
			}
		}
		// 是否有基础会员年度登记费（门店）
		boolean memberBasicDoorFlag = false;
		if (orderDetailList != null && orderDetailList.size() > 0) {
			// 循环判断 是否有会员缴费收费项
			for (int j = 0; j < orderDetailList.size(); j++) {
				if ("1".equals(orderDetailList.get(j).getChargingItemId())) {
					memberbFlag = true;
				} else if ("3".equals(orderDetailList.get(j).getChargingItemId())) {
					memberpFlag = true;
				} else if ("2".equals(orderDetailList.get(j).getChargingItemId())) {
					memberfFlag = true;
				} else if ("962c2f6e11e8412c8a000c1c8751dbb6".equals(orderDetailList.get(j).getChargingItemId())) {
					memberBasicDoorFlag = true;
				}
			}
		}
		// 判断是否是冻结会员
		Member member = memberService.getByMemberCode(orderDetailList.get(0).getMemberCode());
		if ("1".equals(member.getFreezeFlag())) {
			throw new ZAException(ZAErrorCode.ZA_ERROR, "此会员已冻结！");
		}
		// 判断会员是否过期
		if (!MemberUtil.isActiveMember(member)) {
			if (MemberUtil.isBasicMember(member)) {
				// 基础
				if (memberfFlag && memberpFlag) {
					// 无效基础会员直接缴纳 2专业会员初次注册费，3专业会员年度登记费，应该允许缴纳
				} else {
					// 是否有基础会员年度登记费（门店）
					if (!memberbFlag && !memberBasicDoorFlag) {
						throw new ZAException(ZAErrorCode.ZA_ERROR, "此会员无效，录入收费项目必须包含基础会员年度登记费！");
					}
				}
			} else if (MemberUtil.isProfessionalMember(member)) {
				// 专业会员
				if (!memberpFlag) {
					throw new ZAException(ZAErrorCode.ZA_ERROR, "此会员无效，录入收费项目必须包含专业会员年度登记费！");
				}
			} else {
				// 外籍会员
				if (orderDetailList.stream().noneMatch(od -> "0".equals(od.getChargingItemId()))) {
					// 如果不是充值订单则校验会员有效
					// 刘慧敏要求不修改跟以前一样按专业会员收费项走
					if (!memberpFlag) {
						throw new ZAException(ZAErrorCode.ZA_ERROR, "此会员无效，录入收费项目必须包含专业会员年度登记费！");
					}
				}
			}
		}
		// 插入订单详细
		PaymentOrderDetail model = new PaymentOrderDetail();
		for (PaymentOrderDetail paymentOrderDetail : orderDetailList) {
			// 需要进行项目拆分的项目id
			boolean flag = false;
			String[] strs = { "76", "13", "100", "134" };
			for (String str : strs) {
				if (str.equals(paymentOrderDetail.getChargingItemId())) {
					flag = true;
					break;
				}
			}
			if (flag) {
				paymentOrderDetail.setOrderCode(runningNumber);
				paymentOrderDetail.setAddTime(addTime);
				paymentOrderDetail.setProccessState("0");
				try {
					PropertyUtils.copyProperties(model, paymentOrderDetail);
					// 服务费为每个项目的金额-100再*业务数量
					Double fee = Integer.parseInt(paymentOrderDetail.getNum())
							* (Double.parseDouble(paymentOrderDetail.getPrice()) - Double.parseDouble("100"));
					Double price = Double.parseDouble(model.getPrice()) - Double.parseDouble("100");
					orderTotal = orderTotal + fee;
					model.setPrice(price.toString());// 计算后服务费的总价
					model.setTotalPrice(fee.toString());
					model.setIsNewRecord(false);
					model.preInsert();// 设置该记录为新添记录
					model.setChargingItemId("217");// 服务费项目ID
					model.setChargingItemName("新生幼犬芯片埋植服务费");// 服务费项目名称
					paymentOrderDetailDao.insert(model);
				} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
					e.printStackTrace();
				}
				// 此类项目只收费100，剩余的作为服务费进行结算
				Double total = Integer.parseInt(paymentOrderDetail.getNum()) * Double.parseDouble("100");
				orderTotal = orderTotal + total;
				paymentOrderDetail.setPrice("100");
				paymentOrderDetail.setTotalPrice(total.toString());
				paymentOrderDetail.preInsert();
				paymentOrderDetailDao.insert(paymentOrderDetail);
			} else {
				paymentOrderDetail.setOrderCode(runningNumber);
				paymentOrderDetail.setAddTime(addTime);
				paymentOrderDetail.setProccessState("0");
				Double total = Integer.parseInt(paymentOrderDetail.getNum())
						* Double.parseDouble(paymentOrderDetail.getPrice());
				orderTotal = orderTotal + total;
				paymentOrderDetail.setTotalPrice(total.toString());
				paymentOrderDetail.preInsert();
				paymentOrderDetailDao.insert(paymentOrderDetail);
			}
		}
		// 产出项目购物车临时表
		paymentProjectCartDao.deleteByVPM(new PaymentProjectCart(orderDetailList.get(0).getProjectId(),
				orderDetailList.get(0).getMemberCode(), orderDetailList.get(0).getVoucherCode()));
		// 插入订单
		User u = UserUtils.getLoginUser();
		paymentOrder.setSource(u.getLoginType());
		paymentOrder.setOrderCode(runningNumber);
		paymentOrder.setAddTime(addTime);
		paymentOrder.setLocked("0");
		paymentOrder.setTotalPrice(orderTotal.toString());
		if (!"28".equals(paymentOrder.getPaymentWay())) {
			paymentOrder.setPaymentState("2");
			paymentOrder.setPaymentTime(new Date());
		} else {
			paymentOrder.setPaymentState("1");
		}
		paymentOrder.setMemberCode(orderDetailList.get(0).getMemberCode());
		paymentOrder.setMemberName(orderDetailList.get(0).getMemberName());
		paymentOrder.setProjectId(orderDetailList.get(0).getProjectId());
		paymentOrder.setProjectName(orderDetailList.get(0).getProjectName());
		paymentOrder.setReceiver(member.getName());
		paymentOrder.setReceiveAddress(member.getAddress());
		paymentOrder.setReceiveCity(member.getCity());
		paymentOrder.setReceiveProvince(member.getProvince());
		paymentOrder.setReceiveDel(member.getMobile());
		paymentOrder.setReceivePostCode(member.getPostcode());
		super.save(paymentOrder);

		// 生成流水记录
		PaymentRecord paymentRecord = new PaymentRecord();
		paymentRecord.setRunningNumber(runningNumber);
		paymentRecord.setMemberCode(paymentOrder.getMemberCode());
		paymentRecord.setPaymentState("2");
		paymentRecord.setPaymentWay(paymentOrder.getPaymentWay());
		paymentRecord.setPaymentTime(new Date());
		paymentRecord.setPrice(paymentOrder.getTotalPrice());
		paymentRecord.setPaymentAmount(paymentOrder.getTotalPrice());
		// 所有现金收入都为96
		paymentRecord.setChargingItemId("96");
		// 设置注册地址
		paymentRecordService.setRecordRegister(paymentRecord);
		// 余额支付，扣款
		if ("25".equals(paymentOrder.getPaymentWay())) {
			memberService.memberCharge(paymentOrder.getMemberCode(), paymentOrder.getTotalPrice(), runningNumber);
			// 如果是余额支付，收费项为69
			paymentRecord.setChargingItemId("69");
		}
		// 如果订单录入是现场微信支付则不生成流水
		// by yuanshuai--2019年7月31日14:18:59
		if (!"28".equals(paymentRecord.getPaymentWay())) {
			paymentRecordService.newRecord(paymentRecord);
		}
		// 拆分
		splitOrderService.initSplitAsync(paymentOrder.getOrderCode());
	}

	/**
	 * 添加订单
	 * 
	 * @author yuanshuai
	 * @date 2023/6/19 14:38
	 */
	@Transactional(readOnly = false)
	public void addOrder(PaymentOrder order) {
		order.preInsert();
		dao.insert(order);
	}

	/**
	 * 添加订单明细
	 * 
	 * @author yuanshuai
	 * @date 2023/6/19 14:38
	 */
	@Transactional(readOnly = false)
	public void addOrderDetail(PaymentOrderDetail orderDetail) {
		orderDetail.preInsert();
		paymentOrderDetailDao.insert(orderDetail);
	}

	/**
	 * 添加订单明细
	 * 
	 * @author zhangjunwu
	 * @date 2023/6/29 14:38
	 */
	@Transactional(readOnly = false)
	public void addOrderDetailList(List<PaymentOrderDetail> orderDetailList) {
		orderDetailList.forEach(od -> {
			od.preInsert();
		});
		int row = paymentOrderDetailDao.batchInsert(orderDetailList);
		System.out.println(row);
	}

	/**
	 * 自动处理
	 *
	 * @param paymentOrderDetail
	 */
	public void sysProccess(PaymentOrderDetail paymentOrderDetail) {
		String itemId = paymentOrderDetail.getChargingItemId();
		// 订单缴费会员号
		String memberCode = paymentOrderDetail.getMemberCode();
		PaymentChargingItem paymentChargingItem = paymentChargingItemService.get(new PaymentChargingItem(itemId));
		/*
		 * 基础会员年度登记费，会员过期后从当前时间计算会员有效期延后一年，会员未过期时从截止时间算延后一年 zhuoHeng
		 */
		if ("1".equals(itemId) || "962c2f6e11e8412c8a000c1c8751dbb6".equals(itemId)) {
			Member member = memberService.getByMemberCode(memberCode);
			Date memberEndDateOld = member.getMemberEndDate();
			if (member == null) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "无此会员信息！");
			}
			Date endDate = member.getMemberEndDate() == null ? new Date() : member.getMemberEndDate();
			Date date = new Date();
			Calendar calendar = Calendar.getInstance();
			if (endDate.before(new Date())) {
				calendar.setTime(date);
				calendar.add(Calendar.YEAR, 1);
				date = calendar.getTime();
			} else {
				calendar.setTime(endDate);
				calendar.add(Calendar.YEAR, 1);
				date = calendar.getTime();
			}
			int result = memberService.memberEndDatecharge(paymentOrderDetail.getMemberCode(), date, null);
			if (result != 1) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "更改会员有效期失败！");
			}
			String memberCardType = memberService.getMemberCardTypeByMemberCode(memberCode);
			memberDao.updateMemberType(memberCode, MemberType.basic.toString(), memberCardType);
			// 增加会员变动日志
			member.setMemberEndDate(memberEndDateOld);
			memberService.saveMemberRecord(paymentOrderDetail.getOrderCode(), member, paymentOrderDetail.getCreateBy());
			// 更新会员表第一次缴费时间
			memberService.updateFirstPaymentTime(paymentOrderDetail.getOrderCode(), member);
			/*
			 * 专业会员初次注册费，将会员截止时间设置为当前时间 zhuoHeng
			 */
		} else if ("2".equals(itemId)) {
			Member oldMember = memberService.getByMemberCode(memberCode);
			Date memberEndDateOld = oldMember.getMemberEndDate();
			Date date = new Date();
			int result = memberService.memberEndDatecharge(paymentOrderDetail.getMemberCode(), date, null);
			if (result != 1) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "更改会员有效期失败！");
			}
			// 增加会员变动日志
			oldMember.setMemberEndDate(memberEndDateOld);
			memberService.saveMemberRecord(paymentOrderDetail.getOrderCode(), oldMember,
					paymentOrderDetail.getCreateBy());
			// 更新会员表第一次缴费时间
			memberService.updateFirstPaymentTime(paymentOrderDetail.getOrderCode(), oldMember);
			/*
			 * 专业会员年度登记费，获取会员截止时间在此基础上延后一年 zhuoHeng
			 */
		} else if ("3".equals(itemId)) {
			Member member = memberService.getByMemberCode(memberCode);
			Date memberEndDateOld = member.getMemberEndDate();
			if (member == null) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "无此会员信息！");
			}
			// 判断同一个订单里是否有专业会员初次注册费，如果有且为未处理，则提示先处理初次注册费
			List<PaymentOrderDetail> paymentOrderDetailList = paymentOrderDetailDao
					.getOrderByRunningNum(paymentOrderDetail.getOrderCode(), paymentOrderDetail.getMemberCode());
			for (PaymentOrderDetail orderDetail : paymentOrderDetailList) {
				if ("2".equals(orderDetail.getChargingItemId()) && "0".equals(orderDetail.getProccessState())) {
					throw new ZAException(ZAErrorCode.ZA_ERROR, "请先处理专业会员初次注册费！");
				}
			}
			Date endDate = member.getMemberEndDate() == null ? new Date() : member.getMemberEndDate();
			Date date = new Date();
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(endDate);
			calendar.add(Calendar.YEAR, 1);
			date = calendar.getTime();
			int result = memberService.memberEndDatecharge(paymentOrderDetail.getMemberCode(), date, null);
			if (result != 1) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "更改会员有效期失败！");
			}
			String memberCardType = memberService.getMemberCardTypeByMemberCode(memberCode);
			memberDao.updateMemberType(memberCode, MemberType.professional.toString(), memberCardType);
			// 增加会员变动日志
			member.setMemberEndDate(memberEndDateOld);
			memberService.saveMemberRecord(paymentOrderDetail.getOrderCode(), member, paymentOrderDetail.getCreateBy());
			// 更新会员表第一次缴费时间
			memberService.updateFirstPaymentTime(paymentOrderDetail.getOrderCode(), member);
			/*
			 * 基础会员升级升级专业会员，会员类型从基础升级为专业，截止时间更新为当前时间 zhuoHeng
			 */
		} else if ("10".equals(itemId)) {
			Member oldMember = memberService.getByMemberCode(memberCode);
			Date memberEndDateOld = oldMember.getMemberEndDate();
			Date date = new Date();
			int result = memberService.memberEndDatecharge(paymentOrderDetail.getMemberCode(), date, "professional");
			if (result != 1) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "更改会员类型/有效期失败！");
			}
			// 增加会员变动日志
			oldMember.setMemberEndDate(memberEndDateOld);
			memberService.saveMemberRecord(paymentOrderDetail.getOrderCode(), oldMember,
					paymentOrderDetail.getCreateBy());
			// 更新会员表第一次缴费时间
			memberService.updateFirstPaymentTime(paymentOrderDetail.getOrderCode(), oldMember);
		} else if ("6".equals(itemId)) {
			Member oldMember = memberService.getByMemberCode(memberCode);
			// 犬舍年度缴费
			Kennel kennel = kennelService.getKennelByMemberCode(paymentOrderDetail.getMemberCode());
			if (kennel == null) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "本会员没有注册犬舍信息！");
			}
			Date endTimeOld = kennel.getEndTime();
			Date nowDate = new Date();
			if (kennel.getEndTime() != null) {
				nowDate = kennel.getEndTime();
			}
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
			Calendar calendar = Calendar.getInstance();// 日历对象
			calendar.setTime(nowDate);// 设置当前日期
			calendar.add(Calendar.YEAR, 1);// 年份+1
			kennel.setEndTime(calendar.getTime());
			int result = kennelService.kennelEndDatecharge(kennel);
			if (result != 1) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "更改犬舍类型/有效期失败！");
			}
			String memberCardType = memberService.getMemberCardTypeByMemberCode(memberCode);
			memberDao.updateMemberType(memberCode, MemberType.professional.toString(), memberCardType);
			// 增加会员变动日志;
			if (oldMember.getKennel() != null) {
				oldMember.getKennel().setEndTime(endTimeOld);
			}
			memberService.saveMemberRecord(paymentOrderDetail.getOrderCode(), oldMember,
					paymentOrderDetail.getCreateBy());
			// 更新会员表第一次缴费时间
			memberService.updateFirstPaymentTime(paymentOrderDetail.getOrderCode(), oldMember);
			// 添加核算日期及状态
			// kennelService.kennelXFAfterPay(kennel.getId());
		} else if ("57053cefa38149a8a04d4ae6d8a68741".equals(itemId)) {
			Member oldMember = memberService.getByMemberCode(memberCode);
			// 犬舍永久缴费
			Kennel kennel = kennelService.getKennelByMemberCode(paymentOrderDetail.getMemberCode());
			if (kennel == null) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "本会员没有注册犬舍信息！");
			}
			Date endTimeOld = kennel.getEndTime();
			kennel.setType(KennelType.permanent.toString());
			Date nowDate = new Date();
			Calendar calendar = Calendar.getInstance();// 日历对象
			calendar.setTime(nowDate);// 设置当前日期
			calendar.add(Calendar.YEAR, 100);// 年份+1
			kennel.setEndTime(calendar.getTime());
			int result = kennelService.kennelTypeChange(kennel);
			if (result != 1) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "更改犬舍类型/有效期失败！");
			}
			String memberCardType = memberService.getMemberCardTypeByMemberCode(memberCode);
			memberDao.updateMemberType(memberCode, MemberType.professional.toString(), memberCardType);
			// 增加会员变动日志
			if (oldMember.getKennel() != null) {
				oldMember.getKennel().setEndTime(endTimeOld);
			}
			memberService.saveMemberRecord(paymentOrderDetail.getOrderCode(), oldMember,
					paymentOrderDetail.getCreateBy());
			// 更新会员表第一次缴费时间
			memberService.updateFirstPaymentTime(paymentOrderDetail.getOrderCode(), oldMember);
			// 添加核算日期及状态
			// kennelService.kennelXFAfterPay(kennel.getId());
		} else if ("5".equals(itemId)) {
			Member oldMember = memberService.getByMemberCode(memberCode);
			// 犬舍初次注册费
			Kennel kennel = kennelService.getKennelByMemberCode(paymentOrderDetail.getMemberCode());
			if (kennel == null) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "本会员没有注册犬舍信息！");
			}
			Date endTimeOld = kennel.getEndTime();
			Date nowDate = new Date();
			kennel.setEndTime(nowDate);
			int result = kennelService.kennelEndDatecharge(kennel);
			if (result != 1) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "更改犬舍类型/有效期失败！");
			}
			// 增加会员变动日志
			if (oldMember.getKennel() != null) {
				oldMember.getKennel().setEndTime(endTimeOld);
			}
			memberService.saveMemberRecord(paymentOrderDetail.getOrderCode(), oldMember,
					paymentOrderDetail.getCreateBy());
			// 更新会员表第一次缴费时间
			memberService.updateFirstPaymentTime(paymentOrderDetail.getOrderCode(), oldMember);
			// 添加核算日期及状态
			// kennelService.kennelZCAfterPay(kennel.getId());
		}
	}

	@Transactional(readOnly = false)
	public void delete(PaymentOrder paymentOrder) {
		super.delete(paymentOrder);
	}

	@Transactional(readOnly = false)
	public void locked(PaymentOrder paymentOrder) {
		paymentOrder.setLocked("0".equals(paymentOrder.getLocked()) ? "1" : "0");
		dao.locked(paymentOrder);
	}

	@Transactional(readOnly = false)
	public void updateProccessState(String id, String detailId) {
		PaymentOrder paymentOrder = this.get(id);
		PaymentOrderDetail paymentOrderDetail = paymentOrderDetailDao.get(detailId);
		if (!paymentOrder.getOrderCode().contains("@")) {
			sysProccess(paymentOrderDetail);
		}
		paymentOrderDetail.setProccessState("1");
		paymentOrderDetail.setProccessTime(new Date());
		paymentOrderDetailDao.updateProccessState(paymentOrderDetail);
	}

	@Transactional(readOnly = false)
	public void updateBusinessInfo(String orderCode, String orderDetailId, String chargingItemId, String businessIds,
			String businessTable) {
		List<PaymentOrderDetail> detailList = paymentOrderDetailDao.findByOrderCodeAndDetailIdAndItemId(orderCode,
				orderDetailId, chargingItemId);
		if (!CollectionUtils.isEmpty(detailList)) {
			detailList.forEach(detail -> {
				detail.setBusinessIds(businessIds);
				detail.setBusinessTable(businessTable);
				paymentOrderDetailDao.updateBusinessInfo(detail);
			});
		}
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
	public void removeOrderTask(PaymentOrder order) {
		this.removeOrder(order);
	}

	/**
	 * 删除一个订单 1.删除购物车的一个物品，会删除业务id相同的其他商品 2.删除购物车的一个物品，会同时删除业务表的数据
	 */
	@Transactional(readOnly = false)
	public void removeOrder(PaymentOrder order) {
		logger.info("开始删除订单：订单号" + order.getId());
		PaymentOrder po = dao.get(order.getId());
		// 已交费的订单不删除
		if ("2".equals(po.getPaymentState())) {
			return;
		}
		List<PaymentOrderDetail> orderDetailList = paymentOrderDetailDao.getOrderByRunningNum(po.getOrderCode(),
				po.getMemberCode());
		// 删除当前的业务数据
		dao.delete(po);
		// 删除业务订单数据
		businessOrderService.deleteByOrderCode(po.getOrderCode());
		// 删除业务数据
		String userId = UserUtils.getLoginUser().getId();
		userId = StringUtils.isBlank(userId) ? "null" : userId;
		logger.info("删除订单--订单号:" + order.getId() + ",user:" + userId);
		// 遍历所有的detail，删除所有的业务数据
		for (PaymentOrderDetail detail : orderDetailList) {
			String tableName = detail.getBusinessTable();
			String businessIds = detail.getBusinessIds();
			logger.info("删除订单--订单号:" + order.getId() + ",user:" + userId + ", tableName:" + tableName + ", businessIds:"
					+ businessIds);
			// tableName为空表示没有业务表，不需要删业务数据
			if (StringUtils.isNotBlank(tableName)) {
				if ("dog_birth_certificate".equals(tableName)) {
					// 出生证明表根据配种证明号进行删除
					dao.deleteDogBirthCertificate(businessIds);
					DogSecondBreeder dogSecondBreeder = dogSecondBreederDao
							.getByBreedCertifiedCodeAndOrderCode(businessIds, detail.getOrderCode());
					if (dogSecondBreeder != null) {
						dogSecondBreederDao.delete(dogSecondBreeder);
					}
				} else if (tableName.startsWith("sys")) {
					// 会员业务一般是缴费
					// 绝对不能随便删除会员
					// 优惠劵清空使用标记位
					// 出生纸优惠劵清空使用字段
					if (tableName.equals("sys_coupon")) {
						// 优惠劵清空使用标记位
						dao.clearCouponItem(tableName, businessIds);
					}
				} else if (tableName.equals("club_dog")) {// 淘宠宝鉴定犬业务删除
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("buying_order")) {// 抢购购物车表
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("groomer_course_application")) {// 抢购购物车表
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.startsWith("groomer")) {
					// 美容只有报名能删除
					if (tableName.equals("groomer_register")) {
						dao.deleteOrderItem(tableName, businessIds);
					} else if (tableName.equals("groomer_written_exam_info")) {
						dao.deleteOrderItem(tableName, businessIds);
						logger.info("笔试考试补考订单业务表删除成功，tableName : " + tableName);
					}
				} else if (tableName.startsWith("handler")) {
					// 牵犬师只有报名能删除
					if (tableName.equals("handler_register")) {
						dao.deleteOrderItem(tableName, businessIds);
					}
				} else if (tableName.equals("show_apply") || tableName.equals("show_champion_login")) {
					// 赛事报名与冠军登录可删除
					if (businessIds.indexOf("#") != -1) {
						// 参赛劵清空使用标记位
						String id = businessIds.split("#")[0];
						String pedigreeCertified = businessIds.split("#")[1];
						dao.deleteOrderItem(tableName, id);
						dao.clearCouponShowItem(tableName, businessIds, pedigreeCertified);
					} else {
						dao.deleteOrderItem(tableName, businessIds);
					}
				} else if (tableName.equals("dog_birth_certificate") || tableName.equals("dog_chip")
						|| tableName.equals("dog_pedigree_certified_redo")
						|| tableName.equals("dog_pedigree_certified_change")
						|| tableName.equals("dog_pedigree_certified_export") || tableName.equals("dog_owner_change")
						|| tableName.equals("dog_appraisal") || tableName.equals("dog_tibetan_mastiff")
						|| tableName.equals("dog_blood_save") || tableName.equals("dog_dna_archive")
						|| tableName.equals("dog_dna_parents_compare") || tableName.equals("dog_chip_change")
						|| tableName.equals("dog_video_appraisal")) {
					String[] idArr = businessIds.split(",");
					if (tableName.equals("dog_chip_change")) {
						clubDogChipDeleteService.removeDogChipChangeOrder(businessIds);
					}
					if (tableName.equals("dog_chip")) {// 整窝第二繁殖人
						DogSecondBreeder dogSecondBreeder = dogSecondBreederDao
								.getByBreedCertifiedCodeAndOrderCode(businessIds, detail.getOrderCode());
						if (dogSecondBreeder != null) {
							dogSecondBreederDao.delete(dogSecondBreeder);
						}
						// 删除血统证书订单一并删除dog_birth_certificate里的新犬主
						dao.deleteDogChipTempMember(businessIds);
					}
					if (tableName.equals("dog_appraisal")) {
						dogAppraisalDao.updateVideoById(businessIds);
					}
					// 血统证书业务删除购物车的时候需要清空登记卡的addUser字段
					/**
					 * update by zhangjunwu 2021-04-19 修改因单独删除芯片代打费时，出生纸表 add_user
					 * 字段消失，导致俱乐部无法打印证书问题结案 修改方案：判断订单详情，如订单详情项为芯片代打费时，不做 add_user 更新操作
					 */
					if (!(tableName.equals("dog_chip") && "328".equals(detail.getChargingItemId()))) {
						dogChipDeleteService.deleteDogBirthCertificateAddUser(tableName, businessIds);
					}
					if (tableName.equals("dog_dna_archive")) {
						Stream.of(idArr).forEach(id -> {
							DogDnaArchive dogDnaArchive = dogDnaArchiveDao.get(id);
							// 解绑采样包
							if (!Objects.isNull(dogDnaArchive)
									&& StringUtils.isNotBlank(dogDnaArchive.getSamplingCode())) {
								samplingService.unbindDogInfoBySamplingCode(dogDnaArchive.getSamplingCode());
							}
						});
					}
					Stream.of(idArr).forEach(id -> {
						// 这些繁殖业务是允许删除数据的
						dao.deleteOrderItem(tableName, id);
					});
				} else if (tableName.equals("dog_newborn")) {// 配种证明
					// 清除精子信息中的配种证明号
					dogNewbornDeleteService.clearDogSemen(businessIds);
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("dog_frozen_semen")) {// 种犬申报报备
					// 删除犬只精子相关记录
					dogFrozenSemenService.deleteDogSemen(businessIds);
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("dog_semen_change")) {// 种犬精子变更
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("kennel_rename")) {// 犬舍名称变更业务删除
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("kennel")) {
					// 订单删除犬舍注册记录时，同时把犬舍信息逻辑删除
					kennelRegisterDeleteService.logicDeleteKennelRegister(businessIds);
				} else if (tableName.equals("dog_activation")) {
					// 订单俱乐部超时激活信息时、删除超时激活记录
					dogActivationService.deleteById(businessIds);
					DogActivation dogActivation = dogActivationDao.get(businessIds);
					DogBirthCertificate certificate = dogbirthcertificatedao
							.getByBirthCerRegCode(dogActivation.getBirthCode());
					if (StringUtils.isNotBlank(certificate.getActivitionState())
							&& "3".equals(certificate.getActivitionState())) {
						dogbirthcertificatedao.updateActivationStates(certificate.getBirthCerRegCode(), null);
					}
				} else if (tableName.equals("dog_sticker_apply")) {// 犬只等级贴纸申请
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("user_coupon_compose")) {
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("kennel_owner_change")) {
					dao.deleteOrderItem(tableName, businessIds);
				} else if (tableName.equals("appreciation_apply")) {
					dao.deleteOrderItem(tableName, businessIds);
				} else {
					// 其他未知的表也不允许删除
				}
			}
			// 删除当前业务详情数据
			paymentOrderDetailDao.delete(detail);

		}
		List<PaymentPayLog> payLogList = paymentPayLogService.findByOrderId(order.getId());
		// 24 为微信支付
		if (!CollectionUtils.isEmpty(payLogList) && "24".equals(payLogList.get(0).getPayType())) {
			closeWxPayOrder(po.getId());
		}
		// 1 为支付宝支付
		if (!CollectionUtils.isEmpty(payLogList) && "1".equals(payLogList.get(0).getPayType())) {
			// 因支付宝订单产生时机问题，无法在此取消交易，暂不处理
			// closeAliPayOrder(po.getId());
		}
		logger.info("删除订单结束：订单id" + order.getId());
	}

	private void closeWxPayOrder(String orderId) {
		// 参数组
		String appid = config.getAppID();
		String mch_id = config.getMchID();
		String nonce_str = RandCharsUtils.getRandomString(16);
		String out_trade_no = orderId;
		// 参数：开始生成签名
		SortedMap<Object, Object> parameters = new TreeMap<>();
		parameters.put("appid", appid);
		parameters.put("mch_id", mch_id);
		parameters.put("nonce_str", nonce_str);
		parameters.put("out_trade_no", out_trade_no);
		// 构造签名
		String sign = WXSignUtils.createSign("UTF-8", parameters);
		// xml构造对象
		Unifiedorder unifiedorder = new Unifiedorder();
		unifiedorder.setAppid(appid);
		unifiedorder.setMch_id(mch_id);
		unifiedorder.setOut_trade_no(out_trade_no);
		unifiedorder.setNonce_str(nonce_str);
		unifiedorder.setSign(sign);
		// 构造xml参数
		String xmlInfo = HttpXmlUtils.xmlCloseInfo(unifiedorder);
		String wxUrl = "https://api.mch.weixin.qq.com/pay/closeorder";
		String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, "POST", xmlInfo).toString();
		logger.debug(weixinPost);
		// 增加支付日志
		paymentPayLogService.updatePayState(orderId, "4", "用户：" + UserUtils.getLoginUser().getId() + "，删除订单，系统关闭交易单");
	}

	// /**
	// * 删除所有的前一天的未付款的订单
	// * 清空所有的购物车
	// */
	// @Transactional(readOnly = false)
	// public void removeUnpayOrder(){
	// Date date = new Date();
	// try {
	// //设置时间为当前日期0时0分0秒
	// date = new SimpleDateFormat("yyyy-MM-dd").parse(DateUtils.getDate());
	// } catch (ParseException e1) {
	// e1.printStackTrace();
	// }
	// List<PaymentOrder> orders = dao.findUnpayedOrderByDate(date);
	// for(PaymentOrder order:orders){
	// try{
	// this.removeOrder(order);
	// }catch(Exception e){
	// e.printStackTrace();
	// }
	// }
	//
	// List<PaymentCart> carts = paymentCartService.findAll();
	// for(PaymentCart cart:carts){
	// try{
	// paymentCartService.removeCart(cart.getId(),true);
	// }catch(Exception e){
	// e.printStackTrace();
	// }
	// }
	//
	// //删除地方俱乐部提交的新生犬登记，未生成订单的记录
	// clubDogChipDeleteService.removeDogChipChangeNoOrder();
	// }

	/**
	 * @description: （逻辑）删除未缴费订单
	 * @author: laiguanglong
	 * @date: 2017/4/12 15:51
	 */
	@Transactional(readOnly = false)
	public int unpayedOrderDelete() {
		logger.info("计划任务-删除订单-开始");
		int count = 0;
		Date date = new Date();
		try {
			// 设置时间为当前日期0时0分0秒
			date = new SimpleDateFormat("yyyy-MM-dd").parse(DateUtils.getDate());
		} catch (ParseException e1) {
			e1.printStackTrace();
		}
		List<PaymentOrder> orders = dao.findUnpayedOrderByDate(date);
		for (PaymentOrder order : orders) {
			try {
				this.removeOrder(order);
				count++;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		logger.info("计划任务-删除订单-结束");
		return count;
	}

	/**
	 * @description: （物理）删除购物车
	 * @author: laiguanglong
	 * @date: 2017/4/12 15:53
	 */
	@Transactional(readOnly = false)
	public int paymentCartDelete() {
		int count = 0;
		List<PaymentCart> carts = paymentCartService.findAll();
		for (PaymentCart cart : carts) {
			try {
				paymentCartService.removeCart(cart.getId(), true);
				count++;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return count;
	}

	/**
	 * 根据订单号查找
	 *
	 * @Author chaixueteng
	 * @2016年10月18日下午2:18:09
	 */
	public PaymentOrder getByOrderCode(String orderCode) {
		return dao.getOrderByRunningNum(orderCode);
	}

	/**
	 * 根据订单号查找
	 *
	 * @Author chaixueteng
	 * @2016年10月18日下午2:18:09
	 */
	public List<PaymentOrder> getByOrderCodes(List<String> orderCodes) {
		return dao.getOrderByRunningNums(orderCodes);
	}

	/**
	 *
	 * @description: 根据流水号获取支付时间
	 * @author: laiguanglong
	 * @date: 2016年11月4日 下午5:14:55
	 */
	public Date getPaymentTimeByOrderCode(String orderCode) {
		return dao.getOrderByRunningNum(orderCode).getPaymentTime();
	}

	public Page<PaymentOrder> dogChipInjectList(Page<PaymentOrder> page, PaymentOrder order) {
		order.setPage(page);
		List<PaymentOrder> orderList = dao.dogChipInjectList(order);
		page.setList(orderList);
		return page;
	}

	@Transactional(readOnly = false)
	public void cancled(String orderId) {
		PaymentOrder order = dao.get(orderId);
		if (order == null) {
			throw new ZAException(ZAErrorCode.ZA_ERROR, "找不到该订单信息、无法作废！");
		}
		if (StringUtils.isNotBlank(order.getLocked()) && "1".equals(order.getLocked())) {
			throw new ZAException(ZAErrorCode.ZA_ERROR, "该订单已被锁定、无法作废！");
		}
		if (StringUtils.isNotBlank(order.getDelFlag()) && "1".equals(order.getDelFlag())) {
			throw new ZAException(ZAErrorCode.ZA_ERROR, "该订单已被作废！");
		}
		if ("21".equals(order.getPaymentWay())) {
			throw new ZAException(ZAErrorCode.ZA_ERROR, "支付方式为“比赛现场收入”不允许作废，请联系技术部门修改！");
		}
		String userId = UserUtils.getLoginUser().getId();
		userId = StringUtils.isBlank(userId) ? "null" : userId;
		String runningNumber = "";
		List<PaymentOrderDetail> orderDetailList = paymentOrderDetailDao.findByOrderCode(order.getOrderCode());
		for (PaymentOrderDetail orderDetail : orderDetailList) {
			if (StringUtils.isNotBlank(orderDetail.getProccessState()) && "1".equals(orderDetail.getProccessState())) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "该订单已被处理、无法作废！");
			}
			if (StringUtils.isNotBlank(orderDetail.getBusinessIds())
					|| StringUtils.isNotBlank(orderDetail.getBusinessTable())) {
				throw new ZAException(ZAErrorCode.ZA_ERROR, "该订单已经录入、无法作废！");
			}
			PaymentChargingItem paymentChargingItem = paymentChargingItemDao.get(orderDetail.getChargingItemId());
			if (paymentChargingItem.getType().equals("1")) {
				String jumpUrl = paymentChargingItem.getJumpUrl();
				Map tableByJumpUrl = paymentChargingItemDao.getTableByJumpUrl(jumpUrl);
				Integer num = paymentOrderDetailDao.getUsedDetail((String) tableByJumpUrl.get("table_name"),
						orderDetail.getOrderCode());
				if (num > 0) {
					throw new ZAException(ZAErrorCode.ZA_ERROR, "该订单已经录入、无法作废！");
				}
			}
		}
		for (PaymentOrderDetail orderDetail : orderDetailList) {
			// paymentOrderDetailDao.delete(orderDetail);
			// 修改拆分后的状态
			List<SaPaymentDetailTotal> totalList = saPaymentDetailTotalDao.getByRunningNumber(order.getOrderCode());
			for (SaPaymentDetailTotal data : totalList) {
				data.setOrderStates("1");
				data.setRemarks("作废订单--date" + DateUtils.formatDateTime(new Date()) + "userid:" + userId);
				data.preUpdate();
				saPaymentDetailTotalDao.update(data);
			}
			// 生成回充流水
			PaymentRecord paymentRecord = new PaymentRecord();
			runningNumber = SysCodeUtil.getPayRunningNumber();
			paymentRecord.setRunningNumber(runningNumber);
			paymentRecord.setMemberCode(orderDetail.getMemberCode());
			paymentRecord.setPaymentState("2");
			paymentRecord.setChargingItemNum(Integer.parseInt(orderDetail.getNum()));
			paymentRecord.setPaymentWay("27");
			paymentRecord.setPaymentTime(new Date());
			paymentRecord.setPrice(0 - Double.parseDouble(orderDetail.getTotalPrice()) + "");
			paymentRecord.setPaymentAmount(0 - Double.parseDouble(orderDetail.getTotalPrice()) + "");
			paymentRecord.setChargingItemId(orderDetail.getChargingItemId());
			paymentRecordService.setRecordRegister(paymentRecord);
			paymentRecordService.newRecord(paymentRecord);
			// 回充流水拆分
			splitOrderService.initSplit(runningNumber);
			PaymentChargingItem chargingItem = paymentChargingItemDao.get(orderDetail.getChargingItemId());
			List<SaPaymentDetailTotal> list = saPaymentDetailTotalDao.getByRunningNumber(runningNumber);
			for (SaPaymentDetailTotal data : list) {
				data.setOldRunningNumber(order.getOrderCode());
				data.setOrderStates("2");
				double price = Double.parseDouble(data.getPrice());
				if (price > 0 && StringUtils.isNotBlank(chargingItem.getShortName())
						&& !chargingItem.getShortName().contains("sys_coupon")) {
					price = 0 - price;
				}
				data.setPayMemberCode(splitOrderService.getPayMemberCodeByOrder(order.getOrderCode()));
				data.setPrice(price + "");
				data.preUpdate();
				saPaymentDetailTotalDao.update(data);
			}
		}
		// 删除订单
		logger.info("开始作废订单：订单id" + order.getId());
		dao.delete(order);
		// PaymentRecord record =
		// paymentRecordDao.getByRunningNumber(order.getOrderCode());
		// paymentRecordService.delete(record);
		logger.info("作废订单--订单id:" + order.getId() + ",user:" + userId);
		// 已缴费的订单、订单金额充值到会员余额
		if (StringUtils.isNotBlank(order.getPaymentState()) && "2".equals(order.getPaymentState())) {
			Member member = memberService.getByMemberCode(order.getMemberCode());
			BigDecimal accountBalance = new BigDecimal(member.getAccountBalance())
					.add(new BigDecimal(order.getTotalPrice()));
			memberDao.updateAccountBalance(order.getMemberCode(), accountBalance);
			int resultChange = memberDao.insertSysAccountBalanceChange(order.getMemberCode(), runningNumber,
					String.valueOf(member.getAccountBalance()), order.getTotalPrice());
			if (resultChange <= 0) {
				throw new ZAException(ZAErrorCode.ZA_ERC_PAYMENTRECORD_MEMBERUPDATEFAIL_STATE, "增加余额变动记录失败！");
			}
		}

	}

	public Page<PaymentRefundOrderVO> refundList(Page<PaymentRefundOrderVO> page, PaymentRefundOrderVO paymentOrder) {
		paymentOrder.setPage(page);
		page.setList(dao.findRefundListPage(paymentOrder));
		return page;
	}

	public PaymentOrder getByBusinessOrderCode(String businessOrderCode) {
		return paymentOrderDao.getByBusinessOrderCode(businessOrderCode);
	}

	// 通过
	@SuppressWarnings("deprecation")
	@Transactional(readOnly = false)
	public Map<String, String> refundAgree(PaymentRefundOrderVO refundOrder) {
		// paymentorder 行级锁
		paymentOrderDao.getByIdForUpdate(refundOrder.getId());

		Map<String, String> map = new HashMap<>();
		map.put("code", "0");
		map.put("msg", "OK");
		// 上线前改为最终上线日期，上线之后一天产生的订单可以申请退款
		Date onLineDate = new Date(2020 - 1900, 2 - 1, 18 + 1, 0, 0);
		PaymentOrderDetail entity = new PaymentOrderDetail();
		entity.setBusinessOrderCode(refundOrder.getBusinessOrderCode());
		entity.setBusinessRefundState("1");
		List<PaymentOrderDetail> details = paymentOrderDetailDao.findList(entity);
		if (details.size() == 0) {
			map.put("code", "-1");
			map.put("msg", "未找到订单明细！");
			return map;
		}
		PaymentOrderDetail orderDetail = details.get(0);
		// businessRefund; 业务退款 0不支持,1支持 businessRefundState; 业务退款状态 1退款待审核，2审核不通过，3审核通过
		if (details.size() == 0 || orderDetail == null || !"1".equals(orderDetail.getBusinessRefund())
				|| !"1".equals(orderDetail.getBusinessRefundState())) {
			map.put("code", "-1");
			map.put("msg", "未找到订单明细或订单状态异常！");
			return map;
		}
		// 验证业务状态 和是否为新订单（写死的日期）
		if (!orderDetail.getCreateDate().after(onLineDate)) {
			map.put("code", "-1");
			map.put("msg", "此订单为旧订单，不允许系统退款！");
			return map;
		}
		// 处理原订单
		doRefundForOriginalOrder(details);
		doRefundForHedge(details, refundOrder.isMatchFullRefundFlag(), Boolean.TRUE, Boolean.FALSE);
		return map;
	}

	/**
	 * 执行退款逻辑
	 * 
	 * @author yuanshuai
	 * @date 2021/5/21 15:58
	 */
	@Transactional(readOnly = false)
	public void doRefundForHedge(List<PaymentOrderDetail> detailList, boolean matchFullRefundFlag,
			boolean changeBusinessFlag, boolean allCouponRefundFlag) {
		PaymentOrderDetail detail = detailList.get(0);
		// 区分收费项是否为优惠券或者减免项
		List<PaymentChargingItem> couponList = paymentChargingItemDao.getNegativeItems();
		if (allCouponRefundFlag) {
			List<PaymentChargingItem> memberDogCouponList = paymentChargingItemDao.getMemberDogCouponItems();
			couponList = Stream.concat(couponList.stream(), memberDogCouponList.stream()).collect(Collectors.toList());
		}
		Set<String> couponSet = couponList.stream().map(BaseEntity::getId).collect(Collectors.toSet());

		// 生成红冲
		PaymentOrder order = dao.getByorderCode(detail.getOrderCode());
		BigDecimal change = BigDecimal.ZERO;
		for (PaymentOrderDetail tempDetail : detailList) {
			// 第三步 生成回充流水
			// 计算当前明细金额
			BigDecimal currentPrice = new BigDecimal(tempDetail.getTotalPrice());
			// 生成流水号
			String runningNumber = SysCodeUtil.getPayRunningNumber();
			// 生成流水
			PaymentRecord paymentRecord = new PaymentRecord();
			paymentRecord.setRunningNumber(runningNumber);
			paymentRecord.setMemberCode(tempDetail.getMemberCode());
			paymentRecord.setPaymentState("2");
			paymentRecord.setPaymentWay("27");
			paymentRecord.setPaymentTime(new Date());
			paymentRecord.setPrice(BigDecimal.ZERO.subtract(currentPrice).toString());
			paymentRecord.setPaymentAmount(BigDecimal.ZERO.subtract(currentPrice).toString());
			paymentRecord.setChargingItemId(tempDetail.getChargingItemId());
			paymentRecord.setRemarks(
					"退款订单--date" + DateUtils.formatDateTime(new Date()) + "userid:" + UserUtils.getLoginUser().getId());
//          如果是赛事退款、回充流水增加备注
			ShowApply showApply = showApplyDao.getByRunningNumber(tempDetail.getOrderCode());
			if (showApply != null) {
				String[] split = showApply.getShowCode().split("-");
				if (matchFullRefundFlag) {
					paymentRecord.setPaymentRemarks(split[0] + split[1] + "（赛事报名全额退费）");
				} else {
					paymentRecord.setPaymentRemarks(split[0] + split[1] + "（赛事报名退费手续费）");
				}
			}

			paymentRecordService.setRecordRegister(paymentRecord);
			paymentRecordService.newRecord(paymentRecord);
			// 第四步 回充流水拆分
			splitOrderService.initSplit(runningNumber);
			List<SaPaymentDetailTotal> list = saPaymentDetailTotalDao.getByRunningNumber(runningNumber);
			for (SaPaymentDetailTotal total : list) {
				total.setOldRunningNumber(order.getOrderCode());
				total.setOrderStates("2");
				total.preUpdate();
				if (Double.parseDouble(total.getPrice()) > 0 && !couponSet.contains(tempDetail.getChargingItemId())) {
					total.setPrice(0 - Double.parseDouble(total.getPrice()) + "");
				} else if (couponSet.contains(tempDetail.getChargingItemId())
						&& Double.parseDouble(total.getPrice()) < 0) {
					total.setPrice(0 - Double.parseDouble(total.getPrice()) + "");
				}
				if (Double.parseDouble(total.getPaymentMoney()) > 0
						&& !couponSet.contains(tempDetail.getChargingItemId())) {
					total.setPaymentMoney(0 - Double.parseDouble(total.getPaymentMoney()) + "");
				} else if (couponSet.contains(tempDetail.getChargingItemId())
						&& Double.parseDouble(total.getPrice()) < 0) {
					total.setPaymentMoney(0 - Double.parseDouble(total.getPaymentMoney()) + "");
				}
				saPaymentDetailTotalDao.update(total);
			}
			change = change.add(currentPrice);
		}
		// 第五步 已缴费的订单、订单金额充值到会员余额
		BigDecimal accountBalance = null;
		if (StringUtils.isNotBlank(order.getPaymentState()) && "2".equals(order.getPaymentState())) {
			Member member = memberService.getByMemberCode(order.getMemberCode());
			// 余额变动记录
			List<SaPaymentDetailTotal> saPaymentDetailTotalList = saPaymentDetailTotalDao
					.getByOldRunningNumber(order.getOrderCode());
			Set<String> runningNumberSet = saPaymentDetailTotalList.stream().map(SaPaymentDetailTotal::getRunningNumber)
					.collect(Collectors.toSet());
			Float accountBalanceTemp = Float.valueOf(member.getAccountBalance());
			for (String runningNumber : runningNumberSet) {
				PaymentRecord paymentRecord = paymentRecordService.getByRunningNumber(runningNumber);
				Float paymentAmount = Float.valueOf(paymentRecord.getPaymentAmount()) * -1;
				int resultChange = memberDao.insertSysAccountBalanceChange(order.getMemberCode(),
						paymentRecord.getRunningNumber(), String.valueOf(accountBalanceTemp), paymentAmount.toString());
				accountBalanceTemp += paymentAmount;
				if (resultChange <= 0) {
					throw new ZAException(ZAErrorCode.ZA_ERC_PAYMENTRECORD_MEMBERUPDATEFAIL_STATE, "增加余额变动记录失败！");
				}
			}

			accountBalance = new BigDecimal(member.getAccountBalance()).add(change);
			memberDao.updateAccountBalance(order.getMemberCode(), accountBalance);
		}
		// 第六步 修改业务表状态 0 待审核 1通过 2未通过 3已注销
		if (changeBusinessFlag) {
			saveBusinessState(detailList);
		}
		// 第七步 退回优惠券
		saveCouponsState(detailList, couponSet);

		// 如赛事不是全额退费，才执行以下逻辑
		// 赛事特殊处理，生成一条30%金额的正向流水
		if (!matchFullRefundFlag && StringUtils.isNotBlank(order.getPaymentState())
				&& "2".equals(order.getPaymentState())
				&& ("1027".equals(detail.getBusinessId()) || "1030".equals(detail.getBusinessId())
						|| "1033".equals(detail.getBusinessId()) || "1036".equals(detail.getBusinessId())
						|| "1039".equals(detail.getBusinessId()) || "1042".equals(detail.getBusinessId())
						|| "1070".equals(detail.getBusinessId()) || "1073".equals(detail.getBusinessId()))) {
			// 计算金额 实付金额的30%，四舍五入保留整数
			BigDecimal price = change.multiply(new BigDecimal("0.3")).setScale(0, BigDecimal.ROUND_HALF_UP);
			// 生成流水及财务拆分项
			createShowRecordAndSaDetail(detail, price.toString());
			// 修改充值金额为总金额-30
			memberDao.updateAccountBalance(order.getMemberCode(), accountBalance.subtract(price));
		}
	}

	/**
	 * 退单处理原订单
	 * 
	 * @author yuanshuai
	 * @date 2021/5/24 15:31
	 */
	public void doRefundForOriginalOrder(List<PaymentOrderDetail> detailList) {
		// 第一步 修改OrderDetail状态
		PaymentOrderDetail detail = detailList.get(0);
		detail.setBusinessRefundState("3");
		detail.preUpdate();
		paymentOrderDetailDao.updateRefundStateByParam(detail);
		// 第二步 修改拆分后状态
		List<String> q = detailList.stream().map(BaseEntity::getId).collect(Collectors.toList());
		List<SaPaymentDetailTotal> totalList = saPaymentDetailTotalDao.listByOrderIds(q);
		for (SaPaymentDetailTotal data : totalList) {
			// `order_states` varchar(1) DEFAULT NULL COMMENT '订单状态 ：1:：作废，2：回充，3：退款',
			data.setOrderStates("3");
			data.setRemarks(
					"退款订单--date" + DateUtils.formatDateTime(new Date()) + "userid:" + UserUtils.getLoginUser().getId());
			data.preUpdate();
			saPaymentDetailTotalDao.update(data);
		}
	}

	/**
	 * 生成赛事退费后30%扣款的流水和财务拆分项
	 *
	 * @author: yuanshuai
	 * @date: 2020/6/9 10:31
	 * @param orderDetail 订单详情
	 * @param price       扣除金额（实付金额的30%）
	 */
	private void createShowRecordAndSaDetail(PaymentOrderDetail orderDetail, String price) {
		// now
		Date now = new Date();
		// 付款方式
		final String paymentWay = "25";
		// 收费项-报名退费手续费
		final String chargingItemId = "b196aba404ce4ff2b331d32ba1e3152f";
		// 生成流水
		PaymentRecord paymentRecord = new PaymentRecord();
		String runningNumber = SysCodeUtil.getPayRunningNumber();
		paymentRecord.setRunningNumber(runningNumber);
		paymentRecord.setMemberCode(orderDetail.getMemberCode());
		paymentRecord.setPaymentState("2");
		paymentRecord.setPaymentWay(paymentWay);
		paymentRecord.setPaymentTime(now);
		paymentRecord.setPrice(price);
		paymentRecord.setChargingItemNum(1);
		paymentRecord.setPaymentAmount(price);
		paymentRecord.setBusinessId(orderDetail.getBusinessIds());
		paymentRecord.setChargingItemId(chargingItemId);
		paymentRecord.setRemarks(
				"赛事报名退费手续费--date" + DateUtils.formatDateTime(now) + "userid:" + UserUtils.getLoginUser().getId());
		ShowApply showApply = showApplyDao.getByRunningNumber(orderDetail.getOrderCode());
		if (showApply != null) {
			String[] split = showApply.getShowCode().split("-");
			paymentRecord.setPaymentRemarks(split[0] + split[1] + "（赛事报名退费手续费）");
		}
		paymentRecordService.newRecord(paymentRecord);
		// 生成财务拆分项
		// 查询拆分后收费项
		HashMap<String, String> ship = cabFinanceStatisticsDao.relationShipGetById(chargingItemId);
		if (ship.isEmpty() || (StringUtils.isBlank(ship.get("CKU")) && StringUtils.isBlank(ship.get("CAB")))) {
			throw new ZAException(ZAErrorCode.ZA_ERROR, "无法获取赛事报名退费手续费对应的拆分收费项");
		}
		SaPaymentDetailTotal saDetail = new SaPaymentDetailTotal();
		saDetail.setPaymentNum("1");
		saDetail.setMemberCode(orderDetail.getMemberCode());
		saDetail.setChargeDate(orderDetail.getAddTime());
		saDetail.setRunningNumber(runningNumber);
		saDetail.setPaymentMoney(price);
		saDetail.setSourceCharge(chargingItemId);
		if (!StringUtils.isBlank(ship.get("CAB"))) {
			saDetail.setType(PAYMENT_TYPE_CAB);
			saDetail.setChargeItemId(ship.get("CAB"));
		}
		saDetail.setPrice(price);
		saDetail.setRecordId(paymentRecord.getId());
		saDetail.setPaymentTime(now);
		saDetail.setDeptId(ship.get("dept"));
		saDetail.setChargeGroupId(orderDetail.getBusinessId());
		saDetail.setPaymentWay(paymentWay);
		saDetail.setPayMemberCode(orderDetail.getMemberCode());
		saDetail.setRemarks(
				"赛事报名退费手续费--date" + DateUtils.formatDateTime(now) + "userid:" + UserUtils.getLoginUser().getId());
		saDetail.preInsert();
		saPaymentDetailTotalDao.insert(saDetail);
		// 改为已完成
		saPaymentDetailTotalDao.updateRevenueRecognition(saDetail.getId(), now);
		// 余额变动记录
		Member member = memberService.getByMemberCode(orderDetail.getMemberCode());
		int resultChange = memberDao.insertSysAccountBalanceChange(orderDetail.getMemberCode(), runningNumber,
				String.valueOf(member.getAccountBalance()), "-" + saDetail.getPaymentMoney());
		if (resultChange <= 0) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PAYMENTRECORD_MEMBERUPDATEFAIL_STATE, "增加余额变动记录失败！");
		}
	}

	private void saveCouponsState(List<PaymentOrderDetail> details, Set<String> couponSet) {
		// 得到所有该退回的优惠券的target_id
		Set<String> couponDetails = details.stream().filter(detail -> couponSet.contains(detail.getChargingItemId()))
				.map(PaymentOrderDetail::getBusinessIds).collect(Collectors.toSet());
		if (couponDetails.size() > 0) {
			SysCoupon vo = new SysCoupon();
			vo.preUpdate();
			sysCouponDao.refundCoupon(vo, couponDetails);
			sysCouponDao.refundCouponById(vo, couponDetails);
		}
	}

	private void saveBusinessState(List<PaymentOrderDetail> details) {
		// 部分业务有关联两套表 先对只涉及一张表的部分进行聚合，提高效率
		Map<String, Set<String>> map = details.stream()
				.filter(s -> StringUtils.isNotEmpty(s.getBusinessTable()) && StringUtils.isNotEmpty(s.getBusinessIds()))
				.collect(Collectors.groupingBy(PaymentOrderDetail::getBusinessTable,
						Collectors.mapping(PaymentOrderDetail::getBusinessIds, Collectors.toSet())));
		String businessTable = "";
		String orderCode = details.get(0).getOrderCode();
		for (Entry<String, Set<String>> m : map.entrySet()) {
			businessTable = m.getKey();
			Set<String> businessIds = new HashSet<>();
			// 兼容businessId 为逗号分隔的多个业务项情况
			m.getValue().forEach(id -> {
				if (id.contains(",")) {
					businessIds.addAll(Arrays.asList(id.split(",")));
				} else {
					businessIds.add(id);
				}
			});
			if ("sys_coupon".equals(businessTable)) {
				continue;
			} else if ("dog_birth_certificate".equals(businessTable)) {
				DogBirthCertificate vo = new DogBirthCertificate();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				vo.setRunningNumber(orderCode);
				dogbirthcertificatedao.refundDogBirthCertificate(vo, businessIds);
				List<DogSecondBreeder> list = dogSecondBreederDao.getByBreedCertifiedCodes(businessIds);
				if (!Collections3.isEmpty(list)) {
					for (DogSecondBreeder dogSecondBreeder : list) {
						if (orderCode.equals(dogSecondBreeder.getRunningNumber())) {

							dogSecondBreeder.setReviewState("3");
							dogSecondBreeder.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
							dogSecondBreeder.preUpdate();
							dogSecondBreederDao.update(dogSecondBreeder);
						}
					}
				}
			} else if ("show_champion_login".equals(businessTable)) {
				ChampionLogin vo = new ChampionLogin();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				championLoginDao.refundShowChampionLogin(vo, businessIds);
			} else if ("dog_pedigree_certified_redo".equals(businessTable)) {
				// 证书补做的业务状态跟其他不同 2是已撤销 3是不通过
				DogPedigreeCertifiedRedo vo = new DogPedigreeCertifiedRedo();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				dogpedigreecertifiedredodao.refundDogpedigreecertifiedredo(vo, businessIds);
			} else if ("groomer_register".equals(businessTable)) {
				// 【请假及取消】状态改为：是
				GroomerRegister vo = new GroomerRegister();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				vo.setLeaveCancel("1");
				groomerRegisterDao.refundGroomerRegister(vo, businessIds);
			} else if ("handler_register".equals(businessTable)) {
				// 【请假及取消】状态改为：是
				HandlerRegister vo = new HandlerRegister();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				vo.setLeaveCancel("1");
				vo.setShowLevel("2");
				handlerRegisterDao.refundHandlerRegister(vo, businessIds);
			} else if ("dog_blood_save".equals(businessTable) || "dog_dna_archive".equals(businessTable)
					|| "dog_dna_parents_compare".equals(businessTable)) {
				// 血统证书业务中，血样留存表的记录也要置为已删除
				DogBloodSave vo = new DogBloodSave();
				vo.preUpdate();
				dogBloodSaveDao.refundDogBloodSave(vo, businessIds, businessTable);
				// 金质证书中，订单中待邮寄物品删除,
				// 找到对应订单是否为金质证书业务，删除订单对应的邮寄物品
				if ("dog_dna_archive".equals(businessTable)) {
					expressQueueService.deleteByBusinessIds(businessIds);
				}
			} else if ("dog_chip".equals(businessTable)) {
				// 血统证书 整窝businessIds为fmdogBreedCertifiedCode 单只businessIds为ID
				DogChip vo = new DogChip();
				vo.preUpdate();
				vo.setRunningNumber(orderCode);
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				dogChipDao.refundDogChip(vo, businessIds);
				// 配种证明中：登记数量、出生数量、出生日期置为空
				dogNewbornDao.refundDogNewbornDaoForAll(businessIds);
				// 整窝 新生犬登记卡也要置为无效
				DogBirthCertificate vo2 = new DogBirthCertificate();
				vo2.preUpdate();
				vo2.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				dogbirthcertificatedao.refundDogBirthCertificateForAll(vo2, businessIds);
				// 如果选择了合作机构 需要把出生纸的add_user也清空
				dogbirthcertificatedao.refundDogBirthCertificateDelAddUser((String) businessIds.toArray()[0]);
				//删除血统证书订单一并删除dog_birth_certificate里的新犬主
				dao.deleteDogChipTempMember((String) businessIds.toArray()[0]);

				// 如果是整窝，需要dog_blood_save已存的记录置为无效
				DogBloodSave vo3 = new DogBloodSave();
				vo3.preUpdate();
				vo3.setRunningNumber(orderCode);
				vo3.setFmdogBreedCertifiedCode(businessIds.iterator().next());
				dogBloodSaveDao.refundDogBloodSaveFAll(vo3);
				List<DogSecondBreeder> list = dogSecondBreederDao.getByBreedCertifiedCodes(businessIds);
				if (!Collections3.isEmpty(list)) {
					for (DogSecondBreeder dogSecondBreeder : list) {
						if (orderCode.equals(dogSecondBreeder.getRunningNumber())) {
							dogSecondBreeder.setReviewState("3");
							dogSecondBreeder.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
							dogSecondBreeder.preUpdate();
							dogSecondBreederDao.update(dogSecondBreeder);
						}
					}
				}
			} else if ("show_apply".equals(businessTable)) {
				// 赛事特殊处理 1、报名截止前申请的将‘’赛前退费‘’改成‘是’；2、在报名截止后赛事开始前：将‘赛场请假’置为‘是’
				List<String> ids = new ArrayList<>(businessIds);
				ids = ids.stream().map(a -> {
					if (StringUtils.isNotEmpty(a)) {
						return a.split("#")[0];
					}
					return null;
				}).collect(Collectors.toList());
				ShowApply vo = new ShowApply();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				showApplyDao.refundShowApply(vo, ids);
			} else if ("dog_video_appraisal".equals(businessTable)) {
				// 视频鉴定退款
				List<String> ids = new ArrayList<>(businessIds);
				ids = ids.stream().map(a -> {
					if (StringUtils.isNotEmpty(a)) {
						return a.split("#")[0];
					}
					return null;
				}).collect(Collectors.toList());
				DogVideoAppraisal vo = new DogVideoAppraisal();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				dogVideoAppraisalDao.refunddogVideoAppraisal(vo, ids);
			} else if ("dog_appraisal".equals(businessTable)) {
				// 繁殖鉴定退款
				List<String> ids = new ArrayList<>(businessIds);
				ids = ids.stream().map(a -> {
					if (StringUtils.isNotEmpty(a)) {
						return a.split("#")[0];
					}
					return null;
				}).collect(Collectors.toList());
				DogAppraisal vo = new DogAppraisal();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				dogAppraisalDao.refunddogAppraisal(vo, ids);
			} else {
				DogChip vo = new DogChip();
				vo.preUpdate();
				vo.setReviewRemarks("已退款" + DateUtils.formatDateTime(new Date()));
				dao.saveBusinessState(businessTable, businessIds, vo);
			}
		}
	}

	// 不通过
	@Transactional(readOnly = false)
	public Map<String, String> refundDisagree(PaymentRefundOrderVO refundOrder) {
		Map<String, String> map = new HashMap<>();
		map.put("code", "0");
		map.put("msg", "OK");
		PaymentOrderDetail entity = new PaymentOrderDetail();
		entity.setBusinessOrderCode(refundOrder.getBusinessOrderCode());
		entity.setBusinessRefundState("1");
		List<PaymentOrderDetail> details = paymentOrderDetailDao.findList(entity);
		if (details.size() == 0) {
			map.put("code", "-1");
			map.put("msg", "未找到订单明细！");
			return map;
		}
		PaymentOrderDetail datail = details.get(0);
		if (!"1".equals(datail.getBusinessRefund()) || !"1".equals(datail.getBusinessRefundState())) {
			map.put("code", "-1");
			map.put("msg", "未找到订单明细或订单状态异常！");
			return map;
		}
		entity.setBusinessRefundState("2");
		entity.preUpdate();
		paymentOrderDetailDao.updateRefundStateByParam(entity);
		return map;
	}

	// 一键通过
	@Transactional(readOnly = false)
	public Map<String, String> refundAgreeALL(List<PaymentRefundOrderVO> refundOrders) {
		Map<String, String> map = new HashMap<>();
		map.put("code", "0");
		map.put("msg", "OK");
		for (PaymentRefundOrderVO vo : refundOrders) {
			if (StringUtils.isNotEmpty(vo.getBusinessOrderCode())) {
				map = refundAgree(vo);
				if (!"0".equals(map.get("code"))) {
					break;
				}
			}
		}
		return map;
	}

	// 提供公共查询方式，根据业务表记录得到 业务的退款状态的MAP
	public Map<String, String> getRefundStateByBusinessId(Set<String> ids) {
		if (ids != null && ids.size() > 0) {
			List<PaymentOrderDetail> list = paymentOrderDetailDao.getByBusinessIds(ids);
			Map<String, String> resultMap = new HashMap<>();
			list.forEach(p -> {
				if (p.getBusinessIds().contains(",")) {
					Arrays.asList(p.getBusinessIds().split(",")).forEach(bi -> {
						resultMap.put(bi.toString(), p.getBusinessRefundState());
					});
				} else {
					resultMap.put(p.getBusinessIds(), p.getBusinessRefundState());
				}
			});
			return resultMap;
		}
		return new HashMap<>();
	}

	// 针对几个特殊业务
	public Map<String, String> getRefundStateByBusinessIdAOrderCode(List<PaymentOrderDetailQueryVO> params) {
		if (params != null && params.size() > 0) {
			Set<String> ids = params.stream().map(a -> a.getBusinessId()).collect(Collectors.toSet());
			List<PaymentOrderDetail> list = paymentOrderDetailDao.getByBusinessIds(ids);
			Set<String> conditions = params.stream().map(a -> a.getBusinessId() + a.getOrderCode())
					.collect(Collectors.toSet());

			return list.stream().filter(a -> conditions.contains(a.getBusinessIds() + a.getOrderCode()))
					.collect(Collectors.toMap(a -> a.getBusinessIds() + a.getOrderCode(),
							PaymentOrderDetail::getBusinessRefundState, (key1, key2) -> key2));
		}
		return new HashMap<>();
	}

	// 根据业务ID和订单编号查询退款状态
	public String getRefundStateByBusinessIdAOrderCode(String businessIds, String orderCode) {
		PaymentOrderDetail entity = new PaymentOrderDetail();
		entity.setBusinessIds(businessIds);
		entity.setOrderCode(orderCode);
		// 尝试解决OOM
		if (StringUtils.isBlank(businessIds) && StringUtils.isBlank(orderCode)) {
			return null;
		}
		List<PaymentOrderDetail> list = paymentOrderDetailDao.findList(entity);
		if (!CollectionUtils.isEmpty(list)) {
			return list.get(0).getBusinessRefundState();
		}
		return null;
	}

	public boolean getCanCanceledByBusinessIdAOrderCode(String businessIds, String orderCode) {
		String refundState = this.getRefundStateByBusinessIdAOrderCode(businessIds, orderCode);
		return refundState == null || "2".equals(refundState) ? Boolean.TRUE : Boolean.FALSE;
	}

	// 针对血液留存区分整窝和单只
	public Map<String, String> getRefundStateForDogBloodSave(List<PaymentOrderDetailQueryVO> params) {
		// 根据ID 和fmdogBreedCertifiedCode 查出所有数据，再根据单号过滤
		if (params != null && params.size() > 0) {
			Set<String> ids = params.stream().map(a -> a.getBusinessId()).collect(Collectors.toSet());
			Set<String> fmdogBreedCertifiedCodes = params.stream().map(a -> a.getFmdogBreedCertifiedCode())
					.collect(Collectors.toSet());
			ids.addAll(fmdogBreedCertifiedCodes);
			List<PaymentOrderDetail> list = paymentOrderDetailDao.getByBusinessIds(ids);
			Set<String> conditions = params.stream().map(a -> a.getBusinessId() + a.getOrderCode())
					.collect(Collectors.toSet());
			Set<String> conditions2 = params.stream().map(a -> a.getFmdogBreedCertifiedCode() + a.getOrderCode())
					.collect(Collectors.toSet());

			return list.stream()
					.filter(a -> conditions.contains(a.getBusinessIds() + a.getOrderCode())
							|| conditions2.contains(a.getBusinessIds() + a.getOrderCode()))
					.collect(Collectors.toMap(a -> a.getBusinessIds() + a.getOrderCode(),
							PaymentOrderDetail::getBusinessRefundState, (key1, key2) -> key2));
		}
		return new HashMap<>();
	}
	// public Page<PaymentOrder> findPageCost(Page<PaymentOrder> page, PaymentOrder
	// paymentOrder) {
	// int pageNo = page.getPageNo();
	// int pageSize = page.getPageSize();
	// paymentOrder.setPage(page);
	// page.setList(dao.findListCost(paymentOrder));
	// if((pageNo-1)*pageSize>=page.getCount()){
	// page.setList(new ArrayList<PaymentOrder>(0));
	// }
	// return page;
	// }

	/**
	 * 根据订单号获得订单明细
	 * 
	 * @author yuanshuai
	 * @date 2021/5/21 14:18
	 */
	public List<PaymentOrderDetail> findOrderDetailByOrderCode(String orderCode) {
		return paymentOrderDetailDao.findByOrderCode(orderCode);
	}

	/**
	 * 根据订单号获得订单明细
	 * 
	 * @author yuanshuai
	 * @date 2021/5/21 14:18
	 */
	public List<PaymentOrderDetail> findOrderDetailByOrderCodes(List<String> orderCodes) {
		return paymentOrderDetailDao.findByOrderCodes(orderCodes);
	}

	public int getShowRefundCount() {
		PaymentRefundOrderVO vo = new PaymentRefundOrderVO();
		vo.setDepartment("赛事服务");
		vo.setBusinessRefundState("1");
		List<PaymentRefundOrderVO> list = dao.findRefundListPage(vo);
		return CollectionUtils.isEmpty(list) ? 0 : list.size();
	}

	/**
	 * 建立只有一条明细的简单订单信息--前台订单
	 * 
	 * @param member
	 * @param shortName
	 * @param businessIds
	 * @param businessTable
	 * @param source        来源
	 * @return
	 */
	public PaymentOrder saveOrderForOneDetail(Member member, String shortName, String businessIds, String businessTable,
			String source, String paymentWay, String businessId) {
		PaymentChargingItem item = paymentChargingItemDao.getByShortName(shortName);
		if (item == null) {
			throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "收费项没有找到！");
		}
		String orderCode = SysCodeUtil.getPayRunningNumberWithMemberCode(member.getMemberCode());
		Date now = new Date();
		// 生成订单明细
		PaymentOrderDetail detail = new PaymentOrderDetail();
		detail.setOrderCode(orderCode);
		detail.setAddTime(now);
		detail.setProccessState("1");
		detail.setProccessTime(now);
		detail.setChargingItemId(item.getId());
		detail.setChargingItemName(item.getName());
		detail.setPrice(item.getPrice());
		detail.setTotalPrice(item.getPrice());
		detail.setNum("1");
		detail.setBusinessIds(businessIds);
		detail.setBusinessTable(businessTable);
		detail.setMemberCode(member.getMemberCode());
		detail.setMemberName(member.getName());
		if (StringUtil.isNullOrEmpty(businessId)) {
			throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, businessId + "业务名字不存在");
		}
		SaFinanceSubjectMapping bizId = saFinanceSubjectMappingService.get(businessId);
		if (bizId == null) {
			throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, businessId + "业务名字不存在");
		}
		detail.setBusinessId(businessId);
		detail.setBusinessName(bizId.getSubjectName());
		detail.setBusinessRefund(bizId.getBusinessRefund());
		detail.preInsert();
		paymentOrderDetailDao.insert(detail);
		// 生成订单
		PaymentOrder order = new PaymentOrder();
		order.setSource(StringUtils.isBlank(source) ? member.getLoginType() : source);
		order.setPaymentWay(paymentWay);
		order.setOrderCode(orderCode);
		order.setAddTime(now);
		order.setLocked("0");
		order.setTotalPrice(item.getPrice());
		order.setPaymentState("1");
		order.setPaymentTime(now);
		order.setMemberCode(member.getMemberCode());
		order.setMemberName(member.getName());
		order.setReceiver(member.getName());
		order.setReceiveAddress(member.getAddress());
		order.setReceiveCity(member.getCity());
		order.setReceiveProvince(member.getProvince());
		order.setReceiveDel(member.getMobile());
		order.setReceivePostCode(member.getPostcode());
		order.preInsert();
		paymentOrderDao.insert(order);
		return order;

	}

	public PaymentOrder getByIdForUpdate(String id) {
		return dao.getByIdForUpdate(id);
	}

	/**
	 * 通过表名和订单号查找对应的业务ID
	 * 
	 * @author yuanshuai
	 * @date 2023/6/19 17:03
	 */
	public String findBusinessIdsByTableNameAndOrderCode(String tableName, String orderCode) {
		if (StringUtils.isBlank(tableName) || StringUtils.isBlank(orderCode)) {
			throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "表名或订单号为空,请先配置后使用");
		}
		return dao.findBusinessIdsByTableNameAndOrderCode(tableName, orderCode);
	}

	@Transactional(readOnly = false)
	public void saveOrder(PaymentOrder paymentOrder, Double orderTotal, Date addTime) {
		// 插入订单
		String runningNumber = SysCodeUtil.getPayRunningNumberWithMemberCode(paymentOrder.getMemberCode());
		Member member = memberDao.getByMemberCode(paymentOrder.getMemberCode());
		// 校验是否会员已冻结
		if ("1".equals(member.getFreezeFlag()) && !member.getMemberCode().contains("HZ")) {
			throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "会员已被冻结,无法生成订单");
		}
		paymentOrder.setOrderCode(runningNumber);
		paymentOrder.setAddTime(addTime);
		paymentOrder.setLocked("0");
		paymentOrder.setTotalPrice(orderTotal.toString());
		paymentOrder.setPaymentState("1");
		paymentOrder.setSource("oa");
		paymentOrder.preInsert();
		paymentOrderDao.insert(paymentOrder);
	}

	@Transactional(readOnly = false)
	public void balPay(PaymentOrder paymentOrder) {
		// 充值订单不能使余额支付
		if ("1".equals(paymentOrder.getIsRecharge())) {
			throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "充值订单不能使余额支付");
		}
		// 扣除用户的余额
		paymentOrder.setPaymentWay("25");// 25代表余额支付
		memberService.memberCharge(paymentOrder.getMemberCode(), paymentOrder.getTotalPrice(),
				paymentOrder.getOrderCode());
	}

	public List<PaymentOrder> findByRunningMembers(List<String> runningNumbers) {
		logger.info("PaymentOrderService findByRunningMembers param : {}",
				JSONObjectUtils.toJsonString(runningNumbers));
		List<PaymentOrder> byRunningNumbers = dao.getByRunningNumbers(runningNumbers);
		logger.info("PaymentOrderService findByRunningMembers result : {}",
				JSONObjectUtils.toJsonString(byRunningNumbers));
		return byRunningNumbers;
	}

}