2 Commits 236e11f6e3 ... ea21e69aba

Author SHA1 Message Date
  luofeiyun ea21e69aba fix: 下单时对营销政策进行操作,待完善 1 week ago
  luofeiyun 57a81ac6d4 fix: 保险通知接口修改 1 week ago
27 changed files with 944 additions and 96 deletions
  1. 22 0
      ship-module-marketing/ship-module-marketing-api/src/main/java/com/yc/ship/module/marketing/api/policy/PolicyApi.java
  2. 2 0
      ship-module-marketing/ship-module-marketing-api/src/main/java/com/yc/ship/module/marketing/enums/ErrorCodeConstants.java
  3. 36 0
      ship-module-marketing/ship-module-marketing-biz/src/main/java/com/yc/ship/module/marketing/api/policy/PolicyApiImpl.java
  4. 24 0
      ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/insurance/dto/InsuranceCancelReqDTO.java
  5. 24 0
      ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/insurance/dto/InsuranceOrderInfoCancelDTO.java
  6. 21 0
      ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/insurance/dto/InsuredCancelDTO.java
  7. 4 3
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/api/insurance/InsuranceApiImpl.java
  8. 3 3
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/insurance/InsuranceController.java
  9. 3 2
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/notify/NotifyController.java
  10. 3 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderOtcCreateVO.java
  11. 34 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderPolicyReqVO.java
  12. 34 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderPolicyRespVO.java
  13. 95 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/orderpolicy/OrderPolicyController.java
  14. 41 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/orderpolicy/vo/OrderPolicyPageReqVO.java
  15. 48 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/orderpolicy/vo/OrderPolicyRespVO.java
  16. 34 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/orderpolicy/vo/OrderPolicySaveReqVO.java
  17. 71 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/dataobject/orderpolicy/OrderPolicyDO.java
  18. 35 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/mysql/orderpolicy/OrderPolicyMapper.java
  19. 1 1
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/insurance/InsuranceService.java
  20. 34 80
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/insurance/InsuranceServiceImpl.java
  21. 11 2
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/notify/NotifyServiceImpl.java
  22. 55 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/orderpolicy/OrderPolicyService.java
  23. 64 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/orderpolicy/OrderPolicyServiceImpl.java
  24. 66 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/impl/OtcTradeOrderServiceImpl.java
  25. 131 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/InsuranceUtil.java
  26. 46 4
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/SignUtil.java
  27. 2 1
      ship-server-web/src/main/resources/application.yaml

+ 22 - 0
ship-module-marketing/ship-module-marketing-api/src/main/java/com/yc/ship/module/marketing/api/policy/PolicyApi.java

@@ -0,0 +1,22 @@
+package com.yc.ship.module.marketing.api.policy;
+
+import java.math.BigDecimal;
+
+public interface PolicyApi {
+
+    /**
+     * 减剩余优惠数量
+     *
+     * @param policyId 政策ID
+     * @param num 使用了的数量
+     */
+    void updatePolicySurplusNum(Long policyId, BigDecimal num);
+
+    /**
+     * 检查优惠券剩余数量
+     *
+     * @param policyId 政策ID
+     * @return true-剩余数量充足
+     */
+    Boolean checkPolicySurplusNum(Long policyId, BigDecimal num);
+}

+ 2 - 0
ship-module-marketing/ship-module-marketing-api/src/main/java/com/yc/ship/module/marketing/enums/ErrorCodeConstants.java

@@ -48,6 +48,8 @@ public interface ErrorCodeConstants {
 
     ErrorCode COUPON_PACKAGE_OVER_TIMES = new ErrorCode(1_005_001_019, "优惠券包剩余次数不足");
 
+    ErrorCode POLICY_OVER_NUM = new ErrorCode(1_005_001_020, "优惠政策剩余房间数不足");
+
 
     // ========== 装修模板 1-013-017-000 ==========
     ErrorCode DIY_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_017_000, "装修模板不存在");

+ 36 - 0
ship-module-marketing/ship-module-marketing-biz/src/main/java/com/yc/ship/module/marketing/api/policy/PolicyApiImpl.java

@@ -0,0 +1,36 @@
+package com.yc.ship.module.marketing.api.policy;
+
+import com.yc.ship.module.marketing.dal.dataobject.policy.PolicyDO;
+import com.yc.ship.module.marketing.dal.mysql.policy.PolicyMapper;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+
+import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static com.yc.ship.module.marketing.enums.ErrorCodeConstants.POLICY_OVER_NUM;
+
+@Service
+public class PolicyApiImpl implements PolicyApi{
+
+    @Resource
+    private PolicyMapper policyMapper;
+    @Override
+    public void updatePolicySurplusNum(Long policyId, BigDecimal num) {
+        PolicyDO policyDO = policyMapper.selectById(policyId);
+        if(policyDO.getSurplusNum().compareTo(num) < 0) {
+            throw exception(POLICY_OVER_NUM);
+        }
+        policyDO.setSurplusNum(policyDO.getSurplusNum().subtract(num));
+        policyMapper.updateById(policyDO);
+    }
+
+    @Override
+    public Boolean checkPolicySurplusNum(Long policyId, BigDecimal num) {
+        PolicyDO policyDO = policyMapper.selectById(policyId);
+        if(policyDO.getSurplusNum().compareTo(num) < 0) {
+            return false;
+        }
+        return true;
+    }
+}

+ 24 - 0
ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/insurance/dto/InsuranceCancelReqDTO.java

@@ -0,0 +1,24 @@
+package com.yc.ship.module.trade.api.insurance.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "RPC 服务 - Insurance 退保 Request DTO")
+@Data
+public class InsuranceCancelReqDTO {
+
+    /** 服务类型 */
+    private String service;
+
+    /** 回调URL */
+    private String replyUrl;
+
+    /** 订单信息 */
+    private InsuranceOrderInfoCancelDTO order;
+
+    /** 被保险人信息列表 */
+    private List<InsuredCancelDTO> insureds;
+
+}

+ 24 - 0
ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/insurance/dto/InsuranceOrderInfoCancelDTO.java

