gcstruct.py 32 KB

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