更新之后,我也不知道有没有问题
This commit is contained in:
parent
390eeb67af
commit
7b7d491663
21
README.md
21
README.md
@ -267,6 +267,27 @@ MIT License
|
|||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
### v1.3 (2025-07-20)
|
||||||
|
|
||||||
|
#### 功能优化
|
||||||
|
- 采购单赠品处理逻辑优化:修改了银豹采购单中赠品的处理方式
|
||||||
|
- ~~之前:赠品数量单独填写在"赠送量"列,与正常采购量分开处理~~
|
||||||
|
- ~~现在:将赠品数量合并到采购量中,赠送量列留空~~
|
||||||
|
- ~~有正常商品且有赠品的情况:采购量 = 正常商品数量 + 赠品数量,单价 = 原单价 × 正常商品数量 ÷ 总数量~~
|
||||||
|
- ~~只有赠品的情况:采购量填写赠品数量,单价为0~~
|
||||||
|
- 更新说明:经用户反馈,赠品处理逻辑已还原为原始方式,正常商品数量和赠品数量分开填写
|
||||||
|
|
||||||
|
### v1.2 (2025-07-15)
|
||||||
|
|
||||||
|
#### 功能优化
|
||||||
|
- 规格提取优化:改进了从商品名称中提取规格的逻辑,优先识别"容量*数量"格式
|
||||||
|
- 例如从"美汁源果粒橙1.8L*8瓶"能准确提取"1.8L*8"而非错误的"1.8L*1"
|
||||||
|
- 规格解析增强:优化`parse_specification`方法,能正确解析"1.8L*8"格式规格,确保准确提取包装数量
|
||||||
|
- 单位推断增强:在`extract_product_info`方法中增加新逻辑,当单位为空且有条码、规格、数量、单价时,根据规格格式(如容量*数量格式或简单数量*数量格式)自动推断单位为"件"
|
||||||
|
- 件单位处理优化:确保当设置单位为"件"时,正确触发UnitConverter单位处理逻辑,将数量乘以包装数量,单价除以包装数量,单位转为"瓶"
|
||||||
|
- 整体改进:提高了系统处理复杂格式商品名称和规格的能力,使单位转换更加准确可靠
|
||||||
|
- 规格提取逻辑修正:修复了在Excel中已有规格信息时仍会从商品名称推断规格的问题,现在系统会优先使用Excel中的数据,只有在规格为空时才尝试从商品名称推断
|
||||||
|
|
||||||
### v1.1 (2025-05-07)
|
### v1.1 (2025-05-07)
|
||||||
|
|
||||||
#### 功能更新
|
#### 功能更新
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
BIN
app/core/excel/__pycache__/validators.cpython-39.pyc
Normal file
BIN
app/core/excel/__pycache__/validators.cpython-39.pyc
Normal file
Binary file not shown.
@ -9,6 +9,12 @@ import logging
|
|||||||
from typing import Dict, Tuple, Optional, Any, List, Union
|
from typing import Dict, Tuple, Optional, Any, List, Union
|
||||||
|
|
||||||
from ..utils.log_utils import get_logger
|
from ..utils.log_utils import get_logger
|
||||||
|
from .handlers.barcode_mapper import BarcodeMapper
|
||||||
|
from .handlers.unit_converter_handlers import (
|
||||||
|
JianUnitHandler, BoxUnitHandler, TiHeUnitHandler,
|
||||||
|
GiftUnitHandler, UnitHandler
|
||||||
|
)
|
||||||
|
from .validators import ProductValidator
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@ -94,6 +100,27 @@ class UnitConverter:
|
|||||||
(r'([\d\.]+)(?:mL|毫升)[*xX×]?(\d+)?', r'\1mL*\2' if r'\2' else r'\1mL*1'),
|
(r'([\d\.]+)(?:mL|毫升)[*xX×]?(\d+)?', r'\1mL*\2' if r'\2' else r'\1mL*1'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# 初始化处理程序
|
||||||
|
self._init_handlers()
|
||||||
|
|
||||||
|
# 初始化验证器
|
||||||
|
self.validator = ProductValidator()
|
||||||
|
|
||||||
|
def _init_handlers(self):
|
||||||
|
"""
|
||||||
|
初始化各种处理程序
|
||||||
|
"""
|
||||||
|
# 创建条码处理程序
|
||||||
|
self.barcode_mapper = BarcodeMapper(self.special_barcodes)
|
||||||
|
|
||||||
|
# 创建单位处理程序列表,优先级从高到低
|
||||||
|
self.unit_handlers: List[UnitHandler] = [
|
||||||
|
GiftUnitHandler(), # 首先处理赠品,优先级最高
|
||||||
|
JianUnitHandler(), # 处理"件"单位
|
||||||
|
BoxUnitHandler(), # 处理"箱"单位
|
||||||
|
TiHeUnitHandler() # 处理"提"和"盒"单位
|
||||||
|
]
|
||||||
|
|
||||||
def extract_unit_from_quantity(self, quantity_str: str) -> Tuple[Optional[float], Optional[str]]:
|
def extract_unit_from_quantity(self, quantity_str: str) -> Tuple[Optional[float], Optional[str]]:
|
||||||
"""
|
"""
|
||||||
从数量字符串中提取单位
|
从数量字符串中提取单位
|
||||||
@ -368,103 +395,15 @@ class UnitConverter:
|
|||||||
logger.error(f"解析规格时出错: {e}")
|
logger.error(f"解析规格时出错: {e}")
|
||||||
return 1, 1, None
|
return 1, 1, None
|
||||||
|
|
||||||
def _process_standard_unit_conversion(self, product: Dict) -> Dict:
|
|
||||||
"""
|
|
||||||
处理标准单位转换(件、箱、提、盒等单位)
|
|
||||||
|
|
||||||
Args:
|
|
||||||
product: 商品信息字典
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
处理后的商品信息字典
|
|
||||||
"""
|
|
||||||
# 复制原始数据,避免修改原始字典
|
|
||||||
result = product.copy()
|
|
||||||
|
|
||||||
unit = result.get('unit', '')
|
|
||||||
quantity = result.get('quantity', 0)
|
|
||||||
price = result.get('price', 0)
|
|
||||||
specification = result.get('specification', '')
|
|
||||||
|
|
||||||
# 跳过无效数据
|
|
||||||
if not specification:
|
|
||||||
return result
|
|
||||||
|
|
||||||
# 解析规格信息
|
|
||||||
level1, level2, level3 = self.parse_specification(specification)
|
|
||||||
|
|
||||||
# "件"单位处理
|
|
||||||
if unit in ['件']:
|
|
||||||
# 计算包装数量(二级*三级,如果无三级则仅二级)
|
|
||||||
packaging_count = level2 * (level3 or 1)
|
|
||||||
|
|
||||||
# 数量×包装数量
|
|
||||||
new_quantity = quantity * packaging_count
|
|
||||||
|
|
||||||
# 单价÷包装数量
|
|
||||||
new_price = price / packaging_count if price else 0
|
|
||||||
|
|
||||||
logger.info(f"件单位处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: 件 -> 瓶")
|
|
||||||
|
|
||||||
result['quantity'] = new_quantity
|
|
||||||
result['price'] = new_price
|
|
||||||
result['unit'] = '瓶'
|
|
||||||
return result
|
|
||||||
|
|
||||||
# "箱"单位处理 - 与"件"单位处理相同
|
|
||||||
if unit in ['箱']:
|
|
||||||
# 计算包装数量
|
|
||||||
packaging_count = level2 * (level3 or 1)
|
|
||||||
|
|
||||||
# 数量×包装数量
|
|
||||||
new_quantity = quantity * packaging_count
|
|
||||||
|
|
||||||
# 单价÷包装数量
|
|
||||||
new_price = price / packaging_count if price else 0
|
|
||||||
|
|
||||||
logger.info(f"箱单位处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: 箱 -> 瓶")
|
|
||||||
|
|
||||||
result['quantity'] = new_quantity
|
|
||||||
result['price'] = new_price
|
|
||||||
result['unit'] = '瓶'
|
|
||||||
return result
|
|
||||||
|
|
||||||
# "提"和"盒"单位处理
|
|
||||||
if unit in ['提', '盒']:
|
|
||||||
# 如果是三级规格,按件处理
|
|
||||||
if level3 is not None:
|
|
||||||
# 计算包装数量 - 只乘以最后一级数量
|
|
||||||
packaging_count = level3
|
|
||||||
|
|
||||||
# 数量×包装数量
|
|
||||||
new_quantity = quantity * packaging_count
|
|
||||||
|
|
||||||
# 单价÷包装数量
|
|
||||||
new_price = price / packaging_count if price else 0
|
|
||||||
|
|
||||||
logger.info(f"提/盒单位(三级规格)处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: {unit} -> 瓶")
|
|
||||||
|
|
||||||
result['quantity'] = new_quantity
|
|
||||||
result['price'] = new_price
|
|
||||||
result['unit'] = '瓶'
|
|
||||||
else:
|
|
||||||
# 如果是二级规格,保持不变
|
|
||||||
logger.info(f"提/盒单位(二级规格)处理: 保持原样 数量: {quantity}, 单价: {price}, 单位: {unit}")
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
# 其他单位保持不变
|
|
||||||
logger.info(f"其他单位处理: 保持原样 数量: {quantity}, 单价: {price}, 单位: {unit}")
|
|
||||||
return result
|
|
||||||
|
|
||||||
def process_unit_conversion(self, product: Dict) -> Dict:
|
def process_unit_conversion(self, product: Dict) -> Dict:
|
||||||
"""
|
"""
|
||||||
处理单位转换,按照以下规则:
|
处理单位转换,按照以下规则:
|
||||||
1. 特殊条码: 优先处理特殊条码
|
1. 特殊条码: 优先处理特殊条码
|
||||||
2. "件"单位: 数量×包装数量, 单价÷包装数量, 单位转为"瓶"
|
2. 赠品处理: 对于赠品,维持数量转换但单价为0
|
||||||
3. "箱"单位: 数量×包装数量, 单价÷包装数量, 单位转为"瓶"
|
3. "件"单位: 数量×包装数量, 单价÷包装数量, 单位转为"瓶"
|
||||||
4. "提"和"盒"单位: 如果是三级规格, 按件处理; 如果是二级规格, 保持不变
|
4. "箱"单位: 数量×包装数量, 单价÷包装数量, 单位转为"瓶"
|
||||||
5. 其他单位: 保持不变
|
5. "提"和"盒"单位: 如果是三级规格, 按件处理; 如果是二级规格, 保持不变
|
||||||
|
6. 其他单位: 保持不变
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
product: 商品信息字典
|
product: 商品信息字典
|
||||||
@ -472,62 +411,40 @@ class UnitConverter:
|
|||||||
Returns:
|
Returns:
|
||||||
处理后的商品信息字典
|
处理后的商品信息字典
|
||||||
"""
|
"""
|
||||||
|
# 首先验证商品数据
|
||||||
|
product = self.validator.validate_product(product)
|
||||||
|
|
||||||
# 复制原始数据,避免修改原始字典
|
# 复制原始数据,避免修改原始字典
|
||||||
result = product.copy()
|
result = product.copy()
|
||||||
|
|
||||||
barcode = result.get('barcode', '')
|
barcode = result.get('barcode', '')
|
||||||
unit = result.get('unit', '')
|
|
||||||
quantity = result.get('quantity', 0)
|
|
||||||
price = result.get('price', 0)
|
|
||||||
specification = result.get('specification', '')
|
specification = result.get('specification', '')
|
||||||
|
|
||||||
# 跳过无效数据
|
# 跳过无效数据
|
||||||
if not barcode or not quantity:
|
if not barcode:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# 特殊条码处理
|
# 先处理条码映射
|
||||||
if barcode in self.special_barcodes:
|
result = self.barcode_mapper.map_barcode(result)
|
||||||
special_config = self.special_barcodes[barcode]
|
|
||||||
|
|
||||||
# 处理条码映射情况
|
# 如果没有规格信息,无法进行单位转换
|
||||||
if 'map_to' in special_config:
|
if not specification:
|
||||||
new_barcode = special_config['map_to']
|
# 尝试从商品名称推断规格
|
||||||
logger.info(f"条码映射: {barcode} -> {new_barcode}")
|
inferred_spec = self.infer_specification_from_name(result.get('name', ''))
|
||||||
result['barcode'] = new_barcode
|
if inferred_spec:
|
||||||
# 如果只是条码映射且没有其他特殊处理,继续执行标准单位处理
|
result['specification'] = inferred_spec
|
||||||
if len(special_config) == 2: # 只有map_to和description两个字段
|
logger.info(f"从商品名称推断规格: {result.get('name', '')} -> {inferred_spec}")
|
||||||
# 继续标准处理流程,不提前返回
|
else:
|
||||||
return self._process_standard_unit_conversion(result)
|
return result
|
||||||
|
|
||||||
multiplier = special_config.get('multiplier', 1)
|
# 解析规格信息
|
||||||
target_unit = special_config.get('target_unit', '瓶')
|
level1, level2, level3 = self.parse_specification(result.get('specification', ''))
|
||||||
|
|
||||||
# 数量乘以倍数
|
# 使用单位处理程序处理单位转换
|
||||||
new_quantity = quantity * multiplier
|
for handler in self.unit_handlers:
|
||||||
|
if handler.can_handle(result):
|
||||||
|
return handler.handle(result, level1, level2, level3)
|
||||||
|
|
||||||
# 如果有单价,单价除以倍数
|
# 没有找到适用的处理程序,保持不变
|
||||||
new_price = price / multiplier if price else 0
|
logger.info(f"其他单位处理: 保持原样 数量: {result.get('quantity', 0)}, 单价: {result.get('price', 0)}, 单位: {result.get('unit', '')}")
|
||||||
|
return result
|
||||||
# 如果有固定单价,优先使用
|
|
||||||
if 'fixed_price' in special_config:
|
|
||||||
new_price = special_config['fixed_price']
|
|
||||||
logger.info(f"特殊条码({barcode})使用固定单价: {new_price}")
|
|
||||||
|
|
||||||
# 如果有固定规格,设置规格
|
|
||||||
if 'specification' in special_config:
|
|
||||||
result['specification'] = special_config['specification']
|
|
||||||
# 解析规格以获取包装数量
|
|
||||||
package_quantity = self.parse_specification(special_config['specification'])
|
|
||||||
if package_quantity:
|
|
||||||
result['package_quantity'] = package_quantity
|
|
||||||
logger.info(f"特殊条码({barcode})使用固定规格: {special_config['specification']}, 包装数量={package_quantity}")
|
|
||||||
|
|
||||||
logger.info(f"特殊条码处理: {barcode}, 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: {unit} -> {target_unit}")
|
|
||||||
|
|
||||||
result['quantity'] = new_quantity
|
|
||||||
result['price'] = new_price
|
|
||||||
result['unit'] = target_unit
|
|
||||||
return result
|
|
||||||
|
|
||||||
# 没有特殊条码,使用标准单位处理
|
|
||||||
return self._process_standard_unit_conversion(result)
|
|
||||||
11
app/core/excel/handlers/__init__.py
Normal file
11
app/core/excel/handlers/__init__.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
"""
|
||||||
|
单位转换处理程序包
|
||||||
|
-----------------
|
||||||
|
提供单位转换和条码处理的各种处理程序
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
# 导出所有处理程序类
|
||||||
|
from .barcode_mapper import BarcodeMapper
|
||||||
|
from .unit_converter_handlers import JianUnitHandler, BoxUnitHandler, TiHeUnitHandler, GiftUnitHandler, UnitHandler
|
||||||
BIN
app/core/excel/handlers/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
app/core/excel/handlers/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
83
app/core/excel/handlers/barcode_mapper.py
Normal file
83
app/core/excel/handlers/barcode_mapper.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
"""
|
||||||
|
条码映射处理程序
|
||||||
|
-------------
|
||||||
|
处理特殊条码的映射和转换
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Dict, Optional, Any
|
||||||
|
|
||||||
|
from ...utils.log_utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BarcodeMapper:
|
||||||
|
"""
|
||||||
|
条码映射器:负责特殊条码的映射和处理
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, special_barcodes: Dict[str, Dict[str, Any]]):
|
||||||
|
"""
|
||||||
|
初始化条码映射器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
special_barcodes: 特殊条码配置字典
|
||||||
|
"""
|
||||||
|
self.special_barcodes = special_barcodes or {}
|
||||||
|
|
||||||
|
def map_barcode(self, product: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
映射商品条码,处理特殊情况
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 包含条码的商品信息字典
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的商品信息字典
|
||||||
|
"""
|
||||||
|
result = product.copy()
|
||||||
|
barcode = result.get('barcode', '')
|
||||||
|
|
||||||
|
# 如果条码不在特殊条码列表中,直接返回
|
||||||
|
if not barcode or barcode not in self.special_barcodes:
|
||||||
|
return result
|
||||||
|
|
||||||
|
special_config = self.special_barcodes[barcode]
|
||||||
|
|
||||||
|
# 处理条码映射
|
||||||
|
if 'map_to' in special_config:
|
||||||
|
new_barcode = special_config['map_to']
|
||||||
|
logger.info(f"条码映射: {barcode} -> {new_barcode}")
|
||||||
|
result['barcode'] = new_barcode
|
||||||
|
|
||||||
|
# 处理特殊倍数
|
||||||
|
if 'multiplier' in special_config:
|
||||||
|
multiplier = special_config.get('multiplier', 1)
|
||||||
|
target_unit = special_config.get('target_unit', '瓶')
|
||||||
|
|
||||||
|
# 数量乘以倍数
|
||||||
|
quantity = result.get('quantity', 0)
|
||||||
|
new_quantity = quantity * multiplier
|
||||||
|
|
||||||
|
# 单价除以倍数
|
||||||
|
price = result.get('price', 0)
|
||||||
|
new_price = price / multiplier if price else 0
|
||||||
|
|
||||||
|
# 如果有固定单价,优先使用
|
||||||
|
if 'fixed_price' in special_config:
|
||||||
|
new_price = special_config['fixed_price']
|
||||||
|
logger.info(f"特殊条码({barcode})使用固定单价: {new_price}")
|
||||||
|
|
||||||
|
# 如果有固定规格,设置规格
|
||||||
|
if 'specification' in special_config:
|
||||||
|
result['specification'] = special_config['specification']
|
||||||
|
logger.info(f"特殊条码({barcode})使用固定规格: {special_config['specification']}")
|
||||||
|
|
||||||
|
logger.info(f"特殊条码处理: {barcode}, 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: {result.get('unit', '')} -> {target_unit}")
|
||||||
|
|
||||||
|
result['quantity'] = new_quantity
|
||||||
|
result['price'] = new_price
|
||||||
|
result['unit'] = target_unit
|
||||||
|
|
||||||
|
return result
|
||||||
284
app/core/excel/handlers/unit_converter_handlers.py
Normal file
284
app/core/excel/handlers/unit_converter_handlers.py
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
"""
|
||||||
|
单位转换处理程序
|
||||||
|
-------------
|
||||||
|
处理不同单位的转换逻辑
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Dict, Optional, Any, Tuple, Protocol
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
from ...utils.log_utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class UnitHandler(ABC):
|
||||||
|
"""
|
||||||
|
单位处理器基类:定义单位处理接口
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def can_handle(self, product: Dict[str, Any]) -> bool:
|
||||||
|
"""
|
||||||
|
检查是否可以处理该商品
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否可以处理
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
处理单位转换
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
level1: 一级包装数量
|
||||||
|
level2: 二级包装数量
|
||||||
|
level3: 三级包装数量,可能为None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的商品信息字典
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class JianUnitHandler(UnitHandler):
|
||||||
|
"""
|
||||||
|
处理"件"单位的转换
|
||||||
|
"""
|
||||||
|
|
||||||
|
def can_handle(self, product: Dict[str, Any]) -> bool:
|
||||||
|
"""
|
||||||
|
检查是否可以处理该商品(单位为"件")
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否可以处理
|
||||||
|
"""
|
||||||
|
unit = product.get('unit', '')
|
||||||
|
return unit == '件'
|
||||||
|
|
||||||
|
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
处理"件"单位转换:数量×包装数量,单价÷包装数量,单位转为"瓶"
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
level1: 一级包装数量
|
||||||
|
level2: 二级包装数量
|
||||||
|
level3: 三级包装数量,可能为None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的商品信息字典
|
||||||
|
"""
|
||||||
|
result = product.copy()
|
||||||
|
|
||||||
|
quantity = result.get('quantity', 0)
|
||||||
|
price = result.get('price', 0)
|
||||||
|
|
||||||
|
# 计算包装数量(二级*三级,如果无三级则仅二级)
|
||||||
|
packaging_count = level2 * (level3 or 1)
|
||||||
|
|
||||||
|
# 数量×包装数量
|
||||||
|
new_quantity = quantity * packaging_count
|
||||||
|
|
||||||
|
# 单价÷包装数量
|
||||||
|
new_price = price / packaging_count if price else 0
|
||||||
|
|
||||||
|
logger.info(f"件单位处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: 件 -> 瓶")
|
||||||
|
|
||||||
|
result['quantity'] = new_quantity
|
||||||
|
result['price'] = new_price
|
||||||
|
result['unit'] = '瓶'
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class BoxUnitHandler(UnitHandler):
|
||||||
|
"""
|
||||||
|
处理"箱"单位的转换
|
||||||
|
"""
|
||||||
|
|
||||||
|
def can_handle(self, product: Dict[str, Any]) -> bool:
|
||||||
|
"""
|
||||||
|
检查是否可以处理该商品(单位为"箱")
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否可以处理
|
||||||
|
"""
|
||||||
|
unit = product.get('unit', '')
|
||||||
|
return unit == '箱'
|
||||||
|
|
||||||
|
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
处理"箱"单位转换:数量×包装数量,单价÷包装数量,单位转为"瓶"
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
level1: 一级包装数量
|
||||||
|
level2: 二级包装数量
|
||||||
|
level3: 三级包装数量,可能为None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的商品信息字典
|
||||||
|
"""
|
||||||
|
result = product.copy()
|
||||||
|
|
||||||
|
quantity = result.get('quantity', 0)
|
||||||
|
price = result.get('price', 0)
|
||||||
|
|
||||||
|
# 计算包装数量(二级*三级,如果无三级则仅二级)
|
||||||
|
packaging_count = level2 * (level3 or 1)
|
||||||
|
|
||||||
|
# 数量×包装数量
|
||||||
|
new_quantity = quantity * packaging_count
|
||||||
|
|
||||||
|
# 单价÷包装数量
|
||||||
|
new_price = price / packaging_count if price else 0
|
||||||
|
|
||||||
|
logger.info(f"箱单位处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: 箱 -> 瓶")
|
||||||
|
|
||||||
|
result['quantity'] = new_quantity
|
||||||
|
result['price'] = new_price
|
||||||
|
result['unit'] = '瓶'
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class TiHeUnitHandler(UnitHandler):
|
||||||
|
"""
|
||||||
|
处理"提"和"盒"单位的转换
|
||||||
|
"""
|
||||||
|
|
||||||
|
def can_handle(self, product: Dict[str, Any]) -> bool:
|
||||||
|
"""
|
||||||
|
检查是否可以处理该商品(单位为"提"或"盒")
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否可以处理
|
||||||
|
"""
|
||||||
|
unit = product.get('unit', '')
|
||||||
|
return unit in ['提', '盒']
|
||||||
|
|
||||||
|
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
处理"提"和"盒"单位转换:
|
||||||
|
- 如果是三级规格,按件处理(数量×包装数量,单价÷包装数量,单位转为"瓶")
|
||||||
|
- 如果是二级规格,保持不变
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
level1: 一级包装数量
|
||||||
|
level2: 二级包装数量
|
||||||
|
level3: 三级包装数量,可能为None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的商品信息字典
|
||||||
|
"""
|
||||||
|
result = product.copy()
|
||||||
|
|
||||||
|
quantity = result.get('quantity', 0)
|
||||||
|
price = result.get('price', 0)
|
||||||
|
unit = result.get('unit', '')
|
||||||
|
|
||||||
|
# 如果是三级规格,按件处理
|
||||||
|
if level3 is not None:
|
||||||
|
# 计算包装数量 - 只乘以最后一级数量
|
||||||
|
packaging_count = level3
|
||||||
|
|
||||||
|
# 数量×包装数量
|
||||||
|
new_quantity = quantity * packaging_count
|
||||||
|
|
||||||
|
# 单价÷包装数量
|
||||||
|
new_price = price / packaging_count if price else 0
|
||||||
|
|
||||||
|
logger.info(f"提/盒单位(三级规格)处理: 数量: {quantity} -> {new_quantity}, 单价: {price} -> {new_price}, 单位: {unit} -> 瓶")
|
||||||
|
|
||||||
|
result['quantity'] = new_quantity
|
||||||
|
result['price'] = new_price
|
||||||
|
result['unit'] = '瓶'
|
||||||
|
else:
|
||||||
|
# 如果是二级规格,保持不变
|
||||||
|
logger.info(f"提/盒单位(二级规格)处理: 保持原样 数量: {quantity}, 单价: {price}, 单位: {unit}")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class GiftUnitHandler(UnitHandler):
|
||||||
|
"""
|
||||||
|
处理赠品的特殊情况
|
||||||
|
"""
|
||||||
|
|
||||||
|
def can_handle(self, product: Dict[str, Any]) -> bool:
|
||||||
|
"""
|
||||||
|
检查是否可以处理该商品(是否为赠品)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否可以处理
|
||||||
|
"""
|
||||||
|
return product.get('is_gift', False) is True
|
||||||
|
|
||||||
|
def handle(self, product: Dict[str, Any], level1: int, level2: int, level3: Optional[int]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
处理赠品的单位转换:
|
||||||
|
- 对于件/箱单位,数量仍然需要转换,但赠品的单价保持为0
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品信息字典
|
||||||
|
level1: 一级包装数量
|
||||||
|
level2: 二级包装数量
|
||||||
|
level3: 三级包装数量,可能为None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
处理后的商品信息字典
|
||||||
|
"""
|
||||||
|
result = product.copy()
|
||||||
|
|
||||||
|
unit = result.get('unit', '')
|
||||||
|
quantity = result.get('quantity', 0)
|
||||||
|
|
||||||
|
# 根据单位类型选择适当的包装数计算
|
||||||
|
if unit in ['件', '箱']:
|
||||||
|
# 计算包装数量(二级*三级,如果无三级则仅二级)
|
||||||
|
packaging_count = level2 * (level3 or 1)
|
||||||
|
|
||||||
|
# 数量×包装数量
|
||||||
|
new_quantity = quantity * packaging_count
|
||||||
|
|
||||||
|
logger.info(f"赠品{unit}单位处理: 数量: {quantity} -> {new_quantity}, 单价: 0, 单位: {unit} -> 瓶")
|
||||||
|
|
||||||
|
result['quantity'] = new_quantity
|
||||||
|
result['unit'] = '瓶'
|
||||||
|
elif unit in ['提', '盒'] and level3 is not None:
|
||||||
|
# 对于三级规格的提/盒,类似件处理
|
||||||
|
new_quantity = quantity * level3
|
||||||
|
|
||||||
|
logger.info(f"赠品{unit}单位(三级规格)处理: 数量: {quantity} -> {new_quantity}, 单价: 0, 单位: {unit} -> 瓶")
|
||||||
|
|
||||||
|
result['quantity'] = new_quantity
|
||||||
|
result['unit'] = '瓶'
|
||||||
|
else:
|
||||||
|
# 其他情况保持不变
|
||||||
|
logger.info(f"赠品{unit}单位处理: 保持原样 数量: {quantity}, 单价: 0, 单位: {unit}")
|
||||||
|
|
||||||
|
# 确保单价为0
|
||||||
|
result['price'] = 0
|
||||||
|
|
||||||
|
return result
|
||||||
@ -295,8 +295,15 @@ class ExcelProcessor:
|
|||||||
if package_quantity:
|
if package_quantity:
|
||||||
product['package_quantity'] = package_quantity
|
product['package_quantity'] = package_quantity
|
||||||
logger.info(f"解析规格: {product['specification']} -> 包装数量={package_quantity}")
|
logger.info(f"解析规格: {product['specification']} -> 包装数量={package_quantity}")
|
||||||
|
elif column_mapping.get('specification') and not pd.isna(row[column_mapping['specification']]):
|
||||||
|
# 添加这段逻辑以处理通过列映射找到的规格列
|
||||||
|
product['specification'] = str(row[column_mapping['specification']])
|
||||||
|
package_quantity = self.parse_specification(product['specification'])
|
||||||
|
if package_quantity:
|
||||||
|
product['package_quantity'] = package_quantity
|
||||||
|
logger.info(f"从映射列解析规格: {product['specification']} -> 包装数量={package_quantity}")
|
||||||
else:
|
else:
|
||||||
# 逻辑1: 如果规格为空,尝试从商品名称推断规格
|
# 只有在无法从Excel获取规格时,才尝试从商品名称推断规格
|
||||||
if product['name']:
|
if product['name']:
|
||||||
# 特殊处理:优先检查名称中是否包含"容量*数量"格式
|
# 特殊处理:优先检查名称中是否包含"容量*数量"格式
|
||||||
container_pattern = r'.*?(\d+(?:\.\d+)?)\s*(?:ml|[mM][lL]|[lL]|升|毫升)[*×xX](\d+).*'
|
container_pattern = r'.*?(\d+(?:\.\d+)?)\s*(?:ml|[mM][lL]|[lL]|升|毫升)[*×xX](\d+).*'
|
||||||
|
|||||||
355
app/core/excel/test_converter.py
Normal file
355
app/core/excel/test_converter.py
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
"""
|
||||||
|
单位转换器测试模块
|
||||||
|
---------------
|
||||||
|
测试单位转换和条码映射逻辑
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
# 添加项目根目录到Python路径
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..')))
|
||||||
|
|
||||||
|
from app.core.excel.converter import UnitConverter
|
||||||
|
from app.core.excel.validators import ProductValidator
|
||||||
|
|
||||||
|
|
||||||
|
class TestUnitConverter(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
测试单位转换器功能
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
测试前的准备工作
|
||||||
|
"""
|
||||||
|
self.converter = UnitConverter()
|
||||||
|
|
||||||
|
def test_jian_unit_conversion(self):
|
||||||
|
"""
|
||||||
|
测试"件"单位的转换
|
||||||
|
"""
|
||||||
|
# 准备测试数据
|
||||||
|
product = {
|
||||||
|
'barcode': '6954767400129',
|
||||||
|
'name': '美汁源果粒橙1.8L*8瓶',
|
||||||
|
'specification': '1.8L*8',
|
||||||
|
'quantity': 1.0,
|
||||||
|
'unit': '件',
|
||||||
|
'price': 65.0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行转换
|
||||||
|
result = self.converter.process_unit_conversion(product)
|
||||||
|
|
||||||
|
# 验证结果
|
||||||
|
self.assertEqual(result['quantity'], 8.0)
|
||||||
|
self.assertEqual(result['price'], 8.125)
|
||||||
|
self.assertEqual(result['unit'], '瓶')
|
||||||
|
|
||||||
|
def test_box_unit_conversion(self):
|
||||||
|
"""
|
||||||
|
测试"箱"单位的转换
|
||||||
|
"""
|
||||||
|
# 准备测试数据
|
||||||
|
product = {
|
||||||
|
'barcode': '6925303721244',
|
||||||
|
'name': '统一鲜橙多2L*6瓶',
|
||||||
|
'specification': '2L*6',
|
||||||
|
'quantity': 1.0,
|
||||||
|
'unit': '箱',
|
||||||
|
'price': 43.0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行转换
|
||||||
|
result = self.converter.process_unit_conversion(product)
|
||||||
|
|
||||||
|
# 验证结果
|
||||||
|
self.assertEqual(result['quantity'], 6.0)
|
||||||
|
self.assertEqual(result['price'], 7.1666666666666667)
|
||||||
|
self.assertEqual(result['unit'], '瓶')
|
||||||
|
|
||||||
|
def test_tihe_unit_conversion_level3(self):
|
||||||
|
"""
|
||||||
|
测试"提"单位的转换(三级规格)
|
||||||
|
"""
|
||||||
|
# 准备测试数据(三级规格:1*6*4,表示1排6提,每提4瓶)
|
||||||
|
product = {
|
||||||
|
'barcode': '6921168509347',
|
||||||
|
'name': '农夫山泉550ml*24瓶',
|
||||||
|
'specification': '1*6*4',
|
||||||
|
'quantity': 2.0,
|
||||||
|
'unit': '提',
|
||||||
|
'price': 16.0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行转换
|
||||||
|
result = self.converter.process_unit_conversion(product)
|
||||||
|
|
||||||
|
# 验证结果:三级规格,提单位特殊处理,数量*最后一级
|
||||||
|
self.assertEqual(result['quantity'], 8.0) # 2提 * 4瓶/提
|
||||||
|
self.assertEqual(result['price'], 4.0) # 16元/提 ÷ 4瓶/提
|
||||||
|
self.assertEqual(result['unit'], '瓶')
|
||||||
|
|
||||||
|
def test_tihe_unit_conversion_level2(self):
|
||||||
|
"""
|
||||||
|
测试"提"单位的转换(二级规格)
|
||||||
|
"""
|
||||||
|
# 准备测试数据(二级规格:1*4,表示每件4提)
|
||||||
|
product = {
|
||||||
|
'barcode': '6921168509347',
|
||||||
|
'name': '农夫山泉550ml*4瓶',
|
||||||
|
'specification': '1*4',
|
||||||
|
'quantity': 5.0,
|
||||||
|
'unit': '提',
|
||||||
|
'price': 10.0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行转换
|
||||||
|
result = self.converter.process_unit_conversion(product)
|
||||||
|
|
||||||
|
# 验证结果:二级规格,提单位保持不变
|
||||||
|
self.assertEqual(result['quantity'], 5.0)
|
||||||
|
self.assertEqual(result['price'], 10.0)
|
||||||
|
self.assertEqual(result['unit'], '提')
|
||||||
|
|
||||||
|
def test_barcode_mapping(self):
|
||||||
|
"""
|
||||||
|
测试条码映射
|
||||||
|
"""
|
||||||
|
# 准备测试数据(使用需要被映射的条码)
|
||||||
|
product = {
|
||||||
|
'barcode': '6920584471055', # 这个条码应映射到6920584471017
|
||||||
|
'name': '测试映射条码商品',
|
||||||
|
'specification': '1*12',
|
||||||
|
'quantity': 1.0,
|
||||||
|
'unit': '件',
|
||||||
|
'price': 60.0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行转换
|
||||||
|
result = self.converter.process_unit_conversion(product)
|
||||||
|
|
||||||
|
# 验证结果:条码应该被映射
|
||||||
|
self.assertEqual(result['barcode'], '6920584471017')
|
||||||
|
self.assertEqual(result['quantity'], 12.0) # 同时处理件单位转换
|
||||||
|
self.assertEqual(result['price'], 5.0) # 60元/件 ÷ 12瓶/件
|
||||||
|
self.assertEqual(result['unit'], '瓶')
|
||||||
|
|
||||||
|
def test_special_barcode_multiplier(self):
|
||||||
|
"""
|
||||||
|
测试特殊条码的倍数处理
|
||||||
|
"""
|
||||||
|
# 准备测试数据(使用特殊条码)
|
||||||
|
product = {
|
||||||
|
'barcode': '6925019900087', # 特殊条码:数量*10,单位转瓶
|
||||||
|
'name': '特殊条码商品',
|
||||||
|
'specification': '1*10',
|
||||||
|
'quantity': 2.0,
|
||||||
|
'unit': '箱',
|
||||||
|
'price': 100.0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行转换
|
||||||
|
result = self.converter.process_unit_conversion(product)
|
||||||
|
|
||||||
|
# 验证结果:特殊条码乘数应该生效
|
||||||
|
self.assertEqual(result['quantity'], 20.0) # 2箱 * 10倍数
|
||||||
|
self.assertEqual(result['price'], 5.0) # 100元/箱 ÷ 10倍数/箱
|
||||||
|
self.assertEqual(result['unit'], '瓶')
|
||||||
|
|
||||||
|
|
||||||
|
class TestProductValidator(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
测试商品数据验证器功能
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
测试前的准备工作
|
||||||
|
"""
|
||||||
|
self.validator = ProductValidator()
|
||||||
|
|
||||||
|
def test_validate_barcode(self):
|
||||||
|
"""
|
||||||
|
测试条码验证
|
||||||
|
"""
|
||||||
|
# 测试有效条码
|
||||||
|
is_valid, barcode, error = self.validator.validate_barcode('6925303721244')
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(barcode, '6925303721244')
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试包含非数字字符的条码
|
||||||
|
is_valid, barcode, error = self.validator.validate_barcode('6925303-721244')
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(barcode, '6925303721244')
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试5开头的条码修正
|
||||||
|
is_valid, barcode, error = self.validator.validate_barcode('5925303721244')
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(barcode, '6925303721244')
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试过短的条码
|
||||||
|
is_valid, barcode, error = self.validator.validate_barcode('12345')
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(barcode, '12345')
|
||||||
|
self.assertIn("条码长度异常", error)
|
||||||
|
|
||||||
|
# 测试仓库标识
|
||||||
|
is_valid, barcode, error = self.validator.validate_barcode('仓库')
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(barcode, '仓库')
|
||||||
|
self.assertEqual(error, "条码为仓库标识")
|
||||||
|
|
||||||
|
# 测试空值
|
||||||
|
is_valid, barcode, error = self.validator.validate_barcode(None)
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(barcode, "")
|
||||||
|
self.assertEqual(error, "条码为空")
|
||||||
|
|
||||||
|
def test_validate_quantity(self):
|
||||||
|
"""
|
||||||
|
测试数量验证
|
||||||
|
"""
|
||||||
|
# 测试有效数量
|
||||||
|
is_valid, quantity, error = self.validator.validate_quantity(10)
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(quantity, 10.0)
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试字符串数量
|
||||||
|
is_valid, quantity, error = self.validator.validate_quantity("25.5")
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(quantity, 25.5)
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试带单位的数量
|
||||||
|
is_valid, quantity, error = self.validator.validate_quantity("30瓶")
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(quantity, 30.0)
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试零数量
|
||||||
|
is_valid, quantity, error = self.validator.validate_quantity(0)
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(quantity, 0.0)
|
||||||
|
self.assertIn("数量必须大于0", error)
|
||||||
|
|
||||||
|
# 测试负数量
|
||||||
|
is_valid, quantity, error = self.validator.validate_quantity(-5)
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(quantity, 0.0)
|
||||||
|
self.assertIn("数量必须大于0", error)
|
||||||
|
|
||||||
|
# 测试非数字
|
||||||
|
is_valid, quantity, error = self.validator.validate_quantity("abc")
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(quantity, 0.0)
|
||||||
|
self.assertIn("数量不包含数字", error)
|
||||||
|
|
||||||
|
# 测试空值
|
||||||
|
is_valid, quantity, error = self.validator.validate_quantity(None)
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(quantity, 0.0)
|
||||||
|
self.assertEqual(error, "数量为空")
|
||||||
|
|
||||||
|
def test_validate_price(self):
|
||||||
|
"""
|
||||||
|
测试单价验证
|
||||||
|
"""
|
||||||
|
# 测试有效单价
|
||||||
|
is_valid, price, is_gift, error = self.validator.validate_price(12.5)
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(price, 12.5)
|
||||||
|
self.assertFalse(is_gift)
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试字符串单价
|
||||||
|
is_valid, price, is_gift, error = self.validator.validate_price("8.0")
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(price, 8.0)
|
||||||
|
self.assertFalse(is_gift)
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试零单价(赠品)
|
||||||
|
is_valid, price, is_gift, error = self.validator.validate_price(0)
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(price, 0.0)
|
||||||
|
self.assertTrue(is_gift)
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试"赠品"标记
|
||||||
|
is_valid, price, is_gift, error = self.validator.validate_price("赠品")
|
||||||
|
self.assertTrue(is_valid)
|
||||||
|
self.assertEqual(price, 0.0)
|
||||||
|
self.assertTrue(is_gift)
|
||||||
|
self.assertIsNone(error)
|
||||||
|
|
||||||
|
# 测试负单价
|
||||||
|
is_valid, price, is_gift, error = self.validator.validate_price(-5)
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(price, 0.0)
|
||||||
|
self.assertTrue(is_gift)
|
||||||
|
self.assertIn("单价不能为负数", error)
|
||||||
|
|
||||||
|
# 测试空值
|
||||||
|
is_valid, price, is_gift, error = self.validator.validate_price(None)
|
||||||
|
self.assertFalse(is_valid)
|
||||||
|
self.assertEqual(price, 0.0)
|
||||||
|
self.assertTrue(is_gift)
|
||||||
|
self.assertEqual(error, "单价为空,视为赠品")
|
||||||
|
|
||||||
|
def test_validate_product(self):
|
||||||
|
"""
|
||||||
|
测试商品数据验证
|
||||||
|
"""
|
||||||
|
# 准备测试数据(有效商品)
|
||||||
|
product = {
|
||||||
|
'barcode': '6954767400129',
|
||||||
|
'name': '测试商品',
|
||||||
|
'specification': '1*12',
|
||||||
|
'quantity': 3.0,
|
||||||
|
'price': 36.0,
|
||||||
|
'unit': '件',
|
||||||
|
'is_gift': False
|
||||||
|
}
|
||||||
|
|
||||||
|
# 验证有效商品
|
||||||
|
result = self.validator.validate_product(product)
|
||||||
|
self.assertEqual(result['barcode'], '6954767400129')
|
||||||
|
self.assertEqual(result['quantity'], 3.0)
|
||||||
|
self.assertEqual(result['price'], 36.0)
|
||||||
|
self.assertFalse(result['is_gift'])
|
||||||
|
|
||||||
|
# 验证赠品商品
|
||||||
|
gift_product = product.copy()
|
||||||
|
gift_product['price'] = 0
|
||||||
|
result = self.validator.validate_product(gift_product)
|
||||||
|
self.assertEqual(result['price'], 0.0)
|
||||||
|
self.assertTrue(result['is_gift'])
|
||||||
|
|
||||||
|
# 验证需要修复的商品
|
||||||
|
invalid_product = {
|
||||||
|
'barcode': '5954767-400129', # 需要修复前缀和移除非数字
|
||||||
|
'name': '测试商品',
|
||||||
|
'specification': '1*12',
|
||||||
|
'quantity': '2件', # 需要提取数字
|
||||||
|
'price': '赠品', # 赠品标记
|
||||||
|
'unit': '件',
|
||||||
|
'is_gift': False
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self.validator.validate_product(invalid_product)
|
||||||
|
self.assertEqual(result['barcode'], '6954767400129') # 5->6,移除 '-'
|
||||||
|
self.assertEqual(result['quantity'], 2.0) # 提取数字
|
||||||
|
self.assertEqual(result['price'], 0.0) # 赠品价格为0
|
||||||
|
self.assertTrue(result['is_gift']) # 标记为赠品
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
215
app/core/excel/validators.py
Normal file
215
app/core/excel/validators.py
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
"""
|
||||||
|
数据验证器模块
|
||||||
|
----------
|
||||||
|
提供对商品数据的验证和修复功能
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import logging
|
||||||
|
from typing import Dict, Any, Optional, List, Tuple, Union
|
||||||
|
|
||||||
|
from ..utils.log_utils import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ProductValidator:
|
||||||
|
"""
|
||||||
|
商品数据验证器:验证和修复商品数据
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
初始化商品数据验证器
|
||||||
|
"""
|
||||||
|
# 仓库标识列表
|
||||||
|
self.warehouse_identifiers = ["仓库", "仓库全名", "warehouse"]
|
||||||
|
|
||||||
|
def validate_barcode(self, barcode: Any) -> Tuple[bool, str, Optional[str]]:
|
||||||
|
"""
|
||||||
|
验证并修复条码
|
||||||
|
|
||||||
|
Args:
|
||||||
|
barcode: 原始条码值
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(是否有效, 修复后的条码, 错误信息)元组
|
||||||
|
"""
|
||||||
|
error_message = None
|
||||||
|
|
||||||
|
# 处理空值
|
||||||
|
if barcode is None:
|
||||||
|
return False, "", "条码为空"
|
||||||
|
|
||||||
|
# 转为字符串
|
||||||
|
barcode_str = str(barcode).strip()
|
||||||
|
|
||||||
|
# 处理"仓库"特殊情况
|
||||||
|
if barcode_str in self.warehouse_identifiers:
|
||||||
|
return False, barcode_str, "条码为仓库标识"
|
||||||
|
|
||||||
|
# 清理条码格式(移除非数字字符)
|
||||||
|
barcode_clean = re.sub(r'\D', '', barcode_str)
|
||||||
|
|
||||||
|
# 如果清理后为空,无效
|
||||||
|
if not barcode_clean:
|
||||||
|
return False, barcode_str, "条码不包含数字"
|
||||||
|
|
||||||
|
# 对特定的错误条码进行修正(5开头改为6开头)
|
||||||
|
if len(barcode_clean) > 8 and barcode_clean.startswith('5') and not barcode_clean.startswith('53'):
|
||||||
|
original_barcode = barcode_clean
|
||||||
|
barcode_clean = '6' + barcode_clean[1:]
|
||||||
|
logger.info(f"修正条码前缀 5->6: {original_barcode} -> {barcode_clean}")
|
||||||
|
|
||||||
|
# 验证条码长度
|
||||||
|
if len(barcode_clean) < 8 or len(barcode_clean) > 13:
|
||||||
|
error_message = f"条码长度异常: {barcode_clean}, 长度={len(barcode_clean)}"
|
||||||
|
logger.warning(error_message)
|
||||||
|
return False, barcode_clean, error_message
|
||||||
|
|
||||||
|
# 验证条码是否全为数字
|
||||||
|
if not barcode_clean.isdigit():
|
||||||
|
error_message = f"条码包含非数字字符: {barcode_clean}"
|
||||||
|
logger.warning(error_message)
|
||||||
|
return False, barcode_clean, error_message
|
||||||
|
|
||||||
|
# 对于序号9的特殊情况,允许其条码格式
|
||||||
|
if barcode_clean == "5321545613":
|
||||||
|
logger.info(f"特殊条码验证通过: {barcode_clean}")
|
||||||
|
return True, barcode_clean, None
|
||||||
|
|
||||||
|
logger.debug(f"条码验证通过: {barcode_clean}")
|
||||||
|
return True, barcode_clean, None
|
||||||
|
|
||||||
|
def validate_quantity(self, quantity: Any) -> Tuple[bool, float, Optional[str]]:
|
||||||
|
"""
|
||||||
|
验证并修复数量
|
||||||
|
|
||||||
|
Args:
|
||||||
|
quantity: 原始数量值
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(是否有效, 修复后的数量, 错误信息)元组
|
||||||
|
"""
|
||||||
|
# 处理空值
|
||||||
|
if quantity is None:
|
||||||
|
return False, 0.0, "数量为空"
|
||||||
|
|
||||||
|
# 如果是字符串,尝试解析
|
||||||
|
if isinstance(quantity, str):
|
||||||
|
# 去除空白和非数字字符(保留小数点)
|
||||||
|
quantity_clean = re.sub(r'[^\d\.]', '', quantity.strip())
|
||||||
|
if not quantity_clean:
|
||||||
|
return False, 0.0, "数量不包含数字"
|
||||||
|
|
||||||
|
try:
|
||||||
|
quantity_value = float(quantity_clean)
|
||||||
|
except ValueError:
|
||||||
|
return False, 0.0, f"无法将数量 '{quantity}' 转换为数字"
|
||||||
|
else:
|
||||||
|
# 尝试直接转换
|
||||||
|
try:
|
||||||
|
quantity_value = float(quantity)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return False, 0.0, f"无法将数量 '{quantity}' 转换为数字"
|
||||||
|
|
||||||
|
# 数量必须大于0
|
||||||
|
if quantity_value <= 0:
|
||||||
|
return False, 0.0, f"数量必须大于0,当前值: {quantity_value}"
|
||||||
|
|
||||||
|
return True, quantity_value, None
|
||||||
|
|
||||||
|
def validate_price(self, price: Any) -> Tuple[bool, float, bool, Optional[str]]:
|
||||||
|
"""
|
||||||
|
验证并修复单价
|
||||||
|
|
||||||
|
Args:
|
||||||
|
price: 原始单价值
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(是否有效, 修复后的单价, 是否为赠品, 错误信息)元组
|
||||||
|
"""
|
||||||
|
# 初始化不是赠品
|
||||||
|
is_gift = False
|
||||||
|
|
||||||
|
# 处理空值
|
||||||
|
if price is None:
|
||||||
|
return False, 0.0, True, "单价为空,视为赠品"
|
||||||
|
|
||||||
|
# 如果是字符串,检查赠品标识
|
||||||
|
if isinstance(price, str):
|
||||||
|
price_str = price.strip().lower()
|
||||||
|
if price_str in ["赠品", "gift", "赠送", "0", ""]:
|
||||||
|
return True, 0.0, True, None
|
||||||
|
|
||||||
|
# 去除空白和非数字字符(保留小数点)
|
||||||
|
price_clean = re.sub(r'[^\d\.]', '', price_str)
|
||||||
|
if not price_clean:
|
||||||
|
return False, 0.0, True, "单价不包含数字,视为赠品"
|
||||||
|
|
||||||
|
try:
|
||||||
|
price_value = float(price_clean)
|
||||||
|
except ValueError:
|
||||||
|
return False, 0.0, True, f"无法将单价 '{price}' 转换为数字,视为赠品"
|
||||||
|
else:
|
||||||
|
# 尝试直接转换
|
||||||
|
try:
|
||||||
|
price_value = float(price)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return False, 0.0, True, f"无法将单价 '{price}' 转换为数字,视为赠品"
|
||||||
|
|
||||||
|
# 单价为0视为赠品
|
||||||
|
if price_value == 0:
|
||||||
|
return True, 0.0, True, None
|
||||||
|
|
||||||
|
# 单价必须大于0
|
||||||
|
if price_value < 0:
|
||||||
|
return False, 0.0, True, f"单价不能为负数: {price_value},视为赠品"
|
||||||
|
|
||||||
|
return True, price_value, False, None
|
||||||
|
|
||||||
|
def validate_product(self, product: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
验证并修复商品数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product: 商品数据字典
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
修复后的商品数据字典
|
||||||
|
"""
|
||||||
|
# 创建新字典,避免修改原始数据
|
||||||
|
validated_product = product.copy()
|
||||||
|
|
||||||
|
# 验证条码
|
||||||
|
barcode = product.get('barcode', '')
|
||||||
|
is_valid, fixed_barcode, error_msg = self.validate_barcode(barcode)
|
||||||
|
if is_valid:
|
||||||
|
validated_product['barcode'] = fixed_barcode
|
||||||
|
else:
|
||||||
|
logger.warning(f"条码验证失败: {error_msg}")
|
||||||
|
if fixed_barcode:
|
||||||
|
# 即使验证失败,但如果有修复后的条码仍然使用它
|
||||||
|
validated_product['barcode'] = fixed_barcode
|
||||||
|
|
||||||
|
# 验证数量
|
||||||
|
quantity = product.get('quantity', 0)
|
||||||
|
is_valid, fixed_quantity, error_msg = self.validate_quantity(quantity)
|
||||||
|
if is_valid:
|
||||||
|
validated_product['quantity'] = fixed_quantity
|
||||||
|
else:
|
||||||
|
logger.warning(f"数量验证失败: {error_msg}")
|
||||||
|
validated_product['quantity'] = 0.0
|
||||||
|
|
||||||
|
# 验证单价
|
||||||
|
price = product.get('price', 0)
|
||||||
|
is_valid, fixed_price, is_gift, error_msg = self.validate_price(price)
|
||||||
|
validated_product['price'] = fixed_price
|
||||||
|
|
||||||
|
# 如果单价验证结果表示为赠品,更新赠品标识
|
||||||
|
if is_gift:
|
||||||
|
validated_product['is_gift'] = True
|
||||||
|
if error_msg:
|
||||||
|
logger.info(error_msg)
|
||||||
|
|
||||||
|
return validated_product
|
||||||
@ -367,3 +367,21 @@
|
|||||||
2025-05-07 22:28:53,640 - __main__ - INFO - 发现 1 个采购单文件
|
2025-05-07 22:28:53,640 - __main__ - INFO - 发现 1 个采购单文件
|
||||||
2025-05-07 22:28:53,640 - __main__ - WARNING - 只有1个采购单文件 D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250507222846.xls,无需合并
|
2025-05-07 22:28:53,640 - __main__ - WARNING - 只有1个采购单文件 D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250507222846.xls,无需合并
|
||||||
2025-05-07 22:28:53,641 - __main__ - INFO - === 完整流程处理成功(只有一个文件,跳过合并)===
|
2025-05-07 22:28:53,641 - __main__ - INFO - === 完整流程处理成功(只有一个文件,跳过合并)===
|
||||||
|
2025-05-08 19:45:41,035 - __main__ - INFO - === 流程步骤 1: OCR识别 ===
|
||||||
|
2025-05-08 19:45:41,036 - __main__ - INFO - 批量处理所有图片
|
||||||
|
2025-05-08 19:45:48,795 - __main__ - INFO - OCR处理完成,总计: 1,成功: 1
|
||||||
|
2025-05-08 19:45:48,795 - __main__ - INFO - === 流程步骤 2: Excel处理 ===
|
||||||
|
2025-05-08 19:45:48,797 - __main__ - INFO - 处理最新的Excel文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:45:56,356 - __main__ - INFO - Excel处理成功,输出文件: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 19:45:56,357 - __main__ - INFO - === 流程步骤 3: 订单合并 ===
|
||||||
|
2025-05-08 19:45:56,358 - __main__ - INFO - 发现 1 个采购单文件
|
||||||
|
2025-05-08 19:45:56,358 - __main__ - WARNING - 只有1个采购单文件 D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls,无需合并
|
||||||
|
2025-05-08 19:45:56,358 - __main__ - INFO - === 完整流程处理成功(只有一个文件,跳过合并)===
|
||||||
|
2025-05-08 19:47:28,886 - __main__ - INFO - 处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:47:34,495 - __main__ - INFO - Excel处理成功,输出文件: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 19:51:23,190 - __main__ - INFO - 处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:51:27,459 - __main__ - INFO - Excel处理成功,输出文件: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 20:04:06,909 - __main__ - INFO - 处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 20:04:14,985 - __main__ - INFO - Excel处理成功,输出文件: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 20:46:00,701 - __main__ - INFO - 处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 20:46:07,564 - __main__ - INFO - Excel处理成功,输出文件: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
|||||||
@ -1832,3 +1832,42 @@
|
|||||||
2025-05-07 22:28:53,518 - app.core.excel.converter - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 55.0 -> 3.6666666666666665, 单位: 件 -> 瓶
|
2025-05-07 22:28:53,518 - app.core.excel.converter - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 55.0 -> 3.6666666666666665, 单位: 件 -> 瓶
|
||||||
2025-05-07 22:28:53,518 - app.core.excel.converter - INFO - 解析容量(ml)规格: 600ml*15 -> 1*15
|
2025-05-07 22:28:53,518 - app.core.excel.converter - INFO - 解析容量(ml)规格: 600ml*15 -> 1*15
|
||||||
2025-05-07 22:28:53,518 - app.core.excel.converter - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 55.0 -> 3.6666666666666665, 单位: 件 -> 瓶
|
2025-05-07 22:28:53,518 - app.core.excel.converter - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 55.0 -> 3.6666666666666665, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:45:49,632 - app.core.excel.converter - INFO - 提取规格: 外星人-维B水阳光青提500mL -> 500*None
|
||||||
|
2025-05-08 19:45:49,635 - app.core.excel.converter - INFO - 从名称推断规格(通用模式): 外星人-维B水阳光青提500mL -> 500*None
|
||||||
|
2025-05-08 19:45:49,639 - app.core.excel.converter - WARNING - 无法解析规格: 500*None,使用默认值1*1
|
||||||
|
2025-05-08 19:47:29,598 - app.core.excel.converter - INFO - 提取规格: 外星人-维B水阳光青提500mL -> 500*None
|
||||||
|
2025-05-08 19:47:29,599 - app.core.excel.converter - INFO - 从名称推断规格(通用模式): 外星人-维B水阳光青提500mL -> 500*None
|
||||||
|
2025-05-08 19:47:29,601 - app.core.excel.converter - WARNING - 无法解析规格: 500*None,使用默认值1*1
|
||||||
|
2025-05-08 19:51:24,077 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
2025-05-08 19:51:24,078 - app.core.excel.converter - INFO - 解析容量(ml)规格: 600ml*15 -> 1*15
|
||||||
|
2025-05-08 19:51:24,081 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
2025-05-08 19:51:24,086 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 19:51:24,088 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 19:51:24,089 - app.core.excel.converter - INFO - 解析容量(ml)规格: 600ml*15 -> 1*15
|
||||||
|
2025-05-08 19:51:24,104 - app.core.excel.converter - INFO - 解析容量(ml)规格: 900ml*12 -> 1*12
|
||||||
|
2025-05-08 19:51:24,106 - app.core.excel.converter - INFO - 解析容量(ml)规格: 900ml*12 -> 1*12
|
||||||
|
2025-05-08 19:51:24,106 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 19:51:24,107 - app.core.excel.converter - INFO - 解析容量(ml)规格: 480ml*15 -> 1*15
|
||||||
|
2025-05-08 19:51:24,108 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,790 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,793 - app.core.excel.converter - INFO - 解析容量(ml)规格: 600ml*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,794 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,798 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,799 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,822 - app.core.excel.converter - INFO - 解析容量(ml)规格: 600ml*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,823 - app.core.excel.converter - INFO - 解析容量(ml)规格: 900ml*12 -> 1*12
|
||||||
|
2025-05-08 20:04:07,824 - app.core.excel.converter - INFO - 解析容量(ml)规格: 900ml*12 -> 1*12
|
||||||
|
2025-05-08 20:04:07,825 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,827 - app.core.excel.converter - INFO - 解析容量(ml)规格: 480ml*15 -> 1*15
|
||||||
|
2025-05-08 20:04:07,843 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,837 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,839 - app.core.excel.converter - INFO - 解析容量(ml)规格: 600ml*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,840 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,867 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,868 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,869 - app.core.excel.converter - INFO - 解析容量(ml)规格: 600ml*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,869 - app.core.excel.converter - INFO - 解析容量(ml)规格: 900ml*12 -> 1*12
|
||||||
|
2025-05-08 20:46:01,870 - app.core.excel.converter - INFO - 解析容量(ml)规格: 900ml*12 -> 1*12
|
||||||
|
2025-05-08 20:46:01,871 - app.core.excel.converter - INFO - 解析容量(ml)规格: 400mL*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,872 - app.core.excel.converter - INFO - 解析容量(ml)规格: 480ml*15 -> 1*15
|
||||||
|
2025-05-08 20:46:01,873 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
|
||||||
|
|||||||
0
logs/app.core.excel.handlers.barcode_mapper.log
Normal file
0
logs/app.core.excel.handlers.barcode_mapper.log
Normal file
35
logs/app.core.excel.handlers.unit_converter_handlers.log
Normal file
35
logs/app.core.excel.handlers.unit_converter_handlers.log
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
2025-05-08 19:45:49,639 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 0.0 -> 0.0, 单价: 56.0 -> 56.0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:47:29,601 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 1.0, 单价: 56.0 -> 56.0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,077 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 68.0 -> 4.533333333333333, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,078 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 68.0 -> 4.533333333333333, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,082 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,086 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,089 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,090 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 30.0 -> 2.0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,105 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品件单位处理: 数量: 1.0 -> 12.0, 单价: 0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,106 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品件单位处理: 数量: 1.0 -> 12.0, 单价: 0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 19:51:24,106 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 2.0, 单价: 0, 单位: 瓶
|
||||||
|
2025-05-08 19:51:24,107 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 1.0, 单价: 0, 单位: 瓶
|
||||||
|
2025-05-08 19:51:24,108 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 9.0, 单价: 0, 单位: 瓶
|
||||||
|
2025-05-08 20:04:07,791 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 68.0 -> 4.533333333333333, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:04:07,793 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 68.0 -> 4.533333333333333, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:04:07,794 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:04:07,798 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:04:07,799 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:04:07,822 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 30.0 -> 2.0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:04:07,823 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品件单位处理: 数量: 1.0 -> 12.0, 单价: 0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:04:07,825 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品件单位处理: 数量: 1.0 -> 12.0, 单价: 0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:04:07,826 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 2.0, 单价: 0, 单位: 瓶
|
||||||
|
2025-05-08 20:04:07,827 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 1.0, 单价: 0, 单位: 瓶
|
||||||
|
2025-05-08 20:04:07,843 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 9.0, 单价: 0, 单位: 瓶
|
||||||
|
2025-05-08 20:46:01,838 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 68.0 -> 4.533333333333333, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:46:01,839 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 68.0 -> 4.533333333333333, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:46:01,840 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:46:01,867 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:46:01,868 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 56.0 -> 3.7333333333333334, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:46:01,869 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 30.0 -> 2.0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:46:01,870 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品件单位处理: 数量: 1.0 -> 12.0, 单价: 0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:46:01,870 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品件单位处理: 数量: 1.0 -> 12.0, 单价: 0, 单位: 件 -> 瓶
|
||||||
|
2025-05-08 20:46:01,871 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 2.0, 单价: 0, 单位: 瓶
|
||||||
|
2025-05-08 20:46:01,872 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 1.0, 单价: 0, 单位: 瓶
|
||||||
|
2025-05-08 20:46:03,157 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 9.0, 单价: 0, 单位: 瓶
|
||||||
@ -481,3 +481,15 @@
|
|||||||
2025-05-07 22:28:51,556 - app.core.excel.merger - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
2025-05-07 22:28:51,556 - app.core.excel.merger - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
2025-05-07 22:28:53,639 - app.core.excel.merger - INFO - 搜索目录 D:\My Documents\python\orc-order-v2\data\output 中的采购单Excel文件
|
2025-05-07 22:28:53,639 - app.core.excel.merger - INFO - 搜索目录 D:\My Documents\python\orc-order-v2\data\output 中的采购单Excel文件
|
||||||
2025-05-07 22:28:53,640 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
2025-05-07 22:28:53,640 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-05-08 19:45:41,034 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger
|
||||||
|
2025-05-08 19:45:41,035 - app.core.excel.merger - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 19:45:56,357 - app.core.excel.merger - INFO - 搜索目录 D:\My Documents\python\orc-order-v2\data\output 中的采购单Excel文件
|
||||||
|
2025-05-08 19:45:56,358 - app.core.excel.merger - INFO - 找到 1 个采购单Excel文件
|
||||||
|
2025-05-08 19:47:28,885 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger
|
||||||
|
2025-05-08 19:47:28,886 - app.core.excel.merger - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 19:51:23,189 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger
|
||||||
|
2025-05-08 19:51:23,189 - app.core.excel.merger - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 20:04:06,909 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger
|
||||||
|
2025-05-08 20:04:06,909 - app.core.excel.merger - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 20:46:00,700 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger
|
||||||
|
2025-05-08 20:46:00,701 - app.core.excel.merger - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
|||||||
@ -5374,3 +5374,382 @@ ValueError: could not convert string to float: '2\n96'
|
|||||||
2025-05-07 22:28:53,634 - app.core.excel.processor - INFO - 条码 6902538007169 处理结果:正常商品数量15.0,单价3.6666666666666665,赠品数量0
|
2025-05-07 22:28:53,634 - app.core.excel.processor - INFO - 条码 6902538007169 处理结果:正常商品数量15.0,单价3.6666666666666665,赠品数量0
|
||||||
2025-05-07 22:28:53,637 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250507222846.xls
|
2025-05-07 22:28:53,637 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250507222846.xls
|
||||||
2025-05-07 22:28:53,639 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250507222846.xls
|
2025-05-07 22:28:53,639 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250507222846.xls
|
||||||
|
2025-05-08 19:45:41,032 - app.core.excel.processor - INFO - 初始化ExcelProcessor
|
||||||
|
2025-05-08 19:45:41,034 - app.core.excel.processor - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 19:45:48,795 - app.core.excel.processor - INFO - 搜索目录 D:\My Documents\python\orc-order-v2\data\output 中的Excel文件
|
||||||
|
2025-05-08 19:45:48,797 - app.core.excel.processor - INFO - 找到最新的Excel文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:45:48,798 - app.core.excel.processor - INFO - 开始处理Excel文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:45:49,604 - app.core.excel.processor - INFO - 成功读取Excel文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250508194532.xlsx, 共 13 行
|
||||||
|
2025-05-08 19:45:49,606 - app.core.excel.processor - INFO - 找到可能的表头行: 第1行,评分: 60
|
||||||
|
2025-05-08 19:45:49,606 - app.core.excel.processor - INFO - 识别到表头在第 1 行
|
||||||
|
2025-05-08 19:45:49,623 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 12 行有效数据
|
||||||
|
2025-05-08 19:45:49,623 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
|
||||||
|
2025-05-08 19:45:49,623 - app.core.excel.processor - INFO - 使用条码列: 商品条码
|
||||||
|
2025-05-08 19:45:49,623 - app.core.excel.processor - INFO - 找到name列: 商品名称
|
||||||
|
2025-05-08 19:45:49,623 - app.core.excel.processor - INFO - 找到specification列: 规格型号
|
||||||
|
2025-05-08 19:45:49,623 - app.core.excel.processor - INFO - 找到quantity列: 数量
|
||||||
|
2025-05-08 19:45:49,624 - app.core.excel.processor - INFO - 找到unit列: 单位
|
||||||
|
2025-05-08 19:45:49,624 - app.core.excel.processor - INFO - 找到price列: 单价
|
||||||
|
2025-05-08 19:45:49,624 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品名称', 'specification': '规格型号', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
|
||||||
|
2025-05-08 19:45:49,625 - app.core.excel.processor - INFO - 是否存在规格列: False
|
||||||
|
2025-05-08 19:45:49,625 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6937003700207, 名称=外星人PRO运动恢复类-原味, 规格=, 数量=0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 19:45:49,628 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6937003706346, 名称=600ml外星人电解质西柚, 规格=, 数量=0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 19:45:49,629 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6937003706568, 名称=外星人-维B水阳光青提500mL, 规格=, 数量=0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:45:49,637 - app.core.excel.processor - INFO - 从商品名称推断规格: 外星人-维B水阳光青提500mL -> 500*None, 包装数量=None
|
||||||
|
2025-05-08 19:45:49,639 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石榴复合果蔬汁饮品, 规格=, 数量=0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:45:49,640 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6937003708166, 名称=天山爷爷新疆玉葡萄复合果汁饮品, 规格=, 数量=0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:45:49,640 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6937003703086, 名称=外星人WAVE风味水饮品淡柠檬味, 规格=, 数量=0, 单位=件, 单价=30.0
|
||||||
|
2025-05-08 19:45:49,641 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6975176784785, 名称=大柠檬冰茶, 规格=, 数量=0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 19:45:49,641 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6937003703437, 名称=大葡萄柚冰绿茶, 规格=, 数量=0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 19:45:49,879 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石复合果蔬汁饮品, 规格=, 数量=2.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:45:49,880 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6975176781777, 名称=日式可乐味苏打气泡水, 规格=, 数量=0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:45:49,882 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6975176782460, 名称=燃茶无糖茉莉花茶无糖饮料, 规格=, 数量=9.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:45:49,883 - app.core.excel.processor - INFO - 提取到 11 个商品信息
|
||||||
|
2025-05-08 19:45:49,892 - app.core.excel.processor - INFO - 开始处理11 个产品信息
|
||||||
|
2025-05-08 19:45:49,893 - app.core.excel.processor - INFO - 处理商品: 条码=6937003700207, 数量=0.0, 单价=68.0, 是否赠品=False
|
||||||
|
2025-05-08 19:45:49,893 - app.core.excel.processor - INFO - 发现正常商品:条码6937003700207, 数量=0.0, 单价=68.0
|
||||||
|
2025-05-08 19:45:49,893 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706346, 数量=0.0, 单价=68.0, 是否赠品=False
|
||||||
|
2025-05-08 19:45:49,893 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706346, 数量=0.0, 单价=68.0
|
||||||
|
2025-05-08 19:45:49,894 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706568, 数量=0.0, 单价=56.0, 是否赠品=False
|
||||||
|
2025-05-08 19:45:49,894 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706568, 数量=0.0, 单价=56.0
|
||||||
|
2025-05-08 19:45:49,894 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=0.0, 单价=56.0, 是否赠品=False
|
||||||
|
2025-05-08 19:45:49,894 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708173, 数量=0.0, 单价=56.0
|
||||||
|
2025-05-08 19:45:49,894 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708166, 数量=0.0, 单价=56.0, 是否赠品=False
|
||||||
|
2025-05-08 19:45:49,894 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708166, 数量=0.0, 单价=56.0
|
||||||
|
2025-05-08 19:45:49,895 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703086, 数量=0.0, 单价=30.0, 是否赠品=False
|
||||||
|
2025-05-08 19:45:49,895 - app.core.excel.processor - INFO - 发现正常商品:条码6937003703086, 数量=0.0, 单价=30.0
|
||||||
|
2025-05-08 19:45:49,895 - app.core.excel.processor - INFO - 处理商品: 条码=6975176784785, 数量=0.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:45:49,895 - app.core.excel.processor - INFO - 发现赠品:条码6975176784785, 数量=0.0
|
||||||
|
2025-05-08 19:45:49,895 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703437, 数量=0.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:45:49,895 - app.core.excel.processor - INFO - 发现赠品:条码6937003703437, 数量=0.0
|
||||||
|
2025-05-08 19:45:49,895 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=2.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:45:49,896 - app.core.excel.processor - INFO - 发现赠品:条码6937003708173, 数量=2.0
|
||||||
|
2025-05-08 19:45:49,896 - app.core.excel.processor - INFO - 处理商品: 条码=6975176781777, 数量=0.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:45:49,896 - app.core.excel.processor - INFO - 发现赠品:条码6975176781777, 数量=0.0
|
||||||
|
2025-05-08 19:45:49,896 - app.core.excel.processor - INFO - 处理商品: 条码=6975176782460, 数量=9.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:45:49,897 - app.core.excel.processor - INFO - 发现赠品:条码6975176782460, 数量=9.0
|
||||||
|
2025-05-08 19:45:49,897 - app.core.excel.processor - INFO - 分组后共10 个不同条码的商品
|
||||||
|
2025-05-08 19:45:49,897 - app.core.excel.processor - INFO - 条码 6937003700207 处理结果:正常商品数量0.0,单价68.0,赠品数量0
|
||||||
|
2025-05-08 19:45:49,897 - app.core.excel.processor - INFO - 条码 6937003706346 处理结果:正常商品数量0.0,单价68.0,赠品数量0
|
||||||
|
2025-05-08 19:45:49,897 - app.core.excel.processor - INFO - 条码 6937003706568 处理结果:正常商品数量0.0,单价56.0,赠品数量0
|
||||||
|
2025-05-08 19:45:49,897 - app.core.excel.processor - INFO - 条码 6937003708173 处理结果:正常商品数量0.0,单价56.0,赠品数量2.0
|
||||||
|
2025-05-08 19:45:49,898 - app.core.excel.processor - INFO - 条码 6937003708166 处理结果:正常商品数量0.0,单价56.0,赠品数量0
|
||||||
|
2025-05-08 19:45:56,348 - app.core.excel.processor - INFO - 条码 6937003703086 处理结果:正常商品数量0.0,单价30.0,赠品数量0
|
||||||
|
2025-05-08 19:45:56,348 - app.core.excel.processor - INFO - 条码 6975176784785 处理结果:只有赠品,数量=0.0
|
||||||
|
2025-05-08 19:45:56,348 - app.core.excel.processor - INFO - 条码 6937003703437 处理结果:只有赠品,数量=0.0
|
||||||
|
2025-05-08 19:45:56,348 - app.core.excel.processor - INFO - 条码 6975176781777 处理结果:只有赠品,数量=0.0
|
||||||
|
2025-05-08 19:45:56,348 - app.core.excel.processor - INFO - 条码 6975176782460 处理结果:只有赠品,数量=9.0
|
||||||
|
2025-05-08 19:45:56,349 - app.core.excel.processor - INFO - 条码 6937003708173 填充:采购量=0.0,赠品数量2.0
|
||||||
|
2025-05-08 19:45:56,349 - app.core.excel.processor - INFO - 条码 6975176784785 填充:仅有赠品,采购量=0,赠品数量=0.0
|
||||||
|
2025-05-08 19:45:56,349 - app.core.excel.processor - INFO - 条码 6937003703437 填充:仅有赠品,采购量=0,赠品数量=0.0
|
||||||
|
2025-05-08 19:45:56,349 - app.core.excel.processor - INFO - 条码 6975176781777 填充:仅有赠品,采购量=0,赠品数量=0.0
|
||||||
|
2025-05-08 19:45:56,349 - app.core.excel.processor - INFO - 条码 6975176782460 填充:仅有赠品,采购量=0,赠品数量=9.0
|
||||||
|
2025-05-08 19:45:56,354 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 19:45:56,356 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 19:47:28,884 - app.core.excel.processor - INFO - 初始化ExcelProcessor
|
||||||
|
2025-05-08 19:47:28,885 - app.core.excel.processor - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 19:47:28,886 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:47:29,546 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx, 共 13 行
|
||||||
|
2025-05-08 19:47:29,551 - app.core.excel.processor - INFO - 找到可能的表头行: 第1行,评分: 60
|
||||||
|
2025-05-08 19:47:29,551 - app.core.excel.processor - INFO - 识别到表头在第 1 行
|
||||||
|
2025-05-08 19:47:29,589 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 12 行有效数据
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 使用条码列: 商品条码
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 找到name列: 商品名称
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 找到specification列: 规格型号
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 找到quantity列: 数量
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 找到unit列: 单位
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 找到price列: 单价
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品名称', 'specification': '规格型号', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
|
||||||
|
2025-05-08 19:47:29,590 - app.core.excel.processor - INFO - 是否存在规格列: False
|
||||||
|
2025-05-08 19:47:29,591 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6937003700207, 名称=外星人PRO运动恢复类-原味, 规格=, 数量=1.0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 19:47:29,597 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6937003706346, 名称=600ml外星人电解质西柚, 规格=, 数量=1.0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 19:47:29,598 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6937003706568, 名称=外星人-维B水阳光青提500mL, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:47:29,600 - app.core.excel.processor - INFO - 从商品名称推断规格: 外星人-维B水阳光青提500mL -> 500*None, 包装数量=None
|
||||||
|
2025-05-08 19:47:29,602 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石榴复合果蔬汁饮品, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:47:29,602 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6937003708166, 名称=天山爷爷新疆玉葡萄复合果汁饮品, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:47:29,602 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6937003703086, 名称=外星人WAVE风味水饮品淡柠檬味, 规格=, 数量=1.0, 单位=件, 单价=30.0
|
||||||
|
2025-05-08 19:47:29,603 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6975176784785, 名称=大柠檬冰茶, 规格=, 数量=1.0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 19:47:29,603 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6937003703437, 名称=大葡萄柚冰绿茶, 规格=, 数量=1.0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 19:47:29,603 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石复合果蔬汁饮品, 规格=, 数量=2.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:47:29,604 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6975176781777, 名称=日式可乐味苏打气泡水, 规格=, 数量=1.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:47:29,604 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6975176782460, 名称=燃茶无糖茉莉花茶无糖饮料, 规格=, 数量=9.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:47:29,604 - app.core.excel.processor - INFO - 提取到 11 个商品信息
|
||||||
|
2025-05-08 19:47:29,616 - app.core.excel.processor - INFO - 开始处理11 个产品信息
|
||||||
|
2025-05-08 19:47:29,616 - app.core.excel.processor - INFO - 处理商品: 条码=6937003700207, 数量=1.0, 单价=68.0, 是否赠品=False
|
||||||
|
2025-05-08 19:47:29,616 - app.core.excel.processor - INFO - 发现正常商品:条码6937003700207, 数量=1.0, 单价=68.0
|
||||||
|
2025-05-08 19:47:29,617 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706346, 数量=1.0, 单价=68.0, 是否赠品=False
|
||||||
|
2025-05-08 19:47:29,617 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706346, 数量=1.0, 单价=68.0
|
||||||
|
2025-05-08 19:47:29,617 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706568, 数量=1.0, 单价=56.0, 是否赠品=False
|
||||||
|
2025-05-08 19:47:29,673 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706568, 数量=1.0, 单价=56.0
|
||||||
|
2025-05-08 19:47:29,673 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=1.0, 单价=56.0, 是否赠品=False
|
||||||
|
2025-05-08 19:47:29,673 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708173, 数量=1.0, 单价=56.0
|
||||||
|
2025-05-08 19:47:29,673 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708166, 数量=1.0, 单价=56.0, 是否赠品=False
|
||||||
|
2025-05-08 19:47:29,674 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708166, 数量=1.0, 单价=56.0
|
||||||
|
2025-05-08 19:47:29,674 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703086, 数量=1.0, 单价=30.0, 是否赠品=False
|
||||||
|
2025-05-08 19:47:29,674 - app.core.excel.processor - INFO - 发现正常商品:条码6937003703086, 数量=1.0, 单价=30.0
|
||||||
|
2025-05-08 19:47:29,674 - app.core.excel.processor - INFO - 处理商品: 条码=6975176784785, 数量=1.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:47:29,674 - app.core.excel.processor - INFO - 发现赠品:条码6975176784785, 数量=1.0
|
||||||
|
2025-05-08 19:47:29,674 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703437, 数量=1.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:47:29,674 - app.core.excel.processor - INFO - 发现赠品:条码6937003703437, 数量=1.0
|
||||||
|
2025-05-08 19:47:29,674 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=2.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 发现赠品:条码6937003708173, 数量=2.0
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 处理商品: 条码=6975176781777, 数量=1.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 发现赠品:条码6975176781777, 数量=1.0
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 处理商品: 条码=6975176782460, 数量=9.0, 单价=0.0, 是否赠品=True
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 发现赠品:条码6975176782460, 数量=9.0
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 分组后共10 个不同条码的商品
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 条码 6937003700207 处理结果:正常商品数量1.0,单价68.0,赠品数量0
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 条码 6937003706346 处理结果:正常商品数量1.0,单价68.0,赠品数量0
|
||||||
|
2025-05-08 19:47:29,675 - app.core.excel.processor - INFO - 条码 6937003706568 处理结果:正常商品数量1.0,单价56.0,赠品数量0
|
||||||
|
2025-05-08 19:47:29,676 - app.core.excel.processor - INFO - 条码 6937003708173 处理结果:正常商品数量1.0,单价56.0,赠品数量2.0
|
||||||
|
2025-05-08 19:47:29,676 - app.core.excel.processor - INFO - 条码 6937003708166 处理结果:正常商品数量1.0,单价56.0,赠品数量0
|
||||||
|
2025-05-08 19:47:29,676 - app.core.excel.processor - INFO - 条码 6937003703086 处理结果:正常商品数量1.0,单价30.0,赠品数量0
|
||||||
|
2025-05-08 19:47:29,676 - app.core.excel.processor - INFO - 条码 6975176784785 处理结果:只有赠品,数量=1.0
|
||||||
|
2025-05-08 19:47:29,676 - app.core.excel.processor - INFO - 条码 6937003703437 处理结果:只有赠品,数量=1.0
|
||||||
|
2025-05-08 19:47:29,676 - app.core.excel.processor - INFO - 条码 6975176781777 处理结果:只有赠品,数量=1.0
|
||||||
|
2025-05-08 19:47:29,676 - app.core.excel.processor - INFO - 条码 6975176782460 处理结果:只有赠品,数量=9.0
|
||||||
|
2025-05-08 19:47:29,677 - app.core.excel.processor - INFO - 条码 6937003708173 填充:采购量=1.0,赠品数量2.0
|
||||||
|
2025-05-08 19:47:29,677 - app.core.excel.processor - INFO - 条码 6975176784785 填充:仅有赠品,采购量=0,赠品数量=1.0
|
||||||
|
2025-05-08 19:47:29,677 - app.core.excel.processor - INFO - 条码 6937003703437 填充:仅有赠品,采购量=0,赠品数量=1.0
|
||||||
|
2025-05-08 19:47:29,677 - app.core.excel.processor - INFO - 条码 6975176781777 填充:仅有赠品,采购量=0,赠品数量=1.0
|
||||||
|
2025-05-08 19:47:29,677 - app.core.excel.processor - INFO - 条码 6975176782460 填充:仅有赠品,采购量=0,赠品数量=9.0
|
||||||
|
2025-05-08 19:47:29,681 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 19:47:29,683 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 19:51:23,178 - app.core.excel.processor - INFO - 初始化ExcelProcessor
|
||||||
|
2025-05-08 19:51:23,188 - app.core.excel.processor - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 19:51:23,190 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:51:24,003 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx, 共 13 行
|
||||||
|
2025-05-08 19:51:24,008 - app.core.excel.processor - INFO - 找到可能的表头行: 第1行,评分: 60
|
||||||
|
2025-05-08 19:51:24,008 - app.core.excel.processor - INFO - 识别到表头在第 1 行
|
||||||
|
2025-05-08 19:51:24,060 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 12 行有效数据
|
||||||
|
2025-05-08 19:51:24,060 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
|
||||||
|
2025-05-08 19:51:24,061 - app.core.excel.processor - INFO - 使用条码列: 商品条码
|
||||||
|
2025-05-08 19:51:24,061 - app.core.excel.processor - INFO - 找到name列: 商品名称
|
||||||
|
2025-05-08 19:51:24,061 - app.core.excel.processor - INFO - 找到specification列: 规格型号
|
||||||
|
2025-05-08 19:51:24,061 - app.core.excel.processor - INFO - 找到quantity列: 数量
|
||||||
|
2025-05-08 19:51:24,061 - app.core.excel.processor - INFO - 找到unit列: 单位
|
||||||
|
2025-05-08 19:51:24,061 - app.core.excel.processor - INFO - 找到price列: 单价
|
||||||
|
2025-05-08 19:51:24,061 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品名称', 'specification': '规格型号', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
|
||||||
|
2025-05-08 19:51:24,061 - app.core.excel.processor - INFO - 是否存在规格列: False
|
||||||
|
2025-05-08 19:51:24,075 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6937003700207, 名称=外星人PRO运动恢复类-原味, 规格=, 数量=1.0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 19:51:24,076 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 19:51:24,077 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6937003706346, 名称=600ml外星人电解质西柚, 规格=, 数量=1.0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 19:51:24,078 - app.core.excel.processor - INFO - 从映射列解析规格: 600ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 19:51:24,081 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6937003706568, 名称=外星人-维B水阳光青提500mL, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:51:24,081 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 19:51:24,083 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石榴复合果蔬汁饮品, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:51:24,088 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6937003708166, 名称=天山爷爷新疆玉葡萄复合果汁饮品, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 19:51:24,089 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6937003703086, 名称=外星人WAVE风味水饮品淡柠檬味, 规格=, 数量=1.0, 单位=件, 单价=30.0
|
||||||
|
2025-05-08 19:51:24,089 - app.core.excel.processor - INFO - 从映射列解析规格: 600ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 19:51:24,090 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6975176784785, 名称=大柠檬冰茶, 规格=, 数量=1.0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 19:51:24,104 - app.core.excel.processor - INFO - 从映射列解析规格: 900ml*12 -> 包装数量=12
|
||||||
|
2025-05-08 19:51:24,105 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6937003703437, 名称=大葡萄柚冰绿茶, 规格=, 数量=1.0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 19:51:24,105 - app.core.excel.processor - INFO - 从映射列解析规格: 900ml*12 -> 包装数量=12
|
||||||
|
2025-05-08 19:51:24,106 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石复合果蔬汁饮品, 规格=, 数量=2.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:51:24,107 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6975176781777, 名称=日式可乐味苏打气泡水, 规格=, 数量=1.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:51:24,107 - app.core.excel.processor - INFO - 从映射列解析规格: 480ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 19:51:24,108 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6975176782460, 名称=燃茶无糖茉莉花茶无糖饮料, 规格=, 数量=9.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 19:51:24,108 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 19:51:24,109 - app.core.excel.processor - INFO - 提取到 11 个商品信息
|
||||||
|
2025-05-08 19:51:24,122 - app.core.excel.processor - INFO - 开始处理11 个产品信息
|
||||||
|
2025-05-08 19:51:24,122 - app.core.excel.processor - INFO - 处理商品: 条码=6937003700207, 数量=15.0, 单价=4.533333333333333, 是否赠品=False
|
||||||
|
2025-05-08 19:51:24,122 - app.core.excel.processor - INFO - 发现正常商品:条码6937003700207, 数量=15.0, 单价=4.533333333333333
|
||||||
|
2025-05-08 19:51:24,123 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706346, 数量=15.0, 单价=4.533333333333333, 是否赠品=False
|
||||||
|
2025-05-08 19:51:24,123 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706346, 数量=15.0, 单价=4.533333333333333
|
||||||
|
2025-05-08 19:51:24,123 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706568, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 19:51:24,123 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706568, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 19:51:24,123 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 19:51:24,123 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708173, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 19:51:24,123 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708166, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 19:51:24,124 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708166, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 19:51:24,124 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703086, 数量=15.0, 单价=2.0, 是否赠品=False
|
||||||
|
2025-05-08 19:51:24,124 - app.core.excel.processor - INFO - 发现正常商品:条码6937003703086, 数量=15.0, 单价=2.0
|
||||||
|
2025-05-08 19:51:24,124 - app.core.excel.processor - INFO - 处理商品: 条码=6975176784785, 数量=12.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 19:51:27,449 - app.core.excel.processor - INFO - 发现赠品:条码6975176784785, 数量=12.0
|
||||||
|
2025-05-08 19:51:27,450 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703437, 数量=12.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 19:51:27,450 - app.core.excel.processor - INFO - 发现赠品:条码6937003703437, 数量=12.0
|
||||||
|
2025-05-08 19:51:27,450 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=2.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 19:51:27,450 - app.core.excel.processor - INFO - 发现赠品:条码6937003708173, 数量=2.0
|
||||||
|
2025-05-08 19:51:27,450 - app.core.excel.processor - INFO - 处理商品: 条码=6975176781777, 数量=1.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 19:51:27,450 - app.core.excel.processor - INFO - 发现赠品:条码6975176781777, 数量=1.0
|
||||||
|
2025-05-08 19:51:27,451 - app.core.excel.processor - INFO - 处理商品: 条码=6975176782460, 数量=9.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 19:51:27,451 - app.core.excel.processor - INFO - 发现赠品:条码6975176782460, 数量=9.0
|
||||||
|
2025-05-08 19:51:27,451 - app.core.excel.processor - INFO - 分组后共10 个不同条码的商品
|
||||||
|
2025-05-08 19:51:27,451 - app.core.excel.processor - INFO - 条码 6937003700207 处理结果:正常商品数量15.0,单价4.533333333333333,赠品数量0
|
||||||
|
2025-05-08 19:51:27,451 - app.core.excel.processor - INFO - 条码 6937003706346 处理结果:正常商品数量15.0,单价4.533333333333333,赠品数量0
|
||||||
|
2025-05-08 19:51:27,452 - app.core.excel.processor - INFO - 条码 6937003706568 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量0
|
||||||
|
2025-05-08 19:51:27,452 - app.core.excel.processor - INFO - 条码 6937003708173 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量2.0
|
||||||
|
2025-05-08 19:51:27,452 - app.core.excel.processor - INFO - 条码 6937003708166 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量0
|
||||||
|
2025-05-08 19:51:27,452 - app.core.excel.processor - INFO - 条码 6937003703086 处理结果:正常商品数量15.0,单价2.0,赠品数量0
|
||||||
|
2025-05-08 19:51:27,452 - app.core.excel.processor - INFO - 条码 6975176784785 处理结果:只有赠品,数量=12.0
|
||||||
|
2025-05-08 19:51:27,452 - app.core.excel.processor - INFO - 条码 6937003703437 处理结果:只有赠品,数量=12.0
|
||||||
|
2025-05-08 19:51:27,452 - app.core.excel.processor - INFO - 条码 6975176781777 处理结果:只有赠品,数量=1.0
|
||||||
|
2025-05-08 19:51:27,452 - app.core.excel.processor - INFO - 条码 6975176782460 处理结果:只有赠品,数量=9.0
|
||||||
|
2025-05-08 19:51:27,453 - app.core.excel.processor - INFO - 条码 6937003708173 填充:采购量=15.0,赠品数量2.0
|
||||||
|
2025-05-08 19:51:27,453 - app.core.excel.processor - INFO - 条码 6975176784785 填充:仅有赠品,采购量=0,赠品数量=12.0
|
||||||
|
2025-05-08 19:51:27,453 - app.core.excel.processor - INFO - 条码 6937003703437 填充:仅有赠品,采购量=0,赠品数量=12.0
|
||||||
|
2025-05-08 19:51:27,453 - app.core.excel.processor - INFO - 条码 6975176781777 填充:仅有赠品,采购量=0,赠品数量=1.0
|
||||||
|
2025-05-08 19:51:27,453 - app.core.excel.processor - INFO - 条码 6975176782460 填充:仅有赠品,采购量=0,赠品数量=9.0
|
||||||
|
2025-05-08 19:51:27,457 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 19:51:27,459 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 20:04:06,908 - app.core.excel.processor - INFO - 初始化ExcelProcessor
|
||||||
|
2025-05-08 20:04:06,908 - app.core.excel.processor - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 20:04:06,910 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 20:04:07,659 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx, 共 13 行
|
||||||
|
2025-05-08 20:04:07,674 - app.core.excel.processor - INFO - 找到可能的表头行: 第1行,评分: 60
|
||||||
|
2025-05-08 20:04:07,674 - app.core.excel.processor - INFO - 识别到表头在第 1 行
|
||||||
|
2025-05-08 20:04:07,785 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 12 行有效数据
|
||||||
|
2025-05-08 20:04:07,786 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
|
||||||
|
2025-05-08 20:04:07,786 - app.core.excel.processor - INFO - 使用条码列: 商品条码
|
||||||
|
2025-05-08 20:04:07,786 - app.core.excel.processor - INFO - 找到name列: 商品名称
|
||||||
|
2025-05-08 20:04:07,786 - app.core.excel.processor - INFO - 找到specification列: 规格型号
|
||||||
|
2025-05-08 20:04:07,786 - app.core.excel.processor - INFO - 找到quantity列: 数量
|
||||||
|
2025-05-08 20:04:07,787 - app.core.excel.processor - INFO - 找到unit列: 单位
|
||||||
|
2025-05-08 20:04:07,787 - app.core.excel.processor - INFO - 找到price列: 单价
|
||||||
|
2025-05-08 20:04:07,787 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品名称', 'specification': '规格型号', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
|
||||||
|
2025-05-08 20:04:07,787 - app.core.excel.processor - INFO - 是否存在规格列: False
|
||||||
|
2025-05-08 20:04:07,788 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6937003700207, 名称=外星人PRO运动恢复类-原味, 规格=, 数量=1.0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 20:04:07,789 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:04:07,792 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6937003706346, 名称=600ml外星人电解质西柚, 规格=, 数量=1.0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 20:04:07,792 - app.core.excel.processor - INFO - 从映射列解析规格: 600ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:04:07,793 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6937003706568, 名称=外星人-维B水阳光青提500mL, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 20:04:07,794 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:04:07,796 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石榴复合果蔬汁饮品, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 20:04:07,799 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6937003708166, 名称=天山爷爷新疆玉葡萄复合果汁饮品, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 20:04:07,818 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6937003703086, 名称=外星人WAVE风味水饮品淡柠檬味, 规格=, 数量=1.0, 单位=件, 单价=30.0
|
||||||
|
2025-05-08 20:04:07,821 - app.core.excel.processor - INFO - 从映射列解析规格: 600ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:04:07,822 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6975176784785, 名称=大柠檬冰茶, 规格=, 数量=1.0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 20:04:07,823 - app.core.excel.processor - INFO - 从映射列解析规格: 900ml*12 -> 包装数量=12
|
||||||
|
2025-05-08 20:04:07,824 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6937003703437, 名称=大葡萄柚冰绿茶, 规格=, 数量=1.0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 20:04:07,824 - app.core.excel.processor - INFO - 从映射列解析规格: 900ml*12 -> 包装数量=12
|
||||||
|
2025-05-08 20:04:07,825 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石复合果蔬汁饮品, 规格=, 数量=2.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 20:04:07,826 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6975176781777, 名称=日式可乐味苏打气泡水, 规格=, 数量=1.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 20:04:07,826 - app.core.excel.processor - INFO - 从映射列解析规格: 480ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:04:07,827 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6975176782460, 名称=燃茶无糖茉莉花茶无糖饮料, 规格=, 数量=9.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 20:04:07,842 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:04:07,844 - app.core.excel.processor - INFO - 提取到 11 个商品信息
|
||||||
|
2025-05-08 20:04:07,872 - app.core.excel.processor - INFO - 开始处理11 个产品信息
|
||||||
|
2025-05-08 20:04:07,872 - app.core.excel.processor - INFO - 处理商品: 条码=6937003700207, 数量=15.0, 单价=4.533333333333333, 是否赠品=False
|
||||||
|
2025-05-08 20:04:07,873 - app.core.excel.processor - INFO - 发现正常商品:条码6937003700207, 数量=15.0, 单价=4.533333333333333
|
||||||
|
2025-05-08 20:04:07,873 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706346, 数量=15.0, 单价=4.533333333333333, 是否赠品=False
|
||||||
|
2025-05-08 20:04:07,873 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706346, 数量=15.0, 单价=4.533333333333333
|
||||||
|
2025-05-08 20:04:07,873 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706568, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 20:04:07,873 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706568, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 20:04:07,873 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 20:04:07,873 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708173, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 20:04:07,874 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708166, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 20:04:10,344 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708166, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 20:04:10,344 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703086, 数量=15.0, 单价=2.0, 是否赠品=False
|
||||||
|
2025-05-08 20:04:10,344 - app.core.excel.processor - INFO - 发现正常商品:条码6937003703086, 数量=15.0, 单价=2.0
|
||||||
|
2025-05-08 20:04:10,344 - app.core.excel.processor - INFO - 处理商品: 条码=6975176784785, 数量=12.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 发现赠品:条码6975176784785, 数量=12.0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703437, 数量=12.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 发现赠品:条码6937003703437, 数量=12.0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=2.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 发现赠品:条码6937003708173, 数量=2.0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 处理商品: 条码=6975176781777, 数量=1.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 发现赠品:条码6975176781777, 数量=1.0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 处理商品: 条码=6975176782460, 数量=9.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 发现赠品:条码6975176782460, 数量=9.0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 分组后共10 个不同条码的商品
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 条码 6937003700207 处理结果:正常商品数量15.0,单价4.533333333333333,赠品数量0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 条码 6937003706346 处理结果:正常商品数量15.0,单价4.533333333333333,赠品数量0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 条码 6937003706568 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 条码 6937003708173 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量2.0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 条码 6937003708166 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量0
|
||||||
|
2025-05-08 20:04:10,345 - app.core.excel.processor - INFO - 条码 6937003703086 处理结果:正常商品数量15.0,单价2.0,赠品数量0
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6975176784785 处理结果:只有赠品,数量=12.0
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6937003703437 处理结果:只有赠品,数量=12.0
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6975176781777 处理结果:只有赠品,数量=1.0
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6975176782460 处理结果:只有赠品,数量=9.0
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6937003700207 填充:采购量=15.0(原商品15.0+赠品0),单价=4.533333333333333
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6937003706346 填充:采购量=15.0(原商品15.0+赠品0),单价=4.533333333333333
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6937003706568 填充:采购量=15.0(原商品15.0+赠品0),单价=3.7333333333333334
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6937003708173 单价调整: 原价=3.7333333333333334, 新价=3.2941176470588234 (包含赠品后重新计算)
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6937003708173 填充:采购量=17.0(原商品15.0+赠品2.0),单价=3.2941176470588234
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6937003708166 填充:采购量=15.0(原商品15.0+赠品0),单价=3.7333333333333334
|
||||||
|
2025-05-08 20:04:10,346 - app.core.excel.processor - INFO - 条码 6937003703086 填充:采购量=15.0(原商品15.0+赠品0),单价=2.0
|
||||||
|
2025-05-08 20:04:10,347 - app.core.excel.processor - INFO - 条码 6975176784785 填充:仅有赠品,采购量=12.0,单价=0
|
||||||
|
2025-05-08 20:04:10,347 - app.core.excel.processor - INFO - 条码 6937003703437 填充:仅有赠品,采购量=12.0,单价=0
|
||||||
|
2025-05-08 20:04:10,347 - app.core.excel.processor - INFO - 条码 6975176781777 填充:仅有赠品,采购量=1.0,单价=0
|
||||||
|
2025-05-08 20:04:14,980 - app.core.excel.processor - INFO - 条码 6975176782460 填充:仅有赠品,采购量=9.0,单价=0
|
||||||
|
2025-05-08 20:04:14,983 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 20:04:14,985 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 20:46:00,697 - app.core.excel.processor - INFO - 初始化ExcelProcessor
|
||||||
|
2025-05-08 20:46:00,700 - app.core.excel.processor - INFO - 初始化完成,模板文件: templates\银豹-采购单模板.xls
|
||||||
|
2025-05-08 20:46:00,750 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 20:46:01,732 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx, 共 13 行
|
||||||
|
2025-05-08 20:46:01,737 - app.core.excel.processor - INFO - 找到可能的表头行: 第1行,评分: 60
|
||||||
|
2025-05-08 20:46:01,737 - app.core.excel.processor - INFO - 识别到表头在第 1 行
|
||||||
|
2025-05-08 20:46:01,833 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 12 行有效数据
|
||||||
|
2025-05-08 20:46:01,833 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
|
||||||
|
2025-05-08 20:46:01,834 - app.core.excel.processor - INFO - 使用条码列: 商品条码
|
||||||
|
2025-05-08 20:46:01,834 - app.core.excel.processor - INFO - 找到name列: 商品名称
|
||||||
|
2025-05-08 20:46:01,834 - app.core.excel.processor - INFO - 找到specification列: 规格型号
|
||||||
|
2025-05-08 20:46:01,834 - app.core.excel.processor - INFO - 找到quantity列: 数量
|
||||||
|
2025-05-08 20:46:01,834 - app.core.excel.processor - INFO - 找到unit列: 单位
|
||||||
|
2025-05-08 20:46:01,834 - app.core.excel.processor - INFO - 找到price列: 单价
|
||||||
|
2025-05-08 20:46:01,835 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品名称', 'specification': '规格型号', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
|
||||||
|
2025-05-08 20:46:01,835 - app.core.excel.processor - INFO - 是否存在规格列: False
|
||||||
|
2025-05-08 20:46:01,836 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6937003700207, 名称=外星人PRO运动恢复类-原味, 规格=, 数量=1.0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 20:46:01,836 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:46:01,838 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6937003706346, 名称=600ml外星人电解质西柚, 规格=, 数量=1.0, 单位=件, 单价=68.0
|
||||||
|
2025-05-08 20:46:01,838 - app.core.excel.processor - INFO - 从映射列解析规格: 600ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:46:01,840 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6937003706568, 名称=外星人-维B水阳光青提500mL, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 20:46:01,840 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:46:01,859 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石榴复合果蔬汁饮品, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 20:46:01,868 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6937003708166, 名称=天山爷爷新疆玉葡萄复合果汁饮品, 规格=, 数量=1.0, 单位=件, 单价=56.0
|
||||||
|
2025-05-08 20:46:01,868 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6937003703086, 名称=外星人WAVE风味水饮品淡柠檬味, 规格=, 数量=1.0, 单位=件, 单价=30.0
|
||||||
|
2025-05-08 20:46:01,868 - app.core.excel.processor - INFO - 从映射列解析规格: 600ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:46:01,869 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6975176784785, 名称=大柠檬冰茶, 规格=, 数量=1.0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 20:46:01,869 - app.core.excel.processor - INFO - 从映射列解析规格: 900ml*12 -> 包装数量=12
|
||||||
|
2025-05-08 20:46:01,870 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6937003703437, 名称=大葡萄柚冰绿茶, 规格=, 数量=1.0, 单位=件, 单价=0.0
|
||||||
|
2025-05-08 20:46:01,870 - app.core.excel.processor - INFO - 从映射列解析规格: 900ml*12 -> 包装数量=12
|
||||||
|
2025-05-08 20:46:01,871 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6937003708173, 名称=天山爷爷新疆甜石复合果蔬汁饮品, 规格=, 数量=2.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 20:46:01,872 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6975176781777, 名称=日式可乐味苏打气泡水, 规格=, 数量=1.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 20:46:01,872 - app.core.excel.processor - INFO - 从映射列解析规格: 480ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:46:01,872 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6975176782460, 名称=燃茶无糖茉莉花茶无糖饮料, 规格=, 数量=9.0, 单位=瓶, 单价=0.0
|
||||||
|
2025-05-08 20:46:01,872 - app.core.excel.processor - INFO - 从映射列解析规格: 500ml*15 -> 包装数量=15
|
||||||
|
2025-05-08 20:46:03,157 - app.core.excel.processor - INFO - 提取到 11 个商品信息
|
||||||
|
2025-05-08 20:46:03,171 - app.core.excel.processor - INFO - 开始处理11 个产品信息
|
||||||
|
2025-05-08 20:46:03,171 - app.core.excel.processor - INFO - 处理商品: 条码=6937003700207, 数量=15.0, 单价=4.533333333333333, 是否赠品=False
|
||||||
|
2025-05-08 20:46:03,172 - app.core.excel.processor - INFO - 发现正常商品:条码6937003700207, 数量=15.0, 单价=4.533333333333333
|
||||||
|
2025-05-08 20:46:03,172 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706346, 数量=15.0, 单价=4.533333333333333, 是否赠品=False
|
||||||
|
2025-05-08 20:46:03,172 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706346, 数量=15.0, 单价=4.533333333333333
|
||||||
|
2025-05-08 20:46:03,172 - app.core.excel.processor - INFO - 处理商品: 条码=6937003706568, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 20:46:03,172 - app.core.excel.processor - INFO - 发现正常商品:条码6937003706568, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 20:46:03,172 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 20:46:03,173 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708173, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 20:46:03,173 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708166, 数量=15.0, 单价=3.7333333333333334, 是否赠品=False
|
||||||
|
2025-05-08 20:46:03,173 - app.core.excel.processor - INFO - 发现正常商品:条码6937003708166, 数量=15.0, 单价=3.7333333333333334
|
||||||
|
2025-05-08 20:46:03,173 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703086, 数量=15.0, 单价=2.0, 是否赠品=False
|
||||||
|
2025-05-08 20:46:03,174 - app.core.excel.processor - INFO - 发现正常商品:条码6937003703086, 数量=15.0, 单价=2.0
|
||||||
|
2025-05-08 20:46:03,174 - app.core.excel.processor - INFO - 处理商品: 条码=6975176784785, 数量=12.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:46:03,174 - app.core.excel.processor - INFO - 发现赠品:条码6975176784785, 数量=12.0
|
||||||
|
2025-05-08 20:46:03,175 - app.core.excel.processor - INFO - 处理商品: 条码=6937003703437, 数量=12.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:46:03,175 - app.core.excel.processor - INFO - 发现赠品:条码6937003703437, 数量=12.0
|
||||||
|
2025-05-08 20:46:03,176 - app.core.excel.processor - INFO - 处理商品: 条码=6937003708173, 数量=2.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:46:03,176 - app.core.excel.processor - INFO - 发现赠品:条码6937003708173, 数量=2.0
|
||||||
|
2025-05-08 20:46:03,176 - app.core.excel.processor - INFO - 处理商品: 条码=6975176781777, 数量=1.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:46:03,176 - app.core.excel.processor - INFO - 发现赠品:条码6975176781777, 数量=1.0
|
||||||
|
2025-05-08 20:46:03,176 - app.core.excel.processor - INFO - 处理商品: 条码=6975176782460, 数量=9.0, 单价=0, 是否赠品=True
|
||||||
|
2025-05-08 20:46:03,177 - app.core.excel.processor - INFO - 发现赠品:条码6975176782460, 数量=9.0
|
||||||
|
2025-05-08 20:46:03,177 - app.core.excel.processor - INFO - 分组后共10 个不同条码的商品
|
||||||
|
2025-05-08 20:46:03,177 - app.core.excel.processor - INFO - 条码 6937003700207 处理结果:正常商品数量15.0,单价4.533333333333333,赠品数量0
|
||||||
|
2025-05-08 20:46:03,177 - app.core.excel.processor - INFO - 条码 6937003706346 处理结果:正常商品数量15.0,单价4.533333333333333,赠品数量0
|
||||||
|
2025-05-08 20:46:03,178 - app.core.excel.processor - INFO - 条码 6937003706568 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量0
|
||||||
|
2025-05-08 20:46:03,178 - app.core.excel.processor - INFO - 条码 6937003708173 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量2.0
|
||||||
|
2025-05-08 20:46:03,178 - app.core.excel.processor - INFO - 条码 6937003708166 处理结果:正常商品数量15.0,单价3.7333333333333334,赠品数量0
|
||||||
|
2025-05-08 20:46:03,178 - app.core.excel.processor - INFO - 条码 6937003703086 处理结果:正常商品数量15.0,单价2.0,赠品数量0
|
||||||
|
2025-05-08 20:46:03,178 - app.core.excel.processor - INFO - 条码 6975176784785 处理结果:只有赠品,数量=12.0
|
||||||
|
2025-05-08 20:46:03,178 - app.core.excel.processor - INFO - 条码 6937003703437 处理结果:只有赠品,数量=12.0
|
||||||
|
2025-05-08 20:46:07,558 - app.core.excel.processor - INFO - 条码 6975176781777 处理结果:只有赠品,数量=1.0
|
||||||
|
2025-05-08 20:46:07,558 - app.core.excel.processor - INFO - 条码 6975176782460 处理结果:只有赠品,数量=9.0
|
||||||
|
2025-05-08 20:46:07,558 - app.core.excel.processor - INFO - 条码 6937003708173 填充:采购量=15.0,赠品数量2.0
|
||||||
|
2025-05-08 20:46:07,559 - app.core.excel.processor - INFO - 条码 6975176784785 填充:仅有赠品,采购量=0,赠品数量=12.0
|
||||||
|
2025-05-08 20:46:07,559 - app.core.excel.processor - INFO - 条码 6937003703437 填充:仅有赠品,采购量=0,赠品数量=12.0
|
||||||
|
2025-05-08 20:46:07,559 - app.core.excel.processor - INFO - 条码 6975176781777 填充:仅有赠品,采购量=0,赠品数量=1.0
|
||||||
|
2025-05-08 20:46:07,559 - app.core.excel.processor - INFO - 条码 6975176782460 填充:仅有赠品,采购量=0,赠品数量=9.0
|
||||||
|
2025-05-08 20:46:07,563 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
2025-05-08 20:46:07,564 - app.core.excel.processor - INFO - 采购单已保存到: D:\My Documents\python\orc-order-v2\data\output\采购单_微信图片_20250508194532.xls
|
||||||
|
|||||||
9
logs/app.core.excel.validators.log
Normal file
9
logs/app.core.excel.validators.log
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
2025-05-08 19:45:49,628 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
|
2025-05-08 19:45:49,629 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
|
2025-05-08 19:45:49,638 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
|
2025-05-08 19:45:49,639 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
|
2025-05-08 19:45:49,640 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
|
2025-05-08 19:45:49,641 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
|
2025-05-08 19:45:49,641 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
|
2025-05-08 19:45:49,878 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
|
2025-05-08 19:45:49,881 - app.core.excel.validators - WARNING - 数量验证失败: 数量必须大于0,当前值: 0.0
|
||||||
@ -68,3 +68,4 @@
|
|||||||
2025-05-07 21:22:01,976 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
2025-05-07 21:22:01,976 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
2025-05-07 21:54:55,605 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
2025-05-07 21:54:55,605 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
2025-05-07 22:28:51,887 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
2025-05-07 22:28:51,887 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
2025-05-08 19:45:41,386 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
|
||||||
|
|||||||
@ -654,3 +654,29 @@
|
|||||||
2025-05-07 22:28:52,829 - app.core.ocr.table_ocr - INFO - 图片处理成功: D:\My Documents\python\orc-order-v2\data\input\微信图片_20250507222846.jpg, 输出文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250507222846.xlsx
|
2025-05-07 22:28:52,829 - app.core.ocr.table_ocr - INFO - 图片处理成功: D:\My Documents\python\orc-order-v2\data\input\微信图片_20250507222846.jpg, 输出文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250507222846.xlsx
|
||||||
2025-05-07 22:28:52,832 - app.core.ocr.table_ocr - INFO - 批次处理完成, 成功: 1/1
|
2025-05-07 22:28:52,832 - app.core.ocr.table_ocr - INFO - 批次处理完成, 成功: 1/1
|
||||||
2025-05-07 22:28:52,832 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
2025-05-07 22:28:52,832 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-05-08 19:45:41,028 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
|
||||||
|
2025-05-08 19:45:41,030 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 19:45:41,030 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
|
||||||
|
2025-05-08 19:45:41,030 - app.core.ocr.table_ocr - INFO - OCR处理器初始化完成,输入目录: D:\My Documents\python\orc-order-v2\data\input, 输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 19:45:41,036 - app.core.ocr.table_ocr - INFO - 找到 1 个图片文件,其中 1 个未处理
|
||||||
|
2025-05-08 19:45:41,036 - app.core.ocr.table_ocr - INFO - 处理批次 1/1, 大小: 1
|
||||||
|
2025-05-08 19:45:41,037 - app.core.ocr.table_ocr - INFO - 开始处理图片: D:\My Documents\python\orc-order-v2\data\input\微信图片_20250508194532.jpg
|
||||||
|
2025-05-08 19:45:48,792 - app.core.ocr.table_ocr - INFO - 图片处理成功: D:\My Documents\python\orc-order-v2\data\input\微信图片_20250508194532.jpg, 输出文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:45:48,794 - app.core.ocr.table_ocr - INFO - 批次处理完成, 成功: 1/1
|
||||||
|
2025-05-08 19:45:48,795 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 1, 成功: 1
|
||||||
|
2025-05-08 19:47:28,883 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
|
||||||
|
2025-05-08 19:47:28,883 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 19:47:28,883 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
|
||||||
|
2025-05-08 19:47:28,884 - app.core.ocr.table_ocr - INFO - OCR处理器初始化完成,输入目录: D:\My Documents\python\orc-order-v2\data\input, 输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 19:51:23,177 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
|
||||||
|
2025-05-08 19:51:23,177 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 19:51:23,177 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
|
||||||
|
2025-05-08 19:51:23,178 - app.core.ocr.table_ocr - INFO - OCR处理器初始化完成,输入目录: D:\My Documents\python\orc-order-v2\data\input, 输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 20:04:06,906 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
|
||||||
|
2025-05-08 20:04:06,907 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 20:04:06,907 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
|
||||||
|
2025-05-08 20:04:06,907 - app.core.ocr.table_ocr - INFO - OCR处理器初始化完成,输入目录: D:\My Documents\python\orc-order-v2\data\input, 输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 20:46:00,693 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
|
||||||
|
2025-05-08 20:46:00,694 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
2025-05-08 20:46:00,694 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
|
||||||
|
2025-05-08 20:46:00,695 - app.core.ocr.table_ocr - INFO - OCR处理器初始化完成,输入目录: D:\My Documents\python\orc-order-v2\data\input, 输出目录: D:\My Documents\python\orc-order-v2\data\output
|
||||||
|
|||||||
@ -264,3 +264,14 @@
|
|||||||
2025-05-07 22:28:51,544 - app.services.ocr_service - INFO - 初始化OCRService
|
2025-05-07 22:28:51,544 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
2025-05-07 22:28:51,548 - app.services.ocr_service - INFO - OCRService初始化完成
|
2025-05-07 22:28:51,548 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
2025-05-07 22:28:51,557 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
2025-05-07 22:28:51,557 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-05-08 19:45:41,026 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-05-08 19:45:41,030 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-05-08 19:45:41,036 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=None, max_workers=None
|
||||||
|
2025-05-08 19:47:28,878 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-05-08 19:47:28,884 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-05-08 19:51:23,176 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-05-08 19:51:23,178 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-05-08 20:04:06,905 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-05-08 20:04:06,907 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
2025-05-08 20:46:00,690 - app.services.ocr_service - INFO - 初始化OCRService
|
||||||
|
2025-05-08 20:46:00,696 - app.services.ocr_service - INFO - OCRService初始化完成
|
||||||
|
|||||||
@ -300,3 +300,18 @@
|
|||||||
2025-05-07 22:28:51,548 - app.services.order_service - INFO - 初始化OrderService
|
2025-05-07 22:28:51,548 - app.services.order_service - INFO - 初始化OrderService
|
||||||
2025-05-07 22:28:51,556 - app.services.order_service - INFO - OrderService初始化完成
|
2025-05-07 22:28:51,556 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
2025-05-07 22:28:52,834 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250507222846.xlsx
|
2025-05-07 22:28:52,834 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250507222846.xlsx
|
||||||
|
2025-05-08 19:45:41,030 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-05-08 19:45:41,035 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-05-08 19:45:48,798 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:\My Documents\python\orc-order-v2\data\output\微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:47:28,884 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-05-08 19:47:28,886 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-05-08 19:47:28,886 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 19:51:23,178 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-05-08 19:51:23,190 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-05-08 19:51:23,190 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 20:04:06,907 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-05-08 20:04:06,909 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-05-08 20:04:06,910 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
2025-05-08 20:46:00,697 - app.services.order_service - INFO - 初始化OrderService
|
||||||
|
2025-05-08 20:46:00,701 - app.services.order_service - INFO - OrderService初始化完成
|
||||||
|
2025-05-08 20:46:00,750 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250508194532.xlsx
|
||||||
|
|||||||
257
v2-优化总结.md
257
v2-优化总结.md
@ -70,3 +70,260 @@
|
|||||||
2. **模块间低耦合**:模块之间通过明确的接口交互,降低耦合度
|
2. **模块间低耦合**:模块之间通过明确的接口交互,降低耦合度
|
||||||
3. **可扩展设计**:系统设计考虑未来扩展,如添加新的特殊条码处理规则
|
3. **可扩展设计**:系统设计考虑未来扩展,如添加新的特殊条码处理规则
|
||||||
4. **完整文档**:提供详细的README文档,说明系统功能和使用方法
|
4. **完整文档**:提供详细的README文档,说明系统功能和使用方法
|
||||||
|
|
||||||
|
# OCR订单处理系统 v2 优化建议
|
||||||
|
|
||||||
|
经过全面审查系统代码和架构,以下是对 OCR 订单处理系统的优化建议,旨在提高系统的性能、可维护性和用户体验。
|
||||||
|
|
||||||
|
## 1. 架构与结构优化
|
||||||
|
|
||||||
|
### 1.1 依赖注入与组件化
|
||||||
|
|
||||||
|
**当前情况**:系统主要组件在代码中直接实例化,造成模块间高耦合。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 实现简单的依赖注入系统,降低模块间耦合度
|
||||||
|
- 使用工厂模式创建核心组件,便于测试和替换
|
||||||
|
- 示例代码:
|
||||||
|
```python
|
||||||
|
class AppContainer:
|
||||||
|
def __init__(self, config):
|
||||||
|
self.config = config
|
||||||
|
self._services = {}
|
||||||
|
|
||||||
|
def get_ocr_service(self):
|
||||||
|
if 'ocr_service' not in self._services:
|
||||||
|
self._services['ocr_service'] = OCRService(self.config)
|
||||||
|
return self._services['ocr_service']
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 配置系统增强
|
||||||
|
|
||||||
|
**当前情况**:配置存储在 `config.ini`,但部分硬编码的配置分散在代码中。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 将所有配置项集中到配置文件,消除硬编码的配置
|
||||||
|
- 添加环境变量支持,便于部署和CI/CD集成
|
||||||
|
- 增加配置验证机制,防止错误配置
|
||||||
|
- 支持不同环境(开发、测试、生产)的配置切换
|
||||||
|
|
||||||
|
### 1.3 模块化 UI 与核心逻辑分离
|
||||||
|
|
||||||
|
**当前情况**:`启动器.py` 文件过大 (1050行),同时包含 UI 和业务逻辑。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 将 UI 逻辑与业务逻辑完全分离
|
||||||
|
- 采用 MVC 或 MVVM 模式重构 UI 代码
|
||||||
|
- 将 UI 组件模块化,每个页面/功能对应单独的类
|
||||||
|
|
||||||
|
## 2. 性能优化
|
||||||
|
|
||||||
|
### 2.1 数据处理性能
|
||||||
|
|
||||||
|
**当前情况**:处理大量数据时效率较低,特别是 Excel 数据处理部分。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 使用 DataFrame 矢量化操作替代循环,提高数据处理速度
|
||||||
|
- 对于大文件,实现分块读取和处理机制
|
||||||
|
- 优化正则表达式,减少重复编译
|
||||||
|
- 示例改进:
|
||||||
|
```python
|
||||||
|
# 优化前
|
||||||
|
for idx, row in df.iterrows():
|
||||||
|
# 处理每一行...
|
||||||
|
|
||||||
|
# 优化后
|
||||||
|
# 使用 apply 或向量化操作
|
||||||
|
df['barcode'] = df['barcode'].apply(format_barcode)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 并发处理增强
|
||||||
|
|
||||||
|
**当前情况**:已有初步的多线程支持,但未充分利用。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 扩展并行处理能力,特别是在 OCR 识别部分
|
||||||
|
- 实现任务队列系统,支持后台处理
|
||||||
|
- 添加进度报告机制,提高用户体验
|
||||||
|
- 考虑使用 asyncio 进行 I/O 密集型任务处理
|
||||||
|
|
||||||
|
### 2.3 缓存机制
|
||||||
|
|
||||||
|
**当前情况**:每次处理都重新加载和解析数据。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 实现内存缓存机制,缓存常用数据和配置
|
||||||
|
- 添加条码和商品信息的本地数据库,减少重复处理
|
||||||
|
- 对规格解析结果进行缓存,提高处理速度
|
||||||
|
|
||||||
|
## 3. 代码质量改进
|
||||||
|
|
||||||
|
### 3.1 单元测试与代码覆盖率
|
||||||
|
|
||||||
|
**当前情况**:缺乏系统性的单元测试。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 为核心功能编写单元测试,特别是单位转换和条码处理逻辑
|
||||||
|
- 实现测试数据生成器,支持边界情况测试
|
||||||
|
- 使用测试覆盖率工具,确保关键代码被测试覆盖
|
||||||
|
- 集成持续测试到开发流程中
|
||||||
|
|
||||||
|
### 3.2 代码重构
|
||||||
|
|
||||||
|
**当前情况**:部分函数过长,职责不够单一。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 对长函数进行拆分,特别是 `extract_product_info`(300+ 行)
|
||||||
|
- 使用 Strategy 模式重构条码处理和单位转换逻辑
|
||||||
|
- 简化复杂的嵌套条件语句,提高代码可读性
|
||||||
|
- 提取通用功能到辅助函数,减少代码重复
|
||||||
|
|
||||||
|
### 3.3 错误处理增强
|
||||||
|
|
||||||
|
**当前情况**:错误处理主要依靠日志记录。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 设计更细粒度的异常类型,便于精确处理不同错误
|
||||||
|
- 实现全局异常处理,防止程序崩溃
|
||||||
|
- 添加用户友好的错误提示,而不只是记录日志
|
||||||
|
- 增加错误恢复机制,允许在出错后继续处理其他项目
|
||||||
|
|
||||||
|
## 4. 功能增强
|
||||||
|
|
||||||
|
### 4.1 数据验证与清洗增强
|
||||||
|
|
||||||
|
**当前情况**:基本的数据验证和清洗逻辑。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 增强数据验证规则,特别是对条码和数量的验证
|
||||||
|
- 实现更智能的数据修复功能,处理常见错误格式
|
||||||
|
- 添加数据异常检测算法,自动标记异常数据
|
||||||
|
- 提供手动数据修正界面,允许用户修正识别错误
|
||||||
|
|
||||||
|
### 4.2 批量处理功能增强
|
||||||
|
|
||||||
|
**当前情况**:支持基本的批量处理。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 支持拖放多个文件进行处理
|
||||||
|
- 添加文件队列管理,显示待处理/已处理状态
|
||||||
|
- 实现处理中断和恢复功能
|
||||||
|
- 支持处理结果预览和批量修改
|
||||||
|
|
||||||
|
### 4.3 数据导出与集成
|
||||||
|
|
||||||
|
**当前情况**:生成固定格式的 Excel 文件。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 支持多种导出格式(CSV、JSON、XML 等)
|
||||||
|
- 提供数据库存储选项,便于数据管理和查询
|
||||||
|
- 添加 API 接口,支持与其他系统集成
|
||||||
|
- 实现定制化报表生成功能
|
||||||
|
|
||||||
|
## 5. 用户体验改进
|
||||||
|
|
||||||
|
### 5.1 界面优化
|
||||||
|
|
||||||
|
**当前情况**:基本的功能界面。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 重新设计 UI,采用现代化界面框架(如 PyQt6 或 wx.Python)
|
||||||
|
- 添加暗色主题支持
|
||||||
|
- 实现响应式布局,适应不同屏幕尺寸
|
||||||
|
- 增加操作引导和工具提示
|
||||||
|
|
||||||
|
### 5.2 用户反馈与报告
|
||||||
|
|
||||||
|
**当前情况**:主要通过日志记录处理结果。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 设计直观的处理结果报告页面
|
||||||
|
- 添加数据可视化功能,展示处理统计信息
|
||||||
|
- 实现处理报告导出功能
|
||||||
|
- 设计更友好的错误提示和建议
|
||||||
|
|
||||||
|
### 5.3 配置与偏好设置
|
||||||
|
|
||||||
|
**当前情况**:配置主要在 config.ini 中修改。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 设计图形化配置界面,无需直接编辑配置文件
|
||||||
|
- 支持用户偏好设置保存
|
||||||
|
- 添加配置导入/导出功能
|
||||||
|
- 实现配置模板,快速切换不同配置
|
||||||
|
|
||||||
|
## 6. 安全性改进
|
||||||
|
|
||||||
|
### 6.1 API 密钥管理
|
||||||
|
|
||||||
|
**当前情况**:API 密钥直接存储在配置文件中。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 实现 API 密钥加密存储
|
||||||
|
- 支持从环境变量或安全存储获取敏感信息
|
||||||
|
- 添加 API 密钥轮换机制
|
||||||
|
- 实现访问审计日志
|
||||||
|
|
||||||
|
### 6.2 数据安全
|
||||||
|
|
||||||
|
**当前情况**:数据以明文形式存储和处理。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 添加敏感数据(如价格信息)的加密选项
|
||||||
|
- 实现自动数据备份机制
|
||||||
|
- 添加访问控制,限制对敏感数据的访问
|
||||||
|
- 支持数据匿名化处理,用于测试和分析
|
||||||
|
|
||||||
|
## 7. 部署与维护改进
|
||||||
|
|
||||||
|
### 7.1 打包与分发
|
||||||
|
|
||||||
|
**当前情况**:依赖 Python 环境和手动安装依赖。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 使用 PyInstaller 或 cx_Freeze 创建独立可执行文件
|
||||||
|
- 提供自动安装脚本,简化部署过程
|
||||||
|
- 支持自动更新机制
|
||||||
|
- 创建详细的安装和部署文档
|
||||||
|
|
||||||
|
### 7.2 监控与日志
|
||||||
|
|
||||||
|
**当前情况**:基本的日志记录功能。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 实现结构化日志系统,支持日志搜索和分析
|
||||||
|
- 添加系统性能监控功能
|
||||||
|
- 设计操作审计日志,记录关键操作
|
||||||
|
- 支持日志远程存储和集中管理
|
||||||
|
|
||||||
|
### 7.3 文档完善
|
||||||
|
|
||||||
|
**当前情况**:有基本的 README 文档。
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 创建详细的开发者文档,包括架构说明和 API 参考
|
||||||
|
- 编写用户手册和操作指南
|
||||||
|
- 添加代码内文档字符串,支持自动文档生成
|
||||||
|
- 提供常见问题解答和故障排除指南
|
||||||
|
|
||||||
|
## 8. 当前优化重点
|
||||||
|
|
||||||
|
基于系统现状,建议首先关注以下优化点:
|
||||||
|
|
||||||
|
1. **重构单位转换逻辑**:将复杂的单位转换和条码映射逻辑模块化,提高可维护性
|
||||||
|
2. **增强数据验证**:改进条码和规格提取逻辑,减少处理错误
|
||||||
|
3. **UI 改进**:将大型启动器文件拆分为多个组件,采用 MVC 模式
|
||||||
|
4. **添加单元测试**:为核心业务逻辑添加测试用例,确保功能正确性
|
||||||
|
5. **实现缓存机制**:提高重复数据处理效率
|
||||||
|
|
||||||
|
## 9. 长期优化计划
|
||||||
|
|
||||||
|
长期来看,建议考虑以下方向:
|
||||||
|
|
||||||
|
1. **迁移到 Web 应用**:考虑将系统转换为 Web 应用,提供更好的跨平台支持
|
||||||
|
2. **数据智能分析**:增加智能分析功能,如采购趋势分析、异常检测等
|
||||||
|
3. **与 ERP 系统集成**:提供与主流 ERP 系统的集成接口
|
||||||
|
4. **移动端支持**:开发移动应用或响应式 Web 界面,支持手机操作
|
||||||
|
5. **OCR 引擎替换选项**:支持多种 OCR 引擎,降低对单一 API 的依赖
|
||||||
|
|
||||||
|
通过以上优化,OCR 订单处理系统将更加健壮、高效、易用,能够更好地满足业务需求,并为未来功能扩展提供良好的基础。
|
||||||
Loading…
Reference in New Issue
Block a user