|
|
@@ -0,0 +1,215 @@
|
|
|
+package com.finikes.oc.vote.service;
|
|
|
+
|
|
|
+import com.finikes.oc.vote.LockService;
|
|
|
+import com.finikes.oc.vote.dao.ChoiceDao;
|
|
|
+import com.finikes.oc.vote.dao.OptionDao;
|
|
|
+import com.finikes.oc.vote.dao.VoteActivityDao;
|
|
|
+import com.finikes.oc.vote.dao.VoteDao;
|
|
|
+import com.finikes.oc.vote.dto.*;
|
|
|
+import com.finikes.oc.vote.entity.Choice;
|
|
|
+import com.finikes.oc.vote.entity.Option;
|
|
|
+import com.finikes.oc.vote.entity.Vote;
|
|
|
+import com.finikes.oc.vote.entity.VoteActivity;
|
|
|
+import com.finikes.oc.vote.exception.BusinessException;
|
|
|
+import com.finikes.oc.vote.mapper.VoteActivityMapper;
|
|
|
+import com.finikes.oc.vote.mapper.VoteMapper;
|
|
|
+import com.github.pagehelper.Page;
|
|
|
+import com.github.pagehelper.PageHelper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class VoteServiceImpl implements VoteService {
|
|
|
+
|
|
|
+ private final ChoiceDao choiceDao;
|
|
|
+
|
|
|
+ private final OptionDao optionDao;
|
|
|
+
|
|
|
+ private final VoteActivityDao voteActivityDao;
|
|
|
+
|
|
|
+ private final VoteDao voteDao;
|
|
|
+
|
|
|
+ private final LockService lockService;
|
|
|
+
|
|
|
+ public VoteServiceImpl(ChoiceDao choiceDao, OptionDao optionDao, VoteActivityDao voteActivityDao, VoteDao voteDao,
|
|
|
+ LockService lockService) {
|
|
|
+ this.choiceDao = choiceDao;
|
|
|
+ this.optionDao = optionDao;
|
|
|
+ this.voteActivityDao = voteActivityDao;
|
|
|
+ this.voteDao = voteDao;
|
|
|
+ this.lockService = lockService;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int createVoteActivity(VoteActivityCreateDto dto) {
|
|
|
+ voteActivityDateCheck(dto.getLaunchTime(), dto.getDeadline());
|
|
|
+
|
|
|
+ VoteActivity voteActivity = new VoteActivity();
|
|
|
+ voteActivity.setTitle(dto.getTitle());
|
|
|
+ voteActivity.setContent(dto.getContent());
|
|
|
+ voteActivity.setStartTime(dto.getLaunchTime().getTime());
|
|
|
+ voteActivity.setEndTime(dto.getDeadline().getTime());
|
|
|
+ voteActivityDao.insert(voteActivity);
|
|
|
+ return voteActivity.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateVoteActivity(VoteActivityUpdateDto dto) {
|
|
|
+ voteActivityDateCheck(dto.getLaunchTime(), dto.getDeadline());
|
|
|
+
|
|
|
+ VoteActivity voteActivity = new VoteActivity();
|
|
|
+ voteActivity.setId(dto.getId());
|
|
|
+ voteActivity.setTitle(dto.getTitle());
|
|
|
+ voteActivity.setContent(dto.getContent());
|
|
|
+ voteActivity.setStartTime(dto.getLaunchTime().getTime());
|
|
|
+ voteActivity.setEndTime(dto.getDeadline().getTime());
|
|
|
+ int effectRow = voteActivityDao.update(voteActivity);
|
|
|
+ if (effectRow != 1) {
|
|
|
+ throw new BusinessException("更新失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String timestampToStrDate(long timestamp) {
|
|
|
+ Date date = new Date(timestamp);
|
|
|
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
+ return simpleDateFormat.format(date);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<VoteActivityViewDto> searchVoteActivity(VoteActivitySearchDto dto) {
|
|
|
+ List<VoteActivity> activities;
|
|
|
+
|
|
|
+ try (Page<VoteActivity> page = PageHelper.startPage(dto.getPageNum(), dto.getPageCapacity(), false)){
|
|
|
+ if (dto.getStartTime() == null || dto.getEndTime() == null) {
|
|
|
+ activities = voteActivityDao.selectByTitleAndStartTimeAndEndTime(dto.getKey(),
|
|
|
+ null, null);
|
|
|
+ } else {
|
|
|
+ activities = voteActivityDao.selectByTitleAndStartTimeAndEndTime(dto.getKey(),
|
|
|
+ dto.getStartTime().getTime(), dto.getEndTime().getTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return activities.stream().map(i -> {
|
|
|
+ VoteActivityViewDto viewDto = VoteActivityMapper.INSTANCE.voteActivityToVoteActivityViewDto(i);
|
|
|
+ viewDto.setLaunchTime(timestampToStrDate(i.getStartTime()));
|
|
|
+ viewDto.setDeadline(timestampToStrDate(i.getEndTime()));
|
|
|
+ return viewDto;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int createVote(VoteCreateDto dto) {
|
|
|
+ VoteActivity activity = voteActivityDao.selectByPrimaryKey(dto.getActivityId());
|
|
|
+ if (activity == null) {
|
|
|
+ throw new BusinessException("投票活动不存在");
|
|
|
+ }
|
|
|
+ Vote vote = VoteMapper.INSTANCE.voteCreateDtoToVote(dto);
|
|
|
+ voteDao.insert(vote);
|
|
|
+
|
|
|
+ List<Option> options = dto.getOptions().stream()
|
|
|
+ .map(value -> {
|
|
|
+ Option option = new Option();
|
|
|
+ option.setVoteId(vote.getId());
|
|
|
+ option.setValue(value);
|
|
|
+ return option;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ optionDao.bulkInsert(options);
|
|
|
+
|
|
|
+ return vote.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateVote(VoteUpdateDto dto) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 投票活动日期检查
|
|
|
+ *
|
|
|
+ * @param startDate 开始日期
|
|
|
+ * @param endDate 结束日期
|
|
|
+ */
|
|
|
+ private void voteActivityDateCheck(Date startDate, Date endDate) {
|
|
|
+
|
|
|
+ if (startDate == null || endDate == null) {
|
|
|
+ throw new BusinessException("开始日期和结束日期不可为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (startDate.getTime() == endDate.getTime()) {
|
|
|
+ throw new BusinessException("开始日期和结束日期不可为同一天");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (endDate.getTime() < startDate.getTime()) {
|
|
|
+ throw new BusinessException("结束日期不可早于开始日期");
|
|
|
+ }
|
|
|
+
|
|
|
+ Calendar calendar = Calendar.getInstance(Locale.CHINA);
|
|
|
+ calendar.set(Calendar.HOUR, 0);
|
|
|
+ calendar.set(Calendar.MINUTE, 0);
|
|
|
+ calendar.set(Calendar.SECOND, 0);
|
|
|
+ calendar.set(Calendar.MILLISECOND, 0);
|
|
|
+ Date today = calendar.getTime();
|
|
|
+
|
|
|
+ if (endDate.getTime() <= today.getTime()) {
|
|
|
+ throw new BusinessException("结束日期不可为当前日期");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void madeChoice(ChoiceDto dto) {
|
|
|
+ int voterId = 0;
|
|
|
+ // TODO 需要方法获取登录用户信息
|
|
|
+
|
|
|
+ // TODO 这里需要锁住 用户ID 防止单个用户的并发调用, 锁住用户具有的房产主键已达到一房一票的需求.
|
|
|
+ String resourceId = "vote:" + voterId;
|
|
|
+ String ownerId = UUID.randomUUID().toString();
|
|
|
+ boolean locked = lockService.lock(resourceId, ownerId, 60, TimeUnit.SECONDS);
|
|
|
+ if (!locked) {
|
|
|
+ throw new BusinessException("请稍后再试");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ long now = System.currentTimeMillis();
|
|
|
+
|
|
|
+ Option option = optionDao.selectByPrimaryKey(dto.getOptionId());
|
|
|
+ if (option == null) {
|
|
|
+ throw new BusinessException("参与的投票不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ Vote vote = voteDao.selectByPrimaryKey(option.getVoteId());
|
|
|
+ if (vote == null) {
|
|
|
+ throw new BusinessException("参与的投票不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ VoteActivity activity = voteActivityDao.selectByPrimaryKey(vote.getActivityId());
|
|
|
+ if (activity == null) {
|
|
|
+ throw new BusinessException("参与的投票不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (now < activity.getStartTime()) {
|
|
|
+ throw new BusinessException("投票日期未到");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (now > activity.getEndTime()) {
|
|
|
+ throw new BusinessException("投票日期已过");
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO 检查此登录人员的房产下的绑定人员是否参与过此抽奖.
|
|
|
+
|
|
|
+ Choice choice = new Choice();
|
|
|
+ choice.setAssigneeId(voterId);
|
|
|
+ choice.setOptionId(dto.getOptionId());
|
|
|
+ choice.setProxy(false);
|
|
|
+ choice.setChooseTime(now);
|
|
|
+
|
|
|
+ choiceDao.insert(choice);
|
|
|
+ } finally {
|
|
|
+ lockService.unlock(resourceId, ownerId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|