#!/usr/bin/env python3 """ 配置文件加载工具 支持从config.ini读取配置参数 """ import configparser import os from typing import Any, Optional from dataclasses import dataclass @dataclass class ExcelConfig: """Excel配置""" input_file: str sheet_name: str data_start_row: int col_received_amount: int col_handling_fee: int col_order_num: int col_amount: int col_account_name: int @dataclass class OutputConfig: """输出配置""" json_output: str excel_output: str validation_report: str @dataclass class ProcessingConfig: """处理配置""" amount_tolerance: float skip_empty_orders: bool @dataclass class AccountingConfig: """会计配置""" default_exchange_rate: float exchange_rate_file: str account_code_bank: str account_code_fee: str account_code_receivable: str account_name_bank: str account_name_fee: str account_name_receivable: str @dataclass class LoggingConfig: """日志配置""" log_level: str log_format: str log_file: str class ConfigLoader: """配置加载器""" def __init__(self, config_file: str = 'config.ini'): """ 初始化配置加载器 参数: config_file: 配置文件路径 """ self.config_file = config_file self.config = configparser.ConfigParser() if os.path.exists(config_file): self.config.read(config_file, encoding='utf-8') else: raise FileNotFoundError(f"配置文件不存在: {config_file}") def _get_value(self, section: str, key: str, default: Any = None, value_type: type = str) -> Any: """ 获取配置值 参数: section: 配置节名 key: 配置键名 default: 默认值 value_type: 值类型 返回: 配置值 """ try: if value_type == bool: return self.config.getboolean(section, key) elif value_type == int: return self.config.getint(section, key) elif value_type == float: return self.config.getfloat(section, key) else: return self.config.get(section, key) except (configparser.NoSectionError, configparser.NoOptionError): return default def load_excel_config(self) -> ExcelConfig: """加载Excel配置""" return ExcelConfig( input_file=self._get_value('Excel', 'input_file', 'data/data.xlsx'), sheet_name=self._get_value('Excel', 'sheet_name', 'Sheet1'), data_start_row=self._get_value('Excel', 'data_start_row', 2, int), col_received_amount=self._get_value('Excel', 'col_received_amount', 6, int), col_handling_fee=self._get_value('Excel', 'col_handling_fee', 7, int), col_order_num=self._get_value('Excel', 'col_order_num', 8, int), col_amount=self._get_value('Excel', 'col_amount', 9, int), col_account_name=self._get_value('Excel', 'col_account_name', 15, int) ) def load_output_config(self) -> OutputConfig: """加载输出配置""" return OutputConfig( json_output=self._get_value('Output', 'json_output', 'res.json'), excel_output=self._get_value('Output', 'excel_output', 'AccountingEntries.xlsx'), validation_report=self._get_value('Output', 'validation_report', 'validation_report.txt') ) def load_processing_config(self) -> ProcessingConfig: """加载处理配置""" return ProcessingConfig( amount_tolerance=self._get_value('Processing', 'amount_tolerance', 0.01, float), skip_empty_orders=self._get_value('Processing', 'skip_empty_orders', True, bool) ) def load_accounting_config(self) -> AccountingConfig: """加载会计配置""" return AccountingConfig( default_exchange_rate=self._get_value('Accounting', 'default_exchange_rate', 7.1072, float), exchange_rate_file=self._get_value('Accounting', 'exchange_rate_file', 'exchange_rate.txt'), account_code_bank=self._get_value('Accounting', 'account_code_bank', '1002.02'), account_code_fee=self._get_value('Accounting', 'account_code_fee', '5603.03'), account_code_receivable=self._get_value('Accounting', 'account_code_receivable', '1122'), account_name_bank=self._get_value('Accounting', 'account_name_bank', '银行存款 - 中行USD'), account_name_fee=self._get_value('Accounting', 'account_name_fee', '财务费用-手续费'), account_name_receivable=self._get_value('Accounting', 'account_name_receivable', '应收账款') ) def load_logging_config(self) -> LoggingConfig: """加载日志配置""" return LoggingConfig( log_level=self._get_value('Logging', 'log_level', 'INFO'), log_format=self._get_value('Logging', 'log_format', '%(asctime)s - %(levelname)s - %(message)s'), log_file=self._get_value('Logging', 'log_file', 'processing.log') ) def load_all(self) -> dict: """ 加载所有配置 返回: 包含所有配置的字典 """ return { 'excel': self.load_excel_config(), 'output': self.load_output_config(), 'processing': self.load_processing_config(), 'accounting': self.load_accounting_config(), 'logging': self.load_logging_config() } def main(): """测试配置加载""" try: loader = ConfigLoader() configs = loader.load_all() print("配置加载成功:") print("-" * 60) print("\nExcel配置:") print(f" 输入文件: {configs['excel'].input_file}") print(f" 工作表: {configs['excel'].sheet_name}") print(f" 数据起始行: {configs['excel'].data_start_row}") print("\n输出配置:") print(f" JSON输出: {configs['output'].json_output}") print(f" Excel输出: {configs['output'].excel_output}") print("\n处理配置:") print(f" 金额容差: {configs['processing'].amount_tolerance}") print(f" 跳过空订单: {configs['processing'].skip_empty_orders}") print("\n会计配置:") print(f" 默认汇率: {configs['accounting'].default_exchange_rate}") print(f" 银行科目代码: {configs['accounting'].account_code_bank}") print("\n日志配置:") print(f" 日志级别: {configs['logging'].log_level}") print(f" 日志文件: {configs['logging'].log_file}") except Exception as e: print(f"配置加载失败: {e}") if __name__ == '__main__': main()