package com.ym.mec.biz.service.impl;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.PictureData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ym.mec.biz.dal.dao.GoodsDao;
import com.ym.mec.biz.dal.dao.GoodsProcurementDao;
import com.ym.mec.biz.dal.dao.SellOrderDao;
import com.ym.mec.biz.dal.dao.SysConfigDao;
import com.ym.mec.biz.dal.dao.TeacherDao;
import com.ym.mec.biz.dal.dto.BasicUserDto;
import com.ym.mec.biz.dal.dto.GoodsSellDto;
import com.ym.mec.biz.dal.entity.Goods;
import com.ym.mec.biz.dal.entity.GoodsProcurement;
import com.ym.mec.biz.dal.entity.SellOrder;
import com.ym.mec.biz.dal.enums.AccountType;
import com.ym.mec.biz.dal.enums.GoodsType;
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
import com.ym.mec.biz.dal.enums.SellStatus;
import com.ym.mec.biz.dal.enums.StockType;
import com.ym.mec.biz.dal.enums.TemplateTypeEnum;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;
import com.ym.mec.biz.service.GoodsService;
import com.ym.mec.biz.service.SysMessageService;
import com.ym.mec.biz.service.UploadFileService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.UploadReturnBean;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.excel.IniFileUtil;
import com.ym.mec.util.excel.POIUtil;

@Service
public class GoodsServiceImpl extends BaseServiceImpl<Integer, Goods>  implements GoodsService {
	private static final Logger LOGGER = LoggerFactory.getLogger(CourseScheduleTeacherSalaryServiceImpl.class);
	
	@Autowired
	private GoodsDao goodsDao;
	@Autowired
	private UploadFileService uploadFileService;
	@Autowired
	private IdGeneratorService idGeneratorService;
	@Autowired
	private GoodsProcurementDao goodsProcurementDao;
	@Autowired
	private SysConfigDao sysConfigDao;
	@Autowired
	private SysMessageService sysMessageService;
	@Autowired
	private TeacherDao teacherDao;
	@Autowired
	private SellOrderDao sellOrderDao;

	@Override
	public BaseDAO<Integer, Goods> getDAO() {
		return goodsDao;
	}

