Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import re
- class AccountTree():
- def __init__(self):
- self.struct = {} # На Всяко дете, кой е прекия родител
- self.children = None
- self.top_digits = {} # На коя сметка колко цифри има в първата група
- self.groups = {} # На коя сметка колко групи има
- self.top_group_min_digits_count = None # Беше None
- self.top_group_max_digits_count = None # Беше None
- self.max_groups_count = None # Беше None
- # code е нешо от типа "123-456-789"
- def add_code(self, code): # TODO IZPOLZWAM 1 Прави STRUCT !!!
- self.children = None # Нулираме кеша на родители-деца
- # "123-456-789" дава ["123", "456", "789"]
- groups_digits = re.findall('[0-9]+', code)
- # "123-456-789" дава ["-", "-"]
- groups_seps = re.findall('[^0-9]+', code)
- groups_digits_len = len(groups_digits)
- # Следим максималния брой аналитични сметки
- if self.max_groups_count is None:
- self.max_groups_count = groups_digits_len
- elif groups_digits_len > self.max_groups_count: # МОже би трябва да е IF ???
- self.max_groups_count = groups_digits_len
- # От този код трябва да построим този клон:
- #1
- #12 -------TODO----- ВАЖНО -> ТОП родителя е този, който е подаден от Excel с най-малко цифри !!!
- #123 -------TODO---- -> Няма смисъл да раздробяваме на по-малки кодове сметките в Оборотната ведомост !
- #123-456
- #123-456-789
- # Напр 123 # groups_digits е списък с групите
- top_group_digits = groups_digits[0] # Първата група
- #print("top_group_digits", top_group_digits)
- top_group_digits_len = len(top_group_digits) # Брой цифри в 1-вата група
- # В ancestors ще трупаме [сметка, родител, пра-родител и т.н.] но по цели групи от цифри
- ancestors = []
- ancestors_top_group_digits = []
- ancestors_groups = []
- # За ["123", "456", "789"] len1 ще мине през 3, 2, 1
- for len1 in range(groups_digits_len, 0, -1):
- # len1=3 дава ["123", "456", "789"]
- # len1=2 дава ["123", "456"]
- # len1=1 дава ["123"]
- code1 = ""
- # len1=3, то idx ше мине през 0, 1, 2
- # len1=2, то idx ше мине през 0, 1
- # len1=1, то idx ше мине през 0
- for idx in range(len1):
- if code1 != "":
- code1 += groups_seps[idx - 1]
- pass
- code1 += groups_digits[idx]
- ancestors.append(code1)
- ancestors_top_group_digits.append(top_group_digits_len)
- ancestors_groups.append(len1)
- # Следим коя е най-дългата първа група
- if self.top_group_max_digits_count is None:
- self.top_group_max_digits_count = top_group_digits_len
- elif top_group_digits_len > self.top_group_max_digits_count:
- self.top_group_max_digits_count = top_group_digits_len
- # Следим коя е най-късата първа група
- if self.top_group_min_digits_count is None:
- self.top_group_min_digits_count = top_group_digits_len
- elif top_group_digits_len < self.top_group_min_digits_count:
- self.top_group_min_digits_count = top_group_digits_len
- # В следния цикъл добавяме в ancestors и родителите на 1-вата група до една цифра
- #print("top_group_digits_len", top_group_digits_len)
- for len1 in range(top_group_digits_len-1, 0, -1):
- #print("len1", len1)
- code1 = top_group_digits[0: len1]
- ancestors.append(code1)
- ancestors_top_group_digits.append(len1)
- ancestors_groups.append(1)
- # print("След анализ на първата група: ancestors", ancestors)
- # В тази точка ancestors съдържа всички прародители до 1 цифра
- # Сега обхождаме ancestors, за да добавим връзките дете-към-родител в self.struct
- ancestors_len = len(ancestors)
- for idx in range(ancestors_len):
- child = ancestors[idx]
- child_top_group_digits_len = ancestors_top_group_digits[idx]
- child_groups = ancestors_groups[idx]
- parent_idx = idx + 1
- if parent_idx < ancestors_len: # Бащата присъства в списъка
- parent = ancestors[parent_idx] # Вземаме бащата от списъка
- else: # Бащата не е в списъка
- parent = "" # Затова бащата е коренът
- if child in self.struct:
- # Няма нужда са се минава нататък през родителите му, понеже те вече са вписани
- #print(f"Вече е вписано, че {child} има родител {parent}, пропускаме останалото родословие")
- break
- else:
- self.struct[child] = parent
- self.top_digits[child] = child_top_group_digits_len
- self.groups[child] = child_groups
- # print('ancestors', ancestors)
- def get_max_groups_count(self):
- return self.max_groups_count
- def get_top_group_max_digits_count(self):
- return self.top_group_max_digits_count
- def get_top_group_digits(self, code):
- return self.top_digits[code]
- def get_groups(self, code):
- return self.groups[code]
- # Връща дълбочината на дадена сметка в дървото
- def get_depth(self, code): # TODO Izpolzwam 2
- if code not in self.struct: # Няма таква сметка
- return None
- # Такава сметка има
- depth = 0
- next_code = code
- while next_code in self.struct:
- depth += 1
- next_code = self.struct[next_code]
- return depth
- def print_struct(self): # TODO up_struct = children ????
- print('struct', self.struct) # struct {'10-100-20-25': '10-100-20', '10-100-20': '10-100', '10-100': '10', '10': '1', '1': ''}
- up_struct = {}
- for key in self.struct:
- if self.struct[key] == self.struct[key]:
- key_up_struct = self.struct[key]
- if key_up_struct in up_struct:
- up_struct[key_up_struct] += [key]
- elif key_up_struct not in up_struct:
- up_struct[key_up_struct] = [key]
- # Сортиране на децата -> List in value
- for parent_acc in up_struct:
- up_struct[parent_acc].sort()
- print('up_struct', up_struct)
- # Връща list с само преките деца на даден code
- def get_children(self, code):
- if self.children is None:
- self.children = {}
- # Ще бъде речник с изброени преки деца на всяка сметка {"150": ["150-1", "150-2", ...], ...}
- for child in self.struct:
- parent = self.struct[child]
- if parent not in self.children:
- self.children[parent] = []
- self.children[parent].append(child)
- if code in self.children: # Ако кодът има деца...
- return self.children[code] # връшаме ги Връща лист !
- # Щом сме стигнали дотук, кодът няма деца
- return [] # Затова връщаме празен списък
- # Връща list с всички деца, внуци и т.н. на даден код
- def get_all_children(self, code, max_depth = 999):
- if max_depth == 0:
- return []
- max_depth -= 1
- processed = []
- children = self.get_children(code)
- #print(f"АААААА {code} има за деца {children}")
- depth = 0
- while depth < max_depth:
- children1 = []
- for child in children:
- children1.append(child)
- if child in processed: # вече сме добавили преките деца на това дете
- continue # затова пропускаме
- children2 = self.get_children(child)
- #print(f"Ниво {depth}: {child} има за деца {children2}")
- processed.append(child)
- for child2 in children2:
- children1.append(child2)
- #print(f"Заместваме {children} с {children1}")
- children = children1
- depth += 1
- return children
- def get_parent(self, acc_code):
- # print(f"acc_code {acc_code}")
- # print('self.struct[acc_code]: ', self.struct[acc_code])
- if acc_code is None:
- return None
- print(self.struct)
- # if acc_code in self.struct[acc_code]: # Писано от Владо
- if acc_code in self.struct: # Писано от мен
- return self.struct[acc_code]
- def get_ancestors(self, acc_code):
- ancestors = []
- # Почваме от даения код, вземаме родителя, после неговия родител и т.н.
- # докато опрем в корена
- browse_code = acc_code
- while True:
- parent = self.get_parent(browse_code)
- if parent == "" or parent == None: # Опряли сме в корена на дървото
- break # няма повече родители
- ancestors.push(parent) # Добавяме родителя в списъка с предци
- return ancestors
- # В TrialBalanceFilter на много места се искаме да знаем дали code1 е дете на code2.
- # Там правим сложни аналзи на групи цифри -- те трябва да се махнат.
- # ТАМ има self.acc_tree, което е обект от клас AccountTree
- # AccountTree tрябва да се сдобие с методи като is_child() по-долу,
- # kойто да отговаря на тоя въпрос като използва своя self.struct
- def is_child(self, child, parent):
- # Трябва да връша true или false
- pass
- def is_parent(self, child, parent):
- # Трябва да връша true или false
- pass
- if __name__ == '__main__':
- acc_tree = AccountTree()
- acc_tree.add_code("100")
- acc_tree.print_struct()
- acc_tree.get_parent('100')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement