diff --git a/README.md b/README.md index d16cf22..bfb1a68 100644 --- a/README.md +++ b/README.md @@ -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) #### 功能优化 diff --git a/app/core/excel/__pycache__/converter.cpython-39.pyc b/app/core/excel/__pycache__/converter.cpython-39.pyc index 3e66958..56e6fbb 100644 Binary files a/app/core/excel/__pycache__/converter.cpython-39.pyc and b/app/core/excel/__pycache__/converter.cpython-39.pyc differ diff --git a/app/core/excel/__pycache__/merger.cpython-39.pyc b/app/core/excel/__pycache__/merger.cpython-39.pyc index c2627ee..cd1b3bb 100644 Binary files a/app/core/excel/__pycache__/merger.cpython-39.pyc and b/app/core/excel/__pycache__/merger.cpython-39.pyc differ diff --git a/app/core/excel/__pycache__/processor.cpython-39.pyc b/app/core/excel/__pycache__/processor.cpython-39.pyc index d39cafb..a778a34 100644 Binary files a/app/core/excel/__pycache__/processor.cpython-39.pyc and b/app/core/excel/__pycache__/processor.cpython-39.pyc differ diff --git a/app/core/excel/converter.py b/app/core/excel/converter.py index 9cd51ca..5cba87f 100644 --- a/app/core/excel/converter.py +++ b/app/core/excel/converter.py @@ -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 = [ @@ -447,4 +400,98 @@ class UnitConverter: # 没有找到适用的处理程序,保持不变 logger.info(f"其他单位处理: 保持原样 数量: {result.get('quantity', 0)}, 单价: {result.get('price', 0)}, 单位: {result.get('unit', '')}") - return result \ No newline at end of file + 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) \ No newline at end of file diff --git a/app/core/excel/merger.py b/app/core/excel/merger.py index ca35f9f..0740943 100644 --- a/app/core/excel/merger.py +++ b/app/core/excel/merger.py @@ -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) - - # 获取模板文件路径 - 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) - - # 检查模板文件是否存在 - if not os.path.exists(self.template_path): - logger.error(f"模板文件不存在: {self.template_path}") - raise FileNotFoundError(f"模板文件不存在: {self.template_path}") - - # 用于记录已合并的文件 - self.cache_file = os.path.join(self.output_dir, "merged_files.json") - self.merged_files = self._load_merged_files() - - logger.info(f"初始化完成,模板文件: {self.template_path}") + # 修复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 = 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.warning(f"模板文件不存在: {self.template_path}") + + # 用于记录已合并的文件 + self.merged_files_json = os.path.join(self.output_dir, "merged_files.json") + self.merged_files = self._load_merged_files() + + 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]: """ diff --git a/app/core/excel/processor.py b/app/core/excel/processor.py index 87231ea..a3c38d4 100644 --- a/app/core/excel/processor.py +++ b/app/core/excel/processor.py @@ -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) - - # 获取模板文件路径 - 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) - - # 检查模板文件是否存在 - if not os.path.exists(self.template_path): - logger.error(f"模板文件不存在: {self.template_path}") - raise FileNotFoundError(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() - - logger.info(f"初始化完成,模板文件: {self.template_path}") + # 修复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') + + # 获取模板文件路径 + self.template_path = config.get('Paths', 'template_file', fallback='templates/银豹-采购单模板.xls') + if not os.path.exists(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() + + # 确保目录存在 + os.makedirs(self.output_dir, exist_ok=True) + os.makedirs(self.temp_dir, exist_ok=True) + + # 记录实际路径 + 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]: """ diff --git a/app/core/ocr/__pycache__/baidu_ocr.cpython-39.pyc b/app/core/ocr/__pycache__/baidu_ocr.cpython-39.pyc index abeda2a..0d04bf2 100644 Binary files a/app/core/ocr/__pycache__/baidu_ocr.cpython-39.pyc and b/app/core/ocr/__pycache__/baidu_ocr.cpython-39.pyc differ diff --git a/app/core/ocr/__pycache__/table_ocr.cpython-39.pyc b/app/core/ocr/__pycache__/table_ocr.cpython-39.pyc index aa67f94..37da3eb 100644 Binary files a/app/core/ocr/__pycache__/table_ocr.cpython-39.pyc and b/app/core/ocr/__pycache__/table_ocr.cpython-39.pyc differ diff --git a/app/core/ocr/baidu_ocr.py b/app/core/ocr/baidu_ocr.py index 14e2d7a..1ff4eef 100644 --- a/app/core/ocr/baidu_ocr.py +++ b/app/core/ocr/baidu_ocr.py @@ -105,34 +105,53 @@ 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') - - # 创建令牌管理器 - self.token_manager = TokenManager( - self.api_key, - self.secret_key, - self.max_retries, - self.retry_delay - ) - - # 验证API配置 - if not self.api_key or not self.secret_key: - logger.warning("API密钥未设置,请在配置文件中设置API密钥") + # 从配置中读取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( + self.api_key, + self.secret_key, + self.max_retries, + self.retry_delay + ) + + # 验证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]: """ diff --git a/app/core/ocr/table_ocr.py b/app/core/ocr/table_ocr.py index 725f3a4..7682c98 100644 --- a/app/core/ocr/table_ocr.py +++ b/app/core/ocr/table_ocr.py @@ -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客户端 - self.ocr_client = BaiduOCRClient(self.config) + # 修复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) + + # 记录实际路径 + 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}") + + # 初始化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.processed_files = self._load_processed_files() + + logger.info(f"初始化OCRProcessor完成:输入目录={self.input_folder}, 输出目录={self.output_folder}") + except Exception as e: + logger.error(f"初始化OCRProcessor失败: {e}") + raise + + def _load_processed_files(self) -> Dict[str, str]: + """ + 加载已处理的文件记录 - # 获取配置 - 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)}") - - 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') - - # 处理性能配置 - 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) - - # 初始化处理记录管理器 - record_file = self.config.get('Paths', 'processed_record', 'data/processed_files.json') - self.record_manager = ProcessedRecordManager(record_file) - - logger.info(f"OCR处理器初始化完成,输入目录: {self.input_folder}, 输出目录: {self.output_folder}") + 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,31 +344,38 @@ 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() if not unprocessed_images: logger.warning("没有需要处理的图片") 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) - - logger.info(f"批次处理完成, 成功: {sum(1 for result in results if result is not None)}/{len(batch)}") - - logger.info(f"所有图片处理完成, 总计: {total}, 成功: {success}") - return total, success \ No newline at end of file + # 统计成功数 + success_count += sum(1 for result in results if result is not None) + + logger.info(f"所有图片处理完成, 总计: {total}, 成功: {success_count}") + return total, success_count diff --git a/app/core/utils/__pycache__/dialog_utils.cpython-39.pyc b/app/core/utils/__pycache__/dialog_utils.cpython-39.pyc new file mode 100644 index 0000000..e27d99e Binary files /dev/null and b/app/core/utils/__pycache__/dialog_utils.cpython-39.pyc differ diff --git a/app/core/utils/__pycache__/log_utils.cpython-39.pyc b/app/core/utils/__pycache__/log_utils.cpython-39.pyc index 8771efd..377f308 100644 Binary files a/app/core/utils/__pycache__/log_utils.cpython-39.pyc and b/app/core/utils/__pycache__/log_utils.cpython-39.pyc differ diff --git a/app/core/utils/dialog_utils.py b/app/core/utils/dialog_utils.py new file mode 100644 index 0000000..af29ac0 --- /dev/null +++ b/app/core/utils/dialog_utils.py @@ -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) \ No newline at end of file diff --git a/app/core/utils/log_utils.py b/app/core/utils/log_utils.py index 099a2ec..ce765a6 100644 --- a/app/core/utils/log_utils.py +++ b/app/core/utils/log_utils.py @@ -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: """ 清理日志活跃标记 diff --git a/app/services/__pycache__/ocr_service.cpython-39.pyc b/app/services/__pycache__/ocr_service.cpython-39.pyc index 9edaa89..cd31aa9 100644 Binary files a/app/services/__pycache__/ocr_service.cpython-39.pyc and b/app/services/__pycache__/ocr_service.cpython-39.pyc differ diff --git a/app/services/__pycache__/tobacco_service.cpython-39.pyc b/app/services/__pycache__/tobacco_service.cpython-39.pyc new file mode 100644 index 0000000..5c04dc9 Binary files /dev/null and b/app/services/__pycache__/tobacco_service.cpython-39.pyc differ diff --git a/app/services/ocr_service.py b/app/services/ocr_service.py index c965fe4..2be2c1b 100644 --- a/app/services/ocr_service.py +++ b/app/services/ocr_service.py @@ -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: """ 验证图片是否有效 diff --git a/app/services/tobacco_service.py b/app/services/tobacco_service.py new file mode 100644 index 0000000..d5ed574 --- /dev/null +++ b/app/services/tobacco_service.py @@ -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}") \ No newline at end of file diff --git a/config/barcode_mappings.json b/config/barcode_mappings.json new file mode 100644 index 0000000..7d278cc --- /dev/null +++ b/config/barcode_mappings.json @@ -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" + } +} \ No newline at end of file diff --git a/logs/__main__.active b/logs/__main__.active new file mode 100644 index 0000000..b266a30 --- /dev/null +++ b/logs/__main__.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:39 \ No newline at end of file diff --git a/logs/__main__.log b/logs/__main__.log index 86403d2..98367b7 100644 --- a/logs/__main__.log +++ b/logs/__main__.log @@ -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 - 配置信息: +2025-05-09 11:58:49,250 - __main__ - INFO - 配置信息: +2025-05-09 12:02:05,165 - __main__ - INFO - 配置信息: +2025-05-09 12:07:05,179 - __main__ - INFO - 配置信息: +2025-05-09 12:07:54,655 - __main__ - INFO - 配置信息: +2025-05-09 12:12:42,101 - __main__ - INFO - 配置信息: +2025-05-09 12:13:52,578 - __main__ - INFO - 配置信息: +2025-05-09 12:45:35,994 - __main__ - INFO - 配置信息: +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 - 烟草订单处理失败 diff --git a/logs/app.core.excel.converter.active b/logs/app.core.excel.converter.active new file mode 100644 index 0000000..617fce6 --- /dev/null +++ b/logs/app.core.excel.converter.active @@ -0,0 +1 @@ +Active since: 2025-05-10 11:21:12 \ No newline at end of file diff --git a/logs/app.core.excel.converter.log b/logs/app.core.excel.converter.log index 9acdd9e..aebf1fc 100644 --- a/logs/app.core.excel.converter.log +++ b/logs/app.core.excel.converter.log @@ -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项 diff --git a/logs/app.core.excel.handlers.barcode_mapper.active b/logs/app.core.excel.handlers.barcode_mapper.active new file mode 100644 index 0000000..617fce6 --- /dev/null +++ b/logs/app.core.excel.handlers.barcode_mapper.active @@ -0,0 +1 @@ +Active since: 2025-05-10 11:21:12 \ No newline at end of file diff --git a/logs/app.core.excel.handlers.barcode_mapper.log b/logs/app.core.excel.handlers.barcode_mapper.log index e69de29..bb7f523 100644 --- a/logs/app.core.excel.handlers.barcode_mapper.log +++ b/logs/app.core.excel.handlers.barcode_mapper.log @@ -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 diff --git a/logs/app.core.excel.handlers.unit_converter_handlers.active b/logs/app.core.excel.handlers.unit_converter_handlers.active new file mode 100644 index 0000000..617fce6 --- /dev/null +++ b/logs/app.core.excel.handlers.unit_converter_handlers.active @@ -0,0 +1 @@ +Active since: 2025-05-10 11:21:12 \ No newline at end of file diff --git a/logs/app.core.excel.handlers.unit_converter_handlers.log b/logs/app.core.excel.handlers.unit_converter_handlers.log index 6831ead..a6a8184 100644 --- a/logs/app.core.excel.handlers.unit_converter_handlers.log +++ b/logs/app.core.excel.handlers.unit_converter_handlers.log @@ -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, 单位: 件 -> 瓶 diff --git a/logs/app.core.excel.merger.active b/logs/app.core.excel.merger.active new file mode 100644 index 0000000..5367524 --- /dev/null +++ b/logs/app.core.excel.merger.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:38 \ No newline at end of file diff --git a/logs/app.core.excel.merger.log b/logs/app.core.excel.merger.log index bd77cdd..882f714 100644 --- a/logs/app.core.excel.merger.log +++ b/logs/app.core.excel.merger.log @@ -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 diff --git a/logs/app.core.excel.processor.active b/logs/app.core.excel.processor.active new file mode 100644 index 0000000..5367524 --- /dev/null +++ b/logs/app.core.excel.processor.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:38 \ No newline at end of file diff --git a/logs/app.core.excel.processor.log b/logs/app.core.excel.processor.log index 7137c3c..19d3197 100644 --- a/logs/app.core.excel.processor.log +++ b/logs/app.core.excel.processor.log @@ -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 diff --git a/logs/app.core.excel.validators.active b/logs/app.core.excel.validators.active new file mode 100644 index 0000000..617fce6 --- /dev/null +++ b/logs/app.core.excel.validators.active @@ -0,0 +1 @@ +Active since: 2025-05-10 11:21:12 \ No newline at end of file diff --git a/logs/app.core.ocr.baidu_ocr.active b/logs/app.core.ocr.baidu_ocr.active new file mode 100644 index 0000000..1fe4767 --- /dev/null +++ b/logs/app.core.ocr.baidu_ocr.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:37 \ No newline at end of file diff --git a/logs/app.core.ocr.baidu_ocr.log b/logs/app.core.ocr.baidu_ocr.log index e51cdd7..2afc301 100644 --- a/logs/app.core.ocr.baidu_ocr.log +++ b/logs/app.core.ocr.baidu_ocr.log @@ -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 - 成功获取访问令牌 diff --git a/logs/app.core.ocr.table_ocr.active b/logs/app.core.ocr.table_ocr.active new file mode 100644 index 0000000..1fe4767 --- /dev/null +++ b/logs/app.core.ocr.table_ocr.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:37 \ No newline at end of file diff --git a/logs/app.core.ocr.table_ocr.log b/logs/app.core.ocr.table_ocr.log index f6daaea..e0a9d6a 100644 --- a/logs/app.core.ocr.table_ocr.log +++ b/logs/app.core.ocr.table_ocr.log @@ -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 diff --git a/logs/app.core.utils.file_utils.active b/logs/app.core.utils.file_utils.active new file mode 100644 index 0000000..2ec83bf --- /dev/null +++ b/logs/app.core.utils.file_utils.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:36 \ No newline at end of file diff --git a/logs/app.services.ocr_service.active b/logs/app.services.ocr_service.active new file mode 100644 index 0000000..1fe4767 --- /dev/null +++ b/logs/app.services.ocr_service.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:37 \ No newline at end of file diff --git a/logs/app.services.ocr_service.log b/logs/app.services.ocr_service.log index e89077d..c7b637f 100644 --- a/logs/app.services.ocr_service.log +++ b/logs/app.services.ocr_service.log @@ -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 diff --git a/logs/app.services.order_service.active b/logs/app.services.order_service.active new file mode 100644 index 0000000..5367524 --- /dev/null +++ b/logs/app.services.order_service.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:38 \ No newline at end of file diff --git a/logs/app.services.order_service.log b/logs/app.services.order_service.log index cf0cdb2..d2ff2c6 100644 --- a/logs/app.services.order_service.log +++ b/logs/app.services.order_service.log @@ -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 diff --git a/logs/app.services.tobacco_service.active b/logs/app.services.tobacco_service.active new file mode 100644 index 0000000..b266a30 --- /dev/null +++ b/logs/app.services.tobacco_service.active @@ -0,0 +1 @@ +Active since: 2025-05-09 16:01:39 \ No newline at end of file diff --git a/logs/app.services.tobacco_service.log b/logs/app.services.tobacco_service.log new file mode 100644 index 0000000..2ac9467 --- /dev/null +++ b/logs/app.services.tobacco_service.log @@ -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 - 未找到可处理的烟草订单明细文件 diff --git a/run.py b/run.py index f7cea95..180bc97 100644 --- a/run.py +++ b/run.py @@ -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='输入订单明细文件路径') + + # 解析参数 + parsed_args = parser.parse_args() + + return parsed_args -def run_ocr(ocr_service: OCRService, args) -> bool: +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 - - 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 = parse_args() - 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 + # 加载配置 + 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: - # 创建配置管理器 - config = ConfigManager(parsed_args.config) if parsed_args.config else ConfigManager() - - # 创建服务 - 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) - else: - parser.print_help() - return 1 + 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 - return 0 if success 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) + + # 1. OCR处理 + if args.input: + # 处理单个文件 + excel_file = ocr_service.process_image(args.input) + else: + # 批量处理 + 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 + + # 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()) \ No newline at end of file diff --git a/启动器.py b/启动器.py index b17eab3..4951e41 100644 --- a/启动器.py +++ b/启动器.py @@ -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() \ No newline at end of file