Explorar el Código

Merge remote-tracking branch 'origin/dev' into dev

zuy hace 2 años
padre
commit
57bf76eaf6

+ 13 - 7
admin/src/main/java/com/kym/admin/controller/StatementsController.java

@@ -1,11 +1,10 @@
 package com.kym.admin.controller;
 
 import com.kym.common.R;
-import com.kym.entity.admin.Statements;
 import com.kym.service.admin.StatementsService;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 /**
@@ -20,15 +19,22 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping("/statements")
 public class StatementsController {
 
-    private  final StatementsService statementsService;
+    private final StatementsService statementsService;
 
     public StatementsController(StatementsService statementsService) {
         this.statementsService = statementsService;
     }
 
-    @PostMapping("/create")
-    R<?> create(@RequestBody Statements statements) {
-        statementsService.createStatements(statements);
+    /**
+     * 生成对账单(创建前先录入抄表电量和电费金额)
+     *
+     * @param stationId
+     * @param statMonth
+     * @return
+     */
+    @GetMapping("/create")
+    R<?> create(@RequestParam("stationId") String stationId, @RequestParam("statMonth") String statMonth) {
+        statementsService.createStatements(stationId, statMonth);
         return R.success();
     }
 

+ 2 - 0
common/src/main/java/com/kym/common/annotation/DynamicCache.java

@@ -11,6 +11,8 @@ import java.lang.annotation.*;
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface DynamicCache {
+    String spel() default "";
+
     String value() default "";
 
     String key() default "";

+ 37 - 1
common/src/main/java/com/kym/common/aspect/DynamicCacheAspect.java

@@ -8,9 +8,15 @@ import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Pointcut;
 import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.core.DefaultParameterNameDiscoverer;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.stereotype.Component;
 
 import java.lang.reflect.Method;
+import java.util.Objects;
 
 /**
  * @author skyline
@@ -21,6 +27,8 @@ import java.lang.reflect.Method;
 @Aspect
 public class DynamicCacheAspect {
     private DynamicDataCache cache = DynamicDataCache.INSTANCE;
+    private SpelExpressionParser parserSpel = new SpelExpressionParser();
+    private DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
 
     @Pointcut("@annotation(com.kym.common.annotation.DynamicCache)")
     public void cachePointCut() {
@@ -31,12 +39,16 @@ public class DynamicCacheAspect {
         MethodSignature signature = (MethodSignature) joinPoint.getSignature();
         Method method = signature.getMethod();
         DynamicCache dynamicCache = method.getAnnotation(DynamicCache.class);
+
+        //获取运行时参数的值
+        String spelParamValue = generateKeyBySpEL(dynamicCache.spel(), joinPoint);
+
         // 获取方法名
         var methodName = signature.getName();
         // 获取注解上的缓存时间
         var timeout = dynamicCache.timeout();
         // 获取注解上的缓存key
-        var key = dynamicCache.key();
+        var key = CommUtil.isEmptyOrNull(spelParamValue) ? methodName+":"+spelParamValue : dynamicCache.key();
         var data = cache.get(CommUtil.isEmptyOrNull(key) ? methodName : key);
         if (data != null) {
             return data;
@@ -47,4 +59,28 @@ public class DynamicCacheAspect {
         cache.put(CommUtil.isEmptyOrNull(key) ? methodName : key, result, timeout >= 0 ? timeout : 5 * 60 * 1000);
         return result;
     }
+
+    /**
+     * 生成缓存key
+     *
+     * @param key
+     * @param pjp
+     * @return
+     */
+    public String generateKeyBySpEL(String key, ProceedingJoinPoint pjp) {
+        if (CommUtil.isEmptyOrNull(key)) {
+            return null;
+        }
+        Expression expression = parserSpel.parseExpression(key);
+        EvaluationContext context = new StandardEvaluationContext();
+        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
+        Object[] args = pjp.getArgs();
+        String[] paramNames = parameterNameDiscoverer.getParameterNames(methodSignature.getMethod());
+        for (int i = 0; i < args.length; i++) {
+            assert paramNames != null;
+            context.setVariable(paramNames[i], args[i]);
+        }
+        return Objects.requireNonNull(expression.getValue(context)).toString();
+    }
+
 }

+ 2 - 7
entity/src/main/java/com/kym/entity/admin/Statements.java

@@ -45,14 +45,9 @@ public class Statements extends BaseEntity {
     private String stationName;
 
     /**
-     * 开始时间
+     * 统计时间(月)
      */
-    private LocalDateTime startTime;
-
-    /**
-     * 结束时间
-     */
-    private LocalDateTime endTime;
+    private String statMonth;
 
     /**
      * 订单电量

+ 12 - 0
entity/src/main/java/com/kym/entity/admin/StationStatMonth.java

@@ -93,4 +93,16 @@ public class StationStatMonth extends BaseEntity {
      * 设备使用率
      */
     private Double connectorUsageRate;
+
+    /**
+     * 实际抄表电量
+     */
+    private Double actualPower;
+
+    /**
+     * 实际抄表电费金额(分)
+     */
+    private Integer actualElecMoney;
+
+
 }

