张延森 преди 2 години
родител
ревизия
f3cfcdc77d
променени са 19 файла, в които са добавени 745 реда и са изтрити 1 реда
  1. 1
    1
      pom.xml
  2. 30
    0
      src/main/java/com/njyunzhi/pet_identity/common/DateUtils.java
  3. 13
    0
      src/main/java/com/njyunzhi/pet_identity/common/WxPayUtils.java
  4. 25
    0
      src/main/java/com/njyunzhi/pet_identity/common/excelConverter/WxStringConverter.java
  5. 113
    0
      src/main/java/com/njyunzhi/pet_identity/controller/TaAccountLogController.java
  6. 49
    0
      src/main/java/com/njyunzhi/pet_identity/entity/TaAccountLog.java
  7. 37
    0
      src/main/java/com/njyunzhi/pet_identity/entity/TaAccountMonthly.java
  8. 133
    0
      src/main/java/com/njyunzhi/pet_identity/entity/TaWxBillList.java
  9. 47
    0
      src/main/java/com/njyunzhi/pet_identity/job/Reconciliation.java
  10. 24
    0
      src/main/java/com/njyunzhi/pet_identity/mapper/TaAccountLogMapper.java
  11. 17
    0
      src/main/java/com/njyunzhi/pet_identity/mapper/TaAccountMonthlyMapper.java
  12. 17
    0
      src/main/java/com/njyunzhi/pet_identity/mapper/TaWxBillListMapper.java
  13. 9
    0
      src/main/java/com/njyunzhi/pet_identity/service/ITaAccountLogService.java
  14. 14
    0
      src/main/java/com/njyunzhi/pet_identity/service/ITaAccountMonthlyService.java
  15. 158
    0
      src/main/java/com/njyunzhi/pet_identity/service/impl/TaAccountLogServiceImpl.java
  16. 19
    0
      src/main/java/com/njyunzhi/pet_identity/service/impl/TaAccountMonthlyServiceImpl.java
  17. 29
    0
      src/main/resources/mapper/TaAccountLogMapper.xml
  18. 5
    0
      src/main/resources/mapper/TaAccountMonthlyMapper.xml
  19. 5
    0
      src/main/resources/mapper/TaWxBillListMapper.xml

+ 1
- 1
pom.xml Целия файл

@@ -10,7 +10,7 @@
10 10
 	</parent>
11 11
 	<groupId>com.njyunzhi</groupId>
12 12
 	<artifactId>pet_identity</artifactId>
13
-	<version>0.0.7</version>
13
+	<version>0.0.8</version>
14 14
 	<name>pet_identity</name>
15 15
 	<description>Demo project for Spring Boot</description>
16 16
 

+ 30
- 0
src/main/java/com/njyunzhi/pet_identity/common/DateUtils.java Целия файл

@@ -57,4 +57,34 @@ public class DateUtils {
57 57
 
58 58
         return toString(LocalDateTime.now(ZoneId.of("Asia/Shanghai")), formater);
59 59
     }
60
+
61
+    public static int getDayNum(int year, int month) {
62
+        int days = 0;
63
+        if (month != 2) {
64
+            switch (month) {
65
+                case 1:
66
+                case 3:
67
+                case 5:
68
+                case 7:
69
+                case 8:
70
+                case 10:
71
+                case 12:
72
+                    days = 31;
73
+                    break;
74
+                case 4:
75
+                case 6:
76
+                case 9:
77
+                case 11:
78
+                    days = 30;
79
+
80
+            }
81
+        } else {
82
+            // 闰年
83
+            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
84
+                days = 29;
85
+            else
86
+                days = 28;
87
+        }
88
+        return days;
89
+    }
60 90
 }

+ 13
- 0
src/main/java/com/njyunzhi/pet_identity/common/WxPayUtils.java Целия файл

@@ -1,7 +1,11 @@
1 1
 package com.njyunzhi.pet_identity.common;
2 2
 
3
+import com.github.binarywang.wxpay.bean.request.WxPayApplyTradeBillV3Request;
4
+import com.github.binarywang.wxpay.bean.request.WxPayDownloadBillRequest;
3 5
 import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
4 6
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
7
+import com.github.binarywang.wxpay.bean.result.WxPayApplyBillV3Result;
8
+import com.github.binarywang.wxpay.bean.result.WxPayBillResult;
5 9
 import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
6 10
 import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
7 11
 import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
@@ -12,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
12 16
 import org.springframework.beans.factory.annotation.Value;
13 17
 import org.springframework.stereotype.Component;
14 18
 
19
+import java.io.InputStream;
15 20
 import java.time.LocalDateTime;
16 21
 import java.time.ZoneOffset;
17 22
 
@@ -65,4 +70,12 @@ public class WxPayUtils {
65 70
         return result;
66 71
     }
67 72
 
73
+    public InputStream download(String date) throws Exception {
74
+        WxPayService payService = wxUtils.getPayService();
75
+        WxPayApplyTradeBillV3Request request = new WxPayApplyTradeBillV3Request();
76
+        request.setBillDate(date);
77
+        request.setBillType("ALL");
78
+        WxPayApplyBillV3Result wxPayApplyBillV3Result = payService.applyTradeBill(request);
79
+        return payService.downloadV3(wxPayApplyBillV3Result.getDownloadUrl());
80
+    }
68 81
 }

+ 25
- 0
src/main/java/com/njyunzhi/pet_identity/common/excelConverter/WxStringConverter.java Целия файл

@@ -0,0 +1,25 @@
1
+package com.njyunzhi.pet_identity.common.excelConverter;
2
+
3
+import com.alibaba.excel.converters.Converter;
4
+import com.alibaba.excel.converters.ReadConverterContext;
5
+import com.alibaba.excel.enums.CellDataTypeEnum;
6
+
7
+public class WxStringConverter implements Converter<String> {
8
+    @Override
9
+    public Class supportJavaTypeKey() {
10
+        return String.class;
11
+    }
12
+
13
+    @Override
14
+    public CellDataTypeEnum supportExcelTypeKey() {
15
+        return CellDataTypeEnum.STRING;
16
+    }
17
+
18
+    @Override
19
+    public String convertToJavaData(ReadConverterContext<?> context) throws Exception {
20
+        String val = context.getReadCellData().getStringValue();
21
+        if (null == val) return null;
22
+        return val.replaceFirst("^`", "");
23
+    }
24
+
25
+}

+ 113
- 0
src/main/java/com/njyunzhi/pet_identity/controller/TaAccountLogController.java Целия файл

@@ -0,0 +1,113 @@
1
+package com.njyunzhi.pet_identity.controller;
2
+
3
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4
+import com.baomidou.mybatisplus.core.metadata.IPage;
5
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
6
+import com.njyunzhi.pet_identity.common.BaseController;
7
+import com.njyunzhi.pet_identity.common.Constants;
8
+import com.njyunzhi.pet_identity.common.ResponseBean;
9
+import com.njyunzhi.pet_identity.common.StringUtils;
10
+import com.njyunzhi.pet_identity.entity.SysUser;
11
+import com.njyunzhi.pet_identity.entity.TaAccountLog;
12
+import com.njyunzhi.pet_identity.entity.TaAccountMonthly;
13
+import com.njyunzhi.pet_identity.service.ITaAccountLogService;
14
+import com.njyunzhi.pet_identity.service.ITaAccountMonthlyService;
15
+import io.swagger.annotations.Api;
16
+import io.swagger.annotations.ApiOperation;
17
+import io.swagger.annotations.ApiParam;
18
+import org.springframework.beans.factory.annotation.Autowired;
19
+import org.springframework.web.bind.annotation.*;
20
+
21
+import java.time.LocalDateTime;
22
+
23
+@Api(tags = "账户流水")
24
+@RestController
25
+@RequestMapping("/admin")
26
+public class TaAccountLogController extends BaseController {
27
+
28
+    @Autowired
29
+    ITaAccountLogService iTaAccountLogService;
30
+
31
+    @Autowired
32
+    ITaAccountMonthlyService iTaAccountMonthlyService;
33
+
34
+    /**
35
+     * 分页查询列表
36
+     * @param pageNum
37
+     * @param pageSize
38
+     * @return
39
+     */
40
+    @RequestMapping(value="/account-log",method= RequestMethod.GET)
41
+    @ApiOperation(value="账户流水", notes = "账户流水", httpMethod = "GET", response = ResponseBean.class)
42
+    public ResponseBean getDailyList(@ApiParam("页码") @RequestParam(value ="pageNum",defaultValue = "1") Integer pageNum,
43
+                                    @ApiParam("单页数据量") @RequestParam(value ="pageSize",defaultValue = "10") Integer pageSize,
44
+                                    @ApiParam("日期") @RequestParam(value ="dailyId", required = false) String dailyId,
45
+                                     @ApiParam("月份") @RequestParam(value ="monthId", required = false) String monthId,
46
+                                    @ApiParam("订单号") @RequestParam(value ="orderNo", required = false) String orderNo) throws Exception{
47
+
48
+        IPage<TaAccountLog> pg = new Page<>(pageNum, pageSize);
49
+        QueryWrapper<TaAccountLog> queryWrapper = new QueryWrapper<>();
50
+        queryWrapper.eq(!StringUtils.isEmpty(dailyId), "daily_id", dailyId);
51
+        queryWrapper.like(!StringUtils.isEmpty(orderNo), "order_no", "%" + orderNo + "%");
52
+        queryWrapper.like(!StringUtils.isEmpty(monthId), "daily_id", monthId + "%");
53
+        queryWrapper.orderByDesc("daily_id");
54
+        queryWrapper.orderByDesc("create_date");
55
+
56
+        IPage<TaAccountLog> result = iTaAccountLogService.page(pg, queryWrapper);
57
+        return ResponseBean.success(result);
58
+    }
59
+
60
+    @RequestMapping(value="/account-log",method= RequestMethod.POST)
61
+    @ApiOperation(value="对账", notes = "对账", httpMethod = "POST", response = ResponseBean.class)
62
+    public ResponseBean newReconciliation(@ApiParam("日期") @RequestParam(value ="dailyId") String dailyId) throws Exception {
63
+        iTaAccountLogService.reconciliation(dailyId);
64
+        return ResponseBean.success("ok");
65
+    }
66
+
67
+
68
+    /**
69
+     * 分页查询列表
70
+     * @param pageNum
71
+     * @param pageSize
72
+     * @return
73
+     */
74
+    @RequestMapping(value="/account-log/month",method= RequestMethod.GET)
75
+    @ApiOperation(value="月度账户流水", notes = "月度账户流水", httpMethod = "GET", response = ResponseBean.class)
76
+    public ResponseBean getMonthList(@ApiParam("页码") @RequestParam(value ="pageNum",defaultValue = "1") Integer pageNum,
77
+                                     @ApiParam("单页数据量") @RequestParam(value ="pageSize",defaultValue = "10") Integer pageSize,
78
+                                     @ApiParam("月份") @RequestParam(value ="monthId", required = false) String monthId) throws Exception{
79
+
80
+        IPage<TaAccountMonthly> pg = new Page<>(pageNum, pageSize);
81
+        QueryWrapper<TaAccountMonthly> queryWrapper = new QueryWrapper<>();
82
+        queryWrapper.eq(!StringUtils.isEmpty(monthId), "month_id", monthId);
83
+        queryWrapper.orderByDesc("month_id");
84
+        queryWrapper.orderByDesc("create_date");
85
+
86
+        IPage<TaAccountMonthly> result = iTaAccountMonthlyService.page(pg, queryWrapper);
87
+        return ResponseBean.success(result);
88
+    }
89
+
90
+    @RequestMapping(value="/account-log/month",method= RequestMethod.POST)
91
+    @ApiOperation(value="月度账单生成", notes = "月度账单生成", httpMethod = "POST", response = ResponseBean.class)
92
+    public ResponseBean newReconciliationMonth(@ApiParam("月份") @RequestParam(value ="monthId") String monthId) throws Exception {
93
+        iTaAccountLogService.reconcileMonthly(monthId, true);
94
+        return ResponseBean.success("ok");
95
+    }
96
+
97
+    @RequestMapping(value="/account-log/month",method= RequestMethod.PUT)
98
+    @ApiOperation(value="月度账单对账", notes = "月度账单对账", httpMethod = "PUT", response = ResponseBean.class)
99
+    public ResponseBean monthlyUpdate(@ApiParam("月份") @RequestBody TaAccountMonthly taAccountMonthly) throws Exception {
100
+        TaAccountMonthly accountMonthly = iTaAccountMonthlyService.getById(taAccountMonthly.getMonthId());
101
+        if (null == accountMonthly) {
102
+            return ResponseBean.error("未找到对账月度信息");
103
+        }
104
+
105
+        accountMonthly.setStatus(taAccountMonthly.getStatus());
106
+        if (Constants.STATUS_NORMAL == taAccountMonthly.getStatus()) {
107
+            accountMonthly.setReconcileDate(LocalDateTime.now());
108
+        }
109
+
110
+        iTaAccountMonthlyService.updateById(accountMonthly);
111
+        return ResponseBean.success("ok");
112
+    }
113
+}

+ 49
- 0
src/main/java/com/njyunzhi/pet_identity/entity/TaAccountLog.java Целия файл

@@ -0,0 +1,49 @@
1
+package com.njyunzhi.pet_identity.entity;
2
+
3
+import com.baomidou.mybatisplus.annotation.IdType;
4
+import com.baomidou.mybatisplus.annotation.TableId;
5
+import io.swagger.annotations.ApiModel;
6
+import io.swagger.annotations.ApiModelProperty;
7
+import lombok.Data;
8
+import lombok.EqualsAndHashCode;
9
+import lombok.experimental.Accessors;
10
+
11
+import java.io.Serializable;
12
+import java.time.LocalDateTime;
13
+
14
+@Data
15
+@EqualsAndHashCode(callSuper = false)
16
+@Accessors(chain = true)
17
+@ApiModel(value="TaAccountLog对象", description="账户流水")
18
+public class TaAccountLog implements Serializable {
19
+
20
+    private static final long serialVersionUID = 1L;
21
+
22
+    @ApiModelProperty(value = "流水ID")
23
+    @TableId(value = "serial_no", type = IdType.AUTO)
24
+    private Integer serialNo;
25
+
26
+    @ApiModelProperty(value = "日期ID")
27
+    private String dailyId;
28
+
29
+    @ApiModelProperty(value = "订单ID")
30
+    private String orderId;
31
+
32
+    @ApiModelProperty(value = "订单号")
33
+    private String orderNo;
34
+
35
+    @ApiModelProperty(value = "总金额;单位分")
36
+    private Integer charges;
37
+
38
+    @ApiModelProperty(value = "手续费;单位分")
39
+    private Integer poundage;
40
+
41
+    @ApiModelProperty(value = "支付类型;1收入,-1支出")
42
+    private Integer chargeType;
43
+
44
+    @ApiModelProperty(value = "状态;0未对账,1对账")
45
+    private Integer status;
46
+
47
+    @ApiModelProperty(value = "创建日期")
48
+    private LocalDateTime createDate;
49
+}

+ 37
- 0
src/main/java/com/njyunzhi/pet_identity/entity/TaAccountMonthly.java Целия файл

@@ -0,0 +1,37 @@
1
+package com.njyunzhi.pet_identity.entity;
2
+
3
+import com.baomidou.mybatisplus.annotation.IdType;
4
+import com.baomidou.mybatisplus.annotation.TableId;
5
+import io.swagger.annotations.ApiModel;
6
+import io.swagger.annotations.ApiModelProperty;
7
+import lombok.Data;
8
+import lombok.EqualsAndHashCode;
9
+import lombok.experimental.Accessors;
10
+
11
+import java.io.Serializable;
12
+import java.time.LocalDateTime;
13
+
14
+@Data
15
+@EqualsAndHashCode(callSuper = false)
16
+@Accessors(chain = true)
17
+@ApiModel(value="TaAccountMonthly对象", description="账户月结")
18
+public class TaAccountMonthly implements Serializable {
19
+
20
+    private static final long serialVersionUID = 1L;
21
+
22
+    @ApiModelProperty(value = "月度ID")
23
+    @TableId(value = "month_id", type = IdType.INPUT)
24
+    private String monthId;
25
+
26
+    @ApiModelProperty(value = "总金额;单位分")
27
+    private Integer totalCharge;
28
+
29
+    @ApiModelProperty(value = "状态;0未对账,1对账")
30
+    private Integer status;
31
+
32
+    @ApiModelProperty(value = "创建日期")
33
+    private LocalDateTime createDate;
34
+
35
+    @ApiModelProperty(value = "对账日期")
36
+    private LocalDateTime reconcileDate;
37
+}

+ 133
- 0
src/main/java/com/njyunzhi/pet_identity/entity/TaWxBillList.java Целия файл

@@ -0,0 +1,133 @@
1
+package com.njyunzhi.pet_identity.entity;
2
+
3
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
4
+import com.alibaba.excel.annotation.ExcelProperty;
5
+import com.baomidou.mybatisplus.annotation.IdType;
6
+import com.baomidou.mybatisplus.annotation.TableId;
7
+import com.njyunzhi.pet_identity.common.excelConverter.WxStringConverter;
8
+import io.swagger.annotations.ApiModel;
9
+import io.swagger.annotations.ApiModelProperty;
10
+import lombok.Data;
11
+import lombok.EqualsAndHashCode;
12
+
13
+@Data
14
+@EqualsAndHashCode(callSuper = false)
15
+@ApiModel(value="TaWxBillList对象", description="微信账单")
16
+@ExcelIgnoreUnannotated
17
+public class TaWxBillList {
18
+
19
+    @ApiModelProperty(value = "交易时间")
20
+    @ExcelProperty(index = 0, converter = WxStringConverter.class)
21
+    private String tradeTime;
22
+
23
+    @ApiModelProperty(value = "公众账号ID")
24
+    @ExcelProperty(index = 1, converter = WxStringConverter.class)
25
+    private String appId;
26
+
27
+    @ApiModelProperty(value = "商户号")
28
+    @ExcelProperty(index = 2, converter = WxStringConverter.class)
29
+    private String mchId;
30
+
31
+    @ApiModelProperty(value = "特约商户号")
32
+    @ExcelProperty(index = 3, converter = WxStringConverter.class)
33
+    private String subMchId;
34
+
35
+    @ApiModelProperty(value = "设备号")
36
+    @ExcelProperty(index = 4, converter = WxStringConverter.class)
37
+    private String deviceInfo;
38
+
39
+    @ApiModelProperty(value = "微信订单号")
40
+    @TableId(value = "transaction_id", type = IdType.INPUT)
41
+    @ExcelProperty(index = 5, converter = WxStringConverter.class)
42
+    private String transactionId;
43
+
44
+    @ApiModelProperty(value = "商户订单号")
45
+    @ExcelProperty(index = 6, converter = WxStringConverter.class)
46
+    private String outTradeNo;
47
+
48
+    @ApiModelProperty(value = "用户标识")
49
+    @ExcelProperty(index = 7, converter = WxStringConverter.class)
50
+    private String openId;
51
+
52
+    @ApiModelProperty(value = "交易类型")
53
+    @ExcelProperty(index = 8, converter = WxStringConverter.class)
54
+    private String tradeType;
55
+
56
+    @ApiModelProperty(value = "交易状态")
57
+    @ExcelProperty(index = 9, converter = WxStringConverter.class)
58
+    private String tradeState;
59
+
60
+    @ApiModelProperty(value = "付款银行")
61
+    @ExcelProperty(index = 10, converter = WxStringConverter.class)
62
+    private String bankType;
63
+
64
+    @ApiModelProperty(value = "货币种类")
65
+    @ExcelProperty(index = 11, converter = WxStringConverter.class)
66
+    private String feeType;
67
+
68
+    @ApiModelProperty(value = "应结订单金额")
69
+    @ExcelProperty(index = 12, converter = WxStringConverter.class)
70
+    private String totalFee;
71
+
72
+    @ApiModelProperty(value = "代金券金额")
73
+    @ExcelProperty(index = 13, converter = WxStringConverter.class)
74
+    private String couponFee;
75
+
76
+    @ApiModelProperty(value = "微信退款单号")
77
+    @ExcelProperty(index = 14, converter = WxStringConverter.class)
78
+    private String refundId;
79
+
80
+    @ApiModelProperty(value = "商户退款单号")
81
+    @ExcelProperty(index = 15, converter = WxStringConverter.class)
82
+    private String outRefundNo;
83
+
84
+    @ApiModelProperty(value = "退款金额")
85
+    @ExcelProperty(index = 16, converter = WxStringConverter.class)
86
+    private String settlementRefundFee;
87
+
88
+    @ApiModelProperty(value = "充值券退款金额")
89
+    @ExcelProperty(index = 17, converter = WxStringConverter.class)
90
+    private String couponRefundFee;
91
+
92
+    @ApiModelProperty(value = "退款类型")
93
+    @ExcelProperty(index = 18, converter = WxStringConverter.class)
94
+    private String refundChannel;
95
+
96
+    @ApiModelProperty(value = "退款状态")
97
+    @ExcelProperty(index = 19, converter = WxStringConverter.class)
98
+    private String refundState;
99
+
100
+    @ApiModelProperty(value = "商品名称")
101
+    @ExcelProperty(index = 20, converter = WxStringConverter.class)
102
+    private String body;
103
+
104
+    @ApiModelProperty(value = "商户数据包")
105
+    @ExcelProperty(index = 21, converter = WxStringConverter.class)
106
+    private String attach;
107
+
108
+    @ApiModelProperty(value = "手续费")
109
+    @ExcelProperty(index = 22, converter = WxStringConverter.class)
110
+    private String poundage;
111
+
112
+    @ApiModelProperty(value = "费率")
113
+    @ExcelProperty(index = 23, converter = WxStringConverter.class)
114
+    private String poundageRate;
115
+
116
+    @ApiModelProperty(value = "订单金额")
117
+    @ExcelProperty(index = 24, converter = WxStringConverter.class)
118
+    private String totalAmount;
119
+
120
+    @ApiModelProperty(value = "申请退款金额")
121
+    @ExcelProperty(index = 25, converter = WxStringConverter.class)
122
+    private String appliedRefundAmount;
123
+
124
+    @ApiModelProperty(value = "费率备注")
125
+    @ExcelProperty(index = 26, converter = WxStringConverter.class)
126
+    private String feeRemark;
127
+
128
+//    @ExcelProperty(index = 27)
129
+//    private String refundTime;
130
+//
131
+//    @ExcelProperty(index = 28)
132
+//    private String refundSuccessTime;
133
+}

+ 47
- 0
src/main/java/com/njyunzhi/pet_identity/job/Reconciliation.java Целия файл

@@ -0,0 +1,47 @@
1
+package com.njyunzhi.pet_identity.job;
2
+
3
+import com.njyunzhi.pet_identity.common.DateUtils;
4
+import com.njyunzhi.pet_identity.common.WxPayUtils;
5
+import com.njyunzhi.pet_identity.service.ITaAccountLogService;
6
+import org.springframework.beans.factory.annotation.Autowired;
7
+import org.springframework.context.annotation.Configuration;
8
+import org.springframework.scheduling.annotation.EnableScheduling;
9
+import org.springframework.scheduling.annotation.Scheduled;
10
+
11
+import java.time.LocalDateTime;
12
+
13
+/**
14
+ * 对账
15
+ */
16
+@Configuration
17
+@EnableScheduling
18
+public class Reconciliation {
19
+    @Autowired
20
+    ITaAccountLogService iTaAccountLogService;
21
+
22
+    /**
23
+     * 微信对账, 官方建议在每天的 10 点之后
24
+     */
25
+    @Scheduled(cron = "0 0 11 * * ?")
26
+    public void daily() {
27
+        try {
28
+            String yestoday = DateUtils.toString(LocalDateTime.now().minusDays(1), "yyyy-MM-dd");
29
+            iTaAccountLogService.reconciliation(yestoday);
30
+        } catch (Exception e) {
31
+            e.printStackTrace();
32
+        }
33
+    }
34
+
35
+    /**
36
+     * 月度对账, 每月2号14点
37
+     */
38
+    @Scheduled(cron = "0 0 14 2 * ?")
39
+    public void monthly() {
40
+        try {
41
+            String lastMonth = DateUtils.toString(LocalDateTime.now().minusMonths(1), "yyyy-MM");
42
+            iTaAccountLogService.reconcileMonthly(lastMonth, false);
43
+        } catch (Exception e) {
44
+            e.printStackTrace();
45
+        }
46
+    }
47
+}

+ 24
- 0
src/main/java/com/njyunzhi/pet_identity/mapper/TaAccountLogMapper.java Целия файл

@@ -0,0 +1,24 @@
1
+package com.njyunzhi.pet_identity.mapper;
2
+
3
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
+import com.njyunzhi.pet_identity.entity.TaAccountLog;
5
+import com.njyunzhi.pet_identity.entity.TaAccountMonthly;
6
+import org.apache.ibatis.annotations.Mapper;
7
+import org.apache.ibatis.annotations.Param;
8
+import org.apache.ibatis.annotations.Select;
9
+
10
+/**
11
+ * <p>
12
+ * 账户流水 Mapper 接口
13
+ * </p>
14
+ *
15
+ * @author yansen
16
+ * @since 2022-05-24
17
+ */
18
+@Mapper
19
+public interface TaAccountLogMapper extends BaseMapper<TaAccountLog> {
20
+
21
+    int countNumMonth(@Param("monthStr") String monthStr);
22
+
23
+    int accTotalCharge(@Param("monthStr") String monthStr);
24
+}

+ 17
- 0
src/main/java/com/njyunzhi/pet_identity/mapper/TaAccountMonthlyMapper.java Целия файл

@@ -0,0 +1,17 @@
1
+package com.njyunzhi.pet_identity.mapper;
2
+
3
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
+import com.njyunzhi.pet_identity.entity.TaAccountMonthly;
5
+import org.apache.ibatis.annotations.Mapper;
6
+
7
+/**
8
+ * <p>
9
+ * 账户月结 Mapper 接口
10
+ * </p>
11
+ *
12
+ * @author yansen
13
+ * @since 2022-05-24
14
+ */
15
+@Mapper
16
+public interface TaAccountMonthlyMapper  extends BaseMapper<TaAccountMonthly> {
17
+}

+ 17
- 0
src/main/java/com/njyunzhi/pet_identity/mapper/TaWxBillListMapper.java Целия файл

@@ -0,0 +1,17 @@
1
+package com.njyunzhi.pet_identity.mapper;
2
+
3
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4
+import com.njyunzhi.pet_identity.entity.TaWxBillList;
5
+import org.apache.ibatis.annotations.Mapper;
6
+
7
+/**
8
+ * <p>
9
+ * 微信账单 Mapper 接口
10
+ * </p>
11
+ *
12
+ * @author yansen
13
+ * @since 2022-05-24
14
+ */
15
+@Mapper
16
+public interface TaWxBillListMapper extends BaseMapper<TaWxBillList> {
17
+}

+ 9
- 0
src/main/java/com/njyunzhi/pet_identity/service/ITaAccountLogService.java Целия файл

@@ -0,0 +1,9 @@
1
+package com.njyunzhi.pet_identity.service;
2
+
3
+import com.njyunzhi.pet_identity.entity.TaAccountLog;
4
+
5
+public interface ITaAccountLogService extends IBaseService<TaAccountLog> {
6
+    void reconciliation(String dayStr) throws Exception;
7
+
8
+    void reconcileMonthly(String monthStr, boolean force) throws Exception;
9
+}

+ 14
- 0
src/main/java/com/njyunzhi/pet_identity/service/ITaAccountMonthlyService.java Целия файл

@@ -0,0 +1,14 @@
1
+package com.njyunzhi.pet_identity.service;
2
+
3
+import com.njyunzhi.pet_identity.entity.TaAccountMonthly;
4
+
5
+/**
6
+ * <p>
7
+ * 账户月结 服务类
8
+ * </p>
9
+ *
10
+ * @author yansen
11
+ * @since 2022-05-24
12
+ */
13
+public interface ITaAccountMonthlyService extends IBaseService<TaAccountMonthly> {
14
+}

+ 158
- 0
src/main/java/com/njyunzhi/pet_identity/service/impl/TaAccountLogServiceImpl.java Целия файл

@@ -0,0 +1,158 @@
1
+package com.njyunzhi.pet_identity.service.impl;
2
+
3
+import com.alibaba.excel.EasyExcel;
4
+import com.alibaba.excel.read.listener.PageReadListener;
5
+import com.alibaba.excel.support.ExcelTypeEnum;
6
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
7
+import com.github.binarywang.wxpay.bean.result.WxPayBillInfo;
8
+import com.github.binarywang.wxpay.bean.result.WxPayBillResult;
9
+import com.njyunzhi.pet_identity.common.Constants;
10
+import com.njyunzhi.pet_identity.common.DateUtils;
11
+import com.njyunzhi.pet_identity.common.WxPayUtils;
12
+import com.njyunzhi.pet_identity.entity.TaAccountLog;
13
+import com.njyunzhi.pet_identity.entity.TaAccountMonthly;
14
+import com.njyunzhi.pet_identity.entity.TaWxBillList;
15
+import com.njyunzhi.pet_identity.mapper.TaAccountLogMapper;
16
+import com.njyunzhi.pet_identity.mapper.TaAccountMonthlyMapper;
17
+import com.njyunzhi.pet_identity.mapper.TaWxBillListMapper;
18
+import com.njyunzhi.pet_identity.service.ITaAccountLogService;
19
+import org.springframework.beans.factory.annotation.Autowired;
20
+import org.springframework.beans.factory.annotation.Value;
21
+import org.springframework.stereotype.Service;
22
+
23
+import java.io.InputStream;
24
+import java.time.LocalDateTime;
25
+
26
+/**
27
+ * <p>
28
+ * 账户流水 服务类
29
+ * </p>
30
+ *
31
+ * @author yansen
32
+ * @since 2022-05-24
33
+ */
34
+@Service
35
+public class TaAccountLogServiceImpl extends BaseServiceImpl<TaAccountLogMapper, TaAccountLog> implements ITaAccountLogService {
36
+
37
+    @Autowired
38
+    TaWxBillListMapper taWxBillListMapper;
39
+
40
+    @Autowired
41
+    TaAccountMonthlyMapper taAccountMonthlyMapper;
42
+
43
+    @Autowired
44
+    WxPayUtils wxPayUtils;
45
+
46
+    @Value("${weixin.pay.appId}")
47
+    String payAppId;
48
+
49
+    @Override
50
+    public void reconciliation(String dayStr) throws Exception {
51
+        InputStream inputStream = wxPayUtils.download(dayStr);
52
+
53
+        // 先删除原始数据
54
+        deleteLogByDailyId(dayStr);
55
+
56
+        EasyExcel.read(inputStream, TaWxBillList.class, new PageReadListener<TaWxBillList>(dataList -> {
57
+            if (null != dataList) {
58
+                int len = 0;
59
+                for (TaWxBillList billInfo : dataList) {
60
+                    // 只记录当前 APPID 的
61
+                    String appid = billInfo.getAppId();
62
+                    if (!payAppId.equals(appid)) continue;
63
+                    // 如果读到汇总区, 则代表读完了
64
+                    if ("应结订单总金额".equals(appid)) break;
65
+
66
+                    // 先删除原始数据
67
+                    taWxBillListMapper.deleteById(billInfo.getTransactionId());
68
+                    // 再插入
69
+                    taWxBillListMapper.insert(billInfo);
70
+
71
+                    TaAccountLog taAccountLog = new TaAccountLog();
72
+                    taAccountLog.setDailyId(dayStr);
73
+                    taAccountLog.setOrderNo(billInfo.getOutTradeNo());
74
+
75
+                    // 交易类型
76
+                    int chargeType = "REFUND".equals(billInfo.getTradeState()) ? -1 : 1;
77
+                    taAccountLog.setChargeType(chargeType);
78
+                    // 订单费用
79
+                    int charges = (int) (getDouble(billInfo.getTotalAmount()) * 100);
80
+                    // 手续费 , 微信手续费有正负, 所以不需要依据交易类型特殊处理
81
+                    int poundage = (int) (getDouble(billInfo.getPoundage()) * 100);
82
+                    // 退款金额
83
+                    int appliedRefundAmount = (int) (getDouble(billInfo.getAppliedRefundAmount()) * 100);
84
+                    // 如果是退款
85
+                    if (chargeType == -1) {
86
+                        charges = -appliedRefundAmount;
87
+                    }
88
+                    taAccountLog.setCharges(charges);
89
+                    taAccountLog.setPoundage(poundage);
90
+                    //
91
+                    taAccountLog.setCreateDate(DateUtils.from(billInfo.getTradeTime(), "yyyy-MM-dd HH:mm:ss"));
92
+
93
+                    save(taAccountLog);
94
+
95
+                    // 记录处理条数
96
+                    len++;
97
+                }
98
+
99
+                if (len == 0) {
100
+                    // 如果当月没有明细, 插入一条 0 记录
101
+                    TaAccountLog taAccountLog = new TaAccountLog();
102
+                    taAccountLog.setDailyId(dayStr);
103
+                    taAccountLog.setChargeType(1);
104
+                    taAccountLog.setCharges(0);
105
+                    taAccountLog.setPoundage(0);
106
+                    save(taAccountLog);
107
+                }
108
+            }
109
+        })).excelType(ExcelTypeEnum.CSV).sheet().headRowNumber(1).doRead();
110
+    }
111
+
112
+    @Override
113
+    public void reconcileMonthly(String monthStr, boolean force) throws Exception {
114
+        if (!force) {
115
+            if (!checkBillNum(monthStr)) {
116
+                throw new Exception("对账明细不全");
117
+            }
118
+        }
119
+
120
+        // 先删除原来的
121
+        TaAccountMonthly origin = taAccountMonthlyMapper.selectById(monthStr);
122
+        if (null != origin) {
123
+            if (Constants.STATUS_NORMAL == origin.getStatus()) {
124
+                throw new Exception(monthStr + " 已经核对过账目");
125
+            }
126
+
127
+            taAccountMonthlyMapper.deleteById(monthStr);
128
+        }
129
+
130
+        int totalCharge = baseMapper.accTotalCharge(monthStr);
131
+        TaAccountMonthly accountMonthly = new TaAccountMonthly();
132
+        accountMonthly.setMonthId(monthStr);
133
+        accountMonthly.setTotalCharge(totalCharge);
134
+        accountMonthly.setStatus(Constants.STATUS_READY);
135
+        accountMonthly.setCreateDate(LocalDateTime.now());
136
+        taAccountMonthlyMapper.insert(accountMonthly);
137
+    }
138
+
139
+    private boolean checkBillNum(String monthStr) {
140
+        String[] parts = monthStr.split("-");
141
+        int days = DateUtils.getDayNum(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
142
+        int cnt = baseMapper.countNumMonth(monthStr);
143
+
144
+        return days == cnt;
145
+    }
146
+
147
+    private double getDouble(String item) {
148
+        if (null == item) return 0.0;
149
+
150
+        return Double.parseDouble(item);
151
+    }
152
+
153
+    private boolean deleteLogByDailyId(String date) {
154
+        QueryWrapper<TaAccountLog> queryWrapper = new QueryWrapper<>();
155
+        queryWrapper.eq("daily_id", date);
156
+        return remove(queryWrapper);
157
+    }
158
+}

+ 19
- 0
src/main/java/com/njyunzhi/pet_identity/service/impl/TaAccountMonthlyServiceImpl.java Целия файл

@@ -0,0 +1,19 @@
1
+package com.njyunzhi.pet_identity.service.impl;
2
+
3
+
4
+import com.njyunzhi.pet_identity.entity.TaAccountMonthly;
5
+import com.njyunzhi.pet_identity.mapper.TaAccountMonthlyMapper;
6
+import com.njyunzhi.pet_identity.service.ITaAccountMonthlyService;
7
+import org.springframework.stereotype.Service;
8
+
9
+/**
10
+ * <p>
11
+ * 账户月结 服务类
12
+ * </p>
13
+ *
14
+ * @author yansen
15
+ * @since 2022-05-24
16
+ */
17
+@Service
18
+public class TaAccountMonthlyServiceImpl extends BaseServiceImpl<TaAccountMonthlyMapper, TaAccountMonthly> implements ITaAccountMonthlyService {
19
+}

+ 29
- 0
src/main/resources/mapper/TaAccountLogMapper.xml Целия файл

@@ -0,0 +1,29 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3
+<mapper namespace="com.njyunzhi.pet_identity.mapper.TaAccountLogMapper">
4
+
5
+    <select id="countNumMonth" resultType="java.lang.Integer">
6
+        SELECT
7
+            count( 1 )
8
+        FROM
9
+            (
10
+                SELECT
11
+                    t.daily_id,
12
+                    max( t.charges )
13
+                FROM
14
+                    ta_account_log t
15
+                WHERE
16
+                    t.daily_id LIKE CONCAT( #{monthStr}, '%' )
17
+                GROUP BY
18
+                    t.daily_id
19
+            ) s
20
+    </select>
21
+    <select id="accTotalCharge" resultType="java.lang.Integer">
22
+        SELECT
23
+            SUM( t.charges - t.poundage )
24
+        FROM
25
+            ta_account_log t
26
+        WHERE
27
+            t.daily_id LIKE CONCAT( #{monthStr}, '%' )
28
+    </select>
29
+</mapper>

+ 5
- 0
src/main/resources/mapper/TaAccountMonthlyMapper.xml Целия файл

@@ -0,0 +1,5 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3
+<mapper namespace="com.njyunzhi.pet_identity.mapper.TaAccountMonthlyMapper">
4
+
5
+</mapper>

+ 5
- 0
src/main/resources/mapper/TaWxBillListMapper.xml Целия файл

@@ -0,0 +1,5 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3
+<mapper namespace="com.njyunzhi.pet_identity.mapper.TaWxBillListMapper">
4
+
5
+</mapper>