Administrator
2024-05-29 62a7f3228c94db41bf57858a6549eb0db033bf1e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
package com.dy.pipIrrSell.wallet;
 
import com.dy.common.aop.SsoAop;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.common.webUtil.QueryResultVo;
import com.dy.common.webUtil.ResultCodeMsg;
import com.dy.pipIrrGlobal.pojoSe.SeConsume;
import com.dy.pipIrrGlobal.pojoSe.SeRefund;
import com.dy.pipIrrGlobal.pojoSe.SeWallet;
import com.dy.pipIrrGlobal.pojoSe.SeWalletRecharge;
import com.dy.pipIrrGlobal.voSe.VoActiveCard;
import com.dy.pipIrrGlobal.voSe.VoWallet;
import com.dy.pipIrrGlobal.voSe.VoWalletRecharge;
import com.dy.pipIrrGlobal.voSe.VoWalletRefund;
import com.dy.pipIrrSell.result.SellResultCode;
import com.dy.pipIrrSell.wallet.enums.LastOperateENUM;
import com.dy.pipIrrSell.wallet.enums.RefundStatusENUM;
import com.dy.pipIrrSell.wallet.qo.QoWalletRecharge;
import com.dy.pipIrrSell.wallet.qo.QueryVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
 
import java.text.DecimalFormat;
import java.util.*;
 
/**
 * @author ZhuBaoMin
 * @date 2023/12/11 16:36
 * @LastEditTime 2023/12/11 16:36
 * @Description
 */
 
@Slf4j
@Tag(name = "电子钱包管理", description = "电子钱包管理")
@RestController
@RequestMapping(path="wallet")
@RequiredArgsConstructor
@Validated
public class WalletCtrl {
    private final WalletSv walletSv;
 