+ 3 - 1
mapper/src/main/resources/mappers/admin/StationStatMonthMapper.xml

@@ -19,13 +19,15 @@
         <result column="avg_order_money" property="avgOrderMoney" />
         <result column="avg_connector_elec" property="avgConnectorElec" />
         <result column="connector_usage_rate" property="connectorUsageRate" />
+        <result column="actual_power" property="actualPower" />
+        <result column="actual_elec_money" property="actualElecMoney" />
         <result column="create_time" property="createTime" />
         <result column="update_time" property="updateTime" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id,station_id, stat_month, charge_users, valid_orders, total_power, total_money, elec_money, service_money,service_money_discount,discount_amount, avg_order_elec, avg_order_money, avg_connector_elec,connector_usage_rate,create_time, update_time
+        id,station_id, stat_month, charge_users, valid_orders, total_power, total_money, elec_money, service_money,service_money_discount,discount_amount, avg_order_elec, avg_order_money, avg_connector_elec,connector_usage_rate,actual_power,actual_elec_money,create_time,update_time,create_time, update_time
     </sql>
 
 </mapper>

+ 1 - 1
miniapp/src/main/java/com/kym/miniapp/jobs/StartChargeDelayJob.java

@@ -84,7 +84,7 @@ public class StartChargeDelayJob implements DelayService<DelayChargeOrder> {
                     chargeService.queryStartCharge(order.getUserId(), order.getConnectorId(), null, false, null, null);
                     log.info("预约充电启动成功:用户:{},订单号:{},预约启动时间:{}", order.getUserId(), order.getStartChargeSeq(), order.getStartTime());
                     // 线程休眠100ms
-                    Thread.sleep(100);
+                    Thread.sleep(200);
                 } catch (Exception e) {
                     if (e instanceof InterruptedException) {
                         log.error("预约充电队列take异常", e);

+ 2 - 2
miniapp/src/main/java/com/kym/miniapp/jobs/StopChargeDelayJob.java

@@ -78,7 +78,7 @@ public class StopChargeDelayJob implements DelayService<DelayChargeOrder> {
             DelayedItem<DelayChargeOrder> delayedItem;
             while (true) {
                 try {
-                    Thread.sleep(200);
+                    Thread.sleep(100);
                     delayedItem = STOP_DELAY_QUEUE.take();
                     // 停止充电
                     var order = delayedItem.data;
@@ -89,7 +89,7 @@ public class StopChargeDelayJob implements DelayService<DelayChargeOrder> {
                         chargeService.queryStopCharge(order.getUserId(), order.getConnectorId());
                         log.info("预约充电停止成功:用户:{},订单号:{},预约停止时间:{}", order.getUserId(), order.getStartChargeSeq(), order.getEndTime());
                         // 线程休眠100ms
-                        Thread.sleep(100);
+                        Thread.sleep(200);
                     } else {
                         log.error("预约充电停止异常:订单不匹配:原订单:{},当前设备最新订单:{}", order.getStartChargeSeq(), currentChargeOrder.getStartChargeSeq());
                         throw new BusinessException("预约充电停止异常");

+ 1 - 1
service/src/main/java/com/kym/service/admin/StatementsService.java

@@ -13,5 +13,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface StatementsService extends IService<Statements> {
 
-    void createStatements(Statements statements);
+    void createStatements(String stationId, String statMonth);
 }

+ 47 - 9
service/src/main/java/com/kym/service/admin/impl/StatementsServiceImpl.java

@@ -4,10 +4,14 @@ import com.baomidou.dynamic.datasource.annotation.DS;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.kym.entity.admin.InvestorInfo;
 import com.kym.entity.admin.Statements;
+import com.kym.entity.admin.StationStatMonth;
 import com.kym.mapper.admin.StatementsMapper;
 import com.kym.service.admin.InvestorInfoService;
 import com.kym.service.admin.StatementsService;
+import com.kym.service.admin.StationStatMonthService;
+import com.kym.service.cache.KymCache;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * <p>
@@ -23,18 +27,52 @@ public class StatementsServiceImpl extends ServiceImpl<StatementsMapper, Stateme
 
     private final InvestorInfoService investorInfoService;
 
-    public StatementsServiceImpl(InvestorInfoService investorInfoService) {
+    private final StationStatMonthService stationStatMonthService;
+
+    public StatementsServiceImpl(InvestorInfoService investorInfoService, StationStatMonthService stationStatMonthService) {
         this.investorInfoService = investorInfoService;
+        this.stationStatMonthService = stationStatMonthService;
     }
 
     @Override
-    public void createStatements(Statements statements) {
-        var investmentInfo = investorInfoService.lambdaQuery().eq(InvestorInfo::getAdminUserId, statements.getAdminUserId()).one();
-        statements.setAdminUserName(investmentInfo.getAdminUserName())
-               .setStationId(statements.getStationId())
-                .setStationName(statements.getStationName())
-                .setVatRate(investmentInfo.getVatRate())
-                .setSplittingProportion(investmentInfo.getSplittingProportion());
-        // TODO: 2023-12-28 其他数据字段填充 
+    @Transactional
+    public void createStatements(String stationId, String statMonth) {
+        // 站点统计信息
+        var statMonthInfo = stationStatMonthService.lambdaQuery()
+                .eq(StationStatMonth::getStationId, stationId)
+                .eq(StationStatMonth::getStatMonth, statMonth)
+                .one();
+        // 站点关联客户和物业信息
+        var investorInfoList = investorInfoService.lambdaQuery()
+                .eq(InvestorInfo::getStationId, stationId)
+                .list();
+
+        // 创建客户对账单
+        var res = investorInfoList.stream().map(investorInfo -> {
+            var actualServiceMoney = statMonthInfo.getServiceMoney() - statMonthInfo.getDiscountAmount() - (statMonthInfo.getActualElecMoney() - statMonthInfo.getElecMoney());
+            var vatAmount = (int) (actualServiceMoney * investorInfo.getVatRate());
+            return new Statements()
+                    .setAdminUserId(investorInfo.getAdminUserId())
+                    .setAdminUserName(investorInfo.getAdminUserName())
+                    .setStationId(investorInfo.getStationId())
+                    .setStationName(KymCache.INSTANCE.getStationNameById(investorInfo.getStationId()))
+                    .setStatMonth(statMonthInfo.getStatMonth())
+                    .setTotalPower(statMonthInfo.getTotalPower())
+                    .setActualPower(statMonthInfo.getActualPower()) // 实际抄表电量
+                    .setElecLossPower(statMonthInfo.getActualPower() - statMonthInfo.getTotalPower()) // 电损电量
+                    .setTotalMoney(statMonthInfo.getTotalMoney())
+                    .setElecMoney(statMonthInfo.getElecMoney())
+                    .setElecLossMoney(statMonthInfo.getActualElecMoney() - statMonthInfo.getElecMoney()) // 电损电费(分)
+                    .setServiceMoney(statMonthInfo.getServiceMoney())
+                    .setDiscountAmount(statMonthInfo.getDiscountAmount())
+                    .setServiceMoneyDiscount(statMonthInfo.getServiceMoneyDiscount())
+                    .setActualServiceMoney(actualServiceMoney) // 实际参与分成的服务费(分)
+                    .setSplittingProportion(investorInfo.getSplittingProportion()) // 分成比例 0.45表示45%
+                    .setSplittingAmount((int) (actualServiceMoney * investorInfo.getSplittingProportion()))  // 分成金额(分)
+                    .setVatRate(investorInfo.getVatRate()) // 增值税率 0.06表示6%
+                    .setVatAmount(vatAmount) // 增值税额(分)
+                    .setActualSplittingAmount(actualServiceMoney - vatAmount); // 实际分成金额(分)
+        }).toList();
+        saveBatch(res);
     }
 }

+ 2 - 0
service/src/main/java/com/kym/service/enplus/impl/EnPlusServiceImpl.java

@@ -5,6 +5,7 @@ import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.crypto.digest.HMac;
 import cn.hutool.crypto.digest.HmacAlgorithm;
 import com.alibaba.fastjson2.JSONObject;
+import com.kym.common.annotation.DynamicCache;
 import com.kym.common.constant.ResponseEnum;
 import com.kym.common.enums.EnPlusApi;
 import com.kym.common.exception.BusinessException;
@@ -236,6 +237,7 @@ public class EnPlusServiceImpl implements EnPlusService {
      * @return
      */
     @Override
+    @DynamicCache(spel = "#connectorId")
     public JSONObject queryEquipBusinessPolicy(String equipBizSeq, String connectorId) {
         var param = """
                 {

+ 1 - 1
service/src/main/java/com/kym/service/wechat/impl/WxPayServiceImpl.java

@@ -714,6 +714,7 @@ public class WxPayServiceImpl implements WxPayService {
                     .setInvoiceTitle(buyerInformation.getName())
                     .setTaxId(buyerInformation.getTaxpayer_id())
                     .setAddress(buyerInformation.getAddress())
+                    .setTelephone(buyerInformation.getTelephone())
                     .setBankName(buyerInformation.getBank_name())
                     .setBankAccount(buyerInformation.getBank_account())
                     .setEmail(buyerInformation.getEmail())
@@ -837,7 +838,6 @@ public class WxPayServiceImpl implements WxPayService {
                 .setTaxpayer_id(invoice.getTaxId())
                 .setTelephone(invoice.getTelephone())
                 .setAddress(invoice.getAddress())
-                .setTelephone(invoice.getPhone())
                 .setBank_name(invoice.getBankName())
                 .setBank_account(invoice.getBankAccount());