diff --git a/src/main/java/com/petstore/controller/ReportLeadController.java b/src/main/java/com/petstore/controller/ReportLeadController.java index 833eff0..eb1aef3 100644 --- a/src/main/java/com/petstore/controller/ReportLeadController.java +++ b/src/main/java/com/petstore/controller/ReportLeadController.java @@ -55,7 +55,11 @@ public class ReportLeadController { data.put("unsubscribeToken", lead.getUnsubscribeToken()); data.put("wechatBound", outcome.wechatBound()); data.put("repeatSubmit", outcome.repeatSubmit()); - return Map.of("code", 200, "data", data); + data.put("alreadySubmitted", outcome.repeatSubmit()); + String message = outcome.repeatSubmit() + ? "该手机号已登记过本报告的提醒,信息已更新" + : "提交成功"; + return Map.of("code", 200, "message", message, "data", data); } catch (IllegalArgumentException e) { return Map.of("code", 400, "message", e.getMessage()); } diff --git a/src/main/java/com/petstore/entity/ReportLead.java b/src/main/java/com/petstore/entity/ReportLead.java index 5619bfe..6d89d07 100644 --- a/src/main/java/com/petstore/entity/ReportLead.java +++ b/src/main/java/com/petstore/entity/ReportLead.java @@ -8,12 +8,17 @@ import java.time.LocalDateTime; /** * 宠主在报告页留下的联系方式 + 下次服务提醒。 - * 一约可多条(宠主可以改手机号重新留资),status 用于软退订与去重。 + * 同一报告下同一手机号仅一条(数据库唯一约束);换手机号可再留一条。 + * remind_status 等用于软退订与发送状态。 */ @Data @Entity @Table( name = "t_report_lead", + uniqueConstraints = @UniqueConstraint( + name = "uk_lead_report_phone", + columnNames = {"report_id", "phone"} + ), indexes = { @Index(name = "idx_lead_report_id", columnList = "report_id"), @Index(name = "idx_lead_store_status_remind", columnList = "store_id,remind_status,remind_date"), diff --git a/src/main/java/com/petstore/service/ReportLeadService.java b/src/main/java/com/petstore/service/ReportLeadService.java index 84800fd..cdfe760 100644 --- a/src/main/java/com/petstore/service/ReportLeadService.java +++ b/src/main/java/com/petstore/service/ReportLeadService.java @@ -10,6 +10,7 @@ import com.petstore.mapper.ServiceIntervalMapper; import com.petstore.mapper.UserMapper; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Service; import java.time.LocalDate; @@ -128,6 +129,7 @@ public class ReportLeadService { LocalDateTime now = LocalDateTime.now(); ReportLead lead = reportLeadMapper.findFirstByReportIdAndPhone(report.getId(), phone).orElse(null); boolean repeatSubmit = lead != null; + final boolean insertingNew = lead == null; if (lead == null) { lead = new ReportLead(); lead.setReportId(report.getId()); @@ -170,7 +172,32 @@ public class ReportLeadService { lead.setWechatUnionid(uid); } - lead = reportLeadMapper.save(lead); + try { + lead = reportLeadMapper.save(lead); + } catch (DataIntegrityViolationException ex) { + if (!insertingNew) { + throw ex; + } + ReportLead existing = reportLeadMapper.findFirstByReportIdAndPhone(report.getId(), phone).orElse(null); + if (existing == null) { + throw ex; + } + lead = existing; + repeatSubmit = true; + lead.setReminderType(reminderType); + lead.setRemindDate(remindDate); + lead.setRemindStatus("pending"); + lead.setConsentAt(now); + lead.setConsentIp(consentIp); + lead.setUpdateTime(now); + if (oid != null && !oid.isBlank()) { + lead.setWechatOpenid(oid); + } + if (uid != null && !uid.isBlank()) { + lead.setWechatUnionid(uid); + } + lead = reportLeadMapper.save(lead); + } boolean wechatBound = false; if (oid != null && !oid.isBlank()) {