| | |
| | | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.api.feignClient.AppUserWhitelistClient; |
| | | import com.ruoyi.account.api.feignClient.ChargingCardClient; |
| | | import com.ruoyi.account.api.feignClient.VinManagementClient; |
| | | import com.ruoyi.account.api.model.TAppUserWhitelist; |
| | | import com.ruoyi.account.api.model.TChargingCard; |
| | | import com.ruoyi.account.api.model.TVinManagement; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.other.api.domain.TFleet; |
| | | import com.ruoyi.other.api.domain.TGroupCompany; |
| | | import com.ruoyi.other.api.model.TCompanyRechargeRecord; |
| | | import com.ruoyi.other.api.vo.CompanyChargingUserVO; |
| | | import com.ruoyi.other.mapper.TCompanyRechargeRecordMapper; |
| | | import com.ruoyi.other.mapper.TFleetMapper; |
| | | import com.ruoyi.other.mapper.TGroupCompanyMapper; |
| | |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | /** 公司账号角色类型(sys_user.roleType=5) */ |
| | | private static final int COMPANY_ROLE_TYPE = 5; |
| | | |
| | | /** 账户模式:共享模式(新增企业未指定时按此建档) */ |
| | | private static final int ACCOUNT_MODE_SHARED = 1; |
| | | |
| | | /** 账户模式:分配模式 */ |
| | | private static final int ACCOUNT_MODE_ALLOCATION = 2; |
| | | |
| | | /** 充电用户类型:VIN码 */ |
| | | private static final int USER_TYPE_VIN = 1; |
| | | |
| | | /** 充电用户类型:刷卡 */ |
| | | private static final int USER_TYPE_CARD = 2; |
| | | |
| | | /** 充电用户类型:白名单 */ |
| | | private static final int USER_TYPE_WHITELIST = 3; |
| | | |
| | | /** 账户状态:正常 */ |
| | | private static final int ACCOUNT_STATUS_NORMAL = 1; |
| | | |
| | | /** 账户状态:欠款 */ |
| | | private static final int ACCOUNT_STATUS_OVERDUE = 2; |
| | | |
| | | /** |
| | | * 车队 Mapper。 |
| | | * 此处注入 Mapper 而非 TFleetService:TFleetServiceImpl 已依赖 TGroupCompanyService, |
| | |
| | | @Resource |
| | | private SysRoleClient sysRoleClient; |
| | | |
| | | /** VIN管理远程客户端(公司详情-充电用户信息聚合使用) */ |
| | | @Resource |
| | | private VinManagementClient vinManagementClient; |
| | | |
| | | /** 充电卡远程客户端(公司详情-充电用户信息聚合使用) */ |
| | | @Resource |
| | | private ChargingCardClient chargingCardClient; |
| | | |
| | | /** 白名单远程客户端(公司详情-充电用户信息聚合使用) */ |
| | | @Resource |
| | | private AppUserWhitelistClient appUserWhitelistClient; |
| | | |
| | | @Override |
| | | public TGroupCompany getDetail(Integer id) { |
| | | if (id == null) { |
| | |
| | | // 累计充值到账金额:作为公司总账户余额展示(额度分配弹窗使用),仅覆盖响应对象,不落库 |
| | | company.setTotalRechargeAmount(sumRechargeAmount(id)); |
| | | return company; |
| | | } |
| | | |
| | | @Override |
| | | public TGroupCompany getDetailWithChargingUsers(Integer id) { |
| | | TGroupCompany company = getDetail(id); |
| | | if (company == null) { |
| | | return null; |
| | | } |
| | | company.setChargingUsers(buildChargingUsers(company)); |
| | | return company; |
| | | } |
| | | |
| | | /** |
| | | * 聚合公司充电用户信息:VIN码、刷卡、白名单三类数据按统一结构返回。 |
| | | * 仅公司详情使用;remoteGet 远程调用保持 getDetail(不聚合),避免跨服务循环调用。 |
| | | */ |
| | | private List<CompanyChargingUserVO> buildChargingUsers(TGroupCompany company) { |
| | | Integer companyId = company.getId(); |
| | | Integer accountMode = company.getAccountMode(); |
| | | List<CompanyChargingUserVO> result = new ArrayList<>(); |
| | | |
| | | List<TVinManagement> vins = fetchVins(companyId); |
| | | List<TChargingCard> cards = fetchCards(companyId); |
| | | List<TAppUserWhitelist> whitelists = fetchWhitelists(companyId); |
| | | |
| | | List<Integer> fleetIds = new ArrayList<>(); |
| | | for (TVinManagement vin : vins) { |
| | | if (vin.getFleetId() != null) { |
| | | fleetIds.add(vin.getFleetId()); |
| | | } |
| | | } |
| | | for (TChargingCard card : cards) { |
| | | if (card.getFleetId() != null) { |
| | | fleetIds.add(card.getFleetId()); |
| | | } |
| | | } |
| | | for (TAppUserWhitelist whitelist : whitelists) { |
| | | if (whitelist.getFleetId() != null) { |
| | | fleetIds.add(whitelist.getFleetId()); |
| | | } |
| | | } |
| | | Map<Integer, String> fleetNameMap = loadFleetNameMap(fleetIds); |
| | | |
| | | String companyName = company.getName(); |
| | | BigDecimal companyBalance = company.getAvailableBalance(); |
| | | for (TVinManagement vin : vins) { |
| | | result.add(buildRow(USER_TYPE_VIN + "-" + vin.getId(), USER_TYPE_VIN, vin.getVin(), |
| | | companyName, fleetNameMap.get(vin.getFleetId()), accountMode, |
| | | vin.getBalance(), companyBalance, vin.getStatus())); |
| | | } |
| | | for (TChargingCard card : cards) { |
| | | result.add(buildRow(USER_TYPE_CARD + "-" + card.getId(), USER_TYPE_CARD, card.getCardNo(), |
| | | companyName, fleetNameMap.get(card.getFleetId()), accountMode, |
| | | card.getBalance(), companyBalance, card.getStatus())); |
| | | } |
| | | for (TAppUserWhitelist whitelist : whitelists) { |
| | | result.add(buildRow(USER_TYPE_WHITELIST + "-" + whitelist.getId(), USER_TYPE_WHITELIST, whitelist.getPhone(), |
| | | companyName, fleetNameMap.get(whitelist.getFleetId()), accountMode, |
| | | whitelist.getBalance(), companyBalance, whitelist.getStatus())); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 组装单行充电用户信息。可用余额:分配模式取子账户余额/初始分配额度,共享模式取公司可用余额。 |
| | | * 超额/账户状态按余额正负推算:余额为负时超额=|余额|、账户状态=欠款;否则无超额、状态正常。 |
| | | */ |
| | | private CompanyChargingUserVO buildRow(String rowKey, Integer userType, String userInfo, |
| | | String companyName, String fleetName, Integer accountMode, |
| | | BigDecimal accountBalance, BigDecimal companyBalance, Integer status) { |
| | | CompanyChargingUserVO vo = new CompanyChargingUserVO(); |
| | | vo.setRowKey(rowKey); |
| | | vo.setUserType(userType); |
| | | vo.setUserInfo(userInfo); |
| | | vo.setCompanyName(companyName); |
| | | vo.setFleetName(fleetName); |
| | | vo.setAccountMode(accountMode); |
| | | vo.setBalance(resolveBalance(accountMode, accountBalance, companyBalance)); |
| | | vo.setOverrun(null); |
| | | vo.setAccountStatus(ACCOUNT_STATUS_NORMAL); |
| | | BigDecimal balance = vo.getBalance(); |
| | | if (balance != null && balance.compareTo(BigDecimal.ZERO) < 0) { |
| | | vo.setOverrun(balance.abs().setScale(AMOUNT_SCALE, RoundingMode.HALF_UP)); |
| | | vo.setAccountStatus(ACCOUNT_STATUS_OVERDUE); |
| | | } |
| | | vo.setStatus(status); |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * 计算可用余额:分配模式=子账户余额/初始分配额度,共享模式=公司可用余额 |
| | | */ |
| | | private BigDecimal resolveBalance(Integer accountMode, BigDecimal accountBalance, BigDecimal companyBalance) { |
| | | if (Integer.valueOf(ACCOUNT_MODE_ALLOCATION).equals(accountMode)) { |
| | | return accountBalance; |
| | | } |
| | | if (Integer.valueOf(ACCOUNT_MODE_SHARED).equals(accountMode)) { |
| | | return companyBalance; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 远程查询公司VIN码列表(降级返回空列表,保证详情主流程不受影响) |
| | | */ |
| | | private List<TVinManagement> fetchVins(Integer companyId) { |
| | | try { |
| | | R<List<TVinManagement>> response = vinManagementClient.listByCompany(companyId); |
| | | return (response != null && R.isSuccess(response) && response.getData() != null) |
| | | ? response.getData() : new ArrayList<>(); |
| | | } catch (Exception e) { |
| | | return new ArrayList<>(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 远程查询公司卡片列表(降级返回空列表) |
| | | */ |
| | | private List<TChargingCard> fetchCards(Integer companyId) { |
| | | try { |
| | | R<List<TChargingCard>> response = chargingCardClient.listByCompany(companyId); |
| | | return (response != null && R.isSuccess(response) && response.getData() != null) |
| | | ? response.getData() : new ArrayList<>(); |
| | | } catch (Exception e) { |
| | | return new ArrayList<>(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 远程查询公司白名单列表(降级返回空列表) |
| | | */ |
| | | private List<TAppUserWhitelist> fetchWhitelists(Integer companyId) { |
| | | try { |
| | | R<List<TAppUserWhitelist>> response = appUserWhitelistClient.listByCompany(companyId); |
| | | return (response != null && R.isSuccess(response) && response.getData() != null) |
| | | ? response.getData() : new ArrayList<>(); |
| | | } catch (Exception e) { |
| | | return new ArrayList<>(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 批量查询车队名称(本地库 t_fleet,逻辑删除由 @TableLogic 自动过滤) |
| | | */ |
| | | private Map<Integer, String> loadFleetNameMap(List<Integer> fleetIds) { |
| | | Map<Integer, String> map = new HashMap<>(); |
| | | if (fleetIds == null || fleetIds.isEmpty()) { |
| | | return map; |
| | | } |
| | | List<Integer> distinctIds = fleetIds.stream() |
| | | .filter(Objects::nonNull) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | if (distinctIds.isEmpty()) { |
| | | return map; |
| | | } |
| | | List<TFleet> fleets = fleetMapper.selectList( |
| | | Wrappers.<TFleet>lambdaQuery().in(TFleet::getId, distinctIds)); |
| | | for (TFleet fleet : fleets) { |
| | | map.put(fleet.getId(), fleet.getFleetName()); |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | |
| | | public AjaxResult addCompany(TGroupCompany company) { |
| | | if (!StringUtils.hasText(company.getAccount())) { |
| | | return AjaxResult.error("登录账号不能为空"); |
| | | } |
| | | // 添加企业弹窗不再配置账户模式:未指定时按共享模式建档,后续可在“账户模式”弹窗切换 |
| | | if (company.getAccountMode() == null) { |
| | | company.setAccountMode(ACCOUNT_MODE_SHARED); |
| | | } |
| | | if (!StringUtils.hasText(company.getPassword())) { |
| | | return AjaxResult.error("登录密码不能为空"); |
| | |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult updateAccountMode(Integer id, Integer accountMode) { |
| | | if (id == null) { |
| | | return AjaxResult.error("公司ID不能为空"); |
| | | } |
| | | if (accountMode == null |
| | | || (accountMode != ACCOUNT_MODE_SHARED && accountMode != ACCOUNT_MODE_ALLOCATION)) { |
| | | return AjaxResult.error("账户模式不合法"); |
| | | } |
| | | TGroupCompany company = getById(id); |
| | | if (company == null) { |
| | | return AjaxResult.error("公司不存在"); |
| | | } |
| | | TGroupCompany update = new TGroupCompany(); |
| | | update.setId(id); |
| | | update.setAccountMode(accountMode); |
| | | updateById(update); |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | | } |