gcstruct.py 7.5 KB

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