/*
 * Copyright (C), 2002-2015, 江苏三六五网络股份有限公司
 * FileName: ExchangeUserLoginInterfaceImpl.java
 * Author:   Administrator
 * Date:     2015年5月5日 下午2:57:41
 * Description: //模块目的、功能描述
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.house365.ws.interfaces.rest;

import com.google.common.base.Strings;
import com.house365.beans.entity.*;
import com.house365.beans.system.QueryParams;
import com.house365.beans.vo.CmOrderVo;
import com.house365.rest.context.CmConstant;
import com.house365.rest.context.Parameter;
import com.house365.rest.exception.IllegalServiceParameterException;
import com.house365.rest.exception.ServiceRunException;
import com.house365.ws.cached.RedisUtilsInterface;
import com.house365.ws.dao.interfaces.ICmCreditRuleDao;
import com.house365.ws.dao.interfaces.ICmSeckillBookedDao;
import com.house365.ws.interfaces.impl.CmSmsCodeImpl;
import com.house365.ws.service.interfaces.*;
import com.house365.ws.system.ReturnAppResult;
import com.house365.ws.util.CmCommonUtils;
import com.house365.ws.util.DateUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author Administrator
 * @version [版本号, 2015年5月5日]
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Component("orderSubmitInterface")
public class OrderSubmitInterfaceImpl implements IOrderSubmitInterface {
    static final String lockKey = "order:lock";
    /**
     * 日志记录器
     */
    private static final Logger LOGGER = LoggerFactory.getLogger("InterfaceLog");
    /**
     * 接口参数手机号码
     */
    private static final String PHONE = "phone";
    /**
     * 购买商品Id
     */
    private static final String GOODSID = "goodsId";
    /**
     * 购买商品数量
     */
    private static final String GOODSNUMBER = "goodsNumber";
    /**
     * 定义常量
     */
    public static final String[] CreditGoodsDetails = {PHONE, GOODSID, GOODSNUMBER};
    /**
     * 接口参数手机号码
     */
    private static final String SMSCODE = "smsCode";
    /**
     * 非必传字段，收货人姓名
     */
    private static final String RECEIVERNAME = "receiverName";
    /**
     * 非必传字段，收货人手机
     */
    private static final String RECEIVERPHONE = "receiverPhone";
    /**
     * 非必传字段，收货地区
     */
    private static final String DELIVERPOSITION = "deliverPosition";
    /**
     * 非必传字段，收货人详细地址
     */
    private static final String DELIVERDETAILADDRESS = "deliverDetailAddress";
    /**
     * 非必传字段，邮编
     */
    private static final String ZIPCODE = "zipCode";
    @Autowired
    ICmPromotionProductService promotionProductService;
    @Autowired
    ICmPromotionService promotionService;
    @Autowired
    RedisUtilsInterface redisUtils;
    /**
     * 周期内最多订单数, 默认2次
     */
    @Value("#{system.orderLimitCount}")
    private Integer ORDER_LIMIT_COUNT = 0;
    @Autowired
    private ICmOrderService<CmOrderEntity> cmOrderService;
    @Autowired
    private ICmSmsCodeService<CmSmsCodeEntity> cmSmsCodeService;
    @Autowired
    private ICmUserService<CmUserEntity> cmUserService;
    @Autowired
    private ICmCreditGoodsService<CmCreditGoodsEntity> creditGoodsService;
    @Autowired
    private ICmDeliveryAddressService<CmDeliveryAddressEntity> deliveryAddressService;
    @Autowired
    private ICmCreditRuleDao<CmCreditRuleEntity> cmCreditRuleDao;
    @Autowired
    private ICmSeckillBookedDao<CmSeckillBookedEntity> secKillBoockedDao;

    public static String parseDate(Date date, String format) {
        SimpleDateFormat dateformat = new SimpleDateFormat(format);
        return dateformat.format(date);
    }

    public static Date parseDate(String datestr, String format) {
        SimpleDateFormat df = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = df.parse(datestr);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    @Override
    public synchronized Object exectue(Parameter parameter) throws ServiceRunException {
        // 取得所需参数
        Map<String, Object> map = parameter.getArgs();
        Map<String, Object> response = new HashMap<>();
        // 业务校验统一入口
        try {
            CmCommonUtils.checkInterfaceParameter(CreditGoodsDetails, map);
        } catch (IllegalServiceParameterException e) {
            response.put("result", ReturnAppResult.APP_FAIL.getResultCode());
            response.put("msg", e.getMessage());
            return JSONObject.fromObject(response).toString();
        }
        // 业务层统一处理
        try {
            Map<String, Object> data = doBusiness(map);
            Integer orderCode = Integer.parseInt(data.get("orderCode").toString());
            if (orderCode == 10000) {
                response.put("data", data);
                response.put("result", ReturnAppResult.APP_SUCCESS.getResultCode());
                response.put("msg", ReturnAppResult.APP_SUCCESS.getResultMessage());
            } else {
                response.put("result", ReturnAppResult.APP_FAIL.getResultCode());
                response.put("msg", data.get("msg").toString());
            }
        } catch (ServiceRunException e) {
            response.put("result", ReturnAppResult.APP_FAIL.getResultCode());
            response.put("msg", e.getMessage());
        }

        return JSONObject.fromObject(response).toString();
    }

    /**
     * 业务层统逻辑处理
     *
     * @param map 下单参数
     * @return 统一返回参数
     * @throws ServiceRunException
     * @since [产品/模块版本](可选)
     */
    @SuppressWarnings("null")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    protected Map<String, Object> doBusiness(Map<String, Object> map) throws ServiceRunException {
        // 返回Json对象
        Map<String, Object> resultMap = new HashMap<>();
        CmOrderEntity orderEntity = new CmOrderEntity();
        CmUserEntity userEntity;
        CmCreditRecordEntity creditRecordEntity = new CmCreditRecordEntity();
        /**
         * 入参：用户Id,用户手机,购买商品Id,购买商品数据,手机验证码,
         * 收货信息(收货人姓名receiver_name,收货人手机receiver_phone,地区deliver_position 送货详细地址deliver_detail_address,邮编zip_code)
         * 验证手机验证码
         * 验证用户积分是否够兑换该商品
         * 验证库存是否够用户兑换
         * 新增或更新收货地址
         * 提交兑换后，新增订单表，更新货物表库存，用户表中用户积分，积分明细表积分记录（统一控制在同一事务中）
         */
        try {
            String userId = ((String[]) map.get(CmConstant.USER_ID))[0];
            if (StringUtils.isBlank(userId)) {
                throw new ServiceRunException("该用户ID不存在!");
            }

            // 查询参数
            Integer userIdType = Integer.parseInt(((String[]) map.get(CmConstant.USERID_TYPE))[0]);
            String cityKey = CmCommonUtils.getCityFromMap(map);
            userEntity = cmUserService.getUserByUserIdCityKeyUserType(userId, cityKey, userIdType);
            if (userEntity == null) {
                throw new ServiceRunException("该用户不存在!");
            }

            //一次只能处理一个订单,本地一次订单入库大概需要90ms,如有超卖问题，可适当调整持有锁的时间
            while (true) {
                long time = System.currentTimeMillis() + 30;
                boolean isNotLock = redisUtils.setNotExists(lockKey, time + "");
                if (isNotLock || (redisUtils.getValByKeyNew(
                    lockKey) != null && System.currentTimeMillis() > Long.parseLong(
                    redisUtils.getValByKeyNew(lockKey)) && System.currentTimeMillis() > Long.parseLong(
                    redisUtils.getSet(lockKey, time + "")))) {
                    LOGGER.debug("===== Get LOCK ");
                    break;
                } else {
                    Thread.sleep(35);
                }
            }

            long start = System.currentTimeMillis();


            if (!Strings.isNullOrEmpty(cityKey) && Strings.isNullOrEmpty(userEntity.getCityId())) {
                userEntity.setCityId(cityKey);
            }

            Integer uid = userEntity.getId();

            String phone = ((String[]) map.get(PHONE))[0];
            String goodsId = ((String[]) map.get(GOODSID))[0];
            String goodsNumber = ((String[]) map.get(GOODSNUMBER))[0];
            String smsCode = map.containsKey(SMSCODE) ? ((String[]) map.get(SMSCODE))[0] : "";

            String receiverName = null;
            String receiverPhone = null;
            String deliverPosition = null;
            String deliverDetailAddress = null;
            String zipCode = null;

            if (map.get(RECEIVERNAME) != null) {
                receiverName = ((String[]) map.get(RECEIVERNAME))[0];
            }
            if (map.get(RECEIVERPHONE) != null) {
                receiverPhone = ((String[]) map.get(RECEIVERPHONE))[0];
            }
            if (map.get(DELIVERPOSITION) != null) {
                deliverPosition = ((String[]) map.get(DELIVERPOSITION))[0];
            }
            if (map.get(DELIVERDETAILADDRESS) != null) {
                deliverDetailAddress = ((String[]) map.get(DELIVERDETAILADDRESS))[0];
            }
            if (map.get(ZIPCODE) != null) {
                zipCode = ((String[]) map.get(ZIPCODE))[0];
            }

            CmCreditGoodsEntity creditGoodsEntity = null;
            if (Strings.isNullOrEmpty(userId) || Strings.isNullOrEmpty(phone) || Strings.isNullOrEmpty(
                goodsId) || Strings.isNullOrEmpty(goodsNumber) || Strings.isNullOrEmpty(smsCode)) {
                creditGoodsEntity = creditGoodsService.getById(Integer.valueOf(goodsId));
                //第三方商品不需要验证码
                if (!"2".equalsIgnoreCase(creditGoodsEntity.getGoodsType())) {
                    throw new Exception("无效的参数 !!!");
                }
            }

            CmOrderVo orderVo = new CmOrderVo();
            //根据商品Id获取兑换商品积分
            if (creditGoodsEntity == null) {
                creditGoodsEntity = creditGoodsService.getById(Integer.valueOf(goodsId));
            }

            //每个用户每个月只能兑换两次
            //获取当月的次数
            if (1 == creditGoodsEntity.getIsBuyLimit() && cmOrderService.isOrderOutOfLimits(userEntity)) {
                throw new ServiceRunException("30天内只能兑换" + ORDER_LIMIT_COUNT + "次哟!");
            }
            CmSmsCodeEntity smsCodeEntity = null;
            if (!"2".equalsIgnoreCase(creditGoodsEntity.getGoodsType())) {
                //根据手机号校验手机验证码
                smsCodeEntity = cmSmsCodeService.getByPhone(phone);
                if (smsCodeEntity == null || smsCodeEntity.getSendTime() == null) {
                    throw new Exception("手机" + phone + "验证码不存在 !!!");
                }
            }

            //校验手机验证码是否过期，判定时间 (n分钟内有效)，未超过n分钟的情况 此处设置6分钟是因为短信发送会有点延时
            if ("2".equalsIgnoreCase(creditGoodsEntity.getGoodsType()) || CmSmsCodeImpl.exitInMinuteTime(
                smsCodeEntity.getSendTime(), 6) && smsCode.equals(smsCodeEntity.getAuthCode())) {

                if (creditGoodsEntity == null || 1 == creditGoodsEntity.getStatus()) {
                    return returnWithFail(resultMap, userId, "该商品已下架！");
                }

                //2018.6.13产品赵健知会去掉根据虚拟商品有效期下架的判断，只保留商品状态的判断 by wenjiaxin
//                if (creditGoodsEntity.getEndTime() != null && creditGoodsEntity.getEndTime().before(new Date())) {
//                    return returnWithFail(resultMap, userId, "该商品已下架！");
//                }

                if (creditGoodsEntity.getStock() <= 0 || creditGoodsEntity.getStock() < Integer.valueOf(goodsNumber)) {
                    return returnWithFail(resultMap, userId, "该商品库存不足！");
                }

                //userEntity = cmUserService.getById(uid);

                if (null == creditGoodsEntity.getCreditsNeeded()) {
                    return returnWithFail(resultMap, userId, "该商品未设置兑换积分值！");
                }

                if (null == userEntity.getCredits()) {
                    return returnWithFail(resultMap, userId, "用户积分不足！");
                }

                //商品可用的促销信息
                HashMap<String, HashMap> promotions = promotionProductService.getProductHitPromotions(
                    creditGoodsEntity.getId());
                if (null != promotions && !promotions.isEmpty() && promotions.containsKey("1")) {
                    //用户是否命中新人专享
                    if (!promotionProductService.checkUserIsHitNewUserPromotion(promotions, userId)) {
                        return returnWithFail(resultMap, userId, String.valueOf(promotions.get("1").get("msg")));
                    }
                }

                CmCreditRuleEntity cmCreditRuleEntity = cmCreditRuleDao.getById(CmConstant.CREDITS_RULE_EXCHANGE_GOODS);
                if (cmCreditRuleEntity == null) {
                    throw new ServiceRunException("兑换规则不存在!");
                }
                String ruleName = cmCreditRuleEntity.getCreditRuleName();

                //用户所持有积分
                Integer userIntegral = userEntity.getCredits();
                //商品兑换所需积分
                Integer goodsIntegral = creditGoodsEntity.getCreditsNeeded();
                //兑换商品消耗总积分
                Integer consumptionTotalIntegral = goodsIntegral * Integer.valueOf(goodsNumber);

                if (userIntegral < consumptionTotalIntegral) {
                    return returnWithFail(resultMap, userId, "用户积分不足！");
                }

                //用户剩余积分
                Integer userSurplusIntegral = userIntegral - consumptionTotalIntegral;

                //判断商品是否为秒杀商品, 待订单成功增加缓存中下单个数
                Integer secKillId = null;
                Integer isSecKill = creditGoodsEntity.getIsSeckill();
                boolean isSeckillPorduct = false;

                if (isSecKill != null && 1 == isSecKill) {
                    isSeckillPorduct = true;
                    //判断是否有秒杀锁定记录
                    QueryParams<CmSeckillBookedEntity> queryParams1 = new QueryParams<>();
                    Map<String, Object> map1 = new HashMap<>();
                    map1.put("EQ_goodId", creditGoodsEntity.getId());
                    map1.put("EQ_userId", userId);
                    queryParams1.setSearchParams(map1);
                    List<CmSeckillBookedEntity> skList = secKillBoockedDao.queryAll(queryParams1);

                    // 必须有锁定记录并且在秒杀时间内
                    // 有秒杀记录则可以下单,无须判断秒杀时间   2016-06-30
                    //                    if (skList.isEmpty() || creditGoodsEntity.getSeckillEndTime().compareTo(new Date()) < 0) {
                    if (skList.isEmpty()) {
                        return returnWithFail(resultMap, userId, "秒杀已结束!");
                    }

                    if (skList != null && !skList.isEmpty()) {
                        secKillId = skList.get(0).getId();
                    }

                }

                //set is seckill order
                orderEntity.setIsSeckill(isSeckillPorduct ? 1 : 0);

                //实物商品
                if ("0".equals(creditGoodsEntity.getGoodsType())) {
                    resultMap = saveProductOrder(orderEntity, userEntity, creditRecordEntity, uid, goodsId, goodsNumber,
                                                 receiverName, receiverPhone, deliverPosition, deliverDetailAddress,
                                                 zipCode, creditGoodsEntity, orderVo, smsCodeEntity, ruleName,
                                                 consumptionTotalIntegral, userSurplusIntegral, secKillId, isSecKill);

                } else if ("1".equals(creditGoodsEntity.getGoodsType())) {
                    //虚拟商品
                    resultMap = saveVirtualOrder(orderEntity, userEntity, creditRecordEntity, uid, goodsId, goodsNumber,
                                                 receiverName, receiverPhone, deliverPosition, deliverDetailAddress,
                                                 zipCode, creditGoodsEntity, orderVo, smsCodeEntity, ruleName,
                                                 consumptionTotalIntegral, userSurplusIntegral, secKillId, isSecKill);

                } else if ("2".equals(creditGoodsEntity.getGoodsType())) {
                    resultMap = saveThirdProductOrder(orderEntity, userEntity, creditRecordEntity, uid, goodsId,
                                                      goodsNumber, receiverName, receiverPhone, deliverPosition,
                                                      deliverDetailAddress, zipCode, creditGoodsEntity, orderVo,
                                                      smsCodeEntity, ruleName, consumptionTotalIntegral,
                                                      userSurplusIntegral, secKillId, isSecKill);
                }
            } else {
                //验证码失效
                resultMap.put("orderCode", -10000);
                resultMap.put("msg", "验证码失效！");
            }

            LOGGER.debug("===== 订单提交成功! USE {} MS", System.currentTimeMillis() - start);
            //移除订单提交标记
            return resultMap;
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
            throw new ServiceRunException(ex.getMessage());
        } finally {
            //移除订单提交标记
            LOGGER.debug("===== 移除订单提交标记!");
            redisUtils.deleteKey(lockKey);
        }
    }

    //虚拟商品
    private Map<String, Object> saveVirtualOrder(
        CmOrderEntity orderEntity, CmUserEntity userEntity, CmCreditRecordEntity creditRecordEntity, Integer uid,
        String goodsId, String goodsNumber, String receiverName, String receiverPhone, String deliverPosition,
        String deliverDetailAddress, String zipCode, CmCreditGoodsEntity creditGoodsEntity, CmOrderVo orderVo,
        CmSmsCodeEntity smsCodeEntity, String ruleName, Integer consumptionTotalIntegral, Integer userSurplusIntegral,
        Integer secKillId, Integer isSecKill
    ) throws ServiceRunException {
        Map<String, Object> resultMap;//组装订单信息
        orderEntity.setCreateTime(new Date());
        orderEntity.setUserId(uid);
        orderEntity.setUserName(userEntity.getUserName());
        orderEntity.setUserPhone(userEntity.getPhoneNumber());
        orderEntity.setDeliverType("虚拟商品");
        orderEntity.setDeliverTime(creditGoodsEntity.getStartTime());
        orderEntity.setReceiveTime(creditGoodsEntity.getEndTime());
        orderEntity.setReceiverName(receiverName);
        orderEntity.setReceiverPhone(receiverPhone);
        orderEntity.setReceiverArea(deliverPosition);
        orderEntity.setReceiverDetailAddress(deliverDetailAddress);
        orderEntity.setReceiverZipCode(zipCode);
        orderEntity.setCredits(consumptionTotalIntegral);//消耗的n件商品的总积分
        orderEntity.setOrderStatus(1);//待发货
        orderEntity.setCityId(creditGoodsEntity.getCityId());
        orderEntity.setCityName(creditGoodsEntity.getCityName());
        orderEntity.setIsDeleted(0);
        orderEntity.setGoodsId(Integer.valueOf(goodsId));
        orderEntity.setGoodsName(creditGoodsEntity.getGoodsName());
        orderEntity.setGoodsType(1);//虚拟
        orderEntity.setGoodsAmount(Integer.valueOf(goodsNumber));
        orderEntity.setGoodsPicture(creditGoodsEntity.getSmallListPicture());
        orderEntity.setGoodsCreditAmount(creditGoodsEntity.getCreditsNeeded());//商品积分
        orderEntity.setGoodsTotalCreditAmount(consumptionTotalIntegral);//消耗的n件商品的总积分
        orderEntity.setCityKey(creditGoodsEntity.getCityKey());
        orderEntity.setCityName(creditGoodsEntity.getCityName());
        orderVo.setEntity(orderEntity);

        //组装更新用户信息
        userEntity.setCredits(userSurplusIntegral);
        orderVo.setUserEntity(userEntity);

        //组装更新货物表库存
                                        /*Integer surplusStock = creditGoodsEntity.getStock()-Integer.valueOf(goodsNumber);//剩余库存
                                        creditGoodsEntity.setStock(surplusStock);*/
        orderVo.setCreditGoodsEntity(creditGoodsEntity);

        //组装积分明细记录
        creditRecordEntity.setUserId(uid);
        creditRecordEntity.setUserName(userEntity.getUserName());
        creditRecordEntity.setUserPhone(userEntity.getPhoneNumber());
        creditRecordEntity.setGoodsId(Integer.valueOf(goodsId));
        creditRecordEntity.setGoodsName(creditGoodsEntity.getGoodsName());
        creditRecordEntity.setRuleId(CmConstant.CREDITS_RULE_EXCHANGE_GOODS);
        creditRecordEntity.setRuleName(ruleName);
        creditRecordEntity.setOrderId(null);//订单号暂时没有，到下层拿
        creditRecordEntity.setAmount(-consumptionTotalIntegral);//兑换商品消耗积分数量
        creditRecordEntity.setRemainingAmount(userSurplusIntegral);//积分余额
        creditRecordEntity.setHappenTime(new Date());
        creditRecordEntity.setCityId(creditGoodsEntity.getCityId());
        creditRecordEntity.setCityName(userEntity.getCity());
        orderVo.setCreditRecordEntity(creditRecordEntity);
        //提交兑换后，新增订单表，更新货物表库存，用户表中用户积分，积分明细表积分记录（统一控制在同一事务中）
        resultMap = cmOrderService.transUpdateOrderStockIntegral(orderVo);
        //禁用验证码
        disableSmsCode(smsCodeEntity);
        if ("10000".equals(resultMap.get("orderCode").toString())) {
            //如果是秒杀商品，则需要去除预定记录
            if (isSecKill != null && isSecKill == 1) {
                deleteSeckillBook(secKillId);
                redisUtils.increaseByKey(CmConstant.ORDER_COUNT + creditGoodsEntity.getId());
            }
        }
        return resultMap;
    }

    //第三方商品订单
    private Map<String, Object> saveThirdProductOrder(
        CmOrderEntity orderEntity, CmUserEntity userEntity, CmCreditRecordEntity creditRecordEntity, Integer uid,
        String goodsId, String goodsNumber, String receiverName, String receiverPhone, String deliverPosition,
        String deliverDetailAddress, String zipCode, CmCreditGoodsEntity creditGoodsEntity, CmOrderVo orderVo,
        CmSmsCodeEntity smsCodeEntity, String ruleName, Integer consumptionTotalIntegral, Integer userSurplusIntegral,
        Integer secKillId, Integer isSecKill
    ) throws ServiceRunException {
        Map<String, Object> resultMap;//校验收货地址

        //组装订单信息
        orderEntity.setCreateTime(new Date());
        orderEntity.setUserId(uid);
        orderEntity.setUserName(userEntity.getUserName());
        orderEntity.setUserPhone(userEntity.getPhoneNumber());
        orderEntity.setDeliverType("第三方提供");
        orderEntity.setDeliverTime(creditGoodsEntity.getStartTime());
        orderEntity.setReceiveTime(creditGoodsEntity.getEndTime());
        orderEntity.setReceiverName(receiverName);
        orderEntity.setReceiverPhone(receiverPhone);
        orderEntity.setReceiverArea(deliverPosition);
        orderEntity.setReceiverDetailAddress(deliverDetailAddress);
        orderEntity.setReceiverZipCode(zipCode);
        orderEntity.setCredits(consumptionTotalIntegral);//消耗的n件商品的总积分
        orderEntity.setOrderStatus(1);//已完成
        orderEntity.setCityId(creditGoodsEntity.getCityId());
        orderEntity.setCityName(userEntity.getCity());
        orderEntity.setIsDeleted(0);
        orderEntity.setGoodsId(Integer.valueOf(goodsId));
        orderEntity.setGoodsName(creditGoodsEntity.getGoodsName());
        orderEntity.setGoodsType(2);//实物
        orderEntity.setGoodsAmount(Integer.valueOf(goodsNumber));
        orderEntity.setGoodsPicture(creditGoodsEntity.getSmallListPicture());
        orderEntity.setGoodsCreditAmount(creditGoodsEntity.getCreditsNeeded());//商品积分
        orderEntity.setGoodsTotalCreditAmount(consumptionTotalIntegral);//消耗的n件商品的总积分
        orderEntity.setCityKey(creditGoodsEntity.getCityKey());
        orderEntity.setCityName(creditGoodsEntity.getCityName());

        orderVo.setEntity(orderEntity);
        //组装更新用户信息
        userEntity.setCredits(userSurplusIntegral);
        orderVo.setUserEntity(userEntity);

        //组装更新货物表库存
        //Integer surplusStock = creditGoodsEntity.getStock()-Integer.valueOf(goodsNumber);//剩余库存
        //creditGoodsEntity.setStock(surplusStock);
        orderVo.setCreditGoodsEntity(creditGoodsEntity);
        //组装积分明细记录
        creditRecordEntity.setUserId(uid);
        creditRecordEntity.setUserName(userEntity.getUserName());
        creditRecordEntity.setUserPhone(userEntity.getPhoneNumber());
        creditRecordEntity.setGoodsId(Integer.valueOf(goodsId));
        creditRecordEntity.setRuleId(CmConstant.CREDITS_RULE_EXCHANGE_GOODS);
        creditRecordEntity.setRuleName(ruleName);
        creditRecordEntity.setGoodsName(creditGoodsEntity.getGoodsName());
        creditRecordEntity.setOrderId(null);//订单号暂时没有，到下层拿
        creditRecordEntity.setAmount(-consumptionTotalIntegral);//兑换商品消耗积分数量
        creditRecordEntity.setRemainingAmount(userSurplusIntegral);//积分余额
        creditRecordEntity.setHappenTime(new Date());
        creditRecordEntity.setCityId(creditGoodsEntity.getCityId());
        creditRecordEntity.setCityName(userEntity.getCity());
        orderVo.setCreditRecordEntity(creditRecordEntity);

        //提交兑换后，新增订单表，更新货物表库存，用户表中用户积分，积分明细表积分记录（统一控制在同一事务中）
        resultMap = cmOrderService.transUpdateOrderStockIntegral(orderVo);

        return resultMap;
    }

    //实物商品
    private Map<String, Object> saveProductOrder(
        CmOrderEntity orderEntity, CmUserEntity userEntity, CmCreditRecordEntity creditRecordEntity, Integer uid,
        String goodsId, String goodsNumber, String receiverName, String receiverPhone, String deliverPosition,
        String deliverDetailAddress, String zipCode, CmCreditGoodsEntity creditGoodsEntity, CmOrderVo orderVo,
        CmSmsCodeEntity smsCodeEntity, String ruleName, Integer consumptionTotalIntegral, Integer userSurplusIntegral,
        Integer secKillId, Integer isSecKill
    ) throws ServiceRunException {
        Map<String, Object> resultMap;//校验收货地址
        //                    if (StringUtils.isBlank(receiverName) || StringUtils.isBlank(receiverPhone) || StringUtils.isBlank(
        //                        deliverPosition) || StringUtils.isBlank(deliverDetailAddress)) {
        //                        return returnWithFail(resultMap, userId, "用户收货地址参数缺失！");
        //                    }

        //更新送货信息接口
        //                    CmDeliveryAddressEntity deliveryAddressEntity = deliveryAddressService.getByUserId(uid);
        //                    if (null == deliveryAddressEntity) {
        //未获取到收货地址则新增
        //                        deliveryAddressEntity = new CmDeliveryAddressEntity();
        //                        deliveryAddressEntity.setUserId(uid);
        //                        deliveryAddressEntity.setReceiverName(receiverName);
        //                        deliveryAddressEntity.setReceiverPhone(receiverPhone);
        //                        deliveryAddressEntity.setDeliverPosition(deliverPosition);
        //                        deliveryAddressEntity.setDeliverDetailAddress(deliverDetailAddress);
        //                        deliveryAddressEntity.setZipCode(zipCode);
        //                        deliveryAddressEntity.setIsDeleted(0);
        //                        deliveryAddressService.save(deliveryAddressEntity);
        //                    } else {
        //获取到收货地址则更新
        //                        deliveryAddressEntity.setReceiverName(receiverName);
        //                        deliveryAddressEntity.setReceiverPhone(receiverPhone);
        //                        deliveryAddressEntity.setDeliverPosition(deliverPosition);
        //                        deliveryAddressEntity.setDeliverDetailAddress(deliverDetailAddress);
        //                        deliveryAddressEntity.setZipCode(zipCode);
        //                        deliveryAddressEntity.setIsDeleted(0);
        //                        deliveryAddressService.update(deliveryAddressEntity);
        //                    }

        //组装订单信息
        orderEntity.setCreateTime(new Date());
        orderEntity.setUserId(uid);
        orderEntity.setUserName(userEntity.getUserName());
        orderEntity.setUserPhone(userEntity.getPhoneNumber());
        orderEntity.setDeliverType("");
        orderEntity.setDeliverTime(creditGoodsEntity.getStartTime());
        orderEntity.setReceiveTime(creditGoodsEntity.getEndTime());
        orderEntity.setReceiverName(receiverName);
        orderEntity.setReceiverPhone(receiverPhone);
        orderEntity.setReceiverArea(deliverPosition);
        orderEntity.setReceiverDetailAddress(deliverDetailAddress);
        orderEntity.setReceiverZipCode(zipCode);
        orderEntity.setCredits(consumptionTotalIntegral);//消耗的n件商品的总积分
        orderEntity.setOrderStatus(0);//待发货
        orderEntity.setCityId(creditGoodsEntity.getCityId());
        orderEntity.setCityName(userEntity.getCity());
        orderEntity.setIsDeleted(0);
        orderEntity.setGoodsId(Integer.valueOf(goodsId));
        orderEntity.setGoodsName(creditGoodsEntity.getGoodsName());
        orderEntity.setGoodsType(0);//实物
        orderEntity.setGoodsAmount(Integer.valueOf(goodsNumber));
        orderEntity.setGoodsPicture(creditGoodsEntity.getSmallListPicture());
        orderEntity.setGoodsCreditAmount(creditGoodsEntity.getCreditsNeeded());//商品积分
        orderEntity.setGoodsTotalCreditAmount(consumptionTotalIntegral);//消耗的n件商品的总积分
        orderEntity.setCityKey(creditGoodsEntity.getCityKey());
        orderEntity.setCityName(creditGoodsEntity.getCityName());

        orderVo.setEntity(orderEntity);
        //组装更新用户信息
        userEntity.setCredits(userSurplusIntegral);
        orderVo.setUserEntity(userEntity);

        //组装更新货物表库存
        //Integer surplusStock = creditGoodsEntity.getStock()-Integer.valueOf(goodsNumber);//剩余库存
        //creditGoodsEntity.setStock(surplusStock);
        orderVo.setCreditGoodsEntity(creditGoodsEntity);
        //组装积分明细记录
        creditRecordEntity.setUserId(uid);
        creditRecordEntity.setUserName(userEntity.getUserName());
        creditRecordEntity.setUserPhone(userEntity.getPhoneNumber());
        creditRecordEntity.setGoodsId(Integer.valueOf(goodsId));
        creditRecordEntity.setRuleId(CmConstant.CREDITS_RULE_EXCHANGE_GOODS);
        creditRecordEntity.setRuleName(ruleName);
        creditRecordEntity.setGoodsName(creditGoodsEntity.getGoodsName());
        creditRecordEntity.setOrderId(null);//订单号暂时没有，到下层拿
        creditRecordEntity.setAmount(-consumptionTotalIntegral);//兑换商品消耗积分数量
        creditRecordEntity.setRemainingAmount(userSurplusIntegral);//积分余额
        creditRecordEntity.setHappenTime(new Date());
        creditRecordEntity.setCityId(creditGoodsEntity.getCityId());
        creditRecordEntity.setCityName(userEntity.getCity());
        orderVo.setCreditRecordEntity(creditRecordEntity);

        //提交兑换后，新增订单表，更新货物表库存，用户表中用户积分，积分明细表积分记录（统一控制在同一事务中）
        resultMap = cmOrderService.transUpdateOrderStockIntegral(orderVo);

        //禁用验证码
        disableSmsCode(smsCodeEntity);
        if ("10000".equals(resultMap.get("orderCode").toString())) {
            //如果是秒杀订单，则需要去除预定记录，增加订单数量
            if (isSecKill != null && 1 == isSecKill) {
                deleteSeckillBook(secKillId);
                redisUtils.increaseByKey(CmConstant.ORDER_COUNT + creditGoodsEntity.getId());
            }
        }
        return resultMap;
    }

    private Map<String, Object> returnWithFail(Map<String, Object> resultMap, String userId, String message) {
        resultMap.put("orderCode", -10000);
        resultMap.put("msg", message);
        return resultMap;
    }

    /**
     * 让验证码失效
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param smsCodeEntity
     * @author yinchangming
     * @version [v1.0.0, 2015年11月14日]
     * @since [产品/模块版本](可选)
     */
    private void disableSmsCode(CmSmsCodeEntity smsCodeEntity) {
        smsCodeEntity.setCreateTime(DateUtils.parseDate("1980-10-10", "yyyy-MM-dd"));
        cmSmsCodeService.update(smsCodeEntity);
    }

    /**
     * 删除
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param bookId
     * @author yinchangming
     * @version [v1.0.0, 2015年12月1日]
     * @since [产品/模块版本](可选)
     */
    private void deleteSeckillBook(Integer bookId) {
        secKillBoockedDao.delete(bookId);
    }

    /**
     * 判断服务是否具有控制逻辑
     *
     * @return 是否判断
     */
    public boolean isControlService() {

        return false;
    }

    /**
     * 判断服务是否需要记录日志
     *
     * @return 是否判断
     */
    public boolean isLogService() {

        return false;
    }

    /**
     * 判断服务是否需要监控
     *
     * @return 是否判断
     */
    public boolean isMonitorService() {

        return false;
    }

    /**
     * 事务回滚
     *
     * @return 事务回滚预留结果，暂无用途
     */
    public Object rollback() {

        return null;
    }

    /**
     * 事务提交
     */
    public void commit() {

    }
}
