- # -*- coding: utf-8 -*-
- # Excel 转换工具配置文件
- import os
- import json
- import sys
- import logging
-
- # 模板文件路径
- TEMPLATE_PATH = "template.xlsx"
-
- # 配置文件路径
- # 检测是否为打包环境
- if getattr(sys, 'frozen', False):
- # PyInstaller打包后的环境
- CONFIG_DIR = os.path.dirname(sys.executable)
- else:
- # 开发环境
- CONFIG_DIR = os.path.dirname(os.path.abspath(__file__))
-
- EMPLOYEE_CONFIG_PATH = os.path.join(CONFIG_DIR, "employee_info.json")
- COMPANY_CONFIG_PATH = os.path.join(CONFIG_DIR, "company_options.json") # 保留兼容性
- BANK_CONFIG_PATH = os.path.join(CONFIG_DIR, "bank_options.json") # 保留兼容性
-
- # 设置日志记录
- logging.basicConfig(
- level=logging.DEBUG,
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
- handlers=[
- logging.FileHandler(os.path.join(CONFIG_DIR, "config.log")),
- logging.StreamHandler()
- ]
- )
- logger = logging.getLogger("config")
-
- # 单元格映射关系(源文件位置 -> 目标文件位置)
- # 格式:{(源文件sheet索引, 行, 列): (目标文件sheet索引, 行, 列)}
- # 注意:源文件行索引为0表示从C3开始的行
- CELL_MAPPINGS = {
- # 第一个Sheet的映射关系
- (0, 0, 3): (0, 2, 5), # C3 -> E2 氏名
- (0, 0, 4): (0, 3, 5), # D3 -> E3 労働日数
- (0, 0, 2): (0, 3, 3), # B3 -> C3 ID
- (0, 0, 5): (0, 6, 4), # E3 -> D6 基本給
- (0, 0, 6): (0, 7, 4), # F3 -> D7 職務給
- (0, 0, 7): (0, 8, 4), # G3 -> D8 資格手当
- (0, 0, 8): (0, 9, 4), # H3 -> D9 住宅手当
- (0, 0, 9): (0, 10, 4), # I3 -> D10 能力手当
- (0, 0, 10): (0, 11, 4), # J3 -> D11 通勤手当
- (0, 0, 11): (0, 12, 4), # K3 -> D12 残業(固定)
- (0, 0, 12): (0, 13, 4), # L3 -> D13 週末・祝日出勤手当
- (0, 0, 13): (0, 14, 4), # M3 -> D14 時間外EC操作
- (0, 0, 15): (0, 17, 4), # O3 -> D17
- (0, 0, 16): (0, 18, 4), # P3 -> D18
- (0, 0, 17): (0, 19, 4), # Q3 -> D19
- (0, 0, 18): (0, 20, 4), # R3 -> D20
- (0, 0, 19): (0, 21, 4), # S3 -> D21
- (0, 0, 20): (0, 22, 4), # T3 -> D22
- (0, 0, 25): (0, 25, 5), # Y3 -> E25
- }
-
- # 自定义值的单元格位置
- CUSTOM_CELLS = {
- "company": (0, 2, 3), # C2 - 所属公司
- "bank": (0, 29, 2), # B29 - 转账银行
- "other": (0, 2, 6), # F2 - 其他信息
- }
-
- # 文件名提取信息
- FILENAME_CONFIG = {
- "name_cell": (0, 3, 3), # Sheet1 的 C3 - 员工姓名
- "year_month_cell": (1, 4, 2), # Sheet2 的 B4 - 年月信息
- }
-
- # 第二个Sheet的命名格式
- SHEET2_NAME_FORMAT = "{month}月勤怠一覧"
-
- # 输出文件名格式
- OUTPUT_FILENAME_FORMAT = "{year}年{month}月份給料明細書-{name}.xlsx"
-
- # 默认选项列表(仅在配置文件不存在时使用)
- DEFAULT_COMPANY_OPTIONS = []
-
- # 银行信息默认结构 - 扩展为字典格式,包含更多字段
- DEFAULT_BANK_OPTIONS = [
- # 银行信息示例:
- # {
- # "employee_name": "田中太郎", # 员工姓名
- # "bank_name": "三井住友銀行", # 银行名称
- # "branch_account": "新宿通支店661 普通 8324403", # 支店和账号
- # "account_holder": "田中太郎" # 账户持有人
- # }
- ]
-
- # 员工信息默认结构 - 合并公司和银行信息
- DEFAULT_EMPLOYEE_INFO = [
- # 员工信息示例:
- # {
- # "employee_name": "田中太郎", # 员工姓名
- # "bank_name": "三井住友銀行", # 银行名称
- # "branch_account": "新宿通支店661 普通 8324403", # 支店和账号
- # "account_holder": "田中太郎", # 账户持有人
- # "company_name": "SPD株式会社" # 所属公司
- # }
- ]
-
- # 加载员工信息
- def load_employee_info():
- # 检查是否存在员工信息配置
- logger.debug("尝试从 {0} 加载员工信息".format(EMPLOYEE_CONFIG_PATH))
-
- if os.path.exists(EMPLOYEE_CONFIG_PATH):
- try:
- with open(EMPLOYEE_CONFIG_PATH, 'r', encoding='utf-8') as f:
- employee_info = json.load(f)
- logger.info("成功加载 {0} 条员工信息".format(len(employee_info)))
- return employee_info
- except Exception as e:
- logger.error("加载员工信息出错: {0}".format(str(e)))
- return DEFAULT_EMPLOYEE_INFO
- else:
- # 如果不存在,尝试从旧的配置中导入
- logger.warning("员工信息配置文件不存在,尝试从旧配置导入")
- employee_info = []
- company_options = []
- bank_options = []
-
- # 加载旧的公司配置
- if os.path.exists(COMPANY_CONFIG_PATH):
- try:
- with open(COMPANY_CONFIG_PATH, 'r', encoding='utf-8') as f:
- company_options = json.load(f)
- logger.info("从旧配置加载了 {0} 个公司选项".format(len(company_options)))
- except Exception as e:
- logger.error("加载公司配置出错: {0}".format(str(e)))
-
- # 加载旧的银行配置
- if os.path.exists(BANK_CONFIG_PATH):
- try:
- with open(BANK_CONFIG_PATH, 'r', encoding='utf-8') as f:
- bank_options = json.load(f)
-
- # 兼容旧版本:如果是字符串列表,转换为字典
- if bank_options and isinstance(bank_options[0], str):
- new_bank_options = []
- for bank_name in bank_options:
- new_bank_options.append({
- "employee_name": "",
- "bank_name": bank_name,
- "branch_account": "",
- "account_holder": ""
- })
- bank_options = new_bank_options
- logger.info("从旧配置加载了 {0} 个银行选项".format(len(bank_options)))
- except Exception as e:
- logger.error("加载银行配置出错: {0}".format(str(e)))
-
- # 合并旧配置
- if bank_options and isinstance(bank_options[0], dict):
- for bank_option in bank_options:
- employee_name = bank_option.get("employee_name", "")
- if employee_name: # 如果有员工姓名,则添加为一条记录
- employee_info.append({
- "employee_name": employee_name,
- "bank_name": bank_option.get("bank_name", ""),
- "branch_account": bank_option.get("branch_account", ""),
- "account_holder": bank_option.get("account_holder", ""),
- "company_name": company_options[0] if company_options else ""
- })
-
- # 保存新的员工信息
- save_options(EMPLOYEE_CONFIG_PATH, employee_info)
- logger.info("创建了新的员工信息配置,包含 {0} 条记录".format(len(employee_info)))
- return employee_info
-
- # 保存选项
- def save_options(config_path, options):
- try:
- # 确保目录存在
- config_dir = os.path.dirname(config_path)
- if not os.path.exists(config_dir):
- os.makedirs(config_dir)
- logger.info("创建目录: {0}".format(config_dir))
-
- # 保存前记录当前工作目录和文件路径
- logger.debug("当前工作目录: {0}".format(os.getcwd()))
- logger.debug("保存配置到: {0}".format(config_path))
-
- # 保存配置
- with open(config_path, 'w', encoding='utf-8') as f:
- json.dump(options, f, ensure_ascii=False, indent=4)
-
- # 验证保存是否成功
- if os.path.exists(config_path):
- logger.info("成功保存配置到 {0}".format(config_path))
- return True
- else:
- logger.error("保存失败,文件不存在: {0}".format(config_path))
- return False
- except Exception as e:
- logger.error("保存配置出错: {0}".format(str(e)), exc_info=True)
- return False
-
- # 加载选项
- try:
- logger.info("开始加载配置...")
- EMPLOYEE_INFO = load_employee_info()
- COMPANY_OPTIONS = [info.get("company_name") for info in EMPLOYEE_INFO if info.get("company_name")]
- COMPANY_OPTIONS = list(set(COMPANY_OPTIONS)) # 去重
- BANK_OPTIONS = [info for info in EMPLOYEE_INFO] # 兼容性:旧代码可能仍使用BANK_OPTIONS
- logger.info("加载了 {0} 条员工信息, {1} 个公司选项".format(len(EMPLOYEE_INFO), len(COMPANY_OPTIONS)))
- except Exception as e:
- logger.critical("配置加载失败: {0}".format(str(e)), exc_info=True)
- EMPLOYEE_INFO = DEFAULT_EMPLOYEE_INFO
- COMPANY_OPTIONS = []
- BANK_OPTIONS = []
|