客户关联产品开发

This commit is contained in:
朱昊天
2026-06-18 18:19:07 +08:00
parent 27807c14eb
commit d1506d24e5
13 changed files with 717 additions and 3 deletions

View File

@@ -0,0 +1,75 @@
package com.gear.oa.controller;
import com.gear.common.annotation.Log;
import com.gear.common.annotation.RepeatSubmit;
import com.gear.common.core.controller.BaseController;
import com.gear.common.core.domain.R;
import com.gear.common.core.validate.AddGroup;
import com.gear.common.enums.BusinessType;
import com.gear.oa.domain.bo.GearCustomerProductBo;
import com.gear.oa.domain.vo.GearCustomerProductVo;
import com.gear.oa.service.IGearCustomerProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
/**
* 客户-产品关联
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/oa/customerProduct")
public class GearCustomerProductController extends BaseController {
private final IGearCustomerProductService iGearCustomerProductService;
/**
* 查询客户关联产品列表
*/
@GetMapping("/customer/{customerId}")
public R<List<GearCustomerProductVo>> listByCustomer(@NotNull(message = "客户ID不能为空")
@PathVariable Long customerId) {
return R.ok(iGearCustomerProductService.queryByCustomerId(customerId));
}
/**
* 查询产品关联客户列表
*/
@GetMapping("/product/{productId}")
public R<List<GearCustomerProductVo>> listByProduct(@NotNull(message = "产品ID不能为空")
@PathVariable Long productId) {
return R.ok(iGearCustomerProductService.queryByProductId(productId));
}
/**
* 新增客户关联产品
*/
@Log(title = "客户关联产品", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping
public R<Void> add(@Validated(AddGroup.class) @RequestBody GearCustomerProductBo bo) {
return toAjax(iGearCustomerProductService.insertByBo(bo));
}
/**
* 删除客户关联产品
*/
@Log(title = "客户关联产品", businessType = BusinessType.DELETE)
@DeleteMapping("/{relationIds}")
public R<Void> remove(@NotEmpty(message = "关联ID不能为空")
@PathVariable Long[] relationIds) {
return toAjax(iGearCustomerProductService.deleteWithValidByIds(Arrays.asList(relationIds), true));
}
}

View File

@@ -0,0 +1,46 @@
package com.gear.oa.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.gear.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 客户-产品关联对象 gear_customer_product
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("gear_customer_product")
public class GearCustomerProduct extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 关联ID
*/
@TableId(value = "relation_id")
private Long relationId;
/**
* 客户ID
*/
private Long customerId;
/**
* 产品ID
*/
private Long productId;
/**
* 备注
*/
private String remark;
/**
* 删除标志0=正常1=已删除)
*/
@TableLogic
private Integer delFlag;
}

View File

