|
@@ -741,36 +741,29 @@ public class AuthService {
|
|
|
grantLicenseApprovedReward(userId, license.getId());
|
|
grantLicenseApprovedReward(userId, license.getId());
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- // 已存在记录:保存第三方变更的入驻信息到数据库
|
|
|
|
|
- // 尤其是双方都审核通过(APPROVED)的情况,需要记录第三方变更的字段
|
|
|
|
|
|
|
+ // 已存在记录:更新入驻字段,原已审核通过的记录重置为PENDING重新审核
|
|
|
boolean upgradedToApproved = false;
|
|
boolean upgradedToApproved = false;
|
|
|
boolean wasApproved = LicenseStatus.APPROVED.name().equals(existing.getReviewStatus());
|
|
boolean wasApproved = LicenseStatus.APPROVED.name().equals(existing.getReviewStatus());
|
|
|
|
|
|
|
|
- // 更新审核状态
|
|
|
|
|
if (!wasApproved) {
|
|
if (!wasApproved) {
|
|
|
- // 我方未审核通过:允许第三方直接覆盖本地
|
|
|
|
|
|
|
+ // 本地未审核通过:允许第三方直接覆盖状态
|
|
|
existing.setReviewStatus(reviewStatus);
|
|
existing.setReviewStatus(reviewStatus);
|
|
|
upgradedToApproved = LicenseStatus.APPROVED.name().equals(reviewStatus);
|
|
upgradedToApproved = LicenseStatus.APPROVED.name().equals(reviewStatus);
|
|
|
- applyThirdPartyLicenseFields(existing, req, storeName, terminalType);
|
|
|
|
|
- } else if (LicenseStatus.APPROVED.name().equals(reviewStatus)) {
|
|
|
|
|
- // 双方都审核通过:检测字段是否不一致
|
|
|
|
|
- // 不直接覆盖本地,而是保存差异记录,等待运营人工确认
|
|
|
|
|
- Map<String, String[]> diff = detectLicenseDiff(existing, req, storeName, terminalType);
|
|
|
|
|
- if (!diff.isEmpty()) {
|
|
|
|
|
- log.info("第三方与本地入驻信息存在差异(双方均已审核通过),保存差异记录待运营确认: userId={}, licenseId={}, diffFields={}",
|
|
|
|
|
- userId, existing.getId(), diff.keySet());
|
|
|
|
|
- saveLicenseSyncDiffRecords(userId, existing.getId(), diff);
|
|
|
|
|
- recordThirdPartyUpdateAudit(req.getPhone(), userId, existing.getId(), diff);
|
|
|
|
|
- }
|
|
|
|
|
} else {
|
|
} else {
|
|
|
- // 本地已审核通过,第三方变为非通过状态:仅更新状态,保留本地字段
|
|
|
|
|
- existing.setReviewStatus(reviewStatus);
|
|
|
|
|
|
|
+ // 本地已审核通过,第三方再次同步时更新字段并重置为PENDING重新审核
|
|
|
|
|
+ // rewardGranted保持不变,确保不重复奖励
|
|
|
|
|
+ existing.setReviewStatus(LicenseStatus.PENDING.name());
|
|
|
|
|
+ existing.setShowVerifiedBadge(false);
|
|
|
|
|
+ log.info("第三方店铺同步,原已审核通过,更新入驻字段并重置为PENDING待重新审核: licenseId={}, userId={}",
|
|
|
|
|
+ existing.getId(), userId);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 更新第三方传入的入驻字段(非空即覆盖)
|
|
|
|
|
+ applyThirdPartyLicenseFields(existing, req, storeName, terminalType);
|
|
|
businessLicenseService.updateById(existing);
|
|
businessLicenseService.updateById(existing);
|
|
|
|
|
|
|
|
- log.info("第三方店铺同步已存在记录: licenseId={}, userId={}, wasApproved={}, thirdStatus={}, upgradedToApproved={}",
|
|
|
|
|
- existing.getId(), userId, wasApproved, reviewStatus, upgradedToApproved);
|
|
|
|
|
|
|
+ log.info("第三方店铺同步已存在记录: licenseId={}, userId={}, wasApproved={}, newStatus={}, upgradedToApproved={}",
|
|
|
|
|
+ existing.getId(), userId, wasApproved, existing.getReviewStatus(), upgradedToApproved);
|
|
|
|
|
|
|
|
if (upgradedToApproved) {
|
|
if (upgradedToApproved) {
|
|
|
grantLicenseApprovedReward(userId, existing.getId());
|
|
grantLicenseApprovedReward(userId, existing.getId());
|
|
@@ -1003,16 +996,29 @@ public class AuthService {
|
|
|
grantLicenseApprovedReward(userId, license.getId());
|
|
grantLicenseApprovedReward(userId, license.getId());
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- // 已存在记录:仅允许更新审核状态,其他字段保留原值(后续由运营端确认更新)
|
|
|
|
|
|
|
+ // 已存在记录:更新入驻字段,原已审核通过的记录重置为PENDING重新审核
|
|
|
|
|
+ boolean wasApproved = LicenseStatus.APPROVED.name().equals(existing.getReviewStatus());
|
|
|
boolean upgradedToApproved = false;
|
|
boolean upgradedToApproved = false;
|
|
|
- if (!LicenseStatus.APPROVED.name().equals(existing.getReviewStatus())) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (!wasApproved) {
|
|
|
|
|
+ // 本地未审核通过:允许第三方直接覆盖状态
|
|
|
existing.setReviewStatus(reviewStatus);
|
|
existing.setReviewStatus(reviewStatus);
|
|
|
upgradedToApproved = LicenseStatus.APPROVED.name().equals(reviewStatus);
|
|
upgradedToApproved = LicenseStatus.APPROVED.name().equals(reviewStatus);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 本地已审核通过,第三方再次同步时更新字段并重置为PENDING重新审核
|
|
|
|
|
+ // rewardGranted保持不变,确保不重复奖励
|
|
|
|
|
+ existing.setReviewStatus(LicenseStatus.PENDING.name());
|
|
|
|
|
+ existing.setShowVerifiedBadge(false);
|
|
|
|
|
+ log.info("第三方用户{}重新同步入驻信息,原已审核通过,重置为PENDING待重新审核: licenseId={}",
|
|
|
|
|
+ userId, existing.getId());
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 更新第三方传入的入驻字段(非空即覆盖)
|
|
|
|
|
+ applySyncInfoLicenseFields(existing, request, storeName);
|
|
|
businessLicenseService.updateById(existing);
|
|
businessLicenseService.updateById(existing);
|
|
|
|
|
|
|
|
- log.info("第三方用户{}重新同步入驻信息,已存在记录仅更新状态: licenseId={}, oldStatus={}, newStatus={}",
|
|
|
|
|
- userId, existing.getId(), existing.getReviewStatus(), reviewStatus);
|
|
|
|
|
|
|
+ log.info("第三方用户{}重新同步入驻信息: licenseId={}, wasApproved={}, newStatus={}",
|
|
|
|
|
+ userId, existing.getId(), wasApproved, existing.getReviewStatus());
|
|
|
|
|
|
|
|
// 从非APPROVED升级到APPROVED:赠送30天高级会员 + 推送Redis事件
|
|
// 从非APPROVED升级到APPROVED:赠送30天高级会员 + 推送Redis事件
|
|
|
if (upgradedToApproved) {
|
|
if (upgradedToApproved) {
|
|
@@ -1025,16 +1031,66 @@ public class AuthService {
|
|
|
return s != null && !s.isBlank();
|
|
return s != null && !s.isBlank();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 将 SyncInfoRequest 中的入驻字段覆盖到本地记录(非空即覆盖)
|
|
|
|
|
+ */
|
|
|
|
|
+ private void applySyncInfoLicenseFields(
|
|
|
|
|
+ com.xuekairui.user.entity.BusinessLicense existing,
|
|
|
|
|
+ SyncInfoRequest req, String storeName) {
|
|
|
|
|
+ if (storeName != null) {
|
|
|
|
|
+ existing.setStoreName(storeName);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getTerminalType())) {
|
|
|
|
|
+ existing.setTerminalType(req.getTerminalType());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getProvince())) {
|
|
|
|
|
+ existing.setProvince(req.getProvince());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getCity())) {
|
|
|
|
|
+ existing.setCity(req.getCity());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getDistrict())) {
|
|
|
|
|
+ existing.setDistrict(req.getDistrict());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getPharmacyAddress())) {
|
|
|
|
|
+ existing.setStoreAddress(req.getPharmacyAddress());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getContactPerson())) {
|
|
|
|
|
+ existing.setContactPerson(req.getContactPerson());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getContactPhone())) {
|
|
|
|
|
+ existing.setContactPhone(req.getContactPhone());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getBusinessLicenseUrl())) {
|
|
|
|
|
+ existing.setLicenseImageUrl(req.getBusinessLicenseUrl());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getDrugLicenseUrl())) {
|
|
|
|
|
+ existing.setDrugLicenseUrl(req.getDrugLicenseUrl());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getMedicalDeviceClass2Url())) {
|
|
|
|
|
+ existing.setMedicalDeviceClass2Url(req.getMedicalDeviceClass2Url());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getMedicalDeviceClass3Url())) {
|
|
|
|
|
+ existing.setMedicalDeviceClass3Url(req.getMedicalDeviceClass3Url());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNotBlank(req.getBusinessLicenseNo())) {
|
|
|
|
|
+ existing.setCreditCode(req.getBusinessLicenseNo());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 首次入驻审核通过:赠送30天高级会员 + 推送Redis事件供活动模块消费
|
|
* 首次入驻审核通过:赠送30天高级会员 + 推送Redis事件供活动模块消费
|
|
|
* <p>与 BusinessLicenseService.approve() 的奖励逻辑保持一致。
|
|
* <p>与 BusinessLicenseService.approve() 的奖励逻辑保持一致。
|
|
|
- * <p>幂等性检查:若用户已有其他审核通过的入驻记录,不再重复赠送,避免高级会员过期时间累加。
|
|
|
|
|
|
|
+ * <p>幂等性检查:通过 rewardGranted 标记保证同一入驻记录仅奖励一次,
|
|
|
|
|
+ * 即使审核通过后重新编辑→重新审核,也不会重复发放。
|
|
|
*/
|
|
*/
|
|
|
private void grantLicenseApprovedReward(Long userId, Long licenseId) {
|
|
private void grantLicenseApprovedReward(Long userId, Long licenseId) {
|
|
|
- if (businessLicenseService.hasOtherApprovedLicensePublic(userId, licenseId)) {
|
|
|
|
|
- log.info("用户{}已有其他审核通过的入驻记录,跳过重复赠送高级会员: licenseId={}", userId, licenseId);
|
|
|
|
|
|
|
+ com.xuekairui.user.entity.BusinessLicense license = businessLicenseService.getById(licenseId);
|
|
|
|
|
+ if (license != null && Boolean.TRUE.equals(license.getRewardGranted())) {
|
|
|
|
|
+ log.info("用户{}的入驻记录奖励已发放,跳过重复赠送: licenseId={}", userId, licenseId);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
membershipService.grantOrExtendMembership(
|
|
membershipService.grantOrExtendMembership(
|
|
|
userId,
|
|
userId,
|
|
|
MembershipLevel.PRO,
|
|
MembershipLevel.PRO,
|
|
@@ -1043,7 +1099,14 @@ public class AuthService {
|
|
|
"入驻信息审核通过赠送30天高级会员");
|
|
"入驻信息审核通过赠送30天高级会员");
|
|
|
log.info("入驻信息审核通过(第三方同步),赠送用户{} 30天高级会员", userId);
|
|
log.info("入驻信息审核通过(第三方同步),赠送用户{} 30天高级会员", userId);
|
|
|
|
|
|
|
|
|
|
+ // 标记奖励已发放,防止重复
|
|
|
|
|
+ if (license != null) {
|
|
|
|
|
+ license.setRewardGranted(true);
|
|
|
|
|
+ businessLicenseService.updateById(license);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 事务提交后推送 Redis 事件,供活动模块消费(邀请有礼等)
|
|
// 事务提交后推送 Redis 事件,供活动模块消费(邀请有礼等)
|
|
|
|
|
+ // 活动模块通过 uk_invitee 唯一索引保证同一被邀请人仅奖励一次
|
|
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
|
|
@Override
|
|
@Override
|
|
|
public void afterCommit() {
|
|
public void afterCommit() {
|