新增条码映射编辑功能图形化界面

This commit is contained in:
侯欢 2025-05-10 11:39:11 +08:00
parent 7b7d491663
commit 5c0b709528
46 changed files with 2510 additions and 499 deletions

117
README.md
View File

@ -4,8 +4,8 @@
## 版本信息
- **当前版本**: v1.1
- **发布日期**: 2025-05-07
- **当前版本**: v1.5
- **发布日期**: 2025-05-09
- **作者**: OCR订单处理团队
## 功能特点
@ -17,6 +17,11 @@
- **批量处理**:支持批量处理多张图片
- **图形界面**:提供简洁直观的图形界面,方便操作
- **命令行支持**:支持命令行方式调用,便于自动化处理
- **OCR识别**: 支持图片中表格的自动识别和提取
- **Excel处理**: 将OCR识别结果处理为规范的Excel表格
- **订单合并**: 将多个采购单自动合并为一个总表
- **完整流程**: 一键执行从OCR识别到订单合并的完整处理流程
- **烟草订单处理**: 专门处理烟草公司特定格式的订单明细文件,生成银豹采购单
## 系统架构
@ -95,33 +100,56 @@ template_file = templates/银豹-采购单模板.xls
## 使用方法
### 图形界面
1. **启动系统**
- 双击运行 `启动器.py` 文件,启动图形界面
- 或者通过命令行运行 `python run.py <命令> [选项]`
运行`启动器.py`启动图形界面:
2. **图形界面操作**
- **处理Excel文件**: 处理指定的Excel文件或最新的Excel文件
- **OCR批量识别**: 批量处理input目录下的所有图片
- **完整处理流程**: 一键执行OCR识别、Excel处理和订单合并
- **处理单个图片**: 处理指定的单张图片
- **合并采购单**: 合并多个采购单为一个总表
- **处理烟草订单**: 处理烟草公司特定格式的订单明细文件,生成银豹采购单格式
- **整理项目文件**: 整理项目文件结构
- **清除处理缓存**: 清除处理缓存,使系统重新处理所有文件
- **清理文件**: 清理所有数据文件
- **切换主题**: 在浅色和深色主题之间切换
```bash
python 启动器.py
## 命令行使用
系统支持通过命令行操作,基本用法:
```
python run.py <命令> [选项]
```
图形界面包括以下功能:
- **处理单个文件**:选择并处理单个图片文件
- **批量处理**处理data/input目录中的所有图片文件
- **合并处理**:合并多个采购单
- **清理文件**清理input和output目录中的文件
- **查看日志**:实时显示处理日志
支持的命令:
### 命令行模式
1. **ocr**: OCR识别
```
python run.py ocr [--input 图片路径] [--batch] [--batch-size 批大小] [--max-workers 最大线程数]
```
```bash
# 处理单个文件
python run.py --file=image.jpg
2. **excel**: Excel处理
```
python run.py excel [--input Excel文件路径]
```
# 批量处理目录中的所有文件
python run.py --batch
3. **merge**: 订单合并
```
python run.py merge [--input 采购单文件路径列表,以逗号分隔]
```
# 合并采购单
python run.py --merge
```
4. **pipeline**: 完整流程
```
python run.py pipeline [--input 图片路径]
```
5. **tobacco**: 烟草订单处理
```
python run.py tobacco [--input 烟草订单明细文件路径]
```
## 单位处理规则
@ -267,6 +295,53 @@ MIT License
## 更新日志
### v1.5 (2025-05-09)
#### 功能改进
- 烟草订单处理结果展示:改进烟草订单处理完成后的结果展示界面
- 美化结果 展示界面,显示订单时间、总金额和处理条目数
- 添加文件信息展示,包括文件大小和创建时间
- 提供打开文件、打开所在文件夹等便捷操作按钮
- 统一与Excel处理结果展示风格提升用户体验
- 增强结果文件路径解析能力,确保正确找到并显示结果文件
- 条码映射编辑功能:
- 添加图形化条码映射编辑工具,方便管理条码映射和特殊处理规则
- 支持添加、修改和删除条码映射关系
- 支持配置特殊处理规则,如乘数、目标单位、固定单价等
- 自动保存到配置文件,便于后续使用
#### 问题修复
- 修复烟草订单处理时出现双重弹窗问题
- 修复烟草订单处理完成后结果展示弹窗无法正常显示的问题
- 修复ConfigParser兼容性问题支持标准ConfigParser对象
- 修复百度OCR客户端中getint方法调用不兼容问题
- 修复OCRService中缺少batch_process方法的问题确保OCR功能正常工作
- 改进日志管理,确保所有日志正确关闭
- 优化UI界面统一按钮样式
- 修复启动器中处理烟草订单按钮的显示样式
- 修复run.py中close_logger调用缺少参数的问题
#### 代码改进
- 改进TobaccoService类对配置的处理方式使用标准get方法
- 添加fallback机制以增强配置健壮性
- 优化启动器中结果预览逻辑,避免重复弹窗
- 统一UI组件风格提升用户体验
- 增强错误处理,提供更清晰的错误信息
### v1.4 (2025-05-09)
#### 新功能
- 烟草订单处理:新增烟草公司特定格式订单明细文件处理功能
- 支持自动处理标准烟草订单明细格式
- 根据烟草公司"盒码"作为条码生成银豹采购单
- 自动将"订单量"转换为"采购量"并计算采购单价
- 处理结果以银豹采购单格式保存,方便直接导入
#### 功能优化
- 配置兼容性优化配置处理逻辑兼容标准ConfigParser对象
- 启动器优化:启动器界面增加"处理烟草订单"功能按钮
- 代码结构优化:将烟草订单处理功能模块化,集成到整体服务架构
### v1.3 (2025-07-20)
#### 功能优化

View File

@ -6,6 +6,8 @@
import re
import logging
import os
import json
from typing import Dict, Tuple, Optional, Any, List, Union
from ..utils.log_utils import get_logger
@ -18,6 +20,9 @@ from .validators import ProductValidator
logger = get_logger(__name__)
# 条码映射配置文件路径
BARCODE_MAPPING_CONFIG = "config/barcode_mappings.json"
class UnitConverter:
"""
单位转换器处理不同单位之间的转换支持从商品名称推断规格
@ -27,60 +32,8 @@ class UnitConverter:
"""
初始化单位转换器
"""
# 特殊条码配置
self.special_barcodes = {
'6925019900087': {
'multiplier': 10, # 数量乘以10
'target_unit': '', # 目标单位
'description': '特殊处理:数量*10单位转换为瓶'
},
'6921168593804': {
'multiplier': 30, # 数量乘以30
'target_unit': '', # 目标单位
'description': 'NFC产品特殊处理每箱30瓶'
},
'6901826888138': {
'multiplier': 30, # 数量乘以30
'target_unit': '', # 目标单位
'fixed_price': 112/30, # 固定单价为112/30
'specification': '1*30', # 固定规格
'description': '特殊处理: 规格1*30数量*30单价=112/30'
},
# 条码映射转换配置
'6920584471055': {
'map_to': '6920584471017', # 映射到新条码
'description': '条码映射6920584471055 -> 6920584471017'
},
'6925861571159': {
'map_to': '69021824', # 映射到新条码
'description': '条码映射6925861571159 -> 69021824'
},
'6923644268923': {
'map_to': '6923644268480', # 映射到新条码
'description': '条码映射6923644268923 -> 6923644268480'
},
'6907992501819': {
'map_to': '6907992500133', # 映射到新条码
'description': '条码映射6907992501819 -> 6907992500133'
},
'6923644268916': {
'map_to': '6923644268503', # 映射到新条码
'description': '条码映射6923644268916 -> 6923644268503'
},
'6923644283582': {
'map_to': '6923644283575', # 映射到新条码
'description': '条码映射6923644283582 -> 6923644283575'
},
'6923644268930': {
'map_to': '6923644268497', # 映射到新条码
'description': '条码映射6923644268930 -> 6923644268497'
},
'6923644210151': {
'map_to': '6923644223458', # 映射到新条码
'description': '条码映射6923644210151 -> 6923644223458'
}
# 可以添加更多特殊条码的配置
}
# 加载特殊条码配置
self.special_barcodes = self.load_barcode_mappings()
# 规格推断的正则表达式模式
self.spec_patterns = [
@ -448,3 +401,97 @@ class UnitConverter:
# 没有找到适用的处理程序,保持不变
logger.info(f"其他单位处理: 保持原样 数量: {result.get('quantity', 0)}, 单价: {result.get('price', 0)}, 单位: {result.get('unit', '')}")
return result
def load_barcode_mappings(self) -> Dict[str, Dict[str, Any]]:
"""
从配置文件加载条码映射
Returns:
条码映射字典
"""
# 默认映射
default_mappings = {
'6925019900087': {
'multiplier': 10,
'target_unit': '',
'description': '特殊处理:数量*10单位转换为瓶'
},
'6921168593804': {
'multiplier': 30,
'target_unit': '',
'description': 'NFC产品特殊处理每箱30瓶'
},
'6901826888138': {
'multiplier': 30,
'target_unit': '',
'fixed_price': 112/30,
'specification': '1*30',
'description': '特殊处理: 规格1*30数量*30单价=112/30'
},
# 条码映射配置
'6920584471055': {
'map_to': '6920584471017',
'description': '条码映射6920584471055 -> 6920584471017'
},
'6925861571159': {
'map_to': '69021824',
'description': '条码映射6925861571159 -> 69021824'
},
'6923644268923': {
'map_to': '6923644268480',
'description': '条码映射6923644268923 -> 6923644268480'
}
}
try:
# 检查配置文件是否存在
if os.path.exists(BARCODE_MAPPING_CONFIG):
with open(BARCODE_MAPPING_CONFIG, 'r', encoding='utf-8') as file:
mappings = json.load(file)
logger.info(f"成功加载条码映射配置,共{len(mappings)}")
return mappings
else:
# 创建默认配置文件
self.save_barcode_mappings(default_mappings)
logger.info(f"创建默认条码映射配置,共{len(default_mappings)}")
return default_mappings
except Exception as e:
logger.error(f"加载条码映射配置失败: {e}")
return default_mappings
def save_barcode_mappings(self, mappings: Dict[str, Dict[str, Any]]) -> bool:
"""
保存条码映射到配置文件
Args:
mappings: 条码映射字典
Returns:
保存是否成功
"""
try:
# 确保配置目录存在
os.makedirs(os.path.dirname(BARCODE_MAPPING_CONFIG), exist_ok=True)
# 写入配置文件
with open(BARCODE_MAPPING_CONFIG, 'w', encoding='utf-8') as file:
json.dump(mappings, file, ensure_ascii=False, indent=2)
logger.info(f"条码映射配置保存成功,共{len(mappings)}")
return True
except Exception as e:
logger.error(f"保存条码映射配置失败: {e}")
return False
def update_barcode_mappings(self, new_mappings: Dict[str, Dict[str, Any]]) -> bool:
"""
更新条码映射配置
Args:
new_mappings: 新的条码映射字典
Returns:
更新是否成功
"""
self.special_barcodes = new_mappings
return self.save_barcode_mappings(new_mappings)

View File

@ -36,35 +36,44 @@ class PurchaseOrderMerger:
采购单合并器将多个采购单Excel文件合并成一个文件
"""
def __init__(self, config: Optional[ConfigManager] = None):
def __init__(self, config):
"""
初始化采购单合并器
Args:
config: 配置管理器如果为None则创建新的
config: 配置信息
"""
logger.info("初始化PurchaseOrderMerger")
self.config = config or ConfigManager()
self.config = config
# 获取配置
self.output_dir = self.config.get_path('Paths', 'output_folder', 'data/output', create=True)
# 修复ConfigParser对象没有get_path方法的问题
try:
# 获取输出目录
self.output_dir = config.get('Paths', 'output_folder', fallback='data/output')
# 确保目录存在
os.makedirs(self.output_dir, exist_ok=True)
# 记录实际路径
logger.info(f"使用输出目录: {os.path.abspath(self.output_dir)}")
# 获取模板文件路径
template_folder = self.config.get('Paths', 'template_folder', 'templates')
template_name = self.config.get('Templates', 'purchase_order', '银豹-采购单模板.xls')
template_folder = config.get('Paths', 'template_folder', fallback='templates')
template_name = config.get('Templates', 'purchase_order', fallback='银豹-采购单模板.xls')
self.template_path = os.path.join(template_folder, template_name)
# 检查模板文件是否存在
if not os.path.exists(self.template_path):
logger.error(f"模板文件不存在: {self.template_path}")
raise FileNotFoundError(f"模板文件不存在: {self.template_path}")
logger.warning(f"模板文件不存在: {self.template_path}")
# 用于记录已合并的文件
self.cache_file = os.path.join(self.output_dir, "merged_files.json")
self.merged_files_json = os.path.join(self.output_dir, "merged_files.json")
self.merged_files = self._load_merged_files()
logger.info(f"初始化完成,模板文件: {self.template_path}")
logger.info(f"初始化PurchaseOrderMerger完成模板文件: {self.template_path}")
except Exception as e:
logger.error(f"初始化PurchaseOrderMerger失败: {e}")
raise
def _load_merged_files(self) -> Dict[str, str]:
"""
@ -73,11 +82,11 @@ class PurchaseOrderMerger:
Returns:
合并记录字典
"""
return load_json(self.cache_file, {})
return load_json(self.merged_files_json, {})
def _save_merged_files(self) -> None:
"""保存已合并文件的缓存"""
save_json(self.merged_files, self.cache_file)
save_json(self.merged_files, self.merged_files_json)
def get_purchase_orders(self) -> List[str]:
"""

View File

@ -39,39 +39,44 @@ class ExcelProcessor:
提取条码单价和数量并按照采购单模板的格式填充
"""
def __init__(self, config: Optional[ConfigManager] = None):
def __init__(self, config):
"""
初始化Excel处理器
Args:
config: 配置管理器如果为None则创建新的
config: 配置信息
"""
logger.info("初始化ExcelProcessor")
self.config = config or ConfigManager()
self.config = config
# 获取配置
self.output_dir = self.config.get_path('Paths', 'output_folder', 'data/output', create=True)
self.temp_dir = self.config.get_path('Paths', 'temp_folder', 'data/temp', create=True)
# 修复ConfigParser对象没有get_path方法的问题
try:
# 获取输入和输出目录
self.output_dir = config.get('Paths', 'output_folder', fallback='data/output')
self.temp_dir = config.get('Paths', 'temp_folder', fallback='data/temp')
# 获取模板文件路径
template_folder = self.config.get('Paths', 'template_folder', 'templates')
template_name = self.config.get('Templates', 'purchase_order', '银豹-采购单模板.xls')
self.template_path = os.path.join(template_folder, template_name)
# 检查模板文件是否存在
self.template_path = config.get('Paths', 'template_file', fallback='templates/银豹-采购单模板.xls')
if not os.path.exists(self.template_path):
logger.error(f"模板文件不存在: {self.template_path}")
raise FileNotFoundError(f"模板文件不存在: {self.template_path}")
logger.warning(f"模板文件不存在: {self.template_path}")
# 用于记录已处理的文件
# 设置缓存文件路径
self.cache_file = os.path.join(self.output_dir, "processed_files.json")
self.processed_files = self._load_processed_files()
# 创建单位转换器
self.unit_converter = UnitConverter()
# 确保目录存在
os.makedirs(self.output_dir, exist_ok=True)
os.makedirs(self.temp_dir, exist_ok=True)
logger.info(f"初始化完成,模板文件: {self.template_path}")
# 记录实际路径
logger.info(f"使用输出目录: {os.path.abspath(self.output_dir)}")
logger.info(f"使用临时目录: {os.path.abspath(self.temp_dir)}")
# 加载单位转换器和配置
self.unit_converter = UnitConverter()
logger.info(f"初始化ExcelProcessor完成模板文件: {self.template_path}")
except Exception as e:
logger.error(f"初始化ExcelProcessor失败: {e}")
raise
def _load_processed_files(self) -> Dict[str, str]:
"""

View File

@ -105,22 +105,39 @@ class BaiduOCRClient:
百度OCR API客户端
"""
def __init__(self, config: Optional[ConfigManager] = None):
def __init__(self, config):
"""
初始化百度OCR客户端
Args:
config: 配置管理器如果为None则创建新的
config: 配置信息
"""
self.config = config or ConfigManager()
self.config = config
# 获取配置
self.api_key = self.config.get('API', 'api_key')
self.secret_key = self.config.get('API', 'secret_key')
self.timeout = self.config.getint('API', 'timeout', 30)
self.max_retries = self.config.getint('API', 'max_retries', 3)
self.retry_delay = self.config.getint('API', 'retry_delay', 2)
self.api_url = self.config.get('API', 'api_url', 'https://aip.baidubce.com/rest/2.0/ocr/v1/table')
# 从配置中读取API信息
try:
# 修复getint调用方式
self.timeout = config.get('API', 'timeout', fallback=30)
if isinstance(self.timeout, str):
self.timeout = int(self.timeout)
self.api_key = config.get('API', 'api_key', fallback='')
self.secret_key = config.get('API', 'secret_key', fallback='')
# 使用fallback而不是位置参数
try:
self.max_retries = config.getint('API', 'max_retries', fallback=3)
except (TypeError, AttributeError):
# 如果getint不支持fallback则使用get再转换
self.max_retries = int(config.get('API', 'max_retries', fallback='3'))
try:
self.retry_delay = config.getint('API', 'retry_delay', fallback=2)
except (TypeError, AttributeError):
# 如果getint不支持fallback则使用get再转换
self.retry_delay = int(config.get('API', 'retry_delay', fallback='2'))
self.api_url = config.get('API', 'api_url', fallback='https://aip.baidubce.com/rest/2.0/ocr/v1/table')
# 创建令牌管理器
self.token_manager = TokenManager(
@ -133,6 +150,8 @@ class BaiduOCRClient:
# 验证API配置
if not self.api_key or not self.secret_key:
logger.warning("API密钥未设置请在配置文件中设置API密钥")
except Exception as e:
logger.error(f"初始化失败: {e}")
def read_image(self, image_path: str) -> Optional[bytes]:
"""

View File

@ -103,51 +103,65 @@ class ProcessedRecordManager:
class OCRProcessor:
"""
OCR处理器用于表格识别与处理
OCR处理器负责协调OCR识别和结果处理
"""
def __init__(self, config: Optional[ConfigManager] = None):
def __init__(self, config):
"""
初始化OCR处理器
Args:
config: 配置管理器如果为None则创建新的
config: 配置信息
"""
self.config = config or ConfigManager()
self.config = config
# 创建百度OCR客户端
# 修复ConfigParser对象没有get_path方法的问题
try:
# 获取输入和输出目录
self.input_folder = config.get('Paths', 'input_folder', fallback='data/input')
self.output_folder = config.get('Paths', 'output_folder', fallback='data/output')
self.temp_folder = config.get('Paths', 'temp_folder', fallback='data/temp')
# 确保目录存在
os.makedirs(self.input_folder, exist_ok=True)
os.makedirs(self.output_folder, exist_ok=True)
os.makedirs(self.temp_folder, exist_ok=True)
# 获取文件类型列表
allowed_extensions_str = config.get('File', 'allowed_extensions', fallback='.jpg,.jpeg,.png,.bmp')
self.file_types = [ext.strip() for ext in allowed_extensions_str.split(',') if ext.strip()]
if not self.file_types:
self.file_types = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tif', '.tiff']
# 初始化OCR客户端
self.ocr_client = BaiduOCRClient(self.config)
# 获取配置
self.input_folder = self.config.get_path('Paths', 'input_folder', 'data/input', create=True)
self.output_folder = self.config.get_path('Paths', 'output_folder', 'data/output', create=True)
self.temp_folder = self.config.get_path('Paths', 'temp_folder', 'data/temp', create=True)
# 确保目录结构正确
for folder in [self.input_folder, self.output_folder, self.temp_folder]:
if not os.path.exists(folder):
os.makedirs(folder, exist_ok=True)
logger.info(f"创建目录: {folder}")
# 记录实际路径
logger.info(f"使用输入目录: {os.path.abspath(self.input_folder)}")
logger.info(f"使用输出目录: {os.path.abspath(self.output_folder)}")
logger.info(f"使用临时目录: {os.path.abspath(self.temp_folder)}")
logger.info(f"允许的文件类型: {self.file_types}")
self.allowed_extensions = self.config.get_list('File', 'allowed_extensions', '.jpg,.jpeg,.png,.bmp')
self.max_file_size_mb = self.config.getfloat('File', 'max_file_size_mb', 4.0)
self.excel_extension = self.config.get('File', 'excel_extension', '.xlsx')
# 初始化processed_files_json和record_manager
self.processed_files_json = os.path.join(self.output_folder, 'processed_files.json')
self.record_manager = ProcessedRecordManager(self.processed_files_json)
# 处理性能配置
self.max_workers = self.config.getint('Performance', 'max_workers', 4)
self.batch_size = self.config.getint('Performance', 'batch_size', 5)
self.skip_existing = self.config.getboolean('Performance', 'skip_existing', True)
# 加载已处理文件记录
self.processed_files = self._load_processed_files()
# 初始化处理记录管理器
record_file = self.config.get('Paths', 'processed_record', 'data/processed_files.json')
self.record_manager = ProcessedRecordManager(record_file)
logger.info(f"初始化OCRProcessor完成输入目录={self.input_folder}, 输出目录={self.output_folder}")
except Exception as e:
logger.error(f"初始化OCRProcessor失败: {e}")
raise
logger.info(f"OCR处理器初始化完成输入目录: {self.input_folder}, 输出目录: {self.output_folder}")
def _load_processed_files(self) -> Dict[str, str]:
"""
加载已处理的文件记录
Returns:
已处理的文件记录字典键为输入文件路径值为输出文件路径
"""
return load_json(self.processed_files_json, {})
def get_unprocessed_images(self) -> List[str]:
"""
@ -157,10 +171,16 @@ class OCRProcessor:
未处理的图片文件路径列表
"""
# 获取所有图片文件
image_files = get_files_by_extensions(self.input_folder, self.allowed_extensions)
image_files = get_files_by_extensions(self.input_folder, self.file_types)
# 如果需要跳过已存在的文件
if self.skip_existing:
skip_existing = True
try:
skip_existing = self.config.getboolean('Performance', 'skip_existing', fallback=True)
except:
pass
if skip_existing:
# 过滤已处理的文件
unprocessed_files = self.record_manager.get_unprocessed_files(image_files)
logger.info(f"找到 {len(image_files)} 个图片文件,其中 {len(unprocessed_files)} 个未处理")
@ -186,13 +206,19 @@ class OCRProcessor:
# 检查文件扩展名
ext = get_file_extension(image_path)
if ext not in self.allowed_extensions:
if ext not in self.file_types:
logger.warning(f"不支持的文件类型: {ext}, 文件: {image_path}")
return False
# 检查文件大小
if not is_file_size_valid(image_path, self.max_file_size_mb):
logger.warning(f"文件大小超过限制 ({self.max_file_size_mb}MB): {image_path}")
max_size_mb = 4.0
try:
max_size_mb = float(self.config.get('File', 'max_file_size_mb', fallback='4.0'))
except:
pass
if not is_file_size_valid(image_path, max_size_mb):
logger.warning(f"文件大小超过限制 ({max_size_mb}MB): {image_path}")
return False
return True
@ -211,8 +237,15 @@ class OCRProcessor:
if not self.validate_image(image_path):
return None
# 获取是否跳过已处理文件的配置
skip_existing = True
try:
skip_existing = self.config.getboolean('Performance', 'skip_existing', fallback=True)
except:
pass
# 如果需要跳过已处理的文件
if self.skip_existing and self.record_manager.is_processed(image_path):
if skip_existing and self.record_manager.is_processed(image_path):
output_file = self.record_manager.get_output_file(image_path)
logger.info(f"图片已处理,跳过: {image_path}, 输出文件: {output_file}")
return output_file
@ -220,12 +253,19 @@ class OCRProcessor:
logger.info(f"开始处理图片: {image_path}")
try:
# 获取Excel扩展名
excel_extension = '.xlsx'
try:
excel_extension = self.config.get('File', 'excel_extension', fallback='.xlsx')
except:
pass
# 生成输出文件路径
file_name = os.path.splitext(os.path.basename(image_path))[0]
output_file = os.path.join(self.output_folder, f"{file_name}{self.excel_extension}")
output_file = os.path.join(self.output_folder, f"{file_name}{excel_extension}")
# 检查是否已存在对应的Excel文件
if os.path.exists(output_file) and self.skip_existing:
if os.path.exists(output_file) and skip_existing:
logger.info(f"已存在对应的Excel文件跳过处理: {os.path.basename(image_path)} -> {os.path.basename(output_file)}")
# 记录处理结果
self.record_manager.mark_as_processed(image_path, output_file)
@ -304,8 +344,17 @@ class OCRProcessor:
(总处理数, 成功处理数)元组
"""
# 使用配置值或参数值
batch_size = batch_size or self.batch_size
max_workers = max_workers or self.max_workers
if batch_size is None:
try:
batch_size = self.config.getint('Performance', 'batch_size', fallback=5)
except:
batch_size = 5
if max_workers is None:
try:
max_workers = self.config.getint('Performance', 'max_workers', fallback=4)
except:
max_workers = 4
# 获取未处理的图片
unprocessed_images = self.get_unprocessed_images()
@ -314,21 +363,19 @@ class OCRProcessor:
return 0, 0
total = len(unprocessed_images)
success = 0
success_count = 0
# 按批次处理
for i in range(0, total, batch_size):
batch = unprocessed_images[i:i + batch_size]
logger.info(f"处理批次 {i//batch_size + 1}/{(total-1)//batch_size + 1}, 大小: {len(batch)}")
batch = unprocessed_images[i:i+batch_size]
logger.info(f"处理批次 {i//batch_size+1}/{(total+batch_size-1)//batch_size}: {len(batch)} 个文件")
# 使用线程池并行处理
# 使用线程处理批次
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(self.process_image, batch))
# 统计成功数
success += sum(1 for result in results if result is not None)
success_count += sum(1 for result in results if result is not None)
logger.info(f"批次处理完成, 成功: {sum(1 for result in results if result is not None)}/{len(batch)}")
logger.info(f"所有图片处理完成, 总计: {total}, 成功: {success}")
return total, success
logger.info(f"所有图片处理完成, 总计: {total}, 成功: {success_count}")
return total, success_count

Binary file not shown.

View File

@ -0,0 +1,468 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
对话框工具模块
-------------
提供各种弹窗和对话框显示功能
"""
import os
import tkinter as tk
from tkinter import messagebox, ttk
from datetime import datetime
def create_custom_dialog(title="提示", message="", result_file=None, time_info=None,
count_info=None, amount_info=None, additional_info=None):
"""
创建自定义结果对话框
Args:
title: 对话框标题
message: 主要消息
result_file: 结果文件路径如果有
time_info: 时间信息订单时间
count_info: 数量信息处理条目数
amount_info: 金额信息总金额
additional_info: 其他附加信息字典格式
Returns:
dialog: 对话框对象
"""
# 创建对话框
dialog = tk.Toplevel()
dialog.title(title)
dialog.geometry("450x320")
dialog.resizable(False, False)
# 使弹窗居中显示
center_window(dialog)
# 添加标题
tk.Label(dialog, text=message, font=("Arial", 16, "bold")).pack(pady=10)
# 创建内容框架
result_frame = tk.Frame(dialog)
result_frame.pack(pady=10, fill=tk.BOTH, expand=True)
# 添加时间、数量、金额等信息
if time_info:
tk.Label(result_frame, text=f"时间信息: {time_info}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
if count_info:
tk.Label(result_frame, text=f"处理数量: {count_info}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
if amount_info:
tk.Label(result_frame, text=f"金额信息: {amount_info}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
# 添加其他附加信息
if additional_info and isinstance(additional_info, dict):
for key, value in additional_info.items():
tk.Label(result_frame, text=f"{key}: {value}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
# 如果有结果文件,显示文件信息
if result_file and os.path.exists(result_file):
tk.Label(result_frame, text=f"输出文件: {os.path.basename(result_file)}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
# 成功提示
tk.Label(result_frame, text="处理已成功完成!", font=("Arial", 12, "bold"), fg="#28a745").pack(pady=10)
# 文件信息框
file_frame = tk.Frame(result_frame, relief=tk.GROOVE, borderwidth=1)
file_frame.pack(fill=tk.X, padx=15, pady=5)
tk.Label(file_frame, text="文件信息", font=("Arial", 10, "bold")).pack(anchor=tk.W, padx=10, pady=5)
# 获取文件大小和时间
try:
file_size = os.path.getsize(result_file)
file_time = datetime.fromtimestamp(os.path.getmtime(result_file))
size_text = f"{file_size / 1024:.1f} KB" if file_size < 1024*1024 else f"{file_size / (1024*1024):.1f} MB"
tk.Label(file_frame, text=f"文件大小: {size_text}", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
tk.Label(file_frame, text=f"创建时间: {file_time.strftime('%Y-%m-%d %H:%M:%S')}", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
except:
tk.Label(file_frame, text="无法获取文件信息", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
# 添加按钮
button_frame = tk.Frame(dialog)
button_frame.pack(pady=10)
tk.Button(button_frame, text="打开文件", command=lambda: os.startfile(result_file)).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="打开所在文件夹", command=lambda: os.startfile(os.path.dirname(result_file))).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="关闭", command=dialog.destroy).pack(side=tk.LEFT, padx=5)
else:
# 如果没有结果文件或文件不存在
if result_file:
tk.Label(result_frame, text="未找到输出文件", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
tk.Label(result_frame, text="请检查输出目录", font=("Arial", 12, "bold"), fg="#dc3545").pack(pady=10)
# 添加按钮
button_frame = tk.Frame(dialog)
button_frame.pack(pady=10)
tk.Button(button_frame, text="打开输出目录", command=lambda: os.startfile(os.path.abspath("data/output"))).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="关闭", command=dialog.destroy).pack(side=tk.LEFT, padx=5)
# 确保窗口显示在最前
dialog.lift()
dialog.attributes('-topmost', True)
dialog.after_idle(lambda: dialog.attributes('-topmost', False))
return dialog
def show_custom_dialog(*args, **kwargs):
"""
显示自定义对话框
参数与create_custom_dialog相同
Returns:
dialog: 对话框对象
"""
return create_custom_dialog(*args, **kwargs)
def center_window(window):
"""使窗口居中显示"""
window.update_idletasks()
width = window.winfo_width()
height = window.winfo_height()
x = (window.winfo_screenwidth() // 2) - (width // 2)
y = (window.winfo_screenheight() // 2) - (height // 2)
window.geometry('{}x{}+{}+{}'.format(width, height, x, y))
def create_barcode_mapping_dialog(parent=None, on_save=None, current_mappings=None):
"""
创建条码映射编辑弹窗
Args:
parent: 父窗口
on_save: 保存回调函数接收修改后的映射数据
current_mappings: 当前的映射数据
Returns:
dialog: 对话框对象
"""
dialog = tk.Toplevel(parent)
dialog.title("条码映射编辑")
dialog.geometry("600x500")
dialog.resizable(True, True)
# 使弹窗居中显示
center_window(dialog)
# 创建主框架
main_frame = tk.Frame(dialog)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 创建选项卡控件
tab_control = ttk.Notebook(main_frame)
# 创建两个选项卡页面
tab1 = tk.Frame(tab_control)
tab2 = tk.Frame(tab_control)
tab_control.add(tab1, text="条码映射")
tab_control.add(tab2, text="特殊处理")
tab_control.pack(expand=True, fill=tk.BOTH)
# ========= 条码映射选项卡 =========
# 顶部输入区域
input_frame = tk.Frame(tab1)
input_frame.pack(fill=tk.X, padx=5, pady=5)
tk.Label(input_frame, text="源条码:").grid(row=0, column=0, padx=5, pady=5)
source_entry = tk.Entry(input_frame, width=20)
source_entry.grid(row=0, column=1, padx=5, pady=5)
tk.Label(input_frame, text="目标条码:").grid(row=0, column=2, padx=5, pady=5)
target_entry = tk.Entry(input_frame, width=20)
target_entry.grid(row=0, column=3, padx=5, pady=5)
# 存储映射列表的变量
mapping_list = []
# 映射列表显示区域
list_frame = tk.Frame(tab1)
list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
columns = ("源条码", "目标条码")
mapping_tree = ttk.Treeview(list_frame, columns=columns, show="headings", selectmode="browse")
for col in columns:
mapping_tree.heading(col, text=col)
mapping_tree.column(col, width=100)
mapping_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# 添加滚动条
scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=mapping_tree.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
mapping_tree.configure(yscrollcommand=scrollbar.set)
# ========= 特殊处理选项卡 =========
# 顶部输入区域
special_input_frame = tk.Frame(tab2)
special_input_frame.pack(fill=tk.X, padx=5, pady=5)
tk.Label(special_input_frame, text="条码:").grid(row=0, column=0, padx=5, pady=5)
special_barcode_entry = tk.Entry(special_input_frame, width=20)
special_barcode_entry.grid(row=0, column=1, padx=5, pady=5)
tk.Label(special_input_frame, text="乘数:").grid(row=1, column=0, padx=5, pady=5)
multiplier_entry = tk.Entry(special_input_frame, width=10)
multiplier_entry.grid(row=1, column=1, padx=5, pady=5)
tk.Label(special_input_frame, text="目标单位:").grid(row=1, column=2, padx=5, pady=5)
unit_entry = tk.Entry(special_input_frame, width=10)
unit_entry.grid(row=1, column=3, padx=5, pady=5)
tk.Label(special_input_frame, text="固定单价:").grid(row=2, column=0, padx=5, pady=5)
price_entry = tk.Entry(special_input_frame, width=10)
price_entry.grid(row=2, column=1, padx=5, pady=5)
tk.Label(special_input_frame, text="规格:").grid(row=2, column=2, padx=5, pady=5)
spec_entry = tk.Entry(special_input_frame, width=10)
spec_entry.grid(row=2, column=3, padx=5, pady=5)
tk.Label(special_input_frame, text="描述:").grid(row=3, column=0, padx=5, pady=5)
desc_entry = tk.Entry(special_input_frame, width=40)
desc_entry.grid(row=3, column=1, columnspan=3, padx=5, pady=5)
# 特殊处理列表显示区域
special_list_frame = tk.Frame(tab2)
special_list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
special_columns = ("条码", "乘数", "目标单位", "固定单价", "规格", "描述")
special_tree = ttk.Treeview(special_list_frame, columns=special_columns, show="headings", selectmode="browse")
for col in special_columns:
special_tree.heading(col, text=col)
special_tree.column(col, width=80)
special_tree.column("描述", width=200)
special_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# 添加滚动条
special_scrollbar = ttk.Scrollbar(special_list_frame, orient=tk.VERTICAL, command=special_tree.yview)
special_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
special_tree.configure(yscrollcommand=special_scrollbar.set)
# 存储特殊处理列表的变量
special_list = []
# 按钮区域
def add_mapping():
source = source_entry.get().strip()
target = target_entry.get().strip()
if not source or not target:
messagebox.showwarning("输入错误", "源条码和目标条码不能为空")
return
# 检查是否已存在
for item in mapping_list:
if item[0] == source:
messagebox.showwarning("重复条码", f"条码 {source} 已存在映射")
return
# 添加到列表
mapping_list.append((source, target))
mapping_tree.insert("", tk.END, values=(source, target))
# 清空输入框
source_entry.delete(0, tk.END)
target_entry.delete(0, tk.END)
def remove_mapping():
selected = mapping_tree.selection()
if not selected:
messagebox.showwarning("未选择", "请先选择要删除的条目")
return
# 获取选中项的索引
item = mapping_tree.item(selected[0])
source = item['values'][0]
# 从列表中移除
for i, (s, _) in enumerate(mapping_list):
if s == source:
mapping_list.pop(i)
break
# 从树中移除
mapping_tree.delete(selected[0])
def add_special():
barcode = special_barcode_entry.get().strip()
multiplier = multiplier_entry.get().strip()
unit = unit_entry.get().strip()
price = price_entry.get().strip()
spec = spec_entry.get().strip()
desc = desc_entry.get().strip()
if not barcode:
messagebox.showwarning("输入错误", "条码不能为空")
return
# 检查是否已存在
for item in special_list:
if item[0] == barcode:
messagebox.showwarning("重复条码", f"条码 {barcode} 已存在特殊处理")
return
# 添加到列表
special_list.append((barcode, multiplier, unit, price, spec, desc))
special_tree.insert("", tk.END, values=(barcode, multiplier, unit, price, spec, desc))
# 清空输入框
special_barcode_entry.delete(0, tk.END)
multiplier_entry.delete(0, tk.END)
unit_entry.delete(0, tk.END)
price_entry.delete(0, tk.END)
spec_entry.delete(0, tk.END)
desc_entry.delete(0, tk.END)
def remove_special():
selected = special_tree.selection()
if not selected:
messagebox.showwarning("未选择", "请先选择要删除的条目")
return
# 获取选中项的索引
item = special_tree.item(selected[0])
barcode = item['values'][0]
# 从列表中移除
for i, (b, _, _, _, _, _) in enumerate(special_list):
if b == barcode:
special_list.pop(i)
break
# 从树中移除
special_tree.delete(selected[0])
# 条码映射按钮
btn_frame = tk.Frame(tab1)
btn_frame.pack(fill=tk.X, padx=5, pady=5)
add_btn = tk.Button(btn_frame, text="添加映射", command=add_mapping)
add_btn.pack(side=tk.LEFT, padx=5)
remove_btn = tk.Button(btn_frame, text="删除映射", command=remove_mapping)
remove_btn.pack(side=tk.LEFT, padx=5)
# 特殊处理按钮
special_btn_frame = tk.Frame(tab2)
special_btn_frame.pack(fill=tk.X, padx=5, pady=5)
add_special_btn = tk.Button(special_btn_frame, text="添加特殊处理", command=add_special)
add_special_btn.pack(side=tk.LEFT, padx=5)
remove_special_btn = tk.Button(special_btn_frame, text="删除特殊处理", command=remove_special)
remove_special_btn.pack(side=tk.LEFT, padx=5)
# 底部按钮区域
bottom_frame = tk.Frame(dialog)
bottom_frame.pack(fill=tk.X, padx=10, pady=10)
def save_mappings():
# 构建保存数据
mappings = {}
# 添加条码映射
for source, target in mapping_list:
mappings[source] = {
'map_to': target,
'description': f'条码映射:{source} -> {target}'
}
# 添加特殊处理
for barcode, multiplier, unit, price, spec, desc in special_list:
mappings[barcode] = {}
if multiplier:
try:
# 安全地转换multiplier为数字
if isinstance(multiplier, str):
if '.' in multiplier:
mappings[barcode]['multiplier'] = float(multiplier)
else:
mappings[barcode]['multiplier'] = int(multiplier)
else:
# 已经是数字类型
mappings[barcode]['multiplier'] = multiplier
except ValueError:
# 如果转换失败,保持原始字符串
mappings[barcode]['multiplier'] = multiplier
if unit:
mappings[barcode]['target_unit'] = unit
if price:
try:
# 安全地转换price为浮点数
mappings[barcode]['fixed_price'] = float(price)
except ValueError:
# 如果转换失败,保持原始字符串
mappings[barcode]['fixed_price'] = price
if spec:
mappings[barcode]['specification'] = spec
if desc:
mappings[barcode]['description'] = desc
# 调用保存回调
if on_save:
on_save(mappings)
messagebox.showinfo("保存成功", f"已保存{len(mapping_list)}个条码映射和{len(special_list)}个特殊处理规则")
dialog.destroy()
def cancel():
dialog.destroy()
save_btn = tk.Button(bottom_frame, text="保存", command=save_mappings)
save_btn.pack(side=tk.RIGHT, padx=5)
cancel_btn = tk.Button(bottom_frame, text="取消", command=cancel)
cancel_btn.pack(side=tk.RIGHT, padx=5)
# 导入当前映射数据
if current_mappings:
for barcode, data in current_mappings.items():
if 'map_to' in data:
# 这是条码映射
mapping_list.append((barcode, data['map_to']))
mapping_tree.insert("", tk.END, values=(barcode, data['map_to']))
else:
# 这是特殊处理
multiplier = data.get('multiplier', '')
unit = data.get('target_unit', '')
price = data.get('fixed_price', '')
spec = data.get('specification', '')
desc = data.get('description', '')
special_list.append((barcode, multiplier, unit, price, spec, desc))
special_tree.insert("", tk.END, values=(barcode, multiplier, unit, price, spec, desc))
# 确保窗口显示在最前
dialog.transient(parent)
dialog.grab_set()
return dialog
def show_barcode_mapping_dialog(*args, **kwargs):
"""
显示条码映射编辑弹窗
参数与create_barcode_mapping_dialog相同
Returns:
dialog: 对话框对象
"""
# 确保已导入ttk
import tkinter.ttk as ttk
return create_barcode_mapping_dialog(*args, **kwargs)

View File

@ -97,6 +97,36 @@ def get_logger(name: str) -> logging.Logger:
return setup_logger(name)
return logger
def set_log_level(level: str) -> None:
"""
设置所有日志记录器的级别
Args:
level: 日志级别(DEBUG, INFO, WARNING, ERROR, CRITICAL)
"""
level_map = {
'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'critical': logging.CRITICAL
}
# 获取对应的日志级别
log_level = level_map.get(level.lower(), logging.INFO)
# 获取所有记录器
loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict]
# 设置每个记录器的级别
for logger in loggers:
logger.setLevel(log_level)
# 设置根记录器的级别
logging.getLogger().setLevel(log_level)
print(f"所有日志记录器级别已设置为: {logging.getLevelName(log_level)}")
def close_logger(name: str) -> None:
"""
关闭日志记录器的所有处理器
@ -113,6 +143,25 @@ def close_logger(name: str) -> None:
_handlers.pop(f"{name}_file", None)
_handlers.pop(f"{name}_console", None)
def close_all_loggers() -> None:
"""
关闭所有日志记录器的处理器
"""
# 获取所有记录器
loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict]
# 关闭每个记录器的处理器
for logger in loggers:
if hasattr(logger, 'handlers'):
for handler in logger.handlers[:]:
handler.close()
logger.removeHandler(handler)
# 清空处理器缓存
_handlers.clear()
print("所有日志记录器已关闭")
def cleanup_active_marker(name: str) -> None:
"""
清理日志活跃标记

View File

@ -75,6 +75,21 @@ class OCRService:
logger.info(f"OCRService开始批量处理图片, batch_size={batch_size}, max_workers={max_workers}")
return self.ocr_processor.process_images_batch(batch_size, max_workers)
# 添加batch_process作为process_images_batch的别名确保兼容性
def batch_process(self, batch_size: int = None, max_workers: int = None) -> Tuple[int, int]:
"""
批量处理图片别名方法与process_images_batch功能相同
Args:
batch_size: 批处理大小
max_workers: 最大线程数
Returns:
(总处理数, 成功处理数)元组
"""
logger.info(f"OCRService.batch_process被调用转发到process_images_batch")
return self.process_images_batch(batch_size, max_workers)
def validate_image(self, image_path: str) -> bool:
"""
验证图片是否有效

View File

@ -0,0 +1,255 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
烟草公司订单处理服务
----------------
处理烟草公司特定格式的订单明细文件生成银豹采购单
"""
import os
import glob
import datetime
import pandas as pd
import xlrd
import xlwt
import re
from xlutils.copy import copy
from openpyxl import load_workbook
from typing import Optional, Dict, Any, List, Tuple
from app.core.utils.log_utils import get_logger
from app.core.utils.dialog_utils import show_custom_dialog # 导入自定义弹窗工具
from ..config.settings import ConfigManager
logger = get_logger(__name__)
class TobaccoService:
"""烟草公司订单处理服务"""
def __init__(self, config: Dict[str, Any]):
"""
初始化服务
Args:
config: 配置信息
"""
self.config = config
# 修复配置获取方式使用fallback机制
self.output_dir = config.get('Paths', 'output_folder', fallback='data/output')
self.template_file = config.get('Paths', 'template_file', fallback='templates/银豹-采购单模板.xls')
self.output_file = os.path.join(self.output_dir, '银豹采购单_烟草公司.xls')
def get_latest_tobacco_order(self) -> Optional[str]:
"""
获取最新的烟草订单明细文件
Returns:
文件路径或None
"""
# 获取今日开始时间戳
today = datetime.date.today()
today_start = datetime.datetime.combine(today, datetime.time.min).timestamp()
# 查找订单明细文件
file_pattern = os.path.join(self.output_dir, "订单明细*.xlsx")
candidates = glob.glob(file_pattern)
if not candidates:
logger.warning("未找到烟草公司订单明细文件")
return None
# 按创建时间排序
candidates.sort(key=os.path.getctime, reverse=True)
latest_file = candidates[0]
# 检查是否是今天的文件
if os.path.getctime(latest_file) >= today_start:
logger.info(f"找到最新烟草订单明细文件: {latest_file}")
return latest_file
else:
logger.warning(f"找到的烟草订单明细文件不是今天创建的: {latest_file}")
return latest_file # 仍然返回最新文件,但给出警告
def process_tobacco_order(self, input_file=None):
"""
处理烟草订单
Args:
input_file: 输入文件路径如果为None则自动查找最新文件
Returns:
输出文件路径或None如果处理失败
"""
try:
# 如果没有指定输入文件,查找最新的文件
if input_file is None:
input_file = self.get_latest_tobacco_order()
if input_file is None:
logger.warning("未找到烟草公司订单明细文件")
logger.error("未找到可处理的烟草订单明细文件")
return None
logger.info(f"开始处理烟草公司订单: {input_file}")
# 读取订单时间和总金额
order_info = self._read_order_info(input_file)
if not order_info:
logger.error(f"读取订单信息失败: {input_file}")
return None
order_time, total_amount = order_info
# 读取订单数据
order_data = self._read_order_data(input_file)
if not order_data:
logger.error(f"读取订单数据失败: {input_file}")
return None
# 生成银豹采购单
output_file = self._generate_pospal_order(order_data, order_time)
if not output_file:
logger.error("生成银豹采购单失败")
return None
# 获取处理条目数
total_count = len(order_data)
# 输出处理结果
logger.info(f"烟草公司订单处理成功,订单时间: {order_time}, 总金额: {total_amount}, 处理条目: {total_count}")
logger.info(f"采购单已生成: {output_file}")
# 显示处理结果对话框
self.show_result_dialog(output_file, order_time, total_count, total_amount)
return output_file
except Exception as e:
logger.error(f"处理烟草公司订单时发生错误: {e}", exc_info=True)
return None
def _read_order_info(self, file_path: str) -> Optional[Tuple[str, float]]:
"""
读取订单信息时间和总金额
Args:
file_path: 文件路径
Returns:
包含订单时间和总金额的元组或None
"""
try:
wb_info = load_workbook(file_path, data_only=True)
ws_info = wb_info.active
order_time = ws_info["H1"].value or "(空)"
total_amount = ws_info["H3"].value or 0
return (order_time, total_amount)
except Exception as e:
logger.error(f"读取订单信息出错: {e}")
return None
def _read_order_data(self, file_path: str) -> Optional[pd.DataFrame]:
"""
读取订单数据
Args:
file_path: 文件路径
Returns:
订单数据DataFrame或None
"""
columns = ['商品', '盒码', '条码', '建议零售价', '批发价', '需求量', '订单量', '金额']
try:
# 读取Excel文件
df_old = pd.read_excel(file_path, header=None, skiprows=3, names=columns)
# 过滤订单量不为0的数据并计算采购量和单价
df_filtered = df_old[df_old['订单量'] != 0].copy()
df_filtered['采购量'] = df_filtered['订单量'] * 10
df_filtered['采购单价'] = df_filtered['金额'] / df_filtered['采购量']
df_filtered = df_filtered.reset_index(drop=True)
return df_filtered
except Exception as e:
logger.error(f"读取订单数据失败: {e}")
return None
def _generate_pospal_order(self, order_data: pd.DataFrame, order_time: str) -> Optional[str]:
"""
生成银豹采购单
Args:
order_data: 订单数据
order_time: 订单时间
Returns:
输出文件路径或None
"""
try:
# 检查模板文件是否存在
if not os.path.exists(self.template_file):
logger.error(f"采购单模板文件不存在: {self.template_file}")
return None
# 打开模板,准备写入
template_rd = xlrd.open_workbook(self.template_file, formatting_info=True)
template_wb = copy(template_rd)
template_ws = template_wb.get_sheet(0)
# 获取模板中的表头列索引
header_row = template_rd.sheet_by_index(0).row_values(0)
barcode_col = header_row.index("条码(必填)")
amount_col = header_row.index("采购量(必填)")
gift_col = header_row.index("赠送量")
price_col = header_row.index("采购单价(必填)")
# 写入数据到模板
for i, row in order_data.iterrows():
template_ws.write(i + 1, barcode_col, row['盒码']) # 商品条码
template_ws.write(i + 1, amount_col, int(row['采购量'])) # 采购量
template_ws.write(i + 1, gift_col, "") # 赠送量为空
template_ws.write(i + 1, price_col, round(row['采购单价'], 2)) # 采购单价保留两位小数
# 确保输出目录存在
os.makedirs(os.path.dirname(self.output_file), exist_ok=True)
# 保存输出文件
template_wb.save(self.output_file)
logger.info(f"采购单生成成功: {self.output_file}")
return self.output_file
except Exception as e:
logger.error(f"生成银豹采购单失败: {e}")
return None
def show_result_dialog(self, output_file, order_time, total_count, total_amount):
"""
显示处理结果对话框
Args:
output_file: 输出文件路径
order_time: 订单时间
total_count: 总处理条目
total_amount: 总金额
"""
# 创建附加信息
additional_info = {
"订单来源": "烟草公司",
"处理时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
# 显示自定义对话框
show_custom_dialog(
title="烟草订单处理结果",
message="烟草订单处理完成",
result_file=output_file,
time_info=order_time,
count_info=f"{total_count}个商品",
amount_info=f"¥{total_amount:.2f}",
additional_info=additional_info
)
# 记录日志
logger.info(f"烟草公司订单处理成功,订单时间: {order_time}, 总金额: {total_amount}, 处理条目: {total_count}")

View File

@ -0,0 +1,35 @@
{
"6920584471055": {
"map_to": "6920584471017",
"description": "条码映射6920584471055 -> 6920584471017"
},
"6925861571159": {
"map_to": "69021824",
"description": "条码映射6925861571159 -> 69021824"
},
"6923644268923": {
"map_to": "6923644268480",
"description": "条码映射6923644268923 -> 6923644268480"
},
"6925861571466": {
"map_to": "6925861571459",
"description": "条码映射6925861571466 -> 6925861571459"
},
"6925019900087": {
"multiplier": 10,
"target_unit": "瓶",
"description": "特殊处理:数量*10单位转换为瓶"
},
"6921168593804": {
"multiplier": 30,
"target_unit": "瓶",
"description": "NFC产品特殊处理每箱30瓶"
},
"6901826888138": {
"multiplier": 30,
"target_unit": "瓶",
"fixed_price": 3.7333333333333334,
"specification": "1*30",
"description": "特殊处理: 规格1*30数量*30单价=112/30"
}
}

1
logs/__main__.active Normal file
View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:39

View File

@ -385,3 +385,57 @@
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
2025-05-09 11:55:03,576 - __main__ - INFO - 配置信息: <configparser.ConfigParser object at 0x000002AD48FC6310>
2025-05-09 11:58:49,250 - __main__ - INFO - 配置信息: <configparser.ConfigParser object at 0x000002784E8172E0>
2025-05-09 12:02:05,165 - __main__ - INFO - 配置信息: <configparser.ConfigParser object at 0x0000029382E282B0>
2025-05-09 12:07:05,179 - __main__ - INFO - 配置信息: <configparser.ConfigParser object at 0x000001B1A2BE82E0>
2025-05-09 12:07:54,655 - __main__ - INFO - 配置信息: <configparser.ConfigParser object at 0x0000014A9D9D8400>
2025-05-09 12:12:42,101 - __main__ - INFO - 配置信息: <configparser.ConfigParser object at 0x00000263F3448400>
2025-05-09 12:13:52,578 - __main__ - INFO - 配置信息: <configparser.ConfigParser object at 0x00000244BAAA73D0>
2025-05-09 12:45:35,994 - __main__ - INFO - 配置信息: <configparser.ConfigParser object at 0x000001E499EA73A0>
2025-05-09 12:45:35,999 - __main__ - INFO - 开始烟草公司订单处理
2025-05-09 12:45:36,000 - __main__ - INFO - 处理最新的烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 12:45:36,103 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:21:53,249 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:22:48,497 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:25:59,111 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:29:28,837 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:30:21,973 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:30:43,780 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:34:49,132 - __main__ - INFO - 开始烟草公司订单处理
2025-05-09 13:34:49,291 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:34:49,291 - __main__ - INFO - 烟草订单处理完成,绝对路径: D:\My Documents\python\orc-order-v2\data\output\银豹采购单_烟草公司.xls
2025-05-09 13:37:56,253 - __main__ - INFO - 开始烟草公司订单处理
2025-05-09 13:37:56,482 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:37:56,482 - __main__ - INFO - 烟草订单处理完成,绝对路径: D:\My Documents\python\orc-order-v2\data\output\银豹采购单_烟草公司.xls
2025-05-09 13:39:38,187 - __main__ - ERROR - 执行过程中发生错误: 'OrderService' object has no attribute 'merge_all_purchase_orders'
Traceback (most recent call last):
File "D:\My Documents\python\orc-order-v2\run.py", line 128, in main
result = order_service.merge_all_purchase_orders()
AttributeError: 'OrderService' object has no attribute 'merge_all_purchase_orders'
2025-05-09 13:39:52,436 - __main__ - INFO - 开始烟草公司订单处理
2025-05-09 13:39:52,581 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:39:52,581 - __main__ - INFO - 烟草订单处理完成,绝对路径: D:\My Documents\python\orc-order-v2\data\output\银豹采购单_烟草公司.xls
2025-05-09 13:50:34,352 - __main__ - INFO - 开始烟草公司订单处理
2025-05-09 13:50:34,773 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:50:34,773 - __main__ - INFO - 烟草订单处理完成,绝对路径: D:\My Documents\python\orc-order-v2\data\output\银豹采购单_烟草公司.xls
2025-05-09 13:52:17,577 - __main__ - INFO - 开始烟草公司订单处理
2025-05-09 13:52:17,706 - __main__ - INFO - 烟草订单处理成功,输出文件: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:52:17,707 - __main__ - INFO - 烟草订单处理完成,绝对路径: D:\My Documents\python\orc-order-v2\data\output\银豹采购单_烟草公司.xls
2025-05-09 14:26:54,513 - __main__ - ERROR - 执行过程中发生错误: 'OrderService' object has no attribute 'process_latest_excel'
Traceback (most recent call last):
File "D:\My Documents\python\orc-order-v2\run.py", line 116, in main
result = order_service.process_latest_excel()
AttributeError: 'OrderService' object has no attribute 'process_latest_excel'
2025-05-09 14:27:08,881 - __main__ - ERROR - 执行过程中发生错误: 'OCRService' object has no attribute 'batch_process'
Traceback (most recent call last):
File "D:\My Documents\python\orc-order-v2\run.py", line 98, in main
total, success = ocr_service.batch_process(
AttributeError: 'OCRService' object has no attribute 'batch_process'
2025-05-09 14:27:31,662 - __main__ - ERROR - 执行过程中发生错误: 'OCRService' object has no attribute 'batch_process'
Traceback (most recent call last):
File "D:\My Documents\python\orc-order-v2\run.py", line 98, in main
total, success = ocr_service.batch_process(
AttributeError: 'OCRService' object has no attribute 'batch_process'
2025-05-09 14:32:56,697 - __main__ - INFO - 开始烟草公司订单处理
2025-05-09 14:32:56,706 - __main__ - ERROR - 烟草订单处理失败

View File

@ -0,0 +1 @@
Active since: 2025-05-10 11:21:12

View File

@ -1871,3 +1871,109 @@
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
2025-05-09 14:08:44,053 - app.core.excel.converter - INFO - 解析二级规格: 1*20 -> 1*20
2025-05-09 14:08:44,053 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 10.0, 单位: 瓶
2025-05-09 14:08:44,055 - app.core.excel.converter - INFO - 解析二级规格: 1*48 -> 1*48
2025-05-09 14:08:44,055 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 10.0, 单价: 2.3, 单位: 杯
2025-05-09 14:08:44,056 - app.core.excel.converter - INFO - 解析二级规格: 1*10组*5瓶 -> 1*10
2025-05-09 14:08:44,056 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 9.0, 单位: 组
2025-05-09 14:08:44,057 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:08:44,057 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 3.0, 单位: 袋
2025-05-09 14:08:44,057 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:08:44,058 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 3.0, 单位: 袋
2025-05-09 14:08:44,058 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:08:44,058 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 3.0, 单位: 袋
2025-05-09 14:08:44,060 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:08:44,060 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 3.0, 单位: 袋
2025-05-09 14:08:44,106 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:08:44,106 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 10.0, 单位: 瓶
2025-05-09 14:08:44,107 - app.core.excel.converter - INFO - 解析二级规格: 1*20 -> 1*20
2025-05-09 14:08:44,107 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 7.5, 单位: 瓶
2025-05-09 14:08:44,108 - app.core.excel.converter - INFO - 解析二级规格: 1*20 -> 1*20
2025-05-09 14:08:44,108 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 6.3, 单位: 瓶
2025-05-09 14:08:44,108 - app.core.excel.converter - INFO - 解析二级规格: 1*20 -> 1*20
2025-05-09 14:08:44,108 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 6.3, 单位: 瓶
2025-05-09 14:08:44,109 - app.core.excel.converter - INFO - 解析二级规格: 1*24 -> 1*24
2025-05-09 14:08:44,109 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 7.1, 单位: 瓶
2025-05-09 14:08:44,110 - app.core.excel.converter - INFO - 解析二级规格: 1*16 -> 1*16
2025-05-09 14:08:44,110 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 8.0, 单价: 3.0, 单位: 袋
2025-05-09 14:08:44,111 - app.core.excel.converter - INFO - 解析二级规格: 1*16 -> 1*16
2025-05-09 14:08:44,111 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 4.0, 单价: 6.5, 单位: 杯
2025-05-09 14:08:44,111 - app.core.excel.converter - INFO - 解析二级规格: 1*24 -> 1*24
2025-05-09 14:08:44,111 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 5.5, 单位: 瓶
2025-05-09 14:23:40,858 - app.core.excel.converter - INFO - 解析二级规格: 1*20 -> 1*20
2025-05-09 14:23:40,865 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 10.0, 单位: 瓶
2025-05-09 14:23:40,878 - app.core.excel.converter - INFO - 解析二级规格: 1*48 -> 1*48
2025-05-09 14:23:40,878 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 10.0, 单价: 2.3, 单位: 杯
2025-05-09 14:23:40,879 - app.core.excel.converter - INFO - 解析二级规格: 1*10组*5瓶 -> 1*10
2025-05-09 14:23:40,880 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 9.0, 单位: 组
2025-05-09 14:23:40,888 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:23:40,888 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 3.0, 单位: 袋
2025-05-09 14:23:40,890 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:23:40,890 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 3.0, 单位: 袋
2025-05-09 14:23:40,896 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:23:40,896 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 3.0, 单位: 袋
2025-05-09 14:23:40,897 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:23:40,897 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 3.0, 单位: 袋
2025-05-09 14:23:40,898 - app.core.excel.converter - INFO - 解析二级规格: 1*12 -> 1*12
2025-05-09 14:23:40,899 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 10.0, 单位: 瓶
2025-05-09 14:23:40,900 - app.core.excel.converter - INFO - 解析二级规格: 1*20 -> 1*20
2025-05-09 14:23:40,900 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 7.5, 单位: 瓶
2025-05-09 14:23:41,461 - app.core.excel.converter - INFO - 解析二级规格: 1*20 -> 1*20
2025-05-09 14:23:41,461 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 6.3, 单位: 瓶
2025-05-09 14:23:41,462 - app.core.excel.converter - INFO - 解析二级规格: 1*20 -> 1*20
2025-05-09 14:23:41,462 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 6.3, 单位: 瓶
2025-05-09 14:23:41,462 - app.core.excel.converter - INFO - 解析二级规格: 1*24 -> 1*24
2025-05-09 14:23:41,463 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 2.0, 单价: 7.1, 单位: 瓶
2025-05-09 14:23:41,463 - app.core.excel.converter - INFO - 解析二级规格: 1*16 -> 1*16
2025-05-09 14:23:41,464 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 8.0, 单价: 3.0, 单位: 袋
2025-05-09 14:23:41,465 - app.core.excel.converter - INFO - 解析二级规格: 1*16 -> 1*16
2025-05-09 14:23:41,465 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 4.0, 单价: 6.5, 单位: 杯
2025-05-09 14:23:41,466 - app.core.excel.converter - INFO - 解析二级规格: 1*24 -> 1*24
2025-05-09 14:23:41,466 - app.core.excel.converter - INFO - 其他单位处理: 保持原样 数量: 6.0, 单价: 5.5, 单位: 瓶
2025-05-09 14:31:54,333 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 14:31:54,334 - app.core.excel.converter - INFO - 解析容量(ml)规格: 260ML*24 -> 1*24
2025-05-09 14:31:54,338 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 14:31:54,339 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 14:31:54,341 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 14:31:54,342 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 14:31:54,432 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 14:31:54,432 - app.core.excel.converter - INFO - 解析容量(ml)规格: 245ML*12 -> 1*12
2025-05-09 14:31:54,433 - app.core.excel.converter - INFO - 解析容量(ml)规格: 125ML*36 -> 1*36
2025-05-09 14:31:54,434 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 14:31:54,434 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*24 -> 1*24
2025-05-09 14:31:54,435 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*24 -> 1*24
2025-05-09 14:31:54,435 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*24 -> 1*24
2025-05-09 14:31:54,436 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 14:32:21,071 - app.core.excel.converter - INFO - 解析容量(ml)规格: 500ml*15 -> 1*15
2025-05-09 14:32:21,077 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,081 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,082 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,083 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,086 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,214 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,215 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,217 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,218 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 14:32:21,219 - app.core.excel.converter - INFO - 解析容量(L)规格: 1L*12 -> 1*12
2025-05-09 15:15:10,369 - app.core.excel.converter - INFO - 条码映射配置保存成功共6项
2025-05-09 15:15:10,377 - app.core.excel.converter - INFO - 创建默认条码映射配置共6项
2025-05-09 16:01:39,293 - app.core.excel.converter - INFO - 成功加载条码映射配置共6项
2025-05-09 16:01:39,480 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 16:01:39,481 - app.core.excel.converter - INFO - 解析容量(ml)规格: 260ML*24 -> 1*24
2025-05-09 16:01:39,482 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 16:01:39,483 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 16:01:39,484 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 16:01:39,484 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 16:01:39,485 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 16:01:39,711 - app.core.excel.converter - INFO - 解析容量(ml)规格: 245ML*12 -> 1*12
2025-05-09 16:01:39,712 - app.core.excel.converter - INFO - 解析容量(ml)规格: 125ML*36 -> 1*36
2025-05-09 16:01:39,713 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 16:01:39,714 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*24 -> 1*24
2025-05-09 16:01:39,715 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*24 -> 1*24
2025-05-09 16:01:39,716 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*24 -> 1*24
2025-05-09 16:01:39,717 - app.core.excel.converter - INFO - 解析容量(ml)规格: 250ML*12 -> 1*12
2025-05-09 16:03:48,340 - app.core.excel.converter - INFO - 成功加载条码映射配置共6项
2025-05-09 16:07:24,661 - app.core.excel.converter - INFO - 成功加载条码映射配置共6项
2025-05-09 16:08:24,335 - app.core.excel.converter - INFO - 条码映射配置保存成功共7项
2025-05-09 16:08:28,902 - app.core.excel.converter - INFO - 成功加载条码映射配置共7项

View File

@ -0,0 +1 @@
Active since: 2025-05-10 11:21:12

View File

@ -0,0 +1,9 @@
2025-05-09 14:31:54,337 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6923644283582 -> 6923644283575
2025-05-09 14:31:54,340 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6923644268930 -> 6923644268497
2025-05-09 14:31:54,341 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6923644268916 -> 6923644268503
2025-05-09 14:31:54,432 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6920584471055 -> 6920584471017
2025-05-09 14:31:54,433 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6925861571159 -> 69021824
2025-05-09 14:31:54,434 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6923644210151 -> 6923644223458
2025-05-09 14:31:54,435 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6907992501819 -> 6907992500133
2025-05-09 16:01:39,710 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6920584471055 -> 6920584471017
2025-05-09 16:01:39,712 - app.core.excel.handlers.barcode_mapper - INFO - 条码映射: 6925861571159 -> 69021824

View File

@ -0,0 +1 @@
Active since: 2025-05-10 11:21:12

View File

@ -33,3 +33,42 @@
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, 单位: 瓶
2025-05-09 14:31:54,333 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 52.0 -> 4.333333333333333, 单位: 件 -> 瓶
2025-05-09 14:31:54,334 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 3.0 -> 72.0, 单价: 50.0 -> 2.0833333333333335, 单位: 件 -> 瓶
2025-05-09 14:31:54,338 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 30.0 -> 2.5, 单位: 件 -> 瓶
2025-05-09 14:31:54,340 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 30.0 -> 2.5, 单位: 件 -> 瓶
2025-05-09 14:31:54,341 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 30.0 -> 2.5, 单位: 件 -> 瓶
2025-05-09 14:31:54,342 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 30.0 -> 2.5, 单位: 件 -> 瓶
2025-05-09 14:31:54,432 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 4.0 -> 48.0, 单价: 45.0 -> 3.75, 单位: 件 -> 瓶
2025-05-09 14:31:54,433 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 50.0 -> 4.166666666666667, 单位: 件 -> 瓶
2025-05-09 14:31:54,433 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 72.0, 单价: 65.0 -> 1.8055555555555556, 单位: 件 -> 瓶
2025-05-09 14:31:54,434 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 45.0 -> 3.75, 单位: 件 -> 瓶
2025-05-09 14:31:54,435 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 3.0 -> 72.0, 单价: 55.0 -> 2.2916666666666665, 单位: 件 -> 瓶
2025-05-09 14:31:54,435 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 3.0 -> 72.0, 单价: 63.0 -> 2.625, 单位: 件 -> 瓶
2025-05-09 14:31:54,436 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 3.0 -> 72.0, 单价: 54.0 -> 2.25, 单位: 件 -> 瓶
2025-05-09 14:31:54,436 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,072 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 15.0, 单价: 33.0 -> 2.2, 单位: 件 -> 瓶
2025-05-09 14:32:21,077 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,081 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,082 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,084 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,086 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,214 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,215 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,217 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶
2025-05-09 14:32:21,218 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品件单位处理: 数量: 1.0 -> 12.0, 单价: 0, 单位: 件 -> 瓶
2025-05-09 14:32:21,219 - app.core.excel.handlers.unit_converter_handlers - INFO - 赠品瓶单位处理: 保持原样 数量: 1.0, 单价: 0, 单位: 瓶
2025-05-09 16:01:39,480 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 52.0 -> 4.333333333333333, 单位: 件 -> 瓶
2025-05-09 16:01:39,481 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 3.0 -> 72.0, 单价: 50.0 -> 2.0833333333333335, 单位: 件 -> 瓶
2025-05-09 16:01:39,482 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 30.0 -> 2.5, 单位: 件 -> 瓶
2025-05-09 16:01:39,483 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 30.0 -> 2.5, 单位: 件 -> 瓶
2025-05-09 16:01:39,484 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 30.0 -> 2.5, 单位: 件 -> 瓶
2025-05-09 16:01:39,485 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 30.0 -> 2.5, 单位: 件 -> 瓶
2025-05-09 16:01:39,485 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 4.0 -> 48.0, 单价: 45.0 -> 3.75, 单位: 件 -> 瓶
2025-05-09 16:01:39,711 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 50.0 -> 4.166666666666667, 单位: 件 -> 瓶
2025-05-09 16:01:39,712 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 72.0, 单价: 65.0 -> 1.8055555555555556, 单位: 件 -> 瓶
2025-05-09 16:01:39,713 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 1.0 -> 12.0, 单价: 45.0 -> 3.75, 单位: 件 -> 瓶
2025-05-09 16:01:39,714 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 3.0 -> 72.0, 单价: 55.0 -> 2.2916666666666665, 单位: 件 -> 瓶
2025-05-09 16:01:39,715 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 3.0 -> 72.0, 单价: 63.0 -> 2.625, 单位: 件 -> 瓶
2025-05-09 16:01:39,716 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 3.0 -> 72.0, 单价: 54.0 -> 2.25, 单位: 件 -> 瓶
2025-05-09 16:01:39,717 - app.core.excel.handlers.unit_converter_handlers - INFO - 件单位处理: 数量: 2.0 -> 24.0, 单价: 42.0 -> 3.5, 单位: 件 -> 瓶

View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:38

View File

@ -493,3 +493,22 @@
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
2025-05-09 12:12:42,109 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger
2025-05-09 12:13:52,585 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:13:52,585 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls
2025-05-09 12:45:35,998 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:45:35,998 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls
2025-05-09 13:39:38,184 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 13:39:38,186 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls
2025-05-09 14:08:43,903 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:08:43,903 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls
2025-05-09 14:23:40,515 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:23:40,515 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls
2025-05-09 14:26:54,510 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:26:54,511 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls
2025-05-09 14:31:54,258 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:31:54,259 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls
2025-05-09 14:32:20,941 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:32:20,942 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls
2025-05-09 16:01:39,294 - app.core.excel.merger - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 16:01:39,294 - app.core.excel.merger - INFO - 初始化PurchaseOrderMerger完成模板文件: templates\银豹-采购单模板.xls

View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:38

View File

@ -5753,3 +5753,448 @@ ValueError: could not convert string to float: '2\n96'
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
2025-05-09 12:07:05,182 - app.core.excel.processor - INFO - 初始化ExcelProcessor
2025-05-09 12:07:54,661 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:07:54,661 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:07:54,661 - app.core.excel.processor - ERROR - 初始化ExcelProcessor失败: name 'TableHeaderFinder' is not defined
2025-05-09 12:12:42,106 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:12:42,107 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:12:42,108 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 12:13:52,582 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:13:52,582 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:13:52,584 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 12:45:35,997 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:45:35,998 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:45:35,998 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 13:39:38,182 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 13:39:38,183 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 13:39:38,183 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 14:08:43,902 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:08:43,902 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 14:08:43,902 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 14:08:43,903 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/高新-益选便利店销售单2025-05-09.xlsx
2025-05-09 14:08:43,986 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/高新-益选便利店销售单2025-05-09.xlsx, 共 21 行
2025-05-09 14:08:43,992 - app.core.excel.processor - INFO - 找到可能的表头行: 第5行评分: 60
2025-05-09 14:08:43,992 - app.core.excel.processor - INFO - 识别到表头在第 5 行
2025-05-09 14:08:44,045 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 16 行有效数据
2025-05-09 14:08:44,045 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
2025-05-09 14:08:44,045 - app.core.excel.processor - INFO - 使用条码列: 商品条码
2025-05-09 14:08:44,045 - app.core.excel.processor - INFO - 找到name列: 商品名称
2025-05-09 14:08:44,045 - app.core.excel.processor - INFO - 找到specification列: 规格
2025-05-09 14:08:44,046 - app.core.excel.processor - INFO - 找到quantity列: 数量
2025-05-09 14:08:44,046 - app.core.excel.processor - INFO - 找到unit列: 单位
2025-05-09 14:08:44,046 - app.core.excel.processor - INFO - 找到price列: 单价
2025-05-09 14:08:44,046 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品名称', 'specification': '规格', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
2025-05-09 14:08:44,046 - app.core.excel.processor - INFO - 是否存在规格列: True
2025-05-09 14:08:44,047 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6901209255021, 名称=光明look噜渴458ml, 规格=, 数量=2.0, 单位=瓶, 单价=10.0
2025-05-09 14:08:44,050 - app.core.excel.processor - INFO - 解析规格: 1*20 -> 包装数量=20
2025-05-09 14:08:44,054 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6907992103587, 名称=伊利U形红枣杯160g, 规格=, 数量=10.0, 单位=杯, 单价=2.3
2025-05-09 14:08:44,054 - app.core.excel.processor - INFO - 解析规格: 1*48 -> 包装数量=48
2025-05-09 14:08:44,055 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6907992102726, 名称=伊利每益添100ml, 规格=, 数量=2.0, 单位=组, 单价=9.0
2025-05-09 14:08:44,056 - app.core.excel.processor - INFO - 解析规格: 1*10组*5瓶 -> 包装数量=10
2025-05-09 14:08:44,057 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6975382530176, 名称=海河草莓味牛奶220ml, 规格=, 数量=6.0, 单位=袋, 单价=3.0
2025-05-09 14:08:44,057 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:08:44,057 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6975382531333, 名称=海河玫瑰荔枝味220g, 规格=, 数量=6.0, 单位=袋, 单价=3.0
2025-05-09 14:08:44,057 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:08:44,058 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6975382531142, 名称=海河樱花白桃牛奶220ml, 规格=, 数量=6.0, 单位=袋, 单价=3.0
2025-05-09 14:08:44,058 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:08:44,058 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6975382530350, 名称=海河可可牛奶220ml, 规格=, 数量=6.0, 单位=袋, 单价=3.0
2025-05-09 14:08:44,060 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:08:44,106 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6907992106915, 名称=伊利天然牧场鲜牛奶405ml, 规格=, 数量=2.0, 单位=瓶, 单价=10.0
2025-05-09 14:08:44,106 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:08:44,106 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6907992103594, 名称=伊利桶红枣酸牛奶450ml, 规格=, 数量=2.0, 单位=瓶, 单价=7.5
2025-05-09 14:08:44,106 - app.core.excel.processor - INFO - 解析规格: 1*20 -> 包装数量=20
2025-05-09 14:08:44,107 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6907992108018, 名称=伊利每益添果蔬益生菌饮品羽衣甘蓝+猕猴桃330ml, 规格=, 数量=2.0, 单位=瓶, 单价=6.3
2025-05-09 14:08:44,107 - app.core.excel.processor - INFO - 解析规格: 1*20 -> 包装数量=20
2025-05-09 14:08:44,108 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6907992108025, 名称=伊利每益添果蔬益生菌饮品红甜菜+樱桃330ml, 规格=, 数量=2.0, 单位=瓶, 单价=6.3
2025-05-09 14:08:44,108 - app.core.excel.processor - INFO - 解析规格: 1*20 -> 包装数量=20
2025-05-09 14:08:44,109 - app.core.excel.processor - INFO - 第12行: 提取商品信息 条码=6907992107639, 名称=伊利250ml畅轻西柚芒果+青稞爆珠风味发酵乳, 规格=, 数量=2.0, 单位=瓶, 单价=7.1
2025-05-09 14:08:44,109 - app.core.excel.processor - INFO - 解析规格: 1*24 -> 包装数量=24
2025-05-09 14:08:44,110 - app.core.excel.processor - INFO - 第13行: 提取商品信息 条码=6903979800999, 名称=菊乐嚼酸奶(燕麦百香果味)170g*16, 规格=, 数量=8.0, 单位=袋, 单价=3.0
2025-05-09 14:08:44,110 - app.core.excel.processor - INFO - 解析规格: 1*16 -> 包装数量=16
2025-05-09 14:08:44,110 - app.core.excel.processor - INFO - 第14行: 提取商品信息 条码=6907992106861, 名称=伊利-大口嚼180克, 规格=, 数量=4.0, 单位=杯, 单价=6.5
2025-05-09 14:08:44,110 - app.core.excel.processor - INFO - 解析规格: 1*16 -> 包装数量=16
2025-05-09 14:08:44,111 - app.core.excel.processor - INFO - 第15行: 提取商品信息 条码=6934665087653, 名称=蒙牛优益c原味340, 规格=, 数量=6.0, 单位=瓶, 单价=5.5
2025-05-09 14:08:44,111 - app.core.excel.processor - INFO - 解析规格: 1*24 -> 包装数量=24
2025-05-09 14:08:44,112 - app.core.excel.processor - INFO - 提取到 15 个商品信息
2025-05-09 14:08:44,125 - app.core.excel.processor - INFO - 开始处理15 个产品信息
2025-05-09 14:08:44,125 - app.core.excel.processor - INFO - 处理商品: 条码=6901209255021, 数量=2.0, 单价=10.0, 是否赠品=False
2025-05-09 14:08:44,126 - app.core.excel.processor - INFO - 发现正常商品条码6901209255021, 数量=2.0, 单价=10.0
2025-05-09 14:08:47,592 - app.core.excel.processor - INFO - 处理商品: 条码=6907992103587, 数量=10.0, 单价=2.3, 是否赠品=False
2025-05-09 14:08:47,592 - app.core.excel.processor - INFO - 发现正常商品条码6907992103587, 数量=10.0, 单价=2.3
2025-05-09 14:08:47,592 - app.core.excel.processor - INFO - 处理商品: 条码=6907992102726, 数量=2.0, 单价=9.0, 是否赠品=False
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 发现正常商品条码6907992102726, 数量=2.0, 单价=9.0
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 处理商品: 条码=6975382530176, 数量=6.0, 单价=3.0, 是否赠品=False
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 发现正常商品条码6975382530176, 数量=6.0, 单价=3.0
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 处理商品: 条码=6975382531333, 数量=6.0, 单价=3.0, 是否赠品=False
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 发现正常商品条码6975382531333, 数量=6.0, 单价=3.0
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 处理商品: 条码=6975382531142, 数量=6.0, 单价=3.0, 是否赠品=False
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 发现正常商品条码6975382531142, 数量=6.0, 单价=3.0
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 处理商品: 条码=6975382530350, 数量=6.0, 单价=3.0, 是否赠品=False
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 发现正常商品条码6975382530350, 数量=6.0, 单价=3.0
2025-05-09 14:08:47,593 - app.core.excel.processor - INFO - 处理商品: 条码=6907992106915, 数量=2.0, 单价=10.0, 是否赠品=False
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 发现正常商品条码6907992106915, 数量=2.0, 单价=10.0
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 处理商品: 条码=6907992103594, 数量=2.0, 单价=7.5, 是否赠品=False
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 发现正常商品条码6907992103594, 数量=2.0, 单价=7.5
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 处理商品: 条码=6907992108018, 数量=2.0, 单价=6.3, 是否赠品=False
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 发现正常商品条码6907992108018, 数量=2.0, 单价=6.3
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 处理商品: 条码=6907992108025, 数量=2.0, 单价=6.3, 是否赠品=False
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 发现正常商品条码6907992108025, 数量=2.0, 单价=6.3
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 处理商品: 条码=6907992107639, 数量=2.0, 单价=7.1, 是否赠品=False
2025-05-09 14:08:47,594 - app.core.excel.processor - INFO - 发现正常商品条码6907992107639, 数量=2.0, 单价=7.1
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 处理商品: 条码=6903979800999, 数量=8.0, 单价=3.0, 是否赠品=False
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 发现正常商品条码6903979800999, 数量=8.0, 单价=3.0
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 处理商品: 条码=6907992106861, 数量=4.0, 单价=6.5, 是否赠品=False
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 发现正常商品条码6907992106861, 数量=4.0, 单价=6.5
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 处理商品: 条码=6934665087653, 数量=6.0, 单价=5.5, 是否赠品=False
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 发现正常商品条码6934665087653, 数量=6.0, 单价=5.5
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 分组后共15 个不同条码的商品
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 条码 6901209255021 处理结果正常商品数量2.0单价10.0赠品数量0
2025-05-09 14:08:47,595 - app.core.excel.processor - INFO - 条码 6907992103587 处理结果正常商品数量10.0单价2.3赠品数量0
2025-05-09 14:08:47,596 - app.core.excel.processor - INFO - 条码 6907992102726 处理结果正常商品数量2.0单价9.0赠品数量0
2025-05-09 14:08:47,596 - app.core.excel.processor - INFO - 条码 6975382530176 处理结果正常商品数量6.0单价3.0赠品数量0
2025-05-09 14:08:47,596 - app.core.excel.processor - INFO - 条码 6975382531333 处理结果正常商品数量6.0单价3.0赠品数量0
2025-05-09 14:08:47,596 - app.core.excel.processor - INFO - 条码 6975382531142 处理结果正常商品数量6.0单价3.0赠品数量0
2025-05-09 14:08:51,773 - app.core.excel.processor - INFO - 条码 6975382530350 处理结果正常商品数量6.0单价3.0赠品数量0
2025-05-09 14:08:51,773 - app.core.excel.processor - INFO - 条码 6907992106915 处理结果正常商品数量2.0单价10.0赠品数量0
2025-05-09 14:08:51,773 - app.core.excel.processor - INFO - 条码 6907992103594 处理结果正常商品数量2.0单价7.5赠品数量0
2025-05-09 14:08:51,774 - app.core.excel.processor - INFO - 条码 6907992108018 处理结果正常商品数量2.0单价6.3赠品数量0
2025-05-09 14:08:51,774 - app.core.excel.processor - INFO - 条码 6907992108025 处理结果正常商品数量2.0单价6.3赠品数量0
2025-05-09 14:08:51,774 - app.core.excel.processor - INFO - 条码 6907992107639 处理结果正常商品数量2.0单价7.1赠品数量0
2025-05-09 14:08:51,774 - app.core.excel.processor - INFO - 条码 6903979800999 处理结果正常商品数量8.0单价3.0赠品数量0
2025-05-09 14:08:51,774 - app.core.excel.processor - INFO - 条码 6907992106861 处理结果正常商品数量4.0单价6.5赠品数量0
2025-05-09 14:08:51,774 - app.core.excel.processor - INFO - 条码 6934665087653 处理结果正常商品数量6.0单价5.5赠品数量0
2025-05-09 14:08:51,778 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_高新-益选便利店销售单2025-05-09.xls
2025-05-09 14:08:51,780 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_高新-益选便利店销售单2025-05-09.xls
2025-05-09 14:23:40,514 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:23:40,514 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 14:23:40,514 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 14:23:40,516 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/高新-益选便利店销售单2025-05-09.xlsx
2025-05-09 14:23:40,658 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/高新-益选便利店销售单2025-05-09.xlsx, 共 21 行
2025-05-09 14:23:40,668 - app.core.excel.processor - INFO - 找到可能的表头行: 第5行评分: 60
2025-05-09 14:23:40,669 - app.core.excel.processor - INFO - 识别到表头在第 5 行
2025-05-09 14:23:40,841 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 16 行有效数据
2025-05-09 14:23:40,841 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
2025-05-09 14:23:40,841 - app.core.excel.processor - INFO - 使用条码列: 商品条码
2025-05-09 14:23:40,842 - app.core.excel.processor - INFO - 找到name列: 商品名称
2025-05-09 14:23:40,842 - app.core.excel.processor - INFO - 找到specification列: 规格
2025-05-09 14:23:40,842 - app.core.excel.processor - INFO - 找到quantity列: 数量
2025-05-09 14:23:40,843 - app.core.excel.processor - INFO - 找到unit列: 单位
2025-05-09 14:23:40,843 - app.core.excel.processor - INFO - 找到price列: 单价
2025-05-09 14:23:40,843 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品名称', 'specification': '规格', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
2025-05-09 14:23:40,843 - app.core.excel.processor - INFO - 是否存在规格列: True
2025-05-09 14:23:40,845 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6901209255021, 名称=光明look噜渴458ml, 规格=, 数量=2.0, 单位=瓶, 单价=10.0
2025-05-09 14:23:40,851 - app.core.excel.processor - INFO - 解析规格: 1*20 -> 包装数量=20
2025-05-09 14:23:40,877 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6907992103587, 名称=伊利U形红枣杯160g, 规格=, 数量=10.0, 单位=杯, 单价=2.3
2025-05-09 14:23:40,877 - app.core.excel.processor - INFO - 解析规格: 1*48 -> 包装数量=48
2025-05-09 14:23:40,879 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6907992102726, 名称=伊利每益添100ml, 规格=, 数量=2.0, 单位=组, 单价=9.0
2025-05-09 14:23:40,879 - app.core.excel.processor - INFO - 解析规格: 1*10组*5瓶 -> 包装数量=10
2025-05-09 14:23:40,880 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6975382530176, 名称=海河草莓味牛奶220ml, 规格=, 数量=6.0, 单位=袋, 单价=3.0
2025-05-09 14:23:40,888 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:23:40,889 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6975382531333, 名称=海河玫瑰荔枝味220g, 规格=, 数量=6.0, 单位=袋, 单价=3.0
2025-05-09 14:23:40,890 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:23:40,891 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6975382531142, 名称=海河樱花白桃牛奶220ml, 规格=, 数量=6.0, 单位=袋, 单价=3.0
2025-05-09 14:23:40,896 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:23:40,897 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6975382530350, 名称=海河可可牛奶220ml, 规格=, 数量=6.0, 单位=袋, 单价=3.0
2025-05-09 14:23:40,897 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:23:40,898 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6907992106915, 名称=伊利天然牧场鲜牛奶405ml, 规格=, 数量=2.0, 单位=瓶, 单价=10.0
2025-05-09 14:23:40,898 - app.core.excel.processor - INFO - 解析规格: 1*12 -> 包装数量=12
2025-05-09 14:23:40,899 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6907992103594, 名称=伊利桶红枣酸牛奶450ml, 规格=, 数量=2.0, 单位=瓶, 单价=7.5
2025-05-09 14:23:40,899 - app.core.excel.processor - INFO - 解析规格: 1*20 -> 包装数量=20
2025-05-09 14:23:40,900 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6907992108018, 名称=伊利每益添果蔬益生菌饮品羽衣甘蓝+猕猴桃330ml, 规格=, 数量=2.0, 单位=瓶, 单价=6.3
2025-05-09 14:23:40,900 - app.core.excel.processor - INFO - 解析规格: 1*20 -> 包装数量=20
2025-05-09 14:23:41,461 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6907992108025, 名称=伊利每益添果蔬益生菌饮品红甜菜+樱桃330ml, 规格=, 数量=2.0, 单位=瓶, 单价=6.3
2025-05-09 14:23:41,461 - app.core.excel.processor - INFO - 解析规格: 1*20 -> 包装数量=20
2025-05-09 14:23:41,462 - app.core.excel.processor - INFO - 第12行: 提取商品信息 条码=6907992107639, 名称=伊利250ml畅轻西柚芒果+青稞爆珠风味发酵乳, 规格=, 数量=2.0, 单位=瓶, 单价=7.1
2025-05-09 14:23:41,462 - app.core.excel.processor - INFO - 解析规格: 1*24 -> 包装数量=24
2025-05-09 14:23:41,463 - app.core.excel.processor - INFO - 第13行: 提取商品信息 条码=6903979800999, 名称=菊乐嚼酸奶(燕麦百香果味)170g*16, 规格=, 数量=8.0, 单位=袋, 单价=3.0
2025-05-09 14:23:41,463 - app.core.excel.processor - INFO - 解析规格: 1*16 -> 包装数量=16
2025-05-09 14:23:41,464 - app.core.excel.processor - INFO - 第14行: 提取商品信息 条码=6907992106861, 名称=伊利-大口嚼180克, 规格=, 数量=4.0, 单位=杯, 单价=6.5
2025-05-09 14:23:41,464 - app.core.excel.processor - INFO - 解析规格: 1*16 -> 包装数量=16
2025-05-09 14:23:41,466 - app.core.excel.processor - INFO - 第15行: 提取商品信息 条码=6934665087653, 名称=蒙牛优益c原味340, 规格=, 数量=6.0, 单位=瓶, 单价=5.5
2025-05-09 14:23:41,466 - app.core.excel.processor - INFO - 解析规格: 1*24 -> 包装数量=24
2025-05-09 14:23:41,467 - app.core.excel.processor - INFO - 提取到 15 个商品信息
2025-05-09 14:23:41,480 - app.core.excel.processor - INFO - 开始处理15 个产品信息
2025-05-09 14:23:41,480 - app.core.excel.processor - INFO - 处理商品: 条码=6901209255021, 数量=2.0, 单价=10.0, 是否赠品=False
2025-05-09 14:23:41,481 - app.core.excel.processor - INFO - 发现正常商品条码6901209255021, 数量=2.0, 单价=10.0
2025-05-09 14:23:41,481 - app.core.excel.processor - INFO - 处理商品: 条码=6907992103587, 数量=10.0, 单价=2.3, 是否赠品=False
2025-05-09 14:23:41,481 - app.core.excel.processor - INFO - 发现正常商品条码6907992103587, 数量=10.0, 单价=2.3
2025-05-09 14:23:41,481 - app.core.excel.processor - INFO - 处理商品: 条码=6907992102726, 数量=2.0, 单价=9.0, 是否赠品=False
2025-05-09 14:23:41,481 - app.core.excel.processor - INFO - 发现正常商品条码6907992102726, 数量=2.0, 单价=9.0
2025-05-09 14:23:41,481 - app.core.excel.processor - INFO - 处理商品: 条码=6975382530176, 数量=6.0, 单价=3.0, 是否赠品=False
2025-05-09 14:23:41,481 - app.core.excel.processor - INFO - 发现正常商品条码6975382530176, 数量=6.0, 单价=3.0
2025-05-09 14:23:41,481 - app.core.excel.processor - INFO - 处理商品: 条码=6975382531333, 数量=6.0, 单价=3.0, 是否赠品=False
2025-05-09 14:23:41,482 - app.core.excel.processor - INFO - 发现正常商品条码6975382531333, 数量=6.0, 单价=3.0
2025-05-09 14:23:41,482 - app.core.excel.processor - INFO - 处理商品: 条码=6975382531142, 数量=6.0, 单价=3.0, 是否赠品=False
2025-05-09 14:23:41,482 - app.core.excel.processor - INFO - 发现正常商品条码6975382531142, 数量=6.0, 单价=3.0
2025-05-09 14:23:45,553 - app.core.excel.processor - INFO - 处理商品: 条码=6975382530350, 数量=6.0, 单价=3.0, 是否赠品=False
2025-05-09 14:23:45,553 - app.core.excel.processor - INFO - 发现正常商品条码6975382530350, 数量=6.0, 单价=3.0
2025-05-09 14:23:45,553 - app.core.excel.processor - INFO - 处理商品: 条码=6907992106915, 数量=2.0, 单价=10.0, 是否赠品=False
2025-05-09 14:23:45,553 - app.core.excel.processor - INFO - 发现正常商品条码6907992106915, 数量=2.0, 单价=10.0
2025-05-09 14:23:45,553 - app.core.excel.processor - INFO - 处理商品: 条码=6907992103594, 数量=2.0, 单价=7.5, 是否赠品=False
2025-05-09 14:23:45,553 - app.core.excel.processor - INFO - 发现正常商品条码6907992103594, 数量=2.0, 单价=7.5
2025-05-09 14:23:45,553 - app.core.excel.processor - INFO - 处理商品: 条码=6907992108018, 数量=2.0, 单价=6.3, 是否赠品=False
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 发现正常商品条码6907992108018, 数量=2.0, 单价=6.3
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 处理商品: 条码=6907992108025, 数量=2.0, 单价=6.3, 是否赠品=False
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 发现正常商品条码6907992108025, 数量=2.0, 单价=6.3
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 处理商品: 条码=6907992107639, 数量=2.0, 单价=7.1, 是否赠品=False
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 发现正常商品条码6907992107639, 数量=2.0, 单价=7.1
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 处理商品: 条码=6903979800999, 数量=8.0, 单价=3.0, 是否赠品=False
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 发现正常商品条码6903979800999, 数量=8.0, 单价=3.0
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 处理商品: 条码=6907992106861, 数量=4.0, 单价=6.5, 是否赠品=False
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 发现正常商品条码6907992106861, 数量=4.0, 单价=6.5
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 处理商品: 条码=6934665087653, 数量=6.0, 单价=5.5, 是否赠品=False
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 发现正常商品条码6934665087653, 数量=6.0, 单价=5.5
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 分组后共15 个不同条码的商品
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 条码 6901209255021 处理结果正常商品数量2.0单价10.0赠品数量0
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 条码 6907992103587 处理结果正常商品数量10.0单价2.3赠品数量0
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 条码 6907992102726 处理结果正常商品数量2.0单价9.0赠品数量0
2025-05-09 14:23:45,554 - app.core.excel.processor - INFO - 条码 6975382530176 处理结果正常商品数量6.0单价3.0赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6975382531333 处理结果正常商品数量6.0单价3.0赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6975382531142 处理结果正常商品数量6.0单价3.0赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6975382530350 处理结果正常商品数量6.0单价3.0赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6907992106915 处理结果正常商品数量2.0单价10.0赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6907992103594 处理结果正常商品数量2.0单价7.5赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6907992108018 处理结果正常商品数量2.0单价6.3赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6907992108025 处理结果正常商品数量2.0单价6.3赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6907992107639 处理结果正常商品数量2.0单价7.1赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6903979800999 处理结果正常商品数量8.0单价3.0赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6907992106861 处理结果正常商品数量4.0单价6.5赠品数量0
2025-05-09 14:23:45,555 - app.core.excel.processor - INFO - 条码 6934665087653 处理结果正常商品数量6.0单价5.5赠品数量0
2025-05-09 14:23:49,343 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_高新-益选便利店销售单2025-05-09.xls
2025-05-09 14:23:49,345 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_高新-益选便利店销售单2025-05-09.xls
2025-05-09 14:26:54,509 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:26:54,509 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 14:26:54,509 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 14:31:54,257 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:31:54,258 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 14:31:54,258 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 14:31:54,259 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142624.xlsx
2025-05-09 14:31:54,289 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142624.xlsx, 共 16 行
2025-05-09 14:31:54,293 - app.core.excel.processor - INFO - 找到可能的表头行: 第1行评分: 45
2025-05-09 14:31:54,294 - app.core.excel.processor - INFO - 识别到表头在第 1 行
2025-05-09 14:31:54,326 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 15 行有效数据
2025-05-09 14:31:54,327 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
2025-05-09 14:31:54,327 - app.core.excel.processor - INFO - 使用条码列: 商品条码
2025-05-09 14:31:54,327 - app.core.excel.processor - INFO - 找到name列(部分匹配): 商品条码
2025-05-09 14:31:54,327 - app.core.excel.processor - INFO - 找到specification列: 规格
2025-05-09 14:31:54,327 - app.core.excel.processor - INFO - 找到quantity列: 数量
2025-05-09 14:31:54,327 - app.core.excel.processor - INFO - 找到unit列: 单位
2025-05-09 14:31:54,327 - app.core.excel.processor - INFO - 找到price列: 单价
2025-05-09 14:31:54,328 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品条码', 'specification': '规格', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
2025-05-09 14:31:54,328 - app.core.excel.processor - INFO - 是否存在规格列: True
2025-05-09 14:31:54,329 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6907992508344, 名称=6907992508344.0, 规格=, 数量=1.0, 单位=件, 单价=52.0
2025-05-09 14:31:54,334 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6903979000979, 名称=6903979000979.0, 规格=, 数量=3.0, 单位=件, 单价=50.0
2025-05-09 14:31:54,335 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6923644283582, 名称=6923644283582.0, 规格=, 数量=1.0, 单位=件, 单价=30.0
2025-05-09 14:31:54,338 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6923644268909, 名称=6923644268909.0, 规格=, 数量=2.0, 单位=件, 单价=30.0
2025-05-09 14:31:54,340 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6923644268930, 名称=6923644268930.0, 规格=, 数量=2.0, 单位=件, 单价=30.0
2025-05-09 14:31:54,341 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6923644268916, 名称=6923644268916.0, 规格=, 数量=2.0, 单位=件, 单价=30.0
2025-05-09 14:31:54,342 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6923644266318, 名称=6923644266318.0, 规格=, 数量=4.0, 单位=件, 单价=45.0
2025-05-09 14:31:54,432 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6920584471055, 名称=6920584471055.0, 规格=, 数量=2.0, 单位=件, 单价=50.0
2025-05-09 14:31:54,433 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6925861571159, 名称=6925861571159.0, 规格=, 数量=2.0, 单位=件, 单价=65.0
2025-05-09 14:31:54,434 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6925861571466, 名称=6925861571466.0, 规格=, 数量=1.0, 单位=件, 单价=45.0
2025-05-09 14:31:54,434 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6923644210151, 名称=6923644210151.0, 规格=, 数量=3.0, 单位=件, 单价=55.0
2025-05-09 14:31:54,435 - app.core.excel.processor - INFO - 第12行: 提取商品信息 条码=6907992501819, 名称=6907992501819.0, 规格=, 数量=3.0, 单位=件, 单价=63.0
2025-05-09 14:31:54,435 - app.core.excel.processor - INFO - 第13行: 提取商品信息 条码=6907992502052, 名称=6907992502052.0, 规格=, 数量=3.0, 单位=件, 单价=54.0
2025-05-09 14:31:54,436 - app.core.excel.processor - INFO - 第14行: 提取商品信息 条码=6907992507385, 名称=6907992507385.0, 规格=, 数量=2.0, 单位=件, 单价=42.0
2025-05-09 14:31:54,436 - app.core.excel.processor - INFO - 提取到 14 个商品信息
2025-05-09 14:31:54,446 - app.core.excel.processor - INFO - 开始处理14 个产品信息
2025-05-09 14:31:54,447 - app.core.excel.processor - INFO - 处理商品: 条码=6907992508344, 数量=12.0, 单价=4.333333333333333, 是否赠品=False
2025-05-09 14:31:54,448 - app.core.excel.processor - INFO - 发现正常商品条码6907992508344, 数量=12.0, 单价=4.333333333333333
2025-05-09 14:31:54,448 - app.core.excel.processor - INFO - 处理商品: 条码=6903979000979, 数量=72.0, 单价=2.0833333333333335, 是否赠品=False
2025-05-09 14:31:57,685 - app.core.excel.processor - INFO - 发现正常商品条码6903979000979, 数量=72.0, 单价=2.0833333333333335
2025-05-09 14:31:57,685 - app.core.excel.processor - INFO - 处理商品: 条码=6923644283575, 数量=12.0, 单价=2.5, 是否赠品=False
2025-05-09 14:31:57,685 - app.core.excel.processor - INFO - 发现正常商品条码6923644283575, 数量=12.0, 单价=2.5
2025-05-09 14:31:57,685 - app.core.excel.processor - INFO - 处理商品: 条码=6923644268909, 数量=24.0, 单价=2.5, 是否赠品=False
2025-05-09 14:31:57,685 - app.core.excel.processor - INFO - 发现正常商品条码6923644268909, 数量=24.0, 单价=2.5
2025-05-09 14:31:57,686 - app.core.excel.processor - INFO - 处理商品: 条码=6923644268497, 数量=24.0, 单价=2.5, 是否赠品=False
2025-05-09 14:31:57,686 - app.core.excel.processor - INFO - 发现正常商品条码6923644268497, 数量=24.0, 单价=2.5
2025-05-09 14:31:57,686 - app.core.excel.processor - INFO - 处理商品: 条码=6923644268503, 数量=24.0, 单价=2.5, 是否赠品=False
2025-05-09 14:31:57,686 - app.core.excel.processor - INFO - 发现正常商品条码6923644268503, 数量=24.0, 单价=2.5
2025-05-09 14:31:57,686 - app.core.excel.processor - INFO - 处理商品: 条码=6923644266318, 数量=48.0, 单价=3.75, 是否赠品=False
2025-05-09 14:31:57,686 - app.core.excel.processor - INFO - 发现正常商品条码6923644266318, 数量=48.0, 单价=3.75
2025-05-09 14:31:57,687 - app.core.excel.processor - INFO - 处理商品: 条码=6920584471017, 数量=24.0, 单价=4.166666666666667, 是否赠品=False
2025-05-09 14:31:57,687 - app.core.excel.processor - INFO - 发现正常商品条码6920584471017, 数量=24.0, 单价=4.166666666666667
2025-05-09 14:31:57,687 - app.core.excel.processor - INFO - 处理商品: 条码=69021824, 数量=72.0, 单价=1.8055555555555556, 是否赠品=False
2025-05-09 14:31:57,687 - app.core.excel.processor - INFO - 发现正常商品条码69021824, 数量=72.0, 单价=1.8055555555555556
2025-05-09 14:31:57,687 - app.core.excel.processor - INFO - 处理商品: 条码=6925861571466, 数量=12.0, 单价=3.75, 是否赠品=False
2025-05-09 14:31:57,687 - app.core.excel.processor - INFO - 发现正常商品条码6925861571466, 数量=12.0, 单价=3.75
2025-05-09 14:31:57,687 - app.core.excel.processor - INFO - 处理商品: 条码=6923644223458, 数量=72.0, 单价=2.2916666666666665, 是否赠品=False
2025-05-09 14:31:57,687 - app.core.excel.processor - INFO - 发现正常商品条码6923644223458, 数量=72.0, 单价=2.2916666666666665
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 处理商品: 条码=6907992500133, 数量=72.0, 单价=2.625, 是否赠品=False
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 发现正常商品条码6907992500133, 数量=72.0, 单价=2.625
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 处理商品: 条码=6907992502052, 数量=72.0, 单价=2.25, 是否赠品=False
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 发现正常商品条码6907992502052, 数量=72.0, 单价=2.25
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 处理商品: 条码=6907992507385, 数量=24.0, 单价=3.5, 是否赠品=False
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 发现正常商品条码6907992507385, 数量=24.0, 单价=3.5
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 分组后共14 个不同条码的商品
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 条码 6907992508344 处理结果正常商品数量12.0单价4.333333333333333赠品数量0
2025-05-09 14:31:57,688 - app.core.excel.processor - INFO - 条码 6903979000979 处理结果正常商品数量72.0单价2.0833333333333335赠品数量0
2025-05-09 14:31:57,689 - app.core.excel.processor - INFO - 条码 6923644283575 处理结果正常商品数量12.0单价2.5赠品数量0
2025-05-09 14:31:57,689 - app.core.excel.processor - INFO - 条码 6923644268909 处理结果正常商品数量24.0单价2.5赠品数量0
2025-05-09 14:31:57,689 - app.core.excel.processor - INFO - 条码 6923644268497 处理结果正常商品数量24.0单价2.5赠品数量0
2025-05-09 14:31:57,689 - app.core.excel.processor - INFO - 条码 6923644268503 处理结果正常商品数量24.0单价2.5赠品数量0
2025-05-09 14:31:57,689 - app.core.excel.processor - INFO - 条码 6923644266318 处理结果正常商品数量48.0单价3.75赠品数量0
2025-05-09 14:32:02,676 - app.core.excel.processor - INFO - 条码 6920584471017 处理结果正常商品数量24.0单价4.166666666666667赠品数量0
2025-05-09 14:32:02,677 - app.core.excel.processor - INFO - 条码 69021824 处理结果正常商品数量72.0单价1.8055555555555556赠品数量0
2025-05-09 14:32:02,677 - app.core.excel.processor - INFO - 条码 6925861571466 处理结果正常商品数量12.0单价3.75赠品数量0
2025-05-09 14:32:02,677 - app.core.excel.processor - INFO - 条码 6923644223458 处理结果正常商品数量72.0单价2.2916666666666665赠品数量0
2025-05-09 14:32:02,677 - app.core.excel.processor - INFO - 条码 6907992500133 处理结果正常商品数量72.0单价2.625赠品数量0
2025-05-09 14:32:02,677 - app.core.excel.processor - INFO - 条码 6907992502052 处理结果正常商品数量72.0单价2.25赠品数量0
2025-05-09 14:32:02,677 - app.core.excel.processor - INFO - 条码 6907992507385 处理结果正常商品数量24.0单价3.5赠品数量0
2025-05-09 14:32:02,682 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_微信图片_20250509142624.xls
2025-05-09 14:32:02,684 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_微信图片_20250509142624.xls
2025-05-09 14:32:20,938 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:32:20,939 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 14:32:20,940 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 14:32:20,954 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142700.xlsx
2025-05-09 14:32:21,010 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142700.xlsx, 共 13 行
2025-05-09 14:32:21,017 - app.core.excel.processor - INFO - 找到可能的表头行: 第1行评分: 45
2025-05-09 14:32:21,018 - app.core.excel.processor - INFO - 识别到表头在第 1 行
2025-05-09 14:32:21,057 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 12 行有效数据
2025-05-09 14:32:21,057 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
2025-05-09 14:32:21,057 - app.core.excel.processor - INFO - 使用条码列: 商品条码
2025-05-09 14:32:21,058 - app.core.excel.processor - INFO - 找到name列(部分匹配): 商品条码
2025-05-09 14:32:21,058 - app.core.excel.processor - INFO - 找到specification列: 规格
2025-05-09 14:32:21,066 - app.core.excel.processor - INFO - 找到quantity列: 数量
2025-05-09 14:32:21,066 - app.core.excel.processor - INFO - 找到unit列: 单位
2025-05-09 14:32:21,066 - app.core.excel.processor - INFO - 找到price列: 单价
2025-05-09 14:32:21,066 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品条码', 'specification': '规格', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
2025-05-09 14:32:21,066 - app.core.excel.processor - INFO - 是否存在规格列: True
2025-05-09 14:32:21,068 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6922456805012, 名称=6922456805012.0, 规格=, 数量=1.0, 单位=件, 单价=33.0
2025-05-09 14:32:21,068 - app.core.excel.processor - INFO - 解析规格: 500ml*15 -> 包装数量=15
2025-05-09 14:32:21,073 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6922456892067, 名称=6922456892067.0, 规格=, 数量=2.0, 单位=件, 单价=42.0
2025-05-09 14:32:21,075 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,078 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6922456891985, 名称=6922456891985.0, 规格=, 数量=1.0, 单位=件, 单价=42.0
2025-05-09 14:32:21,078 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,082 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6922456889944, 名称=6922456889944.0, 规格=, 数量=1.0, 单位=件, 单价=42.0
2025-05-09 14:32:21,082 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,083 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6922456896362, 名称=6922456896362.0, 规格=, 数量=1.0, 单位=件, 单价=42.0
2025-05-09 14:32:21,083 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,086 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6922456889920, 名称=6922456889920.0, 规格=, 数量=1.0, 单位=件, 单价=42.0
2025-05-09 14:32:21,086 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,087 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6922456843571, 名称=6922456843571.0, 规格=, 数量=1.0, 单位=件, 单价=42.0
2025-05-09 14:32:21,088 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,215 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6922456840259, 名称=6922456840259.0, 规格=, 数量=1.0, 单位=件, 单价=42.0
2025-05-09 14:32:21,215 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,216 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6922456889982, 名称=6922456889982.0, 规格=, 数量=1.0, 单位=件, 单价=42.0
2025-05-09 14:32:21,216 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,217 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6922456896362, 名称=6922456896362.0, 规格=, 数量=1.0, 单位=件, 单价=0
2025-05-09 14:32:21,218 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,218 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6922456896362, 名称=6922456896362.0, 规格=, 数量=1.0, 单位=瓶, 单价=0
2025-05-09 14:32:21,218 - app.core.excel.processor - INFO - 解析规格: 1L*12 -> 包装数量=12
2025-05-09 14:32:21,219 - app.core.excel.processor - INFO - 提取到 11 个商品信息
2025-05-09 14:32:21,230 - app.core.excel.processor - INFO - 开始处理11 个产品信息
2025-05-09 14:32:21,231 - app.core.excel.processor - INFO - 处理商品: 条码=6922456805012, 数量=15.0, 单价=2.2, 是否赠品=False
2025-05-09 14:32:21,231 - app.core.excel.processor - INFO - 发现正常商品条码6922456805012, 数量=15.0, 单价=2.2
2025-05-09 14:32:21,231 - app.core.excel.processor - INFO - 处理商品: 条码=6922456892067, 数量=24.0, 单价=3.5, 是否赠品=False
2025-05-09 14:32:21,231 - app.core.excel.processor - INFO - 发现正常商品条码6922456892067, 数量=24.0, 单价=3.5
2025-05-09 14:32:21,231 - app.core.excel.processor - INFO - 处理商品: 条码=6922456891985, 数量=12.0, 单价=3.5, 是否赠品=False
2025-05-09 14:32:21,232 - app.core.excel.processor - INFO - 发现正常商品条码6922456891985, 数量=12.0, 单价=3.5
2025-05-09 14:32:21,232 - app.core.excel.processor - INFO - 处理商品: 条码=6922456889944, 数量=12.0, 单价=3.5, 是否赠品=False
2025-05-09 14:32:21,232 - app.core.excel.processor - INFO - 发现正常商品条码6922456889944, 数量=12.0, 单价=3.5
2025-05-09 14:32:21,232 - app.core.excel.processor - INFO - 处理商品: 条码=6922456896362, 数量=12.0, 单价=3.5, 是否赠品=False
2025-05-09 14:32:21,232 - app.core.excel.processor - INFO - 发现正常商品条码6922456896362, 数量=12.0, 单价=3.5
2025-05-09 14:32:21,232 - app.core.excel.processor - INFO - 处理商品: 条码=6922456889920, 数量=12.0, 单价=3.5, 是否赠品=False
2025-05-09 14:32:21,232 - app.core.excel.processor - INFO - 发现正常商品条码6922456889920, 数量=12.0, 单价=3.5
2025-05-09 14:32:21,233 - app.core.excel.processor - INFO - 处理商品: 条码=6922456843571, 数量=12.0, 单价=3.5, 是否赠品=False
2025-05-09 14:32:21,233 - app.core.excel.processor - INFO - 发现正常商品条码6922456843571, 数量=12.0, 单价=3.5
2025-05-09 14:32:21,233 - app.core.excel.processor - INFO - 处理商品: 条码=6922456840259, 数量=12.0, 单价=3.5, 是否赠品=False
2025-05-09 14:32:24,203 - app.core.excel.processor - INFO - 发现正常商品条码6922456840259, 数量=12.0, 单价=3.5
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 处理商品: 条码=6922456889982, 数量=12.0, 单价=3.5, 是否赠品=False
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 发现正常商品条码6922456889982, 数量=12.0, 单价=3.5
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 处理商品: 条码=6922456896362, 数量=12.0, 单价=0, 是否赠品=True
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 发现赠品条码6922456896362, 数量=12.0
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 处理商品: 条码=6922456896362, 数量=1.0, 单价=0, 是否赠品=True
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 发现赠品条码6922456896362, 数量=1.0
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 分组后共9 个不同条码的商品
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 条码 6922456805012 处理结果正常商品数量15.0单价2.2赠品数量0
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 条码 6922456892067 处理结果正常商品数量24.0单价3.5赠品数量0
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 条码 6922456891985 处理结果正常商品数量12.0单价3.5赠品数量0
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 条码 6922456889944 处理结果正常商品数量12.0单价3.5赠品数量0
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 条码 6922456896362 处理结果正常商品数量12.0单价3.5赠品数量13.0
2025-05-09 14:32:24,204 - app.core.excel.processor - INFO - 条码 6922456889920 处理结果正常商品数量12.0单价3.5赠品数量0
2025-05-09 14:32:24,205 - app.core.excel.processor - INFO - 条码 6922456843571 处理结果正常商品数量12.0单价3.5赠品数量0
2025-05-09 14:32:24,205 - app.core.excel.processor - INFO - 条码 6922456840259 处理结果正常商品数量12.0单价3.5赠品数量0
2025-05-09 14:32:24,205 - app.core.excel.processor - INFO - 条码 6922456889982 处理结果正常商品数量12.0单价3.5赠品数量0
2025-05-09 14:32:24,205 - app.core.excel.processor - INFO - 条码 6922456896362 填充:采购量=12.0赠品数量13.0
2025-05-09 14:32:24,299 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_微信图片_20250509142700.xls
2025-05-09 14:32:24,300 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_微信图片_20250509142700.xls
2025-05-09 16:01:39,292 - app.core.excel.processor - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 16:01:39,292 - app.core.excel.processor - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 16:01:39,293 - app.core.excel.processor - INFO - 初始化ExcelProcessor完成模板文件: templates/银豹-采购单模板.xls
2025-05-09 16:01:39,295 - app.core.excel.processor - INFO - 开始处理Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142624.xlsx
2025-05-09 16:01:39,349 - app.core.excel.processor - INFO - 成功读取Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142624.xlsx, 共 16 行
2025-05-09 16:01:39,363 - app.core.excel.processor - INFO - 找到可能的表头行: 第1行评分: 45
2025-05-09 16:01:39,363 - app.core.excel.processor - INFO - 识别到表头在第 1 行
2025-05-09 16:01:39,469 - app.core.excel.processor - INFO - 使用表头行重新读取数据,共 15 行有效数据
2025-05-09 16:01:39,469 - app.core.excel.processor - INFO - 找到精确匹配的条码列: 商品条码
2025-05-09 16:01:39,469 - app.core.excel.processor - INFO - 使用条码列: 商品条码
2025-05-09 16:01:39,469 - app.core.excel.processor - INFO - 找到name列(部分匹配): 商品条码
2025-05-09 16:01:39,469 - app.core.excel.processor - INFO - 找到specification列: 规格
2025-05-09 16:01:39,469 - app.core.excel.processor - INFO - 找到quantity列: 数量
2025-05-09 16:01:39,470 - app.core.excel.processor - INFO - 找到unit列: 单位
2025-05-09 16:01:39,470 - app.core.excel.processor - INFO - 找到price列: 单价
2025-05-09 16:01:39,470 - app.core.excel.processor - INFO - 列名映射结果: {'barcode': '商品条码', 'name': '商品条码', 'specification': '规格', 'quantity': '数量', 'unit': '单位', 'price': '单价'}
2025-05-09 16:01:39,470 - app.core.excel.processor - INFO - 是否存在规格列: True
2025-05-09 16:01:39,474 - app.core.excel.processor - INFO - 第1行: 提取商品信息 条码=6907992508344, 名称=6907992508344.0, 规格=, 数量=1.0, 单位=件, 单价=52.0
2025-05-09 16:01:39,481 - app.core.excel.processor - INFO - 第2行: 提取商品信息 条码=6903979000979, 名称=6903979000979.0, 规格=, 数量=3.0, 单位=件, 单价=50.0
2025-05-09 16:01:39,481 - app.core.excel.processor - INFO - 第3行: 提取商品信息 条码=6923644283582, 名称=6923644283582.0, 规格=, 数量=1.0, 单位=件, 单价=30.0
2025-05-09 16:01:39,482 - app.core.excel.processor - INFO - 第4行: 提取商品信息 条码=6923644268909, 名称=6923644268909.0, 规格=, 数量=2.0, 单位=件, 单价=30.0
2025-05-09 16:01:39,483 - app.core.excel.processor - INFO - 第5行: 提取商品信息 条码=6923644268930, 名称=6923644268930.0, 规格=, 数量=2.0, 单位=件, 单价=30.0
2025-05-09 16:01:39,484 - app.core.excel.processor - INFO - 第6行: 提取商品信息 条码=6923644268916, 名称=6923644268916.0, 规格=, 数量=2.0, 单位=件, 单价=30.0
2025-05-09 16:01:39,485 - app.core.excel.processor - INFO - 第7行: 提取商品信息 条码=6923644266318, 名称=6923644266318.0, 规格=, 数量=4.0, 单位=件, 单价=45.0
2025-05-09 16:01:39,487 - app.core.excel.processor - INFO - 第8行: 提取商品信息 条码=6920584471055, 名称=6920584471055.0, 规格=, 数量=2.0, 单位=件, 单价=50.0
2025-05-09 16:01:39,712 - app.core.excel.processor - INFO - 第9行: 提取商品信息 条码=6925861571159, 名称=6925861571159.0, 规格=, 数量=2.0, 单位=件, 单价=65.0
2025-05-09 16:01:39,713 - app.core.excel.processor - INFO - 第10行: 提取商品信息 条码=6925861571466, 名称=6925861571466.0, 规格=, 数量=1.0, 单位=件, 单价=45.0
2025-05-09 16:01:39,714 - app.core.excel.processor - INFO - 第11行: 提取商品信息 条码=6923644210151, 名称=6923644210151.0, 规格=, 数量=3.0, 单位=件, 单价=55.0
2025-05-09 16:01:39,715 - app.core.excel.processor - INFO - 第12行: 提取商品信息 条码=6907992501819, 名称=6907992501819.0, 规格=, 数量=3.0, 单位=件, 单价=63.0
2025-05-09 16:01:39,715 - app.core.excel.processor - INFO - 第13行: 提取商品信息 条码=6907992502052, 名称=6907992502052.0, 规格=, 数量=3.0, 单位=件, 单价=54.0
2025-05-09 16:01:39,716 - app.core.excel.processor - INFO - 第14行: 提取商品信息 条码=6907992507385, 名称=6907992507385.0, 规格=, 数量=2.0, 单位=件, 单价=42.0
2025-05-09 16:01:39,717 - app.core.excel.processor - INFO - 提取到 14 个商品信息
2025-05-09 16:01:39,730 - app.core.excel.processor - INFO - 开始处理14 个产品信息
2025-05-09 16:01:39,731 - app.core.excel.processor - INFO - 处理商品: 条码=6907992508344, 数量=12.0, 单价=4.333333333333333, 是否赠品=False
2025-05-09 16:01:39,731 - app.core.excel.processor - INFO - 发现正常商品条码6907992508344, 数量=12.0, 单价=4.333333333333333
2025-05-09 16:01:39,731 - app.core.excel.processor - INFO - 处理商品: 条码=6903979000979, 数量=72.0, 单价=2.0833333333333335, 是否赠品=False
2025-05-09 16:01:39,731 - app.core.excel.processor - INFO - 发现正常商品条码6903979000979, 数量=72.0, 单价=2.0833333333333335
2025-05-09 16:01:39,731 - app.core.excel.processor - INFO - 处理商品: 条码=6923644283582, 数量=12.0, 单价=2.5, 是否赠品=False
2025-05-09 16:01:39,731 - app.core.excel.processor - INFO - 发现正常商品条码6923644283582, 数量=12.0, 单价=2.5
2025-05-09 16:01:39,731 - app.core.excel.processor - INFO - 处理商品: 条码=6923644268909, 数量=24.0, 单价=2.5, 是否赠品=False
2025-05-09 16:01:39,731 - app.core.excel.processor - INFO - 发现正常商品条码6923644268909, 数量=24.0, 单价=2.5
2025-05-09 16:01:44,609 - app.core.excel.processor - INFO - 处理商品: 条码=6923644268930, 数量=24.0, 单价=2.5, 是否赠品=False
2025-05-09 16:01:44,609 - app.core.excel.processor - INFO - 发现正常商品条码6923644268930, 数量=24.0, 单价=2.5
2025-05-09 16:01:44,609 - app.core.excel.processor - INFO - 处理商品: 条码=6923644268916, 数量=24.0, 单价=2.5, 是否赠品=False
2025-05-09 16:01:44,609 - app.core.excel.processor - INFO - 发现正常商品条码6923644268916, 数量=24.0, 单价=2.5
2025-05-09 16:01:44,609 - app.core.excel.processor - INFO - 处理商品: 条码=6923644266318, 数量=48.0, 单价=3.75, 是否赠品=False
2025-05-09 16:01:44,609 - app.core.excel.processor - INFO - 发现正常商品条码6923644266318, 数量=48.0, 单价=3.75
2025-05-09 16:01:44,610 - app.core.excel.processor - INFO - 处理商品: 条码=6920584471017, 数量=24.0, 单价=4.166666666666667, 是否赠品=False
2025-05-09 16:01:44,610 - app.core.excel.processor - INFO - 发现正常商品条码6920584471017, 数量=24.0, 单价=4.166666666666667
2025-05-09 16:01:44,610 - app.core.excel.processor - INFO - 处理商品: 条码=69021824, 数量=72.0, 单价=1.8055555555555556, 是否赠品=False
2025-05-09 16:01:44,610 - app.core.excel.processor - INFO - 发现正常商品条码69021824, 数量=72.0, 单价=1.8055555555555556
2025-05-09 16:01:44,610 - app.core.excel.processor - INFO - 处理商品: 条码=6925861571466, 数量=12.0, 单价=3.75, 是否赠品=False
2025-05-09 16:01:44,610 - app.core.excel.processor - INFO - 发现正常商品条码6925861571466, 数量=12.0, 单价=3.75
2025-05-09 16:01:44,610 - app.core.excel.processor - INFO - 处理商品: 条码=6923644210151, 数量=72.0, 单价=2.2916666666666665, 是否赠品=False
2025-05-09 16:01:44,610 - app.core.excel.processor - INFO - 发现正常商品条码6923644210151, 数量=72.0, 单价=2.2916666666666665
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 处理商品: 条码=6907992501819, 数量=72.0, 单价=2.625, 是否赠品=False
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 发现正常商品条码6907992501819, 数量=72.0, 单价=2.625
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 处理商品: 条码=6907992502052, 数量=72.0, 单价=2.25, 是否赠品=False
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 发现正常商品条码6907992502052, 数量=72.0, 单价=2.25
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 处理商品: 条码=6907992507385, 数量=24.0, 单价=3.5, 是否赠品=False
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 发现正常商品条码6907992507385, 数量=24.0, 单价=3.5
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 分组后共14 个不同条码的商品
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 条码 6907992508344 处理结果正常商品数量12.0单价4.333333333333333赠品数量0
2025-05-09 16:01:44,611 - app.core.excel.processor - INFO - 条码 6903979000979 处理结果正常商品数量72.0单价2.0833333333333335赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 6923644283582 处理结果正常商品数量12.0单价2.5赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 6923644268909 处理结果正常商品数量24.0单价2.5赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 6923644268930 处理结果正常商品数量24.0单价2.5赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 6923644268916 处理结果正常商品数量24.0单价2.5赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 6923644266318 处理结果正常商品数量48.0单价3.75赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 6920584471017 处理结果正常商品数量24.0单价4.166666666666667赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 69021824 处理结果正常商品数量72.0单价1.8055555555555556赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 6925861571466 处理结果正常商品数量12.0单价3.75赠品数量0
2025-05-09 16:01:44,612 - app.core.excel.processor - INFO - 条码 6923644210151 处理结果正常商品数量72.0单价2.2916666666666665赠品数量0
2025-05-09 16:01:44,613 - app.core.excel.processor - INFO - 条码 6907992501819 处理结果正常商品数量72.0单价2.625赠品数量0
2025-05-09 16:01:51,983 - app.core.excel.processor - INFO - 条码 6907992502052 处理结果正常商品数量72.0单价2.25赠品数量0
2025-05-09 16:01:51,983 - app.core.excel.processor - INFO - 条码 6907992507385 处理结果正常商品数量24.0单价3.5赠品数量0
2025-05-09 16:01:51,987 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_微信图片_20250509142624.xls
2025-05-09 16:01:51,989 - app.core.excel.processor - INFO - 采购单已保存到: data/output\采购单_微信图片_20250509142624.xls

View File

@ -0,0 +1 @@
Active since: 2025-05-10 11:21:12

View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:37

View File

@ -69,3 +69,14 @@
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-08 19:45:41,386 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
2025-05-09 11:58:49,251 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 12:02:05,168 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 12:07:05,181 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 12:07:54,656 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 12:12:42,103 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 12:13:52,580 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 12:45:35,995 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 14:27:08,879 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 14:27:31,660 - app.core.ocr.baidu_ocr - ERROR - 初始化失败: getint() takes 3 positional arguments but 4 were given
2025-05-09 14:31:02,533 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌
2025-05-09 14:31:02,581 - app.core.ocr.baidu_ocr - INFO - 成功获取访问令牌

View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:37

View File

@ -680,3 +680,54 @@
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
2025-05-09 12:02:05,168 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 12:02:05,169 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 12:02:05,169 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:02:05,170 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:07:05,181 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 12:07:05,181 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:07:05,181 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:07:05,181 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
2025-05-09 12:07:05,182 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 12:07:54,657 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 12:07:54,657 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:07:54,657 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:07:54,657 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
2025-05-09 12:07:54,657 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 12:12:42,103 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 12:12:42,104 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:12:42,104 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:12:42,104 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
2025-05-09 12:12:42,104 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 12:13:52,580 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 12:13:52,581 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:13:52,581 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:13:52,581 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
2025-05-09 12:13:52,581 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 12:45:35,996 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 12:45:35,996 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 12:45:35,996 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 12:45:35,996 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
2025-05-09 12:45:35,996 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 14:27:08,879 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 14:27:08,880 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:27:08,880 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 14:27:08,880 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
2025-05-09 14:27:08,880 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 14:27:31,661 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 14:27:31,661 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:27:31,661 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 14:27:31,662 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
2025-05-09 14:27:31,662 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 14:31:02,077 - app.core.ocr.table_ocr - INFO - 使用输入目录: D:\My Documents\python\orc-order-v2\data\input
2025-05-09 14:31:02,077 - app.core.ocr.table_ocr - INFO - 使用输出目录: D:\My Documents\python\orc-order-v2\data\output
2025-05-09 14:31:02,078 - app.core.ocr.table_ocr - INFO - 使用临时目录: D:\My Documents\python\orc-order-v2\data\temp
2025-05-09 14:31:02,078 - app.core.ocr.table_ocr - INFO - 允许的文件类型: ['.jpg', '.jpeg', '.png', '.bmp']
2025-05-09 14:31:02,078 - app.core.ocr.table_ocr - INFO - 初始化OCRProcessor完成输入目录=data/input, 输出目录=data/output
2025-05-09 14:31:02,079 - app.core.ocr.table_ocr - INFO - 找到 2 个图片文件,其中 2 个未处理
2025-05-09 14:31:02,079 - app.core.ocr.table_ocr - INFO - 处理批次 1/1: 2 个文件
2025-05-09 14:31:02,085 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20250509142624.jpg
2025-05-09 14:31:02,105 - app.core.ocr.table_ocr - INFO - 开始处理图片: data/input\微信图片_20250509142700.jpg
2025-05-09 14:31:04,140 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20250509142624.jpg, 输出文件: data/output\微信图片_20250509142624.xlsx
2025-05-09 14:31:04,271 - app.core.ocr.table_ocr - INFO - 图片处理成功: data/input\微信图片_20250509142700.jpg, 输出文件: data/output\微信图片_20250509142700.xlsx
2025-05-09 14:31:04,274 - app.core.ocr.table_ocr - INFO - 所有图片处理完成, 总计: 2, 成功: 2

View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:36

View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:37

View File

@ -275,3 +275,24 @@
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初始化完成
2025-05-09 11:55:03,577 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 11:58:49,250 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 12:02:05,166 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 12:07:05,179 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 12:07:05,182 - app.services.ocr_service - INFO - OCRService初始化完成
2025-05-09 12:07:54,655 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 12:07:54,658 - app.services.ocr_service - INFO - OCRService初始化完成
2025-05-09 12:12:42,102 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 12:12:42,104 - app.services.ocr_service - INFO - OCRService初始化完成
2025-05-09 12:13:52,579 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 12:13:52,581 - app.services.ocr_service - INFO - OCRService初始化完成
2025-05-09 12:45:35,994 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 12:45:35,996 - app.services.ocr_service - INFO - OCRService初始化完成
2025-05-09 14:27:08,878 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 14:27:08,880 - app.services.ocr_service - INFO - OCRService初始化完成
2025-05-09 14:27:31,659 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 14:27:31,662 - app.services.ocr_service - INFO - OCRService初始化完成
2025-05-09 14:31:02,076 - app.services.ocr_service - INFO - 初始化OCRService
2025-05-09 14:31:02,078 - app.services.ocr_service - INFO - OCRService初始化完成
2025-05-09 14:31:02,078 - app.services.ocr_service - INFO - OCRService.batch_process被调用转发到process_images_batch
2025-05-09 14:31:02,078 - app.services.ocr_service - INFO - OCRService开始批量处理图片, batch_size=5, max_workers=4

View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:38

View File

@ -315,3 +315,29 @@
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
2025-05-09 12:07:05,182 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 12:07:54,658 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 12:12:42,104 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 12:13:52,581 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 12:13:52,586 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 12:45:35,997 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 12:45:35,999 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 13:39:38,178 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 13:39:38,187 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 14:08:43,900 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 14:08:43,903 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 14:08:43,903 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/高新-益选便利店销售单2025-05-09.xlsx
2025-05-09 14:23:40,512 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 14:23:40,516 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 14:23:40,516 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/高新-益选便利店销售单2025-05-09.xlsx
2025-05-09 14:26:54,507 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 14:26:54,511 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 14:31:54,256 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 14:31:54,259 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 14:31:54,259 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142624.xlsx
2025-05-09 14:32:20,936 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 14:32:20,942 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 14:32:20,954 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142700.xlsx
2025-05-09 16:01:39,291 - app.services.order_service - INFO - 初始化OrderService
2025-05-09 16:01:39,294 - app.services.order_service - INFO - OrderService初始化完成
2025-05-09 16:01:39,295 - app.services.order_service - INFO - OrderService开始处理指定Excel文件: D:/My Documents/python/orc-order-v2/data/output/微信图片_20250509142624.xlsx

View File

@ -0,0 +1 @@
Active since: 2025-05-09 16:01:39

View File

@ -0,0 +1,97 @@
2025-05-09 12:45:35,999 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 12:45:36,000 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 12:45:36,102 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 12:45:36,103 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 12:45:36,103 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:11:06,843 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:11:06,844 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:11:06,923 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:11:06,924 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:11:06,925 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:11:53,142 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:11:53,143 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:11:53,195 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:11:53,196 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:11:53,196 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:13:30,197 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:13:30,197 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:13:30,253 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:13:30,256 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:13:30,256 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:16:20,406 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:16:20,407 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:16:20,583 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:16:20,584 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:16:20,596 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:18:16,271 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:18:16,271 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:18:16,334 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:18:16,335 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:18:16,336 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:19:40,681 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:19:40,681 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:19:40,735 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:19:40,736 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:19:40,736 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:21:06,878 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:21:06,879 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:21:06,918 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:21:06,919 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:21:06,920 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:21:53,150 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:21:53,150 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:21:53,248 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:21:53,248 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:21:53,249 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:22:48,435 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:22:48,435 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:22:48,496 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:22:48,497 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:22:48,497 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:25:59,038 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:25:59,038 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:25:59,110 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:25:59,110 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:25:59,110 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:29:28,788 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:29:28,788 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:29:28,834 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:29:28,835 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:29:28,836 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:30:21,809 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:30:21,809 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:30:21,940 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:30:21,966 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:30:21,972 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:30:43,719 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:30:43,719 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:30:43,779 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:30:43,779 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:30:43,780 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:34:49,133 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:34:49,136 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:34:49,289 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:34:49,290 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:34:49,291 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:37:56,254 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:37:56,254 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:37:56,481 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:37:56,481 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:37:56,481 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:39:52,438 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509114847.xlsx
2025-05-09 13:39:52,438 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509114847.xlsx
2025-05-09 13:39:52,580 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:39:52,581 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-05-06, 总金额: 12836.76, 处理条目: 36
2025-05-09 13:39:52,581 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:50:34,355 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509134955.xlsx
2025-05-09 13:50:34,355 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509134955.xlsx
2025-05-09 13:50:34,766 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:50:34,766 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-04-27, 总金额: 10844.48, 处理条目: 34
2025-05-09 13:50:34,772 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:52:17,578 - app.services.tobacco_service - INFO - 找到最新烟草订单明细文件: data/output\订单明细20250509135149.xlsx
2025-05-09 13:52:17,579 - app.services.tobacco_service - INFO - 开始处理烟草公司订单: data/output\订单明细20250509135149.xlsx
2025-05-09 13:52:17,705 - app.services.tobacco_service - INFO - 采购单生成成功: data/output\银豹采购单_烟草公司.xls
2025-05-09 13:52:17,705 - app.services.tobacco_service - INFO - 烟草公司订单处理成功,订单时间: 2025-04-21, 总金额: 9550.10, 处理条目: 30
2025-05-09 13:52:17,706 - app.services.tobacco_service - INFO - 采购单已生成: data/output\银豹采购单_烟草公司.xls
2025-05-09 14:32:56,705 - app.services.tobacco_service - WARNING - 未找到烟草公司订单明细文件
2025-05-09 14:32:56,706 - app.services.tobacco_service - ERROR - 未找到可处理的烟草订单明细文件

411
run.py
View File

@ -13,318 +13,193 @@ import argparse
from typing import List, Optional
from app.config.settings import ConfigManager
from app.core.utils.log_utils import get_logger, close_logger
from app.core.utils.log_utils import get_logger, close_all_loggers, set_log_level
from app.services.ocr_service import OCRService
from app.services.order_service import OrderService
from app.services.tobacco_service import TobaccoService
logger = get_logger(__name__)
def create_parser() -> argparse.ArgumentParser:
def parse_args():
"""
创建命令行参数解析器
解析命令行参数
Returns:
参数解析器
解析后的参数
"""
parser = argparse.ArgumentParser(description='OCR订单处理系统')
# 通用选项
parser.add_argument('--config', type=str, help='配置文件路径')
parser.add_argument('--log-level', type=str, choices=['debug', 'info', 'warning', 'error', 'critical'], help='日志级别')
# 子命令
subparsers = parser.add_subparsers(dest='command', help='子命令')
# OCR识别命令
ocr_parser = subparsers.add_parser('ocr', help='OCR识别')
ocr_parser.add_argument('--input', type=str, help='输入图片文件路径')
ocr_parser.add_argument('--batch', action='store_true', help='批量处理模式')
ocr_parser.add_argument('--batch-size', type=int, help='批处理大小')
ocr_parser.add_argument('--max-workers', type=int, help='最大线程数')
ocr_parser.add_argument('--input', type=str, help='输入图片路径')
ocr_parser.add_argument('--batch', action='store_true', help='批量处理')
ocr_parser.add_argument('--batch-size', type=int, default=5, help='批处理大小')
ocr_parser.add_argument('--max-workers', type=int, default=4, help='最大线程数')
# Excel处理命令
excel_parser = subparsers.add_parser('excel', help='Excel处理')
excel_parser.add_argument('--input', type=str, help='输入Excel文件路径,如果不指定则处理最新的文件')
excel_parser.add_argument('--input', type=str, help='输入Excel文件路径')
# 订单合并命令
merge_parser = subparsers.add_parser('merge', help='订单合并')
merge_parser.add_argument('--input', type=str, help='输入采购单文件路径列表,以逗号分隔,如果不指定则合并所有采购单')
# 合并命令
merge_parser = subparsers.add_parser('merge', help='合并采购单')
merge_parser.add_argument('--input', type=str, help='输入采购单文件路径(逗号分隔)')
# 完整流程命令
pipeline_parser = subparsers.add_parser('pipeline', help='完整流程')
pipeline_parser.add_argument('--input', type=str, help='输入图片文件路径,如果不指定则处理所有图片')
pipeline_parser = subparsers.add_parser('pipeline', help='完整处理流程')
pipeline_parser.add_argument('--input', type=str, help='输入图片路径')
pipeline_parser.add_argument('--merge', action='store_true', help='是否合并采购单')
return parser
# 烟草订单处理
tobacco_parser = subparsers.add_parser('tobacco', help='处理烟草订单')
tobacco_parser.add_argument('--input', type=str, help='输入订单明细文件路径')
def run_ocr(ocr_service: OCRService, args) -> bool:
# 解析参数
parsed_args = parser.parse_args()
return parsed_args
def main():
"""
运行OCR识别
Args:
ocr_service: OCR服务
args: 命令行参数
主函数入口
Returns:
处理是否成功
退出码
"""
if args.input:
if not os.path.exists(args.input):
logger.error(f"输入文件不存在: {args.input}")
return False
# 解析命令行参数
args = parse_args()
if not ocr_service.validate_image(args.input):
logger.error(f"输入文件无效: {args.input}")
return False
logger.info(f"处理单个图片: {args.input}")
result = ocr_service.process_image(args.input)
if result:
logger.info(f"OCR处理成功输出文件: {result}")
return True
else:
logger.error("OCR处理失败")
return False
elif args.batch:
logger.info("批量处理模式")
total, success = ocr_service.process_images_batch(args.batch_size, args.max_workers)
if total == 0:
logger.warning("没有找到需要处理的文件")
return False
logger.info(f"批量处理完成,总计: {total},成功: {success}")
return success > 0
else:
# 列出未处理的文件
files = ocr_service.get_unprocessed_images()
if not files:
logger.info("没有未处理的文件")
return True
logger.info(f"未处理的文件 ({len(files)}):")
for file in files:
logger.info(f" {file}")
return True
def run_excel(order_service: OrderService, args) -> bool:
"""
运行Excel处理
Args:
order_service: 订单服务
args: 命令行参数
Returns:
处理是否成功
"""
if args.input:
if not os.path.exists(args.input):
logger.error(f"输入文件不存在: {args.input}")
return False
logger.info(f"处理Excel文件: {args.input}")
result = order_service.process_excel(args.input)
else:
latest_file = order_service.get_latest_excel()
if not latest_file:
logger.warning("未找到可处理的Excel文件")
return False
logger.info(f"处理最新的Excel文件: {latest_file}")
result = order_service.process_excel(latest_file)
if result:
logger.info(f"Excel处理成功输出文件: {result}")
return True
else:
logger.error("Excel处理失败")
return False
def run_merge(order_service: OrderService, args) -> bool:
"""
运行订单合并
Args:
order_service: 订单服务
args: 命令行参数
Returns:
处理是否成功
"""
if args.input:
# 分割输入文件列表
file_paths = [path.strip() for path in args.input.split(',')]
# 检查文件是否存在
for path in file_paths:
if not os.path.exists(path):
logger.error(f"输入文件不存在: {path}")
return False
logger.info(f"合并指定的采购单文件: {file_paths}")
result = order_service.merge_orders(file_paths)
else:
# 获取所有采购单文件
file_paths = order_service.get_purchase_orders()
if not file_paths:
logger.warning("未找到采购单文件")
return False
logger.info(f"合并所有采购单文件: {len(file_paths)}")
result = order_service.merge_orders()
if result:
logger.info(f"订单合并成功,输出文件: {result}")
return True
else:
logger.error("订单合并失败")
return False
def run_pipeline(ocr_service: OCRService, order_service: OrderService, args) -> bool:
"""
运行完整流程
Args:
ocr_service: OCR服务
order_service: 订单服务
args: 命令行参数
Returns:
处理是否成功
"""
# 1. OCR识别
logger.info("=== 流程步骤 1: OCR识别 ===")
if args.input:
if not os.path.exists(args.input):
logger.error(f"输入文件不存在: {args.input}")
return False
if not ocr_service.validate_image(args.input):
logger.error(f"输入文件无效: {args.input}")
return False
logger.info(f"处理单个图片: {args.input}")
ocr_result = ocr_service.process_image(args.input)
if not ocr_result:
logger.error("OCR处理失败")
return False
logger.info(f"OCR处理成功输出文件: {ocr_result}")
else:
# 批量处理所有图片
logger.info("批量处理所有图片")
total, success = ocr_service.process_images_batch()
if total == 0:
logger.warning("没有找到需要处理的图片")
# 继续下一步因为可能已经有处理好的Excel文件
elif success == 0:
logger.error("OCR处理失败没有成功处理的图片")
return False
else:
logger.info(f"OCR处理完成总计: {total},成功: {success}")
# 2. Excel处理
logger.info("=== 流程步骤 2: Excel处理 ===")
latest_file = order_service.get_latest_excel()
if not latest_file:
logger.warning("未找到可处理的Excel文件")
return False
logger.info(f"处理最新的Excel文件: {latest_file}")
excel_result = order_service.process_excel(latest_file)
if not excel_result:
logger.error("Excel处理失败")
return False
logger.info(f"Excel处理成功输出文件: {excel_result}")
# 3. 订单合并
logger.info("=== 流程步骤 3: 订单合并 ===")
# 获取所有采购单文件
file_paths = order_service.get_purchase_orders()
if not file_paths:
logger.warning("未找到采购单文件,跳过合并步骤")
logger.info("=== 完整流程处理成功(未执行合并步骤)===")
# 非错误状态,继续执行
return True
# 有文件需要合并
logger.info(f"发现 {len(file_paths)} 个采购单文件")
if len(file_paths) == 1:
logger.warning(f"只有1个采购单文件 {file_paths[0]},无需合并")
logger.info("=== 完整流程处理成功(只有一个文件,跳过合并)===")
return True
logger.info(f"合并所有采购单文件: {len(file_paths)}")
merge_result = order_service.merge_orders()
if not merge_result:
logger.error("订单合并失败")
return False
logger.info(f"订单合并成功,输出文件: {merge_result}")
logger.info("=== 完整流程处理成功 ===")
return True
def main(args: Optional[List[str]] = None) -> int:
"""
主函数
Args:
args: 命令行参数如果为None则使用sys.argv
Returns:
退出状态码
"""
parser = create_parser()
parsed_args = parser.parse_args(args)
if parsed_args.command is None:
parser.print_help()
if not args.command:
argparse.ArgumentParser().print_help()
return 1
try:
# 创建配置管理器
config = ConfigManager(parsed_args.config) if parsed_args.config else ConfigManager()
# 加载配置
config_path = args.config
config_manager = ConfigManager(config_path)
config = config_manager.config
# 创建服务
# 设置日志级别
log_level = getattr(args, 'log_level', None)
if log_level:
set_log_level(log_level)
try:
if args.command == 'ocr':
# OCR识别处理
ocr_service = OCRService(config)
if args.batch:
# 批量处理
total, success = ocr_service.batch_process(
batch_size=args.batch_size,
max_workers=args.max_workers
)
return 0 if success > 0 else 1
else:
# 处理单个文件
result = ocr_service.process_image(args.input)
return 0 if result else 1
elif args.command == 'excel':
# Excel处理
order_service = OrderService(config)
if args.input:
# 处理指定文件
result = order_service.process_excel(args.input)
else:
# 处理最新文件
result = order_service.process_latest_excel()
return 0 if result else 1
elif args.command == 'merge':
# 合并采购单
order_service = OrderService(config)
if args.input:
# 合并指定文件
file_list = args.input.split(',')
result = order_service.merge_purchase_orders(file_list)
else:
# 合并所有采购单
result = order_service.merge_all_purchase_orders()
return 0 if result else 1
elif args.command == 'pipeline':
# 完整流程
ocr_service = OCRService(config)
order_service = OrderService(config)
# 根据命令执行不同功能
if parsed_args.command == 'ocr':
success = run_ocr(ocr_service, parsed_args)
elif parsed_args.command == 'excel':
success = run_excel(order_service, parsed_args)
elif parsed_args.command == 'merge':
success = run_merge(order_service, parsed_args)
elif parsed_args.command == 'pipeline':
success = run_pipeline(ocr_service, order_service, parsed_args)
# 1. OCR处理
if args.input:
# 处理单个文件
excel_file = ocr_service.process_image(args.input)
else:
parser.print_help()
# 批量处理
total, success = ocr_service.batch_process()
if success == 0:
logger.error("OCR处理失败没有成功处理任何文件")
return 1
excel_file = None # 批量处理不返回具体文件
# 2. Excel处理
if excel_file:
# 处理指定的Excel文件
result = order_service.process_excel(excel_file)
else:
# 处理最新的Excel文件
result = order_service.process_latest_excel()
if not result:
logger.error("Excel处理失败")
return 1
return 0 if success else 1
# 3. 合并采购单(可选)
if args.merge:
result = order_service.merge_all_purchase_orders()
if not result:
logger.warning("合并采购单失败")
# 不影响整体流程,继续执行
return 0
elif args.command == 'tobacco':
# 烟草订单处理
tobacco_service = TobaccoService(config)
if args.input:
# 处理指定文件
logger.info(f"开始处理烟草订单,输入文件: {args.input}")
result = tobacco_service.process_tobacco_order(args.input)
else:
# 处理最新文件
logger.info("开始烟草公司订单处理")
result = tobacco_service.process_tobacco_order()
# 检查结果是否为None
if result is None:
logger.error("烟草订单处理失败")
return 1
else:
logger.info(f"烟草订单处理成功,输出文件: {result}")
# 确保result是绝对路径
if not os.path.isabs(result):
result = os.path.abspath(result)
logger.info(f"烟草订单处理完成,绝对路径: {result}")
return 0
else:
logger.error(f"未知命令: {args.command}")
return 1
except Exception as e:
logger.error(f"执行过程中发生错误: {e}")
import traceback
logger.error(traceback.format_exc())
logger.error(f"执行过程中发生错误: {e}", exc_info=True)
return 1
finally:
# 关闭日志
close_logger(__name__)
# 关闭所有日志记录器
close_all_loggers()
if __name__ == '__main__':
if __name__ == "__main__":
sys.exit(main())

View File

@ -21,6 +21,10 @@ import json
import re
from typing import Dict, List, Optional, Any
# 导入自定义对话框工具
from app.core.utils.dialog_utils import show_custom_dialog, show_barcode_mapping_dialog
from app.core.excel.converter import UnitConverter
# 全局变量,用于跟踪任务状态
RUNNING_TASK = None
THEME_MODE = "light" # 默认浅色主题
@ -200,8 +204,8 @@ def run_command_with_logging(command, log_widget, status_bar=None, on_complete=N
if on_complete:
log_widget.after(0, lambda: on_complete(process.returncode, output_text))
# 如果处理成功,显示成功信息
if process.returncode == 0:
# 如果处理成功且没有指定on_complete回调函数显示默认成功信息
elif process.returncode == 0:
if status_bar:
log_widget.after(0, lambda: status_bar.set_status("处理完成", 100))
log_widget.after(0, lambda: show_result_preview(command, output_text))
@ -434,7 +438,7 @@ def show_pipeline_result_preview(output):
# 添加处理结果提示(即使没有可合并文件也显示成功)
no_files_match = re.search(r'未找到可合并的文件', output)
if no_files_match:
tk.Label(preview, text="未找到可合并文件,但其他步骤已成功执行", font=("Arial", 12)).pack(pady=0)
tk.Label(preview, text="未找到可合并文件,但其他步骤已成功执行", font=("Arial", 12)).pack(pady=0)
result_frame = tk.Frame(preview)
result_frame.pack(pady=10, fill=tk.BOTH, expand=True)
@ -758,7 +762,7 @@ def main():
text="处理Excel文件",
width=button_width,
height=button_height,
command=lambda: process_excel_file(log_text, status_bar)
command=lambda: process_excel_file_with_status(log_text, status_bar)
).pack(side=tk.LEFT, padx=button_padx)
# OCR批量识别
@ -789,7 +793,7 @@ def main():
text="处理单个图片",
width=button_width,
height=button_height,
command=lambda: process_single_image(log_text, status_bar)
command=lambda: process_single_image_with_status(log_text, status_bar)
).pack(side=tk.LEFT, padx=button_padx)
# 第三行
@ -818,6 +822,15 @@ def main():
row4 = tk.Frame(button_area)
row4.pack(fill=tk.X, pady=button_pady)
# 处理烟草订单按钮
tk.Button(
row4,
text="处理烟草订单",
width=button_width,
height=button_height,
command=lambda: run_command_with_logging(["python", "run.py", "tobacco"], log_text, status_bar, on_complete=show_tobacco_result_preview)
).pack(side=tk.LEFT, padx=button_padx)
# 清除处理缓存按钮
tk.Button(
row4,
@ -827,15 +840,6 @@ def main():
command=lambda: clean_cache(log_text)
).pack(side=tk.LEFT, padx=button_padx)
# 清理文件按钮
tk.Button(
row4,
text="清理文件",
width=button_width,
height=button_height,
command=lambda: clean_data_files(log_text)
).pack(side=tk.LEFT, padx=button_padx)
# 第五行
row5 = tk.Frame(button_area)
row5.pack(fill=tk.X, pady=button_pady)
@ -858,6 +862,50 @@ def main():
command=lambda: os.startfile(os.path.abspath("data/output"))
).pack(side=tk.LEFT, padx=button_padx)
# 第六行
row6 = tk.Frame(button_area)
row6.pack(fill=tk.X, pady=button_pady)
# 清理文件按钮
tk.Button(
row6,
text="清理文件",
width=button_width,
height=button_height,
command=lambda: clean_data_files(log_text)
).pack(side=tk.LEFT, padx=button_padx)
# 切换主题按钮
tk.Button(
row6,
text="切换主题",
width=button_width,
height=button_height,
command=lambda: toggle_theme(root, log_text, status_bar)
).pack(side=tk.LEFT, padx=button_padx)
# 第七行
row7 = tk.Frame(button_area)
row7.pack(fill=tk.X, pady=button_pady)
# 演示自定义弹窗按钮
tk.Button(
row7,
text="自定义弹窗演示",
width=button_width,
height=button_height,
command=lambda: show_demo_dialog(log_text)
).pack(side=tk.LEFT, padx=button_padx)
# 条码映射编辑按钮
tk.Button(
row7,
text="编辑条码映射",
width=button_width,
height=button_height,
command=lambda: edit_barcode_mappings(log_text)
).pack(side=tk.LEFT, padx=button_padx)
# 底部说明
tk.Label(left_frame, text="© 2025 益选-OCR订单处理系统 v1.0 by 欢欢欢", font=("Arial", 9)).pack(side=tk.BOTTOM, pady=10)
@ -1046,5 +1094,178 @@ def center_window(window):
y = (window.winfo_screenheight() // 2) - (height // 2)
window.geometry('{}x{}+{}+{}'.format(width, height, x, y))
def show_tobacco_result_preview(returncode, output):
"""显示烟草订单处理结果预览"""
# 只在成功时显示结果预览
if returncode != 0:
return
try:
# 查找输出文件路径
result_file = None
order_time = "(未知)"
total_amount = "(未知)"
items_count = 0
# 先使用更可靠的方式查找文件路径
abs_path_match = re.search(r'烟草订单处理完成,绝对路径: (.+)(?:\n|$)', output)
if abs_path_match:
result_file = abs_path_match.group(1).strip()
# 提取处理结果信息
for line in output.split('\n'):
# 提取订单时间和金额
if "烟草公司订单处理成功" in line and "订单时间" in line:
time_match = re.search(r'订单时间: ([^,]+)', line)
amount_match = re.search(r'总金额: ([^,]+)', line)
items_match = re.search(r'处理条目: (\d+)', line)
if time_match:
order_time = time_match.group(1).strip()
if amount_match:
total_amount = amount_match.group(1).strip()
if items_match:
items_count = int(items_match.group(1).strip())
# 如果没有找到文件路径,使用默认路径
if not result_file or not os.path.exists(result_file):
default_path = os.path.abspath("data/output/银豹采购单_烟草公司.xls")
if os.path.exists(default_path):
result_file = default_path
# 创建结果预览对话框
preview = tk.Toplevel()
preview.title("烟草订单处理结果")
preview.geometry("450x320")
preview.resizable(False, False)
# 使弹窗居中显示
center_window(preview)
# 添加内容
tk.Label(preview, text="烟草订单处理完成", font=("Arial", 16, "bold")).pack(pady=10)
result_frame = tk.Frame(preview)
result_frame.pack(pady=10, fill=tk.BOTH, expand=True)
tk.Label(result_frame, text=f"订单时间: {order_time}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
tk.Label(result_frame, text=f"订单总金额: {total_amount}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
tk.Label(result_frame, text=f"处理商品数量: {items_count}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
# 文件信息
if result_file and os.path.exists(result_file):
tk.Label(result_frame, text=f"输出文件: {os.path.basename(result_file)}", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
# 处理成功提示
tk.Label(result_frame, text="银豹采购单已成功生成!", font=("Arial", 12, "bold"), fg="#28a745").pack(pady=10)
# 文件信息框
file_frame = tk.Frame(result_frame, relief=tk.GROOVE, borderwidth=1)
file_frame.pack(fill=tk.X, padx=15, pady=5)
tk.Label(file_frame, text="文件信息", font=("Arial", 10, "bold")).pack(anchor=tk.W, padx=10, pady=5)
# 获取文件大小和时间
try:
file_size = os.path.getsize(result_file)
file_time = datetime.datetime.fromtimestamp(os.path.getmtime(result_file))
size_text = f"{file_size / 1024:.1f} KB" if file_size < 1024*1024 else f"{file_size / (1024*1024):.1f} MB"
tk.Label(file_frame, text=f"文件大小: {size_text}", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
tk.Label(file_frame, text=f"创建时间: {file_time.strftime('%Y-%m-%d %H:%M:%S')}", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
except:
tk.Label(file_frame, text="无法获取文件信息", font=("Arial", 10)).pack(anchor=tk.W, padx=10, pady=2)
# 添加按钮
button_frame = tk.Frame(preview)
button_frame.pack(pady=10)
tk.Button(button_frame, text="打开文件", command=lambda: os.startfile(result_file)).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="打开所在文件夹", command=lambda: os.startfile(os.path.dirname(result_file))).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="关闭", command=preview.destroy).pack(side=tk.LEFT, padx=5)
else:
# 文件不存在或未找到的情况
tk.Label(result_frame, text="未找到输出文件", font=("Arial", 12)).pack(anchor=tk.W, padx=20, pady=5)
tk.Label(result_frame, text="请检查data/output目录", font=("Arial", 12, "bold"), fg="#dc3545").pack(pady=10)
# 添加按钮
button_frame = tk.Frame(preview)
button_frame.pack(pady=10)
tk.Button(button_frame, text="打开输出目录", command=lambda: os.startfile(os.path.abspath("data/output"))).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="关闭", command=preview.destroy).pack(side=tk.LEFT, padx=5)
# 确保窗口显示在最前
preview.lift()
preview.attributes('-topmost', True)
preview.after_idle(lambda: preview.attributes('-topmost', False))
except Exception as e:
# 发生异常,显示错误消息
messagebox.showerror(
"处理异常",
f"显示预览时发生错误: {e}\n请检查日志了解详细信息。"
)
def show_demo_dialog(log_widget):
"""演示自定义弹窗功能"""
try:
add_to_log(log_widget, "显示自定义弹窗演示...\n", "info")
# 创建一个示例结果文件路径
sample_file = os.path.join(os.path.abspath("data/output"), "样例文件.xlsx")
# 获取当前时间
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 创建其他信息
additional_info = {
"客户名称": "示例客户",
"订单编号": "ORD-20250509-001",
"处理类型": "自定义处理"
}
# 显示自定义弹窗
show_custom_dialog(
title="自定义弹窗演示",
message="这是一个自定义弹窗示例",
result_file=sample_file, # 文件可能不存在,会展示文件未找到的情况
time_info=current_time,
count_info="50个商品",
amount_info="¥1,234.56",
additional_info=additional_info
)
add_to_log(log_widget, "自定义弹窗已显示\n", "success")
except Exception as e:
add_to_log(log_widget, f"显示自定义弹窗时出错: {str(e)}\n", "error")
def edit_barcode_mappings(log_widget):
"""编辑条码映射配置"""
try:
add_to_log(log_widget, "正在加载条码映射配置...\n", "info")
# 创建单位转换器实例,用于加载和保存条码映射
unit_converter = UnitConverter()
# 加载现有的映射配置
current_mappings = unit_converter.special_barcodes
# 回调函数,保存更新后的映射
def save_mappings(new_mappings):
success = unit_converter.update_barcode_mappings(new_mappings)
if success:
add_to_log(log_widget, f"成功保存条码映射配置,共{len(new_mappings)}\n", "success")
else:
add_to_log(log_widget, "保存条码映射配置失败\n", "error")
# 显示条码映射编辑对话框
show_barcode_mapping_dialog(None, save_mappings, current_mappings)
except Exception as e:
add_to_log(log_widget, f"编辑条码映射时出错: {str(e)}\n", "error")
messagebox.showerror("错误", f"编辑条码映射时出错: {str(e)}")
if __name__ == "__main__":
main()