| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- import pandas as pd
- from tkinter import messagebox
- from fund_classification_rules import get_classification_rules
- class JournalGenerator:
- """日记账生成器"""
-
- def __init__(self):
- self.param_df = None
- self.account_info_df = None
- self.shouzhi_class_df = None
- self.classification_rules = get_classification_rules()
-
- def load_parameter_table(self, param_file_path):
- """加载参数表"""
- try:
- self.param_df = pd.read_excel(param_file_path, dtype=str)
-
- account_info_sheet = pd.read_excel(param_file_path, sheet_name="账户信息参数", dtype=str, header=1)
- self.account_info_df = account_info_sheet
-
- shouzhi_class_sheet = pd.read_excel(param_file_path, sheet_name="收支分类参数", dtype=str, header=1)
- self.shouzhi_class_df = shouzhi_class_sheet
-
- return True
- except Exception as e:
- messagebox.showerror("错误", f"加载参数表失败:{str(e)}")
- return False
-
- def generate_journal_data(self, company_name, bank_name, param_file_path, flow_df):
- """生成日记账数据"""
- if not self.load_parameter_table(param_file_path):
- return None
-
- try:
- bank_keyword_mapping = {
- "微众银行": "微众",
- "中国银行": "中国银行",
- "农业银行": "农业银行",
- "建设银行": "建设银行"
- }
-
- bank_keyword = bank_keyword_mapping.get(bank_name, bank_name)
-
- company_accounts = self.account_info_df[self.account_info_df["公司"] == company_name]
-
- account_info = None
- for _, account in company_accounts.iterrows():
- if bank_keyword in account["开户行"]:
- account_info = company_accounts[company_accounts.index == account.name]
- break
-
- if account_info is None or account_info.empty:
- messagebox.showerror("错误", f"未找到账户信息:{company_name} - {bank_name}")
- return None
-
- account_code = account_info["编号"].values[0]
- account_short_name = account_info["简称"].values[0]
- company_name_full = account_info["公司"].values[0]
-
- journal_data = []
-
- for _, row in flow_df.iterrows():
- transaction_time = row["交易时间"]
- opponent_name = str(row["对方户名"]).strip()
- summary = str(row["摘要"]).strip()
- income = pd.to_numeric(row["收入"], errors="coerce")
- expense = pd.to_numeric(row["支出"], errors="coerce")
- balance = str(row["余额"]).strip()
-
- if pd.isna(income):
- income = 0
- if pd.isna(expense):
- expense = 0
-
- if income == 0 and expense == 0:
- continue
-
- amount = income if income > 0 else expense
- shouzhi_type = "收入" if income > 0 else "支出"
-
- try:
- transaction_date = pd.to_datetime(transaction_time, errors="coerce")
- if pd.isna(transaction_date):
- continue
- formatted_date = f"{transaction_date.year}/{transaction_date.month}/{transaction_date.day}"
- month = str(transaction_date.month)
- except:
- continue
-
- opponent_bank = str(row.get("对方开户机构", "")).strip()
- flow_remark = str(row.get("备注", "")).strip()
-
- is_settlement = False
- if opponent_name in self.account_info_df["公司"].values:
- is_settlement = True
-
- context = {
- "is_settlement": is_settlement,
- "income": income,
- "opponent_name": opponent_name,
- "summary": summary,
- "flow_remark": flow_remark
- }
-
- fund_level1 = ""
- fund_level2 = ""
- fund_level3 = ""
-
- for rule in self.classification_rules:
- if rule.match(context):
- result = rule.apply(context)
- fund_level1 = result["level1"]
- fund_level2 = result["level2"]
- fund_level3 = result["level3"]
- break
-
- if "手续费" in summary or "服务费" in summary:
- opponent_name = "手续费"
- remark = "手续费"
- elif "会长提现" in flow_remark or "提现" in flow_remark:
- remark = opponent_name + flow_remark
- elif flow_remark is not None and flow_remark.strip() != "" and flow_remark != "nan":
- remark = flow_remark
- else:
- remark = opponent_name + opponent_bank
-
- journal_row = {
- "编号": account_code,
- "简称": account_short_name,
- "企业": company_name_full,
- "日期": formatted_date,
- "月份": month,
- "收支": shouzhi_type,
- "资金分类-1级": fund_level1,
- "资金分类-2级": fund_level2,
- "资金分类-3级": fund_level3,
- "对手户": opponent_name,
- "备注": remark,
- "发生额": amount,
- "余额": balance,
- "备注.1": ""
- }
-
- journal_data.append(journal_row)
-
- if not journal_data:
- messagebox.showwarning("警告", "未生成任何日记账数据")
- return None
-
- journal_df = pd.DataFrame(journal_data)
-
- column_order = ["编号", "简称", "企业", "日期", "月份", "收支", "资金分类-1级",
- "资金分类-2级", "资金分类-3级", "对手户", "备注", "发生额", "余额", "备注.1"]
- journal_df = journal_df[column_order]
-
- return journal_df
-
- except Exception as e:
- messagebox.showerror("错误", f"生成日记账数据失败:{str(e)}")
- return None
-
- def save_journal(self, journal_df, save_path):
- """保存日记账"""
- try:
- journal_df.to_excel(save_path, index=False)
- return True
- except Exception as e:
- messagebox.showerror("错误", f"保存日记账失败:{str(e)}")
- return False
|