Merge branch '2.2' of http://120.76.84.145:10101/gitblit/r/java/mx_charging_pile into 2.2
| | |
| | | @ApiModel(value = "AppUserWhitelistImportDTO", description = "白名单用户导入行") |
| | | public class AppUserWhitelistImportDTO { |
| | | |
| | | @Excel(name = "用户手机号", prompt = "填写11位手机号,如:13800138000") |
| | | @Excel(name = "用户手机号", width = 18, prompt = "填写11位手机号,如:13800138000") |
| | | @ApiModelProperty(value = "用户手机号") |
| | | private String phone; |
| | | |
| | | @Excel(name = "享受权益", prompt = "1=全部免费,2=免电费,3=免服务费", combo = {"1", "2", "3"}) |
| | | @Excel(name = "享受权益", width = 18, prompt = "1=全部免费,2=免电费,3=免服务费", combo = {"1", "2", "3"}) |
| | | @ApiModelProperty(value = "享受权益") |
| | | private String benefitType; |
| | | |
| | | @Excel(name = "白名单电站", prompt = "填写all表示全部电站;指定电站填写平台站点编号,多个用英文逗号分隔,如:ST001,ST002") |
| | | @Excel(name = "白名单电站", width = 40, prompt = "填写all表示全部电站;指定电站填写平台站点编号,多个用英文逗号分隔,如:ST001,ST002") |
| | | @ApiModelProperty(value = "白名单电站") |
| | | private String whitelistSite; |
| | | } |
| | |
| | | private String userId; |
| | | @TableField(exist = false) |
| | | private String uid; |
| | | @TableField(exist = false) |
| | | private Integer siteId; |
| | | } |
| | |
| | | @ApiModelProperty(value = "站点id") |
| | | private Integer siteId; |
| | | |
| | | @ApiModelProperty(value = "当前账号可查看的站点id,前端忽略") |
| | | private List<Integer> siteIds; |
| | | |
| | | @ApiModelProperty(value = "合作商id") |
| | | private Integer partnerId; |
| | | |
| | |
| | | * @date 2026-06-25 |
| | | */ |
| | | public interface SysFaqMapper { |
| | | |
| | | int ensureFaultPullTutorial(); |
| | | /** |
| | | * 查询常见问题 |
| | | * |
| | |
| | | |
| | | import java.util.List; |
| | | import javax.annotation.Resource; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import org.springframework.stereotype.Service; |
| | | import com.ruoyi.system.mapper.SysFaqMapper; |
| | | import com.ruoyi.system.domain.SysFaq; |
| | |
| | | */ |
| | | @Service |
| | | public class SysFaqServiceImpl implements ISysFaqService { |
| | | private static final String FAULT_PULL_TUTORIAL = "故障拔枪教程"; |
| | | |
| | | @Resource |
| | | private SysFaqMapper sysFaqMapper; |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public List<SysFaq> selectSysFaqList(SysFaq sysFaq) { |
| | | sysFaqMapper.ensureFaultPullTutorial(); |
| | | return sysFaqMapper.selectSysFaqList(sysFaq); |
| | | } |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public int deleteSysFaqByIds(Long[] faqIds) { |
| | | for (Long faqId : faqIds) { |
| | | SysFaq faq = sysFaqMapper.selectSysFaqById(faqId); |
| | | if (faq != null && FAULT_PULL_TUTORIAL.equals(faq.getQuestion())) { |
| | | throw new ServiceException("故障拔枪教程为固定内容,只能编辑"); |
| | | } |
| | | } |
| | | return sysFaqMapper.deleteSysFaqByIds(faqIds); |
| | | } |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public int deleteSysFaqById(Long faqId) { |
| | | SysFaq faq = sysFaqMapper.selectSysFaqById(faqId); |
| | | if (faq != null && FAULT_PULL_TUTORIAL.equals(faq.getQuestion())) { |
| | | throw new ServiceException("故障拔枪教程为固定内容,只能编辑"); |
| | | } |
| | | return sysFaqMapper.deleteSysFaqById(faqId); |
| | | } |
| | | |
| | |
| | | from sys_faq |
| | | </sql> |
| | | |
| | | <insert id="ensureFaultPullTutorial"> |
| | | insert into sys_faq (question, answer, sort_order, status, create_by, create_time, del_flag) |
| | | select '故障拔枪教程', '', 0, '0', 'system', now(), '0' |
| | | where not exists ( |
| | | select 1 from sys_faq where question = '故障拔枪教程' and del_flag = '0' |
| | | ) |
| | | </insert> |
| | | |
| | | <select id="selectSysFaqList" parameterType="com.ruoyi.system.domain.SysFaq" resultMap="SysFaqResult"> |
| | | <include refid="selectSysFaqVo"/> |
| | | <where> |
| | |
| | | @Resource |
| | | private SiteClient siteClient; |
| | | |
| | | @Value("${wx.applet.price-drop-template-id:}") |
| | | @Value("${wx.applet.price-drop-template-id:7nCycRUZxQ2jxAb2UaYazjp2sPZy3qYyeLqVytyhHhY}") |
| | | private String priceDropTemplateId; |
| | | |
| | | @GetMapping("/list") |
| | |
| | | @Resource |
| | | private RedissonClient redissonClient; |
| | | |
| | | @Value("${wx.applet.price-drop-template-id:}") |
| | | @Value("${wx.applet.price-drop-template-id:7nCycRUZxQ2jxAb2UaYazjp2sPZy3qYyeLqVytyhHhY}") |
| | | private String templateId; |
| | | |
| | | @Value("${wx.applet.price-drop-page:pagesMine/myCollection/myCollection}") |
| | | @Value("${wx.applet.price-drop-page:pagesMine/favoriteSite/favoriteSite}") |
| | | private String page; |
| | | |
| | | @Scheduled(fixedDelay = 30 * 60 * 1000L, initialDelay = 2 * 60 * 1000L) |
| | |
| | | } |
| | | |
| | | Integer resolveDefaultRoleId(Integer partnerType) { |
| | | String roleName = partnerTypeRoleName(partnerType); |
| | | Integer roleId = this.baseMapper.getDefaultPartnerRoleId(roleName); |
| | | if (roleId == null && !Integer.valueOf(1).equals(partnerType)) { |
| | | roleId = this.baseMapper.getDefaultPartnerRoleId("合作商"); |
| | | List<String> roleNames = partnerTypeRoleNames(partnerType); |
| | | Integer roleId = null; |
| | | for (String roleName : roleNames) { |
| | | roleId = this.baseMapper.getDefaultPartnerRoleId(roleName); |
| | | if (roleId != null) { |
| | | break; |
| | | } |
| | | } |
| | | if (roleId == null) { |
| | | throw new RuntimeException("系统内置角色【" + roleName + "】不存在,请先配置角色"); |
| | | throw new RuntimeException("系统内置角色【" + roleNames.get(0) + "】不存在,请先配置角色"); |
| | | } |
| | | return roleId; |
| | | } |
| | | |
| | | private String partnerTypeRoleName(Integer partnerType) { |
| | | private List<String> partnerTypeRoleNames(Integer partnerType) { |
| | | if (Integer.valueOf(2).equals(partnerType)) { |
| | | return "场地方"; |
| | | return Arrays.asList("场地方", "合作商"); |
| | | } |
| | | if (Integer.valueOf(3).equals(partnerType)) { |
| | | return "服务商"; |
| | | return Arrays.asList("服务商", "合作商"); |
| | | } |
| | | return "合作商"; |
| | | return Arrays.asList("独立合作商", "合作商"); |
| | | } |
| | | /** |
| | | * 删除合作商 |
| | |
| | | } |
| | | |
| | | @Test |
| | | void independentPartnerUsesUnifiedRoleNameBeforeLegacyAlias() { |
| | | PartnerServiceImpl service = new PartnerServiceImpl(); |
| | | PartnerMapper mapper = mock(PartnerMapper.class); |
| | | ReflectionTestUtils.setField(service, "baseMapper", mapper); |
| | | when(mapper.getDefaultPartnerRoleId("独立合作商")).thenReturn(11); |
| | | |
| | | assertEquals(11, service.resolveDefaultRoleId(1)); |
| | | verify(mapper).getDefaultPartnerRoleId("独立合作商"); |
| | | verify(mapper, never()).getDefaultPartnerRoleId("合作商"); |
| | | } |
| | | |
| | | @Test |
| | | void clearingShareRatiosStillProducesExplicitDatabaseUpdate() { |
| | | PartnerServiceImpl service = new PartnerServiceImpl(); |
| | | PartnerMapper mapper = mock(PartnerMapper.class); |
| | |
| | | export.setPhone(dto.getPhone()); |
| | | export.setOrderStatus(dto.getPayTime() != null ? "订单支付成功" : "订单完成"); |
| | | export.setStatus(formatPayOrderStatus(dto.getType(), dto.getStatus())); |
| | | export.setRefundStatus(dto.getRefundStatus() != null && dto.getRefundStatus() == 1 ? "有退款" : "无退款"); |
| | | export.setRefundStatus(dto.getRefundStatus() != null && dto.getRefundStatus() > 0 ? "有退款" : "无退款"); |
| | | export.setRechargeAmount(dto.getRechargeAmount()); |
| | | export.setPaymentAmount(dto.getPaymentAmount()); |
| | | export.setFinalAmount(dto.getFinalAmount()); |
| | |
| | | @PostMapping(value = "/pay/order/refund/list") |
| | | @ApiOperation(value = "列表", tags = {"管理后台-支付订单-退款订单"}) |
| | | public R<PageInfo<TChargingOrderRefund>> refundList(@RequestBody ChargingRefundDto chargingRefundDto) { |
| | | Integer pageCurr = chargingRefundDto.getPageCurr(); |
| | | Integer pageSize = chargingRefundDto.getPageSize(); |
| | | // R<PageInfo<TChargingOrderRefund>> refundList = chargingOrderService.getRefundList(chargingRefundDto); |
| | | chargingRefundDto.setPageCurr(1); |
| | | chargingRefundDto.setPageSize(199999999); |
| | | R<PageInfo<TChargingOrderRefund>> refundList1 = chargingOrderService.getRefundList(chargingRefundDto); |
| | | Long userId = tokenService.getLoginUser().getUserid(); |
| | | //如果没传siteId,获取当前登陆人所有的siteIds |
| | | List<Integer> siteIds = new ArrayList<>(); |
| | | if (userId != null){ |
| | | List<GetSiteListDTO> data = siteClient.getSiteListByUserId(userId).getData(); |
| | | for (GetSiteListDTO datum : data) { |
| | | siteIds.add(datum.getId()); |
| | | SysUser sysUser = sysUserClient.getSysUser(userId).getData(); |
| | | if (sysUser != null && Integer.valueOf(2).equals(sysUser.getRoleType())) { |
| | | List<Integer> siteIds = new ArrayList<>(); |
| | | List<GetSiteListDTO> sites = siteClient.getSiteListByUserId(userId).getData(); |
| | | if (sites != null) { |
| | | for (GetSiteListDTO site : sites) { |
| | | siteIds.add(site.getId()); |
| | | } |
| | | } |
| | | |
| | | if (siteIds.isEmpty()){ |
| | | siteIds.add(-1); |
| | | chargingRefundDto.setSiteIds(siteIds.isEmpty() ? Collections.singletonList(-1) : siteIds); |
| | | } |
| | | // 查询当前登陆人按钮权限 |
| | | SysUser sysUser = sysUserClient.getSysUser(tokenService.getLoginUser().getUserid()).getData(); |
| | | Integer roleType = sysUser.getRoleType(); |
| | | List<TChargingOrderRefund> tChargingOrderRefunds = new ArrayList<>(); |
| | | for (TChargingOrderRefund record : refundList1.getData().getRecords()) { |
| | | if (roleType==1){ |
| | | tChargingOrderRefunds.add(record); |
| | | continue; |
| | | } |
| | | if (record.getType()!=1){ |
| | | tChargingOrderRefunds.add(record); |
| | | } |
| | | TChargingOrder byId = chargingOrderService.getById(record.getOrderId()); |
| | | record.setUid(record.getId().toString()); |
| | | if (byId==null){ |
| | | continue; |
| | | } |
| | | if (roleType==2&&siteIds.contains(byId.getSiteId())){ |
| | | |
| | | tChargingOrderRefunds.add(record); |
| | | } |
| | | } |
| | | PageInfo<TChargingOrderRefund> data = refundList1.getData(); |
| | | |
| | | List<TChargingOrderRefund> res1 = testing4(tChargingOrderRefunds.size(), pageCurr, pageSize, tChargingOrderRefunds); |
| | | data.setTotal(tChargingOrderRefunds.size()); |
| | | data.setRecords(res1); |
| | | return refundList1; |
| | | |
| | | return chargingOrderService.getRefundList(chargingRefundDto); |
| | | } |
| | | |
| | | |
| | |
| | | import com.ruoyi.order.api.model.TShoppingOrder; |
| | | import com.ruoyi.order.api.model.TVipOrder; |
| | | import com.ruoyi.order.api.model.TVipOrderRefund; |
| | | import com.ruoyi.order.api.query.ChargingOrderQuery; |
| | | import com.ruoyi.order.api.query.ShoppingOrderQuery; |
| | | import com.ruoyi.order.api.query.VipShoppingOrderQuery; |
| | | import com.ruoyi.order.api.vo.ChargingOrderVO; |
| | | import com.ruoyi.order.dto.TEnterpriseExport; |
| | | import com.ruoyi.order.export.EnterpriseChargingDetailExport; |
| | | import com.ruoyi.order.export.TVipOrderExport; |
| | | import com.ruoyi.order.service.TChargingOrderService; |
| | | import com.ruoyi.order.service.TVipOrderRefundService; |
| | | import com.ruoyi.order.service.TVipOrderService; |
| | | import com.ruoyi.other.api.domain.TEnterpriseUserApplication; |
| | |
| | | private OtherClient otherClient; |
| | | @Resource |
| | | private TVipOrderRefundService vipOrderRefundService; |
| | | @Resource |
| | | private TChargingOrderService chargingOrderService; |
| | | |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | @RequiresPermissions(value = {"/vipList", "/vipList/export"}, logical = Logical.OR) |
| | | @ApiOperation(tags = {"管理后台-会员列表"}, value = "导出会员充值订单") |
| | | @ApiOperation(tags = {"管理后台-会员列表"}, value = "导出会员充电订单") |
| | | @PutMapping(value = "/exportVipOrderByVipUser") |
| | | @Log(title = "会员列表导出会员充值订单", businessType = BusinessType.EXPORT) |
| | | @Log(title = "会员列表导出会员充电订单", businessType = BusinessType.EXPORT) |
| | | public void exportVipOrderByVipUser(@RequestBody UserListQueryDto query) { |
| | | List<Long> userIds = appUserClient.getVipUserIds(query).getData(); |
| | | if (userIds == null || userIds.isEmpty()) { |
| | | writeVipOrderWorkbook(new ArrayList<>()); |
| | | writeVipChargingOrderWorkbook(new ArrayList<>()); |
| | | return; |
| | | } |
| | | VipShoppingOrderQuery orderQuery = new VipShoppingOrderQuery(); |
| | | ChargingOrderQuery orderQuery = new ChargingOrderQuery(); |
| | | orderQuery.setUserIds(userIds); |
| | | if (query != null) { |
| | | orderQuery.setVipId(query.getVipTypeId()); |
| | | } |
| | | orderQuery.setPageCurr(1); |
| | | orderQuery.setPageSize(100000); |
| | | List<TVipOrder> list = vipOrderService.pageList(orderQuery).getRecords(); |
| | | List<TVipOrderExport> exports = new ArrayList<>(); |
| | | for (TVipOrder vipOrder : list) { |
| | | TVipOrderExport export = new TVipOrderExport(); |
| | | BeanUtils.copyProperties(vipOrder, export); |
| | | export.setCreateTime(DateUtils.localDateTimeToString(vipOrder.getCreateTime())); |
| | | List<ChargingOrderVO> list = chargingOrderService.chargingOrderList(orderQuery).getRecords(); |
| | | List<EnterpriseChargingDetailExport> exports = new ArrayList<>(); |
| | | for (ChargingOrderVO order : list) { |
| | | EnterpriseChargingDetailExport export = new EnterpriseChargingDetailExport(); |
| | | export.setCode(order.getCode()); |
| | | export.setOrderType(Integer.valueOf(1).equals(order.getOrderType()) ? "小程序" : "刷卡"); |
| | | export.setOrderClassification("充电订单"); |
| | | export.setSiteName(order.getSiteName()); |
| | | export.setTerminalName(order.getTerminalName()); |
| | | export.setStatus(getChargingOrderStatus(order.getStatus())); |
| | | export.setChargingSecond(order.getChargingSecond()); |
| | | export.setTotalAmount(order.getOrderAmount()); |
| | | export.setCouponDiscountAmount(order.getCouponDiscountAmount()); |
| | | export.setVipDiscountAmount(order.getVipDiscountAmount()); |
| | | export.setPaymentAmount(order.getPaymentAmount()); |
| | | export.setRefundAmount(order.getRefundAmount()); |
| | | export.setPhone(order.getPhone()); |
| | | export.setOrderSource(getChargingOrderSource(order.getOrderSource())); |
| | | export.setStartTime(DateUtils.localDateTimeToString(order.getStartTime())); |
| | | export.setEndTime(DateUtils.localDateTimeToString(order.getEndTime())); |
| | | exports.add(export); |
| | | } |
| | | writeVipOrderWorkbook(exports); |
| | | writeVipChargingOrderWorkbook(exports); |
| | | } |
| | | |
| | | private String getChargingOrderStatus(Integer status) { |
| | | if (status == null) return "未知"; |
| | | String[] names = {"未知", "等待中", "启动中", "充电中", "停止中", "已结束"}; |
| | | return status >= 0 && status < names.length ? names[status] : "未知"; |
| | | } |
| | | |
| | | private String getChargingOrderSource(Integer source) { |
| | | if (Integer.valueOf(1).equals(source)) return "明星充电"; |
| | | if (Integer.valueOf(2).equals(source)) return "快电"; |
| | | if (Integer.valueOf(3).equals(source)) return "新电途"; |
| | | return ""; |
| | | } |
| | | |
| | | private void writeVipChargingOrderWorkbook(List<EnterpriseChargingDetailExport> exports) { |
| | | Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), EnterpriseChargingDetailExport.class, exports); |
| | | writeWorkbook(workbook, "会员充电订单导出.xls"); |
| | | } |
| | | |
| | | private void writeVipOrderWorkbook(List<TVipOrderExport> exports) { |
| | | Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), TVipOrderExport.class, exports); |
| | | writeWorkbook(workbook, "会员订单导出.xls"); |
| | | } |
| | | |
| | | private void writeWorkbook(Workbook workbook, String exportFileName) { |
| | | HttpServletResponse response = WebUtils.response(); |
| | | response.setCharacterEncoding("utf-8"); |
| | | ServletOutputStream outputStream = null; |
| | | try { |
| | | String fileName = URLEncoder.encode("会员订单导出.xls", "utf-8"); |
| | | String fileName = URLEncoder.encode(exportFileName, "utf-8"); |
| | | response.setHeader("Content-Disposition", "attachment;filename=" + fileName); |
| | | response.setContentType("application/vnd.ms-excel;charset=UTF-8"); |
| | | response.setHeader("Pragma", "no-cache"); |
| | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class ChargingRefundDto extends BasePage { |
| | | @ApiModelProperty("订单编号") |
| | |
| | | private String refundCode; |
| | | @ApiModelProperty("是否特殊退款处理") |
| | | private Boolean specialRefund; |
| | | @ApiModelProperty(value = "可查看站点ID", hidden = true) |
| | | private List<Integer> siteIds; |
| | | } |
| | |
| | | @ApiModelProperty("Phone") |
| | | private String phone; |
| | | |
| | | @ApiModelProperty("License plate") |
| | | private String licensePlate; |
| | | |
| | | @ApiModelProperty("Charging capacity") |
| | | private BigDecimal chargingCapacity; |
| | | |
| | | @ApiModelProperty("Electricity fee") |
| | | private BigDecimal electrovalence; |
| | | |
| | | @ApiModelProperty("Service fee") |
| | | private BigDecimal serviceCharge; |
| | | |
| | | @ApiModelProperty("Charging end mode") |
| | | private Integer endMode; |
| | | |
| | | @ApiModelProperty("Accounting period count") |
| | | private Integer periodCount; |
| | | |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private LocalDateTime createTime; |
| | | |
| | |
| | | @Excel(name = "充电时长(秒)", width = 20) |
| | | private Long chargingSecond; |
| | | |
| | | @Excel(name = "总金额", width = 20) |
| | | @Excel(name = "总金额", width = 20, numFormat = "0.00") |
| | | private BigDecimal totalAmount; |
| | | |
| | | @Excel(name = "优惠券抵扣", width = 20) |
| | | @Excel(name = "优惠券抵扣", width = 20, numFormat = "0.00") |
| | | private BigDecimal couponDiscountAmount; |
| | | |
| | | @Excel(name = "会员抵扣", width = 20) |
| | | @Excel(name = "会员抵扣", width = 20, numFormat = "0.00") |
| | | private BigDecimal vipDiscountAmount; |
| | | |
| | | @Excel(name = "实付金额", width = 20) |
| | | @Excel(name = "实付金额", width = 20, numFormat = "0.00") |
| | | private BigDecimal paymentAmount; |
| | | |
| | | @Excel(name = "退款金额", width = 20) |
| | | @Excel(name = "退款金额", width = 20, numFormat = "0.00") |
| | | private BigDecimal refundAmount; |
| | | |
| | | @Excel(name = "归属合作商/服务商", width = 30) |
| | |
| | | |
| | | List<Map<String, Object>> enterpriseTopSites(@Param("data") EnterpriseChargingAnalysisQuery query); |
| | | |
| | | List<Map<String, Object>> enterpriseTopSitesByCompanies(@Param("data") EnterpriseChargingAnalysisQuery query, |
| | | @Param("companyNames") List<String> companyNames); |
| | | |
| | | List<LocalDateTime> enterpriseChargingTimes(@Param("data") EnterpriseChargingAnalysisQuery query); |
| | | |
| | | List<Map<String, Object>> enterpriseChargingTimesByCompanies(@Param("data") EnterpriseChargingAnalysisQuery query, |
| | | @Param("companyNames") List<String> companyNames); |
| | | |
| | | List<EnterpriseChargingDetailVO> enterpriseChargingDetail(@Param("pageInfo") PageInfo<EnterpriseChargingDetailVO> pageInfo, |
| | | @Param("data") EnterpriseChargingAnalysisQuery query); |
| | | |
| | |
| | | pageInfo.setRecords(list); |
| | | return R.ok(pageInfo); |
| | | } |
| | | @Override |
| | | @Override |
| | | public R<PageInfo<EnterpriseChargingAnalysisVO>> enterpriseChargingAnalysis(EnterpriseChargingAnalysisQuery query) { |
| | | PageInfo<EnterpriseChargingAnalysisVO> pageInfo = new PageInfo<>(query.getPageCurr(), query.getPageSize()); |
| | | List<EnterpriseChargingAnalysisVO> list = this.baseMapper.enterpriseChargingAnalysis(pageInfo, query); |
| | | if (list == null || list.isEmpty()) { |
| | | pageInfo.setRecords(Collections.emptyList()); |
| | | return R.ok(pageInfo); |
| | | } |
| | | List<String> companyNames = list.stream() |
| | | .map(EnterpriseChargingAnalysisVO::getCompanyName) |
| | | .filter(Objects::nonNull) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | Map<String, List<Map<String, Object>>> topSitesByCompany = groupByCompany( |
| | | this.baseMapper.enterpriseTopSitesByCompanies(query, companyNames)); |
| | | Map<String, List<Map<String, Object>>> chargingTimesByCompany = groupByCompany( |
| | | this.baseMapper.enterpriseChargingTimesByCompanies(query, companyNames)); |
| | | for (EnterpriseChargingAnalysisVO row : list) { |
| | | EnterpriseChargingAnalysisQuery rowQuery = buildEnterpriseRowQuery(query, row); |
| | | List<Map<String, Object>> topSites = this.baseMapper.enterpriseTopSites(rowQuery); |
| | | String companyKey = companyKey(row.getCompanyName(), row.getSocialCreditCode()); |
| | | List<Map<String, Object>> topSites = topSitesByCompany.getOrDefault(companyKey, Collections.emptyList()); |
| | | String topSiteNames = topSites.stream() |
| | | .sorted(Comparator.comparing((Map<String, Object> item) -> ((Number) item.getOrDefault("counts", 0)).longValue()).reversed()) |
| | | .limit(3) |
| | | .map(item -> Objects.toString(item.get("siteName"), "")) |
| | | .filter(org.springframework.util.StringUtils::hasText) |
| | | .collect(Collectors.joining("、")); |
| | | row.setTopSiteNames(topSiteNames); |
| | | row.setAverageChargingInterval(calculateAverageChargingInterval(this.baseMapper.enterpriseChargingTimes(rowQuery))); |
| | | List<LocalDateTime> chargingTimes = chargingTimesByCompany.getOrDefault(companyKey, Collections.emptyList()).stream() |
| | | .map(item -> toLocalDateTime(item.get("startTime"))) |
| | | .filter(Objects::nonNull) |
| | | .sorted() |
| | | .collect(Collectors.toList()); |
| | | row.setAverageChargingInterval(calculateAverageChargingInterval(chargingTimes)); |
| | | } |
| | | pageInfo.setRecords(list); |
| | | return R.ok(pageInfo); |
| | | } |
| | | |
| | | private Map<String, List<Map<String, Object>>> groupByCompany(List<Map<String, Object>> rows) { |
| | | if (rows == null || rows.isEmpty()) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | return rows.stream().collect(Collectors.groupingBy(row -> companyKey( |
| | | Objects.toString(row.get("companyName"), null), |
| | | Objects.toString(row.get("socialCreditCode"), "")))); |
| | | } |
| | | |
| | | private String companyKey(String companyName, String socialCreditCode) { |
| | | return Objects.toString(companyName, "") + "\u0000" + Objects.toString(socialCreditCode, ""); |
| | | } |
| | | |
| | | private LocalDateTime toLocalDateTime(Object value) { |
| | | if (value instanceof LocalDateTime) { |
| | | return (LocalDateTime) value; |
| | | } |
| | | if (value instanceof java.sql.Timestamp) { |
| | | return ((java.sql.Timestamp) value).toLocalDateTime(); |
| | | } |
| | | if (value instanceof Date) { |
| | | return LocalDateTime.ofInstant(((Date) value).toInstant(), ZoneId.systemDefault()); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (times == null || times.size() < 2) { |
| | | return BigDecimal.ZERO; |
| | | } |
| | | long totalMinutes = 0L; |
| | | long totalSeconds = 0L; |
| | | for (int i = 1; i < times.size(); i++) { |
| | | long minutes = ChronoUnit.MINUTES.between(times.get(i - 1), times.get(i)); |
| | | if (minutes > 0) { |
| | | totalMinutes += minutes; |
| | | long seconds = Duration.between(times.get(i - 1), times.get(i)).getSeconds(); |
| | | if (seconds > 0) { |
| | | totalSeconds += seconds; |
| | | } |
| | | } |
| | | return BigDecimal.valueOf(totalMinutes) |
| | | return BigDecimal.valueOf(totalSeconds) |
| | | .divide(BigDecimal.valueOf(times.size() - 1L), 4, RoundingMode.HALF_UP) |
| | | .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP); |
| | | .divide(BigDecimal.valueOf(3600), 2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | @Override |
| | | public R<PageInfo<TChargingOrderRefund>> getRefundList(ChargingRefundDto chargingRefundDto) { |
| | | PageInfo<TChargingOrderRefund> pageInfo = new PageInfo<>(chargingRefundDto.getPageCurr(), chargingRefundDto.getPageSize()); |
| | | List<TChargingOrderRefund> list = this.baseMapper.getRefundList(pageInfo, chargingRefundDto); |
| | | for (TChargingOrderRefund refund : list) { |
| | | refund.setUid(refund.getType() + "-" + refund.getId()); |
| | | } |
| | | pageInfo.setRecords(list); |
| | | |
| | | return R.ok(pageInfo); |
| | |
| | | this.updateById(chargingOrder); |
| | | triggerChargingOrderShare(chargingOrder); |
| | | } else { |
| | | //构建退款明细 |
| | | TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund(); |
| | | chargingOrderRefund.setChargingOrderId(chargingOrder.getId()); |
| | | SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
| | | chargingOrderRefund.setRefundCode("CDF" + sdf1.format(new Date()) + (Double.valueOf(Math.random() * 1000).intValue())); |
| | | chargingOrderRefund.setRefundAmount(refundAmount); |
| | | chargingOrderRefund.setBalanceRefundAmount(balanceRefundAmount); |
| | | chargingOrderRefund.setThirdRefundAmount(thirdRefundAmount); |
| | | chargingOrderRefund.setRefundStatus(2); |
| | | chargingOrderRefund.setPayType(rechargePaymentType); |
| | | chargingOrderRefund.setCode(chargingOrder.getCode()); |
| | | chargingOrderRefund.setRefundTitle("充电完成退款"); |
| | | chargingOrderRefund.setRefundContent("充电完成退款"); |
| | | chargingOrderRefund.setRefundReason("充电完成退款"); |
| | | chargingOrderRefund.setRefundRemark("实际充电消费金额:" + chargingOrder.getPaymentAmount()); |
| | | chargingOrderRefund.setRefundTotalAmount(refundAmount); |
| | | chargingOrderRefund.setPayAmount(rechargeAmount); |
| | | chargingOrderRefund.setRefundTime(LocalDateTime.now()); |
| | | chargingOrderRefundService.save(chargingOrderRefund); |
| | | if (balanceRefundAmount.compareTo(BigDecimal.ZERO) > 0) { |
| | | changeUserBalance(chargingOrder.getAppUserId(), balanceRefundAmount); |
| | | recordBalanceRefund(chargingOrder, balanceRefundAmount, chargingOrderRefund.getRefundCode()); |
| | | } |
| | | |
| | | chargingOrder.setRefundStatus(2); |
| | | chargingOrder.setRefundTime(LocalDateTime.now()); |
| | | this.updateById(chargingOrder); |
| | | // 无可退金额时正常结算,不生成金额为 0 的退款记录。 |
| | | triggerChargingOrderShare(chargingOrder); |
| | | } |
| | | } |
| | |
| | | if (order == null) { |
| | | return R.fail("未查询到支付成功的充电订单"); |
| | | } |
| | | mergeSuccessfulRefundAmounts(order); |
| | | PayOrderInfoDto dto = new PayOrderInfoDto(); |
| | | dto.setOrderId(order.getId().toString()); |
| | | dto.setCode(order.getCode()); |
| | |
| | | if (order == null) { |
| | | return R.fail("充电订单不存在"); |
| | | } |
| | | mergeSuccessfulRefundAmounts(order); |
| | | BigDecimal refundAmount = money(payOrderQueryDto.getRefundAmount()); |
| | | BigDecimal refundableAmount = money(order.getPaymentAmount()).subtract(money(order.getRefundAmount())).setScale(2, RoundingMode.HALF_UP); |
| | | if (refundAmount.compareTo(refundableAmount) > 0) { |
| | |
| | | } |
| | | } |
| | | |
| | | private void mergeSuccessfulRefundAmounts(TChargingOrder order) { |
| | | if (order == null || order.getId() == null) { |
| | | return; |
| | | } |
| | | List<TChargingOrderRefund> refunds = chargingOrderRefundService.list( |
| | | new LambdaQueryWrapper<TChargingOrderRefund>() |
| | | .eq(TChargingOrderRefund::getChargingOrderId, order.getId()) |
| | | .eq(TChargingOrderRefund::getRefundStatus, 2)); |
| | | if (refunds == null || refunds.isEmpty()) { |
| | | return; |
| | | } |
| | | BigDecimal successfulAmount = BigDecimal.ZERO; |
| | | BigDecimal explicitBalanceAmount = BigDecimal.ZERO; |
| | | BigDecimal explicitThirdAmount = BigDecimal.ZERO; |
| | | BigDecimal unspecifiedAmount = BigDecimal.ZERO; |
| | | for (TChargingOrderRefund refund : refunds) { |
| | | BigDecimal amount = money(refund.getRefundAmount()); |
| | | BigDecimal balanceAmount = money(refund.getBalanceRefundAmount()); |
| | | BigDecimal thirdAmount = money(refund.getThirdRefundAmount()); |
| | | successfulAmount = successfulAmount.add(amount); |
| | | explicitBalanceAmount = explicitBalanceAmount.add(balanceAmount); |
| | | explicitThirdAmount = explicitThirdAmount.add(thirdAmount); |
| | | if (balanceAmount.add(thirdAmount).compareTo(BigDecimal.ZERO) == 0) { |
| | | unspecifiedAmount = unspecifiedAmount.add(amount); |
| | | } |
| | | } |
| | | BigDecimal inferredThirdAmount = unspecifiedAmount.min( |
| | | getRefundableThirdPayAmount(order).subtract(explicitThirdAmount).max(BigDecimal.ZERO)); |
| | | BigDecimal inferredBalanceAmount = unspecifiedAmount.subtract(inferredThirdAmount).max(BigDecimal.ZERO); |
| | | order.setRefundAmount(money(order.getRefundAmount()).max(money(successfulAmount))); |
| | | order.setThirdRefundAmount(money(order.getThirdRefundAmount()).max(money(explicitThirdAmount.add(inferredThirdAmount)))); |
| | | order.setBalanceRefundAmount(money(order.getBalanceRefundAmount()).max(money(explicitBalanceAmount.add(inferredBalanceAmount)))); |
| | | } |
| | | |
| | | private R refundIcbcShareBeforeMainRefund(TChargingOrder order, TChargingOrderRefund refund, BigDecimal thirdRefundAmount) { |
| | | if (order == null || refund == null || thirdRefundAmount == null || thirdRefundAmount.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return R.ok(); |
| | |
| | | import com.ruoyi.account.api.model.TAppUserCar; |
| | | import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient; |
| | | import com.ruoyi.chargingPile.api.feignClient.SiteClient; |
| | | import com.ruoyi.chargingPile.api.dto.GetSiteListDTO; |
| | | import com.ruoyi.chargingPile.api.model.Partner; |
| | | import com.ruoyi.chargingPile.api.model.Site; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | |
| | | import com.ruoyi.other.api.feignClient.CouponClient; |
| | | import com.ruoyi.other.api.feignClient.GoodsClient; |
| | | import com.ruoyi.other.api.feignClient.InvoiceTypeClient; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import org.redisson.api.RLock; |
| | | import org.redisson.api.RedissonClient; |
| | | import org.springframework.beans.BeanUtils; |
| | |
| | | private CouponClient couponClient; |
| | | @Resource |
| | | private AppUserClient appUserClient; |
| | | |
| | | @Resource |
| | | private SysUserClient sysUserClient; |
| | | |
| | | @Resource |
| | | private TChargingOrderAccountingStrategyService chargingOrderAccountingStrategyService; |
| | |
| | | |
| | | @Override |
| | | public PageInfo<TOrderInvoiceVO> pageList(TOrderInvoiceQuery query) { |
| | | applyPartnerSiteScope(query); |
| | | List<TAppUser> tAppUsers = new ArrayList<>(); |
| | | // 查询申请用户 |
| | | if (org.springframework.util.StringUtils.hasLength(query.getUserPhone())){ |
| | |
| | | |
| | | @Override |
| | | public Map<String, Integer> statusCount(TOrderInvoiceQuery query) { |
| | | applyPartnerSiteScope(query); |
| | | Map<String, Integer> map = new HashMap<>(); |
| | | List<TAppUser> tAppUsers = new ArrayList<>(); |
| | | |
| | |
| | | |
| | | @Override |
| | | public List<TOrderInvoiceVO> export(TOrderInvoiceQuery query) { |
| | | applyPartnerSiteScope(query); |
| | | List<TAppUser> tAppUsers = new ArrayList<>(); |
| | | // 查询申请用户 |
| | | if (org.springframework.util.StringUtils.hasLength(query.getUserPhone())){ |
| | |
| | | return list; |
| | | } |
| | | |
| | | private void applyPartnerSiteScope(TOrderInvoiceQuery query) { |
| | | if (query == null) { |
| | | return; |
| | | } |
| | | Long userId = tokenService.getLoginUser().getUserid(); |
| | | SysUser sysUser = sysUserClient.getSysUser(userId).getData(); |
| | | if (sysUser == null || !Integer.valueOf(2).equals(sysUser.getRoleType())) { |
| | | return; |
| | | } |
| | | List<GetSiteListDTO> sites = siteClient.getSiteListByUserId(userId).getData(); |
| | | List<Integer> siteIds = sites == null ? new ArrayList<>() : sites.stream() |
| | | .map(GetSiteListDTO::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | if (query.getSiteId() != null) { |
| | | siteIds = siteIds.contains(query.getSiteId()) |
| | | ? Collections.singletonList(query.getSiteId()) |
| | | : Collections.singletonList(-1); |
| | | } |
| | | if (siteIds.isEmpty()) { |
| | | siteIds = Collections.singletonList(-1); |
| | | } |
| | | query.setSiteIds(siteIds); |
| | | } |
| | | |
| | | private void fillInvoiceDetailAmount(TOrderInvoiceVO invoice, List<TOrderInvoiceDetail> details) { |
| | | List<TOrderInvoiceDetail> currentDetails = details.stream() |
| | | .filter(t -> t.getOrderInvoiceId().equals(invoice.getId())) |
| | |
| | | co.create_time as pay_time, |
| | | co.id as order_id, |
| | | co.app_user_id as user_id, |
| | | co.site_id as site_id, |
| | | co.pay_method as pay_method, |
| | | 1 as type |
| | | FROM t_charging_order_refund re |
| | |
| | | so.create_time as pay_time, |
| | | so.id as order_id, |
| | | so.app_user_id as user_id, |
| | | null as site_id, |
| | | 3 as pay_method, |
| | | 2 as type |
| | | FROM t_shopping_order_refund re |
| | |
| | | vo.create_time as pay_time, |
| | | vo.id as order_id, |
| | | vo.app_user_id as user_id, |
| | | null as site_id, |
| | | 3 as pay_method, |
| | | 3 as type |
| | | FROM t_vip_order_refund vr |
| | |
| | | </if> |
| | | <if test="data.specialRefund != null and data.specialRefund"> |
| | | AND o.refund_title = '特殊退款处理' |
| | | </if> |
| | | <if test="data.siteIds != null and data.siteIds.size() > 0"> |
| | | AND (o.type != 1 OR o.site_id IN |
| | | <foreach collection="data.siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | </where> |
| | | order by o.refund_time desc |
| | |
| | | |
| | | <select id="chargingOrderShareIncomeByOrderIds" resultType="map"> |
| | | select |
| | | charging_order_id as orderId, |
| | | sum(IFNULL(channel_pay_amount, 0) - IFNULL(share_amount, 0)) as platformIncome, |
| | | sum(IFNULL(share_amount, 0)) as partnerIncome |
| | | from `charging_pile_order`.t_charging_order_share_record |
| | | where del_flag = 0 and charging_order_id is not null |
| | | s.charging_order_id as orderId, |
| | | sum( |
| | | IFNULL(s.channel_pay_amount, 0) |
| | | - IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END) |
| | | - IFNULL(s.share_amount, 0) |
| | | * (IFNULL(s.channel_pay_amount, 0) |
| | | - IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END)) |
| | | / IFNULL(s.channel_pay_amount, 0) |
| | | ) as platformIncome, |
| | | sum( |
| | | IFNULL(s.share_amount, 0) |
| | | * (IFNULL(s.channel_pay_amount, 0) |
| | | - IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END)) |
| | | / IFNULL(s.channel_pay_amount, 0) |
| | | ) as partnerIncome |
| | | from `charging_pile_order`.t_charging_order_share_record s |
| | | inner join `charging_pile_order`.t_charging_order o on o.id = s.charging_order_id |
| | | where s.del_flag = 0 and s.charging_order_id is not null |
| | | and IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END) |
| | | < IFNULL(s.channel_pay_amount, 0) |
| | | <if test="orderIds != null and orderIds.size()>0"> |
| | | and charging_order_id in |
| | | and s.charging_order_id in |
| | | <foreach collection="orderIds" item="item" index="index" separator="," open="(" close=")"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | group by charging_order_id |
| | | group by s.charging_order_id |
| | | </select> |
| | | |
| | | <select id="chargingOrderShareIncomeByPayChannel" resultType="map"> |
| | | select |
| | | s.pay_channel as payChannel, |
| | | sum(IFNULL(s.share_amount, 0)) as shareAmount |
| | | sum( |
| | | IFNULL(s.share_amount, 0) |
| | | * (IFNULL(s.channel_pay_amount, 0) |
| | | - IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END)) |
| | | / IFNULL(s.channel_pay_amount, 0) |
| | | ) as shareAmount |
| | | from t_charging_order_share_record s |
| | | inner join t_charging_order o on s.charging_order_id = o.id |
| | | where s.del_flag = 0 |
| | |
| | | and o.del_flag = 0 |
| | | and o.recharge_payment_status = 2 |
| | | and o.status = 5 |
| | | and IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END) |
| | | < IFNULL(s.channel_pay_amount, 0) |
| | | <if test="sixBefore != null"> |
| | | and o.create_time >= #{sixBefore} |
| | | </if> |
| | |
| | | |
| | | <select id="chargingOrderShareIncomeSummaryByOrderIds" resultType="map"> |
| | | select |
| | | sum(IFNULL(channel_pay_amount, 0) - IFNULL(share_amount, 0)) as platformIncomeTotal, |
| | | sum(IFNULL(share_amount, 0)) as partnerIncomeTotal |
| | | from `charging_pile_order`.t_charging_order_share_record |
| | | where del_flag = 0 and charging_order_id is not null |
| | | sum( |
| | | IFNULL(s.channel_pay_amount, 0) |
| | | - IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END) |
| | | - IFNULL(s.share_amount, 0) |
| | | * (IFNULL(s.channel_pay_amount, 0) |
| | | - IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END)) |
| | | / IFNULL(s.channel_pay_amount, 0) |
| | | ) as platformIncomeTotal, |
| | | sum( |
| | | IFNULL(s.share_amount, 0) |
| | | * (IFNULL(s.channel_pay_amount, 0) |
| | | - IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END)) |
| | | / IFNULL(s.channel_pay_amount, 0) |
| | | ) as partnerIncomeTotal |
| | | from `charging_pile_order`.t_charging_order_share_record s |
| | | inner join `charging_pile_order`.t_charging_order o on o.id = s.charging_order_id |
| | | where s.del_flag = 0 and s.charging_order_id is not null |
| | | and IFNULL(o.third_refund_amount, CASE WHEN o.pay_method = 3 THEN IFNULL(o.refund_amount, 0) ELSE 0 END) |
| | | < IFNULL(s.channel_pay_amount, 0) |
| | | <if test="orderIds != null and orderIds.size()>0"> |
| | | and charging_order_id in |
| | | and s.charging_order_id in |
| | | <foreach collection="orderIds" item="item" index="index" separator="," open="(" close=")"> |
| | | #{item} |
| | | </foreach> |
| | |
| | | |
| | | <sql id="enterpriseChargingBaseWhere"> |
| | | toi.invoicing_object_type = 2 |
| | | AND toi.status IN (2, 3) |
| | | AND toi.status IN (1, 2, 3) |
| | | AND tod.order_type = 1 |
| | | AND co.del_flag = 0 |
| | | AND co.recharge_payment_status = 2 |
| | |
| | | MAX(IFNULL(toi.total_amount, 0)) AS totalAmount, |
| | | SUM(IFNULL(tod.invoice_amount, 0)) AS detailInvoiceAmount, |
| | | COUNT(DISTINCT co.id) AS orderCount, |
| | | MAX(co.end_time) AS latestChargingTime |
| | | MAX(co.start_time) AS latestChargingTime |
| | | FROM t_order_invoice toi |
| | | INNER JOIN t_order_invoice_detail tod ON tod.order_invoice_id = toi.id |
| | | INNER JOIN t_charging_order co ON co.id = tod.order_id |
| | |
| | | LIMIT 3 |
| | | </select> |
| | | |
| | | <select id="enterpriseTopSitesByCompanies" resultType="map"> |
| | | SELECT |
| | | toi.name AS companyName, |
| | | IFNULL(toi.tax_identification_number, '') AS socialCreditCode, |
| | | s.name AS siteName, |
| | | COUNT(DISTINCT co.id) AS counts |
| | | FROM t_order_invoice toi |
| | | INNER JOIN t_order_invoice_detail tod ON tod.order_invoice_id = toi.id |
| | | INNER JOIN t_charging_order co ON co.id = tod.order_id |
| | | LEFT JOIN charging_pile_service.t_site s ON s.id = co.site_id |
| | | <where> |
| | | <include refid="enterpriseChargingBaseWhere" /> |
| | | AND s.name IS NOT NULL |
| | | AND toi.name IN |
| | | <foreach collection="companyNames" item="companyName" open="(" separator="," close=")"> |
| | | #{companyName} |
| | | </foreach> |
| | | </where> |
| | | GROUP BY toi.name, toi.tax_identification_number, s.id, s.name |
| | | </select> |
| | | |
| | | <select id="enterpriseChargingTimes" resultType="java.time.LocalDateTime"> |
| | | SELECT DISTINCT co.start_time |
| | | FROM t_order_invoice toi |
| | |
| | | AND co.start_time IS NOT NULL |
| | | </where> |
| | | ORDER BY co.start_time ASC |
| | | </select> |
| | | |
| | | <select id="enterpriseChargingTimesByCompanies" resultType="map"> |
| | | SELECT DISTINCT |
| | | toi.name AS companyName, |
| | | IFNULL(toi.tax_identification_number, '') AS socialCreditCode, |
| | | co.start_time AS startTime |
| | | FROM t_order_invoice toi |
| | | INNER JOIN t_order_invoice_detail tod ON tod.order_invoice_id = toi.id |
| | | INNER JOIN t_charging_order co ON co.id = tod.order_id |
| | | LEFT JOIN charging_pile_service.t_site s ON s.id = co.site_id |
| | | <where> |
| | | <include refid="enterpriseChargingBaseWhere" /> |
| | | AND co.start_time IS NOT NULL |
| | | AND toi.name IN |
| | | <foreach collection="companyNames" item="companyName" open="(" separator="," close=")"> |
| | | #{companyName} |
| | | </foreach> |
| | | </where> |
| | | ORDER BY toi.name, co.start_time |
| | | </select> |
| | | |
| | | <sql id="enterpriseChargingDetailWhere"> |
| | |
| | | co.order_source AS orderSource, |
| | | p.name AS partnerName, |
| | | au.phone AS phone, |
| | | car.license_plate AS licensePlate, |
| | | co.charging_capacity AS chargingCapacity, |
| | | IFNULL(price.electrovalence, 0) AS electrovalence, |
| | | IFNULL(price.serviceCharge, 0) AS serviceCharge, |
| | | co.end_mode AS endMode, |
| | | IFNULL(price.periodCount, 0) AS periodCount, |
| | | co.create_time AS createTime, |
| | | co.start_time AS startTime, |
| | | co.end_time AS endTime, |
| | |
| | | LEFT JOIN charging_pile_service.t_charging_pile cp ON cp.id = co.charging_pile_id |
| | | LEFT JOIN charging_pile_service.t_charging_gun cg ON cg.id = co.charging_gun_id |
| | | LEFT JOIN charging_pile_account.t_app_user au ON au.id = co.app_user_id |
| | | LEFT JOIN charging_pile_account.t_app_user_car car ON car.id = co.app_user_car_id |
| | | LEFT JOIN ( |
| | | SELECT charging_order_id, |
| | | SUM(period_electric_price) AS electrovalence, |
| | | SUM(period_service_price) AS serviceCharge, |
| | | COUNT(1) AS periodCount |
| | | FROM t_charging_order_accounting_strategy |
| | | GROUP BY charging_order_id |
| | | ) price ON price.charging_order_id = co.id |
| | | </sql> |
| | | |
| | | <select id="enterpriseChargingDetail" resultType="com.ruoyi.order.dto.EnterpriseChargingDetailVO"> |
| | |
| | | <if test="query.siteId != null"> |
| | | AND toi.site_id = #{query.siteId} |
| | | </if> |
| | | <if test="query.siteIds != null and query.siteIds.size() > 0"> |
| | | AND toi.site_id IN |
| | | <foreach collection="query.siteIds" close=")" open="(" item="siteId" separator=","> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | <if test="query.partnerId != null"> |
| | | AND toi.partner_id = #{query.partnerId} |
| | | </if> |
| | |
| | | </if> |
| | | <if test="query.siteId != null"> |
| | | AND toi.site_id = #{query.siteId} |
| | | </if> |
| | | <if test="query.siteIds != null and query.siteIds.size() > 0"> |
| | | AND toi.site_id IN |
| | | <foreach collection="query.siteIds" close=")" open="(" item="siteId" separator=","> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | <if test="query.partnerId != null"> |
| | | AND toi.partner_id = #{query.partnerId} |
| | |
| | | <if test="query.siteId != null"> |
| | | AND toi.site_id = #{query.siteId} |
| | | </if> |
| | | <if test="query.siteIds != null and query.siteIds.size() > 0"> |
| | | AND toi.site_id IN |
| | | <foreach collection="query.siteIds" close=")" open="(" item="siteId" separator=","> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | <if test="query.partnerId != null"> |
| | | AND toi.partner_id = #{query.partnerId} |
| | | </if> |
| New file |
| | |
| | | package com.ruoyi.order.mapper; |
| | | |
| | | import org.junit.jupiter.api.Test; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.InputStreamReader; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertNotNull; |
| | | import static org.junit.jupiter.api.Assertions.assertTrue; |
| | | |
| | | class EnterpriseChargingDetailMapperTest { |
| | | |
| | | @Test |
| | | void selectsExpectedChargingDetailColumns() throws IOException { |
| | | InputStream input = getClass().getClassLoader() |
| | | .getResourceAsStream("mapper/order/TChargingOrderMapper.xml"); |
| | | assertNotNull(input); |
| | | |
| | | String mapper; |
| | | try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { |
| | | mapper = reader.lines().collect(Collectors.joining("\n")); |
| | | } |
| | | |
| | | String detailSelect = mapper.substring( |
| | | mapper.indexOf("<sql id=\"enterpriseChargingDetailSelect\""), |
| | | mapper.indexOf("<select id=\"enterpriseChargingDetail\"")); |
| | | assertTrue(detailSelect.contains("AS licensePlate")); |
| | | assertTrue(detailSelect.contains("AS chargingCapacity")); |
| | | assertTrue(detailSelect.contains("AS electrovalence")); |
| | | assertTrue(detailSelect.contains("AS serviceCharge")); |
| | | assertTrue(detailSelect.contains("AS endMode")); |
| | | assertTrue(detailSelect.contains("AS periodCount")); |
| | | } |
| | | } |
| | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | | import static org.junit.jupiter.api.Assertions.assertNotNull; |
| | | import static org.junit.jupiter.api.Assertions.assertTrue; |
| | | |
| | | class PayOrderQueryPerformanceMapperTest { |
| | | |
| | |
| | | assertFalse(payOrderQuery.contains("t_vip_order_refund")); |
| | | } |
| | | |
| | | @Test |
| | | void refundListAppliesPartnerSiteScopeInsidePagedQuery() throws IOException { |
| | | InputStream input = getClass().getClassLoader() |
| | | .getResourceAsStream("mapper/order/TChargingOrderMapper.xml"); |
| | | assertNotNull(input); |
| | | |
| | | String mapper; |
| | | try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { |
| | | mapper = reader.lines().collect(Collectors.joining("\n")); |
| | | } |
| | | |
| | | String refundQuery = mapper.substring( |
| | | mapper.indexOf("<select id=\"getRefundList\""), |
| | | mapper.indexOf("<select id=\"chargingOrderGroup\"")); |
| | | assertTrue(refundQuery.contains("data.siteIds")); |
| | | assertTrue(refundQuery.contains("o.site_id IN")); |
| | | assertEquals(3, countOccurrences(refundQuery, "as site_id")); |
| | | } |
| | | |
| | | private int countOccurrences(String text, String target) { |
| | | int count = 0; |
| | | int index = 0; |
| New file |
| | |
| | | -- 系统管理-角色:补齐合作商类型内置角色的菜单权限 |
| | | -- 仅追加基础合作商角色已有的菜单,不覆盖管理员在目标角色上的自定义权限。 |
| | | |
| | | INSERT IGNORE INTO sys_role_menu (role_id, menu_id) |
| | | SELECT target_role.role_id, source_menu.menu_id |
| | | FROM sys_role target_role |
| | | JOIN sys_role_menu source_menu |
| | | ON source_menu.role_id = ( |
| | | SELECT role_id |
| | | FROM sys_role |
| | | WHERE del_flag = '0' |
| | | AND status = '0' |
| | | AND role_name IN ('独立合作商', '合作商') |
| | | ORDER BY CASE role_name WHEN '独立合作商' THEN 0 ELSE 1 END, role_id |
| | | LIMIT 1 |
| | | ) |
| | | WHERE target_role.del_flag = '0' |
| | | AND target_role.status = '0' |
| | | AND target_role.role_name IN ('独立合作商', '合作商', '场地方', '服务商'); |