SHOW:
|
|
- or go back to the newest paste.
| 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.top_group_min_digits_count = None # Беше None |
| 10 | + | self.max_groups_count = None # Беше None |
| 11 | - | self.top_group_max_digits_count = None # Беше None |
| 11 | + | |
| 12 | - | self.max_groups_count = None # Беше None |
| 12 | + | |
| 13 | - | self.max_depth = None |
| 13 | + | def add_code(self, code): # TODO IZPOLZWAM 1 Прави STRUCT !!! |
| 14 | - | self.all_accs = [] |
| 14 | + | |
| 15 | # "123-456-789" дава ["123", "456", "789"] | |
| 16 | groups_digits = re.findall('[0-9]+', code)
| |
| 17 | - | def add_code(self, code): # TODO IZPOLZWAM 1 Прави STRUCT !!! |
| 17 | + | |
| 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 | - | elif groups_digits_len > self.max_groups_count: # МОже би трябва да е IF ??? |
| 27 | + | |
| 28 | #1 | |
| 29 | #12 -------TODO----- ВАЖНО -> ТОП родителя е този, който е подаден от Excel с най-малко цифри !!! | |
| 30 | - | # 1 |
| 30 | + | #123 -------TODO---- -> Няма смисъл да раздробяваме на по-малки кодове сметките в Оборотната ведомост ! |
| 31 | - | # 12 -------TODO----- ВАЖНО -> ТОП родителя е този, който е подаден от Excel с най-малко цифри !!! |
| 31 | + | #123-456 |
| 32 | - | # 123 -------TODO---- -> Няма смисъл да раздробяваме на по-малки кодове сметките в Оборотната ведомост ! |
| 32 | + | #123-456-789 |
| 33 | - | # 123-456 |
| 33 | + | |
| 34 | - | # 123-456-789 |
| 34 | + | |
| 35 | top_group_digits = groups_digits[0] # Първата група | |
| 36 | #print("top_group_digits", top_group_digits)
| |
| 37 | - | # print("top_group_digits", top_group_digits)
|
| 37 | + | |
| 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 | - | for len1 in range(top_group_digits_len - 1, 0, -1): |
| 71 | + | |
| 72 | - | # print("len1", len1)
|
| 72 | + | |
| 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 | - | if self.max_depth is None: |
| 80 | + | # print("След анализ на първата група: ancestors", ancestors)
|
| 81 | - | self.max_depth = ancestors_len |
| 81 | + | |
| 82 | - | elif ancestors_len > self.max_depth: |
| 82 | + | |
| 83 | - | self.max_depth = ancestors_len |
| 83 | + | |
| 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 | - | if len(child) > 0 and child not in self.all_accs: # TODO -> НЕ СЪДЪРЖА ВСИЧКИ СМЕТКИ !!! |
| 97 | + | #print(f"Вече е вписано, че {child} има родител {parent}, пропускаме останалото родословие")
|
| 98 | - | self.all_accs.append(parent) |
| 98 | + | |
| 99 | - | if len(parent) > 0 and parent not in self.all_accs: |
| 99 | + | |
| 100 | - | self.all_accs.append(parent) |
| 100 | + | |
| 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 | - | def get_max_depth(self): |
| 118 | + | |
| 119 | - | return self.max_depth |
| 119 | + | |
| 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 | - | def print_struct(self): # TODO up_struct = children ???? |
| 133 | + | |
| 134 | - | print('struct', self.struct) # struct {'10-100-20-25': '10-100-20', '10-100-20': '10-100', '10-100': '10', '10': '1', '1': ''}
|
| 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 code in self.children: # Ако кодът има деца... |
| 157 | + | |
| 158 | self.children[parent] = [] | |
| 159 | self.children[parent].append(child) | |
| 160 | - | return [] # Затова връщаме празен списък |
| 160 | + | |
| 161 | if code in self.children: # Ако кодът има деца... | |
| 162 | return self.children[code] # връшаме ги Връща лист ! | |
| 163 | - | def get_all_children(self, code, max_depth=None): |
| 163 | + | |
| 164 | - | if max_depth is None: |
| 164 | + | |
| 165 | - | max_depth = self.max_depth |
| 165 | + | return [] # Затова връщаме празен списък |
| 166 | ||
| 167 | # Връща list с всички деца, внуци и т.н. на даден код | |
| 168 | def get_all_children(self, code, max_depth = 999): | |
| 169 | if max_depth == 0: | |
| 170 | return [] | |
| 171 | - | # print(f"АААААА {code} има за деца {children}")
|
| 171 | + | |
| 172 | processed = [] | |
| 173 | children = self.get_children(code) | |
| 174 | - | # print(f"get_all_children() depth {depth}")
|
| 174 | + | #print(f"АААААА {code} има за деца {children}")
|
| 175 | depth = 0 | |
| 176 | - | children_on_this_depth = 0 |
| 176 | + | |
| 177 | children1 = [] | |
| 178 | for child in children: | |
| 179 | children1.append(child) | |
| 180 | if child in processed: # вече сме добавили преките деца на това дете | |
| 181 | continue # затова пропускаме | |
| 182 | - | # print(f"Ниво {depth}: {child} има за деца {children2}")
|
| 182 | + | |
| 183 | - | children_on_this_depth += len(children2) |
| 183 | + | #print(f"Ниво {depth}: {child} има за деца {children2}")
|
| 184 | processed.append(child) | |
| 185 | for child2 in children2: | |
| 186 | children1.append(child2) | |
| 187 | - | if children_on_this_depth == 0: |
| 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 | - | if acc_code is None or acc_code == '': |
| 194 | + | # print('self.struct[acc_code]: ', self.struct[acc_code])
|
| 195 | if acc_code is None: | |
| 196 | - | if acc_code in self.struct: # Писано от мен |
| 196 | + | |
| 197 | print(self.struct) | |
| 198 | # if acc_code in self.struct[acc_code]: # Писано от Владо | |
| 199 | - | def get_all_parents(self, acc_code): |
| 199 | + | if acc_code in self.struct: # Писано от мен |
| 200 | - | parents = [] |
| 200 | + | |
| 201 | - | # Почваме от даения код, вземаме родителя, после неговия родител и т.н. докато опрем в корена |
| 201 | + | |
| 202 | def get_ancestors(self, acc_code): | |
| 203 | ancestors = [] | |
| 204 | # Почваме от даения код, вземаме родителя, после неговия родител и т.н. | |
| 205 | # докато опрем в корена | |
| 206 | - | break # няма повече родители |
| 206 | + | |
| 207 | - | parents.append(parent) # Добавяме родителя в списъка с предци |
| 207 | + | |
| 208 | - | browse_code = parent |
| 208 | + | |
| 209 | - | return parents |
| 209 | + | |
| 210 | break # няма повече родители | |
| 211 | - | # Листа на дървото = тези които нямат деца = най-дълбоки деца |
| 211 | + | ancestors.push(parent) # Добавяме родителя в списъка с предци |
| 212 | - | def get_leaves(self): |
| 212 | + | return ancestors |
| 213 | - | # всички които имат родители са KEY в struct |
| 213 | + | |
| 214 | - | # всики които имат деца са VALUE в struct |
| 214 | + | # В TrialBalanceFilter на много места се искаме да знаем дали code1 е дете на code2. |
| 215 | - | # значи листа са тези които ги няма в стойностите, но ги има в ключовете |
| 215 | + | # Там правим сложни аналзи на групи цифри -- те трябва да се махнат. |
| 216 | - | values = self.struct.values() # list1 |
| 216 | + | # ТАМ има self.acc_tree, което е обект от клас AccountTree |
| 217 | - | keys = self.struct.keys() # list2 |
| 217 | + | # AccountTree tрябва да се сдобие с методи като is_child() по-долу, |
| 218 | - | #leaves = има в keys, но ги няма в values |
| 218 | + | # kойто да отговаря на тоя въпрос като използва своя self.struct |
| 219 | - | leaves = set(keys).difference(values) |
| 219 | + | def is_child(self, child, parent): |
| 220 | - | return leaves |
| 220 | + | # Трябва да връша true или false |
| 221 | pass | |
| 222 | - | def get_leaves_bycode(self, list_accs: list): |
| 222 | + | def is_parent(self, child, parent): |
| 223 | - | list_leaves_bycode = [] |
| 223 | + | # Трябва да връша true или false |
| 224 | - | # TODO -> Подавам код и проверяван дали е родител |
| 224 | + | pass |
| 225 | - | print('get_leaves_bycode list_accs: ', list_accs)
|
| 225 | + | |
| 226 | - | for leaf in list_accs: |
| 226 | + | |
| 227 | - | is_parent = self.is_parent(leaf) |
| 227 | + | |
| 228 | - | if not is_parent: |
| 228 | + | |
| 229 | - | list_leaves_bycode.append(leaf) |
| 229 | + | acc_tree.add_code("100")
|
| 230 | - | return list_leaves_bycode |
| 230 | + | |
| 231 | acc_tree.get_parent('100')
| |
| 232 | - | def get_all_deepest_parents(self): |
| 232 | + |