@@ -0,0 +1,24 @@
+package com.yc.ship.module.trade.api.insurance.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Schema(description = "RPC 服务 - Insurance 投保订单信息 Request DTO")
+@Data
+public class InsuranceOrderInfoCancelDTO {
+
+    /** 必填 - 字符串 - 贵方的订单号 */
+    @Schema(description = "贵方的订单号")
+    @NotBlank
+    private String externalOrderNo;
+    /** 必填 - 字符串 - 起保日期时间 yyyy-MM-dd */
+    @Schema(description = "开始日期")
+    private String beginDate;
+
+    /** 必填 - 字符串 - 止保日期时间 yyyy-MM-dd */
+    @Schema(description = "结束日期")
+    private String endDate;
+
+}

+ 21 - 0
ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/api/insurance/dto/InsuredCancelDTO.java

@@ -0,0 +1,21 @@
+package com.yc.ship.module.trade.api.insurance.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "RPC 服务 - Insurance 退保时的被保人 Request DTO")
+@Data
+public class InsuredCancelDTO {
+    /**
+     *        //必填 - 贵方系统中的投保单号,此处值需与投保时的值相同
+     *   	  //个保时,需与投保请求中insureds[i].externalPolicyNumber相同
+     *   	  //团保时,需与投保请求中order.externalPolicyNumber相同
+     */
+    @Schema(description = "贵方系统中的投保单号,此处值需与投保时的值相同")
+    private String externalPolicyNumber;
+
+    /**
+     *  //必填 - 保单号
+     */
+   private String policyNum;
+}

+ 4 - 3
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/api/insurance/InsuranceApiImpl.java

@@ -11,7 +11,6 @@ import javax.annotation.Resource;
 import java.util.List;
 
 /**
- * @author le'yang
  */
 @RestController
 @Validated
@@ -29,7 +28,9 @@ public class InsuranceApiImpl implements InsuranceApi {
 
     @Override
     public CommonResult<Boolean> cancelInsurance(List<Long> ticketIdList) {
-        insuranceService.applyCancelInsurance(ticketIdList);
-        return CommonResult.success(true);
+        // TODO: 待实现
+//        insuranceService.applyCancelInsurance(ticketIdList);
+//        return CommonResult.success(true);
+        return null;
     }
 }

+ 3 - 3
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/insurance/InsuranceController.java

@@ -88,12 +88,12 @@ public class InsuranceController {
     }
 
 
-    @PostMapping("/cancel")
+    @PutMapping("/cancel")
     @Operation(summary = "退保")
     @OperateLog(type = API)
     @PreAuthorize("@ss.hasPermission('trade:insurance:apply')")
-    public CommonResult<Boolean>  cancelInsurance(@RequestBody List<Long> ticketIdList){
-        insuranceService.applyCancelInsurance(ticketIdList);
+    public CommonResult<Boolean>  cancelInsurance(@RequestParam("orderId") Long orderId){
+        insuranceService.applyCancelInsurance(orderId);
         return success(true);
     }
 }

+ 3 - 2
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/notify/NotifyController.java