@@ -0,0 +1,40 @@
package com.gear.oa.domain.bo;
import com.gear.common.core.domain.BaseEntity;
import com.gear.common.core.validate.AddGroup;
import com.gear.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
/**
* 客户-产品关联业务对象
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class GearCustomerProductBo extends BaseEntity {
/**
* 关联ID
*/
@NotNull(message = "关联ID不能为空", groups = EditGroup.class)
private Long relationId;
/**
* 客户ID
*/
@NotNull(message = "客户ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long customerId;
/**
* 产品ID
*/
@NotNull(message = "产品ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long productId;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,47 @@
package com.gear.oa.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 客户-产品关联视图对象
*/
@Data
@ExcelIgnoreUnannotated
public class GearCustomerProductVo {
private static final long serialVersionUID = 1L;
@ExcelProperty(value = "关联ID")
private Long relationId;
@ExcelProperty(value = "客户ID")
private Long customerId;
@ExcelProperty(value = "客户名称")
private String customerName;
@ExcelProperty(value = "产品ID")
private Long productId;
@ExcelProperty(value = "产品编号")
private String productCode;
@ExcelProperty(value = "产品名称")
private String productName;
@ExcelProperty(value = "负责人")
private String owner;
@ExcelProperty(value = "单位")
private String unit;
@ExcelProperty(value = "备注")
private String remark;
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,24 @@
package com.gear.oa.mapper;
import com.gear.common.core.mapper.BaseMapperPlus;
import com.gear.oa.domain.GearCustomerProduct;
import com.gear.oa.domain.vo.GearCustomerProductVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 客户-产品关联Mapper接口
*/
public interface GearCustomerProductMapper extends BaseMapperPlus<GearCustomerProductMapper, GearCustomerProduct, GearCustomerProductVo> {
/**
* 按客户查询关联产品
*/
List<GearCustomerProductVo> selectByCustomerId(@Param("customerId") Long customerId);
/**
* 按产品查询关联客户
*/
List<GearCustomerProductVo> selectByProductId(@Param("productId") Long productId);
}

View File

@@ -0,0 +1,33 @@
package com.gear.oa.service;
import com.gear.oa.domain.bo.GearCustomerProductBo;
import com.gear.oa.domain.vo.GearCustomerProductVo;
import java.util.Collection;
import java.util.List;
/**
* 客户-产品关联Service接口
*/
public interface IGearCustomerProductService {
/**
* 按客户查询关联产品
*/
List<GearCustomerProductVo> queryByCustomerId(Long customerId);
/**
* 按产品查询关联客户
*/
List<GearCustomerProductVo> queryByProductId(Long productId);
/**
* 新增客户-产品关联
*/
Boolean insertByBo(GearCustomerProductBo bo);
/**
* 批量删除客户-产品关联
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,81 @@
package com.gear.oa.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gear.common.exception.ServiceException;
import com.gear.oa.domain.GearCustomerProduct;
import com.gear.oa.domain.bo.GearCustomerProductBo;
import com.gear.oa.domain.vo.GearCustomerProductVo;
import com.gear.oa.mapper.GearCustomerMapper;
import com.gear.oa.mapper.GearCustomerProductMapper;
import com.gear.oa.mapper.GearProductMapper;
import com.gear.oa.service.IGearCustomerProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
/**
* 客户-产品关联Service业务层处理
*/
@RequiredArgsConstructor
@Service
public class GearCustomerProductServiceImpl implements IGearCustomerProductService {
private final GearCustomerProductMapper baseMapper;
private final GearCustomerMapper customerMapper;
private final GearProductMapper productMapper;
@Override
public List<GearCustomerProductVo> queryByCustomerId(Long customerId) {
return baseMapper.selectByCustomerId(customerId);
}
@Override
public List<GearCustomerProductVo> queryByProductId(Long productId) {
return baseMapper.selectByProductId(productId);
}
@Override
public Boolean insertByBo(GearCustomerProductBo bo) {
validEntityBeforeSave(bo);
GearCustomerProduct add = BeanUtil.toBean(bo, GearCustomerProduct.class);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setRelationId(add.getRelationId());
}
return flag;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid && (ids == null || ids.isEmpty())) {
throw new ServiceException("关联ID不能为空");
}
return baseMapper.deleteBatchIds(ids) > 0;
}
private void validEntityBeforeSave(GearCustomerProductBo bo) {
if (bo.getCustomerId() == null) {
throw new ServiceException("客户不能为空");
}
if (bo.getProductId() == null) {
throw new ServiceException("产品不能为空");
}
if (customerMapper.selectById(bo.getCustomerId()) == null) {
throw new ServiceException("客户不存在");
}
if (productMapper.selectById(bo.getProductId()) == null) {
throw new ServiceException("产品不存在");
}
Long count = baseMapper.selectCount(
Wrappers.<GearCustomerProduct>lambdaQuery()
.eq(GearCustomerProduct::getCustomerId, bo.getCustomerId())
.eq(GearCustomerProduct::getProductId, bo.getProductId())
);
if (count != null && count > 0) {
throw new ServiceException("该客户已关联此产品,请勿重复添加");
}
}
}

View File

@@ -0,0 +1,59 @@
<?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.gear.oa.mapper.GearCustomerProductMapper">
<resultMap type="com.gear.oa.domain.GearCustomerProduct" id="GearCustomerProductResult">
<result property="relationId" column="relation_id"/>
<result property="customerId" column="customer_id"/>
<result property="productId" column="product_id"/>
<result property="remark" column="remark"/>
<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 property="delFlag" column="del_flag"/>
</resultMap>
<select id="selectByCustomerId" resultType="com.gear.oa.domain.vo.GearCustomerProductVo">
select
cp.relation_id,
cp.customer_id,
c.name as customer_name,
cp.product_id,
p.product_code,
p.product_name,
p.owner,
p.unit,
cp.remark,
cp.create_time
from gear_customer_product cp
left join gear_customer c on c.customer_id = cp.customer_id and c.del_flag = 0
left join gear_product p on p.product_id = cp.product_id and p.del_flag = 0
where cp.del_flag = 0
and cp.customer_id = #{customerId}
order by cp.create_time desc, cp.relation_id desc
</select>
<select id="selectByProductId" resultType="com.gear.oa.domain.vo.GearCustomerProductVo">
select
cp.relation_id,
cp.customer_id,
c.name as customer_name,
cp.product_id,
p.product_code,
p.product_name,
p.owner,
p.unit,
cp.remark,
cp.create_time
from gear_customer_product cp
left join gear_customer c on c.customer_id = cp.customer_id and c.del_flag = 0
left join gear_product p on p.product_id = cp.product_id and p.del_flag = 0
where cp.del_flag = 0
and cp.product_id = #{productId}
order by cp.create_time desc, cp.relation_id desc
</select>
</mapper>