    /**
     * 注册电子钱包账户
     * 需要考虑已注册账户的情况
     * @param clientId
     * @return
     */
    @Operation(summary = "注册电子钱包", description = "注册电子钱包")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "操作结果:true:成功,false:失败(BaseResponse.content)",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Boolean.class))}
            )
    })
    @PostMapping(path = "add_wallet")
    @SsoAop()
    public BaseResponse<Boolean> addWallet(@RequestParam("clientId") @NotNull(message = "农户编号不能为空") Long clientId){
        if(clientId == null || clientId < 0) {
            return BaseResponseUtils.buildFail(SellResultCode.CLIENT_ID_CANNOT_BE_NULL.getMessage());
        }
 
        if(walletSv.getWalletByClientId(clientId) != null) {
            //return BaseResponseUtils.buildFail(SellResultCode.WALLET_ACCOUNT_EXIST.getMessage());
        }
 
        SeWallet seWallet = new SeWallet();
        seWallet.setClientId(clientId);
        seWallet.setMoney(0d);
        seWallet.setLastOperate(LastOperateENUM.OPEN_ACCOUNT.getCode());
        seWallet.setLastOperateTime(new Date());
        seWallet.setCreateTime(new Date());
        Long rec = Optional.ofNullable(walletSv.addWallet(seWallet)).orElse(0L);
        if(rec == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage());
        }
        return BaseResponseUtils.buildSuccess(true) ;
    }
 
    /**
     * 电子钱包账户充值
     * 需要考虑未注册账户的情况
     * @param po
     * @param bindingResult
     * @return
     */
    @Operation(summary = "电子钱包充值", description = "电子钱包充值")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "操作结果:true:成功,false:失败(BaseResponse.content)",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Boolean.class))}
            )
    })
    @PostMapping(path = "add_recharge", consumes = MediaType.APPLICATION_JSON_VALUE)
    @Transactional(rollbackFor = Exception.class)
    @SsoAop()
    public BaseResponse<Boolean> addRecharge(@RequestBody @Valid SeWalletRecharge po, BindingResult bindingResult){
        Long clientId = Optional.ofNullable(po .getClientId()).orElse(0L);
        Double amount = Optional.ofNullable(po.getAmount()).orElse(0.0);
 
        // 验证该农户是否已经注册电子钱包账户并取出ID及当前账户余额
        SeWallet seWallet = walletSv.getWalletByClientId(clientId);
        if(seWallet == null) {
            return BaseResponseUtils.buildFail(SellResultCode.NO_ACCOUNT.getMessage());
        }
        Long wallerId = Optional.ofNullable(seWallet.getId()).orElse(0L);
        Double money = Optional.ofNullable(seWallet.getMoney()).orElse(0.0);
 
        // 计算充值后余额
        Double afterRrecharge = money + amount;
 
        // 修改电子钱包余额、最后操作类型、最后操作时间
        seWallet.setMoney(afterRrecharge);
        seWallet.setLastOperate(LastOperateENUM.RECHARGE.getCode());
        seWallet.setLastOperateTime(new Date());
        Integer rec_updateWaller = Optional.ofNullable(walletSv.updateWallet(seWallet)).orElse(0);
        if(rec_updateWaller == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.UPDATE_ACCOUNT_FAIL.getMessage());
        }
 
        // 添加充值记录
        po.setWalletId(wallerId);
        po.setClientId(clientId);
        po.setMoney(money);
        po.setAmount(amount);
        po.setAfterRecharge(afterRrecharge);
        po.setRechargeTime(new Date());
        Long rec = Optional.ofNullable(walletSv.addRecharge(po)).orElse(0L);
        if(rec == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.RECHARGE_FAIL.getMessage());
        }
        return BaseResponseUtils.buildSuccess(true) ;
    }
 
    /**
     * 电子钱包消费
     * 需要考虑未注册账户的情况、余额不足的情况
     * @param po
     * @param bindingResult
     * @return
     */
    @Operation(summary = "电子钱包消费", description = "电子钱包消费")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "操作结果:true:成功,false:失败(BaseResponse.content)",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Boolean.class))}
            )
    })
    @PostMapping(path = "add_consume", consumes = MediaType.APPLICATION_JSON_VALUE)
    @Transactional(rollbackFor = Exception.class)
    @SsoAop()
    public BaseResponse<Boolean> addConsume(@RequestBody @Valid SeConsume po, BindingResult bindingResult){
        Long clientId = po .getClientId();
        Double consumption = po.getConsumption();
        Date vot = po.getVot();
        Date vct = po.getVct();
 
        // 计算开关阀时间差及用水时长
        Long timeDifference = vct.getTime() - vot.getTime();
        DecimalFormat df = new DecimalFormat("#.00");
        Double duration = Double.parseDouble(df.format((float)timeDifference / (1000 * 60 * 60)));
 
        // 验证该农户是否已经注册电子钱包账户并取出ID及当前账户余额
        SeWallet seWallet = walletSv.getWalletByClientId(clientId);
        if(seWallet == null) {
            return BaseResponseUtils.buildFail(SellResultCode.NO_ACCOUNT.getMessage());
        }
        Long wallerId = Optional.ofNullable(seWallet.getId()).orElse(0L);
        Double money = Optional.ofNullable(seWallet.getMoney()).orElse(0.0);
 
        if(money < consumption) {
            return BaseResponseUtils.buildFail(SellResultCode.BALANCE_IS_INSUFFICIENT.getMessage());
        }
        // 计算消费后余额
        Double afterConsume = money - consumption;
 
        // 修改电子钱包余额、最后操作类型、最后操作时间
        seWallet.setMoney(afterConsume);
        seWallet.setLastOperate(LastOperateENUM.CONSUME.getCode());
        seWallet.setLastOperateTime(new Date());
        Integer rec_updateWaller = Optional.ofNullable(walletSv.updateWallet(seWallet)).orElse(0);
        if(rec_updateWaller == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.UPDATE_ACCOUNT_FAIL.getMessage());
        }
 
        // 添加消费记录
        po.setWalletId(wallerId);
        po.setMoney(money);
        po.setAfterConsume(afterConsume);
        po.setDuration(duration);
        Long rec = Optional.ofNullable(walletSv.addConsume(po)).orElse(0L);
        if(rec == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.CONSUME_FAIL.getMessage());
        }
        return BaseResponseUtils.buildSuccess(true) ;
    }
 
    /**
     * 申请退款
     * 需要考虑申请退款金额大于余额的情况
     * @param po
     * @param bindingResult
     * @return
     */
    @Operation(summary = "电子钱包申请退费", description = "电子钱包申请退费")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "操作结果:true:成功,false:失败(BaseResponse.content)",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Boolean.class))}
            )
    })
    @PostMapping(path = "add_refund", consumes = MediaType.APPLICATION_JSON_VALUE)
    @Transactional(rollbackFor = Exception.class)
    @SsoAop()
    public BaseResponse<Boolean> addRefund(@RequestBody @Valid SeRefund po, BindingResult bindingResult){
        Long clientId = po .getClientId();
        Double refundAmount = po.getRefundAmount();
 
        // 验证该农户是否已经注册电子钱包账户并取出ID及当前账户余额
        SeWallet seWallet = walletSv.getWalletByClientId(clientId);
        if(seWallet == null) {
            return BaseResponseUtils.buildFail(SellResultCode.NO_ACCOUNT.getMessage());
        }
        Long wallerId = Optional.ofNullable(seWallet.getId()).orElse(0L);
        Double money = Optional.ofNullable(seWallet.getMoney()).orElse(0.0);
 
        // 验证退款金额是否大于余额
        if(money < refundAmount) {
            return BaseResponseUtils.buildFail(SellResultCode.REFUND_AMOUNT_CANNOT_GREATER_THAN_MONEY.getMessage());
        }
        // 计算消费后余额
        Double afterRefund = money - refundAmount;
 
        // 修改电子钱包余额、最后操作类型、最后操作时间
        seWallet.setMoney(afterRefund);
        seWallet.setLastOperate(LastOperateENUM.APPLY_REFUND.getCode());
        seWallet.setLastOperateTime(new Date());
        Integer rec_updateWaller = Optional.ofNullable(walletSv.updateWallet(seWallet)).orElse(0);
        if(rec_updateWaller == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.UPDATE_ACCOUNT_FAIL.getMessage());
        }
 
        // 添加消费记录
        po.setWalletId(wallerId);
        po.setMoney(money);
        po.setAfterRefund(afterRefund);
        po.setApplicationTime(new Date());
        po.setRefundStatus(RefundStatusENUM.NO_REFUND.getCode());
        Long rec = Optional.ofNullable(walletSv.addRefund(po)).orElse(0L);
        if(rec == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.APPLICATION_REFUND_FAIL.getMessage());
        }
        return BaseResponseUtils.buildSuccess(true) ;
    }
 
    /**
     * 审核退款申请
     * 需要考虑该电子钱包没有待审核的退款申请的情况
     * @param po
     * @param bindingResult
     * @return
     */
    @Operation(summary = "电子钱包审核退款申请", description = "电子钱包审核退款申请")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "操作结果:true:成功,false:失败(BaseResponse.content)",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Boolean.class))}
            )
    })
    @PostMapping(path = "audit_refund", consumes = MediaType.APPLICATION_JSON_VALUE)
    @Transactional(rollbackFor = Exception.class)
    @SsoAop()
    public BaseResponse<Boolean> auditRefund(@RequestBody @Valid SeRefund po, BindingResult bindingResult){
        Long clientId = po.getClientId();
        Byte refundStatus = po.getRefundStatus();
        Long auditor = po.getAuditor();
        String remarks = po.getRemarks();
 
        // 验证该农户是否已经注册电子钱包账户并取出ID及当前账户余额
        SeWallet seWallet = walletSv.getWalletByClientId(clientId);
        if(seWallet == null) {
            return BaseResponseUtils.buildFail(SellResultCode.NO_ACCOUNT.getMessage());
        }
        Long wallerId = Optional.ofNullable(seWallet.getId()).orElse(0L);
        Double money = Optional.ofNullable(seWallet.getMoney()).orElse(0.0);
 
        // 验证该电子钱包是否有待审核的退款申请(根据钱包ID获取待审核的退款申请对象)
        SeRefund seRefund = walletSv.getRefundByWallerId(wallerId);
        if(seRefund == null) {
            return BaseResponseUtils.buildFail(SellResultCode.NO_TO_AUDIT_REFUND.getMessage());
        }
 
        // 修改电子钱包最后操作类型、最后操作时间
        seWallet.setLastOperate(LastOperateENUM.AUDIT_REFUND.getCode());
        seWallet.setLastOperateTime(new Date());
        Integer rec_updateWaller = Optional.ofNullable(walletSv.updateWallet(seWallet)).orElse(0);
        if(rec_updateWaller == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.UPDATE_ACCOUNT_FAIL.getMessage());
        }
 
        // 添加消费记录
        seRefund.setRefundStatus(refundStatus);
        seRefund.setAuditor(auditor);
        seRefund.setAuditTime(new Date());
        seRefund.setRemarks(remarks);
        Integer rec = Optional.ofNullable(walletSv.auditRefund(seRefund)).orElse(0);
        if(rec == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.AUDIT_REFUND_FAIL.getMessage());
        }
        return BaseResponseUtils.buildSuccess(true) ;
    }
 
    /**
     * 根据农户姓名获取电子钱包账户记录
     * @param vo
     * @return
     */
    @Operation(summary = "获取电子钱包账户记录", description = "返回电子钱包账户记录")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "返回一页补卡数据(BaseResponse.content:QueryResultVo[{}])",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = VoActiveCard.class))}
            )
    })
    @GetMapping(path = "/get_wallets")
    @SsoAop()
    public BaseResponse<QueryResultVo<List<VoWallet>>> getWallets(QueryVo vo){
        try {
            QueryResultVo<List<VoWallet>> res = walletSv.getWallets(vo);
            if(res.itemTotal == 0) {
                return BaseResponseUtils.buildFail(SellResultCode.No_ReissueCards.getMessage());
            }
            return BaseResponseUtils.buildSuccess(res);
        } catch (Exception e) {
            log.error("获取电子钱包账户记录", e);
            return BaseResponseUtils.buildException(e.getMessage()) ;
        }
    }
 
    /**
     * 获取电子钱包充值记录
     * @param vo
     * @return
     */
    @Operation(summary = "获取电子钱包充值记录", description = "返回电子钱包充值记录")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "返回一页补卡数据(BaseResponse.content:QueryResultVo[{}])",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = VoActiveCard.class))}
            )
    })
    @GetMapping(path = "/get_recharges")
    @SsoAop()
    public BaseResponse<QueryResultVo<List<VoWalletRecharge>>> getWalletRecharges(QoWalletRecharge vo){
        try {
            QueryResultVo<List<VoWalletRecharge>> res = walletSv.getWalletRecharges(vo);
            if(res.itemTotal == 0) {
                return BaseResponseUtils.buildFail(SellResultCode.No_WALLER_RECHARGES.getMessage());
            }
            return BaseResponseUtils.buildSuccess(res);
        } catch (Exception e) {
            log.error("获取电子钱包充值记录异常", e);
            return BaseResponseUtils.buildException(e.getMessage()) ;
        }
    }
 
    @Operation(summary = "获取电子钱包消费记录", description = "返回电子钱包消费记录")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "返回一页补卡数据(BaseResponse.content:QueryResultVo[{}])",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = VoActiveCard.class))}
            )
    })
    @GetMapping(path = "/get_consume")
    @SsoAop()
    public BaseResponse<Map> getWalletConsumes(QueryVo vo){
        Long clientId = Optional.ofNullable(vo.getClientId()).orElse(0L);
        if(clientId == 0) {
            return BaseResponseUtils.buildFail(SellResultCode.WALLET_CLIENT_ID_CANNOT_BE_NULL.getMessage());
        }
        try {
            Map res = Optional.ofNullable(walletSv.getWalletConsumes(vo)).orElse(new HashMap());
            if(res.size() <= 0) {
                return BaseResponseUtils.buildFail(SellResultCode.No_WALLER_RECHARGES.getMessage());
            }
            return BaseResponseUtils.buildSuccess(res);
        } catch (Exception e) {
            log.error("获取电子钱包充值记录异常", e);
            return BaseResponseUtils.buildException(e.getMessage()) ;
        }
    }
 
    /**
     * 获取电子钱包退款记录
     * @param vo
     * @return
     */
    @Operation(summary = "获取电子钱包退款记录", description = "返回电子钱包退款记录")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE,
                    description = "返回一页补卡数据(BaseResponse.content:QueryResultVo[{}])",
                    content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = VoActiveCard.class))}
            )
    })
    @GetMapping(path = "/get_refunds")
    @SsoAop()
    public BaseResponse<QueryResultVo<List<VoWalletRefund>>> getWalletRefunds(QueryVo vo){
        try {
            QueryResultVo<List<VoWalletRefund>> res = walletSv.getWalletRefunds(vo);
            if(res.itemTotal == 0) {
                return BaseResponseUtils.buildFail(SellResultCode.No_REFUNDS.getMessage());
            }
            return BaseResponseUtils.buildSuccess(res);
        } catch (Exception e) {
            log.error("获取电子钱包退款记录异常", e);
            return BaseResponseUtils.buildException(e.getMessage()) ;
        }
    }
}