From de68066d84de0b4dae5715c15840fa217e8387da Mon Sep 17 00:00:00 2001 From: JIAN Date: Mon, 2 Sep 2024 20:55:02 +0800 Subject: [PATCH 01/21] =?UTF-8?q?refactor(orders):=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=AE=A2=E5=8D=95=E6=A8=A1=E5=9D=97=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jzo2o-oreders/jzo2o-orders-base/pom.xml | 87 +++++ .../base/config/AutoImportConfiguration.java | 17 + .../orders/base/constants/ErrorInfo.java | 12 + .../base/constants/EsIndexConstants.java | 10 + .../orders/base/constants/FieldConstants.java | 50 +++ .../orders/base/constants/OrderConstants.java | 36 +++ .../base/constants/OrdersOriginType.java | 6 + .../orders/base/constants/RedisConstants.java | 169 ++++++++++ .../base/enums/BreachHaviorTypeEnum.java | 19 ++ .../orders/base/enums/OrderPayStatusEnum.java | 24 ++ .../base/enums/OrderRefundStatusEnum.java | 26 ++ .../enums/OrderStatusChangeEventEnum.java | 44 +++ .../orders/base/enums/OrderStatusEnum.java | 39 +++ .../orders/base/enums/ServeStatusEnum.java | 21 ++ .../base/mapper/BreachRecordMapper.java | 34 ++ .../mapper/HistoryOrdersServeSyncMapper.java | 21 ++ .../base/mapper/HistoryOrdersSyncMapper.java | 21 ++ .../base/mapper/OrdersCanceledMapper.java | 16 + .../base/mapper/OrdersDispatchMapper.java | 27 ++ .../orders/base/mapper/OrdersMapper.java | 22 ++ .../base/mapper/OrdersRefundMapper.java | 16 + .../orders/base/mapper/OrdersSeizeMapper.java | 16 + .../orders/base/mapper/OrdersServeMapper.java | 26 ++ .../base/mapper/ServeProviderSyncMapper.java | 21 ++ .../base/model/domain/BreachRecord.java | 95 ++++++ .../domain/CurrentServeProviderTime.java | 38 +++ .../model/domain/HistoryOrdersServeSync.java | 222 +++++++++++++ .../base/model/domain/HistoryOrdersSync.java | 301 ++++++++++++++++++ .../orders/base/model/domain/Orders.java | 201 ++++++++++++ .../base/model/domain/OrdersCanceled.java | 68 ++++ .../base/model/domain/OrdersDispatch.java | 114 +++++++ .../base/model/domain/OrdersRefund.java | 51 +++ .../orders/base/model/domain/OrdersSeize.java | 122 +++++++ .../orders/base/model/domain/OrdersServe.java | 178 +++++++++++ .../base/model/domain/ServeProviderInfo.java | 71 +++++ .../base/model/domain/ServeProviderSync.java | 48 +++ .../base/model/dto/OrderSnapshotDTO.java | 247 ++++++++++++++ .../base/model/dto/OrderUpdateStatusDTO.java | 73 +++++ .../base/properties/DispatchProperties.java | 32 ++ .../base/properties/ExecutorProperties.java | 61 ++++ .../base/service/IOrdersCommonService.java | 18 ++ .../IOrdersDiversionCommonService.java | 17 + .../service/impl/OrdersCommonServiceImpl.java | 40 +++ .../OrdersDiversionCommonServiceImpl.java | 119 +++++++ .../jzo2o/orders/base/utils/RedisUtils.java | 16 + .../orders/base/utils/ServeTimeUtils.java | 24 ++ .../spring-configuration-metadata.json | 9 + .../main/resources/META-INF/spring.factories | 2 + .../resources/mapper/BreachRecordMapper.xml | 5 + .../mapper/HistoryOrdersServeSyncMapper.xml | 5 + .../mapper/HistoryOrdersSyncMapper.xml | 5 + .../resources/mapper/IDispatchService.xml | 5 + .../mapper/IHistoryOrdersSyncService.xml | 5 + .../resources/mapper/OrdersCanceledMapper.xml | 5 + .../resources/mapper/OrdersDispatchMapper.xml | 5 + .../main/resources/mapper/OrdersMapper.xml | 5 + .../resources/mapper/OrdersRefundMapper.xml | 5 + .../resources/mapper/OrdersSeizeMapper.xml | 5 + .../mapper/ServeProviderSyncMapper.xml | 5 + jzo2o-oreders/jzo2o-orders-manager/Dockerfile | 8 + jzo2o-oreders/jzo2o-orders-manager/pom.xml | 121 +++++++ .../manager/OrdersManagerApplication.java | 23 ++ .../orders/manager/constants/EsIndex.java | 5 + .../agency/AgencyOrdersServeController.java | 23 ++ .../consumer/ConsumerOrdersController.java | 56 ++++ .../inner/InnerOrdersController.java | 60 ++++ .../inner/InnerOrdersServeController.java | 47 +++ .../operation/OperationOrdersController.java | 30 ++ .../OperationOrdersServeController.java | 22 ++ .../worker/WorkerOrdersServeController.java | 25 ++ .../manager/model/dto/OrderCancelDTO.java | 71 +++++ .../manager/model/dto/ServeProviderInfo.java | 55 ++++ .../dto/request/OrderPageQueryReqDTO.java | 75 +++++ .../dto/request/OrderServeCancelReqDTO.java | 23 ++ .../request/OrdersDispatchReceiveReqDTO.java | 18 ++ .../request/OrdersDispatchRejectReqDTO.java | 21 ++ .../model/dto/request/OrdersPayReqDTO.java | 22 ++ .../model/dto/request/OrdersSeizeReqDTO.java | 15 + .../request/OrdersServeAllocationReqDTO.java | 20 ++ ...rsServePageQueryByServeProviderReqDTO.java | 28 ++ .../request/OrdersServePageQueryReqDTO.java | 31 ++ .../model/dto/request/PlaceOrderReqDTO.java | 29 ++ .../dto/request/ServeFinishedReqDTO.java | 24 ++ .../model/dto/request/ServeStartReqDTO.java | 23 ++ .../response/OperationOrdersDetailResDTO.java | 200 ++++++++++++ .../dto/response/OrdersDispatchResDTO.java | 31 ++ .../model/dto/response/OrdersPayResDTO.java | 30 ++ .../dto/response/OrdersSeizeListResDTO.java | 89 ++++++ .../dto/response/OrdersServeDetailResDTO.java | 125 ++++++++ .../dto/response/OrdersServeListResDTO.java | 19 ++ .../model/dto/response/OrdersServeResDTO.java | 60 ++++ .../response/OrdersServeStatusNumResDTO.java | 27 ++ .../model/dto/response/PlaceOrderResDTO.java | 19 ++ .../response/ServeProviderServeResDTO.java | 65 ++++ .../porperties/OrdersJobProperties.java | 34 ++ .../manager/porperties/TradeProperties.java | 24 ++ .../manager/service/IBreachRecordService.java | 34 ++ .../service/IOrdersCanceledService.java | 16 + .../manager/service/IOrdersCreateService.java | 33 ++ .../service/IOrdersManagerService.java | 65 ++++ .../manager/service/IOrdersRefundService.java | 24 ++ .../service/IOrdersServeManagerService.java | 48 +++ .../service/impl/BreachRecordServiceImpl.java | 39 +++ .../impl/OrdersCanceledServiceImpl.java | 20 ++ .../service/impl/OrdersCreateServiceImpl.java | 22 ++ .../impl/OrdersManagerServiceImpl.java | 109 +++++++ .../service/impl/OrdersRefundServiceImpl.java | 36 +++ .../impl/OrdersServeManagerServiceImpl.java | 63 ++++ .../src/main/resources/bootstrap-dev.yml | 18 ++ .../src/main/resources/bootstrap-prod.yml | 14 + .../src/main/resources/bootstrap-test.yml | 14 + .../src/main/resources/bootstrap.yml | 76 +++++ .../src/main/resources/seata.conf | 5 + jzo2o-oreders/pom.xml | 27 ++ 114 files changed, 5263 insertions(+) create mode 100644 jzo2o-oreders/jzo2o-orders-base/pom.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/config/AutoImportConfiguration.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/ErrorInfo.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/EsIndexConstants.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/FieldConstants.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/OrderConstants.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/OrdersOriginType.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/RedisConstants.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/BreachHaviorTypeEnum.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderPayStatusEnum.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderRefundStatusEnum.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderStatusChangeEventEnum.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderStatusEnum.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/ServeStatusEnum.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/BreachRecordMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/HistoryOrdersServeSyncMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/HistoryOrdersSyncMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersCanceledMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersDispatchMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersRefundMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersSeizeMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersServeMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/ServeProviderSyncMapper.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/BreachRecord.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/CurrentServeProviderTime.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/HistoryOrdersServeSync.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/HistoryOrdersSync.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/Orders.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersCanceled.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersDispatch.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersRefund.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersSeize.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersServe.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/ServeProviderInfo.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/ServeProviderSync.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderSnapshotDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderUpdateStatusDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/properties/DispatchProperties.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/properties/ExecutorProperties.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersCommonService.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersDiversionCommonService.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersDiversionCommonServiceImpl.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/utils/RedisUtils.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/utils/ServeTimeUtils.java create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/META-INF/spring-configuration-metadata.json create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/META-INF/spring.factories create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/BreachRecordMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/HistoryOrdersServeSyncMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/HistoryOrdersSyncMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/IDispatchService.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/IHistoryOrdersSyncService.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersCanceledMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersDispatchMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersRefundMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersSeizeMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/ServeProviderSyncMapper.xml create mode 100644 jzo2o-oreders/jzo2o-orders-manager/Dockerfile create mode 100644 jzo2o-oreders/jzo2o-orders-manager/pom.xml create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/OrdersManagerApplication.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/constants/EsIndex.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/agency/AgencyOrdersServeController.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersController.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersServeController.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/operation/OperationOrdersController.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/operation/OperationOrdersServeController.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/worker/WorkerOrdersServeController.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/OrderCancelDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/ServeProviderInfo.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrderPageQueryReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrderServeCancelReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersDispatchReceiveReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersDispatchRejectReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersPayReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersSeizeReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServeAllocationReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServePageQueryByServeProviderReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServePageQueryReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/PlaceOrderReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/ServeFinishedReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/ServeStartReqDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OperationOrdersDetailResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersDispatchResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersPayResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersSeizeListResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeDetailResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeListResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeStatusNumResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/PlaceOrderResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/ServeProviderServeResDTO.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/porperties/OrdersJobProperties.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/porperties/TradeProperties.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IBreachRecordService.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCanceledService.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersRefundService.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersServeManagerService.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/BreachRecordServiceImpl.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCanceledServiceImpl.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersRefundServiceImpl.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersServeManagerServiceImpl.java create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-dev.yml create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-prod.yml create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-test.yml create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap.yml create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/resources/seata.conf create mode 100644 jzo2o-oreders/pom.xml diff --git a/jzo2o-oreders/jzo2o-orders-base/pom.xml b/jzo2o-oreders/jzo2o-orders-base/pom.xml new file mode 100644 index 0000000..fb68f5c --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/pom.xml @@ -0,0 +1,87 @@ + + + + jzo2o-oreders + com.jzo2o + 1.0-SNAPSHOT + + 4.0.0 + + jzo2o-orders-base + + + 11 + 11 + + + + + com.jzo2o + jzo2o-common + + + com.jzo2o + jzo2o-mysql + + + com.jzo2o + jzo2o-redis + + + + + + + + + + + + + + + + + com.jzo2o + jzo2o-canal-sync + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.antlr + antlr + + + com.jzo2o + jzo2o-mvc + + + + \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/config/AutoImportConfiguration.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/config/AutoImportConfiguration.java new file mode 100644 index 0000000..481213b --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/config/AutoImportConfiguration.java @@ -0,0 +1,17 @@ +package com.jzo2o.orders.base.config; + +import com.jzo2o.orders.base.properties.DispatchProperties; +import com.jzo2o.orders.base.properties.ExecutorProperties; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@ComponentScan({"com.jzo2o.orders.base.service","com.jzo2o.orders.base.handler"}) +@MapperScan("com.jzo2o.orders.base.mapper") +//@Import({OrderStateMachine.class}) +@EnableConfigurationProperties({DispatchProperties.class, ExecutorProperties.class}) +public class AutoImportConfiguration { +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/ErrorInfo.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/ErrorInfo.java new file mode 100644 index 0000000..5701188 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/ErrorInfo.java @@ -0,0 +1,12 @@ +package com.jzo2o.orders.base.constants; + +public class ErrorInfo { + public static class Msg { + public static final String SEIZE_ORDERS_FAILD = "单子已经被抢走了"; + public static final String SEIZE_ORDERS_SERVE_TIME_EXISTS = "当前服务预约时间冲突"; + public static final String SEIZE_ORDERS_RECEIVE_ORDERS_NUM_OVER = "当前接单数已超出范围"; + + public static final String SEIZE_ORDERS_RECEIVE_CLOSED = "当前接单设置已关闭,如需抢单,需开启接单"; + + } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/EsIndexConstants.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/EsIndexConstants.java new file mode 100644 index 0000000..c8c00be --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/EsIndexConstants.java @@ -0,0 +1,10 @@ +package com.jzo2o.orders.base.constants; + +public class EsIndexConstants { + /** + * 服务人员信息索引 + */ + public static final String SERVER_PROVIDER_INFO = "serve_provider_info"; + + public static final String ORDERS_SEIZE = "orders_seize"; +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/FieldConstants.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/FieldConstants.java new file mode 100644 index 0000000..976c002 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/FieldConstants.java @@ -0,0 +1,50 @@ +package com.jzo2o.orders.base.constants; + +public class FieldConstants { + /** + * 预约时间 + */ + public static final String SERVE_START_TIME = "serve_start_time"; + + /** + * 城市编码 + */ + public static final String CITY_CODE = "city_code"; + + /** + * 服务类型id + */ + public static final String SERVE_TYPE_ID = "serve_type_id"; + + /** + * 服务项id + */ + public static final String SERVE_ITEM_ID = "serve_item_id"; + + /** + * 服务类型名称 + */ + public static final String SERVE_TYPE_NAME = "serve_type_name"; + + /** + * 服务项名称 + */ + public static final String SERVE_ITEM_NAME = "serve_item_name"; + + /** + * 关键字字段 + */ + public static final String KEY_WORDS = "key_words"; + + /** + * 经纬度 + */ + public static final String LOCATION = "location"; + + public static final String SERVE_TIME = "serve_time"; + + /** + * 排序字段 + */ + public static final String SORT_BY = "sort_by"; +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/OrderConstants.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/OrderConstants.java new file mode 100644 index 0000000..4978812 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/OrderConstants.java @@ -0,0 +1,36 @@ +package com.jzo2o.orders.base.constants; + +/** + * 订单常量 + * + * @author itcast + * @create 2023/7/28 15:06 + **/ +public class OrderConstants { + public static final class Status { + public static final String NO_PAY = "NO_PAY"; + public static final String DISPATCHING = "DISPATCHING"; + public static final String NO_SERVE = "NO_SERVE"; + public static final String SERVING = "SERVING"; + public static final String NO_EVALUATION = "NO_EVALUATION"; + public static final String FINISHED = "FINISHED"; + public static final String CANCELED = "CANCELED"; + public static final String CHARGEBACK = "CHARGEBACK"; + } + + public static final class ChangeEvent { + public static final String PAYED = "PAYED"; + public static final String DISPATCH = "DISPATCH"; + public static final String START_SERVE = "START_SERVE"; + public static final String COMPLETE_SERVE = "COMPLETE_SERVE"; + public static final String EVALUATE = "EVALUATE"; + public static final String CANCEL = "CANCEL"; + public static final String SERVE_PROVIDER_CANCEL = "SERVE_PROVIDER_CANCEL"; + + public static final String CLOSE_DISPATCHING_ORDER = "CLOSE_DISPATCHING_ORDER"; + public static final String CLOSE_NO_SERVE_ORDER = "CLOSE_NO_SERVE_ORDER"; + public static final String CLOSE_SERVING_ORDER = "CLOSE_SERVING_ORDER"; + public static final String CLOSE_NO_EVALUATION_ORDER = "CLOSE_NO_EVALUATION_ORDER"; + public static final String CLOSE_FINISHED_ORDER = "CLOSE_FINISHED_ORDER"; + } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/OrdersOriginType.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/OrdersOriginType.java new file mode 100644 index 0000000..e1781f4 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/OrdersOriginType.java @@ -0,0 +1,6 @@ +package com.jzo2o.orders.base.constants; + +public class OrdersOriginType { + public static final int SEIZE = 1; + public static final int DISPATCH = 2; +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/RedisConstants.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/RedisConstants.java new file mode 100644 index 0000000..7b559a2 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/constants/RedisConstants.java @@ -0,0 +1,169 @@ +package com.jzo2o.orders.base.constants; + +public class RedisConstants { + public static final class RedisFormatter { + /** + * 抢单用户锁模板,格式:ORDERS:SEIZE_#{serveProviderId} + */ + public static final String SEIZE = "ORDERS:SEIZE_#{serveProviderId}"; + + /** + * 派单锁模板,格式:ORDERS:DISPATCH_#{id} + */ + public static final String DISPATCH = "ORDERS:DISPATCH_#{id}"; + /** + * 加入派单池锁模板,格式:ORDERS:JSONDISPATCHLIST_#{id} + */ + public static final String JSONDISPATCHLIST = "ORDERS:JSONDISPATCHLIST_#{id}"; + + public static final String REJECT = "ORDERS:DISPATCH:REJECT_#{dispatchRejectReqDTO.id}"; + + /** + * 抢单超时 + */ + public static final String SEIZE_TIME_OUT = "ORDERS:SEIZE:TIME_OUT:#{cityCode}"; + + public static final String ORDERS_SERVE_TIMEOUT = "ORDERS:SEVER_TIMEOUT:#{ordersServe.id}"; + } + public static final class RedisKey { + /** + * 抢单id列表redis key模板:ORDERS:SEIZE:IDS_{服务人员id或机构id}_{citycode} + */ + public static final String ORDERS_SEIZE_IDS_FOR_SERVE_PROVIDE = "ORDERS:SEIZE:IDS_%s_%s"; + + /** + * 抢单列表redis key模板:ORDERS:SEIZE:PAGE_{citycode} + */ + public static final String ORDERS_SEIZE_PAGE = "ORDERS:SEIZE:PAGE_%s"; + + // 抢单相关 + /** + *抢单池,key格式:ORDERS:SEIZE:POOL_{抢单id}_{抢单id尾号} + */ + public static final String ORDERS_SEIZE = "ORDERS:SEIZE:%s_{%s}"; + + /** + * 抢单结果同步队列,该队列分为10条,格式:ORDERS:SEIZE:SYNC_{抢单id尾号} + * 序号分别为:0到9的10个数字 + */ + public static final String ORERS_SEIZE_SYNC_QUEUE_NAME = "ORDERS:SEIZE:SYNC"; + + /** + * 当前用户/机构当前接单数量,接单+派单总数量 + * 接单+派单操作+1 + * 完成服务/取消服务-1 + * 格式:PROVIDER:SERVE:NUM_{cityCode}_{序号} + */ + public static final String PROVIDER_SERVE_NUM = "PROVIDER:SERVE:NUM_%s_{%s}"; + + /** + * 所有服务单放在一起 + */ + public static final String SERVE_ORDERS = "SERVE_ORDERS:PAGE_QUERY:PAGE_%s"; + + public static final String SERVE_ORDERS_KEY = "SERVE_ORDERS:PAGE_QUERY:PAGE_#{serveProviderId}"; + + /** + * 服务人员或机构每日取消服务单次数 + */ + public static final String SERVE_CANCEL_TIMES_EVERY_DAY = "ORDERS:SERVE:CANCEL_%s_%s"; + + public static final String SERVE_TIME_UPDATE = "ORDERS:SERVE_TIME:#{id}"; + + /** + * 库存,hash结构 + */ + public static final String ORDERS_RESOURCE_STOCK = "ORDERS:RESOURCE:STOCK:{%s}"; + + /** + * 派单连续失败次数 string + */ + public static final String ORDERS_DISPATCH_FAILD_TIMES = "ORDERS:DISPATCH:FAILD_TIMES_%s_{%s}"; + + /** + * 派单成功同步队列名称 + */ + public static final String ORERS_DISPATCH_SYNC_QUEUE_NAME = "ORDERS:DISPATCH:SYNC"; + + /** + * 服务时间状态 string 格式:PROVIDER:SERVE_TIME:{serveProviderId}_{serveTime}_{序号} + */ + public static final String SERVE_PROVIDER_TIMES = "PROVIDER:SERVE_TIME:%s_%s_{%s}"; + + /** + * 服务状态表 hash 格式:PROVIDER:SERVE_STATE:{序号} + * key 格式:{服务人员/机构id}_{times或num};time表示接单时间列表,nun表示接单数量 + */ + public static final String SERVE_PROVIDER_STATE = "PROVIDER:SERVE_STATE:{%s}"; + + /** + * 派单列表 - zSet结构 + */ + public static final String DISPATCH_LIST = "ORDERS:DISPATCH:LIST"; + + /** + * 用户端滚动分页查询订单 + */ + public static final String ORDERS = "ORDERS:PAGE_QUERY:PAGE_%s"; + } + + public static class Lock { + /** + * 抢派单分布式锁 + */ + public static final String DISPATCH_OR_SEIZE_LOCK = "ORDERS:DISPATCH_OR_SEIZE:%s"; + + public static final String PROVIDER_DISPATCH_LOCK = "PROVIDER:DISPATCH:LOCK_%s"; + + /** + * 派单同步锁定同步队列redis分布式锁 + */ + public static final String DISPATCH_SYNC_LOCK = "ORDERS:DISPATCH:SYNC_%s"; + + /** + * 接单超时 + */ + public static final String DISPATCH_RECEIVE_TIMEOUT_LOCK = "ORDERS:DISPATCH:TIMEOUT"; + + /** + * 抢单单同步锁定同步队列redis分布式锁 + */ + public static final String SEIZE_SYNC_LOCK = "ORDERS:SEIZE:SYNC_%s"; + + /** + * 订单分片id获取锁 + */ + public static final String ORDERS_SHARD_KEY_ID_LOCK = "ORDERS:SHARD_KEY:LOCK"; + + public static final String ORDERS_SHARD_KEY_ID_GENERATOR = "ORDERS:SHARD_KEY:GENERATOR"; + + } + public static class Ttl { + /** + * 订单抢单缓存 60s + */ + public static final long ORDERS_SEIZE_PAGE_TTL = 60; + + /** + * 服务单分页有效期 + */ + public static final long SERVE_ORSERS_PAGE_TTL = 600; + + + /** + * 订单分页有效期 + */ + public static final long ORDERS_PAGE_TTL = 600; + + + /** + * 抢单派单处理超时时间单位s + */ + public static final long DISPATCH_SEIZE_LOCK_TTL = 10; + + /** + * 派单锁定,10分钟内不能再次派单 + */ + public static final long PROVIDER_DISPATCH_LOCK_TTL = 600; + } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/BreachHaviorTypeEnum.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/BreachHaviorTypeEnum.java new file mode 100644 index 0000000..6f36158 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/BreachHaviorTypeEnum.java @@ -0,0 +1,19 @@ +package com.jzo2o.orders.base.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 违约行为枚举 + */ +@AllArgsConstructor +@Getter +public enum BreachHaviorTypeEnum { + CANCEL_ALLOCATION(1,"机构取消未分配服务单违约行为"), + CANCEL_NO_SERVE(2,"机构或服务人员取消待服务订单违约行为"), + CANCEL_SERVING(3,"机构或服务人员取消服务中订单违约行为"), + DISPATCH_REJECT(4,"机构或服务人员拒绝接单违约行为"); + private int type; + private String desc; + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderPayStatusEnum.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderPayStatusEnum.java new file mode 100644 index 0000000..77e3f97 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderPayStatusEnum.java @@ -0,0 +1,24 @@ +package com.jzo2o.orders.base.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author itcast + */ + +@Getter +@AllArgsConstructor +public enum OrderPayStatusEnum { + NO_PAY(2, "未支付"), + PAY_SUCCESS(4, "支付成功"); + + private int status; + private final String desc; + + public boolean equals(int status) { + return this.status == status; + } + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderRefundStatusEnum.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderRefundStatusEnum.java new file mode 100644 index 0000000..823305f --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderRefundStatusEnum.java @@ -0,0 +1,26 @@ +package com.jzo2o.orders.base.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author itcast + */ + +@Getter +@AllArgsConstructor +public enum OrderRefundStatusEnum { +// APPLY_REFUND(0, "发起退款"), + REFUNDING(1, "退款中"), + REFUND_SUCCESS(2, "退款成功"), + REFUND_FAIL(3, "退款失败"); + + private int status; + private final String desc; + + public boolean equals(int status) { + return this.status == status; + } + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderStatusChangeEventEnum.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderStatusChangeEventEnum.java new file mode 100644 index 0000000..da5d604 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderStatusChangeEventEnum.java @@ -0,0 +1,44 @@ +package com.jzo2o.orders.base.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author itcast + */ +@Getter +@AllArgsConstructor +public enum OrderStatusChangeEventEnum { + PAYED(OrderStatusEnum.NO_PAY, OrderStatusEnum.DISPATCHING, "支付成功", "payed"), + DISPATCH(OrderStatusEnum.DISPATCHING, OrderStatusEnum.NO_SERVE, "接单/抢单成功", "dispatch"), + START_SERVE(OrderStatusEnum.NO_SERVE, OrderStatusEnum.SERVING, "开始服务", "start_serve"), + COMPLETE_SERVE(OrderStatusEnum.SERVING, OrderStatusEnum.FINISHED, "完成服务", "complete_serve"), +// EVALUATE(OrderStatusEnum.NO_EVALUATION, OrderStatusEnum.FINISHED, "评价完成", "evaluate"), + CANCEL(OrderStatusEnum.NO_PAY, OrderStatusEnum.CANCELED, "取消订单", "cancel"), + SERVE_PROVIDER_CANCEL(OrderStatusEnum.NO_SERVE, OrderStatusEnum.DISPATCHING, "服务人员/机构取消订单", "serve_provider_cancel"), + CLOSE_DISPATCHING_ORDER(OrderStatusEnum.DISPATCHING, OrderStatusEnum.CLOSED, "派单中订单关闭", "close_dispatching_order"), + CLOSE_NO_SERVE_ORDER(OrderStatusEnum.NO_SERVE, OrderStatusEnum.CLOSED, "待服务订单关闭", "close_no_serve_order"), + CLOSE_SERVING_ORDER(OrderStatusEnum.SERVING, OrderStatusEnum.CLOSED, "服务中订单关闭", "close_serving_order"), +// CLOSE_NO_EVALUATION_ORDER(OrderStatusEnum.NO_EVALUATION, OrderStatusEnum.CLOSED, "待评价订单关闭", "close_no_evaluation_order"), + CLOSE_FINISHED_ORDER(OrderStatusEnum.FINISHED, OrderStatusEnum.CLOSED, "已完成订单关闭", "close_finished_order"); + + /** + * 源状态 + */ + private final OrderStatusEnum sourceStatus; + + /** + * 目标状态 + */ + private final OrderStatusEnum targetStatus; + + /** + * 描述 + */ + private final String desc; + + /** + * 代码 + */ + private final String code; +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderStatusEnum.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderStatusEnum.java new file mode 100644 index 0000000..be199ab --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/OrderStatusEnum.java @@ -0,0 +1,39 @@ +package com.jzo2o.orders.base.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author itcast + */ +@Getter +@AllArgsConstructor +public enum OrderStatusEnum { + NO_PAY(0, "待支付", "NO_PAY"), + DISPATCHING(100, "派单中", "DISPATCHING"), + NO_SERVE(200, "待服务", "NO_SERVE"), + SERVING(300, "服务中", "SERVING"), +// NO_EVALUATION(400, "待评价", "NO_EVALUATION"), + FINISHED(500, "已完成", "FINISHED"), + CANCELED(600, "已取消", "CANCELED"), + CLOSED(700, "已关闭", "CLOSED"); + + private final Integer status; + private final String desc; + private final String code; + + /** + * 根据状态值获得对应枚举 + * + * @param status 状态 + * @return 状态对应枚举 + */ + public static OrderStatusEnum codeOf(Integer status) { + for (OrderStatusEnum orderStatusEnum : values()) { + if (orderStatusEnum.status.equals(status)) { + return orderStatusEnum; + } + } + return null; + } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/ServeStatusEnum.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/ServeStatusEnum.java new file mode 100644 index 0000000..4267dd0 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/enums/ServeStatusEnum.java @@ -0,0 +1,21 @@ +package com.jzo2o.orders.base.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ServeStatusEnum { + + NO_ALLOCATION(0, "待分配"), + NO_SERVED(1,"待服务"), + SERVING(2,"服务中"), + SERVE_FINISHED(3, "服务完成"), + CANCLE(4, "取消"); + private int status; + private String desc; + + public boolean equals(Integer status) { + return status != null && status.equals(this.getStatus()); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/BreachRecordMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/BreachRecordMapper.java new file mode 100644 index 0000000..7f10fe3 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/BreachRecordMapper.java @@ -0,0 +1,34 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.BreachRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * 违约记录 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +public interface BreachRecordMapper extends BaseMapper { + + /** + * 批量添加违约记录 + * @param breachRecords + * @return + */ +// @Insert("") +// Integer batchAdd(@Param("breachRecords")List breachRecords); + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/HistoryOrdersServeSyncMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/HistoryOrdersServeSyncMapper.java new file mode 100644 index 0000000..8b3f59d --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/HistoryOrdersServeSyncMapper.java @@ -0,0 +1,21 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.HistoryOrdersServeSync; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Select; + +import java.time.LocalDateTime; + +/** + *

+ * 服务任务 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-09-14 + */ +public interface HistoryOrdersServeSyncMapper extends BaseMapper { + + @Select("select max(sort_time) from history_orders_sync") + LocalDateTime queryMaxSortTime(); +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/HistoryOrdersSyncMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/HistoryOrdersSyncMapper.java new file mode 100644 index 0000000..e16369e --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/HistoryOrdersSyncMapper.java @@ -0,0 +1,21 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.HistoryOrdersSync; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Select; + +import java.time.LocalDateTime; + +/** + *

+ * 历史订单完成15天后同步到历史订单同步表中,通过canal同步到历史订单库中;1天后删除(删除条件当天数据和历史订单库中的订单数据数量一致) Mapper 接口 + *

+ * + * @author itcast + * @since 2023-09-13 + */ +public interface HistoryOrdersSyncMapper extends BaseMapper { + + @Select("select max(sort_time) from history_orders_sync") + LocalDateTime queryMaxSortTime(); +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersCanceledMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersCanceledMapper.java new file mode 100644 index 0000000..5a3390f --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersCanceledMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.OrdersCanceled; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author itcast + * @since 2023-08-19 + */ +public interface OrdersCanceledMapper extends BaseMapper { + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersDispatchMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersDispatchMapper.java new file mode 100644 index 0000000..779e9aa --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersDispatchMapper.java @@ -0,0 +1,27 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.OrdersDispatch; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 派单池 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-08-08 + */ +public interface OrdersDispatchMapper extends BaseMapper { + +// @Insert("") +// Integer batchAdd(@Param("records")List ordersDispatches); + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersMapper.java new file mode 100644 index 0000000..b1de8d7 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersMapper.java @@ -0,0 +1,22 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +import java.time.LocalDateTime; + +/** + *

+ * 订单表 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +public interface OrdersMapper extends BaseMapper { + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersRefundMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersRefundMapper.java new file mode 100644 index 0000000..da50b0b --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersRefundMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.OrdersRefund; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单退款表 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-09-07 + */ +public interface OrdersRefundMapper extends BaseMapper { + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersSeizeMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersSeizeMapper.java new file mode 100644 index 0000000..7b0fd7e --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersSeizeMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.OrdersSeize; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 抢单池 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-08-15 + */ +public interface OrdersSeizeMapper extends BaseMapper { + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersServeMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersServeMapper.java new file mode 100644 index 0000000..68bbb5a --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/OrdersServeMapper.java @@ -0,0 +1,26 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.OrdersServe; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 服务任务 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +public interface OrdersServeMapper extends BaseMapper { + + /** + * 物理删除服务单 + * @param id 服务单id + * @param serveProviderId 服务人员或机构id + * @return 删除数量 + */ +// @Delete("delete from orders_serve where id=#{id} and serve_provider_id=#{serveProviderId}") +// Integer deleteByIdAndServeProviderId(@Param("id") Long id, @Param("serveProviderId") Long serveProviderId); +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/ServeProviderSyncMapper.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/ServeProviderSyncMapper.java new file mode 100644 index 0000000..b7d66eb --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/mapper/ServeProviderSyncMapper.java @@ -0,0 +1,21 @@ +package com.jzo2o.orders.base.mapper; + +import com.jzo2o.orders.base.model.domain.ServeProviderSync; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + *

+ * 机构服务端更新服务时间 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-08-09 + */ +public interface ServeProviderSyncMapper extends BaseMapper { + +// @Update("update serve_provider_sync set serve_times=JSON_ARRAY_APPEND(serve_times,'$',#{serveTime})," + +// "acceptance_num=acceptance_num+1 where id=#{id}") +// int addServeTimes(@Param("id")Long id, @Param("serveTime") Integer serveTime); +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/BreachRecord.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/BreachRecord.java new file mode 100644 index 0000000..9c52b73 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/BreachRecord.java @@ -0,0 +1,95 @@ +package com.jzo2o.orders.base.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 违约记录 + *

+ * + * @author itcast + * @since 2023-08-06 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("breach_record") +public class BreachRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 违约id + */ + @TableId(value = "id", type = IdType.NONE) + private Long id; + + /** + * 违约机构或师傅 + */ + private Long serveProviderId; + + /** + * 类型,2:师傅、3:机构 + */ + private Integer serveProviderType; + + /** + * 行为类型,1:待分配时取消,2:待服务时取消,3:服务中取消,4:派单拒绝,5:派单超时 + */ + private Integer behaviorType; + + /** + * 违约原因 + */ + private String breachReason; + + /** + * 服务项名称 + */ + private String serveItemName; + + /** + * 服务地址 + */ + private String serveAddress; + + /** + * 被服务人 + */ + private Long servedUserId; + + /** + * 被服务人员手机号,脱敏 + */ + private String servedPhone; + + /** + * 违约时间 + */ + private LocalDateTime breachTime; + + /** + * 违约日,格式例如20200512,2020年5月12日 + */ + private Integer breachDay; + + /** + * 违约单订单id + */ + private Long ordersId; + + /** + * 服务单id + */ + private Long ordersServeId; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/CurrentServeProviderTime.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/CurrentServeProviderTime.java new file mode 100644 index 0000000..3088dfd --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/CurrentServeProviderTime.java @@ -0,0 +1,38 @@ +package com.jzo2o.orders.base.model.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 机构服务端更新服务时间 + *

+ * + * @author itcast + * @since 2023-08-08 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName(value = "current_serve_provider_time",autoResultMap = true) +public class CurrentServeProviderTime implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.NONE) + private Long id; + + @TableField(typeHandler = JacksonTypeHandler.class) + private List serveTimes; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/HistoryOrdersServeSync.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/HistoryOrdersServeSync.java new file mode 100644 index 0000000..d692a88 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/HistoryOrdersServeSync.java @@ -0,0 +1,222 @@ +package com.jzo2o.orders.base.model.domain; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 服务任务 + *

+ * + * @author itcast + * @since 2023-09-14 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName(value = "history_orders_serve_sync",autoResultMap = true) +public class HistoryOrdersServeSync implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 服务单id,和 + */ + @TableId(value = "id", type = IdType.NONE) + private Long id; + + /** + * 服务人员或服务机构id + */ + private Long serveProviderId; + + /** + * 服务者类型,2:服务端服务,3:机构端服务 + */ + private Integer serveProviderType; + + /** + * 机构服务人员id + */ + private Long institutionStaffId; + + /** + * 机构工作人员姓名 + */ + private String institutionStaffName; + /** + * 机构名称 + */ + private String institutionName; + + /** + * 订单来源类型,1:抢单,2:派单 + */ + private Integer ordersOriginType; + + /** + * 客户姓名 + */ + private String contactsName; + + /** + * 客户电话 + */ + private String contactsPhone; + + /** + * 服务地址 + */ + private String serveAddress; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 服务分类id + */ + private Long serveTypeId; + + /** + * 服务分裂名称 + */ + private String serveTypeName; + + /** + * 预约时间 + */ + private LocalDateTime serveStartTime; + + /** + * 服务项名称 + */ + private String serveItemName; + + /** + * 服务项id + */ + private Long serveItemId; + + /** + * 服务图片 + */ + private String serveItemImg; + + /** + * 服务单状态,3:服务完成,4:订单关闭 + */ + private Integer serveStatus; + + /** + * 服务人姓名 + */ + private String serveProviderStaffName; + + /** + * 服务人手机号 + */ + private String serveProviderStaffPhone; + + /** + * 取消人姓名 + */ + private String cancelerName; + /** + * 取消/被退单时间 + */ + private LocalDateTime cancelTime; + + /** + * 取消/被退单原因 + */ + private String cancelReason; + + /** + * 实际服务开始时间 + */ + private LocalDateTime realServeStartTime; + + /** + * 实际服务完结时间 + */ + private LocalDateTime realServeEndTime; + + /** + * 服务前照片 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List serveBeforeImgs; + + /** + * 服务后照片 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List serveAfterImgs; + + /** + * 服务前说明 + */ + private String serveBeforeIllustrate; + + /** + * 服务后说明 + */ + private String serveAfterIllustrate; + + /** + * 订单金额 + */ + private BigDecimal ordersAmount; + + /** + * 服务数量 + */ + private Integer serveNum; + + /** + * 服务单位 + */ + private Integer unit; + + /** + * 服务端/机构端是否展示,1:展示,0:隐藏 + */ + private Integer display; + + /** + * 是否是逻辑删除 + */ + private Integer isDeleted; + + /** + * 更新人 + */ + private Long updateBy; + + /** + * 排序时间(15天后数据无法再次修改,并迁移到历史订单中) + */ + private LocalDateTime sortTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/HistoryOrdersSync.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/HistoryOrdersSync.java new file mode 100644 index 0000000..274a0ae --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/HistoryOrdersSync.java @@ -0,0 +1,301 @@ +package com.jzo2o.orders.base.model.domain; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 历史订单完成15天后同步到历史订单同步表中,通过canal同步到历史订单库中;1天后删除(删除条件当天数据和历史订单库中的订单数据数量一致) + *

+ * + * @author itcast + * @since 2023-09-13 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName(value = "history_orders_sync",autoResultMap = true) +public class HistoryOrdersSync implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.NONE) + private Long id; + + /** + * 订单所属人 + */ + private Long userId; + + /** + * 服务类型id + */ + private Long serveTypeId; + + /** + * 服务人 + */ + private Long serveProviderId; + + /** + * 服务人类型,2:服务人员,3:机构 + */ + private Integer serveProviderType; + + /** + * 服务项id + */ + private Long serveItemId; + + /** + * 服务id + */ + private Long serveId; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 服务类型名称 + */ + private String serveTypeName; + + /** + * 服务项名称 + */ + private String serveItemName; + + /** + * 服务项图片 + */ + private String serveItemImg; + + /** + * 服务单位 + */ + private Integer unit; + + /** + * 订单状态,500:订单完成,600:已取消,700:已关闭 + */ + private Integer ordersStatus; + + /** + * 支付状态,1:支付成功,2:已关闭 + */ + private Integer payStatus; + + + /** + * 退款,0:发起退款,1:退款中,2:退款成功 3:退款失败 + */ + private Integer refundStatus; + + /** + * 订单完成时间 + */ + private LocalDateTime tradeFinishTime; + + /** + * 支付渠道,ALI_PAY:支付宝,WECHAT_PAY:微信 + */ + private String tradingChannel; + + /** + * 支付流水 + */ + private String thirdOrderId; + + /** + * 派单时间 + */ + private LocalDateTime dispatchTime; + + /** + * 单价 + */ + private BigDecimal price; + + /** + * 购买数量 + */ + private Integer purNum; + + /** + * 订单总金额 + */ + private BigDecimal totalAmount; + + /** + * 实际支付金额 + */ + private BigDecimal realPayAmount; + + /** + * 退款流水 + */ + private String thirdRefundOrderId; + + /** + * 取消人姓名 + */ + private String cancelerName; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 服务详细地址 + */ + private String serveAddress; + + /** + * 联系人手机号 + */ + private String contactsPhone; + + /** + * 联系人姓名 + */ + private String contactsName; + + /** + * 服务人姓名 + */ + private String serveProviderStaffName; + + /** + * 服务人手机号 + */ + private String serveProviderStaffPhone; + + /** + * 机构名称 + */ + private String institutionName; + + /** + * 机构电话 + */ + private String institutionPhone; + + /** + * 下单时间 + */ + private LocalDateTime placeOrderTime; + + /** + * 服务开始时间 + */ + private LocalDateTime serveStartTime; + + /** + * 实际服务开始时间 + */ + private LocalDateTime realServeStartTime; + + /** + * 实际服务结束时间 + */ + private LocalDateTime realServeEndTime; + + /** + * 服务开始图片 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List serveBeforeImgs; + + /** + * 服务开始说明 + */ + private String serveBeforeIllustrate; + + /** + * 服务完成图片 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List serveAfterImgs; + + /** + * 服务完成说明 + */ + private String serveAfterIllustrate; + + /** + * 支付超时时间,该时间只对待支付有意义 + */ + private LocalDateTime paymentTimeout; + + /** + * 经度 + */ + private Double lon; + + /** + * 纬度 + */ + private Double lat; + + /** + * 支付时间 + */ + private LocalDateTime payTime; + + /** + * 取消/被退单时间 + */ + private LocalDateTime cancelTime; + + /** + * 取消/被退单原因 + */ + private String cancelReason; + + /** + * 下单年份,格式:yyyy + */ + private Integer year; + + /** + * 下单月份,格式:yyyyMM + */ + private Integer month; + + /** + * 下单所在日,格式:yyyyMMdd + */ + private Integer day; + + /** + * 下单所在小时,格式:yyyyMMddHH + */ + private Integer hour; + + /** + * 排序时间字段(15天后数据无法再次修改,并迁移到历史订单中) + */ + private LocalDateTime sortTime; + + private LocalDateTime updateTime; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/Orders.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/Orders.java new file mode 100644 index 0000000..56acf39 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/Orders.java @@ -0,0 +1,201 @@ +package com.jzo2o.orders.base.model.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 订单表 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("orders") +public class Orders implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.NONE) + private Long id; + + /** + * 订单所属人 + */ + private Long userId; + + /** + * 服务类型id + */ + private Long serveTypeId; + + /** + * 服务类型名称 + */ + private String serveTypeName; + + /** + * 服务项id + */ + private Long serveItemId; + + /** + * 服务项名称 + */ + private String serveItemName; + + /** + * 服务项图片 + */ + private String serveItemImg; + + /** + * 服务单位 + */ + private Integer unit; + + /** + * 服务id + */ + private Long serveId; + + /** + * 订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:已取消,700:已关闭 + */ + private Integer ordersStatus; + + /** + * 交易状态,0:待支付,1:支付成功 + */ + private Integer payStatus; + + /** + * 退款,0:发起退款,1:退款中,2:退款成功 3:退款失败 + */ + private Integer refundStatus; + + /** + * 单价 + */ + private BigDecimal price; + + /** + * 购买数量 + */ + private Integer purNum; + + /** + * 订单总金额 + */ + private BigDecimal totalAmount; + + /** + * 实际支付金额 + */ + private BigDecimal realPayAmount; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 服务详细地址 + */ + private String serveAddress; + + /** + * 联系人手机号 + */ + private String contactsPhone; + + /** + * 联系人姓名 + */ + private String contactsName; + + /** + * 服务开始时间 + */ + private LocalDateTime serveStartTime; + + /** + * 经度 + */ + private Double lon; + + /** + * 纬度 + */ + private Double lat; + + /** + * 支付时间 + */ + private LocalDateTime payTime; + + /** + * 评价时间 + */ + private LocalDateTime evaluationTime; + + /** + * 用户端是否展示,1:展示,0:隐藏 + */ + private Integer display; + + /** + * 排序字段(serve_start_time秒级时间戳+订单id后6位) + */ + private Long sortBy; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; + + /** + * 支付服务交易单号 + */ + private Long tradingOrderNo; + + /** + * 第三方支付的交易号 + */ + private String transactionId; + + /** + * 支付服务退款单号 + */ + private Long refundNo; + + /** + * 第三方支付的退款单号 + */ + private String refundId; + + /** + * 支付渠道 + */ + private String tradingChannel; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersCanceled.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersCanceled.java new file mode 100644 index 0000000..bd7a5f4 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersCanceled.java @@ -0,0 +1,68 @@ +package com.jzo2o.orders.base.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-08-19 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("orders_canceled") +public class OrdersCanceled implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 取消人 + */ + private Long cancellerId; + + /** + * 取消人名称 + */ + private String cancelerName; + + /** + * 取消人类型,1:普通用户,4:运营人员 + */ + private Integer cancellerType; + + /** + * 取消原因 + */ + private String cancelReason; + + /** + * 取消时间 + */ + private LocalDateTime cancelTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersDispatch.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersDispatch.java new file mode 100644 index 0000000..d0ad400 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersDispatch.java @@ -0,0 +1,114 @@ +package com.jzo2o.orders.base.model.domain; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; + +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 派单池 + *

+ * + * @author itcast + * @since 2023-08-08 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("orders_dispatch") +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class OrdersDispatch implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.NONE) + private Long id; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 服务分类id + */ + private Long serveTypeId; + + /** + * 服务名称 + */ + private String serveItemName; + + /** + * 服务分类名称 + */ + private String serveTypeName; + + /** + * 服务项id + */ + private Long serveItemId; + + /** + * 服务地址 + */ + private String serveAddress; + + /** + * 服务项目图片 + */ + private String serveItemImg; + + /** + * 订单金额 + */ + private BigDecimal ordersAmount; + + /** + * 服务开始时间 + */ + private LocalDateTime serveStartTime; + + /** + * 经度 + */ + private Double lon; + + /** + * 纬度 + */ + private Double lat; + + /** + * 服务数量 + */ + private Integer purNum; + + /** + * 是否转人工 + */ + private Integer isTransferManual; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersRefund.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersRefund.java new file mode 100644 index 0000000..b1fbb73 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersRefund.java @@ -0,0 +1,51 @@ +package com.jzo2o.orders.base.model.domain; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 订单退款表 + *

+ * + * @author itcast + * @since 2023-09-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("orders_refund") +public class OrdersRefund implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 支付服务交易单号 + */ + private Long tradingOrderNo; + + /** + * 实付金额 + */ + private BigDecimal realPayAmount; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersSeize.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersSeize.java new file mode 100644 index 0000000..63c5d32 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersSeize.java @@ -0,0 +1,122 @@ +package com.jzo2o.orders.base.model.domain; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; + +import lombok.*; +import lombok.experimental.Accessors; + +/** + *

+ * 抢单池 + *

+ * + * @author itcast + * @since 2023-08-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrdersSeize implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.NONE) + private Long id; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 服务分类id + */ + private Long serveTypeId; + + /** + * 服务名称 + */ + private String serveItemName; + + /** + * 服务分类名称 + */ + private String serveTypeName; + + /** + * 服务项id + */ + private Long serveItemId; + + /** + * 服务地址 + */ + private String serveAddress; + + /** + * 服务项目图片 + */ + private String serveItemImg; + + /** + * 订单总金额 + */ + private BigDecimal ordersAmount; + + /** + * 服务开始时间 + */ + private LocalDateTime serveStartTime; + + /** + * 订单支付成功时间,用于计算是否进入派单 + */ + private LocalDateTime paySuccessTime; + + /** + * 经度 + */ + private Double lon; + + /** + * 纬度 + */ + private Double lat; + + /** + * 服务数量 + */ + private Integer purNum; + + /** + * 抢单是否超时 + */ + private Integer isTimeOut; + + /** + * 抢单列表排序字段 + */ + private Long sortBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersServe.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersServe.java new file mode 100644 index 0000000..596f1ff --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersServe.java @@ -0,0 +1,178 @@ +package com.jzo2o.orders.base.model.domain; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableField; +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 服务任务 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName(value = "orders_serve",autoResultMap = true) +public class OrdersServe implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 任务id + */ + @TableId(value = "id", type = IdType.NONE) + private Long id; + + /** + * 属于哪个用户 + */ + private Long userId; + + /** + * 服务人员或服务机构id + */ + private Long serveProviderId; + + /** + * 服务者类型,2:服务端服务,3:机构端服务 + */ + private Integer serveProviderType; + + /** + * 机构服务人员id + */ + private Long institutionStaffId; + + /** + * 订单id + */ + private Long ordersId; + + /** + * 订单来源类型,1:抢单,2:派单 + */ + private Integer ordersOriginType; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 服务分类id + */ + private Long serveTypeId; + + /** + * 预约时间 + */ + private LocalDateTime serveStartTime; + + /** + * 服务项id + */ + private Long serveItemId; + + /** + * 服务图片地址 + */ + private String serveItemImg; + + /** + * 任务状态 + */ + private Integer serveStatus; + + /** + * 结算状态,0:不可结算,1:待结算,2:结算完成 + */ + private Integer settlementStatus; + + /** + * 实际服务开始时间 + */ + private LocalDateTime realServeStartTime; + + /** + * 实际服务完结时间 + */ + private LocalDateTime realServeEndTime; + + /** + * 服务前照片 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List serveBeforeImgs; + + /** + * 服务后照片 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List serveAfterImgs; + + /** + * 服务前说明 + */ + private String serveBeforeIllustrate; + + /** + * 服务后说明 + */ + private String serveAfterIllustrate; + + /** + * 取消时间,可以是退单,可以是取消时间 + */ + private LocalDateTime cancelTime; + + /** + * 订单金额 + */ + private BigDecimal ordersAmount; + + /** + * 购买数量 + */ + private Integer purNum; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 排序字段(serve_start_time(秒级时间戳)+订单id(后6位)) + */ + private Long sortBy; + + /** + * 服务端/机构端是否展示,1:展示,0:隐藏 + */ + private Integer display; + + + /** + * 更新人 + */ + private Long updateBy; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/ServeProviderInfo.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/ServeProviderInfo.java new file mode 100644 index 0000000..28d0c33 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/ServeProviderInfo.java @@ -0,0 +1,71 @@ +package com.jzo2o.orders.base.model.domain; + +import com.jzo2o.common.model.Location; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; + +import java.util.List; + +@Data +public class ServeProviderInfo { + /** + * 服务人员或机构同步表 + */ + private Long id; + + /** + * 类型,2:服务人员,3:机构 + */ + private Integer serveProviderType; + + /** + * 技能列表 + */ + private List serveItemIds; + + /** + * 经纬度 + */ + private Location location; + + /** + * 城市编码 + */ + private String cityCode; + +// /** +// * 接单距离 +// */ +// private Double receiveDistance; + + /** + * 接单开关1,:接单开启,0:接单关闭 + */ + private Integer pickUp; + + /** + * 评分,默认50分 + */ + private Double evaluationScore; + + /** + * 服务时间 + */ + private List serveTimes; + + /** + * 首次设置状态,0:未完成,1:已完成设置 + */ + private Integer settingStatus; + + /** + * 接单数 + */ + private Integer acceptanceNum; + + /** + * 状态,0:正常,1:冻结 + */ + private Integer status; +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/ServeProviderSync.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/ServeProviderSync.java new file mode 100644 index 0000000..766bb69 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/ServeProviderSync.java @@ -0,0 +1,48 @@ +package com.jzo2o.orders.base.model.domain; + +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 机构服务端更新服务时间 + *

+ * + * @author itcast + * @since 2023-08-09 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName(value = "serve_provider_sync",autoResultMap = true) +public class ServeProviderSync implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.NONE) + private Long id; + + /** + * 服务时间段 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List serveTimes; + + /** + * 接单数 + */ + private Integer acceptanceNum; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderSnapshotDTO.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderSnapshotDTO.java new file mode 100644 index 0000000..62409bb --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderSnapshotDTO.java @@ -0,0 +1,247 @@ +package com.jzo2o.orders.base.model.dto; + +//import com.jzo2o.statemachine.core.StateMachineSnapshot; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 订单快照 + * + * @author itcast + * @create 2023/8/19 10:30 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrderSnapshotDTO { + /** + * 订单id + */ + private Long id; + + /** + * 订单所属人 + */ + private Long userId; + + /** + * 服务类型id + */ + private Long serveTypeId; + + /** + * 服务类型名称 + */ + private String serveTypeName; + + /** + * 服务项id + */ + private Long serveItemId; + + /** + * 服务项名称 + */ + private String serveItemName; + + /** + * 服务项图片 + */ + private String serveItemImg; + + /** + * 服务单位 + */ + private Integer unit; + + /** + * 服务id + */ + private Long serveId; + + /** + * 订单状态,0:待支付,100:派单中,200:待服务,300:服务中,500:订单完成,600:订单取消,700已关闭 + */ + private Integer ordersStatus; + + /** + * 支付状态,2:待支付,4:支付成功 + */ + private Integer payStatus; + + /** + * 退款,0:发起退款,1:退款中,2:退款成功 3:退款失败 + */ + private Integer refundStatus; + + /** + * 单价 + */ + private BigDecimal price; + + /** + * 购买数量 + */ + private Integer purNum; + + /** + * 订单总金额 + */ + private BigDecimal totalAmount; + + /** + * 实际支付金额 + */ + private BigDecimal realPayAmount; + + /** + * 优惠金额 + */ + private BigDecimal discountAmount; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 服务详细地址 + */ + private String serveAddress; + + /** + * 联系人手机号 + */ + private String contactsPhone; + + /** + * 联系人姓名 + */ + private String contactsName; + + /** + * 服务开始时间 + */ + private LocalDateTime serveStartTime; + + /** + * 经度 + */ + private String lon; + + /** + * 纬度 + */ + private String lat; + + /** + * 支付时间 + */ + private LocalDateTime payTime; + + /** + * 评价时间 + */ + private LocalDateTime evaluationTime; + + /** + * 订单创建时间 + */ + private LocalDateTime createTime; + + /** + * 订单更新时间 + */ + private LocalDateTime updateTime; + + /** + * 支付服务交易单号 + */ + private Long tradingOrderNo; + + /** + * 支付服务退款单号 + */ + private Long refundNo; + + + + /** + * 支付渠道【支付宝、微信、现金、免单挂账】 + */ + private String tradingChannel; + + + /** + * 三方流水,微信支付订单号或支付宝订单号 + */ + private String thirdOrderId; + + /** + * 退款三方流水,微信支付订单号或支付宝订单号 + */ + private String thirdRefundOrderId; + + + /** + * 取消人id + */ + private Long cancellerId; + + /** + * 取消人名称 + */ + private String cancelerName; + + /** + * 取消人类型 + */ + private Integer cancellerType; + + /** + * 取消时间 + */ + private LocalDateTime cancelTime; + + /** + * 取消原因 + */ + private String cancelReason; + + /** + * 实际服务完成时间 + */ + private LocalDateTime realServeEndTime; + + /** + * 评价状态 + */ + private Integer evaluationStatus; + + +// @Override +// public String getSnapshotId() { +// return String.valueOf(id); +// } +// +// @Override +// public Integer getSnapshotStatus() { +// return ordersStatus; +// } +// +// @Override +// public void setSnapshotId(String snapshotId) { +// this.id = Long.parseLong(snapshotId); +// } +// +// @Override +// public void setSnapshotStatus(Integer snapshotStatus) { +// this.ordersStatus = snapshotStatus; +// } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderUpdateStatusDTO.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderUpdateStatusDTO.java new file mode 100644 index 0000000..be60f36 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderUpdateStatusDTO.java @@ -0,0 +1,73 @@ +package com.jzo2o.orders.base.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class OrderUpdateStatusDTO { + /** + * 订单id + */ + private Long id; + + /** + * 原订单状态 + */ + private Integer originStatus; + + /** + * 目标订单状态 + */ + private Integer targetStatus; + + /** + * 支付状态 + */ + private Integer payStatus; + /** + * 退款状态 + */ + private Integer refundStatus; + + /** + * 支付时间 + */ + private LocalDateTime payTime; + + /** + * 评价时间 + */ + private LocalDateTime evaluationTime; + + /** + * 支付服务交易单号 + */ + private Long tradingOrderNo; + + /** + * 第三方支付的交易号 + */ + private String transactionId; + + /** + * 支付渠道 + */ + private String tradingChannel; + + /** + * 实际服务完成时间 + */ + private LocalDateTime realServeEndTime; + + /** + * 评价状态 + */ + private Integer evaluationStatus; +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/properties/DispatchProperties.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/properties/DispatchProperties.java new file mode 100644 index 0000000..bcb2643 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/properties/DispatchProperties.java @@ -0,0 +1,32 @@ +package com.jzo2o.orders.base.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 派单配置 + */ +@Configuration +@ConfigurationProperties(prefix = "orders.dispatch") +@Data +public class DispatchProperties { + /** + * 机构端展示抢单列表数量 + */ + public Integer seizeListDispalyNumOfInstitution = 50; + /** + * 服务端展示抢单列表数量 + */ + public Integer seizeListDispalyNumOfServe = 20; + + /** + * 机构端拥有服务单数量 + */ + public Integer serveTaskNumOrInstitution = 50; + + /** + * 服务人员最大拥有服务数量 + */ + public Integer serveTaskNumOfServe = 10; +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/properties/ExecutorProperties.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/properties/ExecutorProperties.java new file mode 100644 index 0000000..6d8cd36 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/properties/ExecutorProperties.java @@ -0,0 +1,61 @@ +package com.jzo2o.orders.base.properties; + +import com.jzo2o.common.utils.ObjectUtils; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; + +@Configuration +@ConfigurationProperties(prefix = "executor") +@Data +public class ExecutorProperties { + + /** + * 线程池配置 + */ + @NestedConfigurationProperty + private Map pools = new HashMap<>(); + + /** + * 线程池配置 + */ + @Data + public static class ThreadPool { + /** + * 核心线程数 默认15 + */ + private Integer corePoolSize = 15; + + /** + * 最大线程数 默认30 + */ + private Integer maxPoolSize = 30; + + /** + * 队列大小默认 5000 + */ + private Integer queueCapacity = 5000; + + /** + * 线程名称,默认orders- + */ + private String threadNamePrefix = "orders-"; + } + + /** + * 线程池名称 + * + * @param name + * @return + */ + public final ThreadPool get(String name) { + ThreadPool threadPool = pools.get(name); + return ObjectUtils.isNull(threadPool) ? new ThreadPool() : threadPool; + } + + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersCommonService.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersCommonService.java new file mode 100644 index 0000000..c35345b --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersCommonService.java @@ -0,0 +1,18 @@ +package com.jzo2o.orders.base.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; + +/** + *

+ * 订单表 服务类 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +public interface IOrdersCommonService extends IService { + + Integer updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO); +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersDiversionCommonService.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersDiversionCommonService.java new file mode 100644 index 0000000..530e34f --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersDiversionCommonService.java @@ -0,0 +1,17 @@ +package com.jzo2o.orders.base.service; + +import com.jzo2o.orders.base.model.domain.Orders; + +/** + * 订单分流 + */ +public interface IOrdersDiversionCommonService { + + /** + * 订单分流,所有订单均可抢单 + * + * @param orders + */ + void diversion(Orders orders); + +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java new file mode 100644 index 0000000..72c781c --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java @@ -0,0 +1,40 @@ +package com.jzo2o.orders.base.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.orders.base.mapper.OrdersMapper; +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; +import com.jzo2o.orders.base.service.IOrdersCommonService; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单表 服务实现类 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +@Service +public class OrdersCommonServiceImpl extends ServiceImpl implements IOrdersCommonService { + @Override + public Integer updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO) { + LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate() + .eq(Orders::getId, orderUpdateStatusReqDTO.getId()) + .gt(Orders::getUserId, 0) + .eq(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getOriginStatus()),Orders::getOrdersStatus,orderUpdateStatusReqDTO.getOriginStatus()) + .set(Orders::getOrdersStatus, orderUpdateStatusReqDTO.getTargetStatus()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getPayStatus()),Orders::getPayStatus,orderUpdateStatusReqDTO.getPayStatus()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getPayTime()),Orders::getPayTime,orderUpdateStatusReqDTO.getPayTime()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getEvaluationTime()),Orders::getEvaluationTime,orderUpdateStatusReqDTO.getEvaluationTime()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingOrderNo()),Orders::getTradingOrderNo,orderUpdateStatusReqDTO.getTradingOrderNo()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTransactionId()),Orders::getTransactionId,orderUpdateStatusReqDTO.getTransactionId()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingChannel()),Orders::getTradingChannel,orderUpdateStatusReqDTO.getTradingChannel()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getRefundStatus()),Orders::getRefundStatus,orderUpdateStatusReqDTO.getRefundStatus()); + boolean update = super.update(updateWrapper); + return update?1:0; + } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersDiversionCommonServiceImpl.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersDiversionCommonServiceImpl.java new file mode 100644 index 0000000..ea0d566 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersDiversionCommonServiceImpl.java @@ -0,0 +1,119 @@ +//package com.jzo2o.orders.base.service.impl; +// +//import com.jzo2o.api.foundations.RegionApi; +//import com.jzo2o.api.foundations.ServeApi; +//import com.jzo2o.api.foundations.dto.response.ConfigRegionInnerResDTO; +//import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; +//import com.jzo2o.common.utils.BooleanUtils; +//import com.jzo2o.common.utils.DateUtils; +//import com.jzo2o.common.utils.ObjectUtils; +//import com.jzo2o.orders.base.mapper.OrdersDispatchMapper; +//import com.jzo2o.orders.base.mapper.OrdersSeizeMapper; +//import com.jzo2o.orders.base.model.domain.Orders; +//import com.jzo2o.orders.base.model.domain.OrdersDispatch; +//import com.jzo2o.orders.base.model.domain.OrdersSeize; +//import com.jzo2o.orders.base.service.IOrdersDiversionCommonService; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.data.redis.core.RedisTemplate; +//import org.springframework.stereotype.Service; +//import org.springframework.transaction.annotation.Transactional; +// +//import javax.annotation.Resource; +//import java.time.Duration; +// +//@Service +//@Slf4j +//public class OrdersDiversionCommonServiceImpl implements IOrdersDiversionCommonService { +// +// +// @Resource +// private RedisTemplate redisTemplate; +// +// @Resource +// private RegionApi regionApi; +// +// @Resource +// private ServeApi serveApi; +// +// @Resource +// private OrdersDiversionCommonServiceImpl owner; +// +// @Resource +// private OrdersSeizeMapper ordersSeizeMapper; +// @Resource +// private OrdersDispatchMapper ordersDispatchMapper; +// +// @Override +// public void diversion(Orders orders) { +// log.debug("订单分流,id:{}",orders.getId()); +// // 1.当前时间已超过服务预约时间则不再分流 +// if (orders.getServeStartTime().compareTo(DateUtils.now()) < 0) { +// log.debug("订单{}当前时间已超过服务预约时间则不再分流",orders.getId()); +// return; +// } +// ConfigRegionInnerResDTO configRegion = regionApi.findConfigRegionByCityCode(orders.getCityCode()); +// ServeAggregationResDTO serveAggregationResDTO = serveApi.findById(orders.getServeId()); +// //订单分流数据存储 +// owner.diversionCommit(orders,configRegion,serveAggregationResDTO); +// } +// +// @Transactional(rollbackFor = Exception.class) +// public void diversionCommit(Orders orders, ConfigRegionInnerResDTO configRegion, ServeAggregationResDTO serveAggregationResDTO) { +// //流间隔(单位分钟),即当前时间与服务预计开始时间的间隔 +// Integer diversionInterval = configRegion.getDiversionInterval(); +// +// //当前时间与服务预约时间的间隔 +// Duration between = DateUtils.between(DateUtils.now(), orders.getServeStartTime()); +// //服务类型名称 +// String serveTypeName = ObjectUtils.get(serveAggregationResDTO, ServeAggregationResDTO::getServeTypeName); +// //服务类型id +// Long serveTypeId = ObjectUtils.get(serveAggregationResDTO, ServeAggregationResDTO::getServeTypeId); +// //服务项名称 +// String serveItemName = ObjectUtils.get(serveAggregationResDTO, ServeAggregationResDTO::getServeItemName); +// //服务项图片 +// String serveItemImg = ObjectUtils.get(serveAggregationResDTO, ServeAggregationResDTO::getServeItemImg); +// //用于排序,服务预约时间戳加订单号后5位 +// long sortBy = DateUtils.toEpochMilli(orders.getServeStartTime()) + orders.getId() % 100000; +// OrdersSeize ordersSeize = OrdersSeize.builder() +// .id(orders.getId()) +// .ordersAmount(orders.getRealPayAmount()) +// .cityCode(orders.getCityCode()) +// .serveTypeId(serveTypeId) +// .serveTypeName(serveTypeName) +// .serveItemId(orders.getServeItemId()) +// .serveItemName(serveItemName) +// .serveItemImg(serveItemImg) +// .ordersAmount(orders.getRealPayAmount()) +// .serveStartTime(orders.getServeStartTime()) +// .serveAddress(orders.getServeAddress()) +// .lon(orders.getLon()) +// .lat(orders.getLat()) +// .paySuccessTime(DateUtils.now()) +// .paySuccessTime(orders.getPayTime()) +// .sortBy(sortBy) +// .isTimeOut(BooleanUtils.toInt(between.toMinutes() < diversionInterval)) +// .purNum(orders.getPurNum()).build(); +// ordersSeizeMapper.insert(ordersSeize); +// //当前时间与服务预约时间的间隔 小于指定间隔则插入派单表 +// if (between.toMinutes() < diversionInterval) { +// OrdersDispatch ordersDispatch = OrdersDispatch.builder() +// .id(orders.getId()) +// .ordersAmount(orders.getRealPayAmount()) +// .cityCode(orders.getCityCode()) +// .serveTypeId(serveTypeId) +// .serveTypeName(serveTypeName) +// .serveItemId(orders.getServeItemId()) +// .serveItemName(serveItemName) +// .serveItemImg(serveItemImg) +// .ordersAmount(orders.getRealPayAmount()) +// .serveStartTime(orders.getServeStartTime()) +// .serveAddress(orders.getServeAddress()) +// .lon(orders.getLon()) +// .lat(orders.getLat()) +// .purNum(orders.getPurNum()).build(); +// ordersDispatchMapper.insert(ordersDispatch); +// } +// } +// +// +//} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/utils/RedisUtils.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/utils/RedisUtils.java new file mode 100644 index 0000000..fa38e6c --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/utils/RedisUtils.java @@ -0,0 +1,16 @@ +package com.jzo2o.orders.base.utils; + +import com.jzo2o.common.utils.NumberUtils; + +public class RedisUtils { + + /** + * 获取城市编码最后以为数字 + * + * @param cityCode + * @return + */ + public static int getCityIndex(String cityCode) { + return NumberUtils.parseInt(cityCode) % 10; + } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/utils/ServeTimeUtils.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/utils/ServeTimeUtils.java new file mode 100644 index 0000000..46652a7 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/utils/ServeTimeUtils.java @@ -0,0 +1,24 @@ +package com.jzo2o.orders.base.utils; + +import com.jzo2o.common.utils.DateUtils; +import com.jzo2o.common.utils.NumberUtils; + +import java.time.LocalDateTime; + +public class ServeTimeUtils { + + /** + * 获取服务时间,用来处理抢单和派单的时间冲突问题 + * + * @param serveStartTime + * @return + */ + public static int getServeTimeInt(LocalDateTime serveStartTime) { + return NumberUtils.parseInt(DateUtils.format(serveStartTime, "yyyyMMddHH")); + } + + public static void main(String[] args) { + long number = 2023082400000000001L; + System.out.println(number % 10000000000L % 150000); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/META-INF/spring-configuration-metadata.json b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/META-INF/spring-configuration-metadata.json new file mode 100644 index 0000000..799a9c6 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/META-INF/spring-configuration-metadata.json @@ -0,0 +1,9 @@ +{ + "groups": [ + + ], + "properties": [ + + ], + "hints": [] +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/META-INF/spring.factories b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..c069af3 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.jzo2o.orders.base.config.AutoImportConfiguration \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/BreachRecordMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/BreachRecordMapper.xml new file mode 100644 index 0000000..2aac618 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/BreachRecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/HistoryOrdersServeSyncMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/HistoryOrdersServeSyncMapper.xml new file mode 100644 index 0000000..608f6f3 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/HistoryOrdersServeSyncMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/HistoryOrdersSyncMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/HistoryOrdersSyncMapper.xml new file mode 100644 index 0000000..d4886ef --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/HistoryOrdersSyncMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/IDispatchService.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/IDispatchService.xml new file mode 100644 index 0000000..4662a1b --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/IDispatchService.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/IHistoryOrdersSyncService.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/IHistoryOrdersSyncService.xml new file mode 100644 index 0000000..d6ea21e --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/IHistoryOrdersSyncService.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersCanceledMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersCanceledMapper.xml new file mode 100644 index 0000000..2c72a34 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersCanceledMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersDispatchMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersDispatchMapper.xml new file mode 100644 index 0000000..b8a672c --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersDispatchMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersMapper.xml new file mode 100644 index 0000000..e6bde84 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersRefundMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersRefundMapper.xml new file mode 100644 index 0000000..aa7032e --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersRefundMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersSeizeMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersSeizeMapper.xml new file mode 100644 index 0000000..7fc9199 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/OrdersSeizeMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/ServeProviderSyncMapper.xml b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/ServeProviderSyncMapper.xml new file mode 100644 index 0000000..c09a5ba --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/resources/mapper/ServeProviderSyncMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-oreders/jzo2o-orders-manager/Dockerfile b/jzo2o-oreders/jzo2o-orders-manager/Dockerfile new file mode 100644 index 0000000..bf35fbb --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/Dockerfile @@ -0,0 +1,8 @@ +FROM openjdk:11-jdk +LABEL maintainer="研究院研发组 " +RUN echo "Asia/Shanghai" > /etc/timezone +ARG PACKAGE_PATH=./target/jzo2o-orders-manager.jar + +ADD ${PACKAGE_PATH:-./} app.jar +EXPOSE 11504 +ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS app.jar"] \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/pom.xml b/jzo2o-oreders/jzo2o-orders-manager/pom.xml new file mode 100644 index 0000000..f931d9a --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/pom.xml @@ -0,0 +1,121 @@ + + + + jzo2o-oreders + com.jzo2o + 1.0-SNAPSHOT + + 4.0.0 + + jzo2o-orders-manager + + + 11 + 11 + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + org.springframework.cloud + spring-cloud-starter-bootstrap + + + com.jzo2o + jzo2o-mvc + + + + com.jzo2o + jzo2o-knife4j-web + + + + com.jzo2o + jzo2o-mysql + + + com.mysql + mysql-connector-j + + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.jzo2o + jzo2o-api + + + + com.jzo2o + jzo2o-redis + + + + mysql + mysql-connector-java + 8.0.19 + + + + com.jzo2o + jzo2o-orders-base + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + junit + junit + test + + + com.jzo2o + jzo2o-xxl-job + + + com.jzo2o + jzo2o-es + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + build-info + + + + + com.jzo2o.orders.manager.OrdersManagerApplication + + + + + \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/OrdersManagerApplication.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/OrdersManagerApplication.java new file mode 100644 index 0000000..e006be7 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/OrdersManagerApplication.java @@ -0,0 +1,23 @@ +package com.jzo2o.orders.manager; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * @author itcast + */ +@SpringBootApplication +@EnableAspectJAutoProxy +@Slf4j +@EnableTransactionManagement +public class OrdersManagerApplication { + public static void main(String[] args) { + new SpringApplicationBuilder(OrdersManagerApplication.class) + .build(args) + .run(args); + log.info("家政服务-订单管理微服务启动"); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/constants/EsIndex.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/constants/EsIndex.java new file mode 100644 index 0000000..eea8ec9 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/constants/EsIndex.java @@ -0,0 +1,5 @@ +package com.jzo2o.orders.manager.constants; + +public class EsIndex { + public static final String SERVE_PROVIDER_INFO = "serve_provider_info"; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/agency/AgencyOrdersServeController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/agency/AgencyOrdersServeController.java new file mode 100644 index 0000000..976b228 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/agency/AgencyOrdersServeController.java @@ -0,0 +1,23 @@ +package com.jzo2o.orders.manager.controller.agency; + +import com.jzo2o.common.model.PageResult; +import com.jzo2o.mvc.utils.UserContext; +import com.jzo2o.orders.manager.model.dto.request.*; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeDetailResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeStatusNumResDTO; +import com.jzo2o.orders.manager.service.IOrdersServeManagerService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +@RestController("orders-agency") +@Api(tags = "机构端-服务单相关接口") +@RequestMapping("/agency") +public class AgencyOrdersServeController { +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java new file mode 100644 index 0000000..fd2c70b --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java @@ -0,0 +1,56 @@ +package com.jzo2o.orders.manager.controller.consumer; + +import cn.hutool.core.bean.BeanUtil; +import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; +import com.jzo2o.api.orders.dto.request.OrderCancelReqDTO; +import com.jzo2o.api.orders.dto.response.OrderResDTO; +import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; +import com.jzo2o.common.model.CurrentUserInfo; +import com.jzo2o.mvc.utils.UserContext; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; +import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; +import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; +import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; +import com.jzo2o.orders.manager.service.IOrdersCreateService; +import com.jzo2o.orders.manager.service.IOrdersManagerService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author itcast + */ +@RestController("consumerOrdersController") +@Api(tags = "用户端-订单相关接口") +@RequestMapping("/consumer/orders") +public class ConsumerOrdersController { + + @Resource + private IOrdersManagerService ordersManagerService; + + + @GetMapping("/{id}") + @ApiOperation("根据订单id查询") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) + }) + public OrderResDTO detail(@PathVariable("id") Long id) { + return ordersManagerService.getDetail(id); + } + @GetMapping("/consumerQueryList") + @ApiOperation("订单滚动分页查询") + @ApiImplicitParams({ + @ApiImplicitParam(name = "ordersStatus", value = "订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:订单取消,700:已关闭", required = false, dataTypeClass = Integer.class), + @ApiImplicitParam(name = "sortBy", value = "排序字段", required = false, dataTypeClass = Long.class) + }) + public List consumerQueryList(@RequestParam(value = "ordersStatus", required = false) Integer ordersStatus, + @RequestParam(value = "sortBy", required = false) Long sortBy) { + return ordersManagerService.consumerQueryList(UserContext.currentUserId(), ordersStatus, sortBy); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersController.java new file mode 100644 index 0000000..b32f7ba --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersController.java @@ -0,0 +1,60 @@ +package com.jzo2o.orders.manager.controller.inner; + +import cn.hutool.core.bean.BeanUtil; +import com.jzo2o.api.orders.OrdersApi; +import com.jzo2o.api.orders.dto.response.OrderResDTO; +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.manager.service.IOrdersManagerService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author itcast + */ +@RestController +@Api(tags = "内部接口 - 订单相关接口") +@RequestMapping("/inner/orders") +public class InnerOrdersController implements OrdersApi { + + @Resource + private IOrdersManagerService ordersManagerService; + + + @Override + @GetMapping("/{id}") + @ApiOperation("根据订单id查询") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class), + }) + public OrderResDTO queryById(@PathVariable("id") Long id) { + Orders orders = ordersManagerService.queryById(id); + return BeanUtil.toBean(orders, OrderResDTO.class); + } + + @Override + @GetMapping("queryByIds") + @ApiOperation("根据订单id列表批量查询") + @ApiImplicitParams({ + @ApiImplicitParam(name = "ids", value = "订单id列表", required = true, dataTypeClass = Long.class), + }) + public List queryByIds(@RequestParam("ids") List ids) { + List ordersList = ordersManagerService.batchQuery(ids); + return BeanUtil.copyToList(ordersList, OrderResDTO.class); + } + + @Override + @PutMapping("evaluate/{id}") + @ApiOperation("根据订单id评价") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class), + }) + public void evaluate(@PathVariable("id") Long id) { + ordersManagerService.evaluationOrder(id); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersServeController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersServeController.java new file mode 100644 index 0000000..ffa7dbe --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersServeController.java @@ -0,0 +1,47 @@ +package com.jzo2o.orders.manager.controller.inner; + +import com.jzo2o.api.orders.OrdersServeApi; +//import com.jzo2o.api.orders.dto.response.InstitutionStaffServeCountResDTO; +import com.jzo2o.api.orders.dto.response.InstitutionStaffServeCountResDTO; +import com.jzo2o.api.orders.dto.response.ServeProviderIdResDTO; +import com.jzo2o.orders.base.model.domain.OrdersServe; +import com.jzo2o.orders.manager.service.IOrdersServeManagerService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +@RestController +@Api(tags = "内部接口 - 服务单相关接口") +@RequestMapping("/inner/orders-serve") +public class InnerOrdersServeController implements OrdersServeApi { + + @Resource + private IOrdersServeManagerService ordersServeManagerService; + + @Override + @GetMapping("/queryServeProviderIdByOrderId/{id}") + @ApiOperation("根据订单id查询服务人员/机构id") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class), + }) + public ServeProviderIdResDTO queryServeProviderIdByOrderId(@PathVariable("id") Long id) { + OrdersServe ordersServe = ordersServeManagerService.queryById(id); + return new ServeProviderIdResDTO(ordersServe.getServeProviderId()); + } + + @Override + @GetMapping("/countByInstitutionStaffId") + @ApiOperation("根据机构服务人员查询服务数量") + @ApiImplicitParams({ + @ApiImplicitParam(name = "institutionStaffId", value = "机构服务人员id", required = true, dataTypeClass = Long.class), + }) + public InstitutionStaffServeCountResDTO countByInstitutionStaffId(@RequestParam("institutionStaffId") Long institutionStaffId) { + return ordersServeManagerService.countByInstitutionStaffId(institutionStaffId); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/operation/OperationOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/operation/OperationOrdersController.java new file mode 100644 index 0000000..87d762f --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/operation/OperationOrdersController.java @@ -0,0 +1,30 @@ +package com.jzo2o.orders.manager.controller.operation; + +import cn.hutool.core.bean.BeanUtil; +import com.jzo2o.api.orders.dto.request.OrderCancelReqDTO; +import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; +import com.jzo2o.common.model.CurrentUserInfo; +import com.jzo2o.common.model.PageResult; +import com.jzo2o.mvc.utils.UserContext; +import com.jzo2o.orders.manager.model.dto.request.OrderPageQueryReqDTO; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; +import com.jzo2o.orders.manager.model.dto.response.OperationOrdersDetailResDTO; +import com.jzo2o.orders.manager.service.IOrdersManagerService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * @author itcast + */ +@RestController("operationOrdersController") +@Api(tags = "运营端-订单相关接口") +@RequestMapping("/operation/orders") +public class OperationOrdersController { + + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/operation/OperationOrdersServeController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/operation/OperationOrdersServeController.java new file mode 100644 index 0000000..2b9e4e4 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/operation/OperationOrdersServeController.java @@ -0,0 +1,22 @@ +package com.jzo2o.orders.manager.controller.operation; + +import com.jzo2o.common.model.PageResult; +import com.jzo2o.orders.manager.model.dto.request.OrdersServePageQueryByServeProviderReqDTO; +import com.jzo2o.orders.manager.model.dto.response.*; +import com.jzo2o.orders.manager.service.IOrdersServeManagerService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * @author itcast + */ +@RestController("orders-operation") +@Api(tags = "运营端-服务单相关接口") +@RequestMapping("/operation/ordersServe") +public class OperationOrdersServeController { + + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/worker/WorkerOrdersServeController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/worker/WorkerOrdersServeController.java new file mode 100644 index 0000000..25c87aa --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/worker/WorkerOrdersServeController.java @@ -0,0 +1,25 @@ +package com.jzo2o.orders.manager.controller.worker; + +import com.jzo2o.mvc.utils.UserContext; +import com.jzo2o.orders.manager.model.dto.request.*; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeDetailResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeListResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeStatusNumResDTO; +import com.jzo2o.orders.manager.service.IOrdersServeManagerService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +@RestController("orders-worker") +@Api(tags = "服务端-服务单相关接口") +@RequestMapping("/worker") +public class WorkerOrdersServeController { + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/OrderCancelDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/OrderCancelDTO.java new file mode 100644 index 0000000..8dc5693 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/OrderCancelDTO.java @@ -0,0 +1,71 @@ +package com.jzo2o.orders.manager.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 订单取消模型 + * + * @author itcast + * @create 2023/8/7 17:12 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrderCancelDTO { + /** + * 订单id + */ + private Long id; + + /** + * 用户id + */ + private Long userId; + + /** + * 当前用户id + */ + private Long currentUserId; + + /** + * 当前用户名称 + */ + private String currentUserName; + + /** + * 当前用户类型 + */ + private Integer currentUserType; + + /** + * 取消原因 + */ + private String cancelReason; + + /** + * 预约服务开始时间 + */ + private LocalDateTime serveStartTime; + + /** + * 实际支付金额 + */ + private BigDecimal realPayAmount; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 支付服务交易单号 + */ + private Long tradingOrderNo; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/ServeProviderInfo.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/ServeProviderInfo.java new file mode 100644 index 0000000..b84b047 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/ServeProviderInfo.java @@ -0,0 +1,55 @@ +package com.jzo2o.orders.manager.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; + +import java.util.List; + +@Data +public class ServeProviderInfo { + /** + * 服务人员或机构同步表 + */ + private Long id; + + /** + * 技能列表 + */ + private List serveItemIds; + + /** + * 经纬度 + */ + private String location; + + /** + * 城市编码 + */ + private String cityCode; + + /** + * 接单距离 + */ + private Double recieveDistance; + + /** + * 接单开关1,:接单开启,0:接单关闭 + */ + private Integer pickUp; + + /** + * 评分,默认50分 + */ + private Double evaluationScore; + + /** + * 服务时间 + */ + private List serveTimes; + + /** + * 首次设置状态,0:未完成,1:已完成设置 + */ + private Integer setttingStatus; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrderPageQueryReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrderPageQueryReqDTO.java new file mode 100644 index 0000000..ec48636 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrderPageQueryReqDTO.java @@ -0,0 +1,75 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import com.jzo2o.common.model.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 订单分页查询请求 + * + * @author itcast + * @create 2023/7/20 21:17 + **/ +@Data +@ApiModel("订单分页查询请求") +public class OrderPageQueryReqDTO extends PageQueryDTO { + /** + * 订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:订单取消,700:订单关闭 + */ + @ApiModelProperty("订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:订单取消,700:订单关闭") + private Integer ordersStatus; + + /** + * 支付状态,0:待支付,1:支付成功 + */ + @ApiModelProperty("支付状态,0:待支付,1:支付成功") + private Integer payStatus; + + /** + * 退款状态,0:发起退款,1:退款中,2:退款成功 3:退款失败 + */ + @ApiModelProperty("退款状态,0:发起退款,1:退款中,2:退款成功 3:退款失败") + private Integer refundStatus; + /** + * 用户id + */ + @ApiModelProperty("用户id") + private Long userId; + + /** + * 订单id + */ + @ApiModelProperty("订单id") + private Long id; + + /** + * 客户电话 + */ + @ApiModelProperty("客户电话") + private String contactsPhone; + + /** + * 最小创建时间 + */ + @ApiModelProperty("最小创建时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime minCreateTime; + + /** + * 最大创建时间 + */ + @ApiModelProperty("最大创建时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime maxCreateTime; + + /** + * 订单id列表 + */ + @ApiModelProperty("订单id列表") + private List ordersIdList; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrderServeCancelReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrderServeCancelReqDTO.java new file mode 100644 index 0000000..2c0e4df --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrderServeCancelReqDTO.java @@ -0,0 +1,23 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author itcast + */ +@Data +@ApiModel("服务取消模型") +public class OrderServeCancelReqDTO { + @ApiModelProperty(value = "服务单id",required = true) + @NotNull(message = "操作失败") + private Long id; + + @ApiModelProperty(value = "取消原因",required = true) + @NotNull(message = "操作失败") + private String cancelReason; + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersDispatchReceiveReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersDispatchReceiveReqDTO.java new file mode 100644 index 0000000..b6356f6 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersDispatchReceiveReqDTO.java @@ -0,0 +1,18 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author itcast + */ +@ApiModel("接单模型") +@Data +public class OrdersDispatchReceiveReqDTO { + @ApiModelProperty(value = "派单id",required = true) + @NotNull(message = "接单失败") + private Long id; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersDispatchRejectReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersDispatchRejectReqDTO.java new file mode 100644 index 0000000..ee3dd44 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersDispatchRejectReqDTO.java @@ -0,0 +1,21 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author itcast + */ +@ApiModel("接单模型") +@Data +public class OrdersDispatchRejectReqDTO { + @ApiModelProperty(value = "派单id",required = true) + @NotNull(message = "接单失败") + private Long id; + @ApiModelProperty(value = "拒单原因",required = true) + @NotNull(message = "拒单失败") + private String rejectReason; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersPayReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersPayReqDTO.java new file mode 100644 index 0000000..4f4cce3 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersPayReqDTO.java @@ -0,0 +1,22 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import com.jzo2o.api.trade.enums.PayChannelEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 订单支付请求体 + * + * @author itcast + * @create 2023/9/4 10:00 + **/ +@Data +@ApiModel("订单支付请求体") +public class OrdersPayReqDTO { + @ApiModelProperty(value = "支付渠道", required = true) + @NotNull(message = "支付渠道不能为空") + private PayChannelEnum tradingChannel; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersSeizeReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersSeizeReqDTO.java new file mode 100644 index 0000000..6d2f05f --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersSeizeReqDTO.java @@ -0,0 +1,15 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("抢单模型") +public class OrdersSeizeReqDTO { + /** + * 抢单id + */ + @ApiModelProperty("抢单id") + private Long id; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServeAllocationReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServeAllocationReqDTO.java new file mode 100644 index 0000000..b6a9ca1 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServeAllocationReqDTO.java @@ -0,0 +1,20 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author itcast + */ +@Data +public class OrdersServeAllocationReqDTO { + + @ApiModelProperty("服务单id") + @NotNull(message = "人员分配失败") + private Long id; + @ApiModelProperty("服务人员id") + @NotNull(message = "人员分配失败") + private Long institutionStaffId; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServePageQueryByServeProviderReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServePageQueryByServeProviderReqDTO.java new file mode 100644 index 0000000..4ffdc0c --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServePageQueryByServeProviderReqDTO.java @@ -0,0 +1,28 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import com.jzo2o.common.model.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 根据服务人员/机构分页查询服务数据 + * + * @author itcast + * @create 2023/9/15 18:55 + **/ +@Data +@ApiModel("根据服务人员/机构分页查询服务单相关模型") +public class OrdersServePageQueryByServeProviderReqDTO extends PageQueryDTO { + /** + * 用户类型,2:服务人员,3:机构 + */ + @ApiModelProperty(value = "用户类型,2:服务人员,3:机构") + private Integer userType; + + /** + * 服务人员/机构id + */ + @ApiModelProperty(value = "服务人员/机构id") + private Long serveProviderId; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServePageQueryReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServePageQueryReqDTO.java new file mode 100644 index 0000000..f03827f --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/OrdersServePageQueryReqDTO.java @@ -0,0 +1,31 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import com.jzo2o.common.model.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; + +/** + * @author itcast + */ +@Data +@ApiModel("服务单分页查询相关模型") +public class OrdersServePageQueryReqDTO extends PageQueryDTO { + + @ApiModelProperty(value = "服务状态,0:待分配,1:待上门,2:服务中(待完工),3:服务完成,4:取消,5:被退单") + private Integer serveStatus; + + @ApiModelProperty(value = "服务单编码") + private Long id; + + @ApiModelProperty(value = "服务项id") + private String serveItemId; + + @ApiModelProperty(value = "服务时间 - 最小") + private Date minServeStartTime; + + @ApiModelProperty(value = "服务时间 - 最大") + private Date maxServeStartTime; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/PlaceOrderReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/PlaceOrderReqDTO.java new file mode 100644 index 0000000..3520cd4 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/PlaceOrderReqDTO.java @@ -0,0 +1,29 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@ApiModel("下单请求信息") +@Data +public class PlaceOrderReqDTO { + @ApiModelProperty(value = "服务id",required = true) + @NotNull(message = "您还未选择服务") + private Long serveId; + + @ApiModelProperty(value = "预约地址id",required = true) + @NotNull(message = "您还未选择服务地址") + private Long addressBookId; + + @ApiModelProperty(value = "购买数量",required = false) + private Integer purNum; + + @ApiModelProperty(value = "预约时间",required = true) + private LocalDateTime serveStartTime; + + @ApiModelProperty(value = "优惠券id", required = false) + private Long couponId; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/ServeFinishedReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/ServeFinishedReqDTO.java new file mode 100644 index 0000000..568e47e --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/ServeFinishedReqDTO.java @@ -0,0 +1,24 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.List; + +@Data +@ApiModel("服务开始模型") +public class ServeFinishedReqDTO { + @ApiModelProperty("服务id") + private Long id; + + @ApiModelProperty("服务完成图片") + @NotNull(message = "请上传服务完成图片") + @Size(min = 1, max = 3, message = "上传1-3张照片") + private List serveAfterImgs; + + @ApiModelProperty("服务完成说明") + private String serveAfterIllustrate; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/ServeStartReqDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/ServeStartReqDTO.java new file mode 100644 index 0000000..6f9b76e --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/request/ServeStartReqDTO.java @@ -0,0 +1,23 @@ +package com.jzo2o.orders.manager.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author itcast + */ +@Data +@ApiModel("服务完成模型") +public class ServeStartReqDTO { + @ApiModelProperty("服务开始id") + private Long id; + + @ApiModelProperty("服务图片") + private List serveBeforeImgs; + + @ApiModelProperty("服务前说明") + private String serveBeforeIllustrate; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OperationOrdersDetailResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OperationOrdersDetailResDTO.java new file mode 100644 index 0000000..cabe773 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OperationOrdersDetailResDTO.java @@ -0,0 +1,200 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 管理端订单详情 + * + * @author itcast + * @create 2023/9/12 21:05 + **/ +@Data +@ApiModel("管理端订单详情响应数据") +public class OperationOrdersDetailResDTO { + @ApiModelProperty("状态流转") + private List ordersProgress; + + @ApiModelProperty("订单信息") + private OrderInfo orderInfo; + + @ApiModelProperty("支付信息") + private PayInfo payInfo; + + @ApiModelProperty("服务信息") + private ServeInfo serveInfo; + + @ApiModelProperty("退款信息") + private RefundInfo refundInfo; + + @ApiModelProperty("订单取消理由") + private CancelInfo cancelInfo; + + @Data + @ApiModel("订单信息模型") + public static class OrderInfo { + @ApiModelProperty("订单id") + private Long id; + + @ApiModelProperty("订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:订单取消,700已关闭") + private Integer ordersStatus; + + @ApiModelProperty("服务项名称") + private String serveItemName; + + @ApiModelProperty("下单时间") + private LocalDateTime createTime; + + @ApiModelProperty("客户名称") + private String contactsName; + + @ApiModelProperty("客户电话") + private String contactsPhone; + + @ApiModelProperty("服务地址") + private String serveAddress; + + @ApiModelProperty("预约时间") + private LocalDateTime serveStartTime; + + @ApiModelProperty("订单总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("实际支付金额") + private BigDecimal realPayAmount; + + @ApiModelProperty("购买数量") + private Integer purNum; + + @ApiModelProperty("服务单位") + private Integer unit; + + @ApiModelProperty("服务人员类型,2:服务人员,3:机构") + private Integer serveProviderType; + + @ApiModelProperty("服务人员/机构名称") + private String serveProviderName; + + @ApiModelProperty("服务人员/机构电话") + private String serveProviderPhone; + + @ApiModelProperty("机构下属服务人员姓名") + private String institutionStaffName; + + @ApiModelProperty("机构下属服务人员电话") + private String institutionStaffPhone; + + } + + @Data + @ApiModel("支付记录模型") + public static class PayInfo { + @ApiModelProperty("支付状态,2:待支付,4:支付成功") + private Integer payStatus; + + @ApiModelProperty("支付渠道,ALI_PAY:支付宝,WECHAT_PAY:微信") + private String tradingChannel; + + @ApiModelProperty("三方流水,微信支付订单号或支付宝订单号") + private String thirdOrderId; + + @ApiModelProperty("订单总金额") + private BigDecimal totalAmount; + + @ApiModelProperty("实付金额") + private BigDecimal realPayAmount; + } + + @Data + @ApiModel("服务信息模型") + public static class ServeInfo { + @ApiModelProperty("服务人员类型") + private Integer serveProviderType; + + @ApiModelProperty("服务人员/机构名称") + private String serveProviderName; + + @ApiModelProperty("机构下属服务人员姓名") + private String institutionStaffName; + + @ApiModelProperty("服务实际开始时间") + private LocalDateTime realServeStartTime; + + @ApiModelProperty("服务开始图片") + private List serveBeforeImgs; + + @ApiModelProperty("服务开始说明") + private String serveBeforeIllustrate; + + @ApiModelProperty("服务完成时间") + private LocalDateTime realServeEndTime; + + @ApiModelProperty("服务完成图片") + private List serveAfterImgs; + + @ApiModelProperty("服务完成说明") + private String serveAfterIllustrate; + } + + @Data + @ApiModel("退款信息模型") + public static class RefundInfo { + @ApiModelProperty("退款状态:0:发起退款,1:退款中,2:成功,3:失败") + private Integer refundStatus; + + @ApiModelProperty("取消人类型,0:系统,1:普通用户,4:管理员") + private Integer cancellerType; + + @ApiModelProperty("退款人,退款人和取消人保持一致") + private String cancelerName; + + @ApiModelProperty("退款理由和取消理由一致") + private String cancelReason; + + @ApiModelProperty("支付渠道,ALI_PAY:支付宝,WECHAT_PAY:微信") + private String tradingChannel; + + @ApiModelProperty("退款三方流水,微信支付订单号或支付宝订单号") + private String thirdRefundOrderId; + + @ApiModelProperty("退款金额,和实付金额保持一致") + private BigDecimal realPayAmount; + + @ApiModelProperty("退款时间;和取消时间保持一致") + private LocalDateTime cancelTime; + } + + @Data + @ApiModel("订单取消模型") + public static class CancelInfo { + @ApiModelProperty("取消人类型,0:系统,1:普通用户,4:管理员") + private Integer cancellerType; + + @ApiModelProperty("取消人") + private String cancelerName; + + @ApiModelProperty("取消时间") + private LocalDateTime cancelTime; + + @ApiModelProperty("取消理由") + private String cancelReason; + + } + + @Data + @ApiModel("状态节点流转模型") + @AllArgsConstructor + public static class OrderProgress { + @ApiModelProperty("订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:订单取消,700已退单") + private Integer status; + + @ApiModelProperty("时间") + private LocalDateTime dateTime; + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersDispatchResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersDispatchResDTO.java new file mode 100644 index 0000000..4355504 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersDispatchResDTO.java @@ -0,0 +1,31 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author itcast + */ +@Data +@ApiModel("派单列表") +public class OrdersDispatchResDTO { + @ApiModelProperty(value = "派单id",required = true) + private Long id; + @ApiModelProperty(value = "订单编号", required = true) + private String ordersNo; + @ApiModelProperty(value = "分类名称",required = true) + private String serveTypeName; + @ApiModelProperty(value = "服务项名称",required = true) + private String serveItemName; + @ApiModelProperty(value = "服务费",required = true) + private BigDecimal serveFee; + @ApiModelProperty(value = "预约时间",required = true) + private LocalDateTime serveStartTime; + @ApiModelProperty(value = "服务地址",required = true) + private String serveAddress; + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersPayResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersPayResDTO.java new file mode 100644 index 0000000..e922b47 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersPayResDTO.java @@ -0,0 +1,30 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import com.jzo2o.api.trade.enums.PayChannelEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 订单支付响应体 + * + * @author itcast + * @create 2023/9/4 10:00 + **/ +@Data +@ApiModel("订单支付响应体") +public class OrdersPayResDTO { + + @ApiModelProperty(value = "二维码base64数据") + private String qrCode; + @ApiModelProperty(value = "业务系统订单号") + private Long productOrderNo; + @ApiModelProperty(value = "交易系统订单号【对于三方来说:商户订单】") + private Long tradingOrderNo; + @ApiModelProperty(value = "支付渠道【支付宝、微信、现金、免单挂账】") + private String tradingChannel; + @ApiModelProperty(value = "支付状态 待支付或支付成功") + private int payStatus; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersSeizeListResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersSeizeListResDTO.java new file mode 100644 index 0000000..8e754ea --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersSeizeListResDTO.java @@ -0,0 +1,89 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Data +@ApiModel("抢单列表") +@NoArgsConstructor +@AllArgsConstructor +public class OrdersSeizeListResDTO implements Serializable { + + @ApiModelProperty("抢单列表") + private List ordersSeizes; + + @Data + public static class OrdersSeize implements Serializable{ + /** + * 订单id + */ + @ApiModelProperty(value = "订单id",required = true) + private Long id; + + /** + * 服务名称 + */ + @ApiModelProperty(value = "服务项名称",required = true) + private String serveItemName; + + @ApiModelProperty(value = "服务分类id",required = true) + private Long serveTypeId; + + /** + * 服务分类名称 + */ + @ApiModelProperty(value = "服务类型名称",required = true) + private String serveTypeName; + + /** + * 服务地址 + */ + @ApiModelProperty(value = "服务地址",required = true) + private String serveAddress; + + /** + * 服务项目图片 + */ + @ApiModelProperty(value = "服务图片",required = true) + private String serveItemImg; + + /** + * 收益 + */ + @ApiModelProperty(value = "服务费",required = true) + private BigDecimal serveFee; + + /** + * 服务开始时间 + */ + @ApiModelProperty(value = "服务开始时间",required = true) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @JsonSerialize(using = LocalDateTimeSerializer.class) + private LocalDateTime serveStartTime; + + /** + * 开始派单时间 + */ + @ApiModelProperty(value = "服务开始派单时间",required = true) + private LocalDateTime startDispatchTime; + + + /** + * 服务数量 + */ + @ApiModelProperty(value = "服务数量",required = true) + private Integer purNum; + + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeDetailResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeDetailResDTO.java new file mode 100644 index 0000000..cf77d05 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeDetailResDTO.java @@ -0,0 +1,125 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author itcast + */ +@Data +@ApiModel("订单详情信息") +public class OrdersServeDetailResDTO { + @ApiModelProperty("服务单id") + private Long id; + @ApiModelProperty(value = "服务单状态,0:待分配,1:待服务,2:服务中,3:服务完成,4:已取消,5:被退单", required = true) + private Integer serveStatus; + + @ApiModelProperty("服务信息") + private ServeInfo serveInfo; + + @ApiModelProperty("客户信息") + private CustomerInfo customerInfo; + + @ApiModelProperty("订单信息") + private OrdersInfo ordersInfo; + + @ApiModelProperty("退款信息") + private RefundInfo refundInfo; + + @ApiModelProperty("取消信息") + private CancelInfo cancelInfo; +// +// + @Data + @ApiModel("取消详情") + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class CancelInfo { + @ApiModelProperty("取消原因") + private String cancelReason; + @ApiModelProperty("取消时间") + private LocalDateTime cancelTime; + } + @Data + @ApiModel("退款信息") + private static class RefundInfo { + @ApiModelProperty("退款时间") + private LocalDateTime refundTime; + @ApiModelProperty("退款原因") + private String refundReason; + @ApiModelProperty("退款金额") + private BigDecimal refundAmount; + } + @Data + @ApiModel("服务信息") + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class ServeInfo { + @ApiModelProperty(value = "服务类型", required = true) + private String serveTypeName; + @ApiModelProperty(value = "服务项名称", required = true) + private String serveItemName; + @ApiModelProperty(value = "服务数量", required = true) + private Integer serveNum; + @ApiModelProperty(value = "服务单位", required = true) + private Integer unit; + @ApiModelProperty(value = "机构服务人", required = true) + private String institutionStaffName; + @ApiModelProperty(value = "服务前照片列表") + private List serveBeforeImgs; + @ApiModelProperty(value = "服务前照片列表") + private List serveAfterImgs; + @ApiModelProperty(value = "服务开始说明") + private String serveBeforeIllustrate; + @ApiModelProperty(value = "服务完成说明") + private String serveAfterIllustrate; + @ApiModelProperty("服务实际开始时间") + private LocalDateTime realServeStartTime; + @ApiModelProperty("服务实际完成时间") + private LocalDateTime realServeEndTime; + @ApiModelProperty("服务图片地址") + private String serveItemImg; + } + + + @Data + @ApiModel("客户信息") + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class CustomerInfo { + @ApiModelProperty(value = "联系人", required = true) + private String contactsName; + @ApiModelProperty(value = "联系人手机号", required = true) + private String contactsPhone; + @ApiModelProperty(value = "服务地址", required = true) + private String serveAddress; + } + + + @Data + @ApiModel("订单信息") + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class OrdersInfo { + + @ApiModelProperty(value = "服务单单编号", required = true) + private Long ordersId; + @ApiModelProperty(value = "服务开始时间", required = true) + private LocalDateTime serveStartTime; + @ApiModelProperty("订单金额") + private BigDecimal ordersAmount; + } + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeListResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeListResDTO.java new file mode 100644 index 0000000..274f07e --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeListResDTO.java @@ -0,0 +1,19 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@ApiModel("服务单列表,无分页") +@NoArgsConstructor +@AllArgsConstructor +public class OrdersServeListResDTO { + + @ApiModelProperty("服务单列表") + private List ordersServes; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeResDTO.java new file mode 100644 index 0000000..f5a61b5 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeResDTO.java @@ -0,0 +1,60 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author itcast + */ +@Data +@ApiModel("服务分页查询相关模型") +public class OrdersServeResDTO { + + @ApiModelProperty(value = "服务单id",required = true) + private Long id; + + @ApiModelProperty(value = "服务分类名称",required = true) + private String serveTypeName; + + @ApiModelProperty("服务名称") + private String serveItemName; + + @ApiModelProperty(value = "服务地址",required = true) + private String serveAddress; + + @ApiModelProperty(value = "服务开始时间",required = true) + private LocalDateTime serveStartTime; + + @ApiModelProperty("服务图片地址") + private String serveItemImg; + + @ApiModelProperty(value = "订单金额",required = true) + private BigDecimal ordersAmount; + + @ApiModelProperty(value = "创建时间",required = true) + private LocalDateTime createTime; + + @ApiModelProperty("服务状态:服务状态,0:待分配,1:待服务,2:服务中,3:服务完成,4:已取消,5:被退单") + private Integer serveStatus; + + @ApiModelProperty("取消时间") + private LocalDateTime cancelTime; + + @ApiModelProperty("实际服务开始时间") + private LocalDateTime realServeStartTime; + + @ApiModelProperty("实际服务结束时间") + private LocalDateTime realServeEndTime; + + @ApiModelProperty("订单id") + private Long ordersId; + + @ApiModelProperty("排序字段") + private Long sortBy; + + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeStatusNumResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeStatusNumResDTO.java new file mode 100644 index 0000000..3920950 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/OrdersServeStatusNumResDTO.java @@ -0,0 +1,27 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author itcast + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel("服务单状态的数量") +public class OrdersServeStatusNumResDTO { + @ApiModelProperty(required = true, value = "未分配") + private Long noAllocation; + @ApiModelProperty(required = true, value = "未开始服务") + private Long noServed; + @ApiModelProperty(required = true, value = "服务中,待服务完成") + private Long serving; + + public static OrdersServeStatusNumResDTO empty() { + return new OrdersServeStatusNumResDTO(0L,0L,0L); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/PlaceOrderResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/PlaceOrderResDTO.java new file mode 100644 index 0000000..7bfd719 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/PlaceOrderResDTO.java @@ -0,0 +1,19 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author itcast + */ +@ApiModel("下单响应信息") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PlaceOrderResDTO { + @ApiModelProperty("订单id") + private Long id; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/ServeProviderServeResDTO.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/ServeProviderServeResDTO.java new file mode 100644 index 0000000..7ad8d93 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/model/dto/response/ServeProviderServeResDTO.java @@ -0,0 +1,65 @@ +package com.jzo2o.orders.manager.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 服务人员/机构服务数据 + * + * @author itcast + * @create 2023/9/15 14:26 + **/ +@Data +@ApiModel("服务人员/机构服务数据") +public class ServeProviderServeResDTO { + + @ApiModelProperty("订单id") + private Long id; + + @ApiModelProperty("服务名称") + private String serveItemName; + + @ApiModelProperty("机构下属服务人员id") + private Long institutionStaffId; + + @ApiModelProperty("机构下属服务人员姓名") + private String institutionStaffName; + + @ApiModelProperty("机构下属服务人员电话") + private String institutionStaffPhone; + + /** + * 服务前照片 + */ + @ApiModelProperty("服务前照片") + private List serveBeforeImgs; + + /** + * 服务后照片 + */ + @ApiModelProperty("服务后照片") + private List serveAfterImgs; + + /** + * 实际支付金额 + */ + @ApiModelProperty("实际支付金额") + private BigDecimal ordersAmount; + + /** + * 评分 + */ + @ApiModelProperty("评分") + private Double score; + + /** + * 实际服务完结时间 + */ + @ApiModelProperty("实际服务完结时间") + private LocalDateTime realServeEndTime; +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/porperties/OrdersJobProperties.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/porperties/OrdersJobProperties.java new file mode 100644 index 0000000..bc91b3d --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/porperties/OrdersJobProperties.java @@ -0,0 +1,34 @@ +package com.jzo2o.orders.manager.porperties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author itcast + */ +@Data +@Component +@ConfigurationProperties(prefix = "jzo2o.job") +public class OrdersJobProperties { + + /** + * 自动评价订单数量,默认100 + */ + private Integer autoEvaluateCount = 100; + + /** + * 退款订单数量,默认100 + */ + private Integer refundOrderCount = 100; + + /** + * 超时支付订单数量,默认100 + */ + private Integer overTimePayOrderCount = 100; + + /** + * 派单超时订单数量,默认100 + */ + private Integer dispatchOverTimeOrderCount = 100; +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/porperties/TradeProperties.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/porperties/TradeProperties.java new file mode 100644 index 0000000..9f58a27 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/porperties/TradeProperties.java @@ -0,0 +1,24 @@ +package com.jzo2o.orders.manager.porperties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author itcast + */ +@Data +@Component +@ConfigurationProperties(prefix = "jzo2o.trade") +public class TradeProperties { + + /** + * 支付宝商户id + */ + private Long aliEnterpriseId; + + /** + * 微信支付商户id + */ + private Long wechatEnterpriseId; +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IBreachRecordService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IBreachRecordService.java new file mode 100644 index 0000000..b9b3080 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IBreachRecordService.java @@ -0,0 +1,34 @@ +package com.jzo2o.orders.manager.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.orders.base.enums.BreachHaviorTypeEnum; +import com.jzo2o.orders.base.model.domain.BreachRecord; + +/** + *

+ * 违约记录 服务类 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +public interface IBreachRecordService extends IService { + + + /** + * 单独添加违约记录 + * + * @param breachRecord 违约信息 + */ + void add(BreachRecord breachRecord); + + + /** + * 统计违约记录 + * @param serveProviderId 服务人员或机构id + * @param breachHaviorTypeEnum 拒单类型 + * @return + */ + int count(Long serveProviderId, BreachHaviorTypeEnum breachHaviorTypeEnum, int breachDay); + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCanceledService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCanceledService.java new file mode 100644 index 0000000..45c90c3 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCanceledService.java @@ -0,0 +1,16 @@ +package com.jzo2o.orders.manager.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.orders.base.model.domain.OrdersCanceled; + +/** + *

+ * 订单取消服务类 + *

+ * + * @author itcast + * @since 2023-08-19 + */ +public interface IOrdersCanceledService extends IService { + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java new file mode 100644 index 0000000..0728e0f --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java @@ -0,0 +1,33 @@ +package com.jzo2o.orders.manager.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.api.market.dto.request.CouponUseBackReqDTO; +import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; +import com.jzo2o.api.orders.dto.response.OrderResDTO; +import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; +import com.jzo2o.common.model.PageResult; +import com.jzo2o.common.model.msg.TradeStatusMsg; +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; +import com.jzo2o.orders.manager.model.dto.request.OrderPageQueryReqDTO; +import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; +import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.orders.manager.model.dto.response.OperationOrdersDetailResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; +import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; + +import java.util.List; + +/** + *

+ * 下单服务类 + *

+ * + * @author itcast + * @since 2023-07-10 + */ +public interface IOrdersCreateService extends IService { + + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java new file mode 100644 index 0000000..ed1301c --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java @@ -0,0 +1,65 @@ +package com.jzo2o.orders.manager.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.api.market.dto.request.CouponUseBackReqDTO; +import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; +import com.jzo2o.api.orders.dto.response.OrderResDTO; +import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; +import com.jzo2o.common.model.PageResult; +import com.jzo2o.common.model.msg.TradeStatusMsg; +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; +import com.jzo2o.orders.manager.model.dto.request.OrderPageQueryReqDTO; +import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; +import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.orders.manager.model.dto.response.OperationOrdersDetailResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; +import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; + +import java.util.List; + +/** + *

+ * 订单表 服务类 + *

+ * + * @author itcast + * @since 2023-07-10 + */ +public interface IOrdersManagerService extends IService { + + /** + * @param ids + * @return + */ + List batchQuery(List ids); + + Orders queryById(Long id); + + /** + * 滚动分页查询 + * + * @param currentUserId 当前用户id + * @param ordersStatus 订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:已取消,700:已关闭 + * @param sortBy 排序字段 + * @return 订单列表 + */ + List consumerQueryList(Long currentUserId, Integer ordersStatus, Long sortBy); + + + /** + * 根据订单id查询 + * + * @param id 订单id + * @return 订单详情 + */ + OrderResDTO getDetail(Long id); + /** + * 订单评价 + * + * @param ordersId 订单id + */ + void evaluationOrder(Long ordersId); + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersRefundService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersRefundService.java new file mode 100644 index 0000000..6707a4b --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersRefundService.java @@ -0,0 +1,24 @@ +package com.jzo2o.orders.manager.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.orders.base.model.domain.OrdersRefund; + +import java.util.List; + +/** + *

+ * 订单退款表 服务类 + *

+ * + * @author itcast + * @since 2023-09-07 + */ +public interface IOrdersRefundService extends IService { + + /** + * 查询指定数量的退款订单 + * + * @param count 数量 + */ + List queryRefundOrderListByCount(Integer count); +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersServeManagerService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersServeManagerService.java new file mode 100644 index 0000000..08076a0 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersServeManagerService.java @@ -0,0 +1,48 @@ +package com.jzo2o.orders.manager.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.api.orders.dto.response.InstitutionStaffServeCountResDTO; +import com.jzo2o.common.model.PageResult; +import com.jzo2o.orders.base.model.domain.OrdersServe; +import com.jzo2o.orders.manager.model.dto.request.*; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeDetailResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeResDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersServeStatusNumResDTO; +import com.jzo2o.orders.manager.model.dto.response.ServeProviderServeResDTO; + +import java.util.List; + +/** + *

+ * 服务服务单 服务类 + *

+ * + * @author itcast + * @since 2023-07-26 + */ +public interface IOrdersServeManagerService extends IService { + + + /** + * 批量获取服务单 + * + * @param ids 服务单id列表 + * @return 服务单列表 + */ + List batchQuery(List ids); + + /** + * 获取服务单信息 + * @param id + * @return 服务单信息 + */ + OrdersServe queryById(Long id); + + /** + * 根据机构服务人员id查询服务数量 + * + * @param institutionStaffId 机构服务人员id + * @return 服务数量 + */ + InstitutionStaffServeCountResDTO countByInstitutionStaffId(Long institutionStaffId); +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/BreachRecordServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/BreachRecordServiceImpl.java new file mode 100644 index 0000000..b3e326b --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/BreachRecordServiceImpl.java @@ -0,0 +1,39 @@ +package com.jzo2o.orders.manager.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.common.utils.DateUtils; +import com.jzo2o.orders.base.enums.BreachHaviorTypeEnum; +import com.jzo2o.orders.base.mapper.BreachRecordMapper; +import com.jzo2o.orders.base.model.domain.BreachRecord; +import com.jzo2o.orders.manager.service.IBreachRecordService; +import org.springframework.stereotype.Service; + +/** + *

+ * 违约记录 服务实现类 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +@Service +public class BreachRecordServiceImpl extends ServiceImpl implements IBreachRecordService { + + + + @Override + public void add(BreachRecord breachRecord) { + breachRecord.setBreachDay(DateUtils.getDay()); + breachRecord.setBreachTime(DateUtils.now()); + baseMapper.insert(breachRecord); + } + + + @Override + public int count(Long serveProviderId, BreachHaviorTypeEnum breachHaviorTypeEnum, int breachDay) { + return lambdaQuery().eq(BreachRecord::getServeProviderId, serveProviderId) + .eq(BreachRecord::getBehaviorType, breachHaviorTypeEnum.getType()) + .eq(BreachRecord::getBreachDay, breachDay) + .count(); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCanceledServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCanceledServiceImpl.java new file mode 100644 index 0000000..bbdf8e3 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCanceledServiceImpl.java @@ -0,0 +1,20 @@ +package com.jzo2o.orders.manager.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.orders.base.mapper.OrdersCanceledMapper; +import com.jzo2o.orders.base.model.domain.OrdersCanceled; +import com.jzo2o.orders.manager.service.IOrdersCanceledService; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单取消服务实现类 + *

+ * + * @author itcast + * @since 2023-08-19 + */ +@Service +public class OrdersCanceledServiceImpl extends ServiceImpl implements IOrdersCanceledService { + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java new file mode 100644 index 0000000..5863b4c --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java @@ -0,0 +1,22 @@ +package com.jzo2o.orders.manager.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.orders.base.mapper.OrdersMapper; +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.manager.service.IOrdersCreateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 下单服务类 + *

+ * + * @author itcast + * @since 2023-07-10 + */ +@Slf4j +@Service +public class OrdersCreateServiceImpl extends ServiceImpl implements IOrdersCreateService { + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java new file mode 100644 index 0000000..129a217 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java @@ -0,0 +1,109 @@ +package com.jzo2o.orders.manager.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.api.orders.dto.response.OrderResDTO; +import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; +import com.jzo2o.common.enums.EnableStatusEnum; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.orders.base.mapper.OrdersMapper; +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.base.model.dto.OrderSnapshotDTO; +import com.jzo2o.orders.manager.service.IOrdersManagerService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static com.jzo2o.orders.base.constants.FieldConstants.SORT_BY; + +/** + *

+ * 订单表 服务实现类 + *

+ * + * @author itcast + * @since 2023-07-10 + */ +@Slf4j +@Service +public class OrdersManagerServiceImpl extends ServiceImpl implements IOrdersManagerService { + + @Override + public List batchQuery(List ids) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().in(Orders::getId, ids).ge(Orders::getUserId, 0); + return baseMapper.selectList(queryWrapper); + } + + @Override + public Orders queryById(Long id) { + return baseMapper.selectById(id); + } + + /** + * 滚动分页查询 + * + * @param currentUserId 当前用户id + * @param ordersStatus 订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:已取消,700:已关闭 + * @param sortBy 排序字段 + * @return 订单列表 + */ + @Override + public List consumerQueryList(Long currentUserId, Integer ordersStatus, Long sortBy) { + //1.构件查询条件 + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .eq(ObjectUtils.isNotNull(ordersStatus), Orders::getOrdersStatus, ordersStatus) + .lt(ObjectUtils.isNotNull(sortBy), Orders::getSortBy, sortBy) + .eq(Orders::getUserId, currentUserId) + .eq(Orders::getDisplay, EnableStatusEnum.ENABLE.getStatus()); + Page queryPage = new Page<>(); + queryPage.addOrder(OrderItem.desc(SORT_BY)); + queryPage.setSearchCount(false); + + //2.查询订单列表 + Page ordersPage = baseMapper.selectPage(queryPage, queryWrapper); + List records = ordersPage.getRecords(); + List orderSimpleResDTOS = BeanUtil.copyToList(records, OrderSimpleResDTO.class); + return orderSimpleResDTOS; + + } + /** + * 根据订单id查询 + * + * @param id 订单id + * @return 订单详情 + */ + @Override + public OrderResDTO getDetail(Long id) { + Orders orders = queryById(id); + OrderResDTO orderResDTO = BeanUtil.toBean(orders, OrderResDTO.class); + return orderResDTO; + } + + /** + * 订单评价 + * + * @param ordersId 订单id + */ + @Override + @Transactional + public void evaluationOrder(Long ordersId) { +// //查询订单详情 +// Orders orders = queryById(ordersId); +// +// //构建订单快照 +// OrderSnapshotDTO orderSnapshotDTO = OrderSnapshotDTO.builder() +// .evaluationTime(LocalDateTime.now()) +// .build(); +// +// //订单状态变更 +// orderStateMachine.changeStatus(orders.getUserId(), orders.getId().toString(), OrderStatusChangeEventEnum.EVALUATE, orderSnapshotDTO); + } + +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersRefundServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersRefundServiceImpl.java new file mode 100644 index 0000000..d959208 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersRefundServiceImpl.java @@ -0,0 +1,36 @@ +package com.jzo2o.orders.manager.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.orders.base.mapper.OrdersRefundMapper; +import com.jzo2o.orders.base.model.domain.OrdersRefund; +import com.jzo2o.orders.manager.service.IOrdersRefundService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 订单退款表 服务实现类 + *

+ * + * @author itcast + * @since 2023-09-07 + */ +@Service +public class OrdersRefundServiceImpl extends ServiceImpl implements IOrdersRefundService { + + /** + * 查询指定数量的退款订单 + * + * @param count 数量 + */ + @Override + public List queryRefundOrderListByCount(Integer count) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .orderByAsc(OrdersRefund::getCreateTime) + .last("limit " + count); + return baseMapper.selectList(queryWrapper); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersServeManagerServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersServeManagerServiceImpl.java new file mode 100644 index 0000000..2dd47ab --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersServeManagerServiceImpl.java @@ -0,0 +1,63 @@ +package com.jzo2o.orders.manager.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.api.orders.dto.response.InstitutionStaffServeCountResDTO; +import com.jzo2o.common.utils.CollUtils; +import com.jzo2o.orders.base.mapper.OrdersServeMapper; +import com.jzo2o.orders.base.model.domain.OrdersServe; +import com.jzo2o.orders.manager.service.IOrdersServeManagerService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务服务单 服务实现类 + *

+ * + * @author itcast + * @since 2023-07-26 + */ +@Service +@Slf4j +public class OrdersServeManagerServiceImpl extends ServiceImpl implements IOrdersServeManagerService { + + + @Override + public List batchQuery(List ids) { + return lambdaQuery() + .in(OrdersServe::getId, ids) + .ge(OrdersServe::getServeProviderId, 0) + .list(); + } + + @Override + public OrdersServe queryById(Long id) { + List list = lambdaQuery() + .eq(OrdersServe::getId, id) + .ge(OrdersServe::getServeProviderId, 0) + .last(" limit 1") + .list(); + return CollUtils.getFirst(list); + } + + + /** + * 根据机构服务人员id查询服务数量 + * + * @param institutionStaffId 机构服务人员id + * @return 服务数量 + */ + @Override + public InstitutionStaffServeCountResDTO countByInstitutionStaffId(Long institutionStaffId) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .eq(OrdersServe::getInstitutionStaffId, institutionStaffId) + .gt(OrdersServe::getId, 0) + .gt(OrdersServe::getServeProviderId, 0); + Integer count = baseMapper.selectCount(queryWrapper); + return new InstitutionStaffServeCountResDTO(count); + } +} diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-dev.yml b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-dev.yml new file mode 100644 index 0000000..f6f1d00 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-dev.yml @@ -0,0 +1,18 @@ +spring: + cloud: + nacos: + username: nacos + password: nacos + server-addr: 192.168.122.135:8848 + config: + namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63 + file-extension: yaml + discovery: + namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63 + ip: ${ACCESS_IP:} + +################# 日志配置 ################# +logging: + level: + com.jzo2o: debug + org.mongodb.driver: info \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-prod.yml b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-prod.yml new file mode 100644 index 0000000..7569cd9 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-prod.yml @@ -0,0 +1,14 @@ +spring: + cloud: + nacos: + username: ${NACOS_USERNAME} + password: ${NACOS_PASSWORD} + server-addr: ${NACOS_ADDR} + config: + namespace: ${NACOS_NAMESPACE} + file-extension: yaml + discovery: + namespace: ${NACOS_NAMESPACE} +logging: + level: + com.jzo2o: debug \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-test.yml b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-test.yml new file mode 100644 index 0000000..7569cd9 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap-test.yml @@ -0,0 +1,14 @@ +spring: + cloud: + nacos: + username: ${NACOS_USERNAME} + password: ${NACOS_PASSWORD} + server-addr: ${NACOS_ADDR} + config: + namespace: ${NACOS_NAMESPACE} + file-extension: yaml + discovery: + namespace: ${NACOS_NAMESPACE} +logging: + level: + com.jzo2o: debug \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap.yml b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..3c239a9 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap.yml @@ -0,0 +1,76 @@ +################# 服务器配置 ################# +server: + port: 11504 + undertow: + accesslog: + enabled: true + pattern: "%t %a "%r" %s (%D ms)" + dir: /data/logs/undertow/${spring.application.name}/access-logs/ + servlet: + context-path: /orders-manager +################# spring公共配置 ################# +spring: + mvc: + path-match: + matching-strategy: ant_path_matcher + format: + date: yyyy-MM-dd HH:mm:ss + jackson: + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + profiles: + active: dev + application: + name: jzo2o-orders-manager + main: + # 支持循环依赖注入 + allow-circular-references: true + # bean名相同覆盖 + allow-bean-definition-overriding: true + cloud: + nacos: + config: + file-extension: yaml + shared-configs: # 共享配置 + - data-id: shared-redis-cluster.yaml # 共享redis集群配置 + refresh: false + - data-id: shared-xxl-job.yaml # xxl-job配置 + refresh: false + - data-id: shared-rabbitmq.yaml # rabbitmq配置 + refresh: false + - data-id: shared-es.yaml # es + refresh: false + - data-id: shared-mysql.yaml # mysql配置 + refresh: false +# - data-id: shared-spring-seata.yaml # seata +# refresh: false + + +################# 项目独有配置 ################# +mysql: + db-name: jzo2o-orders +mybatis: + mapper-locations: mapper/*.xml + type-aliases-package: com.jzo2o.orders.base.mapper +swagger: + enable: true + package-path: com.jzo2o.orders.manager.controller + title: 家政服务-订单管理模块接口文档 + description: 管理订单的生命周期、订单状态、订单信息 + contact-name: 传智教育·研究院 + contact-url: http://www.itcast.cn/ + contact-email: yjy@itcast.cn + version: v1.0 +feign: + enable: true +seata: + enabled: true + + + +################# 日志配置 ################# +logging: + level: + com.jzo2o: debug + io.seata: debug + org.apache.shardingsphere: debug diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/seata.conf b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/seata.conf new file mode 100644 index 0000000..763df30 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/seata.conf @@ -0,0 +1,5 @@ +client { + application.id = jzo2o-orders-manager ## 应用唯一主键 +; transaction.service.group = DEFAULT_GROUP ## 所属事务组 + transaction.service.group = jzo2o-seata +} \ No newline at end of file diff --git a/jzo2o-oreders/pom.xml b/jzo2o-oreders/pom.xml new file mode 100644 index 0000000..b4042b6 --- /dev/null +++ b/jzo2o-oreders/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + jzo2o-oreders + 1.0-SNAPSHOT + pom + + + jzo2o-parent + com.jzo2o + 1.0-SNAPSHOT + + + + jzo2o-orders-base + jzo2o-orders-manager + + + + 11 + 11 + UTF-8 + + \ No newline at end of file From c2d0d9b6475f6b6d2a56904c6c0816338562c321 Mon Sep 17 00:00:00 2001 From: JIAN Date: Mon, 2 Sep 2024 22:16:46 +0800 Subject: [PATCH 02/21] =?UTF-8?q?feat(foundations):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=9C=8D=E5=8A=A1=E8=AF=A6=E6=83=85=E7=9A=84?= =?UTF-8?q?=E5=86=85=E9=83=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/jzo2o/api/foundations/ServeApi.java | 14 ++++---- .../inner/InnerServeController.java | 32 +++++++++++++++++++ .../jzo2o/foundations/mapper/ServeMapper.java | 6 ++++ .../foundations/service/IServeService.java | 6 ++++ .../service/impl/ServeServiceImpl.java | 6 ++++ .../src/main/resources/mapper/ServeMapper.xml | 26 +++++++++++++++ 6 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 jzo2o-foundations/src/main/java/com/jzo2o/foundations/controller/inner/InnerServeController.java diff --git a/jzo2o-api/src/main/java/com/jzo2o/api/foundations/ServeApi.java b/jzo2o-api/src/main/java/com/jzo2o/api/foundations/ServeApi.java index 374f6cb..a9f1aa7 100644 --- a/jzo2o-api/src/main/java/com/jzo2o/api/foundations/ServeApi.java +++ b/jzo2o-api/src/main/java/com/jzo2o/api/foundations/ServeApi.java @@ -4,14 +4,16 @@ import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; - -import java.util.List; +/** + * 内部接口 - 服务相关接口 + * @author JIAN + */ @FeignClient(contextId = "jzo2o-foundations", value = "jzo2o-foundations", path = "/foundations/inner/serve") public interface ServeApi { - + /** + * 根据服务id获取服务信息 + */ @GetMapping("/{id}") ServeAggregationResDTO findById(@PathVariable("id") Long id); - -} +} \ No newline at end of file diff --git a/jzo2o-foundations/src/main/java/com/jzo2o/foundations/controller/inner/InnerServeController.java b/jzo2o-foundations/src/main/java/com/jzo2o/foundations/controller/inner/InnerServeController.java new file mode 100644 index 0000000..fd79158 --- /dev/null +++ b/jzo2o-foundations/src/main/java/com/jzo2o/foundations/controller/inner/InnerServeController.java @@ -0,0 +1,32 @@ +package com.jzo2o.foundations.controller.inner; + +import com.jzo2o.api.foundations.ServeApi; +import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; +import com.jzo2o.foundations.service.IServeService; +import io.swagger.annotations.Api; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @author JIAN + */ +@RestController +@RequestMapping("/inner/serve") +@Api(tags = "内部接口 - 服务相关接口") +public class InnerServeController implements ServeApi { + @Resource + private IServeService serveService; + + /** + * 根据服务id获取服务信息 + */ + @Override + @GetMapping("/{id}") + public ServeAggregationResDTO findById(@PathVariable Long id) { + return serveService.getServeAggregationById(id); + } +} \ No newline at end of file diff --git a/jzo2o-foundations/src/main/java/com/jzo2o/foundations/mapper/ServeMapper.java b/jzo2o-foundations/src/main/java/com/jzo2o/foundations/mapper/ServeMapper.java index 4947ee0..2962a5c 100644 --- a/jzo2o-foundations/src/main/java/com/jzo2o/foundations/mapper/ServeMapper.java +++ b/jzo2o-foundations/src/main/java/com/jzo2o/foundations/mapper/ServeMapper.java @@ -1,6 +1,7 @@ package com.jzo2o.foundations.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; import com.jzo2o.foundations.model.domain.Serve; import com.jzo2o.foundations.model.dto.response.ServeAggregationSimpleResDTO; import com.jzo2o.foundations.model.dto.response.ServeCategoryResDTO; @@ -34,4 +35,9 @@ public interface ServeMapper extends BaseMapper { * @param regionId 区域id */ List queryHotServeListByRegionId(Long regionId); + + /** + * 查询指定id的服务信息 + */ + ServeAggregationResDTO getServeAggregationById(Long id); } \ No newline at end of file diff --git a/jzo2o-foundations/src/main/java/com/jzo2o/foundations/service/IServeService.java b/jzo2o-foundations/src/main/java/com/jzo2o/foundations/service/IServeService.java index 2fc795d..f4a3600 100644 --- a/jzo2o-foundations/src/main/java/com/jzo2o/foundations/service/IServeService.java +++ b/jzo2o-foundations/src/main/java/com/jzo2o/foundations/service/IServeService.java @@ -1,6 +1,7 @@ package com.jzo2o.foundations.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; import com.jzo2o.common.model.PageResult; import com.jzo2o.foundations.model.domain.Serve; import com.jzo2o.foundations.model.dto.request.ServePageQueryReqDTO; @@ -86,4 +87,9 @@ public interface IServeService extends IService { * 查询指定区域的服务 */ List findServeList(String cityCode, Long serveTypeId, String keyword); + + /** + * 获取指定id的服务 + */ + ServeAggregationResDTO getServeAggregationById(Long id); } \ No newline at end of file diff --git a/jzo2o-foundations/src/main/java/com/jzo2o/foundations/service/impl/ServeServiceImpl.java b/jzo2o-foundations/src/main/java/com/jzo2o/foundations/service/impl/ServeServiceImpl.java index 340b5cc..18bb20f 100644 --- a/jzo2o-foundations/src/main/java/com/jzo2o/foundations/service/impl/ServeServiceImpl.java +++ b/jzo2o-foundations/src/main/java/com/jzo2o/foundations/service/impl/ServeServiceImpl.java @@ -5,6 +5,7 @@ import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.elasticsearch.core.SearchResponse; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers; +import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; import com.jzo2o.common.expcetions.CommonException; import com.jzo2o.common.expcetions.ForbiddenOperationException; import com.jzo2o.common.model.PageResult; @@ -380,6 +381,11 @@ public class ServeServiceImpl extends ServiceImpl implements } } + @Override + public ServeAggregationResDTO getServeAggregationById(Long id) { + return baseMapper.getServeAggregationById(id); + } + @Resource private IRegionService regionService; @Resource diff --git a/jzo2o-foundations/src/main/resources/mapper/ServeMapper.xml b/jzo2o-foundations/src/main/resources/mapper/ServeMapper.xml index 6d47c61..252fa0d 100644 --- a/jzo2o-foundations/src/main/resources/mapper/ServeMapper.xml +++ b/jzo2o-foundations/src/main/resources/mapper/ServeMapper.xml @@ -71,4 +71,30 @@ AND serve.is_hot = 1 # 保证热门状态 ORDER BY item.sort_num + + \ No newline at end of file From 2781689e778f6dc01d61ecc0b68e6fc43f677d04 Mon Sep 17 00:00:00 2001 From: JIAN Date: Mon, 2 Sep 2024 22:20:18 +0800 Subject: [PATCH 03/21] =?UTF-8?q?feat(customer):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=9C=B0=E5=9D=80=E4=BF=A1=E6=81=AF=E7=9A=84?= =?UTF-8?q?=E5=86=85=E9=83=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jzo2o/api/customer/AddressBookApi.java | 19 +++++++++++ .../inner/InnerAddressBookController.java | 34 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 jzo2o-api/src/main/java/com/jzo2o/api/customer/AddressBookApi.java create mode 100644 jzo2o-customer/src/main/java/com/jzo2o/customer/controller/inner/InnerAddressBookController.java diff --git a/jzo2o-api/src/main/java/com/jzo2o/api/customer/AddressBookApi.java b/jzo2o-api/src/main/java/com/jzo2o/api/customer/AddressBookApi.java new file mode 100644 index 0000000..dd019a6 --- /dev/null +++ b/jzo2o-api/src/main/java/com/jzo2o/api/customer/AddressBookApi.java @@ -0,0 +1,19 @@ +package com.jzo2o.api.customer; + +import com.jzo2o.api.customer.dto.response.AddressBookResDTO; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +/** + * 内部接口 - 地址簿相关接口 + * @author JIAN + */ +@FeignClient(contextId = "jzo2o-customer", value = "jzo2o-customer", path = "/customer/inner/address-book") +public interface AddressBookApi { + /** + * 获取指定id对应的地址信息 + */ + @GetMapping("/{id}") + AddressBookResDTO getById(@PathVariable Long id); +} \ No newline at end of file diff --git a/jzo2o-customer/src/main/java/com/jzo2o/customer/controller/inner/InnerAddressBookController.java b/jzo2o-customer/src/main/java/com/jzo2o/customer/controller/inner/InnerAddressBookController.java new file mode 100644 index 0000000..322e366 --- /dev/null +++ b/jzo2o-customer/src/main/java/com/jzo2o/customer/controller/inner/InnerAddressBookController.java @@ -0,0 +1,34 @@ +package com.jzo2o.customer.controller.inner; + +import com.jzo2o.api.customer.AddressBookApi; +import com.jzo2o.api.customer.dto.response.AddressBookResDTO; +import com.jzo2o.common.utils.BeanUtils; +import com.jzo2o.customer.service.IAddressBookService; +import io.swagger.annotations.Api; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * 内部接口 - 地址簿相关接口 + * @author JIAN + */ +@RestController +@RequestMapping("/inner/address-book") +@Api(tags = "内部接口 - 地址簿相关接口") +public class InnerAddressBookController implements AddressBookApi { + @Resource + private IAddressBookService addressBookService; + + /** + * 获取指定id对应的地址信息 + */ + @Override + @GetMapping("/{id}") + public AddressBookResDTO getById(@PathVariable Long id) { + return BeanUtils.toBean(addressBookService.getById(id), AddressBookResDTO.class); + } +} \ No newline at end of file From 27dc6c16af04ab5f5987a466cf224cee689f8413 Mon Sep 17 00:00:00 2001 From: JIAN Date: Mon, 2 Sep 2024 23:14:15 +0800 Subject: [PATCH 04/21] =?UTF-8?q?feat(customer):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=9C=B0=E5=9D=80=E5=92=8C=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=9A=84=E7=86=94=E6=96=AD=E7=AD=96=E7=95=A5?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jzo2o-oreders/jzo2o-orders-manager/pom.xml | 4 ++ .../service/client/CustomerClient.java | 59 +++++++++++++++++++ .../src/main/resources/bootstrap.yml | 4 +- 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/client/CustomerClient.java diff --git a/jzo2o-oreders/jzo2o-orders-manager/pom.xml b/jzo2o-oreders/jzo2o-orders-manager/pom.xml index f931d9a..4383d9f 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/pom.xml +++ b/jzo2o-oreders/jzo2o-orders-manager/pom.xml @@ -97,6 +97,10 @@ jzo2o-es + + com.jzo2o + jzo2o-sentinel + diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/client/CustomerClient.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/client/CustomerClient.java new file mode 100644 index 0000000..eba7ee1 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/client/CustomerClient.java @@ -0,0 +1,59 @@ +package com.jzo2o.orders.manager.service.client; + +import com.alibaba.csp.sentinel.annotation.SentinelResource; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.jzo2o.api.customer.AddressBookApi; +import com.jzo2o.api.customer.dto.response.AddressBookResDTO; +import com.jzo2o.api.foundations.ServeApi; +import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 自定义Feign客户端用于熔断降级 + * @author JIAN + */ +@Slf4j +@Component +@SuppressWarnings("unused") +public class CustomerClient { + @Resource + private ServeApi serveApi; + + @Resource + private AddressBookApi addressBookApi; + + @SentinelResource(value = "addressBookDetail", + fallback = "getAddressDetailFallback", blockHandler = "getAddressDetailBlockHandler") + public AddressBookResDTO getAddressDetail(Long id) { + return addressBookApi.getById(id); + } + + public AddressBookResDTO getAddressDetailFallback(Long id, Throwable throwable) { + log.warn("地址簿接口异常(未触发熔断), 地址簿id: {}", id, throwable); + return new AddressBookResDTO(); + } + + public AddressBookResDTO getAddressDetailBlockHandler(Long id, BlockException blockException) { + log.warn("地址簿接口异常(触发熔断降级), 地址簿id: {}", id, blockException); + return new AddressBookResDTO(); + } + + @SentinelResource(value = "serveAggregation", + fallback = "getServeAggregationDetailFallback", blockHandler = "getServeAggregationDetailBlockHandler") + public ServeAggregationResDTO getServeAggregation(Long id) { + return serveApi.findById(id); + } + + public ServeAggregationResDTO getServeAggregationDetailFallback(Long id, Throwable throwable) { + log.warn("服务接口异常(未触发熔断), 服务id: {}", id, throwable); + return new ServeAggregationResDTO(); + } + + public ServeAggregationResDTO getServeAggregationDetailBlockHandler(Long id, BlockException blockException) { + log.warn("服务接口异常(触发熔断降级), 服务id: {}", id, blockException); + return new ServeAggregationResDTO(); + } +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap.yml b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap.yml index 3c239a9..6dfee13 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap.yml +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/resources/bootstrap.yml @@ -42,6 +42,8 @@ spring: refresh: false - data-id: shared-mysql.yaml # mysql配置 refresh: false + - data-id: shared-sentinel.yaml # sentinel配置 + refresh: false # - data-id: shared-spring-seata.yaml # seata # refresh: false @@ -73,4 +75,4 @@ logging: level: com.jzo2o: debug io.seata: debug - org.apache.shardingsphere: debug + org.apache.shardingsphere: debug \ No newline at end of file From 85b6192ba1607cf7c791dd639b3fbd95dd4100bc Mon Sep 17 00:00:00 2001 From: JIAN Date: Sun, 8 Sep 2024 17:38:43 +0800 Subject: [PATCH 05/21] =?UTF-8?q?feat(orders.manager):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=B8=8B=E5=8D=95=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../orders/base/model/domain/Orders.java | 10 +- .../consumer/ConsumerOrdersController.java | 31 +++--- .../manager/service/IOrdersCreateService.java | 22 +---- .../service/impl/OrdersCreateServiceImpl.java | 95 ++++++++++++++++++- 4 files changed, 122 insertions(+), 36 deletions(-) diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/Orders.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/Orders.java index 56acf39..0bbcd1a 100644 --- a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/Orders.java +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/Orders.java @@ -3,6 +3,7 @@ package com.jzo2o.orders.base.model.domain; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; @@ -20,6 +21,7 @@ import java.time.LocalDateTime; * @since 2023-08-02 */ @Data +@Builder @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("orders") @@ -79,7 +81,7 @@ public class Orders implements Serializable { private Integer ordersStatus; /** - * 交易状态,0:待支付,1:支付成功 + * 支付状态,2:待支付,4:支付成功 */ private Integer payStatus; @@ -164,7 +166,7 @@ public class Orders implements Serializable { private Integer display; /** - * 排序字段(serve_start_time秒级时间戳+订单id后6位) + * 排序字段(serve_start_time秒级时间戳+订单id后5位) */ private Long sortBy; @@ -196,6 +198,4 @@ public class Orders implements Serializable { * 支付渠道 */ private String tradingChannel; - - -} +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java index fd2c70b..b0e633f 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java @@ -1,16 +1,10 @@ package com.jzo2o.orders.manager.controller.consumer; -import cn.hutool.core.bean.BeanUtil; -import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; -import com.jzo2o.api.orders.dto.request.OrderCancelReqDTO; import com.jzo2o.api.orders.dto.response.OrderResDTO; import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; -import com.jzo2o.common.model.CurrentUserInfo; +import com.jzo2o.common.utils.ObjectUtils; import com.jzo2o.mvc.utils.UserContext; -import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; -import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; -import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; import com.jzo2o.orders.manager.service.IOrdersCreateService; import com.jzo2o.orders.manager.service.IOrdersManagerService; @@ -27,13 +21,14 @@ import java.util.List; * @author itcast */ @RestController("consumerOrdersController") -@Api(tags = "用户端-订单相关接口") +@Api(tags = "用户端 - 订单相关接口") @RequestMapping("/consumer/orders") public class ConsumerOrdersController { - @Resource private IOrdersManagerService ordersManagerService; + @Resource + private IOrdersCreateService ordersCreateService; @GetMapping("/{id}") @ApiOperation("根据订单id查询") @@ -43,14 +38,26 @@ public class ConsumerOrdersController { public OrderResDTO detail(@PathVariable("id") Long id) { return ordersManagerService.getDetail(id); } + @GetMapping("/consumerQueryList") @ApiOperation("订单滚动分页查询") @ApiImplicitParams({ - @ApiImplicitParam(name = "ordersStatus", value = "订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:订单取消,700:已关闭", required = false, dataTypeClass = Integer.class), - @ApiImplicitParam(name = "sortBy", value = "排序字段", required = false, dataTypeClass = Long.class) + @ApiImplicitParam(name = "ordersStatus", value = "订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:订单取消,700:已关闭", dataTypeClass = Integer.class), + @ApiImplicitParam(name = "sortBy", value = "排序字段", dataTypeClass = Long.class) }) public List consumerQueryList(@RequestParam(value = "ordersStatus", required = false) Integer ordersStatus, @RequestParam(value = "sortBy", required = false) Long sortBy) { return ordersManagerService.consumerQueryList(UserContext.currentUserId(), ordersStatus, sortBy); } -} + + @PostMapping("/place") + @ApiOperation("下单接口") + public PlaceOrderResDTO place(@RequestBody PlaceOrderReqDTO placeOrderReqDTO) { + // 默认下单1个服务 + if (ObjectUtils.isEmpty(placeOrderReqDTO.getPurNum())) { + placeOrderReqDTO.setPurNum(1); + } + + return ordersCreateService.placeOrder(placeOrderReqDTO); + } +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java index 0728e0f..58079bd 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java @@ -1,24 +1,10 @@ package com.jzo2o.orders.manager.service; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; -import com.jzo2o.api.market.dto.request.CouponUseBackReqDTO; -import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; -import com.jzo2o.api.orders.dto.response.OrderResDTO; -import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; -import com.jzo2o.common.model.PageResult; -import com.jzo2o.common.model.msg.TradeStatusMsg; import com.jzo2o.orders.base.model.domain.Orders; -import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; -import com.jzo2o.orders.manager.model.dto.request.OrderPageQueryReqDTO; -import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; -import com.jzo2o.orders.manager.model.dto.response.OperationOrdersDetailResDTO; -import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; -import java.util.List; - /** *

* 下单服务类 @@ -28,6 +14,8 @@ import java.util.List; * @since 2023-07-10 */ public interface IOrdersCreateService extends IService { - - -} + /** + * 客户端下单接口 + */ + PlaceOrderResDTO placeOrder(PlaceOrderReqDTO placeOrderReqDTO); +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java index 5863b4c..d8f97e9 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java @@ -1,22 +1,113 @@ package com.jzo2o.orders.manager.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.api.customer.dto.response.AddressBookResDTO; +import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.common.expcetions.ForbiddenOperationException; +import com.jzo2o.common.utils.DateUtils; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.mvc.utils.UserContext; +import com.jzo2o.orders.base.constants.RedisConstants; +import com.jzo2o.orders.base.enums.OrderPayStatusEnum; +import com.jzo2o.orders.base.enums.OrderStatusEnum; import com.jzo2o.orders.base.mapper.OrdersMapper; import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; import com.jzo2o.orders.manager.service.IOrdersCreateService; +import com.jzo2o.orders.manager.service.client.CustomerClient; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; /** *

* 下单服务类 *

- * * @author itcast * @since 2023-07-10 */ @Slf4j @Service public class OrdersCreateServiceImpl extends ServiceImpl implements IOrdersCreateService { + @Resource + private CustomerClient customerClient; + @Resource + private RedisTemplate redisTemplate; + @Resource + private TransactionTemplate transactionTemplate; -} + /** + * 生成订单号(2位年+2位月+2位日+13位序号) + */ + private Long generateOrderId() { + Long idNo = redisTemplate.opsForValue().increment(RedisConstants.Lock.ORDERS_SHARD_KEY_ID_GENERATOR, 1); + String orderId = DateUtils.format(LocalDateTime.now(), "yyMMdd") + String.format("%013d", idNo); + return Long.valueOf(orderId); + } + + @Override + public PlaceOrderResDTO placeOrder(PlaceOrderReqDTO placeOrderReqDTO) { + // 获取下单的基本信息(下单人/地址等) + AddressBookResDTO address = customerClient.getAddressDetail(placeOrderReqDTO.getAddressBookId()); + if (ObjectUtils.isEmpty(address.getId())) { + throw new ForbiddenOperationException("无法获取地址信息下单失败"); + } + // 获取下单的服务信息 + ServeAggregationResDTO serve = customerClient.getServeAggregation(placeOrderReqDTO.getServeId()); + if (ObjectUtils.isEmpty(serve.getId())) { + throw new ForbiddenOperationException("无法获取服务信息下单失败"); + } + // 获取订单id + Long orderId = generateOrderId(); + // TODO 获取优惠卷相关信息 + BigDecimal discountAmount = BigDecimal.ZERO; + // 计算价格 + BigDecimal totalAmount = serve.getPrice().multiply(BigDecimal.valueOf(placeOrderReqDTO.getPurNum())); + BigDecimal realPayAmount = totalAmount.subtract(discountAmount); + + // 组装订单信息插入数据库完成下单 + LocalDateTime serveStartTime = placeOrderReqDTO.getServeStartTime(); + Long sortColumn = DateUtils.toEpochMilli(serveStartTime) * 100000 + orderId % 100000; + Orders orderToPay = Orders.builder() + .id(orderId) + .userId(UserContext.currentUserId()) + .serveTypeId(serve.getServeTypeId()) + .serveTypeName(serve.getServeTypeName()) + .serveItemId(serve.getServeItemId()) + .serveItemName(serve.getServeItemName()) + .serveItemImg(serve.getServeItemImg()) + .unit(serve.getUnit()) + .serveId(serve.getId()) + .ordersStatus(OrderStatusEnum.NO_PAY.getStatus()) + .payStatus(OrderPayStatusEnum.NO_PAY.getStatus()) + .price(serve.getPrice()) + .purNum(placeOrderReqDTO.getPurNum()) + .totalAmount(totalAmount) + .discountAmount(discountAmount) + .realPayAmount(realPayAmount) + .cityCode(serve.getCityCode()) + .serveAddress(address.getAddress()) + .contactsPhone(address.getPhone()) + .contactsName(address.getName()) + .serveStartTime(serveStartTime) + .lon(address.getLon()) + .lat(address.getLat()) + .sortBy(sortColumn).build(); + + // 减小事务管理的颗粒度 + return new PlaceOrderResDTO( + transactionTemplate.execute(status -> { + if (baseMapper.insert(orderToPay) == 0) { + throw new CommonException("下单失败"); + } + return orderToPay.getId(); + })); + } +} \ No newline at end of file From 18ebfcc04f93a0f47992929ef19f49a417f4f428 Mon Sep 17 00:00:00 2001 From: JIAN Date: Sun, 8 Sep 2024 19:20:34 +0800 Subject: [PATCH 06/21] =?UTF-8?q?refactor(trade):=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=94=AF=E4=BB=98=E6=A8=A1=E5=9D=97=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jzo2o-trade/Dockerfile | 8 + jzo2o-trade/pom.xml | 111 +++++++ .../com/jzo2o/trade/TradeApplication.java | 23 ++ .../jzo2o/trade/annotation/PayChannel.java | 17 ++ .../com/jzo2o/trade/config/QRCodeConfig.java | 58 ++++ .../trade/config/RedissonConfiguration.java | 39 +++ .../com/jzo2o/trade/constant/Constants.java | 19 ++ .../trade/constant/TradingCacheConstant.java | 42 +++ .../jzo2o/trade/constant/TradingConstant.java | 71 +++++ .../controller/inner/NativePayController.java | 49 +++ .../inner/RefundRecordController.java | 53 ++++ .../controller/inner/TradingController.java | 84 +++++ .../controller/open/NotifyController.java | 86 ++++++ .../jzo2o/trade/enums/RefundStatusEnum.java | 36 +++ .../com/jzo2o/trade/enums/TradingEnum.java | 66 ++++ .../jzo2o/trade/enums/TradingStateEnum.java | 39 +++ .../jzo2o/trade/handler/BasicPayHandler.java | 45 +++ .../jzo2o/trade/handler/BeforePayHandler.java | 52 ++++ .../jzo2o/trade/handler/HandlerFactory.java | 33 ++ .../jzo2o/trade/handler/JsapiPayHandler.java | 18 ++ .../jzo2o/trade/handler/NativePayHandler.java | 21 ++ .../handler/alipay/AliBasicPayHandler.java | 165 ++++++++++ .../handler/alipay/AliNativePayHandler.java | 63 ++++ .../trade/handler/alipay/AlipayConfig.java | 50 +++ .../handler/impl/BeforePayHandlerImpl.java | 126 ++++++++ .../handler/wechat/WeChatBasicPayHandler.java | 198 ++++++++++++ .../handler/wechat/WechatJsapiPayHandler.java | 117 +++++++ .../wechat/WechatNativePayHandler.java | 67 ++++ .../handler/wechat/WechatPayHttpClient.java | 161 ++++++++++ .../handler/wechat/bean/JsapiPayParam.java | 50 +++ .../wechat/response/WeChatResponse.java | 35 +++ .../java/com/jzo2o/trade/job/TradeJob.java | 163 ++++++++++ .../jzo2o/trade/mapper/PayChannelMapper.java | 13 + .../trade/mapper/RefundRecordMapper.java | 13 + .../com/jzo2o/trade/mapper/TradingMapper.java | 13 + .../jzo2o/trade/model/domain/PayChannel.java | 96 ++++++ .../trade/model/domain/RefundRecord.java | 103 +++++++ .../com/jzo2o/trade/model/domain/Trading.java | 162 ++++++++++ .../jzo2o/trade/model/dto/PayChannelDTO.java | 55 ++++ .../trade/model/dto/RefundRecordDTO.java | 53 ++++ .../com/jzo2o/trade/model/dto/TradingDTO.java | 82 +++++ .../model/dto/request/JsapiPayReqDTO.java | 32 ++ .../model/dto/response/JsapiPayResDTO.java | 26 ++ .../dto/response/TradingStateResDTO.java | 23 ++ .../jzo2o/trade/service/BasicPayService.java | 68 +++++ .../jzo2o/trade/service/JsapiPayService.java | 22 ++ .../jzo2o/trade/service/NativePayService.java | 19 ++ .../jzo2o/trade/service/NotifyService.java | 34 +++ .../trade/service/PayChannelService.java | 60 ++++ .../jzo2o/trade/service/QRCodeService.java | 23 ++ .../trade/service/RefundRecordService.java | 47 +++ .../jzo2o/trade/service/TradingService.java | 60 ++++ .../service/impl/BasicPayServiceImpl.java | 286 ++++++++++++++++++ .../service/impl/JsapiPayServiceImpl.java | 84 +++++ .../service/impl/NativePayServiceImpl.java | 132 ++++++++ .../trade/service/impl/NotifyServiceImpl.java | 188 ++++++++++++ .../service/impl/PayChannelServiceImpl.java | 78 +++++ .../trade/service/impl/QRCodeServiceImpl.java | 51 ++++ .../service/impl/RefundRecordServiceImpl.java | 54 ++++ .../service/impl/TradingServiceImpl.java | 98 ++++++ .../src/main/resources/bootstrap-dev.yml | 17 ++ .../src/main/resources/bootstrap-prod.yml | 16 + .../src/main/resources/bootstrap-test.yml | 16 + jzo2o-trade/src/main/resources/bootstrap.yml | 88 ++++++ .../src/main/resources/logos/alipay.png | Bin 0 -> 1614 bytes .../src/main/resources/logos/wechat.png | Bin 0 -> 2702 bytes 66 files changed, 4277 insertions(+) create mode 100644 jzo2o-trade/Dockerfile create mode 100644 jzo2o-trade/pom.xml create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/TradeApplication.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/annotation/PayChannel.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/config/QRCodeConfig.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/config/RedissonConfiguration.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/constant/Constants.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/constant/TradingCacheConstant.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/constant/TradingConstant.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/NativePayController.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/RefundRecordController.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/TradingController.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/controller/open/NotifyController.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/enums/RefundStatusEnum.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/enums/TradingEnum.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/enums/TradingStateEnum.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/BasicPayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/BeforePayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/HandlerFactory.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/JsapiPayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/NativePayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AliBasicPayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AliNativePayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AlipayConfig.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/impl/BeforePayHandlerImpl.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WeChatBasicPayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatJsapiPayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatNativePayHandler.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatPayHttpClient.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/bean/JsapiPayParam.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/response/WeChatResponse.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/job/TradeJob.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/PayChannelMapper.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/RefundRecordMapper.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/TradingMapper.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/PayChannel.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/RefundRecord.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/Trading.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/PayChannelDTO.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/RefundRecordDTO.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/TradingDTO.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/request/JsapiPayReqDTO.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/response/JsapiPayResDTO.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/response/TradingStateResDTO.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/BasicPayService.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/JsapiPayService.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/NativePayService.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/NotifyService.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/PayChannelService.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/QRCodeService.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/RefundRecordService.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/TradingService.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/BasicPayServiceImpl.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/JsapiPayServiceImpl.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/NativePayServiceImpl.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/NotifyServiceImpl.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/PayChannelServiceImpl.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/QRCodeServiceImpl.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/RefundRecordServiceImpl.java create mode 100644 jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/TradingServiceImpl.java create mode 100644 jzo2o-trade/src/main/resources/bootstrap-dev.yml create mode 100644 jzo2o-trade/src/main/resources/bootstrap-prod.yml create mode 100644 jzo2o-trade/src/main/resources/bootstrap-test.yml create mode 100644 jzo2o-trade/src/main/resources/bootstrap.yml create mode 100644 jzo2o-trade/src/main/resources/logos/alipay.png create mode 100644 jzo2o-trade/src/main/resources/logos/wechat.png diff --git a/jzo2o-trade/Dockerfile b/jzo2o-trade/Dockerfile new file mode 100644 index 0000000..f15b796 --- /dev/null +++ b/jzo2o-trade/Dockerfile @@ -0,0 +1,8 @@ +FROM openjdk:11-jdk +LABEL maintainer="研究院研发组 " +RUN echo "Asia/Shanghai" > /etc/timezone +ARG PACKAGE_PATH=./target/jzo2o-trade.jar + +ADD ${PACKAGE_PATH:-./} app.jar +EXPOSE 11505 +ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS app.jar"] \ No newline at end of file diff --git a/jzo2o-trade/pom.xml b/jzo2o-trade/pom.xml new file mode 100644 index 0000000..59bf080 --- /dev/null +++ b/jzo2o-trade/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + + jzo2o-trade + 1.0-SNAPSHOT + + + jzo2o-parent + com.jzo2o + 1.0-SNAPSHOT + + + + 11 + 11 + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + org.springframework.cloud + spring-cloud-starter-bootstrap + + + com.jzo2o + jzo2o-mvc + + + + com.jzo2o + jzo2o-knife4j-web + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.jzo2o + jzo2o-api + + + + com.jzo2o + jzo2o-mysql + + + com.jzo2o + jzo2o-xxl-job + + + com.jzo2o + jzo2o-rabbitmq + + + com.jzo2o + jzo2o-redis + + + + com.alipay.sdk + alipay-easysdk + 2.2.2 + + + com.github.wechatpay-apiv3 + wechatpay-apache-httpclient + 0.4.7 + + + + com.google.zxing + core + 3.5.0 + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + build-info + + + + + com.jzo2o.trade.TradeApplication + + + + + \ No newline at end of file diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/TradeApplication.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/TradeApplication.java new file mode 100644 index 0000000..c1f714d --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/TradeApplication.java @@ -0,0 +1,23 @@ +package com.jzo2o.trade; + +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +/** + * @author itcast + */ +@Slf4j +@MapperScan("com.jzo2o.trade.mapper") +@SpringBootApplication +public class TradeApplication { + public static void main(String[] args) { + new SpringApplicationBuilder(TradeApplication.class) + .build(args) + .run(args); + log.info("家政服务-支付服务启动"); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/annotation/PayChannel.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/annotation/PayChannel.java new file mode 100644 index 0000000..57251f0 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/annotation/PayChannel.java @@ -0,0 +1,17 @@ +package com.jzo2o.trade.annotation; + +import com.jzo2o.api.trade.enums.PayChannelEnum; + +import java.lang.annotation.*; + +/** + * @author itcast + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented //标记注解 +public @interface PayChannel { + + PayChannelEnum type(); + +} \ No newline at end of file diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/config/QRCodeConfig.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/config/QRCodeConfig.java new file mode 100644 index 0000000..1f97181 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/config/QRCodeConfig.java @@ -0,0 +1,58 @@ +package com.jzo2o.trade.config; + +import cn.hutool.core.img.ImgUtil; +import cn.hutool.core.io.resource.ResourceUtil; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.awt.*; + +/** + * 二维码生成参数配置 + * + * @author zzj + * @version 1.0 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "jzo2o.qrcode") +public class QRCodeConfig { + + private static Image WECHAT_LOGO; + private static Image ALIPAY_LOGO; + + static { + WECHAT_LOGO = ImgUtil.read(ResourceUtil.getResource("logos/wechat.png")); + ALIPAY_LOGO = ImgUtil.read(ResourceUtil.getResource("logos/alipay.png")); + } + + //边距,二维码和背景之间的边距 + private Integer margin = 2; + // 二维码颜色,默认黑色 + private String foreColor = "#000000"; + //背景色,默认白色 + private String backColor = "#ffffff"; + //纠错级别,可选参数:L、M、Q、H,默认:M + //低级别的像素块更大,可以远距离识别,但是遮挡就会造成无法识别。高级别则相反,像素块小,允许遮挡一定范围,但是像素块更密集。 + private String errorCorrectionLevel = "M"; + //宽 + private Integer width = 300; + //高 + private Integer height = 300; + + public Image getLogo(PayChannelEnum payChannelEnum) { + switch (payChannelEnum) { + case ALI_PAY: { + return ALIPAY_LOGO; + } + case WECHAT_PAY: { + return WECHAT_LOGO; + } + default: { + return null; + } + } + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/config/RedissonConfiguration.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/config/RedissonConfiguration.java new file mode 100644 index 0000000..33bde07 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/config/RedissonConfiguration.java @@ -0,0 +1,39 @@ +//package com.jzo2o.trade.config; +// +//import cn.hutool.core.convert.Convert; +//import cn.hutool.core.util.StrUtil; +//import lombok.Data; +//import org.redisson.Redisson; +//import org.redisson.api.RedissonClient; +//import org.redisson.config.Config; +//import org.redisson.config.SingleServerConfig; +//import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +//import org.springframework.boot.context.properties.EnableConfigurationProperties; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +// +//import javax.annotation.Resource; +// +//@Configuration +//@EnableConfigurationProperties(RedisProperties.class) +//@Data +//public class RedissonConfiguration { +// +// @Resource +// private RedisProperties redisProperties; +// +// @Bean +// public RedissonClient redissonSingle() { +// Config config = new Config(); +// SingleServerConfig serverConfig = config.useSingleServer() +// .setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort()); +// if (null != (redisProperties.getTimeout())) { +// serverConfig.setTimeout(1000 * Convert.toInt(redisProperties.getTimeout().getSeconds())); +// } +// if (StrUtil.isNotEmpty(redisProperties.getPassword())) { +// serverConfig.setPassword(redisProperties.getPassword()); +// } +// return Redisson.create(config); +// } +// +//} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/Constants.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/Constants.java new file mode 100644 index 0000000..9cd0e3d --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/Constants.java @@ -0,0 +1,19 @@ +package com.jzo2o.trade.constant; + +/** + * 静态变量 + * + * @author zzj + * @version 1.0 + */ +public interface Constants { + /** + * 常量是 + */ + String YES = "YES"; + + /** + * 常量否 + */ + String NO = "NO"; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/TradingCacheConstant.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/TradingCacheConstant.java new file mode 100644 index 0000000..ec77457 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/TradingCacheConstant.java @@ -0,0 +1,42 @@ +package com.jzo2o.trade.constant; + +/** + * @ClassName TradingCacheConstant.java + * @Description 交易缓存维护 + */ +public class TradingCacheConstant { + + //默认redis等待时间 + public static final int REDIS_WAIT_TIME = 5; + + //默认redis自动释放时间 + public static final int REDIS_LEASETIME = 4; + + //安全组前缀 + public static final String PREFIX = "trading:"; + + //分布式锁前缀 + public static final String LOCK_PREFIX = PREFIX + "lock:"; + + //创建交易加锁 + public static final String CREATE_PAY = LOCK_PREFIX + "create_pay"; + + //查询交易状态加锁 + public static final String QUERY_PAY = LOCK_PREFIX + "query_pay"; + + //创建退款加锁 + public static final String REFUND_PAY = LOCK_PREFIX + "refund_pay"; + + //退款查询加锁 + public static final String REFUND_QUERY_PAY = LOCK_PREFIX + "refund_query_pay"; + + //创建退款加锁 + public static final String PAY_CHANNEL_LIST = PREFIX + "pay_channel_list&ttl=-1"; + + //创建退款加锁 + public static final String CLOSE_PAY = LOCK_PREFIX + "close_pay"; + + + //page分页 + public static final String PAGE = PREFIX + "page"; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/TradingConstant.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/TradingConstant.java new file mode 100644 index 0000000..9ac4afa --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/constant/TradingConstant.java @@ -0,0 +1,71 @@ +package com.jzo2o.trade.constant; + +import com.jzo2o.api.trade.enums.PayChannelEnum; + +/** + * @ClassName TardingConstant.java + * @Description 交易常量类 + */ +public class TradingConstant { + + //【阿里云退款返回状态】 + //REFUND_SUCCESS:成功 + public static final String REFUND_SUCCESS = "REFUND_SUCCESS"; + + //【阿里云返回付款状态】 + //TRADE_CLOSED:未付款交易超时关闭,或支付完成后全额退款 + public static final String ALI_TRADE_CLOSED = "TRADE_CLOSED"; + //TRADE_SUCCESS:交易支付成功 + public static final String ALI_TRADE_SUCCESS = "TRADE_SUCCESS"; + //TRADE_FINISHED:交易结束不可退款 + public static final String ALI_TRADE_FINISHED = "TRADE_FINISHED"; + + + //【微信退款返回状态】 + //SUCCESS:退款成功 + public static final String WECHAT_REFUND_SUCCESS = "SUCCESS"; + //CLOSED:退款关闭 + public static final String WECHAT_REFUND_CLOSED = "CLOSED"; + //PROCESSING:退款处理中 + public static final String WECHAT_REFUND_PROCESSING = "PROCESSING"; + //ABNORMAL:退款异常 + public static final String WECHAT_REFUND_ABNORMAL = "TRADE_CLOSED"; + + //【微信返回付款状态】 + //SUCCESS:支付成功 + public static final String WECHAT_TRADE_SUCCESS = "SUCCESS"; + //REFUND:转入退款 + public static final String WECHAT_TRADE_REFUND = "REFUND"; + //NOTPAY:未支付 + public static final String WECHAT_TRADE_NOTPAY = "NOTPAY"; + //CLOSED:已关闭 + public static final String WECHAT_TRADE_CLOSED = "CLOSED"; + //REVOKED:已撤销(仅付款码支付会返回) + public static final String WECHAT_TRADE_REVOKED = "REVOKED"; + //USERPAYING:用户支付中(仅付款码支付会返回) + public static final String WECHAT_TRADE_USERPAYING = "USERPAYING"; + //PAYERROR:支付失败(仅付款码支付会返回) + public static final String WECHAT_TRADE_PAYERROR = "PAYERROR"; + + //【平台:交易渠道】 + //阿里支付 + public static final String TRADING_CHANNEL_ALI_PAY = PayChannelEnum.ALI_PAY.name(); + //微信支付 + public static final String TRADING_CHANNEL_WECHAT_PAY = PayChannelEnum.WECHAT_PAY.name(); + //现金 + public static final String TRADING_CHANNEL_CASH_PAY = "CASH_PAY"; + //免单挂账【信用渠道】 + public static final String TRADING_CHANNEL_CREDIT_PAY = "CREDIT_PAY"; + + //【平台:交易动作】 + //付款 + public static final String TRADING_TYPE_FK = "FK"; + //退款 + public static final String TRADING_TYPE_TK = "TK"; + //免单 + public static final String TRADING_TYPE_MD = "MD"; + //挂账 + public static final String TRADING_TYPE_GZ = "GZ"; + + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/NativePayController.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/NativePayController.java new file mode 100644 index 0000000..5290b23 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/NativePayController.java @@ -0,0 +1,49 @@ +package com.jzo2o.trade.controller.inner; + +import cn.hutool.core.bean.BeanUtil; +import com.jzo2o.api.trade.NativePayApi; +import com.jzo2o.api.trade.dto.request.NativePayReqDTO; +import com.jzo2o.api.trade.dto.response.NativePayResDTO; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.service.NativePayService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * Native支付方式Face接口:商户生成二维码,用户扫描支付 + * + * @author itcast + */ +@Validated +@RestController("innerNativePayController") +@Api(tags = "内部接口 - Native支付") +@RequestMapping("/inner/native") +public class NativePayController implements NativePayApi { + + @Resource + private NativePayService nativePayService; + + /*** + * 扫码支付,收银员通过收银台或商户后台调用此接口,生成二维码后,展示给用户,由用户扫描二维码完成订单支付。 + * + * @param nativePayDTO 扫码支付提交参数 + * @return 扫码支付响应数据,其中包含二维码路径 + */ + @Override + @PostMapping + @ApiOperation(value = "统一收单线下交易", notes = "统一收单线下交易") + @ApiImplicitParam(name = "nativePayDTO", value = "扫码支付提交参数", required = true) + public NativePayResDTO createDownLineTrading(@RequestBody NativePayReqDTO nativePayDTO) { + Trading tradingEntity = BeanUtil.toBean(nativePayDTO, Trading.class); + Trading trading = this.nativePayService.createDownLineTrading(nativePayDTO.isChangeChannel(),tradingEntity); + return BeanUtil.toBean(trading, NativePayResDTO.class); + } + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/RefundRecordController.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/RefundRecordController.java new file mode 100644 index 0000000..633d168 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/RefundRecordController.java @@ -0,0 +1,53 @@ +package com.jzo2o.trade.controller.inner; + +import cn.hutool.core.bean.BeanUtil; +import com.jzo2o.api.trade.RefundRecordApi; +import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.service.BasicPayService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.math.BigDecimal; + +/** + * 基础支付控制器 + * + * @author itcast + */ +@RequestMapping("/inner/refund-record") +@RestController("innerRefundRecordController") +@Api(tags = "内部接口 - 退款") +public class RefundRecordController implements RefundRecordApi { + + @Resource + private BasicPayService basicPayService; + + /*** + * 统一收单交易退款接口 + * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家, + * 将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。 + * @param tradingOrderNo 交易单号 + * @param refundAmount 退款金额 + * @return + */ + @Override + @PostMapping("refund") + @ApiOperation(value = "统一收单交易退款", notes = "统一收单交易退款") + @ApiImplicitParams({ + @ApiImplicitParam(name = "tradingOrderNo", value = "交易单号", required = true), + @ApiImplicitParam(name = "refundAmount", value = "退款金额", required = true) + }) + public ExecutionResultResDTO refundTrading(@RequestParam("tradingOrderNo") Long tradingOrderNo, + @RequestParam("refundAmount") BigDecimal refundAmount) { + RefundRecord refundRecord = this.basicPayService.refundTrading(tradingOrderNo, refundAmount); + return BeanUtil.toBean(refundRecord,ExecutionResultResDTO.class); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/TradingController.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/TradingController.java new file mode 100644 index 0000000..5f57172 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/inner/TradingController.java @@ -0,0 +1,84 @@ +package com.jzo2o.trade.controller.inner; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import com.jzo2o.api.trade.TradingApi; +import com.jzo2o.api.trade.dto.response.TradingResDTO; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.model.dto.TradingDTO; +import com.jzo2o.trade.service.BasicPayService; +import com.jzo2o.trade.service.TradingService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +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; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author zzj + * @version 1.0 + */ +@RestController("innerTradingController") +@Api(tags = "内部接口 - 交易单服务") +@RequestMapping("/inner/tradings") +public class TradingController implements TradingApi { + + @Resource + private TradingService tradingService; + @Resource + private BasicPayService basicPayService; + +// /** +// * 根据订单号查询已结算交易单 +// * +// * @param productOrderNo 订单号 +// * @return 交易单数据 +// */ +// @Override +// @GetMapping("/findYjsTradByProductOrderNo") +// @ApiOperation(value = "根据订单号查询已结算交易单", notes = "根据业务订单号查询交易单") +// @ApiImplicitParams({ +// @ApiImplicitParam(name = "productOrderNo", value = "业务订单号", required = true, dataTypeClass = Long.class) +// }) +// public TradingResDTO findYjsTradByProductOrderNo(@RequestParam("productOrderNo") Long productOrderNo) { +// List yjsTradByProductOrderNo = tradingService.findYjsTradByProductOrderNo(productOrderNo); +// if(ObjectUtil.isNotEmpty(yjsTradByProductOrderNo)){ +// Trading trading = yjsTradByProductOrderNo.get(0); +// return BeanUtil.toBean(trading, TradingResDTO.class); +// } +// return null; +// } + +// @Override +// @GetMapping("/findTradByTradingOrderNo") +// @ApiOperation(value = "根据交易单号查询交易单", notes = "根据交易单号查询交易单") +// @ApiImplicitParams({ +// @ApiImplicitParam(name = "tradingOrderNo", value = "交易单号", required = true, dataTypeClass = Long.class) +// }) +// public TradingResDTO findTradByTradingOrderNo(Long tradingOrderNo) { +// Trading tradByTradingOrderNo = tradingService.findTradByTradingOrderNo(tradingOrderNo); +// TradingResDTO tradingResDTO = BeanUtil.toBean(tradByTradingOrderNo, TradingResDTO.class); +// return tradingResDTO; +// } + + @Override + @GetMapping("/findTradResultByTradingOrderNo") + @ApiOperation(value = "根据交易单号查询交易单的交易结果", notes = "根据交易单号查询交易单的交易结果") + @ApiImplicitParams({ + @ApiImplicitParam(name = "tradingOrderNo", value = "交易单号", required = true, dataTypeClass = Long.class) + }) + public TradingResDTO findTradResultByTradingOrderNo(Long tradingOrderNo) { + TradingDTO tradingDTO = basicPayService.queryTradingResult(tradingOrderNo); + TradingResDTO tradingResDTO = BeanUtil.toBean(tradingDTO, TradingResDTO.class); + return tradingResDTO; + } + + + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/open/NotifyController.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/open/NotifyController.java new file mode 100644 index 0000000..317ae10 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/controller/open/NotifyController.java @@ -0,0 +1,86 @@ +package com.jzo2o.trade.controller.open; + +import cn.hutool.core.map.MapUtil; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.service.NotifyService; +import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest; +import io.swagger.annotations.Api; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * 支付结果的通知 + */ +@RestController("openNotifyController") +@Api(tags = "白名单接口 - 支付通知") +@RequestMapping("/open/notify") +public class NotifyController { + + @Resource + private NotifyService notifyService; + + /** + * 微信支付成功回调(成功后无需响应内容) + * + * @param httpEntity 微信请求信息 + * @param enterpriseId 商户id + * @return 正常响应200,否则响应500 + */ + @PostMapping("wx/{enterpriseId}") + public ResponseEntity wxPayNotify(HttpEntity httpEntity, @PathVariable("enterpriseId") Long enterpriseId) { + try { + //获取请求头 + HttpHeaders headers = httpEntity.getHeaders(); + + //构建微信请求数据对象 + NotificationRequest request = new NotificationRequest.Builder() + .withSerialNumber(headers.getFirst("Wechatpay-Serial")) //证书序列号(微信平台) + .withNonce(headers.getFirst("Wechatpay-Nonce")) //随机串 + .withTimestamp(headers.getFirst("Wechatpay-Timestamp")) //时间戳 + .withSignature(headers.getFirst("Wechatpay-Signature")) //签名字符串 + .withBody(httpEntity.getBody()) + .build(); + + //微信通知的业务处理 + this.notifyService.wxPayNotify(request, enterpriseId); + + } catch (CommonException e) { + Map result = MapUtil.builder() + .put("code", "FAIL") + .put("message", e.getMessage()) + .build(); + //响应500 + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result); + } + return ResponseEntity.ok(null); + } + + /** + * 支付宝支付成功回调(成功后需要响应success) + * + * @param enterpriseId 商户id + * @return 正常响应200,否则响应500 + */ + @PostMapping("alipay/{enterpriseId}") + public ResponseEntity aliPayNotify(HttpServletRequest request, + @PathVariable("enterpriseId") Long enterpriseId) { + try { + //支付宝通知的业务处理 + this.notifyService.aliPayNotify(request, enterpriseId); + } catch (CommonException e) { + //响应500 + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + return ResponseEntity.ok("success"); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/RefundStatusEnum.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/RefundStatusEnum.java new file mode 100644 index 0000000..6e5730e --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/RefundStatusEnum.java @@ -0,0 +1,36 @@ +package com.jzo2o.trade.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * 退款状态枚举 + * + * @author zzj + * @version 1.0 + */ +public enum RefundStatusEnum { + + APPLY_REFUND(0, "发起退款"), + SENDING(1, "退款中"), + SUCCESS(2, "成功"), + FAIL(3, "失败"); + + @EnumValue + @JsonValue + private final Integer code; + private final String value; + + RefundStatusEnum(Integer code, String value) { + this.code = code; + this.value = value; + } + + public Integer getCode() { + return this.code; + } + + public String getValue() { + return this.value; + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/TradingEnum.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/TradingEnum.java new file mode 100644 index 0000000..a311c13 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/TradingEnum.java @@ -0,0 +1,66 @@ +package com.jzo2o.trade.enums; + +/** + * 交易枚举 + */ +public enum TradingEnum { + + SUCCEED(1001, 200, "操作成功"), + ERROR(1002, "操作失败"), + CHECK_TRADING_FAIL(1003, "交易单校验失败"), + TRY_LOCK_TRADING_FAIL(1004, "交易单加锁失败"), + PAYING_TRADING_FAIL(1005, "交易单支付失败"), + TRADING_STATE_SUCCEED(1006, "交易单已完成"), + TRADING_STATE_PAYING(1007, "交易单交易中"), + CONFIG_EMPTY(1008, "支付配置为空"), + CONFIG_ERROR(1009, "支付配置错误"), + NATIVE_PAY_FAIL(1010, "统一下单交易失败"), + NATIVE_QRCODE_FAIL(1011, "生成二维码失败"), + REFUND_FAIL(1012, "查询统一下单交易退款失败"), + SAVE_OR_UPDATE_FAIL(1013, "交易单保存或修改失败"), + TRADING_TYPE_FAIL(1014, "未定义的交易类型"), + NATIVE_QUERY_FAIL(1015, "查询统一下单交易失败"), + NATIVE_REFUND_FAIL(1016, "统一下单退款交易失败"), + NATIVE_QUERY_REFUND_FAIL(1017, "统一下单查询退款失败"), + CASH_PAY_FAIL(1018, "现金交易失败"), + CASH_REFUND_FAIL(1019, "统一下单退款交易失败"), + CREDIT_PAY_FAIL(1020, "信用交易失败"), + LIST_TRADE_STATE_FAIL(1021, "按交易状态查询交易单失败"), + NOT_FOUND(1022, "交易单不存在"), + CLOSE_FAIL(1023, "关闭交易单失败"), + BASIC_REFUND_OUT_FAIL(1024, "退款金额超过订单总金额"), + REFUND_NOT_FOUND(1025, "退款记录不存在"), + REFUND_ALREADY_COMPLETED(1026, "退款记录已经完成"), + BASIC_REFUND_COUNT_OUT_FAIL(1027, "退款次数超出限制,最多20次"), + TRADING_QUERY_PARAM_ERROR(1028, "查询交易单错误,交易单号为空"), + REFUND_QUERY_PARAM_ERROR(1029, "查询退款单错误,订单号或交易单号至少传递一个"), + REFUND_DURING(1030, "退款进行中"); + + private final Integer code; + private final Integer status; + private final String value; + + TradingEnum(Integer code, String value) { + this.code = code; + this.value = value; + this.status = 500; + } + + TradingEnum(Integer code, Integer status, String value) { + this.code = code; + this.value = value; + this.status = status; + } + + public Integer getCode() { + return code; + } + + public String getValue() { + return this.value; + } + + public Integer getStatus() { + return this.status; + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/TradingStateEnum.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/TradingStateEnum.java new file mode 100644 index 0000000..5f2acc6 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/enums/TradingStateEnum.java @@ -0,0 +1,39 @@ +package com.jzo2o.trade.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * 交易单状态枚举 + * + * @author zzj + * @version 1.0 + */ +public enum TradingStateEnum{ + +// DFK(1, "待付款"), + FKZ(2, "付款中"), + FKSB(3, "付款失败"), + YJS(4, "已付款"), + QXDD(5, "取消订单"), + MD(6, "免单"), + GZ(7, "挂账"); + + @EnumValue + @JsonValue + private final Integer code; + private final String value; + + TradingStateEnum(Integer code, String value) { + this.code = code; + this.value = value; + } + + public Integer getCode() { + return this.code; + } + + public String getValue() { + return this.value; + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/BasicPayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/BasicPayHandler.java new file mode 100644 index 0000000..163a955 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/BasicPayHandler.java @@ -0,0 +1,45 @@ +package com.jzo2o.trade.handler; + +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.model.domain.Trading; + +/** + * 基础支付功能的定义,具体业务由不同的支付渠道实现 + * + * @author zzj + * @version 1.0 + */ +public interface BasicPayHandler { + + /*** + * 统一收单线下交易查询 + * 该接口提供所有支付订单的查询,商户可以通过该接口主动查询订单状态,完成下一步的业务逻辑。 + * @return 是否有变化 + */ + Boolean queryTrading(Trading trading) throws CommonException; + + /*** + * 关闭交易 + * @return 是否成功 + */ + Boolean closeTrading(Trading trading) throws CommonException; + + /*** + * 统一收单交易退款接口 + * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家, + * 将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。 + * @param refundRecord 退款记录对象 + * @return 是否有变化 + */ + Boolean refundTrading(RefundRecord refundRecord) throws CommonException; + + /*** + * 统一收单交易退款查询接口 + * + * @param refundRecord 退款交易单号 + * @return 是否有变化 + */ + Boolean queryRefundTrading(RefundRecord refundRecord) throws CommonException; + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/BeforePayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/BeforePayHandler.java new file mode 100644 index 0000000..2820b74 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/BeforePayHandler.java @@ -0,0 +1,52 @@ +package com.jzo2o.trade.handler; + +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.model.dto.TradingDTO; + +import java.math.BigDecimal; + +/** + * 交易前置处理接口 + * + * @author itcast + */ +public interface BeforePayHandler { + + + + /*** + * 交易单参数校验 + * @param tradingEntity 交易订单 + * @return 是否符合要求 + */ + void checkCreateTrading(Trading tradingEntity); + + /*** + * QueryTrading交易单参数校验 + * @param trading 交易订单 + */ + void checkQueryTrading(Trading trading); + + + /*** + * RefundTrading退款交易单参数校验 + * @param trading 交易订单 + * @param refundAmount 退款金额 + */ + void checkRefundTrading(Trading trading,BigDecimal refundAmount); + + + /*** + * QueryRefundTrading交易单参数校验 + * @param refundRecord 退款记录 + */ + void checkQueryRefundTrading(RefundRecord refundRecord); + + /*** + * CloseTrading交易单参数校验 + * @param trading 交易订单 + */ + void checkCloseTrading(Trading trading); +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/HandlerFactory.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/HandlerFactory.java new file mode 100644 index 0000000..275d619 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/HandlerFactory.java @@ -0,0 +1,33 @@ +package com.jzo2o.trade.handler; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.jzo2o.trade.annotation.PayChannel; +import com.jzo2o.api.trade.enums.PayChannelEnum; + +import java.util.Map; + +/** + * Handler工厂,用于获取指定类型的具体渠道的实例对象 + */ +public class HandlerFactory { + + private HandlerFactory() { + + } + + public static T get(PayChannelEnum payChannel, Class handler) { + Map beans = SpringUtil.getBeansOfType(handler); + for (Map.Entry entry : beans.entrySet()) { + PayChannel payChannelAnnotation = entry.getValue().getClass().getAnnotation(PayChannel.class); + if (ObjectUtil.isNotEmpty(payChannelAnnotation) && ObjectUtil.equal(payChannel, payChannelAnnotation.type())) { + return entry.getValue(); + } + } + return null; + } + + public static T get(String payChannel, Class handler) { + return get(PayChannelEnum.valueOf(payChannel), handler); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/JsapiPayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/JsapiPayHandler.java new file mode 100644 index 0000000..1b3699b --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/JsapiPayHandler.java @@ -0,0 +1,18 @@ +package com.jzo2o.trade.handler; + +import com.jzo2o.trade.model.domain.Trading; + +/** + * jsapi下单处理 + * + * @author itcast + */ +public interface JsapiPayHandler { + + /** + * 创建交易 + * + * @param tradingEntity 交易单 + */ + void createJsapiTrading(Trading tradingEntity); +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/NativePayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/NativePayHandler.java new file mode 100644 index 0000000..9a86e64 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/NativePayHandler.java @@ -0,0 +1,21 @@ +package com.jzo2o.trade.handler; + +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.model.domain.Trading; + +/** + * @author itcast + * @ClassName NativePayHandler.java + * @Description Native支付方式Handler:商户生成二维码,用户扫描支付 + */ +public interface NativePayHandler { + + + /*** + * @description 统一收单线下交易预创建 + * 收银员通过收银台或商户后台调用此接口,生成二维码后,展示给用户,由用户扫描二维码完成订单支付。 + * @param tradingEntity 交易单 + */ + void createDownLineTrading(Trading tradingEntity) throws CommonException; + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AliBasicPayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AliBasicPayHandler.java new file mode 100644 index 0000000..a0905c9 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AliBasicPayHandler.java @@ -0,0 +1,165 @@ +package com.jzo2o.trade.handler.alipay; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.alipay.easysdk.factory.Factory; +import com.alipay.easysdk.kernel.Config; +import com.alipay.easysdk.kernel.util.ResponseChecker; +import com.alipay.easysdk.payment.common.models.AlipayTradeCloseResponse; +import com.alipay.easysdk.payment.common.models.AlipayTradeFastpayRefundQueryResponse; +import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse; +import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.annotation.PayChannel; +import com.jzo2o.trade.constant.TradingConstant; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.enums.RefundStatusEnum; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.BasicPayHandler; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.model.domain.Trading; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 支付宝基础支付功能的实现 + * + * @author zzj + * @version 1.0 + */ +@Slf4j +@Component("aliBasicPayHandler") +@PayChannel(type = PayChannelEnum.ALI_PAY) +public class AliBasicPayHandler implements BasicPayHandler { + + @Override + public Boolean queryTrading(Trading trading) throws CommonException { + //查询配置 + Config config = AlipayConfig.getConfig(trading.getEnterpriseId()); + //Factory使用配置 + Factory.setOptions(config); + AlipayTradeQueryResponse queryResponse; + try { + //调用支付宝API:通用查询支付情况 + queryResponse = Factory + .Payment + .Common() + .query(String.valueOf(trading.getTradingOrderNo())); + } catch (Exception e) { + String msg = StrUtil.format("查询支付宝统一下单失败:trading = {}", trading); + log.error(msg, e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_FAIL.getValue()); + } + + //修改交易单状态 + trading.setTransactionId(queryResponse.getTradeNo()); + trading.setResultCode(queryResponse.getSubCode()); + trading.setResultMsg(queryResponse.getSubMsg()); + trading.setResultJson(JSONUtil.toJsonStr(queryResponse)); + + boolean success = ResponseChecker.success(queryResponse); + //响应成功,分析交易状态 + if (success) { + String tradeStatus = queryResponse.getTradeStatus(); + if (StrUtil.equals(TradingConstant.ALI_TRADE_CLOSED, tradeStatus)) { + //支付取消:TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款) + trading.setTradingState(TradingStateEnum.QXDD); + } else if (StrUtil.equalsAny(tradeStatus, TradingConstant.ALI_TRADE_SUCCESS, TradingConstant.ALI_TRADE_FINISHED)) { + // TRADE_SUCCESS(交易支付成功) + // TRADE_FINISHED(交易结束,不可退款) + trading.setTradingState(TradingStateEnum.YJS); + } else { + //非最终状态不处理,当前交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)不处理 + return false; + } + return true; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_FAIL.getValue()); + } + + @Override + public Boolean closeTrading(Trading trading) throws CommonException { + //查询配置 + Config config = AlipayConfig.getConfig(trading.getEnterpriseId()); + //Factory使用配置 + Factory.setOptions(config); + try { + //调用支付宝API:通用查询支付情况 + AlipayTradeCloseResponse closeResponse = Factory + .Payment + .Common() + .close(String.valueOf(trading.getTradingOrderNo())); + boolean success = ResponseChecker.success(closeResponse); + if (success) { + trading.setTradingState(TradingStateEnum.QXDD); + return true; + } + return false; + } catch (Exception e) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.CLOSE_FAIL.getValue()); + } + } + + @Override + public Boolean refundTrading(RefundRecord refundRecord) throws CommonException { + //查询配置 + Config config = AlipayConfig.getConfig(refundRecord.getEnterpriseId()); + //Factory使用配置 + Factory.setOptions(config); + //调用支付宝API:通用查询支付情况 + AlipayTradeRefundResponse refundResponse; + try { + // 支付宝easy sdk + refundResponse = Factory + .Payment + .Common() + //扩展参数:退款单号 + .optional("out_request_no", refundRecord.getRefundNo()) + .refund(Convert.toStr(refundRecord.getTradingOrderNo()), + Convert.toStr(refundRecord.getRefundAmount())); + } catch (Exception e) { + String msg = StrUtil.format("调用支付宝退款接口出错!refundRecord = {}", refundRecord); + log.error(msg, e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, msg); + } + refundRecord.setRefundId(null); + refundRecord.setRefundCode(refundResponse.getSubCode()); + refundRecord.setRefundMsg(JSONUtil.toJsonStr(refundResponse)); + boolean success = ResponseChecker.success(refundResponse); + if (success) { + refundRecord.setRefundStatus(RefundStatusEnum.SUCCESS); + return true; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_REFUND_FAIL.getValue()); + } + + @Override + public Boolean queryRefundTrading(RefundRecord refundRecord) throws CommonException { + //查询配置 + Config config = AlipayConfig.getConfig(refundRecord.getEnterpriseId()); + //Factory使用配置 + Factory.setOptions(config); + AlipayTradeFastpayRefundQueryResponse response; + try { + response = Factory.Payment.Common().queryRefund( + Convert.toStr(refundRecord.getTradingOrderNo()), + Convert.toStr(refundRecord.getRefundNo())); + } catch (Exception e) { + log.error("调用支付宝查询退款接口出错!refundRecord = {}", refundRecord, e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_REFUND_FAIL.getValue()); + } + + refundRecord.setRefundCode(response.getSubCode()); + refundRecord.setRefundMsg(JSONUtil.toJsonStr(response)); + boolean success = ResponseChecker.success(response); + if (success) { + refundRecord.setRefundStatus(RefundStatusEnum.SUCCESS); + return true; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_REFUND_FAIL.getValue()); + } + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AliNativePayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AliNativePayHandler.java new file mode 100644 index 0000000..55b118f --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AliNativePayHandler.java @@ -0,0 +1,63 @@ +package com.jzo2o.trade.handler.alipay; + +import cn.hutool.core.convert.Convert; +import cn.hutool.json.JSONUtil; +import com.alipay.easysdk.factory.Factory; +import com.alipay.easysdk.kernel.Config; +import com.alipay.easysdk.kernel.util.ResponseChecker; +import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.annotation.PayChannel; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.NativePayHandler; +import com.jzo2o.trade.model.domain.Trading; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 支付宝的扫描支付的具体实现 + */ +@Slf4j +@Component("aliNativePayHandler") +@PayChannel(type = PayChannelEnum.ALI_PAY) +public class AliNativePayHandler implements NativePayHandler { + + @Override + public void createDownLineTrading(Trading tradingEntity) throws CommonException { + //查询配置 + Config config = AlipayConfig.getConfig(tradingEntity.getEnterpriseId()); + //Factory使用配置 + Factory.setOptions(config); + AlipayTradePrecreateResponse response; + try { + //调用支付宝API面对面支付 + response = Factory + .Payment + .FaceToFace() + .preCreate(tradingEntity.getMemo(), //订单描述 + Convert.toStr(tradingEntity.getTradingOrderNo()), //业务订单号 + Convert.toStr(tradingEntity.getTradingAmount())); //金额 + } catch (Exception e) { + log.error("支付宝统一下单创建失败:tradingEntity = {}", tradingEntity, e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } + + //受理结果【只表示请求是否成功,而不是支付是否成功】 + boolean isSuccess = ResponseChecker.success(response); + //6.1、受理成功:修改交易单 + if (isSuccess) { + String subCode = response.getSubCode(); + String subMsg = response.getQrCode(); + tradingEntity.setPlaceOrderCode(subCode); //返回的编码 + tradingEntity.setPlaceOrderMsg(subMsg); //二维码需要展现的信息 + tradingEntity.setPlaceOrderJson(JSONUtil.toJsonStr(response)); + tradingEntity.setTradingState(TradingStateEnum.FKZ); + return; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AlipayConfig.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AlipayConfig.java new file mode 100644 index 0000000..bc1df33 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/alipay/AlipayConfig.java @@ -0,0 +1,50 @@ +package com.jzo2o.trade.handler.alipay; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.alipay.easysdk.kernel.Config; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.constant.TradingConstant; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.model.domain.PayChannel; +import com.jzo2o.trade.service.PayChannelService; + +/** + * @author zzj + * @version 1.0 + */ +public class AlipayConfig { + + /** + * 将支付渠道配置转化为支付宝的配置 + * + * @param enterpriseId 商户ID + * @return 支付宝的配置 + */ + public static Config getConfig(Long enterpriseId) { + // 查询配置 + PayChannelService payChannelService = SpringUtil.getBean(PayChannelService.class); + PayChannel payChannel = payChannelService.findByEnterpriseId(enterpriseId, TradingConstant.TRADING_CHANNEL_ALI_PAY); + + if (ObjectUtil.isEmpty(payChannel)) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.CONFIG_EMPTY.getValue()); + } + + Config config = new Config(); + config.protocol = "https"; + config.gatewayHost = payChannel.getDomain(); + config.signType = "RSA2"; + config.appId = payChannel.getAppId(); + //配置应用私钥 + config.merchantPrivateKey = payChannel.getMerchantPrivateKey(); + //配置支付宝公钥 + config.alipayPublicKey = payChannel.getPublicKey(); + //可设置异步通知接收服务地址(可选) + config.notifyUrl = payChannel.getNotifyUrl(); + //设置AES密钥,调用AES加解密相关接口时需要(可选) + config.encryptKey = payChannel.getEncryptKey(); + return config; + } + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/impl/BeforePayHandlerImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/impl/BeforePayHandlerImpl.java new file mode 100644 index 0000000..16d974e --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/impl/BeforePayHandlerImpl.java @@ -0,0 +1,126 @@ +package com.jzo2o.trade.handler.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; +import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.enums.RefundStatusEnum; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.BasicPayHandler; +import com.jzo2o.trade.handler.BeforePayHandler; +import com.jzo2o.trade.handler.HandlerFactory; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.model.dto.TradingDTO; +import com.jzo2o.trade.service.RefundRecordService; +import com.jzo2o.trade.service.TradingService; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 交易前置处理接口 + * + * @author zzj + * @version 1.0 + */ +@Component +public class BeforePayHandlerImpl implements BeforePayHandler { + + @Resource + private TradingService tradingService; + @Resource + private IdentifierGenerator identifierGenerator; + @Resource + private RefundRecordService refundRecordService; + + + @Override + public void checkCreateTrading(Trading tradingEntity) { + //校验不为为空,订单备注、订单号、企业号、交易金额、支付渠道 + boolean flag = ObjectUtil.isAllNotEmpty(tradingEntity, + tradingEntity.getMemo(), + tradingEntity.getProductOrderNo(), + tradingEntity.getEnterpriseId(), + tradingEntity.getTradingAmount(), + tradingEntity.getTradingChannel()); + //金额不能小于等于0 + boolean flag2 = !NumberUtil.isLessOrEqual(tradingEntity.getTradingAmount(), BigDecimal.valueOf(0)); + if (!flag || !flag2) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.CONFIG_ERROR.getValue()); + } + + List tradings = tradingService.queryByProductOrder(tradingEntity.getProductAppId(),tradingEntity.getProductOrderNo()); + if (ObjectUtil.isEmpty(tradings)) { + //新交易单,生成交易号 + tradingEntity.setTradingOrderNo((Long) identifierGenerator.nextId(tradingEntity)); + return ; + } + //找到已付款的记录 + Trading finishedTrading = tradingService.findFinishedTrading(tradingEntity.getProductAppId(),tradingEntity.getProductOrderNo()); + if (ObjectUtil.isNotEmpty(finishedTrading)) { + //存在已付款单子直接抛出重复支付异常 + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.TRADING_STATE_SUCCEED.getValue()); + } + //找到该支付渠道支付中的单子 + Trading trading = tradingService.queryDuringTrading(tradingEntity.getProductAppId(),tradingEntity.getProductOrderNo(), tradingEntity.getTradingChannel()); + if (ObjectUtil.isNotEmpty(trading)) { + //存在相同支付渠道的付款中单子 + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.TRADING_STATE_PAYING.getValue()); + } + //新交易单,生成交易号 + tradingEntity.setTradingOrderNo((Long) identifierGenerator.nextId(tradingEntity)); + } + + @Override + public void checkQueryTrading(Trading trading) { + if (ObjectUtil.isEmpty(trading)) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NOT_FOUND.getValue()); + } + + } + + + @Override + public void checkRefundTrading(Trading trading,BigDecimal refundAmount) { + if (ObjectUtil.isEmpty(trading)) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NOT_FOUND.getValue()); + } + + if (trading.getTradingState() != TradingStateEnum.YJS) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_REFUND_FAIL.getValue()); + } + + //退款总金额不可超实付总金额 + if (NumberUtil.isGreater(refundAmount, trading.getTradingAmount())) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.BASIC_REFUND_OUT_FAIL.getValue()); + } + + } + + @Override + public void checkQueryRefundTrading(RefundRecord refundRecord) { + if (ObjectUtil.isEmpty(refundRecord)) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.REFUND_NOT_FOUND.getValue()); + } + + if (ObjectUtil.equals(refundRecord.getRefundStatus(), RefundStatusEnum.SUCCESS)) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.REFUND_ALREADY_COMPLETED.getValue()); + } + } + + @Override + public void checkCloseTrading(Trading trading) { + if (ObjectUtil.notEqual(TradingStateEnum.FKZ, trading.getTradingState())) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.CLOSE_FAIL.getValue()); + } + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WeChatBasicPayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WeChatBasicPayHandler.java new file mode 100644 index 0000000..9edc16f --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WeChatBasicPayHandler.java @@ -0,0 +1,198 @@ +package com.jzo2o.trade.handler.wechat; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.annotation.PayChannel; +import com.jzo2o.trade.constant.TradingConstant; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.enums.RefundStatusEnum; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.BasicPayHandler; +import com.jzo2o.trade.handler.wechat.response.WeChatResponse; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.model.domain.Trading; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.temporal.ChronoUnit; +import java.util.Map; + +import static com.jzo2o.trade.enums.TradingEnum.NATIVE_REFUND_FAIL; + +/** + * 微信基础支付功能的实现 + * + * @author zzj + * @version 1.0 + */ +@Slf4j +@Component("weChatBasicPayHandler") +@PayChannel(type = PayChannelEnum.WECHAT_PAY) +public class WeChatBasicPayHandler implements BasicPayHandler { + + @Override + public Boolean queryTrading(Trading trading) throws CommonException { + // 获取微信支付的client对象 + WechatPayHttpClient client = WechatPayHttpClient.get(trading.getEnterpriseId()); + + //请求地址 + String apiPath = StrUtil.format("/v3/pay/transactions/out-trade-no/{}", trading.getTradingOrderNo()); + + //请求参数 + Map params = MapUtil.builder() + .put("mchid", client.getMchId()) + .build(); + + WeChatResponse response; + try { + response = client.doGet(apiPath, params); + } catch (Exception e) { + log.error("调用微信接口出错!apiPath = {}, params = {}", apiPath, JSONUtil.toJsonStr(params), e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, NATIVE_REFUND_FAIL.getValue()); + } + if (response.isOk()) { + JSONObject jsonObject = JSONUtil.parseObj(response.getBody()); + // 交易状态,枚举值: + // SUCCESS:支付成功 + // REFUND:转入退款 + // NOTPAY:未支付 + // CLOSED:已关闭 + // REVOKED:已撤销(仅付款码支付会返回) + // USERPAYING:用户支付中(仅付款码支付会返回) + // PAYERROR:支付失败(仅付款码支付会返回) + String tradeStatus = jsonObject.getStr("trade_state"); + //已关闭或已撤单的更新状态为取消订单 + if (StrUtil.equalsAny(tradeStatus, TradingConstant.WECHAT_TRADE_CLOSED, TradingConstant.WECHAT_TRADE_REVOKED)) { + trading.setTradingState(TradingStateEnum.QXDD); + //支付成功或转入退款的更新为已付款 + } else if (StrUtil.equalsAny(tradeStatus, TradingConstant.WECHAT_TRADE_SUCCESS, TradingConstant.WECHAT_TRADE_REFUND)) { + trading.setTradingState(TradingStateEnum.YJS); + } else if (StrUtil.equalsAny(tradeStatus, TradingConstant.WECHAT_TRADE_PAYERROR)) { + trading.setTradingState(TradingStateEnum.FKSB); + } else { + //非最终状态不处理 + return false; + } + //修改交易单状态 + trading.setTransactionId(jsonObject.getStr("transaction_id")); + trading.setResultCode(tradeStatus); + trading.setResultMsg(jsonObject.getStr("trade_state_desc")); + trading.setResultJson(response.getBody()); + return true; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, NATIVE_REFUND_FAIL.getValue()); + } + + @Override + public Boolean closeTrading(Trading trading) throws CommonException { + // 获取微信支付的client对象 + WechatPayHttpClient client = WechatPayHttpClient.get(trading.getEnterpriseId()); + //请求地址 + String apiPath = StrUtil.format("/v3/pay/transactions/out-trade-no/{}/close", trading.getTradingOrderNo()); + //请求参数 + Map params = MapUtil.builder() + .put("mchid", client.getMchId()) + .build(); + try { + WeChatResponse response = client.doPost(apiPath, params); + if (response.getStatus() == 204) { + trading.setTradingState(TradingStateEnum.QXDD); + return true; + } + return false; + } catch (Exception e) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.CLOSE_FAIL.getValue()); + } + } + + @Override + public Boolean refundTrading(RefundRecord refundRecord) throws CommonException { + // 获取微信支付的client对象 + WechatPayHttpClient client = WechatPayHttpClient.get(refundRecord.getEnterpriseId()); + //请求地址 + String apiPath = "/v3/refund/domestic/refunds"; + //请求参数 + Map params = MapUtil.builder() + .put("out_refund_no", Convert.toStr(refundRecord.getRefundNo())) + .put("out_trade_no", Convert.toStr(refundRecord.getTradingOrderNo())) + .put("amount", MapUtil.builder() + .put("refund", NumberUtil.mul(refundRecord.getRefundAmount(), 100)) //本次退款金额 + .put("total", NumberUtil.mul(refundRecord.getTotal(), 100)) //原订单金额 + .put("currency", "CNY") //币种 + .build()) + .build(); + WeChatResponse response; + try { + response = client.doPost(apiPath, params); + } catch (Exception e) { + log.error("调用微信接口出错!apiPath = {}, params = {}", apiPath, JSONUtil.toJsonStr(params), e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, NATIVE_REFUND_FAIL.getValue()); + } + refundRecord.setRefundCode(Convert.toStr(response.getStatus())); + refundRecord.setRefundMsg(response.getBody()); + if (response.isOk()) { + JSONObject jsonObject = JSONUtil.parseObj(response.getBody()); + refundRecord.setRefundId(jsonObject.getStr("refund_id")); + // SUCCESS:退款成功 + // CLOSED:退款关闭 + // PROCESSING:退款处理中 + // ABNORMAL:退款异常 + String status = jsonObject.getStr("status"); + if (StrUtil.equals(status, TradingConstant.WECHAT_REFUND_PROCESSING)) { + refundRecord.setRefundStatus(RefundStatusEnum.SENDING); + } else if (StrUtil.equals(status, TradingConstant.WECHAT_REFUND_SUCCESS)) { + refundRecord.setRefundStatus(RefundStatusEnum.SUCCESS); + } else { + refundRecord.setRefundStatus(RefundStatusEnum.FAIL); + } + return true; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, NATIVE_REFUND_FAIL.getValue()); + } + + @Override + public Boolean queryRefundTrading(RefundRecord refundRecord) throws CommonException { + // 获取微信支付的client对象 + WechatPayHttpClient client = WechatPayHttpClient.get(refundRecord.getEnterpriseId()); + + //请求地址 + String apiPath = StrUtil.format("/v3/refund/domestic/refunds/{}", refundRecord.getRefundNo()); + + WeChatResponse response; + try { + response = client.doGet(apiPath); + } catch (Exception e) { + log.error("调用微信接口出错!apiPath = {}", apiPath, e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_REFUND_FAIL.getValue()); + } + + refundRecord.setRefundCode(Convert.toStr(response.getStatus())); + refundRecord.setRefundMsg(response.getBody()); + if (response.isOk()) { + JSONObject jsonObject = JSONUtil.parseObj(response.getBody()); + refundRecord.setRefundId(jsonObject.getStr("refund_id")); + // SUCCESS:退款成功 + // CLOSED:退款关闭 + // PROCESSING:退款处理中 + // ABNORMAL:退款异常 + String status = jsonObject.getStr("status"); + if (StrUtil.equals(status, TradingConstant.WECHAT_REFUND_PROCESSING)) { + refundRecord.setRefundStatus(RefundStatusEnum.SENDING); + } else if (StrUtil.equals(status, TradingConstant.WECHAT_REFUND_SUCCESS)) { + refundRecord.setRefundStatus(RefundStatusEnum.SUCCESS); + } else { + refundRecord.setRefundStatus(RefundStatusEnum.FAIL); + } + return true; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_REFUND_FAIL.getValue()); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatJsapiPayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatJsapiPayHandler.java new file mode 100644 index 0000000..d8a6362 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatJsapiPayHandler.java @@ -0,0 +1,117 @@ +package com.jzo2o.trade.handler.wechat; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.annotation.PayChannel; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.JsapiPayHandler; +import com.jzo2o.trade.handler.wechat.bean.JsapiPayParam; +import com.jzo2o.trade.handler.wechat.response.WeChatResponse; +import com.jzo2o.trade.model.domain.Trading; +import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; +import org.springframework.stereotype.Component; + +import java.io.ByteArrayInputStream; +import java.security.PrivateKey; +import java.security.Signature; +import java.util.Base64; +import java.util.Map; + +/** + * 微信jsapi的实现 + * + * @author zzj + * @version 1.0 + */ +@Component("wechatJsapiPayHandler") +@PayChannel(type = PayChannelEnum.WECHAT_PAY) +public class WechatJsapiPayHandler implements JsapiPayHandler { + + @Override + public void createJsapiTrading(Trading tradingEntity) { + // 查询配置 + WechatPayHttpClient client = WechatPayHttpClient.get(tradingEntity.getEnterpriseId()); + //请求地址 + String apiPath = "/v3/pay/transactions/jsapi"; + //请求参数 + Map params = MapUtil.builder() + .put("mchid", client.getMchId()) + .put("appid", client.getAppId()) + .put("description", tradingEntity.getMemo()) + .put("notify_url", client.getNotifyUrl()) + .put("out_trade_no", Convert.toStr(tradingEntity.getTradingOrderNo())) + .put("amount", MapUtil.builder() + .put("total", Convert.toInt(NumberUtil.mul(tradingEntity.getTradingAmount(), 100))) //金额,单位:分 + .put("currency", "CNY") //人民币 + .build()) + .put("payer", MapUtil.builder() + .put("openid", tradingEntity.getOpenId()) //用户识别标识 + .build()) + .build(); + try { + WeChatResponse response = client.doPost(apiPath, params); + if (!response.isOk()) { + //下单失败 + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } + //指定统一下单code + tradingEntity.setPlaceOrderCode(Convert.toStr(response.getStatus())); + //jsapi发起支付需要的预支付id + tradingEntity.setPlaceOrderMsg(JSONUtil.parseObj(response.getBody()).getStr("prepay_id")); + + //指定交易状态 + tradingEntity.setTradingState(TradingStateEnum.FKZ); + + //封装JSAPI调起支付的参数(给前端使用) + Long timeStamp = System.currentTimeMillis() / 1000; + String nonceStr = IdUtil.simpleUUID(); + String packages = "prepay_id=" + tradingEntity.getPlaceOrderMsg(); + JsapiPayParam jsapiPayParam = JsapiPayParam.builder() + .timeStamp(timeStamp) + .appId(client.getAppId()) + .nonceStr(nonceStr) + .packages(packages) + .paySign(this.createPaySign(client, timeStamp, nonceStr, packages)) + .build(); + + //设置jsapi调起支付的参数 + tradingEntity.setPlaceOrderJson(JSONUtil.toJsonStr(jsapiPayParam)); + } catch (Exception e) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } + } + + /** + * 生成 + * + * @param client 微信client对象 + * @param timeStamp 时间戳 + * @param nonceStr 随机数 + * @param packages 预支付字符串 + * @return 签名字符串 + * @throws Exception 不处理异常,全部抛出 + */ + private String createPaySign(WechatPayHttpClient client, Long timeStamp, String nonceStr, String packages) throws Exception { + Signature sign = Signature.getInstance("SHA256withRSA"); + // 加载商户私钥 + PrivateKey privateKey = PemUtil + .loadPrivateKey(new ByteArrayInputStream(client.getPrivateKey().getBytes(CharsetUtil.CHARSET_UTF_8))); + sign.initSign(privateKey); + String message = StrUtil.format("{}\n{}\n{}\n{}\n", + client.getAppId(), + timeStamp, + nonceStr, + packages); + sign.update(message.getBytes()); + return Base64.getEncoder().encodeToString(sign.sign()); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatNativePayHandler.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatNativePayHandler.java new file mode 100644 index 0000000..9668d1b --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatNativePayHandler.java @@ -0,0 +1,67 @@ +package com.jzo2o.trade.handler.wechat; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.json.JSONUtil; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.annotation.PayChannel; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.NativePayHandler; +import com.jzo2o.trade.handler.wechat.response.WeChatResponse; +import com.jzo2o.trade.model.domain.Trading; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 微信二维码支付 + * + * @author zzj + * @version 1.0 + */ +@Component("wechatNativePayHandler") +@PayChannel(type = PayChannelEnum.WECHAT_PAY) +public class WechatNativePayHandler implements NativePayHandler { + + @Override + public void createDownLineTrading(Trading tradingEntity) throws CommonException { + // 查询配置 + WechatPayHttpClient client = WechatPayHttpClient.get(tradingEntity.getEnterpriseId()); + //请求地址 + String apiPath = "/v3/pay/transactions/native"; + + //请求参数 + Map params = MapUtil.builder() + .put("mchid", client.getMchId()) + .put("appid", client.getAppId()) + .put("description", tradingEntity.getMemo()) + .put("notify_url", client.getNotifyUrl()) + .put("out_trade_no", Convert.toStr(tradingEntity.getTradingOrderNo())) + .put("amount", MapUtil.builder() + .put("total", Convert.toInt(NumberUtil.mul(tradingEntity.getTradingAmount(), 100))) //金额,单位:分 + .put("currency", "CNY") //人民币 + .build()) + .build(); + + try { + WeChatResponse response = client.doPost(apiPath, params); + if (!response.isOk()) { + //下单失败 + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } + //指定统一下单code + tradingEntity.setPlaceOrderCode(Convert.toStr(response.getStatus())); + //二维码需要展现的信息 + tradingEntity.setPlaceOrderMsg(JSONUtil.parseObj(response.getBody()).getStr("code_url")); + //指定统一下单json字符串 + tradingEntity.setPlaceOrderJson(JSONUtil.toJsonStr(response)); + + } catch (Exception e) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatPayHttpClient.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatPayHttpClient.java new file mode 100644 index 0000000..17d7250 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/WechatPayHttpClient.java @@ -0,0 +1,161 @@ +package com.jzo2o.trade.handler.wechat; + +import cn.hutool.core.net.url.UrlBuilder; +import cn.hutool.core.net.url.UrlPath; +import cn.hutool.core.net.url.UrlQuery; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.constant.TradingConstant; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.handler.wechat.response.WeChatResponse; +import com.jzo2o.trade.model.domain.PayChannel; +import com.jzo2o.trade.service.PayChannelService; +import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; +import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials; +import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator; +import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager; +import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.security.PrivateKey; +import java.util.Map; + +/** + * 微信支付远程调用对象 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WechatPayHttpClient { + + private String mchId; //商户号 + private String appId; //商户号 + private String privateKey; //私钥字符串 + private String mchSerialNo; //商户证书序列号 + private String apiV3Key; //V3密钥 + private String domain; //请求域名 + private String notifyUrl; //请求地址 + + public static WechatPayHttpClient get(Long enterpriseId) { + // 查询配置 + PayChannelService payChannelService = SpringUtil.getBean(PayChannelService.class); + PayChannel payChannel = payChannelService.findByEnterpriseId(enterpriseId, TradingConstant.TRADING_CHANNEL_WECHAT_PAY); + + if (ObjectUtil.isEmpty(payChannel)) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.CONFIG_EMPTY.getValue()); + } + + //通过渠道对象转化成微信支付的client对象 + JSONObject otherConfig = JSONUtil.parseObj(payChannel.getOtherConfig()); + return WechatPayHttpClient.builder() + .appId(payChannel.getAppId()) + .domain(payChannel.getDomain()) + .privateKey(payChannel.getMerchantPrivateKey()) + .mchId(otherConfig.getStr("mchId")) + .mchSerialNo(otherConfig.getStr("mchSerialNo")) + .apiV3Key(otherConfig.getStr("apiV3Key")) + .notifyUrl(payChannel.getNotifyUrl()) + .build(); + } + + /*** + * 构建CloseableHttpClient远程请求对象 + * @return {@link CloseableHttpClient} + */ + public CloseableHttpClient createHttpClient() throws Exception { + // 加载商户私钥(privateKey:私钥字符串) + PrivateKey merchantPrivateKey = PemUtil + .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8"))); + + // 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥) + PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, merchantPrivateKey); + WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials( + mchId, privateKeySigner); + + // 向证书管理器增加需要自动更新平台证书的商户信息 + CertificatesManager certificatesManager = CertificatesManager.getInstance(); + certificatesManager.putMerchant(mchId, wechatPay2Credentials, apiV3Key.getBytes("utf-8")); + + // 初始化httpClient + return com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder.create() + .withMerchant(mchId, mchSerialNo, merchantPrivateKey) + .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId))) + .build(); + } + + /*** + * 支持post请求的远程调用 + * @param apiPath api地址 + * @param params 携带请求参数 + * @return 返回字符串 + */ + public WeChatResponse doPost(String apiPath, Map params) throws Exception { + String url = StrUtil.format("https://{}{}", this.domain, apiPath); + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("Accept", "application/json"); + httpPost.addHeader("Content-type", "application/json; charset=utf-8"); + + String body = JSONUtil.toJsonStr(params); + httpPost.setEntity(new StringEntity(body, CharsetUtil.UTF_8)); + + CloseableHttpResponse response = this.createHttpClient().execute(httpPost); + return new WeChatResponse(response); + } + + /*** + * 支持get请求的远程调用 + * @param apiPath api地址 + * @param params 在路径中请求的参数 + * @return 返回字符串 + */ + public WeChatResponse doGet(String apiPath, Map params) throws Exception { + URI uri = UrlBuilder.create() + .setHost(this.domain) + .setScheme("https") + .setPath(UrlPath.of(apiPath, CharsetUtil.CHARSET_UTF_8)) + .setQuery(UrlQuery.of(params)) + .setCharset(CharsetUtil.CHARSET_UTF_8) + .toURI(); + return this.doGet(uri); + } + + /*** + * 支持get请求的远程调用 + * @param apiPath api地址 + * @return 返回字符串 + */ + public WeChatResponse doGet(String apiPath) throws Exception { + URI uri = UrlBuilder.create() + .setHost(this.domain) + .setScheme("https") + .setPath(UrlPath.of(apiPath, CharsetUtil.CHARSET_UTF_8)) + .setCharset(CharsetUtil.CHARSET_UTF_8) + .toURI(); + return this.doGet(uri); + } + + private WeChatResponse doGet(URI uri) throws Exception { + HttpGet httpGet = new HttpGet(uri); + httpGet.addHeader("Accept", "application/json"); + CloseableHttpResponse response = this.createHttpClient().execute(httpGet); + return new WeChatResponse(response); + } + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/bean/JsapiPayParam.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/bean/JsapiPayParam.java new file mode 100644 index 0000000..e9f4b9a --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/bean/JsapiPayParam.java @@ -0,0 +1,50 @@ +package com.jzo2o.trade.handler.wechat.bean; + +import cn.hutool.core.annotation.Alias; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class JsapiPayParam { + + /** + * 由微信生成的应用ID,全局唯一。 + * 请求基础下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的服务号APPID + */ + private String appId; + + /** + * 时间戳,标准北京时间,时区为东八区, + * 自1970年1月1日 0点0分0秒以来的秒数。 + * 注意:部分系统取到的值为毫秒级,需要转换成秒(10位数字)。 + */ + private Long timeStamp; + + /** + * 随机字符串,不长于32位。 + */ + private String nonceStr; + + /** + * JSAPI下单接口返回的prepay_id参数值,提交格式如: + * prepay_id=wx201410272009395522657a690389285100 + */ + @Alias("package") + private String packages; + + /** + * 签名类型,默认为RSA,仅支持RSA。 + */ + private String signType = "RSA"; + + /** + * 签名,使用字段appId、timeStamp、nonceStr、package计算得出的签名值 + */ + private String paySign; + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/response/WeChatResponse.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/response/WeChatResponse.java new file mode 100644 index 0000000..0e53d70 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/handler/wechat/response/WeChatResponse.java @@ -0,0 +1,35 @@ +package com.jzo2o.trade.handler.wechat.response; + +import cn.hutool.core.util.CharsetUtil; +import lombok.Data; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.util.EntityUtils; + +/** + * @author zzj + * @version 1.0 + */ +@Data +public class WeChatResponse { + + private int status; //响应状态码 + private String body; //响应体数据 + + public WeChatResponse() { + + } + + public WeChatResponse(CloseableHttpResponse response) { + this.status = response.getStatusLine().getStatusCode(); + try { + this.body = EntityUtils.toString(response.getEntity(), CharsetUtil.UTF_8); + } catch (Exception e) { + // 如果出现异常,响应体为null + } + } + + public Boolean isOk() { + return this.status == 200; + } + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/job/TradeJob.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/job/TradeJob.java new file mode 100644 index 0000000..f8a7d90 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/job/TradeJob.java @@ -0,0 +1,163 @@ +package com.jzo2o.trade.job; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.json.JSONUtil; +import com.jzo2o.common.constants.MqConstants; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.common.model.msg.TradeStatusMsg; +import com.jzo2o.rabbitmq.client.RabbitClient; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.BasicPayHandler; +import com.jzo2o.trade.handler.HandlerFactory; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.model.dto.TradingDTO; +import com.jzo2o.trade.service.BasicPayService; +import com.jzo2o.trade.service.RefundRecordService; +import com.jzo2o.trade.service.TradingService; +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; + +/** + * 交易任务,主要是查询订单的支付状态 和 退款的成功状态 + * + * @author zzj + * @version 1.0 + */ +@Slf4j +@Component +public class TradeJob { + + @Value("${jzo2o.job.trading.count:100}") + private Integer tradingCount; + @Value("${jzo2o.job.refund.count:100}") + private Integer refundCount; + @Resource + private TradingService tradingService; + @Resource + private RefundRecordService refundRecordService; + @Resource + private BasicPayService basicPayService; + @Resource + private RabbitClient rabbitClient; + + /** + * 分片广播方式查询支付状态 + * 逻辑:每次最多查询{tradingCount}个未完成的交易单,交易单id与shardTotal取模,值等于shardIndex进行处理 + */ + @XxlJob("tradingJob") + public void tradingJob() { + // 分片参数 + int shardIndex = NumberUtil.max(XxlJobHelper.getShardIndex(), 0); + int shardTotal = NumberUtil.max(XxlJobHelper.getShardTotal(), 1); + + List list = this.tradingService.findListByTradingState(TradingStateEnum.FKZ, tradingCount); + if (CollUtil.isEmpty(list)) { + XxlJobHelper.log("查询到交易单列表为空!shardIndex = {}, shardTotal = {}", shardIndex, shardTotal); + return; + } + + //定义消息通知列表,只要是状态不为【付款中】就需要通知其他系统 + List tradeMsgList = new ArrayList<>(); + for (Trading trading : list) { + if (trading.getTradingOrderNo() % shardTotal != shardIndex) { + continue; + } + try { + //查询交易单 + TradingDTO tradingDTO = this.basicPayService.queryTradingResult(trading.getTradingOrderNo()); + if (TradingStateEnum.FKZ != tradingDTO.getTradingState()) { + TradeStatusMsg tradeStatusMsg = TradeStatusMsg.builder() + .tradingOrderNo(trading.getTradingOrderNo()) + .productOrderNo(trading.getProductOrderNo()) + .productAppId(trading.getProductAppId()) + .transactionId(tradingDTO.getTransactionId()) + .tradingChannel(tradingDTO.getTradingChannel()) + .statusCode(tradingDTO.getTradingState().getCode()) + .statusName(tradingDTO.getTradingState().name()) + .info(tradingDTO.getMemo())//备注信息 + .build(); + tradeMsgList.add(tradeStatusMsg); + }else{ + //如果是未支付,需要判断下时间,超过20分钟未支付的订单需要关闭订单以及设置状态为QXDD + long between = LocalDateTimeUtil.between(trading.getCreateTime(), LocalDateTimeUtil.now(), ChronoUnit.MINUTES); + if (between >= 20) { + try { + basicPayService.closeTrading(trading.getTradingOrderNo()); + } catch (Exception e) { + log.error("超过20分钟未支付自动关单出现异常,交易单号:{}",trading.getTradingOrderNo()); + } + } + } + } catch (Exception e) { + XxlJobHelper.log("查询交易单出错!shardIndex = {}, shardTotal = {}, trading = {}", shardIndex, shardTotal, trading, e); + } + } + + if (CollUtil.isEmpty(tradeMsgList)) { + return; + } + + //发送消息通知其他系统 + String msg = JSONUtil.toJsonStr(tradeMsgList); + rabbitClient.sendMsg(MqConstants.Exchanges.TRADE, MqConstants.RoutingKeys.TRADE_UPDATE_STATUS, msg); + } + + /** + * 分片广播方式查询退款状态 + */ +// @XxlJob("refundJob") +// public void refundJob() { +// // 分片参数 +// int shardIndex = NumberUtil.max(XxlJobHelper.getShardIndex(), 0); +// int shardTotal = NumberUtil.max(XxlJobHelper.getShardTotal(), 1); +// +// List list = this.refundRecordService.findListByRefundStatus(RefundStatusEnum.SENDING, refundCount); +// if (CollUtil.isEmpty(list)) { +// XxlJobHelper.log("查询到退款单列表为空!shardIndex = {}, shardTotal = {}", shardIndex, shardTotal); +// return; +// } +// +// //定义消息通知列表,只要是状态不为【退款中】就需要通知其他系统 +// List tradeMsgList = new ArrayList<>(); +// +// for (RefundRecordEntity refundRecord : list) { +// if (refundRecord.getRefundNo() % shardTotal != shardIndex) { +// continue; +// } +// try { +// //查询退款单 +// RefundRecordDTO refundRecordDTO = this.basicPayService.queryRefundTrading(refundRecord.getRefundNo()); +// if (RefundStatusEnum.SENDING != refundRecordDTO.getRefundStatus()) { +// TradeStatusMsg tradeStatusMsg = TradeStatusMsg.builder() +// .tradingOrderNo(refundRecord.getTradingOrderNo()) +// .productOrderNo(refundRecord.getProductOrderNo()) +// .refundNo(refundRecord.getRefundNo()) +// .statusCode(refundRecord.getRefundStatus().getCode()) +// .statusName(refundRecord.getRefundStatus().name()) +// .build(); +// tradeMsgList.add(tradeStatusMsg); +// } +// } catch (Exception e) { +// XxlJobHelper.log("查询退款单出错!shardIndex = {}, shardTotal = {}, refundRecord = {}", shardIndex, shardTotal, refundRecord, e); +// } +// } +// +// if (CollUtil.isEmpty(tradeMsgList)) { +// return; +// } +// +// //发送消息通知其他系统 +// String msg = JSONUtil.toJsonStr(tradeMsgList); +// this.mqFeign.sendMsg(Constants.MQ.Exchanges.TRADE, Constants.MQ.RoutingKeys.REFUND_UPDATE_STATUS, msg); +// } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/PayChannelMapper.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/PayChannelMapper.java new file mode 100644 index 0000000..e27514e --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/PayChannelMapper.java @@ -0,0 +1,13 @@ +package com.jzo2o.trade.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jzo2o.trade.model.domain.PayChannel; +import org.apache.ibatis.annotations.Mapper; + +/** + * 交易渠道表Mapper接口 + */ +@Mapper +public interface PayChannelMapper extends BaseMapper { + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/RefundRecordMapper.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/RefundRecordMapper.java new file mode 100644 index 0000000..fab7980 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/RefundRecordMapper.java @@ -0,0 +1,13 @@ +package com.jzo2o.trade.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jzo2o.trade.model.domain.RefundRecord; +import org.apache.ibatis.annotations.Mapper; + +/** + * 退款记录表Mapper接口 + */ +@Mapper +public interface RefundRecordMapper extends BaseMapper { + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/TradingMapper.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/TradingMapper.java new file mode 100644 index 0000000..cb2e2a5 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/mapper/TradingMapper.java @@ -0,0 +1,13 @@ +package com.jzo2o.trade.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jzo2o.trade.model.domain.Trading; +import org.apache.ibatis.annotations.Mapper; + +/** + * 交易订单表Mapper接口 + */ +@Mapper +public interface TradingMapper extends BaseMapper { + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/PayChannel.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/PayChannel.java new file mode 100644 index 0000000..c31eb0f --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/PayChannel.java @@ -0,0 +1,96 @@ +package com.jzo2o.trade.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author itcast + * @Description:交易渠道表 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("pay_channel") +public class PayChannel implements Serializable { + private static final long serialVersionUID = -1452774366739615656L; + + /** + * 主键 + */ + private Long id; + + /** + * 通道名称 + */ + private String channelName; + + /** + * 通道唯一标记 + */ + private String channelLabel; + + /** + * 域名 + */ + private String domain; + + /** + * 商户appid + */ + private String appId; + + /** + * 支付公钥 + */ + private String publicKey; + + /** + * 商户私钥 + */ + private String merchantPrivateKey; + + /** + * 其他配置 + */ + private String otherConfig; + + /** + * AES混淆密钥 + */ + private String encryptKey; + + /** + * 说明 + */ + private String remark; + + /** + * 回调地址 + */ + private String notifyUrl; + + /** + * 是否有效 + */ + protected String enableFlag; + + /** + * 商户号 + */ + private Long enterpriseId; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/RefundRecord.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/RefundRecord.java new file mode 100644 index 0000000..3fff2bf --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/RefundRecord.java @@ -0,0 +1,103 @@ +package com.jzo2o.trade.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.jzo2o.trade.enums.RefundStatusEnum; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author itcast + * @Description:退款记录表 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("refund_record") +public class RefundRecord implements Serializable { + private static final long serialVersionUID = -3998253241655800061L; + + /** + * 主键 + */ + private Long id; + + /** + * 交易系统订单号【对于三方来说:商户订单】 + */ + private Long tradingOrderNo; + + /** + * 业务系统应用标识 + */ + private String productAppId; + + /** + * 业务系统订单号 + */ + private Long productOrderNo; + + /** + * 本次退款订单号 + */ + private Long refundNo; + + /** + * 第三方支付的退款单号 + */ + private String refundId; + + /** + * 商户号 + */ + private Long enterpriseId; + + /** + * 退款渠道【支付宝、微信、现金】 + */ + private String tradingChannel; + + /** + * 退款状态 + */ + private RefundStatusEnum refundStatus; + + /** + * 返回编码 + */ + private String refundCode; + + /** + * 返回信息 + */ + private String refundMsg; + + /** + * 备注【订单门店,桌台信息】 + */ + private String memo; + + /** + * 本次退款金额 + */ + private BigDecimal refundAmount; + + /** + * 原订单金额 + */ + private BigDecimal total; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/Trading.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/Trading.java new file mode 100644 index 0000000..d027592 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/domain/Trading.java @@ -0,0 +1,162 @@ +package com.jzo2o.trade.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.jzo2o.trade.enums.TradingStateEnum; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author itcast + * @Description:交易订单表 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("trading") +public class Trading implements Serializable { + private static final long serialVersionUID = -3427581867070559590L; + + /** + * 主键 + */ + private Long id; + + /** + * openId标识 + */ + private String openId; + + /** + * 业务系统应用标识 + */ + private String productAppId; + /** + * 业务系统订单号 + */ + private Long productOrderNo; + + /** + * 交易系统订单号【对于三方来说:商户订单】 + */ + private Long tradingOrderNo; + + /** + * 第三方支付的交易号 + */ + private String transactionId; + + /** + * 支付渠道【支付宝、微信、现金、免单挂账】 + */ + private String tradingChannel; + + /** + * 交易类型【付款、退款、免单、挂账】 + */ + private String tradingType; + + /** + * 交易单状态【DFK待付款,FKZ付款中,QXDD取消订单,YJS已结算,MD免单,GZ挂账】 + */ + private TradingStateEnum tradingState; + + /** + * 收款人姓名 + */ + private String payeeName; + + /** + * 收款人账户ID + */ + private Long payeeId; + + /** + * 付款人姓名 + */ + private String payerName; + + /** + * 付款人Id + */ + private Long payerId; + + /** + * 交易金额 + */ + private BigDecimal tradingAmount; + + /** + * 退款金额【付款后】 + */ + private BigDecimal refund; + + /** + * 是否有退款:YES,NO + */ + private String isRefund; + + /** + * 第三方交易返回编码【最终确认交易结果】 + */ + private String resultCode; + + /** + * 第三方交易返回提示消息【最终确认交易信息】 + */ + private String resultMsg; + + /** + * 第三方交易返回信息json【分析交易最终信息】 + */ + private String resultJson; + + /** + * 统一下单返回编码 + */ + private String placeOrderCode; + + /** + * 统一下单返回信息 + */ + private String placeOrderMsg; + + /** + * 统一下单返回信息json【用于生产二维码、Android ios唤醒支付等】 + */ + private String placeOrderJson; + + /** + * 商户号 + */ + private Long enterpriseId; + + /** + * 备注【订单门店,桌台信息】 + */ + private String memo; + + /** + * 二维码base64数据 + */ + private String qrCode; + + /** + * 是否有效 + */ + protected String enableFlag; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/PayChannelDTO.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/PayChannelDTO.java new file mode 100644 index 0000000..6ba8f2e --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/PayChannelDTO.java @@ -0,0 +1,55 @@ +package com.jzo2o.trade.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @ClassName PayChannelVo.java + * @Description 支付通道 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("支付通道对象") +public class PayChannelDTO { + + @ApiModelProperty(value = "主键") + private Long id; + @ApiModelProperty(value = "通道名称") + private String channelName; + @ApiModelProperty(value = "通道唯一标记") + private String channelLabel; + @ApiModelProperty(value = "域名") + private String domain; + @ApiModelProperty(value = "商户appid") + private String appId; + @ApiModelProperty(value = "公钥") + private String publicKey; + @ApiModelProperty(value = "商户私钥") + private String merchantPrivateKey; + @ApiModelProperty(value = "其他配置") + private String otherConfig; + @ApiModelProperty(value = "AES混淆密钥") + private String encryptKey; + @ApiModelProperty(value = "说明") + private String remark; + @ApiModelProperty(value = "选中节点") + private String[] checkedIds; + @ApiModelProperty(value = "回调地址") + private String notifyUrl; + @ApiModelProperty(value = "是否有效") + protected String enableFlag; + @ApiModelProperty(value = "商户号") + private Long enterpriseId; + @ApiModelProperty(value = "创建时间") + protected LocalDateTime createdTime; + @ApiModelProperty(value = "更新时间") + protected LocalDateTime updatedTime; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/RefundRecordDTO.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/RefundRecordDTO.java new file mode 100644 index 0000000..699835e --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/RefundRecordDTO.java @@ -0,0 +1,53 @@ +package com.jzo2o.trade.model.dto; + +import com.jzo2o.trade.enums.RefundStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @Description: + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("退款对象") +public class RefundRecordDTO { + + @ApiModelProperty(value = "主键") + private Long id; + @ApiModelProperty(value = "交易系统订单号【对于三方来说:商户订单】") + private Long tradingOrderNo; + @ApiModelProperty(value = "业务系统应用标识") + private String productAppId; + @ApiModelProperty(value = "业务系统订单号") + private Long productOrderNo; + @ApiModelProperty(value = "本次退款订单号") + private String refundNo; + @ApiModelProperty(value = "商户号") + private Long enterpriseId; + @ApiModelProperty(value = "退款渠道【支付宝、微信、现金】") + private String tradingChannel; + @ApiModelProperty(value = "退款状态") + private RefundStatusEnum refundStatus; + @ApiModelProperty(value = "返回编码") + private String refundCode; + @ApiModelProperty(value = "返回信息") + private String refundMsg; + @ApiModelProperty(value = "备注【订单门店,桌台信息】") + private String memo; + @ApiModelProperty(value = "原订单金额") + private BigDecimal total; + @ApiModelProperty(value = "创建时间") + protected LocalDateTime created; + @ApiModelProperty(value = "更新时间") + protected LocalDateTime updated; + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/TradingDTO.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/TradingDTO.java new file mode 100644 index 0000000..3911868 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/TradingDTO.java @@ -0,0 +1,82 @@ +package com.jzo2o.trade.model.dto; + +import com.jzo2o.trade.enums.TradingStateEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("交易数据对象") +public class TradingDTO { + + @ApiModelProperty(value = "主键") + private Long id; + @ApiModelProperty(value = "openId标识") + private String openId; + @ApiModelProperty(value = "业务系统应用标识") + private String productAppId; + @ApiModelProperty(value = "业务系统订单号") + private Long productOrderNo; + @ApiModelProperty(value = "交易系统订单号【对于三方来说:商户订单】") + private Long tradingOrderNo; + + @ApiModelProperty(value = "第三方支付的交易号") + private String transactionId; + @ApiModelProperty(value = "支付渠道【支付宝、微信、现金、免单挂账】") + private String tradingChannel; + @ApiModelProperty(value = "交易类型【付款、退款、免单、挂账】") + private String tradingType; + @ApiModelProperty(value = "交易单状态【DFK待付款,FKZ付款中,QXDD取消订单,YJS已结算,MD免单,GZ挂账】") + private TradingStateEnum tradingState; + @ApiModelProperty(value = "收款人姓名") + private String payeeName; + @ApiModelProperty(value = "收款人账户ID") + private Long payeeId; + @ApiModelProperty(value = "付款人姓名") + private String payerName; + @ApiModelProperty(value = "付款人Id") + private Long payerId; + @ApiModelProperty(value = "交易金额,单位:元") + private BigDecimal tradingAmount; + @ApiModelProperty(value = "退款金额【付款后】,单位:元") + private BigDecimal refund; + @ApiModelProperty(value = "是否有退款:YES,NO") + private String isRefund; + @ApiModelProperty(value = "第三方交易返回编码【最终确认交易结果】") + private String resultCode; + @ApiModelProperty(value = "第三方交易返回提示消息【最终确认交易信息】") + private String resultMsg; + @ApiModelProperty(value = "第三方交易返回信息json【分析交易最终信息】") + private String resultJson; + @ApiModelProperty(value = "统一下单返回编码") + private String placeOrderCode; + @ApiModelProperty(value = "统一下单返回信息") + private String placeOrderMsg; + @ApiModelProperty(value = "统一下单返回信息json【用于生产二维码、Android ios唤醒支付等】") + private String placeOrderJson; + @ApiModelProperty(value = "商户号") + private Long enterpriseId; + @ApiModelProperty(value = "备注,如:运费") + private String memo; + @ApiModelProperty(value = "二维码base64数据") + private String qrCode; + @ApiModelProperty(value = "是否有效") + protected String enableFlag; + @ApiModelProperty(value = "退款请求号") + private String outRequestNo; + @ApiModelProperty(value = "操作退款金额") + private BigDecimal operTionRefund; + @ApiModelProperty(value = "创建时间") + protected LocalDateTime created; + @ApiModelProperty(value = "更新时间") + protected LocalDateTime updated; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/request/JsapiPayReqDTO.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/request/JsapiPayReqDTO.java new file mode 100644 index 0000000..77a7069 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/request/JsapiPayReqDTO.java @@ -0,0 +1,32 @@ +package com.jzo2o.trade.model.dto.request; + +import com.jzo2o.api.trade.enums.PayChannelEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * jsapi提交支付请求对象 + * + * @author zzj + * @version 1.0 + */ +@Data +public class JsapiPayReqDTO { + + @ApiModelProperty(value = "openId标识", required = true) + private String openId; + @ApiModelProperty(value = "商户号", required = true) + private Long enterpriseId; + @ApiModelProperty(value = "业务系统应用标识", required = true) + private String productAppId; + @ApiModelProperty(value = "业务系统订单号", required = true) + private Long productOrderNo; + @ApiModelProperty(value = "支付渠道", required = true) + private PayChannelEnum tradingChannel; + @ApiModelProperty(value = "交易金额,单位:元", required = true) + private BigDecimal tradingAmount; + @ApiModelProperty(value = "备注,如:运费", required = true) + private String memo; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/response/JsapiPayResDTO.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/response/JsapiPayResDTO.java new file mode 100644 index 0000000..74a620a --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/response/JsapiPayResDTO.java @@ -0,0 +1,26 @@ +package com.jzo2o.trade.model.dto.response; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 扫码支付响应数据 + * + * @author zzj + * @version 1.0 + */ +@Data +public class JsapiPayResDTO { + + @ApiModelProperty(value = "业务系统订单号") + private Long productOrderNo; + @ApiModelProperty(value = "交易系统订单号【对于三方来说:商户订单】") + private Long tradingOrderNo; + @ApiModelProperty(value = "支付渠道【支付宝、微信、现金、免单挂账】") + private String tradingChannel; + @ApiModelProperty(value = "统一下单返回信息,预支付编号") + private String placeOrderMsg; + @ApiModelProperty(value = "统一下单返回信息json【用于生产二维码、Android ios唤醒支付等】") + private String placeOrderJson; + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/response/TradingStateResDTO.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/response/TradingStateResDTO.java new file mode 100644 index 0000000..3f3fe56 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/model/dto/response/TradingStateResDTO.java @@ -0,0 +1,23 @@ +package com.jzo2o.trade.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 交易单状态响应数据 + * + * @author itcast + * @create 2023/9/11 10:41 + **/ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("交易单状态响应数据") +public class TradingStateResDTO { + + @ApiModelProperty(value = "交易单状态,2:付款中,4:已结算") + private Integer tradingState; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/BasicPayService.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/BasicPayService.java new file mode 100644 index 0000000..503fede --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/BasicPayService.java @@ -0,0 +1,68 @@ +package com.jzo2o.trade.service; + +import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.model.dto.RefundRecordDTO; +import com.jzo2o.trade.model.dto.TradingDTO; + +import java.math.BigDecimal; + +/** + * 支付的基础功能 + * + * @author zzj + * @version 1.0 + */ +public interface BasicPayService { + + /*** + * 统一收单线下交易查询 + * 该接口提供所有支付订单的查询,商户可以通过该接口主动查询订单状态,完成下一步的业务逻辑。 + * @param tradingOrderNo 交易单号 + * @return 交易数据对象 + */ + TradingDTO queryTradingResult(Long tradingOrderNo) throws CommonException; + + /*** + * 统一收单交易退款接口 + * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家, + * 将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。 + * + * + * @param tradingOrderNo 交易单号 + * @param refundAmount 退款金额,不能大于总支付的总金额 + * @return 是否成功 + */ + RefundRecord refundTrading(Long tradingOrderNo, BigDecimal refundAmount) throws CommonException; + +// /** +// * 通过业务订单号进行退款,方便业务系统接入 +// * +// * @param tradingOrderNo 交易单号 +// * @param refundAmount 退款金额,不能大于总支付的总金额 +// * @return +// * @throws CommonException +// */ +// ExecutionResultResDTO refundTradingByTradingOrderNo(Long tradingOrderNo, BigDecimal refundAmount) throws CommonException; + + /*** + * 统一收单交易退款查询接口 + * @param refundNo 退款单号 + * @return 退款记录数据 + */ + RefundRecordDTO queryRefundTrading(Long refundNo) throws CommonException; + + /*** + * 对于退款中的记录需要同步退款状态 + * @param tradingOrderNo 交易单号 + */ + void syncRefundResult(Long tradingOrderNo) throws CommonException; + + /*** + * 关闭交易单 + * @param tradingOrderNo 交易单号 + * @return 是否成功 + */ + Boolean closeTrading(Long tradingOrderNo) throws CommonException; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/JsapiPayService.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/JsapiPayService.java new file mode 100644 index 0000000..03c7a89 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/JsapiPayService.java @@ -0,0 +1,22 @@ +package com.jzo2o.trade.service; + +import com.jzo2o.trade.model.domain.Trading; + +/** + * jsapi支付、微信小程序支付 + * + * @author zzj + * @version 1.0 + */ +public interface JsapiPayService { + + /*** + * 统一jsapi交易预创建 + * 商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易会话标识后再按Native、 + * JSAPI、APP等不同场景生成交易串调起支付。 + * @param tradingEntity 交易单 + * + * @return 交易单,支付串码 + */ + Trading createJsapiTrading(Trading tradingEntity); +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/NativePayService.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/NativePayService.java new file mode 100644 index 0000000..7b7cbe8 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/NativePayService.java @@ -0,0 +1,19 @@ +package com.jzo2o.trade.service; + +import com.jzo2o.api.trade.dto.response.NativePayResDTO; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.model.domain.Trading; + +/** + * 二维码支付 + */ +public interface NativePayService { + /*** + * 扫码支付,收银员通过收银台或商户后台调用此接口,生成二维码后,展示给用户,由用户扫描二维码完成订单支付。 + * + * @param changeChannel 是否切换二维码 + * @param tradingEntity 扫码支付提交参数 + * @return 交易数据 + */ + Trading createDownLineTrading(boolean changeChannel, Trading tradingEntity); +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/NotifyService.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/NotifyService.java new file mode 100644 index 0000000..9812837 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/NotifyService.java @@ -0,0 +1,34 @@ +package com.jzo2o.trade.service; + +import com.jzo2o.common.expcetions.CommonException; +import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest; + +import javax.servlet.http.HttpServletRequest; + +/** + * 支付通知 + * + * @author zzj + * @version 1.0 + */ +public interface NotifyService { + + + /** + * 微信支付通知,官方文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml + * + * @param request 微信请求对象 + * @param enterpriseId 商户id + * @throws CommonException 抛出异常,通过异常决定是否响应200 + */ + void wxPayNotify(NotificationRequest request, Long enterpriseId) throws CommonException; + + /** + * 支付宝支付通知,官方文档:https://opendocs.alipay.com/open/194/103296?ref=api + * + * @param request 请求对象 + * @param enterpriseId 商户id + * @throws CommonException 抛出异常,通过异常决定是否响应200 + */ + void aliPayNotify(HttpServletRequest request, Long enterpriseId) throws CommonException; +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/PayChannelService.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/PayChannelService.java new file mode 100644 index 0000000..3f7fa43 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/PayChannelService.java @@ -0,0 +1,60 @@ +package com.jzo2o.trade.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.trade.model.domain.PayChannel; +import com.jzo2o.trade.model.dto.PayChannelDTO; + +import java.util.List; + +/** + * @Description: 支付通道服务类 + */ +public interface PayChannelService extends IService { + + /** + * @param payChannelDTO 查询条件 + * @param pageNum 当前页 + * @param pageSize 当前页 + * @return Page 分页对象 + * @Description 支付通道列表 + */ + Page findPayChannelPage(PayChannelDTO payChannelDTO, int pageNum, int pageSize); + + /** + * 根据商户id查询渠道配置,该配置会被缓存10分钟 + * + * @param enterpriseId 商户id + * @param channelLabel 通道唯一标记 + * @return PayChannelEntity 交易渠道对象 + */ + PayChannel findByEnterpriseId(Long enterpriseId, String channelLabel); + + /** + * @param payChannelDTO 对象信息 + * @return PayChannelEntity 交易渠道对象 + * @Description 创建支付通道 + */ + PayChannel createPayChannel(PayChannelDTO payChannelDTO); + + /** + * @param payChannelDTO 对象信息 + * @return Boolean 是否成功 + * @Description 修改支付通道 + */ + Boolean updatePayChannel(PayChannelDTO payChannelDTO); + + /** + * @param checkedIds 选择的支付通道ID + * @return Boolean 是否成功 + * @Description 删除支付通道 + */ + Boolean deletePayChannel(String[] checkedIds); + + /** + * @param channelLabel 支付通道标识 + * @return 支付通道列表 + * @Description 查找渠道标识 + */ + List findPayChannelList(String channelLabel); +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/QRCodeService.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/QRCodeService.java new file mode 100644 index 0000000..d962fa5 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/QRCodeService.java @@ -0,0 +1,23 @@ +package com.jzo2o.trade.service; + +import com.jzo2o.api.trade.enums.PayChannelEnum; + +public interface QRCodeService { + + /** + * 生成二维码 + * + * @param content 二维码中的内容 + * @return 图片base64数据 + */ + String generate(String content); + + /** + * 生成二维码,带logo + * + * @param content 二维码中的内容 + * @param payChannel 付款渠道 + * @return 图片base64数据 + */ + String generate(String content, PayChannelEnum payChannel); +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/RefundRecordService.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/RefundRecordService.java new file mode 100644 index 0000000..2ae570f --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/RefundRecordService.java @@ -0,0 +1,47 @@ +package com.jzo2o.trade.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.trade.enums.RefundStatusEnum; +import com.jzo2o.trade.model.domain.RefundRecord; + +import java.util.List; + +/** + * @Description: 退款记录表服务类 + */ +public interface RefundRecordService extends IService { + + /** + * 根据退款单号查询退款记录 + * + * @param refundNo 退款单号 + * @return 退款记录数据 + */ + RefundRecord findByRefundNo(Long refundNo); + + /** + * 根据交易单号查询退款单 + * + * @param tradingOrderNo 交易单号 + * @return 退款列表 + */ + List findByTradingOrderNo(Long tradingOrderNo); + + /** + * 根据订单号查询退款列表 + * + * @param productAppId 业务系统标识 + * @param productOrderNo 订单号 + * @return 退款列表 + */ + List findListByProductOrderNo(String productAppId,Long productOrderNo); + + /*** + * 按状态查询退款单,按照时间正序排序 + * + * @param refundStatus 状态 + * @param count 查询数量,默认查询10条 + * @return 退款单数据列表 + */ + List findListByRefundStatus(RefundStatusEnum refundStatus, Integer count); +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/TradingService.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/TradingService.java new file mode 100644 index 0000000..5fe2755 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/TradingService.java @@ -0,0 +1,60 @@ +package com.jzo2o.trade.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.model.dto.TradingDTO; + +import java.util.List; + +/** + * @Description:交易订单表 服务类 + */ +public interface TradingService extends IService { + + /*** + * 按交易单号查询交易单 + * + * @param tradingOrderNo 交易单号 + * @return 交易单数据 + */ + Trading findTradByTradingOrderNo(Long tradingOrderNo); + + + + /*** + * 按交易状态查询交易单,按照时间正序排序 + * @param tradingState 状态 + * @param count 查询数量,默认查询10条 + * @return 交易单数据列表 + */ + List findListByTradingState(TradingStateEnum tradingState, Integer count); + + + /** + * 根据订单id和支付方式查询付款中的交易单 + * @param productAppId 业务系统标识 + * @param productOrderNo 订单号 + * @param tradingChannel 支付渠道代码 + * @return 交易单 + */ + Trading queryDuringTrading(String productAppId,Long productOrderNo, String tradingChannel); + + /** + * 根据订单id查询交易单 + * + * @param productAppId 业务系统标识 + * @param productOrderNo 订单号 + * @return 交易单 + */ + List queryByProductOrder(String productAppId,Long productOrderNo); + + /** + * 根据订单id查询已付款的交易单 + * @param productAppId 业务系统标识 + * @param productOrderNo 订单id + * @return 交易单 + */ + Trading findFinishedTrading(String productAppId,Long productOrderNo); +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/BasicPayServiceImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/BasicPayServiceImpl.java new file mode 100644 index 0000000..6cd442d --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/BasicPayServiceImpl.java @@ -0,0 +1,286 @@ +package com.jzo2o.trade.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; +import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.constant.Constants; +import com.jzo2o.trade.constant.TradingCacheConstant; +import com.jzo2o.trade.enums.RefundStatusEnum; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.BasicPayHandler; +import com.jzo2o.trade.handler.BeforePayHandler; +import com.jzo2o.trade.handler.HandlerFactory; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.model.dto.RefundRecordDTO; +import com.jzo2o.trade.model.dto.TradingDTO; +import com.jzo2o.trade.service.BasicPayService; +import com.jzo2o.trade.service.RefundRecordService; +import com.jzo2o.trade.service.TradingService; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * 支付的基础功能 + */ +@Slf4j +@Service +public class BasicPayServiceImpl implements BasicPayService { + + @Resource + private BeforePayHandler beforePayHandler; + @Resource + private RedissonClient redissonClient; + @Resource + private TradingService tradingService; + @Resource + private RefundRecordService refundRecordService; + @Resource + private IdentifierGenerator identifierGenerator; + + @Override + public TradingDTO queryTradingResult(Long tradingOrderNo) throws CommonException { + //通过单号查询交易单数据 + Trading trading = this.tradingService.findTradByTradingOrderNo(tradingOrderNo); + if(ObjectUtil.isNull(trading)){ + return null; + } + //如果已付款或已取消直接返回 + if(StrUtil.equalsAny(trading.getTradingState().getValue(),TradingStateEnum.YJS.getValue(),TradingStateEnum.QXDD.getValue())){ + return BeanUtil.toBean(trading,TradingDTO.class); + } + //查询前置处理:检测交易单参数 + this.beforePayHandler.checkQueryTrading(trading); + //支付状态 + TradingStateEnum tradingState = trading.getTradingState(); + //如果支付成功或支付取消就直接返回 + if (ObjectUtil.equal(tradingState, TradingStateEnum.YJS) || ObjectUtil.equal(tradingState, TradingStateEnum.QXDD)) { + return BeanUtil.toBean(trading, TradingDTO.class); + } + String key = TradingCacheConstant.QUERY_PAY + tradingOrderNo; + RLock lock = redissonClient.getFairLock(key); + try { + //获取锁 + if (lock.tryLock(TradingCacheConstant.REDIS_WAIT_TIME, TimeUnit.SECONDS)) { + //选取不同的支付渠道实现 + BasicPayHandler handler = HandlerFactory.get(trading.getTradingChannel(), BasicPayHandler.class); + Boolean result = handler.queryTrading(trading); + if (result) { + //如果交易单已经完成,需要将二维码数据删除,节省数据库空间,如果有需要可以再次生成 + if (ObjectUtil.equal(trading.getTradingState(), TradingStateEnum.YJS) || ObjectUtil.equal(trading.getTradingState(), TradingStateEnum.QXDD)) { + trading.setQrCode(""); + } + //更新数据 + this.tradingService.saveOrUpdate(trading); + } + return BeanUtil.toBean(trading, TradingDTO.class); + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_FAIL.getValue()); + } catch (CommonException e) { + throw e; + } catch (Exception e) { + log.error("查询交易单数据异常: trading = {}", trading, e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_FAIL.getValue()); + } finally { + lock.unlock(); + } + } + +// @Override +// @Transactional +// public ExecutionResultResDTO refundTradingByTradingOrderNo(Long tradingOrderNo, BigDecimal refundAmount) throws CommonException { +// //根据业务订单号查看交易单信息 +// Trading trading = this.tradingService.findTradByTradingOrderNo(tradingOrderNo); +// if(ObjectUtil.isEmpty(trading)){ +// throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NOT_FOUND.getValue()); +// } +// //只有已付款的交易单方可退款 +// if(ObjectUtil.notEqual(TradingStateEnum.YJS,trading.getTradingState())){ +// throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.REFUND_FAIL.getValue()); +// } +// +// ExecutionResultResDTO executionResultResDTO = refundTrading(trading.getTradingOrderNo(), refundAmount); +// return executionResultResDTO; +// } + + @Override + @Transactional + public RefundRecord refundTrading(Long tradingOrderNo, BigDecimal refundAmount) throws CommonException { + //通过单号查询交易单数据 + Trading trading = this.tradingService.findTradByTradingOrderNo(tradingOrderNo); + //入库前置检查 + this.beforePayHandler.checkRefundTrading(trading,refundAmount); + String key = TradingCacheConstant.REFUND_PAY + trading.getTradingOrderNo(); + RLock lock = redissonClient.getFairLock(key); + try { + //获取锁 + if (lock.tryLock(TradingCacheConstant.REDIS_WAIT_TIME, TimeUnit.SECONDS)) { + + //对于退款中的记录需要同步退款状态 + syncRefundResult(tradingOrderNo); + //查询退款记录 + List refundRecordList = this.refundRecordService.findByTradingOrderNo(trading.getTradingOrderNo()); + //取出退款成功或退款中的记录 + List collect = refundRecordList.stream().filter(r -> StrUtil.equalsAny(r.getRefundStatus().getValue(),RefundStatusEnum.SENDING.getValue(),RefundStatusEnum.SUCCESS.getValue())).collect(Collectors.toList()); + //当没有退款成功和退款中的记录时方可继续退款 + if(ObjectUtil.isEmpty(collect)){ + //设置退款金额 + trading.setRefund(refundAmount); + + RefundRecord refundRecord = new RefundRecord(); + //退款单号 + refundRecord.setRefundNo(Convert.toLong(this.identifierGenerator.nextId(refundRecord))); + refundRecord.setTradingOrderNo(trading.getTradingOrderNo()); + refundRecord.setProductOrderNo(trading.getProductOrderNo()); + refundRecord.setProductAppId(trading.getProductAppId()); + refundRecord.setRefundAmount(refundAmount); + refundRecord.setEnterpriseId(trading.getEnterpriseId()); + refundRecord.setTradingChannel(trading.getTradingChannel()); + refundRecord.setTotal(trading.getTradingAmount()); + //初始状态为退款中 + refundRecord.setRefundStatus(RefundStatusEnum.APPLY_REFUND); + this.refundRecordService.save(refundRecord); + //设置交易单是退款订单 + trading.setIsRefund(Constants.YES); + this.tradingService.saveOrUpdate(trading); + + //请求第三方退款 + //选取不同的支付渠道实现 + BasicPayHandler handler = HandlerFactory.get(refundRecord.getTradingChannel(), BasicPayHandler.class); + Boolean result = handler.refundTrading(refundRecord); + if (result) { + //更新退款记录数据 + this.refundRecordService.saveOrUpdate(refundRecord); + } + return refundRecord; + } + //取出第一条记录返回 + RefundRecord first = CollectionUtil.getFirst(refundRecordList); + if(ObjectUtil.isNotNull(first)){ + return first; + } + + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_FAIL.getValue()); + } catch (CommonException e) { + throw e; + } catch (Exception e) { + log.error("查询交易单数据异常:{}", ExceptionUtil.stacktraceToString(e)); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_FAIL.getValue()); + } finally { + lock.unlock(); + } + } + + /*** + * 对于退款中的记录需要同步退款状态 + * @param tradingOrderNo 交易单号 + */ + @Override + public void syncRefundResult(Long tradingOrderNo) throws CommonException{ + //查询退款记录 + List refundRecordList = this.refundRecordService.findByTradingOrderNo(tradingOrderNo); + //存在退款中记录 + List collect = refundRecordList.stream().filter(r -> r.getRefundStatus().equals(RefundStatusEnum.SENDING)).collect(Collectors.toList()); + + if (ObjectUtil.isNotEmpty(collect)) { + collect.forEach(v->{ + queryRefundTrading(v.getRefundNo()); + }); + } + + } + @Override + public RefundRecordDTO queryRefundTrading(Long refundNo) throws CommonException { + //通过单号查询交易单数据 + RefundRecord refundRecord = this.refundRecordService.findByRefundNo(refundNo); + //查询前置处理 + this.beforePayHandler.checkQueryRefundTrading(refundRecord); + + String key = TradingCacheConstant.REFUND_QUERY_PAY + refundNo; + RLock lock = redissonClient.getFairLock(key); + try { + //获取锁 + if (lock.tryLock(TradingCacheConstant.REDIS_WAIT_TIME, TimeUnit.SECONDS)) { + + //选取不同的支付渠道实现 + BasicPayHandler handler = HandlerFactory.get(refundRecord.getTradingChannel(), BasicPayHandler.class); + Boolean result = handler.queryRefundTrading(refundRecord); + if (result) { + //更新数据 + this.refundRecordService.saveOrUpdate(refundRecord); + } + return BeanUtil.toBean(refundRecord, RefundRecordDTO.class); + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.REFUND_FAIL.getValue()); + } catch (CommonException e) { + throw e; + } catch (Exception e) { + log.error("查询退款交易单数据异常: refundRecord = {}", refundRecord, e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.REFUND_FAIL.getValue()); + } finally { + lock.unlock(); + } + } + + /*** + * 关闭交易单 + * @param tradingOrderNo 交易单号 + * @return 是否成功 + */ + @Override + public Boolean closeTrading(Long tradingOrderNo) throws CommonException { + //通过单号查询交易单数据 + Trading trading = this.tradingService.findTradByTradingOrderNo(tradingOrderNo); + if (ObjectUtil.isEmpty(trading)) { + return true; + } + + //入库前置检查 + this.beforePayHandler.checkCloseTrading(trading); + + String key = TradingCacheConstant.CLOSE_PAY + trading.getTradingOrderNo(); + RLock lock = redissonClient.getFairLock(key); + try { + //获取锁 + if (lock.tryLock(TradingCacheConstant.REDIS_WAIT_TIME, TimeUnit.SECONDS)) { + + //选取不同的支付渠道实现 + BasicPayHandler handler = HandlerFactory.get(trading.getTradingChannel(), BasicPayHandler.class); + Boolean result = handler.closeTrading(trading); + if (result) { + trading.setQrCode(""); + this.tradingService.saveOrUpdate(trading); + } + return true; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_FAIL.getValue()); + } catch (CommonException e) { + throw e; + } catch (Exception e) { + log.error("查询交易单数据异常:{}", ExceptionUtil.stacktraceToString(e)); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_QUERY_FAIL.getValue()); + } finally { + lock.unlock(); + } + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/JsapiPayServiceImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/JsapiPayServiceImpl.java new file mode 100644 index 0000000..5b6c813 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/JsapiPayServiceImpl.java @@ -0,0 +1,84 @@ +package com.jzo2o.trade.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.constant.Constants; +import com.jzo2o.trade.constant.TradingCacheConstant; +import com.jzo2o.trade.constant.TradingConstant; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.handler.BeforePayHandler; +import com.jzo2o.trade.handler.HandlerFactory; +import com.jzo2o.trade.handler.JsapiPayHandler; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.service.JsapiPayService; +import com.jzo2o.trade.service.TradingService; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.concurrent.TimeUnit; + +/** + * @author itcast + */ +@Slf4j +@Service +public class JsapiPayServiceImpl implements JsapiPayService { + + @Resource + private RedissonClient redissonClient; + @Resource + private TradingService tradingService; + @Resource + private BeforePayHandler beforePayHandler; + + @Override + public Trading createJsapiTrading(Trading tradingEntity) { + //获取付款中的记录 + Trading trading = tradingService.queryDuringTrading(tradingEntity.getProductAppId(),tradingEntity.getProductOrderNo(), tradingEntity.getTradingChannel()); + //付款中的记录直接返回 + if (ObjectUtil.isNotNull(trading)){ + return trading; + } + //交易前置处理:检测交易单参数 + beforePayHandler.checkCreateTrading(tradingEntity); + tradingEntity.setEnableFlag(Constants.YES); + tradingEntity.setTradingType(TradingConstant.TRADING_TYPE_FK); + + //对交易订单加锁 + Long productOrderNo = tradingEntity.getProductOrderNo(); + String key = TradingCacheConstant.CREATE_PAY + productOrderNo; + RLock lock = redissonClient.getFairLock(key); + try { + //获取锁 + if (lock.tryLock(TradingCacheConstant.REDIS_WAIT_TIME, TimeUnit.SECONDS)) { + + //交易前置处理:幂等性处理 +// this.beforePayHandler.idempotentCreateTrading(tradingEntity); + + //调用不同的支付渠道进行处理 + JsapiPayHandler jsapiPayHandler = HandlerFactory.get(tradingEntity.getTradingChannel(), JsapiPayHandler.class); + jsapiPayHandler.createJsapiTrading(tradingEntity); + + //新增或更新交易数据 + boolean flag = this.tradingService.saveOrUpdate(tradingEntity); + if (!flag) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.SAVE_OR_UPDATE_FAIL.getValue()); + } + + return tradingEntity; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } catch (CommonException e) { + throw e; + } catch (Exception e) { + log.error("Jsapi预创建异常: tradingDTO = {}", tradingEntity, e); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } finally { + lock.unlock(); + } + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/NativePayServiceImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/NativePayServiceImpl.java new file mode 100644 index 0000000..9aa87fd --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/NativePayServiceImpl.java @@ -0,0 +1,132 @@ +package com.jzo2o.trade.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.ObjectUtil; +import com.jzo2o.api.trade.dto.response.NativePayResDTO; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.trade.constant.Constants; +import com.jzo2o.trade.constant.TradingCacheConstant; +import com.jzo2o.trade.constant.TradingConstant; +import com.jzo2o.trade.enums.TradingEnum; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.BasicPayHandler; +import com.jzo2o.trade.handler.BeforePayHandler; +import com.jzo2o.trade.handler.HandlerFactory; +import com.jzo2o.trade.handler.NativePayHandler; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.service.BasicPayService; +import com.jzo2o.trade.service.NativePayService; +import com.jzo2o.trade.service.QRCodeService; +import com.jzo2o.trade.service.TradingService; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * Native支付方式Face接口:商户生成二维码,用户扫描支付 + * + * @author itcast + */ +@Service +@Slf4j +public class NativePayServiceImpl implements NativePayService { + + @Resource + private RedissonClient redissonClient; + @Resource + private TradingService tradingService; + @Resource + private BeforePayHandler beforePayHandler; + @Resource + private QRCodeService qrCodeService; + @Resource + private BasicPayService basicPayService; + /** + * 切换支付渠道自动关单 + * @param tradingChannel 要切换的目标支付渠道 + * @param productAppId 业务系统标识 + * @param productOrderNo 业务订单号 + */ + private void changeChannelAndCloseTrading(String productAppId,Long productOrderNo,String tradingChannel){ + //根据订单号查询交易单 + List yjsTradByProductOrderNo = tradingService.queryByProductOrder(productAppId,productOrderNo); + + yjsTradByProductOrderNo.forEach(v->{ + //与目标支付渠道不同的渠道且支付中的进行关单 + if(ObjectUtil.notEqual(v.getTradingChannel(),tradingChannel) && + v.getTradingState().equals(TradingStateEnum.FKZ)){ + //关单 + Boolean result = basicPayService.closeTrading(v.getTradingOrderNo()); + log.info("业务系统:{},业务订单:{},切换交易订单:{}的支付渠道为:{},关闭其它支付渠道:{}",productAppId,productOrderNo,v.getTradingOrderNo(),tradingChannel,v.getTradingChannel()); + } + }); + + } + + @Override + public Trading createDownLineTrading(boolean changeChannel,Trading tradingEntity) { + //获取付款中的记录 + Trading trading = tradingService.queryDuringTrading(tradingEntity.getProductAppId(),tradingEntity.getProductOrderNo(), tradingEntity.getTradingChannel()); + //如果切换二维码需要查询其它支付渠道付款中的交易单进行退款操作 + if(changeChannel){ + changeChannelAndCloseTrading(tradingEntity.getProductAppId(),tradingEntity.getProductOrderNo(),tradingEntity.getTradingChannel()); + } + //付款中的记录直接返回无需生成二维码 + if (ObjectUtil.isNotNull(trading)){ + return trading; + } + //交易前置处理:检测交易单参数 + beforePayHandler.checkCreateTrading(tradingEntity); + + tradingEntity.setTradingType(TradingConstant.TRADING_TYPE_FK); + tradingEntity.setEnableFlag(Constants.YES); + + //对交易订单加锁 + Long productOrderNo = tradingEntity.getProductOrderNo(); + String key = TradingCacheConstant.CREATE_PAY + productOrderNo; + RLock lock = redissonClient.getFairLock(key); + try { + //获取锁 + if (lock.tryLock(TradingCacheConstant.REDIS_WAIT_TIME, TimeUnit.SECONDS)) { + //交易前置处理:幂等性处理 +// this.beforePayHandler.idempotentCreateTrading(tradingEntity); + + //调用不同的支付渠道进行处理 + PayChannelEnum payChannel = PayChannelEnum.valueOf(tradingEntity.getTradingChannel()); + NativePayHandler nativePayHandler = HandlerFactory.get(payChannel, NativePayHandler.class); + nativePayHandler.createDownLineTrading(tradingEntity); + + //生成统一收款二维码 + String placeOrderMsg = tradingEntity.getPlaceOrderMsg(); + String qrCode = this.qrCodeService.generate(placeOrderMsg, payChannel); + tradingEntity.setQrCode(qrCode); + //指定交易状态为付款中 + tradingEntity.setTradingState(TradingStateEnum.FKZ); + //新增交易数据 + boolean flag = this.tradingService.save(tradingEntity); + if (!flag) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.SAVE_OR_UPDATE_FAIL.getValue()); + } + + return tradingEntity; + } + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } catch (CommonException e) { + throw e; + } catch (Exception e) { + log.error("统一收单线下交易预创建异常:{}", ExceptionUtil.stacktraceToString(e)); + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, TradingEnum.NATIVE_PAY_FAIL.getValue()); + } finally { + lock.unlock(); + } + } + +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/NotifyServiceImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/NotifyServiceImpl.java new file mode 100644 index 0000000..8941fcf --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/NotifyServiceImpl.java @@ -0,0 +1,188 @@ +package com.jzo2o.trade.service.impl; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.alipay.easysdk.factory.Factory; +import com.alipay.easysdk.kernel.Config; +import com.jzo2o.common.constants.ErrorInfo; +import com.jzo2o.common.constants.MqConstants; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.common.model.msg.TradeStatusMsg; +import com.jzo2o.rabbitmq.client.RabbitClient; +import com.jzo2o.trade.constant.TradingCacheConstant; +import com.jzo2o.trade.constant.TradingConstant; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.handler.alipay.AlipayConfig; +import com.jzo2o.trade.handler.wechat.WechatPayHttpClient; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.service.NotifyService; +import com.jzo2o.trade.service.TradingService; +import com.wechat.pay.contrib.apache.httpclient.auth.Verifier; +import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager; +import com.wechat.pay.contrib.apache.httpclient.notification.Notification; +import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler; +import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * 支付成功的通知处理 + * + * @author itcast + */ +@Slf4j +@Service +public class NotifyServiceImpl implements NotifyService { + + @Resource + private TradingService tradingService; + @Resource + private RedissonClient redissonClient; + // @Resource +// private MQFeign mqFeign; + @Resource + private RabbitClient rabbitClient; + + @Override + public void wxPayNotify(NotificationRequest request, Long enterpriseId) throws CommonException { + // 查询配置 + WechatPayHttpClient client = WechatPayHttpClient.get(enterpriseId); + + JSONObject jsonData; + + //验证签名,确保请求来自微信 + try { + //确保在管理器中存在自动更新的商户证书 + client.createHttpClient(); + + CertificatesManager certificatesManager = CertificatesManager.getInstance(); + Verifier verifier = certificatesManager.getVerifier(client.getMchId()); + + //验签和解析请求数据 + NotificationHandler notificationHandler = new NotificationHandler(verifier, client.getApiV3Key().getBytes(StandardCharsets.UTF_8)); + Notification notification = notificationHandler.parse(request); + //通知的类型,支付成功通知的类型为TRANSACTION.SUCCESS,只处理此类通知 + if (!StrUtil.equals("TRANSACTION.SUCCESS", notification.getEventType())) { + return; + } + + //获取解密后的数据 + jsonData = JSONUtil.parseObj(notification.getDecryptData()); + } catch (Exception e) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, "验签失败"); + } + + //交易状态 + String tradeStateFromWX = jsonData.getStr("trade_state"); + /** + 交易状态,枚举值: + SUCCESS:支付成功 + REFUND:转入退款 + NOTPAY:未支付 + CLOSED:已关闭 + REVOKED:已撤销(付款码支付) + USERPAYING:用户支付中(付款码支付) + PAYERROR:支付失败(其他原因,如银行返回失败) + */ + String tradeStatus = TradingStateEnum.FKZ.getValue(); + if (StrUtil.equalsAny(tradeStateFromWX, TradingConstant.WECHAT_TRADE_CLOSED, TradingConstant.WECHAT_TRADE_REVOKED)) { + tradeStatus = TradingStateEnum.QXDD.getValue(); + //支付成功或转入退款的更新为已付款 + } else if (StrUtil.equalsAny(tradeStateFromWX, TradingConstant.WECHAT_TRADE_SUCCESS, TradingConstant.WECHAT_TRADE_REFUND)) { + tradeStatus = TradingStateEnum.YJS.getValue(); + } else if (StrUtil.equalsAny(tradeStateFromWX, TradingConstant.WECHAT_TRADE_PAYERROR)) { + tradeStatus = TradingStateEnum.FKSB.getValue(); + } + + //交易单号 + Long tradingOrderNo = jsonData.getLong("out_trade_no"); + log.info("微信支付通知:tradingOrderNo = {}, data = {}", tradingOrderNo, jsonData); + + //更新交易单 + this.updateTrading(tradingOrderNo, jsonData.getStr("transaction_id"),tradeStatus, jsonData.getStr("trade_state_desc"), jsonData.toString()); + } + + private void updateTrading(Long tradingOrderNo, String transactionId,String tradeStatus, String resultMsg, String resultJson) { + try { + Trading trading = this.tradingService.findTradByTradingOrderNo(tradingOrderNo); + trading.setTradingState(TradingStateEnum.valueOf(tradeStatus)); + //清空二维码数据 + trading.setQrCode(""); + trading.setTransactionId(transactionId); + trading.setResultMsg(resultMsg); + trading.setResultJson(resultJson); + this.tradingService.saveOrUpdate(trading); + + // 发消息通知其他系统 + TradeStatusMsg tradeStatusMsg = TradeStatusMsg.builder() + .tradingOrderNo(trading.getTradingOrderNo()) + .productOrderNo(trading.getProductOrderNo()) + .productAppId(trading.getProductAppId()) + .transactionId(trading.getTransactionId()) + .tradingChannel(trading.getTradingChannel()) + .statusCode(TradingStateEnum.YJS.getCode()) + .statusName(TradingStateEnum.YJS.name()) + .info(trading.getMemo())//备注信息 + .build(); + + String msg = JSONUtil.toJsonStr(Collections.singletonList(tradeStatusMsg)); + rabbitClient.sendMsg(MqConstants.Exchanges.TRADE, MqConstants.RoutingKeys.TRADE_UPDATE_STATUS, msg); + return; + } catch (Exception e) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, "处理业务失败"); + } + } + + @Override + public void aliPayNotify(HttpServletRequest request, Long enterpriseId) throws CommonException { + //获取参数 + Map parameterMap = request.getParameterMap(); + Map param = new HashMap<>(); + for (Map.Entry entry : parameterMap.entrySet()) { + param.put(entry.getKey(), StrUtil.join(",", entry.getValue())); + } + + String tradeStatusFromAli = param.get("trade_status"); + String tradeStatus = TradingStateEnum.FKZ.getValue(); + if (StrUtil.equals(TradingConstant.ALI_TRADE_CLOSED, tradeStatusFromAli)) { + //支付取消:TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款) + tradeStatus = TradingStateEnum.QXDD.getValue(); + } else if (StrUtil.equalsAny(tradeStatusFromAli, TradingConstant.ALI_TRADE_SUCCESS, TradingConstant.ALI_TRADE_FINISHED)) { + // TRADE_SUCCESS(交易支付成功) + // TRADE_FINISHED(交易结束,不可退款) + tradeStatus = TradingStateEnum.YJS.getValue(); + } + + //查询配置 + Config config = AlipayConfig.getConfig(enterpriseId); + Factory.setOptions(config); + try { + Boolean result = Factory + .Payment + .Common().verifyNotify(param); + if (!result) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, "验签失败"); + } + } catch (Exception e) { + throw new CommonException(ErrorInfo.Code.TRADE_FAILED, "验签失败"); + } + + //获取交易单号 + Long tradingOrderNo = Convert.toLong(param.get("out_trade_no")); + String transactionId = param.get("trade_no"); + //更新交易单 + this.updateTrading(tradingOrderNo, transactionId, tradeStatus,"", JSONUtil.toJsonStr(param)); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/PayChannelServiceImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/PayChannelServiceImpl.java new file mode 100644 index 0000000..014c1a0 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/PayChannelServiceImpl.java @@ -0,0 +1,78 @@ +package com.jzo2o.trade.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.trade.constant.Constants; +import com.jzo2o.trade.mapper.PayChannelMapper; +import com.jzo2o.trade.model.domain.PayChannel; +import com.jzo2o.trade.model.dto.PayChannelDTO; +import com.jzo2o.trade.service.PayChannelService; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.List; + +/** + * @author itcast + * @Description: 服务实现类 + */ +@Service +public class PayChannelServiceImpl extends ServiceImpl implements PayChannelService { + + @Override + public Page findPayChannelPage(PayChannelDTO payChannelDTO, int pageNum, int pageSize) { + Page page = new Page<>(pageNum, pageSize); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + + //设置条件 + queryWrapper.eq(StrUtil.isNotEmpty(payChannelDTO.getChannelLabel()), PayChannel::getChannelLabel, payChannelDTO.getChannelLabel()); + queryWrapper.likeRight(StrUtil.isNotEmpty(payChannelDTO.getChannelName()), PayChannel::getChannelName, payChannelDTO.getChannelName()); + queryWrapper.eq(StrUtil.isNotEmpty(payChannelDTO.getEnableFlag()), PayChannel::getEnableFlag, payChannelDTO.getEnableFlag()); + //设置排序 + queryWrapper.orderByAsc(PayChannel::getCreateTime); + + return super.page(page, queryWrapper); + } + + @Override + public PayChannel findByEnterpriseId(Long enterpriseId, String channelLabel) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PayChannel::getEnterpriseId, enterpriseId) + .eq(PayChannel::getChannelLabel, channelLabel) + .eq(PayChannel::getEnableFlag, Constants.YES); + return super.getOne(queryWrapper); + } + + @Override + public PayChannel createPayChannel(PayChannelDTO payChannelDTO) { + PayChannel payChannel = BeanUtil.toBean(payChannelDTO, PayChannel.class); + boolean flag = super.save(payChannel); + if (flag) { + return payChannel; + } + return null; + } + + @Override + public Boolean updatePayChannel(PayChannelDTO payChannelDTO) { + PayChannel payChannel = BeanUtil.toBean(payChannelDTO, PayChannel.class); + return super.updateById(payChannel); + } + + @Override + public Boolean deletePayChannel(String[] checkedIds) { + List ids = Arrays.asList(checkedIds); + return super.removeByIds(ids); + } + + @Override + public List findPayChannelList(String channelLabel) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PayChannel::getChannelLabel, channelLabel) + .eq(PayChannel::getEnableFlag, Constants.YES); + return list(queryWrapper); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/QRCodeServiceImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/QRCodeServiceImpl.java new file mode 100644 index 0000000..ce0a366 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/QRCodeServiceImpl.java @@ -0,0 +1,51 @@ +package com.jzo2o.trade.service.impl; + +import cn.hutool.core.img.ImgUtil; +import cn.hutool.core.util.HexUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.qrcode.QrCodeUtil; +import cn.hutool.extra.qrcode.QrConfig; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; +import com.jzo2o.trade.config.QRCodeConfig; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.service.QRCodeService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * @author itcast + */ +@Service +public class QRCodeServiceImpl implements QRCodeService { + + @Resource + private QRCodeConfig qrCodeConfig; + + @Override + public String generate(String content, PayChannelEnum payChannel) { + QrConfig qrConfig = new QrConfig(); + //设置边距 + qrConfig.setMargin(this.qrCodeConfig.getMargin()); + //二维码颜色 + qrConfig.setForeColor(HexUtil.decodeColor(this.qrCodeConfig.getForeColor())); + //设置背景色 + qrConfig.setBackColor(HexUtil.decodeColor(this.qrCodeConfig.getBackColor())); + //纠错级别 + qrConfig.setErrorCorrection(ErrorCorrectionLevel.valueOf(this.qrCodeConfig.getErrorCorrectionLevel())); + //设置宽 + qrConfig.setWidth(this.qrCodeConfig.getWidth()); + //设置高 + qrConfig.setHeight(this.qrCodeConfig.getHeight()); + if (ObjectUtil.isNotEmpty(payChannel)) { + //设置logo + qrConfig.setImg(this.qrCodeConfig.getLogo(payChannel)); + } + return QrCodeUtil.generateAsBase64(content, qrConfig, ImgUtil.IMAGE_TYPE_PNG); + } + + @Override + public String generate(String content) { + return generate(content, null); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/RefundRecordServiceImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/RefundRecordServiceImpl.java new file mode 100644 index 0000000..3b26ab7 --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/RefundRecordServiceImpl.java @@ -0,0 +1,54 @@ +package com.jzo2o.trade.service.impl; + +import cn.hutool.core.util.NumberUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.trade.enums.RefundStatusEnum; +import com.jzo2o.trade.mapper.RefundRecordMapper; +import com.jzo2o.trade.model.domain.RefundRecord; +import com.jzo2o.trade.service.RefundRecordService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author itcast + * @Description: 退款记录服务实现类 + */ +@Service +public class RefundRecordServiceImpl extends ServiceImpl implements RefundRecordService { + + @Override + public RefundRecord findByRefundNo(Long refundNo) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RefundRecord::getRefundNo, refundNo); + return super.getOne(queryWrapper); + } + + @Override + public List findByTradingOrderNo(Long tradingOrderNo) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RefundRecord::getTradingOrderNo, tradingOrderNo); + queryWrapper.orderByDesc(RefundRecord::getCreateTime); + return super.list(queryWrapper); + } + + @Override + public List findListByProductOrderNo(String productAppId,Long productOrderNo) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RefundRecord::getProductOrderNo, productOrderNo) + .eq(RefundRecord::getProductAppId, productAppId); + queryWrapper.orderByDesc(RefundRecord::getCreateTime); + return super.list(queryWrapper); + } + + @Override + public List findListByRefundStatus(RefundStatusEnum refundStatus, Integer count) { + count = NumberUtil.max(count, 10); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RefundRecord::getRefundStatus, refundStatus) + .orderByAsc(RefundRecord::getCreateTime) + .last("LIMIT " + count); + return list(queryWrapper); + } +} diff --git a/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/TradingServiceImpl.java b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/TradingServiceImpl.java new file mode 100644 index 0000000..353ac7a --- /dev/null +++ b/jzo2o-trade/src/main/java/com/jzo2o/trade/service/impl/TradingServiceImpl.java @@ -0,0 +1,98 @@ +package com.jzo2o.trade.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.NumberUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.trade.constant.Constants; +import com.jzo2o.trade.enums.TradingStateEnum; +import com.jzo2o.trade.mapper.TradingMapper; +import com.jzo2o.trade.model.domain.Trading; +import com.jzo2o.trade.model.dto.TradingDTO; +import com.jzo2o.trade.service.BasicPayService; +import com.jzo2o.trade.service.TradingService; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * @author itcast + * @Description:交易订单表 服务实现类 + */ +@Service +public class TradingServiceImpl extends ServiceImpl implements TradingService { + @Resource + private BasicPayService basicPayService; + @Override + public Trading findTradByTradingOrderNo(Long tradingOrderNo) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Trading::getTradingOrderNo, tradingOrderNo); + Trading one = super.getOne(queryWrapper); + return one; + } + + + + @Override + public List findListByTradingState(TradingStateEnum tradingState, Integer count) { + count = NumberUtil.max(count, 10); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Trading::getTradingState, tradingState) + .eq(Trading::getEnableFlag, Constants.YES) + .orderByAsc(Trading::getCreateTime) + .last("LIMIT " + count); + return list(queryWrapper); + } + + /** + * 根据订单id和支付方式查询付款中的交易单 + * + * @param productOrderNo 订单号 + * @param tradingChannel 支付渠道代码 + * @return 交易单 + */ + @Override + public Trading queryDuringTrading(String productAppId,Long productOrderNo, String tradingChannel){ + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Trading::getProductOrderNo, productOrderNo) + .eq(Trading::getProductAppId,productAppId) + .eq(Trading::getTradingState,TradingStateEnum.FKZ) + .eq(Trading::getTradingChannel, tradingChannel); + List list = list(queryWrapper); + Trading trading = CollectionUtil.getFirst(list); + return trading; + } + /** + * 根据订单id查询交易单 + * + * @param productOrderNo 订单号 + * @return 交易单 + */ + @Override + public List queryByProductOrder(String productAppId,Long productOrderNo){ + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Trading::getProductOrderNo, productOrderNo) + .eq(Trading::getProductAppId, productAppId); + return list(queryWrapper); + } + /** + * 根据订单id查询已付款的交易单 + * + * @param productOrderNo 订单id + * @return 交易单 + */ + @Override + public Trading findFinishedTrading(String productAppId,Long productOrderNo){ + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(Trading::getProductOrderNo, productOrderNo) + .eq(Trading::getProductAppId,productAppId) + .eq(Trading::getTradingState,TradingStateEnum.YJS); + List list = list(queryWrapper); + Trading first = CollectionUtil.getFirst(list); + return first; + } +} diff --git a/jzo2o-trade/src/main/resources/bootstrap-dev.yml b/jzo2o-trade/src/main/resources/bootstrap-dev.yml new file mode 100644 index 0000000..9e68052 --- /dev/null +++ b/jzo2o-trade/src/main/resources/bootstrap-dev.yml @@ -0,0 +1,17 @@ +spring: + cloud: + nacos: + username: nacos + password: nacos + server-addr: 192.168.122.135:8848 + config: + namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63 + file-extension: yaml + discovery: + namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63 + ip: ${ACCESS_IP:} + +################# 日志配置 ################# +logging: + level: + com.jzo2o: debug \ No newline at end of file diff --git a/jzo2o-trade/src/main/resources/bootstrap-prod.yml b/jzo2o-trade/src/main/resources/bootstrap-prod.yml new file mode 100644 index 0000000..06e37e6 --- /dev/null +++ b/jzo2o-trade/src/main/resources/bootstrap-prod.yml @@ -0,0 +1,16 @@ +spring: + cloud: + nacos: + username: ${NACOS_USERNAME} + password: ${NACOS_PASSWORD} + server-addr: ${NACOS_ADDR} + config: + namespace: ${NACOS_NAMESPACE} + file-extension: yaml + discovery: + namespace: ${NACOS_NAMESPACE} +logging: + level: + com.jzo2o: debug +server: + port: 8080 \ No newline at end of file diff --git a/jzo2o-trade/src/main/resources/bootstrap-test.yml b/jzo2o-trade/src/main/resources/bootstrap-test.yml new file mode 100644 index 0000000..06e37e6 --- /dev/null +++ b/jzo2o-trade/src/main/resources/bootstrap-test.yml @@ -0,0 +1,16 @@ +spring: + cloud: + nacos: + username: ${NACOS_USERNAME} + password: ${NACOS_PASSWORD} + server-addr: ${NACOS_ADDR} + config: + namespace: ${NACOS_NAMESPACE} + file-extension: yaml + discovery: + namespace: ${NACOS_NAMESPACE} +logging: + level: + com.jzo2o: debug +server: + port: 8080 \ No newline at end of file diff --git a/jzo2o-trade/src/main/resources/bootstrap.yml b/jzo2o-trade/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..0ad235f --- /dev/null +++ b/jzo2o-trade/src/main/resources/bootstrap.yml @@ -0,0 +1,88 @@ +################# 服务器配置 ################# +server: + port: 11505 + undertow: + accesslog: + enabled: true + pattern: "%t %a "%r" %s (%D ms)" + dir: /data/logs/undertow/${spring.application.name}/access-logs/ + servlet: + context-path: /trade + +################# spring公共配置 ################# +spring: + mvc: + path-match: + matching-strategy: ant_path_matcher + format: + date: yyyy-MM-dd HH:mm:ss + jackson: + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + profiles: + active: dev + application: + name: jzo2o-trade + main: + # 支持循环依赖注入 + allow-circular-references: true + # bean名相同覆盖 + allow-bean-definition-overriding: true + cloud: + nacos: + username: ${NACOS_USERNAME} + password: ${NACOS_PASSWORD} + server-addr: ${NACOS_ADDR} + discovery: + namespace: ${NACOS_NAMESPACE} + config: + namespace: ${NACOS_NAMESPACE} + file-extension: yaml + shared-configs: # 共享配置 + - data-id: shared-redis-cluster.yaml # 共享redis配置 + refresh: false + - data-id: shared-xxl-job.yaml # xxl-job配置 + refresh: false + - data-id: shared-rabbitmq.yaml # rabbitmq配置 + refresh: false + - data-id: shared-mysql.yaml # mysql配置 + refresh: false + +jzo2o: + job: + trading: + count: ${job.trading.count} #每次查询交易单的数量 + refund: + count: ${job.refund.count} #每次查询退款单的数量 + qrcode: #二维码生成参数 + margin: ${qrcode.margin} #边距,二维码和背景之间的边距 + fore-color: ${qrcode.fore-color} #二维码颜色,默认黑色 + back-color: ${qrcode.back-color} #背景色,默认白色 + #低级别的像素块更大,可以远距离识别,但是遮挡就会造成无法识别。高级别则相反,像素块小,允许遮挡一定范围,但是像素块更密集。 + error-correction-level: ${qrcode.error-correction-level} #纠错级别,可选参数:L、M、Q、H,默认:M + width: ${qrcode.width} #宽 + height: ${qrcode.height} #高 + +################# 项目独有配置 ################# +mysql: + db-name: jzo2o-trade +mybatis: + mapper-locations: mapper/*.xml + type-aliases-package: com.jzo2o.trade.mapper +swagger: + enable: true + package-path: com.jzo2o.trade.controller + title: 家政服务-支付服务接口文档 + description: 该微服务完记录交易、对接支付宝微信支付平台。 + contact-name: 传智教育·研究院 + contact-url: http://www.itcast.cn/ + contact-email: yjy@itcast.cn + version: v1.0 + +################# 日志配置 ################# +logging: + level: + com.jzo2o: debug + org.apache.http: info #es请求日志 +feign: + enable: true \ No newline at end of file diff --git a/jzo2o-trade/src/main/resources/logos/alipay.png b/jzo2o-trade/src/main/resources/logos/alipay.png new file mode 100644 index 0000000000000000000000000000000000000000..07b9a1d46d1dac47ebb5cb38e71c85e3adce44d5 GIT binary patch literal 1614 zcmX9-3pkW%6rQqEVzmaDXhTb-k=iZWZlo)jai3`tT2bvP*(JMjof(;NZ74>gqIA)a zP>HOBGI>-;*)DRA5WEK2!dWXtRz^%$G2h72?afbG?oak zJq0U-_%<91L$Ev&i^8xWk(8E+(C3kEgwzd%ZW!sH_zb&LGCpx{90}_b(k8MH4n#&G z5#d8TMVH`dH=evfWea{f2CX16U_}!M`Y?vgNzgokvR4@Xgv}?&+K77YG-Bg%&;rRC z%;K;%4nK=g)rR+<;d%}~#Nv24-i@Mf1brXyWfIdf7#v0NT?F5NyajigF*J&aDb&73 zSiyg-@loDHwyY5ddN4{G$-ch%3p>(rARFFUICKTidN4W;VKIJ_!CC@+KJK?-d&fS~|x85o-&=kt3G;!2TPiBvff$`D$By_v8{ z!K!Fv)necyG=t!E35rjc0j8$W_70^l5qlfXXRz!j)C18!f-7|};3MT8K2Ly?hVu_l z+lhUbkzGfQomf*$3As~#Ax6f)Jc-0|IG#pEHM-wJd}v!j>fLJPU>pi`{Qp6M$YC$Z_03=>Lhz zy4pLP!=ln93i=IdGL<#V%*pAU>d8^isj3OK{S=ClF3V~Q_vhL~>A1xL_QIn!soF;2 zT2k{jrQJc-I#1qiY7Y4Aw)MdRsfO(9CXE$t$D*{04zZJ6hKjO_4mDKx!}`GRFTsoS z#-{gXyq)aj*Yn<{7ph0KCv_SoIM`PnJ)M?dwn%o}Mtx39uXd`J`byI}H8o{JlXsO? z+P)@+@@f~lCZ(kz>YU|jyL}<7$sej*_x$5#pkAUJ>N8i)w&)pH*VN`=Mm_X)@w`2! zs`Rw1L&KKrd7|7NTeYLW{Be5rY?w0eih3^4#rY+wRNPThUylrth7j_Nw06X%OG7ZezO7H*r{OxU|fD zR{TC!-hO)FfJ8Q8ygi@B*m-m1s*I&eXt}J~T@OVi-2(2PJq#Ze@$W|%+fyZyv}IC` zuX9A^H3!cJ1$v_Mor9jWeNNOk_JdtX@h|e!jGUIzL$8+xVG{ z`azLQK27dE5a-)5bAeX#hk00n$=Q)QbHSx!-Up*?U;g^zd2R>GNSN)o<7%nu&D|6w zH>sbG<+H4UwNKrGi|Mu&Us}gi>F0D@%AX6|%6Wl33_-`?p|EI9R!zFUR@dxiIY+!u z#=M`9{>8(_SWU^?KPM*3ctgIVh1<0_CRcln@XpvP6@@B`(jeNvK3A$D*5`Pf(6ciT z*0;@bdZo{v<}&}Bj;j%9U*yc<%?KqGgQ1@$9Gs%3#QxzvoTmA2tAq1x7u*}u=eDsX zzw{SYheqBzRd283(leKqH$IV{Yqq?^@bdKJ2|uQigTaIje9v};7$(0TJKuiSVIz#b zR(S0fdpB2W&aYAKeBrTGG|OPQdXVGht2h+B;=b ZEe;`dC*7F=SBA*H#Ikm@y0+Cz_%EuVlF0x7 literal 0 HcmV?d00001 diff --git a/jzo2o-trade/src/main/resources/logos/wechat.png b/jzo2o-trade/src/main/resources/logos/wechat.png new file mode 100644 index 0000000000000000000000000000000000000000..036893733bcc648fff9e4a8f6c915df9b906f931 GIT binary patch literal 2702 zcmV;93UT#`P)2rqh4Anc2C?-95ka zec$ifMv_c?`S6blNY zV@E$%zfr-FbFyYm8#E>0N)|O!_~nXsDLnjYSrk5K8iD)Xs^ayBKiGAyxYY{l$f;{Y zBtwBxLM2#YQE|g?S0P%3S(X{+ag6kwz|g|0?*4h+T~5s@@&IpeCzMT#|;?s#KgzO3>X2ASk%H8 zcV=P&p0|@t5KTp2pF6ms_{oyG@}MW6sSebBDSf**g>q2DL}i-d4L;qweEg#ehZO=g zg{I;hK3odVDP;&4tbTEF=dv$X)WsT;+yM;5f(L+smv5f#7w`rN(lbGQgd#@7;%xD? z_y21218(eA1fx)Qcn08yE|eART6(7CtY7ytLZO|I($}E7*F)Zz#nAb-YSS>+=D%>? z@InY*?SO~=g0urARiYkkI8n57$zy4oSQo0 zqe7$ST|GBHZCc3NALs?i0OqPHMwAM8f(SgnVB4b4PHqo*Ly`i5+M-d!PHjrr{OX3< zp^hSl9P()?)UXVTSt+iR$pa@W$elkiZH)c>?y4_y0+|{9!GeYfcuI+;?Wo$bVCyeE zx?4vC;e>d}`iW%0yDF11pmsqPMP`Cz@(YkjtJMt0Oe-&teN)EN{EQh>(yz03cdY5e zhRP3LJ@nRsVTDg$ztU#9fCtuNOz!{U*W0Rg`W*pa0i;EIEqMX5g;f9$9E3t7WVM}Q zat9m(HIBS%bFycH*+4kqZSp6YYlna%kPt2mk0HUQDEV z04V1%Gd3x7?V{m}-Z--U^V6TZiQlQ|C_w^2|LX=$x-)zBjYFn)B!)6` z{}123S@G_c6I(SE`!p{S-7BgWHp4fjPk(XxGd_n8L6V{PE5CYX!{LoCr;o^}03Wo^ zFr&HtoL6W5$?xzz@%6Ktk8d@2%&YsLz)>1AESiy&dSgbx9a*=I4~>G{BuI#q>Tu1Q zrR&~3@?isLj^@{i1|^bJ6HRED;Y|P4YYU#c%AYOZTVgFs_paQ2b~lVpq7vDyAY71r zv(1b@JgR8v#Kl0=Pfu=pspR$VYReod$w|(>E$il4LkfoX&lT+elMPw~E8%$CmQ&mR zTJc`#g))ukPSuG7D?z=Glzb2uZW^&xR}&x(ELzjEnbJNfMmB{uRy%ehwyUMS3+ z2Q>l_?9f09I--3Jl-E_PE8no`*p?WL`gEU)H32La64>oy)^0YC1h?jXaq81QNuMl} zZ?-n zlBZxpgkG7{{OHK1ua~bYsV{RAw@Y)&;tH)s9Q8P#MD4j1jT?Ev>_6u}pXJX4%?D1R z^`#qE>|f<_y6qx$%s0DQEmn9==B$_VU+7qe+6&s?b9#^vCF$#wD_K!4 z#iZ4Y&d$tVeZwk`=1IuTvBsnGK6@Zyv=SAXM8)k@mC;kkxmR;Pcm0z$W#*q~KC$|n zS9YA<6QNNzc3`5xRkL0U$STU`$zts;`Bpr;C6E; z9k-ZbF*Ba(4oyrQxAWAl^R2ahPcrBLkiBJlpLnh8Er^m34IaH%M=tyeM;%@dNmg)G?FBwDi-E9QIMk*{ zLuPW;=G)&3x&oGHV^uIeu_QvZZFP%x|E9S5K){uh7@%Cv7F!1{5{q|?r7Jry-fm$b z_(;6X?eM-Y0NE#Lql>Y0`^zu5jzNkc`l!!J)KyicUMEZ4wv!V0+A zZ1ob)AFg|B-Zi&FDnYUk$RVtM(d)?;huR;k{@1eNrz#r``<=<4Eqyn*J;B40W~&i( ztFGmf9=>nbd?b9GwDvNuouij6pg`-PV~r;s-?yr`=0K9}lP!pP>F7kM8S7dPgPP6J zrlCoL9-p*)cJ@qBLS_lR^kB4QokSZk1XI5u+W6Bg_nvO6@~9qBfKKlC^06jH6)3Z1 z8BrE@sm_8y(^gJiHrSUYXA|sCwTs>bzVoRV@}OeUYDDIIe9x)oli)#MV484vl4lf{ z$g0@PrK#YOXYd%4`Vzn(PEojNvU^sKBIQ_`l0gCK=% z8IV4n(9$j`>;?}rfm4l;x69sHy6^WoM9a`^*|$A3x(J%JKH5-Gcet|YculmvF Date: Sun, 8 Sep 2024 21:29:26 +0800 Subject: [PATCH 07/21] =?UTF-8?q?feat(orders.manager):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=8E=B7=E5=8F=96=E6=94=AF=E4=BB=98=E4=BA=8C?= =?UTF-8?q?=E7=BB=B4=E7=A0=81=E6=94=AF=E4=BB=98=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/dto/request/NativePayReqDTO.java | 10 ++- .../consumer/ConsumerOrdersController.java | 12 ++++ .../manager/service/IOrdersCreateService.java | 9 ++- .../service/impl/OrdersCreateServiceImpl.java | 65 +++++++++++++++++++ 4 files changed, 92 insertions(+), 4 deletions(-) diff --git a/jzo2o-api/src/main/java/com/jzo2o/api/trade/dto/request/NativePayReqDTO.java b/jzo2o-api/src/main/java/com/jzo2o/api/trade/dto/request/NativePayReqDTO.java index 5d9106f..1cf5b59 100644 --- a/jzo2o-api/src/main/java/com/jzo2o/api/trade/dto/request/NativePayReqDTO.java +++ b/jzo2o-api/src/main/java/com/jzo2o/api/trade/dto/request/NativePayReqDTO.java @@ -2,13 +2,18 @@ package com.jzo2o.api.trade.dto.request; import com.jzo2o.api.trade.enums.PayChannelEnum; import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; import lombok.Data; import java.math.BigDecimal; +/** + * 支付服务请求参数 + * @author JIAN + */ @Data +@Builder public class NativePayReqDTO { - @ApiModelProperty(value = "商户号", required = true) private Long enterpriseId; @ApiModelProperty(value = "业务系统标识", required = true) @@ -27,5 +32,4 @@ public class NativePayReqDTO { @ApiModelProperty(value = "是否切换支付渠道", required = true) private boolean changeChannel=false; - -} +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java index b0e633f..dbb7de3 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java @@ -4,7 +4,9 @@ import com.jzo2o.api.orders.dto.response.OrderResDTO; import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; import com.jzo2o.common.utils.ObjectUtils; import com.jzo2o.mvc.utils.UserContext; +import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; import com.jzo2o.orders.manager.service.IOrdersCreateService; import com.jzo2o.orders.manager.service.IOrdersManagerService; @@ -60,4 +62,14 @@ public class ConsumerOrdersController { return ordersCreateService.placeOrder(placeOrderReqDTO); } + + @PutMapping("/pay/{id}") + @ApiOperation("订单支付") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) + }) + public OrdersPayResDTO pay(@PathVariable("id") Long id, + @RequestBody OrdersPayReqDTO ordersPayReqDTO) { + return ordersCreateService.payOrder(id, ordersPayReqDTO); + } } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java index 58079bd..d6e0b82 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java @@ -2,14 +2,15 @@ package com.jzo2o.orders.manager.service; import com.baomidou.mybatisplus.extension.service.IService; import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; /** *

* 下单服务类 *

- * * @author itcast * @since 2023-07-10 */ @@ -18,4 +19,10 @@ public interface IOrdersCreateService extends IService { * 客户端下单接口 */ PlaceOrderResDTO placeOrder(PlaceOrderReqDTO placeOrderReqDTO); + + /** + * 客户端支付接口 + * @param id 订单id + */ + OrdersPayResDTO payOrder(Long id, OrdersPayReqDTO ordersPayReqDTO); } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java index d8f97e9..8bc800c 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java @@ -3,8 +3,13 @@ package com.jzo2o.orders.manager.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jzo2o.api.customer.dto.response.AddressBookResDTO; import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; +import com.jzo2o.api.trade.NativePayApi; +import com.jzo2o.api.trade.dto.request.NativePayReqDTO; +import com.jzo2o.api.trade.dto.response.NativePayResDTO; +import com.jzo2o.api.trade.enums.PayChannelEnum; import com.jzo2o.common.expcetions.CommonException; import com.jzo2o.common.expcetions.ForbiddenOperationException; +import com.jzo2o.common.utils.BeanUtils; import com.jzo2o.common.utils.DateUtils; import com.jzo2o.common.utils.ObjectUtils; import com.jzo2o.mvc.utils.UserContext; @@ -13,8 +18,11 @@ import com.jzo2o.orders.base.enums.OrderPayStatusEnum; import com.jzo2o.orders.base.enums.OrderStatusEnum; import com.jzo2o.orders.base.mapper.OrdersMapper; import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; +import com.jzo2o.orders.manager.porperties.TradeProperties; import com.jzo2o.orders.manager.service.IOrdersCreateService; import com.jzo2o.orders.manager.service.client.CustomerClient; import lombok.extern.slf4j.Slf4j; @@ -42,6 +50,12 @@ public class OrdersCreateServiceImpl extends ServiceImpl i private RedisTemplate redisTemplate; @Resource private TransactionTemplate transactionTemplate; + @Resource + private NativePayApi nativePayApi; + @Resource + private TradeProperties tradeProperties; + + private final String PRODUCT_APP_ID = "jzo2o.orders"; /** * 生成订单号(2位年+2位月+2位日+13位序号) @@ -110,4 +124,55 @@ public class OrdersCreateServiceImpl extends ServiceImpl i return orderToPay.getId(); })); } + + @Override + public OrdersPayResDTO payOrder(Long id, OrdersPayReqDTO ordersPayReqDTO) { + Orders orders = baseMapper.selectById(id); + if (ObjectUtils.isEmpty(orders)) { + throw new ForbiddenOperationException("订单不存在无法支付"); + } + + // 初步防止重复发起支付请求 + if (orders.getPayStatus() == OrderPayStatusEnum.PAY_SUCCESS.getStatus()) { + OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(orders, OrdersPayResDTO.class); + ordersPayResDTO.setProductOrderNo(id); + return ordersPayResDTO; + } + + // 构造公共参数 + PayChannelEnum tradingChannel = ordersPayReqDTO.getTradingChannel(); + NativePayReqDTO nativePayReqDTO = NativePayReqDTO.builder() + .productAppId(PRODUCT_APP_ID) + .productOrderNo(id) + .tradingChannel(tradingChannel) + .tradingAmount(/*orders.getRealPayAmount() 测试统一使用0.1元*/ new BigDecimal("0.1")) + .memo(orders.getServeItemName() + orders.getPurNum() + "个") + .changeChannel(tradingChannel.name().equals(orders.getTradingChannel())) + .build(); + + // 获取支付渠道对应的商户号 + if (tradingChannel == PayChannelEnum.WECHAT_PAY) { + nativePayReqDTO.setEnterpriseId(tradeProperties.getWechatEnterpriseId()); + } else if (tradingChannel == PayChannelEnum.ALI_PAY) { + nativePayReqDTO.setEnterpriseId(tradeProperties.getAliEnterpriseId()); + } else { + throw new ForbiddenOperationException("未知支付渠道无法支付"); + } + + // 支付服务获取支付二维码 + NativePayResDTO nativePayResDTO = nativePayApi.createDownLineTrading(nativePayReqDTO); + + // 更新订单表信息 + if (!lambdaUpdate().eq(Orders::getId, id) + .set(Orders::getTradingOrderNo, nativePayResDTO.getTradingOrderNo()) + .set(Orders::getTradingChannel, nativePayResDTO.getTradingChannel()) + .update()) { + log.warn("订单表更新失败(已正常生成支付二维码), 订单id: {}", id); + } + + // 组装响应信息返回 + OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(nativePayResDTO, OrdersPayResDTO.class); + ordersPayResDTO.setPayStatus(OrderPayStatusEnum.NO_PAY.getStatus()); + return ordersPayResDTO; + } } \ No newline at end of file From 7e0b8840a4996334461837cb36dd4dd5cf99a828 Mon Sep 17 00:00:00 2001 From: JIAN Date: Sun, 8 Sep 2024 22:32:15 +0800 Subject: [PATCH 08/21] =?UTF-8?q?feat(orders.manager):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=8E=B7=E5=8F=96=E6=94=AF=E4=BB=98=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../consumer/ConsumerOrdersController.java | 9 ++++ .../manager/service/IOrdersCreateService.java | 5 ++ .../service/impl/OrdersCreateServiceImpl.java | 46 ++++++++++++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java index dbb7de3..b6a5345 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java @@ -72,4 +72,13 @@ public class ConsumerOrdersController { @RequestBody OrdersPayReqDTO ordersPayReqDTO) { return ordersCreateService.payOrder(id, ordersPayReqDTO); } + + @GetMapping("/pay/{id}/result") + @ApiOperation("查询订单支付结果") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) + }) + public OrdersPayResDTO payResult(@PathVariable("id") Long id) { + return ordersCreateService.getPayResult(id); + } } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java index d6e0b82..1951266 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java @@ -25,4 +25,9 @@ public interface IOrdersCreateService extends IService { * @param id 订单id */ OrdersPayResDTO payOrder(Long id, OrdersPayReqDTO ordersPayReqDTO); + + /** + * 客户端获取支付状态 + */ + OrdersPayResDTO getPayResult(Long id); } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java index 8bc800c..6088ca8 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java @@ -4,9 +4,12 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jzo2o.api.customer.dto.response.AddressBookResDTO; import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO; import com.jzo2o.api.trade.NativePayApi; +import com.jzo2o.api.trade.TradingApi; import com.jzo2o.api.trade.dto.request.NativePayReqDTO; import com.jzo2o.api.trade.dto.response.NativePayResDTO; +import com.jzo2o.api.trade.dto.response.TradingResDTO; import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.api.trade.enums.TradingStateEnum; import com.jzo2o.common.expcetions.CommonException; import com.jzo2o.common.expcetions.ForbiddenOperationException; import com.jzo2o.common.utils.BeanUtils; @@ -53,6 +56,8 @@ public class OrdersCreateServiceImpl extends ServiceImpl i @Resource private NativePayApi nativePayApi; @Resource + private TradingApi tradingApi; + @Resource private TradeProperties tradeProperties; private final String PRODUCT_APP_ID = "jzo2o.orders"; @@ -88,7 +93,7 @@ public class OrdersCreateServiceImpl extends ServiceImpl i // 组装订单信息插入数据库完成下单 LocalDateTime serveStartTime = placeOrderReqDTO.getServeStartTime(); - Long sortColumn = DateUtils.toEpochMilli(serveStartTime) * 100000 + orderId % 100000; + Long sortColumn = DateUtils.toEpochMilli(serveStartTime) + orderId % 100000; Orders orderToPay = Orders.builder() .id(orderId) .userId(UserContext.currentUserId()) @@ -175,4 +180,43 @@ public class OrdersCreateServiceImpl extends ServiceImpl i ordersPayResDTO.setPayStatus(OrderPayStatusEnum.NO_PAY.getStatus()); return ordersPayResDTO; } + + @Override + public OrdersPayResDTO getPayResult(Long id) { + Orders orders = baseMapper.selectById(id); + if (ObjectUtils.isEmpty(orders)) { + throw new CommonException("订单不存在"); + } + + // 公共返回参数 + OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(orders, OrdersPayResDTO.class); + ordersPayResDTO.setProductOrderNo(id); + + // 未支付订单更新状态 + Long tradingOrderNo = orders.getTradingOrderNo(); + if (ObjectUtils.isNotEmpty(tradingOrderNo) + && orders.getPayStatus() == OrderPayStatusEnum.NO_PAY.getStatus()) { + TradingResDTO tradingResDTO = tradingApi.findTradResultByTradingOrderNo(tradingOrderNo); + + // 支付成功 + if (ObjectUtils.isNotEmpty(tradingResDTO) + && tradingResDTO.getTradingState() == TradingStateEnum.YJS) { + lambdaUpdate() + .eq(Orders::getId, id) + .set(Orders::getPayTime, LocalDateTime.now()) + .set(Orders::getPayStatus, OrderPayStatusEnum.PAY_SUCCESS.getStatus()) + .set(Orders::getOrdersStatus, OrderStatusEnum.DISPATCHING.getStatus()) + .set(Orders::getTransactionId, tradingResDTO.getTransactionId()) + .update(); + + // 支付成功更新最终响应信息的状态 + ordersPayResDTO.setPayStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus()); + } else { + // 未支付成功返回二维码 + ordersPayResDTO.setQrCode(tradingResDTO.getQrCode()); + } + } + + return ordersPayResDTO; + } } \ No newline at end of file From 31c36abeaa7f5b4721159932f9ea72f9a0df8854 Mon Sep 17 00:00:00 2001 From: JIAN Date: Tue, 10 Sep 2024 11:29:43 +0800 Subject: [PATCH 09/21] =?UTF-8?q?feat(orders.manager):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=9B=91=E5=90=AC=E6=94=AF=E4=BB=98=E6=88=90=E5=8A=9F=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E6=9B=B4=E6=96=B0=E6=94=AF=E4=BB=98=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/service/IOrdersCommonService.java | 8 +- .../service/impl/OrdersCommonServiceImpl.java | 28 +++---- .../manager/listener/TradeStatusListener.java | 77 +++++++++++++++++++ .../manager/service/IOrdersCreateService.java | 5 ++ 4 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/listener/TradeStatusListener.java diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersCommonService.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersCommonService.java index c35345b..e013b2c 100644 --- a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersCommonService.java +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/IOrdersCommonService.java @@ -13,6 +13,8 @@ import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; * @since 2023-08-02 */ public interface IOrdersCommonService extends IService { - - Integer updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO); -} + /** + * 更新指定id订单的状态 + */ + Boolean updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO); +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java index 72c781c..fa38736 100644 --- a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java @@ -1,8 +1,6 @@ package com.jzo2o.orders.base.service.impl; import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jzo2o.orders.base.mapper.OrdersMapper; import com.jzo2o.orders.base.model.domain.Orders; @@ -14,27 +12,25 @@ import org.springframework.stereotype.Service; *

* 订单表 服务实现类 *

- * * @author itcast * @since 2023-08-02 */ @Service public class OrdersCommonServiceImpl extends ServiceImpl implements IOrdersCommonService { @Override - public Integer updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO) { - LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate() + public Boolean updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO) { + return lambdaUpdate() .eq(Orders::getId, orderUpdateStatusReqDTO.getId()) .gt(Orders::getUserId, 0) - .eq(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getOriginStatus()),Orders::getOrdersStatus,orderUpdateStatusReqDTO.getOriginStatus()) + .eq(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getOriginStatus()), Orders::getOrdersStatus, orderUpdateStatusReqDTO.getOriginStatus()) .set(Orders::getOrdersStatus, orderUpdateStatusReqDTO.getTargetStatus()) - .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getPayStatus()),Orders::getPayStatus,orderUpdateStatusReqDTO.getPayStatus()) - .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getPayTime()),Orders::getPayTime,orderUpdateStatusReqDTO.getPayTime()) - .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getEvaluationTime()),Orders::getEvaluationTime,orderUpdateStatusReqDTO.getEvaluationTime()) - .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingOrderNo()),Orders::getTradingOrderNo,orderUpdateStatusReqDTO.getTradingOrderNo()) - .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTransactionId()),Orders::getTransactionId,orderUpdateStatusReqDTO.getTransactionId()) - .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingChannel()),Orders::getTradingChannel,orderUpdateStatusReqDTO.getTradingChannel()) - .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getRefundStatus()),Orders::getRefundStatus,orderUpdateStatusReqDTO.getRefundStatus()); - boolean update = super.update(updateWrapper); - return update?1:0; + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getPayStatus()), Orders::getPayStatus, orderUpdateStatusReqDTO.getPayStatus()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getPayTime()), Orders::getPayTime, orderUpdateStatusReqDTO.getPayTime()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getEvaluationTime()), Orders::getEvaluationTime, orderUpdateStatusReqDTO.getEvaluationTime()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingOrderNo()), Orders::getTradingOrderNo, orderUpdateStatusReqDTO.getTradingOrderNo()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTransactionId()), Orders::getTransactionId, orderUpdateStatusReqDTO.getTransactionId()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingChannel()), Orders::getTradingChannel, orderUpdateStatusReqDTO.getTradingChannel()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getRefundStatus()), Orders::getRefundStatus, orderUpdateStatusReqDTO.getRefundStatus()) + .update(); } -} +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/listener/TradeStatusListener.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/listener/TradeStatusListener.java new file mode 100644 index 0000000..d92dd81 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/listener/TradeStatusListener.java @@ -0,0 +1,77 @@ +package com.jzo2o.orders.manager.listener; + +import com.alibaba.fastjson.JSON; +import com.jzo2o.common.constants.MqConstants; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.model.msg.TradeStatusMsg; +import com.jzo2o.common.utils.CollUtils; +import com.jzo2o.orders.base.enums.OrderPayStatusEnum; +import com.jzo2o.orders.base.enums.OrderStatusEnum; +import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; +import com.jzo2o.orders.base.service.IOrdersCommonService; +import com.jzo2o.orders.manager.service.IOrdersCreateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.ExchangeTypes; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 监听支付订单状态更新的消息 + * @author JIAN + */ +@Slf4j +@Component +public class TradeStatusListener { + @Resource + private IOrdersCreateService ordersCreateService; + @Resource + private IOrdersCommonService ordersCommonService; + @Resource + private TransactionTemplate transactionTemplate; + + + @RabbitListener(bindings = @QueueBinding( + value = @Queue(name = MqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS), + exchange = @Exchange(name = MqConstants.Exchanges.TRADE, type = ExchangeTypes.TOPIC), + key = MqConstants.RoutingKeys.TRADE_UPDATE_STATUS)) + public void onStatusUpdateMsg(String msg) { + log.info("接收到支付结果状态的消息 ({}) -> {}", MqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS, msg); + + List msgList = JSON.parseArray(msg, TradeStatusMsg.class); + if (CollUtils.isEmpty(msgList)) { + return; + } + + // 处理当前微服务并且支付成功的订单 + List tradeStatusMsgList = msgList.stream() + .filter(statusMsg -> ordersCreateService.PRODUCT_APP_ID.equals(statusMsg.getProductAppId()) + && statusMsg.getStatusCode() == OrderPayStatusEnum.PAY_SUCCESS.getStatus()) + .collect(Collectors.toList()); + + transactionTemplate.execute(status -> { + for (TradeStatusMsg tradeStatusMsg : tradeStatusMsgList) { + if (!ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(tradeStatusMsg.getProductOrderNo()) + .originStatus(OrderStatusEnum.NO_PAY.getStatus()) + .targetStatus(OrderStatusEnum.DISPATCHING.getStatus()) + .payStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus()) + .tradingOrderNo(tradeStatusMsg.getTradingOrderNo()) + .transactionId(tradeStatusMsg.getTransactionId()) + .tradingChannel(tradeStatusMsg.getTradingChannel()) + .payTime(LocalDateTime.now()).build())) { + throw new DBException("更新订单状态失败"); + } + } + return true; + }); + } +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java index 1951266..6858b43 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCreateService.java @@ -15,6 +15,11 @@ import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; * @since 2023-07-10 */ public interface IOrdersCreateService extends IService { + /** + * 微服务标识 + */ + String PRODUCT_APP_ID = "jzo2o.orders"; + /** * 客户端下单接口 */ From edc2cbf7efbe8a8e8dccf3dc729203ff6a22a454 Mon Sep 17 00:00:00 2001 From: JIAN Date: Tue, 10 Sep 2024 11:30:22 +0800 Subject: [PATCH 10/21] =?UTF-8?q?refactor(orders.manager):=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=9B=B4=E6=96=B0=E8=AE=A2=E5=8D=95=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../manager/listener/TradeStatusListener.java | 6 ++--- .../service/impl/OrdersCreateServiceImpl.java | 25 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/listener/TradeStatusListener.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/listener/TradeStatusListener.java index d92dd81..86673fe 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/listener/TradeStatusListener.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/listener/TradeStatusListener.java @@ -1,6 +1,7 @@ package com.jzo2o.orders.manager.listener; import com.alibaba.fastjson.JSON; +import com.jzo2o.api.trade.enums.TradingStateEnum; import com.jzo2o.common.constants.MqConstants; import com.jzo2o.common.expcetions.DBException; import com.jzo2o.common.model.msg.TradeStatusMsg; @@ -54,10 +55,10 @@ public class TradeStatusListener { // 处理当前微服务并且支付成功的订单 List tradeStatusMsgList = msgList.stream() .filter(statusMsg -> ordersCreateService.PRODUCT_APP_ID.equals(statusMsg.getProductAppId()) - && statusMsg.getStatusCode() == OrderPayStatusEnum.PAY_SUCCESS.getStatus()) + && TradingStateEnum.YJS.getCode().equals(statusMsg.getStatusCode())) .collect(Collectors.toList()); - transactionTemplate.execute(status -> { + transactionTemplate.executeWithoutResult(status -> { for (TradeStatusMsg tradeStatusMsg : tradeStatusMsgList) { if (!ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() .id(tradeStatusMsg.getProductOrderNo()) @@ -71,7 +72,6 @@ public class TradeStatusListener { throw new DBException("更新订单状态失败"); } } - return true; }); } } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java index 6088ca8..9bde263 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCreateServiceImpl.java @@ -21,6 +21,8 @@ import com.jzo2o.orders.base.enums.OrderPayStatusEnum; import com.jzo2o.orders.base.enums.OrderStatusEnum; import com.jzo2o.orders.base.mapper.OrdersMapper; import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; +import com.jzo2o.orders.base.service.IOrdersCommonService; import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; @@ -59,8 +61,8 @@ public class OrdersCreateServiceImpl extends ServiceImpl i private TradingApi tradingApi; @Resource private TradeProperties tradeProperties; - - private final String PRODUCT_APP_ID = "jzo2o.orders"; + @Resource + private IOrdersCommonService ordersCommonService; /** * 生成订单号(2位年+2位月+2位日+13位序号) @@ -150,7 +152,7 @@ public class OrdersCreateServiceImpl extends ServiceImpl i .productAppId(PRODUCT_APP_ID) .productOrderNo(id) .tradingChannel(tradingChannel) - .tradingAmount(/*orders.getRealPayAmount() 测试统一使用0.1元*/ new BigDecimal("0.1")) + .tradingAmount(/*orders.getRealPayAmount() 测试统一使用0.01元*/ new BigDecimal("0.01")) .memo(orders.getServeItemName() + orders.getPurNum() + "个") .changeChannel(tradingChannel.name().equals(orders.getTradingChannel())) .build(); @@ -201,13 +203,16 @@ public class OrdersCreateServiceImpl extends ServiceImpl i // 支付成功 if (ObjectUtils.isNotEmpty(tradingResDTO) && tradingResDTO.getTradingState() == TradingStateEnum.YJS) { - lambdaUpdate() - .eq(Orders::getId, id) - .set(Orders::getPayTime, LocalDateTime.now()) - .set(Orders::getPayStatus, OrderPayStatusEnum.PAY_SUCCESS.getStatus()) - .set(Orders::getOrdersStatus, OrderStatusEnum.DISPATCHING.getStatus()) - .set(Orders::getTransactionId, tradingResDTO.getTransactionId()) - .update(); + + ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(id) + .originStatus(OrderStatusEnum.NO_PAY.getStatus()) + .targetStatus(OrderStatusEnum.DISPATCHING.getStatus()) + .payStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus()) + .tradingOrderNo(tradingResDTO.getTradingOrderNo()) + .transactionId(tradingResDTO.getTransactionId()) + .tradingChannel(tradingResDTO.getTradingChannel()) + .payTime(LocalDateTime.now()).build()); // 支付成功更新最终响应信息的状态 ordersPayResDTO.setPayStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus()); From f3604d983001fd79467c6daab5a135739e68c9ab Mon Sep 17 00:00:00 2001 From: JIAN Date: Tue, 10 Sep 2024 13:52:06 +0800 Subject: [PATCH 11/21] =?UTF-8?q?feat(orders.manager):=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=8F=96=E6=B6=88=E6=9C=AA=E6=94=AF=E4=BB=98=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD=20=201.=20=E6=89=8B=E5=8A=A8?= =?UTF-8?q?=E8=AE=BF=E9=97=AE=E5=8F=96=E6=B6=88=202.=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E8=BD=AE=E8=AF=A2=E5=8F=96=E6=B6=88=203.=20=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=97=B6=E8=87=AA=E5=8A=A8=E5=8F=96=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/model/domain/OrdersCanceled.java | 13 +- .../consumer/ConsumerOrdersController.java | 21 +++ .../inner/InnerOrdersController.java | 4 +- .../orders/manager/job/OrderCancelJob.java | 38 +++++ .../service/IOrdersManagerService.java | 41 +++-- .../impl/OrdersManagerServiceImpl.java | 152 +++++++++++++++--- 6 files changed, 221 insertions(+), 48 deletions(-) create mode 100644 jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/job/OrderCancelJob.java diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersCanceled.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersCanceled.java index bd7a5f4..484156a 100644 --- a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersCanceled.java +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersCanceled.java @@ -1,23 +1,26 @@ package com.jzo2o.orders.base.model.domain; -import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; -import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.TableId; -import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.time.LocalDateTime; + /** *

- * + * *

* * @author itcast * @since 2023-08-19 */ @Data +@Builder @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("orders_canceled") @@ -65,4 +68,4 @@ public class OrdersCanceled implements Serializable { * 更新时间 */ private LocalDateTime updateTime; -} +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java index b6a5345..e05dc99 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java @@ -1,9 +1,13 @@ package com.jzo2o.orders.manager.controller.consumer; +import com.jzo2o.api.orders.dto.request.OrderCancelReqDTO; import com.jzo2o.api.orders.dto.response.OrderResDTO; import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; +import com.jzo2o.common.expcetions.RequestUnauthorizedException; +import com.jzo2o.common.model.CurrentUserInfo; import com.jzo2o.common.utils.ObjectUtils; import com.jzo2o.mvc.utils.UserContext; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; @@ -81,4 +85,21 @@ public class ConsumerOrdersController { public OrdersPayResDTO payResult(@PathVariable("id") Long id) { return ordersCreateService.getPayResult(id); } + + @PutMapping("/cancel") + @ApiOperation("取消订单") + public void cancel(@RequestBody OrderCancelReqDTO orderCancelReqDTO) { + CurrentUserInfo currentUser = UserContext.currentUser(); + if (ObjectUtils.isEmpty(currentUser) || ObjectUtils.isEmpty(currentUser.getId())) { + throw new RequestUnauthorizedException("无法获取当前用户信息"); + } + + ordersManagerService.cancel(OrderCancelDTO.builder() + .id(orderCancelReqDTO.getId()) + .cancelReason(orderCancelReqDTO.getCancelReason()) + .currentUserId(currentUser.getId()) + .currentUserName(currentUser.getName()) + .currentUserType(currentUser.getUserType()) + .build()); + } } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersController.java index b32f7ba..c14450b 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersController.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/inner/InnerOrdersController.java @@ -33,7 +33,7 @@ public class InnerOrdersController implements OrdersApi { @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class), }) public OrderResDTO queryById(@PathVariable("id") Long id) { - Orders orders = ordersManagerService.queryById(id); + Orders orders = ordersManagerService.getById(id); return BeanUtil.toBean(orders, OrderResDTO.class); } @@ -57,4 +57,4 @@ public class InnerOrdersController implements OrdersApi { public void evaluate(@PathVariable("id") Long id) { ordersManagerService.evaluationOrder(id); } -} +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/job/OrderCancelJob.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/job/OrderCancelJob.java new file mode 100644 index 0000000..faaa839 --- /dev/null +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/job/OrderCancelJob.java @@ -0,0 +1,38 @@ +package com.jzo2o.orders.manager.job; + +import com.jzo2o.common.utils.CollUtils; +import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.manager.service.IOrdersManagerService; +import com.xxl.job.core.context.XxlJobHelper; +import com.xxl.job.core.handler.annotation.XxlJob; +import org.springframework.stereotype.Component; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 自动轮询取消订单 + * @author JIAN + */ +@Component +@SuppressWarnings("unused") +public class OrderCancelJob { + @Resource + private IOrdersManagerService ordersManagerService; + @Resource + private TransactionTemplate transactionTemplate; + + @XxlJob("cancelPayOverTimeOrder") + public void cancelPayOverTimeOrder() { + List orderList = ordersManagerService.getPayOverTimeOrder(100); + if (CollUtils.isEmpty(orderList)) { + XxlJobHelper.log("没有超时订单"); + return; + } + + // 取消所有超时未支付订单 + transactionTemplate.executeWithoutResult(status -> + orderList.forEach(order -> ordersManagerService.cancelPayOverTimeOrder(order.getId()))); + } +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java index ed1301c..ff70fd8 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java @@ -1,21 +1,10 @@ package com.jzo2o.orders.manager.service; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; -import com.jzo2o.api.market.dto.request.CouponUseBackReqDTO; -import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; import com.jzo2o.api.orders.dto.response.OrderResDTO; import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; -import com.jzo2o.common.model.PageResult; -import com.jzo2o.common.model.msg.TradeStatusMsg; import com.jzo2o.orders.base.model.domain.Orders; import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; -import com.jzo2o.orders.manager.model.dto.request.OrderPageQueryReqDTO; -import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; -import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; -import com.jzo2o.orders.manager.model.dto.response.OperationOrdersDetailResDTO; -import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; -import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; import java.util.List; @@ -23,23 +12,17 @@ import java.util.List; *

* 订单表 服务类 *

- * * @author itcast * @since 2023-07-10 */ public interface IOrdersManagerService extends IService { - /** - * @param ids - * @return + * 查询对应订单id的所有订单信息 */ List batchQuery(List ids); - Orders queryById(Long id); - /** * 滚动分页查询 - * * @param currentUserId 当前用户id * @param ordersStatus 订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:已取消,700:已关闭 * @param sortBy 排序字段 @@ -47,19 +30,33 @@ public interface IOrdersManagerService extends IService { */ List consumerQueryList(Long currentUserId, Integer ordersStatus, Long sortBy); - /** * 根据订单id查询 - * * @param id 订单id * @return 订单详情 */ OrderResDTO getDetail(Long id); + /** * 订单评价 - * * @param ordersId 订单id */ void evaluationOrder(Long ordersId); -} + /** + * 取消订单 + */ + void cancel(OrderCancelDTO orderCancelDTO); + + /** + * 系统取消超时订单(无前置判断) + *
仅内部使用!!! + */ + void cancelPayOverTimeOrder(Long id); + + /** + * 获取支付超时订单 + * @param count 订单数量 + */ + List getPayOverTimeOrder(Integer count); +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java index 129a217..9b81f40 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java @@ -1,7 +1,6 @@ package com.jzo2o.orders.manager.service.impl; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -9,16 +8,30 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jzo2o.api.orders.dto.response.OrderResDTO; import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; +import com.jzo2o.api.trade.TradingApi; +import com.jzo2o.api.trade.dto.response.TradingResDTO; +import com.jzo2o.api.trade.enums.TradingStateEnum; +import com.jzo2o.common.constants.UserType; import com.jzo2o.common.enums.EnableStatusEnum; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.expcetions.ForbiddenOperationException; import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.orders.base.enums.OrderStatusEnum; import com.jzo2o.orders.base.mapper.OrdersMapper; import com.jzo2o.orders.base.model.domain.Orders; -import com.jzo2o.orders.base.model.dto.OrderSnapshotDTO; +import com.jzo2o.orders.base.model.domain.OrdersCanceled; +import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; +import com.jzo2o.orders.base.service.IOrdersCommonService; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; +import com.jzo2o.orders.manager.service.IOrdersCanceledService; import com.jzo2o.orders.manager.service.IOrdersManagerService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionTemplate; +import javax.annotation.Resource; +import java.time.LocalDateTime; import java.util.List; import static com.jzo2o.orders.base.constants.FieldConstants.SORT_BY; @@ -27,28 +40,36 @@ import static com.jzo2o.orders.base.constants.FieldConstants.SORT_BY; *

* 订单表 服务实现类 *

- * * @author itcast * @since 2023-07-10 */ @Slf4j @Service public class OrdersManagerServiceImpl extends ServiceImpl implements IOrdersManagerService { + @Resource + private IOrdersCommonService ordersCommonService; + @Resource + private IOrdersCanceledService ordersCanceledService; + @Resource + private TransactionTemplate transactionTemplate; + @Resource + private TradingApi tradingApi; + + /** + * 订单超时时间 + */ + private final long PAY_OVERTIME_MINUTE = 15; @Override public List batchQuery(List ids) { - LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().in(Orders::getId, ids).ge(Orders::getUserId, 0); + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .in(Orders::getId, ids) + .ge(Orders::getUserId, 0); return baseMapper.selectList(queryWrapper); } - @Override - public Orders queryById(Long id) { - return baseMapper.selectById(id); - } - /** * 滚动分页查询 - * * @param currentUserId 当前用户id * @param ordersStatus 订单状态,0:待支付,100:派单中,200:待服务,300:服务中,400:待评价,500:订单完成,600:已取消,700:已关闭 * @param sortBy 排序字段 @@ -56,7 +77,7 @@ public class OrdersManagerServiceImpl extends ServiceImpl */ @Override public List consumerQueryList(Long currentUserId, Integer ordersStatus, Long sortBy) { - //1.构件查询条件 + // 1.构造查询条件 LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() .eq(ObjectUtils.isNotNull(ordersStatus), Orders::getOrdersStatus, ordersStatus) .lt(ObjectUtils.isNotNull(sortBy), Orders::getSortBy, sortBy) @@ -66,29 +87,46 @@ public class OrdersManagerServiceImpl extends ServiceImpl queryPage.addOrder(OrderItem.desc(SORT_BY)); queryPage.setSearchCount(false); - //2.查询订单列表 + // 2.查询订单列表 Page ordersPage = baseMapper.selectPage(queryPage, queryWrapper); List records = ordersPage.getRecords(); - List orderSimpleResDTOS = BeanUtil.copyToList(records, OrderSimpleResDTO.class); - return orderSimpleResDTOS; - + return BeanUtil.copyToList(records, OrderSimpleResDTO.class); } + /** * 根据订单id查询 - * * @param id 订单id * @return 订单详情 */ @Override public OrderResDTO getDetail(Long id) { - Orders orders = queryById(id); + Orders orders = baseMapper.selectById(id); + if (ObjectUtils.isEmpty(orders)) { + return new OrderResDTO(); + } + OrderResDTO orderResDTO = BeanUtil.toBean(orders, OrderResDTO.class); + // 订单超过15分钟未支付则自动取消 + if (OrderStatusEnum.NO_PAY.getStatus().equals(orders.getOrdersStatus()) + && orders.getCreateTime().isBefore(LocalDateTime.now().minusMinutes(PAY_OVERTIME_MINUTE))) { + cancelPayOverTimeOrder(id); + orderResDTO.setOrdersStatus(OrderStatusEnum.CANCELED.getStatus()); + } + + // 订单取消/关闭获取取消/关闭原因 + Integer ordersStatus = orderResDTO.getOrdersStatus(); + if (OrderStatusEnum.CANCELED.getStatus().equals(ordersStatus) + || OrderStatusEnum.CLOSED.getStatus().equals(ordersStatus)) { + OrdersCanceled canceledDetail = ordersCanceledService.getById(id); + orderResDTO.setCancelTime(canceledDetail.getCancelTime()); + orderResDTO.setCancelReason(canceledDetail.getCancelReason()); + } + return orderResDTO; } /** * 订单评价 - * * @param ordersId 订单id */ @Override @@ -106,4 +144,80 @@ public class OrdersManagerServiceImpl extends ServiceImpl // orderStateMachine.changeStatus(orders.getUserId(), orders.getId().toString(), OrderStatusChangeEventEnum.EVALUATE, orderSnapshotDTO); } -} + @Override + public void cancel(OrderCancelDTO orderCancelDTO) { + Long orderId = orderCancelDTO.getId(); + Orders orders = baseMapper.selectById(orderId); + if (ObjectUtils.isEmpty(orders)) { + throw new ForbiddenOperationException("订单不存在无法取消"); + } + // 补充前端无法确定的字段 + orderCancelDTO.setServeStartTime(orders.getServeStartTime()); + orderCancelDTO.setRealPayAmount(orders.getRealPayAmount()); + orderCancelDTO.setCityCode(orders.getCityCode()); + orderCancelDTO.setTradingOrderNo(orders.getTradingOrderNo()); + + Integer ordersStatus = orders.getOrdersStatus(); + if (OrderStatusEnum.NO_PAY.getStatus().equals(ordersStatus)) { + // 1. 未支付订单 -> 取消状态 + cancelNoPayOrder(orderCancelDTO); + } else if (OrderStatusEnum.DISPATCHING.getStatus().equals(ordersStatus)) { + // 2. 已支付订单 -> 关闭状态 + 退款 + cancelDispatchingOrder(orderCancelDTO); + } else { + throw new ForbiddenOperationException("订单无法取消"); + } + } + + @Override + public List getPayOverTimeOrder(Integer count) { + return lambdaQuery() + .eq(Orders::getOrdersStatus, OrderStatusEnum.NO_PAY.getStatus()) + .lt(Orders::getCreateTime, LocalDateTime.now().minusMinutes(PAY_OVERTIME_MINUTE)) + .last("LIMIT " + count) + .list(); + } + + @Override + public void cancelPayOverTimeOrder(Long id) { + // 二次确认防止在此期间支付 + TradingResDTO tradingResDTO = tradingApi.findTradResultByTradingOrderNo(id); + if (ObjectUtils.isEmpty(tradingResDTO) || tradingResDTO.getTradingState() != TradingStateEnum.YJS) { + cancelNoPayOrder(OrderCancelDTO.builder() + .id(id) + .cancelReason("订单超时未支付自动取消") + .currentUserId(-1L) + .currentUserName("SYSTEM") + .currentUserType(UserType.SYSTEM) + .build()); + } + } + + private void cancelNoPayOrder(OrderCancelDTO orderCancelDTO) { + Long orderId = orderCancelDTO.getId(); + transactionTemplate.executeWithoutResult(status -> { + if (!ordersCanceledService.save(OrdersCanceled.builder() + .id(orderId) + .cancellerId(orderCancelDTO.getCurrentUserId()) + .cancelerName(orderCancelDTO.getCurrentUserName()) + .cancellerType(orderCancelDTO.getCurrentUserType()) + .cancelReason(orderCancelDTO.getCancelReason()) + .cancelTime(LocalDateTime.now()) + .build())) { + throw new DBException("订单取消表更新失败"); + } + + if (!ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(orderId) + .originStatus(OrderStatusEnum.NO_PAY.getStatus()) + .targetStatus(OrderStatusEnum.CANCELED.getStatus()) + .build())) { + throw new DBException("订单表订单状态更新失败"); + } + }); + } + + private void cancelDispatchingOrder(OrderCancelDTO orderCancelDTO) { + return; + } +} \ No newline at end of file From e78ff52701a2a88f44f2d2b99e3455517990bd5e Mon Sep 17 00:00:00 2001 From: JIAN Date: Fri, 13 Sep 2024 00:36:56 +0800 Subject: [PATCH 12/21] =?UTF-8?q?feat/refactor(orders.manager):=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=8F=96=E6=B6=88=E6=B4=BE=E5=8D=95=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E7=9A=84=E5=8A=9F=E8=83=BD,=20=E6=95=B4?= =?UTF-8?q?=E5=90=88=E7=9B=B8=E5=85=B3=E5=8F=96=E6=B6=88=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E7=9A=84=E4=BB=A3=E7=A0=81=E5=88=B0=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E8=AE=A2=E5=8D=95=E4=B8=9A=E5=8A=A1=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/model/domain/OrdersRefund.java | 15 +- .../base/model/dto/OrderUpdateStatusDTO.java | 13 +- .../service/impl/OrdersCommonServiceImpl.java | 2 + .../consumer/ConsumerOrdersController.java | 10 +- .../orders/manager/job/OrderCancelJob.java | 25 +++- .../service/IOrdersCanceledService.java | 12 +- .../service/IOrdersManagerService.java | 12 -- .../manager/service/IOrdersRefundService.java | 15 +- .../impl/OrdersCanceledServiceImpl.java | 136 +++++++++++++++++- .../impl/OrdersManagerServiceImpl.java | 86 +---------- .../service/impl/OrdersRefundServiceImpl.java | 74 ++++++++-- 11 files changed, 275 insertions(+), 125 deletions(-) diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersRefund.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersRefund.java index b1fbb73..889e9f1 100644 --- a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersRefund.java +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/domain/OrdersRefund.java @@ -1,15 +1,17 @@ package com.jzo2o.orders.base.model.domain; -import java.math.BigDecimal; -import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; -import java.time.LocalDateTime; -import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + /** *

* 订单退款表 @@ -19,6 +21,7 @@ import lombok.experimental.Accessors; * @since 2023-09-07 */ @Data +@Builder @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("orders_refund") @@ -46,6 +49,4 @@ public class OrdersRefund implements Serializable { * 创建时间 */ private LocalDateTime createTime; - - -} +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderUpdateStatusDTO.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderUpdateStatusDTO.java index be60f36..be34b9f 100644 --- a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderUpdateStatusDTO.java +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/model/dto/OrderUpdateStatusDTO.java @@ -31,6 +31,7 @@ public class OrderUpdateStatusDTO { * 支付状态 */ private Integer payStatus; + /** * 退款状态 */ @@ -56,6 +57,16 @@ public class OrderUpdateStatusDTO { */ private String transactionId; + /** + * 支付服务退款单号 + */ + private Long refundNo; + + /** + * 第三方支付的退款单号 + */ + private String refundId; + /** * 支付渠道 */ @@ -70,4 +81,4 @@ public class OrderUpdateStatusDTO { * 评价状态 */ private Integer evaluationStatus; -} +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java index fa38736..3077b6d 100644 --- a/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-base/src/main/java/com/jzo2o/orders/base/service/impl/OrdersCommonServiceImpl.java @@ -31,6 +31,8 @@ public class OrdersCommonServiceImpl extends ServiceImpl i .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTransactionId()), Orders::getTransactionId, orderUpdateStatusReqDTO.getTransactionId()) .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingChannel()), Orders::getTradingChannel, orderUpdateStatusReqDTO.getTradingChannel()) .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getRefundStatus()), Orders::getRefundStatus, orderUpdateStatusReqDTO.getRefundStatus()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getRefundNo()), Orders::getRefundNo, orderUpdateStatusReqDTO.getRefundNo()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getRefundId()), Orders::getRefundId, orderUpdateStatusReqDTO.getRefundId()) .update(); } } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java index e05dc99..af8ae55 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/controller/consumer/ConsumerOrdersController.java @@ -12,6 +12,7 @@ import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO; import com.jzo2o.orders.manager.model.dto.request.PlaceOrderReqDTO; import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO; import com.jzo2o.orders.manager.model.dto.response.PlaceOrderResDTO; +import com.jzo2o.orders.manager.service.IOrdersCanceledService; import com.jzo2o.orders.manager.service.IOrdersCreateService; import com.jzo2o.orders.manager.service.IOrdersManagerService; import io.swagger.annotations.Api; @@ -30,11 +31,12 @@ import java.util.List; @Api(tags = "用户端 - 订单相关接口") @RequestMapping("/consumer/orders") public class ConsumerOrdersController { - @Resource - private IOrdersManagerService ordersManagerService; - @Resource private IOrdersCreateService ordersCreateService; + @Resource + private IOrdersManagerService ordersManagerService; + @Resource + private IOrdersCanceledService ordersCanceledService; @GetMapping("/{id}") @ApiOperation("根据订单id查询") @@ -94,7 +96,7 @@ public class ConsumerOrdersController { throw new RequestUnauthorizedException("无法获取当前用户信息"); } - ordersManagerService.cancel(OrderCancelDTO.builder() + ordersCanceledService.cancel(OrderCancelDTO.builder() .id(orderCancelReqDTO.getId()) .cancelReason(orderCancelReqDTO.getCancelReason()) .currentUserId(currentUser.getId()) diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/job/OrderCancelJob.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/job/OrderCancelJob.java index faaa839..ce905c1 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/job/OrderCancelJob.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/job/OrderCancelJob.java @@ -2,9 +2,12 @@ package com.jzo2o.orders.manager.job; import com.jzo2o.common.utils.CollUtils; import com.jzo2o.orders.base.model.domain.Orders; +import com.jzo2o.orders.base.model.domain.OrdersRefund; +import com.jzo2o.orders.manager.service.IOrdersCanceledService; import com.jzo2o.orders.manager.service.IOrdersManagerService; -import com.xxl.job.core.context.XxlJobHelper; +import com.jzo2o.orders.manager.service.IOrdersRefundService; import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.transaction.support.TransactionTemplate; @@ -15,24 +18,40 @@ import java.util.List; * 自动轮询取消订单 * @author JIAN */ +@Slf4j @Component @SuppressWarnings("unused") public class OrderCancelJob { @Resource private IOrdersManagerService ordersManagerService; @Resource + private IOrdersRefundService ordersRefundService; + @Resource + private IOrdersCanceledService ordersCanceledService; + @Resource private TransactionTemplate transactionTemplate; @XxlJob("cancelPayOverTimeOrder") public void cancelPayOverTimeOrder() { List orderList = ordersManagerService.getPayOverTimeOrder(100); if (CollUtils.isEmpty(orderList)) { - XxlJobHelper.log("没有超时订单"); + log.info("没有超时订单"); return; } // 取消所有超时未支付订单 transactionTemplate.executeWithoutResult(status -> - orderList.forEach(order -> ordersManagerService.cancelPayOverTimeOrder(order.getId()))); + orderList.forEach(order -> ordersCanceledService.cancelPayOverTimeOrder(order.getId()))); + } + + @XxlJob("handlerRefundOrder") + public void handlerRefundOrder() { + List refundRecords = ordersRefundService.queryRefundOrderListByCount(100); + if (CollUtils.isEmpty(refundRecords)) { + log.info("没有正在退款的订单"); + } + + transactionTemplate.executeWithoutResult(status -> + refundRecords.forEach(ordersRefundService::refundOrderByRefundRecord)); } } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCanceledService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCanceledService.java index 45c90c3..b198b72 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCanceledService.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersCanceledService.java @@ -2,6 +2,7 @@ package com.jzo2o.orders.manager.service; import com.baomidou.mybatisplus.extension.service.IService; import com.jzo2o.orders.base.model.domain.OrdersCanceled; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; /** *

@@ -12,5 +13,14 @@ import com.jzo2o.orders.base.model.domain.OrdersCanceled; * @since 2023-08-19 */ public interface IOrdersCanceledService extends IService { + /** + * 取消订单 + */ + void cancel(OrderCancelDTO orderCancelDTO); -} + /** + * 系统取消超时订单(无前置判断) + *
仅内部使用!!! + */ + void cancelPayOverTimeOrder(Long id); +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java index ff70fd8..c786e06 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersManagerService.java @@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.jzo2o.api.orders.dto.response.OrderResDTO; import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; import com.jzo2o.orders.base.model.domain.Orders; -import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; import java.util.List; @@ -43,17 +42,6 @@ public interface IOrdersManagerService extends IService { */ void evaluationOrder(Long ordersId); - /** - * 取消订单 - */ - void cancel(OrderCancelDTO orderCancelDTO); - - /** - * 系统取消超时订单(无前置判断) - *
仅内部使用!!! - */ - void cancelPayOverTimeOrder(Long id); - /** * 获取支付超时订单 * @param count 订单数量 diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersRefundService.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersRefundService.java index 6707a4b..35bd880 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersRefundService.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/IOrdersRefundService.java @@ -2,6 +2,7 @@ package com.jzo2o.orders.manager.service; import com.baomidou.mybatisplus.extension.service.IService; import com.jzo2o.orders.base.model.domain.OrdersRefund; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; import java.util.List; @@ -21,4 +22,16 @@ public interface IOrdersRefundService extends IService { * @param count 数量 */ List queryRefundOrderListByCount(Integer count); -} + + /** + * 保存退款记录信息 + *
仅供内部使用!!! + */ + boolean saveRefundInfo(OrderCancelDTO orderRefundInfo); + + /** + * 通过订单退款信息退款(内部无校验) + *
仅供内部使用!!! + */ + void refundOrderByRefundRecord(OrdersRefund refundRecord); +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCanceledServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCanceledServiceImpl.java index bbdf8e3..659abf0 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCanceledServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersCanceledServiceImpl.java @@ -1,20 +1,150 @@ package com.jzo2o.orders.manager.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.jzo2o.api.trade.TradingApi; +import com.jzo2o.api.trade.dto.response.TradingResDTO; +import com.jzo2o.api.trade.enums.TradingStateEnum; +import com.jzo2o.common.constants.UserType; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.expcetions.ForbiddenOperationException; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.orders.base.enums.OrderRefundStatusEnum; +import com.jzo2o.orders.base.enums.OrderStatusEnum; import com.jzo2o.orders.base.mapper.OrdersCanceledMapper; +import com.jzo2o.orders.base.model.domain.Orders; import com.jzo2o.orders.base.model.domain.OrdersCanceled; +import com.jzo2o.orders.base.model.domain.OrdersRefund; +import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; +import com.jzo2o.orders.base.service.IOrdersCommonService; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; import com.jzo2o.orders.manager.service.IOrdersCanceledService; +import com.jzo2o.orders.manager.service.IOrdersManagerService; +import com.jzo2o.orders.manager.service.IOrdersRefundService; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; /** *

- * 订单取消服务实现类 + * 订单取消服务实现类 *

- * * @author itcast * @since 2023-08-19 */ @Service public class OrdersCanceledServiceImpl extends ServiceImpl implements IOrdersCanceledService { + @Resource + private IOrdersCommonService ordersCommonService; + @Resource + private IOrdersManagerService ordersManagerService; + @Resource + private IOrdersRefundService ordersRefundService; + @Resource + private TransactionTemplate transactionTemplate; + @Resource + private TradingApi tradingApi; -} + @Override + public void cancel(OrderCancelDTO orderCancelDTO) { + Long orderId = orderCancelDTO.getId(); + Orders orders = ordersManagerService.getById(orderId); + if (ObjectUtils.isEmpty(orders)) { + throw new ForbiddenOperationException("订单不存在无法取消"); + } + // 补充前端无法确定的字段 + orderCancelDTO.setServeStartTime(orders.getServeStartTime()); + orderCancelDTO.setRealPayAmount(/*orders.getRealPayAmount() 测试统一使用0.01元*/ new BigDecimal("0.01")); + orderCancelDTO.setCityCode(orders.getCityCode()); + orderCancelDTO.setTradingOrderNo(orders.getTradingOrderNo()); + + Integer ordersStatus = orders.getOrdersStatus(); + if (OrderStatusEnum.NO_PAY.getStatus().equals(ordersStatus)) { + // 1. 未支付订单 -> 取消状态 + cancelNoPayOrder(orderCancelDTO); + } else if (OrderStatusEnum.DISPATCHING.getStatus().equals(ordersStatus)) { + // 2. 已支付订单 -> 关闭状态 + 退款 + cancelDispatchingOrder(orderCancelDTO); + } else { + throw new ForbiddenOperationException("订单无法取消"); + } + } + + @Override + public void cancelPayOverTimeOrder(Long id) { + // 二次确认防止在此期间支付 + TradingResDTO tradingResDTO = tradingApi.findTradResultByTradingOrderNo(id); + if (ObjectUtils.isEmpty(tradingResDTO) || tradingResDTO.getTradingState() != TradingStateEnum.YJS) { + cancelNoPayOrder(OrderCancelDTO.builder() + .id(id) + .cancelReason("订单超时未支付自动取消") + .currentUserId(-1L) + .currentUserName("SYSTEM") + .currentUserType(UserType.SYSTEM) + .build()); + } + } + + private void cancelNoPayOrder(OrderCancelDTO orderCancelDTO) { + transactionTemplate.executeWithoutResult(status -> { + if (!saveCancelInfo(orderCancelDTO)) { + throw new DBException("订单取消表记录表更新失败"); + } + + if (!ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(orderCancelDTO.getId()) + .originStatus(OrderStatusEnum.NO_PAY.getStatus()) + .targetStatus(OrderStatusEnum.CANCELED.getStatus()) + .build())) { + throw new DBException("订单表订单状态更新失败"); + } + }); + } + + private void cancelDispatchingOrder(OrderCancelDTO orderCancelDTO) { + Long orderId = orderCancelDTO.getId(); + // 更新数据库信息 + // 1. 订单状态信息 2. 取消记录表 2. 退款记录表 + transactionTemplate.executeWithoutResult(status -> { + if (!saveCancelInfo(orderCancelDTO)) { + throw new DBException("订单取消记录表更新失败"); + } + + if (!ordersRefundService.saveRefundInfo(orderCancelDTO)) { + throw new DBException("订单退款记录表更新失败"); + } + + if (!ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(orderId) + .originStatus(OrderStatusEnum.DISPATCHING.getStatus()) + .targetStatus(OrderStatusEnum.CLOSED.getStatus()) + .refundStatus(OrderRefundStatusEnum.REFUNDING.getStatus()) + .build())) { + throw new DBException("订单表订单状态更新失败"); + } + }); + + // 启动新线程执行退款任务 + new Thread(() -> ordersRefundService + .refundOrderByRefundRecord(OrdersRefund.builder() + .id(orderId) + .tradingOrderNo(orderCancelDTO.getTradingOrderNo()) + .realPayAmount(orderCancelDTO.getRealPayAmount()) + .build())) + .start(); + } + + private Boolean saveCancelInfo(OrderCancelDTO orderCancelInfo) { + return SqlHelper.retBool(baseMapper.insert(OrdersCanceled.builder() + .id(orderCancelInfo.getId()) + .cancellerId(orderCancelInfo.getCurrentUserId()) + .cancelerName(orderCancelInfo.getCurrentUserName()) + .cancellerType(orderCancelInfo.getCurrentUserType()) + .cancelReason(orderCancelInfo.getCancelReason()) + .cancelTime(LocalDateTime.now()) + .build())); + } +} \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java index 9b81f40..c3519fe 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersManagerServiceImpl.java @@ -8,27 +8,17 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jzo2o.api.orders.dto.response.OrderResDTO; import com.jzo2o.api.orders.dto.response.OrderSimpleResDTO; -import com.jzo2o.api.trade.TradingApi; -import com.jzo2o.api.trade.dto.response.TradingResDTO; -import com.jzo2o.api.trade.enums.TradingStateEnum; -import com.jzo2o.common.constants.UserType; import com.jzo2o.common.enums.EnableStatusEnum; -import com.jzo2o.common.expcetions.DBException; -import com.jzo2o.common.expcetions.ForbiddenOperationException; import com.jzo2o.common.utils.ObjectUtils; import com.jzo2o.orders.base.enums.OrderStatusEnum; import com.jzo2o.orders.base.mapper.OrdersMapper; import com.jzo2o.orders.base.model.domain.Orders; import com.jzo2o.orders.base.model.domain.OrdersCanceled; -import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; -import com.jzo2o.orders.base.service.IOrdersCommonService; -import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; import com.jzo2o.orders.manager.service.IOrdersCanceledService; import com.jzo2o.orders.manager.service.IOrdersManagerService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Resource; import java.time.LocalDateTime; @@ -46,14 +36,8 @@ import static com.jzo2o.orders.base.constants.FieldConstants.SORT_BY; @Slf4j @Service public class OrdersManagerServiceImpl extends ServiceImpl implements IOrdersManagerService { - @Resource - private IOrdersCommonService ordersCommonService; @Resource private IOrdersCanceledService ordersCanceledService; - @Resource - private TransactionTemplate transactionTemplate; - @Resource - private TradingApi tradingApi; /** * 订单超时时间 @@ -109,7 +93,7 @@ public class OrdersManagerServiceImpl extends ServiceImpl // 订单超过15分钟未支付则自动取消 if (OrderStatusEnum.NO_PAY.getStatus().equals(orders.getOrdersStatus()) && orders.getCreateTime().isBefore(LocalDateTime.now().minusMinutes(PAY_OVERTIME_MINUTE))) { - cancelPayOverTimeOrder(id); + ordersCanceledService.cancelPayOverTimeOrder(id); orderResDTO.setOrdersStatus(OrderStatusEnum.CANCELED.getStatus()); } @@ -144,31 +128,6 @@ public class OrdersManagerServiceImpl extends ServiceImpl // orderStateMachine.changeStatus(orders.getUserId(), orders.getId().toString(), OrderStatusChangeEventEnum.EVALUATE, orderSnapshotDTO); } - @Override - public void cancel(OrderCancelDTO orderCancelDTO) { - Long orderId = orderCancelDTO.getId(); - Orders orders = baseMapper.selectById(orderId); - if (ObjectUtils.isEmpty(orders)) { - throw new ForbiddenOperationException("订单不存在无法取消"); - } - // 补充前端无法确定的字段 - orderCancelDTO.setServeStartTime(orders.getServeStartTime()); - orderCancelDTO.setRealPayAmount(orders.getRealPayAmount()); - orderCancelDTO.setCityCode(orders.getCityCode()); - orderCancelDTO.setTradingOrderNo(orders.getTradingOrderNo()); - - Integer ordersStatus = orders.getOrdersStatus(); - if (OrderStatusEnum.NO_PAY.getStatus().equals(ordersStatus)) { - // 1. 未支付订单 -> 取消状态 - cancelNoPayOrder(orderCancelDTO); - } else if (OrderStatusEnum.DISPATCHING.getStatus().equals(ordersStatus)) { - // 2. 已支付订单 -> 关闭状态 + 退款 - cancelDispatchingOrder(orderCancelDTO); - } else { - throw new ForbiddenOperationException("订单无法取消"); - } - } - @Override public List getPayOverTimeOrder(Integer count) { return lambdaQuery() @@ -177,47 +136,4 @@ public class OrdersManagerServiceImpl extends ServiceImpl .last("LIMIT " + count) .list(); } - - @Override - public void cancelPayOverTimeOrder(Long id) { - // 二次确认防止在此期间支付 - TradingResDTO tradingResDTO = tradingApi.findTradResultByTradingOrderNo(id); - if (ObjectUtils.isEmpty(tradingResDTO) || tradingResDTO.getTradingState() != TradingStateEnum.YJS) { - cancelNoPayOrder(OrderCancelDTO.builder() - .id(id) - .cancelReason("订单超时未支付自动取消") - .currentUserId(-1L) - .currentUserName("SYSTEM") - .currentUserType(UserType.SYSTEM) - .build()); - } - } - - private void cancelNoPayOrder(OrderCancelDTO orderCancelDTO) { - Long orderId = orderCancelDTO.getId(); - transactionTemplate.executeWithoutResult(status -> { - if (!ordersCanceledService.save(OrdersCanceled.builder() - .id(orderId) - .cancellerId(orderCancelDTO.getCurrentUserId()) - .cancelerName(orderCancelDTO.getCurrentUserName()) - .cancellerType(orderCancelDTO.getCurrentUserType()) - .cancelReason(orderCancelDTO.getCancelReason()) - .cancelTime(LocalDateTime.now()) - .build())) { - throw new DBException("订单取消表更新失败"); - } - - if (!ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() - .id(orderId) - .originStatus(OrderStatusEnum.NO_PAY.getStatus()) - .targetStatus(OrderStatusEnum.CANCELED.getStatus()) - .build())) { - throw new DBException("订单表订单状态更新失败"); - } - }); - } - - private void cancelDispatchingOrder(OrderCancelDTO orderCancelDTO) { - return; - } } \ No newline at end of file diff --git a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersRefundServiceImpl.java b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersRefundServiceImpl.java index d959208..2f4bb5d 100644 --- a/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersRefundServiceImpl.java +++ b/jzo2o-oreders/jzo2o-orders-manager/src/main/java/com/jzo2o/orders/manager/service/impl/OrdersRefundServiceImpl.java @@ -1,36 +1,94 @@ package com.jzo2o.orders.manager.service.impl; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.jzo2o.api.trade.RefundRecordApi; +import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO; +import com.jzo2o.api.trade.enums.RefundStatusEnum; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.orders.base.enums.OrderStatusEnum; import com.jzo2o.orders.base.mapper.OrdersRefundMapper; import com.jzo2o.orders.base.model.domain.OrdersRefund; +import com.jzo2o.orders.base.model.dto.OrderUpdateStatusDTO; +import com.jzo2o.orders.base.service.IOrdersCommonService; +import com.jzo2o.orders.manager.model.dto.OrderCancelDTO; import com.jzo2o.orders.manager.service.IOrdersRefundService; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionTemplate; +import javax.annotation.Resource; import java.util.List; /** *

* 订单退款表 服务实现类 *

- * * @author itcast * @since 2023-09-07 */ @Service public class OrdersRefundServiceImpl extends ServiceImpl implements IOrdersRefundService { + @Resource + private RefundRecordApi refundApi; + @Resource + private IOrdersCommonService ordersCommonService; + @Resource + private TransactionTemplate transactionTemplate; /** * 查询指定数量的退款订单 - * * @param count 数量 */ @Override + @SuppressWarnings("unchecked") public List queryRefundOrderListByCount(Integer count) { - LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + return lambdaQuery() .orderByAsc(OrdersRefund::getCreateTime) - .last("limit " + count); - return baseMapper.selectList(queryWrapper); + .last("limit " + count) + .list(); } -} + + @Override + public boolean saveRefundInfo(OrderCancelDTO orderRefundInfo) { + return SqlHelper.retBool(baseMapper.insert(OrdersRefund.builder() + .id(orderRefundInfo.getId()) + .tradingOrderNo(orderRefundInfo.getTradingOrderNo()) + .realPayAmount(orderRefundInfo.getRealPayAmount()) + .build())); + } + + @Override + public void refundOrderByRefundRecord(OrdersRefund refundRecord) { + ExecutionResultResDTO executionResultResDTO; + try { + executionResultResDTO = refundApi.refundTrading(refundRecord.getTradingOrderNo(), refundRecord.getRealPayAmount()); + } catch (Exception e) { + log.error("执行退款接口出错, 出错信息如下", e); + return; + } + + Integer refundStatus = executionResultResDTO.getRefundStatus(); + if (ObjectUtils.isNotEmpty(executionResultResDTO) && + (RefundStatusEnum.SUCCESS.getCode().equals(refundStatus) + || RefundStatusEnum.FAIL.getCode().equals(refundStatus))) { + // 退款成功/失败 1. 删除退款记录 2. 更新订单状态 + Long orderId = refundRecord.getId(); + transactionTemplate.executeWithoutResult(status -> { + if (!SqlHelper.retBool(baseMapper.deleteById(orderId))) { + throw new DBException("删除退款记录失败"); + } + + if (!ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(orderId) + .targetStatus(OrderStatusEnum.CLOSED.getStatus()) + .refundStatus(refundStatus) + .refundNo(executionResultResDTO.getRefundNo()) + .refundId(executionResultResDTO.getRefundId()) + .build())) { + throw new DBException("更新订单状态失败"); + } + }); + } + } +} \ No newline at end of file From c1dce10d9e810604a959826dba530045b0a89766 Mon Sep 17 00:00:00 2001 From: JIAN Date: Fri, 13 Sep 2024 20:14:03 +0800 Subject: [PATCH 13/21] =?UTF-8?q?refactor(health):=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E4=BD=93=E6=A3=80=E6=A8=A1=E5=9D=97=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jzo2o-health/Dockerfile | 9 + jzo2o-health/pom.xml | 103 +++++++++ .../com/jzo2o/health/HealthApplication.java | 18 ++ .../jzo2o/health/annotation/IgnoreToken.java | 19 ++ .../jzo2o/health/config/JwtConfiguration.java | 23 +++ .../jzo2o/health/config/SecurityConfig.java | 19 ++ .../health/config/WebMvcConfiguration.java | 30 +++ .../jzo2o/health/constant/RedisConstants.java | 14 ++ .../jzo2o/health/constant/TradeConstants.java | 20 ++ .../admin/OrdersQueryController.java | 39 ++++ .../admin/OrdersStatsController.java | 23 +++ .../ReservationBatchSettingController.java | 28 +++ .../admin/ReservationSettingController.java | 35 ++++ .../controller/admin/SetmealController.java | 36 ++++ .../controller/open/LoginController.java | 40 ++++ .../controller/user/OrdersController.java | 47 +++++ .../user/OrdersQueryController.java | 41 ++++ .../user/OrdersRefundController.java | 28 +++ .../user/ReservationSettingController.java | 32 +++ .../controller/user/SetmealController.java | 39 ++++ .../health/enums/OrderPayStatusEnum.java | 21 ++ .../jzo2o/health/enums/OrderStatusEnum.java | 35 ++++ .../jzo2o/health/handler/OrdersHandler.java | 58 ++++++ .../interceptor/JwtTokenInterceptor.java | 83 ++++++++ .../health/listener/TradeStatusListener.java | 37 ++++ .../mapper/CheckgroupCheckitemMapper.java | 16 ++ .../jzo2o/health/mapper/CheckgroupMapper.java | 16 ++ .../jzo2o/health/mapper/CheckitemMapper.java | 16 ++ .../com/jzo2o/health/mapper/MemberMapper.java | 16 ++ .../health/mapper/OrdersCancelledMapper.java | 16 ++ .../com/jzo2o/health/mapper/OrdersMapper.java | 23 +++ .../health/mapper/OrdersRefundMapper.java | 16 ++ .../mapper/ReservationSettingMapper.java | 19 ++ .../mapper/SetmealCheckgroupMapper.java | 16 ++ .../jzo2o/health/mapper/SetmealMapper.java | 24 +++ .../com/jzo2o/health/mapper/UserMapper.java | 16 ++ .../jzo2o/health/model/UserThreadLocal.java | 37 ++++ .../jzo2o/health/model/domain/Checkgroup.java | 61 ++++++ .../model/domain/CheckgroupCheckitem.java | 37 ++++ .../jzo2o/health/model/domain/Checkitem.java | 72 +++++++ .../com/jzo2o/health/model/domain/Member.java | 65 ++++++ .../com/jzo2o/health/model/domain/Orders.java | 165 +++++++++++++++ .../health/model/domain/OrdersCancelled.java | 70 +++++++ .../health/model/domain/OrdersRefund.java | 51 +++++ .../model/domain/ReservationSetting.java | 50 +++++ .../jzo2o/health/model/domain/Setmeal.java | 76 +++++++ .../model/domain/SetmealCheckgroup.java | 37 ++++ .../com/jzo2o/health/model/domain/User.java | 90 ++++++++ .../jzo2o/health/model/dto/OrderCountDTO.java | 17 ++ .../dto/request/CommonPageQueryReqDTO.java | 19 ++ .../health/model/dto/request/LoginReqDTO.java | 21 ++ .../model/dto/request/MemberLoginReqDTO.java | 27 +++ .../model/dto/request/OrdersCancelReqDTO.java | 22 ++ .../dto/request/OrdersPageQueryReqDTO.java | 34 +++ .../model/dto/request/OrdersPayReqDTO.java | 22 ++ .../model/dto/request/PlaceOrderReqDTO.java | 33 +++ .../ReservationSettingUpsertReqDTO.java | 35 ++++ .../dto/response/AdminOrdersDetailResDTO.java | 195 ++++++++++++++++++ .../dto/response/CheckGroupDetailResDTO.java | 33 +++ .../model/dto/response/CheckItemResDTO.java | 21 ++ .../model/dto/response/LoginResDTO.java | 17 ++ .../model/dto/response/OrdersCountResDTO.java | 56 +++++ .../dto/response/OrdersDetailResDTO.java | 195 ++++++++++++++++++ .../model/dto/response/OrdersPayResDTO.java | 33 +++ .../model/dto/response/OrdersResDTO.java | 126 +++++++++++ .../model/dto/response/PlaceOrderResDTO.java | 19 ++ .../dto/response/ReservationDateResDTO.java | 27 +++ .../response/ReservationSettingResDTO.java | 37 ++++ .../dto/response/SetmealDetailResDTO.java | 87 ++++++++ .../model/excel/ReservationImportData.java | 25 +++ .../properties/ApplicationProperties.java | 46 +++++ .../properties/OrdersJobProperties.java | 23 +++ .../health/properties/TradeProperties.java | 24 +++ .../service/ICheckgroupCheckitemService.java | 47 +++++ .../health/service/ICheckgroupService.java | 15 ++ .../health/service/ICheckitemService.java | 15 ++ .../jzo2o/health/service/ILoginService.java | 27 +++ .../jzo2o/health/service/IMemberService.java | 30 +++ .../service/IReservationSettingService.java | 13 ++ .../service/ISetmealCheckgroupService.java | 22 ++ .../jzo2o/health/service/ISetmealService.java | 35 ++++ .../jzo2o/health/service/IUserService.java | 22 ++ .../impl/CheckgroupCheckitemServiceImpl.java | 81 ++++++++ .../service/impl/CheckgroupServiceImpl.java | 19 ++ .../service/impl/CheckitemServiceImpl.java | 19 ++ .../health/service/impl/LoginServiceImpl.java | 90 ++++++++ .../service/impl/MemberServiceImpl.java | 54 +++++ .../impl/ReservationSettingServiceImpl.java | 15 ++ .../impl/SetmealCheckgroupServiceImpl.java | 33 +++ .../service/impl/SetmealServiceImpl.java | 84 ++++++++ .../health/service/impl/UserServiceImpl.java | 33 +++ .../src/main/resources/bootstrap-dev.yml | 18 ++ .../src/main/resources/bootstrap-prod.yml | 14 ++ .../src/main/resources/bootstrap-test.yml | 14 ++ jzo2o-health/src/main/resources/bootstrap.yml | 73 +++++++ .../mapper/CheckgroupCheckitemMapper.xml | 5 + .../resources/mapper/CheckgroupMapper.xml | 5 + .../main/resources/mapper/CheckitemMapper.xml | 5 + .../main/resources/mapper/MemberMapper.xml | 5 + .../mapper/OrdersCancelledMapper.xml | 5 + .../main/resources/mapper/OrdersMapper.xml | 5 + .../resources/mapper/OrdersRefundMapper.xml | 5 + .../mapper/ReservationSettingMapper.xml | 5 + .../mapper/SetmealCheckgroupMapper.xml | 5 + .../main/resources/mapper/SetmealMapper.xml | 64 ++++++ .../src/main/resources/mapper/UserMapper.xml | 5 + 106 files changed, 3963 insertions(+) create mode 100644 jzo2o-health/Dockerfile create mode 100644 jzo2o-health/pom.xml create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/HealthApplication.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/annotation/IgnoreToken.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/config/JwtConfiguration.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/config/SecurityConfig.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/config/WebMvcConfiguration.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/constant/RedisConstants.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/constant/TradeConstants.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersQueryController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersStatsController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationBatchSettingController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationSettingController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/SetmealController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/open/LoginController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersRefundController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/user/ReservationSettingController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/controller/user/SetmealController.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderPayStatusEnum.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderStatusEnum.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/handler/OrdersHandler.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/interceptor/JwtTokenInterceptor.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/listener/TradeStatusListener.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckgroupCheckitemMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckgroupMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckitemMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/MemberMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersCancelledMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersRefundMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/SetmealCheckgroupMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/SetmealMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/mapper/UserMapper.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/UserThreadLocal.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Checkgroup.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/CheckgroupCheckitem.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Checkitem.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Member.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Orders.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersCancelled.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersRefund.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/ReservationSetting.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Setmeal.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/SetmealCheckgroup.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/domain/User.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/OrderCountDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/CommonPageQueryReqDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/LoginReqDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/MemberLoginReqDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersCancelReqDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersPageQueryReqDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersPayReqDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/PlaceOrderReqDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/ReservationSettingUpsertReqDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/AdminOrdersDetailResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/CheckGroupDetailResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/CheckItemResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/LoginResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersCountResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersDetailResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersPayResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/PlaceOrderResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/ReservationDateResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/ReservationSettingResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/SetmealDetailResDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/excel/ReservationImportData.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/properties/ApplicationProperties.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/properties/OrdersJobProperties.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/properties/TradeProperties.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckgroupCheckitemService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckgroupService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckitemService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/ILoginService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/IMemberService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/ISetmealCheckgroupService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/ISetmealService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/IUserService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckgroupCheckitemServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckgroupServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckitemServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/LoginServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/MemberServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/SetmealCheckgroupServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/SetmealServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/UserServiceImpl.java create mode 100644 jzo2o-health/src/main/resources/bootstrap-dev.yml create mode 100644 jzo2o-health/src/main/resources/bootstrap-prod.yml create mode 100644 jzo2o-health/src/main/resources/bootstrap-test.yml create mode 100644 jzo2o-health/src/main/resources/bootstrap.yml create mode 100644 jzo2o-health/src/main/resources/mapper/CheckgroupCheckitemMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/CheckgroupMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/CheckitemMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/MemberMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/OrdersCancelledMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/OrdersMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/OrdersRefundMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/ReservationSettingMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/SetmealCheckgroupMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/SetmealMapper.xml create mode 100644 jzo2o-health/src/main/resources/mapper/UserMapper.xml diff --git a/jzo2o-health/Dockerfile b/jzo2o-health/Dockerfile new file mode 100644 index 0000000..7b6ba0b --- /dev/null +++ b/jzo2o-health/Dockerfile @@ -0,0 +1,9 @@ +FROM openjdk:11-jdk +LABEL maintainer="研究院研发组 " +RUN echo "Asia/Shanghai" > /etc/timezone +ARG PACKAGE_PATH=./target/jzo2o-health.jar + +ADD ${PACKAGE_PATH:-./} app.jar +EXPOSE 8080 +EXPOSE 9999 +ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS app.jar"] \ No newline at end of file diff --git a/jzo2o-health/pom.xml b/jzo2o-health/pom.xml new file mode 100644 index 0000000..a941d30 --- /dev/null +++ b/jzo2o-health/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + + com.jzo2o + jzo2o-health + 1.0-SNAPSHOT + health + health + + + jzo2o-parent + com.jzo2o + 1.0-SNAPSHOT + + + + 11 + 11 + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + org.springframework.cloud + spring-cloud-starter-bootstrap + + + com.jzo2o + jzo2o-mvc + + + + com.jzo2o + jzo2o-knife4j-web + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.jzo2o + jzo2o-api + + + com.jzo2o + jzo2o-thirdparty + + + com.jzo2o + jzo2o-mysql + + + com.jzo2o + jzo2o-redis + + + com.jzo2o + jzo2o-xxl-job + + + com.jzo2o + jzo2o-rabbitmq + + + com.alibaba + easyexcel + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + build-info + + + + + com.jzo2o.health.HealthApplication + + + + + + diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/HealthApplication.java b/jzo2o-health/src/main/java/com/jzo2o/health/HealthApplication.java new file mode 100644 index 0000000..e233111 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/HealthApplication.java @@ -0,0 +1,18 @@ +package com.jzo2o.health; + +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@Slf4j +@MapperScan("com.jzo2o.health.mapper") +@SpringBootApplication +public class HealthApplication { + + public static void main(String[] args) { + SpringApplication.run(HealthApplication.class, args); + log.info("家政服务-健康服务启动"); + } + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/annotation/IgnoreToken.java b/jzo2o-health/src/main/java/com/jzo2o/health/annotation/IgnoreToken.java new file mode 100644 index 0000000..24a099c --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/annotation/IgnoreToken.java @@ -0,0 +1,19 @@ +package com.jzo2o.health.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 忽略token校验的注解 + * 虽然在注册JwtTokenInterceptor时可以指定忽略的请求路径,但是无法指定请求方式。 + * 对于同一个请求url,请求方式可以有多种,无法做到区别对待 + * 例如:请求url为/dish,其中POST方式对应的方法需要进行token校验,GET方式对应的方法不需要进行token校验 + * 此时就需要通过IgnoreToken注解来标识当前方法不需要校验 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface IgnoreToken { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/config/JwtConfiguration.java b/jzo2o-health/src/main/java/com/jzo2o/health/config/JwtConfiguration.java new file mode 100644 index 0000000..63ff7b0 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/config/JwtConfiguration.java @@ -0,0 +1,23 @@ +package com.jzo2o.health.config; + +import com.jzo2o.common.utils.JwtTool; +import com.jzo2o.health.properties.ApplicationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.Resource; + +/** + * @author itcast + */ +@Configuration +public class JwtConfiguration { + + @Resource + private ApplicationProperties applicationProperties; + + @Bean + public JwtTool jwtTool() { + return new JwtTool(applicationProperties.getJwtKey()); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/config/SecurityConfig.java b/jzo2o-health/src/main/java/com/jzo2o/health/config/SecurityConfig.java new file mode 100644 index 0000000..796dcaa --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/config/SecurityConfig.java @@ -0,0 +1,19 @@ +package com.jzo2o.health.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * @author itcast + */ +@Configuration +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/config/WebMvcConfiguration.java b/jzo2o-health/src/main/java/com/jzo2o/health/config/WebMvcConfiguration.java new file mode 100644 index 0000000..e4d69c4 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/config/WebMvcConfiguration.java @@ -0,0 +1,30 @@ +package com.jzo2o.health.config; + +import com.jzo2o.health.interceptor.JwtTokenInterceptor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import javax.annotation.Resource; + + +@Slf4j +@Configuration +public class WebMvcConfiguration implements WebMvcConfigurer { + + @Resource + private JwtTokenInterceptor jwtTokenInterceptor; + + /** + * 注册拦截器 + * + * @param registry + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtTokenInterceptor) + .addPathPatterns("/admin/**", "/user/**")//指定拦截的路径 + .excludePathPatterns("/open/**");//添加不拦截路径 + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/constant/RedisConstants.java b/jzo2o-health/src/main/java/com/jzo2o/health/constant/RedisConstants.java new file mode 100644 index 0000000..ab0d4fb --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/constant/RedisConstants.java @@ -0,0 +1,14 @@ +package com.jzo2o.health.constant; + +/** + * 支付相关常量 + * + * @author itcast + * @create 2023/11/7 17:46 + **/ +public class RedisConstants { + /** + * 用户端订单滚动分页查询 + */ + public static final String ORDER_PAGE_QUERY = "ORDERS:PAGE_QUERY:PAGE_%s"; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/constant/TradeConstants.java b/jzo2o-health/src/main/java/com/jzo2o/health/constant/TradeConstants.java new file mode 100644 index 0000000..c55c3f3 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/constant/TradeConstants.java @@ -0,0 +1,20 @@ +package com.jzo2o.health.constant; + +/** + * 支付相关常量 + * + * @author itcast + * @create 2023/11/7 17:46 + **/ +public class TradeConstants { + /** + * 支付来源 + */ + public static final String PRODUCT_APP_ID="health"; + + /** + * rabbitmq支付更新状态队列 + */ + public static final String MQ_TRADE_QUEUE="jzo2o.queue.health.trade.update.Status"; + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersQueryController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersQueryController.java new file mode 100644 index 0000000..f9d7ef0 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersQueryController.java @@ -0,0 +1,39 @@ +package com.jzo2o.health.controller.admin; + +import com.jzo2o.common.model.PageResult; +import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; +import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; +import com.jzo2o.health.model.dto.response.OrdersResDTO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author itcast + */ +@RestController("adminOrdersQueryController") +@RequestMapping("/admin/orders") +@Api(tags = "管理端 - 订单查询接口") +public class OrdersQueryController { + + @ApiOperation("分页查询") + @GetMapping("/page") + public PageResult pageQuery(OrdersPageQueryReqDTO ordersPageQueryReqDTO) { + return null; + } + + @GetMapping("/{id}") + @ApiOperation("根据订单id查询") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) + }) + public AdminOrdersDetailResDTO aggregation(@PathVariable("id") Long id) { + return null; + } + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersStatsController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersStatsController.java new file mode 100644 index 0000000..0e98bb9 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersStatsController.java @@ -0,0 +1,23 @@ +package com.jzo2o.health.controller.admin; + +import com.jzo2o.health.model.dto.response.OrdersCountResDTO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author itcast + */ +@RestController("adminOrdersStatsController") +@RequestMapping("/admin/orders") +@Api(tags = "管理端 - 根据状态统计订单数量") +public class OrdersStatsController { + + @GetMapping("/countByStatus") + @ApiOperation("根据状态统计数量") + public OrdersCountResDTO countByStatus() { + return null; + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationBatchSettingController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationBatchSettingController.java new file mode 100644 index 0000000..b061528 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationBatchSettingController.java @@ -0,0 +1,28 @@ +package com.jzo2o.health.controller.admin; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 预约设置操作 + * + * @author itcast + */ +@Slf4j +@RestController("adminReservationBatchSettingController") +@RequestMapping("/admin/reservation-setting") +@Api(tags = "管理端 - 批量预约设置相关接口") +public class ReservationBatchSettingController { + + @PostMapping("/upload") + @ApiOperation("上传文件批量预约设置") + public void upload(@RequestPart("file") MultipartFile file) { + + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationSettingController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationSettingController.java new file mode 100644 index 0000000..4d22c52 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationSettingController.java @@ -0,0 +1,35 @@ +package com.jzo2o.health.controller.admin; + +import com.jzo2o.health.model.dto.request.ReservationSettingUpsertReqDTO; +import com.jzo2o.health.model.dto.response.ReservationSettingResDTO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 预约设置操作 + * + * @author itcast + */ +@Slf4j +@RestController("adminReservationSettingController") +@RequestMapping("/admin/reservation-setting") +@Api(tags = "管理端 - 预约设置相关接口") +public class ReservationSettingController { + + @GetMapping("/getReservationSettingByMonth") + @ApiOperation("按月查询预约设置") + @ApiImplicitParam(name = "date", value = "月份,格式:yyyy-MM", required = true, dataTypeClass = String.class) + public List getReservationSettingByMonth(@RequestParam("date") String date) { + return null; + } + + @PutMapping("/editNumberByDate") + @ApiOperation("编辑预约设置") + public void editNumberByDate(@RequestBody ReservationSettingUpsertReqDTO reservationSettingUpsertReqDTO) { + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/SetmealController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/SetmealController.java new file mode 100644 index 0000000..62c37ab --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/SetmealController.java @@ -0,0 +1,36 @@ +package com.jzo2o.health.controller.admin; + +import com.jzo2o.common.model.PageResult; +import com.jzo2o.health.model.domain.Setmeal; +import com.jzo2o.health.model.dto.request.CommonPageQueryReqDTO; +import com.jzo2o.health.service.ISetmealService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * 体检套餐管理 + */ +@RestController("adminSetmealController") +@RequestMapping("/admin/setmeal") +@Api(tags = "管理端 - 套餐相关接口") +public class SetmealController { + @Resource + private ISetmealService setmealService; + + @PostMapping("/add") + @ApiOperation("新增套餐") + @ApiImplicitParam(name = "checkgroupIds", value = "检查组id列表", required = true, dataTypeClass = Integer.class) + public void add(@RequestBody Setmeal setmeal, @RequestParam("checkgroupIds") Integer[] checkgroupIds) { + setmealService.add(setmeal, checkgroupIds); + } + + @GetMapping("/findPage") + @ApiOperation("分页查询套餐") + public PageResult findPage(CommonPageQueryReqDTO commonPageQueryReqDTO) { + return setmealService.findPage(commonPageQueryReqDTO); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/open/LoginController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/open/LoginController.java new file mode 100644 index 0000000..a865d08 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/open/LoginController.java @@ -0,0 +1,40 @@ +package com.jzo2o.health.controller.open; + +import com.jzo2o.health.model.dto.request.LoginReqDTO; +import com.jzo2o.health.model.dto.request.MemberLoginReqDTO; +import com.jzo2o.health.model.dto.response.LoginResDTO; +import com.jzo2o.health.service.ILoginService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @author itcast + */ +@RestController("openLoginController") +@RequestMapping("/open/login") +@Api(tags = "白名单接口 - 登录相关接口") +public class LoginController { + + @Resource + private ILoginService loginService; + + @PostMapping("/admin") + @ApiOperation("管理员登录") + public LoginResDTO adminLogin(@RequestBody LoginReqDTO loginReqDTO) { + String token = loginService.adminLogin(loginReqDTO); + return new LoginResDTO(token); + } + + @PostMapping("/user") + @ApiOperation("普通用户登录") + public LoginResDTO userLogin(@RequestBody MemberLoginReqDTO memberLoginReqDTO) { + String token = loginService.memberLogin(memberLoginReqDTO); + return new LoginResDTO(token); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersController.java new file mode 100644 index 0000000..0c9a0c3 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersController.java @@ -0,0 +1,47 @@ +package com.jzo2o.health.controller.user; + +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.health.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.health.model.dto.response.OrdersPayResDTO; +import com.jzo2o.health.model.dto.response.PlaceOrderResDTO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +/** + * @author itcast + */ +@RestController("userOrdersController") +@RequestMapping("/user/orders") +@Api(tags = "用户端 - 下单支付相关接口") +public class OrdersController { + + @ApiOperation("下单接口") + @PostMapping("/place") + public PlaceOrderResDTO place(@RequestBody PlaceOrderReqDTO placeOrderReqDTO) { + return null; + } + + @PutMapping("/pay/{id}") + @ApiOperation("订单支付") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class), + @ApiImplicitParam(name = "tradingChannel", value = "支付渠道:ALI_PAY、WECHAT_PAY", required = true, dataTypeClass = PayChannelEnum.class), + }) + public OrdersPayResDTO pay(@PathVariable("id") Long id, @RequestParam("tradingChannel") PayChannelEnum tradingChannel) { + return null; + } + + @GetMapping("/pay/{id}/result") + @ApiOperation("查询订单支付结果") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) + }) + public OrdersPayResDTO payResult(@PathVariable("id") Long id) { + return null; + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java new file mode 100644 index 0000000..f6ef0e5 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java @@ -0,0 +1,41 @@ +package com.jzo2o.health.controller.user; + +import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; +import com.jzo2o.health.model.dto.response.OrdersResDTO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author itcast + */ +@RestController("userOrdersQueryController") +@RequestMapping("/user/orders") +@Api(tags = "用户端 - 订单查询相关接口") +public class OrdersQueryController { + + @ApiOperation("滚动分页查询") + @GetMapping("/page") + @ApiImplicitParams({ + @ApiImplicitParam(name = "ordersStatus", value = "订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消", required = false, dataTypeClass = Integer.class), + @ApiImplicitParam(name = "sortBy", value = "排序字段", required = false, dataTypeClass = Long.class) + }) + public List pageQuery(@RequestParam(value = "ordersStatus", required = false) Integer ordersStatus, + @RequestParam(value = "sortBy", required = false) Long sortBy) { + return null; + } + + @GetMapping("/{id}") + @ApiOperation("根据订单id查询") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) + }) + public OrdersDetailResDTO detail(@PathVariable("id") Long id) { + return null; + } + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersRefundController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersRefundController.java new file mode 100644 index 0000000..a853378 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersRefundController.java @@ -0,0 +1,28 @@ +package com.jzo2o.health.controller.user; + +import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author itcast + */ +@RestController("userOrdersRefundController") +@RequestMapping("/user/orders") +@Api(tags = "用户端 - 取消订单退款相关接口") +public class OrdersRefundController { + + @PutMapping("/cancel") + @ApiOperation("订单取消") + public void cancel(@RequestBody OrdersCancelReqDTO ordersCancelReqDTO) { + } + + @PutMapping("/refund") + @ApiOperation("订单退款") + public void refund(@RequestBody OrdersCancelReqDTO ordersCancelReqDTO) { + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/ReservationSettingController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/ReservationSettingController.java new file mode 100644 index 0000000..726ab64 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/ReservationSettingController.java @@ -0,0 +1,32 @@ +package com.jzo2o.health.controller.user; + +import com.jzo2o.health.annotation.IgnoreToken; +import com.jzo2o.health.model.dto.response.ReservationDateResDTO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +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; + +/** + * 预约设置操作 + * + * @author itcast + */ +@Slf4j +@RestController("userReservationSettingController") +@RequestMapping("/user/reservation-setting") +@Api(tags = "用户端 - 预约设置相关接口") +public class ReservationSettingController { + + @GetMapping("/getReservationDateByMonth") + @IgnoreToken + @ApiOperation("按月查询可预约日期") + @ApiImplicitParam(name = "month", value = "月份,格式:yyyy-MM", required = true, dataTypeClass = String.class) + public ReservationDateResDTO getReservationDateByMonth(@RequestParam("month") String month) { + return null; + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/SetmealController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/SetmealController.java new file mode 100644 index 0000000..424067b --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/SetmealController.java @@ -0,0 +1,39 @@ +package com.jzo2o.health.controller.user; + +import com.jzo2o.health.annotation.IgnoreToken; +import com.jzo2o.health.model.domain.Setmeal; +import com.jzo2o.health.model.dto.response.SetmealDetailResDTO; +import com.jzo2o.health.service.ISetmealService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +@RestController("userSetmealController") +@RequestMapping("/user/setmeal") +@Api(tags = "用户端 - 套餐相关接口") +public class SetmealController { + @Resource + private ISetmealService setmealService; + + @GetMapping("/getSetmeal") + @IgnoreToken + @ApiOperation("获取所有套餐信息") + public List getSetmeal() { + return setmealService.findAll(); + } + + @GetMapping("/findDetail/{id}") + @IgnoreToken + @ApiOperation("根据id查询套餐信息") + @ApiImplicitParam(name = "id", value = "套餐id", required = true, dataTypeClass = Integer.class) + public SetmealDetailResDTO findById(@PathVariable("id") Integer id) { + return setmealService.findDetail(id); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderPayStatusEnum.java b/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderPayStatusEnum.java new file mode 100644 index 0000000..55b4a1a --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderPayStatusEnum.java @@ -0,0 +1,21 @@ +package com.jzo2o.health.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author itcast + */ + +@Getter +@AllArgsConstructor +public enum OrderPayStatusEnum { + NO_PAY(0, "未支付"), + PAY_SUCCESS(1, "已支付"), + REFUNDING(2, "退款中"), + REFUND_SUCCESS(3, "退款成功"), + REFUND_FAIL(4, "退款失败"); + + private final Integer status; + private final String desc; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderStatusEnum.java b/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderStatusEnum.java new file mode 100644 index 0000000..f44ac6e --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderStatusEnum.java @@ -0,0 +1,35 @@ +package com.jzo2o.health.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author itcast + */ +@Getter +@AllArgsConstructor +public enum OrderStatusEnum { + NO_PAY(0, "待支付"), + WAITING_CHECKUP(100, "待体检"), + COMPLETED_CHECKUP(200, "已体检"), + CLOSED(300, "已关闭"), + CANCELLED(400, "已取消"); + + private final Integer status; + private final String desc; + + /** + * 根据状态值获得对应枚举 + * + * @param status 状态 + * @return 状态对应枚举 + */ + public static OrderStatusEnum codeOf(Integer status) { + for (OrderStatusEnum orderStatusEnum : values()) { + if (orderStatusEnum.status.equals(status)) { + return orderStatusEnum; + } + } + return null; + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/handler/OrdersHandler.java b/jzo2o-health/src/main/java/com/jzo2o/health/handler/OrdersHandler.java new file mode 100644 index 0000000..fdd2366 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/handler/OrdersHandler.java @@ -0,0 +1,58 @@ +package com.jzo2o.health.handler; + +import com.jzo2o.api.trade.RefundRecordApi; +import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO; +import com.jzo2o.health.properties.OrdersJobProperties; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; + +/** + * 订单相关定时任务 + * + * @author itcast + * @create 2023/9/2 16:44 + **/ +@Slf4j +@Component +public class OrdersHandler { + + @Resource + private RefundRecordApi refundRecordApi; + //解决同级方法调用,事务失效问题 + @Resource + private OrdersHandler orderHandler; + @Resource + private OrdersJobProperties ordersJobProperties; + + /** + * 支付超时取消订单 + * 每分钟执行一次 + */ + @XxlJob(value = "cancelOverTimePayOrder") + public void cancelOverTimePayOrder() { + + } + + /** + * 订单退款异步任务 + */ + @XxlJob(value = "handleRefundOrders") + public void handleRefundOrders() { + + } + + /** + * 订单退款处理 + * + * @param id 订单id + * @param executionResultResDTO 第三方退款信息 + */ + @Transactional(rollbackFor = Exception.class) + public void refundOrder(Long id, ExecutionResultResDTO executionResultResDTO) { + + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/interceptor/JwtTokenInterceptor.java b/jzo2o-health/src/main/java/com/jzo2o/health/interceptor/JwtTokenInterceptor.java new file mode 100644 index 0000000..84f5436 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/interceptor/JwtTokenInterceptor.java @@ -0,0 +1,83 @@ +package com.jzo2o.health.interceptor; + +import com.jzo2o.common.expcetions.RequestUnauthorizedException; +import com.jzo2o.common.model.CurrentUserInfo; +import com.jzo2o.common.utils.JwtTool; +import com.jzo2o.common.utils.StringUtils; +import com.jzo2o.health.annotation.IgnoreToken; +import com.jzo2o.health.model.UserThreadLocal; +import com.jzo2o.health.properties.ApplicationProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * token检查拦截器,用于检查后台系统发送的请求 + */ +@Slf4j +@Component +public class JwtTokenInterceptor implements HandlerInterceptor { + + @Resource + private ApplicationProperties applicationProperties; + + /** + * token header名称 + */ + private static final String HEADER_TOKEN = "Authorization"; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + log.info("拦截器拦截到请求:{}", request.getRequestURI()); + + // 如果不是映射到方法的请求则直接放行,例如 /doc.html + if (!(handler instanceof HandlerMethod)) { + log.info("{}无需处理,直接放行", request.getRequestURI()); + return true; + } + + HandlerMethod handlerMethod = (HandlerMethod) handler; + //检查当前请求的Controller方法上是否有IgnoreToken注解 + boolean hasIgnoreToken = handlerMethod.hasMethodAnnotation(IgnoreToken.class); + if (hasIgnoreToken) { + return true; + } + + //获取前端提交的token + String token = request.getHeader(HEADER_TOKEN); + if (StringUtils.isEmpty(token)) { + throw new RequestUnauthorizedException(); + } + log.info("获取到token:{}", token); + + try { + log.info("开始解析token"); + String tokenKey = applicationProperties.getTokenKey().get(JwtTool.getUserType(token) + ""); + if (StringUtils.isEmpty(tokenKey)) { + throw new RequestUnauthorizedException(); + } + + JwtTool jwtTool = new JwtTool(tokenKey); + CurrentUserInfo currentUserInfo = jwtTool.parseToken(token); + UserThreadLocal.set(currentUserInfo); + //token解析成功,放行 + return true; + } catch (Exception ex) { + log.error("token解析失败"); + //401表示未授权,需要前端配合跳转回登录页面 + response.setStatus(401); + return false; + } + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + // 清理用户信息 + UserThreadLocal.clear(); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/listener/TradeStatusListener.java b/jzo2o-health/src/main/java/com/jzo2o/health/listener/TradeStatusListener.java new file mode 100644 index 0000000..b858ec6 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/listener/TradeStatusListener.java @@ -0,0 +1,37 @@ +package com.jzo2o.health.listener; + +import com.jzo2o.common.constants.MqConstants; +import com.jzo2o.health.constant.TradeConstants; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.ExchangeTypes; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +/** + * 监听mq消息,接收支付结果 + * + * @author itcast + **/ +@Slf4j +@Component +public class TradeStatusListener { + + /** + * 更新支付结果 + * 支付成功 + * + * @param msg 消息 + */ + @RabbitListener(bindings = @QueueBinding( + value = @Queue(name = TradeConstants.MQ_TRADE_QUEUE), + exchange = @Exchange(name = MqConstants.Exchanges.TRADE, type = ExchangeTypes.TOPIC), + key = MqConstants.RoutingKeys.TRADE_UPDATE_STATUS + )) + public void listenTradeUpdatePayStatusMsg(String msg) { + log.info("接收到支付结果状态的消息 ({})-> {}", MqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS, msg); + + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckgroupCheckitemMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckgroupCheckitemMapper.java new file mode 100644 index 0000000..e841373 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckgroupCheckitemMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.health.mapper; + +import com.jzo2o.health.model.domain.CheckgroupCheckitem; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface CheckgroupCheckitemMapper extends BaseMapper { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckgroupMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckgroupMapper.java new file mode 100644 index 0000000..8168862 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckgroupMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.health.mapper; + +import com.jzo2o.health.model.domain.Checkgroup; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface CheckgroupMapper extends BaseMapper { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckitemMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckitemMapper.java new file mode 100644 index 0000000..3680122 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/CheckitemMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.health.mapper; + +import com.jzo2o.health.model.domain.Checkitem; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface CheckitemMapper extends BaseMapper { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/MemberMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/MemberMapper.java new file mode 100644 index 0000000..71ca399 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/MemberMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.health.mapper; + +import com.jzo2o.health.model.domain.Member; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 普通用户 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-11-02 + */ +public interface MemberMapper extends BaseMapper { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersCancelledMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersCancelledMapper.java new file mode 100644 index 0000000..512759c --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersCancelledMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.health.mapper; + +import com.jzo2o.health.model.domain.OrdersCancelled; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单取消表 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-11-07 + */ +public interface OrdersCancelledMapper extends BaseMapper { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersMapper.java new file mode 100644 index 0000000..6c08cf2 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersMapper.java @@ -0,0 +1,23 @@ +package com.jzo2o.health.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.model.dto.OrderCountDTO; +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 订单表 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-11-02 + */ +public interface OrdersMapper extends BaseMapper { + + @Select("SELECT order_status AS orderStatus,COUNT(id) AS count FROM orders GROUP BY order_status") + List countByStatus(); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersRefundMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersRefundMapper.java new file mode 100644 index 0000000..a4ec058 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersRefundMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.health.mapper; + +import com.jzo2o.health.model.domain.OrdersRefund; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单退款表 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-11-07 + */ +public interface OrdersRefundMapper extends BaseMapper { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java new file mode 100644 index 0000000..71da200 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java @@ -0,0 +1,19 @@ +package com.jzo2o.health.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jzo2o.health.model.domain.ReservationSetting; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + *

+ * Mapper 接口 + *

+ * + * @author itcast + * @since 2023-11-01 + */ +public interface ReservationSettingMapper extends BaseMapper { + @Update("UPDATE reservation_setting SET reservations = reservations + 1 WHERE id = #{id} AND reservations < number") + Integer updateReservations(@Param("id") Integer id); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/SetmealCheckgroupMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/SetmealCheckgroupMapper.java new file mode 100644 index 0000000..6cfb1a9 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/SetmealCheckgroupMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.health.mapper; + +import com.jzo2o.health.model.domain.SetmealCheckgroup; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface SetmealCheckgroupMapper extends BaseMapper { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/SetmealMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/SetmealMapper.java new file mode 100644 index 0000000..7d75f11 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/SetmealMapper.java @@ -0,0 +1,24 @@ +package com.jzo2o.health.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jzo2o.health.model.domain.Setmeal; +import com.jzo2o.health.model.dto.response.SetmealDetailResDTO; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Mapper 接口 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface SetmealMapper extends BaseMapper { + /** + * 查询套餐详情(包含关联检查组、检查项) + * + * @param id 套餐id + * @return 套餐详情 + */ + SetmealDetailResDTO findDetail(@Param("id") Integer id); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/UserMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/UserMapper.java new file mode 100644 index 0000000..e217c61 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/UserMapper.java @@ -0,0 +1,16 @@ +package com.jzo2o.health.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jzo2o.health.model.domain.User; + +/** + *

+ * 管理员 Mapper 接口 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface UserMapper extends BaseMapper { + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/UserThreadLocal.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/UserThreadLocal.java new file mode 100644 index 0000000..18f361f --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/UserThreadLocal.java @@ -0,0 +1,37 @@ +package com.jzo2o.health.model; + +import com.jzo2o.common.model.CurrentUserInfo; + +public class UserThreadLocal { + + private static final ThreadLocal THREAD_LOCAL_USER = new ThreadLocal<>(); + + /** + * 获取当前用户id + * + * @return 用户id + */ + public static Long currentUserId() { + return THREAD_LOCAL_USER.get().getId(); + } + + public static CurrentUserInfo currentUser() { + return THREAD_LOCAL_USER.get(); + } + + /** + * 设置当前用户id + * + * @param currentUserInfo 当前用户信息 + */ + public static void set(CurrentUserInfo currentUserInfo) { + THREAD_LOCAL_USER.set(currentUserInfo); + } + + /** + * 清理当前线程中的用户信息 + */ + public static void clear() { + THREAD_LOCAL_USER.remove(); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Checkgroup.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Checkgroup.java new file mode 100644 index 0000000..2f628bc --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Checkgroup.java @@ -0,0 +1,61 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("checkgroup") +public class Checkgroup implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 检查组编码 + */ + private String code; + + /** + * 检查组名称 + */ + private String name; + + /** + * 检查组助记码 + */ + private String helpCode; + + /** + * 检查组性别 + */ + private String sex; + + /** + * 检查组说明 + */ + private String remark; + + /** + * 检查组注意事项 + */ + private String attention; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/CheckgroupCheckitem.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/CheckgroupCheckitem.java new file mode 100644 index 0000000..ca579cf --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/CheckgroupCheckitem.java @@ -0,0 +1,37 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("checkgroup_checkitem") +public class CheckgroupCheckitem implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 检查组id + */ + private Integer checkgroupId; + + /** + * 检查项id + */ + private Integer checkitemId; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Checkitem.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Checkitem.java new file mode 100644 index 0000000..e49a126 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Checkitem.java @@ -0,0 +1,72 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("checkitem") +public class Checkitem implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 检查项编码 + */ + private String code; + + /** + * 检查项名称 + */ + private String name; + + /** + * 检查项性别,0:不限,1:男,2:女 + */ + private String sex; + + /** + * 检查项适用年龄 + */ + private String age; + + /** + * 检查项价格 + */ + private Float price; + + /** + * 查检项类型,分为检查和检验两种 + */ + private String type; + + /** + * 检查项注意事项 + */ + private String attention; + + /** + * 检查项说明 + */ + private String remark; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Member.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Member.java new file mode 100644 index 0000000..e3eddc3 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Member.java @@ -0,0 +1,65 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 普通用户 + *

+ * + * @author itcast + * @since 2023-11-02 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("member") +public class Member implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 昵称 + */ + private String nickname; + + /** + * 电话 + */ + private String phone; + + /** + * 头像 + */ + private String avatar; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 是否已删除,0:未删除,1:已删除 + */ + private Integer isDeleted; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Orders.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Orders.java new file mode 100644 index 0000000..ac6e61b --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Orders.java @@ -0,0 +1,165 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 订单表 + *

+ * + * @author itcast + * @since 2023-11-02 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("orders") +public class Orders implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消 + */ + private Integer orderStatus; + + /** + * 支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败 + */ + private Integer payStatus; + + /** + * 套餐id + */ + private Integer setmealId; + + /** + * 套餐名称 + */ + private String setmealName; + + /** + * 套餐价格 + */ + private BigDecimal setmealPrice; + + /** + * 套餐适用性别,0:不限,1:男,2:女 + */ + private Integer setmealSex; + + /** + * 套餐适用年龄 + */ + private String setmealAge; + + /** + * 套餐图片 + */ + private String setmealImg; + + /** + * 套餐说明 + */ + private String setmealRemark; + + /** + * 预约日期,格式:yyyy-MM-dd + */ + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate reservationDate; + + /** + * 体检人姓名 + */ + private String checkupPersonName; + + /** + * 体检人性别,0:不限,1:男,2女 + */ + private Integer checkupPersonSex; + + /** + * 体检人电话 + */ + private String checkupPersonPhone; + + /** + * 体检人身份证号 + */ + private String checkupPersonIdcard; + + /** + * 用户id + */ + private Long memberId; + + /** + * 用户电话 + */ + private String memberPhone; + + /** + * 支付时间 + */ + private LocalDateTime payTime; + + /** + * 支付渠道 + */ + private String tradingChannel; + + /** + * 支付服务交易单号 + */ + private Long tradingOrderNo; + + /** + * 第三方支付的交易号 + */ + private String transactionId; + + /** + * 支付服务退款单号 + */ + private Long refundNo; + + /** + * 第三方支付的退款单号 + */ + private String refundId; + + /** + * 排序字段(取创建时间的时间戳) + */ + private Long sortBy; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersCancelled.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersCancelled.java new file mode 100644 index 0000000..d0a1cdc --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersCancelled.java @@ -0,0 +1,70 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 订单取消表 + *

+ * + * @author itcast + * @since 2023-11-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("orders_cancelled") +public class OrdersCancelled implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 取消人 + */ + private Long cancellerId; + + /** + * 取消人名称 + */ + private String cancellerName; + + /** + * 取消人类型,1:普通用户,4管理员 + */ + private Integer cancellerType; + + /** + * 取消原因 + */ + private String cancelReason; + + /** + * 取消时间 + */ + private LocalDateTime cancelTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersRefund.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersRefund.java new file mode 100644 index 0000000..6c2c4c5 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersRefund.java @@ -0,0 +1,51 @@ +package com.jzo2o.health.model.domain; + +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 订单退款表 + *

+ * + * @author itcast + * @since 2023-11-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("orders_refund") +public class OrdersRefund implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 订单id + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 支付服务交易单号 + */ + private Long tradingOrderNo; + + /** + * 实付金额 + */ + private BigDecimal realPayAmount; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/ReservationSetting.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/ReservationSetting.java new file mode 100644 index 0000000..683211d --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/ReservationSetting.java @@ -0,0 +1,50 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDate; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-11-01 + */ +@Data +@Builder +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("reservation_setting") +public class ReservationSetting implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 预约日期 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate orderDate; + + /** + * 可预约人数 + */ + private Integer number; + + /** + * 已预约人数 + */ + private Integer reservations; +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Setmeal.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Setmeal.java new file mode 100644 index 0000000..c565d5f --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Setmeal.java @@ -0,0 +1,76 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("setmeal") +public class Setmeal implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 套餐名称 + */ + private String name; + + /** + * 套餐编码 + */ + private String code; + + /** + * 套餐助记码 + */ + private String helpCode; + + /** + * 套餐助记码 + */ + private Integer sex; + + /** + * 套餐适用年龄 + */ + private String age; + + /** + * 套餐价格 + */ + private Float price; + + /** + * 套餐说明 + */ + private String remark; + + /** + * 套餐注意事项 + */ + private String attention; + + /** + * 套餐图片 + */ + private String img; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/SetmealCheckgroup.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/SetmealCheckgroup.java new file mode 100644 index 0000000..1ed6a41 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/SetmealCheckgroup.java @@ -0,0 +1,37 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("setmeal_checkgroup") +public class SetmealCheckgroup implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 套餐id + */ + private Integer setmealId; + + /** + * 检查组id + */ + private Integer checkgroupId; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/User.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/User.java new file mode 100644 index 0000000..a99f4c2 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/User.java @@ -0,0 +1,90 @@ +package com.jzo2o.health.model.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.TableId; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 管理员 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("user") +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 用户名 + */ + private String username; + + /** + * 头像 + */ + private String avatar; + + /** + * 管理员姓名 + */ + private String name; + + /** + * 手机号 + */ + private String phone; + + /** + * 密码 + */ + private String password; + + /** + * 账户状态:0-禁用 1-正常 + */ + private Integer status; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建者id + */ + private Long createBy; + + /** + * 更新者id + */ + private Long updateBy; + + /** + * 逻辑删除,默认0 + */ + private Integer isDeleted; + + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/OrderCountDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/OrderCountDTO.java new file mode 100644 index 0000000..eb5c0a3 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/OrderCountDTO.java @@ -0,0 +1,17 @@ +package com.jzo2o.health.model.dto; + +import lombok.Data; + +/** + * 订单数量响应 + * + * @author itcast + * @create 2023/11/9 16:54 + **/ +@Data +public class OrderCountDTO { + + private Integer orderStatus; + + private Integer count; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/CommonPageQueryReqDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/CommonPageQueryReqDTO.java new file mode 100644 index 0000000..d7dc112 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/CommonPageQueryReqDTO.java @@ -0,0 +1,19 @@ +package com.jzo2o.health.model.dto.request; + +import com.jzo2o.common.model.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 检查组分页查询类 + * + * @author itcast + * @create 2023/7/4 12:43 + **/ +@Data +@ApiModel("检查组分页查询类") +public class CommonPageQueryReqDTO extends PageQueryDTO { + @ApiModelProperty("关键词,查询编码或者名称") + private String keyword; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/LoginReqDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/LoginReqDTO.java new file mode 100644 index 0000000..f5270f7 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/LoginReqDTO.java @@ -0,0 +1,21 @@ +package com.jzo2o.health.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("管理员登录模型") +@Data +public class LoginReqDTO { + + /** + * 管理员账号 + */ + @ApiModelProperty("管理员账号") + private String username; + /** + * 登录密码 + */ + @ApiModelProperty("登录密码") + private String password; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/MemberLoginReqDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/MemberLoginReqDTO.java new file mode 100644 index 0000000..883aef9 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/MemberLoginReqDTO.java @@ -0,0 +1,27 @@ +package com.jzo2o.health.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 普通用户登录请求模型 + * + * @author itcast + * @create 2023/11/2 15:48 + **/ +@Data +@ApiModel("普通用户登录模型") +public class MemberLoginReqDTO { + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号", required = true) + private String phone; + + /** + * 验证码 + */ + @ApiModelProperty(value = "验证码", required = true) + private String verifyCode; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersCancelReqDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersCancelReqDTO.java new file mode 100644 index 0000000..3d94040 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersCancelReqDTO.java @@ -0,0 +1,22 @@ +package com.jzo2o.health.model.dto.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 订单取消或退款模型 + * + * @author itcast + * @create 2023/11/10 10:04 + **/ +@Data +@ApiModel("订单取消或退款请求模型") +public class OrdersCancelReqDTO { + + @ApiModelProperty(value = "订单id", required = true) + private Long id; + + @ApiModelProperty(value = "取消或退款原因", required = true) + private String cancelReason; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersPageQueryReqDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersPageQueryReqDTO.java new file mode 100644 index 0000000..2fda168 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersPageQueryReqDTO.java @@ -0,0 +1,34 @@ +package com.jzo2o.health.model.dto.request; + +import com.jzo2o.common.model.dto.PageQueryDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * 订单分页查询请求模型 + * + * @author itcast + * @create 2023/11/3 19:25 + **/ +@Data +@ApiModel("订单分页查询请求模型") +public class OrdersPageQueryReqDTO extends PageQueryDTO { + + @ApiModelProperty(value = "订单id列表", hidden = true) + private List ids; + + /** + * 订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消 + */ + @ApiModelProperty("订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消") + private Integer orderStatus; + + /** + * 用户电话 + */ + @ApiModelProperty("用户电话") + private String memberPhone; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersPayReqDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersPayReqDTO.java new file mode 100644 index 0000000..86f22c2 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/OrdersPayReqDTO.java @@ -0,0 +1,22 @@ +package com.jzo2o.health.model.dto.request; + +import com.jzo2o.api.trade.enums.PayChannelEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 订单支付请求体 + * + * @author itcast + * @create 2023/9/4 10:00 + **/ +@Data +@ApiModel("订单支付请求体") +public class OrdersPayReqDTO { + @ApiModelProperty(value = "支付渠道", required = true) + @NotNull(message = "支付渠道不能为空") + private PayChannelEnum tradingChannel; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/PlaceOrderReqDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/PlaceOrderReqDTO.java new file mode 100644 index 0000000..c755718 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/PlaceOrderReqDTO.java @@ -0,0 +1,33 @@ +package com.jzo2o.health.model.dto.request; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDate; + +@Data +@ApiModel("下单请求信息") +public class PlaceOrderReqDTO { + @ApiModelProperty(value = "套餐id", required = true) + private Integer setmealId; + + @ApiModelProperty(value = "预约日期", required = true) + @JsonFormat(pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate reservationDate; + + @ApiModelProperty(value = "体检人姓名", required = true) + private String checkupPersonName; + + @ApiModelProperty(value = "体检人性别,0:不限,1:男,2女", required = true) + private Integer checkupPersonSex; + + @ApiModelProperty(value = "体检人电话", required = true) + private String checkupPersonPhone; + + @ApiModelProperty(value = "体检人身份证号", required = true) + private String checkupPersonIdcard; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/ReservationSettingUpsertReqDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/ReservationSettingUpsertReqDTO.java new file mode 100644 index 0000000..7addb18 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/request/ReservationSettingUpsertReqDTO.java @@ -0,0 +1,35 @@ +package com.jzo2o.health.model.dto.request; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDate; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-11-01 + */ +@Data +@Builder +@ApiModel("预约设置更新请求模型") +public class ReservationSettingUpsertReqDTO { + /** + * 预约日期 + */ + @ApiModelProperty(value = "预约日期,格式:yyyy-MM-dd", required = true) + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate orderDate; + + /** + * 可预约人数 + */ + @ApiModelProperty(value = "可预约人数", required = true) + private Integer number; +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/AdminOrdersDetailResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/AdminOrdersDetailResDTO.java new file mode 100644 index 0000000..953fbad --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/AdminOrdersDetailResDTO.java @@ -0,0 +1,195 @@ +package com.jzo2o.health.model.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 管理端订单详情 + * + * @author itcast + * @create 2023/11/6 17:31 + **/ +@Data +public class AdminOrdersDetailResDTO { + @ApiModelProperty("订单信息") + private OrderInfo orderInfo; + + @ApiModelProperty("支付信息") + private PayInfo payInfo; + + @ApiModelProperty("退款信息") + private RefundInfo refundInfo; + + @ApiModelProperty("订单取消理由") + private CancelInfo cancelInfo; + + @Data + @ApiModel("订单信息模型") + public static class OrderInfo { + /** + * 订单id + */ + @ApiModelProperty("订单id") + private Long id; + + /** + * 订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消 + */ + @ApiModelProperty("订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消") + private Integer orderStatus; + + /** + * 套餐id + */ + @ApiModelProperty("套餐id") + private Integer setmealId; + + /** + * 套餐名称 + */ + @ApiModelProperty("套餐名称") + private String setmealName; + /** + * 套餐价格 + */ + @ApiModelProperty("套餐价格") + private BigDecimal setmealPrice; + + /** + * 预约日期,格式:yyyy-MM-dd + */ + @ApiModelProperty("预约日期,格式:yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate reservationDate; + + /** + * 体检人姓名 + */ + @ApiModelProperty("体检人姓名") + private String checkupPersonName; + + /** + * 体检人性别,0:不限,1:男,2女 + */ + @ApiModelProperty("体检人性别,0:不限,1:男,2女") + private Integer checkupPersonSex; + + /** + * 体检人电话 + */ + @ApiModelProperty("体检人电话") + private String checkupPersonPhone; + + /** + * 体检人身份证号 + */ + @ApiModelProperty("体检人身份证号") + private String checkupPersonIdcard; + + /** + * 用户id + */ + @ApiModelProperty("用户id") + private Long memberId; + + /** + * 用户电话 + */ + @ApiModelProperty("用户电话") + private String memberPhone; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + } + + @Data + @ApiModel("支付记录模型") + public static class PayInfo { + /** + * 支付状态,0:未支付,1:已支付 + */ + @ApiModelProperty("支付状态,0:未支付,1:已支付") + private Integer payStatus; + + /** + * 支付渠道,ALI_PAY:支付宝,WECHAT_PAY:微信 + */ + @ApiModelProperty("支付渠道,ALI_PAY:支付宝,WECHAT_PAY:微信") + private String tradingChannel; + + /** + * 三方流水,微信支付订单号或支付宝订单号 + */ + @ApiModelProperty("三方流水,微信支付订单号或支付宝订单号") + private String thirdOrderId; + + /** + * 支付时间 + */ + @ApiModelProperty("支付时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime payTime; + } + + @Data + @ApiModel("退款信息模型") + public static class RefundInfo { + /** + * 退款状态,2:退款中,3:退款成功,4:退款失败 + */ + @ApiModelProperty("退款状态,2:退款中,3:退款成功,4:退款失败") + private Integer refundStatus; + + /** + * 退款时间;和取消时间保持一致 + */ + @ApiModelProperty("退款时间;和取消时间保持一致") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime cancelTime; + + /** + * 退款理由和取消理由一致 + */ + @ApiModelProperty("退款理由和取消理由一致") + private String cancelReason; + + /** + * 支付渠道,ALI_PAY:支付宝,WECHAT_PAY:微信 + */ + @ApiModelProperty("支付渠道,ALI_PAY:支付宝,WECHAT_PAY:微信") + private String tradingChannel; + + /** + * 第三方支付的退款单号 + */ + @ApiModelProperty("第三方支付的退款单号") + private String refundId; + } + + @Data + @ApiModel("订单取消模型") + public static class CancelInfo { + /** + * 取消时间 + */ + @ApiModelProperty("取消时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime cancelTime; + + /** + * 取消理由 + */ + @ApiModelProperty("取消理由") + private String cancelReason; + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/CheckGroupDetailResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/CheckGroupDetailResDTO.java new file mode 100644 index 0000000..356ce94 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/CheckGroupDetailResDTO.java @@ -0,0 +1,33 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author itcast + * @create 2023/11/3 18:53 + **/ +@Data +@ApiModel("检查组详情") +public class CheckGroupDetailResDTO { + /** + * 检查组id + */ + @ApiModelProperty("检查组id") + private Integer id; + + /** + * 检查组名称 + */ + @ApiModelProperty("检查组名称") + private String name; + + /** + * 检查项列表 + */ + @ApiModelProperty("检查项列表") + private List checkItemList; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/CheckItemResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/CheckItemResDTO.java new file mode 100644 index 0000000..03cbcf0 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/CheckItemResDTO.java @@ -0,0 +1,21 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("检查项响应模型") +public class CheckItemResDTO { + /** + * 检查项id + */ + @ApiModelProperty("检查项id") + private Integer id; + + /** + * 检查项名称 + */ + @ApiModelProperty("检查项名称") + private String name; +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/LoginResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/LoginResDTO.java new file mode 100644 index 0000000..aa26229 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/LoginResDTO.java @@ -0,0 +1,17 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@ApiModel("登录结果") +@NoArgsConstructor +@AllArgsConstructor +public class LoginResDTO { + + @ApiModelProperty("运营端访问token") + private String token; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersCountResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersCountResDTO.java new file mode 100644 index 0000000..7f25c16 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersCountResDTO.java @@ -0,0 +1,56 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 订单数量 + * + * @author itcast + * @create 2023/11/8 16:02 + **/ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("订单数量响应模型") +public class OrdersCountResDTO { + + /** + * 待支付数量 + */ + @ApiModelProperty("待支付数量") + private Integer noPayCount = 0; + + /** + * 待体检数量 + */ + @ApiModelProperty("待体检数量") + private Integer waitingCheckupCount = 0; + + /** + * 已体检数量 + */ + @ApiModelProperty("已体检数量") + private Integer completedCheckupCount = 0; + + /** + * 已关闭数量 + */ + @ApiModelProperty("已关闭数量") + private Integer closedCount = 0; + + /** + * 已取消数量 + */ + @ApiModelProperty("已取消数量") + private Integer cancelledCount = 0; + + /** + * 全部数量 + */ + @ApiModelProperty("全部数量") + private Integer totalCount = 0; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersDetailResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersDetailResDTO.java new file mode 100644 index 0000000..9dc7fef --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersDetailResDTO.java @@ -0,0 +1,195 @@ +package com.jzo2o.health.model.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 订单表 + *

+ * + * @author itcast + * @since 2023-11-02 + */ +@Data +@ApiModel("订单详情响应体") +public class OrdersDetailResDTO { + /** + * 订单id + */ + @ApiModelProperty("订单id") + private Long id; + + /** + * 订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消 + */ + @ApiModelProperty("订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消") + private Integer orderStatus; + + /** + * 支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败 + */ + @ApiModelProperty("支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败") + private Integer payStatus; + + /** + * 套餐id + */ + @ApiModelProperty("套餐id") + private Integer setmealId; + + /** + * 套餐名称 + */ + @ApiModelProperty("套餐名称") + private String setmealName; + + /** + * 套餐价格 + */ + @ApiModelProperty("套餐价格") + private BigDecimal setmealPrice; + + /** + * 套餐适用性别,0:不限,1:男,2:女 + */ + @ApiModelProperty("套餐适用性别,0:不限,1:男,2:女") + private Integer setmealSex; + + /** + * 套餐适用年龄 + */ + @ApiModelProperty("套餐适用年龄") + private String setmealAge; + + /** + * 套餐图片 + */ + @ApiModelProperty("套餐图片") + private String setmealImg; + + /** + * 套餐说明 + */ + @ApiModelProperty("套餐说明") + private String setmealRemark; + + /** + * 预约日期,格式:yyyy-MM-dd + */ + @ApiModelProperty("预约日期,格式:yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate reservationDate; + + /** + * 体检人姓名 + */ + @ApiModelProperty("体检人姓名") + private String checkupPersonName; + + /** + * 体检人性别,0:不限,1:男,2女 + */ + @ApiModelProperty("体检人性别,0:不限,1:男,2女") + private Integer checkupPersonSex; + + /** + * 体检人电话 + */ + @ApiModelProperty("体检人电话") + private String checkupPersonPhone; + + /** + * 体检人身份证号 + */ + @ApiModelProperty("体检人身份证号") + private String checkupPersonIdcard; + + /** + * 用户id + */ + @ApiModelProperty("用户id") + private Long memberId; + + /** + * 用户电话 + */ + @ApiModelProperty("用户电话") + private String memberPhone; + + /** + * 支付时间 + */ + @ApiModelProperty("支付时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime payTime; + + /** + * 支付渠道 + */ + @ApiModelProperty("支付渠道") + private String tradingChannel; + + /** + * 支付服务交易单号 + */ + @ApiModelProperty("支付服务交易单号") + private Long tradingOrderNo; + + /** + * 第三方支付的交易号 + */ + @ApiModelProperty("第三方支付的交易号") + private String transactionId; + + /** + * 支付服务退款单号 + */ + @ApiModelProperty("支付服务退款单号") + private Long refundNo; + + /** + * 第三方支付的退款单号 + */ + @ApiModelProperty("第三方支付的退款单号") + private String refundId; + + /** + * 排序字段(取创建时间的时间戳) + */ + @ApiModelProperty("排序字段(取创建时间的时间戳)") + private Long sortBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @ApiModelProperty("更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; + + /** + * 取消或退款时间 + */ + @ApiModelProperty("取消或退款时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime cancelTime; + + /** + * 取消或退款原因 + */ + @ApiModelProperty("取消或退款原因") + private String cancelReason; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersPayResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersPayResDTO.java new file mode 100644 index 0000000..08dff8a --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersPayResDTO.java @@ -0,0 +1,33 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 订单支付响应体 + * + * @author itcast + * @create 2023/9/4 10:00 + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("订单支付响应体") +public class OrdersPayResDTO { + + @ApiModelProperty(value = "二维码base64数据") + private String qrCode; + @ApiModelProperty(value = "业务系统订单号") + private Long productOrderNo; + @ApiModelProperty(value = "交易系统订单号【对于三方来说:商户订单】") + private Long tradingOrderNo; + @ApiModelProperty(value = "支付渠道【支付宝、微信、现金、免单挂账】") + private String tradingChannel; + @ApiModelProperty(value = "支付状态,0:待支付,1:支付成功") + private Integer payStatus; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersResDTO.java new file mode 100644 index 0000000..93d6928 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersResDTO.java @@ -0,0 +1,126 @@ +package com.jzo2o.health.model.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 订单响应 + * + * @author itcast + * @create 2023/11/3 19:17 + **/ +@Data +@ApiModel("订单响应模型") +public class OrdersResDTO { + /** + * 订单id + */ + @ApiModelProperty("订单id") + private Long id; + + /** + * 订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消 + */ + @ApiModelProperty("订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消") + private Integer orderStatus; + + /** + * 支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败 + */ + @ApiModelProperty("支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败") + private Integer payStatus; + + + /** + * 套餐id + */ + @ApiModelProperty("套餐id") + private Integer setmealId; + + /** + * 套餐名称 + */ + @ApiModelProperty("套餐名称") + private String setmealName; + + /** + * 套餐价格 + */ + @ApiModelProperty("套餐价格") + private BigDecimal setmealPrice; + + /** + * 套餐适用年龄 + */ + @ApiModelProperty("套餐适用年龄") + private String setmealAge; + + /** + * 套餐适用性别 + */ + @ApiModelProperty("套餐适用性别") + private Integer setmealSex; + + /** + * 套餐图片 + */ + @ApiModelProperty("套餐图片") + private String setmealImg; + + /** + * 套餐说明 + */ + @ApiModelProperty("套餐说明") + private String setmealRemark; + + /** + * 预约日期 + */ + @ApiModelProperty("预约日期") + @JsonFormat(pattern = "yyyy-MM-dd") + private LocalDate reservationDate; + + /** + * 体检人 + */ + @ApiModelProperty("体检人") + private String checkupPersonName; + + /** + * 体检人身份证号 + */ + @ApiModelProperty("体检人身份证号") + private String checkupPersonIdcard; + + /** + * 用户电话 + */ + @ApiModelProperty("用户电话") + private String memberPhone; + + /** + * 排序字段(取创建时间的时间戳) + */ + @ApiModelProperty("排序字段(取创建时间的时间戳)") + private Long sortBy; + + /** + * 创建时间 + */ + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @ApiModelProperty("更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/PlaceOrderResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/PlaceOrderResDTO.java new file mode 100644 index 0000000..967d8fa --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/PlaceOrderResDTO.java @@ -0,0 +1,19 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author itcast + */ +@ApiModel("下单响应信息") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PlaceOrderResDTO { + @ApiModelProperty("订单id") + private Long id; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/ReservationDateResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/ReservationDateResDTO.java new file mode 100644 index 0000000..d9b88ad --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/ReservationDateResDTO.java @@ -0,0 +1,27 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 预约日期响应模型 + * + * @author itcast + * @create 2023/11/6 10:19 + **/ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("预约日期响应模型") +public class ReservationDateResDTO { + /** + * 可预约日期 + */ + @ApiModelProperty("可预约日期") + private List dateList; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/ReservationSettingResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/ReservationSettingResDTO.java new file mode 100644 index 0000000..22a7b07 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/ReservationSettingResDTO.java @@ -0,0 +1,37 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-11-01 + */ +@Data +@Builder +@ApiModel("预约设置响应模型") +public class ReservationSettingResDTO { + /** + * 预约日期 + */ + @ApiModelProperty("预约日期") + private String date; + + /** + * 可预约人数 + */ + @ApiModelProperty("可预约人数") + private Integer number; + + /** + * 已预约人数 + */ + @ApiModelProperty("已预约人数") + private Integer reservations; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/SetmealDetailResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/SetmealDetailResDTO.java new file mode 100644 index 0000000..a5c44dd --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/SetmealDetailResDTO.java @@ -0,0 +1,87 @@ +package com.jzo2o.health.model.dto.response; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Data +@ApiModel("套餐详情响应模型") +public class SetmealDetailResDTO { + + /** + * 套餐id + */ + @ApiModelProperty("套餐id") + private Integer id; + + /** + * 套餐名称 + */ + @ApiModelProperty("套餐名称") + private String name; + + /** + * 套餐编码 + */ + @ApiModelProperty("套餐编码") + private String code; + + /** + * 套餐助记码 + */ + @ApiModelProperty("套餐助记码") + private String helpCode; + + /** + * 性别,0:不限,1:男,2:女 + */ + @ApiModelProperty("性别,0:不限,1:男,2:女") + private String sex; + + /** + * 适用年龄 + */ + @ApiModelProperty("适用年龄") + private String age; + + /** + * 价格 + */ + @ApiModelProperty("价格") + private Float price; + + /** + * 说明 + */ + @ApiModelProperty("说明") + private String remark; + + /** + * 注意事项 + */ + @ApiModelProperty("注意事项") + private String attention; + + /** + * 图片 + */ + @ApiModelProperty("图片") + private String img; + + /** + * 检查组列表 + */ + @ApiModelProperty("检查组列表") + private List checkGroupList; + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/excel/ReservationImportData.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/excel/ReservationImportData.java new file mode 100644 index 0000000..1fb6d07 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/excel/ReservationImportData.java @@ -0,0 +1,25 @@ +package com.jzo2o.health.model.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * 预约导入数据 + * + * @author itcast + * @create 2023/11/1 19:16 + **/ +@Data +public class ReservationImportData { + /** + * 日期,格式:yyyy-MM-dd + */ + @ExcelProperty(index = 0) + private String date; + + /** + * 预约人数 + */ + @ExcelProperty(index = 1) + private Integer number; +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/properties/ApplicationProperties.java b/jzo2o-health/src/main/java/com/jzo2o/health/properties/ApplicationProperties.java new file mode 100644 index 0000000..683abf7 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/properties/ApplicationProperties.java @@ -0,0 +1,46 @@ +package com.jzo2o.health.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Configuration +@ConfigurationProperties(prefix = "jzo2o") +@Data +public class ApplicationProperties { + + /** + * jwt 加密秘钥 + */ + private String jwtKey; + + /** + * 每一个端都要配置一个token解析key + * “1”:xxx c端用户token生成key + * "2": xxx 服务端用户token生成key + * "3": xxx 机构端用户token生成key + * "4": xxx 运营端用户token生成key + * tokenkey + */ + @NestedConfigurationProperty + private final Map tokenKey = new HashMap<>(); + + /** + * 访问路径地址白名单 + */ + @NestedConfigurationProperty + private List accessPathWhiteList = new ArrayList<>(); + + /** + * 访问路径黑名单 + */ + @NestedConfigurationProperty + private List accessPathBlackList = new ArrayList<>(); + +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/properties/OrdersJobProperties.java b/jzo2o-health/src/main/java/com/jzo2o/health/properties/OrdersJobProperties.java new file mode 100644 index 0000000..066b503 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/properties/OrdersJobProperties.java @@ -0,0 +1,23 @@ +package com.jzo2o.health.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author itcast + */ +@Data +@Component +@ConfigurationProperties(prefix = "jzo2o.job") +public class OrdersJobProperties { + /** + * 退款订单数量,默认100 + */ + private Integer refundOrderCount = 100; + + /** + * 超时支付订单数量,默认100 + */ + private Integer overTimePayOrderCount = 100; +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/properties/TradeProperties.java b/jzo2o-health/src/main/java/com/jzo2o/health/properties/TradeProperties.java new file mode 100644 index 0000000..285100b --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/properties/TradeProperties.java @@ -0,0 +1,24 @@ +package com.jzo2o.health.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author itcast + */ +@Data +@Component +@ConfigurationProperties(prefix = "jzo2o.trade") +public class TradeProperties { + + /** + * 支付宝商户id + */ + private Long aliEnterpriseId; + + /** + * 微信支付商户id + */ + private Long wechatEnterpriseId; +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckgroupCheckitemService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckgroupCheckitemService.java new file mode 100644 index 0000000..ab1ed46 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckgroupCheckitemService.java @@ -0,0 +1,47 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.CheckgroupCheckitem; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface ICheckgroupCheckitemService extends IService { + /** + * 删除关联关系 + * + * @param checkGroupId 检查组id + */ + void deleteAssociation(Integer checkGroupId); + + /** + * 根据检查组id查询检查项id + * + * @param checkGroupId 检查组id + * @return 检查项id + */ + List findCheckItemIdsByCheckGroupId(Integer checkGroupId); + + /** + * 新增关联关系 + * + * @param checkGroupId 检查组id + * @param checkItemId 检查项id + */ + void add(Integer checkGroupId, Integer checkItemId); + + /** + * 根据检查项id查询数量 + * + * @param checkItemId 检查项id + * @return 数量 + */ + long findCountByCheckItemId(Integer checkItemId); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckgroupService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckgroupService.java new file mode 100644 index 0000000..8951842 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckgroupService.java @@ -0,0 +1,15 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.Checkgroup; + +/** + *

+ * 服务类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface ICheckgroupService extends IService { +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckitemService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckitemService.java new file mode 100644 index 0000000..79bddd8 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/ICheckitemService.java @@ -0,0 +1,15 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.Checkitem; + +/** + *

+ * 服务类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface ICheckitemService extends IService { +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/ILoginService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/ILoginService.java new file mode 100644 index 0000000..2e0de92 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/ILoginService.java @@ -0,0 +1,27 @@ +package com.jzo2o.health.service; + +import com.jzo2o.health.model.dto.request.LoginReqDTO; +import com.jzo2o.health.model.dto.request.MemberLoginReqDTO; + +/** + * 登录相关业务 + * + * @author itcast + */ +public interface ILoginService { + /** + * 管理员登录 + * + * @param loginReqDTO 管理员登录请求模型 + * @return token + */ + String adminLogin(LoginReqDTO loginReqDTO); + + /** + * 普通用户登录 + * + * @param memberLoginReqDTO 普通用户登录请求模型 + * @return token + */ + String memberLogin(MemberLoginReqDTO memberLoginReqDTO); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IMemberService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IMemberService.java new file mode 100644 index 0000000..970cc8e --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IMemberService.java @@ -0,0 +1,30 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.Member; + +/** + *

+ * 普通用户 服务类 + *

+ * + * @author itcast + * @since 2023-11-02 + */ +public interface IMemberService extends IService { + /** + * 根据手机号查询普通用户 + * + * @param phone 手机号 + * @return 普通用户 + */ + Member findByPhone(String phone); + + /** + * 新增普通用户 + * + * @param phone 手机号 + * @return 普通用户 + */ + Member add(String phone); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java new file mode 100644 index 0000000..3b65f0c --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java @@ -0,0 +1,13 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.ReservationSetting; + +/** + *

+ * 预约设置 服务类 + *

+ * @author JIAN + */ +public interface IReservationSettingService extends IService { +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/ISetmealCheckgroupService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/ISetmealCheckgroupService.java new file mode 100644 index 0000000..e1e5c3f --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/ISetmealCheckgroupService.java @@ -0,0 +1,22 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.SetmealCheckgroup; + +/** + *

+ * 服务类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface ISetmealCheckgroupService extends IService { + /** + * 绑定套餐和检查组的关系 + * + * @param setmealId 套餐id + * @param checkgroupId 检查组id + */ + void setSetmealAndCheckGroup(Integer setmealId, Integer checkgroupId); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/ISetmealService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/ISetmealService.java new file mode 100644 index 0000000..a496467 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/ISetmealService.java @@ -0,0 +1,35 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.common.model.PageResult; +import com.jzo2o.health.model.domain.Setmeal; +import com.jzo2o.health.model.dto.request.CommonPageQueryReqDTO; +import com.jzo2o.health.model.dto.response.SetmealDetailResDTO; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface ISetmealService extends IService { + void add(Setmeal setmeal, Integer[] checkgroupIds); + + List findAll(); + + Setmeal findById(int id); + + /** + * 查询套餐详情(包含关联检查组、检查项) + * + * @param id 套餐id + * @return 套餐详情 + */ + SetmealDetailResDTO findDetail(Integer id); + + PageResult findPage(CommonPageQueryReqDTO commonPageQueryReqDTO); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IUserService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IUserService.java new file mode 100644 index 0000000..11548e3 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IUserService.java @@ -0,0 +1,22 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.User; + +/** + *

+ * 管理员 服务类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +public interface IUserService extends IService { + /** + * 根据用户名查询用户 + * + * @param username 用户名 + * @return 用户信息 + */ + User findByUsername(String username); +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckgroupCheckitemServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckgroupCheckitemServiceImpl.java new file mode 100644 index 0000000..aed23a3 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckgroupCheckitemServiceImpl.java @@ -0,0 +1,81 @@ +package com.jzo2o.health.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.health.mapper.CheckgroupCheckitemMapper; +import com.jzo2o.health.model.domain.CheckgroupCheckitem; +import com.jzo2o.health.service.ICheckgroupCheckitemService; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Service +public class CheckgroupCheckitemServiceImpl extends ServiceImpl implements ICheckgroupCheckitemService { + /** + * 删除关联关系 + * + * @param checkGroupId 检查组id + */ + @Override + public void deleteAssociation(Integer checkGroupId) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(CheckgroupCheckitem::getCheckgroupId, checkGroupId); + baseMapper.delete(queryWrapper); + } + + /** + * 根据检查组id查询检查项id + * + * @param checkGroupId 检查组id + * @return 检查项id + */ + @Override + public List findCheckItemIdsByCheckGroupId(Integer checkGroupId) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .eq(CheckgroupCheckitem::getCheckgroupId, checkGroupId) + .select(CheckgroupCheckitem::getCheckitemId); + List checkgroupCheckitemList = baseMapper.selectList(queryWrapper); + if (ObjectUtil.isEmpty(checkgroupCheckitemList)) { + return Collections.emptyList(); + } + + return checkgroupCheckitemList.stream().map(CheckgroupCheckitem::getCheckitemId).collect(Collectors.toList()); + } + + /** + * 新增关联关系 + * + * @param checkGroupId 检查组id + * @param checkItemId 检查项id + */ + @Override + public void add(Integer checkGroupId, Integer checkItemId) { + CheckgroupCheckitem checkgroupCheckitem = new CheckgroupCheckitem(); + checkgroupCheckitem.setCheckgroupId(checkGroupId); + checkgroupCheckitem.setCheckitemId(checkItemId); + baseMapper.insert(checkgroupCheckitem); + } + + /** + * 根据检查项id查询数量 + * + * @param checkItemId 检查项id + * @return 数量 + */ + @Override + public long findCountByCheckItemId(Integer checkItemId) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(CheckgroupCheckitem::getCheckitemId, checkItemId); + return baseMapper.selectCount(queryWrapper); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckgroupServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckgroupServiceImpl.java new file mode 100644 index 0000000..2551cf9 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckgroupServiceImpl.java @@ -0,0 +1,19 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.health.mapper.CheckgroupMapper; +import com.jzo2o.health.model.domain.Checkgroup; +import com.jzo2o.health.service.ICheckgroupService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Service +public class CheckgroupServiceImpl extends ServiceImpl implements ICheckgroupService { +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckitemServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckitemServiceImpl.java new file mode 100644 index 0000000..ab2411f --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/CheckitemServiceImpl.java @@ -0,0 +1,19 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.health.mapper.CheckitemMapper; +import com.jzo2o.health.model.domain.Checkitem; +import com.jzo2o.health.service.ICheckitemService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Service +public class CheckitemServiceImpl extends ServiceImpl implements ICheckitemService { +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/LoginServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/LoginServiceImpl.java new file mode 100644 index 0000000..10b51a2 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/LoginServiceImpl.java @@ -0,0 +1,90 @@ +package com.jzo2o.health.service.impl; + +import com.jzo2o.api.publics.SmsCodeApi; +import com.jzo2o.common.constants.UserType; +import com.jzo2o.common.enums.SmsBusinessTypeEnum; +import com.jzo2o.common.expcetions.BadRequestException; +import com.jzo2o.common.expcetions.RequestForbiddenException; +import com.jzo2o.common.utils.JwtTool; +import com.jzo2o.common.utils.StringUtils; +import com.jzo2o.health.model.domain.Member; +import com.jzo2o.health.model.domain.User; +import com.jzo2o.health.model.dto.request.LoginReqDTO; +import com.jzo2o.health.model.dto.request.MemberLoginReqDTO; +import com.jzo2o.health.service.ILoginService; +import com.jzo2o.health.service.IMemberService; +import com.jzo2o.health.service.IUserService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * @author itcast + */ +@Service +public class LoginServiceImpl implements ILoginService { + + @Resource + private IUserService userService; + @Resource + private JwtTool jwtTool; + @Resource + private PasswordEncoder passwordEncoder; + @Resource + private SmsCodeApi smsCodeApi; + @Resource + private IMemberService memberService; + + /** + * 管理员登录 + * + * @param loginReqDTO 管理员登录请求模型 + * @return token + */ + @Override + public String adminLogin(LoginReqDTO loginReqDTO) { + //根据输入的账号查询用户信息 + User user = userService.findByUsername(loginReqDTO.getUsername()); + if (user == null) { + throw new RequestForbiddenException("账号或密码错误,请重新输入"); + } + // 比对密码 + if (!passwordEncoder.matches(loginReqDTO.getPassword(), user.getPassword())) { + throw new RequestForbiddenException("账号或密码错误,请重新输入"); + } + //生成令牌 + return jwtTool.createToken(user.getId(), user.getName(), user.getAvatar(), UserType.OPERATION); + } + + /** + * 普通用户登录 + * + * @param memberLoginReqDTO 普通用户登录请求模型 + * @return token + */ + @Override + public String memberLogin(MemberLoginReqDTO memberLoginReqDTO) { + // 校验验证码是否为空 + if (StringUtils.isBlank(memberLoginReqDTO.getVerifyCode())) { + throw new BadRequestException("手机号码或短信验证码错误"); + } + // 校验验证码是否正确 + //家政项目中,验证码业务类型是枚举类,固定死的,这里我们借用 SmsBusinessTypeEnum.SERVE_STAFF_LOGIN 类型 + boolean verifyResult = smsCodeApi.verify(memberLoginReqDTO.getPhone(), SmsBusinessTypeEnum.SERVE_STAFF_LOGIN, memberLoginReqDTO.getVerifyCode()).getIsSuccess(); + if (!verifyResult) { + throw new BadRequestException("手机号码或短信验证码错误"); + } + + // 登录校验,根据手机查询普通用户信息 + Member member = memberService.findByPhone(memberLoginReqDTO.getPhone()); + + // 自动注册 + if (member == null) { + member = memberService.add(memberLoginReqDTO.getPhone()); + } + + // 生成登录token + return jwtTool.createToken(member.getId(), member.getNickname(), member.getAvatar(), UserType.C_USER); + } +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/MemberServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/MemberServiceImpl.java new file mode 100644 index 0000000..0a7ccac --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/MemberServiceImpl.java @@ -0,0 +1,54 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.health.mapper.MemberMapper; +import com.jzo2o.health.model.domain.Member; +import com.jzo2o.health.service.IMemberService; +import org.springframework.stereotype.Service; + +/** + *

+ * 普通用户 服务实现类 + *

+ * + * @author itcast + * @since 2023-11-02 + */ +@Service +public class MemberServiceImpl extends ServiceImpl implements IMemberService { + /** + * 默认头像 + */ + private static final String DEFAULT_AVATAR = "https://yjy-oss-videos.oss-accelerate.aliyuncs.com/tx.png"; + + /** + * 根据手机号查询普通用户 + * + * @param phone 手机号 + * @return 普通用户 + */ + @Override + public Member findByPhone(String phone) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(Member::getPhone, phone); + return baseMapper.selectOne(queryWrapper); + } + + /** + * 新增普通用户 + * + * @param phone 手机号 + * @return 普通用户 + */ + @Override + public Member add(String phone) { + Member member = new Member(); + member.setNickname("普通用户"); + member.setPhone(phone); + //设置默认头像 + member.setAvatar(DEFAULT_AVATAR); + baseMapper.insert(member); + return member; + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java new file mode 100644 index 0000000..23e599a --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java @@ -0,0 +1,15 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.health.mapper.ReservationSettingMapper; +import com.jzo2o.health.model.domain.ReservationSetting; +import com.jzo2o.health.service.IReservationSettingService; + +/** + *

+ * 服务实现类 + *

+ * @author JIAN + */ +public class ReservationSettingServiceImpl extends ServiceImpl implements IReservationSettingService { +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/SetmealCheckgroupServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/SetmealCheckgroupServiceImpl.java new file mode 100644 index 0000000..6a425a7 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/SetmealCheckgroupServiceImpl.java @@ -0,0 +1,33 @@ +package com.jzo2o.health.service.impl; + +import com.jzo2o.health.model.domain.SetmealCheckgroup; +import com.jzo2o.health.mapper.SetmealCheckgroupMapper; +import com.jzo2o.health.service.ISetmealCheckgroupService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Service +public class SetmealCheckgroupServiceImpl extends ServiceImpl implements ISetmealCheckgroupService { + + /** + * 绑定套餐和检查组的关系 + * + * @param setmealId 套餐id + * @param checkgroupId 检查组id + */ + @Override + public void setSetmealAndCheckGroup(Integer setmealId, Integer checkgroupId) { + SetmealCheckgroup setmealCheckgroup = new SetmealCheckgroup(); + setmealCheckgroup.setSetmealId(setmealId); + setmealCheckgroup.setCheckgroupId(checkgroupId); + baseMapper.insert(setmealCheckgroup); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/SetmealServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/SetmealServiceImpl.java new file mode 100644 index 0000000..f355c7f --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/SetmealServiceImpl.java @@ -0,0 +1,84 @@ +package com.jzo2o.health.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.common.model.PageResult; +import com.jzo2o.health.mapper.SetmealMapper; +import com.jzo2o.health.model.domain.Setmeal; +import com.jzo2o.health.model.dto.request.CommonPageQueryReqDTO; +import com.jzo2o.health.model.dto.response.SetmealDetailResDTO; +import com.jzo2o.health.service.ISetmealCheckgroupService; +import com.jzo2o.health.service.ISetmealService; +import com.jzo2o.mysql.utils.PageUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Service +public class SetmealServiceImpl extends ServiceImpl implements ISetmealService { + @Resource + private ISetmealCheckgroupService setmealCheckgroupService; + + //新增套餐 + @Override + public void add(Setmeal setmeal, Integer[] checkgroupIds) { + baseMapper.insert(setmeal); + if (checkgroupIds != null && checkgroupIds.length > 0) { + //绑定套餐和检查组的多对多关系 + setSetmealAndCheckGroup(setmeal.getId(), checkgroupIds); + } + } + + @Override + public List findAll() { + return super.list(); + } + + @Override + public Setmeal findById(int id) { + return baseMapper.selectById(id); + } + + /** + * 查询套餐详情(包含关联检查组、检查项) + * + * @param id 套餐id + * @return 套餐详情 + */ + @Override + public SetmealDetailResDTO findDetail(Integer id) { + return baseMapper.findDetail(id); + } + + //绑定套餐和检查组的多对多关系 + private void setSetmealAndCheckGroup(Integer id, Integer[] checkgroupIds) { + for (Integer checkgroupId : checkgroupIds) { + setmealCheckgroupService.setSetmealAndCheckGroup(id, checkgroupId); + } + } + + @Override + public PageResult findPage(CommonPageQueryReqDTO commonPageQueryReqDTO) { + //开始分页---设置分页条件 + Page page = PageUtils.parsePageQuery(commonPageQueryReqDTO, Setmeal.class); + + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .or().eq(StrUtil.isNotBlank(commonPageQueryReqDTO.getKeyword()), Setmeal::getCode, commonPageQueryReqDTO.getKeyword()) + .or().eq(StrUtil.isNotBlank(commonPageQueryReqDTO.getKeyword()), Setmeal::getName, commonPageQueryReqDTO.getKeyword()) + .or().eq(StrUtil.isNotBlank(commonPageQueryReqDTO.getKeyword()), Setmeal::getHelpCode, commonPageQueryReqDTO.getKeyword()); + Page checkgroupPage = baseMapper.selectPage(page, queryWrapper); + return PageUtils.toPage(checkgroupPage, Setmeal.class); + } +} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/UserServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..611f4b6 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/UserServiceImpl.java @@ -0,0 +1,33 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.health.mapper.UserMapper; +import com.jzo2o.health.model.domain.User; +import com.jzo2o.health.service.IUserService; +import org.springframework.stereotype.Service; + +/** + *

+ * 管理员 服务实现类 + *

+ * + * @author itcast + * @since 2023-10-31 + */ +@Service +public class UserServiceImpl extends ServiceImpl implements IUserService { + + /** + * 根据用户名查询用户 + * + * @param username 用户名 + * @return 用户信息 + */ + @Override + public User findByUsername(String username) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(User::getUsername, username); + return super.getOne(queryWrapper); + } +} diff --git a/jzo2o-health/src/main/resources/bootstrap-dev.yml b/jzo2o-health/src/main/resources/bootstrap-dev.yml new file mode 100644 index 0000000..28a52fe --- /dev/null +++ b/jzo2o-health/src/main/resources/bootstrap-dev.yml @@ -0,0 +1,18 @@ +spring: + cloud: + nacos: + username: nacos + password: nacos + server-addr: 192.168.122.135:8848 + config: + namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63 + file-extension: yaml + discovery: + namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63 + ip: ${ACCESS_IP:} + + +################# 日志配置 ################# +logging: + level: + com.jzo2o: debug \ No newline at end of file diff --git a/jzo2o-health/src/main/resources/bootstrap-prod.yml b/jzo2o-health/src/main/resources/bootstrap-prod.yml new file mode 100644 index 0000000..7569cd9 --- /dev/null +++ b/jzo2o-health/src/main/resources/bootstrap-prod.yml @@ -0,0 +1,14 @@ +spring: + cloud: + nacos: + username: ${NACOS_USERNAME} + password: ${NACOS_PASSWORD} + server-addr: ${NACOS_ADDR} + config: + namespace: ${NACOS_NAMESPACE} + file-extension: yaml + discovery: + namespace: ${NACOS_NAMESPACE} +logging: + level: + com.jzo2o: debug \ No newline at end of file diff --git a/jzo2o-health/src/main/resources/bootstrap-test.yml b/jzo2o-health/src/main/resources/bootstrap-test.yml new file mode 100644 index 0000000..7569cd9 --- /dev/null +++ b/jzo2o-health/src/main/resources/bootstrap-test.yml @@ -0,0 +1,14 @@ +spring: + cloud: + nacos: + username: ${NACOS_USERNAME} + password: ${NACOS_PASSWORD} + server-addr: ${NACOS_ADDR} + config: + namespace: ${NACOS_NAMESPACE} + file-extension: yaml + discovery: + namespace: ${NACOS_NAMESPACE} +logging: + level: + com.jzo2o: debug \ No newline at end of file diff --git a/jzo2o-health/src/main/resources/bootstrap.yml b/jzo2o-health/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..391aa73 --- /dev/null +++ b/jzo2o-health/src/main/resources/bootstrap.yml @@ -0,0 +1,73 @@ +################# 服务器配置 ################# +server: + port: 21500 + undertow: + accesslog: + enabled: true + pattern: "%t %a "%r" %s (%D ms)" + dir: /data/logs/undertow/${spring.application.name}/access-logs/ + servlet: + context-path: /health + +################# spring公共配置 ################# +spring: + mvc: + path-match: + matching-strategy: ant_path_matcher + format: + date: yyyy-MM-dd HH:mm:ss + jackson: + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + profiles: + active: dev + application: + name: jzo2o-health + main: + # 支持循环依赖注入 + allow-circular-references: true + # bean名相同覆盖 + allow-bean-definition-overriding: true + cloud: + nacos: + username: ${NACOS_USERNAME} + password: ${NACOS_PASSWORD} + server-addr: ${NACOS_ADDR} + discovery: + namespace: ${NACOS_NAMESPACE} + config: + namespace: ${NACOS_NAMESPACE} + file-extension: yaml + shared-configs: # 共享配置 + - data-id: shared-mysql.yaml # mysql配置 + refresh: false + - data-id: shared-redis-cluster.yaml # 共享redis集群配置 + refresh: false + - data-id: shared-xxl-job.yaml # xxl-job配置 + refresh: false + - data-id: shared-rabbitmq.yaml # rabbitmq配置 + refresh: false + +################# 项目独有配置 ################# +mysql: + db-name: jzo2o-health +mybatis: + mapper-locations: mapper/*.xml + type-aliases-package: com.jzo2o.health.mapper +swagger: + enable: true + package-path: com.jzo2o.health.controller + title: 即刻体检实战口文档 + description: 用于o2o家政项目实战内容,完成用户预约下单、支付、订单管理流程。 + contact-name: 传智教育·研究院 + contact-url: http://www.itcast.cn/ + contact-email: yjy@itcast.cn + version: v1.0 + + +################# 日志配置 ################# +logging: + level: + com.jzo2o: debug +feign: + enable: true diff --git a/jzo2o-health/src/main/resources/mapper/CheckgroupCheckitemMapper.xml b/jzo2o-health/src/main/resources/mapper/CheckgroupCheckitemMapper.xml new file mode 100644 index 0000000..739af78 --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/CheckgroupCheckitemMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/CheckgroupMapper.xml b/jzo2o-health/src/main/resources/mapper/CheckgroupMapper.xml new file mode 100644 index 0000000..b1402b4 --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/CheckgroupMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/CheckitemMapper.xml b/jzo2o-health/src/main/resources/mapper/CheckitemMapper.xml new file mode 100644 index 0000000..9bf1140 --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/CheckitemMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/MemberMapper.xml b/jzo2o-health/src/main/resources/mapper/MemberMapper.xml new file mode 100644 index 0000000..321ade7 --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/MemberMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/OrdersCancelledMapper.xml b/jzo2o-health/src/main/resources/mapper/OrdersCancelledMapper.xml new file mode 100644 index 0000000..0041dbb --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/OrdersCancelledMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/OrdersMapper.xml b/jzo2o-health/src/main/resources/mapper/OrdersMapper.xml new file mode 100644 index 0000000..8f71570 --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/OrdersMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/OrdersRefundMapper.xml b/jzo2o-health/src/main/resources/mapper/OrdersRefundMapper.xml new file mode 100644 index 0000000..4208a63 --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/OrdersRefundMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/ReservationSettingMapper.xml b/jzo2o-health/src/main/resources/mapper/ReservationSettingMapper.xml new file mode 100644 index 0000000..04d345e --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/ReservationSettingMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/SetmealCheckgroupMapper.xml b/jzo2o-health/src/main/resources/mapper/SetmealCheckgroupMapper.xml new file mode 100644 index 0000000..8b33468 --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/SetmealCheckgroupMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/SetmealMapper.xml b/jzo2o-health/src/main/resources/mapper/SetmealMapper.xml new file mode 100644 index 0000000..4f4de8b --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/SetmealMapper.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jzo2o-health/src/main/resources/mapper/UserMapper.xml b/jzo2o-health/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..8e1edb4 --- /dev/null +++ b/jzo2o-health/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,5 @@ + + + + + From 6003aca88e3ca6ac414ba9a66c71428df09b93db Mon Sep 17 00:00:00 2001 From: JIAN Date: Sat, 14 Sep 2024 21:57:39 +0800 Subject: [PATCH 14/21] =?UTF-8?q?feat(health):=E6=96=B0=E5=A2=9E=E9=A2=84?= =?UTF-8?q?=E7=BA=A6=E8=AE=BE=E7=BD=AE=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=201.=20=E6=9F=A5=E8=AF=A2=E6=9F=90=E6=9C=88=E7=9A=84=E9=A2=84?= =?UTF-8?q?=E7=BA=A6=E8=AE=BE=E7=BD=AE=202.=20=E6=9F=A5=E8=AF=A2=E5=8F=AF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E9=A2=84=E7=BA=A6=E6=97=A5=E6=9C=9F=203.=20(?= =?UTF-8?q?=E6=89=B9=E9=87=8F)=E8=AE=BE=E7=BD=AE=E9=A2=84=E7=BA=A6?= =?UTF-8?q?=E4=BA=BA=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReservationBatchSettingController.java | 27 +++++- .../admin/ReservationSettingController.java | 11 ++- .../user/ReservationSettingController.java | 12 ++- .../mapper/ReservationSettingMapper.java | 10 ++- .../service/IReservationSettingService.java | 26 ++++++ .../impl/ReservationSettingServiceImpl.java | 84 +++++++++++++++++++ 6 files changed, 161 insertions(+), 9 deletions(-) diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationBatchSettingController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationBatchSettingController.java index b061528..6e1ad69 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationBatchSettingController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationBatchSettingController.java @@ -1,5 +1,9 @@ package com.jzo2o.health.controller.admin; +import com.alibaba.excel.EasyExcel; +import com.jzo2o.common.utils.CollUtils; +import com.jzo2o.health.model.excel.ReservationImportData; +import com.jzo2o.health.service.IReservationSettingService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -9,9 +13,12 @@ import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import javax.annotation.Resource; +import java.io.InputStream; +import java.util.List; + /** * 预约设置操作 - * * @author itcast */ @Slf4j @@ -19,10 +26,26 @@ import org.springframework.web.multipart.MultipartFile; @RequestMapping("/admin/reservation-setting") @Api(tags = "管理端 - 批量预约设置相关接口") public class ReservationBatchSettingController { + @Resource + private IReservationSettingService reservationSettingService; @PostMapping("/upload") @ApiOperation("上传文件批量预约设置") public void upload(@RequestPart("file") MultipartFile file) { + List reservationDataList; + try (InputStream inputStream = file.getInputStream()) { + reservationDataList = EasyExcel.read(inputStream) + .head(ReservationImportData.class) + .sheet("预约设置模板") + .doReadSync(); + } catch (Exception e) { + // 防止过度包装 + throw e instanceof RuntimeException ? (RuntimeException) e : new RuntimeException(e); + } + + if (CollUtils.isNotEmpty(reservationDataList)) { + reservationSettingService.editNumberByDateBatch(reservationDataList); + } } -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationSettingController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationSettingController.java index 4d22c52..05c71ac 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationSettingController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/ReservationSettingController.java @@ -2,12 +2,15 @@ package com.jzo2o.health.controller.admin; import com.jzo2o.health.model.dto.request.ReservationSettingUpsertReqDTO; import com.jzo2o.health.model.dto.response.ReservationSettingResDTO; +import com.jzo2o.health.service.IReservationSettingService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import java.time.YearMonth; import java.util.List; /** @@ -20,16 +23,20 @@ import java.util.List; @RequestMapping("/admin/reservation-setting") @Api(tags = "管理端 - 预约设置相关接口") public class ReservationSettingController { + @Resource + private IReservationSettingService reservationSettingService; @GetMapping("/getReservationSettingByMonth") @ApiOperation("按月查询预约设置") @ApiImplicitParam(name = "date", value = "月份,格式:yyyy-MM", required = true, dataTypeClass = String.class) public List getReservationSettingByMonth(@RequestParam("date") String date) { - return null; + YearMonth yearMonth = YearMonth.parse(date); + return reservationSettingService.getReservationSettingByMonth(yearMonth); } @PutMapping("/editNumberByDate") @ApiOperation("编辑预约设置") public void editNumberByDate(@RequestBody ReservationSettingUpsertReqDTO reservationSettingUpsertReqDTO) { + reservationSettingService.editNumberByDate(reservationSettingUpsertReqDTO); } -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/ReservationSettingController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/ReservationSettingController.java index 726ab64..c9f9df7 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/ReservationSettingController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/ReservationSettingController.java @@ -2,6 +2,7 @@ package com.jzo2o.health.controller.user; import com.jzo2o.health.annotation.IgnoreToken; import com.jzo2o.health.model.dto.response.ReservationDateResDTO; +import com.jzo2o.health.service.IReservationSettingService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -11,9 +12,11 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; +import java.time.YearMonth; + /** * 预约设置操作 - * * @author itcast */ @Slf4j @@ -21,12 +24,15 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/user/reservation-setting") @Api(tags = "用户端 - 预约设置相关接口") public class ReservationSettingController { + @Resource + private IReservationSettingService reservationSettingService; @GetMapping("/getReservationDateByMonth") @IgnoreToken @ApiOperation("按月查询可预约日期") @ApiImplicitParam(name = "month", value = "月份,格式:yyyy-MM", required = true, dataTypeClass = String.class) public ReservationDateResDTO getReservationDateByMonth(@RequestParam("month") String month) { - return null; + YearMonth yearMonth = YearMonth.parse(month); + return reservationSettingService.getReservationDateByMonth(yearMonth); } -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java index 71da200..2547343 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java @@ -3,17 +3,23 @@ package com.jzo2o.health.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.jzo2o.health.model.domain.ReservationSetting; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; +import java.time.LocalDate; +import java.util.List; + /** *

* Mapper 接口 *

- * * @author itcast * @since 2023-11-01 */ public interface ReservationSettingMapper extends BaseMapper { @Update("UPDATE reservation_setting SET reservations = reservations + 1 WHERE id = #{id} AND reservations < number") Integer updateReservations(@Param("id") Integer id); -} + + @Select("SELECT order_date FROM reservation_setting WHERE #{start} <= order_date AND order_date <= #{end}") + List getReservationDate(@Param("start") LocalDate start, @Param("end") LocalDate end); +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java index 3b65f0c..55035dc 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java @@ -2,6 +2,13 @@ package com.jzo2o.health.service; import com.baomidou.mybatisplus.extension.service.IService; import com.jzo2o.health.model.domain.ReservationSetting; +import com.jzo2o.health.model.dto.request.ReservationSettingUpsertReqDTO; +import com.jzo2o.health.model.dto.response.ReservationDateResDTO; +import com.jzo2o.health.model.dto.response.ReservationSettingResDTO; +import com.jzo2o.health.model.excel.ReservationImportData; + +import java.time.YearMonth; +import java.util.List; /** *

@@ -10,4 +17,23 @@ import com.jzo2o.health.model.domain.ReservationSetting; * @author JIAN */ public interface IReservationSettingService extends IService { + /** + * 获取指定月份的所有预约数据 + */ + List getReservationSettingByMonth(YearMonth yearMonth); + + /** + * 更新/插入指定日期的预约数据 + */ + void editNumberByDate(ReservationSettingUpsertReqDTO reservationSettingUpsertReqDTO); + + /** + * 批量更新/插入指定日期的预约数据 + */ + void editNumberByDateBatch(List reservationDataList); + + /** + * 获取当前月份可用预约日期 + */ + ReservationDateResDTO getReservationDateByMonth(YearMonth yearMonth); } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java index 23e599a..94aa5d4 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java @@ -1,9 +1,25 @@ package com.jzo2o.health.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.utils.CollUtils; import com.jzo2o.health.mapper.ReservationSettingMapper; import com.jzo2o.health.model.domain.ReservationSetting; +import com.jzo2o.health.model.dto.request.ReservationSettingUpsertReqDTO; +import com.jzo2o.health.model.dto.response.ReservationDateResDTO; +import com.jzo2o.health.model.dto.response.ReservationSettingResDTO; +import com.jzo2o.health.model.excel.ReservationImportData; import com.jzo2o.health.service.IReservationSettingService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; /** *

@@ -11,5 +27,73 @@ import com.jzo2o.health.service.IReservationSettingService; *

* @author JIAN */ +@Service public class ReservationSettingServiceImpl extends ServiceImpl implements IReservationSettingService { + @Override + @SuppressWarnings("unchecked") + public List getReservationSettingByMonth(YearMonth yearMonth) { + List reservationSettingList = lambdaQuery() + .ge(ReservationSetting::getOrderDate, yearMonth.atDay(1)) + .le(ReservationSetting::getOrderDate, yearMonth.atEndOfMonth()) + .orderByDesc(ReservationSetting::getOrderDate) + .list(); + + if (CollUtils.isEmpty(reservationSettingList)) { + return new ArrayList<>(); + } else { + return reservationSettingList.stream() + .map(item -> ReservationSettingResDTO.builder() + .date(item.getOrderDate().toString()) + .number(item.getNumber()) + .reservations(item.getReservations()) + .build()) + .collect(Collectors.toList()); + } + } + + @Override + public void editNumberByDate(ReservationSettingUpsertReqDTO reservationSettingUpsertReqDTO) { + LocalDate orderDate = reservationSettingUpsertReqDTO.getOrderDate(); + Integer number = reservationSettingUpsertReqDTO.getNumber(); + + Optional.ofNullable(lambdaQuery() + .eq(ReservationSetting::getOrderDate, orderDate) + .one()) + .ifPresentOrElse(reservationSetting -> { + // 存在则更新 + if (!lambdaUpdate() + .eq(ReservationSetting::getOrderDate, orderDate) + .set(ReservationSetting::getNumber, number) + .update()) { + throw new DBException("更新预约设置表失败"); + } + }, () -> { + // 不存在则创建 + if (!SqlHelper.retBool(baseMapper.insert(ReservationSetting + .builder() + .orderDate(orderDate) + .reservations(0) + .number(number) + .build()))) { + throw new DBException("插入预约设置表失败"); + } + }); + } + + @Override + @Transactional + public void editNumberByDateBatch(List reservationDataList) { + for (ReservationImportData reservationData : reservationDataList) { + this.editNumberByDate(ReservationSettingUpsertReqDTO.builder() + .orderDate(LocalDate.parse(reservationData.getDate())) + .number(Math.min(reservationData.getNumber(), 999)) + .build()); + } + } + + @Override + public ReservationDateResDTO getReservationDateByMonth(YearMonth yearMonth) { + List dates = baseMapper.getReservationDate(yearMonth.atDay(1), yearMonth.atEndOfMonth()); + return new ReservationDateResDTO(dates); + } } \ No newline at end of file From a0fa46f873f0252c23e391a9223f4e6fceff89b7 Mon Sep 17 00:00:00 2001 From: JIAN Date: Sat, 14 Sep 2024 23:18:58 +0800 Subject: [PATCH 15/21] =?UTF-8?q?feat(health):=E6=96=B0=E5=A2=9E=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E6=9F=A5=E8=AF=A2=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=201.=20=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=202.=20=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E8=AE=A2=E5=8D=95=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/OrdersQueryController.java | 12 +- .../user/OrdersQueryController.java | 16 ++- .../dto/response/AdminOrdersDetailResDTO.java | 6 +- .../health/service/IOrderCancelService.java | 11 ++ .../health/service/IOrderManagerService.java | 31 +++++ .../service/impl/OrderCancelServiceImpl.java | 15 ++ .../service/impl/OrderManagerServiceImpl.java | 129 ++++++++++++++++++ 7 files changed, 208 insertions(+), 12 deletions(-) create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCancelService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersQueryController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersQueryController.java index f9d7ef0..f2b6823 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersQueryController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersQueryController.java @@ -4,6 +4,7 @@ import com.jzo2o.common.model.PageResult; import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO; +import com.jzo2o.health.service.IOrderManagerService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -13,6 +14,8 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; + /** * @author itcast */ @@ -20,11 +23,13 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/admin/orders") @Api(tags = "管理端 - 订单查询接口") public class OrdersQueryController { + @Resource + private IOrderManagerService orderManagerService; @ApiOperation("分页查询") @GetMapping("/page") public PageResult pageQuery(OrdersPageQueryReqDTO ordersPageQueryReqDTO) { - return null; + return orderManagerService.pageQuery(ordersPageQueryReqDTO); } @GetMapping("/{id}") @@ -33,7 +38,6 @@ public class OrdersQueryController { @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) }) public AdminOrdersDetailResDTO aggregation(@PathVariable("id") Long id) { - return null; + return orderManagerService.getAggregationInfo(id); } - -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java index f6ef0e5..93a96a2 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java @@ -1,13 +1,16 @@ package com.jzo2o.health.controller.user; +import com.jzo2o.common.utils.BeanUtils; import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO; +import com.jzo2o.health.service.IOrderManagerService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; import java.util.List; /** @@ -17,16 +20,18 @@ import java.util.List; @RequestMapping("/user/orders") @Api(tags = "用户端 - 订单查询相关接口") public class OrdersQueryController { + @Resource + private IOrderManagerService orderManagerService; @ApiOperation("滚动分页查询") @GetMapping("/page") @ApiImplicitParams({ - @ApiImplicitParam(name = "ordersStatus", value = "订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消", required = false, dataTypeClass = Integer.class), - @ApiImplicitParam(name = "sortBy", value = "排序字段", required = false, dataTypeClass = Long.class) + @ApiImplicitParam(name = "ordersStatus", value = "订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消", dataTypeClass = Integer.class), + @ApiImplicitParam(name = "sortBy", value = "排序字段", dataTypeClass = Long.class) }) public List pageQuery(@RequestParam(value = "ordersStatus", required = false) Integer ordersStatus, @RequestParam(value = "sortBy", required = false) Long sortBy) { - return null; + return orderManagerService.pageQuery(ordersStatus, sortBy); } @GetMapping("/{id}") @@ -35,7 +40,6 @@ public class OrdersQueryController { @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) }) public OrdersDetailResDTO detail(@PathVariable("id") Long id) { - return null; + return BeanUtils.toBean(orderManagerService.getById(id), OrdersDetailResDTO.class); } - -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/AdminOrdersDetailResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/AdminOrdersDetailResDTO.java index 953fbad..6454a10 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/AdminOrdersDetailResDTO.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/AdminOrdersDetailResDTO.java @@ -3,6 +3,7 @@ package com.jzo2o.health.model.dto.response; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; import lombok.Data; import java.math.BigDecimal; @@ -11,7 +12,6 @@ import java.time.LocalDateTime; /** * 管理端订单详情 - * * @author itcast * @create 2023/11/6 17:31 **/ @@ -142,6 +142,7 @@ public class AdminOrdersDetailResDTO { } @Data + @Builder @ApiModel("退款信息模型") public static class RefundInfo { /** @@ -177,6 +178,7 @@ public class AdminOrdersDetailResDTO { } @Data + @Builder @ApiModel("订单取消模型") public static class CancelInfo { /** @@ -192,4 +194,4 @@ public class AdminOrdersDetailResDTO { @ApiModelProperty("取消理由") private String cancelReason; } -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCancelService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCancelService.java new file mode 100644 index 0000000..b44ca1b --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCancelService.java @@ -0,0 +1,11 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.OrdersCancelled; + +/** + * 取消订单相关业务层 + * @author JIAN + */ +public interface IOrderCancelService extends IService { +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java new file mode 100644 index 0000000..ee1ced9 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java @@ -0,0 +1,31 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.common.model.PageResult; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; +import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; +import com.jzo2o.health.model.dto.response.OrdersResDTO; + +import java.util.List; + +/** + * 订单管理相关业务层 + * @author JIAN + */ +public interface IOrderManagerService extends IService { + /** + * 管理端订单分页查询 + */ + PageResult pageQuery(OrdersPageQueryReqDTO ordersPageQueryReqDTO); + + /** + * 用户端订单分页查询 + */ + List pageQuery(Integer orderStatus, Long sortBy); + + /** + * 管理端查询订单详情 + */ + AdminOrdersDetailResDTO getAggregationInfo(Long id); +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java new file mode 100644 index 0000000..620adcc --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java @@ -0,0 +1,15 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.health.mapper.OrdersCancelledMapper; +import com.jzo2o.health.model.domain.OrdersCancelled; +import com.jzo2o.health.service.IOrderCancelService; +import org.springframework.stereotype.Service; + +/** + * 取消订单相关业务层实现 + * @author JIAN + */ +@Service +public class OrderCancelServiceImpl extends ServiceImpl implements IOrderCancelService { +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java new file mode 100644 index 0000000..ecfbc71 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java @@ -0,0 +1,129 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.common.expcetions.ForbiddenOperationException; +import com.jzo2o.common.model.PageResult; +import com.jzo2o.common.utils.BeanUtils; +import com.jzo2o.common.utils.CollUtils; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; +import com.jzo2o.health.mapper.OrdersMapper; +import com.jzo2o.health.model.UserThreadLocal; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.model.domain.OrdersCancelled; +import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; +import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; +import com.jzo2o.health.model.dto.response.OrdersResDTO; +import com.jzo2o.health.service.IOrderCancelService; +import com.jzo2o.health.service.IOrderManagerService; +import com.jzo2o.mysql.utils.PageUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 订单管理相关业务层实现 + * @author JIAN + */ +@Service +public class OrderManagerServiceImpl extends ServiceImpl implements IOrderManagerService { + @Resource + private IOrderCancelService orderCancelService; + + @Override + public PageResult pageQuery(OrdersPageQueryReqDTO ordersPageQueryReqDTO) { + Page ordersPage = PageUtils.parsePageQuery(ordersPageQueryReqDTO, Orders.class); + + Integer orderStatus = ordersPageQueryReqDTO.getOrderStatus(); + String memberPhone = ordersPageQueryReqDTO.getMemberPhone(); + + Page page = lambdaQuery() + .eq(ObjectUtils.isNotEmpty(orderStatus), Orders::getOrderStatus, orderStatus) + .like(ObjectUtils.isNotEmpty(memberPhone), Orders::getMemberPhone, memberPhone) + .page(ordersPage); + + return PageUtils.toPage(page, OrdersResDTO.class); + } + + @Override + public List pageQuery(Integer orderStatus, Long sortBy) { + Long userId = UserThreadLocal.currentUserId(); + if (ObjectUtils.isEmpty(userId)) { + throw new ForbiddenOperationException("无法获取当前用户"); + } + + // 默认每页10条数据 + List ordersList = lambdaQuery() + .eq(Orders::getMemberId, userId) + .eq(ObjectUtils.isNotEmpty(orderStatus), Orders::getOrderStatus, orderStatus) + .lt(ObjectUtils.isNotEmpty(sortBy), Orders::getSortBy, sortBy) + .last("LIMIT 10") + .list(); + + if (CollUtils.isEmpty(ordersList)) { + return new ArrayList<>(); + } else { + return ordersList.stream() + .map(order -> BeanUtils.toBean(order, OrdersResDTO.class)) + .collect(Collectors.toList()); + } + } + + @Override + public AdminOrdersDetailResDTO getAggregationInfo(Long id) { + AdminOrdersDetailResDTO adminOrdersDetailResDTO = new AdminOrdersDetailResDTO(); + + Orders orders = baseMapper.selectById(id); + if (ObjectUtils.isEmpty(orders)) { + return adminOrdersDetailResDTO; + } + + // 订单信息 + adminOrdersDetailResDTO.setOrderInfo( + BeanUtils.toBean(orders, AdminOrdersDetailResDTO.OrderInfo.class)); + + // 支付信息 + AdminOrdersDetailResDTO.PayInfo payInfo = BeanUtils.toBean(orders, AdminOrdersDetailResDTO.PayInfo.class); + payInfo.setThirdOrderId(orders.getTransactionId()); + adminOrdersDetailResDTO.setPayInfo(payInfo); + + Integer orderStatus = orders.getOrderStatus(); + if (OrderStatusEnum.CANCELLED.getStatus().equals(orderStatus)) { + OrdersCancelled cancelInfo = orderCancelService.getById(orders.getId()); + + // 取消信息 + adminOrdersDetailResDTO.setCancelInfo(AdminOrdersDetailResDTO.CancelInfo.builder() + .cancelReason(cancelInfo.getCancelReason()) + .cancelTime(cancelInfo.getCancelTime()) + .build()); + + // 退款信息 + adminOrdersDetailResDTO.setRefundInfo(AdminOrdersDetailResDTO.RefundInfo.builder() + .refundStatus(payInfo.getPayStatus()) + .cancelTime(cancelInfo.getCancelTime()) + .cancelReason(cancelInfo.getCancelReason()) + .tradingChannel(orders.getTradingChannel()) + .refundId(orders.getRefundId()) + .build()); + + payInfo.setPayStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus()); + } else if (OrderStatusEnum.CLOSED.getStatus().equals(orderStatus)) { + OrdersCancelled cancelInfo = orderCancelService.getById(orders.getId()); + + // 取消信息 + adminOrdersDetailResDTO.setCancelInfo(AdminOrdersDetailResDTO.CancelInfo.builder() + .cancelReason(cancelInfo.getCancelReason()) + .cancelTime(cancelInfo.getCancelTime()) + .build()); + + payInfo.setPayStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus()); + } + + return adminOrdersDetailResDTO; + } +} \ No newline at end of file From 79b7dbcadd2cf4eba266cdca99b885d5f1e8d3d5 Mon Sep 17 00:00:00 2001 From: JIAN Date: Mon, 16 Sep 2024 13:13:37 +0800 Subject: [PATCH 16/21] =?UTF-8?q?feat(health):=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E4=B8=8B=E5=8D=95=E5=8F=8A=E6=94=AF=E4=BB=98=E7=9A=84?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jzo2o/health/constant/RedisConstants.java | 9 +- .../controller/user/OrdersController.java | 11 +- .../health/enums/OrderPayStatusEnum.java | 6 +- .../jzo2o/health/enums/OrderStatusEnum.java | 6 +- .../health/model/OrderUpdateStatusDTO.java | 70 ++++++ .../com/jzo2o/health/model/domain/Orders.java | 14 +- .../jzo2o/health/model/domain/Setmeal.java | 12 +- .../model/dto/response/OrdersResDTO.java | 10 +- .../health/service/IOrderCreateService.java | 35 +++ .../health/service/IOrdersCommonService.java | 20 ++ .../service/impl/OrderCreateServiceImpl.java | 210 ++++++++++++++++++ .../service/impl/OrderManagerServiceImpl.java | 6 +- .../service/impl/OrdersCommonServiceImpl.java | 36 +++ 13 files changed, 418 insertions(+), 27 deletions(-) create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/model/OrderUpdateStatusDTO.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCreateService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/IOrdersCommonService.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrdersCommonServiceImpl.java diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/constant/RedisConstants.java b/jzo2o-health/src/main/java/com/jzo2o/health/constant/RedisConstants.java index ab0d4fb..39a7da1 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/constant/RedisConstants.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/constant/RedisConstants.java @@ -10,5 +10,10 @@ public class RedisConstants { /** * 用户端订单滚动分页查询 */ - public static final String ORDER_PAGE_QUERY = "ORDERS:PAGE_QUERY:PAGE_%s"; -} + public static final String ORDER_PAGE_QUERY = "HEALTH:ORDERS:PAGE_QUERY:PAGE_%s"; + + /** + * 用户端下单订单号生成器 + */ + public static final String ORDER_ID_GENERATOR = "HEALTH:ORDERS:GENERATOR"; +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersController.java index 0c9a0c3..3a724be 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersController.java @@ -4,6 +4,7 @@ import com.jzo2o.api.trade.enums.PayChannelEnum; import com.jzo2o.health.model.dto.request.PlaceOrderReqDTO; import com.jzo2o.health.model.dto.response.OrdersPayResDTO; import com.jzo2o.health.model.dto.response.PlaceOrderResDTO; +import com.jzo2o.health.service.IOrderCreateService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -19,11 +20,13 @@ import javax.annotation.Resource; @RequestMapping("/user/orders") @Api(tags = "用户端 - 下单支付相关接口") public class OrdersController { + @Resource + private IOrderCreateService orderCreateService; @ApiOperation("下单接口") @PostMapping("/place") public PlaceOrderResDTO place(@RequestBody PlaceOrderReqDTO placeOrderReqDTO) { - return null; + return orderCreateService.placeOrder(placeOrderReqDTO); } @PutMapping("/pay/{id}") @@ -33,7 +36,7 @@ public class OrdersController { @ApiImplicitParam(name = "tradingChannel", value = "支付渠道:ALI_PAY、WECHAT_PAY", required = true, dataTypeClass = PayChannelEnum.class), }) public OrdersPayResDTO pay(@PathVariable("id") Long id, @RequestParam("tradingChannel") PayChannelEnum tradingChannel) { - return null; + return orderCreateService.payOrder(id, tradingChannel); } @GetMapping("/pay/{id}/result") @@ -42,6 +45,6 @@ public class OrdersController { @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) }) public OrdersPayResDTO payResult(@PathVariable("id") Long id) { - return null; + return orderCreateService.getPayResult(id); } -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderPayStatusEnum.java b/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderPayStatusEnum.java index 55b4a1a..d4e71f1 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderPayStatusEnum.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderPayStatusEnum.java @@ -1,5 +1,7 @@ package com.jzo2o.health.enums; +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; @@ -16,6 +18,8 @@ public enum OrderPayStatusEnum { REFUND_SUCCESS(3, "退款成功"), REFUND_FAIL(4, "退款失败"); + @EnumValue + @JsonValue private final Integer status; private final String desc; -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderStatusEnum.java b/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderStatusEnum.java index f44ac6e..f27c870 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderStatusEnum.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/enums/OrderStatusEnum.java @@ -1,5 +1,7 @@ package com.jzo2o.health.enums; +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; @@ -15,6 +17,8 @@ public enum OrderStatusEnum { CLOSED(300, "已关闭"), CANCELLED(400, "已取消"); + @EnumValue + @JsonValue private final Integer status; private final String desc; @@ -32,4 +36,4 @@ public enum OrderStatusEnum { } return null; } -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/OrderUpdateStatusDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/OrderUpdateStatusDTO.java new file mode 100644 index 0000000..bfabec5 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/OrderUpdateStatusDTO.java @@ -0,0 +1,70 @@ +package com.jzo2o.health.model; + +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * 通用订单更新DTO + * @author JIAN + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrderUpdateStatusDTO { + /** + * 订单id + */ + private Long id; + + /** + * 原订单状态 + */ + private OrderStatusEnum originStatus; + + /** + * 目标订单状态 + */ + private OrderStatusEnum targetStatus; + + /** + * 支付状态 + */ + private OrderPayStatusEnum payStatus; + + /** + * 支付时间 + */ + private LocalDateTime payTime; + + /** + * 支付服务交易单号 + */ + private Long tradingOrderNo; + + /** + * 第三方支付的交易号 + */ + private String transactionId; + + /** + * 支付服务退款单号 + */ + private Long refundNo; + + /** + * 第三方支付的退款单号 + */ + private String refundId; + + /** + * 支付渠道 + */ + private String tradingChannel; +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Orders.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Orders.java index ac6e61b..c129acd 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Orders.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Orders.java @@ -4,6 +4,9 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; +import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; @@ -22,6 +25,7 @@ import java.time.LocalDateTime; * @since 2023-11-02 */ @Data +@Builder @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("orders") @@ -32,18 +36,18 @@ public class Orders implements Serializable { /** * 订单id */ - @TableId(value = "id", type = IdType.ASSIGN_ID) + @TableId(value = "id", type = IdType.NONE) private Long id; /** * 订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消 */ - private Integer orderStatus; + private OrderStatusEnum orderStatus; /** * 支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败 */ - private Integer payStatus; + private OrderPayStatusEnum payStatus; /** * 套餐id @@ -160,6 +164,4 @@ public class Orders implements Serializable { * 更新时间 */ private LocalDateTime updateTime; - - -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Setmeal.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Setmeal.java index c565d5f..12582d7 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Setmeal.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/Setmeal.java @@ -1,16 +1,18 @@ package com.jzo2o.health.model.domain; -import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; -import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.math.BigDecimal; + /** *

- * + * *

* * @author itcast @@ -55,7 +57,7 @@ public class Setmeal implements Serializable { /** * 套餐价格 */ - private Float price; + private BigDecimal price; /** * 套餐说明 @@ -73,4 +75,4 @@ public class Setmeal implements Serializable { private String img; -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersResDTO.java index 93d6928..a629c91 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersResDTO.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersResDTO.java @@ -1,6 +1,8 @@ package com.jzo2o.health.model.dto.response; import com.fasterxml.jackson.annotation.JsonFormat; +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -11,7 +13,6 @@ import java.time.LocalDateTime; /** * 订单响应 - * * @author itcast * @create 2023/11/3 19:17 **/ @@ -28,14 +29,13 @@ public class OrdersResDTO { * 订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消 */ @ApiModelProperty("订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消") - private Integer orderStatus; + private OrderStatusEnum orderStatus; /** * 支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败 */ @ApiModelProperty("支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败") - private Integer payStatus; - + private OrderPayStatusEnum payStatus; /** * 套餐id @@ -123,4 +123,4 @@ public class OrdersResDTO { @ApiModelProperty("更新时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updateTime; -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCreateService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCreateService.java new file mode 100644 index 0000000..4fec073 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCreateService.java @@ -0,0 +1,35 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.health.model.dto.response.OrdersPayResDTO; +import com.jzo2o.health.model.dto.response.PlaceOrderResDTO; + +/** + * 订单创建相关业务层 + * @author JIAN + */ +public interface IOrderCreateService extends IService { + /** + * 微服务标识 + */ + String PRODUCT_APP_ID = "health.orders"; + + /** + * 用户下单 + */ + PlaceOrderResDTO placeOrder(PlaceOrderReqDTO placeOrderReqDTO); + + /** + * 用户支付(返回支付二维码) + * @param id 本系统的订单id + */ + OrdersPayResDTO payOrder(Long id, PayChannelEnum tradingChannel); + + /** + * 获取指定订单的支付结果 + */ + OrdersPayResDTO getPayResult(Long id); +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrdersCommonService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrdersCommonService.java new file mode 100644 index 0000000..3f6ddeb --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrdersCommonService.java @@ -0,0 +1,20 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.OrderUpdateStatusDTO; +import com.jzo2o.health.model.domain.Orders; + +/** + *

+ * 订单表 服务类 + *

+ * + * @author itcast + * @since 2023-08-02 + */ +public interface IOrdersCommonService extends IService { + /** + * 更新指定id订单的状态 + */ + Boolean updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO); +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java new file mode 100644 index 0000000..d17d038 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java @@ -0,0 +1,210 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.jzo2o.api.trade.NativePayApi; +import com.jzo2o.api.trade.TradingApi; +import com.jzo2o.api.trade.dto.request.NativePayReqDTO; +import com.jzo2o.api.trade.dto.response.NativePayResDTO; +import com.jzo2o.api.trade.dto.response.TradingResDTO; +import com.jzo2o.api.trade.enums.PayChannelEnum; +import com.jzo2o.api.trade.enums.TradingStateEnum; +import com.jzo2o.common.expcetions.CommonException; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.expcetions.ForbiddenOperationException; +import com.jzo2o.common.expcetions.ServerErrorException; +import com.jzo2o.common.utils.BeanUtils; +import com.jzo2o.common.utils.DateUtils; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.health.constant.RedisConstants; +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; +import com.jzo2o.health.mapper.OrdersMapper; +import com.jzo2o.health.model.OrderUpdateStatusDTO; +import com.jzo2o.health.model.UserThreadLocal; +import com.jzo2o.health.model.domain.Member; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.model.domain.Setmeal; +import com.jzo2o.health.model.dto.request.PlaceOrderReqDTO; +import com.jzo2o.health.model.dto.response.OrdersPayResDTO; +import com.jzo2o.health.model.dto.response.PlaceOrderResDTO; +import com.jzo2o.health.properties.TradeProperties; +import com.jzo2o.health.service.IMemberService; +import com.jzo2o.health.service.IOrderCreateService; +import com.jzo2o.health.service.IOrdersCommonService; +import com.jzo2o.health.service.ISetmealService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 订单创建相关业务层 + * @author JIAN + */ +@Slf4j +@Service +public class OrderCreateServiceImpl extends ServiceImpl implements IOrderCreateService { + @Resource + private IMemberService memberService; + @Resource + private ISetmealService setmealService; + @Resource + private IOrdersCommonService ordersCommonService; + @Resource + private TradingApi tradingApi; + @Resource + private NativePayApi nativePayApi; + @Resource + private TradeProperties tradeProperties; + @Resource + private RedisTemplate redisTemplate; + + /** + * 生成订单号(2位年+2位月+2位日+13位序号) + */ + private Long generateOrderId() { + Long idNo = redisTemplate.opsForValue().increment(RedisConstants.ORDER_ID_GENERATOR, 1); + String orderId = DateUtils.format(LocalDateTime.now(), "yyMMdd") + String.format("%013d", idNo); + return Long.valueOf(orderId); + } + + @Override + public PlaceOrderResDTO placeOrder(PlaceOrderReqDTO placeOrderReqDTO) { + Long currentUserId = UserThreadLocal.currentUserId(); + if (ObjectUtils.isEmpty(currentUserId)) { + throw new ForbiddenOperationException("用户信息不存在无法下单"); + } + + Member member = memberService.getById(currentUserId); + if (ObjectUtils.isEmpty(member)) { + throw new ForbiddenOperationException("用户信息不存在无法下单"); + } + + Setmeal setmeal = setmealService.getById(placeOrderReqDTO.getSetmealId()); + if (ObjectUtils.isEmpty(setmeal)) { + throw new ForbiddenOperationException("套餐信息不存在无法下单"); + } + + // 生成订单id + Long orderId = this.generateOrderId(); + if (ObjectUtils.isEmpty(orderId)) { + throw new ServerErrorException("生成订单id失败无法下单"); + } + + if (!SqlHelper.retBool(baseMapper.insert(Orders.builder() + .id(orderId) + .orderStatus(OrderStatusEnum.NO_PAY) + .payStatus(OrderPayStatusEnum.NO_PAY) + .setmealId(setmeal.getId()) + .setmealName(setmeal.getName()) + .setmealPrice(setmeal.getPrice()) + .setmealSex(setmeal.getSex()) + .setmealAge(setmeal.getAge()) + .setmealImg(setmeal.getImg()) + .setmealRemark(setmeal.getRemark()) + .reservationDate(placeOrderReqDTO.getReservationDate()) + .checkupPersonName(placeOrderReqDTO.getCheckupPersonName()) + .checkupPersonSex(placeOrderReqDTO.getCheckupPersonSex()) + .checkupPersonPhone(placeOrderReqDTO.getCheckupPersonPhone()) + .checkupPersonIdcard(placeOrderReqDTO.getCheckupPersonIdcard()) + .memberId(member.getId()) + .memberPhone(member.getPhone()) + .sortBy(DateUtils.toEpochMilli(LocalDateTime.now())) + .build()))) { + throw new DBException("订单表插入失败下单失败"); + } + + return new PlaceOrderResDTO(orderId); + } + + @Override + public OrdersPayResDTO payOrder(Long id, PayChannelEnum tradingChannel) { + Orders orderInfo = baseMapper.selectById(id); + if (ObjectUtils.isEmpty(orderInfo)) { + throw new ForbiddenOperationException("订单不存在无法支付"); + } + + // 初步防止重复发起支付请求 + if (orderInfo.getPayStatus() == OrderPayStatusEnum.PAY_SUCCESS) { + OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(orderInfo, OrdersPayResDTO.class); + ordersPayResDTO.setProductOrderNo(id); + return ordersPayResDTO; + } + + // 下单 + String tradingChannelOld = orderInfo.getTradingChannel(); + NativePayResDTO nativePayResDTO = nativePayApi.createDownLineTrading(NativePayReqDTO.builder() + .productOrderNo(id) + .productAppId(IOrderCreateService.PRODUCT_APP_ID) + .tradingChannel(tradingChannel) + .tradingAmount(/*orderInfo.getSetmealPrice()*/ new BigDecimal("0.01")) + .memo(orderInfo.getSetmealName()) + .changeChannel(ObjectUtils.isNotEmpty(tradingChannelOld) + && !tradingChannelOld.equals(tradingChannel.name())) + .enterpriseId(tradingChannel == PayChannelEnum.WECHAT_PAY + ? tradeProperties.getWechatEnterpriseId() + : tradeProperties.getAliEnterpriseId()) + .build()); + + if (!lambdaUpdate() + .eq(Orders::getId, id) + .set(Orders::getTradingOrderNo, nativePayResDTO.getTradingOrderNo()) + .set(Orders::getTradingChannel, nativePayResDTO.getTradingChannel()) + .update()) { + log.warn("订单表更新失败(已正常生成支付二维码), 订单id: {}", id); + } + + OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(nativePayResDTO, OrdersPayResDTO.class); + ordersPayResDTO.setPayStatus(OrderPayStatusEnum.NO_PAY.getStatus()); + return ordersPayResDTO; + } + + @Override + public OrdersPayResDTO getPayResult(Long id) { + Orders orders = baseMapper.selectById(id); + if (ObjectUtils.isEmpty(orders)) { + throw new CommonException("订单不存在"); + } + + // 公共返回参数 + OrdersPayResDTO ordersPayResDTO = BeanUtils.toBean(orders, OrdersPayResDTO.class); + ordersPayResDTO.setProductOrderNo(id); + + // 未支付订单更新状态 + Long tradingOrderNo = orders.getTradingOrderNo(); + if (ObjectUtils.isNotEmpty(tradingOrderNo) + && orders.getPayStatus() == OrderPayStatusEnum.NO_PAY) { + TradingResDTO tradingResDTO = tradingApi.findTradResultByTradingOrderNo(tradingOrderNo); + + // 支付成功 + if (ObjectUtils.isNotEmpty(tradingResDTO) + && tradingResDTO.getTradingState() == TradingStateEnum.YJS) { + + if (!ordersCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(id) + .originStatus(OrderStatusEnum.NO_PAY) + .targetStatus(OrderStatusEnum.WAITING_CHECKUP) + .payStatus(OrderPayStatusEnum.PAY_SUCCESS) + .tradingOrderNo(tradingResDTO.getTradingOrderNo()) + .transactionId(tradingResDTO.getTransactionId()) + .tradingChannel(tradingResDTO.getTradingChannel()) + .payTime(LocalDateTime.now()) + .build())) { + throw new DBException("订单表更新失败"); + } + + // 支付成功更新最终响应信息的状态 + ordersPayResDTO.setPayStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus()); + } else { + // 未支付成功返回二维码 + ordersPayResDTO.setQrCode(tradingResDTO.getQrCode()); + } + } + + return ordersPayResDTO; + } +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java index ecfbc71..0fb2f68 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java @@ -92,8 +92,8 @@ public class OrderManagerServiceImpl extends ServiceImpl i payInfo.setThirdOrderId(orders.getTransactionId()); adminOrdersDetailResDTO.setPayInfo(payInfo); - Integer orderStatus = orders.getOrderStatus(); - if (OrderStatusEnum.CANCELLED.getStatus().equals(orderStatus)) { + OrderStatusEnum orderStatus = orders.getOrderStatus(); + if (OrderStatusEnum.CANCELLED == orderStatus) { OrdersCancelled cancelInfo = orderCancelService.getById(orders.getId()); // 取消信息 @@ -112,7 +112,7 @@ public class OrderManagerServiceImpl extends ServiceImpl i .build()); payInfo.setPayStatus(OrderPayStatusEnum.PAY_SUCCESS.getStatus()); - } else if (OrderStatusEnum.CLOSED.getStatus().equals(orderStatus)) { + } else if (OrderStatusEnum.CLOSED == orderStatus) { OrdersCancelled cancelInfo = orderCancelService.getById(orders.getId()); // 取消信息 diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrdersCommonServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrdersCommonServiceImpl.java new file mode 100644 index 0000000..3505d4a --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrdersCommonServiceImpl.java @@ -0,0 +1,36 @@ +package com.jzo2o.health.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.health.mapper.OrdersMapper; +import com.jzo2o.health.model.OrderUpdateStatusDTO; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.service.IOrdersCommonService; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单表 服务实现类 + *

+ * @author itcast + * @since 2023-08-02 + */ +@Service +public class OrdersCommonServiceImpl extends ServiceImpl implements IOrdersCommonService { + @Override + public Boolean updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO) { + return lambdaUpdate() + .eq(Orders::getId, orderUpdateStatusReqDTO.getId()) + .gt(Orders::getMemberId, 0) + .eq(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getOriginStatus()), Orders::getOrderStatus, orderUpdateStatusReqDTO.getOriginStatus()) + .set(Orders::getOrderStatus, orderUpdateStatusReqDTO.getTargetStatus()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getPayStatus()), Orders::getPayStatus, orderUpdateStatusReqDTO.getPayStatus()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getPayTime()), Orders::getPayTime, orderUpdateStatusReqDTO.getPayTime()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingOrderNo()), Orders::getTradingOrderNo, orderUpdateStatusReqDTO.getTradingOrderNo()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTransactionId()), Orders::getTransactionId, orderUpdateStatusReqDTO.getTransactionId()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getTradingChannel()), Orders::getTradingChannel, orderUpdateStatusReqDTO.getTradingChannel()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getRefundNo()), Orders::getRefundNo, orderUpdateStatusReqDTO.getRefundNo()) + .set(ObjectUtil.isNotNull(orderUpdateStatusReqDTO.getRefundId()), Orders::getRefundId, orderUpdateStatusReqDTO.getRefundId()) + .update(); + } +} \ No newline at end of file From a48fae5d305f8a144975cd8b76c9dd704eac3fae Mon Sep 17 00:00:00 2001 From: JIAN Date: Mon, 16 Sep 2024 22:31:32 +0800 Subject: [PATCH 17/21] =?UTF-8?q?feat(health):=E6=96=B0=E5=A2=9EMQ?= =?UTF-8?q?=E6=8E=A5=E6=94=B6=E6=94=AF=E4=BB=98=E6=88=90=E5=8A=9F=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../health/listener/OrderStatusListener.java | 79 +++++++++++++++++++ .../health/listener/TradeStatusListener.java | 37 --------- 2 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java delete mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/listener/TradeStatusListener.java diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java b/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java new file mode 100644 index 0000000..4a847d3 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java @@ -0,0 +1,79 @@ +package com.jzo2o.health.listener; + +import com.jzo2o.api.trade.enums.TradingStateEnum; +import com.jzo2o.common.constants.MqConstants; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.model.msg.TradeStatusMsg; +import com.jzo2o.common.utils.CollUtils; +import com.jzo2o.common.utils.JsonUtils; +import com.jzo2o.health.constant.TradeConstants; +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; +import com.jzo2o.health.model.OrderUpdateStatusDTO; +import com.jzo2o.health.service.IOrderCommonService; +import com.jzo2o.health.service.IOrderCreateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.ExchangeTypes; +import org.springframework.amqp.rabbit.annotation.Exchange; +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.QueueBinding; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 监听MQ消息 + * @author itcast + **/ +@Slf4j +@Component +public class OrderStatusListener { + @Resource + private IOrderCommonService orderCommonService; + @Resource + private TransactionTemplate transactionTemplate; + + /** + * 接收支付成功信息 + * @param msg 消息 + */ + @RabbitListener(bindings = @QueueBinding( + value = @Queue(name = TradeConstants.MQ_TRADE_QUEUE), + exchange = @Exchange(name = MqConstants.Exchanges.TRADE, type = ExchangeTypes.TOPIC), + key = MqConstants.RoutingKeys.TRADE_UPDATE_STATUS)) + public void listenTradeUpdatePayStatusMsg(String msg) { + log.info("接收到支付结果状态的消息 ({})-> {}", MqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS, msg); + + List msgList = JsonUtils.parseArray(msg).toList(TradeStatusMsg.class); + if (CollUtils.isEmpty(msgList)) { + return; + } + + // 处理当前微服务并且支付成功的订单 + List tradeStatusMsgList = msgList.stream() + .filter(statusMsg -> IOrderCreateService.PRODUCT_APP_ID.equals(statusMsg.getProductAppId()) + && TradingStateEnum.YJS.getCode().equals(statusMsg.getStatusCode())) + .collect(Collectors.toList()); + + transactionTemplate.executeWithoutResult(status -> { + for (TradeStatusMsg tradeStatusMsg : tradeStatusMsgList) { + if (!orderCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(tradeStatusMsg.getProductOrderNo()) + .originStatus(OrderStatusEnum.NO_PAY) + .targetStatus(OrderStatusEnum.WAITING_CHECKUP) + .payStatus(OrderPayStatusEnum.PAY_SUCCESS) + .tradingOrderNo(tradeStatusMsg.getTradingOrderNo()) + .transactionId(tradeStatusMsg.getTransactionId()) + .tradingChannel(tradeStatusMsg.getTradingChannel()) + .payTime(LocalDateTime.now()).build())) { + throw new DBException("更新订单状态失败"); + } + } + }); + } +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/listener/TradeStatusListener.java b/jzo2o-health/src/main/java/com/jzo2o/health/listener/TradeStatusListener.java deleted file mode 100644 index b858ec6..0000000 --- a/jzo2o-health/src/main/java/com/jzo2o/health/listener/TradeStatusListener.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.jzo2o.health.listener; - -import com.jzo2o.common.constants.MqConstants; -import com.jzo2o.health.constant.TradeConstants; -import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.core.ExchangeTypes; -import org.springframework.amqp.rabbit.annotation.Exchange; -import org.springframework.amqp.rabbit.annotation.Queue; -import org.springframework.amqp.rabbit.annotation.QueueBinding; -import org.springframework.amqp.rabbit.annotation.RabbitListener; -import org.springframework.stereotype.Component; - -/** - * 监听mq消息,接收支付结果 - * - * @author itcast - **/ -@Slf4j -@Component -public class TradeStatusListener { - - /** - * 更新支付结果 - * 支付成功 - * - * @param msg 消息 - */ - @RabbitListener(bindings = @QueueBinding( - value = @Queue(name = TradeConstants.MQ_TRADE_QUEUE), - exchange = @Exchange(name = MqConstants.Exchanges.TRADE, type = ExchangeTypes.TOPIC), - key = MqConstants.RoutingKeys.TRADE_UPDATE_STATUS - )) - public void listenTradeUpdatePayStatusMsg(String msg) { - log.info("接收到支付结果状态的消息 ({})-> {}", MqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS, msg); - - } -} From db85c197a86e8e5a53377286893a10d527599b4d Mon Sep 17 00:00:00 2001 From: JIAN Date: Mon, 16 Sep 2024 22:35:23 +0800 Subject: [PATCH 18/21] =?UTF-8?q?feat(health):=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=8F=96=E6=B6=88/=E9=80=80=E6=AC=BE=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tionMapper.xml => IOrderCommonService.xml} | 0 .../user/OrdersQueryController.java | 3 +- .../user/OrdersRefundController.java | 12 +- .../jzo2o/health/handler/OrdersHandler.java | 58 ------- .../com/jzo2o/health/job/OrderRefundJob.java | 40 +++++ .../health/model/domain/OrdersCancelled.java | 16 +- .../health/model/domain/OrdersRefund.java | 18 +-- .../dto/response/OrdersDetailResDTO.java | 8 +- .../health/service/IOrderCancelService.java | 10 ++ ...nService.java => IOrderCommonService.java} | 2 +- .../health/service/IOrderManagerService.java | 6 + .../health/service/IOrderRefundService.java | 29 ++++ .../service/impl/OrderCancelServiceImpl.java | 64 ++++++++ ...eImpl.java => OrderCommonServiceImpl.java} | 4 +- .../service/impl/OrderCreateServiceImpl.java | 4 +- .../service/impl/OrderManagerServiceImpl.java | 36 +++++ .../service/impl/OrderRefundServiceImpl.java | 141 ++++++++++++++++++ 17 files changed, 365 insertions(+), 86 deletions(-) rename jzo2o-customer/src/main/resources/mapper/{WorkerCertificationMapper.xml => IOrderCommonService.xml} (100%) delete mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/handler/OrdersHandler.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/job/OrderRefundJob.java rename jzo2o-health/src/main/java/com/jzo2o/health/service/{IOrdersCommonService.java => IOrderCommonService.java} (86%) create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderRefundService.java rename jzo2o-health/src/main/java/com/jzo2o/health/service/impl/{OrdersCommonServiceImpl.java => OrderCommonServiceImpl.java} (92%) create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderRefundServiceImpl.java diff --git a/jzo2o-customer/src/main/resources/mapper/WorkerCertificationMapper.xml b/jzo2o-customer/src/main/resources/mapper/IOrderCommonService.xml similarity index 100% rename from jzo2o-customer/src/main/resources/mapper/WorkerCertificationMapper.xml rename to jzo2o-customer/src/main/resources/mapper/IOrderCommonService.xml diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java index 93a96a2..ee35ab4 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersQueryController.java @@ -1,6 +1,5 @@ package com.jzo2o.health.controller.user; -import com.jzo2o.common.utils.BeanUtils; import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO; import com.jzo2o.health.service.IOrderManagerService; @@ -40,6 +39,6 @@ public class OrdersQueryController { @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) }) public OrdersDetailResDTO detail(@PathVariable("id") Long id) { - return BeanUtils.toBean(orderManagerService.getById(id), OrdersDetailResDTO.class); + return orderManagerService.getOrderById(id); } } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersRefundController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersRefundController.java index a853378..721dc46 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersRefundController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/user/OrdersRefundController.java @@ -1,6 +1,8 @@ package com.jzo2o.health.controller.user; import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; +import com.jzo2o.health.service.IOrderCancelService; +import com.jzo2o.health.service.IOrderRefundService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.PutMapping; @@ -8,6 +10,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; + /** * @author itcast */ @@ -15,14 +19,20 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/user/orders") @Api(tags = "用户端 - 取消订单退款相关接口") public class OrdersRefundController { + @Resource + private IOrderCancelService orderCancelService; + @Resource + private IOrderRefundService orderRefundService; @PutMapping("/cancel") @ApiOperation("订单取消") public void cancel(@RequestBody OrdersCancelReqDTO ordersCancelReqDTO) { + orderCancelService.cancelOrder(ordersCancelReqDTO); } @PutMapping("/refund") @ApiOperation("订单退款") public void refund(@RequestBody OrdersCancelReqDTO ordersCancelReqDTO) { + orderRefundService.refundOrder(ordersCancelReqDTO); } -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/handler/OrdersHandler.java b/jzo2o-health/src/main/java/com/jzo2o/health/handler/OrdersHandler.java deleted file mode 100644 index fdd2366..0000000 --- a/jzo2o-health/src/main/java/com/jzo2o/health/handler/OrdersHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.jzo2o.health.handler; - -import com.jzo2o.api.trade.RefundRecordApi; -import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO; -import com.jzo2o.health.properties.OrdersJobProperties; -import com.xxl.job.core.handler.annotation.XxlJob; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.Resource; - -/** - * 订单相关定时任务 - * - * @author itcast - * @create 2023/9/2 16:44 - **/ -@Slf4j -@Component -public class OrdersHandler { - - @Resource - private RefundRecordApi refundRecordApi; - //解决同级方法调用,事务失效问题 - @Resource - private OrdersHandler orderHandler; - @Resource - private OrdersJobProperties ordersJobProperties; - - /** - * 支付超时取消订单 - * 每分钟执行一次 - */ - @XxlJob(value = "cancelOverTimePayOrder") - public void cancelOverTimePayOrder() { - - } - - /** - * 订单退款异步任务 - */ - @XxlJob(value = "handleRefundOrders") - public void handleRefundOrders() { - - } - - /** - * 订单退款处理 - * - * @param id 订单id - * @param executionResultResDTO 第三方退款信息 - */ - @Transactional(rollbackFor = Exception.class) - public void refundOrder(Long id, ExecutionResultResDTO executionResultResDTO) { - - } -} diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/job/OrderRefundJob.java b/jzo2o-health/src/main/java/com/jzo2o/health/job/OrderRefundJob.java new file mode 100644 index 0000000..607e722 --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/job/OrderRefundJob.java @@ -0,0 +1,40 @@ +package com.jzo2o.health.job; + + +import com.jzo2o.common.utils.CollUtils; +import com.jzo2o.health.model.domain.OrdersRefund; +import com.jzo2o.health.properties.OrdersJobProperties; +import com.jzo2o.health.service.IOrderRefundService; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 订单退款任务 + * @author JIAN + */ +@Slf4j +@Component +@SuppressWarnings("unused") +public class OrderRefundJob { + @Resource + private IOrderRefundService orderRefundService; + @Resource + private OrdersJobProperties ordersJobProperties; + + /** + * 订单退款异步任务 + */ + @XxlJob(value = "handleRefundOrders") + public void handleRefundOrders() { + List latestRefundInfo = orderRefundService.getLatestRefundInfo(ordersJobProperties.getRefundOrderCount()); + if (CollUtils.isEmpty(latestRefundInfo)) { + log.info("没有需要退款的订单"); + } + + latestRefundInfo.forEach(refundInfo -> orderRefundService.refundOrder(refundInfo)); + } +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersCancelled.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersCancelled.java index d0a1cdc..fb2cd53 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersCancelled.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersCancelled.java @@ -1,23 +1,25 @@ package com.jzo2o.health.model.domain; -import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; -import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.TableId; -import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.time.LocalDateTime; + /** *

* 订单取消表 *

- * * @author itcast * @since 2023-11-07 */ @Data +@Builder @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("orders_cancelled") @@ -28,7 +30,7 @@ public class OrdersCancelled implements Serializable { /** * 订单id */ - @TableId(value = "id", type = IdType.ASSIGN_ID) + @TableId(value = "id", type = IdType.NONE) private Long id; /** @@ -65,6 +67,4 @@ public class OrdersCancelled implements Serializable { * 更新时间 */ private LocalDateTime updateTime; - - -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersRefund.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersRefund.java index 6c2c4c5..4fb13f9 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersRefund.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/domain/OrdersRefund.java @@ -1,24 +1,26 @@ package com.jzo2o.health.model.domain; -import java.math.BigDecimal; -import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; -import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.TableId; -import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + /** *

* 订单退款表 *

- * * @author itcast * @since 2023-11-07 */ @Data +@Builder @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("orders_refund") @@ -29,7 +31,7 @@ public class OrdersRefund implements Serializable { /** * 订单id */ - @TableId(value = "id", type = IdType.ASSIGN_ID) + @TableId(value = "id", type = IdType.NONE) private Long id; /** @@ -46,6 +48,4 @@ public class OrdersRefund implements Serializable { * 创建时间 */ private LocalDateTime createTime; - - -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersDetailResDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersDetailResDTO.java index 9dc7fef..e980527 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersDetailResDTO.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/response/OrdersDetailResDTO.java @@ -1,6 +1,8 @@ package com.jzo2o.health.model.dto.response; import com.fasterxml.jackson.annotation.JsonFormat; +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -30,13 +32,13 @@ public class OrdersDetailResDTO { * 订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消 */ @ApiModelProperty("订单状态,0:未支付,100:待体检,200:已体检,300:已关闭,400:已取消") - private Integer orderStatus; + private OrderStatusEnum orderStatus; /** * 支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败 */ @ApiModelProperty("支付状态,0:未支付,1:已支付,2:退款中,3:退款成功,4:退款失败") - private Integer payStatus; + private OrderPayStatusEnum payStatus; /** * 套餐id @@ -192,4 +194,4 @@ public class OrdersDetailResDTO { */ @ApiModelProperty("取消或退款原因") private String cancelReason; -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCancelService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCancelService.java index b44ca1b..b5418af 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCancelService.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCancelService.java @@ -2,10 +2,20 @@ package com.jzo2o.health.service; import com.baomidou.mybatisplus.extension.service.IService; import com.jzo2o.health.model.domain.OrdersCancelled; +import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; /** * 取消订单相关业务层 * @author JIAN */ public interface IOrderCancelService extends IService { + /** + * 用户取消订单 + */ + void cancelOrder(OrdersCancelReqDTO ordersCancelReqDTO); + + /** + * 取消订单(内部使用) + */ + void cancelOrder(OrdersCancelled ordersCancelled); } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrdersCommonService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCommonService.java similarity index 86% rename from jzo2o-health/src/main/java/com/jzo2o/health/service/IOrdersCommonService.java rename to jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCommonService.java index 3f6ddeb..67233ff 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrdersCommonService.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderCommonService.java @@ -12,7 +12,7 @@ import com.jzo2o.health.model.domain.Orders; * @author itcast * @since 2023-08-02 */ -public interface IOrdersCommonService extends IService { +public interface IOrderCommonService extends IService { /** * 更新指定id订单的状态 */ diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java index ee1ced9..502aa5b 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java @@ -5,6 +5,7 @@ import com.jzo2o.common.model.PageResult; import com.jzo2o.health.model.domain.Orders; import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; +import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO; import java.util.List; @@ -28,4 +29,9 @@ public interface IOrderManagerService extends IService { * 管理端查询订单详情 */ AdminOrdersDetailResDTO getAggregationInfo(Long id); + + /** + * 用户端获取订单详情 + */ + OrdersDetailResDTO getOrderById(Long id); } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderRefundService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderRefundService.java new file mode 100644 index 0000000..a04a8be --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderRefundService.java @@ -0,0 +1,29 @@ +package com.jzo2o.health.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.health.model.domain.OrdersRefund; +import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; + +import java.util.List; + +/** + * 订单退款相关业务层 + * @author JIAN + */ +public interface IOrderRefundService extends IService { + /** + * 用户订单退款 + */ + void refundOrder(OrdersCancelReqDTO ordersCancelReqDTO); + + /** + * 调用API退款(内部使用) + */ + void refundOrder(OrdersRefund ordersRefund); + + /** + * 获取最新的订单退款信息 + * @param count 处理数量 + */ + List getLatestRefundInfo(Integer count); +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java index 620adcc..0b8af4b 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java @@ -1,10 +1,26 @@ package com.jzo2o.health.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.expcetions.ForbiddenOperationException; +import com.jzo2o.common.model.CurrentUserInfo; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; import com.jzo2o.health.mapper.OrdersCancelledMapper; +import com.jzo2o.health.model.OrderUpdateStatusDTO; +import com.jzo2o.health.model.UserThreadLocal; +import com.jzo2o.health.model.domain.Orders; import com.jzo2o.health.model.domain.OrdersCancelled; +import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; import com.jzo2o.health.service.IOrderCancelService; +import com.jzo2o.health.service.IOrderCommonService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.LocalDateTime; /** * 取消订单相关业务层实现 @@ -12,4 +28,52 @@ import org.springframework.stereotype.Service; */ @Service public class OrderCancelServiceImpl extends ServiceImpl implements IOrderCancelService { + @Resource + private IOrderCommonService orderCommonService; + + @Override + @Transactional + public void cancelOrder(OrdersCancelReqDTO ordersCancelReqDTO) { + CurrentUserInfo currentUser = UserThreadLocal.currentUser(); + if (ObjectUtils.isEmpty(currentUser) || ObjectUtils.isEmpty(currentUser.getId())) { + throw new ForbiddenOperationException("无法获取用户信息无法取消"); + } + + Long orderId = ordersCancelReqDTO.getId(); + Orders orders = orderCommonService.getById(orderId); + if (ObjectUtils.isEmpty(orders)) { + throw new ForbiddenOperationException("订单不存在无法取消"); + } + + if (orders.getOrderStatus() != OrderStatusEnum.NO_PAY || orders.getPayStatus() != OrderPayStatusEnum.NO_PAY) { + throw new ForbiddenOperationException("订单状态错误无法取消"); + } + + this.cancelOrder(OrdersCancelled.builder() + .id(orderId) + .cancelTime(LocalDateTime.now()) + .cancelReason(ordersCancelReqDTO.getCancelReason()) + .cancellerName(currentUser.getName()) + .cancellerId(currentUser.getId()) + .cancellerType(currentUser.getUserType()) + .build()); + } + + @Override + @Transactional + public void cancelOrder(OrdersCancelled ordersCancelled) { + Long orderId = ordersCancelled.getId(); + + if (!orderCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(orderId) + .originStatus(OrderStatusEnum.NO_PAY) + .targetStatus(OrderStatusEnum.CANCELLED) + .build())) { + throw new DBException("更新订单表失败"); + } + + if (!SqlHelper.retBool(baseMapper.insert(ordersCancelled))) { + throw new DBException("更新取消表失败"); + } + } } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrdersCommonServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCommonServiceImpl.java similarity index 92% rename from jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrdersCommonServiceImpl.java rename to jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCommonServiceImpl.java index 3505d4a..9ba2371 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrdersCommonServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCommonServiceImpl.java @@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jzo2o.health.mapper.OrdersMapper; import com.jzo2o.health.model.OrderUpdateStatusDTO; import com.jzo2o.health.model.domain.Orders; -import com.jzo2o.health.service.IOrdersCommonService; +import com.jzo2o.health.service.IOrderCommonService; import org.springframework.stereotype.Service; /** @@ -16,7 +16,7 @@ import org.springframework.stereotype.Service; * @since 2023-08-02 */ @Service -public class OrdersCommonServiceImpl extends ServiceImpl implements IOrdersCommonService { +public class OrderCommonServiceImpl extends ServiceImpl implements IOrderCommonService { @Override public Boolean updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO) { return lambdaUpdate() diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java index d17d038..d089c39 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java @@ -31,7 +31,7 @@ import com.jzo2o.health.model.dto.response.PlaceOrderResDTO; import com.jzo2o.health.properties.TradeProperties; import com.jzo2o.health.service.IMemberService; import com.jzo2o.health.service.IOrderCreateService; -import com.jzo2o.health.service.IOrdersCommonService; +import com.jzo2o.health.service.IOrderCommonService; import com.jzo2o.health.service.ISetmealService; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; @@ -53,7 +53,7 @@ public class OrderCreateServiceImpl extends ServiceImpl im @Resource private ISetmealService setmealService; @Resource - private IOrdersCommonService ordersCommonService; + private IOrderCommonService ordersCommonService; @Resource private TradingApi tradingApi; @Resource diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java index 0fb2f68..5243e3a 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java @@ -2,6 +2,7 @@ package com.jzo2o.health.service.impl; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jzo2o.common.constants.UserType; import com.jzo2o.common.expcetions.ForbiddenOperationException; import com.jzo2o.common.model.PageResult; import com.jzo2o.common.utils.BeanUtils; @@ -15,6 +16,7 @@ import com.jzo2o.health.model.domain.Orders; import com.jzo2o.health.model.domain.OrdersCancelled; import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; +import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO; import com.jzo2o.health.service.IOrderCancelService; import com.jzo2o.health.service.IOrderManagerService; @@ -22,6 +24,7 @@ import com.jzo2o.mysql.utils.PageUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -126,4 +129,37 @@ public class OrderManagerServiceImpl extends ServiceImpl i return adminOrdersDetailResDTO; } + + @Override + public OrdersDetailResDTO getOrderById(Long id) { + Orders orders = baseMapper.selectById(id); + if (ObjectUtils.isEmpty(orders)) { + return new OrdersDetailResDTO(); + } + OrdersDetailResDTO ordersDetailResDTO = BeanUtils.toBean(orders, OrdersDetailResDTO.class); + + // 订单超时则取消 + if (orders.getOrderStatus() == OrderStatusEnum.NO_PAY + && orders.getPayStatus() == OrderPayStatusEnum.NO_PAY + && orders.getCreateTime().isBefore(LocalDateTime.now().minusMinutes(15))) { + orderCancelService.cancelOrder(OrdersCancelled.builder() + .id(id) + .cancelTime(LocalDateTime.now()) + .cancelReason("订单超时自动取消") + .cancellerType(UserType.SYSTEM) + .build()); + + ordersDetailResDTO.setOrderStatus(OrderStatusEnum.CANCELLED); + } + + if (orders.getOrderStatus() == OrderStatusEnum.CANCELLED + || orders.getOrderStatus() == OrderStatusEnum.CLOSED) { + OrdersCancelled cancelInfo = orderCancelService.getById(id); + + ordersDetailResDTO.setCancelReason(cancelInfo.getCancelReason()); + ordersDetailResDTO.setCancelTime(cancelInfo.getCancelTime()); + } + + return ordersDetailResDTO; + } } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderRefundServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderRefundServiceImpl.java new file mode 100644 index 0000000..5a5503a --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderRefundServiceImpl.java @@ -0,0 +1,141 @@ +package com.jzo2o.health.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.jzo2o.api.trade.RefundRecordApi; +import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO; +import com.jzo2o.api.trade.enums.RefundStatusEnum; +import com.jzo2o.common.expcetions.DBException; +import com.jzo2o.common.expcetions.ForbiddenOperationException; +import com.jzo2o.common.expcetions.ServerErrorException; +import com.jzo2o.common.model.CurrentUserInfo; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.health.enums.OrderPayStatusEnum; +import com.jzo2o.health.enums.OrderStatusEnum; +import com.jzo2o.health.mapper.OrdersRefundMapper; +import com.jzo2o.health.model.OrderUpdateStatusDTO; +import com.jzo2o.health.model.UserThreadLocal; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.model.domain.OrdersCancelled; +import com.jzo2o.health.model.domain.OrdersRefund; +import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; +import com.jzo2o.health.service.IOrderCancelService; +import com.jzo2o.health.service.IOrderCommonService; +import com.jzo2o.health.service.IOrderRefundService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 订单退款相关业务层实现 + * @author JIAN + */ +@Service +public class OrderRefundServiceImpl extends ServiceImpl implements IOrderRefundService { + @Resource + private IOrderCommonService orderCommonService; + @Resource + private IOrderCancelService orderCancelService; + @Resource + private TransactionTemplate transactionTemplate; + @Resource + private RefundRecordApi refundRecordApi; + + @Override + @Transactional + public void refundOrder(OrdersCancelReqDTO ordersCancelReqDTO) { + CurrentUserInfo currentUser = UserThreadLocal.currentUser(); + if (ObjectUtils.isEmpty(currentUser) || ObjectUtils.isEmpty(currentUser.getId())) { + throw new ForbiddenOperationException("无法获取用户信息无法取消"); + } + + Long orderId = ordersCancelReqDTO.getId(); + Orders orders = orderCommonService.getById(orderId); + if (ObjectUtils.isEmpty(orders)) { + throw new ForbiddenOperationException("订单不存在无法取消"); + } + + if (orders.getOrderStatus() != OrderStatusEnum.WAITING_CHECKUP || orders.getPayStatus() != OrderPayStatusEnum.PAY_SUCCESS) { + throw new ForbiddenOperationException("订单状态错误无法取消"); + } + + if (!orderCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(orderId) + .originStatus(OrderStatusEnum.WAITING_CHECKUP) + .targetStatus(OrderStatusEnum.CLOSED) + .payStatus(OrderPayStatusEnum.REFUNDING) + .build())) { + throw new DBException("更新订单表失败"); + } + + if (!orderCancelService.save(OrdersCancelled.builder() + .id(orderId) + .cancelTime(LocalDateTime.now()) + .cancelReason(ordersCancelReqDTO.getCancelReason()) + .cancellerName(currentUser.getName()) + .cancellerId(currentUser.getId()) + .cancellerType(currentUser.getUserType()) + .build())) { + throw new DBException("更新取消表失败"); + } + + OrdersRefund ordersRefund = OrdersRefund.builder() + .id(orderId) + .tradingOrderNo(orders.getTradingOrderNo()) + .realPayAmount(/*orders.getSetmealPrice()*/ new BigDecimal("0.01")) + .build(); + if (!SqlHelper.retBool(baseMapper.insert(ordersRefund))) { + throw new DBException("更新退款表失败"); + } + + new Thread(() -> this.refundOrder(ordersRefund)).start(); + } + + @Override + public void refundOrder(OrdersRefund ordersRefund) { + ExecutionResultResDTO executionResultResDTO = refundRecordApi.refundTrading(ordersRefund.getTradingOrderNo(), ordersRefund.getRealPayAmount()); + if (ObjectUtils.isEmpty(executionResultResDTO)) { + throw new ServerErrorException("退款接口调用失败请重试"); + } + + Integer refundStatus = executionResultResDTO.getRefundStatus(); + OrderPayStatusEnum payStatus; + if (RefundStatusEnum.SUCCESS.getCode().equals(refundStatus)) { + payStatus = OrderPayStatusEnum.REFUND_SUCCESS; + } else if (RefundStatusEnum.FAIL.getCode().equals(refundStatus)) { + payStatus = OrderPayStatusEnum.REFUND_FAIL; + } else { + return; + } + + transactionTemplate.executeWithoutResult(status -> { + if (!orderCommonService.updateStatus(OrderUpdateStatusDTO.builder() + .id(ordersRefund.getId()) + .targetStatus(OrderStatusEnum.CLOSED) + .refundNo(executionResultResDTO.getRefundNo()) + .refundId(executionResultResDTO.getRefundId()) + .payStatus(payStatus) + .build())) { + throw new DBException("更新订单表失败"); + } + + if (!SqlHelper.retBool(baseMapper.deleteById(ordersRefund.getId()))) { + throw new DBException("更新退款表失败"); + } + }); + } + + @Override + @SuppressWarnings("unchecked") + public List getLatestRefundInfo(Integer count) { + return lambdaQuery() + .orderByDesc(OrdersRefund::getCreateTime) + .last("LIMIT " + count) + .list(); + } +} \ No newline at end of file From 9d3d19ef7ae6d17aa88c3f95f64a030a80f5568d Mon Sep 17 00:00:00 2001 From: JIAN Date: Tue, 17 Sep 2024 22:54:11 +0800 Subject: [PATCH 19/21] =?UTF-8?q?feat(health):=E6=96=B0=E5=A2=9E=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E4=B8=8D=E5=90=8C=E8=AE=A2=E5=8D=95=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E7=9A=84=E6=95=B0=E9=87=8F=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/OrdersStatsController.java | 9 +++-- .../com/jzo2o/health/mapper/OrdersMapper.java | 6 ++-- .../jzo2o/health/model/dto/OrderCountDTO.java | 5 +-- .../health/service/IOrderManagerService.java | 6 ++++ .../service/impl/OrderManagerServiceImpl.java | 33 +++++++++++++++++++ 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersStatsController.java b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersStatsController.java index 0e98bb9..6ad1589 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersStatsController.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/controller/admin/OrdersStatsController.java @@ -1,12 +1,15 @@ package com.jzo2o.health.controller.admin; import com.jzo2o.health.model.dto.response.OrdersCountResDTO; +import com.jzo2o.health.service.IOrderManagerService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; + /** * @author itcast */ @@ -14,10 +17,12 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/admin/orders") @Api(tags = "管理端 - 根据状态统计订单数量") public class OrdersStatsController { + @Resource + private IOrderManagerService orderManagerService; @GetMapping("/countByStatus") @ApiOperation("根据状态统计数量") public OrdersCountResDTO countByStatus() { - return null; + return orderManagerService.countByStatus(); } -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersMapper.java index 6c08cf2..ab12df6 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersMapper.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/OrdersMapper.java @@ -6,7 +6,6 @@ import com.jzo2o.health.model.dto.OrderCountDTO; import org.apache.ibatis.annotations.Select; import java.util.List; -import java.util.Map; /** *

@@ -17,7 +16,6 @@ import java.util.Map; * @since 2023-11-02 */ public interface OrdersMapper extends BaseMapper { - @Select("SELECT order_status AS orderStatus,COUNT(id) AS count FROM orders GROUP BY order_status") - List countByStatus(); -} + List countStatus(); +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/OrderCountDTO.java b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/OrderCountDTO.java index eb5c0a3..dc34306 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/OrderCountDTO.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/model/dto/OrderCountDTO.java @@ -4,14 +4,11 @@ import lombok.Data; /** * 订单数量响应 - * * @author itcast * @create 2023/11/9 16:54 **/ @Data public class OrderCountDTO { - private Integer orderStatus; - private Integer count; -} +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java index 502aa5b..9f7c7b4 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IOrderManagerService.java @@ -5,6 +5,7 @@ import com.jzo2o.common.model.PageResult; import com.jzo2o.health.model.domain.Orders; import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; +import com.jzo2o.health.model.dto.response.OrdersCountResDTO; import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO; @@ -34,4 +35,9 @@ public interface IOrderManagerService extends IService { * 用户端获取订单详情 */ OrdersDetailResDTO getOrderById(Long id); + + /** + * 获取每种状态的订单数 + */ + OrdersCountResDTO countByStatus(); } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java index 5243e3a..febcff4 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java @@ -14,8 +14,10 @@ import com.jzo2o.health.mapper.OrdersMapper; import com.jzo2o.health.model.UserThreadLocal; import com.jzo2o.health.model.domain.Orders; import com.jzo2o.health.model.domain.OrdersCancelled; +import com.jzo2o.health.model.dto.OrderCountDTO; import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; +import com.jzo2o.health.model.dto.response.OrdersCountResDTO; import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO; import com.jzo2o.health.service.IOrderCancelService; @@ -27,6 +29,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -162,4 +165,34 @@ public class OrderManagerServiceImpl extends ServiceImpl i return ordersDetailResDTO; } + + @Override + public OrdersCountResDTO countByStatus() { + OrdersCountResDTO ordersCountResDTO = new OrdersCountResDTO(); + + List orderCountList = baseMapper.countStatus(); + if (CollUtils.isEmpty(orderCountList)) { + return ordersCountResDTO; + } + + Map map = orderCountList + .stream() + .collect(Collectors + .toMap(OrderCountDTO::getOrderStatus, OrderCountDTO::getCount)); + + Integer noPayCount = map.getOrDefault(OrderStatusEnum.NO_PAY.getStatus(), 0); + Integer waitingCheckupCount = map.getOrDefault(OrderStatusEnum.WAITING_CHECKUP.getStatus(), 0); + Integer completedCheckupCount = map.getOrDefault(OrderStatusEnum.COMPLETED_CHECKUP.getStatus(), 0); + Integer closedCount = map.getOrDefault(OrderStatusEnum.CLOSED.getStatus(), 0); + Integer cancelledCount = map.getOrDefault(OrderStatusEnum.CANCELLED.getStatus(), 0); + + ordersCountResDTO.setNoPayCount(noPayCount); + ordersCountResDTO.setWaitingCheckupCount(waitingCheckupCount); + ordersCountResDTO.setCompletedCheckupCount(completedCheckupCount); + ordersCountResDTO.setClosedCount(closedCount); + ordersCountResDTO.setCancelledCount(cancelledCount); + ordersCountResDTO.setTotalCount(noPayCount + waitingCheckupCount + completedCheckupCount + closedCount + cancelledCount); + + return ordersCountResDTO; + } } \ No newline at end of file From 084455fd76996929e4b940b35a19ba9ca9499ae9 Mon Sep 17 00:00:00 2001 From: JIAN Date: Tue, 17 Sep 2024 23:17:09 +0800 Subject: [PATCH 20/21] =?UTF-8?q?fix(health):=E4=BF=AE=E5=A4=8D=E5=B7=B2?= =?UTF-8?q?=E9=A2=84=E7=BA=A6=E4=BA=BA=E6=95=B0=E6=B2=A1=E6=9C=89=E8=B7=9F?= =?UTF-8?q?=E9=9A=8F=E8=AE=A2=E5=8D=95=E5=8F=98=E5=8C=96=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/ReservationSettingMapper.java | 4 +- .../service/IReservationSettingService.java | 8 +++ .../service/impl/OrderCancelServiceImpl.java | 6 ++ .../service/impl/OrderCreateServiceImpl.java | 59 +++++++++++-------- .../service/impl/OrderManagerServiceImpl.java | 6 ++ .../service/impl/OrderRefundServiceImpl.java | 6 ++ .../impl/ReservationSettingServiceImpl.java | 8 +++ 7 files changed, 69 insertions(+), 28 deletions(-) diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java index 2547343..e10a0c8 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/mapper/ReservationSettingMapper.java @@ -17,8 +17,8 @@ import java.util.List; * @since 2023-11-01 */ public interface ReservationSettingMapper extends BaseMapper { - @Update("UPDATE reservation_setting SET reservations = reservations + 1 WHERE id = #{id} AND reservations < number") - Integer updateReservations(@Param("id") Integer id); + @Update("UPDATE reservation_setting SET reservations = reservations + #{count} WHERE order_date = #{time} AND reservations < number") + Integer plusReservationCount(@Param("time") LocalDate time, @Param("count") Integer count); @Select("SELECT order_date FROM reservation_setting WHERE #{start} <= order_date AND order_date <= #{end}") List getReservationDate(@Param("start") LocalDate start, @Param("end") LocalDate end); diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java index 55035dc..c1c4bfd 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/IReservationSettingService.java @@ -7,6 +7,7 @@ import com.jzo2o.health.model.dto.response.ReservationDateResDTO; import com.jzo2o.health.model.dto.response.ReservationSettingResDTO; import com.jzo2o.health.model.excel.ReservationImportData; +import java.time.LocalDate; import java.time.YearMonth; import java.util.List; @@ -36,4 +37,11 @@ public interface IReservationSettingService extends IService * 获取当前月份可用预约日期 */ ReservationDateResDTO getReservationDateByMonth(YearMonth yearMonth); + + /** + * 增加已预约人数数量 + * @param time + * @param count 数量 + */ + void plusReservationCount(LocalDate time, Integer count); } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java index 0b8af4b..c54aedc 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCancelServiceImpl.java @@ -16,6 +16,7 @@ import com.jzo2o.health.model.domain.OrdersCancelled; import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; import com.jzo2o.health.service.IOrderCancelService; import com.jzo2o.health.service.IOrderCommonService; +import com.jzo2o.health.service.IReservationSettingService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -30,6 +31,8 @@ import java.time.LocalDateTime; public class OrderCancelServiceImpl extends ServiceImpl implements IOrderCancelService { @Resource private IOrderCommonService orderCommonService; + @Resource + private IReservationSettingService reservationSettingService; @Override @Transactional @@ -57,6 +60,9 @@ public class OrderCancelServiceImpl extends ServiceImpl im @Resource private IOrderCommonService ordersCommonService; @Resource + private IReservationSettingService reservationSettingService; + @Resource private TradingApi tradingApi; @Resource private NativePayApi nativePayApi; @@ -62,6 +62,8 @@ public class OrderCreateServiceImpl extends ServiceImpl im private TradeProperties tradeProperties; @Resource private RedisTemplate redisTemplate; + @Resource + private TransactionTemplate transactionTemplate; /** * 生成订单号(2位年+2位月+2位日+13位序号) @@ -95,28 +97,33 @@ public class OrderCreateServiceImpl extends ServiceImpl im throw new ServerErrorException("生成订单id失败无法下单"); } - if (!SqlHelper.retBool(baseMapper.insert(Orders.builder() - .id(orderId) - .orderStatus(OrderStatusEnum.NO_PAY) - .payStatus(OrderPayStatusEnum.NO_PAY) - .setmealId(setmeal.getId()) - .setmealName(setmeal.getName()) - .setmealPrice(setmeal.getPrice()) - .setmealSex(setmeal.getSex()) - .setmealAge(setmeal.getAge()) - .setmealImg(setmeal.getImg()) - .setmealRemark(setmeal.getRemark()) - .reservationDate(placeOrderReqDTO.getReservationDate()) - .checkupPersonName(placeOrderReqDTO.getCheckupPersonName()) - .checkupPersonSex(placeOrderReqDTO.getCheckupPersonSex()) - .checkupPersonPhone(placeOrderReqDTO.getCheckupPersonPhone()) - .checkupPersonIdcard(placeOrderReqDTO.getCheckupPersonIdcard()) - .memberId(member.getId()) - .memberPhone(member.getPhone()) - .sortBy(DateUtils.toEpochMilli(LocalDateTime.now())) - .build()))) { - throw new DBException("订单表插入失败下单失败"); - } + transactionTemplate.executeWithoutResult(status -> { + if (!SqlHelper.retBool(baseMapper.insert(Orders.builder() + .id(orderId) + .orderStatus(OrderStatusEnum.NO_PAY) + .payStatus(OrderPayStatusEnum.NO_PAY) + .setmealId(setmeal.getId()) + .setmealName(setmeal.getName()) + .setmealPrice(setmeal.getPrice()) + .setmealSex(setmeal.getSex()) + .setmealAge(setmeal.getAge()) + .setmealImg(setmeal.getImg()) + .setmealRemark(setmeal.getRemark()) + .reservationDate(placeOrderReqDTO.getReservationDate()) + .checkupPersonName(placeOrderReqDTO.getCheckupPersonName()) + .checkupPersonSex(placeOrderReqDTO.getCheckupPersonSex()) + .checkupPersonPhone(placeOrderReqDTO.getCheckupPersonPhone()) + .checkupPersonIdcard(placeOrderReqDTO.getCheckupPersonIdcard()) + .memberId(member.getId()) + .memberPhone(member.getPhone()) + .sortBy(DateUtils.toEpochMilli(LocalDateTime.now())) + .build()))) { + throw new DBException("订单表插入失败下单失败"); + } + + // 已预约人数 + 1 + reservationSettingService.plusReservationCount(placeOrderReqDTO.getReservationDate(), 1); + }); return new PlaceOrderResDTO(orderId); } diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java index febcff4..61ae1e2 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderManagerServiceImpl.java @@ -22,6 +22,7 @@ import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO; import com.jzo2o.health.service.IOrderCancelService; import com.jzo2o.health.service.IOrderManagerService; +import com.jzo2o.health.service.IReservationSettingService; import com.jzo2o.mysql.utils.PageUtils; import org.springframework.stereotype.Service; @@ -40,6 +41,8 @@ import java.util.stream.Collectors; public class OrderManagerServiceImpl extends ServiceImpl implements IOrderManagerService { @Resource private IOrderCancelService orderCancelService; + @Resource + private IReservationSettingService reservationSettingService; @Override public PageResult pageQuery(OrdersPageQueryReqDTO ordersPageQueryReqDTO) { @@ -152,6 +155,9 @@ public class OrderManagerServiceImpl extends ServiceImpl i .cancellerType(UserType.SYSTEM) .build()); + // 已预约人数 - 1 + reservationSettingService.plusReservationCount(orders.getReservationDate(), -1); + ordersDetailResDTO.setOrderStatus(OrderStatusEnum.CANCELLED); } diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderRefundServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderRefundServiceImpl.java index 5a5503a..7d51693 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderRefundServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderRefundServiceImpl.java @@ -22,6 +22,7 @@ import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; import com.jzo2o.health.service.IOrderCancelService; import com.jzo2o.health.service.IOrderCommonService; import com.jzo2o.health.service.IOrderRefundService; +import com.jzo2o.health.service.IReservationSettingService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionTemplate; @@ -45,6 +46,8 @@ public class OrderRefundServiceImpl extends ServiceImpl this.refundOrder(ordersRefund)).start(); } diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java index 94aa5d4..c308aca 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java @@ -2,6 +2,7 @@ package com.jzo2o.health.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import com.jzo2o.common.expcetions.CommonException; import com.jzo2o.common.expcetions.DBException; import com.jzo2o.common.utils.CollUtils; import com.jzo2o.health.mapper.ReservationSettingMapper; @@ -96,4 +97,11 @@ public class ReservationSettingServiceImpl extends ServiceImpl dates = baseMapper.getReservationDate(yearMonth.atDay(1), yearMonth.atEndOfMonth()); return new ReservationDateResDTO(dates); } + + @Override + public void plusReservationCount(LocalDate time, Integer count) { + if (SqlHelper.retBool(baseMapper.plusReservationCount(time, count))) { + throw new CommonException("预约人数已满不能预约"); + } + } } \ No newline at end of file From b4d10a7306825c0180d1e9d3f3dc524f7db096d0 Mon Sep 17 00:00:00 2001 From: JIAN Date: Thu, 19 Sep 2024 19:46:10 +0800 Subject: [PATCH 21/21] =?UTF-8?q?feat(health):=E6=96=B0=E5=A2=9E=E5=BB=B6?= =?UTF-8?q?=E6=97=B6=E9=98=9F=E5=88=97=E5=A4=84=E7=90=86=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jzo2o-health/pom.xml | 6 +- .../config/DelayQueueConfiguration.java | 61 ++++++++++++++++++ .../health/constant/HealthMqConstants.java | 23 +++++++ .../health/listener/OrderStatusListener.java | 62 +++++++++++++++++-- .../service/impl/OrderCreateServiceImpl.java | 6 ++ .../impl/ReservationSettingServiceImpl.java | 2 +- 6 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/config/DelayQueueConfiguration.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/constant/HealthMqConstants.java diff --git a/jzo2o-health/pom.xml b/jzo2o-health/pom.xml index a941d30..b2cff47 100644 --- a/jzo2o-health/pom.xml +++ b/jzo2o-health/pom.xml @@ -6,8 +6,8 @@ com.jzo2o jzo2o-health 1.0-SNAPSHOT - health - health + jzo2o-health + jzo2o-health jzo2o-parent @@ -100,4 +100,4 @@ - + \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/config/DelayQueueConfiguration.java b/jzo2o-health/src/main/java/com/jzo2o/health/config/DelayQueueConfiguration.java new file mode 100644 index 0000000..ff0bcdf --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/config/DelayQueueConfiguration.java @@ -0,0 +1,61 @@ +package com.jzo2o.health.config; + +import com.jzo2o.health.constant.HealthMqConstants; +import com.jzo2o.rabbitmq.config.RabbitMqConfiguration; +import org.springframework.amqp.core.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import java.util.concurrent.TimeUnit; + +/** + * RabbitMQ延时队列 + * @author JIAN + */ +@Configuration +@Import(RabbitMqConfiguration.class) +public class DelayQueueConfiguration { + @Bean + public Exchange delayExchange() { + return ExchangeBuilder + .topicExchange(HealthMqConstants.Exchanges.HEALTH_ORDER) + .durable(true) + .build(); + } + + @Bean + public Queue delayQueueIn() { + return QueueBuilder + .durable(HealthMqConstants.Queues.DELAY_IN) + // 订单默认15分钟超时 + .ttl((int) TimeUnit.MINUTES.toMillis(15)) + .deadLetterExchange(HealthMqConstants.Exchanges.HEALTH_ORDER) + .deadLetterRoutingKey(HealthMqConstants.RoutingKeys.ORDER_OVERTIME_OUT) + .build(); + } + + @Bean + public Queue delayQueueOut() { + return QueueBuilder.durable(HealthMqConstants.Queues.DELAY_OUT) + .build(); + } + + @Bean + public Binding bindDelayQueueIn() { + return BindingBuilder + .bind(delayQueueIn()) + .to(delayExchange()) + .with(HealthMqConstants.RoutingKeys.ORDER_OVERTIME_IN) + .noargs(); + } + + @Bean + public Binding bindDelayQueueOut() { + return BindingBuilder + .bind(delayQueueOut()) + .to(delayExchange()) + .with(HealthMqConstants.RoutingKeys.ORDER_OVERTIME_OUT) + .noargs(); + } +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/constant/HealthMqConstants.java b/jzo2o-health/src/main/java/com/jzo2o/health/constant/HealthMqConstants.java new file mode 100644 index 0000000..dde8a0b --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/constant/HealthMqConstants.java @@ -0,0 +1,23 @@ +package com.jzo2o.health.constant; + +import com.jzo2o.common.constants.MqConstants; + +/** + * 即刻体检MQ常量 + * @author JIAN + */ +public interface HealthMqConstants extends MqConstants { + interface Exchanges extends MqConstants.Exchanges { + String HEALTH_ORDER = "health.exchange.topic.order"; + } + + interface Queues extends MqConstants.Queues { + String DELAY_IN = "health.queue.orders.delay.in"; + String DELAY_OUT = "health.queue.orders.delay.out"; + } + + interface RoutingKeys extends MqConstants.RoutingKeys { + String ORDER_OVERTIME_IN = "order.overtime.in"; + String ORDER_OVERTIME_OUT = "order.overtime.out"; + } +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java b/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java index 4a847d3..42e3d13 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java @@ -1,17 +1,25 @@ package com.jzo2o.health.listener; +import com.jzo2o.api.trade.TradingApi; +import com.jzo2o.api.trade.dto.response.TradingResDTO; import com.jzo2o.api.trade.enums.TradingStateEnum; -import com.jzo2o.common.constants.MqConstants; +import com.jzo2o.common.constants.UserType; import com.jzo2o.common.expcetions.DBException; import com.jzo2o.common.model.msg.TradeStatusMsg; import com.jzo2o.common.utils.CollUtils; import com.jzo2o.common.utils.JsonUtils; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.health.constant.HealthMqConstants; import com.jzo2o.health.constant.TradeConstants; import com.jzo2o.health.enums.OrderPayStatusEnum; import com.jzo2o.health.enums.OrderStatusEnum; import com.jzo2o.health.model.OrderUpdateStatusDTO; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.model.domain.OrdersCancelled; +import com.jzo2o.health.service.IOrderCancelService; import com.jzo2o.health.service.IOrderCommonService; import com.jzo2o.health.service.IOrderCreateService; +import com.jzo2o.health.service.IReservationSettingService; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.ExchangeTypes; import org.springframework.amqp.rabbit.annotation.Exchange; @@ -37,6 +45,12 @@ public class OrderStatusListener { private IOrderCommonService orderCommonService; @Resource private TransactionTemplate transactionTemplate; + @Resource + private IOrderCancelService orderCancelService; + @Resource + private IReservationSettingService reservationSettingService; + @Resource + private TradingApi tradingApi; /** * 接收支付成功信息 @@ -44,10 +58,10 @@ public class OrderStatusListener { */ @RabbitListener(bindings = @QueueBinding( value = @Queue(name = TradeConstants.MQ_TRADE_QUEUE), - exchange = @Exchange(name = MqConstants.Exchanges.TRADE, type = ExchangeTypes.TOPIC), - key = MqConstants.RoutingKeys.TRADE_UPDATE_STATUS)) + exchange = @Exchange(name = HealthMqConstants.Exchanges.TRADE, type = ExchangeTypes.TOPIC), + key = HealthMqConstants.RoutingKeys.TRADE_UPDATE_STATUS)) public void listenTradeUpdatePayStatusMsg(String msg) { - log.info("接收到支付结果状态的消息 ({})-> {}", MqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS, msg); + log.info("接收到支付结果状态的消息 ({})-> {}", HealthMqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS, msg); List msgList = JsonUtils.parseArray(msg).toList(TradeStatusMsg.class); if (CollUtils.isEmpty(msgList)) { @@ -76,4 +90,44 @@ public class OrderStatusListener { } }); } + + @RabbitListener(bindings = @QueueBinding( + value = @Queue(name = HealthMqConstants.Queues.DELAY_OUT), + exchange = @Exchange(name = HealthMqConstants.Exchanges.HEALTH_ORDER, type = ExchangeTypes.TOPIC), + key = HealthMqConstants.RoutingKeys.ORDER_OVERTIME_OUT)) + public void handleOverTimeOrder(String msg) { + Long orderId = Long.parseLong(msg); + if (ObjectUtils.isEmpty(orderId)) { + return; + } + + Orders order = orderCommonService.getById(orderId); + if (ObjectUtils.isEmpty(order)) { + return; + } + + if (order.getOrderStatus() == OrderStatusEnum.NO_PAY && order.getPayStatus() == OrderPayStatusEnum.NO_PAY) { + Long tradingOrderNo = order.getTradingOrderNo(); + if (ObjectUtils.isNotEmpty(tradingOrderNo)) { + // 再次请求防止已支付 + TradingResDTO tradingResDTO = tradingApi.findTradResultByTradingOrderNo(tradingOrderNo); + if (ObjectUtils.isNotEmpty(tradingResDTO) && tradingResDTO.getTradingState() == TradingStateEnum.YJS) { + return; + } + } + + // 事务更新数据表(取消订单) + transactionTemplate.executeWithoutResult(status -> { + orderCancelService.cancelOrder(OrdersCancelled.builder() + .id(orderId) + .cancelTime(LocalDateTime.now()) + .cancelReason("订单超时自动取消") + .cancellerType(UserType.SYSTEM) + .build()); + + // 已预约人数 - 1 + reservationSettingService.plusReservationCount(order.getReservationDate(), -1); + }); + } + } } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java index 2cc73fa..54f3a64 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java @@ -30,6 +30,7 @@ import com.jzo2o.health.model.dto.response.OrdersPayResDTO; import com.jzo2o.health.model.dto.response.PlaceOrderResDTO; import com.jzo2o.health.properties.TradeProperties; import com.jzo2o.health.service.*; +import com.jzo2o.rabbitmq.client.RabbitClient; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -64,6 +65,8 @@ public class OrderCreateServiceImpl extends ServiceImpl im private RedisTemplate redisTemplate; @Resource private TransactionTemplate transactionTemplate; + @Resource + private RabbitClient rabbitClient; /** * 生成订单号(2位年+2位月+2位日+13位序号) @@ -125,6 +128,9 @@ public class OrderCreateServiceImpl extends ServiceImpl im reservationSettingService.plusReservationCount(placeOrderReqDTO.getReservationDate(), 1); }); + // 发送消息到延时队列处理超时订单(发送检测的订单id) + rabbitClient.sendMsg("health.exchange.topic.order", "order.overtime.in", orderId.toString()); + return new PlaceOrderResDTO(orderId); } diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java index c308aca..cae96d6 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java @@ -100,7 +100,7 @@ public class ReservationSettingServiceImpl extends ServiceImpl