gchr_bookings.py 5.7 KB

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