增加代码检测,和映射

This commit is contained in:
wuweihua
2026-10-13 13:39:15 +08:00
parent b40033f424
commit 52816ad618
22 changed files with 1573 additions and 0 deletions
@@ -0,0 +1,277 @@
package com.bms.price.domain.vo;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Order-source product vs customer package comparison result.
*/
public class TabOrderProductCheckResult implements Serializable
{
private static final long serialVersionUID = 1L;
private long orderTotal;
private int scannedOrders;
private int distinctOrderProducts;
private int packageProductCount;
private int matchedCount;
private int missingCount;
private String asOfTime;
private boolean truncated;
private List<PackageProductRow> packageProducts = new ArrayList<PackageProductRow>();
private List<OrderProductRow> orderProducts = new ArrayList<OrderProductRow>();
private List<OrderProductRow> missingProducts = new ArrayList<OrderProductRow>();
public long getOrderTotal()
{
return orderTotal;
}
public void setOrderTotal(long orderTotal)
{
this.orderTotal = orderTotal;
}
public int getScannedOrders()
{
return scannedOrders;
}
public void setScannedOrders(int scannedOrders)
{
this.scannedOrders = scannedOrders;
}
public int getDistinctOrderProducts()
{
return distinctOrderProducts;
}
public void setDistinctOrderProducts(int distinctOrderProducts)
{
this.distinctOrderProducts = distinctOrderProducts;
}
public int getPackageProductCount()
{
return packageProductCount;
}
public void setPackageProductCount(int packageProductCount)
{
this.packageProductCount = packageProductCount;
}
public int getMatchedCount()
{
return matchedCount;
}
public void setMatchedCount(int matchedCount)
{
this.matchedCount = matchedCount;
}
public int getMissingCount()
{
return missingCount;
}
public void setMissingCount(int missingCount)
{
this.missingCount = missingCount;
}
public String getAsOfTime()
{
return asOfTime;
}
public void setAsOfTime(String asOfTime)
{
this.asOfTime = asOfTime;
}
public boolean isTruncated()
{
return truncated;
}
public void setTruncated(boolean truncated)
{
this.truncated = truncated;
}
public List<PackageProductRow> getPackageProducts()
{
return packageProducts;
}
public void setPackageProducts(List<PackageProductRow> packageProducts)
{
this.packageProducts = packageProducts;
}
public List<OrderProductRow> getOrderProducts()
{
return orderProducts;
}
public void setOrderProducts(List<OrderProductRow> orderProducts)
{
this.orderProducts = orderProducts;
}
public List<OrderProductRow> getMissingProducts()
{
return missingProducts;
}
public void setMissingProducts(List<OrderProductRow> missingProducts)
{
this.missingProducts = missingProducts;
}
public static class PackageProductRow implements Serializable
{
private static final long serialVersionUID = 1L;
private String customerCode;
private String productCode;
private String productName;
public String getCustomerCode()
{
return customerCode;
}
public void setCustomerCode(String customerCode)
{
this.customerCode = customerCode;
}
public String getProductCode()
{
return productCode;
}
public void setProductCode(String productCode)
{
this.productCode = productCode;
}
public String getProductName()
{
return productName;
}
public void setProductName(String productName)
{
this.productName = productName;
}
}
public static class OrderProductRow implements Serializable
{
private static final long serialVersionUID = 1L;
private String customerCode;
private String upstreamCode;
private String productName;
private String mappedCode;
private boolean inPackage;
private boolean mappedInPackage;
private boolean covered;
private int orderCount;
private List<String> sampleOrderIds = new ArrayList<String>();
public String getCustomerCode()
{
return customerCode;
}
public void setCustomerCode(String customerCode)
{
this.customerCode = customerCode;
}
public String getUpstreamCode()
{
return upstreamCode;
}
public void setUpstreamCode(String upstreamCode)
{
this.upstreamCode = upstreamCode;
}
public String getProductName()
{
return productName;
}
public void setProductName(String productName)
{
this.productName = productName;
}
public String getMappedCode()
{
return mappedCode;
}
public void setMappedCode(String mappedCode)
{
this.mappedCode = mappedCode;
}
public boolean isInPackage()
{
return inPackage;
}
public void setInPackage(boolean inPackage)
{
this.inPackage = inPackage;
}
public boolean isMappedInPackage()
{
return mappedInPackage;
}
public void setMappedInPackage(boolean mappedInPackage)
{
this.mappedInPackage = mappedInPackage;
}
public boolean isCovered()
{
return covered;
}
public void setCovered(boolean covered)
{
this.covered = covered;
}
public int getOrderCount()
{
return orderCount;
}
public void setOrderCount(int orderCount)
{
this.orderCount = orderCount;
}
public List<String> getSampleOrderIds()
{
return sampleOrderIds;
}
public void setSampleOrderIds(List<String> sampleOrderIds)
{
this.sampleOrderIds = sampleOrderIds;
}
}
}
@@ -27,4 +27,9 @@ public interface OracleUpstreamOrderMapper
@Param("query") TabOrderMonitorQuery query,
@Param("startRow") long startRow,
@Param("endRow") long endRow);
/** Distinct product codes for product-vs-package check (grouped, no pagination). */
List<Map<String, Object>> selectTabOrderProductCodes(
@Param("orderTable") String orderTable,
@Param("query") TabOrderMonitorQuery query);
}
@@ -40,6 +40,7 @@ public class OracleOrderBillMapper
{
product = defaultProductCode;
}
// Keep upstream product code; package miss then maps via product_code_mapping in doQuote.
req.setProductCode(product);
req.setCountryCode(firstStr(row, "COUNTRY"));
String countryName = firstStr(row, "COUNTRY_NAME", "COUNTRY_EINGTH_NAME", "COUNTRY");
@@ -55,6 +55,32 @@ public class TabOrderMonitorService
}
}
@DataSource(DataSourceType.SLAVE)
public List<Map<String, Object>> selectDistinctProductCodes(TabOrderMonitorQuery query)
{
validate(query);
String table = resolveTable();
try
{
PageHelper.clearPage();
long t0 = System.currentTimeMillis();
List<Map<String, Object>> rows = oracleUpstreamOrderMapper.selectTabOrderProductCodes(table, query);
log.info("oracle tab_order product codes customerSize={} begin={} end={} groups={} costMs={}",
query.getCustomerCodes() == null ? 0 : query.getCustomerCodes().size(),
query.getBeginTime(), query.getEndTime(),
rows == null ? 0 : rows.size(), System.currentTimeMillis() - t0);
return rows == null ? Collections.emptyList() : rows;
}
catch (RuntimeException e)
{
throw new ServiceException("Oracle TAB_ORDER product codes failed: " + e.getMessage());
}
finally
{
PageHelper.clearPage();
}
}
@DataSource(DataSourceType.SLAVE)
public List<TabOrderMonitorVo> selectPage(TabOrderMonitorQuery query, int pageNum, int pageSize)
{
@@ -0,0 +1,284 @@
package com.bms.price.oracle;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bms.common.utils.StringUtils;
import com.bms.price.domain.PrcPriceSetProduct;
import com.bms.price.domain.vo.TabOrderMonitorQuery;
import com.bms.price.domain.vo.TabOrderProductCheckResult;
import com.bms.price.domain.vo.TabOrderProductCheckResult.OrderProductRow;
import com.bms.price.domain.vo.TabOrderProductCheckResult.PackageProductRow;
import com.bms.price.service.ITmsPriceQuoteService;
import com.bms.system.service.IBmsProductCodeMappingService;
/**
* Compare distinct TAB_ORDER product codes against customer package products.
*/
@Service
public class TabOrderProductCheckService
{
@Autowired
private TabOrderMonitorService tabOrderMonitorService;
@Autowired
private ITmsPriceQuoteService tmsPriceQuoteService;
@Autowired
private IBmsProductCodeMappingService productCodeMappingService;
public TabOrderProductCheckResult check(TabOrderMonitorQuery query)
{
Date asOf = resolveAsOf(query);
TabOrderProductCheckResult result = new TabOrderProductCheckResult();
result.setAsOfTime(formatAsOf(asOf));
result.setTruncated(false);
List<Map<String, Object>> groups = tabOrderMonitorService.selectDistinctProductCodes(query);
if (groups == null || groups.isEmpty())
{
result.setOrderTotal(0L);
result.setScannedOrders(0);
return result;
}
long orderTotal = 0L;
Set<String> customerCodes = new HashSet<String>();
List<OrderProductRow> orderProducts = new ArrayList<OrderProductRow>();
List<OrderProductRow> missingProducts = new ArrayList<OrderProductRow>();
for (Map<String, Object> g : groups)
{
String customerCode = trim(str(g, "CUSTOMER_CODE"));
String productCode = trim(str(g, "PRODUCT_CODE"));
if (StringUtils.isEmpty(customerCode) || StringUtils.isEmpty(productCode))
{
continue;
}
customerCodes.add(customerCode);
orderTotal += longValue(g, "ORDER_COUNT");
}
Map<String, Set<String>> packageCodeByCustomer = new HashMap<String, Set<String>>();
List<PackageProductRow> packageRows = new ArrayList<PackageProductRow>();
for (String customerCode : customerCodes)
{
List<PrcPriceSetProduct> products = tmsPriceQuoteService.listAllBoundPackageProducts(customerCode, asOf);
Set<String> codes = new HashSet<String>();
if (products != null)
{
for (PrcPriceSetProduct p : products)
{
if (p == null || StringUtils.isEmpty(p.getProductCode()))
{
continue;
}
String code = p.getProductCode().trim();
String upper = code.toUpperCase(Locale.ROOT);
if (!codes.add(upper))
{
continue;
}
PackageProductRow pr = new PackageProductRow();
pr.setCustomerCode(customerCode);
pr.setProductCode(code);
pr.setProductName(trim(p.getProductName()));
packageRows.add(pr);
}
}
packageCodeByCustomer.put(customerCode, codes);
}
packageRows.sort(Comparator
.comparing(PackageProductRow::getCustomerCode, nullSafe())
.thenComparing(PackageProductRow::getProductCode, nullSafe()));
int matched = 0;
for (Map<String, Object> g : groups)
{
String customerCode = trim(str(g, "CUSTOMER_CODE"));
String productCode = trim(str(g, "PRODUCT_CODE"));
if (StringUtils.isEmpty(customerCode) || StringUtils.isEmpty(productCode))
{
continue;
}
Set<String> pkg = packageCodeByCustomer.get(customerCode);
if (pkg == null)
{
pkg = Collections.emptySet();
}
boolean inPackage = pkg.contains(productCode.toUpperCase(Locale.ROOT));
String mappedCode = resolveMappedIfDifferent(productCode);
boolean mappedInPackage = false;
if (StringUtils.isNotEmpty(mappedCode))
{
mappedInPackage = pkg.contains(mappedCode.toUpperCase(Locale.ROOT));
}
boolean covered = inPackage || mappedInPackage;
OrderProductRow row = new OrderProductRow();
row.setCustomerCode(customerCode);
row.setUpstreamCode(productCode);
row.setProductName(trim(str(g, "PRODUCT_NAME")));
row.setMappedCode(mappedCode);
row.setInPackage(inPackage);
row.setMappedInPackage(mappedInPackage);
row.setCovered(covered);
row.setOrderCount((int) Math.min(Integer.MAX_VALUE, longValue(g, "ORDER_COUNT")));
orderProducts.add(row);
if (covered)
{
matched++;
}
else
{
missingProducts.add(row);
}
}
orderProducts.sort(Comparator
.comparing(OrderProductRow::isCovered)
.thenComparing(OrderProductRow::getCustomerCode, nullSafe())
.thenComparing(OrderProductRow::getUpstreamCode, nullSafe()));
missingProducts.sort(Comparator
.comparing(OrderProductRow::getCustomerCode, nullSafe())
.thenComparing(OrderProductRow::getUpstreamCode, nullSafe()));
result.setOrderTotal(orderTotal);
result.setScannedOrders((int) Math.min(Integer.MAX_VALUE, orderTotal));
result.setDistinctOrderProducts(orderProducts.size());
result.setPackageProductCount(packageRows.size());
result.setMatchedCount(matched);
result.setMissingCount(missingProducts.size());
result.setPackageProducts(packageRows);
result.setOrderProducts(orderProducts);
result.setMissingProducts(missingProducts);
return result;
}
private String resolveMappedIfDifferent(String upstreamCode)
{
if (productCodeMappingService == null || StringUtils.isEmpty(upstreamCode))
{
return null;
}
String mapped = productCodeMappingService.resolveBmsProductCode(upstreamCode);
if (StringUtils.isEmpty(mapped) || mapped.equalsIgnoreCase(upstreamCode.trim()))
{
return null;
}
return mapped.trim();
}
private static Date resolveAsOf(TabOrderMonitorQuery query)
{
String raw = query == null ? null : query.getEndTime();
if (StringUtils.isEmpty(raw) && query != null)
{
raw = query.getBeginTime();
}
Date parsed = parseDateTime(raw);
return parsed != null ? parsed : new Date();
}
private static Date parseDateTime(String raw)
{
if (StringUtils.isEmpty(raw))
{
return null;
}
String s = raw.trim().replace('T', ' ');
try
{
if (s.length() >= 19)
{
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(s.substring(0, 19));
}
if (s.length() >= 10)
{
return new SimpleDateFormat("yyyy-MM-dd").parse(s.substring(0, 10));
}
}
catch (ParseException ignore)
{
return null;
}
return null;
}
private static String formatAsOf(Date asOf)
{
if (asOf == null)
{
return null;
}
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(asOf);
}
private static String trim(String s)
{
return StringUtils.isEmpty(s) ? null : s.trim();
}
private static Comparator<String> nullSafe()
{
return Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER);
}
private static String str(Map<String, Object> row, String key)
{
Object v = value(row, key);
return v == null ? null : String.valueOf(v).trim();
}
private static long longValue(Map<String, Object> row, String key)
{
Object v = value(row, key);
if (v == null)
{
return 0L;
}
if (v instanceof Number)
{
return ((Number) v).longValue();
}
try
{
return Long.parseLong(String.valueOf(v).trim());
}
catch (Exception e)
{
return 0L;
}
}
private static Object value(Map<String, Object> row, String key)
{
if (row == null || key == null)
{
return null;
}
if (row.containsKey(key))
{
return row.get(key);
}
for (Map.Entry<String, Object> e : row.entrySet())
{
if (e.getKey() != null && e.getKey().equalsIgnoreCase(key))
{
return e.getValue();
}
}
return null;
}
}
@@ -36,4 +36,11 @@ public interface ITmsPriceQuoteService
* @param bizDate optional; default today (same as-of window as quote)
*/
List<PrcPriceSetProduct> listBoundPackageProducts(String customerCode, Date bizDate);
/**
* Union of products from all effective bound packages (for order-source product check).
* @param customerCode required
* @param bizDate optional; default today
*/
List<PrcPriceSetProduct> listAllBoundPackageProducts(String customerCode, Date bizDate);
}
@@ -9,6 +9,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
@@ -57,6 +58,7 @@ import com.bms.price.search.EsBizLogSupport;
import com.bms.price.search.EsLogType;
import com.bms.price.search.IBillSearchStore;
import com.bms.price.service.ITmsPriceQuoteService;
import com.bms.system.service.IBmsProductCodeMappingService;
/**
* Shared quote/bill calc: customer bind + package version by bizDate (version effective_time).
@@ -103,6 +105,9 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
@Autowired
private BmsProductMapper productMapper;
@Autowired(required = false)
private IBmsProductCodeMappingService productCodeMappingService;
@Autowired
private PrcSurchargeRelMapper surchargeRelMapper;
@@ -261,6 +266,52 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
return Collections.emptyList();
}
@Override
public List<PrcPriceSetProduct> listAllBoundPackageProducts(String customerCode, Date bizDate)
{
if (StringUtils.isEmpty(customerCode))
{
return Collections.emptyList();
}
List<PrcCustomerPriceSet> binds = customerPriceSetMapper.selectEffectiveByCustomerCode(customerCode.trim());
if (binds == null || binds.isEmpty())
{
return Collections.emptyList();
}
Date asOf = bizDate != null ? bizDate : new Date();
Map<String, PrcPriceSetProduct> byCode = new LinkedHashMap<String, PrcPriceSetProduct>();
for (PrcCustomerPriceSet bind : binds)
{
if (bind == null || bind.getPriceSetId() == null)
{
continue;
}
PrcPriceSet set = priceSetMapper.selectPrcPriceSetHeaderById(bind.getPriceSetId());
if (set == null || !"E".equals(set.getStatus()))
{
continue;
}
List<PrcPriceSetProduct> products = loadProductsForPackage(set.getPriceSetId(), asOf);
if (products == null || products.isEmpty())
{
continue;
}
for (PrcPriceSetProduct p : products)
{
if (p == null || StringUtils.isEmpty(p.getProductCode()))
{
continue;
}
String key = p.getProductCode().trim().toUpperCase(Locale.ROOT);
if (!byCode.containsKey(key))
{
byCode.put(key, p);
}
}
}
return new ArrayList<PrcPriceSetProduct>(byCode.values());
}
/** Prefer version active at asOf; else latest version that has set-product rows. */
private List<PrcPriceSetProduct> loadProductsForPackage(Long priceSetId, Date asOf)
{
@@ -373,6 +424,25 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
PrcPriceSetProduct setProduct = resolveSetProduct(version.getPsvId(), productCode);
if (setProduct == null)
{
// Package has no this product: try product_code_mapping (upstream -> BMS).
String mappedCode = resolveMappedProductCode(productCode);
if (mappedCode != null)
{
setProduct = resolveSetProduct(version.getPsvId(), mappedCode);
if (setProduct != null)
{
productCode = mappedCode;
request.setProductCode(mappedCode);
String mappedName = resolveProductName(mappedCode, bizDate);
if (StringUtils.isNotEmpty(mappedName))
{
productName = mappedName;
}
}
}
}
if (setProduct == null)
{
PrcPriceSetProduct probe = new PrcPriceSetProduct();
probe.setPsvId(version.getPsvId());
@@ -470,6 +540,23 @@ public class TmsPriceQuoteServiceImpl implements ITmsPriceQuoteService
return setProductMapper.selectByPsvIdAndCode(psvId, productCode);
}
/**
* Return mapped BMS product code only when mapping exists and differs from upstream code.
*/
private String resolveMappedProductCode(String upstreamCode)
{
if (productCodeMappingService == null || StringUtils.isEmpty(upstreamCode))
{
return null;
}
String mapped = productCodeMappingService.resolveBmsProductCode(upstreamCode);
if (StringUtils.isEmpty(mapped) || mapped.equalsIgnoreCase(upstreamCode.trim()))
{
return null;
}
return mapped.trim();
}
private static final class ZoneResolve
{
private boolean required;
@@ -0,0 +1,92 @@
package com.bms.system.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.bms.common.annotation.Excel;
import com.bms.common.core.domain.BaseEntity;
/**
* 产品代码映射 product_code_mapping
*/
public class BmsProductCodeMapping extends BaseEntity
{
private static final long serialVersionUID = 1L;
private Long mapId;
/** 上游产品代码 */
@Excel(name = "上游产品代码")
private String upstreamCode;
/** BMS产品代码 */
@Excel(name = "BMS产品代码")
private String bmsProductCode;
/** 状态(0正常 1停用) */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
private String delFlag;
public Long getMapId()
{
return mapId;
}
public void setMapId(Long mapId)
{
this.mapId = mapId;
}
public String getUpstreamCode()
{
return upstreamCode;
}
public void setUpstreamCode(String upstreamCode)
{
this.upstreamCode = upstreamCode;
}
public String getBmsProductCode()
{
return bmsProductCode;
}
public void setBmsProductCode(String bmsProductCode)
{
this.bmsProductCode = bmsProductCode;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getDelFlag()
{
return delFlag;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
@Override
public String toString()
{
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("mapId", getMapId())
.append("upstreamCode", getUpstreamCode())
.append("bmsProductCode", getBmsProductCode())
.append("status", getStatus())
.append("remark", getRemark())
.toString();
}
}
@@ -0,0 +1,23 @@
package com.bms.system.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.bms.system.domain.BmsProductCodeMapping;
public interface BmsProductCodeMappingMapper
{
List<BmsProductCodeMapping> selectList(BmsProductCodeMapping query);
BmsProductCodeMapping selectById(Long mapId);
/** Active mapping by upstream code (status=0, del_flag=0). */
BmsProductCodeMapping selectActiveByUpstreamCode(@Param("upstreamCode") String upstreamCode);
int countByUpstreamCode(@Param("upstreamCode") String upstreamCode, @Param("excludeId") Long excludeId);
int insert(BmsProductCodeMapping row);
int update(BmsProductCodeMapping row);
int deleteByIds(Long[] mapIds);
}
@@ -0,0 +1,24 @@
package com.bms.system.service;
import java.util.List;
import com.bms.system.domain.BmsProductCodeMapping;
public interface IBmsProductCodeMappingService
{
List<BmsProductCodeMapping> selectList(BmsProductCodeMapping query);
BmsProductCodeMapping selectById(Long mapId);
int insert(BmsProductCodeMapping row);
int update(BmsProductCodeMapping row);
int deleteByIds(Long[] mapIds);
/**
* Resolve BMS product code from upstream code.
* Used after package product miss: returns mapped code when active mapping exists;
* otherwise returns original code.
*/
String resolveBmsProductCode(String upstreamCode);
}
@@ -0,0 +1,107 @@
package com.bms.system.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bms.common.exception.ServiceException;
import com.bms.common.utils.StringUtils;
import com.bms.system.domain.BmsProductCodeMapping;
import com.bms.system.mapper.BmsProductCodeMappingMapper;
import com.bms.system.service.IBmsProductCodeMappingService;
@Service
public class BmsProductCodeMappingServiceImpl implements IBmsProductCodeMappingService
{
@Autowired
private BmsProductCodeMappingMapper mappingMapper;
@Override
public List<BmsProductCodeMapping> selectList(BmsProductCodeMapping query)
{
return mappingMapper.selectList(query);
}
@Override
public BmsProductCodeMapping selectById(Long mapId)
{
return mappingMapper.selectById(mapId);
}
@Override
public int insert(BmsProductCodeMapping row)
{
normalize(row);
validate(row);
if (mappingMapper.countByUpstreamCode(row.getUpstreamCode(), null) > 0)
{
throw new ServiceException("上游产品代码已存在映射:" + row.getUpstreamCode());
}
if (StringUtils.isEmpty(row.getStatus()))
{
row.setStatus("0");
}
return mappingMapper.insert(row);
}
@Override
public int update(BmsProductCodeMapping row)
{
if (row.getMapId() == null)
{
throw new ServiceException("mapId required");
}
normalize(row);
validate(row);
if (mappingMapper.countByUpstreamCode(row.getUpstreamCode(), row.getMapId()) > 0)
{
throw new ServiceException("上游产品代码已存在映射:" + row.getUpstreamCode());
}
return mappingMapper.update(row);
}
@Override
public int deleteByIds(Long[] mapIds)
{
return mappingMapper.deleteByIds(mapIds);
}
@Override
public String resolveBmsProductCode(String upstreamCode)
{
if (StringUtils.isEmpty(upstreamCode))
{
return upstreamCode;
}
String code = upstreamCode.trim();
BmsProductCodeMapping mapped = mappingMapper.selectActiveByUpstreamCode(code);
if (mapped != null && StringUtils.isNotEmpty(mapped.getBmsProductCode()))
{
return mapped.getBmsProductCode().trim();
}
return code;
}
private void normalize(BmsProductCodeMapping row)
{
if (row.getUpstreamCode() != null)
{
row.setUpstreamCode(row.getUpstreamCode().trim());
}
if (row.getBmsProductCode() != null)
{
row.setBmsProductCode(row.getBmsProductCode().trim());
}
}
private void validate(BmsProductCodeMapping row)
{
if (StringUtils.isEmpty(row.getUpstreamCode()))
{
throw new ServiceException("上游产品代码不能为空");
}
if (StringUtils.isEmpty(row.getBmsProductCode()))
{
throw new ServiceException("BMS产品代码不能为空");
}
}
}
@@ -0,0 +1,92 @@
<?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.bms.system.mapper.BmsProductCodeMappingMapper">
<resultMap type="BmsProductCodeMapping" id="BmsProductCodeMappingResult">
<id property="mapId" column="map_id" />
<result property="upstreamCode" column="upstream_code" />
<result property="bmsProductCode" column="bms_product_code" />
<result property="status" column="status" />
<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>
<sql id="selectVo">
select map_id, upstream_code, bms_product_code, status, remark,
create_by, create_time, update_by, update_time, del_flag
from product_code_mapping
</sql>
<select id="selectList" parameterType="BmsProductCodeMapping" resultMap="BmsProductCodeMappingResult">
<include refid="selectVo"/>
<where>
del_flag = '0'
<if test="upstreamCode != null and upstreamCode != ''">
and upstream_code like concat('%', #{upstreamCode}, '%')
</if>
<if test="bmsProductCode != null and bmsProductCode != ''">
and bms_product_code like concat('%', #{bmsProductCode}, '%')
</if>
<if test="status != null and status != ''">
and status = #{status}
</if>
</where>
order by map_id desc
</select>
<select id="selectById" parameterType="Long" resultMap="BmsProductCodeMappingResult">
<include refid="selectVo"/>
where map_id = #{mapId} and del_flag = '0'
</select>
<select id="selectActiveByUpstreamCode" resultMap="BmsProductCodeMappingResult">
<include refid="selectVo"/>
where del_flag = '0' and status = '0' and upstream_code = #{upstreamCode}
order by map_id desc
limit 1
</select>
<select id="countByUpstreamCode" resultType="int">
select count(1) from product_code_mapping
where del_flag = '0' and upstream_code = #{upstreamCode}
<if test="excludeId != null">and map_id != #{excludeId}</if>
</select>
<insert id="insert" parameterType="BmsProductCodeMapping" useGeneratedKeys="true" keyProperty="mapId">
insert into product_code_mapping (
upstream_code, bms_product_code, status, remark, create_by, create_time, del_flag
) values (
#{upstreamCode}, #{bmsProductCode}, #{status}, #{remark}, #{createBy}, sysdate(), '0'
)
</insert>
<update id="update" parameterType="BmsProductCodeMapping">
update product_code_mapping
<set>
<if test="upstreamCode != null and upstreamCode != ''">upstream_code = #{upstreamCode},</if>
<if test="bmsProductCode != null and bmsProductCode != ''">bms_product_code = #{bmsProductCode},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
update_time = sysdate()
</set>
where map_id = #{mapId}
</update>
<update id="deleteByIds" parameterType="Long">
update product_code_mapping
set del_flag = '1',
upstream_code = concat(upstream_code, '#DEL#', map_id),
update_time = sysdate()
where map_id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</update>
</mapper>
@@ -107,4 +107,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE rn &gt; #{startRow}
</select>
<!-- Distinct product codes under the same filters (no pagination). -->
<select id="selectTabOrderProductCodes" resultType="java.util.HashMap">
SELECT o.CUSTOMER_CODE AS CUSTOMER_CODE,
o.PRODUCT_CODE AS PRODUCT_CODE,
MAX(o.PRODUCT_NAME) AS PRODUCT_NAME,
COUNT(1) AS ORDER_COUNT
FROM ${orderTable} o
WHERE
<include refid="tabOrderMonitorWhere"/>
AND o.PRODUCT_CODE IS NOT NULL
GROUP BY o.CUSTOMER_CODE, o.PRODUCT_CODE
ORDER BY o.CUSTOMER_CODE, o.PRODUCT_CODE
</select>
</mapper>