Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from json_file_io import JsonFileIo
- from Opiti.from_excel.classes.global_inc import registry # TODO KАКВО Е ТОВА ???
- from widget_factory import *
- from account_tree import *
- from excel_acc_data import *
- class TrialBalance:
- def __init__(self): # TODO acc_data_bycode = acc_data1
- self.window = tk.Tk()
- self.widget_factory = WidgetsFactory()
- self.synthetic_value = tk.StringVar(self.window)
- self.analytic_value = tk.StringVar(self.window)
- self.unmapped_value = tk.StringVar(self.window)
- self.level_code = None
- self.acc_data = [] # dict # Сурови данни от Excel -> Списък от речници
- self.acc_data_bycode = {} # Данни от Excel с Ключ "сметка" -> Речник в речник {10: {'code': '10', 'name':..}}
- self.min_top_group_digits = 0 # Минимален брой цифри в топ групата на кода на сметките -> spin_1
- self.max_top_group_digits = 0 # Максимален брой цифри в топ групата на кода на сметките -> spin_1
- self.max_groups = 0 # Максимален брой групи в кода на сметките
- self.min_level_spin_1 = self.min_top_group_digits
- self.max_level_spin_1 = self.max_top_group_digits
- self.max_level_spin_2 = self.max_groups # -1
- self.code_acc = int()
- self.treeview_data = dict()
- self.tree = None # Променливата под която е рисувано Treeview в WidgetFactory
- self.spin_1 = str()
- self.spin_2 = str()
- self.acc_tree = AccountTree()
- self.user_acc_type = tk.StringVar(self.window) # StringVar на Radiobuttons
- self.total_sum_row = ["", "Обща сума", 0, 0, 0, 0, 0, 0, ]
- self.mapped_acc = {} # Речник с маркираните сметки
- self.parent_maped_acc = [] # Values на речника mapped_acc = {'100': [10]}
- self.scrollbar = None
- self.list_radiobuttons = {'kn': 'НК', 'da': 'ДА', 'mz': 'МЗ', 'vz': 'ВЗ', 'invest': 'Ин', 'money': 'Пари',
- 'rbp': 'РБП', 'tax_assets': 'Дан А/П', 'sk': 'СК', 'provision': 'Пров',
- 'zd': 'ЗД', 'pbp': 'ПБП', 'drugi_p': 'Др',
- 'px': 'Пх', 'rx': 'Рх', 'drugi_opr': 'Др'}
- self.correction_mode = False
- self.list_type_account = [] # Списък със всички видове сметки
- self.list_all_code_account = [] # Списък със всички кодове на сметки
- # ['10', '100', '12', '121', '121-13', '121-14', '121-15'.....]
- # Тук pop-message-диалога ще вписва отговора на юзъра
- self.pop_message_answer = None
- self.is_accounts_mapped = False
- self.excel_acc_data = None
- def set_pop_message_answer(self, answer):
- self.pop_message_answer = answer
- def on_ok(self):
- # TODO -> Проверка за немаркирани сметки
- list_unmapped_accs = self.acc_tree.get_unmapped_acc(self.mapped_acc)
- print("BBBB list_unmapped_accs", list_unmapped_accs)
- print("BBBB len(list_unmapped_accs)", len(list_unmapped_accs))
- if len(list_unmapped_accs) > 0:
- # TODO -> Показва pop_message "Има немаркирани сметки ! Желаете ли да маркирате всички сметки ?" Бутони: "ДА", "НЕ"
- pop_message = self.widget_factory.get_pop_message(self.window,
- lambda answer: self.set_pop_message_answer(answer),
- "Има немаркирани сметки !\nЖелаете ли да маркирате всички сметки ?", 2, 'red')
- self.window.wait_window(pop_message.pop)
- # TODO -> Ако "ДА"
- if self.pop_message_answer == 'yes':
- return
- # TODO -> Ако "НЕ"
- # TODO -> mapped_account.txt -> {"121": ["СК"], "121-13": ["СК"], "121-14": ["СК"],....}
- json_file_io = JsonFileIo(file_name=registry['mapped_account_file_name'])
- json_file_io.write_content(self.mapped_acc)
- # TODO -> КАк се излиза от приложението Trial_balance ?? QUIT(), DESTROY(), CLOSE() ?
- self.window.destroy()
- return
- # TODO -> Показва pop_message "Всички сметки са маркирани ! Бутон "ОК"
- pop_message = self.widget_factory.get_pop_message(self.window,
- lambda answer: self.set_pop_message_answer(answer), "Всички сметки са маркирани !", 1, 'blue')
- self.window.wait_window(pop_message.pop)
- # TODO -> mapped_account.txt -> {"121": ["СК"], "121-13": ["СК"], "121-14": ["СК"],....}
- json_file_io = JsonFileIo(file_name=registry['mapped_account_file_name'])
- json_file_io.write_content(self.mapped_acc)
- self.is_accounts_mapped = True # Всички сметки са маркирани !
- # TODO -> acc_data_bycode.txt -> {'10': {'code': '10', 'name':}
- json_file_io = JsonFileIo(file_name=registry['acc_data_bycode_file_name'])
- json_file_io.write_content(self.acc_data_bycode)
- self.window.destroy()
- return
- def on_correction(self):
- self.correction_mode = True
- def mark_accounts(self, acc_code): # Приема TUPLE и прави маркиране на всички под-нива на маркираните сметки
- # print('acc_code: ', acc_code)
- if acc_code in self.mapped_acc:
- return self.mapped_acc[acc_code] # сметката вече е маркирана
- if acc_code == 'total':
- return 'total'
- return None # Подлежат на маркиране само тези които са None !
- def verify_selection(self): # Забрана за маркиране
- if self.correction_mode: return
- selected_items = self.tree.selection() # Прави Tuple от кодовете на маркираните сметки
- # print(selected_items)
- for code in selected_items:
- if code is not None:
- mark_type = self.mark_accounts(code)
- # print("mark_type:", mark_type)
- if mark_type is None: pass # Сметката не е маркирана и чака Бутон 'Запис'
- else: self.tree.selection_remove(code)
- return
- def update_type_account(self):
- pass
- def on_select_acc(self):
- self.verify_selection()
- self.update_type_account()
- def on_save(self): # TODO -> Пълни mapped_acc{} речник с маркираните сметки
- selected_acc_codes = self.tree.selection() # Взимаме селектираните сметки
- type_account = self.user_acc_type.get() # Взимаме селектирания Радиобутон, StringVar на Radiobuttons
- list_of_children_types = [] # Списък с видовете на децата
- if type_account is None or type_account == '' or len(selected_acc_codes) == 0:
- return
- for acc_code in selected_acc_codes: # TODO -> За всяка селектирана сметка: acc_code e '100':
- is_parent = self.acc_tree.is_parent(acc_code) # Проверяваме дали маркираната сметка е родител
- if acc_code in self.mapped_acc and is_parent: # Ако вече е маркирана и е родител
- pop_message = self.widget_factory.get_pop_message(self.window, lambda answer: self.set_pop_message_answer(answer),
- f"Да се промени ли вида на с/ка {acc_code}\nи нейните подсметки ?", 2, 'blue')
- self.window.wait_window(pop_message.pop) #
- if self.pop_message_answer == 'no': # Няма да променяме сметката и децата й !
- self.tree.selection_remove(acc_code) # Дали ще работи ???
- continue # Може би да размаркираме тази сметка в Treeview ???
- else: # TODO -> Ще променим вида на сметката и децата й !
- # TODO -> Да махнем децата от self.mapped_acc
- haves_children = self.acc_tree.get_all_children(acc_code)
- for child in haves_children:
- if child in self.mapped_acc:
- del self.mapped_acc[child]
- # Маркираме сметката type_account е маркирания радиобутон
- if self.list_radiobuttons[type_account] not in self.list_type_account:
- self.list_type_account.append(self.list_radiobuttons[type_account])
- self.mapped_acc[acc_code] = self.list_type_account # mapped_acc = {'121': ['СК']}, Маркираме сметката
- self.list_type_account = []
- # ----Ръчно маркиране
- self.tree.set(acc_code, 'type', '/'.join(self.mapped_acc[acc_code])) # Слагаме вида сметка в Treeview
- # TODO -> Проверяваме дали текущата сметка е родител !!
- is_parent = self.acc_tree.is_parent(acc_code)
- if is_parent:
- haves_children = self.acc_tree.get_all_children(acc_code)
- # TODO -> Проверка на вида на децата !
- for child in haves_children: # Маркиране на child
- if self.list_radiobuttons[type_account] not in self.list_type_account:
- self.list_type_account.append(self.list_radiobuttons[type_account])
- self.mapped_acc[child] = self.list_type_account
- self.list_type_account = []
- # TODO -> До тук текущата сметка е маркирана и всички нейни деца вече са маркирани !
- # TODO -> Автоматично маркиране на всички родители, Проверка дали текущата сметка има родител ?
- is_child = self.acc_tree.is_child(acc_code)
- if is_child:
- parents_codes = self.acc_tree.get_all_parents(acc_code) #Подаваме тек с/ка и получаваме вс/ки родители
- for parent_code in parents_codes:
- # TODO -> Да вземем децата на parent_code и да проверим техните видове !
- children_of_parent_code = self.acc_tree.get_all_children(parent_code) # Децата на всеки родител
- # TODO -> Да съберем в списък list_of_children_types, видовете на всички деца
- for child in children_of_parent_code:
- if child in self.mapped_acc: # Ако детето е вече маркирано
- diff_types = self.acc_tree.asymmetric_compare_lists(self.mapped_acc[child],
- list_of_children_types)
- if diff_types is not None:
- list_of_children_types += diff_types
- self.mapped_acc[parent_code] = list_of_children_types
- list_of_children_types = []
- self.correction_mode = False
- self.fill_treeview() # TODO -> НОВО !
- def fill_treeview(self):
- self.tree.delete(*self.tree.get_children()) # Вградена функция за изтриване на Treeview
- spin_1, spin_2 = int(self.synthetic_value.get()), int(self.analytic_value.get())
- unmapped_spin = self.unmapped_value.get()
- # TODO -> За попълване на немаркираните сметки от Бутон "ОК",
- #list_unmapped_accs = self.acc_tree.get_unmapped_acc(self.mapped_acc, self.list_all_code_account)
- list_unmapped_accs = self.acc_tree.get_unmapped_acc(self.mapped_acc)
- print('list_unmapped_accs: ', list_unmapped_accs)
- parents_with_unmapped_children = []
- # parents_with_unmapped_children има смисъл да се строи само ако unmapped_spin == "немаркирани"
- if unmapped_spin == "немаркирани":
- for code in self.acc_data_bycode:
- if code in list_unmapped_accs: # TypeError: argument of type 'NoneType' is not iterable
- parents = self.acc_tree.get_all_parents(code)
- for parent in parents:
- if parent not in parents_with_unmapped_children:
- parents_with_unmapped_children.append(parent)
- def check_unmapped_acc(code):
- if unmapped_spin == "немаркирани":
- if code in list_unmapped_accs:
- return True
- elif code in parents_with_unmapped_children:
- return True
- return False
- return True
- self.treeview_data = self.acc_data_bycode.copy()
- filtered_dict = {}
- # TODO Accounttree за момента не знае дали дадена сметка е синтетична или не, може да му се добави да знае
- if spin_2 == 0:
- for code in self.treeview_data:
- if check_unmapped_acc(code):
- groups_in_top_code = re.findall('[0-9]+', code) # ['610', '30', '9']
- if len(groups_in_top_code[0]) == spin_1 and len(groups_in_top_code) == 1:
- filtered_dict[code] = self.treeview_data[code]
- else:
- for code in self.treeview_data:
- if check_unmapped_acc(code):
- depth = self.acc_tree.get_depth(code)
- if spin_1 <= depth <= (spin_1 + spin_2):
- filtered_dict[code] = self.treeview_data[code]
- # ---- TODO Дазалепим тотала във filtered_dict !!
- count_rows = len(filtered_dict) + 1 # Брой редове за печат + 1 заради ТОТАЛ
- nsd = nsc = od = oc = ksd = ksc = 0.0
- for acc_code in filtered_dict: # acc_code: 724
- type = ''
- if acc_code in self.mapped_acc:
- type = self.mapped_acc[acc_code]
- nsd += filtered_dict[acc_code]['open_d']
- nsc += filtered_dict[acc_code]['open_c']
- od += filtered_dict[acc_code]['turn_d']
- oc += filtered_dict[acc_code]['turn_c']
- ksd += filtered_dict[acc_code]['close_d']
- ksc += filtered_dict[acc_code]['close_c']
- row = [
- type, # Тук ще влезе вида сметка посочен от порребителя
- acc_code,
- filtered_dict[acc_code]['name'],
- filtered_dict[acc_code]['str_open_d'],
- filtered_dict[acc_code]['str_open_c'],
- filtered_dict[acc_code]['str_turn_d'],
- filtered_dict[acc_code]['str_turn_c'],
- filtered_dict[acc_code]['str_close_d'],
- filtered_dict[acc_code]['str_close_c']]
- tags = []
- iid = acc_code
- self.tree.insert(parent='', index=tk.END, values=row, tags=tags, iid=iid)
- # -------TODO да викна функция за TOTAL и да вмъкна TOTAL в Treeview
- total = ['', '', 'Обща сума:', f'{nsd:,.2f}'.replace(',', ' '), f'{nsc:,.2f}'.replace(',', ' '),
- f'{od:,.2f}'.replace(',', ' '), f'{oc:,.2f}'.replace(',', ' '), f'{ksd:,.2f}'.replace(',', ' '),
- f'{ksc:,.2f}'.replace(',', ' ')]
- self.tree.insert(parent='', index=tk.END, values=total, tags=['total'], iid='total')
- if count_rows > 30:
- self.tree.configure(height=30)
- else: self.tree.configure(height=count_rows)
- self.treeview_data = {}
- def main(self):
- # -----------------------------------------------------
- self.window.title('Оборотна ведомост')
- self.window.geometry('1254x840+150+10')
- self.window.resizable(True, False)
- self.window.attributes('-topmost', 'true')
- widget_factory = WidgetsFactory()
- # -----------TODO BUTTONS-------------------------------
- butt_save = widget_factory.get_save_button(self.window, 20, 560)
- butt_save.bind('<ButtonRelease-1>', lambda e: self.on_save())
- butt_ok = widget_factory.get_ok_button(self.window, 20, 600)
- butt_ok.bind('<ButtonRelease-1>', lambda e: self.on_ok())
- butt_correction = widget_factory.get_correction_button(self.window, 20, 764)
- butt_correction.bind('<ButtonRelease-1>', lambda e: self.on_correction())
- butt_help = widget_factory.get_help_button(self.window, 20, 794)
- butt_help.bind('<ButtonRelease-1>', lambda e: None)
- # -----------TODO LABEL_FRAMES-------------------------------
- label_frame_a = widget_factory.get_label_frame(self.window, 'Актив')
- label_frame_a.place(x=20, y=60)
- label_frame_p = widget_factory.get_label_frame(self.window, 'Пасив')
- label_frame_p.place(x=20, y=290) # 270
- label_frame_opr = widget_factory.get_label_frame(self.window, 'Пх/Рх')
- label_frame_opr.place(x=20, y=445) # 430
- # -----------TODO RADIO BUTTONS-------------------------------
- widget_factory.get_radio_butt(label_frame_a, 7, 'w', list_buttons={'kn': 'Невн.к-л', 'da': 'ДА', 'mz': 'МЗ',
- 'vz': 'Вземания', 'invest': 'Инвест.', 'money': 'Пари', 'rbp': 'РБП', 'tax_assets': 'Дан А/П'},
- var=self.user_acc_type)
- widget_factory.get_radio_butt(label_frame_p, 7, 'w', list_buttons={'sk': 'СК', 'provision': 'Провизии',
- 'zd': 'Задълж.', 'pbp': 'ПБП', 'drugi_p': 'Други'}, var=self.user_acc_type)
- widget_factory.get_radio_butt(label_frame_opr, 7, 'w', list_buttons={'px': 'Приходи', 'rx': 'Разходи',
- 'drugi_opr': 'Други'}, var=self.user_acc_type)
- # -----------TODO LABEL-------------------------------
- # place_on, x, y, text_l, w, p, color
- acc_label = widget_factory.get_label(self.window, 150, 12, 'Сметки', 6, 'w')
- synt_label = widget_factory.get_label(self.window, 250, 12, 'синтет.', 8, 'w')
- analyt_label = widget_factory.get_label(self.window, 320, 12, 'аналит.', 8, 'w')
- some_label = widget_factory.get_label(self.window, 670, 28, 'Начално салдо', 13, 'w')
- some_label2 = widget_factory.get_label(self.window, 880, 28, 'Обороти', 8, 'w')
- some_label3 = widget_factory.get_label(self.window, 1070, 28, 'Крайно салдо', 13, 'w')
- # -----------TODO FRAME-------------------------------
- tv_frame = widget_factory.get_frame(self.window)
- tv_frame.place(x=150, y=50)
- # -----------TODO TREEVIEW-------------------------------
- mapped_acc_data = MappedAccData()
- mapped_acc_data.read_json()
- self.mapped_acc = mapped_acc_data.get_mapped_acc()
- print("TrialBalance: self.mapped_acc", self.mapped_acc)
- self.excel_acc_data = ExcelAccData()
- self.excel_acc_data.convert_json_data()
- self.acc_data_bycode = self.excel_acc_data.get_acc_data_bycode()
- self.min_top_group_digits = self.excel_acc_data.get_min_top_group_digits()
- self.max_top_group_digits = self.excel_acc_data.get_max_top_group_digits()
- self.max_groups = self.excel_acc_data.get_max_groups()
- for acc_code in self.acc_data_bycode:
- self.acc_tree.add_code(acc_code) # Захранваме наследственото дърво
- self.list_all_code_account.append(acc_code)
- list_of_columns = {
- 'type': 'вид',
- 'code': 'код',
- 'acc_name': 'Сметка',
- 'open_d': 'НС Дебит',
- 'open_c': 'НС Кредит',
- 'turn_d': 'Оборот Дт',
- 'turn_c': 'Оборот Кт',
- 'close_d': 'КС Дебит',
- 'close_c': 'КС Кредит'
- }
- self.tree = widget_factory.get_treeview(tv_frame, **list_of_columns)
- self.tree.tag_configure('total', font=('Timesbd', 9, 'bold')) # Общата сума наи-долу
- self.tree.bind('<ButtonRelease-1>', lambda e: self.on_select_acc())
- # -----------TODO SCROLLBAR-------------------------------
- self.scrollbar = widget_factory.get_scrollbar(tv_frame, 'vertical', 'right', 'y')
- self.scrollbar.configure(command=self.tree.yview) # flat, groove, raised, ridge, solid, or sunken
- self.tree.configure(yscrollcommand=self.scrollbar.set)
- # -----------TODO SPINBOX-------------------------------
- list_type = ['всички', 'немаркирани']
- unmapped_acc = self.widget_factory.get_list_spinbox(self.window, list_type, 14, 'center',
- self.unmapped_value, 150, 30)
- unmapped_acc.configure(command=self.fill_treeview)
- self.unmapped_value.set(value='всички')
- synthetic_spinbox = widget_factory.get_spinbox(self.window, str(self.min_top_group_digits),
- str(self.max_top_group_digits), 9, 'center', self.synthetic_value, 250, 30)
- synthetic_spinbox.configure(command=self.fill_treeview)
- self.synthetic_value.set(value='3')
- analytic_spinbox = widget_factory.get_spinbox(self.window, "0", str(self.max_groups), 10, 'center',
- self.analytic_value, 320, 30)
- analytic_spinbox.configure(command=self.fill_treeview)
- self.analytic_value.set(value="0")
- self.fill_treeview()
- self.window.update() # Не знаем дали е полезно, но май не пречи
- self.window.mainloop()
- if __name__ == '__main__':
- test = TrialBalance()
- test.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement