Advertisement
mirovlad

account_tree get_ancestors

Nov 11th, 2022
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import re
  2. class AccountTree():
  3.     def __init__(self):
  4.         self.struct = {}  # На Всяко дете, кой е прекия родител
  5.         self.children = None
  6.         self.top_digits = {}  # На коя сметка колко цифри има в първата група
  7.         self.groups = {}  # На коя сметка колко групи има
  8.         self.top_group_min_digits_count = None     # Беше None
  9.         self.top_group_max_digits_count = None     # Беше None
  10.         self.max_groups_count = None               # Беше None
  11.  
  12.     # code е нешо от типа "123-456-789"
  13.     def add_code(self, code):   # TODO IZPOLZWAM 1 Прави STRUCT !!!
  14.         self.children = None  # Нулираме кеша на родители-деца
  15.         # "123-456-789" дава ["123", "456", "789"]
  16.         groups_digits = re.findall('[0-9]+', code)
  17.         # "123-456-789" дава ["-", "-"]
  18.         groups_seps = re.findall('[^0-9]+', code)
  19.         groups_digits_len = len(groups_digits)
  20.  
  21.         # Следим максималния брой аналитични сметки
  22.         if self.max_groups_count is None:
  23.             self.max_groups_count = groups_digits_len
  24.         elif groups_digits_len > self.max_groups_count: # МОже би трябва да е IF ???
  25.             self.max_groups_count = groups_digits_len
  26.  
  27.             # От този код трябва да построим този клон:
  28.         #1
  29.         #12     -------TODO----- ВАЖНО -> ТОП родителя е този, който е подаден от Excel с най-малко цифри !!!
  30.         #123    -------TODO---- -> Няма смисъл да раздробяваме на по-малки кодове сметките в Оборотната ведомост !
  31.         #123-456
  32.         #123-456-789
  33.  
  34.         # Напр 123  # groups_digits е списък с групите
  35.         top_group_digits = groups_digits[0]  # Първата група
  36.         #print("top_group_digits", top_group_digits)
  37.         top_group_digits_len = len(top_group_digits)  # Брой цифри в 1-вата група
  38.  
  39.         # В ancestors ще трупаме [сметка, родител, пра-родител и т.н.] но по цели групи от цифри
  40.         ancestors = []
  41.         ancestors_top_group_digits = []
  42.         ancestors_groups = []
  43.         # За ["123", "456", "789"] len1 ще мине през 3, 2, 1
  44.         for len1 in range(groups_digits_len, 0, -1):
  45.             # len1=3 дава ["123", "456", "789"]
  46.             # len1=2 дава ["123", "456"]
  47.             # len1=1 дава ["123"]
  48.             code1 = ""
  49.             # len1=3, то idx ше мине през 0, 1, 2
  50.             # len1=2, то idx ше мине през 0, 1
  51.             # len1=1, то idx ше мине през 0
  52.             for idx in range(len1):
  53.                 if code1 != "":
  54.                     code1 += groups_seps[idx - 1]
  55.                     pass
  56.                 code1 += groups_digits[idx]
  57.             ancestors.append(code1)
  58.             ancestors_top_group_digits.append(top_group_digits_len)
  59.             ancestors_groups.append(len1)
  60.  
  61.         # Следим коя е най-дългата първа група
  62.         if self.top_group_max_digits_count is None:
  63.             self.top_group_max_digits_count = top_group_digits_len
  64.         elif top_group_digits_len > self.top_group_max_digits_count:
  65.             self.top_group_max_digits_count = top_group_digits_len
  66.         # Следим коя е най-късата първа група
  67.         if self.top_group_min_digits_count is None:
  68.             self.top_group_min_digits_count = top_group_digits_len
  69.         elif top_group_digits_len < self.top_group_min_digits_count:
  70.             self.top_group_min_digits_count = top_group_digits_len
  71.  
  72.         # В следния цикъл добавяме в ancestors и родителите на 1-вата група до една цифра
  73.         #print("top_group_digits_len", top_group_digits_len)
  74.         for len1 in range(top_group_digits_len-1, 0, -1):
  75.             #print("len1", len1)
  76.             code1 = top_group_digits[0: len1]
  77.             ancestors.append(code1)
  78.             ancestors_top_group_digits.append(len1)
  79.             ancestors_groups.append(1)
  80.         # print("След анализ на първата група: ancestors", ancestors)
  81.  
  82.         # В тази точка ancestors съдържа всички прародители до 1 цифра
  83.         # Сега обхождаме ancestors, за да добавим връзките дете-към-родител в self.struct
  84.         ancestors_len = len(ancestors)
  85.         for idx in range(ancestors_len):
  86.             child = ancestors[idx]
  87.             child_top_group_digits_len = ancestors_top_group_digits[idx]
  88.             child_groups = ancestors_groups[idx]
  89.             parent_idx = idx + 1
  90.             if parent_idx < ancestors_len:  # Бащата присъства в списъка
  91.                 parent = ancestors[parent_idx]  # Вземаме бащата от списъка
  92.             else:  # Бащата не е в списъка
  93.                 parent = ""  # Затова бащата е коренът
  94.  
  95.             if child in self.struct:
  96.                 # Няма нужда са се минава нататък през родителите му, понеже те вече са вписани
  97.                 #print(f"Вече е вписано, че {child} има родител {parent}, пропускаме останалото родословие")
  98.                 break
  99.             else:
  100.                 self.struct[child] = parent
  101.                 self.top_digits[child] = child_top_group_digits_len
  102.                 self.groups[child] = child_groups
  103.         # print('ancestors', ancestors)
  104.     def get_max_groups_count(self):
  105.         return self.max_groups_count
  106.  
  107.     def get_top_group_max_digits_count(self):
  108.         return self.top_group_max_digits_count
  109.  
  110.     def get_top_group_digits(self, code):
  111.         return self.top_digits[code]
  112.  
  113.     def get_groups(self, code):
  114.         return self.groups[code]
  115.  
  116.     # Връща дълбочината на дадена сметка в дървото
  117.     def get_depth(self, code):  # TODO Izpolzwam 2
  118.         if code not in self.struct:  # Няма таква сметка
  119.             return None
  120.         # Такава сметка има
  121.         depth = 0
  122.         next_code = code
  123.         while next_code in self.struct:
  124.             depth += 1
  125.             next_code = self.struct[next_code]
  126.  
  127.         return depth
  128.  
  129.  
  130.  
  131.     def print_struct(self):     # TODO up_struct = children ????
  132.         print('struct', self.struct) # struct {'10-100-20-25': '10-100-20', '10-100-20': '10-100', '10-100': '10', '10': '1', '1': ''}
  133.         up_struct = {}
  134.  
  135.         for key in self.struct:
  136.             if self.struct[key] == self.struct[key]:
  137.                 key_up_struct = self.struct[key]
  138.                 if key_up_struct in up_struct:
  139.                     up_struct[key_up_struct] += [key]
  140.                 elif key_up_struct not in up_struct:
  141.                     up_struct[key_up_struct] = [key]
  142.         # Сортиране на децата -> List in value
  143.         for parent_acc in up_struct:
  144.             up_struct[parent_acc].sort()
  145.  
  146.         print('up_struct', up_struct)
  147.  
  148.  
  149.     # Връща list с само преките деца на даден code
  150.     def get_children(self, code):
  151.  
  152.         if self.children is None:
  153.             self.children = {}
  154.             # Ще бъде речник с изброени преки деца на всяка сметка {"150": ["150-1", "150-2", ...], ...}
  155.             for child in self.struct:
  156.                 parent = self.struct[child]
  157.                 if parent not in self.children:
  158.                     self.children[parent] = []
  159.                 self.children[parent].append(child)
  160.  
  161.         if code in self.children: # Ако кодът има деца...
  162.             return self.children[code]  # връшаме ги Връща лист !
  163.  
  164.         # Щом сме стигнали дотук, кодът няма деца
  165.         return []   # Затова връщаме празен списък
  166.  
  167.     # Връща list с всички деца, внуци и т.н. на даден код
  168.     def get_all_children(self, code, max_depth = 999):
  169.         if max_depth == 0:
  170.             return []
  171.         max_depth -= 1
  172.         processed = []
  173.         children = self.get_children(code)
  174.         #print(f"АААААА {code} има за деца {children}")
  175.         depth = 0
  176.         while depth < max_depth:
  177.             children1 = []
  178.             for child in children:
  179.                 children1.append(child)
  180.                 if child in processed:  # вече сме добавили преките деца на това дете
  181.                     continue  # затова пропускаме
  182.                 children2 = self.get_children(child)
  183.                 #print(f"Ниво {depth}: {child} има за деца {children2}")
  184.                 processed.append(child)
  185.                 for child2 in children2:
  186.                     children1.append(child2)
  187.             #print(f"Заместваме {children} с {children1}")
  188.             children = children1
  189.             depth += 1
  190.         return children
  191.  
  192.     def get_parent(self, acc_code):
  193.         # print(f"acc_code {acc_code}")
  194.         # print('self.struct[acc_code]: ', self.struct[acc_code])
  195.         if acc_code is None:
  196.             return None
  197.         print(self.struct)
  198.         # if acc_code in self.struct[acc_code]: # Писано от Владо
  199.         if acc_code in self.struct: # Писано от мен
  200.             return self.struct[acc_code]
  201.  
  202.     def get_ancestors(self, acc_code):
  203.         ancestors = []
  204.         # Почваме от даения код, вземаме родителя, после неговия родител и т.н.
  205.         # докато опрем в корена
  206.         browse_code = acc_code
  207.         while True:
  208.             parent = self.get_parent(browse_code)
  209.             if parent == "" or parent == None:  # Опряли сме в корена на дървото
  210.                 break   # няма повече родители
  211.             ancestors.push(parent)  # Добавяме родителя в списъка с предци
  212.         return ancestors
  213.    
  214.     # В TrialBalanceFilter на много места се искаме да знаем дали code1 е дете на code2.
  215.     # Там правим сложни аналзи на групи цифри -- те трябва да се махнат.
  216.     # ТАМ има self.acc_tree, което е обект от клас AccountTree
  217.     # AccountTree tрябва да се сдобие с методи като is_child() по-долу,
  218.     # kойто да отговаря на тоя въпрос като използва своя self.struct
  219.     def is_child(self, child, parent):
  220.         # Трябва да връша true или false
  221.         pass
  222.     def is_parent(self, child, parent):
  223.         # Трябва да връша true или false
  224.         pass
  225.  
  226. if __name__ == '__main__':
  227.  
  228.     acc_tree = AccountTree()
  229.     acc_tree.add_code("100")
  230.     acc_tree.print_struct()
  231.     acc_tree.get_parent('100')
  232.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement