package com.oying.modules.pc.store.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.oying.exception.BadRequestException; import com.oying.modules.pc.common.ValueUpdate; import com.oying.modules.pc.common.core.constrant.AuditStatusEnum; import com.oying.modules.pc.store.converter.StoreAssembler; import com.oying.modules.pc.store.converter.StoreQualificationAssembler; import com.oying.modules.pc.store.domain.Store; import com.oying.modules.pc.store.domain.StoreAudit; import com.oying.modules.pc.store.domain.StoreQualification; import com.oying.modules.pc.store.domain.dto.*; import com.oying.modules.pc.store.domain.enums.StoreChangeTypeEnum; import com.oying.modules.pc.store.domain.enums.StoreStatusEnum; import com.oying.modules.pc.store.events.StoreAuditVerdictEvent; import com.oying.modules.pc.store.service.StoreAuditService; import com.oying.modules.pc.store.service.StoreMerchantService; import com.oying.modules.pc.store.service.StoreQualificationService; import com.oying.modules.pc.store.service.StoreService; import com.oying.service.BucketStorageService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @Slf4j @Service @RequiredArgsConstructor public class StoreMerchantServiceImpl implements StoreMerchantService { private final BucketStorageService bucketStorageService; private final StoreService storeService; private final StoreQualificationService qualificationService; private final StoreAuditService auditService; @Override @Transactional(rollbackFor = Exception.class) public Store createStore(StoreCreateRequest request) { Store store = StoreAssembler.to(request); storeService.create(store); this.processQualificationCreate(store, request.getQualificationList()); storeService.bindUser(store.getStoreId()); return store; } @Override @Transactional(rollbackFor = Exception.class) public void updateStore(StoreUpdateRequest request) { Store existingStore = storeService.getOrThrow(request.getStoreId(), request.getVersion()); AuditStatusEnum existingStatus = AuditStatusEnum.getOrDefault(existingStore.getAuditStatus(), AuditStatusEnum.DRAFT); if (AuditStatusEnum.DRAFT.equals(existingStatus)) { this.processStoreImagesUpdate(request, existingStore); this.processQualificationUpdate(request.getDeletedQualificationIds(), request.getUpdatedQualifications(), request.getNewQualifications()); BeanUtil.copyProperties(request, existingStore, CopyOptions.create().setIgnoreNullValue(true)); storeService.update(existingStore, true); } else if (AuditStatusEnum.APPROVED.equals(existingStatus)) { Store originalStore = new Store(); BeanUtil.copyProperties(existingStore, originalStore, CopyOptions.create().setIgnoreNullValue(true)); Store newStore = new Store(); newStore.setQualifications(ListUtil.of()); BeanUtil.copyProperties(request, newStore, CopyOptions.create().setIgnoreNullValue(true)); List existingQualifications = qualificationService.getByStoreId(request.getStoreId()); if (CollectionUtil.isNotEmpty(request.getDeletedQualificationIds())) { List filteredQualifications = existingQualifications.stream() .filter(qualification -> !request.getDeletedQualificationIds().contains(qualification.getQualificationId())) .collect(Collectors.toList()); newStore.getQualifications().addAll(filteredQualifications); } List updatedQualifications = ListUtil.of(); if (CollectionUtil.isNotEmpty(request.getUpdatedQualifications())) { Set updatedQualificationIdSet = request.getUpdatedQualifications().stream().map(StoreQualificationUpdateRequest::getQualificationId).collect(Collectors.toSet()); List filteredQualifications = newStore.getQualifications().stream() .filter(qualification -> !updatedQualificationIdSet.contains(qualification.getQualificationId())) .collect(Collectors.toList()); newStore.setQualifications(filteredQualifications); request.getUpdatedQualifications().forEach(i -> { StoreQualification qualificationUpdate = new StoreQualification(); BeanUtil.copyProperties(i, qualificationUpdate, CopyOptions.create().setIgnoreNullValue(true)); newStore.getQualifications().add(qualificationUpdate); updatedQualifications.add(qualificationUpdate); }); } if (CollectionUtil.isNotEmpty(request.getNewQualifications())) { newStore.getQualifications().addAll(request.getNewQualifications()); } StoreRevisionRecord revisionRecord = new StoreRevisionRecord(); BeanUtil.copyProperties(request, revisionRecord, CopyOptions.create().setIgnoreNullValue(true)); StoreAuditData auditData = new StoreAuditData(); auditData.setOriginalStore(originalStore); auditData.setStore(newStore); auditData.setRevisionRecord(revisionRecord); this.createLatestModification(request.getStoreId(), StoreChangeTypeEnum.STORE_UPDATE, auditData); } } @Override public void updateBusinessStatus(Store resources) { StoreStatusEnum businessStatus = StoreStatusEnum.getOrDefault(resources.getBusinessStatus(), StoreStatusEnum.DRAFT); Store existingStore = storeService.getOrThrow(resources.getStoreId(), resources.getVersion()); AuditStatusEnum existingStatus = AuditStatusEnum.getOrDefault(existingStore.getAuditStatus(), AuditStatusEnum.DRAFT); if (StoreStatusEnum.OPEN.equals(businessStatus) && !AuditStatusEnum.APPROVED.equals(existingStatus)) { throw new BadRequestException("店铺未审核"); } existingStore.setStatus(businessStatus.getValue()); existingStore.setBusinessStatus(businessStatus.getValue()); storeService.update(existingStore, true); } @Override @Transactional(rollbackFor = Exception.class) public void submitStoreAudit(Long storeId) { Store existingStore = storeService.getById(storeId); // 更新店铺状态 existingStore.setStatus(AuditStatusEnum.PENDING.getValue()); existingStore.setAuditStatus(AuditStatusEnum.PENDING.getValue()); storeService.update(existingStore, true); // 创建新的审核 existingStore.setQualifications(qualificationService.getByStoreId(existingStore.getStoreId())); StoreRevisionRecord revisionRecord = new StoreRevisionRecord(); BeanUtil.copyProperties(existingStore, revisionRecord, CopyOptions.create().setIgnoreNullValue(true)); StoreAuditData auditData = new StoreAuditData(); auditData.setStore(existingStore); auditData.setRevisionRecord(revisionRecord); this.createLatestModification(existingStore.getStoreId(), StoreChangeTypeEnum.NEW_STORE, auditData); } @Override @EventListener @Transactional(rollbackFor = Exception.class) public void handleStoreAudit(StoreAuditVerdictEvent event) { try { StoreAudit audit = auditService.getById(event.getAuditId()); StoreChangeTypeEnum changeType = StoreChangeTypeEnum.valueOf(audit.getType()); switch (changeType) { case NEW_STORE: this.handleNewStoreAuditEvent(audit); return; case STORE_UPDATE: this.handleStoreUpdateAuditEvent(audit); } } catch (Exception e) { log.error("处理店铺审核结果异常", e); } } private void processQualificationCreate(Store store, List qualificationRequests) { if (CollectionUtil.isNotEmpty(qualificationRequests)) { List storeQualificationList = qualificationRequests.stream().map(i -> { i.setStoreId(store.getStoreId()); return StoreQualificationAssembler.to(i); }).collect(Collectors.toList()); storeQualificationList.forEach(i -> i.setStoreId(store.getStoreId())); qualificationService.batchCreate(storeQualificationList); store.setQualifications(storeQualificationList); } } private List getDeleteImageIds(List> imageValues) { List deleteImageIds = new ArrayList<>(); for (ValueUpdate imageValue : imageValues) { if (imageValue.isChangeAndOldValueNotEmpty()) { deleteImageIds.add(imageValue.getOldValue()); } } return deleteImageIds; } private void processStoreImagesUpdate(StoreUpdateRequest request, Store existingStore) { List> imageValues = ListUtil.toList( new ValueUpdate<>(request.getLogoImageId(), existingStore.getLogoImageId()), new ValueUpdate<>(request.getCoverImageId(), existingStore.getCoverImageId()) ); List ids = this.getDeleteImageIds(imageValues); if (CollectionUtil.isNotEmpty(ids)) { bucketStorageService.deleteAll(ids); } } private void processQualificationUpdate(List ids, List updateRequests, List newQualifications) { if (CollectionUtil.isNotEmpty(ids)) { qualificationService.deleteAll(ids); } if (CollectionUtil.isNotEmpty(updateRequests)) { qualificationService.batchUpdate(updateRequests); } if (CollectionUtil.isNotEmpty(newQualifications)) { qualificationService.batchCreate(newQualifications); } } private void createLatestModification(Long storeId, StoreChangeTypeEnum changeType, StoreAuditData auditData) { if (auditService.hasPendingByStoreId(storeId)) { throw new BadRequestException("已有审核的内容"); } StoreAudit storeAudit = new StoreAudit(); storeAudit.setStoreId(storeId); storeAudit.setType(changeType.name()); storeAudit.setData(JSON.toJSONString(auditData)); storeAudit.setStatus(AuditStatusEnum.PENDING.getValue()); auditService.create(storeAudit); } private void handleNewStoreAuditEvent(StoreAudit audit) { Store existingStore = storeService.getById(audit.getStoreId()); existingStore.setStatus(audit.getStatus()); existingStore.setAuditStatus(audit.getStatus()); storeService.updateById(existingStore); } private void handleStoreUpdateAuditEvent(StoreAudit audit) { AuditStatusEnum auditStatus = AuditStatusEnum.get(audit.getStatus()); if (AuditStatusEnum.APPROVED.equals(auditStatus)) { StoreAuditData data = JSONObject.parseObject(audit.getData(), StoreAuditData.class); Store existingStore = storeService.getById(audit.getStoreId()); StoreRevisionRecord revisionRecord = data.getRevisionRecord(); BeanUtil.copyProperties(revisionRecord, existingStore, CopyOptions.create().setIgnoreNullValue(true)); storeService.updateById(existingStore); this.processQualificationUpdate(revisionRecord.getDeletedQualificationIds(), revisionRecord.getUpdatedQualifications(), revisionRecord.getNewQualifications()); } } }