gcstruct.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. from bs4 import BeautifulSoup
  8. from functools import reduce
  9. reisacher = False
  10. reisacher_remote = False
  11. dresen = True
  12. config = {
  13. 'path': "c:/projekte/python/gcstruct",
  14. 'path2': "c:/projekte/python/gcstruct",
  15. 'output': "gcstruct.json",
  16. 'default': ["SKR51", "Herkunft_KST", "Absatzkanal", "Kostentraeger", "Marke", "Standort", "Manuelle_Konten"],
  17. 'special': {
  18. 'Planner': ["Kostenstelle", "Ebene1", "Ebene2"],
  19. 'Test': ["Ebene1", "Ebene2"]
  20. }
  21. }
  22. if reisacher:
  23. config = {
  24. 'path': "c:/projekte/python/gcstruct_reisacher_planung",
  25. 'path2': "c:/projekte/python/gcstruct_reisacher_planung",
  26. 'output': "gcstruct_reisacher.json",
  27. 'default': ["Struktur_FB", "Struktur_TEK", "Struktur_GuV", "Struktur_Bilanz", "Struktur_HBV", "Bruttoertrag"],
  28. 'special': {
  29. 'Planner': ["Kostenstelle", "Ebene1", "Ebene2"],
  30. 'Test': ["Ebene1", "Ebene2"]
  31. }
  32. }
  33. if reisacher_remote:
  34. config = {
  35. 'path': "X:/Robert/Planung Reisacher/GCStruct_neue_Struktur_Planung",
  36. 'path2': "C:/Projekte/Angular/gc-form/src/assets/data",
  37. 'output': "gcstruct_reisacher.json",
  38. 'default': ["Struktur_FB", "Struktur_TEK", "Struktur_GuV", "Struktur_Bilanz", "Struktur_HBV", "Bruttoertrag"],
  39. 'special': {
  40. 'Planner': ["Kostenstelle", "Ebene1", "Ebene2"],
  41. 'Test': ["Ebene1", "Ebene2"]
  42. }
  43. }
  44. if dresen:
  45. config = {
  46. 'path': "c:/projekte/gcstruct_dresen",
  47. 'path2': "c:/projekte/gcstruct_dresen",
  48. 'output': "gcstruct.json",
  49. 'default': ["Struktur_FB", "Struktur_TEK", "Struktur_GuV", "Struktur_3"],
  50. 'special': {}
  51. }
  52. columns = ["Konto_Nr", "Konto_Bezeichnung", "Konto_Art", "Kostenstelle", "STK", "Konto_1", "Konto_2", "Konto_3", "Konto_4", "Konto_5"]
  53. json_result = {"accounts": {}, "tree": {}, "flat": {}}
  54. def get_tree_root(node, structure):
  55. id = ";" * 9
  56. return {
  57. "id": id,
  58. "text": node.attrib['Name'],
  59. "children": get_tree(node, [], structure),
  60. "parents": [],
  61. "accounts": [],
  62. "level": 0,
  63. "form": ''
  64. }
  65. def get_tree(node, parents, structure):
  66. result = []
  67. for child in node:
  68. p = get_parents_list(parents)
  69. parents.append(child.attrib['Name'])
  70. id = ";".join(parents) + ";" * (10 - len(parents))
  71. result.append({
  72. "id": id,
  73. "text": child.attrib['Name'],
  74. "children": get_tree(child, parents, structure),
  75. "parents": p,
  76. "accounts": get_accounts(structure, id),
  77. "level": len(parents),
  78. "form": child.attrib.get('Split', '')
  79. })
  80. parents.pop()
  81. return result
  82. def get_flat(node):
  83. result = [{
  84. "id": node['id'],
  85. "text": node['text'],
  86. "children": [x['id'] for x in node['children']],
  87. "children2": [],
  88. "parents": node['parents'],
  89. "accounts": node['accounts'],
  90. "costcenter": "",
  91. "level": node['level'],
  92. "drilldown": node['level'] < 2, # (node['level'] != 2 and len(node['accounts']) == 0),
  93. "form": node['form'],
  94. "accountlevel": False,
  95. "absolute": True,
  96. "seasonal": True,
  97. "status": "0",
  98. "values": [],
  99. "values2": {}
  100. }]
  101. for child in node['children']:
  102. result += get_flat(child)
  103. return result
  104. def get_accounts(structure, id):
  105. return [x['Konto_Nr'] for x in json_result['accounts'] if x[structure] == id]
  106. def get_parents_list(p_list):
  107. id = ";".join(p_list) + ";" * (10 - len(p_list))
  108. if len(p_list) > 0:
  109. return [id] + get_parents_list(p_list[:-1])
  110. return [";" * 9]
  111. def structure_from_tree(node):
  112. result = []
  113. result.append(node['id'])
  114. for child in node['children']:
  115. result.extend(structure_from_tree(child))
  116. return result
  117. def xml_from_tree(xml_node, tree_node):
  118. for child in tree_node['children']:
  119. element = ET.SubElement(xml_node, "Ebene")
  120. element.set("Name", child['text'])
  121. xml_from_tree(element, child)
  122. def split_it(text, index):
  123. try:
  124. return re.findall(r"([^;]+) - ([^;]*);;", text)[0][index]
  125. except Exception:
  126. return ""
  127. def get_default_cols(i):
  128. return ["Ebene" + str(i) for i in range(i * 10 + 1, (i + 1) * 10 + 1)]
  129. def get_structure_and_tree(struct):
  130. with open(f"{config['path']}/Kontenrahmen/Kontenrahmen.csv", 'r', encoding='ansi') as f:
  131. csv_reader = csv.reader(f, delimiter=';')
  132. imported_csv = [row[:50] for row in csv_reader]
  133. # df = pd.read_csv(f"{config['path']}/Kontenrahmen/Kontenrahmen.csv", sep=";", encoding="ansi", quoting=3, converters={i: str for i in range(200)}) # , index_col="Konto_Nr")
  134. df = pd.DataFrame.from_records(np.array(imported_csv[1:], dtype='object'), columns=imported_csv[0]).fillna(value='')
  135. print(df.head())
  136. for i, (s, cols) in enumerate(struct.items()):
  137. df[s] = reduce(lambda x, y: x + ";" + df[y], cols, "")
  138. df[s] = df[s].apply(lambda x: x[1:])
  139. df['LetzteEbene' + str(i + 1) + '_Nr'] = df[s].apply(lambda x: split_it(x, 0))
  140. df['LetzteEbene' + str(i + 1) + '_Bez'] = df[s].apply(lambda x: split_it(x, 1))
  141. len_items = len(struct)
  142. df = df[columns + [*struct] + ['LetzteEbene' + str(i + 1) + '_Nr' for i in range(len_items)] + ['LetzteEbene' + str(i + 1) + '_Bez' for i in range(len_items)]]
  143. json_result["accounts"] = df.to_dict("records")
  144. # df2 = pd.read_csv("config['path'] + "/Strukturen/Kontenrahmen.csv/SKR51.csv", sep=";", encoding="ansi", decimal=",", converters={i: str for i in range(0, 200)})
  145. # print(df2.head())
  146. for i, (s, cols) in enumerate(struct.items()):
  147. try:
  148. tree = ET.parse(f"{config['path']}/Xml/{s}.xml")
  149. json_result["tree"][s] = get_tree_root(tree.getroot(), s)
  150. except FileNotFoundError:
  151. print("XML-Datei fehlt")
  152. used_entries = [x.split(";")[1:] for x in set(df[s].to_numpy())]
  153. print(used_entries)
  154. root = ET.Element("Ebene")
  155. root.set("Name", s)
  156. json_result["tree"][s] = get_tree_root(root, s)
  157. # json_result["tree"][s] = get_tree_from_accounts(cols, [])
  158. json_result["flat"][s] = get_flat(json_result["tree"][s])
  159. json.dump(json_result, open(f"{config['path2']}/{config['output']}", "w"), indent=2)
  160. def post_structure_and_tree():
  161. json_post = json.load(open(f"{config['path']}/{config['output']}", "r"))
  162. # Kontenrahmen.csv
  163. ebenen = ["Ebene" + str(i) for i in range(1, len(config['default']) * 10 + 1)]
  164. header = ";".join(columns + ebenen)
  165. cols = columns + config['default']
  166. with open(config['path'] + "/Kontenrahmen/Kontenrahmen_out.csv", "w", encoding="ansi") as f:
  167. f.write(header + "\n")
  168. for row in json_post['Kontenrahmen']:
  169. f.write(";".join([row[e] for e in cols]) + "\n")
  170. # print(header)
  171. # xml und evtl. Struktur.csv
  172. for i, s in enumerate(config['default']):
  173. with open(config['path'] + "/Strukturen/Kontenrahmen.csv/" + s + "_out.csv", "w", encoding="ansi") as f:
  174. f.write(";".join(["Ebene" + str(i * 10 + j) for j in range(1, 11)]) + "\n")
  175. rows = structure_from_tree({"id": ";" * 9, "children": json_post[s]})
  176. f.write("\n".join(rows))
  177. # with open(config['path'] + "/Strukturen/Kontenrahmen.csv/" + structure + "_2.csv", "w", encoding="ansi") as f:
  178. root = ET.Element("Ebene")
  179. root.set("Name", s)
  180. xml_from_tree(root, {"id": ";" * 9, "children": json_post[s]})
  181. with open(config['path'] + "/Xml/" + s + "_out.xml", "w", encoding="utf-8") as f:
  182. f.write(BeautifulSoup(ET.tostring(root), "xml").prettify())
  183. if __name__ == '__main__':
  184. struct = dict([(x, get_default_cols(i)) for (i, x) in enumerate(config['default'])])
  185. struct.update(config['special'])
  186. print(struct)
  187. get_structure_and_tree(struct)
  188. # post_structure_and_tree()