渠道管理增加应收关联
This commit is contained in:
+7
-6
@@ -114,17 +114,18 @@ public class PayProductController extends BaseController
|
||||
return success(payProductService.selectTemplateOptions(payType));
|
||||
}
|
||||
|
||||
/** 渠道当前价格副本 */
|
||||
/** 渠道当前价格副本;payType 默认应付 AP */
|
||||
@PreAuthorize("@ss.hasAnyPermi('price:pay:query,data:serviceChannel:query,data:serviceChannel:edit')")
|
||||
@GetMapping("/channel/{channelId}")
|
||||
public AjaxResult channelPrice(@PathVariable String channelId)
|
||||
public AjaxResult channelPrice(@PathVariable String channelId,
|
||||
@RequestParam(value = "payType", required = false) String payType)
|
||||
{
|
||||
return success(payProductService.selectChannelPrice(channelId));
|
||||
return success(payProductService.selectChannelPrice(channelId, payType));
|
||||
}
|
||||
|
||||
/** 渠道只绑定产品编号,以后按有效期取价 */
|
||||
/** 渠道只绑定产品编号,以后按有效期取价;支持应收 AR 与应付 AP */
|
||||
@PreAuthorize("@ss.hasAnyPermi('price:pay:edit,data:serviceChannel:edit')")
|
||||
@Log(title = "渠道应付产品", businessType = BusinessType.UPDATE)
|
||||
@Log(title = "渠道产品绑定", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/channel/{channelId}/bind")
|
||||
public AjaxResult bindChannel(@PathVariable String channelId, @RequestBody ChannelProductMap link)
|
||||
{
|
||||
@@ -135,7 +136,7 @@ public class PayProductController extends BaseController
|
||||
return success();
|
||||
}
|
||||
payProductService.bindChannel(channelId, link.getProductId(), link.getPriceSetId(), payType);
|
||||
return success(payProductService.selectChannelPrice(channelId));
|
||||
return success(payProductService.selectChannelPrice(channelId, payType));
|
||||
}
|
||||
|
||||
/** 对照两个价格版本 */
|
||||
|
||||
@@ -15,6 +15,9 @@ public class ChannelProductMap
|
||||
/** 渠道表主键 srv_service_channel.id */
|
||||
private String channelId;
|
||||
|
||||
/** 渠道编码,对应 srv_service_channel.channel_code */
|
||||
private String channelCode;
|
||||
|
||||
private Long productId;
|
||||
|
||||
/** 应收套餐 prc_price_set.price_set_id */
|
||||
|
||||
@@ -22,7 +22,7 @@ public interface PayProductMapper
|
||||
|
||||
Long selectTemplateId(@Param("dictValue") String dictValue);
|
||||
|
||||
List<PayProduct> selectTemplateOptions();
|
||||
List<PayProduct> selectTemplateOptions(@Param("payType") String payType);
|
||||
|
||||
Integer selectMaxVersion(@Param("originId") Long originId);
|
||||
|
||||
|
||||
@@ -47,10 +47,13 @@ public interface IPayProductService
|
||||
/** 公共模板下拉。payType 为空时按应付 AP */
|
||||
List<PayProduct> selectTemplateOptions(String payType);
|
||||
|
||||
/** 渠道绑定的产品。返回的 originId 是不变的产品编号,价格是当前有效版 */
|
||||
/** 渠道绑定的产品。返回的 originId 是不变的产品编号,价格是当前有效版;默认应付 AP */
|
||||
PayProduct selectChannelPrice(String channelId);
|
||||
|
||||
/** 只绑定产品编号,不产生新版本。payType 为空时按应付 AP */
|
||||
/** 按收付类型查询渠道绑定产品,payType 为空时按应付 AP */
|
||||
PayProduct selectChannelPrice(String channelId, String payType);
|
||||
|
||||
/** 只绑定产品编号,不产生新版本;同时落 channel_code。payType 为空时按应付 AP */
|
||||
void bindChannel(String channelId, Long productId, Long priceSetId, String payType);
|
||||
|
||||
/** 取消渠道上指定收付类型的产品。payType 为空时按应付 AP */
|
||||
|
||||
+27
-9
@@ -35,6 +35,8 @@ import com.bms.price.domain.PayProductTerm;
|
||||
import com.bms.price.domain.PaySaveCommand;
|
||||
import com.bms.price.domain.PaySurcharge;
|
||||
import com.bms.price.domain.PayWeightBand;
|
||||
import com.bms.masterdata.domain.ServiceChannel;
|
||||
import com.bms.masterdata.mapper.ServiceChannelMapper;
|
||||
import com.bms.price.mapper.ChannelProductMapMapper;
|
||||
import com.bms.price.mapper.PayProductMapper;
|
||||
import com.bms.price.mapper.PayProductTermMapper;
|
||||
@@ -63,6 +65,9 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
@Autowired
|
||||
private ChannelProductMapMapper channelProductMapMapper;
|
||||
|
||||
@Autowired
|
||||
private ServiceChannelMapper serviceChannelMapper;
|
||||
|
||||
@Autowired
|
||||
private PayProductTermMapper payProductTermMapper;
|
||||
|
||||
@@ -276,21 +281,23 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
@Override
|
||||
public List<PayProduct> selectTemplateOptions(String payType)
|
||||
{
|
||||
if (!PAY_TYPE_AP.equals(payTypeOf(payType)))
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return payProductMapper.selectTemplateOptions();
|
||||
return payProductMapper.selectTemplateOptions(payTypeOf(payType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayProduct selectChannelPrice(String channelId)
|
||||
{
|
||||
return selectChannelPrice(channelId, PAY_TYPE_AP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayProduct selectChannelPrice(String channelId, String payType)
|
||||
{
|
||||
if (isBlank(channelId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Long root = channelProductRoot(channelId);
|
||||
Long root = channelProductRoot(channelId, payTypeOf(payType));
|
||||
if (root == null)
|
||||
{
|
||||
return null;
|
||||
@@ -937,10 +944,16 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
{
|
||||
throw new ServiceException("请先保存渠道,再选择产品");
|
||||
}
|
||||
ServiceChannel channel = serviceChannelMapper.selectServiceChannelById(channelId);
|
||||
if (channel == null || isBlank(channel.getChannelCode()))
|
||||
{
|
||||
throw new ServiceException("渠道不存在或渠道编码为空");
|
||||
}
|
||||
String type = payTypeOf(payType);
|
||||
Long storedId = PAY_TYPE_AP.equals(type) ? resolveRoot(productId) : productId;
|
||||
Long storedId = resolveRoot(productId);
|
||||
ChannelProductMap row = new ChannelProductMap();
|
||||
row.setChannelId(channelId);
|
||||
row.setChannelCode(channel.getChannelCode());
|
||||
row.setProductId(storedId);
|
||||
row.setPriceSetId(priceSetId);
|
||||
row.setPayType(type);
|
||||
@@ -1035,10 +1048,15 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
return saved;
|
||||
}
|
||||
|
||||
/** 渠道应付绑定记在映射表,产品编号是不变的根产品。 */
|
||||
/** 渠道产品绑定记在映射表,产品编号是不变的根产品。 */
|
||||
private Long channelProductRoot(String channelId)
|
||||
{
|
||||
ChannelProductMap link = channelProductMapMapper.selectByChannelAndType(channelId, PAY_TYPE_AP);
|
||||
return channelProductRoot(channelId, PAY_TYPE_AP);
|
||||
}
|
||||
|
||||
private Long channelProductRoot(String channelId, String payType)
|
||||
{
|
||||
ChannelProductMap link = channelProductMapMapper.selectByChannelAndType(channelId, payType);
|
||||
if (link == null || link.getProductId() == null)
|
||||
{
|
||||
return null;
|
||||
|
||||
@@ -5,8 +5,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<mapper namespace="com.bms.price.mapper.ChannelProductMapMapper">
|
||||
|
||||
<select id="selectByChannelAndType" resultType="com.bms.price.domain.ChannelProductMap">
|
||||
select id, channel_id as channelId, product_id as productId, price_set_id as priceSetId,
|
||||
pay_type as payType, create_by as createBy, create_time as createTime,
|
||||
select id, channel_id as channelId, channel_code as channelCode, product_id as productId,
|
||||
price_set_id as priceSetId, pay_type as payType, create_by as createBy, create_time as createTime,
|
||||
update_by as updateBy, update_time as updateTime
|
||||
from srv_channel_product_map
|
||||
where channel_id = #{channelId} and pay_type = #{payType}
|
||||
@@ -15,11 +15,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<insert id="upsert">
|
||||
insert into srv_channel_product_map (
|
||||
channel_id, product_id, price_set_id, pay_type, create_by, create_time, update_by, update_time
|
||||
channel_id, channel_code, product_id, price_set_id, pay_type, create_by, create_time, update_by, update_time
|
||||
) values (
|
||||
#{channelId}, #{productId}, #{priceSetId}, #{payType}, #{createBy}, sysdate(), #{updateBy}, sysdate()
|
||||
#{channelId}, #{channelCode}, #{productId}, #{priceSetId}, #{payType}, #{createBy}, sysdate(), #{updateBy}, sysdate()
|
||||
)
|
||||
on duplicate key update
|
||||
channel_code = values(channel_code),
|
||||
product_id = values(product_id),
|
||||
price_set_id = values(price_set_id),
|
||||
update_by = values(update_by),
|
||||
|
||||
@@ -212,7 +212,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<select id="selectTemplateOptions" resultMap="PayProductResult">
|
||||
select p.product_id, p.product_name, p.dict_value, p.sheet_name, p.supplier_name, p.effective_date,
|
||||
select p.product_id, p.product_name, p.product_type, p.dict_value, p.sheet_name, p.supplier_name, p.effective_date,
|
||||
p.currency, ifnull(cur.version_no, p.version_no) as version_no
|
||||
from pay_product p
|
||||
left join pay_product_term t on t.term_id = (
|
||||
@@ -227,6 +227,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
left join pay_product cur on cur.product_id = t.product_id
|
||||
where (p.channel_id is null or p.channel_id = '')
|
||||
and p.origin_id is null
|
||||
and ifnull(p.product_type, 'AP') = #{payType}
|
||||
order by p.product_name
|
||||
</select>
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ SET NAMES utf8mb4;
|
||||
CREATE TABLE IF NOT EXISTS `srv_channel_product_map` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`channel_id` varchar(50) NOT NULL COMMENT '渠道ID,对应 srv_service_channel.id',
|
||||
`product_id` bigint(20) NOT NULL COMMENT '产品ID,应付时为价卡产品编号',
|
||||
`channel_code` varchar(64) DEFAULT NULL COMMENT '渠道编码,对应 srv_service_channel.channel_code',
|
||||
`product_id` bigint(20) NOT NULL COMMENT '产品ID,应付/应收时为价卡产品编号',
|
||||
`price_set_id` bigint(20) DEFAULT NULL COMMENT '应收套餐ID,对应 prc_price_set.price_set_id',
|
||||
`pay_type` varchar(10) NOT NULL COMMENT '收付类型,字典 bms_pay_type:AR应收 AP应付',
|
||||
`create_by` varchar(64) DEFAULT NULL COMMENT '创建者',
|
||||
@@ -14,7 +15,8 @@ CREATE TABLE IF NOT EXISTS `srv_channel_product_map` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_channel_pay_type` (`channel_id`, `pay_type`),
|
||||
KEY `idx_channel_product_map_product` (`product_id`),
|
||||
KEY `idx_channel_product_map_price_set` (`price_set_id`)
|
||||
KEY `idx_channel_product_map_price_set` (`price_set_id`),
|
||||
KEY `idx_channel_product_map_channel_code` (`channel_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='渠道产品关系映射';
|
||||
|
||||
SET @sql = (
|
||||
@@ -30,6 +32,24 @@ PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql_channel_code = (
|
||||
SELECT IF(
|
||||
COUNT(*) = 0,
|
||||
'ALTER TABLE srv_channel_product_map ADD COLUMN channel_code varchar(64) DEFAULT NULL COMMENT ''渠道编码,对应 srv_service_channel.channel_code'' AFTER channel_id, ADD KEY idx_channel_product_map_channel_code (channel_code)',
|
||||
'SELECT 1'
|
||||
)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'srv_channel_product_map' AND COLUMN_NAME = 'channel_code'
|
||||
);
|
||||
PREPARE stmt FROM @sql_channel_code;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
UPDATE srv_channel_product_map m
|
||||
INNER JOIN srv_service_channel c ON c.id = m.channel_id
|
||||
SET m.channel_code = c.channel_code
|
||||
WHERE m.channel_code IS NULL OR m.channel_code = '';
|
||||
|
||||
SET @copy_sql = (
|
||||
SELECT IF(
|
||||
COUNT(*) > 0,
|
||||
|
||||
@@ -80,10 +80,11 @@ export function comparePay(leftId, rightId) {
|
||||
})
|
||||
}
|
||||
|
||||
export function getChannelPay(channelId) {
|
||||
export function getChannelPay(channelId, payType = 'AP') {
|
||||
return request({
|
||||
url: '/price/pay/channel/' + channelId,
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
params: { payType }
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +149,14 @@
|
||||
<div class="pay-tip">{{ payTip }}</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="应收产品">
|
||||
<el-select v-model="arOriginId" filterable clearable placeholder="选择已导入的应收产品" style="width: 280px" :disabled="viewing || !form.id" @change="onArOrigin">
|
||||
<el-option v-for="item in arOptions" :key="item.productId" :label="payOptionLabel(item)" :value="item.productId" />
|
||||
</el-select>
|
||||
<div class="pay-tip">{{ arTip }}</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -175,9 +183,13 @@ const open = ref(false)
|
||||
const viewing = ref(false)
|
||||
const title = ref('')
|
||||
const payOptions = ref([])
|
||||
const arOptions = ref([])
|
||||
const payOriginId = ref()
|
||||
const arOriginId = ref()
|
||||
const payProduct = ref(null)
|
||||
const arProduct = ref(null)
|
||||
const syncingPay = ref(false)
|
||||
const syncingAr = ref(false)
|
||||
const payTip = computed(() => {
|
||||
if (viewing.value) {
|
||||
if (payProduct.value?.versionNo) return `已绑定第 ${payProduct.value.versionNo} 版。`
|
||||
@@ -187,6 +199,15 @@ const payTip = computed(() => {
|
||||
if (payProduct.value?.versionNo) return `当前按有效期使用第 ${payProduct.value.versionNo} 版。历史订单按下单或计费时间取当时的版本。`
|
||||
return '选择产品后即绑定,按应付 AP 保存。'
|
||||
})
|
||||
const arTip = computed(() => {
|
||||
if (viewing.value) {
|
||||
if (arProduct.value?.versionNo) return `已绑定第 ${arProduct.value.versionNo} 版。`
|
||||
return arOriginId.value ? '已绑定应收产品。' : '未绑定应收产品。'
|
||||
}
|
||||
if (!form.value?.id) return '先保存渠道,再选择应收产品。渠道绑定的是产品编号,更新价格不会换编号。'
|
||||
if (arProduct.value?.versionNo) return `当前按有效期使用第 ${arProduct.value.versionNo} 版。历史订单按下单或计费时间取当时的版本。`
|
||||
return '选择产品后即绑定,按应收 AR 保存。'
|
||||
})
|
||||
|
||||
const openOptions = [
|
||||
{ label: '启用', value: '1' },
|
||||
@@ -260,10 +281,14 @@ function emptyForm() {
|
||||
|
||||
function resetPay() {
|
||||
syncingPay.value = true
|
||||
syncingAr.value = true
|
||||
payOriginId.value = undefined
|
||||
arOriginId.value = undefined
|
||||
payProduct.value = null
|
||||
arProduct.value = null
|
||||
nextTick(() => {
|
||||
syncingPay.value = false
|
||||
syncingAr.value = false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -276,11 +301,14 @@ function loadPayOptions() {
|
||||
listPayOptions('AP').then(res => {
|
||||
payOptions.value = res.data || []
|
||||
})
|
||||
listPayOptions('AR').then(res => {
|
||||
arOptions.value = res.data || []
|
||||
})
|
||||
}
|
||||
|
||||
function loadChannelPay(channelId) {
|
||||
syncingPay.value = true
|
||||
getChannelPay(channelId).then(res => {
|
||||
getChannelPay(channelId, 'AP').then(res => {
|
||||
payProduct.value = res.data || null
|
||||
payOriginId.value = res.data?.originId || res.data?.productId
|
||||
}).finally(() => {
|
||||
@@ -290,6 +318,18 @@ function loadChannelPay(channelId) {
|
||||
})
|
||||
}
|
||||
|
||||
function loadChannelAr(channelId) {
|
||||
syncingAr.value = true
|
||||
getChannelPay(channelId, 'AR').then(res => {
|
||||
arProduct.value = res.data || null
|
||||
arOriginId.value = res.data?.originId || res.data?.productId
|
||||
}).finally(() => {
|
||||
nextTick(() => {
|
||||
syncingAr.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
viewing.value = false
|
||||
form.value = emptyForm()
|
||||
@@ -307,6 +347,7 @@ function handleUpdate(row) {
|
||||
resetPay()
|
||||
loadPayOptions()
|
||||
loadChannelPay(row.id)
|
||||
loadChannelAr(row.id)
|
||||
title.value = '修改渠道'
|
||||
open.value = true
|
||||
nextTick(() => formRef.value && formRef.value.clearValidate())
|
||||
@@ -320,6 +361,7 @@ function handleDetail(row) {
|
||||
resetPay()
|
||||
loadPayOptions()
|
||||
loadChannelPay(row.id)
|
||||
loadChannelAr(row.id)
|
||||
title.value = '渠道详情'
|
||||
open.value = true
|
||||
nextTick(() => formRef.value && formRef.value.clearValidate())
|
||||
@@ -339,6 +381,19 @@ function onPayOrigin(id) {
|
||||
})
|
||||
}
|
||||
|
||||
function onArOrigin(id) {
|
||||
if (viewing.value || !form.value.id || syncingAr.value) return
|
||||
if (!id) {
|
||||
arProduct.value = null
|
||||
bindChannelPay(form.value.id, null, 'AR')
|
||||
return
|
||||
}
|
||||
bindChannelPay(form.value.id, id, 'AR').then(res => {
|
||||
arProduct.value = res.data || null
|
||||
arOriginId.value = res.data?.originId || id
|
||||
})
|
||||
}
|
||||
|
||||
function submitForm() {
|
||||
if (viewing.value) return
|
||||
formRef.value.validate(valid => {
|
||||
|
||||
Reference in New Issue
Block a user