25 files added
19 files modified
New file |
| | |
| | | package com.oying.modules.pc.common.core.constrant; |
| | | |
| | | import lombok.Getter; |
| | | |
| | | import java.util.EnumSet; |
| | | import java.util.Optional; |
| | | |
| | | @Getter |
| | | public enum AuditStatusEnum { |
| | | |
| | | DRAFT(1000, "草稿"), |
| | | PENDING(1001, "待审核"), |
| | | UNDER_REVIEW(1002, "审核中"), |
| | | REJECTED(1003, "拒绝"), |
| | | APPROVED(1004, "同意"), |
| | | CANCELLED(1005, "取消"); |
| | | |
| | | private final Integer value; |
| | | private final String reasonPhrase; |
| | | |
| | | AuditStatusEnum(Integer value, String reasonPhrase) { |
| | | this.value = value; |
| | | this.reasonPhrase = reasonPhrase; |
| | | } |
| | | |
| | | public static AuditStatusEnum get(Integer code) { |
| | | return getOrDefault(code, null); |
| | | } |
| | | |
| | | public static AuditStatusEnum getOrDefault(Integer code, AuditStatusEnum defaultStatus) { |
| | | for (AuditStatusEnum value : values()) { |
| | | if (value.value.equals(code)) { |
| | | return value; |
| | | } |
| | | } |
| | | return defaultStatus; |
| | | } |
| | | |
| | | public static boolean isApproved(Integer code) { |
| | | return Optional.ofNullable(get(code)).map(i -> i.equals(APPROVED)).orElse(false); |
| | | } |
| | | |
| | | public static boolean isCompleted(Integer code) { |
| | | return EnumSet.of(REJECTED, APPROVED, CANCELLED).contains(get(code)); |
| | | } |
| | | |
| | | public static AuditStatusEnum get(String name) { |
| | | return AuditStatusEnum.valueOf(name); |
| | | } |
| | | |
| | | public static EnumSet<AuditStatusEnum> getNext(AuditStatusEnum status) { |
| | | switch (status) { |
| | | case DRAFT: |
| | | return EnumSet.of(PENDING); |
| | | case PENDING: |
| | | return EnumSet.of(UNDER_REVIEW, APPROVED, REJECTED, CANCELLED); |
| | | case UNDER_REVIEW: |
| | | return EnumSet.of(APPROVED, REJECTED); |
| | | case APPROVED: |
| | | case REJECTED: |
| | | case CANCELLED: |
| | | default: |
| | | return EnumSet.noneOf(AuditStatusEnum.class); |
| | | } |
| | | } |
| | | |
| | | public static boolean hasNext(AuditStatusEnum status) { |
| | | return !getNext(status).isEmpty(); |
| | | } |
| | | |
| | | public EnumSet<AuditStatusEnum> getNext() { |
| | | return getNext(this); |
| | | } |
| | | |
| | | public boolean nextContains(AuditStatusEnum status) { |
| | | return getNext().contains(status); |
| | | } |
| | | |
| | | public boolean nextContains(String status) { |
| | | return nextContains(get(status)); |
| | | } |
| | | |
| | | public boolean hasNext() { |
| | | return hasNext(this); |
| | | } |
| | | } |
| | |
| | | * https请求 |
| | | */ |
| | | public static final String HTTPS = "https://"; |
| | | |
| | | /** |
| | | * 否 |
| | | */ |
| | | public static final Integer NOT = 0; |
| | | |
| | | /** |
| | | * 是 |
| | | */ |
| | | public static final Integer YES = 1; |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.domain; |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.bean.copier.CopyOptions; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.oying.base.BaseEntity; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @description / |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @Getter |
| | | @Setter |
| | | @TableName("pc_product_audit") |
| | | public class ProductAudit extends BaseEntity implements Serializable { |
| | | |
| | | @TableId(value = "audit_id", type = IdType.AUTO) |
| | | @ApiModelProperty(value = "审核ID") |
| | | private Long auditId; |
| | | |
| | | @NotNull |
| | | @ApiModelProperty(value = "商品ID") |
| | | private Long productId; |
| | | |
| | | @NotBlank |
| | | @ApiModelProperty(value = "类型") |
| | | private String type; |
| | | |
| | | @ApiModelProperty(value = "审核状态") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "审核原因") |
| | | private String reason; |
| | | |
| | | @ApiModelProperty(value = "审核人") |
| | | private String auditor; |
| | | |
| | | @ApiModelProperty(value = "审核时间") |
| | | private Date auditTime; |
| | | |
| | | @NotBlank |
| | | @ApiModelProperty(value = "审核内容") |
| | | private String data; |
| | | |
| | | public void copy(ProductAudit source){ |
| | | BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); |
| | | } |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.domain.dto; |
| | | |
| | | import com.oying.modules.pc.store.domain.Store; |
| | | import com.oying.modules.pc.store.domain.dto.StoreRevisionRecord; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class ProductAuditData { |
| | | |
| | | private Store store; |
| | | private StoreRevisionRecord revisionRecord; |
| | | |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.domain.dto; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @Data |
| | | public class ProductAuditQueryCriteria { |
| | | |
| | | @NotNull |
| | | @ApiModelProperty(value = "商品ID") |
| | | private Long productId; |
| | | |
| | | @NotBlank |
| | | @ApiModelProperty(value = "类型") |
| | | private String type; |
| | | |
| | | @ApiModelProperty(value = "页码", example = "1") |
| | | private Integer page = 1; |
| | | |
| | | @ApiModelProperty(value = "每页数据量", example = "10") |
| | | private Integer size = 10; |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.domain.dto; |
| | | |
| | | import com.oying.modules.pc.store.domain.StoreQualification; |
| | | import com.oying.modules.pc.store.domain.dto.StoreQualificationUpdateRequest; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class ProductRevisionRecord { |
| | | |
| | | @ApiModelProperty(value = "店铺ID") |
| | | private Long storeId; |
| | | |
| | | @ApiModelProperty(value = "店铺名称") |
| | | private String storeName; |
| | | |
| | | @ApiModelProperty(value = "资质") |
| | | private List<StoreQualification> qualifications = new ArrayList<>(); |
| | | |
| | | @ApiModelProperty(value = "删除的资质") |
| | | private List<Long> deletedQualificationIds = new ArrayList<>(); |
| | | |
| | | @ApiModelProperty(value = "修改的资质") |
| | | private List<StoreQualificationUpdateRequest> updatedQualifications = new ArrayList<>(); |
| | | |
| | | @ApiModelProperty(value = "新增的资质") |
| | | private List<StoreQualification> newQualifications = new ArrayList<>(); |
| | | |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.domain.enums; |
| | | |
| | | public enum ProductChangeTypeEnum { |
| | | |
| | | PUT_ON_SHELF |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | public static ProductStatusEnum get(Integer code) { |
| | | return getOrDefault(code, null); |
| | | } |
| | | |
| | | public static ProductStatusEnum getOrDefault(Integer code, ProductStatusEnum productStatusEnum) { |
| | | for (ProductStatusEnum value : values()) { |
| | | if (value.value.equals(code)) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | return productStatusEnum; |
| | | } |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.events; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class ProductAuditVerdictEvent { |
| | | |
| | | private Long auditId; |
| | | |
| | | public ProductAuditVerdictEvent(Long auditId) { |
| | | this.auditId = auditId; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.oying.modules.pc.product.domain.ProductAudit; |
| | | import com.oying.modules.pc.product.domain.dto.ProductAuditQueryCriteria; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @Mapper |
| | | public interface ProductAuditMapper extends BaseMapper<ProductAudit> { |
| | | |
| | | IPage<ProductAudit> findAll(@Param("criteria") ProductAuditQueryCriteria criteria, Page<Object> page); |
| | | |
| | | List<ProductAudit> findAll(@Param("criteria") ProductAuditQueryCriteria criteria); |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.rest; |
| | | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.oying.annotation.Log; |
| | | import com.oying.modules.pc.product.domain.ProductAudit; |
| | | import com.oying.modules.pc.product.domain.dto.ProductAuditQueryCriteria; |
| | | import com.oying.modules.pc.product.service.ProductAuditService; |
| | | import com.oying.utils.PageResult; |
| | | import com.oying.utils.R; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.annotations.ApiParam; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @RestController |
| | | @RequiredArgsConstructor |
| | | @RequestMapping("/api/pc/product/audit") |
| | | public class ProductAuditController { |
| | | |
| | | private final ProductAuditService auditService; |
| | | |
| | | @GetMapping |
| | | @ApiOperation("查询审批信息") |
| | | //@PreAuthorize("@el.check('productAudit:list')") |
| | | public ResponseEntity<?> queryProductAudit(ProductAuditQueryCriteria criteria) { |
| | | Page<Object> page = new Page<>(criteria.getPage(), criteria.getSize()); |
| | | return ResponseEntity.ok(R.success(auditService.queryAll(criteria, page))); |
| | | } |
| | | |
| | | @PostMapping |
| | | @Log("新增审批信息") |
| | | @ApiOperation("新增审批信息") |
| | | //@PreAuthorize("@el.check('productAudit:add')") |
| | | public ResponseEntity<Object> createProductAudit(@Validated @RequestBody ProductAudit resources) { |
| | | auditService.create(resources); |
| | | return ResponseEntity.status(HttpStatus.CREATED).build(); |
| | | } |
| | | |
| | | @PutMapping |
| | | @Log("修改审批信息") |
| | | @ApiOperation("修改审批信息") |
| | | //@PreAuthorize("@el.check('productAudit:edit')") |
| | | public ResponseEntity<Object> updateProductAudit(@Validated @RequestBody ProductAudit resources) { |
| | | auditService.update(resources, false); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | | @PostMapping(value = "/verdict") |
| | | @ApiOperation("处理审核") |
| | | public ResponseEntity<?> submitAuditVerdict(@RequestBody ProductAudit resources) { |
| | | auditService.processVerdict(resources); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | | @DeleteMapping |
| | | @Log("删除审批信息") |
| | | @ApiOperation("删除审批信息") |
| | | //@PreAuthorize("@el.check('productAudit:del')") |
| | | public ResponseEntity<Object> deleteProductAudit(@ApiParam(value = "传ID数组[]") @RequestBody List<Long> ids) { |
| | | auditService.deleteAll(ids); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.oying.modules.pc.product.domain.ProductAudit; |
| | | import com.oying.modules.pc.product.domain.dto.ProductAuditQueryCriteria; |
| | | import com.oying.utils.PageResult; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @description 服务接口 |
| | | * @date 2025-07-01 |
| | | **/ |
| | | public interface ProductAuditService extends IService<ProductAudit> { |
| | | |
| | | /** |
| | | * 查询数据分页 |
| | | * |
| | | * @param criteria 条件 |
| | | * @param page 分页参数 |
| | | * @return PageResult |
| | | */ |
| | | PageResult<ProductAudit> queryAll(ProductAuditQueryCriteria criteria, Page<Object> page); |
| | | |
| | | /** |
| | | * 查询所有数据不分页 |
| | | * |
| | | * @param criteria 条件参数 |
| | | * @return List<StoreRevisionDto> |
| | | */ |
| | | List<ProductAudit> queryAll(ProductAuditQueryCriteria criteria); |
| | | |
| | | /** |
| | | * 商品ID查询修订数据, |
| | | * |
| | | * @param productId 必须的参数,不能为null |
| | | * @return 查询到的结果 |
| | | */ |
| | | ProductAudit getByProductId(Long productId); |
| | | |
| | | /** |
| | | * 创建 |
| | | * |
| | | * @param resources / |
| | | */ |
| | | void create(ProductAudit resources); |
| | | |
| | | /** |
| | | * 编辑 |
| | | * |
| | | * @param resources / |
| | | */ |
| | | void update(ProductAudit resources, boolean isDirectUpdate); |
| | | |
| | | /** |
| | | * 多选删除 |
| | | * |
| | | * @param ids / |
| | | */ |
| | | void deleteAll(List<Long> ids); |
| | | |
| | | /** |
| | | * 导出数据 |
| | | * |
| | | * @param all 待导出的数据 |
| | | * @param response / |
| | | * @throws IOException / |
| | | */ |
| | | void download(List<ProductAudit> all, HttpServletResponse response) throws IOException; |
| | | |
| | | void processVerdict(ProductAudit resources); |
| | | } |
| | |
| | | |
| | | import com.oying.modules.pc.product.domain.dto.ProductMerchantCreateRequest; |
| | | import com.oying.modules.pc.product.domain.dto.ProductMerchantUpdateRequest; |
| | | import com.oying.modules.pc.product.events.ProductAuditVerdictEvent; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | void batchDelete(List<Long> ids); |
| | | void putOnShelf(Long productId); |
| | | void takeOffShelf(Long productId); |
| | | void handleAuditVerdictEvent(ProductAuditVerdictEvent event); |
| | | |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.product.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.oying.exception.BadRequestException; |
| | | import com.oying.modules.pc.common.core.constrant.AuditStatusEnum; |
| | | import com.oying.modules.pc.product.domain.ProductAudit; |
| | | import com.oying.modules.pc.product.domain.dto.ProductAuditQueryCriteria; |
| | | import com.oying.modules.pc.product.events.ProductAuditVerdictEvent; |
| | | import com.oying.modules.pc.product.mapper.ProductAuditMapper; |
| | | import com.oying.modules.pc.product.service.ProductAuditService; |
| | | import com.oying.utils.FileUtil; |
| | | import com.oying.utils.PageResult; |
| | | import com.oying.utils.PageUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @description 服务实现 |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class ProductAuditServiceImpl extends ServiceImpl<ProductAuditMapper, ProductAudit> implements ProductAuditService { |
| | | |
| | | private final ApplicationEventPublisher eventPublisher; |
| | | |
| | | private final ProductAuditMapper productAuditMapper; |
| | | |
| | | @Override |
| | | public PageResult<ProductAudit> queryAll(ProductAuditQueryCriteria criteria, Page<Object> page) { |
| | | return PageUtil.toPage(productAuditMapper.findAll(criteria, page)); |
| | | } |
| | | |
| | | @Override |
| | | public List<ProductAudit> queryAll(ProductAuditQueryCriteria criteria) { |
| | | return productAuditMapper.findAll(criteria); |
| | | } |
| | | |
| | | @Override |
| | | public ProductAudit getByProductId(Long productId) { |
| | | LambdaQueryWrapper<ProductAudit> wrapper = new LambdaQueryWrapper<ProductAudit>() |
| | | .eq(ProductAudit::getProductId, productId); |
| | | return productAuditMapper.selectOne(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void create(ProductAudit resources) { |
| | | productAuditMapper.insert(resources); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void update(ProductAudit resources, boolean isDirectUpdate) { |
| | | if (isDirectUpdate) { |
| | | productAuditMapper.updateById(resources); |
| | | } else { |
| | | ProductAudit existingRevision = this.getById(resources.getAuditor()); |
| | | existingRevision.copy(resources); |
| | | productAuditMapper.updateById(existingRevision); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void processVerdict(ProductAudit resources) { |
| | | AuditStatusEnum newAuditStatus = AuditStatusEnum.get(resources.getStatus()); |
| | | ProductAudit existingAudit = this.getById(resources.getAuditId()); |
| | | AuditStatusEnum existingAuditStatus = AuditStatusEnum.getOrDefault(existingAudit.getStatus(), AuditStatusEnum.DRAFT); |
| | | if (!existingAuditStatus.nextContains(newAuditStatus)) { |
| | | throw new BadRequestException("审核状态错误"); |
| | | } |
| | | existingAudit.copy(resources); |
| | | productAuditMapper.updateById(existingAudit); |
| | | eventPublisher.publishEvent(new ProductAuditVerdictEvent(existingAudit.getAuditId())); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteAll(List<Long> ids) { |
| | | productAuditMapper.deleteBatchIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | public void download(List<ProductAudit> all, HttpServletResponse response) throws IOException { |
| | | List<Map<String, Object>> list = new ArrayList<>(); |
| | | for (ProductAudit productAudit : all) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("审核ID", productAudit.getAuditId()); |
| | | map.put("商品ID", productAudit.getProductId()); |
| | | map.put("审批ID", productAudit.getAuditId()); |
| | | map.put("类型", productAudit.getType()); |
| | | map.put("新数据", productAudit.getData()); |
| | | map.put("创建人", productAudit.getCreateBy()); |
| | | map.put("创建时间", productAudit.getCreateTime()); |
| | | map.put("修改人", productAudit.getUpdateBy()); |
| | | map.put("修改时间", productAudit.getUpdateTime()); |
| | | list.add(map); |
| | | } |
| | | FileUtil.downloadExcel(list, response); |
| | | } |
| | | } |
| | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.oying.exception.EntityExistException; |
| | | import com.oying.exception.BadRequestException; |
| | | import com.oying.exception.EntityNotFoundException; |
| | | import com.oying.modules.pc.common.core.constrant.AuditStatusEnum; |
| | | import com.oying.modules.pc.product.converter.ProductImageAssembler; |
| | | import com.oying.modules.pc.product.converter.ProductLabelAssembler; |
| | | import com.oying.modules.pc.product.domain.Product; |
| | | import com.oying.modules.pc.product.domain.ProductAudit; |
| | | import com.oying.modules.pc.product.domain.ProductImage; |
| | | import com.oying.modules.pc.product.domain.ProductLabel; |
| | | import com.oying.modules.pc.product.domain.dto.ProductImageCreateRequest; |
| | | import com.oying.modules.pc.product.domain.dto.ProductLabelCreateRequest; |
| | | import com.oying.modules.pc.product.domain.dto.ProductMerchantCreateRequest; |
| | | import com.oying.modules.pc.product.domain.dto.ProductMerchantUpdateRequest; |
| | | import com.oying.modules.pc.product.domain.enums.ProductChangeTypeEnum; |
| | | import com.oying.modules.pc.product.domain.enums.ProductStatusEnum; |
| | | import com.oying.modules.pc.product.service.ProductImageService; |
| | | import com.oying.modules.pc.product.service.ProductLabelService; |
| | | import com.oying.modules.pc.product.service.ProductMerchantService; |
| | | import com.oying.modules.pc.product.service.ProductService; |
| | | import com.oying.modules.pc.product.events.ProductAuditVerdictEvent; |
| | | import com.oying.modules.pc.product.service.*; |
| | | import com.oying.modules.pc.utils.ImageUtils; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.context.event.EventListener; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Slf4j |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class ProductMerchantServiceImpl implements ProductMerchantService { |
| | |
| | | private final ProductService productService; |
| | | private final ProductImageService productImageService; |
| | | private final ProductLabelService productLabelService; |
| | | private final ProductAuditService productAuditService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void update(ProductMerchantUpdateRequest request) { |
| | | Product existingProduct = this.findOrThrow(request.getProductId()); |
| | | this.validateApprovedStatus(existingProduct.getStatus()); |
| | | this.processImagesUpdate(request); |
| | | this.processLabelsUpdate(request); |
| | | BeanUtils.copyProperties(request, existingProduct); |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateImages(ProductMerchantUpdateRequest request) { |
| | | Product existingProduct = this.findOrThrow(request.getProductId()); |
| | | this.validateApprovedStatus(existingProduct.getStatus()); |
| | | this.findOrThrow(request.getProductId()); |
| | | this.processImagesUpdate(request); |
| | | } |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateLabels(ProductMerchantUpdateRequest request) { |
| | | Product existingProduct = this.findOrThrow(request.getProductId()); |
| | | this.validateApprovedStatus(existingProduct.getStatus()); |
| | | this.findOrThrow(request.getProductId()); |
| | | this.processImagesUpdate(request); |
| | | } |
| | |
| | | |
| | | @Override |
| | | public void putOnShelf(Long productId) { |
| | | ProductAudit audit = new ProductAudit(); |
| | | audit.setProductId(productId); |
| | | audit.setType(ProductChangeTypeEnum.PUT_ON_SHELF.name()); |
| | | audit.setStatus(AuditStatusEnum.PENDING.getValue()); |
| | | productAuditService.create(audit); |
| | | LambdaUpdateWrapper<Product> wrapper = new LambdaUpdateWrapper<Product>() |
| | | .eq(Product::getProductId, productId) |
| | | .set(Product::getStatus, ProductStatusEnum.AVAILABLE.getValue()); |
| | | .set(Product::getStatus, ProductStatusEnum.PENDING.getValue()); |
| | | productService.update(wrapper); |
| | | } |
| | | |
| | |
| | | .eq(Product::getProductId, productId) |
| | | .set(Product::getStatus, ProductStatusEnum.NO_AVAILABLE.getValue()); |
| | | productService.update(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | @EventListener |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void handleAuditVerdictEvent(ProductAuditVerdictEvent event) { |
| | | try { |
| | | ProductAudit audit = productAuditService.getById(event.getAuditId()); |
| | | ProductChangeTypeEnum changeType = ProductChangeTypeEnum.valueOf(audit.getType()); |
| | | if (changeType == ProductChangeTypeEnum.PUT_ON_SHELF) { |
| | | this.handlePutOnShelfAuditEvent(audit); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("处理商品审核结果异常", e); |
| | | } |
| | | } |
| | | |
| | | private Product findOrThrow(Long productId) { |
| | |
| | | productLabelService.batchCreate(newLabels); |
| | | } |
| | | } |
| | | |
| | | private void handlePutOnShelfAuditEvent(ProductAudit audit) { |
| | | AuditStatusEnum auditStatus = AuditStatusEnum.get(audit.getStatus()); |
| | | if (AuditStatusEnum.APPROVED.equals(auditStatus)) { |
| | | Product existingProduct = productService.getById(audit.getProductId()); |
| | | existingProduct.setStatus(auditStatus.getValue()); |
| | | productService.updateById(existingProduct); |
| | | } |
| | | } |
| | | |
| | | private void validateApprovedStatus(Integer status) { |
| | | Set<ProductStatusEnum> statusEnumSet = CollectionUtil.newHashSet(ProductStatusEnum.PENDING, |
| | | ProductStatusEnum.UNDER_REVIEW, ProductStatusEnum.AVAILABLE); |
| | | ProductStatusEnum existingStatus = ProductStatusEnum.getOrDefault(status, ProductStatusEnum.DRAFT); |
| | | if (statusEnumSet.contains(existingStatus)) { |
| | | throw new BadRequestException("在售商品无法修改"); |
| | | } |
| | | } |
| | | } |
| | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalTime; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @ApiModelProperty(value = "营业结束时间") |
| | | private LocalTime closeTime; |
| | | |
| | | @ApiModelProperty(value = "营业状态") |
| | | private Integer businessStatus; |
| | | |
| | | @ApiModelProperty(value = "省级代码") |
| | | private String provinceCode; |
| | | |
| | |
| | | @ApiModelProperty(value = "是否支持自提") |
| | | private Integer selfPickup; |
| | | |
| | | @NotNull |
| | | @ApiModelProperty(value = "版本号") |
| | | private Long version; |
| | | @ApiModelProperty(value = "审核状态") |
| | | private Integer auditStatus; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "评分") |
| | |
| | | @ApiModelProperty(value = "月销售量") |
| | | private Integer monthlyUnitsSold = 0; |
| | | |
| | | @NotNull |
| | | @ApiModelProperty(value = "版本号") |
| | | private Long version; |
| | | |
| | | @TableField(exist = false) |
| | | @ApiModelProperty(value = "资质") |
| | | private List<StoreQualification> qualifications; |
New file |
| | |
| | | package com.oying.modules.pc.store.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.oying.base.BaseEntity; |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import cn.hutool.core.bean.copier.CopyOptions; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | |
| | | /** |
| | | * @description / |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @Getter |
| | | @Setter |
| | | @TableName("pc_store_audit") |
| | | public class StoreAudit extends BaseEntity implements Serializable { |
| | | |
| | | @TableId(value = "audit_id", type = IdType.AUTO) |
| | | @ApiModelProperty(value = "审核ID") |
| | | private Long auditId; |
| | | |
| | | @NotNull |
| | | @ApiModelProperty(value = "店铺ID") |
| | | private Long storeId; |
| | | |
| | | @NotBlank |
| | | @ApiModelProperty(value = "类型") |
| | | private String type; |
| | | |
| | | @ApiModelProperty(value = "审核状态") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "审核原因") |
| | | private String reason; |
| | | |
| | | @ApiModelProperty(value = "审核人") |
| | | private String auditor; |
| | | |
| | | @ApiModelProperty(value = "审核时间") |
| | | private Date auditTime; |
| | | |
| | | @NotBlank |
| | | @ApiModelProperty(value = "审核内容") |
| | | private String data; |
| | | |
| | | public void copy(StoreAudit source){ |
| | | BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); |
| | | } |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.domain.dto; |
| | | |
| | | import com.oying.modules.pc.store.domain.Store; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class StoreAuditData { |
| | | |
| | | private Store store; |
| | | private StoreRevisionRecord revisionRecord; |
| | | |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @Data |
| | | public class StoreAuditQueryCriteria { |
| | | |
| | | @NotNull |
| | | @ApiModelProperty(value = "店铺ID") |
| | | private Long storeId; |
| | | |
| | | @NotBlank |
| | | @ApiModelProperty(value = "类型") |
| | | private String type; |
| | | |
| | | @ApiModelProperty(value = "页码", example = "1") |
| | | private Integer page = 1; |
| | | |
| | | @ApiModelProperty(value = "每页数据量", example = "10") |
| | | private Integer size = 10; |
| | | } |
| | |
| | | @NotNull(groups = UpdateStoreBusinessStatusGroup.class) |
| | | private Integer businessStatus; |
| | | |
| | | @ApiModelProperty(value = "店铺logo图片") |
| | | private Long logoImageId; |
| | | |
| | | public interface UpdateStoreLogoImageGroup{} |
| | | |
| | | @NotBlank(groups = UpdateStoreLogoImageGroup.class) |
| | | private String logoImageUploadId; |
| | | |
| | | @ApiModelProperty(value = "店铺封面图") |
| | | private Long coverImageId; |
| | | |
| | | public interface UpdateStoreCoverImageGroup{} |
| | | |
| | | @NotBlank(groups = UpdateStoreCoverImageGroup.class) |
| | |
| | | |
| | | private Integer status; |
| | | |
| | | private Integer businessStatus; |
| | | |
| | | private String blurry; |
| | | |
| | | private Double longitude; // 中心点经度 |
| | | |
| | | private Double latitude; // 中心点纬度 |
| | | |
| | | private Integer radius = 10000; // 搜索半径(米) |
| | | private Integer radius = 50000000; // 搜索半径(米) |
| | | |
| | | private Integer limit = 20; // 返回数量限制 |
| | | |
| | |
| | | baseKeyJoiner.add("platformCategoryId=" + platformCategoryId); |
| | | baseKeyJoiner.add("storeName=" + storeName); |
| | | baseKeyJoiner.add("status=" + status); |
| | | baseKeyJoiner.add("businessStatus=" + businessStatus); |
| | | baseKeyJoiner.add("blurry=" + blurry); |
| | | baseKeyJoiner.add("longitude=" + longitude); |
| | | baseKeyJoiner.add("latitude=" + latitude); |
New file |
| | |
| | | package com.oying.modules.pc.store.domain.dto; |
| | | |
| | | import com.oying.modules.pc.store.domain.StoreQualification; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class StoreRevisionRecord { |
| | | |
| | | @ApiModelProperty(value = "店铺ID") |
| | | private Long storeId; |
| | | |
| | | @ApiModelProperty(value = "店铺名称") |
| | | private String storeName; |
| | | |
| | | @ApiModelProperty(value = "资质") |
| | | private List<StoreQualification> qualifications = new ArrayList<>(); |
| | | |
| | | @ApiModelProperty(value = "删除的资质") |
| | | private List<Long> deletedQualificationIds = new ArrayList<>(); |
| | | |
| | | @ApiModelProperty(value = "修改的资质") |
| | | private List<StoreQualificationUpdateRequest> updatedQualifications = new ArrayList<>(); |
| | | |
| | | @ApiModelProperty(value = "新增的资质") |
| | | private List<StoreQualification> newQualifications = new ArrayList<>(); |
| | | |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.domain.enums; |
| | | |
| | | public enum StoreChangeTypeEnum { |
| | | |
| | | NEW_STORE, |
| | | STORE_UPDATE, |
| | | STORE_NAME_UPDATE |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | public static StoreStatusEnum get(Integer code) { |
| | | return getOrDefault(code, null); |
| | | } |
| | | |
| | | public static StoreStatusEnum getOrDefault(Integer code, StoreStatusEnum defaultStatus) { |
| | | for (StoreStatusEnum value : values()) { |
| | | if (value.value.equals(code)) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | return defaultStatus; |
| | | } |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.events; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class StoreAuditVerdictEvent { |
| | | |
| | | private Long auditId; |
| | | |
| | | public StoreAuditVerdictEvent(Long auditId) { |
| | | this.auditId = auditId; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.mapper; |
| | | |
| | | import com.oying.modules.pc.store.domain.StoreAudit; |
| | | import com.oying.modules.pc.store.domain.dto.StoreAuditQueryCriteria; |
| | | import java.util.List; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @Mapper |
| | | public interface StoreAuditMapper extends BaseMapper<StoreAudit> { |
| | | |
| | | IPage<StoreAudit> findAll(@Param("criteria") StoreAuditQueryCriteria criteria, Page<Object> page); |
| | | |
| | | List<StoreAudit> findAll(@Param("criteria") StoreAuditQueryCriteria criteria); |
| | | } |
| | |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | |
| | | List<Store> queryUserStores(@Param("userId") Long userId); |
| | | |
| | | List<Store> queryByIds(@Param("ids") Collection<? extends Serializable> idList); |
| | | |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.rest; |
| | | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.oying.annotation.Log; |
| | | import com.oying.modules.pc.store.domain.StoreAudit; |
| | | import com.oying.modules.pc.store.domain.dto.StoreAuditQueryCriteria; |
| | | import com.oying.modules.pc.store.service.StoreAuditService; |
| | | import com.oying.utils.PageResult; |
| | | import com.oying.utils.R; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.annotations.ApiParam; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @RestController |
| | | @RequiredArgsConstructor |
| | | @RequestMapping("/api/pc/store/audit") |
| | | public class StoreAuditController { |
| | | |
| | | private final StoreAuditService auditService; |
| | | |
| | | @GetMapping |
| | | @ApiOperation("查询审批信息") |
| | | //@PreAuthorize("@el.check('storeAudit:list')") |
| | | public ResponseEntity<?> queryStoreAudit(StoreAuditQueryCriteria criteria) { |
| | | Page<Object> page = new Page<>(criteria.getPage(), criteria.getSize()); |
| | | return ResponseEntity.ok(R.success(auditService.queryAll(criteria, page))); |
| | | } |
| | | |
| | | @PostMapping |
| | | @Log("新增审批信息") |
| | | @ApiOperation("新增审批信息") |
| | | //@PreAuthorize("@el.check('storeAudit:add')") |
| | | public ResponseEntity<Object> createStoreAudit(@Validated @RequestBody StoreAudit resources) { |
| | | auditService.create(resources); |
| | | return new ResponseEntity<>(HttpStatus.CREATED); |
| | | } |
| | | |
| | | @PutMapping |
| | | @Log("修改审批信息") |
| | | @ApiOperation("修改审批信息") |
| | | //@PreAuthorize("@el.check('storeAudit:edit')") |
| | | public ResponseEntity<Object> updateStoreAudit(@Validated @RequestBody StoreAudit resources) { |
| | | auditService.update(resources, false); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | | @PutMapping(value = "/verdict") |
| | | @ApiOperation("处理审核") |
| | | //@PreAuthorize("@el.check('merchant:store:create')") |
| | | public ResponseEntity<?> submitAuditVerdict(@RequestBody StoreAudit resources) { |
| | | auditService.processVerdict(resources); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | | @DeleteMapping |
| | | @Log("删除审批信息") |
| | | @ApiOperation("删除审批信息") |
| | | //@PreAuthorize("@el.check('storeAudit:del')") |
| | | public ResponseEntity<Object> deleteStoreAudit(@ApiParam(value = "传ID数组[]") @RequestBody List<Long> ids) { |
| | | auditService.deleteAll(ids); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | } |
| | |
| | | return ResponseEntity.ok(R.success(storeService.getById(storeId))); |
| | | } |
| | | |
| | | @GetMapping(value = "/{storeId}/name-check") |
| | | public ResponseEntity<?> checkStoreName(@RequestParam String storeName) { |
| | | return ResponseEntity.ok(R.success(storeService.existsStoreName(storeName))); |
| | | } |
| | | |
| | | @PostMapping |
| | | @ApiOperation("创建店铺") |
| | | public ResponseEntity<?> create(@RequestBody StoreCreateRequest request) { |
| | |
| | | import com.oying.modules.pc.product.service.ProductService; |
| | | import com.oying.modules.pc.store.domain.Store; |
| | | import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria; |
| | | import com.oying.modules.pc.store.domain.enums.StoreStatusEnum; |
| | | import com.oying.modules.pc.store.service.StoreQualificationService; |
| | | import com.oying.modules.pc.store.service.StoreQueryService; |
| | | import com.oying.modules.pc.store.service.StoreService; |
| | |
| | | @ApiOperation("查询店铺") |
| | | public ResponseEntity<?> getStoresByPage(StoreQueryCriteria criteria) { |
| | | criteria.setLimit(1000); |
| | | criteria.setBusinessStatus(StoreStatusEnum.OPEN.getValue()); |
| | | PageResult<Store> pagedStores = storeQueryService.findPagedStores(criteria); |
| | | pagedStores.getContent().forEach(store -> store.setProducts(this.getProductsByStoreId(store.getStoreId()))); |
| | | return ResponseEntity.ok(R.success(pagedStores)); |
| | |
| | | public ResponseEntity<?> getStoreDetailsById(@PathVariable("storeId") Long storeId) { |
| | | Store store = storeService.getById(storeId); |
| | | if (ObjUtil.isNotEmpty(store)) { |
| | | store.setQualifications(storeQualificationService.queryByStoreId(storeId)); |
| | | store.setQualifications(storeQualificationService.getByStoreId(storeId)); |
| | | } |
| | | return ResponseEntity.ok(R.success(store)); |
| | | } |
| | |
| | | |
| | | 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 cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.oying.modules.pc.store.domain.dto.StoreUpdateRequest; |
| | | import com.oying.modules.pc.store.service.StoreQualificationService; |
| | | import com.oying.utils.R; |
| | | import com.oying.exception.BadRequestException; |
| | | import com.oying.modules.pc.store.domain.Store; |
| | | import com.oying.modules.pc.store.domain.dto.StoreCreateRequest; |
| | | import com.oying.modules.pc.store.domain.dto.StoreFieldUpdateRequest; |
| | | import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria; |
| | | import com.oying.modules.pc.store.service.StoreCreateService; |
| | | import com.oying.modules.pc.store.service.StoreService; |
| | | import com.oying.modules.pc.store.domain.dto.*; |
| | | import com.oying.modules.pc.store.domain.enums.StoreStatusEnum; |
| | | import com.oying.modules.pc.store.service.*; |
| | | import com.oying.modules.pc.store.view.StoreMerchantView; |
| | | import com.oying.modules.pc.store.view.StoreSimpleView; |
| | | import com.oying.utils.R; |
| | | import com.oying.utils.SecurityUtils; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | private final StoreService storeService; |
| | | private final StoreCreateService storeCreateService; |
| | | private final StoreQualificationService storeQualificationService; |
| | | private final StoreQueryService storeQueryService; |
| | | private final StoreMerchantService storeMerchantService; |
| | | |
| | | @GetMapping(value = "/list") |
| | | @ApiOperation("查询所有店铺") |
| | | //@PreAuthorize("@el.check('merchant:store:list')") |
| | | public ResponseEntity<?> getList() { |
| | | List<Store> stores = Optional.ofNullable(storeService.queryUserStores(SecurityUtils.getCurrentUserId())).orElse(ListUtil.empty()); |
| | | List<Store> stores = Optional.ofNullable(storeService.getUserStores(SecurityUtils.getCurrentUserId())).orElse(ListUtil.empty()); |
| | | return ResponseEntity.ok(R.success(stores)); |
| | | } |
| | | |
| | |
| | | @ApiOperation("查询所有店铺") |
| | | //@PreAuthorize("@el.check('merchant:store:list')") |
| | | public ResponseEntity<?> getSimpleStores() { |
| | | List<Store> stores = Optional.ofNullable(storeService.queryUserStores(SecurityUtils.getCurrentUserId())).orElse(ListUtil.empty()); |
| | | List<Store> stores = Optional.ofNullable(storeService.getUserStores(SecurityUtils.getCurrentUserId())).orElse(ListUtil.empty()); |
| | | List<StoreSimpleView> storeViewList = stores.stream().map(i -> { |
| | | StoreSimpleView view = new StoreSimpleView(); |
| | | BeanUtil.copyProperties(i, view, CopyOptions.create().setIgnoreNullValue(true)); |
| | |
| | | public ResponseEntity<?> getStoreDetailsById(@PathVariable Long storeId) { |
| | | Store store = storeService.getById(storeId); |
| | | if (ObjUtil.isNotEmpty(store)) { |
| | | store.setQualifications(storeQualificationService.queryByStoreId(storeId)); |
| | | store.setQualifications(storeQualificationService.getByStoreId(storeId)); |
| | | } |
| | | return ResponseEntity.ok(R.success(store)); |
| | | } |
| | |
| | | @ApiOperation("创建店铺") |
| | | //@PreAuthorize("@el.check('merchant:store:create')") |
| | | public ResponseEntity<?> create(@RequestBody StoreCreateRequest request) { |
| | | return ResponseEntity.status(HttpStatus.CREATED).body(storeCreateService.create(request)); |
| | | return ResponseEntity.status(HttpStatus.CREATED).body(storeMerchantService.createStore(request)); |
| | | } |
| | | |
| | | @PostMapping(value = "/{storeId}/audit/submit") |
| | | @ApiOperation("提交审核") |
| | | //@PreAuthorize("@el.check('merchant:store:create')") |
| | | public ResponseEntity<?> submitAudit(@PathVariable Long storeId) { |
| | | storeMerchantService.submitStoreAudit(storeId); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | | /** |
| | | * 修改店铺信息 |
| | | */ |
| | | @PostMapping(value = "/{storeId}") |
| | | @PutMapping(value = "/{storeId}") |
| | | @ApiOperation("修改店铺") |
| | | //@PreAuthorize("@el.check('merchant:store:update')" + |
| | | // " and @storeMerchantOwnershipService.check(#storeId)") |
| | | public ResponseEntity<?> update(@PathVariable("storeId") Long storeId, @RequestBody StoreUpdateRequest request) { |
| | | request.setStoreId(ObjectUtil.defaultIfNull(request.getStoreId(), storeId)); |
| | | storeService.update(request); |
| | | storeMerchantService.updateStore(request); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | |
| | | public ResponseEntity<?> updateLogo(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreLogoImageGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | | storeService.updateLogo(storeId, request.getLogoImageUploadId(), request.getVersion()); |
| | | Long logeImageId = Optional.ofNullable(request.getLogoImageId()).orElse(Long.getLong(request.getLogoImageUploadId())); |
| | | storeService.updateLogo(storeId, logeImageId, request.getVersion()); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | |
| | | public ResponseEntity<?> updateName(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreNameGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | | storeService.updateName(storeId, request.getStoreName(), request.getVersion()); |
| | | StoreUpdateRequest updateRequest = new StoreUpdateRequest(); |
| | | updateRequest.setStoreId(storeId); |
| | | updateRequest.setStoreName(request.getStoreName()); |
| | | storeMerchantService.updateStore(updateRequest); |
| | | //storeMerchantService.saveRevisionStore(request, StoreRevisionTypeEnum.NAME_UPDATE); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | |
| | |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/contactPhone") |
| | | @ApiOperation("修改店铺联系电话") |
| | | @PreAuthorize("@el.check('merchant:store:list')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | /*@PreAuthorize("@el.check('merchant:store:list')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> updateContactPhone(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreContactPhoneGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/address") |
| | | @ApiOperation("修改店铺地址") |
| | | @PreAuthorize("@el.check('merchant:store:address')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | /*@PreAuthorize("@el.check('merchant:store:address')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> updateAddress(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreAddressGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/location") |
| | | @ApiOperation("修改店铺坐标") |
| | | @PreAuthorize("@el.check('merchant:store:location')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | /*@PreAuthorize("@el.check('merchant:store:location')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> updateLocation(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreLocationGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/radius") |
| | | @ApiOperation("修改店铺配送范围") |
| | | @PreAuthorize("@el.check('merchant:store:radius')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | /*@PreAuthorize("@el.check('merchant:store:radius')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> updateRadius(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreRadiusGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/platformCategory") |
| | | @ApiOperation("修改店铺绑定的经营类目") |
| | | @PreAuthorize("@el.check('merchant:store:platformCategory')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | /*@PreAuthorize("@el.check('merchant:store:platformCategory')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> updatePlatformCategory(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStorePlatformCategoryGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/businessHours") |
| | | @ApiOperation("修改店铺营业时间") |
| | | @PreAuthorize("@el.check('merchant:store:businessHours')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | /*@PreAuthorize("@el.check('merchant:store:businessHours')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> updateBusinessHours(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreBusinessHoursGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/deliveryMinimum") |
| | | @ApiOperation("修改起送金额") |
| | | @PreAuthorize("@el.check('merchant:store:deliveryMinimum')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | /*@PreAuthorize("@el.check('merchant:store:deliveryMinimum')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> updateDeliveryMinimum(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreDeliveryMinimumGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/deliveryFee") |
| | | @ApiOperation("修改配送费用") |
| | | @PreAuthorize("@el.check('merchant:store:deliveryFee')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | /*@PreAuthorize("@el.check('merchant:store:deliveryFee')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> updateDeliveryFee(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreDeliveryFeeGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | |
| | | * 修改状态 |
| | | */ |
| | | @PatchMapping(value = "/{storeId}/businessStatus") |
| | | @ApiOperation("修改状态") |
| | | @PreAuthorize("@el.check('merchant:store:businessStatus')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)") |
| | | @ApiOperation("修改营业状态") |
| | | /*@PreAuthorize("@el.check('merchant:store:businessStatus')" + |
| | | " and @storeMerchantOwnershipService.check(#storeId)")*/ |
| | | public ResponseEntity<?> businessStatus(@PathVariable("storeId") Long storeId, |
| | | @Validated(value = StoreFieldUpdateRequest.UpdateStoreBusinessStatusGroup.class) |
| | | @RequestBody StoreFieldUpdateRequest request) { |
| | | storeService.updateStatus(storeId, request.getBusinessStatus(), request.getVersion()); |
| | | //storeService.updateStatus(storeId, request.getBusinessStatus(), request.getVersion()); |
| | | Store store = new Store(); |
| | | store.setStoreId(storeId); |
| | | store.setStatus(request.getBusinessStatus()); |
| | | store.setBusinessStatus(request.getBusinessStatus()); |
| | | Set<Integer> statusEnumSet = CollectionUtil.newHashSet(StoreStatusEnum.OPEN.getValue(), StoreStatusEnum.CLOSED.getValue()); |
| | | if (!statusEnumSet.contains(request.getBusinessStatus())) { |
| | | throw new BadRequestException("状态错误"); |
| | | } |
| | | storeMerchantService.updateBusinessStatus(store); |
| | | return ResponseEntity.noContent().build(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.service; |
| | | |
| | | import com.oying.modules.pc.store.domain.StoreAudit; |
| | | import com.oying.modules.pc.store.domain.dto.StoreAuditQueryCriteria; |
| | | |
| | | import java.util.List; |
| | | import java.io.IOException; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.oying.utils.PageResult; |
| | | |
| | | /** |
| | | * @description 服务接口 |
| | | * @author lzp |
| | | * @date 2025-07-01 |
| | | **/ |
| | | public interface StoreAuditService extends IService<StoreAudit> { |
| | | |
| | | /** |
| | | * 查询数据分页 |
| | | * @param criteria 条件 |
| | | * @param page 分页参数 |
| | | * @return PageResult |
| | | */ |
| | | PageResult<StoreAudit> queryAll(StoreAuditQueryCriteria criteria, Page<Object> page); |
| | | |
| | | /** |
| | | * 查询所有数据不分页 |
| | | * @param criteria 条件参数 |
| | | * @return List<StoreRevisionDto> |
| | | */ |
| | | List<StoreAudit> queryAll(StoreAuditQueryCriteria criteria); |
| | | |
| | | /** |
| | | * 店铺ID查询修订数据, |
| | | * |
| | | * @param storeId 必须的参数,不能为null |
| | | * @return 查询到的结果 |
| | | */ |
| | | StoreAudit getByStoreId(Long storeId); |
| | | |
| | | /** |
| | | * 是否有待审记录 |
| | | * |
| | | * @param storeId 必须的参数,不能为null |
| | | * @return 查询到的结果 |
| | | */ |
| | | boolean hasPendingByStoreId(Long storeId); |
| | | |
| | | /** |
| | | * 创建 |
| | | * @param resources / |
| | | */ |
| | | void create(StoreAudit resources); |
| | | |
| | | /** |
| | | * 编辑 |
| | | * @param resources / |
| | | */ |
| | | void update(StoreAudit resources, boolean isDirectUpdate); |
| | | |
| | | /** |
| | | * 多选删除 |
| | | * @param ids / |
| | | */ |
| | | void deleteAll(List<Long> ids); |
| | | |
| | | /** |
| | | * 导出数据 |
| | | * @param all 待导出的数据 |
| | | * @param response / |
| | | * @throws IOException / |
| | | */ |
| | | void download(List<StoreAudit> all, HttpServletResponse response) throws IOException; |
| | | |
| | | void processVerdict(StoreAudit resources); |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.service; |
| | | |
| | | import com.oying.modules.pc.store.domain.Store; |
| | | import com.oying.modules.pc.store.domain.dto.StoreCreateRequest; |
| | | import com.oying.modules.pc.store.domain.dto.StoreUpdateRequest; |
| | | import com.oying.modules.pc.store.events.StoreAuditVerdictEvent; |
| | | |
| | | public interface StoreMerchantService { |
| | | |
| | | Store createStore(StoreCreateRequest request); |
| | | void updateStore(StoreUpdateRequest request); |
| | | void updateBusinessStatus(Store resources); |
| | | void submitStoreAudit(Long storeId); |
| | | void handleStoreAudit(StoreAuditVerdictEvent event); |
| | | |
| | | } |
| | |
| | | * @param storeId 条件参数 |
| | | * @return List<StoreQualification> |
| | | */ |
| | | List<StoreQualification> queryByStoreId(Long storeId); |
| | | List<StoreQualification> getByStoreId(Long storeId); |
| | | |
| | | /** |
| | | * 创建 |
| | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalTime; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * 店铺基础信息Service接口 |
| | |
| | | |
| | | List<Store> queryAll(StoreQueryCriteria criteria); |
| | | |
| | | List<Long> queryStoreIds(StoreQueryCriteria criteria); |
| | | |
| | | Store getMerchantStore(Long merchantId); |
| | | |
| | | List<Store> queryUserStores(Long userId); |
| | | List<Store> getStoresByIds(Set<Long> ids); |
| | | |
| | | List<Store> getUserStores(Long userId); |
| | | |
| | | Store getOrThrow(Long storeId, Long version); |
| | | |
| | | void create(Store resources); |
| | | |
| | | Store create(StoreCreateRequest request); |
| | | |
| | | boolean update(Store resources, boolean isDirectUpdate); |
| | | |
| | | boolean update(StoreUpdateRequest request); |
| | | |
| | | boolean updateLogo(Long storeId, String logo, Long version); |
| | | boolean updateLogo(Long storeId, Long logoImageId, Long version); |
| | | |
| | | boolean updateName(Long storeId, String storeName, Long version); |
| | | |
| | |
| | | boolean existsByIdAndMerchantId(Long storeId, Long merchantId); |
| | | |
| | | boolean existsStoreName(String storeName); |
| | | |
| | | boolean bindUser(Long store); |
| | | } |
New file |
| | |
| | | package com.oying.modules.pc.store.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.oying.exception.BadRequestException; |
| | | import com.oying.modules.pc.common.core.constrant.AuditStatusEnum; |
| | | import com.oying.modules.pc.store.domain.StoreAudit; |
| | | import com.oying.modules.pc.store.domain.dto.StoreAuditQueryCriteria; |
| | | import com.oying.modules.pc.store.events.StoreAuditVerdictEvent; |
| | | import com.oying.modules.pc.store.mapper.StoreAuditMapper; |
| | | import com.oying.modules.pc.store.service.StoreAuditService; |
| | | import com.oying.utils.FileUtil; |
| | | import com.oying.utils.PageResult; |
| | | import com.oying.utils.PageUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author lzp |
| | | * @description 服务实现 |
| | | * @date 2025-07-01 |
| | | **/ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class StoreAuditServiceImpl extends ServiceImpl<StoreAuditMapper, StoreAudit> implements StoreAuditService { |
| | | |
| | | private final ApplicationEventPublisher eventPublisher; |
| | | |
| | | private final StoreAuditMapper storeAuditMapper; |
| | | |
| | | @Override |
| | | public PageResult<StoreAudit> queryAll(StoreAuditQueryCriteria criteria, Page<Object> page) { |
| | | return PageUtil.toPage(storeAuditMapper.findAll(criteria, page)); |
| | | } |
| | | |
| | | @Override |
| | | public List<StoreAudit> queryAll(StoreAuditQueryCriteria criteria) { |
| | | return storeAuditMapper.findAll(criteria); |
| | | } |
| | | |
| | | @Override |
| | | public StoreAudit getByStoreId(Long storeId) { |
| | | LambdaQueryWrapper<StoreAudit> wrapper = new LambdaQueryWrapper<StoreAudit>() |
| | | .eq(StoreAudit::getStoreId, storeId); |
| | | return storeAuditMapper.selectOne(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasPendingByStoreId(Long storeId) { |
| | | LambdaQueryWrapper<StoreAudit> wrapper = new LambdaQueryWrapper<StoreAudit>() |
| | | .eq(StoreAudit::getStoreId, storeId) |
| | | .eq(StoreAudit::getStatus, AuditStatusEnum.PENDING.getValue()); |
| | | return storeAuditMapper.selectCount(wrapper) > 0; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void create(StoreAudit resources) { |
| | | storeAuditMapper.insert(resources); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void update(StoreAudit resources, boolean isDirectUpdate) { |
| | | if (isDirectUpdate) { |
| | | storeAuditMapper.updateById(resources); |
| | | } else { |
| | | StoreAudit existingRevision = this.getById(resources.getAuditor()); |
| | | existingRevision.copy(resources); |
| | | storeAuditMapper.updateById(existingRevision); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void processVerdict(StoreAudit resources) { |
| | | AuditStatusEnum newAuditStatus = AuditStatusEnum.get(resources.getStatus()); |
| | | StoreAudit existingAudit = this.getById(resources.getAuditId()); |
| | | AuditStatusEnum existingAuditStatus = AuditStatusEnum.getOrDefault(existingAudit.getStatus(), AuditStatusEnum.DRAFT); |
| | | if (!existingAuditStatus.nextContains(newAuditStatus)) { |
| | | throw new BadRequestException("审核状态错误"); |
| | | } |
| | | existingAudit.copy(resources); |
| | | storeAuditMapper.updateById(existingAudit); |
| | | eventPublisher.publishEvent(new StoreAuditVerdictEvent(existingAudit.getAuditId())); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteAll(List<Long> ids) { |
| | | storeAuditMapper.deleteBatchIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | public void download(List<StoreAudit> all, HttpServletResponse response) throws IOException { |
| | | List<Map<String, Object>> list = new ArrayList<>(); |
| | | for (StoreAudit storeRevision : all) { |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("审核ID", storeRevision.getAuditId()); |
| | | map.put("店铺ID", storeRevision.getStoreId()); |
| | | map.put("审批ID", storeRevision.getAuditId()); |
| | | map.put("类型", storeRevision.getType()); |
| | | map.put("新数据", storeRevision.getData()); |
| | | map.put("创建人", storeRevision.getCreateBy()); |
| | | map.put("创建时间", storeRevision.getCreateTime()); |
| | | map.put("修改人", storeRevision.getUpdateBy()); |
| | | map.put("修改时间", storeRevision.getUpdateTime()); |
| | | list.add(map); |
| | | } |
| | | FileUtil.downloadExcel(list, response); |
| | | } |
| | | } |
| | |
| | | import com.oying.modules.pc.store.domain.Store; |
| | | import com.oying.modules.pc.store.domain.dto.StoreCreateRequest; |
| | | import com.oying.modules.pc.store.service.StoreCreateService; |
| | | import com.oying.modules.pc.store.service.StoreService; |
| | | import com.oying.modules.pc.store.service.StoreMerchantService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | @RequiredArgsConstructor |
| | | public class StoreCreateServiceImpl implements StoreCreateService { |
| | | |
| | | private final StoreService storeService; |
| | | private final StoreMerchantService storeMerchantService; |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Store create(StoreCreateRequest request) { |
| | | return storeService.create(request); |
| | | return storeMerchantService.createStore(request); |
| | | } |
| | | } |
New file |
| | |
| | | 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()); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<StoreQualification> queryByStoreId(Long storeId) { |
| | | public List<StoreQualification> getByStoreId(Long storeId) { |
| | | LambdaQueryWrapper<StoreQualification> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(StoreQualification::getStoreId, storeId); |
| | | return storeQualificationMapper.selectList(wrapper); |
| | |
| | | package com.oying.modules.pc.store.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.collection.ListUtil; |
| | | import cn.hutool.core.util.NumberUtil; |
| | | import com.oying.modules.pc.store.domain.Store; |
| | | import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria; |
| | | import com.oying.modules.pc.store.mapper.StoreMapper; |
| | | import com.oying.modules.pc.store.service.StoreQueryService; |
| | | import com.oying.modules.pc.store.service.StoreService; |
| | | import com.oying.utils.PageResult; |
| | |
| | | |
| | | private final RedisTemplate<Object, Object> redisTemplate; |
| | | private final StoreService storeService; |
| | | private final StoreMapper storeMapper; |
| | | |
| | | @Override |
| | | public PageResult<Store> findPagedStores(StoreQueryCriteria criteria) { |
| | |
| | | Long total = redisTemplate.opsForZSet().size(setKey); |
| | | if (total == null || total == 0) { |
| | | // 初始化缓存 |
| | | List<Long> ids = storeMapper.queryStoreIds(criteria); |
| | | List<Long> ids = storeService.queryStoreIds(criteria); |
| | | int index = 0; |
| | | for (Long id : ids) { |
| | | redisTemplate.opsForZSet().add(setKey, id, index++); |
| | |
| | | Set<Long> storeIds = Optional.ofNullable(redisTemplate.opsForZSet().range(setKey, offset, end)) |
| | | .orElse(Collections.emptySet()) |
| | | .stream() |
| | | .map(i-> (Long) i) |
| | | .map(i -> (Long) i) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | // 3. 获取详情数据] |
| | | List<Store> stores = Optional.of(storeIds) |
| | | .filter(CollectionUtil::isNotEmpty) |
| | | .map(storeService::listByIds) |
| | | .map(storeService::getStoresByIds) |
| | | .orElse(ListUtil.toList()); |
| | | |
| | | stores.forEach(u -> u.setDeliveryDuration(distanceCalculation(criteria.getLatitude(), criteria.getLongitude(), u.getLatitude(), u.getLongitude()))); |
| | | |
| | | page.setContent(stores); |
| | | page.setTotalElements(total); |
| | | return page; |
| | | } |
| | | |
| | | private Integer distanceCalculation(double lat1, double lon1, double lat2, double lon2) { |
| | | // 地球半径(千米) |
| | | final int R = 6371; |
| | | // 将纬度、经度从度转换为弧度 |
| | | double latDistance = Math.toRadians(lat2 - lat1); |
| | | double lonDistance = Math.toRadians(lon2 - lon1); |
| | | double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) |
| | | + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) |
| | | * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2); |
| | | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); |
| | | return new Double(R * c * 1000).intValue(); |
| | | } |
| | | } |
| | |
| | | package com.oying.modules.pc.store.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.collection.ListUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.oying.exception.BadRequestException; |
| | | import com.oying.exception.EntityNotFoundException; |
| | | import com.oying.modules.pc.common.ValueUpdate; |
| | | 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.StoreQualification; |
| | | import com.oying.modules.pc.store.domain.StoreUser; |
| | | import com.oying.modules.pc.store.domain.dto.StoreCreateRequest; |
| | | import com.oying.modules.pc.store.domain.dto.StoreQualificationCreateRequest; |
| | | import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria; |
| | | import com.oying.modules.pc.store.domain.dto.StoreUpdateRequest; |
| | | import com.oying.modules.pc.store.mapper.StoreMapper; |
| | | import com.oying.modules.pc.store.mapper.StoreUserMapper; |
| | | import com.oying.modules.pc.store.service.StoreQualificationService; |
| | | import com.oying.modules.pc.store.service.StoreService; |
| | | import com.oying.service.BucketStorageService; |
| | | import com.oying.utils.PageResult; |
| | | import com.oying.utils.PageUtil; |
| | | import com.oying.utils.SecurityUtils; |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalTime; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.util.Optional; |
| | | import java.util.stream.Collectors; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * 店铺Service业务层处理 |
| | |
| | | |
| | | private final StoreMapper storeMapper; |
| | | private final StoreUserMapper storeUserMapper; |
| | | private final StoreQualificationService qualificationService; |
| | | private final BucketStorageService bucketStorageService; |
| | | |
| | | @Override |
| | | public PageResult<Store> queryByPage(StoreQueryCriteria criteria) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<Long> queryStoreIds(StoreQueryCriteria criteria) { |
| | | return storeMapper.queryStoreIds(criteria); |
| | | } |
| | | |
| | | @Override |
| | | public Store getMerchantStore(Long merchantId) { |
| | | return storeMapper.selectStoreByMerchantId(merchantId); |
| | | } |
| | | |
| | | @Override |
| | | public List<Store> queryUserStores(Long userId) { |
| | | public List<Store> getStoresByIds(Set<Long> ids) { |
| | | return storeMapper.queryByIds(ids); |
| | | } |
| | | |
| | | @Override |
| | | public List<Store> getUserStores(Long userId) { |
| | | return storeMapper.queryUserStores(userId); |
| | | } |
| | | |
| | | @Override |
| | | public Store getOrThrow(Long storeId, Long version) { |
| | | Objects.requireNonNull(storeId, String.format("方法 '%s' 调用失败:参数 'storeId'(店铺ID)不能为 null", "findOrThrow")); |
| | | LambdaQueryWrapper<Store> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(Store::getStoreId, storeId); |
| | | if (ObjUtil.isNotEmpty(version)) { |
| | | wrapper.eq(Store::getVersion, version); |
| | | } |
| | | Store existingStore = storeMapper.selectOne(wrapper); |
| | | if (ObjUtil.isEmpty(existingStore)) { |
| | | throw new EntityNotFoundException(Store.class, "storeId", storeId.toString()); |
| | | } |
| | | return existingStore; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void create(Store resources) { |
| | | storeMapper.insert(resources); |
| | | } |
| | | |
| | | @Override |
| | |
| | | // 创建店铺 |
| | | Store store = StoreAssembler.to(request); |
| | | storeMapper.insert(store); |
| | | this.processQualificationCreate(store, request.getQualificationList()); |
| | | this.bindUser(store.getStoreId()); |
| | | return store; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean update(Store resources, boolean isDirectUpdate) { |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(resources.getStoreId(), resources.getVersion()); |
| | | if (isDirectUpdate) { |
| | | return this.update(resources, wrapper); |
| | | } else { |
| | | Store existingStore = this.getById(resources.getStoreId()); |
| | | existingStore.copy(resources); |
| | | return this.update(existingStore, wrapper); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean update(StoreUpdateRequest request) { |
| | | Store existingStore = this.findOrThrow(request); |
| | | this.processImagesUpdate(request, existingStore); |
| | | this.processQualificationUpdate(request); |
| | | Store existingStore = this.getOrThrow(request.getStoreId(), request.getVersion()); |
| | | existingStore.copy(StoreAssembler.to(request)); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(existingStore.getStoreId(), existingStore.getVersion()); |
| | | return this.update(existingStore, wrapper); |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean updateLogo(Long storeId, String logo, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | public boolean updateLogo(Long storeId, Long logoImageId, Long version) { |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getLogoImageId, logo); |
| | | .set(Store::getLogoImageId, logoImageId); |
| | | return update(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateName(Long storeId, String storeName, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getStoreName, storeName); |
| | | return update(wrapper); |
| | |
| | | |
| | | @Override |
| | | public boolean updateDescription(Long storeId, String description, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getDescription, description); |
| | | return update(wrapper); |
| | |
| | | |
| | | @Override |
| | | public boolean updateContactPhone(Long storeId, String contactPhone, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getContactPhone, contactPhone); |
| | | return update(wrapper); |
| | |
| | | |
| | | @Override |
| | | public boolean updateAddress(Long storeId, String address, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getAddress, address); |
| | | return update(wrapper); |
| | |
| | | |
| | | @Override |
| | | public boolean updateLocation(Long storeId, Double longitude, Double latitude, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getLongitude, longitude) |
| | | .set(Store::getLatitude, latitude); |
| | |
| | | |
| | | @Override |
| | | public boolean updateRadius(Long storeId, Integer radius, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getRadius, radius); |
| | | return update(wrapper); |
| | |
| | | |
| | | @Override |
| | | public boolean updatePlatformCategory(Long storeId, Long platformCategory, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getPlatformCategoryId, platformCategory); |
| | | return update(wrapper); |
| | |
| | | |
| | | @Override |
| | | public boolean updateBusinessHours(Long storeId, LocalTime openTime, LocalTime endTime, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getOpenTime, openTime) |
| | | .set(Store::getCloseTime, endTime); |
| | |
| | | |
| | | @Override |
| | | public boolean updateDeliveryMinimum(Long storeId, BigDecimal deliveryMinimum, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getDeliveryMinimum, deliveryMinimum); |
| | | return update(wrapper); |
| | |
| | | |
| | | @Override |
| | | public boolean updateDeliveryFee(Long storeId, BigDecimal deliveryFee, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getDeliveryFee, deliveryFee); |
| | | return update(wrapper); |
| | |
| | | |
| | | @Override |
| | | public boolean updateStatus(Long storeId, Integer status, Long version) { |
| | | Store existingStore = this.findOrThrow(storeId, version); |
| | | Store existingStore = this.getOrThrow(storeId, version); |
| | | LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion()) |
| | | .set(Store::getStatus, status); |
| | | return update(wrapper); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public boolean existsByIdAndMerchantId(Long storeId, Long merchantId) { |
| | | if (storeId == null || merchantId == null) { |
| | | return false; |
| | | } |
| | | Store store = getById(storeId); |
| | | return Optional.ofNullable(store).map(i -> merchantId.equals(i.getMerchantId())).orElse(false); |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | private void bindUser(Long storeId) { |
| | | public boolean bindUser(Long storeId) { |
| | | StoreUser storeUser = new StoreUser(); |
| | | storeUser.setStoreId(storeId); |
| | | storeUser.setUserId(SecurityUtils.getCurrentUserId()); |
| | | storeUser.setRoleType(""); |
| | | storeUser.setPermissions(""); |
| | | storeUserMapper.insert(storeUser); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean existsByIdAndMerchantId(Long storeId, Long merchantId) { |
| | | if (storeId == null || merchantId == null) { |
| | | return false; |
| | | } |
| | | Store store = getById(storeId); |
| | | return Optional.ofNullable(store).map(i -> merchantId.equals(i.getMerchantId())).orElse(false); |
| | | } |
| | | |
| | | private LambdaUpdateWrapper<Store> createLambdaUpdateWrapper(Long storeId, Long version) { |
| | |
| | | updateWrapper.eq(Store::getVersion, version); |
| | | updateWrapper.set(Store::getVersion, version + 1); |
| | | } |
| | | updateWrapper.set(Store::getUpdateBy, SecurityUtils.getCurrentUserId()); |
| | | return updateWrapper; |
| | | } |
| | | |
| | | private Store findOrThrow(StoreUpdateRequest request) { |
| | | return this.findOrThrow(request.getStoreId(), request.getVersion()); |
| | | } |
| | | |
| | | private Store findOrThrow(Long storeId, Long version) { |
| | | Objects.requireNonNull(storeId, String.format("方法 '%s' 调用失败:参数 'storeId'(店铺ID)不能为 null", "findOrThrow")); |
| | | LambdaQueryWrapper<Store> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(Store::getStoreId, storeId); |
| | | if (ObjUtil.isNotEmpty(version)) { |
| | | wrapper.eq(Store::getVersion, version); |
| | | } |
| | | Store existingStore = storeMapper.selectOne(wrapper); |
| | | if (ObjUtil.isEmpty(existingStore)) { |
| | | throw new EntityNotFoundException(Store.class, "storeId", storeId.toString()); |
| | | } |
| | | return existingStore; |
| | | } |
| | | |
| | | 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 processImagesUpdate(StoreUpdateRequest request, Store existingStore) { |
| | | List<ValueUpdate<Long>> imageValues = ListUtil.toList( |
| | | new ValueUpdate<>(request.getLogoImageId(), existingStore.getLogoImageId()), |
| | | new ValueUpdate<>(request.getCoverImageId(), existingStore.getCoverImageId()) |
| | | ); |
| | | bucketStorageService.deleteAll(this.getDeleteImageIds(imageValues)); |
| | | } |
| | | |
| | | private void processQualificationUpdate(StoreUpdateRequest request) { |
| | | if (CollectionUtil.isNotEmpty(request.getDeletedQualificationIds())) { |
| | | qualificationService.deleteAll(request.getDeletedQualificationIds()); |
| | | } |
| | | if (CollectionUtil.isNotEmpty(request.getUpdatedQualifications())) { |
| | | qualificationService.batchUpdate(request.getUpdatedQualifications()); |
| | | } |
| | | if (CollectionUtil.isNotEmpty(request.getNewQualifications())) { |
| | | qualificationService.batchCreate(request.getNewQualifications()); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8" ?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > |
| | | <mapper namespace="com.oying.modules.pc.product.mapper.ProductAuditMapper"> |
| | | <resultMap id="BaseResultMap" type="com.oying.modules.pc.product.domain.ProductAudit"> |
| | | <id column="audit_id" property="auditId"/> |
| | | <result column="product_id" property="productId"/> |
| | | <result column="type" property="type"/> |
| | | <result column="status" property="status"/> |
| | | <result column="data" property="data"/> |
| | | <result column="reason" property="reason"/> |
| | | <result column="auditor" property="auditor"/> |
| | | <result column="audit_time" property="auditTime"/> |
| | | <result column="create_by" property="createBy"/> |
| | | <result column="create_time" property="createTime"/> |
| | | <result column="update_by" property="updateBy"/> |
| | | <result column="update_time" property="updateTime"/> |
| | | </resultMap> |
| | | |
| | | <sql id="Base_Column_List"> |
| | | audit_id, product_id, type, status, reason, auditor, audit_time, data, create_by, create_time, update_by, update_time |
| | | </sql> |
| | | |
| | | <select id="findAll" resultMap="BaseResultMap"> |
| | | select |
| | | <include refid="Base_Column_List"/> |
| | | from pc_product_audit |
| | | <where> |
| | | <if test="criteria.productId != null"> |
| | | and product_id = #{criteria.productId} |
| | | </if> |
| | | <if test="criteria.type != null and criteria.type != ''"> |
| | | and type = #{criteria.type} |
| | | </if> |
| | | </where> |
| | | order by audit_id desc |
| | | </select> |
| | | </mapper> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8" ?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > |
| | | <mapper namespace="com.oying.modules.pc.store.mapper.StoreAuditMapper"> |
| | | <resultMap id="BaseResultMap" type="com.oying.modules.pc.store.domain.StoreAudit"> |
| | | <id column="audit_id" property="auditId"/> |
| | | <result column="store_id" property="storeId"/> |
| | | <result column="type" property="type"/> |
| | | <result column="status" property="status"/> |
| | | <result column="data" property="data"/> |
| | | <result column="reason" property="reason"/> |
| | | <result column="auditor" property="auditor"/> |
| | | <result column="audit_time" property="auditTime"/> |
| | | <result column="create_by" property="createBy"/> |
| | | <result column="create_time" property="createTime"/> |
| | | <result column="update_by" property="updateBy"/> |
| | | <result column="update_time" property="updateTime"/> |
| | | </resultMap> |
| | | |
| | | <sql id="Base_Column_List"> |
| | | audit_id, store_id, type, status, reason, auditor, audit_time, data, create_by, create_time, update_by, update_time |
| | | </sql> |
| | | |
| | | <select id="findAll" resultMap="BaseResultMap"> |
| | | select |
| | | <include refid="Base_Column_List"/> |
| | | from pc_store_audit |
| | | <where> |
| | | <if test="criteria.storeId != null"> |
| | | and store_id = #{criteria.storeId} |
| | | </if> |
| | | <if test="criteria.type != null and criteria.type != ''"> |
| | | and type = #{criteria.type} |
| | | </if> |
| | | </where> |
| | | order by audit_id desc |
| | | </select> |
| | | </mapper> |
| | |
| | | <result property="storeName" column="store_name"/> |
| | | <result property="businessScope" column="business_scope"/> |
| | | <result property="status" column="status"/> |
| | | <result property="businessStatus" column="business_status"/> |
| | | <result property="auditStatus" column="audit_status"/> |
| | | <result property="logoImageId" column="logo_image_id"/> |
| | | <result property="logoImageUrl" column="logo_image_url"/> |
| | | <result property="coverImageId" column="cover_image_id"/> |
| | | <result property="coverImageUrl" column="cover_image_url"/> |
| | | <result property="description" column="description"/> |
| | | <result property="tags" column="tags"/> |
| | | <result property="deliveryFee" column="delivery_fee"/> |
| | |
| | | <result property="geoHash" column="geo_hash"/> |
| | | <result property="coordinateSystem" column="coordinate_system"/> |
| | | <result property="radius" column="radius"/> |
| | | <result column="returns" property="returns"/> |
| | | <result column="self_pickup" property="selfPickup"/> |
| | | <result property="returns" column="returns" /> |
| | | <result property="selfPickup" column="self_pickup"/> |
| | | <result property="createBy" column="create_by"/> |
| | | <result property="createTime" column="create_time"/> |
| | | <result property="updateBy" column="update_by"/> |
| | | <result property="updateTime" column="update_time"/> |
| | | <result column="version" property="version"/> |
| | | <result property="version" column="version"/> |
| | | </resultMap> |
| | | |
| | | <sql id="store_column_list"> |
| | | store_id, merchant_id, platform_category_id, store_type, store_code, store_name, business_scope, status, logo_image_id, |
| | | cover_image_id, description, tags, delivery_fee, delivery_minimum, contact_phone, open_time, close_time, |
| | | store_id, merchant_id, platform_category_id, store_type, store_code, store_name, business_scope, status, business_status, audit_status, logo_image_id, logo_image_url, |
| | | cover_image_id, cover_image_url, description, tags, delivery_fee, delivery_minimum, contact_phone, open_time, close_time, |
| | | address, longitude, latitude, geo_hash, geo_point, coordinate_system, radius, returns, self_pickup, create_by, create_time, update_by, update_time, version |
| | | </sql> |
| | | |
| | | <sql id="selectStoreVo"> |
| | | select |
| | | store_id, merchant_id, platform_category_id, store_type, store_code, store_name, business_scope, status, logo_image_id, |
| | | cover_image_id, description, tags, delivery_fee, delivery_minimum, contact_phone, open_time, close_time, |
| | | store_id, merchant_id, platform_category_id, store_type, store_code, store_name, business_scope, status, business_status, audit_status, logo_image_id, logo_image_url, |
| | | cover_image_id, cover_image_url, description, tags, delivery_fee, delivery_minimum, contact_phone, open_time, close_time, |
| | | address, longitude, latitude, geo_hash, geo_point, coordinate_system, radius, returns, self_pickup, create_by, create_time, update_by, update_time, version from pc_store |
| | | </sql> |
| | | |
| | |
| | | </if> |
| | | |
| | | <!-- 营业状态 --> |
| | | <if test="criteria.status != null"> |
| | | AND s.status = #{criteria.status} |
| | | <if test="criteria.businessStatus != null"> |
| | | AND s.business_status = #{criteria.businessStatus} |
| | | </if> |
| | | |
| | | <!-- 类目ID --> |
| | |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="queryByIds" resultMap="StoreResult"> |
| | | SELECT |
| | | <include refid="store_column_list"/> |
| | | FROM pc_store |
| | | WHERE store_id IN |
| | | <foreach collection="ids" item="id" open="(" separator="," close=")"> |
| | | #{id} |
| | | </foreach> |
| | | </select> |
| | | |
| | | <select id="queryUserStores" parameterType="java.lang.Long" resultMap="StoreResult"> |
| | | SELECT s.* |
| | | FROM sys_user_store u INNER JOIN pc_store s ON u.store_id = s.store_id |