	@Override
	@Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
	public void addGoods(Goods goods, Integer operatorId) {
		if(StringUtils.isBlank(goods.getSn())){
			throw new BizException("请指定商品货号");
		}
		Goods existsGood = goodsDao.lockBySn(goods.getSn());
		if(Objects.nonNull(existsGood)){
			throw new BizException("商品货号重复");
		}else{
			if(Objects.isNull(goods.getStockCount())){
				goods.setStockCount(0);
			}
			if(Objects.isNull(goods.getTaxStockCount())){
				goods.setTaxStockCount(0);
			}
			goods.setSellCount(0);
			goodsDao.insert(goods);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void addGoodsProcurement(GoodsProcurement goodsProcurement) {
		Goods existsGood = goodsDao.get(goodsProcurement.getGoodsId());

		if(Objects.isNull(existsGood)){
			throw new BizException("商品不存在");
		}

		if(StringUtils.isNotBlank(existsGood.getComplementGoodsIdList())){
			throw new BizException("此商品为组合商品");
		}

		if(Objects.isNull(goodsProcurement.getStockCount())){
			goodsProcurement.setStockCount(0);
		}
		if(Objects.isNull(goodsProcurement.getTaxStockCount())){
			goodsProcurement.setTaxStockCount(0);
		}

		existsGood.setStockCount(existsGood.getStockCount()+goodsProcurement.getStockCount());
		existsGood.setTaxStockCount(existsGood.getTaxStockCount()+goodsProcurement.getTaxStockCount());
		goodsDao.update(existsGood);

		String batchNo = idGeneratorService.generatorId("payment") + "";
		goodsProcurement.setBatchNo(batchNo);
		goodsProcurement.setGoodsCategoryId(existsGood.getGoodsCategoryId());
		goodsProcurementDao.insert(goodsProcurement);

		sellOrderBatchNoAllot();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateGoodsStatus(Integer goodsId, Integer status) {
		if(Objects.isNull(goodsId)){
			throw new BizException("请指定商品");
		}
		if(Objects.isNull(status)){
			throw new BizException("请指定状态");
		}
		Goods goods = goodsDao.get(goodsId);
		if(Objects.isNull(goods)){
			throw new BizException("商品不存在");
		}
		if(StringUtils.isBlank(goods.getComplementGoodsIdList())){
			if(status==0){
				List<Goods> goodsList = goodsDao.getWithComplementGoodsAndStatus(goodsId, 1);
				if(!CollectionUtils.isEmpty(goodsList)){
					String goodsNames = StringUtils.join(goodsList.stream().map(Goods::getName).collect(Collectors.toList()));
					throw new BizException("{}等商品还在销售中", goodsNames);
				}
			}
		}else{
			if(status==1){
				List<Integer> goodsIds = Arrays.stream(goods.getComplementGoodsIdList().split(",")).map(s -> Integer.valueOf(s)).collect(Collectors.toList());
				List<Goods> goodList = goodsDao.getGoodies(goodsIds);
				List<String> goodsNames = goodList.stream().filter(g -> YesOrNoEnum.NO.equals(g.getStatus())).map(Goods::getName).collect(Collectors.toList());
				if(!CollectionUtils.isEmpty(goodsNames)){
					throw new BizException("{}商品还未上架", StringUtils.join(goodsNames));
				}
			}
		}
		goods.setStatus(status==0?YesOrNoEnum.NO:YesOrNoEnum.YES);
		goodsDao.update(goods);
	}

	@Override
	public List<Goods> findGoodsBySubId(Integer subjectId,String type) {
		return goodsDao.findGoodsBySubId(subjectId,type);
	}

	public int findGoodsNumByCategoryId(Integer goodsCategoryId){
		return goodsDao.findGoodsNumByCategoryId(goodsCategoryId);
	}

	@Override
	public List<Goods> findGoodsByIds(String ids) {
		return goodsDao.findGoodsByIds(ids);
	}

	@Override
	public List<Goods> findTypeGoods(String type) {
		return goodsDao.findTypeGoods(type);
	}

	@Override
	@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
	public List<Goods> importGoods(MultipartFile file, Integer operatorId) throws Exception {
		Map<String, List<Map<String, Object>>> sheetsListMap = POIUtil.importExcel(new ByteArrayInputStream(file.getBytes()), 2, file.getOriginalFilename());
		InputStream inputStream = new ClassPathResource("columnMapper.ini").getInputStream();
		Map<String,String> columns = IniFileUtil.readIniFile(inputStream, TemplateTypeEnum.GOODS.getMsg());
		List<Goods> goodsList = new ArrayList<>();
//		Map<String, Integer> map = MapUtil.convertIntegerMap(goodsCategoryDao.queryCategotyMap());
		Map<String, Integer> map = getMap("goods_category","name_","id_",true,String.class,Integer.class);
		for (String e : sheetsListMap.keySet()) {
			List<Map<String, Object>> sheet = sheetsListMap.get(e);
			valueIsNull: for (Map<String, Object> row : sheet) {
				if (row.size() == 0){
					continue;
				}
				JSONObject objectMap = new JSONObject();
				for (String s : row.keySet()) {
					if(!columns.containsKey(s)){
						continue;
					}
					String columnValue = columns.get(s);
					if(null == row.get(s) || StringUtils.isBlank(row.get(s).toString())){
						LOGGER.error("商品导入异常：参数{}不可为空 param:{}",columnValue,objectMap);
						continue valueIsNull;
					}
					if (columnValue.equals("type")) {
						for (GoodsType goodsType : GoodsType.values()) {
							if (goodsType.getDesc().equals(row.get(s).toString())) {
								objectMap.put(columnValue, goodsType);
								break;
							}
						}
						continue;
					}
					if (columnValue.equals("stockType")) {
						for (StockType stockType : StockType.values()) {
							if (stockType.getMsg().equals(row.get(s).toString())) {
								objectMap.put(columnValue, stockType);
								break;
							}
						}
						continue;
					}
					if (columnValue.equals("educationalShow")) {
						for (YesOrNoEnum yesOrNoEnum : YesOrNoEnum.values()) {
							if (yesOrNoEnum.getMsg().equals(row.get(s).toString())) {
								objectMap.put(columnValue, yesOrNoEnum);
								break;
							}
						}
						continue;
					}
					if (columnValue.equals("musicGroupShow")) {
						for (YesOrNoEnum yesOrNoEnum : YesOrNoEnum.values()) {
							if (yesOrNoEnum.getMsg().equals(row.get(s).toString())) {
								objectMap.put(columnValue, yesOrNoEnum);
								break;
							}
						}
						continue;
					}
					if (columnValue.equals("clientShow")) {
						for (YesOrNoEnum yesOrNoEnum : YesOrNoEnum.values()) {
							if (yesOrNoEnum.getMsg().equals(row.get(s).toString())) {
								objectMap.put(columnValue, yesOrNoEnum);
								break;
							}
						}
						continue;
					}
					if (columnValue.equals("stockWarning")) {
						for (YesOrNoEnum yesOrNoEnum : YesOrNoEnum.values()) {
							if (yesOrNoEnum.getMsg().equals(row.get(s).toString())) {
								objectMap.put(columnValue, yesOrNoEnum);
								break;
							}
						}
						continue;
					}
					if (columnValue.equals("goodsCategoryName")) {
						Integer integer = map.get(row.get(s));
						if(integer == null){
							LOGGER.error("商品导入异常：商品分类解析失败 param:{}",objectMap);
							continue valueIsNull;
						}
						objectMap.put("goodsCategoryId", integer);
						continue;
					}
					if (columnValue.equals("image")) {
						List<PictureData> pictureDataList = (ArrayList<PictureData>) row.get(s);
						if(pictureDataList == null || pictureDataList.size() == 0){
							continue valueIsNull;
						}
						PictureData pictureData = pictureDataList.get(0);
						InputStream in = new ByteArrayInputStream(pictureData.getData());
						UploadReturnBean bean = uploadFileService.uploadFile(in, pictureData.suggestFileExtension());
						if (!bean.isStatus()) {
							LOGGER.error("商品导入异常：上传图片失败 param:{}",objectMap);
							continue valueIsNull;
						}
						objectMap.put(columnValue, bean.getUrl());
						continue;
					}
					objectMap.put(columnValue, row.get(s));
				}
				Goods goods = null;
				try {
					goods = JSONObject.parseObject(objectMap.toJSONString(),Goods.class);
					goods.setSn(StringUtils.trim(goods.getSn()));
					goodsList.add(goods);
				} catch (Exception ex) {
					throw new BizException("导入数据出错", ex);
				}
			}
		}
		if(CollectionUtils.isEmpty(goodsList)){
			return goodsList;
		}

		List<String> goodsSnList = goodsList.stream().map(Goods::getSn).collect(Collectors.toList());
		List<Goods> existsGoods = goodsDao.findBySns(goodsSnList);
		List<String> existsSns = existsGoods.stream().map(Goods::getSn).collect(Collectors.toList());

		Map<String, List<Goods>> snGoodsMap = goodsList.stream().collect(Collectors.groupingBy(Goods::getSn));
		for (Goods existsGood : existsGoods) {
			List<Goods> goods = snGoodsMap.get(existsGood.getSn());
			int stockCount = goods.stream().mapToInt(Goods::getStockCount).sum();
			int taxStockCount = goods.stream().mapToInt(Goods::getTaxStockCount).sum();
			existsGood.setStockCount((Objects.isNull(existsGood.getStockCount())?0:existsGood.getStockCount()) + stockCount);
			existsGood.setTaxStockCount((Objects.isNull(existsGood.getTaxStockCount())?0:existsGood.getTaxStockCount()) + taxStockCount);
			Goods newGoods = goods.get(0);
			if(Objects.nonNull(newGoods.getGoodsCategoryId())&&!newGoods.getGoodsCategoryId().equals(existsGood.getGoodsCategoryId())){
				existsGood.setGoodsCategoryId(newGoods.getGoodsCategoryId());
			}
			if(Objects.nonNull(newGoods.getGoodsCategoryName())&&!newGoods.getGoodsCategoryName().equals(existsGood.getGoodsCategoryName())){
				existsGood.setGoodsCategoryName(newGoods.getGoodsCategoryName());
			}
			if(Objects.nonNull(newGoods.getName())&&!newGoods.getName().equals(existsGood.getName())){
				existsGood.setName(newGoods.getName());
			}
			if(Objects.nonNull(newGoods.getBrand())&&!newGoods.getBrand().equals(existsGood.getBrand())){
				existsGood.setBrand(newGoods.getBrand());
			}
			if(Objects.nonNull(newGoods.getType())&&!newGoods.getType().equals(existsGood.getType())){
				existsGood.setType(newGoods.getType());
			}
			if(Objects.nonNull(newGoods.getSpecification())&&!newGoods.getSpecification().equals(existsGood.getSpecification())){
				existsGood.setSpecification(newGoods.getSpecification());
			}
			if(Objects.nonNull(newGoods.getMarketPrice())&&!newGoods.getMarketPrice().equals(existsGood.getMarketPrice())){
				existsGood.setMarketPrice(newGoods.getMarketPrice());
			}
			if(Objects.nonNull(newGoods.getDiscountPrice())&&!newGoods.getDiscountPrice().equals(existsGood.getDiscountPrice())){
				existsGood.setDiscountPrice(newGoods.getDiscountPrice());
			}
			if(Objects.nonNull(newGoods.getGroupPurchasePrice())&&!newGoods.getGroupPurchasePrice().equals(existsGood.getGroupPurchasePrice())){
				existsGood.setGroupPurchasePrice(newGoods.getGroupPurchasePrice());
			}
			if(Objects.nonNull(newGoods.getImage())&&!newGoods.getImage().equals(existsGood.getImage())){
				existsGood.setImage(newGoods.getImage());
			}
			if(Objects.nonNull(newGoods.getStockType())&&!newGoods.getStockType().equals(existsGood.getStockType())){
				existsGood.setStockType(newGoods.getStockType());
			}
			if(Objects.nonNull(newGoods.getBrief())&&!newGoods.getBrief().equals(existsGood.getBrief())){
				existsGood.setBrief(newGoods.getBrief());
			}
			if(Objects.nonNull(newGoods.getDesc())&&!newGoods.getDesc().equals(existsGood.getDesc())){
				existsGood.setDesc(newGoods.getDesc());
			}
			if(Objects.nonNull(newGoods.getClientShow())&&!newGoods.getClientShow().equals(existsGood.getClientShow())){
				existsGood.setClientShow(newGoods.getClientShow());
			}
			if(Objects.nonNull(newGoods.getStockWarning())&&!newGoods.getStockWarning().equals(existsGood.getStockWarning())){
				existsGood.setStockWarning(newGoods.getStockWarning());
			}
		}

		if(!CollectionUtils.isEmpty(existsGoods)){
			goodsDao.batchUpdate(existsGoods);
		}
		List<Goods> newGoods = goodsList.stream().filter(g -> !existsSns.contains(g.getSn())).collect(Collectors.toList());
		if(!CollectionUtils.isEmpty(newGoods)){
			goodsDao.batchInsert(newGoods);
		}

		Map<String, Integer> existsSnIdMap = existsGoods.stream().collect(Collectors.toMap(Goods::getSn, g -> g.getId()));
		Map<String, Integer> newSnIdMap = newGoods.stream().collect(Collectors.toMap(Goods::getSn, g -> g.getId(), (v1, v2)->v1));
		existsSnIdMap.putAll(newSnIdMap);

		List<GoodsProcurement> goodsProcurements = new ArrayList<>();
		for (Goods goods : goodsList) {
			GoodsProcurement gp = new GoodsProcurement();
			gp.setGoodsId(existsSnIdMap.get(goods.getSn()));
			gp.setGoodsCategoryId(goods.getGoodsCategoryId());
			gp.setSupplyChannel(goods.getSupplyChannel());
			gp.setDiscountPrice(goods.getCostPrice());
			gp.setAgreeCostPrice(goods.getAgreeCostPrice());
			gp.setStockCount(goods.getStockCount());
			gp.setTaxStockCount(goods.getTaxStockCount());
			gp.setOperatorId(operatorId);
			String batchNo = idGeneratorService.generatorId("payment") + "";
			gp.setBatchNo(batchNo);
			goodsProcurements.add(gp);
		}
		goodsProcurementDao.batchInsert(goodsProcurements);

		sellOrderBatchNoAllot();

		return goodsList;
	}

	@Override
	public void repertoryWarn() {
		//预警手机号
		String repertoryWarnPhone = sysConfigDao.findConfigValue("repertory_warn_phone");
		if(StringUtils.isEmpty(repertoryWarnPhone)){
			return;
		}
		BasicUserDto sysUser = teacherDao.findUserByPhone(repertoryWarnPhone);
		if(sysUser == null || sysUser.getUserId() == null){
			throw new BizException("库存预警手机号不存在");
		}
		Map<Integer, String> receivers = new HashMap<>(1);
		receivers.put(sysUser.getUserId(), repertoryWarnPhone);
		//内部库存预警
		String innerRepertoryWarnNum = sysConfigDao.findConfigValue("inner_repertory_warn_num");
		if(StringUtils.isNotEmpty(innerRepertoryWarnNum)){
			String goodsNames = goodsDao.getInnerRepertoryWarnName(innerRepertoryWarnNum);
			if(StringUtils.isNotEmpty(goodsNames)){
				sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SMS_GOODS_REPERTORY_WARN, receivers, null, 0, null,null,
						goodsNames,"内部");
			}
		}

		//外部库存预警
		String outerRepertoryWarnNum = sysConfigDao.findConfigValue("outer_repertory_warn_num");
		if(StringUtils.isNotEmpty(outerRepertoryWarnNum)){
			String goodsNames = goodsDao.getOuterRepertoryWarnName(outerRepertoryWarnNum);
			if(StringUtils.isNotEmpty(goodsNames)){
				sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.YIMEI, MessageTypeEnum.SMS_GOODS_REPERTORY_WARN, receivers, null, 0, null,null,
						goodsNames,"税务");
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
	public void sellOrderBatchNoAllot() {
		List<Integer> noneBatchNoSellOrderIds = sellOrderDao.getNoneBatchNoSellOrderIds();
		if(CollectionUtils.isEmpty(noneBatchNoSellOrderIds)){
			return;
		}
		List<SellOrder> noneBatchNoSellOrders = sellOrderDao.lockSellOrders(noneBatchNoSellOrderIds);
		List<SellOrder> updateSellOrders = new ArrayList<>();
		for (SellOrder noneBatchNoSellOrder : noneBatchNoSellOrders) {
			if(SellStatus.REFUND.equals(noneBatchNoSellOrder.getStatus())){
				continue;
			}
			GoodsProcurement goodsProcurement = null;
			if(StockType.INTERNAL.equals(noneBatchNoSellOrder.getStockType())||(StockType.ALL.equals(noneBatchNoSellOrder.getStockType())&&AccountType.INTERNAL.equals(noneBatchNoSellOrder.getAccountType()))){
				goodsProcurement = goodsProcurementDao.getWithStockSurplusProcurement(noneBatchNoSellOrder.getGoodsId());
				if(Objects.nonNull(goodsProcurement)){
					goodsProcurement.setStockSoldNum(new AtomicInteger(goodsProcurement.getStockSoldNum()).incrementAndGet());
				}
			}else if(StockType.EXTERNAL.equals(noneBatchNoSellOrder.getStockType())||(StockType.ALL.equals(noneBatchNoSellOrder.getStockType())&&AccountType.EXTERNAL.equals(noneBatchNoSellOrder.getAccountType()))){
				goodsProcurement = goodsProcurementDao.getWithTaxStockSurplusProcurement(noneBatchNoSellOrder.getGoodsId());
				if(Objects.nonNull(goodsProcurement)){
					goodsProcurement.setTaxStockSoldNum(new AtomicInteger(goodsProcurement.getTaxStockSoldNum()).incrementAndGet());
				}
			}

			if(Objects.nonNull(goodsProcurement)){
				goodsProcurementDao.update(goodsProcurement);
				noneBatchNoSellOrder.setBatchNo(goodsProcurement.getBatchNo());
				noneBatchNoSellOrder.setSellCost(goodsProcurement.getDiscountPrice());
				Map<String, BigDecimal> CostMap = new HashMap<>();
				CostMap.put("sellCost", goodsProcurement.getDiscountPrice());
				if (Objects.nonNull(goodsProcurement.getAgreeCostPrice())) {
					CostMap.put("SellCost2", goodsProcurement.getAgreeCostPrice());
				}
				noneBatchNoSellOrder.setSellCost2(JSON.toJSONString(CostMap));
				updateSellOrders.add(noneBatchNoSellOrder);
			}
		}
		if(!CollectionUtils.isEmpty(updateSellOrders)){
			sellOrderDao.batchUpdate(updateSellOrders);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
	public List<SellOrder> subtractStock(List<Integer> goodsIds, AccountType accountType) {
		if(CollectionUtils.isEmpty(goodsIds)){
			return Collections.emptyList();
		}

		List<Goods> tempGoodsList = goodsDao.lockGoods(new ArrayList<>(goodsIds));
		Map<Integer, Goods> idTempGoodsMap = tempGoodsList.stream().collect(Collectors.toMap(Goods::getId, g -> g));
		List<GoodsProcurement> goodsProcurements = new ArrayList<>();
		for (Integer goodsId : goodsIds) {
			Goods tempGoods = idTempGoodsMap.get(goodsId);
			List<Goods> childGoods = new ArrayList<>();
			if(StringUtils.isBlank(tempGoods.getComplementGoodsIdList())){
				childGoods.add(tempGoods);
			}else{
				List<Integer> complementGoodsIds = Arrays.stream(tempGoods.getComplementGoodsIdList().split(",")).map(s -> Integer.valueOf(s)).collect(Collectors.toList());
				childGoods = goodsDao.lockGoods(complementGoodsIds);
			}
			for (Goods goods : childGoods) {
				GoodsProcurement goodsProcurement = null;
				if(StockType.INTERNAL.equals(goods.getStockType())||(StockType.ALL.equals(goods.getStockType())&&AccountType.INTERNAL.equals(accountType))){
					goodsProcurement = goodsProcurementDao.getWithStockSurplusProcurement(goods.getId());
					goods.setStockCount(new AtomicInteger(goods.getStockCount()).decrementAndGet());
					if(Objects.nonNull(goodsProcurement)){
						goodsProcurement.setStockSoldNum(new AtomicInteger(goodsProcurement.getStockSoldNum()).incrementAndGet());
					}
				}else if(StockType.EXTERNAL.equals(goods.getStockType())||(StockType.ALL.equals(goods.getStockType())&&AccountType.EXTERNAL.equals(accountType))){
					goodsProcurement = goodsProcurementDao.getWithTaxStockSurplusProcurement(goods.getId());
					goods.setTaxStockCount(new AtomicInteger(goods.getTaxStockCount()).decrementAndGet());
					if(Objects.nonNull(goodsProcurement)){
						goodsProcurement.setTaxStockSoldNum(new AtomicInteger(goodsProcurement.getTaxStockSoldNum()).incrementAndGet());
					}
				}

				goods.setSellCount(new AtomicInteger(goods.getSellCount()).incrementAndGet());

//				goodsDao.update(goods);
				if(Objects.nonNull(goodsProcurement)){
//					goodsProcurementDao.update(goodsProcurement);
				}else{
					goodsProcurement = new GoodsProcurement(goods.getId());
				}
				if(StringUtils.isNotBlank(tempGoods.getComplementGoodsIdList())){
					goodsProcurement.setParentGoodsId(tempGoods.getId());
				}

				goodsProcurements.add(goodsProcurement);
			}
		}

		List<SellOrder> sellOrders = new ArrayList<>();

		List<GoodsProcurement> singleGoodsList = goodsProcurements.stream().filter(g -> Objects.isNull(g.getParentGoodsId())&&Objects.nonNull(g.getBatchNo())).collect(Collectors.toList());
		if(!CollectionUtils.isEmpty(singleGoodsList)){
			Map<String, List<Integer>> batchNoGoodsIdMap = singleGoodsList.stream().collect(Collectors.groupingBy(GoodsProcurement::getBatchNo, Collectors.mapping(GoodsProcurement::getGoodsId, Collectors.toList())));
			for (Map.Entry<String, List<Integer>> batchNoGoodsIdMapEntry : batchNoGoodsIdMap.entrySet()) {
				Map<Integer, Long> goodsNumMap = batchNoGoodsIdMapEntry.getValue().stream().collect(Collectors.groupingBy(gid -> gid, Collectors.counting()));
				for (Map.Entry<Integer, Long> goodsNumMapEntry : goodsNumMap.entrySet()) {
					Goods goods = idTempGoodsMap.get(goodsNumMapEntry.getKey());
					SellOrder sellOrder = new SellOrder();
					sellOrder.setGoodsId(goodsNumMapEntry.getKey());
					sellOrder.setNum(goodsNumMapEntry.getValue().intValue());
					sellOrder.setGoodsName(goods.getName());
					if(StockType.INTERNAL.equals(goods.getStockType())||(StockType.ALL.equals(goods.getStockType())&&AccountType.INTERNAL.equals(accountType))){
						sellOrder.setStockType(StockType.INTERNAL);
					}else if(StockType.EXTERNAL.equals(goods.getStockType())||(StockType.ALL.equals(goods.getStockType())&&AccountType.EXTERNAL.equals(accountType))){
						sellOrder.setStockType(StockType.EXTERNAL);
					}
					sellOrder.setGoodsName(goods.getName());
					sellOrder.setAccountType(accountType);
					sellOrder.setBatchNo(batchNoGoodsIdMapEntry.getKey());
					GoodsProcurement goodsProcurement = goodsProcurementDao.getWithGoodsAndBatchNo(sellOrder.getGoodsId(), sellOrder.getBatchNo());
					sellOrder.setSellCost(goodsProcurement.getDiscountPrice());
					Map<String, BigDecimal> CostMap = new HashMap<>();
					CostMap.put("sellCost", goodsProcurement.getDiscountPrice());
					if (Objects.nonNull(goodsProcurement.getAgreeCostPrice())) {
						CostMap.put("SellCost2", goodsProcurement.getAgreeCostPrice());
					}
					sellOrder.setSellCost2(JSON.toJSONString(CostMap));
					sellOrders.add(sellOrder);
				}
			}
		}

		List<GoodsProcurement> groupGoodsList = goodsProcurements.stream().filter(g -> Objects.nonNull(g.getParentGoodsId())||Objects.isNull(g.getBatchNo())).collect(Collectors.toList());
		if(!CollectionUtils.isEmpty(groupGoodsList)){
			for (GoodsProcurement goodsProcurement : groupGoodsList) {
				Goods goods = goodsDao.lock(goodsProcurement.getGoodsId());
				SellOrder sellOrder = new SellOrder();
				sellOrder.setParentGoodsId(goodsProcurement.getParentGoodsId());
				sellOrder.setGoodsId(goodsProcurement.getGoodsId());
				sellOrder.setNum(1);
				sellOrder.setGoodsName(goods.getName());
				if(StockType.INTERNAL.equals(goods.getStockType())||(StockType.ALL.equals(goods.getStockType())&&AccountType.INTERNAL.equals(accountType))){
					sellOrder.setStockType(StockType.INTERNAL);
				}else if(StockType.EXTERNAL.equals(goods.getStockType())||(StockType.ALL.equals(goods.getStockType())&&AccountType.EXTERNAL.equals(accountType))){
					sellOrder.setStockType(StockType.EXTERNAL);
				}
				sellOrder.setGoodsName(goods.getName());
				sellOrder.setAccountType(accountType);
				sellOrder.setBatchNo(goodsProcurement.getBatchNo());
				if(Objects.nonNull(goodsProcurement.getBatchNo())){
					sellOrder.setSellCost(goodsProcurement.getDiscountPrice());
					Map<String, BigDecimal> CostMap = new HashMap<>();
					CostMap.put("sellCost", goodsProcurement.getDiscountPrice());
					if (Objects.nonNull(goodsProcurement.getAgreeCostPrice())) {
						CostMap.put("SellCost2", goodsProcurement.getAgreeCostPrice());
					}
					sellOrder.setSellCost2(JSON.toJSONString(CostMap));
				}
				sellOrders.add(sellOrder);
			}
		}

		return sellOrders;
	}

	@Override
	@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
	public void increaseStock(List<SellOrder> sellOrders, AccountType accountType) {
		if(CollectionUtils.isEmpty(sellOrders)){
			return;
		}

		Set<Integer> goodsIdList = new HashSet<>();
		sellOrders.forEach(so -> {
			if(Objects.nonNull(so.getParentGoodsId())){
				goodsIdList.add(so.getParentGoodsId());
			}else{
				goodsIdList.add(so.getGoodsId());
			}
		});

		goodsDao.lockGoods(new ArrayList<>(goodsIdList));

		for (SellOrder sellOrder : sellOrders) {
			Goods goods = goodsDao.lock(sellOrder.getGoodsId());
			GoodsProcurement goodsProcurement = goodsProcurementDao.getWithGoodsAndBatchNo(sellOrder.getGoodsId(), sellOrder.getBatchNo());
			if(StockType.INTERNAL.equals(sellOrder.getStockType())){
				goods.setStockCount(new AtomicInteger(goods.getStockCount()).addAndGet(sellOrder.getNum()));
				if(Objects.nonNull(goodsProcurement)){
					goodsProcurement.setStockSoldNum(new AtomicInteger(goodsProcurement.getStockSoldNum()).addAndGet(-sellOrder.getNum()));
				}
			}else if(StockType.EXTERNAL.equals(sellOrder.getStockType())){
				goods.setTaxStockCount(new AtomicInteger(goods.getTaxStockCount()).addAndGet(sellOrder.getNum()));
				if(Objects.nonNull(goodsProcurement)){
					goodsProcurement.setTaxStockSoldNum(new AtomicInteger(goodsProcurement.getTaxStockSoldNum()).addAndGet(-sellOrder.getNum()));
				}
			}
			goods.setSellCount(new AtomicInteger(goods.getSellCount()).addAndGet(-sellOrder.getNum()));

//			goodsDao.update(goods);
//			goodsProcurementDao.update(goodsProcurement);
		}
	}

	@Override
	public List<GoodsSellDto> queryGoodsSellDtos(String goodsId) {
		return goodsDao.queryGoodsSellDtos(goodsId);
	}
}
