gchr_bookings.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import logging
  2. import os
  3. from datetime import datetime
  4. from pathlib import Path
  5. import pandas as pd
  6. class GchrBookings:
  7. base_dir: str
  8. account_bookings: list[str]
  9. _df_bookings: pd.DataFrame
  10. booking_date: datetime
  11. def __init__(self, base_dir: list[str], first_month: str = None):
  12. self.base_dir = base_dir
  13. self.account_bookings = list(Path(self.base_dir).joinpath("data").glob("GuV_Bilanz_Salden*.csv"))
  14. self.first_month_of_financial_year = first_month or "01"
  15. self._df_bookings = self.load_bookings_from_file()
  16. def load_bookings_from_file(self) -> None:
  17. df_list: list[pd.DataFrame] = []
  18. timestamps: list[float] = []
  19. for csv_file in self.account_bookings:
  20. df_list.append(
  21. pd.read_csv(
  22. csv_file,
  23. decimal=",",
  24. sep=";",
  25. encoding="latin-1",
  26. converters={0: str, 1: str},
  27. )
  28. )
  29. timestamps.append(Path(csv_file).stat().st_mtime)
  30. self.booking_date = datetime.fromtimestamp(max(timestamps))
  31. df = pd.concat(df_list)
  32. df["amount"] = (df["Debit Amount"] + df["Credit Amount"]).round(2)
  33. return df
  34. def set_bookkeep_period(self, year: str, month: str) -> None:
  35. self.current_year = year
  36. self.current_month = month
  37. self.period = f"{year}-{month}"
  38. prot_file = f"{self.export_info_dir}\\protokoll_{self.period}.log"
  39. logging.basicConfig(
  40. filename=prot_file,
  41. filemode="w",
  42. encoding="utf-8",
  43. level=logging.DEBUG,
  44. force=True,
  45. )
  46. @property
  47. def last_year(self) -> str:
  48. return str(int(self.current_year) - 1)
  49. @property
  50. def last_year2(self) -> str:
  51. return str(int(self.current_year) - 2)
  52. @property
  53. def next_year(self) -> str:
  54. return str(int(self.current_year) + 1)
  55. def filter_bookings(self, year: str, month: str) -> pd.DataFrame:
  56. self.set_bookkeep_period(year, month)
  57. # Kontensalden auf gegebenen Monat filtern
  58. filter_from = self.current_year + self.first_month_of_financial_year
  59. filter_prev = self.last_year + self.first_month_of_financial_year
  60. if self.first_month_of_financial_year > self.current_month:
  61. filter_from = self.last_year + self.first_month_of_financial_year
  62. filter_prev = self.last_year2 + self.first_month_of_financial_year
  63. filter_to = self.current_year + self.current_month
  64. filter_opening = self.current_year + "00"
  65. filter_prev_opening = self.last_year + "00"
  66. prev_year_closed = True
  67. df_opening_balance = self._df_bookings[(self._df_bookings["Bookkeep Period"] == filter_opening)]
  68. if df_opening_balance.shape[0] == 0:
  69. df_opening_balance = self._df_bookings[
  70. (self._df_bookings["Bookkeep Period"] == filter_prev_opening)
  71. | (
  72. (self._df_bookings["Bookkeep Period"] >= filter_prev)
  73. & (self._df_bookings["Bookkeep Period"] < filter_from)
  74. )
  75. ].copy()
  76. df_opening_balance["Bookkeep Period"] = filter_opening
  77. prev_year_closed = False
  78. df_opening_balance = df_opening_balance[(df_opening_balance["Konto_Nr_Händler"].str.contains(r"-[013]\d\d+-"))]
  79. opening_balance = df_opening_balance["amount"].aggregate("sum").round(2)
  80. logging.info("Gewinn/Verlustvortrag")
  81. logging.info(opening_balance)
  82. if not prev_year_closed:
  83. row = {
  84. "Konto_Nr_Händler": "01-01-0861-00-00-00",
  85. "Bookkeep Period": filter_opening,
  86. "Debit Amount": opening_balance * -1,
  87. "Credit Amount": 0,
  88. "Debit Quantity": 0,
  89. "Credit Quantity": 0,
  90. "amount": opening_balance * -1,
  91. }
  92. df_opening_balance = pd.concat([df_opening_balance, pd.DataFrame.from_records([row])])
  93. df_filtered = self._df_bookings[
  94. (self._df_bookings["Bookkeep Period"] >= filter_from) & (self._df_bookings["Bookkeep Period"] <= filter_to)
  95. ]
  96. # Buchungen kopieren und als Statistikkonten anhängen
  97. df_stats = df_filtered.copy()
  98. # df_stats = df_stats[df_stats['Konto_Nr_Händler'].str.match(r'-[24578]\d\d\d-')]
  99. df_stats["Konto_Nr_Händler"] = df_stats["Konto_Nr_Händler"].str.replace(r"-(\d\d\d+)-", r"-\1_STK-", regex=True)
  100. df_stats["amount"] = (df_filtered["Debit Quantity"] + df_filtered["Credit Quantity"]).round(2)
  101. df_combined = pd.concat([df_opening_balance, df_filtered, df_stats])
  102. # Spalten konvertieren
  103. df_combined["period"] = df_combined["Bookkeep Period"].apply(lambda x: self.bookkeep_filter[x])
  104. return df_combined[df_combined["amount"] != 0.00]
  105. @property
  106. def bookkeep_filter(self) -> dict[str, str]:
  107. period = [self.current_year + str(i).zfill(2) for i in range(1, 13)]
  108. if self.first_month_of_financial_year != "01":
  109. if self.first_month_of_financial_year > self.current_month:
  110. period = [self.last_year + str(i).zfill(2) for i in range(1, 13)] + period
  111. else:
  112. period = period + [self.next_year + str(i).zfill(2) for i in range(1, 13)]
  113. fm = int(self.first_month_of_financial_year)
  114. period = period[fm - 1 : fm + 12]
  115. period = [self.current_year + "00"] + period
  116. rename_to = ["OpeningBalance"] + ["Period" + str(i).zfill(2) for i in range(1, 13)]
  117. return dict(zip(period, rename_to))
  118. @property
  119. def export_info_dir(self) -> str:
  120. info_dir = f"{self.base_dir}\\Export\\{self.current_year}\\info\\"
  121. os.makedirs(info_dir, exist_ok=True)
  122. return info_dir