Răsfoiți Sursa

Merge branch 'sora_code_func'

zoujiajian 10 luni în urmă
părinte
comite
5692138e87

+ 14 - 0
netflix-dao/src/main/java/com/cyksj/mapper/SoraCodeMapper.java

@@ -0,0 +1,14 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.SoraCode;
+
+/**
+ * sora邀请码Mapper接口
+ *
+ * @author system
+ * @date 2025-10-13
+ */
+public interface SoraCodeMapper extends BaseMapper<SoraCode> {
+
+}

+ 37 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/SoraCode.java

@@ -0,0 +1,37 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * sora邀请码实体类
+ *
+ * @author system
+ * @date 2025-10-13
+ */
+@Getter
+@Setter
+@TableName("sora_code")
+public class SoraCode extends BaseEntity {
+
+    /**
+     * 邀请码
+     */
+    private String code;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 订单ID
+     */
+    private Long orderId;
+
+    /**
+     * 使用状态:0-未使用,1-已使用
+     */
+    private Boolean status;
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelSoraCodeData.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ExcelSoraCodeData
+ * 创建者: JavaZou
+ * 创建时间:2025/10/13 18:07
+ */
+@Getter
+@Setter
+public class ExcelSoraCodeData {
+	@ExcelProperty("邀请码")
+	private String code;
+}

+ 20 - 0
netflix-dao/src/main/java/com/cyksj/model/request/SoraCodeAddReq.java

@@ -0,0 +1,20 @@
+package com.cyksj.model.request;
+
+import lombok.Data;
+import javax.validation.constraints.NotBlank;
+
+/**
+ * SoraCode添加请求
+ *
+ * @author system
+ * @date 2025-10-13
+ */
+@Data
+public class SoraCodeAddReq {
+
+    /**
+     * 邀请码
+     */
+    @NotBlank(message = "邀请码不能为空")
+    private String code;
+}

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/request/SoraCodeUpdateReq.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.request;
+
+import lombok.Data;
+import javax.validation.constraints.NotNull;
+
+/**
+ * SoraCode更新请求
+ *
+ * @author system
+ * @date 2025-10-13
+ */
+@Data
+public class SoraCodeUpdateReq {
+
+    /**
+     * ID
+     */
+    @NotNull(message = "ID不能为空")
+    private Long id;
+
+    /**
+     * 邀请码
+     */
+    private String code;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 订单ID
+     */
+    private Long orderId;
+
+    /**
+     * 使用状态
+     */
+    private Boolean status;
+}

+ 4 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java

@@ -216,9 +216,13 @@ public class RenewalView {
 
     @DbIgnore
     private String orderNo;
+
     @DbIgnore
     private Long orderId;
 
+    @DbIgnore
+    private Date orderCreatedTime;
+
     @DbIgnore
     private String transactionId;
 

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -103,12 +103,14 @@ import com.cyksj.service.relation.GroupsRelationExpiryRecordService;
 import com.cyksj.service.relation.GroupsRelationNetflixService;
 import com.cyksj.service.shop.YhShopDistributeService;
 import com.cyksj.service.shop.YhShopFrontService;
+import com.cyksj.service.sora.SoraCodeFrontService;
 import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.service.telegram.TelegramService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.user.UserBenefitsService;
 import com.cyksj.service.user.UserBindRelationService;
 import com.cyksj.service.user.UserCommonService;
+import com.cyksj.service.sora.SoraCodeService;
 import com.cyksj.service.wechat.WeChatService;
 import com.cyksj.task.JobManager;
 import com.ejlchina.searcher.BeanSearcher;
@@ -403,6 +405,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final CodexUserMapper codexUserMapper;
 
+	private final SoraCodeFrontService soraCodeFrontService;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -3287,6 +3291,13 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//GPT独立会员续费 若为代充类型 同步代充次数
 		if (orderDon.getGoodsId() == Constant.GPT_PLUS_GID && sku.getNum() == 1) {
 			incrGroupsRelationRechargeRemainIfRecharge(orderDon.getRelationId(), sku.getMonths(), orderDon.getOrderType());
+			
+			// GPT独立会员购买,赠送sora邀请码
+			try {
+				soraCodeFrontService.grantSoraCodeForGptMember(orderDon.getUserId(), orderDon.getId());
+			} catch (Exception e) {
+				log.error("为GPT独立会员用户{}订单{}赠送sora邀请码失败", orderDon.getUserId(), orderDon.getId(), e);
+			}
 		}
 
 		//查看该订单是否有关闭的余额

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java

@@ -117,4 +117,6 @@ public interface GroupRelationFrontService {
 	TicketRenewUpgradeView getRenewUpgradeInfo(long userId, Long relationId);
 
 	void netflixSubmitFrozen(ErrorNetflixChangeReq req);
+
+	String getSoraCode(Long userId, Long relationId);
 }

+ 52 - 0
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -59,6 +59,7 @@ import com.cyksj.service.order.OrderRefundService;
 import com.cyksj.service.relation.GroupRelationClearService;
 import com.cyksj.service.relation.GroupRelationFrontService;
 import com.cyksj.service.relation.GroupsRelationChangeService;
+import com.cyksj.service.sora.SoraCodeFrontService;
 import com.cyksj.service.translations.BackInfoTranslationsFrontService;
 import com.cyksj.service.user.UserBenefitsService;
 import com.cyksj.service.user.UserBindRelationService;
@@ -223,6 +224,10 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final AccountNetflixFrozenTicketReceivedRecordMapper accountNetflixFrozenTicketReceivedRecordMapper;
 
+	private final SoraCodeMapper soraCodeMapper;
+
+	private final SoraCodeFrontService soraCodeFrontService;
+
 	@Override
 	public SearchResult<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize, String customId, String account, String orderNo, Integer cmt) {
 		User u = userMapper.selectById(userId);
@@ -371,6 +376,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 					ticket.setOrderNo(orderDon.getOrderNo());
 					ticket.setOrderId(orderDon.getId());
 					ticket.setTransactionId(orderDon.getTransactionId());
+					ticket.setOrderCreatedTime(orderDon.getCreatedTime());
 					if (ticket.getSecondType() == 1) {
 						//是否完成邀请 根据订单状态
 						ticket.setIsComplete(orderDon.getStatus() == OrderDon.Status.complete ? true : false);
@@ -2145,6 +2151,52 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		}
 	}
 
+	@Override
+	public String getSoraCode(Long userId, Long relationId) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		GroupsRelation relation = groupsRelationMapper.selectById(relationId);
+		if (relation == null) {
+			throw BusinessRuntimeException.getInstance("车票不存在");
+		}
+		if (!userIdList.contains(relation.getUserId())) {
+			throw BusinessRuntimeException.getInstance("车票不存在");
+		}
+		if (relation.getStatus() != GroupsRelation.Status.validity) {
+			throw BusinessRuntimeException.getInstance("车票不存在");
+		}
+		if (relation.getExpiryTime() != null && relation.getExpiryTime().before(DateTime.now())) {
+			throw BusinessRuntimeException.getInstance("车票已过期");
+		}
+
+		GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
+
+		GoodsDonSku sku = goodsDonSkuMapper.selectById(groupsTrips.getSkuId());
+
+		//非GPT独立
+		if (sku.getGoodsId() != Constant.GPT_PLUS_GID || sku.getNum() != 1) {
+			throw BusinessRuntimeException.getInstance("非GPT独立会员车票");
+		}
+
+		OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class).in(OrderDon::getUserId, userIdList).eq(OrderDon::getRelationId, relationId).notIn(OrderDon::getStatus, Constant.noOrderAllStatus).orderByDesc(OrderDon::getId).last("limit 1"));
+
+		SoraCode soraCode = soraCodeMapper.selectOne(Wrappers.lambdaQuery(SoraCode.class).eq(SoraCode::getOrderId, orderDon.getId()).last("limit 1"));
+		if (soraCode == null) {
+			try {
+				if (orderDon.getCreatedTime().before(DateUtil.parse("2025-10-14 17:30:00"))) {
+					throw BusinessRuntimeException.getInstance("系统异常");
+				}
+				soraCodeFrontService.grantSoraCodeForGptMember(relation.getUserId(), orderDon.getId());
+				soraCode = soraCodeMapper.selectOne(Wrappers.lambdaQuery(SoraCode.class).eq(SoraCode::getOrderId, orderDon.getId()).last("limit 1"));
+			} catch (Exception e) {
+
+			}
+		}
+		if (soraCode == null) {
+			throw BusinessRuntimeException.getInstance("暂无可用sora邀请码,请联系客服");
+		}
+		return soraCode.getCode();
+	}
+
 	private DistributePosterGoodsDetailView setGoodsPoster(RenewalView ticket, User user, List<Long> userIds) {
 		DistributePosterGoodsDetailView distributePosterGoodsDetailView = beanSearcher.searchFirst(DistributePosterGoodsDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
 				.field(DistributePosterGoodsFrontView::getGoodsId, ticket.getGoodsId()).build());

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/sora/SoraCodeFrontService.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.sora;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: SoraCodeFrontService
+ * 创建者: JavaZou
+ * 创建时间:2025/10/14 10:39
+ */
+public interface SoraCodeFrontService {
+	/**
+	 * 为GPT独立会员用户赠送sora邀请码
+	 *
+	 * @param userId 用户ID
+	 * @param orderId 订单ID
+	 */
+	void grantSoraCodeForGptMember(Long userId, Long orderId);
+}

+ 28 - 0
netflix-service/src/main/java/com/cyksj/service/sora/SoraCodeService.java

@@ -0,0 +1,28 @@
+package com.cyksj.service.sora;
+
+import com.cyksj.model.request.SoraCodeAddReq;
+import com.cyksj.model.request.SoraCodeUpdateReq;
+
+/**
+ * Sora邀请码Service接口
+ *
+ * @author system
+ * @date 2025-10-13
+ */
+public interface SoraCodeService {
+
+    /**
+     * 添加Sora邀请码
+     */
+    void addSoraCode(SoraCodeAddReq req);
+
+    /**
+     * 更新Sora邀请码
+     */
+    void updateSoraCode(SoraCodeUpdateReq req);
+
+    /**
+     * 删除Sora邀请码
+     */
+    void deleteSoraCode(Long id);
+}

+ 70 - 0
netflix-service/src/main/java/com/cyksj/service/sora/impl/SoraCodeFrontServiceImpl.java

@@ -0,0 +1,70 @@
+package com.cyksj.service.sora.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.SoraCodeMapper;
+import com.cyksj.model.entity.SoraCode;
+import com.cyksj.service.sora.SoraCodeFrontService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: SoraCodeFrontServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2025/10/14 10:40
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class SoraCodeFrontServiceImpl implements SoraCodeFrontService {
+	private final SoraCodeMapper soraCodeMapper;
+
+	@Override
+	public void grantSoraCodeForGptMember(Long userId, Long orderId) {
+		// 检查该用户是否已经通过此订单获得过sora邀请码
+		Integer existCount = soraCodeMapper.selectCount(
+				new LambdaQueryWrapper<SoraCode>()
+						.eq(SoraCode::getUserId, userId)
+						.eq(SoraCode::getOrderId, orderId)
+		);
+
+		if (existCount > 0) {
+			log.error("用户{}订单{}已赠送过sora邀请码,跳过重复赠送", userId, orderId);
+			return;
+		}
+
+		while (true) {
+			// 查找一个未使用的sora邀请码
+			SoraCode availableCode = soraCodeMapper.selectOne(
+					new LambdaQueryWrapper<SoraCode>()
+							.eq(SoraCode::getStatus, false)
+							.last("limit 1")
+			);
+
+			if (availableCode == null) {
+				log.error("没有可用的sora邀请码赠送给用户{},订单{}", userId, orderId);
+				throw new BusinessRuntimeException("暂无可用的sora邀请码");
+			}
+
+			// 将邀请码绑定给用户和订单
+			availableCode.setUserId(userId);
+			availableCode.setOrderId(orderId);
+			availableCode.setStatus(Boolean.TRUE);
+
+			try {
+				int updateResult = soraCodeMapper.update(availableCode, Wrappers.lambdaUpdate(SoraCode.class).eq(SoraCode::getId, availableCode.getId()).eq(SoraCode::getStatus, Boolean.FALSE));
+				if (updateResult > 0) {
+					log.info("成功为用户{}订单{}赠送sora邀请码:{}", userId, orderId, availableCode.getCode());
+					break;
+				}
+			} catch (Exception e) {
+				log.error("赠送sora邀请码失败,error->{}", StringUtil.getErrorText(e));
+				throw BusinessRuntimeException.getInstance("");
+			}
+		}
+	}
+}

+ 90 - 0
netflix-service/src/main/java/com/cyksj/service/sora/impl/SoraCodeServiceImpl.java

@@ -0,0 +1,90 @@
+package com.cyksj.service.sora.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.SoraCodeMapper;
+import com.cyksj.model.entity.SoraCode;
+import com.cyksj.model.request.SoraCodeAddReq;
+import com.cyksj.model.request.SoraCodeUpdateReq;
+import com.cyksj.service.sora.SoraCodeService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DataAccessException;
+import org.springframework.stereotype.Service;
+
+/**
+ * Sora邀请码Service实现类
+ *
+ * @author system
+ * @date 2025-10-13
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SoraCodeServiceImpl implements SoraCodeService {
+
+    private final SoraCodeMapper soraCodeMapper;
+
+    @Override
+    public void addSoraCode(SoraCodeAddReq req) {
+        // 检查邀请码是否已存在
+        Integer count = soraCodeMapper.selectCount(
+            new LambdaQueryWrapper<SoraCode>()
+                .eq(SoraCode::getCode, req.getCode())
+        );
+        if (count > 0) {
+            throw new BusinessRuntimeException("邀请码已存在");
+        }
+
+        SoraCode soraCode = new SoraCode();
+        soraCode.setCode(req.getCode());
+
+        try {
+            soraCodeMapper.insert(soraCode);
+        } catch (DataAccessException e) {
+
+        }
+    }
+
+    @Override
+    public void updateSoraCode(SoraCodeUpdateReq req) {
+        SoraCode soraCode = soraCodeMapper.selectById(req.getId());
+        if (soraCode == null) {
+            throw new BusinessRuntimeException("Sora邀请码不存在");
+        }
+
+        // 如果要更新邀请码,检查新邀请码是否已存在
+        if (StrUtil.isNotBlank(req.getCode()) && !req.getCode().equals(soraCode.getCode())) {
+            Integer count = soraCodeMapper.selectCount(
+                new LambdaQueryWrapper<SoraCode>()
+                    .eq(SoraCode::getCode, req.getCode())
+                    .ne(SoraCode::getId, req.getId())
+            );
+            if (count > 0) {
+                throw new BusinessRuntimeException("邀请码已存在");
+            }
+        }
+
+        SoraCode updateSoraCode = new SoraCode();
+        updateSoraCode.setId(req.getId());
+
+        if (StrUtil.isNotBlank(req.getCode())) {
+            updateSoraCode.setCode(req.getCode());
+        }
+
+        soraCodeMapper.updateById(updateSoraCode);
+    }
+
+    @Override
+    public void deleteSoraCode(Long id) {
+        SoraCode soraCode = soraCodeMapper.selectById(id);
+        if (soraCode == null) {
+            throw new BusinessRuntimeException("Sora邀请码不存在");
+        }
+        if (soraCode.getStatus()) {
+            throw BusinessRuntimeException.getInstance("Sora邀请码已使用,不可删除");
+        }
+        soraCodeMapper.deleteById(id);
+    }
+}

+ 10 - 0
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -1538,4 +1538,14 @@ public class GroupRelationController {
         }
         return GatewayResponse.SUCCESS.newBuilder().toResult(sysLogs);
     }
+
+    /**
+     * 查看sora邀请码
+     */
+    @GetMapping("/get/sora/code/{relationId}")
+    public Result<String> getSoraCode(@PathVariable Long relationId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        String soraCode = groupRelationFrontService.getSoraCode(userId, relationId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(soraCode);
+    }
 }

+ 122 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/sora/SoraCodeController.java

@@ -0,0 +1,122 @@
+package com.cyksj.web.controller.manage.sora;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.support.ExcelTypeEnum;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.SoraCodeMapper;
+import com.cyksj.model.entity.SoraCode;
+import com.cyksj.model.excel.ExcelSoraCodeData;
+import com.cyksj.model.request.SoraCodeAddReq;
+import com.cyksj.model.request.SoraCodeUpdateReq;
+import com.cyksj.service.sora.SoraCodeService;
+import com.cyksj.web.util.EasyExcelUtils;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DataAccessException;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Sora邀请码管理Controller
+ *
+ * @author system
+ * @date 2025-10-13
+ */
+@Slf4j
+@RestController
+@RequestMapping("/manage/sora-code")
+@RequiredArgsConstructor
+public class SoraCodeController {
+
+    private final SoraCodeService soraCodeService;
+
+    private final SoraCodeMapper soraCodeMapper;
+
+    private final BeanSearcher beanSearcher;
+
+    private final HttpServletRequest request;
+
+    /**
+     * 添加Sora邀请码
+     */
+    @PostMapping("/add")
+    public Result<String> addSoraCode(@RequestBody @Validated SoraCodeAddReq req) {
+        soraCodeService.addSoraCode(req);
+        return GatewayResponse.SUCCESS.newBuilder().toResult("添加成功");
+    }
+
+    /**
+     * 更新Sora邀请码
+     */
+    @PutMapping("/update")
+    public Result<String> updateSoraCode(@RequestBody @Validated SoraCodeUpdateReq req) {
+        soraCodeService.updateSoraCode(req);
+        return GatewayResponse.SUCCESS.newBuilder().toResult("更新成功");
+    }
+
+    /**
+     * 删除Sora邀请码
+     */
+    @DeleteMapping("/delete/{id}")
+    public Result<String> deleteSoraCode(@PathVariable Long id) {
+        soraCodeService.deleteSoraCode(id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");
+    }
+
+    /**
+     * 分页查询Sora邀请码
+     */
+    @GetMapping("/get")
+    public Result<SearchResult<SoraCode> > getSoraCodePage() {
+        SearchResult<SoraCode> search = beanSearcher.search(SoraCode.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+    /**
+     * 批量导入Sora邀请码模板
+     */
+    @GetMapping("/import/template")
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        EasyExcelUtils.createTemplateExcel(response, ExcelSoraCodeData.class, "Sora邀请码导入模板", "Sora邀请码导入模板", ExcelTypeEnum.XLSX, null);
+    }
+
+    /**
+     * 批量导入Sora邀请码
+     */
+    @PostMapping("/batch-import")
+    public Result<String> batchImportSoraCode(MultipartFile file) throws IOException {
+        EasyExcel.read(file.getInputStream(), ExcelSoraCodeData.class, new AnalysisEventListener<ExcelSoraCodeData>() {
+            @Override
+            public void invoke(ExcelSoraCodeData data, AnalysisContext analysisContext) {
+                String code = data.getCode();
+                if (StrUtil.isNotBlank(code)) {
+                    SoraCode soraCode = new SoraCode();
+                    soraCode.setCode(code);
+                    try {
+                        soraCodeMapper.insert(soraCode);
+                    } catch (DataAccessException e) {
+
+                    }
+                }
+            }
+
+            @Override
+            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+            }
+        }).sheet().doRead();
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+}