@@ -25,8 +25,9 @@ public class NotifyController {
     private NotifyService notifyService;
 
     @PostMapping("/insurance")
-    public Boolean insuranceNotify(@RequestBody NotifyInsuranceReqVO reqVO) {
+    public String insuranceNotify(@RequestBody NotifyInsuranceReqVO reqVO) {
         log.info("收到保险通知:{}", JSONObject.toJSONString(reqVO));
-        return notifyService.notifyInsurance(reqVO);
+        notifyService.notifyInsurance(reqVO);
+        return "SUCCESS";
     }
 }

+ 3 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderOtcCreateVO.java

@@ -86,4 +86,7 @@ public class TradeOrderOtcCreateVO {
     @Schema(description = "附加产品信息")
     private List<TradeSpuReqVO> spuList;
 
+    @Schema(description = "政策信息")
+    private List<TradeOrderPolicyReqVO> policyList;
+
 }

+ 34 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderPolicyReqVO.java

@@ -0,0 +1,34 @@
+package com.yc.ship.module.trade.controller.admin.order.vo.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Schema(description = "管理后台 - 订单使用的优惠政策新增/修改 Request VO")
+@Data
+public class TradeOrderPolicyReqVO {
+
+    @Schema(description = "政策ID", example = "25357")
+    private Long policyId;
+
+    @Schema(description = "名称")
+    private String name;
+
+    @Schema(description = "折扣")
+    private BigDecimal discount;
+
+    @Schema(description = "折扣类型")
+    private Integer discountType;
+
+    @Schema(description = "使用数量")
+    private BigDecimal useNum;
+
+    @Schema(description = "优惠金额")
+    private BigDecimal amount;
+
+    @Schema(description = "使用的房间roomIndexId列表")
+    private List<String> rooms;
+
+}

+ 34 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/order/vo/order/TradeOrderPolicyRespVO.java

@@ -0,0 +1,34 @@
+package com.yc.ship.module.trade.controller.admin.order.vo.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Schema(description = "管理后台 - 订单使用的优惠政策新增/修改 Request VO")
+@Data
+public class TradeOrderPolicyRespVO {
+
+    @Schema(description = "政策ID", example = "25357")
+    private Long policyId;
+
+    @Schema(description = "名称")
+    private String name;
+
+    @Schema(description = "折扣")
+    private BigDecimal discount;
+
+    @Schema(description = "折扣类型")
+    private Integer discountType;
+
+    @Schema(description = "使用数量")
+    private BigDecimal useNum;
+
+    @Schema(description = "优惠金额")
+    private BigDecimal amount;
+
+    @Schema(description = "使用的房间roomIndexId列表")
+    private List<String> rooms;
+
+}

+ 95 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/orderpolicy/OrderPolicyController.java

@@ -0,0 +1,95 @@
+package com.yc.ship.module.trade.controller.admin.orderpolicy;
+
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.validation.constraints.*;
+import javax.validation.*;
+import javax.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import com.yc.ship.framework.common.pojo.PageParam;
+import com.yc.ship.framework.common.pojo.PageResult;
+import com.yc.ship.framework.common.pojo.CommonResult;
+import com.yc.ship.framework.common.util.object.BeanUtils;
+import static com.yc.ship.framework.common.pojo.CommonResult.success;
+
+import com.yc.ship.framework.excel.core.util.ExcelUtils;
+
+import com.yc.ship.framework.apilog.core.annotation.ApiAccessLog;
+import static com.yc.ship.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import com.yc.ship.module.trade.controller.admin.orderpolicy.vo.*;
+import com.yc.ship.module.trade.dal.dataobject.orderpolicy.OrderPolicyDO;
+import com.yc.ship.module.trade.service.orderpolicy.OrderPolicyService;
+
+@Tag(name = "管理后台 - 订单使用的优惠政策")
+@RestController
+@RequestMapping("/trade/order-policy")
+@Validated
+public class OrderPolicyController {
+
+    @Resource
+    private OrderPolicyService orderPolicyService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建订单使用的优惠政策")
+    @PreAuthorize("@ss.hasPermission('trade:order-policy:create')")
+    public CommonResult<Long> createOrderPolicy(@Valid @RequestBody OrderPolicySaveReqVO createReqVO) {
+        return success(orderPolicyService.createOrderPolicy(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新订单使用的优惠政策")
+    @PreAuthorize("@ss.hasPermission('trade:order-policy:update')")
+    public CommonResult<Boolean> updateOrderPolicy(@Valid @RequestBody OrderPolicySaveReqVO updateReqVO) {
+        orderPolicyService.updateOrderPolicy(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除订单使用的优惠政策")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('trade:order-policy:delete')")
+    public CommonResult<Boolean> deleteOrderPolicy(@RequestParam("id") Long id) {
+        orderPolicyService.deleteOrderPolicy(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得订单使用的优惠政策")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('trade:order-policy:query')")
+    public CommonResult<OrderPolicyRespVO> getOrderPolicy(@RequestParam("id") Long id) {
+        OrderPolicyDO orderPolicy = orderPolicyService.getOrderPolicy(id);
+        return success(BeanUtils.toBean(orderPolicy, OrderPolicyRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得订单使用的优惠政策分页")
+    @PreAuthorize("@ss.hasPermission('trade:order-policy:query')")
+    public CommonResult<PageResult<OrderPolicyRespVO>> getOrderPolicyPage(@Valid OrderPolicyPageReqVO pageReqVO) {
+        PageResult<OrderPolicyDO> pageResult = orderPolicyService.getOrderPolicyPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, OrderPolicyRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出订单使用的优惠政策 Excel")
+    @PreAuthorize("@ss.hasPermission('trade:order-policy:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportOrderPolicyExcel(@Valid OrderPolicyPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<OrderPolicyDO> list = orderPolicyService.getOrderPolicyPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "订单使用的优惠政策.xls", "数据", OrderPolicyRespVO.class,
+                        BeanUtils.toBean(list, OrderPolicyRespVO.class));
+    }
+
+}

+ 41 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/orderpolicy/vo/OrderPolicyPageReqVO.java

@@ -0,0 +1,41 @@
+package com.yc.ship.module.trade.controller.admin.orderpolicy.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import com.yc.ship.framework.common.pojo.PageParam;
+import java.math.BigDecimal;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static com.yc.ship.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 订单使用的优惠政策分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class OrderPolicyPageReqVO extends PageParam {
+
+    @Schema(description = "订单ID", example = "14709")
+    private Long orderId;
+
+    @Schema(description = "订单号")
+    private String orderNo;
+
+    @Schema(description = "政策ID", example = "25357")
+    private Long policyId;
+
+    @Schema(description = "预占数量")
+    private BigDecimal preUseNum;
+
+    @Schema(description = "实占数量")
+    private BigDecimal realUseNum;
+
+    @Schema(description = "优惠金额")
+    private BigDecimal amount;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 48 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/orderpolicy/vo/OrderPolicyRespVO.java

@@ -0,0 +1,48 @@
+package com.yc.ship.module.trade.controller.admin.orderpolicy.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.math.BigDecimal;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 订单使用的优惠政策 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class OrderPolicyRespVO {
+
+    @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "18521")
+    @ExcelProperty("ID")
+    private Long id;
+
+    @Schema(description = "订单ID", example = "14709")
+    @ExcelProperty("订单ID")
+    private Long orderId;
+
+    @Schema(description = "订单号")
+    @ExcelProperty("订单号")
+    private String orderNo;
+
+    @Schema(description = "政策ID", example = "25357")
+    @ExcelProperty("政策ID")
+    private Long policyId;
+
+    @Schema(description = "预占数量")
+    @ExcelProperty("预占数量")
+    private BigDecimal preUseNum;
+
+    @Schema(description = "实占数量")
+    @ExcelProperty("实占数量")
+    private BigDecimal realUseNum;
+
+    @Schema(description = "优惠金额")
+    @ExcelProperty("优惠金额")
+    private BigDecimal amount;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 34 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/controller/admin/orderpolicy/vo/OrderPolicySaveReqVO.java

@@ -0,0 +1,34 @@
+package com.yc.ship.module.trade.controller.admin.orderpolicy.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import javax.validation.constraints.*;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 订单使用的优惠政策新增/修改 Request VO")
+@Data
+public class OrderPolicySaveReqVO {
+
+    @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "18521")
+    private Long id;
+
+    @Schema(description = "订单ID", example = "14709")
+    private Long orderId;
+
+    @Schema(description = "订单号")
+    private String orderNo;
+
+    @Schema(description = "政策ID", example = "25357")
+    private Long policyId;
+
+    @Schema(description = "预占数量")
+    private BigDecimal preUseNum;
+
+    @Schema(description = "实占数量")
+    private BigDecimal realUseNum;
+
+    @Schema(description = "优惠金额")
+    private BigDecimal amount;
+
+}

+ 71 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/dataobject/orderpolicy/OrderPolicyDO.java

@@ -0,0 +1,71 @@
+package com.yc.ship.module.trade.dal.dataobject.orderpolicy;
+
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import com.yc.ship.framework.tenant.core.db.TenantBaseDO;
+import lombok.*;
+import java.util.*;
+import java.math.BigDecimal;
+import java.math.BigDecimal;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import com.yc.ship.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 订单使用的优惠政策 DO
+ *
+ * @author 管理员
+ */
+@TableName(value = "trade_order_policy", autoResultMap = true)
+@KeySequence("trade_order_policy_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderPolicyDO extends TenantBaseDO {
+
+    /**
+     * ID
+     */
+    @TableId(type = IdType.ASSIGN_ID)
+    private Long id;
+    /**
+     * 订单ID
+     */
+    private Long orderId;
+    /**
+     * 订单号
+     */
+    private String orderNo;
+    /**
+     * 政策ID
+     */
+    private Long policyId;
+
+    /**
+     * 政策名称
+     */
+    private String policyName;
+    /**
+     * 预占数量
+     */
+    private BigDecimal preUseNum;
+    /**
+     * 实占数量
+     */
+    private BigDecimal realUseNum;
+    /**
+     * 优惠金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 使用房间roomIndexId列表
+     */
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private List<String> rooms;
+
+}

+ 35 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/dal/mysql/orderpolicy/OrderPolicyMapper.java

@@ -0,0 +1,35 @@
+package com.yc.ship.module.trade.dal.mysql.orderpolicy;
+
+import java.util.*;
+
+import com.yc.ship.framework.common.pojo.PageResult;
+import com.yc.ship.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.yc.ship.framework.mybatis.core.mapper.BaseMapperX;
+import com.yc.ship.module.trade.dal.dataobject.orderpolicy.OrderPolicyDO;
+import org.apache.ibatis.annotations.Mapper;
+import com.yc.ship.module.trade.controller.admin.orderpolicy.vo.*;
+
+/**
+ * 订单使用的优惠政策 Mapper
+ *
+ * @author 管理员
+ */
+@Mapper
+public interface OrderPolicyMapper extends BaseMapperX<OrderPolicyDO> {
+
+    default PageResult<OrderPolicyDO> selectPage(OrderPolicyPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<OrderPolicyDO>()
+                .eqIfPresent(OrderPolicyDO::getOrderId, reqVO.getOrderId())
+                .eqIfPresent(OrderPolicyDO::getOrderNo, reqVO.getOrderNo())
+                .eqIfPresent(OrderPolicyDO::getPolicyId, reqVO.getPolicyId())
+                .eqIfPresent(OrderPolicyDO::getPreUseNum, reqVO.getPreUseNum())
+                .eqIfPresent(OrderPolicyDO::getRealUseNum, reqVO.getRealUseNum())
+                .eqIfPresent(OrderPolicyDO::getAmount, reqVO.getAmount())
+                .betweenIfPresent(OrderPolicyDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(OrderPolicyDO::getId));
+    }
+
+    default void deleteByOrderId(Long orderId) {
+        delete(new LambdaQueryWrapperX<OrderPolicyDO>().eq(OrderPolicyDO::getOrderId, orderId));
+    }
+}

+ 1 - 1
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/insurance/InsuranceService.java

@@ -54,7 +54,7 @@ public interface InsuranceService {
     /**
      * 取消投保
      */
-    void applyCancelInsurance(List<Long> insuranceIdList);
+    void applyCancelInsurance(Long orderId);
 
     /**
      * 查询电子保单

+ 34 - 80
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/insurance/InsuranceServiceImpl.java

@@ -16,9 +16,7 @@ import com.yc.ship.framework.mybatis.core.util.MyBatisUtils;
 import com.yc.ship.module.infra.api.config.ConfigApi;
 import com.yc.ship.module.product.dal.dataobject.voyage.VoyageDO;
 import com.yc.ship.module.product.service.voyage.VoyageService;
-import com.yc.ship.module.trade.api.insurance.dto.InsuranceApplyReqDTO;
-import com.yc.ship.module.trade.api.insurance.dto.InsuranceOrderInfoDTO;
-import com.yc.ship.module.trade.api.insurance.dto.InsuredDTO;
+import com.yc.ship.module.trade.api.insurance.dto.*;
 import com.yc.ship.module.trade.controller.admin.insurance.vo.InsuranceData;
 import com.yc.ship.module.trade.controller.admin.insurance.vo.InsurancePageReqVO;
 import com.yc.ship.module.trade.controller.admin.insurance.vo.InsuranceRespVO;
@@ -228,89 +226,45 @@ public class InsuranceServiceImpl implements InsuranceService {
     /**
      * 退保
      *
-     * @param orderIdList
+     * @param orderId
      */
     @Override
     @Transactional
-    public void applyCancelInsurance(List<Long> orderIdList) {
-        try {
-            List<InsuranceDO> insuranceList = this.getInsuranceByOrder(orderIdList);
-            if (CollUtil.isNotEmpty(insuranceList)) {
-                for (InsuranceDO insuranceDB : insuranceList) {
-
-                    JSONObject head = this.getCommonHead(insuranceDB.getRationType(), insuranceDB.getRiskCode(), "SURRENDER");
-                    JSONObject cancelInsurance = new JSONObject();
-                    //订单号
-                    cancelInsurance.set("orderNo", insuranceDB.getInsuranceNo());
-                    //要进行注销的保单号
-                    cancelInsurance.set("policyNo", insuranceDB.getPolicyNo());
-                    //渠道标识
-                    cancelInsurance.set("sysFlag", configApi.getConfigValueByKey("insurance.sysflag"));
-                    //交易码
-                    cancelInsurance.set("taCode", configApi.getConfigValueByKey("insurance.taCode"));
-                    //保单退保时间
-                    cancelInsurance.set("surrenderTime", System.currentTimeMillis() + "");
-                    cancelInsurance.set("centerFlag", "JDX");
-                    List<JSONObject> writeOffPolicys = new ArrayList<>();
-                    writeOffPolicys.add(cancelInsurance);
-
-                    JSONObject request = new JSONObject();
-                    request.set("head", head);
-                    request.set("writeOffPolicys", writeOffPolicys);
-
-                    JSONObject insuranceRequest = new JSONObject();
-                    insuranceRequest.set("appKey", configApi.getConfigValueByKey("insurance.appKey"));
-                    insuranceRequest.set("timestamp", System.currentTimeMillis() + "");
-                    insuranceRequest.set("serviceName", "writeOff");
-                    insuranceRequest.set("version", configApi.getConfigValueByKey("insurance.version"));
-                    insuranceRequest.set("encryptType", ENCRYPT_TYPE);
-                    insuranceRequest.set("bizContent", JSONUtil.toJsonStr(request));
-                    String publicKey = configApi.getConfigValueByKey("insurance.publicKey");
-                    String privateKey = configApi.getConfigValueByKey("insurance.privateKey");
-                    //加密加签
-                    InsuranceRequestHelper.encryptAndSign(insuranceRequest, publicKey, privateKey);
-                    String url = configApi.getConfigValueByKey("insurance.url");
-
-                    RLock lock = redissonClient.getLock(INSURANCE_CANCEL_KEY + insuranceDB.getOrderId());
-                    try {
-                        if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
-                            log.error("保险开具申请 data=" + JSONUtil.toJsonStr(insuranceRequest));
-                            String result = HttpUtil.createPost(url + "/writeOff").contentType("application/json").body(JSONUtil.toJsonStr(insuranceRequest)).timeout(15000).execute().body();
-                            log.error("保险开具申请 result=" + result);
-                            JSONObject insuranceResponse = JSONUtil.parseObj(result);
-                            InsuranceRequestHelper.checkSignAndDecrypt(insuranceResponse, publicKey, privateKey);
-                            // 0:失败 1:成功
-                            if (insuranceResponse != null && "200".equals(insuranceResponse.get("code"))) {
-                                String data = insuranceResponse.get("data").toString();
-                                if (data != null) {
-                                    InsuranceData insuranceData = JSONUtil.toBean(data, InsuranceData.class);
-
-                                    if (insuranceData != null && "SUCCESS".equalsIgnoreCase(insuranceData.getHccResults().get(0).getCode())) {
-                                        insuranceDB.setInsuranceStatus(InsuranceStatusEnum.CANCELLED.getValue());
-                                        insuranceMapper.updateById(insuranceDB);
-                                    }
-                                }
-                            }
+    public void applyCancelInsurance(Long orderId) {
+        TradeOrderRespVO orderInfo = tradeOrderMapper.getOrderInfo(orderId);
+        VoyageDO voyage = voyageService.getVoyage(orderInfo.getVoyageId());
 
-                        } else {
-                            log.error("保险取消异常:未获取到锁" );
-                            throw exception(INSURE_CANCEL_FAILED);
-                        }
-                    } catch (Exception e) {
-                        log.error("保险取消异常,:", e);
-                        throw exception(INSURE_CANCEL_FAILED);
-                    } finally {
-                        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
-                            lock.unlock();
-                        }
-                    }
+        //获取投保记录,投保保单号
+        InsuranceDO insuranceDO = insuranceMapper.selectByOrderId(orderId);
 
-                }
-            }
+        InsuranceCancelReqDTO insuranceCancelReqDTO = new InsuranceCancelReqDTO();
+        insuranceCancelReqDTO.setService("cancel");
+        insuranceCancelReqDTO.setReplyUrl(notifyUrl);
 
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw exception(INSURE_CANCEL_FAILED);
+        //订单对象, 一个订单下可以有一批被保险人
+        InsuranceOrderInfoCancelDTO insuranceOrderInfoDTO = new InsuranceOrderInfoCancelDTO();
+
+        insuranceOrderInfoDTO.setExternalOrderNo(orderInfo.getOrderNo());
+        insuranceOrderInfoDTO.setBeginDate(DateUtil.format(voyage.getBoardingTime(), "yyyy-MM-dd"));
+        insuranceOrderInfoDTO.setEndDate(DateUtil.format(voyage.getLeaveTime(), "yyyy-MM-dd"));
+        insuranceCancelReqDTO.setOrder(insuranceOrderInfoDTO);
+
+        List<InsuredCancelDTO> insuredList = new ArrayList<>();
+        InsuredCancelDTO insuredDTO = new InsuredCancelDTO();
+        insuredDTO.setExternalPolicyNumber(orderInfo.getId().toString());
+        insuredDTO.setPolicyNum(insuranceDO.getPolicyNo());
+        insuredList.add(insuredDTO);
+        insuranceCancelReqDTO.setInsureds(insuredList);
+
+        //验证投保信息
+//        CommonResult commonResult = insuranceUtil.validateInsuranceRequest(insuranceApplyReqDTO);
+//        if(!commonResult.isSuccess()) {
+//            throw exception0(commonResult.getCode(),commonResult.getMsg());
+//        }
+        // 开始投保
+        CommonResult commonResult = insuranceUtil.sendInsuranceCancel(insuranceCancelReqDTO);
+        if(!commonResult.isSuccess()) {
+            throw exception0(commonResult.getCode(),commonResult.getMsg());
         }
     }
 

+ 11 - 2
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/notify/NotifyServiceImpl.java

@@ -1,6 +1,7 @@
 package com.yc.ship.module.trade.service.notify;
 
 import cn.hutool.core.date.LocalDateTimeUtil;
+import com.yc.ship.framework.common.util.date.DateUtils;
 import com.yc.ship.module.trade.controller.admin.notify.vo.NotifyInsuranceReqVO;
 import com.yc.ship.module.trade.dal.dataobject.insurance.InsuranceDO;
 import com.yc.ship.module.trade.dal.mysql.insurance.InsuranceMapper;
@@ -8,6 +9,8 @@ import com.yc.ship.module.trade.enums.InsuranceStatusEnum;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 
 /**
  * 第三方调用通知的具体处理业务
@@ -25,12 +28,18 @@ public class NotifyServiceImpl implements NotifyService {
         String downloadUrl = reqVO.getDownloadUrl();
         String successDate = reqVO.getSuccessDate();
         Long orderId = Long.valueOf(externalPolicyNumber);
+        String service = reqVO.getService();
         if("SUCCESS".equals(status)) {
             InsuranceDO insuranceDO = insuranceMapper.selectByOrderId(orderId);
             insuranceDO.setPolicyNo(policyNo);
             insuranceDO.setElectronicPolicy(downloadUrl);
-            insuranceDO.setInsuranceStatus(InsuranceStatusEnum.SUCCESS.getValue());
-            insuranceDO.setInsuranceEffectDate(LocalDateTimeUtil.parse(successDate));
+            if("applyTeam".equals(service)) {
+                insuranceDO.setInsuranceStatus(InsuranceStatusEnum.SUCCESS.getValue());
+            }else if ("cancel".equals(service)) {
+                insuranceDO.setInsuranceStatus(InsuranceStatusEnum.CANCELLED.getValue());
+            }
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+            insuranceDO.setInsuranceEffectDate(LocalDateTime.parse(successDate,formatter));
             insuranceMapper.updateById(insuranceDO);
         }
         return true;

+ 55 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/orderpolicy/OrderPolicyService.java

@@ -0,0 +1,55 @@
+package com.yc.ship.module.trade.service.orderpolicy;
+
+import java.util.*;
+import javax.validation.*;
+import com.yc.ship.module.trade.controller.admin.orderpolicy.vo.*;
+import com.yc.ship.module.trade.dal.dataobject.orderpolicy.OrderPolicyDO;
+import com.yc.ship.framework.common.pojo.PageResult;
+import com.yc.ship.framework.common.pojo.PageParam;
+
+/**
+ * 订单使用的优惠政策 Service 接口
+ *
+ * @author 管理员
+ */
+public interface OrderPolicyService {
+
+    /**
+     * 创建订单使用的优惠政策
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createOrderPolicy(@Valid OrderPolicySaveReqVO createReqVO);
+
+    /**
+     * 更新订单使用的优惠政策
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateOrderPolicy(@Valid OrderPolicySaveReqVO updateReqVO);
+
+    /**
+     * 删除订单使用的优惠政策
+     *
+     * @param id 编号
+     */
+    void deleteOrderPolicy(Long id);
+
+    /**
+     * 获得订单使用的优惠政策
+     *
+     * @param id 编号
+     * @return 订单使用的优惠政策
+     */
+    OrderPolicyDO getOrderPolicy(Long id);
+
+    /**
+     * 获得订单使用的优惠政策分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 订单使用的优惠政策分页
+     */
+    PageResult<OrderPolicyDO> getOrderPolicyPage(OrderPolicyPageReqVO pageReqVO);
+
+}

+ 64 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/orderpolicy/OrderPolicyServiceImpl.java

@@ -0,0 +1,64 @@
+package com.yc.ship.module.trade.service.orderpolicy;
+
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import com.yc.ship.module.trade.controller.admin.orderpolicy.vo.*;
+import com.yc.ship.module.trade.dal.dataobject.orderpolicy.OrderPolicyDO;
+import com.yc.ship.framework.common.pojo.PageResult;
+import com.yc.ship.framework.common.pojo.PageParam;
+import com.yc.ship.framework.common.util.object.BeanUtils;
+
+import com.yc.ship.module.trade.dal.mysql.orderpolicy.OrderPolicyMapper;
+
+import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static com.yc.ship.module.trade.enums.ErrorCodeConstants.*;
+
+/**
+ * 订单使用的优惠政策 Service 实现类
+ *
+ * @author 管理员
+ */
+@Service
+@Validated
+public class OrderPolicyServiceImpl implements OrderPolicyService {
+
+    @Resource
+    private OrderPolicyMapper orderPolicyMapper;
+
+    @Override
+    public Long createOrderPolicy(OrderPolicySaveReqVO createReqVO) {
+        // 插入
+        OrderPolicyDO orderPolicy = BeanUtils.toBean(createReqVO, OrderPolicyDO.class);
+        orderPolicyMapper.insert(orderPolicy);
+        // 返回
+        return orderPolicy.getId();
+    }
+
+    @Override
+    public void updateOrderPolicy(OrderPolicySaveReqVO updateReqVO) {
+        // 更新
+        OrderPolicyDO updateObj = BeanUtils.toBean(updateReqVO, OrderPolicyDO.class);
+        orderPolicyMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteOrderPolicy(Long id) {
+        // 删除
+        orderPolicyMapper.deleteById(id);
+    }
+
+    @Override
+    public OrderPolicyDO getOrderPolicy(Long id) {
+        return orderPolicyMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<OrderPolicyDO> getOrderPolicyPage(OrderPolicyPageReqVO pageReqVO) {
+        return orderPolicyMapper.selectPage(pageReqVO);
+    }
+
+}

+ 66 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/impl/OtcTradeOrderServiceImpl.java

@@ -37,6 +37,7 @@ import com.yc.ship.framework.tenant.core.aop.TenantIgnore;
 import com.yc.ship.framework.tenant.core.context.TenantContextHolder;
 import com.yc.ship.framework.tenant.core.util.TenantUtils;
 import com.yc.ship.module.infra.api.config.ConfigApi;
+import com.yc.ship.module.marketing.api.policy.PolicyApi;
 import com.yc.ship.module.member.api.address.MemberAddressApi;
 import com.yc.ship.module.member.api.user.MemberUserApi;
 import com.yc.ship.module.member.api.user.dto.MemberUserRespDTO;
@@ -82,12 +83,14 @@ import com.yc.ship.module.trade.dal.dataobject.insurance.InsuranceDO;
 import com.yc.ship.module.trade.dal.dataobject.invoice.InvoiceDO;
 import com.yc.ship.module.trade.dal.dataobject.order.*;
 import com.yc.ship.module.trade.dal.dataobject.orderjz.OrderJzDO;
+import com.yc.ship.module.trade.dal.dataobject.orderpolicy.OrderPolicyDO;
 import com.yc.ship.module.trade.dal.dataobject.tradeOrderaudit.TradeOrderAuditDO;
 import com.yc.ship.module.trade.dal.mysql.audituser.AuditUserMapper;
 import com.yc.ship.module.trade.dal.mysql.contract.ContractMapper;
 import com.yc.ship.module.trade.dal.mysql.insurance.InsuranceMapper;
 import com.yc.ship.module.trade.dal.mysql.order.*;
 import com.yc.ship.module.trade.dal.mysql.orderjz.OrderJzMapper;
+import com.yc.ship.module.trade.dal.mysql.orderpolicy.OrderPolicyMapper;
 import com.yc.ship.module.trade.dal.mysql.tradeOrderaudit.TradeOrderAuditMapper;
 import com.yc.ship.module.trade.enums.*;
 import com.yc.ship.module.trade.framework.annotation.TradeOrderLog;
@@ -96,6 +99,7 @@ import com.yc.ship.module.trade.framework.common.TradeOrderLogUtils;
 import com.yc.ship.module.trade.service.invoice.InvoiceService;
 import com.yc.ship.module.trade.service.order.TradeOrderRepositoryService;
 import com.yc.ship.module.trade.service.order.TradeOrderService;
+import com.yc.ship.module.trade.service.orderpolicy.OrderPolicyService;
 import com.yc.ship.module.trade.service.otc.OtcTradeOrderService;
 import com.yc.ship.module.trade.service.pay.TradeOrderPayService;
 import com.yc.ship.module.trade.service.refund.TradeRefundRepositoryService;
@@ -231,6 +235,12 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
     @Resource
     private VoyageApi voyageApi;
 
+    @Resource
+    private OrderPolicyMapper orderPolicyMapper;
+
+    @Resource
+    private PolicyApi policyApi;
+
     @Resource
     private RedissonClient redissonClient;
 
@@ -1491,6 +1501,34 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                 tradeOrderRoomDOList.add(tradeOrderRoomDO);
             });
 
+            // 创建订单优惠政策数据
+            //1.先删除原来的
+            orderPolicyMapper.deleteByOrderId(orderId);
+            List<OrderPolicyDO> orderPolicyDOList = new ArrayList<>();
+            List<TradeOrderPolicyReqVO> policyList = createVO.getPolicyList();
+            policyList.stream().forEach(policy -> {
+                OrderPolicyDO orderPolicyDO = new OrderPolicyDO();
+                orderPolicyDO.setOrderId(orderId);
+                orderPolicyDO.setOrderNo(orderNo);
+                orderPolicyDO.setPolicyId(policy.getPolicyId());
+                if(createVO.getIsYd() != null && createVO.getIsYd() == 1) {
+                    orderPolicyDO.setPreUseNum(policy.getUseNum());
+                    orderPolicyDO.setRealUseNum(BigDecimal.ZERO);
+                }else {
+                    //TODO: 需要修改订单金额,参考文档
+                    orderPolicyDO.setPreUseNum(BigDecimal.ZERO);
+                    orderPolicyDO.setRealUseNum(policy.getUseNum());
+                    policyApi.updatePolicySurplusNum(policy.getPolicyId(), policy.getUseNum());
+                }
+                orderPolicyDO.setAmount(policy.getAmount());
+                orderPolicyDO.setRooms(policy.getRooms());
+                orderPolicyDOList.add(orderPolicyDO);
+            });
+            if(orderPolicyDOList.size() > 0) {
+                //TODO: 判断优惠政策是否需要审核
+                orderPolicyMapper.insertBatch(orderPolicyDOList);
+            }
+
             int auditType = 0;
             BigDecimal leaderTotalMoney = summary.getLeaderTotalMoney();
             if (leaderTotalMoney != null && leaderTotalMoney.compareTo(new BigDecimal(0)) > 0) {
@@ -1766,6 +1804,34 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
                 tradeOrderRoomModelMapper.insertBatch(list);
             }
 
+            // 创建订单优惠政策数据
+            //1.先删除原来的
+            orderPolicyMapper.deleteByOrderId(orderId);
+            List<OrderPolicyDO> orderPolicyDOList = new ArrayList<>();
+            List<TradeOrderPolicyReqVO> policyList = createVO.getPolicyList();
+            policyList.stream().forEach(policy -> {
+                OrderPolicyDO orderPolicyDO = new OrderPolicyDO();
+                orderPolicyDO.setOrderId(orderId);
+                orderPolicyDO.setOrderNo(orderNo);
+                orderPolicyDO.setPolicyId(policy.getPolicyId());
+                if(tradeOrderDO.getOrderStatus() == TradeOrderStatusEnum.UNPAID.getStatus() || tradeOrderDO.getOrderStatus() == TradeOrderStatusEnum.UNPAID.getStatus()) {
+                    orderPolicyDO.setRealUseNum(policy.getUseNum());
+                    orderPolicyDO.setPreUseNum(BigDecimal.ZERO);
+                    policyApi.updatePolicySurplusNum(policy.getPolicyId(), policy.getUseNum());
+                    //TODO: 需要修改订单金额,参考文档
+                }else {
+                    orderPolicyDO.setRealUseNum(BigDecimal.ZERO);
+                    orderPolicyDO.setPreUseNum(policy.getUseNum());
+                }
+                orderPolicyDO.setAmount(policy.getAmount());
+                orderPolicyDO.setRooms(policy.getRooms());
+                orderPolicyDOList.add(orderPolicyDO);
+            });
+            if(orderPolicyDOList.size() > 0) {
+                //TODO: 判断优惠政策是否需要审核
+                orderPolicyMapper.insertBatch(orderPolicyDOList);
+            }
+
             OtcTradeOrderCreateRespVO respVO = TradeOrderConvert.INSTANCE.convert(result.getData());
             return CommonResult.success(respVO, msg);
         } finally {

+ 131 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/InsuranceUtil.java

@@ -3,6 +3,7 @@ package com.yc.ship.module.trade.utils;
 import com.alibaba.fastjson.JSONObject;
 import com.yc.ship.framework.common.pojo.CommonResult;
 import com.yc.ship.module.trade.api.insurance.dto.InsuranceApplyReqDTO;
+import com.yc.ship.module.trade.api.insurance.dto.InsuranceCancelReqDTO;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.*;
 import org.springframework.stereotype.Component;
@@ -29,6 +30,8 @@ public class InsuranceUtil {
 
     public final String RECEIVE_URL = "/policy/receiveJson.do"; // JSON投/退保接口
 
+    public final String QUERY_URL = "/policy/querystatus.do"; // 保单状态查询接口
+
     public final String APPID = "123456";   // appId
 
     public final String KEY = "goldpalm"; // key
@@ -187,4 +190,132 @@ public class InsuranceUtil {
             throw exception0(500,"发送校验请求失败: " + e.getMessage(), e);
         }
     }
+
+    /**
+     * 发送退保请求
+     * 将退保请求发送到阳光系统
+     * @param request 退保请求
+     * @return 退保响应
+     */
+    public CommonResult sendInsuranceCancel(InsuranceCancelReqDTO request) {
+        try {
+            String reqJson = JSONObject.toJSONString(request);
+            String sign = SignUtil.generateMD5Sign(APPID, reqJson, KEY);
+
+            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+            params.add("appId", APPID);
+            params.add("req", reqJson);
+            params.add("sign", sign);
+
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+            HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
+
+            log.info("发送退保请求到阳光系统: {}", HOST + RECEIVE_URL);
+            log.info("请求参数: appId={}, req={}, sign={}", APPID, reqJson, sign);
+
+            // 发送请求并获取响应
+            ResponseEntity<byte[]> response = restTemplate.exchange(
+                    HOST + RECEIVE_URL,
+                    HttpMethod.POST,
+                    entity,
+                    byte[].class
+            );
+
+            log.info("阳光系统响应状态码: {}", response.getStatusCode());
+
+            // 手动处理响应字节流,确保使用UTF-8编码
+            byte[] responseBytes = response.getBody();
+            String responseBody = null;
+            if (responseBytes != null) {
+                try {
+                    responseBody = new String(responseBytes, "UTF-8");
+                } catch (UnsupportedEncodingException e) {
+                    log.error("解析响应内容编码失败", e);
+                    responseBody = new String(responseBytes);
+                }
+            }
+
+            log.info("阳光系统响应内容: {}", responseBody);
+            JSONObject responseBodyJson = JSONObject.parseObject(responseBody);
+
+            if (response.getStatusCode() == HttpStatus.OK) {
+                String status = responseBodyJson.getString("status");
+                if("FAIL".equals(status)) {
+                    return CommonResult.error(500, "阳光系统退保返回错误: " + response.getStatusCode() + responseBody);
+                }else {
+                    return CommonResult.success(responseBody);
+                }
+            } else {
+                return CommonResult.error(500, "阳光系统退保返回错误: " + response.getStatusCode() + responseBody);
+            }
+
+        } catch (Exception e) {
+            log.error("发送退保请求失败", e);
+            return CommonResult.error(500,"发送退保请求失败: " + e.getMessage());
+        }
+    }
+
+    public CommonResult queryInsurance(String orderNo) {
+        try {
+            JSONObject request = new JSONObject();
+            request.put("externalOrderNo", orderNo);
+            String reqJson = JSONObject.toJSONString(request);
+            String sign = SignUtil.generateMD5Sign(APPID, reqJson, KEY);
+
+            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+            params.add("appId", APPID);
+            params.add("req", reqJson);
+            params.add("sign", sign);
+
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+            HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
+
+            log.info("发送退保请求到阳光系统: {}", HOST + RECEIVE_URL);
+            log.info("请求参数: appId={}, req={}, sign={}", APPID, reqJson, sign);
+
+            // 发送请求并获取响应
+            ResponseEntity<byte[]> response = restTemplate.exchange(
+                    HOST + RECEIVE_URL,
+                    HttpMethod.POST,
+                    entity,
+                    byte[].class
+            );
+
+            log.info("阳光系统响应状态码: {}", response.getStatusCode());
+
+            // 手动处理响应字节流,确保使用UTF-8编码
+            byte[] responseBytes = response.getBody();
+            String responseBody = null;
+            if (responseBytes != null) {
+                try {
+                    responseBody = new String(responseBytes, "UTF-8");
+                } catch (UnsupportedEncodingException e) {
+                    log.error("解析响应内容编码失败", e);
+                    responseBody = new String(responseBytes);
+                }
+            }
+
+            log.info("阳光系统响应内容: {}", responseBody);
+            JSONObject responseBodyJson = JSONObject.parseObject(responseBody);
+
+            if (response.getStatusCode() == HttpStatus.OK) {
+                String status = responseBodyJson.getString("status");
+                if("FAIL".equals(status)) {
+                    return CommonResult.error(500, "阳光系统退保返回错误: " + response.getStatusCode() + responseBody);
+                }else {
+                    return CommonResult.success(responseBody);
+                }
+            } else {
+                return CommonResult.error(500, "阳光系统退保返回错误: " + response.getStatusCode() + responseBody);
+            }
+
+        } catch (Exception e) {
+            log.error("发送退保请求失败", e);
+            return CommonResult.error(500,"发送退保请求失败: " + e.getMessage());
+        }
+    }
 }

+ 46 - 4
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/utils/SignUtil.java

@@ -1,11 +1,15 @@
 package com.yc.ship.module.trade.utils;
 
+import com.alibaba.fastjson.JSONObject;
 import com.anji.captcha.util.MD5Util;
+import com.yc.ship.framework.common.util.http.HttpUtils;
+import org.springframework.http.*;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import java.io.UnsupportedEncodingException;
+import java.util.*;
 
 /**
  * 签名工具类
@@ -34,6 +38,14 @@ public class SignUtil {
             throw new RuntimeException("生成MD5签名失败", e);
         }
     }
+
+    public static String generateMD5Sign(Map<String, String> map) {
+        try {
+            return generateMD5Sign(map);
+        } catch (Exception e) {
+            throw new RuntimeException("生成MD5签名失败", e);
+        }
+    }
     
     /**
      * 生成MD5签名
@@ -96,4 +108,34 @@ public class SignUtil {
         String calculatedSign = generateMD5Sign(appId, req, key);
         return calculatedSign.equalsIgnoreCase(sign);
     }
+
+    public static void main(String[] args) {
+        String HOST = "https://lbb-admin.anyitech.ltd";
+        String QUERY_URL = "/policy/querystatus.do"; // 保单状态查询接口
+        RestTemplate restTemplate = new RestTemplate();
+        String orderNo = "lfy001-20260521-YC-1";
+        String APPID = "123456";   // appId
+        String KEY = "goldpalm"; // key
+        Map<String, String> request = new LinkedHashMap<>();
+        request.put("appId", APPID);
+        request.put("externalOrderNo", orderNo);
+        request.put("key", KEY);
+        String sign = MD5Util.md5(APPID+orderNo+KEY);
+
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+        params.add("appId", APPID);
+        params.add("externalOrderNo", orderNo);
+        params.add("sign", sign);
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+
+        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
+
+        String url = HOST + QUERY_URL + "?appId=" + APPID + "&externalOrderNo=" + orderNo + "&sign=" + sign;
+
+        String s = HttpUtils.get(url, null);
+        System.out.println(s);
+
+    }
 }

+ 2 - 1
ship-server-web/src/main/resources/application.yaml

@@ -293,7 +293,7 @@ yudao:
       - /travl-app-api/trade/payNotify
       - /travl-app-api/trade/refundNotify
       - /travl-app-api/system/sms/callback/aliyun
-      - /${yudao.web.admin-url}/notify/** # 统一消息服务,接收消息的接口,不需要登录
+      - /${yudao.web.admin-url}/notify/* # 统一消息服务,接收消息的接口,不需要登录
     ignore-visit-urls:
       - /admin-api/system/user/profile/**
     ignore-tables:
@@ -322,6 +322,7 @@ yudao:
       - trade_order_jz
       - ota_distributor_region
       - ota_region
+      - trade_insurance
     ignore-caches:
       - user_role_ids
       - permission_menu_ids