Compare commits

..

2 Commits

Author SHA1 Message Date
irving
036e8156d5 fix: allow legacy clerk album entries
Some checks failed
Build and Push Backend / docker (push) Failing after 5s
2025-12-05 23:31:46 -05:00
irving
6497788b64 add more logging for debugging 2025-12-05 23:15:14 -05:00
2 changed files with 116 additions and 12 deletions

View File

@@ -278,7 +278,7 @@ public class WxClerkController {
entity.setReviewState("0");
entity.setDataContent(Collections.singletonList(vo.getNickname()));
playClerkDataReviewInfoService.create(entity);
return R.ok("提交成功,等待审核~");
return R.ok().message("提交成功,等待审核~");
}
@ApiOperation(value = "更新性别", notes = "店员更新性别")
@@ -293,7 +293,7 @@ public class WxClerkController {
entity.setReviewState("0");
entity.setDataContent(Collections.singletonList(String.valueOf(vo.getSex())));
playClerkDataReviewInfoService.create(entity);
return R.ok("提交成功,等待审核~");
return R.ok().message("提交成功,等待审核~");
}
@ApiOperation(value = "更新头像", notes = "店员更新头像")
@@ -315,7 +315,7 @@ public class WxClerkController {
list.add(vo.getAvatar());
entity.setDataContent(list);
playClerkDataReviewInfoService.create(entity);
return R.ok("提交成功,等待审核~");
return R.ok().message("提交成功,等待审核~");
}
@ClerkUserLogin
@@ -348,22 +348,76 @@ public class WxClerkController {
.filter(id -> !approvedIds.contains(id))
.collect(java.util.stream.Collectors.toSet());
if (log.isInfoEnabled()) {
log.info("[ClerkAlbumUpdate] clerkId={} tenantId={} requestedSet={} approvedIds={} newMediaIds={}",
userInfo.getId(), userInfo.getTenantId(), requestedSet, approvedIds, newMediaIds);
}
if (!newMediaIds.isEmpty()) {
// 新增媒资必须是当前店员本人名下、已就绪的媒资,才能进入审核流程
java.util.List<com.starry.admin.modules.media.entity.PlayMediaEntity> newMediaEntities =
mediaService.lambdaQuery()
.in(com.starry.admin.modules.media.entity.PlayMediaEntity::getId, newMediaIds)
.list();
if (newMediaEntities.size() != newMediaIds.size()) {
throw new CustomException("存在未完成上传的照片/视频,请稍后重试");
java.util.Set<String> existingMediaIds = newMediaEntities.stream()
.map(com.starry.admin.modules.media.entity.PlayMediaEntity::getId)
.collect(java.util.stream.Collectors.toSet());
java.util.Set<String> missingMediaIds = new java.util.HashSet<>(newMediaIds);
missingMediaIds.removeAll(existingMediaIds);
if (!missingMediaIds.isEmpty()) {
// 这里很可能是历史相册里的纯 URL未经过媒资化我们记录日志但不直接失败
// 在审核内容中仍然保留这些字符串,由审核端用回显逻辑处理。
log.warn(
"[ClerkAlbumUpdate] some album entries not found in play_media, treating as legacy values, clerkId={} tenantId={} missingIds={} existingIds={}",
userInfo.getId(),
userInfo.getTenantId(),
missingMediaIds,
existingMediaIds);
}
if (log.isInfoEnabled()) {
log.info(
"[ClerkAlbumUpdate] loaded newMediaEntities for validation, clerkId={} tenantId={} mediaSummaries={}",
userInfo.getId(),
userInfo.getTenantId(),
newMediaEntities.stream()
.map(m -> String.format("id=%s,status=%s,ownerType=%s,ownerId=%s,tenantId=%s",
m.getId(), m.getStatus(), m.getOwnerType(), m.getOwnerId(), m.getTenantId()))
.collect(java.util.stream.Collectors.toList()));
}
for (com.starry.admin.modules.media.entity.PlayMediaEntity media : newMediaEntities) {
if (!userInfo.getTenantId().equals(media.getTenantId())
|| !MediaOwnerType.CLERK.equals(media.getOwnerType())
|| !userInfo.getId().equals(media.getOwnerId())) {
boolean tenantMatched = userInfo.getTenantId().equals(media.getTenantId());
boolean ownerTypeMatched = MediaOwnerType.CLERK.equals(media.getOwnerType());
boolean ownerIdMatched = userInfo.getId().equals(media.getOwnerId());
boolean statusReady = com.starry.admin.modules.media.enums.MediaStatus.READY.getCode()
.equals(media.getStatus());
if (!tenantMatched || !ownerTypeMatched || !ownerIdMatched || !statusReady) {
log.warn(
"[ClerkAlbumUpdate] invalid new media for clerk, clerkId={} tenantId={} mediaId={} mediaStatus={} mediaTenantId={} mediaOwnerType={} mediaOwnerId={} tenantMatched={} ownerTypeMatched={} ownerIdMatched={} statusReady={}",
userInfo.getId(),
userInfo.getTenantId(),
media.getId(),
media.getStatus(),
media.getTenantId(),
media.getOwnerType(),
media.getOwnerId(),
tenantMatched,
ownerTypeMatched,
ownerIdMatched,
statusReady);
throw new CustomException("存在无效的照片/视频,请刷新后重试");
}
if (!com.starry.admin.modules.media.enums.MediaStatus.READY.getCode().equals(media.getStatus())) {
if (!statusReady) {
log.warn(
"[ClerkAlbumUpdate] media not in READY state for clerk, clerkId={} tenantId={} mediaId={} mediaStatus={}",
userInfo.getId(),
userInfo.getTenantId(),
media.getId(),
media.getStatus());
throw new CustomException("存在未完成上传的照片/视频,请稍后重试");
}
}
@@ -375,7 +429,7 @@ public class WxClerkController {
entity.setReviewState("0");
entity.setDataContent(new ArrayList<>(requestedSet));
playClerkDataReviewInfoService.create(entity);
return R.ok("提交成功,等待审核~");
return R.ok().message("提交成功,等待审核~");
}
// 仅删除/排序:直接应用变更,不再生成审核记录
@@ -392,7 +446,7 @@ public class WxClerkController {
mediaService.softDelete(MediaOwnerType.CLERK, userInfo.getId(), mediaId);
}
return R.ok("修改成功");
return R.ok().message("修改成功");
}
@ClerkUserLogin
@@ -412,7 +466,7 @@ public class WxClerkController {
list.add(vo.getAudio());
entity.setDataContent(list);
playClerkDataReviewInfoService.create(entity);
return R.ok("提交成功,等待审核~");
return R.ok().message("提交成功,等待审核~");
}
@ClerkUserLogin

View File

@@ -238,6 +238,56 @@ class WxClerkAlbumUpdateApiTest extends AbstractApiTest {
.isNotBlank();
}
@Test
void updateAlbumAllowsMixedLegacyUrlsAndNewMediaIdsForReview() throws Exception {
ensureTenantContext();
String clerkId = ApiTestDataSeeder.DEFAULT_CLERK_ID;
String clerkToken = wxTokenService.createWxUserToken(clerkId);
clerkUserInfoService.updateTokenById(clerkId, clerkToken);
// 预置一条已就绪的媒资,模拟“新上传的视频/图片”
PlayMediaEntity media = seedMedia(clerkId);
// 模拟老相册中的 URL未媒资化的历史数据
String legacyUrl1 = "https://oss.apitest/legacy-1.png";
String legacyUrl2 = "https://oss.apitest/legacy-2.png";
long reviewCountBefore = dataReviewInfoService.lambdaQuery()
.eq(com.starry.admin.modules.clerk.module.entity.PlayClerkDataReviewInfoEntity::getClerkId, clerkId)
.eq(com.starry.admin.modules.clerk.module.entity.PlayClerkDataReviewInfoEntity::getDataType, "2")
.count();
ObjectNode payload = objectMapper.createObjectNode();
com.fasterxml.jackson.databind.node.ArrayNode albumArray = payload.putArray("album");
albumArray.add(legacyUrl1);
albumArray.add(legacyUrl2);
albumArray.add(media.getId());
MvcResult result = mockMvc.perform(post("/wx/clerk/user/updateAlbum")
.header(USER_HEADER, DEFAULT_USER)
.header(TENANT_HEADER, DEFAULT_TENANT)
.header(Constants.CLERK_USER_LOGIN_TOKEN, Constants.TOKEN_PREFIX + clerkToken)
.contentType(MediaType.APPLICATION_JSON)
.content(payload.toString()))
.andExpect(status().isOk())
.andReturn();
String body = result.getResponse().getContentAsString();
com.fasterxml.jackson.databind.JsonNode root = new ObjectMapper().readTree(body);
assertThat(root.path("code").asInt())
.as("mixed legacy URLs and new media ids should be accepted for review, response=%s", body)
.isEqualTo(200);
ensureTenantContext();
long reviewCountAfter = dataReviewInfoService.lambdaQuery()
.eq(com.starry.admin.modules.clerk.module.entity.PlayClerkDataReviewInfoEntity::getClerkId, clerkId)
.eq(com.starry.admin.modules.clerk.module.entity.PlayClerkDataReviewInfoEntity::getDataType, "2")
.count();
assertThat(reviewCountAfter)
.as("mixed legacy URLs and new media ids should create exactly one new review record")
.isEqualTo(reviewCountBefore + 1);
}
private PlayMediaEntity seedMedia(String clerkId) {
String mediaId = "media-" + java.util.UUID.randomUUID().toString().substring(0, 16);
PlayMediaEntity entity = new PlayMediaEntity();