gcstruct.py 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. import csv
  2. import json
  3. import re
  4. import xml.etree.ElementTree as ET
  5. from functools import reduce
  6. from pathlib import Path
  7. import chevron
  8. import numpy as np
  9. import pandas as pd
  10. # from shutil import copyfile
  11. from bs4 import BeautifulSoup
  12. def get_flat(node):
  13. result = [
  14. {
  15. "id": node["id"],
  16. "text": node["text"],
  17. "amount_text": node["amount_text"],
  18. "children": [x["id"] for x in node["children"]],
  19. "children2": [],
  20. "parents": node["parents"],
  21. "accounts": node["accounts"],
  22. "costcenter": "",
  23. "level": node["level"],
  24. "drilldown": node["level"] < 2, # (node['level'] != 2 and len(node['accounts']) == 0),
  25. "form": node["form"],
  26. "accountlevel": False,
  27. "absolute": True,
  28. "seasonal": True,
  29. "status": "0",
  30. "values": [],
  31. "values2": {},
  32. }
  33. ]
  34. for child in node["children"]:
  35. result += get_flat(child)
  36. return result
  37. def get_parents_list(p_list):
  38. id = ";".join(p_list) + ";" * (10 - len(p_list))
  39. if len(p_list) > 0:
  40. return [id] + get_parents_list(p_list[:-1])
  41. return [";" * 9]
  42. def structure_from_tree(node):
  43. result = []
  44. result.append(node["id"])
  45. for child in node["children"]:
  46. result.extend(structure_from_tree(child))
  47. return result
  48. def xml_from_tree(xml_node, tree_node):
  49. for child in tree_node["children"]:
  50. element = ET.SubElement(xml_node, "Ebene")
  51. element.set("Name", child["text"])
  52. xml_from_tree(element, child)
  53. def split_it(text, index):
  54. try:
  55. return re.findall(r"([^;]+) - ([^;]*);;", text)[0][index]
  56. except Exception:
  57. return ""
  58. def last_layer(text):
  59. try:
  60. return re.findall(r"([^;]+);;", text)[0]
  61. except Exception:
  62. return ""
  63. def get_default_cols(i):
  64. return ["Ebene" + str(i) for i in range(i * 10 + 1, (i + 1) * 10 + 1)]
  65. def get_structure_exports(s):
  66. result = {
  67. "files": {},
  68. "format": {
  69. "KontoFormat": "{0} - {1}",
  70. "HerstellerkontoFormat": "{{Herstellerkonto_Nr}}",
  71. "HerstellerBezeichnungFormat": "{{Herstellerkonto_Bez}}",
  72. "NeueHerstellerkontenAnlegen": False,
  73. },
  74. }
  75. export_files = [
  76. "ExportStk",
  77. "ExportStrukturenStk",
  78. "ExportAdjazenz",
  79. "ExportUebersetzung",
  80. "ExportUebersetzungStk",
  81. "ExportHerstellerKontenrahmen",
  82. ]
  83. export_format = [
  84. "KontoFormat",
  85. "HerstellerkontoFormat",
  86. "HerstellerBezeichnungFormat",
  87. "NeueHerstellerkontenAnlegen",
  88. ]
  89. for e in export_files:
  90. if s.find(e) is not None and s.find(e).text is not None and s.find(e).text[-4:] == ".csv":
  91. result["files"][e] = s.find(e).text
  92. for e in export_format:
  93. if s.find(e) is not None and s.find(e).text != "":
  94. result["format"][e] = s.find(e).text
  95. result["format"]["NeueHerstellerkontenAnlegen"] = result["format"]["NeueHerstellerkontenAnlegen"] == "true"
  96. return result
  97. class GCStruct:
  98. config = {
  99. "path": "c:/projekte/python/gcstruct",
  100. "path2": "c:/projekte/python/gcstruct",
  101. "file": "c:/projekte/python/gcstruct/config/config.xml",
  102. "output": "gcstruct.json",
  103. "default": [],
  104. "special": {},
  105. "special2": {
  106. "Planner": ["Kostenstelle", "Ebene1", "Ebene2"],
  107. "Test": ["Ebene1", "Ebene2"],
  108. },
  109. "columns": [
  110. "Konto_Nr",
  111. "Konto_Bezeichnung",
  112. "Konto_Art",
  113. "Konto_KST",
  114. "Konto_STK",
  115. "Konto_1",
  116. "Konto_2",
  117. "Konto_3",
  118. "Konto_4",
  119. "Konto_5",
  120. ],
  121. "struct": {},
  122. "export": {},
  123. }
  124. json_result = {
  125. "accounts": {},
  126. "tree": {},
  127. "flat": {},
  128. "struct_export": {},
  129. "skr51_vars": {},
  130. }
  131. structure_ids = []
  132. translate = {
  133. "Konto_Nr": "SKR51",
  134. "Kostenstelle": "KST",
  135. "Absatzkanal": "ABS",
  136. "Kostenträger": "KTR",
  137. "Marke": "MAR",
  138. "Standort": "STA",
  139. "Marke_HBV": "MAR",
  140. "Standort_HBV": "BMC",
  141. }
  142. def __init__(self, struct_dir, export_dir=None):
  143. self.config["path"] = struct_dir
  144. self.config["path2"] = struct_dir + "/export" if export_dir is None else export_dir
  145. self.config["file"] = f"{self.config['path']}/config/gcstruct.xml"
  146. if not Path(self.config["file"]).exists():
  147. self.config["file"] = f"{self.config['path']}/config/config.xml"
  148. cfg = ET.parse(self.config["file"])
  149. self.config["default"] = [
  150. s.find("Name").text for s in cfg.getroot().find("Strukturdefinitionen").findall("Struktur")
  151. ]
  152. self.config["export"] = dict(
  153. [
  154. (s.find("Name").text, get_structure_exports(s))
  155. for s in cfg.getroot().find("Strukturdefinitionen").findall("Struktur")
  156. ]
  157. )
  158. struct = dict([(x, get_default_cols(i)) for (i, x) in enumerate(self.config["default"])])
  159. struct.update(self.config["special"])
  160. self.config["struct"] = struct
  161. # print(self.config['struct'])
  162. def export_header(self, filetype):
  163. return {
  164. "ExportStk": [],
  165. "ExportStrukturenStk": [],
  166. "ExportAdjazenz": [],
  167. "ExportUebersetzung": [
  168. "Konto_Nr_Hersteller",
  169. "Konto_Nr_Split",
  170. "Konto_Nr_Haendler",
  171. "Info",
  172. ],
  173. "ExportUebersetzungStk": [
  174. "Konto_Nr_Hersteller",
  175. "Konto_Nr_Split",
  176. "Konto_Nr_Haendler",
  177. "Info",
  178. ],
  179. "ExportHerstellerKontenrahmen": [
  180. "Konto_Nr",
  181. "Konto_Bezeichnung",
  182. "Case",
  183. "Info",
  184. ],
  185. }.get(filetype, [])
  186. def accounts_from_csv(self, struct):
  187. max_rows = (len(self.config["default"]) + 1) * 10
  188. with open(
  189. f"{self.config['path']}/Kontenrahmen/Kontenrahmen.csv",
  190. "r",
  191. encoding="latin-1",
  192. ) as f:
  193. csv_reader = csv.reader(f, delimiter=";")
  194. imported_csv = [row[:max_rows] for row in csv_reader]
  195. df = pd.DataFrame.from_records(np.array(imported_csv[1:], dtype="object"), columns=imported_csv[0]).fillna(
  196. value=""
  197. )
  198. df = df.rename(columns={"Kostenstelle": "Konto_KST", "STK": "Konto_STK"})
  199. for i, (s, cols) in enumerate(struct.items()):
  200. df[s] = reduce(lambda x, y: x + ";" + df[y], cols, "")
  201. df[s] = df[s].apply(lambda x: x[1:])
  202. df["LetzteEbene" + str(i + 1)] = df[s].apply(lambda x: last_layer(x))
  203. df["LetzteEbene" + str(i + 1) + "_Nr"] = df[s].apply(lambda x: split_it(x, 0))
  204. df["LetzteEbene" + str(i + 1) + "_Bez"] = df[s].apply(lambda x: split_it(x, 1))
  205. df["Herstellerkonto_Nr"] = df["LetzteEbene1_Nr"]
  206. df["Herstellerkonto_Bez"] = df["LetzteEbene1_Bez"]
  207. return df
  208. def tree_from_xml(self, struct, df):
  209. result = {}
  210. for s, cols in struct.items():
  211. try:
  212. tree = ET.parse(f"{self.config['path']}/Xml/{s}.xml")
  213. result[s] = self.get_tree_root(tree.getroot(), s)
  214. except FileNotFoundError:
  215. print("XML-Datei fehlt")
  216. used_entries = [x.split(";")[1:] for x in set(df[s].to_numpy())]
  217. print(used_entries)
  218. root = ET.Element("Ebene")
  219. root.set("Name", s)
  220. result[s] = self.get_tree_root(root, s)
  221. # self.json_result["tree"][s] = get_tree_from_accounts(cols, [])
  222. return result
  223. def get_structure_and_tree(self):
  224. df = self.accounts_from_csv(self.config["struct"])
  225. self.json_result["accounts"] = df.to_dict("records")
  226. self.structure_ids = df.melt(
  227. id_vars=["Konto_Nr"],
  228. value_vars=self.config["struct"].keys(),
  229. var_name="Struktur",
  230. value_name="id",
  231. ).groupby(by=["Struktur", "id"])
  232. self.json_result["tree"] = self.tree_from_xml(self.config["struct"], df)
  233. for s, cols in self.config["struct"].items():
  234. self.json_result["flat"][s] = get_flat(self.json_result["tree"][s])
  235. for s, entries in self.json_result["flat"].items():
  236. cols = self.config["struct"][s]
  237. df_temp = pd.DataFrame([x["id"].split(";") for x in entries], columns=cols)
  238. self.json_result["struct_export"][s] = df_temp.to_dict(orient="records")
  239. # {'accounts': {}, 'tree': {}, 'flat': {}, 'struct_export': {}, 'skr51_vars': {}}
  240. return self.json_result
  241. def export_structure_and_tree(self):
  242. json.dump(
  243. self.json_result,
  244. open(f"{self.config['path2']}/{self.config['output']}", "w"),
  245. indent=2,
  246. )
  247. def get_accounts(self, structure, id):
  248. return [x["Konto_Nr"] for x in self.json_result["accounts"] if x[structure] == id]
  249. # return []
  250. # res = self.structure_ids.groups.get((structure, id))
  251. # if res is None:
  252. # return []
  253. # return res.values
  254. def export(self):
  255. for s in self.config["export"].keys():
  256. if len(self.config["export"][s]["files"]) == 0:
  257. continue
  258. struct_info = {e["id"]: e for e in self.json_result["flat"][s]}
  259. for filetype, filename in self.config["export"][s]["files"].items():
  260. with open(self.config["path2"] + "/" + filename, "w", encoding="latin-1", errors="ignore") as fwh:
  261. fwh.write(";".join(self.export_header(filetype)) + "\n")
  262. unique_accounts = []
  263. for a in self.json_result["accounts"]:
  264. if a["Herstellerkonto_Nr"] == "":
  265. continue
  266. account = chevron.render(
  267. self.config["export"]["SKR51"]["format"]["HerstellerkontoFormat"],
  268. a,
  269. )
  270. amount_text = struct_info.get(a[s], {}).get("amount_text", "")
  271. if amount_text == "" or " - " not in amount_text:
  272. amount_text += " - "
  273. account_amount_nr, account_amount_text = amount_text.split(" - ")
  274. a2 = a.copy()
  275. a2["Herstellerkonto_Nr"] = account_amount_nr
  276. a2["Herstellerkonto_Bez"] = account_amount_text
  277. account2 = chevron.render(
  278. self.config["export"]["SKR51"]["format"]["HerstellerkontoFormat"],
  279. a2,
  280. )
  281. if filetype == "ExportUebersetzungStk" and a["Konto_STK"] != "1":
  282. continue
  283. if filetype == "ExportHerstellerKontenrahmen":
  284. if account not in unique_accounts:
  285. unique_accounts.append(account)
  286. account_text = chevron.render(
  287. self.config["export"]["SKR51"]["format"]["HerstellerBezeichnungFormat"],
  288. a,
  289. )
  290. fwh.write(account + ";" + account_text + ";2;" + a["Herstellerkonto_Bez"] + "\n")
  291. if account_amount_nr != "" and account2 not in unique_accounts:
  292. unique_accounts.append(account2)
  293. account_text = chevron.render(
  294. self.config["export"]["SKR51"]["format"]["HerstellerBezeichnungFormat"],
  295. a2,
  296. )
  297. fwh.write(account2 + ";" + account_text + ";2;" + a["Herstellerkonto_Bez"] + "\n")
  298. elif filetype == "ExportUebersetzungStk":
  299. fwh.write(account2 + ";" + account2 + ";" + a["Konto_Nr"] + ";" + "\n")
  300. else:
  301. fwh.write(account + ";" + account + ";" + a["Konto_Nr"] + ";" + "\n")
  302. def get_tree(self, node, parents, structure):
  303. result = []
  304. for child in node:
  305. p = get_parents_list(parents)
  306. parents.append(child.attrib["Name"])
  307. id = ";".join(parents) + ";" * (10 - len(parents))
  308. result.append(
  309. {
  310. "id": id,
  311. "text": child.attrib["Name"],
  312. "children": self.get_tree(child, parents, structure),
  313. "parents": p,
  314. "accounts": self.get_accounts(structure, id),
  315. "level": len(parents),
  316. "form": child.attrib.get("Split", ""),
  317. "amount_text": child.attrib.get("NameStk", ""),
  318. }
  319. )
  320. parents.pop()
  321. return result
  322. def get_tree_root(self, node, structure):
  323. id = ";" * 9
  324. return {
  325. "id": id,
  326. "text": node.attrib["Name"],
  327. "children": self.get_tree(node, [], structure),
  328. "parents": [],
  329. "accounts": [],
  330. "level": 0,
  331. "form": "",
  332. "amount_text": "",
  333. }
  334. def post_structure_and_tree(self):
  335. json_post = json.load(open(f"{self.config['path']}/{self.config['output']}", "r"))
  336. # Kontenrahmen.csv
  337. ebenen = ["Ebene" + str(i) for i in range(1, len(self.config["default"]) * 10 + 1)]
  338. header = ";".join(self.config["columns"] + ebenen)
  339. cols = self.config["columns"] + self.config["default"]
  340. with open(
  341. self.config["path"] + "/Kontenrahmen/Kontenrahmen_out.csv",
  342. "w",
  343. encoding="latin-1",
  344. ) as f:
  345. f.write(header + "\n")
  346. for row in json_post["Kontenrahmen"]:
  347. f.write(";".join([row[e] for e in cols]) + "\n")
  348. # print(header)
  349. # xml und evtl. Struktur.csv
  350. for i, s in enumerate(self.config["default"]):
  351. with open(
  352. f"{self.config['path']}/Strukturen/Kontenrahmen.csv/{s}_out.csv",
  353. "w",
  354. encoding="latin-1",
  355. ) as f:
  356. f.write(";".join(["Ebene" + str(i * 10 + j) for j in range(1, 11)]) + "\n")
  357. rows = structure_from_tree({"id": ";" * 9, "children": json_post[s]})
  358. f.write("\n".join(rows))
  359. # with open(self.config['path'] + "/Strukturen/Kontenrahmen.csv/" + structure + "_2.csv", "w", encoding="latin-1") as f:
  360. root = ET.Element("Ebene")
  361. root.set("Name", s)
  362. xml_from_tree(root, {"id": ";" * 9, "children": json_post[s]})
  363. with open(f"{self.config['path']}/Xml/{s}_out.xml", "w", encoding="utf-8") as f:
  364. f.write(BeautifulSoup(ET.tostring(root), "xml").prettify())
  365. def skr51_translate(self, accounts_combined_files):
  366. df = self.accounts_from_csv(self.config["struct"])
  367. df_translate = {}
  368. for i, (t_from, t_to) in enumerate(self.translate.items()):
  369. last = "LetzteEbene" + str(i + 1)
  370. from_label = [
  371. "Konto_Nr",
  372. "Konto_Bezeichnung",
  373. last,
  374. last + "_Nr",
  375. last + "_Bez",
  376. "Ebene" + str(i * 10 + 1),
  377. "Ebene" + str(i * 10 + 2),
  378. ]
  379. to_label = [
  380. t_to,
  381. t_to + "_Bez_ori",
  382. t_to + "_Ebene",
  383. t_to + "_Nr",
  384. t_to + "_Bez",
  385. "Ebene1",
  386. "Ebene2",
  387. ]
  388. df_translate[t_from] = df[df[last + "_Nr"] != ""][from_label].rename(
  389. columns=dict(zip(from_label, to_label))
  390. )
  391. df_t4 = df_translate["Konto_Nr"].copy()
  392. df_t4 = df_t4[df_t4["SKR51_Nr"].str.match(r"^[01]")]
  393. df_t5 = df_t4.copy()
  394. df_t4["SKR51_Nr"] = df_t4["SKR51_Nr"] + "_A"
  395. df_t4["SKR51"] = df_t4["SKR51"] + "_A"
  396. df_t5["SKR51_Nr"] = df_t5["SKR51_Nr"] + "_P"
  397. df_t5["SKR51"] = df_t5["SKR51"] + "_P"
  398. df_translate["Konto_Nr"] = pd.concat([df_translate["Konto_Nr"], df_t4, df_t5])
  399. # print(df_translate[t_to].head())
  400. df2 = []
  401. for ac_file in accounts_combined_files:
  402. df2.append(
  403. pd.read_csv(
  404. ac_file,
  405. decimal=",",
  406. sep=";",
  407. encoding="latin-1",
  408. converters={i: str for i in range(0, 200)},
  409. )
  410. )
  411. df_source = pd.concat(df2)
  412. df3 = df_source.copy()
  413. df3["Konto_Nr"] = df3["Konto_Nr"] + "_STK"
  414. df4 = df_source.copy()
  415. df4 = df4[df4["Konto_Nr"].str.match(r"^[01]")]
  416. df5 = df4.copy()
  417. df4["Konto_Nr"] = df4["Konto_Nr"] + "_A"
  418. df5["Konto_Nr"] = df5["Konto_Nr"] + "_P"
  419. df_source = pd.concat([df_source, df3, df4, df5])
  420. for t_from, t_to in self.translate.items():
  421. if t_to == "SKR51":
  422. df_source["SKR51"] = df_source["Konto_Nr"]
  423. elif t_from in ["Marke_HBV"]:
  424. df_source["Marke_HBV"] = df_source["Marke"]
  425. elif t_from in ["Standort_HBV"]:
  426. df_source["Standort_HBV"] = df_source["Standort"] + "_" + df_source["Marke"]
  427. df_source["BMC"] = "BMC_" + df_source["Standort_HBV"]
  428. elif t_to == "KTR":
  429. df_source["KTR"] = np.where(
  430. df_source["Kostenträger_Quelle"] == "TZ",
  431. "KTR_TZ_" + df_source["Kostenträger"],
  432. "KTR_00",
  433. )
  434. df_source["KTR"] = np.where(
  435. df_source["Kostenträger_Quelle"].isin(["NW", "SC"]),
  436. "KTR_"
  437. + df_source["Kostenträger_Quelle"]
  438. + "_"
  439. + df_source["Marke"]
  440. + "_"
  441. + df_source["Kostenträger"],
  442. df_source["KTR"],
  443. )
  444. else:
  445. df_source[t_to] = t_to + "_" + df_source[t_from]
  446. df_source = df_source.merge(df_translate[t_from], how="left", on=[t_to], suffixes=(None, "_" + t_to))
  447. df_source[t_to + "_Nr"] = np.where(
  448. df_source[t_to + "_Nr"].isna(),
  449. df_source[t_from],
  450. df_source[t_to + "_Nr"],
  451. )
  452. df_source["Konto_Nr_SKR51"] = (
  453. df_source["MAR_Nr"]
  454. + "-"
  455. + df_source["STA_Nr"]
  456. + "-"
  457. + df_source["SKR51_Nr"]
  458. + "-"
  459. + df_source["KST_Nr"]
  460. + "-"
  461. + df_source["ABS_Nr"]
  462. + "-"
  463. + df_source["KTR_Nr"]
  464. )
  465. df_source["Konto_Nr_Händler"] = (
  466. df_source["Marke"]
  467. + "-"
  468. + df_source["Standort"]
  469. + "-"
  470. + df_source["Konto_Nr"]
  471. + "-"
  472. + df_source["Kostenstelle"]
  473. + "-"
  474. + df_source["Absatzkanal"]
  475. + "-"
  476. + df_source["Kostenträger"]
  477. )
  478. df_source["Konto_Nr_Händler_mit_KST"] = df_source["Konto_Nr"] + "_" + df_source["Kostenstelle"]
  479. # df_source.to_csv(f"{self.config['path2']}/SKR51_Uebersetzung.csv", sep=';', encoding='latin-1', index=False)
  480. df_source["MAR_Nr_MAR"] = np.where(df_source["MAR_Nr_MAR"].isna(), "0000", df_source["MAR_Nr_MAR"])
  481. from_label = [
  482. "MAR_Nr",
  483. "STA_Nr",
  484. "SKR51_Nr",
  485. "KST_Nr",
  486. "ABS_Nr",
  487. "KTR_Nr",
  488. "KTR_Ebene",
  489. "Konto_Nr_Händler",
  490. "Konto_Nr_SKR51",
  491. "MAR_Nr_MAR",
  492. "BMC_Nr",
  493. "Konto_Nr",
  494. "Konto_Nr_Händler_mit_KST",
  495. "SKR51_Bez_ori",
  496. ]
  497. to_label = [
  498. "Marke",
  499. "Standort",
  500. "Konto_Nr",
  501. "Kostenstelle",
  502. "Absatzkanal",
  503. "Kostenträger",
  504. "Kostenträger_Ebene",
  505. "Konto_Nr_Händler",
  506. "Konto_Nr_SKR51",
  507. "Marke_HBV",
  508. "Standort_HBV",
  509. "Konto_Nr_Händler_kurz",
  510. "Konto_Nr_Händler_mit_KST",
  511. "Konto_Bezeichnung_Händler",
  512. ]
  513. df_combined = df_source[from_label].rename(columns=dict(zip(from_label, to_label)))
  514. df_combined.to_csv(
  515. f"{self.config['path2']}/Kontenrahmen_uebersetzt.csv",
  516. sep=";",
  517. encoding="latin-1",
  518. index=False,
  519. )
  520. def skr51_translate2(self, accounts_combined_file):
  521. df = self.accounts_from_csv(self.config["struct"])
  522. df_list = []
  523. for i, s in enumerate(self.config["struct"].keys()):
  524. from_label = [
  525. "Konto_Nr",
  526. "Ebene" + str(i * 10 + 1),
  527. "Ebene" + str(i * 10 + 2),
  528. "Ebene" + str(i * 10 + 3),
  529. ]
  530. to_label = ["Konto_Nr", "key", "value", "value2"]
  531. df_temp = df[from_label].rename(columns=dict(zip(from_label, to_label)))
  532. df_temp["key"] = "{" + s + "/" + df_temp["key"] + "}"
  533. df_list.append(df_temp[df_temp["value"] != ""])
  534. df_translate = pd.concat(df_list)
  535. # df_translate.to_csv(f"{self.config['path2']}/SKR51_Variablen.csv", sep=';', encoding='latin-1', index=False)
  536. df_source = pd.read_csv(
  537. accounts_combined_file,
  538. decimal=",",
  539. sep=";",
  540. encoding="latin-1",
  541. converters={i: str for i in range(0, 200)},
  542. )
  543. df_source = df_source[df_source["Konto_Nr"].str.contains("_STK") == False]
  544. df_source["Konto_Nr_Gesamt"] = df_source["Konto_Nr"]
  545. df_source["Konto_Nr"] = np.where(
  546. df_source["Konto_Nr"].str.contains(r"^[4578]"),
  547. df_source["Konto_Nr"] + "_" + df_source["Kostenstelle"].str.slice(stop=1),
  548. df_source["Konto_Nr"],
  549. )
  550. df_source["Konto_Nr"] = np.where(
  551. df_source["Konto_Nr"].str.contains(r"^5\d+_4"),
  552. df_source["Konto_Nr"] + df_source["Kostenstelle"].str.slice(start=1, stop=2),
  553. df_source["Konto_Nr"],
  554. )
  555. df_source = df_source.merge(df, how="left", on=["Konto_Nr"])
  556. # rows = df_source.shape[0]
  557. df_source["value"] = ""
  558. cols = get_default_cols(0)
  559. for t_from, t_to in self.translate.items():
  560. if t_from in ["Marke_HBV", "Standort_HBV"]:
  561. continue
  562. if t_from == "Konto_Nr":
  563. df_source[t_to] = df_source[t_from]
  564. else:
  565. df_source[t_to] = t_to + "_" + df_source[t_from]
  566. for e in cols:
  567. df_source = df_source.merge(
  568. df_translate,
  569. how="left",
  570. left_on=[t_to, e],
  571. right_on=["Konto_Nr", "key"],
  572. suffixes=(None, "_" + t_to + "_" + e),
  573. )
  574. df_source[e] = np.where(
  575. df_source["value_" + t_to + "_" + e].notna(),
  576. df_source["value_" + t_to + "_" + e],
  577. df_source[e],
  578. )
  579. # if df_source.shape[0] > rows:
  580. # print(t_to + '_' + e + ': ' + str(df_source.shape[0]))
  581. # df_source.to_csv(f"{self.config['path2']}/SKR51_Variablen2.csv", sep=';', encoding='latin-1', index=False)
  582. # df_source[t_to + '_Nr'] = np.where(df_source[t_to + '_Nr'].isna(), df_source[t_from], df_source[t_to + '_Nr'])
  583. for e in cols:
  584. df_source[e] = np.where(
  585. df_source[e].str.startswith("{"),
  586. df_source[e].str.extract(r"\/(.*)}", expand=False) + " falsch",
  587. df_source[e],
  588. ) # df_source[e].str.extract(r'/(.*)}') +
  589. df_source[e] = np.where(df_source[e] == "[KTR]", df_source["Kostenträger_Ebene"], df_source[e])
  590. # df_all[df_all['Ebene1'] == ]
  591. # print(df_source.head())
  592. df_source["Konto_neu"] = (
  593. df_source["Marke"]
  594. + "-"
  595. + df_source["Standort"]
  596. + "-"
  597. + df_source["Konto_Nr"]
  598. + "-"
  599. + df_source["Kostenstelle"]
  600. + "-"
  601. + df_source["Absatzkanal"]
  602. + "-"
  603. + df_source["Kostenträger"]
  604. + " - "
  605. + df_source["Konto_Bezeichnung"]
  606. )
  607. df_source["Ebene1_empty"] = df_source["Ebene1"].isna() # , df_source['Ebene1'].map(lambda x: x == ''))
  608. df_source["Konto_neu"] = np.where(df_source["Ebene1_empty"], "keine Zuordnung", df_source["Konto_neu"])
  609. df_source["Ebene1"] = np.where(df_source["Ebene1_empty"], "keine Zuordnung", df_source["Ebene1"])
  610. df_source["Konto_Gruppe"] = df_source["Konto_Nr"] + " - " + df_source["Konto_Bezeichnung"]
  611. df_source["Konto_Gruppe"] = np.where(df_source["Ebene1_empty"], "keine Zuordnung", df_source["Konto_Gruppe"])
  612. df_source["Konto_Gesamt"] = df_source["Konto_Nr_Gesamt"] + " - " + df_source["Konto_Bezeichnung"]
  613. df_source["Konto_Händler"] = df_source["Konto_Nr_Händler_kurz"] + " - " + df_source["Konto_Bezeichnung_Händler"]
  614. df_source["Konto_mit_KST_Händler"] = (
  615. df_source["Konto_Nr_Händler_mit_KST"] + " - " + df_source["Konto_Bezeichnung_Händler"]
  616. )
  617. kto_amount = df_source["Ebene63"] == "mit STK"
  618. if kto_amount.sum() > 0:
  619. df_amount = df_source[kto_amount].reset_index()
  620. else:
  621. df_amount = df_source[df_source["Ebene1"] == "Umsatzerlöse"].reset_index()
  622. df_amount["Ebene1"] = "verkaufte Stückzahlen"
  623. df_amount["Ebene72"] = "verkaufte Stückzahlen"
  624. df_amount["Konto_neu"] = "STK " + df_amount["Konto_neu"]
  625. df_amount["Konto_Nr_Händler"] = df_amount["Konto_Nr_Händler"] + "_STK"
  626. df_amount["Konto_Gruppe"] = "STK " + df_amount["Konto_Gruppe"]
  627. df_amount["Konto_Gesamt"] = "STK " + df_amount["Konto_Gesamt"]
  628. df_amount["Konto_Händler"] = "STK " + df_amount["Konto_Händler"]
  629. df_amount["Konto_mit_KST_Händler"] = "STK " + df_amount["Konto_mit_KST_Händler"]
  630. df_source = pd.concat([df_source, df_amount])
  631. if "Ebene81" in df_source.columns:
  632. df_source["Ebene91"] = df_source["Ebene81"]
  633. df_source["Ebene92"] = df_source["Ebene82"]
  634. df_source["Ebene93"] = df_source["Ebene83"]
  635. df_source["Ebene94"] = df_source["Ebene84"]
  636. df_source["Ebene95"] = df_source["Ebene85"]
  637. df_source["Ebene96"] = df_source["Ebene86"]
  638. df_source["Ebene97"] = df_source["Ebene87"]
  639. df_source["Ebene98"] = df_source["Ebene88"]
  640. df_source["Ebene99"] = df_source["Ebene89"]
  641. df_source["Ebene100"] = df_source["Ebene90"]
  642. else:
  643. df_source["Ebene91"] = ""
  644. df_source["Ebene92"] = ""
  645. df_source["Ebene93"] = ""
  646. df_source["Ebene94"] = ""
  647. df_source["Ebene95"] = ""
  648. df_source["Ebene96"] = ""
  649. df_source["Ebene97"] = ""
  650. df_source["Ebene98"] = ""
  651. df_source["Ebene99"] = ""
  652. df_source["Ebene100"] = ""
  653. df_source["GuV"] = df_source["Ebene71"] == "GuV"
  654. df_source["Ebene81"] = np.where(df_source["GuV"], df_source["Ebene72"], "Bilanz")
  655. df_source["Ebene82"] = np.where(df_source["GuV"], df_source["Ebene73"], "")
  656. df_source["Ebene83"] = np.where(df_source["GuV"], df_source["Ebene74"], "")
  657. df_source["Ebene84"] = np.where(df_source["GuV"], df_source["Ebene75"], "")
  658. df_source["Ebene85"] = np.where(df_source["GuV"], df_source["Ebene76"], "")
  659. df_source["Ebene86"] = np.where(df_source["GuV"], df_source["Ebene77"], "")
  660. df_source["Ebene87"] = np.where(df_source["GuV"], df_source["Ebene78"], "")
  661. df_source["Ebene88"] = np.where(df_source["GuV"], df_source["Ebene79"], "")
  662. df_source["Ebene89"] = np.where(df_source["GuV"], df_source["Ebene80"], "")
  663. df_source["Ebene90"] = ""
  664. df_source["Ebene71"] = np.where(df_source["GuV"], "GuV", df_source["Ebene72"])
  665. df_source["Ebene72"] = np.where(df_source["GuV"], "", df_source["Ebene73"])
  666. df_source["Ebene73"] = np.where(df_source["GuV"], "", df_source["Ebene74"])
  667. df_source["Ebene74"] = np.where(df_source["GuV"], "", df_source["Ebene75"])
  668. df_source["Ebene75"] = np.where(df_source["GuV"], "", df_source["Ebene76"])
  669. df_source["Ebene76"] = np.where(df_source["GuV"], "", df_source["Ebene77"])
  670. df_source["Ebene77"] = np.where(df_source["GuV"], "", df_source["Ebene78"])
  671. df_source["Ebene78"] = np.where(df_source["GuV"], "", df_source["Ebene79"])
  672. df_source["Ebene79"] = np.where(df_source["GuV"], "", df_source["Ebene80"])
  673. df_source["Ebene80"] = ""
  674. df_source["Susa"] = df_source["Konto_Gruppe"].str.slice(stop=1)
  675. df_source["Konto_KST"] = ""
  676. df_source["GuV_Bilanz"] = df_source["Konto_Art"]
  677. from_label = ["Konto_neu", "Konto_Nr_Händler", "Konto_Nr_Händler_kurz"]
  678. to_label = ["Konto", "Acct_Nr", "Konto_Nr_Händler"]
  679. df_source = df_source.rename(columns=dict(zip(from_label, to_label)))
  680. df_source = df_source[
  681. [
  682. "Konto",
  683. "Acct_Nr",
  684. "Konto_Bezeichnung",
  685. "GuV_Bilanz",
  686. "Konto_KST",
  687. "Konto_STK",
  688. "Konto_1",
  689. "Konto_2",
  690. "Konto_3",
  691. "Konto_4",
  692. "Konto_5",
  693. ]
  694. + get_default_cols(0)
  695. + get_default_cols(7)
  696. + get_default_cols(8)
  697. + get_default_cols(9)
  698. + [
  699. "Konto_Gruppe",
  700. "Konto_Nr_Gesamt",
  701. "Konto_Gesamt",
  702. "Susa",
  703. "Konto_Nr_Händler",
  704. "Konto_Händler",
  705. "Konto_mit_KST_Händler",
  706. ]
  707. ]
  708. df_source.to_csv(
  709. f"{self.config['path2']}/SKR51_Uebersetzung.csv",
  710. sep=";",
  711. encoding="latin-1",
  712. index=False,
  713. )
  714. is_quantity = df_source["Konto"].str.startswith("STK")
  715. df_source["Konto"] = np.where(
  716. is_quantity,
  717. df_source["Konto"].str.slice_replace(7, 9, "00"),
  718. df_source["Konto"].str.slice_replace(3, 5, "00"),
  719. )
  720. df_source["Acct_Nr"] = df_source["Acct_Nr"].str.slice_replace(3, 5, "00")
  721. df_department = df_source.drop_duplicates()
  722. df_department.to_csv(
  723. f"{self.config['path2']}/SKR51_Uebersetzung_ohne_Standort.csv",
  724. sep=";",
  725. encoding="latin-1",
  726. index=False,
  727. )
  728. def skr51_vars(self):
  729. self.get_structure_and_tree()
  730. cols = get_default_cols(0)
  731. df_temp = pd.read_csv(
  732. f"{self.config['path']}/Export/Kostentraeger.csv",
  733. decimal=",",
  734. sep=";",
  735. encoding="latin-1",
  736. converters={i: str for i in range(0, 200)},
  737. )
  738. df_temp["value"] = df_temp["Ebene33"]
  739. df_temp["key"] = "[KTR]"
  740. df_temp = df_temp[df_temp["value"].str.contains(" - ")]
  741. df_list = [df_temp[["key", "value"]]]
  742. for s, entries in self.json_result["flat"].items():
  743. df = pd.DataFrame([x["id"].split(";") for x in entries], columns=cols)
  744. df["key"] = df[cols[0]].apply(lambda x: "{" + s + "/" + x + "}")
  745. df["value"] = df[cols[1]]
  746. df_list.append(df[["key", "value"]])
  747. df = pd.concat(df_list)
  748. df_vars = df[df["value"] != ""]
  749. # df_vars.to_csv(f"{self.config['path2']}/SKR51_Variablen2.csv", sep=';', encoding='latin-1', index=False)
  750. df_main = pd.DataFrame(
  751. [x["id"].split(";") for x in self.json_result["flat"]["SKR51"]],
  752. columns=cols,
  753. )
  754. df_main["value"] = ""
  755. for c in cols:
  756. df_main = df_main.merge(df_vars, how="left", left_on=c, right_on="key", suffixes=(None, "_" + c))
  757. df_main[c] = np.where(df_main["value_" + c].isna(), df_main[c], df_main["value_" + c])
  758. df_amount = df_main[df_main["Ebene1"] == "Umsatzerlöse"].reset_index()
  759. df_amount["Ebene1"] = "verkaufte Stückzahlen"
  760. df_main = pd.concat([df_main, df_amount])
  761. # from_label = cols
  762. to_label = cols # get_default_cols(9)
  763. # df_main = df_main.rename(columns=dict(zip(from_label, to_label)))
  764. df_main[to_label].to_csv(
  765. f"{self.config['path2']}/SKR51_Struktur.csv",
  766. sep=";",
  767. encoding="latin-1",
  768. index_label="Sortierung",
  769. )
  770. def reisacher():
  771. base_dir = "X:/Robert/Planung Reisacher/GCStruct_neue_Struktur_Planung"
  772. if not Path(base_dir).exists():
  773. base_dir = "/media/fileserver1/austausch/Robert/Planung Reisacher/GCStruct_neue_Struktur_Planung"
  774. struct = GCStruct(base_dir)
  775. struct.get_structure_and_tree()
  776. struct.export_structure_and_tree()
  777. # json.dump(res['flat'], open(f"{self.config['path2']}/{self.config['output']}", 'w'), indent=2)
  778. if __name__ == "__main__":
  779. # struct = GCStruct('c:/projekte/gcstruct_dresen')
  780. # struct = GCStruct('c:/projekte/python/gcstruct')
  781. # struct = GCStruct('c:/projekte/python/gcstruct_reisacher_planung')
  782. reisacher()
  783. # dresen()