| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.api.dto.ChargingCardBalanceDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardExcelDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardQueryDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardSaveDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardStatusDTO; |
| | | import com.ruoyi.account.api.model.TChargingCard; |
| | | import com.ruoyi.account.mapper.TChargingCardMapper; |
| | | import com.ruoyi.account.service.TChargingCardService; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.common.security.utils.SecurityUtils; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import com.ruoyi.system.api.model.LoginUser; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | @Service |
| | | public class TChargingCardServiceImpl extends ServiceImpl<TChargingCardMapper, TChargingCard> |
| | | implements TChargingCardService { |
| | | |
| | | private static final int ENABLED = 1; |
| | | private static final int DISABLED = 2; |
| | | private static final int BALANCE_ADD = 1; |
| | | private static final int BALANCE_SUBTRACT = 2; |
| | | private static final BigDecimal MAX_AMOUNT = new BigDecimal("9999999999.99"); |
| | | |
| | | @Autowired |
| | | private TokenService tokenService; |
| | | |
| | | @Autowired |
| | | private SysUserClient sysUserClient; |
| | | |
| | | @Override |
| | | public IPage<TChargingCard> selectCardPage(ChargingCardQueryDTO query) { |
| | | Page<TChargingCard> page = new Page<>(query.getPageCurr(), query.getPageSize()); |
| | | return baseMapper.selectCardPage(page, query); |
| | | ChargingCardQueryDTO safeQuery = query == null ? new ChargingCardQueryDTO() : query; |
| | | long pageNum = safeQuery.getPageCurr() == null || safeQuery.getPageCurr() < 1 ? 1 : safeQuery.getPageCurr(); |
| | | long pageSize = safeQuery.getPageSize() == null || safeQuery.getPageSize() < 1 ? 10 : safeQuery.getPageSize(); |
| | | Page<TChargingCard> page = new Page<>(pageNum, pageSize); |
| | | return baseMapper.selectCardPage(page, safeQuery); |
| | | } |
| | | |
| | | @Override |
| | | public boolean saveCard(ChargingCardSaveDTO dto) { |
| | | validateCard(dto, false); |
| | | TChargingCard card = new TChargingCard(); |
| | | card.setCardNo(dto.getCardNo().trim()); |
| | | card.setBalance(dto.getBalance() == null ? BigDecimal.ZERO : dto.getBalance()); |
| | | card.setStatus(dto.getStatus() == null ? ENABLED : dto.getStatus()); |
| | | card.setDelFlag(0); |
| | | card.setCreateTime(LocalDateTime.now()); |
| | | card.setCreateBy(SecurityUtils.getUserId()); |
| | | if (!save(card)) { |
| | | throw new ServiceException("新增卡片失败"); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateCard(ChargingCardSaveDTO dto) { |
| | | validateCard(dto, true); |
| | | if (getById(dto.getId()) == null) { |
| | | throw new ServiceException("卡片不存在或已删除"); |
| | | } |
| | | TChargingCard card = new TChargingCard(); |
| | | card.setId(dto.getId()); |
| | | card.setCardNo(dto.getCardNo().trim()); |
| | | card.setStatus(dto.getStatus() == null ? ENABLED : dto.getStatus()); |
| | | card.setUpdateTime(LocalDateTime.now()); |
| | | card.setUpdateBy(SecurityUtils.getUserId()); |
| | | if (!updateById(card)) { |
| | | throw new ServiceException("修改卡片失败"); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean deleteCards(List<Long> ids) { |
| | | if (ids == null || ids.isEmpty()) { |
| | | throw new ServiceException("请选择需要删除的卡片"); |
| | | } |
| | | List<Long> distinctIds = new java.util.ArrayList<>(new HashSet<>(ids)); |
| | | if (listByIds(distinctIds).size() != distinctIds.size()) { |
| | | throw new ServiceException("部分卡片不存在或已删除"); |
| | | } |
| | | if (!removeByIds(distinctIds)) { |
| | | throw new ServiceException("删除卡片失败"); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateStatus(ChargingCardStatusDTO dto) { |
| | | if (dto == null || dto.getId() == null || !isValidStatus(dto.getStatus())) { |
| | | throw new ServiceException("卡片状态参数错误"); |
| | | } |
| | | if (getById(dto.getId()) == null) { |
| | | throw new ServiceException("卡片不存在或已删除"); |
| | | } |
| | | TChargingCard card = new TChargingCard(); |
| | | card.setId(dto.getId()); |
| | | card.setStatus(dto.getStatus()); |
| | | card.setUpdateTime(LocalDateTime.now()); |
| | | card.setUpdateBy(SecurityUtils.getUserId()); |
| | | if (!updateById(card)) { |
| | | throw new ServiceException("更新卡片状态失败"); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean updateBalance(ChargingCardBalanceDTO dto) { |
| | | validateBalanceRequest(dto); |
| | | verifyOperationPassword(dto.getOperationPassword()); |
| | | |
| | | List<TChargingCard> cards = listByIds(dto.getIds()); |
| | | if (cards.size() != new HashSet<>(dto.getIds()).size()) { |
| | | throw new ServiceException("部分卡片不存在或已删除"); |
| | | } |
| | | int updated = baseMapper.adjustBalance(dto.getIds(), dto.getAmount(), dto.getType(), |
| | | MAX_AMOUNT, SecurityUtils.getUserId()); |
| | | if (updated != cards.size()) { |
| | | throw new ServiceException(dto.getType() == BALANCE_SUBTRACT |
| | | ? "部分卡片余额不足,无法完成扣减" |
| | | : "部分卡片余额超过上限,无法完成增加"); |
| | | } |
| | | for (TChargingCard card : cards) { |
| | | baseMapper.insertBalanceRecord(card.getId(), dto.getType(), dto.getAmount(), |
| | | StringUtils.isEmpty(dto.getRemark()) ? null : dto.getRemark().trim(), SecurityUtils.getUserId()); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public List<ChargingCardExcelDTO> selectExportList(ChargingCardQueryDTO query) { |
| | | return baseMapper.selectExportList(query == null ? new ChargingCardQueryDTO() : query); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public String importCards(List<ChargingCardExcelDTO> cards) { |
| | | if (cards == null || cards.isEmpty()) { |
| | | throw new ServiceException("导入数据不能为空"); |
| | | } |
| | | Set<String> importCardNos = new HashSet<>(); |
| | | int row = 1; |
| | | for (ChargingCardExcelDTO item : cards) { |
| | | row++; |
| | | if (item == null || StringUtils.isEmpty(item.getCardNo())) { |
| | | throw new ServiceException("第" + row + "行卡号不能为空"); |
| | | } |
| | | String cardNo = item.getCardNo().trim(); |
| | | if (cardNo.length() > 64) { |
| | | throw new ServiceException("第" + row + "行卡号不能超过64个字符"); |
| | | } |
| | | if (!importCardNos.add(cardNo)) { |
| | | throw new ServiceException("第" + row + "行卡号在文件中重复"); |
| | | } |
| | | if (existsCardNo(cardNo, null)) { |
| | | throw new ServiceException("第" + row + "行卡号已存在"); |
| | | } |
| | | if (item.getBalance() != null) { |
| | | validateAmount(item.getBalance(), true, "第" + row + "行卡余额"); |
| | | } |
| | | parseExcelStatus(item.getStatus(), row); |
| | | } |
| | | |
| | | Long userId = SecurityUtils.getUserId(); |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | for (ChargingCardExcelDTO item : cards) { |
| | | TChargingCard card = new TChargingCard(); |
| | | card.setCardNo(item.getCardNo().trim()); |
| | | card.setBalance(item.getBalance() == null ? BigDecimal.ZERO : item.getBalance()); |
| | | card.setStatus(parseExcelStatus(item.getStatus(), 0)); |
| | | card.setDelFlag(0); |
| | | card.setCreateTime(now); |
| | | card.setCreateBy(userId); |
| | | save(card); |
| | | } |
| | | return "成功导入" + cards.size() + "条卡片数据"; |
| | | } |
| | | |
| | | private void validateCard(ChargingCardSaveDTO dto, boolean update) { |
| | | if (dto == null || StringUtils.isEmpty(dto.getCardNo())) { |
| | | throw new ServiceException("卡号不能为空"); |
| | | } |
| | | if (update && dto.getId() == null) { |
| | | throw new ServiceException("卡片ID不能为空"); |
| | | } |
| | | String cardNo = dto.getCardNo().trim(); |
| | | if (cardNo.length() > 64) { |
| | | throw new ServiceException("卡号不能超过64个字符"); |
| | | } |
| | | if (!update && dto.getBalance() != null) { |
| | | validateAmount(dto.getBalance(), true, "卡余额"); |
| | | } |
| | | if (dto.getStatus() != null && !isValidStatus(dto.getStatus())) { |
| | | throw new ServiceException("卡片状态参数错误"); |
| | | } |
| | | if (existsCardNo(cardNo, dto.getId())) { |
| | | throw new ServiceException("卡号已存在"); |
| | | } |
| | | } |
| | | |
| | | private boolean existsCardNo(String cardNo, Long excludeId) { |
| | | return baseMapper.countByCardNo(cardNo, excludeId) > 0; |
| | | } |
| | | |
| | | private void validateBalanceRequest(ChargingCardBalanceDTO dto) { |
| | | if (dto == null || dto.getIds() == null || dto.getIds().isEmpty()) { |
| | | throw new ServiceException("请选择需要更新余额的卡片"); |
| | | } |
| | | if (dto.getType() == null || (dto.getType() != BALANCE_ADD && dto.getType() != BALANCE_SUBTRACT)) { |
| | | throw new ServiceException("余额调整类型错误"); |
| | | } |
| | | validateAmount(dto.getAmount(), false, "调整金额"); |
| | | if (dto.getRemark() != null && dto.getRemark().trim().length() > 255) { |
| | | throw new ServiceException("备注不能超过255个字符"); |
| | | } |
| | | if (StringUtils.isEmpty(dto.getOperationPassword())) { |
| | | throw new ServiceException("请输入操作密码"); |
| | | } |
| | | } |
| | | |
| | | private void validateAmount(BigDecimal amount, boolean allowZero, String fieldName) { |
| | | if (amount == null || (allowZero ? amount.compareTo(BigDecimal.ZERO) < 0 : amount.compareTo(BigDecimal.ZERO) <= 0)) { |
| | | throw new ServiceException(fieldName + (allowZero ? "不能小于0" : "必须大于0")); |
| | | } |
| | | if (amount.scale() > 2) { |
| | | throw new ServiceException(fieldName + "最多保留2位小数"); |
| | | } |
| | | if (amount.compareTo(MAX_AMOUNT) > 0) { |
| | | throw new ServiceException(fieldName + "不能超过" + MAX_AMOUNT.toPlainString()); |
| | | } |
| | | } |
| | | |
| | | private Integer parseExcelStatus(String status, int row) { |
| | | if (StringUtils.isEmpty(status)) { |
| | | return ENABLED; |
| | | } |
| | | String value = status.trim(); |
| | | if ("1".equals(value) || "启用".equals(value)) { |
| | | return ENABLED; |
| | | } |
| | | if ("2".equals(value) || "禁用".equals(value)) { |
| | | return DISABLED; |
| | | } |
| | | String prefix = row > 0 ? "第" + row + "行" : ""; |
| | | throw new ServiceException(prefix + "启用状态错误"); |
| | | } |
| | | |
| | | private void verifyOperationPassword(String operationPassword) { |
| | | LoginUser loginUser = tokenService.getLoginUser(); |
| | | if (loginUser == null || loginUser.getUserid() == null) { |
| | | throw new ServiceException("登录状态已失效,请重新登录"); |
| | | } |
| | | R<SysUser> response = sysUserClient.getSysUser(loginUser.getUserid()); |
| | | SysUser user = response == null ? null : response.getData(); |
| | | if (user == null || StringUtils.isEmpty(user.getOperationPassword())) { |
| | | throw new ServiceException("当前账号未设置操作密码"); |
| | | } |
| | | if (!SecurityUtils.matchesPassword(operationPassword, user.getOperationPassword())) { |
| | | throw new ServiceException("操作密码错误"); |
| | | } |
| | | } |
| | | |
| | | private boolean isValidStatus(Integer status) { |
| | | return status != null && (status == ENABLED || status == DISABLED); |
| | | } |
| | | } |