Commit e0fbd40a authored by shiyu's avatar shiyu

拍卖生成订单

parent 35084cbe
......@@ -105,6 +105,7 @@ public class SysSupplierItemServiceImpl implements SysSupplierItemService {
public Result findList(SupplierItemRequestDto dto) {
try {
List<SupplierItemVo> supplierItemVos = new ArrayList<>();
dto.setIsDeleted(false);
List<SupplierItem> supplierItemList = supplierItemDao.findList(dto);
PageInfo<SupplierItem> pageInfo = new PageInfo(supplierItemList);
supplierItemList.forEach(supplierItem -> {
......
......@@ -67,7 +67,7 @@ public class SynItemToEsJob {
/**
* 隔2分钟运行一次
*/
@Scheduled(fixedDelay = 1000 * 60 * 2)
// @Scheduled(fixedDelay = 1000 * 60 * 2)
public void execute() {
RLock lock = redissonClient.getLock(QUANKU_SYN_TO_ES_TASK_KEY);
if (!lock.tryLock()) {
......
......@@ -32,6 +32,11 @@ public interface CommConsts {
*/
public static final String UPLOAD_PRE_WXACODE_DIRECTORY = "quanku/wxacode/";
/**
* 拍卖出价的锁
*/
public static final String AUCTION_LOCK_KEY_PRE = "AUCTION:OFFER:";
}
......@@ -21,6 +21,8 @@ dts:
msg-url: pages/consignNodeDetail/index
#分销业务,公众号消息点击后跳转到小程序页面的链接
distribution-msg-url: pages/saleOrderDetail/index
#分销拍卖业务,众号消息点击后跳转到小程序页面的链接
auction-msg-url: pages/saleOrderDetail/index
# 商户证书文件路径
# 请参考“商户证书”一节 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3
......
......@@ -3,6 +3,7 @@ package com.wwdz.ch.db.dao.distribution;
import com.wwdz.ch.db.domain.distribution.AuctionConfig;
import java.util.Date;
import java.util.List;
public interface AuctionConfigDao {
......@@ -30,6 +31,21 @@ public interface AuctionConfigDao {
*/
AuctionConfig findByItemId(long itemId);
/**
* 查询截拍商品记录
* @param
* @return
*/
List<AuctionConfig> findEndList();
/**
* 查询超过截拍时间,但状态没有更改为截拍的商品记录
* @param
* @return
*/
List<AuctionConfig> findTimeOutNotValidList();
/**
* 更新截拍时间
* @param itemId
......
......@@ -3,6 +3,7 @@ package com.wwdz.ch.db.dao.distribution;
import com.wwdz.ch.db.domain.distribution.AuctionRecord;
import com.wwdz.ch.db.dto.request.distribution.AuctionRecordRequestDto;
import java.util.Date;
import java.util.List;
public interface AuctionRecordDao {
......@@ -46,6 +47,14 @@ public interface AuctionRecordDao {
*/
List<AuctionRecord> findByPage(AuctionRecordRequestDto dto);
/**
* 根据商品id查询出价记录
* @param itemId
* @return
*/
List<AuctionRecord> findByItemId(long itemId);
/**
* 查询最新的一条出价记录
* @param itemId
......@@ -63,8 +72,10 @@ public interface AuctionRecordDao {
/**
* 查询用户出价过的商品
* @param userId
* @param startTime
* @param endTime
* @return
*/
List<Long> findItemsOfRecord(long userId);
List<AuctionRecord> findRecordByUserId(long userId, Date startTime, Date endTime);
}
......@@ -55,4 +55,14 @@ public class AuctionRecordRequestDto extends BaseRequestDto implements Entity {
* 分销订单号
*/
private String distributionOrderId;
/**
* 时间范围查询
*/
private Date queryStartTime;
/**
* 时间范围查询
*/
private Date queryEndTime;
}
......@@ -7,7 +7,12 @@ import com.wwdz.ch.db.domain.distribution.DistributionOrderExample;
import com.wwdz.ch.db.mapper.distribution.AuctionConfigMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.TemporalAmount;
import java.util.Date;
import java.util.List;
@Repository
public class AuctionConfigDaoImpl implements AuctionConfigDao {
......@@ -45,6 +50,29 @@ public class AuctionConfigDaoImpl implements AuctionConfigDao {
return auctionConfigMapper.updateByExampleSelective(auctionConfig, example);
}
@Override
public List<AuctionConfig> findEndList() {
AuctionConfigExample example = new AuctionConfigExample();
AuctionConfigExample.Criteria criteria = example.createCriteria();
Date now = new Date();
//查询截单时间一小时内的拍卖
Instant instant = now.toInstant().minus(Duration.ofHours(1));
Date time = Date.from(instant);
criteria.andRealEndTimeGreaterThanOrEqualTo(time);
criteria.andIsValidEqualTo(false);
return auctionConfigMapper.selectByExample(example);
}
@Override
public List<AuctionConfig> findTimeOutNotValidList() {
AuctionConfigExample example = new AuctionConfigExample();
AuctionConfigExample.Criteria criteria = example.createCriteria();
Date now = new Date();
criteria.andRealEndTimeLessThanOrEqualTo(now);
criteria.andIsValidEqualTo(true);
return auctionConfigMapper.selectByExample(example);
}
@Override
public int setEnd(long itemId) {
AuctionConfigExample example = new AuctionConfigExample();
......
......@@ -10,6 +10,7 @@ import com.xxdxxs.db.component.JdbcHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
@Repository
......@@ -65,6 +66,15 @@ public class AuctionRecordDaoImpl implements AuctionRecordDao {
}
@Override
public List<AuctionRecord> findByItemId(long itemId) {
AuctionRecordExample example = new AuctionRecordExample();
AuctionRecordExample.Criteria criteria = example.createCriteria();
criteria.andItemIdEqualTo(itemId);
example.setOrderByClause("create_time desc");
return auctionRecordMapper.selectByExample(example);
}
@Override
public AuctionRecord findLastedRecord(long itemId) {
AuctionRecordExample example = new AuctionRecordExample();
......@@ -86,7 +96,12 @@ public class AuctionRecordDaoImpl implements AuctionRecordDao {
@Override
public List<Long> findItemsOfRecord(long userId) {
return auctionRecordMapper.findItemsOfRecord(userId);
public List<AuctionRecord> findRecordByUserId(long userId, Date startTime, Date endTime) {
AuctionRecordExample example = new AuctionRecordExample();
AuctionRecordExample.Criteria criteria = example.createCriteria();
criteria.andUserIdEqualTo(userId);
criteria.andCreateTimeGreaterThanOrEqualTo(startTime);
criteria.andCreateTimeLessThanOrEqualTo(endTime);
return auctionRecordMapper.selectByExample(example);
}
}
......@@ -134,6 +134,10 @@ public class DistributionOrderDaoImpl implements DistributionOrderDao {
criteria.andDistributionOrderIdEqualTo(distributionOrderId);
DistributionOrder distributionOrder = new DistributionOrder();
distributionOrder.setState(state);
//确认收货,更新完成时间
if (state == 100) {
distributionOrder.setFinishTime(new Date());
}
distributionOrder.setUpdateTime(new Date());
return distributionOrderMapper.updateByExampleSelective(distributionOrder, example) > 0;
}
......
......@@ -40,7 +40,6 @@ public class SupplierItemDaoImpl implements SupplierItemDao {
JdbcHelper.ifPresent(dto.getStock(), criteria::andStockGreaterThan);
JdbcHelper.ifPresent(dto.getIsOnSale(), criteria::andIsOnSaleEqualTo);
JdbcHelper.ifPresent(dto.getIsDeleted(), criteria::andIsDeletedEqualTo);
criteria.andIsDeletedEqualTo(false);
supplierItemExample.setOrderByClause(" id desc");
PageHelper.startPage(dto.getPage(), dto.getLimit());
return supplierItemMapper.selectByExampleWithBLOBs(supplierItemExample);
......
package com.wwdz.ch.wx.entity;
import com.xxdxxs.entity.Entity;
import lombok.Data;
import java.util.Date;
@Data
public class AuctionOfferNoticeMsg implements Entity {
private String templetId;
/**
* 分销订单号
*/
private String distributionOrderId;
/**
* 商品名称
*/
private String itemName;
/**
* 付款金额
*/
private String amount;
/**
* 签收时间
*/
private Date signedTime;
}
......@@ -6,10 +6,31 @@ import lombok.Data;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Data
public class AuctionRecordVo implements Entity {
/**
* 商品id
*/
private Long itemId;
/**
* 商品名称
*/
private String itemName;
/**
* 商品分享的id
*/
private String shareRecordId;
/**
* 用于列表展示的图片对象
*/
private Map<String, Object> homePageImage;
/**
* 当前售价
*/
......@@ -58,5 +79,8 @@ public class AuctionRecordVo implements Entity {
*/
private Integer totalOfferNum;
private Integer auctionUserState;
private String auctionUserStateName;
}
......@@ -173,4 +173,11 @@ public class DistributionOrderDetailVo implements Entity {
*/
private Date payEndTime;
/**
* 商品类型1一口价2竞拍
*/
private Integer type;
private String typeName;
}
......@@ -153,4 +153,11 @@ public class DistributionOrderVo implements Entity {
* 支付截止时间
*/
private Date payEndTime;
/**
* 商品类型1一口价2竞拍
*/
private Integer type;
private String typeName;
}
package com.wwdz.ch.wx.impl.distribution;
import com.wwdz.ch.core.api.OfficialAccountApi;
import com.wwdz.ch.core.api.wxpay.WxPayServiceApi;
import com.wwdz.ch.core.consts.CommConsts;
import com.wwdz.ch.core.consts.DistributionEnum;
import com.wwdz.ch.core.consts.ResultCode;
import com.wwdz.ch.core.type.Result;
import com.wwdz.ch.core.util.MediaUtil;
import com.wwdz.ch.core.util.PriceUtil;
import com.wwdz.ch.db.dao.OfficialAccountSubscribeRecordDao;
import com.wwdz.ch.db.dao.UserDao;
import com.wwdz.ch.db.dao.distribution.*;
import com.wwdz.ch.db.domain.distribution.*;
import com.wwdz.ch.db.dto.request.distribution.AuctionRecordRequestDto;
import com.wwdz.ch.db.dto.request.distribution.DistributionOrderRequestDto;
import com.wwdz.ch.wx.entity.vo.distribution.AuctionRecordVo;
import com.wwdz.ch.wx.service.distribution.AuctionRecordService;
import com.wwdz.ch.wx.util.RedisUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
......@@ -21,20 +23,20 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
public class AuctionRecordServiceImpl implements AuctionRecordService {
private static final Logger logger = LoggerFactory.getLogger(AuctionRecordServiceImpl.class);
private static final String LOCK_KEY_PRE = "AUCTION:OFFER:";
@Autowired
AuctionConfigDao auctionConfigDao;
......@@ -57,11 +59,21 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
@Autowired
DistributorShareRecordDao distributorShareRecordDao;
@Autowired
OfficialAccountApi officialAccountApi;
@Autowired
UserDao userDao;
@Autowired
OfficialAccountSubscribeRecordDao officialAccountSubscribeRecordDao;
@Override
@Transactional
public Result createAuctionRecord(AuctionRecordRequestDto dto) {
long itemId = dto.getItemId();
String itemIdKey = LOCK_KEY_PRE + itemId;
String itemIdKey = CommConsts.AUCTION_LOCK_KEY_PRE + itemId;
RLock lock = redissonClient.getLock(itemIdKey);
try {
if (lock.tryLock(5, 5, TimeUnit.SECONDS)) {
......@@ -92,6 +104,24 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
}
//把上次的最高价记录改为落后
auctionRecordDao.updateNotLeadById(auctionRecord.getId());
//发送模板消息,提示用户出价被超越
/* User user = userDao.queryById(userId);
String unionId = user.getWeixinUnionid();
OfficialAccountSubscribeRecord officialAccountSubscribeRecord = officialAccountSubscribeRecordDao.findOne(unionId);
//没有订阅
if (officialAccountSubscribeRecord == null || officialAccountSubscribeRecord.getEnabled().intValue() == 0) {
logger.info(">>>>>>>>>> 用户 unionId = {} ,尚未订阅公众号,无法推送消息 <<<<<<<<<<<");
//发送短信
} else {
String openId = officialAccountSubscribeRecord.getOpenid();
SupplierItem supplierItem = supplierItemDao.findById(itemId);
String itemName = supplierItem.getName();
String content = "您的出价被超越";
ConsignSaleSubscribeMsg consignSaleSubscribeMsg = ConsignSaleSubscribeMsg.of(itemName.substring(0,10), content, new Date());
consignSaleSubscribeMsg.setPageTitle("拍卖出价被超越");
officialAccountApi.sendModelMsg(openId, consignSaleSubscribeMsg);
}*/
}
//插入最新出价记录
AuctionRecord addRecord = new AuctionRecord();
......@@ -134,32 +164,48 @@ public class AuctionRecordServiceImpl implements AuctionRecordService {
try {
List<AuctionRecordVo> auctionRecordVos = new ArrayList<>();
AuctionRecordVo auctionRecordVo = new AuctionRecordVo();
List<Long> items = auctionRecordDao.findItemsOfRecord(dto.getUserId());
if (CollectionUtils.isEmpty(items)) {
//查询4天内出价记录
Date now = new Date();
Instant instant = now.toInstant().minus(Duration.ofDays(4));
Date queryStartTime = Date.from(instant);
List<AuctionRecord> auctionRecords = auctionRecordDao.findRecordByUserId(dto.getUserId(), queryStartTime, now);
List<Long> itemIds = auctionRecords.stream().map(AuctionRecord::getItemId).distinct().collect(Collectors.toList());
if (CollectionUtils.isEmpty(itemIds)) {
return Result.success();
}
items.forEach(item -> {
List<AuctionRecord> auctionRecordList = auctionRecordDao.findByPage(dto);
itemIds.forEach(itemId -> {
//查询商品信息
SupplierItem supplierItem = supplierItemDao.findById(itemId);
auctionRecordVo.setItemId(itemId);
auctionRecordVo.setItemName(supplierItem.getName());
auctionRecordVo.setHomePageImage(MediaUtil.getHomePageImage(supplierItem.getImages(), supplierItem.getVideos()));
List<AuctionRecord> auctionRecordList = auctionRecordDao.findByItemId(itemId);
//查询商品竞拍信息
AuctionConfig auctionConfig = auctionConfigDao.findByItemId(dto.getItemId());
//当前价
if (CollectionUtils.isEmpty(auctionRecordList)) {
auctionRecordVo.setCurrentPrice(PriceUtil.convertPriceFenToYuan(auctionConfig.getStartPrice()));
//最新出价记录
AuctionRecord lastedRecord = auctionRecordList.get(0);
auctionRecordVo.setCurrentPrice(PriceUtil.convertPriceFenToYuan(lastedRecord.getPrice()));
if (lastedRecord.getUserId().longValue() == dto.getUserId().longValue()) {
auctionRecordVo.setIsLead(true);
} else {
AuctionRecord lastedRecord = auctionRecordDao.findLastedRecord(dto.getItemId());
auctionRecordVo.setCurrentPrice(PriceUtil.convertPriceFenToYuan(lastedRecord.getPrice()));
auctionRecordVo.setIsLead(false);
}
//商品的总出价次数
auctionRecordVo.setTotalOfferNum(auctionRecordList.size());
//用户自己的出价次数
long userOfferNum = auctionRecordList.stream().filter(auctionRecord -> auctionRecord.getUserId().longValue() == dto.getUserId()).count();
auctionRecordVo.setOfferNum((int)userOfferNum);
AuctionRecord selfRecord = auctionRecordList.stream().filter(auctionRecord -> auctionRecord.getUserId().longValue() == dto.getUserId()).findFirst().get();
auctionRecordVo.setShareRecordId(selfRecord.getShareRecordId());
auctionRecordVo.setAuctionRecordList(auctionRecordList);
auctionRecordVo.setStartPrice(PriceUtil.convertPriceFenToYuan(auctionConfig.getStartPrice()));
Date startTime = auctionConfig.getStartTime();
Date realEndTime = auctionConfig.getRealEndTime();
auctionRecordVo.setStartTime(startTime);
auctionRecordVo.setRealEndTime(realEndTime);
Date now = new Date();
if (now.before(startTime)) {
auctionRecordVo.setState(DistributionEnum.AuctionStateEnum.NOT_START.getCode());
auctionRecordVo.setStateName(DistributionEnum.AuctionStateEnum.NOT_START.getDes());
} else if (now.after(realEndTime)) {
if (now.after(realEndTime)) {
auctionRecordVo.setState(DistributionEnum.AuctionStateEnum.END.getCode());
auctionRecordVo.setStateName(DistributionEnum.AuctionStateEnum.END.getDes());
} else {
......
......@@ -116,6 +116,12 @@ public class SendMsgServiceImpl implements SendMsgService {
return Result.success();
}
@Override
public Result sendAuctionOfferOutMsg(String openId, SignedNoticeMsg signedNoticeMsg) {
return null;
}
@Override
public Result sendSignedTempletMsg(String openId, SignedNoticeMsg signedNoticeMsg) {
String token = officialAccountApi.getAccessToken();
......
package com.wwdz.ch.wx.job;
import com.github.pagehelper.PageInfo;
import com.wwdz.ch.core.type.Result;
import com.wwdz.ch.db.dao.ItemDao;
import com.wwdz.ch.db.dao.SynDataRecordDao;
import com.wwdz.ch.db.dao.distribution.AuctionConfigDao;
import com.wwdz.ch.db.dao.distribution.AuctionRecordDao;
import com.wwdz.ch.db.dao.distribution.DistributionOrderDao;
import com.wwdz.ch.db.domain.Item;
import com.wwdz.ch.db.domain.SynDataRecord;
import com.wwdz.ch.db.domain.distribution.AuctionConfig;
import com.wwdz.ch.db.domain.distribution.AuctionRecord;
import com.wwdz.ch.db.domain.distribution.DistributionOrder;
import com.wwdz.ch.db.dto.request.CoinRequestDto;
import com.wwdz.ch.db.dto.request.distribution.DistributionOrderRequestDto;
import com.wwdz.ch.db.es.ItemEsDao;
import com.wwdz.ch.wx.service.distribution.DistributionOrderService;
import com.xxdxxs.utils.DateUtils;
import com.xxdxxs.utils.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
/**
* 拍卖结束自动创建订单
*/
@Component
public class AutoCreateAuctionOrderJob {
private static final Logger logger = LoggerFactory.getLogger(AutoCreateAuctionOrderJob.class);
private final static String AUTO_CREATE_AUCTION_ORDER_KEY = "CREATE_AUCTION_ORDER_KEY";
@Autowired
DistributionOrderService distributionOrderService;
@Autowired
DistributionOrderDao distributionOrderDao;
@Autowired
RedissonClient redissonClient;
@Autowired
AuctionConfigDao auctionConfigDao;
@Autowired
AuctionRecordDao auctionRecordDao;
/**
* 隔2分钟运行一次
*/
@Scheduled(fixedDelay = 1000 * 60 * 5)
public void execute() {
RLock lock = redissonClient.getLock(AUTO_CREATE_AUCTION_ORDER_KEY);
if (!lock.tryLock()) {
logger.warn("自动生成拍卖订单任务,当前服务实例获取锁成功: {} 获取锁失败,锁被占用不执行", Thread.currentThread().getId());
return;
}
logger.info(">>>>>>>>>>>>>>>>>>>>>>> 检测截拍的商品,自动创建订单, 开始执行 <<<<<<<<<<<<<<<<<<<<<");
try {
//查询过期未截拍的商品记录
List<AuctionConfig> timeOutNotValidList = auctionConfigDao.findTimeOutNotValidList();
timeOutNotValidList.forEach(auctionConfig -> {
//修改为已截拍
auctionConfigDao.setEnd(auctionConfig.getItemId());
logger.info("============== 拍卖 商品id:{}, 超过截拍时间,系统自动修改为截拍状态 ==============", auctionConfig.getItemId());
});
//查询一小时内拍卖截拍的商品
List<AuctionConfig> auctionConfigList = auctionConfigDao.findEndList();
auctionConfigList.forEach(auctionConfig -> {
long itemId = auctionConfig.getItemId();
//查询该商品是否有出价记录
AuctionRecord auctionRecord = auctionRecordDao.findLastedRecord(itemId);
if (auctionRecord != null && auctionRecord.getPrice() != null) {
//有出价记录的商品,再去检查有无生成过订单
DistributionOrder distributionOrder = distributionOrderDao.findByItemId(itemId);
//如果还没生成过订单,则系统自动生成订单
if (distributionOrder == null || StringUtils.isEmpty(distributionOrder.getDistributionOrderId())) {
DistributionOrderRequestDto distributionOrderRequestDto = new DistributionOrderRequestDto();
distributionOrderRequestDto.setItemId(itemId);
Result result = distributionOrderService.createAuctionOrder(distributionOrderRequestDto);
if (result.getSuccess()) {
logger.info("============== 拍卖 商品id:{}, 自动生成订单成功 ==============", itemId);
} else {
logger.info("============== ERROR 拍卖 商品id:{}, 自动生成订单失败 ERROR ==============", itemId);
}
}
}
});
} catch (Exception e) {
logger.error("同步item增量数据到ES error {}", e);
} finally {
if (lock != null && lock.isHeldByCurrentThread()) {
lock.unlock();
logger.info("======================== 线程id: {} , 检测截拍的商品,自动创建订单执行结束, 释放锁成功 ========================", Thread.currentThread().getId());
}
}
}
}
......@@ -14,5 +14,13 @@ public interface SendMsgService {
Result sendSignedTempletMsg(String openId, SignedNoticeMsg signedNoticeMsg);
/**
* 出价被超越通知用户
* @param openId
* @param signedNoticeMsg
* @return
*/
Result sendAuctionOfferOutMsg(String openId, SignedNoticeMsg signedNoticeMsg);
String getOpenIdByUserId(long userId);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment