Merge branch 'test'
This commit is contained in:
+3
-3
@@ -47,9 +47,9 @@ public class BmsCustomer extends BaseEntity
|
||||
@Excel(name = "业务类型", readConverterExp = "0=直客,1=同行,2=集运")
|
||||
private String customerType;
|
||||
|
||||
/** 区域类型(字典 data_area_type) */
|
||||
@Excel(name = "区域类型", dictType = "data_area_type")
|
||||
private String areaType;
|
||||
/** 客户区域(字典 customer_area) */
|
||||
@Excel(name = "客户区域", dictType = "customer_area")
|
||||
private String customerArea;
|
||||
|
||||
/** 启用状态(0正常 1停用) */
|
||||
@Excel(name = "启用状态", readConverterExp = "0=正常,1=停用")
|
||||
|
||||
+7
-7
@@ -45,10 +45,10 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
private static final ThreadLocal<SimpleDateFormat> DATE_FMT =
|
||||
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
|
||||
|
||||
/** 区域类型走字典 data_area_type;缓存未命中时保留原编码。 */
|
||||
private static String areaTypeLabel(String value)
|
||||
/** 客户区域走字典 customer_area;缓存未命中时保留原编码。 */
|
||||
private static String customerAreaLabel(String value)
|
||||
{
|
||||
String label = DictUtils.getDictLabel("data_area_type", value);
|
||||
String label = DictUtils.getDictLabel("customer_area", value);
|
||||
return StringUtils.isEmpty(label) ? value : label;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
/**
|
||||
* 需要记录日志的主表字段(顺序即展示顺序)。
|
||||
* requireNonBlank 为 true 的字段对应 update SQL 的 <if test="x!=null and x!=''">,
|
||||
* 其余动态字段仅在新值非 null 时落库;业务员/结算员/客服、区域类型为无条件写入。
|
||||
* 其余动态字段仅在新值非 null 时落库;业务员/结算员/客服、客户区域为无条件写入。
|
||||
*/
|
||||
private static final List<FieldDef> FIELD_DEFS = List.of(
|
||||
new FieldDef("customerCode", "客户编码", BmsCustomer::getCustomerCode, true, Function.identity()),
|
||||
@@ -85,7 +85,7 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
new FieldDef("customerCodeDw", "对外代码", BmsCustomer::getCustomerCodeDw, false, Function.identity()),
|
||||
new FieldDef("creditCode", "统一社会信用代码", BmsCustomer::getCreditCode, false, Function.identity()),
|
||||
new FieldDef("customerType", "业务类型", BmsCustomer::getCustomerType, false, CUSTOMER_TYPE_MAP::get),
|
||||
new FieldDef("areaType", "区域类型", BmsCustomer::getAreaType, false, BmsCustomerLogServiceImpl::areaTypeLabel),
|
||||
new FieldDef("customerArea", "客户区域", BmsCustomer::getCustomerArea, false, BmsCustomerLogServiceImpl::customerAreaLabel),
|
||||
new FieldDef("isEnable", "启用状态", BmsCustomer::getIsEnable, false, ENABLE_MAP::get),
|
||||
new FieldDef("salesUserId", "业务员", c -> userDisplay(c.getSalesUserId(), c.getSalesUser()), false, Function.identity()),
|
||||
new FieldDef("ed", "资金额度(元)", BmsCustomer::getEd, false, BmsCustomerLogServiceImpl::numText),
|
||||
@@ -208,8 +208,8 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService
|
||||
{
|
||||
// 与 update SQL 的动态条件保持一致:未提交(null/空串)的字段本次不落库,不参与比对
|
||||
Object raw = def.rawGetter.apply(newCustomer);
|
||||
// 合同起止、区域类型允许清空;其余动态字段未提交时不落库,也不记日志
|
||||
if (raw == null && !isContractDateField(def.field) && !"areaType".equals(def.field))
|
||||
// 合同起止、客户区域允许清空;其余动态字段未提交时不落库,也不记日志
|
||||
if (raw == null && !isContractDateField(def.field) && !"customerArea".equals(def.field))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
+2
@@ -60,6 +60,7 @@ public class CustomerSyncService
|
||||
private static final int LEN_CODE = 50;
|
||||
private static final int LEN_NAME = 100;
|
||||
private static final int LEN_CODE_DW = 50;
|
||||
private static final int LEN_CUSTOMER_AREA = 32;
|
||||
private static final int LEN_USER = 50;
|
||||
private static final int LEN_REMARK = 500;
|
||||
/** 告警明细最多打印条数 */
|
||||
@@ -178,6 +179,7 @@ public class CustomerSyncService
|
||||
c.setDelFlag("0");
|
||||
|
||||
c.setCustomerCodeDw(truncate(getStr(row, "CUSTOMER_OUTER_CODE"), LEN_CODE_DW, code, "customer_code_dw", warnings));
|
||||
c.setCustomerArea(truncate(getStr(row, "CUSTOMER_AREA"), LEN_CUSTOMER_AREA, code, "customer_area", warnings));
|
||||
String sourceSalesCode = clean(getStr(row, "BELONG_SALER"));
|
||||
c.setSourceSalesCode(sourceSalesCode);
|
||||
c.setSalesUserId(resolveSalesUserId(sourceSalesCode, userIdsByLogin,
|
||||
|
||||
-2
@@ -43,6 +43,4 @@ public class PrcProfitReportProductRow implements Serializable
|
||||
@Excel(name = "未计算提成订单数", width = 20)
|
||||
private Long commissionMissingOrderCount;
|
||||
*/
|
||||
@Excel(name = "产品价或价格缺失订单数", width = 22)
|
||||
private Long incompleteOrderCount;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,6 @@ public class PrcProfitReportQuery extends BaseEntity
|
||||
private String arBillStatus;
|
||||
/** 是否按产品维度分组值下钻订单明细,允许分组字段为空。 */
|
||||
private Boolean productDrilldown;
|
||||
/** 订单明细弹窗的筛选类型:ALL、INCOMPLETE;COMMISSION_MISSING 暂停使用。 */
|
||||
/** 仅用于拒绝已暂停的提成未计算订单下钻请求。 */
|
||||
private String detailType;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ public class PrcProfitReportSummary implements Serializable
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long orderCount;
|
||||
private Long incompleteOrderCount;
|
||||
private String currency;
|
||||
private BigDecimal costAmount;
|
||||
private BigDecimal redlineAmount;
|
||||
|
||||
@@ -11,7 +11,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="customerCodeDw" column="customer_code_dw" />
|
||||
<result property="creditCode" column="credit_code" />
|
||||
<result property="customerType" column="customer_type" />
|
||||
<result property="areaType" column="area_type" />
|
||||
<result property="customerArea" column="customer_area" />
|
||||
<result property="isEnable" column="is_enable" />
|
||||
<result property="salesUserId" column="sales_user_id" />
|
||||
<result property="salesUser" column="sales_user" />
|
||||
@@ -45,7 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<!-- 账户余额/外币余额统一取 ctr_customer_account 余额表(CNY 为本币,其余为外币),不取 ctr_customer 冗余列 -->
|
||||
<!-- 信用额度=总额度+额外额度-已用额度-->
|
||||
<sql id="selectBmsCustomerVo">
|
||||
select c.customer_id, c.customer_code, c.customer_name, c.customer_code_dw, c.credit_code, c.customer_type, c.area_type,
|
||||
select c.customer_id, c.customer_code, c.customer_name, c.customer_code_dw, c.credit_code, c.customer_type, c.customer_area,
|
||||
c.is_enable,
|
||||
case when su.user_id is not null then cast(su.user_id as char) else null end as sales_user_id,
|
||||
su.nick_name as sales_user, c.ed, c.zq, c.settlement_user_id, c.settlement_user,
|
||||
@@ -92,7 +92,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</if>
|
||||
<if test="creditCode != null and creditCode != ''"> and c.credit_code = #{creditCode}</if>
|
||||
<if test="customerType != null and customerType != ''"> and c.customer_type = #{customerType}</if>
|
||||
<if test="areaType != null and areaType != ''"> and c.area_type = #{areaType}</if>
|
||||
<if test="customerArea != null and customerArea != ''"> and c.customer_area = #{customerArea}</if>
|
||||
<if test="isEnable != null and isEnable != ''"> and c.is_enable = #{isEnable}</if>
|
||||
<if test="salesUserId != null and salesUserId != ''"> and c.sales_user_id = #{salesUserId}</if>
|
||||
<if test="salesUser != null and salesUser != ''"> and su.nick_name = #{salesUser}</if>
|
||||
@@ -317,7 +317,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="customerCodeDw != null">customer_code_dw,</if>
|
||||
<if test="creditCode != null">credit_code,</if>
|
||||
<if test="customerType != null">customer_type,</if>
|
||||
<if test="areaType != null">area_type,</if>
|
||||
<if test="customerArea != null">customer_area,</if>
|
||||
<if test="isEnable != null">is_enable,</if>
|
||||
<if test="salesUserId != null">sales_user_id,</if>
|
||||
<if test="salesUser != null">sales_user,</if>
|
||||
@@ -350,7 +350,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="customerCodeDw != null">#{customerCodeDw},</if>
|
||||
<if test="creditCode != null">#{creditCode},</if>
|
||||
<if test="customerType != null">#{customerType},</if>
|
||||
<if test="areaType != null">#{areaType},</if>
|
||||
<if test="customerArea != null">#{customerArea},</if>
|
||||
<if test="isEnable != null">#{isEnable},</if>
|
||||
<if test="salesUserId != null">#{salesUserId},</if>
|
||||
<if test="salesUser != null">#{salesUser},</if>
|
||||
@@ -387,7 +387,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="customerCodeDw != null">customer_code_dw = #{customerCodeDw},</if>
|
||||
<if test="creditCode != null">credit_code = #{creditCode},</if>
|
||||
<if test="customerType != null">customer_type = #{customerType},</if>
|
||||
area_type = #{areaType},
|
||||
customer_area = #{customerArea},
|
||||
<if test="isEnable != null">is_enable = #{isEnable},</if>
|
||||
sales_user_id = #{salesUserId},
|
||||
sales_user = #{salesUser},
|
||||
|
||||
@@ -30,6 +30,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
del_flag, create_by, sales_user_id, source_sales_code
|
||||
<if test="customerCodeDw != null">, customer_code_dw</if>
|
||||
<if test="customerType != null">, customer_type</if>
|
||||
<if test="customerArea != null">, customer_area</if>
|
||||
<if test="salesUser != null">, sales_user</if>
|
||||
<if test="settlementUser != null">, settlement_user</if>
|
||||
<if test="serviceUser != null">, service_user</if>
|
||||
@@ -46,6 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
'0', #{createBy}, #{salesUserId}, #{sourceSalesCode}
|
||||
<if test="customerCodeDw != null">, #{customerCodeDw}</if>
|
||||
<if test="customerType != null">, #{customerType}</if>
|
||||
<if test="customerArea != null">, #{customerArea}</if>
|
||||
<if test="salesUser != null">, #{salesUser}</if>
|
||||
<if test="settlementUser != null">, #{settlementUser}</if>
|
||||
<if test="serviceUser != null">, #{serviceUser}</if>
|
||||
@@ -66,6 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="customerName != null">, customer_name = #{customerName}</if>
|
||||
<if test="customerCodeDw != null">, customer_code_dw = #{customerCodeDw}</if>
|
||||
<if test="customerType != null">, customer_type = #{customerType}</if>
|
||||
<if test="customerArea != null">, customer_area = #{customerArea}</if>
|
||||
, sales_user_id = #{salesUserId}
|
||||
, source_sales_code = #{sourceSalesCode}
|
||||
<if test="salesUser != null">, sales_user = #{salesUser}</if>
|
||||
|
||||
@@ -10,7 +10,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
BELONG_SALER, BELONG_SALER_NAME, SETTLEMENT_MAN, SERVICE_MAN,
|
||||
REMARK, WEIGHT_LIMIT, CREDIT_LIMIT, TEMP_AMOUNT,
|
||||
ACCOUNT_AMOUNT, EUR_AMOUNT,
|
||||
CUSTOMER_TYPE, CUSTOMER_BALANCE_MODE, BL_OPEN,
|
||||
CUSTOMER_TYPE, CUSTOMER_AREA, CUSTOMER_BALANCE_MODE, BL_OPEN,
|
||||
CREATE_DATE, GMT_CREATE
|
||||
FROM WEISHI_USER.TAB_CUSTOMER
|
||||
</select>
|
||||
|
||||
@@ -98,12 +98,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="commissionAmount" column="commission_amount"/>
|
||||
<result property="commissionMissingOrderCount" column="commission_missing_order_count"/>
|
||||
-->
|
||||
<result property="incompleteOrderCount" column="incomplete_order_count"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap type="PrcProfitReportSummary" id="PrcProfitReportSummaryResult">
|
||||
<result property="orderCount" column="order_count"/>
|
||||
<result property="incompleteOrderCount" column="incomplete_order_count"/>
|
||||
<result property="currency" column="currency"/>
|
||||
<result property="costAmount" column="cost_amount"/>
|
||||
<result property="redlineAmount" column="redline_amount"/>
|
||||
@@ -193,16 +191,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</if>
|
||||
</otherwise>
|
||||
</choose>
|
||||
<choose>
|
||||
<!-- 提成未计算订单下钻暂停使用。
|
||||
<when test="detailType == 'COMMISSION_MISSING'">
|
||||
and (cr.commission_rate is null or i.product_amount is null or i.sales_amount is null)
|
||||
</when>
|
||||
-->
|
||||
<when test="detailType == 'INCOMPLETE'">
|
||||
and (i.product_amount is null or i.redline_amount is null or i.sales_amount is null)
|
||||
</when>
|
||||
</choose>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
@@ -271,15 +259,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
then i.sales_amount - i.product_amount else null end) * 100 /
|
||||
sum(case when i.product_amount is not null and i.sales_amount is not null
|
||||
then i.sales_amount else null end), 4)
|
||||
end as sales_gross_margin_rate,
|
||||
end as sales_gross_margin_rate
|
||||
<!-- 提成金额与未计算订单数暂停使用。
|
||||
sum(case when cr.commission_rate is not null and i.product_amount is not null and i.sales_amount is not null
|
||||
then (i.sales_amount - i.product_amount) * cr.commission_rate / 100 else null end) as commission_amount,
|
||||
sum(case when cr.commission_rate is null or i.product_amount is null or i.sales_amount is null
|
||||
then 1 else 0 end) as commission_missing_order_count,
|
||||
-->
|
||||
sum(case when i.product_amount is null or i.redline_amount is null or i.sales_amount is null
|
||||
then 1 else 0 end) as incomplete_order_count
|
||||
<include refid="profitReportFromAndWhere"/>
|
||||
group by p.product_code, p.product_name, p.country_code, p.country_name, i.currency
|
||||
order by p.product_code, p.country_code, i.currency
|
||||
@@ -287,8 +273,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<select id="selectSummary" resultMap="PrcProfitReportSummaryResult">
|
||||
select i.currency, count(*) as order_count,
|
||||
sum(case when i.product_amount is null or i.redline_amount is null or i.sales_amount is null
|
||||
then 1 else 0 end) as incomplete_order_count,
|
||||
sum(i.product_amount) as cost_amount,
|
||||
sum(i.redline_amount) as redline_amount,
|
||||
sum(case when i.product_amount is not null and i.redline_amount is not null
|
||||
|
||||
@@ -355,7 +355,7 @@ CREATE TABLE `ctr_customer` (
|
||||
`customer_code_dw` varchar(50) DEFAULT '' COMMENT '对外代码',
|
||||
`credit_code` varchar(18) DEFAULT '' COMMENT '统一社会信用代码',
|
||||
`customer_type` char(1) DEFAULT '0' COMMENT '业务类型(0直客 1同行 2集运)',
|
||||
`area_type` varchar(32) DEFAULT NULL COMMENT '区域类型(字典 data_area_type)',
|
||||
`customer_area` varchar(32) DEFAULT NULL COMMENT '客户区域(字典 customer_area)',
|
||||
`is_enable` char(1) DEFAULT '0' COMMENT '启用状态(0正常 1停用)',
|
||||
`sales_user_id` varchar(64) DEFAULT NULL COMMENT '业务员系统用户ID(sys_user.user_id)',
|
||||
`source_sales_code` varchar(255) DEFAULT NULL COMMENT '客户同步源业务员工号(内部字段)',
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
-- ctr_customer.area_type:客户区域类型,取值来自字典 data_area_type(可重复执行)
|
||||
SET @col_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'area_type'
|
||||
);
|
||||
SET @sql := IF(@col_exists = 0,
|
||||
'ALTER TABLE `ctr_customer` ADD COLUMN `area_type` varchar(32) DEFAULT NULL COMMENT ''区域类型(字典 data_area_type)'' AFTER `customer_type`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -0,0 +1,173 @@
|
||||
-- Unified migration: ctr_customer.area_type -> customer_area and data_area_type -> customer_area.
|
||||
-- Target: MySQL 5.7.x; run the whole file against the intended database in one connection.
|
||||
-- Confirm both migration_status and dictionary_migration_status report READY.
|
||||
-- Conflicting columns or dictionary values are preserved and reported for manual review.
|
||||
|
||||
SET @customer_table_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer'
|
||||
);
|
||||
SET @customer_area_old_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'area_type'
|
||||
);
|
||||
SET @customer_area_new_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'customer_area'
|
||||
);
|
||||
SET @customer_area_conflict_count := 0;
|
||||
|
||||
-- If both columns exist, require matching non-NULL values before merging and dropping the old column.
|
||||
SET @customer_area_check_sql := IF(
|
||||
@customer_area_old_exists = 1 AND @customer_area_new_exists = 1,
|
||||
'SELECT COUNT(1) INTO @customer_area_conflict_count FROM `ctr_customer` WHERE `area_type` IS NOT NULL AND `customer_area` IS NOT NULL AND BINARY `area_type` <> BINARY `customer_area`',
|
||||
'SELECT 0 INTO @customer_area_conflict_count'
|
||||
);
|
||||
PREPARE customer_area_stmt FROM @customer_area_check_sql;
|
||||
EXECUTE customer_area_stmt;
|
||||
DEALLOCATE PREPARE customer_area_stmt;
|
||||
|
||||
-- In the no-conflict dual-column state, copy values that only exist in the old column.
|
||||
SET @customer_area_merge_sql := IF(
|
||||
@customer_area_old_exists = 1 AND @customer_area_new_exists = 1 AND @customer_area_conflict_count = 0,
|
||||
'UPDATE `ctr_customer` SET `customer_area` = `area_type` WHERE `customer_area` IS NULL AND `area_type` IS NOT NULL',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE customer_area_stmt FROM @customer_area_merge_sql;
|
||||
EXECUTE customer_area_stmt;
|
||||
DEALLOCATE PREPARE customer_area_stmt;
|
||||
|
||||
-- Drop the legacy column only after its values have been merged without conflicts.
|
||||
SET @customer_area_drop_sql := IF(
|
||||
@customer_area_old_exists = 1 AND @customer_area_new_exists = 1 AND @customer_area_conflict_count = 0,
|
||||
'ALTER TABLE `ctr_customer` DROP COLUMN `area_type`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE customer_area_stmt FROM @customer_area_drop_sql;
|
||||
EXECUTE customer_area_stmt;
|
||||
DEALLOCATE PREPARE customer_area_stmt;
|
||||
|
||||
-- Rename the existing column, or create the new column when neither name exists.
|
||||
SET @customer_area_rename_sql := CASE
|
||||
WHEN @customer_table_exists = 1 AND @customer_area_old_exists = 1 AND @customer_area_new_exists = 0 THEN
|
||||
'ALTER TABLE `ctr_customer` CHANGE COLUMN `area_type` `customer_area` varchar(32) DEFAULT NULL COMMENT ''客户区域(字典 customer_area)'' AFTER `customer_type`'
|
||||
WHEN @customer_table_exists = 1 AND @customer_area_old_exists = 0 AND @customer_area_new_exists = 0 THEN
|
||||
'ALTER TABLE `ctr_customer` ADD COLUMN `customer_area` varchar(32) DEFAULT NULL COMMENT ''客户区域(字典 customer_area)'' AFTER `customer_type`'
|
||||
ELSE 'SELECT 1'
|
||||
END;
|
||||
PREPARE customer_area_stmt FROM @customer_area_rename_sql;
|
||||
EXECUTE customer_area_stmt;
|
||||
DEALLOCATE PREPARE customer_area_stmt;
|
||||
|
||||
SET @customer_area_old_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'area_type'
|
||||
);
|
||||
SET @customer_area_new_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ctr_customer' AND COLUMN_NAME = 'customer_area'
|
||||
);
|
||||
|
||||
SELECT CASE
|
||||
WHEN @customer_table_exists = 0 THEN 'ERROR: ctr_customer table does not exist in the selected database'
|
||||
WHEN @customer_area_old_exists = 0 AND @customer_area_new_exists = 1 THEN 'READY'
|
||||
WHEN @customer_area_conflict_count > 0 THEN 'BLOCKED: resolve conflicting values and rerun this full script'
|
||||
ELSE 'ERROR: expected customer_area and no area_type; inspect the table before continuing'
|
||||
END AS migration_status,
|
||||
@customer_area_conflict_count AS conflicting_rows;
|
||||
|
||||
SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'ctr_customer'
|
||||
AND COLUMN_NAME IN ('area_type', 'customer_area')
|
||||
ORDER BY ORDINAL_POSITION;
|
||||
|
||||
-- When migration_status is BLOCKED, inspect these rows, resolve each value manually, then rerun this file.
|
||||
SET @customer_area_conflict_rows_sql := IF(
|
||||
@customer_area_conflict_count > 0,
|
||||
'SELECT `customer_id`, `customer_code`, `area_type`, `customer_area` FROM `ctr_customer` WHERE `area_type` IS NOT NULL AND `customer_area` IS NOT NULL AND BINARY `area_type` <> BINARY `customer_area` ORDER BY `customer_id`',
|
||||
'SELECT ''No conflicting customer area values'' AS conflict_check'
|
||||
);
|
||||
PREPARE customer_area_stmt FROM @customer_area_conflict_rows_sql;
|
||||
EXECUTE customer_area_stmt;
|
||||
DEALLOCATE PREPARE customer_area_stmt;
|
||||
|
||||
-- Rename the dictionary identifier and its values. If both dictionary types already exist,
|
||||
-- or both dictionaries use the same value, stop and report instead of creating ambiguity.
|
||||
SET @customer_area_old_dict_exists := (
|
||||
SELECT COUNT(1) FROM `sys_dict_type` WHERE `dict_type` = 'data_area_type'
|
||||
);
|
||||
SET @customer_area_new_dict_exists := (
|
||||
SELECT COUNT(1) FROM `sys_dict_type` WHERE `dict_type` = 'customer_area'
|
||||
);
|
||||
SET @customer_area_dict_value_conflicts := (
|
||||
SELECT COUNT(1)
|
||||
FROM `sys_dict_data` old_data
|
||||
JOIN `sys_dict_data` new_data ON old_data.`dict_value` = new_data.`dict_value`
|
||||
WHERE old_data.`dict_type` = 'data_area_type'
|
||||
AND new_data.`dict_type` = 'customer_area'
|
||||
);
|
||||
|
||||
SET @customer_area_dict_data_sql := IF(
|
||||
@customer_area_old_exists = 0 AND @customer_area_new_exists = 1
|
||||
AND (@customer_area_old_dict_exists = 1 OR @customer_area_new_dict_exists = 1)
|
||||
AND @customer_area_dict_value_conflicts = 0
|
||||
AND NOT (@customer_area_old_dict_exists = 1 AND @customer_area_new_dict_exists = 1),
|
||||
'UPDATE `sys_dict_data` SET `dict_type` = ''customer_area'' WHERE `dict_type` = ''data_area_type''',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE customer_area_stmt FROM @customer_area_dict_data_sql;
|
||||
EXECUTE customer_area_stmt;
|
||||
DEALLOCATE PREPARE customer_area_stmt;
|
||||
|
||||
SET @customer_area_dict_type_sql := CASE
|
||||
WHEN @customer_area_old_exists = 0 AND @customer_area_new_exists = 1
|
||||
AND @customer_area_old_dict_exists = 1 AND @customer_area_new_dict_exists = 0
|
||||
AND @customer_area_dict_value_conflicts = 0 THEN
|
||||
'UPDATE `sys_dict_type` SET `dict_type` = ''customer_area'', `dict_name` = ''客户区域'', `update_time` = NOW() WHERE `dict_type` = ''data_area_type'''
|
||||
WHEN @customer_area_old_exists = 0 AND @customer_area_new_exists = 1
|
||||
AND @customer_area_old_dict_exists = 0 AND @customer_area_new_dict_exists = 1
|
||||
AND @customer_area_dict_value_conflicts = 0 THEN
|
||||
'UPDATE `sys_dict_type` SET `dict_name` = ''客户区域'', `update_time` = NOW() WHERE `dict_type` = ''customer_area'''
|
||||
ELSE 'SELECT 1'
|
||||
END;
|
||||
PREPARE customer_area_stmt FROM @customer_area_dict_type_sql;
|
||||
EXECUTE customer_area_stmt;
|
||||
DEALLOCATE PREPARE customer_area_stmt;
|
||||
|
||||
SET @customer_area_old_dict_exists := (
|
||||
SELECT COUNT(1) FROM `sys_dict_type` WHERE `dict_type` = 'data_area_type'
|
||||
);
|
||||
SET @customer_area_new_dict_exists := (
|
||||
SELECT COUNT(1) FROM `sys_dict_type` WHERE `dict_type` = 'customer_area'
|
||||
);
|
||||
|
||||
SELECT CASE
|
||||
WHEN @customer_area_old_exists <> 0 OR @customer_area_new_exists <> 1 THEN 'BLOCKED: finish customer column migration first'
|
||||
WHEN @customer_area_old_dict_exists = 0 AND @customer_area_new_dict_exists = 1
|
||||
AND @customer_area_dict_value_conflicts = 0 THEN 'READY'
|
||||
WHEN @customer_area_old_dict_exists = 1 AND @customer_area_new_dict_exists = 1 THEN 'BLOCKED: both dictionary types exist; merge them manually'
|
||||
WHEN @customer_area_dict_value_conflicts > 0 THEN 'BLOCKED: dictionary values overlap; reconcile them manually'
|
||||
ELSE 'MISSING: verify the customer area dictionary in the selected database'
|
||||
END AS dictionary_migration_status,
|
||||
@customer_area_dict_value_conflicts AS overlapping_values;
|
||||
|
||||
SELECT `dict_id`, `dict_name`, `dict_type`, `status`
|
||||
FROM `sys_dict_type`
|
||||
WHERE `dict_type` IN ('data_area_type', 'customer_area')
|
||||
ORDER BY `dict_id`;
|
||||
|
||||
SELECT `dict_code`, `dict_type`, `dict_value`, `dict_label`, `status`
|
||||
FROM `sys_dict_data`
|
||||
WHERE `dict_type` IN ('data_area_type', 'customer_area')
|
||||
ORDER BY `dict_type`, `dict_sort`, `dict_code`;
|
||||
|
||||
SET @customer_area_dict_conflict_rows_sql := IF(
|
||||
@customer_area_dict_value_conflicts > 0,
|
||||
'SELECT old_data.`dict_value`, old_data.`dict_label` AS old_label, new_data.`dict_label` AS new_label FROM `sys_dict_data` old_data JOIN `sys_dict_data` new_data ON old_data.`dict_value` = new_data.`dict_value` WHERE old_data.`dict_type` = ''data_area_type'' AND new_data.`dict_type` = ''customer_area'' ORDER BY old_data.`dict_value`',
|
||||
'SELECT ''No overlapping dictionary values'' AS conflict_check'
|
||||
);
|
||||
PREPARE customer_area_stmt FROM @customer_area_dict_conflict_rows_sql;
|
||||
EXECUTE customer_area_stmt;
|
||||
DEALLOCATE PREPARE customer_area_stmt;
|
||||
@@ -63,10 +63,10 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="区域类型" prop="areaType">
|
||||
<el-select v-model="form.areaType" placeholder="请选择区域类型" clearable style="width: 100%;">
|
||||
<el-form-item label="客户区域" prop="customerArea">
|
||||
<el-select v-model="form.customerArea" placeholder="请选择客户区域" clearable style="width: 100%;">
|
||||
<el-option
|
||||
v-for="dict in data_area_type"
|
||||
v-for="dict in customer_area"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
@@ -739,7 +739,7 @@ const router = useRouter()
|
||||
|
||||
const { settlement_type } = useDict('settlement_type')
|
||||
const { customer_type } = useDict('customer_type')
|
||||
const { data_area_type } = useDict('data_area_type')
|
||||
const { customer_area } = useDict('customer_area')
|
||||
|
||||
const { ensureProducts, findProduct } = useProducts()
|
||||
|
||||
@@ -765,7 +765,7 @@ function buildEmptyForm() {
|
||||
customerCodeDw: null,
|
||||
creditCode: null,
|
||||
customerType: null,
|
||||
areaType: null,
|
||||
customerArea: null,
|
||||
isEnable: null,
|
||||
salesUserId: null,
|
||||
salesUser: null,
|
||||
|
||||
@@ -30,16 +30,16 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="区域类型" prop="areaType">
|
||||
<el-form-item label="客户区域" prop="customerArea">
|
||||
<el-select
|
||||
v-model="queryParams.areaType"
|
||||
placeholder="请选择区域类型"
|
||||
v-model="queryParams.customerArea"
|
||||
placeholder="请选择客户区域"
|
||||
clearable
|
||||
style="width: 160px"
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in data_area_type"
|
||||
v-for="dict in customer_area"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
@@ -167,9 +167,9 @@
|
||||
<dict-tag :options="customer_type" :value="scope.row.customerType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isColVisible('areaType')" label="区域类型" align="center" prop="areaType" width="110">
|
||||
<el-table-column v-if="isColVisible('customerArea')" label="客户区域" align="center" prop="customerArea" width="110">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="data_area_type" :value="scope.row.areaType" />
|
||||
<dict-tag :options="customer_area" :value="scope.row.customerArea" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isColVisible('isEnable')" label="启用状态" align="center" prop="isEnable">
|
||||
@@ -349,7 +349,7 @@ const columnDefs = [
|
||||
{ key: 'customerCodeDw', label: '对外代码' },
|
||||
{ key: 'creditCode', label: '统一社会信用代码' },
|
||||
{ key: 'customerType', label: '业务类型' },
|
||||
{ key: 'areaType', label: '区域类型' },
|
||||
{ key: 'customerArea', label: '客户区域' },
|
||||
{ key: 'isEnable', label: '启用状态' },
|
||||
{ key: 'salesUserId', label: '业务员' },
|
||||
// { key: 'ed', label: '资金额度' },
|
||||
@@ -378,7 +378,7 @@ const single = ref(true)
|
||||
const multiple = ref(true)
|
||||
const total = ref(0)
|
||||
|
||||
const { sys_normal_disable, settlement_type, customer_type, data_area_type } = useDict("sys_normal_disable", "settlement_type", "customer_type", "data_area_type")
|
||||
const { sys_normal_disable, settlement_type, customer_type, customer_area } = useDict("sys_normal_disable", "settlement_type", "customer_type", "customer_area")
|
||||
|
||||
/** 绑定产品代码串 -> 产品名称展示(产品代码+名称;查不到的产品回显原代码) */
|
||||
const { ensureProducts, getProductLabel } = useProducts()
|
||||
@@ -412,7 +412,7 @@ const copyColumns = computed(() => [
|
||||
{ key: 'customerCodeDw', label: '对外代码', get: r => r.customerCodeDw || '' },
|
||||
{ key: 'creditCode', label: '统一社会信用代码', get: r => r.creditCode || '' },
|
||||
{ key: 'customerType', label: '业务类型', get: r => proxy.selectDictLabel(customer_type.value, r.customerType) },
|
||||
{ key: 'areaType', label: '区域类型', get: r => proxy.selectDictLabel(data_area_type.value, r.areaType) },
|
||||
{ key: 'customerArea', label: '客户区域', get: r => proxy.selectDictLabel(customer_area.value, r.customerArea) },
|
||||
{ key: 'isEnable', label: '启用状态', get: r => proxy.selectDictLabel(sys_normal_disable.value, r.isEnable) },
|
||||
{ key: 'salesUserId', label: '业务员', get: r => r.salesUserNickName || '' },
|
||||
{ key: 'zq', label: '回款账期', get: r => (r.zq === null || r.zq === undefined ? '' : r.zq) },
|
||||
@@ -445,7 +445,7 @@ const data = reactive({
|
||||
keywords: undefined,
|
||||
creditCode: undefined,
|
||||
customerType: undefined,
|
||||
areaType: undefined,
|
||||
customerArea: undefined,
|
||||
isEnable: undefined,
|
||||
salesUserId: undefined,
|
||||
salesUser: undefined,
|
||||
|
||||
@@ -16,16 +16,6 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-form-item label="业务员编码" class="filter-item">
|
||||
<el-input v-model="query.belongSalerCode" clearable placeholder="输入业务员编码" class="filter-control" @keyup.enter="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-form-item label="产品代码" class="filter-item">
|
||||
<el-input v-model="query.productCode" clearable placeholder="输入产品代码" class="filter-control" @keyup.enter="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-form-item label="客户名称" class="filter-item">
|
||||
<customer-select
|
||||
@@ -39,6 +29,16 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-form-item label="业务员编码" class="filter-item">
|
||||
<el-input v-model="query.belongSalerCode" clearable placeholder="输入业务员编码" class="filter-control" @keyup.enter="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-form-item label="产品代码" class="filter-item">
|
||||
<el-input v-model="query.productCode" clearable placeholder="输入产品代码" class="filter-control" @keyup.enter="handleSearch" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :lg="8">
|
||||
<el-form-item label="订单号" class="filter-item">
|
||||
<el-input
|
||||
@@ -98,9 +98,6 @@
|
||||
<div class="metric-item"><div class="metric-label">提成金额</div><div class="metric-value">{{ money(summary.commissionAmount) }}</div></div>
|
||||
</el-col>
|
||||
-->
|
||||
<el-col :xs="12" :sm="8" :md="6">
|
||||
<div class="metric-item"><div class="metric-label">价格缺失订单</div><div class="metric-value">{{ summary.incompleteOrderCount || 0 }}</div></div>
|
||||
</el-col>
|
||||
<!-- 提成功能暂停使用。
|
||||
<el-col :xs="12" :sm="8" :md="6">
|
||||
<div class="metric-item"><div class="metric-label">提成未计算订单</div><div class="metric-value">{{ summary.commissionMissingOrderCount || 0 }}</div></div>
|
||||
@@ -149,7 +146,7 @@
|
||||
<el-table-column prop="countryCode" label="国家代码" width="100" align="center" />
|
||||
<el-table-column prop="currency" label="币种" width="80" align="center" />
|
||||
<el-table-column prop="orderCount" label="订单数" width="100" align="right">
|
||||
<template #default="{ row }"><span class="success-value order-count-link" :class="{ 'is-disabled': !row.orderCount }" @click.stop="openOrderList(row, 'ALL', '订单数')">{{ row.orderCount }}</span></template>
|
||||
<template #default="{ row }"><span class="success-value order-count-link" :class="{ 'is-disabled': !row.orderCount }" @click.stop="openOrderList(row)">{{ row.orderCount }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="costAmount" label="产品价" min-width="130" align="right"><template #default="{ row }">{{ money(row.costAmount) }}</template></el-table-column>
|
||||
<el-table-column prop="redlineAmount" label="红线价" min-width="130" align="right"><template #default="{ row }">{{ money(row.redlineAmount) }}</template></el-table-column>
|
||||
@@ -164,9 +161,6 @@
|
||||
<template #default="{ row }"><span class="success-value order-count-link" :class="{ 'is-disabled': !row.commissionMissingOrderCount }" @click.stop="openOrderList(row, 'COMMISSION_MISSING', '提成未计算订单')">{{ row.commissionMissingOrderCount }}</span></template>
|
||||
</el-table-column>
|
||||
-->
|
||||
<el-table-column prop="incompleteOrderCount" label="价格缺失订单" width="130" align="right">
|
||||
<template #default="{ row }"><span class="success-value order-count-link" :class="{ 'is-disabled': !row.incompleteOrderCount }" @click.stop="openOrderList(row, 'INCOMPLETE', '价格缺失订单')">{{ row.incompleteOrderCount }}</span></template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-table-column prop="bizDate" label="计费时间" width="170" align="center"><template #default="{ row }">{{ parseTime(row.bizDate) }}</template></el-table-column>
|
||||
@@ -446,15 +440,12 @@ function handleDimensionChange() {
|
||||
Promise.all([loadSummary(), loadRows()])
|
||||
}
|
||||
|
||||
function openOrderList(row, detailType, label) {
|
||||
function openOrderList(row) {
|
||||
if (!validateMultiValueFilters()) return
|
||||
// 提成未计算订单下钻暂停使用:detailType === 'COMMISSION_MISSING' ? row.commissionMissingOrderCount
|
||||
const count = detailType === 'ALL' ? row.orderCount : row.incompleteOrderCount
|
||||
if (!count) return
|
||||
orderListTitle.value = `${label}订单列表`
|
||||
if (!row.orderCount) return
|
||||
orderListTitle.value = '订单列表'
|
||||
orderListContext.value = {
|
||||
productDrilldown: true,
|
||||
detailType,
|
||||
productCode: row.productCode,
|
||||
countryCode: row.countryCode,
|
||||
currency: row.currency
|
||||
|
||||
Reference in New Issue
Block a user