From 21fccd5afa51ac74782638a0d828ace586901408 Mon Sep 17 00:00:00 2001 From: ValeZh Date: Tue, 23 Apr 2024 09:55:38 +0300 Subject: [PATCH 01/11] make bd and start making api_py --- hw_4/.idea/.gitignore | 3 ++ hw_4/.idea/.name | 1 + hw_4/.idea/hw_4.iml | 10 ++++ .../inspectionProfiles/profiles_settings.xml | 6 +++ hw_4/.idea/misc.xml | 7 +++ hw_4/.idea/modules.xml | 8 +++ hw_4/.idea/vcs.xml | 6 +++ hw_4/api.py | 18 +++++++ hw_4/bank.db | Bin 0 -> 32768 bytes hw_4/initial_db_setup.py | 48 ++++++++++++++++++ 10 files changed, 107 insertions(+) create mode 100644 hw_4/.idea/.gitignore create mode 100644 hw_4/.idea/.name create mode 100644 hw_4/.idea/hw_4.iml create mode 100644 hw_4/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 hw_4/.idea/misc.xml create mode 100644 hw_4/.idea/modules.xml create mode 100644 hw_4/.idea/vcs.xml create mode 100644 hw_4/api.py create mode 100644 hw_4/bank.db create mode 100644 hw_4/initial_db_setup.py diff --git a/hw_4/.idea/.gitignore b/hw_4/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/hw_4/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/hw_4/.idea/.name b/hw_4/.idea/.name new file mode 100644 index 0000000..11a5d8e --- /dev/null +++ b/hw_4/.idea/.name @@ -0,0 +1 @@ +main.py \ No newline at end of file diff --git a/hw_4/.idea/hw_4.iml b/hw_4/.idea/hw_4.iml new file mode 100644 index 0000000..2c80e12 --- /dev/null +++ b/hw_4/.idea/hw_4.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/hw_4/.idea/inspectionProfiles/profiles_settings.xml b/hw_4/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/hw_4/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/hw_4/.idea/misc.xml b/hw_4/.idea/misc.xml new file mode 100644 index 0000000..a0c5da8 --- /dev/null +++ b/hw_4/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/hw_4/.idea/modules.xml b/hw_4/.idea/modules.xml new file mode 100644 index 0000000..7bc33cf --- /dev/null +++ b/hw_4/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/hw_4/.idea/vcs.xml b/hw_4/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/hw_4/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/hw_4/api.py b/hw_4/api.py new file mode 100644 index 0000000..2f19426 --- /dev/null +++ b/hw_4/api.py @@ -0,0 +1,18 @@ +import initial_db_setup as init_db +import argparse +import sqlite3 +import requests +import csv + +def get_data(): + api_key = 'fca_live_bYExvWei85B5olF2iitYB6HunpYb8RYaZAw29iWt' + url = f'https://api.freecurrencyapi.com/v1/latest?apikey={api_key}' + response = requests.get(url) + data = response.json() + print(data) + return data + + +get_data() + + diff --git a/hw_4/bank.db b/hw_4/bank.db new file mode 100644 index 0000000000000000000000000000000000000000..a88980498134c4eeb8760e5a88ad1733cd8129d7 GIT binary patch literal 32768 zcmeI&&u`LT7{Kv%V{{?I?Ls*0^4`T^G4@bJTs4XZU**7ZeV+VqT4Sl(eAZcDWTTntt%|^WfX9GP|_#6JszC6!F;&r zwVOvhGo|T$$A6Qv7YE}YaQ*&dzUh=U8v_X^BCu9ghr6K@jz@88^}9x~+St@J&p&lP zjNY9`j|R3g4u|o+Jxgsj*;u`(6^v@7qJP4gx-wTJc_ghuvSPWbB!k<|;P3o0 zusaU?ys`UU5T4nm&XhAnQ8t+5J4MQ}l)=*)*JN*ZW?iY*w^oYP2bJ4o<3YG9KZ~Cq zE*sVDZT;K**i;S-D{%ag(+|C&zpz`FlV12S4gK0c&z=^tEqmlf;~=neVa^6ea?Z62 zWlWa%DuLT~z4!lmovX9*U8(E(p`Cl`#L+qD&l4wfLoXSc^^bZyBR;*ls-Dbo=|-LY zt2j3cl8n0g)>76mi@A5@=W=vIiJ$Gu^3JlM(Cvj(5kLR|1Q0*~0R#|0009ILP*9*G zbLRP9!OD{|0tg_000IagfB*srAb@~M0=)lMsoLa<00IagfB*srAbk|bwaFC$1Q0*~0R#|0009ILKtNT2-xcv^e*gdg literal 0 HcmV?d00001 diff --git a/hw_4/initial_db_setup.py b/hw_4/initial_db_setup.py new file mode 100644 index 0000000..a8ebaf8 --- /dev/null +++ b/hw_4/initial_db_setup.py @@ -0,0 +1,48 @@ +import sqlite3 + +def create_database(unique_constraint): + # Устанавливаем соединение с базой данных + conn = sqlite3.connect('bank.db') + c = conn.cursor() + + # Создаем таблицу Bank + c.execute('''CREATE TABLE IF NOT EXISTS Bank ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL UNIQUE)''') + + # Создаем таблицу BankTransaction + c.execute('''CREATE TABLE IF NOT EXISTS BankTransaction ( + id INTEGER PRIMARY KEY, + Bank_sender_name TEXT NOT NULL, + Account_sender_id INTEGER NOT NULL, + Bank_receiver_name TEXT NOT NULL, + Account_receiver_id INTEGER NOT NULL, + Sent_Currency TEXT NOT NULL, + Sent_Amount REAL NOT NULL, + Datetime TEXT)''') + + # Создаем таблицу User + if unique_constraint: + c.execute('''CREATE TABLE IF NOT EXISTS User ( + Id INTEGER PRIMARY KEY, + Name TEXT NOT NULL, + Surname TEXT NOT NULL, + Birth_day TEXT, + Accounts TEXT NOT NULL)''') + + # Создаем таблицу Account + c.execute('''CREATE TABLE IF NOT EXISTS Account ( + Id INTEGER PRIMARY KEY, + User_id INTEGER NOT NULL, + Type TEXT NOT NULL, + Account_Number TEXT NOT NULL UNIQUE, + Bank_id INTEGER NOT NULL, + Currency TEXT NOT NULL, + Amount REAL NOT NULL, + Status TEXT)''') + + # Фиксируем изменения и закрываем соединение + conn.commit() + conn.close() + + From 20206b25ec54f54d9996b31be95eddce7f494e14 Mon Sep 17 00:00:00 2001 From: ValeZh Date: Sun, 5 May 2024 18:45:08 +0300 Subject: [PATCH 02/11] i make all functions witch work with user account bank tables tomorrow make transfer --- hw_4/account.csv | 6 ++ hw_4/api.py | 183 +++++++++++++++++++++++++++++++++++++-- hw_4/bank.csv | 11 +++ hw_4/bank.db | Bin 32768 -> 36864 bytes hw_4/initial_db_setup.py | 16 ++-- hw_4/main.py | 59 +++++++++++++ hw_4/user.csv | 6 ++ 7 files changed, 267 insertions(+), 14 deletions(-) create mode 100644 hw_4/account.csv create mode 100644 hw_4/bank.csv create mode 100644 hw_4/main.py create mode 100644 hw_4/user.csv diff --git a/hw_4/account.csv b/hw_4/account.csv new file mode 100644 index 0000000..c215712 --- /dev/null +++ b/hw_4/account.csv @@ -0,0 +1,6 @@ +user_id,type,account_number,bank_id,currency,amount,status +1,credit,123456,3,USD,1000,gold +3,debit,987654,2,USD,500,silver +5,credit,234567,5,EUR,800,platinum +2,debit,876543,4,CAD,1200,gold +4,credit,345678,1,USD,1500,silver \ No newline at end of file diff --git a/hw_4/api.py b/hw_4/api.py index 2f19426..361a017 100644 --- a/hw_4/api.py +++ b/hw_4/api.py @@ -1,18 +1,189 @@ -import initial_db_setup as init_db -import argparse import sqlite3 import requests import csv + +def db_connection(func): + """ + Декоратор для установки соединения с базой данных и его закрытия после выполнения функции. + + Args: + func (function): Функция базы данных, которая будет выполнена. + + Returns: + function: Вложенная функция-обертка, которая обеспечивает соединение и закрытие. + """ + def wrapper(*args, **kwargs): + """ + Вложенная функция-обертка, обеспечивающая соединение и закрытие. + + Args: + *args: Позиционные аргументы, переданные в функцию. + **kwargs: Именованные аргументы, переданные в функцию. + + Returns: + any: Результат выполнения оригинальной функции. + """ + # Устанавливаем соединение с базой данных + conn = sqlite3.connect('bank.db') + # Создаем объект курсора + c = conn.cursor() + try: + # Вызываем оригинальную функцию, передавая ей курсор и все переданные аргументы + result = func(c, *args, **kwargs) + except Exception as e: + # Обрабатываем ошибки и логируем их + print(f"Error: {str(e)}") + result = None + finally: + # Фиксируем изменения в базе данных и закрываем соединение + conn.commit() + conn.close() + # Возвращаем результат выполнения оригинальной функции + return result + # Возвращаем вложенную функцию-обертку в качестве декоратора + return wrapper + + def get_data(): api_key = 'fca_live_bYExvWei85B5olF2iitYB6HunpYb8RYaZAw29iWt' url = f'https://api.freecurrencyapi.com/v1/latest?apikey={api_key}' response = requests.get(url) - data = response.json() - print(data) - return data + if response.status_code == 200: + data = response.json() + print("data_get successfully") + print(data['data']) + return data['data'] + else: + print("data_get failure") + return None + + +# разобраться и переделать +def read_csv_to_dict(file_path): + with open(file_path, 'r') as file: + reader = csv.DictReader(file) + data_dict = [row for row in reader] + return data_dict + + +def merge_dicts(dict_list): + merged_dict = {} + for d in dict_list: + for key, value in d.items(): + # Если ключ уже есть в объединенном словаре, добавляем значение в список + if key in merged_dict: + merged_dict[key].append(value) + # Если ключ новый, создаем список значений + else: + merged_dict[key] = [value] + return merged_dict + + +# проверяет все ли массивы при ключах имеют одинаковую длинну +def equal_length_lists(d): + lengths = {len(lst) for lst in d.values()} + return len(lengths) == 1 + + +@db_connection +def add_bank(c, bank_data): + # Add bank to the database + for bank in bank_data: + c.execute("INSERT INTO Bank(name) VALUES(?)", (bank,)) + return "Bank added successfully." + + +@db_connection +def read_data_from_file(previous_output): + with open(previous_output, "r", encoding="utf-8") as file: + print("read data success") + return list(csv.DictReader(file)) + + +@db_connection +def add_user(c, user_name, birthday, accounts): + for i in range(len(user_name)): + name = str.split(user_name[i])[0] + surname = str.split(user_name[i])[1] + c.execute("INSERT INTO User(name,surname,birth_day,accounts) VALUES(?,?,?,?)", + (name, surname, f"{birthday[i]}", accounts[i],)) + print(f"user {name} {surname} added success") + return 'success' + + +@db_connection +def add_account_to_db(c, user_id, user_type, acc_numb, bank_id, currency, amount, status): + for i in range(len(user_id)): + c.execute("INSERT INTO Account(user_id, type, account_number, bank_id, currency, amount, status) VALUES(?,?,?,?,?,?,?)", + (user_id[i], user_type[i], acc_numb[i], bank_id[i], currency[i], amount[i], status[i])) + # Получаем количество счетов для текущего пользователя + c.execute("SELECT COUNT(*) FROM Account WHERE user_id = ?", (user_id[i],)) + numb_of_acc = c.fetchone()[0] # Извлекаем значение из курсора + # забабахать сюда функцию + c.execute("UPDATE User SET Accounts = ? WHERE id = ?", (numb_of_acc, user_id[i])) + return 'success' + + +@db_connection +def change_something(c, table_name, row_id, column, value): + c.execute(f"UPDATE {table_name} SET {column} = ? WHERE id = ?", (value, row_id)) + return 'success' + + +@db_connection +def delete_row_from_account(c, row_id): + c.execute(f"DELETE FROM Account WHERE id = ?", (row_id,)) + return 'success' + + +@db_connection +def delete_row_from_user(c, row_id): + # забабахать сюда функцию + c.execute(f"DELETE FROM Account WHERE User_id = ?", (row_id, )) + c.execute(f"DELETE FROM User WHERE id = ?", (row_id,)) + return 'success' + + +@db_connection +def delete_row_from_bank(c, row_id): + # забабахать сюда функцию + c.execute(f"DELETE FROM Account WHERE Bank_id = ?", (row_id,)) + c.execute(f"DELETE FROM Bank WHERE id = ?", (row_id,)) + return 'success' + + +@db_connection +def clear_table(c, table_name): + c.execute("DELETE * FROM {}".format(table_name)) + return 'success' + + +def add_account_by_file(path): + data = merge_dicts(read_csv_to_dict(path)) + add_account_to_db(data["user_id"], data["type"], data["account_number"], data["bank_id"], data["currency"], data["amount"], data["status"]) + return "success" + + +def add_bank_by_file(path): + data = merge_dicts(read_csv_to_dict(path)) + add_bank(data['Name']) + return "success" -get_data() +def add_user_by_file(path): + data = merge_dicts(read_csv_to_dict(path)) + add_user(data["user_name"], data["birthday"], data["accounts"]) +@db_connection +def transfer_money(c, bank_sender_name, account_sender_id, bank_receiver_name, account_receiver_id, sent_currency, sent_amount): + c.execute("SELECT Amount FROM Account WHERE id = ?", (account_sender_id,)) + acc_amount = c.fetchone()[0] + # узнать кол во дененег и валюту у человека на акаунте + # если валюта у отправителя и получателя разные то конвертировать валюту отправителя и получателя и сохранить в переменных + # сравнивать с отправляемой если меньше уходить из функции + # при отправлении + # заполнить таблицу транзакций + # отнять у отправтеля деньги в таблице аккаунт + # прибавить деньги у получателя diff --git a/hw_4/bank.csv b/hw_4/bank.csv new file mode 100644 index 0000000..a31bfa9 --- /dev/null +++ b/hw_4/bank.csv @@ -0,0 +1,11 @@ +Name +Bank of America +Wells Fargo +Chase Bank +Citibank +HSBC +TD Bank +PNC Bank +Capital One +US Bank +BB&T diff --git a/hw_4/bank.db b/hw_4/bank.db index a88980498134c4eeb8760e5a88ad1733cd8129d7..627b18d9b986a89cae615ec94838f7c96d4bb4fb 100644 GIT binary patch delta 1168 zcmY+AO^n-A5P;wFvlH8iJG&d))Xk=As})sMg7UN3p93oSS(cV|TV*%e6I9-;*;qJn zn`D9Pp}Vw#BeaTydIBVl^r@)MgET;miWu= zd)ftIp9(_)zrh2z4`0IPa1B0!_u(Q8(eqWx7_n+?yYGZF0cop_ z=k?8(?B0eyK^Zy9+nE0Ahs;XH>A5Xi#oel~MPLhlhY#Ru_zG^q$M6|kf}hazHQ1J! zP6N>d%g{(v0d|l+B`PObmOc@U^TbFr#;dug#510VihGzv{}W}L_LQhF!Hz1Cs3}LH z+NabU8;5&DgjE8oXm}aU!+CUk0k%yVBk7ct-4~w9DZA&|b>At>&*yXbGJaVpM)WC5 zsd&!Y4S&7oZfrVRh55N+u29UC^7};uq%CEk<9fqt&ws0nrC2wI-vJgQnT(~Ja$9ZN z@lN>dZr{iFECx%tVxEvXnbxuRgxz(PJMN&3+;Xmv&lSqJT|-Y{2#fybqrzjHLrDpS*y=g! z?w~YXo|&C%F4v_8eb;-_=^@LaX@jN&U08S4+`-)JOnJH_)+%-J`iAeVA7TLm6S7js zCm@ zf{VGSl5O&AE-6O#&D*%*8Cluc#2uw4=kZENJ0>URm*$nk8$uZzO&Toh;-aFAEyk05 zd5kC5@aRrn$|E-U9Jlb~i#(DbdJ?bd=v0MiLNo&W#< diff --git a/hw_4/initial_db_setup.py b/hw_4/initial_db_setup.py index a8ebaf8..d9decf2 100644 --- a/hw_4/initial_db_setup.py +++ b/hw_4/initial_db_setup.py @@ -1,6 +1,6 @@ import sqlite3 -def create_database(unique_constraint): +def create_database(): # Устанавливаем соединение с базой данных conn = sqlite3.connect('bank.db') c = conn.cursor() @@ -22,13 +22,13 @@ def create_database(unique_constraint): Datetime TEXT)''') # Создаем таблицу User - if unique_constraint: - c.execute('''CREATE TABLE IF NOT EXISTS User ( - Id INTEGER PRIMARY KEY, - Name TEXT NOT NULL, - Surname TEXT NOT NULL, - Birth_day TEXT, - Accounts TEXT NOT NULL)''') + + c.execute('''CREATE TABLE IF NOT EXISTS User ( + Id INTEGER PRIMARY KEY, + Name TEXT NOT NULL UNIQUE, + Surname TEXT NOT NULL UNIQUE, + Birth_day TEXT, + Accounts INTEGER NOT NULL)''') # Создаем таблицу Account c.execute('''CREATE TABLE IF NOT EXISTS Account ( diff --git a/hw_4/main.py b/hw_4/main.py new file mode 100644 index 0000000..e7c3004 --- /dev/null +++ b/hw_4/main.py @@ -0,0 +1,59 @@ +import argparse +import api +import initial_db_setup + +initial_db_setup.create_database() +parser = argparse.ArgumentParser() +parser.add_argument('--bank_path', type=str) +parser.add_argument('--user_path', type=str) +parser.add_argument('--account_path', type=str) +parser.add_argument('--table_name', type=str) +parser.add_argument('--row_id', type=int) +parser.add_argument('--column', type=str) +parser.add_argument('--value', type=str) +parser.add_argument('--delete_user', type=int) +parser.add_argument('--delete_bank', type=int) +parser.add_argument('--delete_account', type=int) +args = parser.parse_args() + + +#чтоб можно было выполнять несколько функций +if args.bank_path: + api.add_bank_by_file(args.bank_path) +if args.account_path: + api.add_account_by_file(args.account_path) +if args.user_path: + api.add_user_by_file(args.user_path) +if args.table_name and args.row_id and args.column and args.value: + api.change_something(args.table_name, args.row_id, args.column, args.value) +if args.delete_user: + print(api.delete_row_from_user(args.delete_user)) +if args.delete_account: + print(api.delete_row_from_account(args.delete_account)) +if args.delete_bank: + print(api.delete_row_from_bank(args.delete_bank)) + + + +#api.add_account_by_file(args.account_path) +""" +parser = argparse.ArgumentParser() +#group = parser.add_mutually_exclusive_group() +parser.add_argument('--bankname', type=str, nargs="+") +parser.add_argument('--user_full_name', type=str, nargs="+") +parser.add_argument('--birthday', type=str, nargs="+") +parser.add_argument('--accounts', type=str, nargs="+") +#group.add_argument('--csvpath', type=str) +args = parser.parse_args() + +if args.bankname: + print(args.bankname) + "python main.py --bankname TestBank " + print(api.add_bank(args.bankname)) +elif args.user_full_name and args.birthday and args.accounts : + print(api.add_user(args.user_full_name, args.birthday, args.accounts)) + +test = ['Lena Zhelezo', '13.01.2005', 1] +print(api.add_user(test[0], test[1], test[2])) +""" + diff --git a/hw_4/user.csv b/hw_4/user.csv new file mode 100644 index 0000000..0476ef4 --- /dev/null +++ b/hw_4/user.csv @@ -0,0 +1,6 @@ +user_name,birthday,accounts +John Doe,1990-05-05,0 +Jane Smith,1985-10-15,0 +Michael Johnson,1978-03-20,0 +Emily Brown,1995-08-08,0 +Alex Rodriguez,1982-12-30,0 \ No newline at end of file From a4786ef7b68a5677b589d9e06f152ab32469870e Mon Sep 17 00:00:00 2001 From: ValeZh Date: Mon, 6 May 2024 21:29:28 +0300 Subject: [PATCH 03/11] part 1 done make it more beauty tommorow and start part 3 --- hw_4/api.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++--- hw_4/bank.db | Bin 36864 -> 36864 bytes hw_4/main.py | 12 +++++-- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/hw_4/api.py b/hw_4/api.py index 361a017..ad91509 100644 --- a/hw_4/api.py +++ b/hw_4/api.py @@ -1,7 +1,7 @@ import sqlite3 import requests import csv - +import datetime def db_connection(func): """ @@ -45,7 +45,7 @@ def wrapper(*args, **kwargs): return wrapper -def get_data(): +def get_curency_data(): api_key = 'fca_live_bYExvWei85B5olF2iitYB6HunpYb8RYaZAw29iWt' url = f'https://api.freecurrencyapi.com/v1/latest?apikey={api_key}' response = requests.get(url) @@ -175,10 +175,87 @@ def add_user_by_file(path): data = merge_dicts(read_csv_to_dict(path)) add_user(data["user_name"], data["birthday"], data["accounts"]) + +def convert_currency(currency_values, orig_currency, conv_currency, amount): + return round((amount/currency_values[orig_currency]) * currency_values[conv_currency], 2) + + @db_connection -def transfer_money(c, bank_sender_name, account_sender_id, bank_receiver_name, account_receiver_id, sent_currency, sent_amount): - c.execute("SELECT Amount FROM Account WHERE id = ?", (account_sender_id,)) - acc_amount = c.fetchone()[0] +def transfer_money(c, sender_id, receiver_id, sent_currency, sent_amount, transfer_time=0): + # берем ключи из апишки с курсом валют (подсказка 'USD': 1) + currency_dict = get_curency_data() + print() + #смотрим есть ли заданая валюта в дикте курса валют + if not (any(item == sent_currency for item in dict.keys(currency_dict))): + print('Error sent_currency') + return 'Error sent_currency' + print('valid current success') + + c.execute('''SELECT bank.name AS bank_name + FROM account + INNER JOIN bank ON account.bank_id = bank.id + WHERE account.id = ?''', (sender_id,)) + + bank_sender_name = c.fetchone()[0] + c.execute('''SELECT bank.name AS bank_name + FROM account + INNER JOIN bank ON account.bank_id = bank.id + WHERE account.id = ?''', (receiver_id,)) + bank_receiver_name = c.fetchone()[0] + + print(bank_sender_name) + print(bank_receiver_name) + print('select bank success') + + c.execute("SELECT Amount FROM Account WHERE id IN (? , ?)", (sender_id, receiver_id,)) + result = c.fetchall() + sender_amount = result[0][0] + receiver_amount = result[1][0] + print('select amount success') + + c.execute("SELECT Currency From Account WHERE id IN (?, ?)", (sender_id, receiver_id,)) + result = c.fetchall() + sender_currency = result[0][0] + receiver_currency = result[1][0] + print('select Currency success') + + sent_am_in_receiver_cur = sent_amount + sent_am_in_sender_cur = sent_amount + sender_am_in_sent_cur = 0 + receiver_am_in_sent_cur = 0 + #вынести в функцию + if sender_currency != sent_currency: + sender_am_in_sent_cur = convert_currency(currency_dict, sender_currency, sent_currency, sender_amount) + print('sender_am_in_sent_cur', sender_am_in_sent_cur) + sent_am_in_sender_cur = convert_currency(currency_dict, sent_currency, sender_currency, sent_amount) + if sender_am_in_sent_cur < sent_amount: + print('not enough money in the account') + return 'not enough money in the account' + + + if receiver_currency != sent_currency: + sent_am_in_receiver_cur = convert_currency(currency_dict, sent_currency, receiver_currency, sent_amount) + print(sent_am_in_receiver_cur) + + + if transfer_time == 0: + transfer_time = datetime.datetime.today() + + print(sender_amount) + print(sent_am_in_sender_cur) + new_sender_amount = sender_amount - sent_am_in_sender_cur + print("new_sender_amount", new_sender_amount) + new_receiver_amount = receiver_amount + sent_am_in_receiver_cur + print("new_receiver_amount",new_receiver_amount) + + change_something('Account', sender_id, 'amount', new_sender_amount) + change_something('Account', receiver_id, 'amount', new_receiver_amount) + + c.execute("INSERT INTO BankTransaction(bank_sender_name, account_sender_id, bank_receiver_name, account_receiver_id, sent_currency, sent_amount, datetime) VALUES(?,?,?,?,?,?,?)", + (bank_sender_name, sender_id, bank_receiver_name, receiver_id, sent_currency, sent_amount, transfer_time,)) + + return 'success' + # узнать кол во дененег и валюту у человека на акаунте # если валюта у отправителя и получателя разные то конвертировать валюту отправителя и получателя и сохранить в переменных # сравнивать с отправляемой если меньше уходить из функции diff --git a/hw_4/bank.db b/hw_4/bank.db index 627b18d9b986a89cae615ec94838f7c96d4bb4fb..7671c619ffbda3d2e7be66865e6213c36f110e47 100644 GIT binary patch delta 276 zcmZozz|^pSX@WGP!bBNoMum+DOY}LI_-8TjU*?~+S%y-uX+p+|atPRit7{SKKvO>%O f8)ME2bdf_h<4ho!HF-#q$XvSSeTocni#V*4Gm&en7pN4n?;_HlVS7YdRYMgcK0G+ diff --git a/hw_4/main.py b/hw_4/main.py index e7c3004..01e01e0 100644 --- a/hw_4/main.py +++ b/hw_4/main.py @@ -14,9 +14,15 @@ parser.add_argument('--delete_user', type=int) parser.add_argument('--delete_bank', type=int) parser.add_argument('--delete_account', type=int) +parser.add_argument('--sender_id', type=int) +parser.add_argument('--receiver_id', type=int) +parser.add_argument('--sent_currency', type=str) +parser.add_argument('--sent_amount', type=int) +parser.add_argument('--time', type=str) args = parser.parse_args() + #чтоб можно было выполнять несколько функций if args.bank_path: api.add_bank_by_file(args.bank_path) @@ -32,8 +38,10 @@ print(api.delete_row_from_account(args.delete_account)) if args.delete_bank: print(api.delete_row_from_bank(args.delete_bank)) - - +if args.sender_id and args.receiver_id and args.sent_currency and args.sent_amount: + api.transfer_money(args.sender_id, args.receiver_id, args.sent_currency, args.sent_amount) +if args.sender_id and args.receiver_id and args.sent_currency and args.sent_amount and args.time: + api.transfer_money(args.sender_id, args.receiver_id, args.sent_currency, args.sent_amount, args.time) #api.add_account_by_file(args.account_path) """ From 02968f44cd53a67b1fde9c76547151db4d52c708 Mon Sep 17 00:00:00 2001 From: ValeZh Date: Tue, 7 May 2024 17:08:51 +0300 Subject: [PATCH 04/11] part 2/3 done improved transfer_money make comments --- hw_4/api.py | 142 +++++++++++++++++++++-------------------------- hw_4/bank.db | Bin 36864 -> 36864 bytes hw_4/validate.py | 44 +++++++++++++++ 3 files changed, 106 insertions(+), 80 deletions(-) create mode 100644 hw_4/validate.py diff --git a/hw_4/api.py b/hw_4/api.py index ad91509..1a5b53c 100644 --- a/hw_4/api.py +++ b/hw_4/api.py @@ -1,7 +1,8 @@ import sqlite3 import requests import csv -import datetime +import validate + def db_connection(func): """ @@ -45,6 +46,7 @@ def wrapper(*args, **kwargs): return wrapper +# получает дикт из валют и их значений относительно доллара def get_curency_data(): api_key = 'fca_live_bYExvWei85B5olF2iitYB6HunpYb8RYaZAw29iWt' url = f'https://api.freecurrencyapi.com/v1/latest?apikey={api_key}' @@ -59,7 +61,7 @@ def get_curency_data(): return None -# разобраться и переделать +# читает цсв файл переобразовывая в дикт def read_csv_to_dict(file_path): with open(file_path, 'r') as file: reader = csv.DictReader(file) @@ -67,6 +69,7 @@ def read_csv_to_dict(file_path): return data_dict +# преобразует лист диктов в дикт листов def merge_dicts(dict_list): merged_dict = {} for d in dict_list: @@ -81,26 +84,22 @@ def merge_dicts(dict_list): # проверяет все ли массивы при ключах имеют одинаковую длинну +# эта функция сделана для заполнения базы данных с помощью командной строк +# при желании это можно реализовать def equal_length_lists(d): lengths = {len(lst) for lst in d.values()} return len(lengths) == 1 +# заполняет таблицу банк @db_connection def add_bank(c, bank_data): - # Add bank to the database for bank in bank_data: c.execute("INSERT INTO Bank(name) VALUES(?)", (bank,)) return "Bank added successfully." -@db_connection -def read_data_from_file(previous_output): - with open(previous_output, "r", encoding="utf-8") as file: - print("read data success") - return list(csv.DictReader(file)) - - +# заполняет таблицу юзер @db_connection def add_user(c, user_name, birthday, accounts): for i in range(len(user_name)): @@ -112,16 +111,17 @@ def add_user(c, user_name, birthday, accounts): return 'success' +# заполняет таблицу аккаунт @db_connection def add_account_to_db(c, user_id, user_type, acc_numb, bank_id, currency, amount, status): for i in range(len(user_id)): - c.execute("INSERT INTO Account(user_id, type, account_number, bank_id, currency, amount, status) VALUES(?,?,?,?,?,?,?)", - (user_id[i], user_type[i], acc_numb[i], bank_id[i], currency[i], amount[i], status[i])) + c.execute('''INSERT INTO Account(user_id, type, account_number, bank_id, currency, amount, status) + VALUES(?,?,?,?,?,?,?)''', + (user_id[i], user_type[i], acc_numb[i], bank_id[i], currency[i], amount[i], status[i])) # Получаем количество счетов для текущего пользователя c.execute("SELECT COUNT(*) FROM Account WHERE user_id = ?", (user_id[i],)) numb_of_acc = c.fetchone()[0] # Извлекаем значение из курсора - # забабахать сюда функцию - c.execute("UPDATE User SET Accounts = ? WHERE id = ?", (numb_of_acc, user_id[i])) + change_something("User", "Accounts", numb_of_acc, user_id[i]) return 'success' @@ -139,20 +139,22 @@ def delete_row_from_account(c, row_id): @db_connection def delete_row_from_user(c, row_id): - # забабахать сюда функцию - c.execute(f"DELETE FROM Account WHERE User_id = ?", (row_id, )) + # в идеале базы данных должны быть связаны между собой по айди + # поэтому чтоб успешно удалить юзера надо еще удалить все записи связаные с ним + # это же и касается банка + delete_row_from_account(row_id) c.execute(f"DELETE FROM User WHERE id = ?", (row_id,)) return 'success' @db_connection def delete_row_from_bank(c, row_id): - # забабахать сюда функцию - c.execute(f"DELETE FROM Account WHERE Bank_id = ?", (row_id,)) + delete_row_from_account(row_id) c.execute(f"DELETE FROM Bank WHERE id = ?", (row_id,)) return 'success' +# она просто очищает таблицы в бд @db_connection def clear_table(c, table_name): c.execute("DELETE * FROM {}".format(table_name)) @@ -161,7 +163,8 @@ def clear_table(c, table_name): def add_account_by_file(path): data = merge_dicts(read_csv_to_dict(path)) - add_account_to_db(data["user_id"], data["type"], data["account_number"], data["bank_id"], data["currency"], data["amount"], data["status"]) + add_account_to_db(data["user_id"], data["type"], data["account_number"], + data["bank_id"], data["currency"], data["amount"], data["status"]) return "success" @@ -181,86 +184,65 @@ def convert_currency(currency_values, orig_currency, conv_currency, amount): @db_connection -def transfer_money(c, sender_id, receiver_id, sent_currency, sent_amount, transfer_time=0): +def get_bankname(c, bank_id): + c.execute('''SELECT bank.name AS bank_name + FROM account + INNER JOIN bank ON account.bank_id = bank.id + WHERE account.id = ?''', (bank_id,)) + return c.fetchone()[0] + + +@db_connection +def get_data_from_table(c, table_name, row_name, row_id): + c.execute(f"SELECT {table_name} FROM {row_name} WHERE id = ? ", (row_id,)) + return c.fetchone()[0] + + +@db_connection +def transfer_money(c, sender_id, receiver_id, sent_currency, sent_amount, transfer_time=None): # берем ключи из апишки с курсом валют (подсказка 'USD': 1) currency_dict = get_curency_data() - print() - #смотрим есть ли заданая валюта в дикте курса валют - if not (any(item == sent_currency for item in dict.keys(currency_dict))): - print('Error sent_currency') - return 'Error sent_currency' + # смотрим есть ли заданая валюта в дикте курса валют + validate.validate_field_value('sent_currency', sent_currency, dict.keys(currency_dict)) print('valid current success') - c.execute('''SELECT bank.name AS bank_name - FROM account - INNER JOIN bank ON account.bank_id = bank.id - WHERE account.id = ?''', (sender_id,)) - - bank_sender_name = c.fetchone()[0] - c.execute('''SELECT bank.name AS bank_name - FROM account - INNER JOIN bank ON account.bank_id = bank.id - WHERE account.id = ?''', (receiver_id,)) - bank_receiver_name = c.fetchone()[0] - - print(bank_sender_name) - print(bank_receiver_name) - print('select bank success') - - c.execute("SELECT Amount FROM Account WHERE id IN (? , ?)", (sender_id, receiver_id,)) - result = c.fetchall() - sender_amount = result[0][0] - receiver_amount = result[1][0] - print('select amount success') - - c.execute("SELECT Currency From Account WHERE id IN (?, ?)", (sender_id, receiver_id,)) - result = c.fetchall() - sender_currency = result[0][0] - receiver_currency = result[1][0] - print('select Currency success') - + # вытаскиваем нужные данные для заполнения таблицы транзакций + bank_sender_name = get_bankname(sender_id) + bank_receiver_name = get_bankname(receiver_id) + sender_amount = get_data_from_table('Amount', 'Account', sender_id) + receiver_amount = get_data_from_table('Amount', 'Account', receiver_id) + sender_currency = get_data_from_table('Currency', 'Account', sender_id) + receiver_currency = get_data_from_table('Currency', 'Account', receiver_id) sent_am_in_receiver_cur = sent_amount sent_am_in_sender_cur = sent_amount - sender_am_in_sent_cur = 0 - receiver_am_in_sent_cur = 0 - #вынести в функцию + sender_am_in_sent_cur = sender_amount + + # проверяем валюты у отправителя if sender_currency != sent_currency: sender_am_in_sent_cur = convert_currency(currency_dict, sender_currency, sent_currency, sender_amount) print('sender_am_in_sent_cur', sender_am_in_sent_cur) sent_am_in_sender_cur = convert_currency(currency_dict, sent_currency, sender_currency, sent_amount) - if sender_am_in_sent_cur < sent_amount: - print('not enough money in the account') - return 'not enough money in the account' - - + # проверяем достаточно ли денег на счету + if sender_am_in_sent_cur <= sent_amount: + raise ValueError('not enough money in the account') + # проверяем валюты у получателя if receiver_currency != sent_currency: sent_am_in_receiver_cur = convert_currency(currency_dict, sent_currency, receiver_currency, sent_amount) - print(sent_am_in_receiver_cur) - - if transfer_time == 0: - transfer_time = datetime.datetime.today() + # проверяем наличие времени + transfer_time = validate.add_transaction_time(transfer_time) - print(sender_amount) - print(sent_am_in_sender_cur) new_sender_amount = sender_amount - sent_am_in_sender_cur - print("new_sender_amount", new_sender_amount) new_receiver_amount = receiver_amount + sent_am_in_receiver_cur - print("new_receiver_amount",new_receiver_amount) + # меняем значения суммы у юзеров change_something('Account', sender_id, 'amount', new_sender_amount) change_something('Account', receiver_id, 'amount', new_receiver_amount) - c.execute("INSERT INTO BankTransaction(bank_sender_name, account_sender_id, bank_receiver_name, account_receiver_id, sent_currency, sent_amount, datetime) VALUES(?,?,?,?,?,?,?)", - (bank_sender_name, sender_id, bank_receiver_name, receiver_id, sent_currency, sent_amount, transfer_time,)) + # заполняем таблицу + c.execute( + '''INSERT INTO BankTransaction(bank_sender_name, account_sender_id, bank_receiver_name, account_receiver_id, + sent_currency, sent_amount, datetime) VALUES(?,?,?,?,?,?,?)''', + (bank_sender_name, sender_id, bank_receiver_name, receiver_id, sent_currency, sent_amount, transfer_time,)) return 'success' - - # узнать кол во дененег и валюту у человека на акаунте - # если валюта у отправителя и получателя разные то конвертировать валюту отправителя и получателя и сохранить в переменных - # сравнивать с отправляемой если меньше уходить из функции - # при отправлении - # заполнить таблицу транзакций - # отнять у отправтеля деньги в таблице аккаунт - # прибавить деньги у получателя - diff --git a/hw_4/bank.db b/hw_4/bank.db index 7671c619ffbda3d2e7be66865e6213c36f110e47..ffd1fc7f01d660c644e021d962327104e2b5a52b 100644 GIT binary patch delta 90 zcmZozz|^pSX@WGP@ Date: Tue, 7 May 2024 18:32:36 +0300 Subject: [PATCH 05/11] part 2/3 done improved transfer_money make comments --- hw_4/api.py | 14 ++++++++------ hw_4/main.py | 15 +++++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/hw_4/api.py b/hw_4/api.py index 1a5b53c..159ea4e 100644 --- a/hw_4/api.py +++ b/hw_4/api.py @@ -103,8 +103,7 @@ def add_bank(c, bank_data): @db_connection def add_user(c, user_name, birthday, accounts): for i in range(len(user_name)): - name = str.split(user_name[i])[0] - surname = str.split(user_name[i])[1] + name, surname = validate.validate_user_full_name(user_name[i]) c.execute("INSERT INTO User(name,surname,birth_day,accounts) VALUES(?,?,?,?)", (name, surname, f"{birthday[i]}", accounts[i],)) print(f"user {name} {surname} added success") @@ -115,19 +114,23 @@ def add_user(c, user_name, birthday, accounts): @db_connection def add_account_to_db(c, user_id, user_type, acc_numb, bank_id, currency, amount, status): for i in range(len(user_id)): + # acc_numb = validate.validate_account_number(acc_numb[i]) c.execute('''INSERT INTO Account(user_id, type, account_number, bank_id, currency, amount, status) VALUES(?,?,?,?,?,?,?)''', (user_id[i], user_type[i], acc_numb[i], bank_id[i], currency[i], amount[i], status[i])) # Получаем количество счетов для текущего пользователя + c.execute("SELECT COUNT(*) FROM Account WHERE user_id = ?", (user_id[i],)) numb_of_acc = c.fetchone()[0] # Извлекаем значение из курсора - change_something("User", "Accounts", numb_of_acc, user_id[i]) + #оказалось что это с функцией по какой то причине не работает оставлю так + c.execute("UPDATE User SET Accounts = ? WHERE id = ?", (numb_of_acc, user_id[i])) + return 'success' @db_connection def change_something(c, table_name, row_id, column, value): - c.execute(f"UPDATE {table_name} SET {column} = ? WHERE id = ?", (value, row_id)) + c.execute(f"UPDATE {table_name} SET {column} = ? WHERE id = ?", (value, row_id, )) return 'success' @@ -157,10 +160,9 @@ def delete_row_from_bank(c, row_id): # она просто очищает таблицы в бд @db_connection def clear_table(c, table_name): - c.execute("DELETE * FROM {}".format(table_name)) + c.execute(f"DELETE FROM {table_name}") return 'success' - def add_account_by_file(path): data = merge_dicts(read_csv_to_dict(path)) add_account_to_db(data["user_id"], data["type"], data["account_number"], diff --git a/hw_4/main.py b/hw_4/main.py index 01e01e0..ff9bd15 100644 --- a/hw_4/main.py +++ b/hw_4/main.py @@ -19,19 +19,22 @@ parser.add_argument('--sent_currency', type=str) parser.add_argument('--sent_amount', type=int) parser.add_argument('--time', type=str) +parser.add_argument('--clear_table', type=str) args = parser.parse_args() #чтоб можно было выполнять несколько функций if args.bank_path: - api.add_bank_by_file(args.bank_path) + print(api.add_bank_by_file(args.bank_path)) if args.account_path: - api.add_account_by_file(args.account_path) + print(api.add_account_by_file(args.account_path)) if args.user_path: - api.add_user_by_file(args.user_path) + print(api.add_user_by_file(args.user_path)) if args.table_name and args.row_id and args.column and args.value: - api.change_something(args.table_name, args.row_id, args.column, args.value) + print(api.change_something(args.table_name, args.row_id, args.column, args.value)) +if args.clear_table: + print(api.clear_table(args.clear_table)) if args.delete_user: print(api.delete_row_from_user(args.delete_user)) if args.delete_account: @@ -39,9 +42,9 @@ if args.delete_bank: print(api.delete_row_from_bank(args.delete_bank)) if args.sender_id and args.receiver_id and args.sent_currency and args.sent_amount: - api.transfer_money(args.sender_id, args.receiver_id, args.sent_currency, args.sent_amount) + print(api.transfer_money(args.sender_id, args.receiver_id, args.sent_currency, args.sent_amount)) if args.sender_id and args.receiver_id and args.sent_currency and args.sent_amount and args.time: - api.transfer_money(args.sender_id, args.receiver_id, args.sent_currency, args.sent_amount, args.time) + print(api.transfer_money(args.sender_id, args.receiver_id, args.sent_currency, args.sent_amount, args.time)) #api.add_account_by_file(args.account_path) """ From 017f8128b084371689aa31165c890544dd08816e Mon Sep 17 00:00:00 2001 From: ValeZh Date: Tue, 7 May 2024 19:16:19 +0300 Subject: [PATCH 06/11] fixed some bugs --- hw_4/api.py | 2 +- hw_4/validate.py | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/hw_4/api.py b/hw_4/api.py index 159ea4e..b347a1b 100644 --- a/hw_4/api.py +++ b/hw_4/api.py @@ -114,7 +114,7 @@ def add_user(c, user_name, birthday, accounts): @db_connection def add_account_to_db(c, user_id, user_type, acc_numb, bank_id, currency, amount, status): for i in range(len(user_id)): - # acc_numb = validate.validate_account_number(acc_numb[i]) + acc_numb[i] = validate.validate_account_number(acc_numb[i]) c.execute('''INSERT INTO Account(user_id, type, account_number, bank_id, currency, amount, status) VALUES(?,?,?,?,?,?,?)''', (user_id[i], user_type[i], acc_numb[i], bank_id[i], currency[i], amount[i], status[i])) diff --git a/hw_4/validate.py b/hw_4/validate.py index 388ef94..b483ae2 100644 --- a/hw_4/validate.py +++ b/hw_4/validate.py @@ -17,22 +17,23 @@ def validate_field_value(field, value, allowed_values): raise ValueError("error: not allowed value {} for field {}!".format(value, field)) -# Функция для валидации и преобразования номера счета def validate_account_number(account_number): # Замена специальных символов на тире account_number = re.sub(r'[#%_?&]', '-', account_number) # Проверка на количество символов - if len(account_number) != 18: - raise ValueError("error: too little/many chars! depend on amount") + if len(account_number) <18: + raise ValueError("error: too little") + if len(account_number) > 18: + raise ValueError("error: many chars") # Проверка формата if not account_number.startswith("ID--"): - raise ValueError("Error: wrong format!") + raise ValueError("error: wrong format") # Проверка на наличие нужного паттерна - if not re.match(r'ID--[a-zA-Z]{1,3}-\d+-[a-zA-Z0-9]+-\d+', account_number): - raise ValueError("Error: broken ID!") + if not re.match(r'ID--[a-zA-Z]{1,3}-\d+-', account_number): + raise ValueError("an error: broken ID") return account_number @@ -42,3 +43,5 @@ def add_transaction_time(transaction_time): if not transaction_time: transaction_time = datetime.now() return transaction_time + + From b8fa4d50c9e39b34fb5333ce64d0f99495415d4e Mon Sep 17 00:00:00 2001 From: ValeZh Date: Tue, 7 May 2024 19:18:01 +0300 Subject: [PATCH 07/11] fixed some bugs q --- hw_4/account.csv | 10 +++++----- hw_4/bank.db | Bin 36864 -> 36864 bytes hw_4/user.csv | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw_4/account.csv b/hw_4/account.csv index c215712..6a23ee4 100644 --- a/hw_4/account.csv +++ b/hw_4/account.csv @@ -1,6 +1,6 @@ user_id,type,account_number,bank_id,currency,amount,status -1,credit,123456,3,USD,1000,gold -3,debit,987654,2,USD,500,silver -5,credit,234567,5,EUR,800,platinum -2,debit,876543,4,CAD,1200,gold -4,credit,345678,1,USD,1500,silver \ No newline at end of file +1,credit,ID--dcd-123568744-,3,USD,1000,gold +3,debit,ID--xyz-987654-uvw,2,USD,500,silver +5,credit,ID--qwe-456789-asd,5,EUR,800,platinum +2,debit,ID--z1-654321-xyz,4,CAD,1200,gold +4,credit,ID--jkl-987654-mno,1,USD,1500,silver \ No newline at end of file diff --git a/hw_4/bank.db b/hw_4/bank.db index ffd1fc7f01d660c644e021d962327104e2b5a52b..7cd98c382d62507d4a40671965f7a529fa4cd2c7 100644 GIT binary patch delta 486 zcmZozz|^pSX@WGP=|mZ4M$?T6OZ3?o`HwU3AK$E)u!?`;1Yss~#>sQ+)fCMY3@xmT z4XupK^^7dcj4jQ185kH?`3o8NpYxyLU&B9Pvw(v=P=nIsLjPzMNhUUi$rt>^HN_d( z7(|5?Ilb~T@?7#$4J|DVbPY^_hzqR!0t5dA{+s;o`G0H{2-wa)F@SUOg?M=}4rWnC zuf)7mCU#~~uvW0@&8!Kp_!T*s#TkQhGfOg<*qDVmfo6gn!pvX9z<-&434alP>1Kg~ z_k5El)XVX)^~Y#@JyejBSdy7nnmbv$UWUEvRT>CP_N!N^H(=&uV3agu6lRiTO)g4J z$t>}7(bX+1Pt`RsH8Z!c)J-f-VRa1+Vpf0|q00o+Ar8_Z$()j!1kq4YS*2@fVQyw> zqFY*4&J-H#!uX{)Gp8)INSl$9ffH)BV$uDc?)wB6J2JYdgd4D`8g>d tKQi<0Vc>tozX#}-tD6NH*6_QCF&i>sI*S=5jApqgvmqx)HQW-g9RQ@tfXe^? delta 539 zcmZozz|^pSX@WGP@fvK(mP_coPv4NGLv7V8+rJ{8U3rO9QYurjrZ(qgfaj7)&N#@E6wvG9*QX6*;}~GxAWBaq+(g z8h@OD{{sI_{^R_QHwy%8=jY^L7Ka!)`9i$B7*MmIS7Kf&6Oh3HG6Ae{H#`*NId;n(SAv zB3G7L#DAYbnp08|7!ab#MX4#7C5A@ECZ=Z0p}{Vb|JTVSu{;DSuP(?*EXm9(%~fRL zWMC8rsg`6;NlnTuv9vHZGc{oXs%HFBoS6eO5a=3390oGKNYBqn;o`pvbloWi{%`yb z_)qb_-Yn3thJRuJpBWdkBqPXfa|>3WA>3e-jafjVU?-U~gP2eYIhiFnAua^~I(&h^ diff --git a/hw_4/user.csv b/hw_4/user.csv index 0476ef4..9349b6c 100644 --- a/hw_4/user.csv +++ b/hw_4/user.csv @@ -1,5 +1,5 @@ user_name,birthday,accounts -John Doe,1990-05-05,0 +John1!! Doe,1990-05-05,0 Jane Smith,1985-10-15,0 Michael Johnson,1978-03-20,0 Emily Brown,1995-08-08,0 From 4004f9116171c3b8e9c6ac0ed94ff95281f778a2 Mon Sep 17 00:00:00 2001 From: ValeZh Date: Tue, 7 May 2024 19:18:16 +0300 Subject: [PATCH 08/11] fixed some bugsee --- hw_4/example.csv | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 hw_4/example.csv diff --git a/hw_4/example.csv b/hw_4/example.csv new file mode 100644 index 0000000..1cd6798 --- /dev/null +++ b/hw_4/example.csv @@ -0,0 +1,5 @@ +full_name,birth_day,accounts +John Doe,1990-05-15,3 +Alice Smith,1985-10-20,5 +Michael Johnson,1978-03-25,2 +Emily Brown,1992-07-12,4 From 719778aef1b3bcd3c32d1f3561ceadf97c0ae93e Mon Sep 17 00:00:00 2001 From: ValeZh Date: Sat, 18 May 2024 00:50:39 +0300 Subject: [PATCH 09/11] remake 4 start to make 5 later make code better --- hw_4/api.py | 408 ++++++++++++++++++++++++--------------- hw_4/initial_db_setup.py | 25 ++- hw_4/main.py | 118 +++++------ hw_4/validate.py | 31 +-- 4 files changed, 331 insertions(+), 251 deletions(-) diff --git a/hw_4/api.py b/hw_4/api.py index b347a1b..e03ff0e 100644 --- a/hw_4/api.py +++ b/hw_4/api.py @@ -1,72 +1,44 @@ -import sqlite3 import requests import csv import validate +from db_con_decor import db_connection +import os +from dotenv import load_dotenv, find_dotenv +import logging +from consts import URL +from datetime import datetime +import random +formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(name)s:%(message)s') +my_logger = logging.getLogger('CustomLogger') +my_handler = logging.FileHandler('file.log') +my_handler.setFormatter(formatter) +my_logger.setLevel(logging.INFO) +my_logger.addHandler(my_handler) -def db_connection(func): - """ - Декоратор для установки соединения с базой данных и его закрытия после выполнения функции. - - Args: - func (function): Функция базы данных, которая будет выполнена. - - Returns: - function: Вложенная функция-обертка, которая обеспечивает соединение и закрытие. - """ - def wrapper(*args, **kwargs): - """ - Вложенная функция-обертка, обеспечивающая соединение и закрытие. - - Args: - *args: Позиционные аргументы, переданные в функцию. - **kwargs: Именованные аргументы, переданные в функцию. - - Returns: - any: Результат выполнения оригинальной функции. - """ - # Устанавливаем соединение с базой данных - conn = sqlite3.connect('bank.db') - # Создаем объект курсора - c = conn.cursor() - try: - # Вызываем оригинальную функцию, передавая ей курсор и все переданные аргументы - result = func(c, *args, **kwargs) - except Exception as e: - # Обрабатываем ошибки и логируем их - print(f"Error: {str(e)}") - result = None - finally: - # Фиксируем изменения в базе данных и закрываем соединение - conn.commit() - conn.close() - # Возвращаем результат выполнения оригинальной функции - return result - # Возвращаем вложенную функцию-обертку в качестве декоратора - return wrapper +load_dotenv(find_dotenv()) # получает дикт из валют и их значений относительно доллара def get_curency_data(): - api_key = 'fca_live_bYExvWei85B5olF2iitYB6HunpYb8RYaZAw29iWt' - url = f'https://api.freecurrencyapi.com/v1/latest?apikey={api_key}' - response = requests.get(url) - if response.status_code == 200: + # .env + # dotenv lib + + response = requests.get(URL.format(os.getenv('API_KEY'))) + if response.status_code == requests.codes.ok: data = response.json() - print("data_get successfully") - print(data['data']) + #сделать логами + my_logger.info("data_get successfully") + my_logger.info(data['data']) return data['data'] - else: - print("data_get failure") - return None + my_logger.error("data_get failure") + return None # читает цсв файл переобразовывая в дикт def read_csv_to_dict(file_path): with open(file_path, 'r') as file: - reader = csv.DictReader(file) - data_dict = [row for row in reader] - return data_dict + return list(csv.DictReader(file)) # преобразует лист диктов в дикт листов @@ -91,160 +63,276 @@ def equal_length_lists(d): return len(lengths) == 1 +def unpack_data(data): + keys = list(data.keys()) + return [data[key] for key in keys] if len(keys) > 1 else data[keys[0]] + +#{ filler_date: [{}, {} ]} +#{ "row1": {}, "row2": {} } # заполняет таблицу банк @db_connection -def add_bank(c, bank_data): - for bank in bank_data: - c.execute("INSERT INTO Bank(name) VALUES(?)", (bank,)) - return "Bank added successfully." +def add_bank(cur, **kwargs): + data = unpack_data(kwargs) + my_logger.info(data) + # распаковать лист диктов + my_logger.info(data) + cur.executemany("INSERT INTO Bank(name) VALUES(:Name)", data) # :param_name, :param_name2 + my_logger.info("Bank added successfully.") # заполняет таблицу юзер @db_connection -def add_user(c, user_name, birthday, accounts): - for i in range(len(user_name)): - name, surname = validate.validate_user_full_name(user_name[i]) - c.execute("INSERT INTO User(name,surname,birth_day,accounts) VALUES(?,?,?,?)", - (name, surname, f"{birthday[i]}", accounts[i],)) - print(f"user {name} {surname} added success") - return 'success' - - +def add_user(cur, **kwargs): + data = unpack_data(kwargs) + my_logger.info(data) + for i in data: + i["name"] = validate.validate_user_full_name(i["user_name"])[0] + i["surname"] = validate.validate_user_full_name(i["user_name"])[1] + cur.executemany("INSERT INTO User(name,surname,birth_day,accounts) VALUES(:name ,:surname,:birthday,:accounts)", + data) + my_logger.info("User added successfully.") + +def unpack_to_string(data): + result = '' + for tup in data: + for item in tup: + result += str(item) + ',' + return result.rstrip(',') +# # заполняет таблицу аккаунт -@db_connection -def add_account_to_db(c, user_id, user_type, acc_numb, bank_id, currency, amount, status): - for i in range(len(user_id)): - acc_numb[i] = validate.validate_account_number(acc_numb[i]) - c.execute('''INSERT INTO Account(user_id, type, account_number, bank_id, currency, amount, status) - VALUES(?,?,?,?,?,?,?)''', - (user_id[i], user_type[i], acc_numb[i], bank_id[i], currency[i], amount[i], status[i])) - # Получаем количество счетов для текущего пользователя - - c.execute("SELECT COUNT(*) FROM Account WHERE user_id = ?", (user_id[i],)) - numb_of_acc = c.fetchone()[0] # Извлекаем значение из курсора - #оказалось что это с функцией по какой то причине не работает оставлю так - c.execute("UPDATE User SET Accounts = ? WHERE id = ?", (numb_of_acc, user_id[i])) - - return 'success' +def set_accounts(cur, data): + for i in data: + cur.execute("SELECT id FROM Account WHERE user_id = ?", (i["user_id"],)) + numb_of_acc = cur.fetchall() # Извлекаем значение из курсора + account_str = unpack_to_string(numb_of_acc) + my_logger.info(account_str) + cur.execute("UPDATE User SET Accounts = ? WHERE id = ?", (account_str, i["user_id"],)) @db_connection -def change_something(c, table_name, row_id, column, value): - c.execute(f"UPDATE {table_name} SET {column} = ? WHERE id = ?", (value, row_id, )) - return 'success' - - -@db_connection -def delete_row_from_account(c, row_id): - c.execute(f"DELETE FROM Account WHERE id = ?", (row_id,)) - return 'success' - - +def add_account(cur, **kwargs): + data = unpack_data(kwargs) + my_logger.info(data) + validate.valid_acc(data) + cur.executemany('''INSERT INTO Account(user_id, type, account_number, bank_id, currency, amount, status) + VALUES(:user_id,:type,:account_number,:bank_id,:currency,:amount,:status)''', + data) + set_accounts(cur, data) + my_logger.info("account added successfully.") + +#update row in bd @db_connection -def delete_row_from_user(c, row_id): - # в идеале базы данных должны быть связаны между собой по айди - # поэтому чтоб успешно удалить юзера надо еще удалить все записи связаные с ним - # это же и касается банка - delete_row_from_account(row_id) - c.execute(f"DELETE FROM User WHERE id = ?", (row_id,)) - return 'success' +def update_row(c, table_name, row_id, column, value): + c.execute(f"UPDATE {table_name} SET {column} = ? WHERE id = ?", (value, row_id, )) + return "success" @db_connection -def delete_row_from_bank(c, row_id): - delete_row_from_account(row_id) - c.execute(f"DELETE FROM Bank WHERE id = ?", (row_id,)) - return 'success' +def delete_row(cur, row_id, fnc): + match fnc: + case "User": + cur.execute("DELETE FROM Account WHERE user_id = ?", (row_id,)) + cur.execute("DELETE FROM User WHERE id = ?", (row_id,)) + case "Bank": + cur.execute("DELETE FROM Account WHERE bank_id = ?", (row_id,)) + cur.execute("DELETE FROM Bank WHERE id = ?", (row_id,)) + case "Account": + cur.execute("DELETE FROM Account WHERE id = ?", (row_id,)) + my_logger.info(f"{fnc} delete successfully.") + return "success" # она просто очищает таблицы в бд @db_connection -def clear_table(c, table_name): - c.execute(f"DELETE FROM {table_name}") +def clear_table(cur, table_name): + cur.execute(f"DELETE FROM {table_name}") return 'success' -def add_account_by_file(path): - data = merge_dicts(read_csv_to_dict(path)) - add_account_to_db(data["user_id"], data["type"], data["account_number"], - data["bank_id"], data["currency"], data["amount"], data["status"]) - return "success" - - -def add_bank_by_file(path): - data = merge_dicts(read_csv_to_dict(path)) - add_bank(data['Name']) - return "success" - -def add_user_by_file(path): - data = merge_dicts(read_csv_to_dict(path)) - add_user(data["user_name"], data["birthday"], data["accounts"]) +def add_table_by_file(path, table_name): + data = read_csv_to_dict(path) + match table_name: + case "Bank": + add_bank(table_filler=data) + case "User": + add_user(table_filler=data) + case "Account": + add_account(table_filler=data) def convert_currency(currency_values, orig_currency, conv_currency, amount): - return round((amount/currency_values[orig_currency]) * currency_values[conv_currency], 2) - + return round((amount / currency_values[orig_currency]) * currency_values[conv_currency], 2) +# достать банкнейм @db_connection -def get_bankname(c, bank_id): - c.execute('''SELECT bank.name AS bank_name - FROM account - INNER JOIN bank ON account.bank_id = bank.id - WHERE account.id = ?''', (bank_id,)) - return c.fetchone()[0] +def get_bankname(cur, id_user): + bank_id = get_data_from_table(table_name ="Account", row_name="bank_id",row_id= id_user) + my_logger.info("get_bankname successfully.") + return get_data_from_table(table_name = "Bank",row_name="name", row_id = bank_id) @db_connection -def get_data_from_table(c, table_name, row_name, row_id): - c.execute(f"SELECT {table_name} FROM {row_name} WHERE id = ? ", (row_id,)) - return c.fetchone()[0] +def get_data_from_table(cur, row_name, table_name, row_id): + cur.execute(f"SELECT {row_name} FROM {table_name} WHERE id = ? ", (row_id,)) + return cur.fetchone()[0] @db_connection -def transfer_money(c, sender_id, receiver_id, sent_currency, sent_amount, transfer_time=None): - # берем ключи из апишки с курсом валют (подсказка 'USD': 1) +def transfer_money(c, sender_id, receiver_id, sent_amount, transfer_time=None): currency_dict = get_curency_data() - # смотрим есть ли заданая валюта в дикте курса валют - validate.validate_field_value('sent_currency', sent_currency, dict.keys(currency_dict)) - print('valid current success') - + my_logger.info('valid current success') # вытаскиваем нужные данные для заполнения таблицы транзакций bank_sender_name = get_bankname(sender_id) - bank_receiver_name = get_bankname(receiver_id) - sender_amount = get_data_from_table('Amount', 'Account', sender_id) - receiver_amount = get_data_from_table('Amount', 'Account', receiver_id) - sender_currency = get_data_from_table('Currency', 'Account', sender_id) - receiver_currency = get_data_from_table('Currency', 'Account', receiver_id) - sent_am_in_receiver_cur = sent_amount + bank_receiver_name = get_bankname( receiver_id) + sender_amount = get_data_from_table("Amount", "Account", sender_id) + receiver_amount = get_data_from_table("Amount", "Account", receiver_id) + sender_currency = get_data_from_table("Currency", "Account", sender_id) + receiver_currency = get_data_from_table("Currency", "Account", receiver_id) sent_am_in_sender_cur = sent_amount - sender_am_in_sent_cur = sender_amount - - # проверяем валюты у отправителя - if sender_currency != sent_currency: - sender_am_in_sent_cur = convert_currency(currency_dict, sender_currency, sent_currency, sender_amount) - print('sender_am_in_sent_cur', sender_am_in_sent_cur) - sent_am_in_sender_cur = convert_currency(currency_dict, sent_currency, sender_currency, sent_amount) - # проверяем достаточно ли денег на счету - if sender_am_in_sent_cur <= sent_amount: + + if sender_amount <= sent_amount: raise ValueError('not enough money in the account') - # проверяем валюты у получателя - if receiver_currency != sent_currency: - sent_am_in_receiver_cur = convert_currency(currency_dict, sent_currency, receiver_currency, sent_amount) + if receiver_currency != sender_currency: + sent_am_in_sender_cur = convert_currency(currency_dict, receiver_currency, sender_currency, sent_amount) # проверяем наличие времени transfer_time = validate.add_transaction_time(transfer_time) new_sender_amount = sender_amount - sent_am_in_sender_cur - new_receiver_amount = receiver_amount + sent_am_in_receiver_cur + new_receiver_amount = receiver_amount + sent_am_in_sender_cur # меняем значения суммы у юзеров - change_something('Account', sender_id, 'amount', new_sender_amount) - change_something('Account', receiver_id, 'amount', new_receiver_amount) + update_row('Account', sender_id, 'amount', round(new_sender_amount,2)) + update_row('Account', receiver_id, 'amount', round(new_receiver_amount,2)) + # вынести функцией # заполняем таблицу c.execute( '''INSERT INTO BankTransaction(bank_sender_name, account_sender_id, bank_receiver_name, account_receiver_id, sent_currency, sent_amount, datetime) VALUES(?,?,?,?,?,?,?)''', - (bank_sender_name, sender_id, bank_receiver_name, receiver_id, sent_currency, sent_amount, transfer_time,)) + (bank_sender_name, sender_id, bank_receiver_name, receiver_id, sender_currency, sent_amount, transfer_time,)) + my_logger.info("success") + return "success" - return 'success' + +@db_connection +def select_random_users_with_discounts(cursor): + cursor.execute("SELECT Id FROM User") + all_users = cursor.fetchall() + random_users = random.sample(all_users, min(10, len(all_users))) # Randomly select up to 10 users + user_discounts = {} + for user_id in random_users: + discount = random.choice([25, 30, 50]) # Randomly choose discount + user_discounts[user_id[0]] = discount + my_logger.info(user_discounts) + my_logger.info("select_random_users_with_discounts success") + return user_discounts + + +@db_connection +def user_with_highest_amount(cursor): + cursor.execute(''' + SELECT User_id + FROM Account + ORDER BY Amount DESC + LIMIT 1 + ''') + user_id = cursor.fetchone()[0] + name = get_data_from_table("name","User", user_id) + my_logger.info(name) + my_logger.info("user_with_highest_amount success") + return name + + +@db_connection +def bank_with_biggest_capital(cursor): + currency_dict = get_curency_data() + # Извлекаем все записи из таблицы Account + cursor.execute("SELECT Bank_id, Currency, Amount FROM Account") + accounts = cursor.fetchall() + + # Создаем словарь для хранения суммарного капитала для каждого банка в долларах + bank_capital = {} + + # Заполняем словарь данными из таблицы Account + for bank_id, currency, amount in accounts: + amount_in_usd = convert_currency(currency_dict, currency, 'USD', amount) + if bank_id in bank_capital: + bank_capital[bank_id] += amount_in_usd + else: + bank_capital[bank_id] = amount_in_usd + + # Находим банк с наибольшим капиталом + max_capital_bank_id = max(bank_capital, key=bank_capital.get) + + # Возвращаем ID банка с наибольшим капиталом + return max_capital_bank_id + + +@db_connection +def bank_serving_oldest_client(cursor): + # Извлекаем все записи из таблицы User + cursor.execute("SELECT Id, Birth_day FROM User") + users = cursor.fetchall() + + # Извлекаем все записи из таблицы Account + cursor.execute("SELECT User_id, Bank_id FROM Account") + accounts = cursor.fetchall() + + # Находим самого старого пользователя + oldest_user_id = None + oldest_birth_day = datetime.max + + for user_id, birth_day in users: + birth_date = datetime.strptime(birth_day, '%Y-%m-%d') + if birth_date < oldest_birth_day: + oldest_birth_day = birth_date + oldest_user_id = user_id + + # Находим банк, которому принадлежит самый старый пользователь + for user_id, bank_id in accounts: + if user_id == oldest_user_id: + return bank_id + + +@db_connection +def print_table(cursor, table_name): + cursor.execute(f"PRAGMA table_info({table_name})") + column_names = [row[1] for row in cursor.fetchall()] + cursor.execute(f"SELECT * FROM {table_name}") + rows = cursor.fetchall() + + print(", ".join(column_names)) + for row in rows: + print(", ".join(map(str, row))) + + +@db_connection +def bank_with_highest_unique_users(cursor): + # Создаем словарь для хранения количества уникальных пользователей для каждого банка + unique_users_by_bank = {} + + # Выбираем все транзакции из таблицы BankTransaction + cursor.execute("SELECT Bank_sender_name, Account_sender_id FROM BankTransaction") + transactions = cursor.fetchall() + + # Подсчитываем количество уникальных пользователей для каждого банка + for bank_name, account_id in transactions: + if bank_name not in unique_users_by_bank: + unique_users_by_bank[bank_name] = set() + unique_users_by_bank[bank_name].add(account_id) + + # Находим банк с наибольшим количеством уникальных пользователей + bank_with_highest_users = max(unique_users_by_bank.items(), key=lambda x: len(x[1])) + + return bank_with_highest_users[0] + +@db_connection +def delete_users_with_incomplete_info(cursor): + cursor.execute("SELECT id FROM User WHERE Name IS NULL OR Surname IS NULL OR Birth_day IS NULL") + deleted_user_id = cursor.fetchall() + cursor.execute("DELETE FROM Account WHERE User_id = ?", deleted_user_id) + return "Deletion complete" + + + \ No newline at end of file diff --git a/hw_4/initial_db_setup.py b/hw_4/initial_db_setup.py index d9decf2..da0c335 100644 --- a/hw_4/initial_db_setup.py +++ b/hw_4/initial_db_setup.py @@ -1,16 +1,17 @@ import sqlite3 -def create_database(): - # Устанавливаем соединение с базой данных + +def create_database(unique_name=True, unique_surname=True): + # Establishing a connection to the database conn = sqlite3.connect('bank.db') c = conn.cursor() - # Создаем таблицу Bank + # Create table Bank c.execute('''CREATE TABLE IF NOT EXISTS Bank ( id INTEGER PRIMARY KEY, name TEXT NOT NULL UNIQUE)''') - # Создаем таблицу BankTransaction + # Create table BankTransaction c.execute('''CREATE TABLE IF NOT EXISTS BankTransaction ( id INTEGER PRIMARY KEY, Bank_sender_name TEXT NOT NULL, @@ -21,16 +22,17 @@ def create_database(): Sent_Amount REAL NOT NULL, Datetime TEXT)''') - # Создаем таблицу User - - c.execute('''CREATE TABLE IF NOT EXISTS User ( + # Create table User + name_uniq = "UNIQUE" if unique_name else "" + surname_uniq = "UNIQUE" if unique_surname else "" + c.execute(f'''CREATE TABLE IF NOT EXISTS User ( Id INTEGER PRIMARY KEY, - Name TEXT NOT NULL UNIQUE, - Surname TEXT NOT NULL UNIQUE, + Name TEXT NOT NULL {name_uniq}, + Surname TEXT NOT NULL {surname_uniq}, Birth_day TEXT, Accounts INTEGER NOT NULL)''') - # Создаем таблицу Account + # Create table Account c.execute('''CREATE TABLE IF NOT EXISTS Account ( Id INTEGER PRIMARY KEY, User_id INTEGER NOT NULL, @@ -41,8 +43,5 @@ def create_database(): Amount REAL NOT NULL, Status TEXT)''') - # Фиксируем изменения и закрываем соединение conn.commit() conn.close() - - diff --git a/hw_4/main.py b/hw_4/main.py index ff9bd15..cebfda6 100644 --- a/hw_4/main.py +++ b/hw_4/main.py @@ -2,69 +2,57 @@ import api import initial_db_setup -initial_db_setup.create_database() -parser = argparse.ArgumentParser() -parser.add_argument('--bank_path', type=str) -parser.add_argument('--user_path', type=str) -parser.add_argument('--account_path', type=str) -parser.add_argument('--table_name', type=str) -parser.add_argument('--row_id', type=int) -parser.add_argument('--column', type=str) -parser.add_argument('--value', type=str) -parser.add_argument('--delete_user', type=int) -parser.add_argument('--delete_bank', type=int) -parser.add_argument('--delete_account', type=int) -parser.add_argument('--sender_id', type=int) -parser.add_argument('--receiver_id', type=int) -parser.add_argument('--sent_currency', type=str) -parser.add_argument('--sent_amount', type=int) -parser.add_argument('--time', type=str) -parser.add_argument('--clear_table', type=str) -args = parser.parse_args() - - - -#чтоб можно было выполнять несколько функций -if args.bank_path: - print(api.add_bank_by_file(args.bank_path)) -if args.account_path: - print(api.add_account_by_file(args.account_path)) -if args.user_path: - print(api.add_user_by_file(args.user_path)) -if args.table_name and args.row_id and args.column and args.value: - print(api.change_something(args.table_name, args.row_id, args.column, args.value)) -if args.clear_table: - print(api.clear_table(args.clear_table)) -if args.delete_user: - print(api.delete_row_from_user(args.delete_user)) -if args.delete_account: - print(api.delete_row_from_account(args.delete_account)) -if args.delete_bank: - print(api.delete_row_from_bank(args.delete_bank)) -if args.sender_id and args.receiver_id and args.sent_currency and args.sent_amount: - print(api.transfer_money(args.sender_id, args.receiver_id, args.sent_currency, args.sent_amount)) -if args.sender_id and args.receiver_id and args.sent_currency and args.sent_amount and args.time: - print(api.transfer_money(args.sender_id, args.receiver_id, args.sent_currency, args.sent_amount, args.time)) - -#api.add_account_by_file(args.account_path) -""" -parser = argparse.ArgumentParser() -#group = parser.add_mutually_exclusive_group() -parser.add_argument('--bankname', type=str, nargs="+") -parser.add_argument('--user_full_name', type=str, nargs="+") -parser.add_argument('--birthday', type=str, nargs="+") -parser.add_argument('--accounts', type=str, nargs="+") -#group.add_argument('--csvpath', type=str) -args = parser.parse_args() - -if args.bankname: - print(args.bankname) - "python main.py --bankname TestBank " - print(api.add_bank(args.bankname)) -elif args.user_full_name and args.birthday and args.accounts : - print(api.add_user(args.user_full_name, args.birthday, args.accounts)) - -test = ['Lena Zhelezo', '13.01.2005', 1] -print(api.add_user(test[0], test[1], test[2])) -""" +def init_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--add_path', type=str) + parser.add_argument('--table_name', type=str) + parser.add_argument('--row_id', type=int) + parser.add_argument('--column', type=str) + parser.add_argument('--value', type=str) + parser.add_argument('--delete_row_id', type=int) + parser.add_argument('--sender_id', type=int) + parser.add_argument('--receiver_id', type=int) + parser.add_argument('--sent_currency', type=str) + parser.add_argument('--sent_amount', type=int) + parser.add_argument('--time', type=str) + parser.add_argument('--clear_table', type=str) + parser.add_argument('--random_disc', type=str) + args = parser.parse_args() + + return args + + +def do_func_with_args(args): + # чтоб можно было выполнять несколько функций + if args.add_path and args.table_name: + api.add_table_by_file(args.add_path, args.table_name) + if args.table_name and args.row_id and args.column and args.value: + api.update_row(args.table_name, args.row_id, args.column, args.value) + if args.clear_table: + api.clear_table(args.clear_table) + if args.delete_row_id and args.table_name: + api.delete_row(args.delete_row_id ,args.table_name) + if args.sender_id and args.receiver_id and args.sent_amount: + api.transfer_money(args.sender_id, args.receiver_id, args.sent_amount) + if args.sender_id and args.receiver_id and args.sent_amount and args.time: + api.transfer_money(args.sender_id, args.receiver_id, args.sent_amount, args.time) + if args.random_disc: + print(api.select_random_users_with_discounts()) + + print(api.user_with_highest_amount()) + # Пример использования + print(api.bank_serving_oldest_client()) + print(api.bank_with_biggest_capital()) + print(api.bank_with_highest_unique_users()) + api.print_table("BankTransaction") + + + +def main(): + initial_db_setup.create_database() + do_func_with_args(init_args()) + + +if __name__ == "__main__": + main() diff --git a/hw_4/validate.py b/hw_4/validate.py index b483ae2..8a9e574 100644 --- a/hw_4/validate.py +++ b/hw_4/validate.py @@ -2,46 +2,51 @@ from datetime import datetime -# Валидация поля user_full_name +# Validation of user_full_name field def validate_user_full_name(user_full_name): - # Удаляем все символы, не являющиеся буквами + # Delete all characters that are not letters user_full_name = re.sub(r'[^a-zA-Z\s]', '', user_full_name) - # Разделяем имя и фамилию по любым пробельным символам - name, surname = user_full_name.strip().split(None, 1) + # Separate first and last name by any whitespace characters + name, surname = user_full_name.strip().split(maxsplit=1) return name, surname -# Валидация полей с строгим набором значений +# Validation of fields with a strict set of values def validate_field_value(field, value, allowed_values): if value not in allowed_values: raise ValueError("error: not allowed value {} for field {}!".format(value, field)) +def valid_acc(data): + type_values = ["credit", "debit"] + status_values = ["gold", "silver", "platinum"] + for i in data: + validate_field_value("type", i["type"], type_values) + validate_field_value("status", i["status"], status_values) + return True def validate_account_number(account_number): - # Замена специальных символов на тире + # Replacing special characters with dashes account_number = re.sub(r'[#%_?&]', '-', account_number) - # Проверка на количество символов - if len(account_number) <18: + # Character count check + if len(account_number) < 18: raise ValueError("error: too little") if len(account_number) > 18: raise ValueError("error: many chars") - # Проверка формата + # Checking the format if not account_number.startswith("ID--"): raise ValueError("error: wrong format") - # Проверка на наличие нужного паттерна + # Checking for the right pattern if not re.match(r'ID--[a-zA-Z]{1,3}-\d+-', account_number): raise ValueError("an error: broken ID") return account_number -# Функция для проверки и добавления времени транзакции +# Function for checking and adding transaction time def add_transaction_time(transaction_time): if not transaction_time: transaction_time = datetime.now() return transaction_time - - From 95de1c682327b0f718a4c9cfc06cde2814f276b3 Mon Sep 17 00:00:00 2001 From: ValeZh Date: Sat, 18 May 2024 00:50:46 +0300 Subject: [PATCH 10/11] remake 4 start to make 5 later make code better --- hw_4/account.csv | 2 +- hw_4/bank.db | Bin 36864 -> 36864 bytes hw_4/consts.py | 1 + hw_4/db_con_decor.py | 44 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 hw_4/consts.py create mode 100644 hw_4/db_con_decor.py diff --git a/hw_4/account.csv b/hw_4/account.csv index 6a23ee4..4acb96d 100644 --- a/hw_4/account.csv +++ b/hw_4/account.csv @@ -1,6 +1,6 @@ user_id,type,account_number,bank_id,currency,amount,status 1,credit,ID--dcd-123568744-,3,USD,1000,gold 3,debit,ID--xyz-987654-uvw,2,USD,500,silver -5,credit,ID--qwe-456789-asd,5,EUR,800,platinum +2,credit,ID--qwe-456789-asd,5,EUR,800,platinum 2,debit,ID--z1-654321-xyz,4,CAD,1200,gold 4,credit,ID--jkl-987654-mno,1,USD,1500,silver \ No newline at end of file diff --git a/hw_4/bank.db b/hw_4/bank.db index 7cd98c382d62507d4a40671965f7a529fa4cd2c7..c7d0bcd3bea30be3eeba65cf5b74b233350eb5d8 100644 GIT binary patch delta 903 zcmb7?O-vI}6oubRr-hQ(3znvVw$PdoP2`pLW~QCaY-nlmhs1~wR)|`l!bsaOP?R=E ziN>v<6JvCtm>4z?qhTQ=EYuC@LSw?h1+ppT+bnhE6ny4{x`|kP9xi9C=F7UGp z{Jf8=T=yrr%HuQl!3Q6a6N(7lzzcW^Phbh|!Zo-IMJTS+kpVD^%@YJ6RDZA|ogWJt zXM>4cW?Uai*T5%6mJpO+4qn1DScQAA3|C+qwi$T}%vYxcbEeG@80|Jcx4CN_t|bH; z%)So-u6M4bl~C<1S6Oj5k%tR8-F)ImZ%5LW98FJTf>v5*Uk~?1B%+K-1k-3xBwB=O zl!T*HAu3Vq{{s?Dl)@w`F}tYXL;=pjvBac~3;H0-5_Yo_soxW2MHAIk#z z-cnB^L859TrpaPhl!!v8!drvAKL%8j<*+Qu3Z>>o`~H1Y4pK#v+4f>M8dGGV?16b? zhi(KrP=Rh(Ua5`mgR-AM@4L^^wU;iK;OXQxQv6iGHs)RNa}=v&D{a<04~K z=Fae#PjDb_)EnadHnjVBX6y~QyVChgZ%!|aGE-Iv!89VZ$}2m^8-sOl2nnt&1a5fX z+JbTLvU2aZYN9qL;u^~P44*Z?xxifAAY?Ccyp%gZ;ap2zCNEjdEk6DUC{HB zIm$Vaa~In#2g>oA7Z`Q5dBn&L!zOCwylt#J4?mn4)C)&b7?&uHMr28(c&b06re8d~P#&bNzBiuu?uP$5#ZI0FTK~5m)*;4Ih%3n^+RGq*rm!hGw zMbN?_I{1XQ*v1pQz0UZ=Yb%5^fXh;{yxq_6G{%=yj*dNhv~x##DL6bM6-XO5mzf=sx0oKub^rE=g@+%?lWmz}hw zxy54PVWhKk`p>&tUTMv(HL4SwOyrOqIzo+*6&9~tEIc?^{x>VWS5c)fQdao5c*KQ? zIfhAlb=T9wN`q7Qq(ryZN25aOe*@iWXT&tCq2JqDOu!Do0e0BU-|&+?`Wa}abDX~K Goc{}c42ypN diff --git a/hw_4/consts.py b/hw_4/consts.py new file mode 100644 index 0000000..7a48541 --- /dev/null +++ b/hw_4/consts.py @@ -0,0 +1 @@ +URL = 'https://api.freecurrencyapi.com/v1/latest?apikey={}' diff --git a/hw_4/db_con_decor.py b/hw_4/db_con_decor.py new file mode 100644 index 0000000..bf97651 --- /dev/null +++ b/hw_4/db_con_decor.py @@ -0,0 +1,44 @@ +import sqlite3 +from functools import wraps + + +def db_connection(func): + """ + Декоратор для установки соединения с базой данных и его закрытия после выполнения функции. + + Args: + func (function): Функция базы данных, которая будет выполнена. + + Returns: + function: Вложенная функция-обертка, которая обеспечивает соединение и закрытие. + """ + # не работает + @wraps(func) + def wrapper(*args, **kwargs): + """ + Вложенная функция-обертка, обеспечивающая соединение и закрытие. + + Args: + *args: Позиционные аргументы, переданные в функцию. + **kwargs: Именованные аргументы, переданные в функцию. + + Returns: + any: Результат выполнения оригинальной функции. + """ + # Устанавливаем соединение с базой данных + conn = sqlite3.connect('bank.db') + # Создаем объект курсора + c = conn.cursor() + result = None + try: + # Вызываем оригинальную функцию, передавая ей курсор и все переданные аргументы + result = func(c, *args, **kwargs) + except Exception as e: + # Обрабатываем ошибки и логируем их + print(f"Error: {str(e)}") + finally: + conn.commit() + conn.close() + return result + # Возвращаем вложенную функцию-обертку в качестве декоратора + return wrapper From 8bca383dacc842bbc7c33a1ef6148b53b5918bf0 Mon Sep 17 00:00:00 2001 From: ValeZh Date: Mon, 20 May 2024 18:15:35 +0300 Subject: [PATCH 11/11] I make all --- hw_4/api.py | 167 +++++++++++++++++++++++++++------------------------ hw_4/main.py | 30 ++++++--- 2 files changed, 109 insertions(+), 88 deletions(-) diff --git a/hw_4/api.py b/hw_4/api.py index e03ff0e..645988e 100644 --- a/hw_4/api.py +++ b/hw_4/api.py @@ -6,7 +6,7 @@ from dotenv import load_dotenv, find_dotenv import logging from consts import URL -from datetime import datetime +from datetime import datetime, timedelta import random formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(name)s:%(message)s') @@ -19,15 +19,13 @@ load_dotenv(find_dotenv()) -# получает дикт из валют и их значений относительно доллара -def get_curency_data(): - # .env - # dotenv lib +# gets dict from currencies and their values relative to the dollar +def get_currency_data(): response = requests.get(URL.format(os.getenv('API_KEY'))) if response.status_code == requests.codes.ok: data = response.json() - #сделать логами + # make logs my_logger.info("data_get successfully") my_logger.info(data['data']) return data['data'] @@ -35,52 +33,31 @@ def get_curency_data(): return None -# читает цсв файл переобразовывая в дикт +# reads csv file converted to dict def read_csv_to_dict(file_path): with open(file_path, 'r') as file: return list(csv.DictReader(file)) -# преобразует лист диктов в дикт листов -def merge_dicts(dict_list): - merged_dict = {} - for d in dict_list: - for key, value in d.items(): - # Если ключ уже есть в объединенном словаре, добавляем значение в список - if key in merged_dict: - merged_dict[key].append(value) - # Если ключ новый, создаем список значений - else: - merged_dict[key] = [value] - return merged_dict - - -# проверяет все ли массивы при ключах имеют одинаковую длинну -# эта функция сделана для заполнения базы данных с помощью командной строк -# при желании это можно реализовать -def equal_length_lists(d): - lengths = {len(lst) for lst in d.values()} - return len(lengths) == 1 - - def unpack_data(data): keys = list(data.keys()) return [data[key] for key in keys] if len(keys) > 1 else data[keys[0]] -#{ filler_date: [{}, {} ]} -#{ "row1": {}, "row2": {} } -# заполняет таблицу банк + +# { filler_date: [{}, {} ]} +# { "row1": {}, "row2": {} } +# fills the table bank @db_connection def add_bank(cur, **kwargs): data = unpack_data(kwargs) my_logger.info(data) - # распаковать лист диктов + # unpack the mass of dicts my_logger.info(data) cur.executemany("INSERT INTO Bank(name) VALUES(:Name)", data) # :param_name, :param_name2 my_logger.info("Bank added successfully.") -# заполняет таблицу юзер +# fills the table user @db_connection def add_user(cur, **kwargs): data = unpack_data(kwargs) @@ -92,23 +69,25 @@ def add_user(cur, **kwargs): data) my_logger.info("User added successfully.") + def unpack_to_string(data): result = '' for tup in data: for item in tup: result += str(item) + ',' return result.rstrip(',') -# -# заполняет таблицу аккаунт + +# fills the table account def set_accounts(cur, data): for i in data: cur.execute("SELECT id FROM Account WHERE user_id = ?", (i["user_id"],)) - numb_of_acc = cur.fetchall() # Извлекаем значение из курсора + numb_of_acc = cur.fetchall() account_str = unpack_to_string(numb_of_acc) my_logger.info(account_str) cur.execute("UPDATE User SET Accounts = ? WHERE id = ?", (account_str, i["user_id"],)) + @db_connection def add_account(cur, **kwargs): data = unpack_data(kwargs) @@ -120,7 +99,8 @@ def add_account(cur, **kwargs): set_accounts(cur, data) my_logger.info("account added successfully.") -#update row in bd + +# update row in bd @db_connection def update_row(c, table_name, row_id, column, value): c.execute(f"UPDATE {table_name} SET {column} = ? WHERE id = ?", (value, row_id, )) @@ -142,7 +122,7 @@ def delete_row(cur, row_id, fnc): return "success" -# она просто очищает таблицы в бд +# it just clears the tables in the database @db_connection def clear_table(cur, table_name): cur.execute(f"DELETE FROM {table_name}") @@ -163,12 +143,11 @@ def add_table_by_file(path, table_name): def convert_currency(currency_values, orig_currency, conv_currency, amount): return round((amount / currency_values[orig_currency]) * currency_values[conv_currency], 2) -# достать банкнейм -@db_connection -def get_bankname(cur, id_user): - bank_id = get_data_from_table(table_name ="Account", row_name="bank_id",row_id= id_user) + +def get_bankname(id_user): + bank_id = get_data_from_table(table_name="Account", row_name="bank_id", row_id=id_user) my_logger.info("get_bankname successfully.") - return get_data_from_table(table_name = "Bank",row_name="name", row_id = bank_id) + return get_data_from_table(table_name="Bank", row_name="name", row_id=bank_id) @db_connection @@ -178,12 +157,25 @@ def get_data_from_table(cur, row_name, table_name, row_id): @db_connection -def transfer_money(c, sender_id, receiver_id, sent_amount, transfer_time=None): - currency_dict = get_curency_data() +def insert_transaction(cur, bank_sender_name, sender_id, bank_receiver_name, + receiver_id, sender_currency, sent_amount, transfer_time): + cur.execute(''' + INSERT INTO BankTransaction + (bank_sender_name, account_sender_id, + bank_receiver_name, account_receiver_id, + sent_currency, sent_amount, datetime) + VALUES(?,?,?,?,?,?,?)''', + (bank_sender_name, sender_id, + bank_receiver_name, receiver_id, + sender_currency, sent_amount, transfer_time,)) + + +def transfer_money(sender_id, receiver_id, sent_amount, transfer_time=None): + currency_dict = get_currency_data() my_logger.info('valid current success') - # вытаскиваем нужные данные для заполнения таблицы транзакций + # pull the necessary data to fill the transaction table bank_sender_name = get_bankname(sender_id) - bank_receiver_name = get_bankname( receiver_id) + bank_receiver_name = get_bankname(receiver_id) sender_amount = get_data_from_table("Amount", "Account", sender_id) receiver_amount = get_data_from_table("Amount", "Account", receiver_id) sender_currency = get_data_from_table("Currency", "Account", sender_id) @@ -191,26 +183,23 @@ def transfer_money(c, sender_id, receiver_id, sent_amount, transfer_time=None): sent_am_in_sender_cur = sent_amount if sender_amount <= sent_amount: - raise ValueError('not enough money in the account') + raise ValueError("not enough money in the account") if receiver_currency != sender_currency: sent_am_in_sender_cur = convert_currency(currency_dict, receiver_currency, sender_currency, sent_amount) - # проверяем наличие времени + # check the time transfer_time = validate.add_transaction_time(transfer_time) new_sender_amount = sender_amount - sent_am_in_sender_cur new_receiver_amount = receiver_amount + sent_am_in_sender_cur - # меняем значения суммы у юзеров - update_row('Account', sender_id, 'amount', round(new_sender_amount,2)) - update_row('Account', receiver_id, 'amount', round(new_receiver_amount,2)) + # change the sum values of the users + update_row("Account", sender_id, "amount", round(new_sender_amount, 2)) + update_row("Account", receiver_id, "amount", round(new_receiver_amount, 2)) - # вынести функцией - # заполняем таблицу - c.execute( - '''INSERT INTO BankTransaction(bank_sender_name, account_sender_id, bank_receiver_name, account_receiver_id, - sent_currency, sent_amount, datetime) VALUES(?,?,?,?,?,?,?)''', - (bank_sender_name, sender_id, bank_receiver_name, receiver_id, sender_currency, sent_amount, transfer_time,)) + # fill the table + insert_transaction(bank_sender_name, sender_id, bank_receiver_name, receiver_id, + sender_currency, sent_amount, transfer_time) my_logger.info("success") return "success" @@ -238,7 +227,7 @@ def user_with_highest_amount(cursor): LIMIT 1 ''') user_id = cursor.fetchone()[0] - name = get_data_from_table("name","User", user_id) + name = get_data_from_table("name", "User", user_id) my_logger.info(name) my_logger.info("user_with_highest_amount success") return name @@ -246,15 +235,15 @@ def user_with_highest_amount(cursor): @db_connection def bank_with_biggest_capital(cursor): - currency_dict = get_curency_data() - # Извлекаем все записи из таблицы Account + currency_dict = get_currency_data() + # Extract all records from the Account table cursor.execute("SELECT Bank_id, Currency, Amount FROM Account") accounts = cursor.fetchall() - # Создаем словарь для хранения суммарного капитала для каждого банка в долларах + # Create a dictionary to store total capital for each bank in dollars bank_capital = {} - # Заполняем словарь данными из таблицы Account + # Create a dictionary to store the total capital for each bank in dollars for bank_id, currency, amount in accounts: amount_in_usd = convert_currency(currency_dict, currency, 'USD', amount) if bank_id in bank_capital: @@ -262,24 +251,22 @@ def bank_with_biggest_capital(cursor): else: bank_capital[bank_id] = amount_in_usd - # Находим банк с наибольшим капиталом + # Find the bank with the most capital max_capital_bank_id = max(bank_capital, key=bank_capital.get) - - # Возвращаем ID банка с наибольшим капиталом + my_logger.info(f"max capital bank id {max_capital_bank_id}") + my_logger.info("bank_with_biggest_capital success") return max_capital_bank_id @db_connection def bank_serving_oldest_client(cursor): - # Извлекаем все записи из таблицы User cursor.execute("SELECT Id, Birth_day FROM User") users = cursor.fetchall() - # Извлекаем все записи из таблицы Account cursor.execute("SELECT User_id, Bank_id FROM Account") accounts = cursor.fetchall() - # Находим самого старого пользователя + # Find the oldest user oldest_user_id = None oldest_birth_day = datetime.max @@ -289,7 +276,7 @@ def bank_serving_oldest_client(cursor): oldest_birth_day = birth_date oldest_user_id = user_id - # Находим банк, которому принадлежит самый старый пользователь + # Find the bank that owns the oldest user for user_id, bank_id in accounts: if user_id == oldest_user_id: return bank_id @@ -309,30 +296,54 @@ def print_table(cursor, table_name): @db_connection def bank_with_highest_unique_users(cursor): - # Создаем словарь для хранения количества уникальных пользователей для каждого банка + # Create a dictionary to store the number of unique users for each bank unique_users_by_bank = {} - # Выбираем все транзакции из таблицы BankTransaction + # Select all transactions from the BankTransaction table cursor.execute("SELECT Bank_sender_name, Account_sender_id FROM BankTransaction") transactions = cursor.fetchall() - # Подсчитываем количество уникальных пользователей для каждого банка + # Count the number of unique users for each bank for bank_name, account_id in transactions: if bank_name not in unique_users_by_bank: unique_users_by_bank[bank_name] = set() unique_users_by_bank[bank_name].add(account_id) - # Находим банк с наибольшим количеством уникальных пользователей + # Find the bank with the unique users bank_with_highest_users = max(unique_users_by_bank.items(), key=lambda x: len(x[1])) return bank_with_highest_users[0] + @db_connection def delete_users_with_incomplete_info(cursor): - cursor.execute("SELECT id FROM User WHERE Name IS NULL OR Surname IS NULL OR Birth_day IS NULL") - deleted_user_id = cursor.fetchall() - cursor.execute("DELETE FROM Account WHERE User_id = ?", deleted_user_id) + while True: + cursor.execute("SELECT id FROM User WHERE Name IS NULL OR Surname IS NULL OR Birth_day IS NULL") + result = cursor.fetchone() + if result is None: + break + deleted_user_id = result[0] + cursor.execute("DELETE FROM Account WHERE User_id = ?", (deleted_user_id,)) + cursor.execute("DELETE FROM User WHERE id = ?", (deleted_user_id,)) return "Deletion complete" +@db_connection +def get_user_transactions(c, user_id): + + # Calculate the date three months ago from today + end_date = datetime.now() + start_date = end_date - timedelta(days=90) + + # Convert dates to string format for SQL query + start_date_str = start_date.strftime('%Y-%m-%d %H:%M:%S') + end_date_str = end_date.strftime('%Y-%m-%d %H:%M:%S') + + query = ''' + SELECT * FROM BankTransaction + WHERE (Account_sender_id = ? OR Account_receiver_id = ?) + AND Datetime BETWEEN ? AND ? + ''' + c.execute(query, (user_id, user_id, start_date_str, end_date_str)) + return c.fetchall() \ No newline at end of file diff --git a/hw_4/main.py b/hw_4/main.py index cebfda6..e93ffdc 100644 --- a/hw_4/main.py +++ b/hw_4/main.py @@ -18,13 +18,19 @@ def init_args(): parser.add_argument('--time', type=str) parser.add_argument('--clear_table', type=str) parser.add_argument('--random_disc', type=str) + parser.add_argument('--highest_amount', type=str) + parser.add_argument('--bank_with_biggest_capital', type=str) + parser.add_argument('--bank_with_highest_unique_users', type=str) + parser.add_argument('--get_user_transactions', type=int) + parser.add_argument('--print_table', type=str) + parser.add_argument('--delete_incomplete', type=str) args = parser.parse_args() return args def do_func_with_args(args): - # чтоб можно было выполнять несколько функций + # to be able to perform multiple functions if args.add_path and args.table_name: api.add_table_by_file(args.add_path, args.table_name) if args.table_name and args.row_id and args.column and args.value: @@ -32,21 +38,25 @@ def do_func_with_args(args): if args.clear_table: api.clear_table(args.clear_table) if args.delete_row_id and args.table_name: - api.delete_row(args.delete_row_id ,args.table_name) + api.delete_row(args.delete_row_id, args.table_name) if args.sender_id and args.receiver_id and args.sent_amount: api.transfer_money(args.sender_id, args.receiver_id, args.sent_amount) if args.sender_id and args.receiver_id and args.sent_amount and args.time: api.transfer_money(args.sender_id, args.receiver_id, args.sent_amount, args.time) if args.random_disc: print(api.select_random_users_with_discounts()) - - print(api.user_with_highest_amount()) - # Пример использования - print(api.bank_serving_oldest_client()) - print(api.bank_with_biggest_capital()) - print(api.bank_with_highest_unique_users()) - api.print_table("BankTransaction") - + if args.highest_amount: + print(api.user_with_highest_amount()) + if args.bank_with_biggest_capital: + print(api.bank_with_biggest_capital()) + if args.bank_with_highest_unique_users: + print(api.bank_with_highest_unique_users()) + if args.get_user_transactions: + print(api.get_user_transactions()) + if args.print_table: + api.print_table(args.print_table) + if args.delete_incomplete: + print(api.delete_users_with_incomplete_info()) def main():