客户编辑添加绑定套餐
This commit is contained in:
+78
@@ -0,0 +1,78 @@
|
|||||||
|
package com.ruoyi.web.controller.customer.customerinfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
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 com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsCustomerPriceSet;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsPriceSetOption;
|
||||||
|
import com.ruoyi.customer.customerinfo.service.IBmsCustomerPriceSetService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户套餐绑定Controller(客户管理-客户编辑-绑定套餐)
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-09-16
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/customersupplier/customerinfo/priceset")
|
||||||
|
public class BmsCustomerPriceSetController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private IBmsCustomerPriceSetService customerPriceSetService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询客户已绑定的套餐列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('customersupplier:customerinfo:list')")
|
||||||
|
@GetMapping("/bind/list")
|
||||||
|
public AjaxResult bindList(Long customerId)
|
||||||
|
{
|
||||||
|
List<BmsCustomerPriceSet> list = customerPriceSetService.selectBindList(customerId);
|
||||||
|
return success(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询可绑定的生效套餐选项
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('customersupplier:customerinfo:list')")
|
||||||
|
@GetMapping("/option/list")
|
||||||
|
public AjaxResult optionList(BmsPriceSetOption query)
|
||||||
|
{
|
||||||
|
return success(customerPriceSetService.selectOptionList(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存客户套餐绑定(已绑定则更新/更换套餐,未绑定则新增)
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('customersupplier:customerinfo:edit')")
|
||||||
|
@Log(title = "客户套餐绑定", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping("/bind")
|
||||||
|
public AjaxResult saveBind(@RequestBody BmsCustomerPriceSet bind)
|
||||||
|
{
|
||||||
|
bind.setCreateBy(getUsername());
|
||||||
|
bind.setUpdateBy(getUsername());
|
||||||
|
return toAjax(customerPriceSetService.saveBind(bind));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解绑客户套餐
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('customersupplier:customerinfo:edit')")
|
||||||
|
@Log(title = "客户套餐解绑", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/bind/{customerPricesetIds}")
|
||||||
|
public AjaxResult removeBind(@PathVariable Long[] customerPricesetIds)
|
||||||
|
{
|
||||||
|
return toAjax(customerPriceSetService.deleteBindByIds(customerPricesetIds));
|
||||||
|
}
|
||||||
|
}
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
package com.ruoyi.customer.customerinfo.domain;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户套餐绑定对象 prc_customer_price_set
|
||||||
|
* 客户管理-客户编辑-绑定套餐 使用;关联 prc_price_set 的字段仅用于页面展示
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-09-16
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class BmsCustomerPriceSet extends BaseEntity
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 客户价格套餐ID */
|
||||||
|
private Long customerPricesetId;
|
||||||
|
|
||||||
|
/** 价格套餐ID */
|
||||||
|
private Long priceSetId;
|
||||||
|
|
||||||
|
/** 客户ID */
|
||||||
|
private Long customerId;
|
||||||
|
|
||||||
|
/** 客户代码 */
|
||||||
|
private String customerCode;
|
||||||
|
|
||||||
|
/** 客户名称 */
|
||||||
|
private String customerName;
|
||||||
|
|
||||||
|
/** 绑定优先级,数字越小越优先 */
|
||||||
|
private Integer bindPriority;
|
||||||
|
|
||||||
|
/** 价格开始生效日期 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date prBegindate;
|
||||||
|
|
||||||
|
/** 价格失效日期(空=长期) */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date prEnddate;
|
||||||
|
|
||||||
|
/** 绑定备注 */
|
||||||
|
private String priceSetNote;
|
||||||
|
|
||||||
|
/* -------- 关联 prc_price_set 展示字段 -------- */
|
||||||
|
|
||||||
|
/** 套餐编码 */
|
||||||
|
private String priceSetCode;
|
||||||
|
|
||||||
|
/** 套餐名称 */
|
||||||
|
private String priceSetName;
|
||||||
|
|
||||||
|
/** 计价类型 FIXED=固定价 DISCOUNT=折扣 */
|
||||||
|
private String setType;
|
||||||
|
|
||||||
|
/** 套餐状态 D草稿 A审核中 E生效 R驳回 S停用 */
|
||||||
|
private String priceSetStatus;
|
||||||
|
|
||||||
|
/** 套餐生效日期 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date setEffectiveDate;
|
||||||
|
|
||||||
|
/** 套餐失效日期 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date setExpireDate;
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package com.ruoyi.customer.customerinfo.domain;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 价格套餐(prc_price_set)简要对象
|
||||||
|
* 仅用于客户编辑-绑定套餐的套餐下拉选择,不参与套餐维护
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-09-16
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BmsPriceSetOption
|
||||||
|
{
|
||||||
|
/** 价格套餐ID */
|
||||||
|
private Long priceSetId;
|
||||||
|
|
||||||
|
/** 套餐编码 */
|
||||||
|
private String priceSetCode;
|
||||||
|
|
||||||
|
/** 套餐名称 */
|
||||||
|
private String priceSetName;
|
||||||
|
|
||||||
|
/** 计价类型 FIXED=固定价 DISCOUNT=折扣 */
|
||||||
|
private String setType;
|
||||||
|
|
||||||
|
/** 套餐状态 D草稿 A审核中 E生效 R驳回 S停用 */
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/** 生效日期 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date effectiveDate;
|
||||||
|
|
||||||
|
/** 失效日期(空=长期) */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date expireDate;
|
||||||
|
|
||||||
|
/** 关键字(编码/名称模糊) */
|
||||||
|
private String keyword;
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
package com.ruoyi.customer.customerinfo.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsCustomerPriceSet;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsPriceSetOption;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户套餐绑定 数据层(客户管理侧独立实现,操作 prc_customer_price_set)
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-09-16
|
||||||
|
*/
|
||||||
|
public interface BmsCustomerPriceSetMapper
|
||||||
|
{
|
||||||
|
/** 按客户查绑定列表(join prc_price_set 取套餐展示字段) */
|
||||||
|
public List<BmsCustomerPriceSet> selectBindListByCustomerId(@Param("customerId") Long customerId);
|
||||||
|
|
||||||
|
/** 按主键查绑定 */
|
||||||
|
public BmsCustomerPriceSet selectBindById(Long customerPricesetId);
|
||||||
|
|
||||||
|
/** 按客户ID查绑定(uk_customer_one_set 保证至多一条) */
|
||||||
|
public BmsCustomerPriceSet selectBindByCustomerId(@Param("customerId") Long customerId);
|
||||||
|
|
||||||
|
/** 新增绑定 */
|
||||||
|
public int insertBind(BmsCustomerPriceSet bind);
|
||||||
|
|
||||||
|
/** 更新绑定(允许更换套餐 price_set_id 与生效区间/优先级/备注) */
|
||||||
|
public int updateBind(BmsCustomerPriceSet bind);
|
||||||
|
|
||||||
|
/** 按主键批量解绑 */
|
||||||
|
public int deleteBindByIds(Long[] customerPricesetIds);
|
||||||
|
|
||||||
|
/** 套餐下拉选项(只列生效中套餐,可按关键字/类型过滤) */
|
||||||
|
public List<BmsPriceSetOption> selectPriceSetOptionList(BmsPriceSetOption query);
|
||||||
|
|
||||||
|
/** 按主键查套餐简要信息 */
|
||||||
|
public BmsPriceSetOption selectPriceSetOptionById(@Param("priceSetId") Long priceSetId);
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package com.ruoyi.customer.customerinfo.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsCustomerPriceSet;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsPriceSetOption;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户套餐绑定 服务层(客户管理侧)
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-09-16
|
||||||
|
*/
|
||||||
|
public interface IBmsCustomerPriceSetService
|
||||||
|
{
|
||||||
|
/** 查询某客户的套餐绑定列表 */
|
||||||
|
public List<BmsCustomerPriceSet> selectBindList(Long customerId);
|
||||||
|
|
||||||
|
/** 查询可绑定的生效套餐选项 */
|
||||||
|
public List<BmsPriceSetOption> selectOptionList(BmsPriceSetOption query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存客户套餐绑定(一个客户一条记录):已绑定则更新(支持更换套餐),未绑定则新增
|
||||||
|
*/
|
||||||
|
public int saveBind(BmsCustomerPriceSet bind);
|
||||||
|
|
||||||
|
/** 按绑定主键解绑 */
|
||||||
|
public int deleteBindByIds(Long[] customerPricesetIds);
|
||||||
|
}
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
package com.ruoyi.customer.customerinfo.service.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsCustomer;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsCustomerPriceSet;
|
||||||
|
import com.ruoyi.customer.customerinfo.domain.BmsPriceSetOption;
|
||||||
|
import com.ruoyi.customer.customerinfo.mapper.BmsCustomerPriceSetMapper;
|
||||||
|
import com.ruoyi.customer.customerinfo.service.IBmsCustomerPriceSetService;
|
||||||
|
import com.ruoyi.customer.customerinfo.service.IBmsCustomerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户套餐绑定 服务实现(客户管理侧,独立于价格套餐维护模块)
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2026-09-16
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class BmsCustomerPriceSetServiceImpl implements IBmsCustomerPriceSetService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private BmsCustomerPriceSetMapper bindMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IBmsCustomerService customerService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BmsCustomerPriceSet> selectBindList(Long customerId)
|
||||||
|
{
|
||||||
|
if (customerId == null)
|
||||||
|
{
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return bindMapper.selectBindListByCustomerId(customerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BmsPriceSetOption> selectOptionList(BmsPriceSetOption query)
|
||||||
|
{
|
||||||
|
return bindMapper.selectPriceSetOptionList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int saveBind(BmsCustomerPriceSet bind)
|
||||||
|
{
|
||||||
|
if (bind.getCustomerId() == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException("客户ID不能为空");
|
||||||
|
}
|
||||||
|
if (bind.getPriceSetId() == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException("请选择要绑定的套餐");
|
||||||
|
}
|
||||||
|
BmsCustomer customer = customerService.selectBmsCustomerByCustomerId(bind.getCustomerId());
|
||||||
|
if (customer == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException("客户不存在或已被删除");
|
||||||
|
}
|
||||||
|
BmsPriceSetOption set = bindMapper.selectPriceSetOptionById(bind.getPriceSetId());
|
||||||
|
if (set == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException("所选套餐不存在");
|
||||||
|
}
|
||||||
|
if (!"E".equals(set.getStatus()))
|
||||||
|
{
|
||||||
|
throw new ServiceException("仅生效中的套餐允许绑定,当前套餐状态不可用");
|
||||||
|
}
|
||||||
|
if (bind.getPrBegindate() == null)
|
||||||
|
{
|
||||||
|
bind.setPrBegindate(set.getEffectiveDate());
|
||||||
|
}
|
||||||
|
if (bind.getPrBegindate() == null)
|
||||||
|
{
|
||||||
|
throw new ServiceException("绑定生效日期不能为空");
|
||||||
|
}
|
||||||
|
if (bind.getPrEnddate() != null && bind.getPrBegindate().after(bind.getPrEnddate()))
|
||||||
|
{
|
||||||
|
throw new ServiceException("失效日期不能早于生效日期");
|
||||||
|
}
|
||||||
|
if (bind.getBindPriority() == null || bind.getBindPriority() < 1)
|
||||||
|
{
|
||||||
|
bind.setBindPriority(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bind.setCustomerCode(customer.getCustomerCode());
|
||||||
|
bind.setCustomerName(customer.getCustomerName());
|
||||||
|
|
||||||
|
BmsCustomerPriceSet existing = bindMapper.selectBindByCustomerId(bind.getCustomerId());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
bind.setCustomerPricesetId(existing.getCustomerPricesetId());
|
||||||
|
return bindMapper.updateBind(bind);
|
||||||
|
}
|
||||||
|
return bindMapper.insertBind(bind);
|
||||||
|
}
|
||||||
|
catch (DuplicateKeyException e)
|
||||||
|
{
|
||||||
|
throw new ServiceException("该客户已存在套餐绑定,请勿重复绑定");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int deleteBindByIds(Long[] customerPricesetIds)
|
||||||
|
{
|
||||||
|
if (customerPricesetIds == null || customerPricesetIds.length == 0)
|
||||||
|
{
|
||||||
|
throw new ServiceException("请选择要解绑的记录");
|
||||||
|
}
|
||||||
|
return bindMapper.deleteBindByIds(customerPricesetIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
+128
@@ -0,0 +1,128 @@
|
|||||||
|
<?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.ruoyi.customer.customerinfo.mapper.BmsCustomerPriceSetMapper">
|
||||||
|
|
||||||
|
<resultMap type="com.ruoyi.customer.customerinfo.domain.BmsCustomerPriceSet" id="BmsCustomerPriceSetResult">
|
||||||
|
<id property="customerPricesetId" column="customer_priceset_id" />
|
||||||
|
<result property="priceSetId" column="price_set_id" />
|
||||||
|
<result property="customerId" column="customer_id" />
|
||||||
|
<result property="customerCode" column="customer_code" />
|
||||||
|
<result property="customerName" column="customer_name" />
|
||||||
|
<result property="bindPriority" column="bind_priority" />
|
||||||
|
<result property="prBegindate" column="pr_begindate" />
|
||||||
|
<result property="prEnddate" column="pr_enddate" />
|
||||||
|
<result property="priceSetNote" column="price_set_note" />
|
||||||
|
<result property="createBy" column="created_by" />
|
||||||
|
<result property="createTime" column="create_time" />
|
||||||
|
<result property="updateBy" column="updated_by" />
|
||||||
|
<result property="updateTime" column="update_time" />
|
||||||
|
<result property="priceSetCode" column="price_set_code" />
|
||||||
|
<result property="priceSetName" column="price_set_name" />
|
||||||
|
<result property="setType" column="set_type" />
|
||||||
|
<result property="priceSetStatus" column="price_set_status" />
|
||||||
|
<result property="setEffectiveDate" column="set_effective_date" />
|
||||||
|
<result property="setExpireDate" column="set_expire_date" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<resultMap type="com.ruoyi.customer.customerinfo.domain.BmsPriceSetOption" id="BmsPriceSetOptionResult">
|
||||||
|
<id property="priceSetId" column="price_set_id" />
|
||||||
|
<result property="priceSetCode" column="price_set_code" />
|
||||||
|
<result property="priceSetName" column="price_set_name" />
|
||||||
|
<result property="setType" column="set_type" />
|
||||||
|
<result property="status" column="status" />
|
||||||
|
<result property="effectiveDate" column="effective_date" />
|
||||||
|
<result property="expireDate" column="expire_date" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="bindVo">
|
||||||
|
select c.customer_priceset_id, c.price_set_id, c.customer_id, c.customer_code, c.customer_name,
|
||||||
|
c.bind_priority, c.pr_begindate, c.pr_enddate, c.price_set_note,
|
||||||
|
c.created_by, c.create_time, c.updated_by, c.update_time,
|
||||||
|
s.price_set_code, s.price_set_name, s.set_type,
|
||||||
|
s.status as price_set_status,
|
||||||
|
s.effective_date as set_effective_date, s.expire_date as set_expire_date
|
||||||
|
from prc_customer_price_set c
|
||||||
|
left join prc_price_set s on s.price_set_id = c.price_set_id
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectBindListByCustomerId" resultMap="BmsCustomerPriceSetResult">
|
||||||
|
<include refid="bindVo"/>
|
||||||
|
where c.customer_id = #{customerId}
|
||||||
|
order by c.bind_priority asc, c.customer_priceset_id asc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectBindById" parameterType="Long" resultMap="BmsCustomerPriceSetResult">
|
||||||
|
<include refid="bindVo"/>
|
||||||
|
where c.customer_priceset_id = #{customerPricesetId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectBindByCustomerId" resultMap="BmsCustomerPriceSetResult">
|
||||||
|
select customer_priceset_id, price_set_id, customer_id, customer_code, customer_name,
|
||||||
|
bind_priority, pr_begindate, pr_enddate, price_set_note,
|
||||||
|
created_by, create_time, updated_by, update_time
|
||||||
|
from prc_customer_price_set
|
||||||
|
where customer_id = #{customerId}
|
||||||
|
limit 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertBind" parameterType="com.ruoyi.customer.customerinfo.domain.BmsCustomerPriceSet"
|
||||||
|
useGeneratedKeys="true" keyProperty="customerPricesetId">
|
||||||
|
insert into prc_customer_price_set (
|
||||||
|
price_set_id, customer_id, customer_code, customer_name,
|
||||||
|
bind_priority, pr_begindate, pr_enddate, price_set_note,
|
||||||
|
created_by, create_time
|
||||||
|
) values (
|
||||||
|
#{priceSetId}, #{customerId}, #{customerCode}, #{customerName},
|
||||||
|
#{bindPriority}, #{prBegindate}, #{prEnddate}, #{priceSetNote},
|
||||||
|
#{createBy}, sysdate()
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateBind" parameterType="com.ruoyi.customer.customerinfo.domain.BmsCustomerPriceSet">
|
||||||
|
update prc_customer_price_set
|
||||||
|
set price_set_id = #{priceSetId},
|
||||||
|
customer_code = #{customerCode},
|
||||||
|
customer_name = #{customerName},
|
||||||
|
bind_priority = #{bindPriority},
|
||||||
|
pr_begindate = #{prBegindate},
|
||||||
|
pr_enddate = #{prEnddate},
|
||||||
|
price_set_note = #{priceSetNote},
|
||||||
|
updated_by = #{updateBy},
|
||||||
|
update_time = sysdate()
|
||||||
|
where customer_priceset_id = #{customerPricesetId}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteBindByIds" parameterType="Long">
|
||||||
|
delete from prc_customer_price_set where customer_priceset_id in
|
||||||
|
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<select id="selectPriceSetOptionList"
|
||||||
|
parameterType="com.ruoyi.customer.customerinfo.domain.BmsPriceSetOption"
|
||||||
|
resultMap="BmsPriceSetOptionResult">
|
||||||
|
select price_set_id, price_set_code, price_set_name, set_type, status, effective_date, expire_date
|
||||||
|
from prc_price_set
|
||||||
|
<where>
|
||||||
|
status = 'E'
|
||||||
|
<if test="setType != null and setType != ''">
|
||||||
|
and set_type = #{setType}
|
||||||
|
</if>
|
||||||
|
<if test="keyword != null and keyword != ''">
|
||||||
|
and (price_set_code like concat('%', #{keyword}, '%')
|
||||||
|
or price_set_name like concat('%', #{keyword}, '%'))
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
order by price_set_id desc
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectPriceSetOptionById" resultMap="BmsPriceSetOptionResult">
|
||||||
|
select price_set_id, price_set_code, price_set_name, set_type, status, effective_date, expire_date
|
||||||
|
from prc_price_set
|
||||||
|
where price_set_id = #{priceSetId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import request from '@/utils/request.js'
|
||||||
|
|
||||||
|
// 查询客户已绑定的套餐列表
|
||||||
|
export function listCustomerPriceSet(customerId) {
|
||||||
|
return request({
|
||||||
|
url: '/customersupplier/customerinfo/priceset/bind/list',
|
||||||
|
method: 'get',
|
||||||
|
params: { customerId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询可绑定的生效套餐选项
|
||||||
|
export function listPriceSetOption(query) {
|
||||||
|
return request({
|
||||||
|
url: '/customersupplier/customerinfo/priceset/option/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存客户套餐绑定(已绑定则更新/更换,未绑定则新增)
|
||||||
|
export function saveCustomerPriceSet(data) {
|
||||||
|
return request({
|
||||||
|
url: '/customersupplier/customerinfo/priceset/bind',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解绑客户套餐
|
||||||
|
export function delCustomerPriceSet(customerPricesetIds) {
|
||||||
|
return request({
|
||||||
|
url: '/customersupplier/customerinfo/priceset/bind/' + customerPricesetIds,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -186,6 +186,50 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- ============ 绑定套餐 ============ -->
|
||||||
|
<el-tab-pane label="绑定套餐" name="priceSet">
|
||||||
|
<div class="pane-toolbar">
|
||||||
|
<el-button type="primary" plain icon="Plus" size="small" :disabled="isAdd" @click="openPriceSetDialog()">
|
||||||
|
{{ boundPriceSets.length ? '更换套餐' : '绑定套餐' }}
|
||||||
|
</el-button>
|
||||||
|
<span class="pane-tip">绑定后写入客户套餐关系表 prc_customer_price_set,一个客户仅可绑定一个价格套餐,仅「生效中」的套餐可绑定</span>
|
||||||
|
</div>
|
||||||
|
<el-table :data="boundPriceSets" border size="small" class="bound-table">
|
||||||
|
<el-table-column label="序号" type="index" width="55" align="center" />
|
||||||
|
<el-table-column label="套餐编码" prop="priceSetCode" width="120" show-overflow-tooltip />
|
||||||
|
<el-table-column label="套餐名称" prop="priceSetName" min-width="180" show-overflow-tooltip />
|
||||||
|
<el-table-column label="计价类型" width="90" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="row.setType === 'DISCOUNT' ? 'warning' : 'primary'" size="small">
|
||||||
|
{{ setTypeMap[row.setType] || row.setType || '-' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="套餐状态" width="90" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="priceSetStatusTagType[row.priceSetStatus] || 'info'" size="small">
|
||||||
|
{{ priceSetStatusMap[row.priceSetStatus] || '未知' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="优先级" prop="bindPriority" width="70" align="center" />
|
||||||
|
<el-table-column label="绑定生效" prop="prBegindate" width="110" align="center" />
|
||||||
|
<el-table-column label="绑定失效" width="100" align="center">
|
||||||
|
<template #default="{ row }">{{ row.prEnddate || '长期' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="备注" prop="priceSetNote" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column label="操作" width="120" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button link type="primary" size="small" @click="openPriceSetDialog(row)">更换</el-button>
|
||||||
|
<el-button link type="danger" size="small" @click="handleUnbindPriceSet(row)">解绑</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<template #empty>
|
||||||
|
<el-empty :description="isAdd ? '请先保存客户后再绑定套餐' : '暂未绑定套餐,点击上方「绑定套餐」'" :image-size="80" />
|
||||||
|
</template>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
<!-- ============ 公司主体 ============ -->
|
<!-- ============ 公司主体 ============ -->
|
||||||
<el-tab-pane label="公司主体" name="company">
|
<el-tab-pane label="公司主体" name="company">
|
||||||
<div class="pane-toolbar">
|
<div class="pane-toolbar">
|
||||||
@@ -582,6 +626,75 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- ====== 绑定套餐对话框 ====== -->
|
||||||
|
<el-dialog :title="priceSetDialogTitle" v-model="priceSetDialogVisible" width="560px" append-to-body>
|
||||||
|
<el-form ref="priceSetRef" :model="priceSetForm" :rules="priceSetRules" label-width="96px">
|
||||||
|
<el-form-item label="价格套餐" prop="priceSetId">
|
||||||
|
<el-select
|
||||||
|
v-model="priceSetForm.priceSetId"
|
||||||
|
filterable
|
||||||
|
placeholder="请选择生效中的套餐"
|
||||||
|
style="width: 100%;"
|
||||||
|
@change="onPriceSetChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="opt in priceSetOptions"
|
||||||
|
:key="opt.priceSetId"
|
||||||
|
:label="((opt.priceSetCode || '') + ' ' + opt.priceSetName).trim()"
|
||||||
|
:value="opt.priceSetId"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="selectedPriceSet" label="套餐信息">
|
||||||
|
<div class="ps-readonly">
|
||||||
|
<el-tag size="small" :type="selectedPriceSet.setType === 'DISCOUNT' ? 'warning' : 'primary'">
|
||||||
|
{{ setTypeMap[selectedPriceSet.setType] || selectedPriceSet.setType }}
|
||||||
|
</el-tag>
|
||||||
|
<span class="ps-readonly__range">
|
||||||
|
套餐有效期:{{ selectedPriceSet.effectiveDate || '-' }} 至 {{ selectedPriceSet.expireDate || '长期' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="优先级" prop="bindPriority">
|
||||||
|
<el-input-number v-model="priceSetForm.bindPriority" :min="1" controls-position="right" style="width: 100%;" />
|
||||||
|
<div class="pane-tip">数字越小优先级越高,1 为最高</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="生效日期" prop="prBegindate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="priceSetForm.prBegindate"
|
||||||
|
type="date"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
placeholder="选择日期"
|
||||||
|
style="width: 100%;"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="失效日期" prop="prEnddate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="priceSetForm.prEnddate"
|
||||||
|
type="date"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
placeholder="长期有效"
|
||||||
|
style="width: 100%;"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-form-item label="备注" prop="priceSetNote">
|
||||||
|
<el-input v-model="priceSetForm.priceSetNote" type="textarea" :rows="2" maxlength="100" show-word-limit placeholder="绑定备注(选填)" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" :loading="priceSetSaving" @click="submitPriceSetForm">确 定</el-button>
|
||||||
|
<el-button @click="priceSetDialogVisible = false">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -590,6 +703,10 @@ import {
|
|||||||
listCustomer, getCustomer, addCustomer, updateCustomer,
|
listCustomer, getCustomer, addCustomer, updateCustomer,
|
||||||
delCustomerCompany, delCustomerContact
|
delCustomerCompany, delCustomerContact
|
||||||
} from '@/api/customersuppliermanagement/customerinfo/customer.js'
|
} from '@/api/customersuppliermanagement/customerinfo/customer.js'
|
||||||
|
import {
|
||||||
|
listCustomerPriceSet, listPriceSetOption,
|
||||||
|
saveCustomerPriceSet, delCustomerPriceSet
|
||||||
|
} from '@/api/customersuppliermanagement/customerinfo/customerPriceSet.js'
|
||||||
import { getToken } from '@/utils/auth'
|
import { getToken } from '@/utils/auth'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { saveAs } from 'file-saver'
|
import { saveAs } from 'file-saver'
|
||||||
@@ -664,6 +781,99 @@ function removeProduct(productId) {
|
|||||||
form.value.productIds = ids.join(',')
|
form.value.productIds = ids.join(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------- 套餐绑定(prc_customer_price_set,一客户一套餐) ---------------- */
|
||||||
|
const setTypeMap = { FIXED: '固定价', DISCOUNT: '折扣' }
|
||||||
|
const priceSetStatusMap = { D: '草稿', A: '审核中', E: '生效', R: '驳回', S: '停用' }
|
||||||
|
const priceSetStatusTagType = { D: 'info', A: 'warning', E: 'success', R: 'danger', S: 'info' }
|
||||||
|
|
||||||
|
const boundPriceSets = ref([])
|
||||||
|
const priceSetOptions = ref([])
|
||||||
|
const priceSetDialogVisible = ref(false)
|
||||||
|
const priceSetDialogTitle = ref('')
|
||||||
|
const priceSetSaving = ref(false)
|
||||||
|
const priceSetRef = ref()
|
||||||
|
const priceSetForm = ref({})
|
||||||
|
|
||||||
|
const priceSetRules = {
|
||||||
|
priceSetId: [{ required: true, message: '请选择价格套餐', trigger: 'change' }],
|
||||||
|
bindPriority: [{ required: true, message: '优先级不能为空', trigger: 'blur' }],
|
||||||
|
prBegindate: [{ required: true, message: '绑定生效日期不能为空', trigger: 'change' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedPriceSet = computed(() =>
|
||||||
|
priceSetOptions.value.find(o => o.priceSetId === priceSetForm.value.priceSetId)
|
||||||
|
)
|
||||||
|
|
||||||
|
/** 加载当前客户已绑定套餐 */
|
||||||
|
function loadBoundPriceSets() {
|
||||||
|
if (!form.value.customerId) {
|
||||||
|
boundPriceSets.value = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
listCustomerPriceSet(form.value.customerId).then(res => {
|
||||||
|
boundPriceSets.value = res.data || []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加载可绑定的生效套餐(仅加载一次) */
|
||||||
|
function ensurePriceSetOptions() {
|
||||||
|
if (priceSetOptions.value.length) return
|
||||||
|
listPriceSetOption().then(res => {
|
||||||
|
priceSetOptions.value = res.data || []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开绑定/更换套餐弹窗:row 为空=新增绑定,有值=更换 */
|
||||||
|
function openPriceSetDialog(row) {
|
||||||
|
if (!form.value.customerId) {
|
||||||
|
proxy.$modal.msgWarning('请先保存客户后再绑定套餐')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ensurePriceSetOptions()
|
||||||
|
priceSetForm.value = row
|
||||||
|
? { ...row }
|
||||||
|
: { priceSetId: null, bindPriority: 1, prBegindate: null, prEnddate: null, priceSetNote: null }
|
||||||
|
priceSetDialogTitle.value = row || boundPriceSets.value.length ? '更换套餐' : '绑定套餐'
|
||||||
|
priceSetDialogVisible.value = true
|
||||||
|
nextTick(() => proxy.$refs['priceSetRef'] && proxy.$refs['priceSetRef'].clearValidate())
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 选择套餐后,生效日期未填时默认带出套餐生效日期 */
|
||||||
|
function onPriceSetChange(priceSetId) {
|
||||||
|
const opt = priceSetOptions.value.find(o => o.priceSetId === priceSetId)
|
||||||
|
if (opt && !priceSetForm.value.prBegindate) {
|
||||||
|
priceSetForm.value.prBegindate = opt.effectiveDate || null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitPriceSetForm() {
|
||||||
|
proxy.$refs['priceSetRef'].validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
if (priceSetForm.value.prEnddate && priceSetForm.value.prBegindate > priceSetForm.value.prEnddate) {
|
||||||
|
proxy.$modal.msgWarning('失效日期不能早于生效日期')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const payload = { ...priceSetForm.value, customerId: form.value.customerId }
|
||||||
|
priceSetSaving.value = true
|
||||||
|
saveCustomerPriceSet(payload).then(() => {
|
||||||
|
proxy.$modal.msgSuccess('保存成功')
|
||||||
|
priceSetDialogVisible.value = false
|
||||||
|
loadBoundPriceSets()
|
||||||
|
}).finally(() => {
|
||||||
|
priceSetSaving.value = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleUnbindPriceSet(row) {
|
||||||
|
proxy.$modal.confirm(`确认解绑套餐「${row.priceSetName || row.priceSetCode || ''}」?解绑后该客户询价将不再命中此套餐。`)
|
||||||
|
.then(() => delCustomerPriceSet(row.customerPricesetId))
|
||||||
|
.then(() => {
|
||||||
|
proxy.$modal.msgSuccess('解绑成功')
|
||||||
|
loadBoundPriceSets()
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------------- 用户冗余姓名 ---------------- */
|
/* ---------------- 用户冗余姓名 ---------------- */
|
||||||
function handleUserChange(uid, user, nameField) {
|
function handleUserChange(uid, user, nameField) {
|
||||||
form.value[nameField] = user ? (user.nickName || user.userName || null) : null
|
form.value[nameField] = user ? (user.nickName || user.userName || null) : null
|
||||||
@@ -976,6 +1186,7 @@ function loadDetail(id) {
|
|||||||
form.value.attachmentList = form.value.attachmentList || []
|
form.value.attachmentList = form.value.attachmentList || []
|
||||||
form.value.companyList = form.value.companyList || []
|
form.value.companyList = form.value.companyList || []
|
||||||
form.value.contactList = form.value.contactList || []
|
form.value.contactList = form.value.contactList || []
|
||||||
|
loadBoundPriceSets()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,6 +1242,7 @@ function initByRoute() {
|
|||||||
loadDetail(customerId.value).finally(() => { pageLoading.value = false })
|
loadDetail(customerId.value).finally(() => { pageLoading.value = false })
|
||||||
} else {
|
} else {
|
||||||
form.value = buildEmptyForm()
|
form.value = buildEmptyForm()
|
||||||
|
boundPriceSets.value = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1085,4 +1297,14 @@ onMounted(() => {
|
|||||||
.bound-table {
|
.bound-table {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
.ps-readonly {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 13px;
|
||||||
|
&__range {
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user