diff --git a/sell/shopfad_sell_price_v2.py b/sell/shopfad_sell_price_v2.py index d6674bf..258c815 100644 --- a/sell/shopfad_sell_price_v2.py +++ b/sell/shopfad_sell_price_v2.py @@ -2,7 +2,11 @@ """ 美国售价模型 V2 (shopfad) 通过输入多包裹体积和采购价格,快速计算售价 +规则版本: 2604 """ +import sys +sys.path.append(r'D:\workspace\dags\logistics') + import math from utils.gtools import MySQLconnect import pandas as pd @@ -24,150 +28,246 @@ class USLogisticsPrice: conn = MySQLconnect('logistics') with conn as c: self.sell_usps = pd.read_sql("SELECT * FROM sell_usps", c.con) - self.sell_uandf = pd.read_sql("SELECT * FROM sell_uandf", c.con) - self.sell_fedex = pd.read_sql("SELECT * FROM sell_fedex", c.con) + # 2604版本价格表 (表名按需修改) + self.sell_uandf_2604 = pd.read_sql("SELECT * FROM sell_uandf_2604", c.con) + self.sell_fedex_price_ref_2604 = pd.read_sql("SELECT * FROM sell_fedex_price_ref_2604", c.con) + self.sell_fedex_order_ref_2604 = pd.read_sql("SELECT * FROM sell_fedex_order_ref_2604", c.con) + # 物流比例限制表 (表名按需修改) + self.logistics_ratio_limit = pd.read_sql("SELECT * FROM logistics_ratio_limit", c.con) - def get_express_fee(self, packages, profit_rate=0.359): + # ========== 包裹计费类型判断 ========== + + def get_package_types(self, packages): """ - 计算快递费用 (尾程) - 支持多包裹 - - Args: - packages: 包裹列表, 每个元素为 dict: - {'length_cm', 'width_cm', 'height_cm', 'weight_g'} - profit_rate: 利润系数 - - Returns: - float: 快递费用 (USD) + USPS:默认 + UandF:最长边>50 或 次长边>40 或 最短边>30 或 实重>2718 或 体积重>4500 + FEDEX:最长边>264 或 实重>67000 或 体积重>95000 或 围长>391 + 卡派:同FEDEX条件(或该SKU的其他包裹为卡派类型) """ - # 先遍历所有包裹确定物流类型(取最严格的) - head_type = 0 - index = 0 + types = [] for pkg in packages: l, w, h, wt = pkg['length_cm'], pkg['width_cm'], pkg['height_cm'], pkg['weight_g'] sizes = sorted([l, w, h], reverse=True) fst, sed, trd = sizes[0], sizes[1], sizes[2] - vol_6000 = l * w * h / 6000 + vol_weight = l * w * h / 6 + girth = fst + sed * 2 + trd * 2 - if wt > 420: - head_type = max(head_type, 1) - if fst > 50 or sed > 40 or trd > 30 or wt > 2718 or vol_6000 > 3624: - head_type = max(head_type, 2) - if fst > 264 or wt > 67000 or vol_6000 > 95000 or (fst + sed * 2 + trd * 2) > 391: - head_type = max(head_type, 3) - index = 1 - if fst > 310: - head_type = max(head_type, 4) - index = 1 + pkg_type = 'USPS' + if fst > 50 or sed > 40 or trd > 30 or wt > 2718 or vol_weight > 4500: + pkg_type = 'UandF' + if fst > 264 or wt > 67000 or vol_weight > 95000 or girth > 391: + pkg_type = 'FEDEX' + types.append(pkg_type) - # 逐包裹计算快递费 - sku_express_fee = 0 - sku_total_cubic_feet = 0 - ltl_over_size = 0 - ltl_over_weightfee = 0 + # FEDEX升级为卡派(同SKU联动) + if 'FEDEX' in types: + types = ['卡派' if t == 'FEDEX' else t for t in types] - for pkg in packages: + return types + + # ========== 快递费计算 ========== + + def _lookup_express_base_fee(self, pkg_type, lbs_weight, oz_weight, profit_rate, fuel_rate): + """ + 查表获取单个包裹的快递基础计费 + USPS/UandF: 直接查表 + FEDEX: FEDEX售价参考表 * (1+快递燃油费率) + 2.9 + """ + if pkg_type == 'USPS': + row = self.sell_usps[self.sell_usps['oz'] == oz_weight] + if len(row) > 0: + return row['最终费用_v2'].iloc[0] / profit_rate, 'USPS' + else: + return self._lookup_express_base_fee('UandF', lbs_weight, oz_weight, profit_rate, fuel_rate) + + if pkg_type == 'UandF': + row = self.sell_uandf_2604[self.sell_uandf_2604['lbs'] == lbs_weight] + if len(row) > 0: + return row['加权价格_v2'].iloc[0] / profit_rate, 'UandF' + else: + return self._lookup_express_base_fee('FEDEX', lbs_weight, oz_weight, profit_rate, fuel_rate) + + if pkg_type in ('FEDEX', '卡派'): + row = self.sell_fedex_price_ref_2604[self.sell_fedex_price_ref_2604['lbs'] == lbs_weight] + if len(row) > 0: + return row['售价尾端价格_v4'].iloc[0] * (1 + fuel_rate) + 2.9, 'FEDEX' + else: + return 99999, 'FEDEX' + + return 0, pkg_type + + def _calc_express_fee(self, packages, types, profit_rate, fuel_rate): + """ + 快递费 = Σ(单包裹快递基础计费 + 大包裹费 + 超重费 + 超尺寸费) + 大包裹费: 最长边>238 或 围长>315 → 109.4 + 超重费: 实重>21000 → 6.1 + 超尺寸费: 最长边>116 或 围长>251 → 7.4 + """ + total_fee = 0 + for i, pkg in enumerate(packages): l, w, h, wt = pkg['length_cm'], pkg['width_cm'], pkg['height_cm'], pkg['weight_g'] sizes = sorted([l, w, h], reverse=True) fst, sed, trd = sizes[0], sizes[1], sizes[2] volume = l * w * h - vol_8500 = volume / 8500 - vol_6000 = volume / 6000 + girth = fst + sed * 2 + trd * 2 - lbs_weight = math.ceil(max(vol_8500 / 0.453, wt / 453)) + lbs_weight = math.ceil(max(volume / 8500 / 0.453, wt / 453)) oz_weight = math.ceil(wt / 28) - express_base_fee = 0 - oversize_charge = 0 - ahs_weight = 0 - ahs_dimension = 0 + pkg_type = types[i] + base_fee, actual_type = self._lookup_express_base_fee( + pkg_type, lbs_weight, oz_weight, profit_rate, fuel_rate + ) - if head_type == 0: - try: - row = self.sell_usps[self.sell_usps['oz'] == oz_weight] - if len(row) > 0: - express_base_fee = row['最终费用_v2'].iloc[0] / profit_rate - else: - head_type = 1 - except: - head_type = 1 + large_pkg_fee = 0 + overweight_fee = 0 + oversize_fee = 0 - if head_type == 1: - try: - row = self.sell_uandf[self.sell_uandf['lbs'] == lbs_weight] - if len(row) > 0: - express_base_fee = row['加权价格_v2'].iloc[0] / profit_rate - else: - head_type = 2 - except: - head_type = 2 + if actual_type in ('FEDEX', '卡派'): + if fst > 238 or girth > 315: + large_pkg_fee = 109.4 + if wt > 21000: + overweight_fee = 6.1 + if fst > 116 or girth > 251: + oversize_fee = 7.4 - if head_type == 2: - try: - row = self.sell_fedex[self.sell_fedex['lbs'] == lbs_weight] - if len(row) > 0: - express_base_fee = row['售价尾端价格_v3'].iloc[0] - else: - express_base_fee = 99999 - head_type = 3 - if fst > 238 or (fst + sed * 2 + trd * 2) > 315: - oversize_charge = 109.4 - elif wt > 21000: - ahs_weight = 6.1 - except: - head_type = 3 + total_fee += base_fee + large_pkg_fee + overweight_fee + oversize_fee - sku_express_fee += express_base_fee + oversize_charge + ahs_weight + ahs_dimension + return total_fee + + # ========== 卡派费计算 ========== + + def _calc_ltl_fee(self, packages, profit_rate): + """ + 卡派费 = 卡派基础费 + 超长费 + 超重费 + 合并体积 = ceil(长x宽x高/1000000 x 35.3) (立方英尺) + """ + total_cubic_feet = 0 + over_length_fee = 0 + over_weight_fee = 0 + + for pkg in packages: + l, w, h, wt = pkg['length_cm'], pkg['width_cm'], pkg['height_cm'], pkg['weight_g'] + sizes = sorted([l, w, h], reverse=True) + fst = sizes[0] + volume = l * w * h - # 卡派计算 cubic_feet = math.ceil(volume / 1000000 * 35.3147) - sku_total_cubic_feet += cubic_feet + total_cubic_feet += cubic_feet + + # 超长费: 最长边>250 if fst > 250: - ltl_over_size = max(ltl_over_size, round(130 / profit_rate - 118, 1)) - if 111000 <= wt < 130000: - ltl_over_weightfee = max(ltl_over_weightfee, round(80 / profit_rate - 78, 1)) + over_length_fee = max(over_length_fee, round(130 / profit_rate - 118, 1)) + # 超重费 if 130000 <= wt < 157000: - ltl_over_weightfee = max(ltl_over_weightfee, round(130 / profit_rate - 118, 1)) + over_weight_fee = max(over_weight_fee, round(130 / profit_rate - 118, 1)) + elif 111000 <= wt < 130000: + over_weight_fee = max(over_weight_fee, round(80 / profit_rate - 78, 1)) - # 卡派基础费用 - if sku_total_cubic_feet < 25: - ltl_base_fee1 = round(198 / profit_rate / 2, 2) - elif sku_total_cubic_feet < 35: - ltl_base_fee1 = round(231 / profit_rate / 2, 2) + # 卡派基础费 + v = total_cubic_feet + if v < 25: + base_fee = round(198 / profit_rate / 2, 2) + elif v < 35: + base_fee = round(231 / profit_rate / 2, 2) else: - ltl_base_fee1 = round(max(231, 6.6 * sku_total_cubic_feet) / profit_rate / 2, 2) + base_fee = round(max(231, 6.6 * v) / profit_rate / 2, 2) - ltl_base_fee = ltl_base_fee1 * 1.025 - ltl_fee = ltl_base_fee + ltl_over_size + ltl_over_weightfee + ltl_fee = base_fee + over_length_fee + over_weight_fee + return ltl_fee, total_cubic_feet - if index == 0: - return min(ltl_fee, sku_express_fee) + # ========== 初始前端展示物流费 ========== + + def _calc_display_logistics_fee(self, packages, types, total_cubic_feet): + """ + 卡派: v<25→90, v<35→90+(v-25)*3, 其他→99+(v-35)*5 + 快递: FEDEX订单参考表查表 + """ + has_ltl = '卡派' in types + + if has_ltl: + v = total_cubic_feet + if v < 25: + display = 90 + elif v < 35: + display = 90 + (v - 25) * 3 + else: + display = 99 + (v - 35) * 5 + print(f"[卡派展示物流费] 合并体积={v} cu ft, 展示费={display}") + return display else: - return ltl_fee + # 快递: FEDEX订单参考表查表 + total = 0 + for pkg in packages: + l, w, h, wt = pkg['length_cm'], pkg['width_cm'], pkg['height_cm'], pkg['weight_g'] + volume = l * w * h + lbs_weight = math.ceil(max(volume / 8500 / 0.453, wt / 453)) + row = self.sell_fedex_order_ref_2604[ + self.sell_fedex_order_ref_2604['lbs'] == lbs_weight + ] + if len(row) > 0: + total += row['售价尾端价格_v3'].iloc[0] + return total + + # ========== 物流比例限制查表 ========== + + def _lookup_logistics_limit(self, category, price): + """通过条目和价格查表得到建议物流比例上限和建议物流绝对上限""" + try: + rows = self.logistics_ratio_limit[ + (self.logistics_ratio_limit['条目'] == category) & + (self.logistics_ratio_limit['价格'] <= price) + ] + if len(rows) > 0: + row = rows.iloc[-1] + return row['建议物流比例上限'], row['建议物流绝对上限'] + return 1.0, float('inf') + except: + return 1.0, float('inf') + + # ========== 统一尾端费用接口 ========== + + def get_tail_fee_info(self, packages, profit_rate=0.359, fuel_rate=0): + """ + 尾端费用 = min(快递费, 卡派费) + 存在卡派类型包裹则强制使用卡派 + """ + types = self.get_package_types(packages) + has_ltl = '卡派' in types + + express_fee = self._calc_express_fee(packages, types, profit_rate, fuel_rate) + ltl_fee, total_cubic_feet = self._calc_ltl_fee(packages, profit_rate) + + if has_ltl: + tail_fee = ltl_fee + else: + tail_fee = min(express_fee, ltl_fee) + + display_fee = self._calc_display_logistics_fee(packages, types, total_cubic_feet) + + return { + 'tail_fee': tail_fee, + 'display_logistics_fee': display_fee, + 'express_fee': express_fee, + 'ltl_fee': ltl_fee, + 'types': types, + 'has_ltl': has_ltl, + 'total_cubic_feet': total_cubic_feet + } class USSellPrice: """ 美国售价计算器 V2 (shopfad) + 规则版本: 2604 使用示例: calculator = USSellPrice() - - # 单包裹 result = calculator.calculate( packages=[{'length_cm': 30, 'width_cm': 20, 'height_cm': 10, 'weight_g': 500}], purchase_price_cny=100, preset='shopfad' ) - - # 多包裹 - result = calculator.calculate( - packages=[ - {'length_cm': 30, 'width_cm': 20, 'height_cm': 10, 'weight_g': 500}, - {'length_cm': 40, 'width_cm': 30, 'height_cm': 15, 'weight_g': 1000}, - ], - purchase_price_cny=100, - preset='shopfad' - ) """ PRESETS = { @@ -181,11 +281,10 @@ class USSellPrice: 'profit_rate': 0.38, 'air_rate': 0.7, 'tax_rate': 0.1, - 'shipping_type': 1, 'fuel_rate': 0, 'extra_rate': 0 }, - 'shopfad2': { + 'shopfad2': { 'ocean_first_cny': 1, 'ocean_first_usd': 1, 'air_first_usd': 0.65, @@ -195,11 +294,23 @@ class USSellPrice: 'profit_rate': 0.38, 'air_rate': 0.7, 'tax_rate': 0.145, - 'shipping_type': 1, 'fuel_rate': 0, 'extra_rate': 0 }, - 'shopfad3': { + 'shopfad3': { + 'ocean_first_cny': 0.67, + 'ocean_first_usd': 0.7, + 'air_first_usd': 0.65, + 'air_cny_type': 0.093, + 'air_first_fix': 22.7, + 'exchange_rate': 6.5, + 'profit_rate': 0.3, + 'air_rate': 0.7, + 'tax_rate': 0.1, + 'fuel_rate': 0, + 'extra_rate': 0 + }, + 'shopfad4': { 'ocean_first_cny': 0.67, 'ocean_first_usd': 0.7, 'air_first_usd': 0.65, @@ -209,7 +320,6 @@ class USSellPrice: 'profit_rate': 0.3, 'air_rate': 0.7, 'tax_rate': 0.1, - 'shipping_type': 1, 'fuel_rate': 0, 'extra_rate': 0 } @@ -218,80 +328,164 @@ class USSellPrice: def __init__(self): self.logistics = USLogisticsPrice() - def calculate(self, packages, purchase_price_cny, preset='shopfad', config=None): + def calculate(self, packages, purchase_price_cny, preset='shopfad', config=None, category=''): """ 计算售价 Args: - packages: 包裹列表, 每个元素为 dict: - {'length_cm', 'width_cm', 'height_cm', 'weight_g'} + packages: 包裹列表 [{'length_cm', 'width_cm', 'height_cm', 'weight_g'}] purchase_price_cny: 采购价(CNY) preset: 预设配置名称 config: 自定义配置 (优先使用) - - Returns: - dict: 包含详细费用信息 + category: 条目 (用于物流比例限制查表) """ cfg = config or self.PRESETS.get(preset, self.PRESETS['shopfad']) - # 汇总体积重 + # 1. 获取尾端费用 + fuel_rate = cfg.get('fuel_rate', 0) + tail_info = self.logistics.get_tail_fee_info(packages, cfg['profit_rate'], fuel_rate) + tail_fee = tail_info['tail_fee'] + display_fee = tail_info['display_logistics_fee'] + + # 2. 判断SPU运输方式 + has_ltl = tail_info['has_ltl'] + shipping_type = '海运' if has_ltl else '空运' + + # 3. 汇总体积重 (长x宽x高/6) total_volume_weight = sum( - p['length_cm'] * p['width_cm'] * p['height_cm'] / 6000 for p in packages + p['length_cm'] * p['width_cm'] * p['height_cm'] / 6 for p in packages ) - # 尾程快递费 - fuel_rate = cfg.get('fuel_rate', 0) - extra_rate = cfg.get('extra_rate', 0) - express_fee = self.logistics.get_express_fee(packages, cfg['profit_rate']) - express_fee = express_fee * (1 + fuel_rate) * (1 + extra_rate) - - purchase_price_usd = purchase_price_cny / cfg['exchange_rate'] tax_amount = purchase_price_cny * cfg['tax_rate'] / cfg['exchange_rate'] - if cfg['shipping_type'] == 0: # 空运 - sell_price = 0 - first_cny = 0 - first_usd = 0 - for pkg in packages: - volume = pkg['length_cm'] * pkg['width_cm'] * pkg['height_cm'] - volume_weight = volume / 6000 - density = pkg['weight_g'] / (volume / 1000) if volume > 0 else 0 - type_weight = min(337, max(37, density)) + # 4. 根据运输方式计算调整前售价 + if shipping_type == '海运': + pre_adjust_price = self._calc_ocean_price( + total_volume_weight, purchase_price_cny, tax_amount, tail_fee, cfg + ) + first_cny = cfg['ocean_first_cny'] / 1000 * total_volume_weight + first_usd = cfg['ocean_first_usd'] / 1000 * total_volume_weight + else: + pre_adjust_price = self._calc_air_price( + packages, purchase_price_cny, tax_amount, tail_fee, cfg + ) + first_cny, first_usd = self._calc_air_first_leg(packages, cfg) - air_first_cny = cfg['air_cny_type'] * type_weight + cfg['air_first_fix'] - air_first_cny_total = air_first_cny * volume_weight - air_first_usd_total = cfg['air_first_usd'] * volume_weight + # 5. 最终修正 (仅海运) + shared_tail_fee = 0 + final_price = pre_adjust_price - sell_price += (purchase_price_usd / cfg['profit_rate'] + - ((air_first_cny_total / cfg['exchange_rate'] + air_first_usd_total + - tax_amount) / cfg['profit_rate'] + express_fee) * cfg['air_rate']) - first_cny += air_first_cny_total - first_usd += air_first_usd_total - shipping_type = '空运' + if shipping_type == '海运': + final_price, shared_tail_fee = self._apply_ocean_adjustment( + pre_adjust_price, display_fee, category + ) - else: # 海运 - ocean_first_cny_total = cfg['ocean_first_cny'] * total_volume_weight - ocean_first_usd_total = cfg['ocean_first_usd'] * total_volume_weight - - sell_price = ((ocean_first_cny_total + purchase_price_cny) / - cfg['exchange_rate'] + ocean_first_usd_total + tax_amount) / cfg['profit_rate'] + express_fee - - first_cny = ocean_first_cny_total - first_usd = ocean_first_usd_total - shipping_type = '海运' + # 头程费用 / 总物流费用 + head_fee = first_cny / cfg['exchange_rate'] + first_usd + total_logistics_fee = head_fee + tail_fee return { - 'sell_price_usd': round(sell_price, 2), - 'sell_price_cny': round(sell_price * cfg['exchange_rate'], 2), + 'sell_price_usd': round(final_price, 2), + 'sell_price_cny': round(final_price * cfg['exchange_rate'], 2), 'purchase_price_cny': purchase_price_cny, - 'express_fee': round(express_fee, 2), + 'express_fee': round(tail_fee, 2), 'first_cny': round(first_cny, 2), 'first_usd': round(first_usd, 2), 'tax_amount': round(tax_amount, 2), 'shipping_type': shipping_type, - 'preset': preset + 'preset': preset, + 'pre_adjust_price': round(pre_adjust_price, 2), + 'display_logistics_fee': round(display_fee, 2), + 'shared_tail_fee': round(shared_tail_fee, 2), + 'head_fee': round(head_fee, 2), + 'total_logistics_fee': round(total_logistics_fee, 2), + 'package_types': tail_info['types'], } + # ========== 海运计费 ========== + + def _calc_ocean_price(self, total_volume_weight, purchase_price_cny, tax_amount, tail_fee, cfg): + """ + 调整前售价 = (((海运头程CNY总价 + 采购价格) / 汇率 + 海运头程USD总价) + + 采购价格 x 税金系数 / 汇率) / 利润系数 + 尾端费用 + """ + ocean_first_cny_total = cfg['ocean_first_cny'] / 1000 * total_volume_weight + ocean_first_usd_total = cfg['ocean_first_usd'] / 1000 * total_volume_weight + + pre_adjust = ( + ((ocean_first_cny_total + purchase_price_cny) / cfg['exchange_rate'] + + ocean_first_usd_total + tax_amount) / cfg['profit_rate'] + tail_fee + ) + return pre_adjust + + # ========== 空运计费 ========== + + def _calc_air_price(self, packages, purchase_price_cny, tax_amount, tail_fee, cfg): + """ + 调整前售价 = (采购价格/汇率/利润系数 + + ((空运头程CNY总价/汇率 + 空运头程USD总价 + 税金) / 利润系数 + 尾端费用) + x 空运分配比例) x (1 + 附加费率) + """ + air_cny_total = 0 + air_usd_total = 0 + + for pkg in packages: + volume = pkg['length_cm'] * pkg['width_cm'] * pkg['height_cm'] + volume_weight = volume / 6 + density = pkg['weight_g'] / (volume / 1000) if volume > 0 else 0 + type_weight = min(337, max(37, math.ceil(density))) + + air_cny_unit = cfg['air_cny_type'] / 1000 * type_weight + cfg['air_first_fix'] / 1000 + air_cny_total += air_cny_unit * volume_weight + air_usd_total += cfg['air_first_usd'] / 1000 * volume_weight + + purchase_usd = purchase_price_cny / cfg['exchange_rate'] + + pre_adjust = ( + purchase_usd / cfg['profit_rate'] + + ((air_cny_total / cfg['exchange_rate'] + air_usd_total + tax_amount) + / cfg['profit_rate'] + tail_fee) * cfg['air_rate'] + ) * (1 + cfg.get('extra_rate', 0)) + + return pre_adjust + + def _calc_air_first_leg(self, packages, cfg): + """计算空运头程费用 (CNY/USD)""" + first_cny = 0 + first_usd = 0 + for pkg in packages: + volume = pkg['length_cm'] * pkg['width_cm'] * pkg['height_cm'] + volume_weight = volume / 6 + density = pkg['weight_g'] / (volume / 1000) if volume > 0 else 0 + type_weight = min(337, max(37, math.ceil(density))) + + air_cny_unit = cfg['air_cny_type'] / 1000 * type_weight + cfg['air_first_fix'] / 1000 + first_cny += air_cny_unit * volume_weight + first_usd += cfg['air_first_usd'] / 1000 * volume_weight + return first_cny, first_usd + + # ========== 最终修正 (海运) ========== + + def _apply_ocean_adjustment(self, pre_adjust_price, display_fee, category): + """ + 前端展示物流费 = min(初始前端展示物流费, 调整前售价×比例上限, 绝对上限) + if min == 初始前端展示物流费: 分摊尾端=0, 最终售价=调整前售价 + else: 分摊尾端=初始前端展示物流费-min, 最终售价=调整前售价+分摊尾端 + """ + total = display_fee + pre_adjust_price + if total <= 0: + return pre_adjust_price, 0 + + ratio_limit, abs_limit = self.logistics._lookup_logistics_limit(category, pre_adjust_price) + actual_display_fee = min(display_fee, pre_adjust_price * ratio_limit, abs_limit) + + if actual_display_fee == display_fee: + return pre_adjust_price, 0 + else: + shared_tail = display_fee - actual_display_fee + final_price = pre_adjust_price + shared_tail + return final_price, shared_tail + if __name__ == '__main__': calc = USSellPrice() @@ -303,6 +497,8 @@ if __name__ == '__main__': preset='shopfad' ) print(f" 30x20x10cm 500g => ${result['sell_price_usd']}") + print(f" 运输方式: {result['shipping_type']}") + print(f" 包裹类型: {result['package_types']}") print("\n=== 多包裹测试 ===") result = calc.calculate( @@ -314,5 +510,8 @@ if __name__ == '__main__': preset='shopfad' ) print(f" 两件包裹 => ${result['sell_price_usd']}") - print(f" 快递费: ${result['express_fee']}") + print(f" 运输方式: {result['shipping_type']}") + print(f" 包裹类型: {result['package_types']}") + print(f" 尾端费用: ${result['express_fee']}") print(f" 头程CNY: {result['first_cny']}, 头程USD: ${result['first_usd']}") + print(f" 总物流: ${result['total_logistics_fee']}")