From b4d3224898d50b8f1e30b5c8083a520743927282 Mon Sep 17 00:00:00 2001
From: xin <1099200748@qq.com>
Date: Mon, 14 Jul 2025 21:08:42 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into xin

---
 oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreMerchantServiceImpl.java |  229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 229 insertions(+), 0 deletions(-)

diff --git a/oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreMerchantServiceImpl.java b/oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreMerchantServiceImpl.java
new file mode 100644
index 0000000..f3ce233
--- /dev/null
+++ b/oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreMerchantServiceImpl.java
@@ -0,0 +1,229 @@
+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 newStore = new Store();
+            newStore.setQualifications(ListUtil.of());
+            BeanUtil.copyProperties(request, newStore, CopyOptions.create().setIgnoreNullValue(true));
+            List<StoreQualification> existingQualifications = qualificationService.getByStoreId(request.getStoreId());
+            if (CollectionUtil.isNotEmpty(request.getDeletedQualificationIds())) {
+                List<StoreQualification> filteredQualifications = existingQualifications.stream()
+                        .filter(qualification -> !request.getDeletedQualificationIds().contains(qualification.getQualificationId()))
+                        .collect(Collectors.toList());
+                newStore.getQualifications().addAll(filteredQualifications);
+            }
+            List<StoreQualification> updatedQualifications = ListUtil.of();
+            if (CollectionUtil.isNotEmpty(request.getUpdatedQualifications())) {
+                Set<Long> updatedQualificationIdSet = request.getUpdatedQualifications().stream().map(StoreQualificationUpdateRequest::getQualificationId).collect(Collectors.toSet());
+                List<StoreQualification> 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.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("店铺未审核");
+        }
+        storeService.updateStatus(existingStore.getStoreId(), businessStatus.getValue(), existingStore.getVersion());
+    }
+
+    @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<StoreQualificationCreateRequest> qualificationRequests) {
+        if (CollectionUtil.isNotEmpty(qualificationRequests)) {
+            List<StoreQualification> 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<Long> getDeleteImageIds(List<ValueUpdate<Long>> imageValues) {
+        List<Long> deleteImageIds = new ArrayList<>();
+        for (ValueUpdate<Long> imageValue : imageValues) {
+            if (imageValue.isChangeAndOldValueNotEmpty()) {
+                deleteImageIds.add(imageValue.getOldValue());
+            }
+        }
+        return deleteImageIds;
+    }
+
+    private void processStoreImagesUpdate(StoreUpdateRequest request, Store existingStore) {
+        List<ValueUpdate<Long>> imageValues = ListUtil.toList(
+                new ValueUpdate<>(request.getLogoImageId(), existingStore.getLogoImageId()),
+                new ValueUpdate<>(request.getCoverImageId(), existingStore.getCoverImageId())
+        );
+        List<Long> ids = this.getDeleteImageIds(imageValues);
+        if (CollectionUtil.isNotEmpty(ids)) {
+            bucketStorageService.deleteAll(ids);
+        }
+    }
+
+    private void processQualificationUpdate(List<Long> ids, List<StoreQualificationUpdateRequest> updateRequests,
+                                            List<StoreQualification> 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());
+        }
+    }
+}

--
Gitblit v1.9.3