| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- 车型匹配脚本:在价格配置表中按ModelCode匹配车型信息
- """
- import os
- import openpyxl
- # 价格列映射
- PRICE_COLUMN_MAP = {
- 'FOB': 'N',
- 'FCA': 'O',
- 'EXW': 'P',
- }
- PRICE_COL_INDEX = {
- 'FOB': 13, # N列 (0-based index)
- 'FCA': 14, # O列
- 'EXW': 15, # P列
- }
- def get_price_config_path():
- """获取价格配置表路径"""
- script_dir = os.path.dirname(os.path.abspath(__file__))
- return os.path.join(script_dir, '..', 'assets', 'vehicle-price-config.xlsx')
- def match_vehicle(model_code: str, trade_term: str = 'FCA'):
- """
- 在价格配置表中匹配车型
-
- Args:
- model_code: 车型型号,如 LZW5030XXYLGHUG
- trade_term: 贸易条款,如 FCA/FOB/EXW
-
- Returns:
- dict or None: {
- 'unit_price_usd': float,
- 'description_cn': str,
- 'description_en': str,
- 'model_code': str,
- 'engine_code': str,
- 'version': str,
- 'config_desc': str,
- 'sheet_name': str,
- }
- """
- if not model_code:
- return None
-
- model_code = model_code.strip().upper()
- trade_term = trade_term.upper()
-
- # 默认使用FCA价格列
- price_col_idx = PRICE_COL_INDEX.get(trade_term, 14)
-
- config_path = get_price_config_path()
- if not os.path.exists(config_path):
- print(f"[WARN] Price config not found: {config_path}")
- return None
-
- wb = openpyxl.load_workbook(config_path, data_only=True)
-
- for sheet_name in wb.sheetnames:
- ws = wb[sheet_name]
- for row in ws.iter_rows(min_row=2, max_row=ws.max_row, values_only=False):
- # G列是型号 (index 6)
- cell_g = row[6] if len(row) > 6 else None
- if cell_g and cell_g.value:
- # ModelCode可能包含换行符,如 "LZW5030XXYLGHUG\n国六B(RDE)"
- cell_val = str(cell_g.value).strip().upper()
- # 分割换行符取第一行作为ModelCode
- cell_model = cell_val.split('\n')[0].strip()
- if cell_model == model_code:
- # 找到匹配
- result = {
- 'model_code': model_code,
- 'sheet_name': sheet_name,
- }
-
- # B列: 市场名称
- result['description_cn'] = str(row[1].value).strip() if row[1].value else ''
- # C列: 版本
- result['version'] = str(row[2].value).strip() if row[2].value else ''
- # F列: 系别 (中英文)
- series_val = str(row[5].value).strip() if row[5].value else ''
- result['description_en'] = series_val
- # 分离F列中英文
- series_lines = [l.strip() for l in series_val.split('\n') if l.strip()]
- result['series_cn'] = series_lines[0] if series_lines else ''
- result['series_en'] = series_lines[1] if len(series_lines) > 1 else ''
- # I列: 发动机代码
- result['engine_code'] = str(row[8].value).strip() if row[8].value else ''
- # J列: 主要配置描述
- result['config_desc'] = str(row[9].value).strip() if row[9].value else ''
-
- # 价格列
- price_cell = row[price_col_idx] if len(row) > price_col_idx else None
- if price_cell and price_cell.value:
- try:
- result['unit_price_usd'] = round(float(price_cell.value), 2)
- except (ValueError, TypeError):
- result['unit_price_usd'] = None
- else:
- result['unit_price_usd'] = None
-
- wb.close()
- return result
-
- wb.close()
- return None
- def build_vehicle_description(vehicle: dict, match_result: dict = None) -> str:
- """
- 构建PI中的商品描述文本
-
- 格式示例: Wuling LZW5030XXYLGHUG, AGMC,1.999L
- """
- import re
-
- model_code = vehicle.get('model_code', '')
- engine_code = vehicle.get('engine_code', '')
-
- # 尝试从匹配结果获取排量信息
- displacement = ''
-
- # 1. 从配置描述中提取排量,如 "(1.999L)"
- if match_result and match_result.get('config_desc'):
- m = re.search(r'\(([\d.]+L)\)', match_result['config_desc'])
- if m:
- displacement = m.group(1)
-
- # 2. 从发动机代码中提取排量,如 "VR5\n(1.999L)\n5MT"
- if not displacement and match_result and match_result.get('engine_code'):
- m = re.search(r'\(([\d.]+L)\)', match_result['engine_code'])
- if m:
- displacement = m.group(1)
-
- # 3. 从版本信息推断
- if not displacement and vehicle.get('version'):
- m = re.search(r'([\d.]+L)', vehicle['version'])
- if m:
- displacement = m.group(1)
-
- # 4. 从车型名称中推断(如 "2.0L 5MT")
- if not displacement and vehicle.get('name_cn'):
- m = re.search(r'([\d.]+L)', vehicle['name_cn'])
- if m:
- displacement = m.group(1)
-
- parts = [p for p in [f'Wuling {model_code}', engine_code, displacement] if p]
- return ', '.join(parts)
- if __name__ == '__main__':
- # 测试
- result = match_vehicle('LZW5030XXYLGHUG', 'FCA')
- print(result)
-
- result2 = match_vehicle('LZW1028SPY', 'FCA')
- print(result2)
|