From 6dd6e95781c85398e366c4d468a6de83babfa206 Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期四, 09 七月 2026 11:30:16 +0800
Subject: [PATCH] feat(menu): 修复工作台权限菜单并完善发票开票功能

---
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java |  193 +++++++++++++++++++++++++++++++++---------------
 1 files changed, 132 insertions(+), 61 deletions(-)

diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java
index f4f4c98..a29e3ac 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java
@@ -32,9 +32,11 @@
 import com.ruoyi.other.api.feignClient.InvoiceTypeClient;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
 import org.springframework.util.CollectionUtils;
 
 import javax.annotation.Resource;
@@ -102,76 +104,144 @@
 	 * @return
 	 */
 	@Override
+	@Transactional(rollbackFor = Exception.class)
 	public AjaxResult addOrderInvoice(AddOrderInvoice addOrderInvoice) {
 		Long userId = tokenService.getLoginUserApplet().getUserId();
 		RLock lock = redissonClient.getLock("ADD_ORDER_INVOICE:" + userId);
+		boolean locked = false;
 		try {
-			boolean tryLock = lock.tryLock(5, 5, TimeUnit.SECONDS);
-			if(tryLock){
-				String orders = addOrderInvoice.getOrders();
-				if(StringUtils.isEmpty(orders)){
-					return AjaxResult.error("请选择有效的订单");
+			locked = lock.tryLock(5, 5, TimeUnit.SECONDS);
+			if (!locked) {
+				return AjaxResult.error("开票申请正在处理中,请勿重复提交");
+			}
+			String orders = addOrderInvoice.getOrders();
+			if (StringUtils.isEmpty(orders)) {
+				return AjaxResult.error("请选择有效的订单");
+			}
+			JSONArray parse = JSONArray.parse(orders);
+			if (parse == null || parse.isEmpty()) {
+				return AjaxResult.error("请选择有效的订单");
+			}
+			List<Long> orderIds = new ArrayList<>();
+			Map<Long, BigDecimal> amountMap = new HashMap<>();
+			for (int i = 0; i < parse.size(); i++) {
+				JSONObject jsonObject = parse.getJSONObject(i);
+				Long id = jsonObject.getLong("id");
+				BigDecimal amount = jsonObject.getBigDecimal("amount");
+				if (id == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
+					return AjaxResult.error("订单金额异常,请刷新后重试");
 				}
-				JSONArray parse = JSONArray.parse(orders);
-				List<Long> orderIds = new ArrayList<>();
-				Map<Long, BigDecimal> map = new HashMap<>();
-				for (int i = 0; i < parse.size(); i++) {
-					JSONObject jsonObject = parse.getJSONObject(i);
-					Long id = jsonObject.getLong("id");
-					BigDecimal amount = jsonObject.getBigDecimal("amount");
-					orderIds.add(id);
-					map.put(id, amount);
-				}
-				long count = orderInvoiceDetailService.count(new LambdaQueryWrapper<TOrderInvoiceDetail>().eq(TOrderInvoiceDetail::getOrderType, addOrderInvoice.getOrderType())
-						.in(TOrderInvoiceDetail::getOrderId, orderIds));
-				if(count > 0){
+				orderIds.add(id);
+				amountMap.put(id, amount);
+			}
+			List<TOrderInvoiceDetail> existingDetails = orderInvoiceDetailService.list(new LambdaQueryWrapper<TOrderInvoiceDetail>()
+					.eq(TOrderInvoiceDetail::getOrderType, addOrderInvoice.getOrderType())
+					.in(TOrderInvoiceDetail::getOrderId, orderIds));
+			if (!CollectionUtils.isEmpty(existingDetails)) {
+				List<Long> invoiceIds = existingDetails.stream().map(TOrderInvoiceDetail::getOrderInvoiceId).distinct().collect(Collectors.toList());
+				long count = this.count(new LambdaQueryWrapper<TOrderInvoice>().in(TOrderInvoice::getId, invoiceIds).ne(TOrderInvoice::getStatus, 4));
+				if (count > 0) {
 					return AjaxResult.error("不能重复申请开票,请刷新数据后重试");
 				}
-				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
-				String code = Double.valueOf(Math.random() * 1000).intValue() + sdf.format(new Date());
-				//获取开票类型
-				TInvoiceType invoiceType = invoiceTypeClient.getInvoiceType(addOrderInvoice.getInvoiceTypeId()).getData();
-				addOrderInvoice.setInvoicingCompany(invoiceType.getInvoicingCompany());
-				addOrderInvoice.setInvoiceType(invoiceType.getName());
-				addOrderInvoice.setInvoiceMaterial(2);
-				addOrderInvoice.setInvoicingMethod(invoiceType.getInvoicingMethod());
-				addOrderInvoice.setAppUserId(userId);
-				addOrderInvoice.setCode(code);
-				addOrderInvoice.setStatus(1);
-				addOrderInvoice.setCreateTime(LocalDateTime.now());
-				fillInvoiceSite(addOrderInvoice, orderIds);
-				if (Integer.valueOf(2).equals(addOrderInvoice.getInvoicingMethod())) {
-					addOrderInvoice.setStatus(3);
-					addOrderInvoice.setBillingTime(LocalDateTime.now());
-				}
-				this.save(addOrderInvoice);
-				for (Long orderId : orderIds) {
-					List<TChargingOrderAccountingStrategy> list = chargingOrderAccountingStrategyService.list(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>()
-							.eq(TChargingOrderAccountingStrategy::getChargingOrderId, orderId));
-					BigDecimal electrovalence = list.stream().map(TChargingOrderAccountingStrategy::getElectrovalence).reduce(BigDecimal.ZERO, BigDecimal::add);
-					BigDecimal serviceCharge = list.stream().map(TChargingOrderAccountingStrategy::getServiceCharge).reduce(BigDecimal.ZERO, BigDecimal::add);
-
-					TOrderInvoiceDetail orderInvoiceDetail = new TOrderInvoiceDetail();
-					orderInvoiceDetail.setOrderInvoiceId(addOrderInvoice.getId());
-					orderInvoiceDetail.setInvoiceAmount(map.get(orderId));
-					orderInvoiceDetail.setOrderType(addOrderInvoice.getOrderType());
-					orderInvoiceDetail.setOrderId(orderId);
-					orderInvoiceDetail.setElectricityTariff(invoiceType.getElectricityTariff());
-					orderInvoiceDetail.setServiceTariff(invoiceType.getServiceTariff());
-					orderInvoiceDetail.setAddedServiceTariff(invoiceType.getAddedServiceTariff());
-					orderInvoiceDetail.setElectrovalence(electrovalence);
-					orderInvoiceDetail.setServiceCharge(serviceCharge);
-					orderInvoiceDetail.setAddedService(serviceCharge.multiply(null == invoiceType.getAddedServiceTariff()
-							? new BigDecimal(1) : invoiceType.getAddedServiceTariff().divide(new BigDecimal(100))));
-					orderInvoiceDetailService.save(orderInvoiceDetail);
-				}
 			}
-		}catch (Exception e){
+			//获取开票类型
+			TInvoiceType invoiceType = invoiceTypeClient.getInvoiceType(addOrderInvoice.getInvoiceTypeId()).getData();
+			if (invoiceType == null) {
+				return AjaxResult.error("请选择有效的发票类型");
+			}
+			Map<Integer, List<Long>> invoiceOrderGroups = buildInvoiceOrderGroups(addOrderInvoice, orderIds);
+			for (List<Long> groupOrderIds : invoiceOrderGroups.values()) {
+				TOrderInvoice invoice = buildOrderInvoice(addOrderInvoice, userId, invoiceType, groupOrderIds, amountMap);
+				this.save(invoice);
+				saveInvoiceDetails(invoice, invoiceType, groupOrderIds, amountMap);
+			}
+			return AjaxResult.success();
+		} catch (Exception e) {
 			e.printStackTrace();
-		}finally {
-			lock.unlock();
+			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+			return AjaxResult.error("开票申请失败:" + (StringUtils.isEmpty(e.getMessage()) ? "请稍后重试" : e.getMessage()));
+		} finally {
+			if (locked && lock.isHeldByCurrentThread()) {
+				lock.unlock();
+			}
 		}
-		return AjaxResult.success();
+	}
+
+	private Map<Integer, List<Long>> buildInvoiceOrderGroups(AddOrderInvoice addOrderInvoice, List<Long> orderIds) {
+		Map<Integer, List<Long>> groups = new LinkedHashMap<>();
+		if (!Integer.valueOf(1).equals(addOrderInvoice.getOrderType())) {
+			groups.put(0, orderIds);
+			return groups;
+		}
+		List<TChargingOrder> chargingOrders = chargingOrderService.listByIds(orderIds);
+		Map<Long, Integer> siteIdMap = chargingOrders.stream().collect(Collectors.toMap(TChargingOrder::getId, TChargingOrder::getSiteId, (a, b) -> a));
+		for (Long orderId : orderIds) {
+			Integer siteId = siteIdMap.get(orderId);
+			if (siteId == null) {
+				throw new IllegalArgumentException("订单所属电站异常,请刷新后重试");
+			}
+			groups.computeIfAbsent(siteId, key -> new ArrayList<>()).add(orderId);
+		}
+		return groups;
+	}
+
+	private TOrderInvoice buildOrderInvoice(AddOrderInvoice source, Long userId, TInvoiceType invoiceType, List<Long> orderIds, Map<Long, BigDecimal> amountMap) {
+		TOrderInvoice invoice = new TOrderInvoice();
+		BeanUtils.copyProperties(source, invoice);
+		invoice.setId(null);
+		invoice.setCode(generateInvoiceCode());
+		invoice.setAppUserId(userId);
+		invoice.setInvoicingCompany(invoiceType.getInvoicingCompany());
+		invoice.setInvoiceType(invoiceType.getName());
+		invoice.setInvoiceMaterial(2);
+		invoice.setInvoicingMethod(invoiceType.getInvoicingMethod());
+		invoice.setTotalAmount(orderIds.stream().map(amountMap::get).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+		invoice.setInvoiceUrl(null);
+		invoice.setBillingUserId(null);
+		invoice.setCancelTime(null);
+		invoice.setStatus(1);
+		invoice.setCreateTime(LocalDateTime.now());
+		invoice.setBillingTime(null);
+		invoice.setSiteId(null);
+		invoice.setPartnerId(null);
+		fillInvoiceSite(invoice, orderIds);
+		if (Integer.valueOf(2).equals(invoice.getInvoicingMethod())) {
+			invoice.setStatus(3);
+			invoice.setBillingTime(LocalDateTime.now());
+		}
+		return invoice;
+	}
+
+	private void saveInvoiceDetails(TOrderInvoice invoice, TInvoiceType invoiceType, List<Long> orderIds, Map<Long, BigDecimal> amountMap) {
+		for (Long orderId : orderIds) {
+			BigDecimal electrovalence = BigDecimal.ZERO;
+			BigDecimal serviceCharge = BigDecimal.ZERO;
+			if (Integer.valueOf(1).equals(invoice.getOrderType())) {
+				List<TChargingOrderAccountingStrategy> list = chargingOrderAccountingStrategyService.list(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>()
+						.eq(TChargingOrderAccountingStrategy::getChargingOrderId, orderId));
+				electrovalence = list.stream().map(TChargingOrderAccountingStrategy::getElectrovalence).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
+				serviceCharge = list.stream().map(TChargingOrderAccountingStrategy::getServiceCharge).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
+			}
+
+			TOrderInvoiceDetail orderInvoiceDetail = new TOrderInvoiceDetail();
+			orderInvoiceDetail.setOrderInvoiceId(invoice.getId());
+			orderInvoiceDetail.setInvoiceAmount(amountMap.get(orderId));
+			orderInvoiceDetail.setOrderType(invoice.getOrderType());
+			orderInvoiceDetail.setOrderId(orderId);
+			orderInvoiceDetail.setElectricityTariff(invoiceType.getElectricityTariff());
+			orderInvoiceDetail.setServiceTariff(invoiceType.getServiceTariff());
+			orderInvoiceDetail.setAddedServiceTariff(invoiceType.getAddedServiceTariff());
+			orderInvoiceDetail.setElectrovalence(electrovalence);
+			orderInvoiceDetail.setServiceCharge(serviceCharge);
+			orderInvoiceDetail.setAddedService(serviceCharge.multiply(null == invoiceType.getAddedServiceTariff()
+					? new BigDecimal(1) : invoiceType.getAddedServiceTariff().divide(new BigDecimal(100))));
+			orderInvoiceDetailService.save(orderInvoiceDetail);
+		}
+	}
+
+	private String generateInvoiceCode() {
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+		return Double.valueOf(Math.random() * 1000).intValue() + sdf.format(new Date());
 	}
 
 	private void fillInvoiceSite(TOrderInvoice invoice, List<Long> orderIds) {
@@ -208,7 +278,7 @@
 		Long userId = tokenService.getLoginUserApplet().getUserId();
 		Integer pageCurr = (query.getPageCurr() - 1) * query.getPageSize();
 		LambdaQueryWrapper<TOrderInvoice> wrapper = new LambdaQueryWrapper<TOrderInvoice>().eq(TOrderInvoice::getAppUserId, userId);
-		if(query.getStatus() != 1){
+		if(query.getStatus() != null){
 			wrapper.eq(TOrderInvoice::getStatus, query.getStatus());
 		}
 		List<TOrderInvoice> list = this.list(wrapper.orderByDesc(TOrderInvoice::getCreateTime).last(" limit " + pageCurr + ", " + query.getPageSize()));
@@ -219,6 +289,7 @@
 			orderInvoiceList.setOrderType(tOrderInvoice.getOrderType());
 			orderInvoiceList.setTotalAmount(tOrderInvoice.getTotalAmount());
 			orderInvoiceList.setName(tOrderInvoice.getName());
+			orderInvoiceList.setStatus(tOrderInvoice.getStatus());
 			orderInvoiceList.setCreateTime(tOrderInvoice.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
 			pageList.add(orderInvoiceList);
 		}

--
Gitblit v1.7.1