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
- self.max_depth = None
- self.all_accs = []
- self.all_real_accs = []
- # code е нешо от типа "123-456-789"
- def add_code(self, code): # TODO IZPOLZWAM 1 Прави STRUCT !!!
- if code not in self.all_real_accs:
- self.all_real_accs.append(code)
- 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-вата група до една цифра
- 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)
- # В тази точка ancestors съдържа всички прародители до 1 цифра
- # Сега обхождаме ancestors, за да добавим връзките дете-към-родител в self.struct
- ancestors_len = len(ancestors)
- if self.max_depth is None:
- self.max_depth = ancestors_len
- elif ancestors_len > self.max_depth:
- self.max_depth = ancestors_len
- 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:
- # Няма нужда са се минава нататък през родителите му, понеже те вече са вписани
- break
- else:
- if len(child) > 0 and child not in self.all_accs: # TODO -> НЕ СЪДЪРЖА ВСИЧКИ СМЕТКИ !!!
- self.all_accs.append(parent)
- if len(parent) > 0 and parent not in self.all_accs:
- self.all_accs.append(parent)
- self.struct[child] = parent
- self.top_digits[child] = child_top_group_digits_len
- self.groups[child] = child_groups
- 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_max_depth(self):
- return self.max_depth
- # Връща дълбочината на дадена сметка в дървото
- 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()
- # Връща 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=None):
- if max_depth is None:
- max_depth = self.max_depth
- if max_depth == 0:
- return []
- max_depth -= 1
- processed = []
- children = self.get_children(code)
- # print(f"АААААА {code} има за деца {children}")
- depth = 0
- while depth < max_depth:
- # print(f"get_all_children() depth {depth}")
- children1 = []
- children_on_this_depth = 0
- for child in children:
- children1.append(child)
- if child in processed: # вече сме добавили преките деца на това дете
- continue # затова пропускаме
- children2 = self.get_children(child)
- # print(f"Ниво {depth}: {child} има за деца {children2}")
- children_on_this_depth += len(children2)
- processed.append(child)
- for child2 in children2:
- children1.append(child2)
- if children_on_this_depth == 0:
- break
- children = children1
- depth += 1
- return children
- def get_parent(self, acc_code):
- if acc_code is None or acc_code == '':
- return None
- if acc_code in self.struct: # Писано от мен
- return self.struct[acc_code]
- def get_all_parents(self, acc_code):
- parents = []
- # Почваме от даения код, вземаме родителя, после неговия родител и т.н. докато опрем в корена
- browse_code = acc_code
- while True:
- parent = self.get_parent(browse_code)
- if parent == "" or parent == None or len(parent) < self.top_group_min_digits_count: # Опряли сме в корена на дървото
- break # няма повече родители
- parents.append(parent) # Добавяме родителя в списъка с предци
- browse_code = parent
- return parents
- # Листа на дървото = тези които нямат деца = най-дълбоки деца
- def get_leaves(self):
- # всички които имат родители са KEY в struct
- # всики които имат деца са VALUE в struct
- # значи листа са тези които ги няма в стойностите, но ги има в ключовете
- values = self.struct.values() # list1
- keys = self.struct.keys() # list2
- #leaves = има в keys, но ги няма в values
- leaves = set(keys).difference(values)
- return leaves
- def get_leaves_bycode(self, list_accs: list):
- list_leaves_bycode = []
- # TODO -> Подавам код и проверяван дали е родител
- print('get_leaves_bycode list_accs: ', list_accs)
- for leaf in list_accs:
- is_parent = self.is_parent(leaf)
- if not is_parent:
- list_leaves_bycode.append(leaf)
- return list_leaves_bycode
- def get_all_deepest_parents(self):
- leaves = self.get_leaves()
- deepest_parents = []
- for leaf in leaves:
- parent = self.get_parent(leaf)
- if parent in deepest_parents: # Добавено от мен.
- continue
- deepest_parents.append(parent)
- return deepest_parents
- def get_deepest_parents(self, acc_code):
- all_children = self.get_all_children(acc_code) # Всичко под acc
- leaves = self.get_leaves() # Всички листа на цялото дърво
- leaves_under_acc = list(set(all_children).intersection(leaves))
- # Остава минем през всяко листо в leaves_under_acc и да му вземем родителя
- deepest_parents = [] # Тук ще трупаме родителите на листата
- for leaf in leaves_under_acc:
- parent = self.get_parent(leaf) # родител на листото
- if parent not in deepest_parents: # избягваме повторения
- deepest_parents.append(parent) # добавяме родителя на листото
- return deepest_parents
- def get_top_parents(self):
- zero = self.get_children('') # top1 ще съдържа децата на корена -- т.е. на практика едноцифрените
- top_parents = [] # Тука ще изсипем децата на децата на корена -- т.е. на практика двуцифрените
- for child in zero: # за всяко дете на корена
- # взимаме му децата и ги изсипваме в tops2
- top_parents += self.get_children(child)
- return top_parents
- def get_top_parents_of_type(self, mapp_accs, acc_type):
- leaves = self.get_leaves()
- found = []
- for leaf in leaves:
- ancestors = self.get_all_parents(leaf) # връща ги от най-дълбок към най-висок
- oldest_of_type = None
- for ancestor in ancestors:
- if ancestor in mapp_accs:
- ancestor_types = mapp_accs[ancestor]
- if len(ancestor_types) == 1 and ancestor_types[0] == acc_type:
- oldest_of_type = ancestor
- if oldest_of_type is not None and oldest_of_type not in found:
- found.append(oldest_of_type)
- return found
- def is_child(self, acc_code):
- test_for_parent = self.get_parent(acc_code)
- if test_for_parent is None:
- return False
- return True
- def is_parent(self, acc_code):
- print('is_parent(self, acc_code)', acc_code)
- test_for_children = self.get_children(acc_code)
- if len(test_for_children) > 0:
- return True
- return False
- def compare_lists(self, list_1, list_2):
- l1 = list_1.sort()
- l2 = list_2.sort()
- if l1==l2:
- return True
- return False
- def asymmetric_compare_lists(self, list_1, list_2):
- diff_1 = list(set(list_1) - set(list_2))
- if len(diff_1) > 0:
- return diff_1
- return None
- def get_all_acc(self):
- return self.all_accs # TODO -> НЕ РАБОТИ !
- def get_unmapped_acc(self, mapp_accs):
- list_unmapped_acc = []
- for code in self.all_accs:
- if code not in mapp_accs:
- if code not in list_unmapped_acc:
- list_unmapped_acc.append(code)
- return list_unmapped_acc
- def get_unadded_acc(self, added_accs, all_accs):
- list_unadded_acc = []
- for code in all_accs:
- if code not in added_accs:
- if code not in list_unadded_acc:
- list_unadded_acc.append(code)
- return list_unadded_acc
- def is_real_acc(self, acc_code):
- if acc_code in self.all_real_accs:
- return True
- return False
- def get_real_accounts(self, acc_codes):
- return [a for a in acc_codes if a in self.all_real_accs]
- if __name__ == '__main__':
- acc_tree = AccountTree()
- test = acc_tree.is_parent("10")
- print(test)
- acc_tree.add_code("200-1")
- acc_tree.print_struct()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement