需求背景

UPS、FedEx 对 AHS(额外操作费) 与 LPS(大包裹附加费) 的触发条件已发布新规,其中 FedEx 新增了 体积触发 与 LPS 超重触发 等关键变化。

我司当前在 WMS>产品信息管理>产品管理>美国货型 的判定仍沿用旧口径,且相关 悬浮说明文案、入库管理>收货管理 的 DO 属性统计 等处也未同步更新,可能会导致货型识别与仓配策略、渠道前置校验存在偏差。

为统一口径,现确定:以 FedEx 货型规则为准 对美国货型:AHS超尺、AHS超重、OS件、超大件、标准件进行判定,并同步更新所有使用“货型”的页面与导出口径,保障头程与仓库判断送仓与上架能力。

需求描述

判定口径(以 FedEx 规则为准)
单位:长度/尺寸用 inch,重量用 lb

计算:
围长 = 最长边 + 2×第二长边 + 2×最短边
体积 = 长×宽×高(单位:in³)
优先级:超大件 > OS件(LPS) > AHS超重 > AHS超尺 > 标准件;命中OS 则不再判 AHS。

触发阈值(任一满足即命中):
超大件:最长边 >108” 或 围长 >165” 或 实重 >150 lb
OS件(LPS):最长边 >96” 或 围长 >130” 或 体积 >17,280 in³ 或 实重 >110 lb
AHS超重:实重 >50 lb
AHS超尺:最长边 >48” 或 第二长边 >30” 或 围长 >105” 或 体积 >10,368 in³
标准件:未命中以上任一条件

开发设计

  1. 重写原更新货型方法,涉及oms/wms项目,oms方法(void updateCargoTypeByMap(Map<String, Object> selUMap);)wms方法(int updateProduct(Map<String, Object> map);
  2. 接口两边逻辑复用,代码复制过去就行
  3. 原实现逻辑写在sql里面,需要改用java代码实现逻辑
  4. task重刷历史数据也需要使用,故这个接口代码,在oms/wms/task都存在,task设计成传入sku,重刷货型

原sql

<update id="updateCargoTypeByMap" parameterType="map">
    update product_cargo_type pct
    JOIN product p on pct.product_id = p.product_id
    JOIN customer c on c.customer_id = p.customer_id
    SET
    pct.product_weight_lb = CEIL(p.product_weight_lb),
    pct.product_length_in = CEIL(p.product_length_in),
    pct.product_width_in = CEIL(p.product_width_in),
    pct.product_height_in = CEIL(p.product_height_in),
    pct.product_weight = ROUND(p.product_weight, 2),
    pct.product_length = ROUND(p.product_length, 2),
    pct.product_width = ROUND(p.product_width, 2),
    pct.product_height = ROUND(p.product_height, 2),
    pct.us_charging_weight = IF(CEIL(p.product_weight_lb) >
    CEIL((CEIL(p.product_length_in) * CEIL(p.product_width_in) *
    CEIL(p.product_height_in)) / 250),
    CEIL(p.product_weight_lb),
    CEIL((CEIL(p.product_length_in) * CEIL(p.product_width_in) *
    CEIL(p.product_height_in)) / 250)),
    pct.us_product_weight  = CEIL(p.product_weight_lb),
    pct.us_volume_weight   = CEIL(
    (CEIL(p.product_length_in) * CEIL(p.product_width_in) * CEIL(p.product_height_in)) /
    250),

    pct.de_charging_weight = CEIL(ROUND(p.product_weight, 2) * 10) / 10,
    pct.de_product_weight  = ROUND(p.product_weight, 2),
    pct.de_volume_weight   = ROUND((ROUND(p.product_length, 2) * ROUND(p.product_width, 2) * ROUND(p.product_height, 2)) / 6000, 2),

    pct.product_type       = CASE
    WHEN IF(CASE
    WHEN c.oversize_round = 1 THEN CEIL(p.product_weight_lb)
    ELSE p.product_weight_lb END >
    CEIL((CEIL(p.product_length_in) * CEIL(p.product_width_in) *
    CEIL(p.product_height_in)) / 250),
    CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(p.product_weight_lb)
    ELSE p.product_weight_lb END,
    CEIL((CEIL(p.product_length_in) * CEIL(p.product_width_in) *
    CEIL(p.product_height_in)) / 250)) > 150
    OR CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(p.product_length_in)
    ELSE p.product_length_in END >= 108
    OR CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(CEIL(p.product_length_in) +
    CEIL(p.product_width_in) * 2 +
    CEIL(p.product_height_in) * 2)
    ELSE p.product_length_in + p.product_width_in * 2 +
    p.product_height_in * 2 END >= 165 THEN 4
    WHEN CASE
    WHEN c.oversize_round = 1 THEN CEIL(p.product_length_in)
    ELSE p.product_length_in END > 96
    OR
    CASE
    WHEN c.oversize_round = 1 THEN CEIL(CEIL(p.product_length_in) +
    CEIL(p.product_width_in) * 2 +
    CEIL(p.product_height_in) * 2)
    ELSE p.product_length_in + p.product_width_in * 2 +
    p.product_height_in * 2 END
    > (CASE WHEN c.oversize_inch = 1 THEN 126 ELSE 130 END) THEN 3
    WHEN CEIL(p.product_weight_lb) > 50 THEN 2
    WHEN CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(p.product_length_in)
    ELSE p.product_length_in END > 48
    OR CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(p.product_width_in)
    ELSE p.product_width_in END > 30
    OR CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(CEIL(p.product_length_in) +
    CEIL(p.product_width_in) * 2 +
    CEIL(p.product_height_in) * 2)
    ELSE p.product_length_in + p.product_width_in * 2 +
    p.product_height_in * 2 END > 105 THEN 1
    ELSE 5 END,

    pct.us_product_type    = CASE
    WHEN IF(CASE
    WHEN c.oversize_round = 1 THEN CEIL(CEIL(p.product_weight_lb))
    ELSE p.product_weight_lb END >
    CEIL((CEIL(p.product_length_in) * CEIL(p.product_width_in) *
    CEIL(p.product_height_in)) / 250),
    CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(p.product_weight_lb)
    ELSE p.product_weight_lb END,
    CEIL((CEIL(p.product_length_in) * CEIL(p.product_width_in) *
    CEIL(p.product_height_in)) / 250)) > 150
    OR CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(p.product_length_in)
    ELSE p.product_length_in END >= 108
    OR CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(CEIL(p.product_length_in) +
    CEIL(p.product_width_in) * 2 +
    CEIL(p.product_height_in) * 2)
    ELSE p.product_length_in + p.product_width_in * 2 +
    p.product_height_in * 2 END >= 165 THEN 4
    WHEN CASE
    WHEN c.oversize_round = 1 THEN CEIL(p.product_length_in)
    ELSE p.product_length_in END > 96
    OR
    CASE
    WHEN c.oversize_round = 1 THEN CEIL(CEIL(p.product_length_in) +
    CEIL(p.product_width_in) * 2 +
    CEIL(p.product_height_in) * 2)
    ELSE p.product_length_in + p.product_width_in * 2 +
    p.product_height_in * 2 END
    > (CASE WHEN c.oversize_inch = 1 THEN 126 ELSE 130 END) THEN 3
    WHEN CEIL(p.product_weight_lb) > 50 THEN 2
    WHEN CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(p.product_length_in)
    ELSE p.product_length_in END > 48
    OR CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(p.product_width_in)
    ELSE p.product_width_in END > 30
    OR CASE
    WHEN c.logistics_fee_round = 1 THEN CEIL(CEIL(p.product_length_in) +
    CEIL(p.product_width_in) * 2 +
    CEIL(p.product_height_in) * 2)
    ELSE p.product_length_in + p.product_width_in * 2 +
    p.product_height_in * 2 END > 105 THEN 1
    ELSE 5 END,

    pct.de_product_type    = CASE
    WHEN ROUND(p.product_length, 2) + ROUND(p.product_width, 2) * 2 + ROUND(p.product_height, 2) * 2 >
    300 THEN 1
    WHEN ROUND(p.product_width, 2) > 80 THEN 2
    WHEN ROUND(p.product_width, 2) > 60 AND ROUND(p.product_width, 2) &lt;= 80 THEN 3
    WHEN ROUND(p.product_length, 2) > 200 THEN 4
    WHEN ROUND(p.product_length, 2) > 120 AND ROUND(p.product_length, 2) &lt;= 200 THEN 5
    WHEN ROUND(p.product_length, 2) >= 15 AND ROUND(p.product_length, 2) &lt;= 120
    AND ROUND(p.product_width, 2) >= 11 AND ROUND(p.product_width, 2) &lt;= 60
    AND ROUND(p.product_height, 2) >= 3 AND ROUND(p.product_height, 2) &lt;= 60 THEN 6

    WHEN ROUND(p.product_length, 2) &lt; 15 OR ROUND(p.product_width, 2) &lt; 11 OR
    ROUND(p.product_height, 2) &lt; 3 THEN 7
    ELSE 0 END
    where
    <if test="productId != null">
      p.product_id = #{productId}
    </if>
  </update>
作者:黄天文  创建时间:2026-01-06 16:18
最后编辑:黄天文  更新时间:2026-03-03 10:08