├── Cafe Management System ├── receipts │ ├── orders.txt │ └── order_receipt_12122.txt ├── app.png ├── icons │ └── coffee.png ├── customWidgets.py ├── readme.md └── main.py ├── Contact Management System ├── files │ ├── test.txt │ └── contacts.db ├── app.png ├── icons │ ├── back.png │ ├── copy.png │ ├── edit.png │ ├── new.png │ ├── save.png │ ├── cancel.png │ ├── delete.png │ ├── phone.ico │ └── search.png ├── readme.md ├── sql_operations.py ├── customWidgets.py └── main.py ├── README.md ├── LICENSE └── .gitignore /Cafe Management System/receipts/orders.txt: -------------------------------------------------------------------------------- 1 | OrderN12122 -------------------------------------------------------------------------------- /Contact Management System/files/test.txt: -------------------------------------------------------------------------------- 1 | test : pyGuru -------------------------------------------------------------------------------- /Cafe Management System/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Cafe Management System/app.png -------------------------------------------------------------------------------- /Contact Management System/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/app.png -------------------------------------------------------------------------------- /Cafe Management System/icons/coffee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Cafe Management System/icons/coffee.png -------------------------------------------------------------------------------- /Contact Management System/icons/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/back.png -------------------------------------------------------------------------------- /Contact Management System/icons/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/copy.png -------------------------------------------------------------------------------- /Contact Management System/icons/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/edit.png -------------------------------------------------------------------------------- /Contact Management System/icons/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/new.png -------------------------------------------------------------------------------- /Contact Management System/icons/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/save.png -------------------------------------------------------------------------------- /Contact Management System/icons/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/cancel.png -------------------------------------------------------------------------------- /Contact Management System/icons/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/delete.png -------------------------------------------------------------------------------- /Contact Management System/icons/phone.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/phone.ico -------------------------------------------------------------------------------- /Contact Management System/icons/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/icons/search.png -------------------------------------------------------------------------------- /Contact Management System/files/contacts.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itspyguru/GUI-Management-Systems/HEAD/Contact Management System/files/contacts.db -------------------------------------------------------------------------------- /Cafe Management System/receipts/order_receipt_12122.txt: -------------------------------------------------------------------------------- 1 | Order Summary 2 | Customer Name : Apurva 3 | Order date time : Jan 23 ,2021 03:06:51 PM 4 | 5 | item | quantity | price | total cost 6 | tea | 1 | 10 | 10 7 | coffee | 2 | 15 | 30 8 | 9 | SubCost : 40 10 | Service Charge : 1.6 11 | GST : 2.0 12 | Discount : 0.0 13 | Total Cost : 43.6 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GUI-Management-Systems 2 | 3 | [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com) 4 | [![forthebadge](https://forthebadge.com/images/badges/made-with-python.svg)](https://forthebadge.com) 5 | [![forthebadge](https://forthebadge.com/images/badges/check-it-out.svg)](https://forthebadge.com) 6 | 7 | This repository contains some of the GUI based Inventory, Management & reservation System Projects written using python by me. 8 | 9 | ### All the projects are listed here 10 | 11 | * ## Cafe Management System 12 | > A simple cafe management system made with python & tkinter.\ 13 | > Link to project : [Cafe Management System](https://github.com/pyGuru123/GUI-Management-Systems/tree/main/Cafe%20Management%20System) 14 | 15 | * ## Contact Management System 16 | > A simple Contact Management System made with python & tkinter. \ 17 | > Link to project : [Contact Management System](https://github.com/pyGuru123/GUI-Management-Systems/tree/main/Contact%20Management%20System) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Prajjwal Pathak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Contact Management System/readme.md: -------------------------------------------------------------------------------- 1 | # Contact Management System 2 | 3 | [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com) 4 | [![forthebadge](https://forthebadge.com/images/badges/built-with-swag.svg)](https://forthebadge.com) 5 | [![forthebadge](https://forthebadge.com/images/badges/made-with-python.svg)](https://forthebadge.com) 6 | 7 | CMS is a simple python based Contact Management System made using the tkinter library. It follows the principles of MVC to bring out the best user experience. 8 | 9 | ![Alt text](app.png?raw=true "Contact Management System") 10 | 11 | ## How to Download 12 | 13 | Download this project from here [Download Contact Management System](https://downgit.github.io/#/home?url=https://github.com/pyGuru123/GUI-Management-Systems/tree/main/Contact%20Management%20System) 14 | 15 | ## Requirements 16 | 17 | No External Package is required. 18 | 19 | ## Usage 20 | 21 | Double click the application.py to open the GUI application, then click on New to start creating new contacts and save them. You can also edit the contacts later. 22 | 23 | ## Contributing 24 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 25 | 26 | Please make sure to update tests as appropriate. -------------------------------------------------------------------------------- /Cafe Management System/customWidgets.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | 3 | class CustomFrame(tk.LabelFrame): 4 | def __init__(self, parent, **kwargs): 5 | tk.LabelFrame.__init__(self, parent, **kwargs) 6 | 7 | width = kwargs.get('width', 10) 8 | height = kwargs.get('height', 10) 9 | bg = kwargs.get('bg', 'white') 10 | fg = kwargs.get('fg', "#248aa2") 11 | bd = kwargs.get('borderwidth', "3") 12 | self.configure(width=width, height=height, font=('verdana',10,'bold'), 13 | borderwidth=bd, relief=tk.RIDGE, highlightthickness=4, bg=bg, fg=fg, 14 | highlightcolor="white", highlightbackground="white") 15 | 16 | class CustomLabel(tk.Label): 17 | def __init__(self, parent, **kwargs): 18 | tk.Label.__init__(self, parent, **kwargs) 19 | 20 | width = kwargs.get('width', 10) 21 | bg = kwargs.get('bg', 'white') 22 | fg = kwargs.get('fg', 'black') 23 | self.configure(width=width, bg=bg, fg=fg, anchor='w', 24 | font=('Verdana', 10, 'bold')) 25 | class CustomEntry(tk.Entry): 26 | def __init__(self, parent, **kwargs): 27 | tk.Entry.__init__(self, parent, **kwargs) 28 | 29 | width = kwargs.get('width', 8) 30 | self.configure(width=width,borderwidth=2,relief=tk.SUNKEN,bg="#248aa2", 31 | fg='white') 32 | 33 | class CustomButton(tk.Button): 34 | def __init__(self, parent, **kwargs): 35 | tk.Button.__init__(self, parent, **kwargs) 36 | 37 | self.configure(width=7, borderwidth=2, font=('Arial',8, 'bold'), 38 | bg='#248aa2', fg="white", relief=tk.RAISED) 39 | -------------------------------------------------------------------------------- /Cafe Management System/readme.md: -------------------------------------------------------------------------------- 1 | # Cafe Management System 2 | 3 | [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com) 4 | [![forthebadge](https://forthebadge.com/images/badges/built-with-swag.svg)](https://forthebadge.com) 5 | [![forthebadge](https://forthebadge.com/images/badges/made-with-python.svg)](https://forthebadge.com) 6 | 7 | Cafe Management System is a simple python based small Cafe Management System made using the tkinter library. 8 | 9 | ![Alt text](app.png?raw=true "Cafe Management System") 10 | 11 | ## How to Download 12 | 13 | Download this project from here [Download Cafe Management System](https://downgit.github.io/#/home?url=https://github.com/pyGuru123/GUI-Management-Systems/tree/main/Cafe%20Management%20System) 14 | 15 | ## Requirements 16 | 17 | No External Package is required. 18 | 19 | ## Usage 20 | 21 | Double click the application.py to open the GUI application, then enter number of orders 22 | of each item, finally click calculate to calculate charges and discount. To generate a 23 | receipt, enter customer name in the name entry and click receipt to get one. Receipts are 24 | stored in a text file inside receipts folder which automatically gets created on 25 | running the app. 26 | 27 | Update the item prices, names, and discount from source code. 28 | 29 | ## Contributing 30 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 31 | 32 | Please make sure to update tests as appropriate. -------------------------------------------------------------------------------- /Contact Management System/sql_operations.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sqlite3 3 | 4 | if not os.path.exists('files/contacts.db'): 5 | with sqlite3.connect('files/contacts.db') as conn: 6 | conn.execute('''CREATE TABLE contacts ( 7 | first_name text NOT NULL, 8 | last_name text, 9 | phone text NOT NULL, 10 | email text) 11 | ''') 12 | print('database created successfully') 13 | 14 | def insert_item(values): 15 | with sqlite3.connect('files/contacts.db') as conn: 16 | cursor = conn.cursor() 17 | try: 18 | cursor.execute("INSERT INTO contacts VALUES (?,?,?,?)", 19 | values) 20 | return 'success' 21 | except: 22 | return 'error' 23 | 24 | def delete_item(first_name, last_name): 25 | query = "DELETE FROM contacts WHERE first_name = ? and last_name = ?" 26 | with sqlite3.connect('files/contacts.db') as conn: 27 | cursor = conn.cursor() 28 | try: 29 | cursor.execute(query, (first_name, last_name)) 30 | return 'success' 31 | except: 32 | return 'error' 33 | 34 | def fetch_single_result(first_name, last_name): 35 | query = "SELECT * FROM contacts WHERE first_name = ? and last_name = ?" 36 | with sqlite3.connect('files/contacts.db') as conn: 37 | cursor = conn.cursor() 38 | try: 39 | cursor.execute(query, (first_name, last_name)) 40 | data = cursor.fetchone() 41 | return data 42 | except: 43 | return 'error' 44 | 45 | def fetch_all_result(): 46 | query = "SELECT * FROM contacts" 47 | with sqlite3.connect('files/contacts.db') as conn: 48 | cursor = conn.cursor() 49 | try: 50 | cursor.execute(query) 51 | data = cursor.fetchall() 52 | return sorted(data) 53 | except: 54 | return 'error' -------------------------------------------------------------------------------- /Contact Management System/customWidgets.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | 3 | class CustomSearch(tk.Entry): 4 | def __init__(self, parent, *args, **kwargs): 5 | tk.Entry.__init__(self, parent, *args, **kwargs) 6 | self.parent = parent 7 | self.bind('', self.add_placeholder) 8 | self.bind('', self.clear_placeholder) 9 | 10 | self.configure(fg="gray70") 11 | self.insert(0, 'Search Contact') 12 | 13 | def add_placeholder(self, event=None): 14 | if not self.get(): 15 | self.configure(fg="gray70") 16 | self.insert(0, 'Search Contact') 17 | 18 | def clear_placeholder(self, event): 19 | if event and self.get() == 'Search Contact': 20 | self.delete('0', 'end') 21 | self.configure(fg="black") 22 | 23 | class CustomEntry(tk.Entry): 24 | def __init__(self, parent, *args, **kwargs): 25 | tk.Entry.__init__(self, parent, *args, **kwargs) 26 | self.parent = parent 27 | self.bind('', self.add_placeholder) 28 | self.bind('', self.clear_placeholder) 29 | 30 | def add_placeholder(self, event=None): 31 | if not self.get(): 32 | self.configure(fg="red") 33 | self.insert(0, 'This field is required') 34 | 35 | def clear_placeholder(self, event): 36 | if event and self.get() == 'This field is required': 37 | self.delete('0', 'end') 38 | self.configure(fg="black") 39 | 40 | class CustomPhone(CustomEntry): 41 | def __init__(self, parent, *args, **kwargs): 42 | CustomEntry.__init__(self, parent, *args, **kwargs) 43 | self.var = tk.StringVar(parent) 44 | self.var.trace('w', self.validate) 45 | self.configure(textvariable=self.var) 46 | self.get, self.set = self.var.get, self.var.set 47 | 48 | def validate(self, *args): 49 | value = self.get() 50 | if len(value) <= 10: 51 | if not value.isdigit(): 52 | self.set(''.join(x for x in value if x.isdigit())) 53 | else: 54 | if value != 'This field is required': 55 | value = value[:10] 56 | self.set(value[:10]) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /Cafe Management System/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tkinter as tk 3 | from tkinter import messagebox 4 | from tkinter import PhotoImage 5 | import datetime 6 | 7 | from customWidgets import CustomLabel, CustomFrame, CustomEntry, CustomButton 8 | 9 | if not os.path.exists('receipts/'): 10 | os.mkdir('receipts/') 11 | with open('receipts/orders.txt', 'w') as file: 12 | file.write('OrderN12121') 13 | 14 | class Application(tk.Frame): 15 | def __init__(self, master=None): 16 | super().__init__(master=master) 17 | self.master = master 18 | self.grid() 19 | 20 | self.draw_frames() 21 | self.draw_title_widgets() 22 | self.draw_body_widgets() 23 | 24 | self.itemCost = { 25 | 'Tea' : 10, 26 | 'Coffee' : 15, 27 | 'Pastery' : 80, 28 | 'Pizza' : 199, 29 | 'Fries' : 60, 30 | 'Burger' : 49, 31 | 'Pepsi' : 14, 32 | 'Cookies' : 4 33 | } 34 | 35 | self.discount_dict = { 36 | 0:0, 100 : 1, 300 : 2, 500 : 3, 1000 : 5, 2000 : 8, 5000 : 15 37 | } 38 | 39 | self.itemList = [item for item in self.itemCost.keys()] 40 | self.entryValues = [tk.StringVar() for item in self.itemList] 41 | self.expression = '' 42 | 43 | 44 | self.draw_item_frame_widgets() 45 | self.draw_bill_frame_widgets() 46 | self.draw_controller_frame_widgets() 47 | self.draw_calculator_frame_widgets() 48 | 49 | def draw_frames(self): 50 | self.title_frame = tk.Frame(self, width=800, height=105, bg='white') 51 | self.main_frame = tk.LabelFrame(self, width=800, height=280, bg='white') 52 | 53 | self.title_frame.grid(row=0, column=0) 54 | self.main_frame.grid(row=1, column=0, pady=5) 55 | 56 | self.title_frame.grid_propagate(False) 57 | self.main_frame.grid_propagate(False) 58 | 59 | def draw_title_widgets(self): 60 | self.icon = tk.Label(self.title_frame, image=coffee_icon1, bg='white') 61 | self.icon.grid(row=0, column=0, rowspan=2, padx=(10,3)) 62 | 63 | self.title = tk.Label(self.title_frame, width=24, height=2, 64 | text='Honest Bistro Cafe', font=('verdana',22,'bold'), fg="#248aa2", bg="white") 65 | self.title.grid(row=0, column=1, columnspan=3) 66 | 67 | self.l1 = tk.Label(self.title_frame, bg='#248aa2', width=25) 68 | self.l2 = tk.Label(self.title_frame, bg='#248aa2', width=5) 69 | self.l1.grid(row=1, column=1) 70 | self.l2.grid(row=1, column=3) 71 | 72 | self.date_time = tk.Label(self.title_frame, text=self.get_current_datetime(), 73 | fg='#fe4a49', font=('verdana', 12, 'bold')) 74 | self.date_time.after(1000, self.update_datetime_label) 75 | self.date_time.grid(row=1, column=2, padx=5) 76 | 77 | def draw_body_widgets(self): 78 | self.items_frame = CustomFrame(self.main_frame, text='Cafe Items', height=240, width=170) 79 | self.items_frame.grid(row=0, column=0, padx=(15,10), pady=15, rowspan=2, sticky='NW') 80 | 81 | self.bill_frame = CustomFrame(self.main_frame, text='Items Bill', height=200, width=192) 82 | self.bill_frame.grid(row=0, column=1, padx=10, pady=(15,0)) 83 | 84 | self.controller = CustomFrame(self.main_frame, width=192, height=30, borderwidth=0) 85 | self.controller.grid(row=1, column=1, padx=10, sticky='N') 86 | 87 | self.calculator = CustomFrame(self.main_frame, text='Calculator', height=200, width=168) 88 | self.calculator.grid(row=0, column=2, padx=5, pady=15, sticky='NW') 89 | 90 | self.contact = CustomFrame(self.main_frame, width=192, height=30, borderwidth=0) 91 | self.contact.grid(row=1, column=2, padx=10, sticky='N') 92 | 93 | l1 = tk.Label(self.contact, bg='#248aa2', width=25, height=2, 94 | text=' Opens 09:00 to 08:30 \n Contact : 876655444', 95 | font=('Verdana', 8, 'bold'), fg='white', anchor='w') 96 | l1.grid(row=0, column=0) 97 | 98 | self.items_frame.grid_propagate(False) 99 | self.bill_frame.grid_propagate(False) 100 | self.controller.grid_propagate(False) 101 | self.calculator.grid_propagate(False) 102 | 103 | def draw_item_frame_widgets(self): 104 | for row, item in enumerate(self.itemList): 105 | label = CustomLabel(self.items_frame, text=(' ' + item)) 106 | label.grid(row=row, column=0, pady=(4,0)) 107 | 108 | entry = CustomEntry(self.items_frame, textvariable=self.entryValues[row]) 109 | entry.grid(row=row, column=1, pady=(4,0)) 110 | 111 | def draw_bill_frame_widgets(self): 112 | self.chargeList = ['Items Cost', 'Service Charge', 'GST Charges','Discount', 'Total'] 113 | self.chargeValues = [tk.StringVar() for item in self.chargeList] 114 | 115 | for row, item in enumerate(self.chargeList): 116 | label = CustomLabel(self.bill_frame, text=item, width=12) 117 | label.grid(row=row, column=0, pady=(3,0)) 118 | 119 | entry = CustomEntry(self.bill_frame, textvariable=self.chargeValues[row]) 120 | entry.grid(row=row, column=1, pady=(3,0)) 121 | 122 | self.name_frame = tk.LabelFrame(self.bill_frame) 123 | self.name_frame.grid(row=5, column=0, columnspan=2, pady=(15,0), padx=3) 124 | 125 | self.customer_name = tk.StringVar() 126 | self.name = CustomLabel(self.name_frame, text='Name', width=7) 127 | self.name_entry = CustomEntry(self.name_frame, width=15, textvariable=self.customer_name) 128 | self.name.grid(row=0, column=0, pady=2, padx=1) 129 | self.name_entry.grid(row=0, column=1, pady=2, padx=1) 130 | 131 | def draw_controller_frame_widgets(self): 132 | self.total = CustomButton(self.controller, text='Calculate', 133 | command=self.calculate_payment) 134 | self.total.grid(row=0, column=0, padx=(2,0)) 135 | 136 | self.clear = CustomButton(self.controller, text='Clear', command=self.clear_all) 137 | self.clear.grid(row=0, column=1, padx=(2,0)) 138 | 139 | self.receipt = CustomButton(self.controller, text='Receipt', command=self.get_receipt) 140 | self.receipt.grid(row=0, column=2, padx=(2,0)) 141 | 142 | def draw_calculator_frame_widgets(self): 143 | self.input_string = tk.StringVar() 144 | self.calc_entry = CustomEntry(self.calculator, width=23, textvariable=self.input_string) 145 | self.calc_entry.grid(row=0, column=0, columnspan=4, pady=(5,3), padx=4) 146 | 147 | self.seven = self.create_button(self.calculator, '7', '#248aa2', "white", 148 | lambda : self.get('7'), 1, 0) 149 | self.eight = self.create_button(self.calculator, '8', '#248aa2', "white", 150 | lambda : self.get('8'), 1, 1) 151 | self.nine = self.create_button(self.calculator, '9', '#248aa2', "white", 152 | lambda : self.get('9'), 1, 2) 153 | self.plus = self.create_button(self.calculator, '+', 'white', "black", 154 | lambda : self.get('+'), 1, 3) 155 | self.four = self.create_button(self.calculator, '4', '#248aa2', "white", 156 | lambda : self.get('4'), 2, 0) 157 | self.five = self.create_button(self.calculator, '5', '#248aa2', "white", 158 | lambda : self.get('5'), 2, 1) 159 | self.six = self.create_button(self.calculator, '6', '#248aa2', "white", 160 | lambda : self.get('6'), 2, 2) 161 | self.minus = self.create_button(self.calculator, '-', 'white', "black", 162 | lambda : self.get('-'), 2, 3) 163 | self.one = self.create_button(self.calculator, '1', '#248aa2', "white", 164 | lambda : self.get('1'), 3, 0) 165 | self.two = self.create_button(self.calculator, '2', '#248aa2', "white", 166 | lambda : self.get('2'), 3, 1) 167 | self.three = self.create_button(self.calculator, '3', '#248aa2', "white", 168 | lambda : self.get('3'), 3, 2) 169 | self.mult = self.create_button(self.calculator, '*', 'white', "black", 170 | lambda : self.get('*'), 3, 3) 171 | self.clear = self.create_button(self.calculator, 'C', '#248aa2', "white", 172 | self.delete_calc_text, 4, 0) 173 | self.zero = self.create_button(self.calculator, '0', '#248aa2', "white", 174 | lambda : self.get('0'), 4, 1) 175 | self.equal = self.create_button(self.calculator, '=', '#248aa2', "white", 176 | self.evaluate_expression, 4, 2) 177 | self.div = self.create_button(self.calculator, '/', 'white', "black", 178 | lambda : self.get('/'), 4, 3) 179 | 180 | def create_button(self, parent, text, bg, fg, command, r, c): 181 | self.button = tk.Button(parent, bg=bg, fg=fg, font=('Arial',10, 'bold')) 182 | self.button['text'] = text 183 | self.button['command'] = command 184 | self.button.config(height=1, width=3) 185 | self.button.grid(row=r, column=c, pady=4) 186 | 187 | return self.button 188 | 189 | def get(self, value): 190 | ops = ['+', '-', '*', '/'] 191 | 192 | if self.expression == 'error': 193 | self.expression = '' 194 | 195 | if len(self.expression) == 0: 196 | if value in ['+', '-']: 197 | self.expression += value 198 | elif value in ['*', '/']: 199 | pass 200 | else: 201 | self.expression += value 202 | elif len(self.expression) > 0: 203 | if value in ops and self.expression[-1] in ops: 204 | self.expression = self.expression[:-1] + value 205 | else: 206 | self.expression += value 207 | 208 | self.input_string.set(self.expression) 209 | 210 | def evaluate_expression(self): 211 | if len(self.expression) > 0: 212 | try: 213 | self.expression = str(round(eval(self.expression), 2)) 214 | except: 215 | self.expression = 'error' 216 | 217 | self.input_string.set(self.expression) 218 | 219 | def delete_calc_text(self): 220 | self.expression = '' 221 | self.calc_entry.delete(0,'end') 222 | 223 | def get_current_datetime(self): 224 | dt = datetime.datetime.now() 225 | return dt.strftime('%b %d ,%Y %I:%M:%S %p') 226 | 227 | def update_datetime_label(self): 228 | dt = self.get_current_datetime() 229 | self.date_time['text'] = dt 230 | self.date_time.after(1000, self.update_datetime_label) 231 | 232 | def get_order_details(self): 233 | total_cost = 0 234 | 235 | for index, item in enumerate(self.itemList): 236 | qty = self.entryValues[index].get() 237 | if qty: 238 | self.hasBought = True 239 | cost = int(qty) * self.itemCost[item] 240 | total_cost += cost 241 | 242 | if self.hasBought: 243 | service_charge = round(0.04 * total_cost, 2) 244 | gst = round(0.05 * total_cost, 2) 245 | 246 | total = total_cost + service_charge + gst 247 | disc = 0 248 | for d in self.discount_dict.keys(): 249 | if total >= d: 250 | disc = d 251 | 252 | cut = self.discount_dict[disc] 253 | discount = round((cut / 100) * total_cost, 2) 254 | total = round(total - discount, 2) 255 | else: 256 | total_cost, service_charge, gst, discount, total = [0 for i in range(5)] 257 | 258 | return total_cost, service_charge, gst, discount, total 259 | 260 | def calculate_payment(self): 261 | self.hasBought = False 262 | total_cost, service_charge, gst, discount, total = self.get_order_details() 263 | 264 | if self.hasBought: 265 | self.chargeValues[0].set(str(total_cost)) 266 | self.chargeValues[1].set(str(service_charge)) 267 | self.chargeValues[2].set(str(gst)) 268 | self.chargeValues[3].set(str(discount)) 269 | self.chargeValues[4].set(str(total)) 270 | 271 | def get_receipt(self): 272 | if self.chargeValues[4].get() != '': 273 | total_cost, service_charge, gst, discount, total = [self.chargeValues[i].get() 274 | for i in range(5)] 275 | name = self.customer_name.get() 276 | if name: 277 | current = self.make_entry() 278 | with open(f'receipts/order_receipt_{current}.txt', 'w') as file: 279 | file.write('Order Summary\n') 280 | file.write(f'Customer Name : {name}\n') 281 | file.write(f'Order date time : {self.get_current_datetime()}\n\n') 282 | i, q, p, t = 'item', 'quantity', 'price', 'total cost' 283 | file.write(f' {i:<12} | {q:<8} | {p:<8} | {t:<12}\n') 284 | for index, item in enumerate(self.itemList): 285 | qty = self.entryValues[index].get() 286 | if qty: 287 | self.hasBought = True 288 | c = self.itemCost[item] 289 | cost = int(qty) * c 290 | 291 | file.write(f' {item.lower():<12}| {qty:<8} | {c:<8} | {cost:<12}\n') 292 | 293 | file.write('\n') 294 | file.write(f'SubCost : {total_cost}\n') 295 | file.write(f'Service Charge : {service_charge}\n') 296 | file.write(f'GST : {gst}\n') 297 | file.write(f'Discount : {discount}\n') 298 | file.write(f'Total Cost : {total}\n') 299 | 300 | messagebox.showinfo('Honest Bistro', 'Receipt Generated') 301 | else: 302 | messagebox.showerror('Honest Bistro', 'Customer Name is required.') 303 | else: 304 | messagebox.showerror('Honest Bistro', 'No items Bought') 305 | 306 | def make_entry(self): 307 | with open('receipts/orders.txt') as file: 308 | current = file.readline() 309 | 310 | current = int(current[6:]) + 1 311 | with open('receipts/orders.txt', 'w') as file: 312 | file.write(('OrderN'+str(current))) 313 | 314 | return current 315 | 316 | def clear_all(self): 317 | for index, item in enumerate(self.itemList): 318 | self.entryValues[index].set('') 319 | 320 | for index, item in enumerate(self.chargeList): 321 | self.chargeValues[index].set('') 322 | 323 | self.customer_name.set('') 324 | self.hasBought = False 325 | 326 | if __name__ == '__main__': 327 | root = tk.Tk() 328 | root.geometry('600x390') 329 | root.title('Honest Bistro') 330 | root.resizable(0,0) 331 | 332 | coffee_icon1 = PhotoImage(file='icons/coffee.png') 333 | 334 | app = Application(master=root) 335 | app.mainloop() -------------------------------------------------------------------------------- /Contact Management System/main.py: -------------------------------------------------------------------------------- 1 | #! python3 2 | """ 3 | @created: 07-11-2020 12:27:00 AM 4 | @author: Prajjwal Pathak ( pyGuru ) 5 | 6 | Contact Management System 7 | 8 | ------------------------------------------------------------------------------- 9 | Dependencies: 10 | 11 | No external package is required 12 | 13 | ------------------------------------------------------------------------------- 14 | Description : 15 | CMS is a advanced contact management system based on MVC architecture made using 16 | python and tkinter 17 | """ 18 | 19 | import re 20 | import tkinter as tk 21 | from tkinter import PhotoImage 22 | from tkinter import messagebox 23 | from collections import namedtuple 24 | 25 | import sql_operations 26 | from customWidgets import CustomSearch, CustomEntry, CustomPhone 27 | 28 | email_regex = r'^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$' 29 | 30 | class Application(tk.Frame): 31 | def __init__(self, master=None): 32 | super().__init__(master=master) 33 | self.master=master 34 | self.pack() 35 | 36 | self._attributes() 37 | self.contacts = sql_operations.fetch_all_result() 38 | 39 | self.draw_header_frames() 40 | self.draw_all_contact_frame() 41 | 42 | def _attributes(self): 43 | self.search_term = tk.StringVar() 44 | self.search_term.set('') 45 | 46 | self.edit_contacts = False 47 | self.on_home = True 48 | self.is_new_contact = False 49 | 50 | self.data = None 51 | 52 | def draw_header_frames(self): 53 | self.header = tk.Frame(self, width=300, height=50, bg='dodgerblue') 54 | self.header.grid(row=0, column=0) 55 | self.header.grid_propagate(False) 56 | 57 | self.header_label = tk.Label(self.header, text='Contacts', font=('Algerian', 24), 58 | bg='dodgerblue', fg='white') 59 | self.header_label.grid(row=0, column=0, ipadx=2, pady=5) 60 | 61 | def draw_all_contact_frame(self): 62 | # Frames 63 | self.contacts_frame = tk.Frame(self, width=300, height=400, bg='gray') 64 | self.search_bar = tk.Frame(self.contacts_frame, width=300, height=30) 65 | self.contact_box = tk.Frame(self.contacts_frame, width=300, height=320) 66 | self.bottom_menu = tk.Frame(self.contacts_frame, width=300, height=50, bg='dodgerblue3') 67 | 68 | self.contacts_frame.grid(row=1, column=0) 69 | self.search_bar.grid(row=0, column=0) 70 | self.contact_box.grid(row=1, column=0) 71 | self.bottom_menu.grid(row=2, column=0) 72 | 73 | self.contacts_frame.grid_propagate(False) 74 | self.search_bar.grid_propagate(False) 75 | self.contact_box.grid_propagate(False) 76 | self.bottom_menu.grid_propagate(False) 77 | 78 | # Widgets 79 | self.search_entry = CustomSearch(self.search_bar, width=32, textvariable=self.search_term) 80 | self.search_entry.grid(row=0, column=0, pady=5, padx=5) 81 | self.search_term.trace_add('write', self.enumerate_content) 82 | 83 | self.search_btn = tk.Button(self.search_bar, image=search_icon, 84 | relief=tk.FLAT) 85 | self.search_btn.grid(row=0, column=1, padx=60) 86 | 87 | self.contact_scroll = tk.Scrollbar(self.contact_box, orient=tk.VERTICAL) 88 | self.contact_scroll.grid(row=1, column=1, sticky='ns', pady=12) 89 | self.contact_list = tk.Listbox(self.contact_box, selectmode=tk.SINGLE, 90 | selectbackground='sky blue', fg='black', 91 | yscrollcommand=self.contact_scroll.set, font=('Times', 11)) 92 | self.contact_list.configure(height=16, width=39) 93 | self.contact_list.bind('', self.show_contact) 94 | self.contact_list.bind('', self.show_contact) 95 | self.contact_list.grid(row=1, column=0, padx=2, sticky='W', pady=12) 96 | self.contact_scroll.config(command=self.contact_list.yview) 97 | 98 | self.num_contacts = tk.Label(self.bottom_menu, text=f'{len(self.contacts)} contacts saved', 99 | fg='white', bg='dodgerblue3', font=('Times', 11), width=16, 100 | anchor='w') 101 | self.num_contacts.grid(row=0, column=0, padx=5, pady=8) 102 | 103 | self.add_new_btn = tk.Button(self.bottom_menu, text=' New', fg='white', image=new_contact_icon, 104 | relief=tk.FLAT, compound=tk.LEFT, font=('Times', 11), borderwidth=1, 105 | bg='dodgerblue3', command=self.create_new_contact) 106 | self.add_new_btn.grid(row=0, column=1, padx=80, pady=5) 107 | 108 | self.enumerate_content() 109 | 110 | def draw_display_contact_frame(self): 111 | self.search_term.set('') 112 | 113 | # frames 114 | self.new_contact_frame = tk.Frame(self, width=300, height=400, bg='gray') 115 | self.create_contact_frame = tk.Frame(self.new_contact_frame, width=300, height=350) 116 | self.bottom_menu = tk.Frame(self.new_contact_frame, width=300, height=50, bg='dodgerblue3') 117 | 118 | self.new_contact_frame.grid(row=1, column=0) 119 | self.create_contact_frame.grid(row=0, column=0) 120 | self.bottom_menu.grid(row=1, column=0) 121 | 122 | self.new_contact_frame.grid_propagate(False) 123 | self.create_contact_frame.grid_propagate(False) 124 | self.bottom_menu.grid_propagate(False) 125 | 126 | # widgets 127 | self.first = tk.LabelFrame(self.create_contact_frame, text='*First Name', bg='dodgerblue3', 128 | width=250, height=40, fg='white') 129 | self.last = tk.LabelFrame(self.create_contact_frame, text='Last Name', bg='dodgerblue3', 130 | width=250, height=40, fg='white') 131 | self.phone = tk.LabelFrame(self.create_contact_frame, text='*Phone', bg='dodgerblue3', 132 | width=250, height=40, fg='white') 133 | self.email = tk.LabelFrame(self.create_contact_frame, text='Email', bg='dodgerblue3', 134 | width=250, height=40, fg='white') 135 | 136 | self.first.grid(row=0, column=0, padx=25, pady=(30,0)) 137 | self.last.grid(row=1, column=0, padx=25, pady=(30,0)) 138 | self.phone.grid(row=2, column=0, padx=25, pady=(30,0)) 139 | self.email.grid(row=3, column=0, padx=25, pady=(30,0)) 140 | 141 | self.first.grid_propagate() 142 | self.last.grid_propagate() 143 | self.phone.grid_propagate() 144 | self.email.grid_propagate() 145 | 146 | if not self.edit_contacts: 147 | self.first_name = tk.Label(self.first, width=33, anchor='w') 148 | self.last_name = tk.Label(self.last, width=33, anchor='w') 149 | self.phone_number = tk.Label(self.phone, width=33, anchor='w') 150 | self.email_id = tk.Label(self.email, width=33, anchor='w') 151 | 152 | self.first_name.grid(row=0, column=0) 153 | self.last_name.grid(row=0, column=0) 154 | self.phone_number.grid(row=0, column=0) 155 | self.email_id.grid(row=0, column=0) 156 | 157 | self.back = tk.Button(self.bottom_menu, image=back_icon, bg='dodgerblue3', 158 | relief=tk.FLAT, command=self.go_back) 159 | self.copy = tk.Button(self.bottom_menu, image=copy_icon, bg='dodgerblue3', 160 | relief=tk.FLAT, command=self.copy_contact) 161 | self.edit = tk.Button(self.bottom_menu, image=edit_icon, bg='dodgerblue3', 162 | relief=tk.FLAT, command=self.edit_contact) 163 | self.delete = tk.Button(self.bottom_menu, image=delete_icon, bg='dodgerblue3', 164 | relief=tk.FLAT, command=self.delete_contact) 165 | 166 | self.back.grid(row=0, column=0, padx=(10,0), pady=4) 167 | self.copy.grid(row=0, column=1, padx=(40,0), pady=4) 168 | self.edit.grid(row=0, column=2, padx=(40,0), pady=4) 169 | self.delete.grid(row=0, column=3, padx=(40,0), pady=4) 170 | else: 171 | self.first_name = CustomEntry(self.first, width=39) 172 | self.last_name = tk.Entry(self.last, width=39) 173 | self.phone_number = CustomPhone(self.phone, width=39) 174 | self.email_id = tk.Entry(self.email, width=39) 175 | 176 | self.first_name.focus_set() 177 | 178 | self.first_name.grid(row=0, column=0) 179 | self.last_name.grid(row=0, column=0) 180 | self.phone_number.grid(row=0, column=0) 181 | self.email_id.grid(row=0, column=0) 182 | 183 | self.cancel = tk.Button(self.bottom_menu, image=cancel_icon, bg='dodgerblue3', 184 | relief=tk.FLAT, command=self.go_back) 185 | self.save_contact = tk.Button(self.bottom_menu, image=save_icon, bg='dodgerblue3', 186 | relief=tk.FLAT, activebackground='dodgerblue3', 187 | command=self.save_contact_in_db) 188 | 189 | self.cancel.grid(row=0, column=0, padx=5) 190 | self.save_contact.grid(row=0, column=1, padx=180) 191 | 192 | 193 | # Custom Functions 194 | 195 | def enumerate_content(self, var=None,indx=None, mode=None): 196 | self.contact_list.delete(0, tk.END) 197 | term = self.search_term.get() 198 | if term == '' or term == 'Search Contact': 199 | for index, contact in enumerate(self.contacts): 200 | self.contact_list.insert(index, (' ' + contact[0] + ' ' + contact[1])) 201 | self.num_contacts['text'] = f'{len(self.contacts)} contacts saved' 202 | else: 203 | temp_contact = [contact for contact in self.contacts if 204 | (term.lower() in (contact[0].lower() + ' ' + contact[1].lower()))] 205 | for index, contact in enumerate(temp_contact): 206 | self.contact_list.insert(index, (' ' + contact[0] + ' ' + contact[1])) 207 | self.num_contacts['text'] = f'{len(temp_contact)} contacts found' 208 | 209 | def show_contact(self, event=None): 210 | if event: 211 | widget = event.widget 212 | selection=widget.curselection() 213 | if selection: 214 | self.data = self.contacts[selection[0]] 215 | 216 | if self.data: 217 | self.on_home = True 218 | self.edit_contacts = False 219 | self.draw_display_contact_frame() 220 | 221 | self.first_name['text'] = self.data[0] 222 | self.last_name['text'] = self.data[1] 223 | self.phone_number['text'] = self.data[2] 224 | self.email_id['text'] = self.data[3] 225 | 226 | self.prev = self.data 227 | self.update() 228 | 229 | def copy_contact(self): 230 | self.clipboard_clear() 231 | self.clipboard_append(self.data[2]) 232 | messagebox.showinfo('CMS', 'Phone number copied to clipboard') 233 | 234 | def edit_contact(self): 235 | self.on_home = False 236 | self.is_new_contact = False 237 | self.edit_contacts = True 238 | self.new_contact_frame.destroy() 239 | self.draw_display_contact_frame() 240 | 241 | self.first_name.delete(0, tk.END) 242 | self.first_name.insert(0, self.data[0]) 243 | self.last_name.delete(0, tk.END) 244 | self.last_name.insert(0, self.data[1]) 245 | self.phone_number.delete(0, tk.END) 246 | self.phone_number.insert(0, self.data[2]) 247 | self.email_id.delete(0, tk.END) 248 | self.email_id.insert(0, self.data[3]) 249 | 250 | def create_new_contact(self): 251 | self.on_home = True 252 | self.is_new_contact = True 253 | self.edit_contacts = True 254 | self.draw_display_contact_frame() 255 | 256 | def save_contact_in_db(self): 257 | first_name = self.first_name.get().strip().lower().capitalize() 258 | last_name = self.last_name.get().strip().lower().capitalize() 259 | phone = self.phone_number.get().strip() 260 | email = self.email_id.get().strip() 261 | 262 | temp_contact = [(contact[0] + ' ' + contact[1]) for contact in self.contacts] 263 | 264 | if (first_name == '' or first_name == 'This field is required' or phone == '' 265 | or phone == 'This field is required'): 266 | messagebox.showerror('CMS', 'Fill in the Mandatory Fields') 267 | elif len(phone) != 10: 268 | messagebox.showerror('CMS', 'Enter 10 digit phone number') 269 | elif email and not valid_email(email): 270 | messagebox.showerror('CMS', 'Invalid email') 271 | else: 272 | if self.is_new_contact: 273 | if (first_name + ' ' + last_name) in temp_contact: 274 | messagebox.showerror('CMS', 'Contact with this name already\nexist, edit & try again') 275 | else: 276 | status = sql_operations.insert_item([first_name ,last_name, phone, email]) 277 | if status == 'success': 278 | messagebox.showinfo('CMS', 'Contact Saved') 279 | else: 280 | messagebox.showerror('CMS', 'An error Occured') 281 | 282 | self.contacts = sql_operations.fetch_all_result() 283 | self.data = (first_name ,last_name, phone, email) 284 | self.show_contact() 285 | else: 286 | status = sql_operations.delete_item(self.prev[0], self.prev[1]) 287 | if status == 'success': 288 | status = sql_operations.insert_item([first_name ,last_name, phone, email]) 289 | if status == 'success': 290 | messagebox.showinfo('CMS', 'Contact Saved') 291 | else: 292 | messagebox.showerror('CMS', 'An error Occured') 293 | 294 | self.contacts = sql_operations.fetch_all_result() 295 | self.data = (first_name ,last_name, phone, email) 296 | self.prev = self.data 297 | self.show_contact() 298 | 299 | def delete_contact(self): 300 | status = sql_operations.delete_item(self.data[0], self.data[1]) 301 | if status == 'success': 302 | messagebox.showinfo('CMS', 'Contact deleted') 303 | else: 304 | messagebox.showerror('CMS', 'An error Occured') 305 | 306 | self.contacts = sql_operations.fetch_all_result() 307 | self.data = None 308 | self.on_home = True 309 | self.go_back() 310 | 311 | def go_back(self): 312 | if self.on_home: 313 | self.new_contact_frame.destroy() 314 | self.draw_all_contact_frame() 315 | self.update() 316 | else: 317 | self.new_contact_frame.destroy() 318 | self.show_contact() 319 | 320 | def valid_email(email): 321 | if re.fullmatch(email_regex, email): 322 | return True 323 | return False 324 | 325 | if __name__ == '__main__': 326 | root = tk.Tk() 327 | root.geometry('300x450') 328 | root.title('CMS') 329 | root.iconbitmap('icons/phone.ico') 330 | root.wm_resizable(0,0) 331 | 332 | search_icon = PhotoImage(file='icons/search.png') 333 | new_contact_icon = PhotoImage(file='icons/new.png') 334 | save_icon = PhotoImage(file='icons/save.png') 335 | back_icon = PhotoImage(file='icons/back.png') 336 | copy_icon = PhotoImage(file='icons/copy.png') 337 | delete_icon = PhotoImage(file='icons/delete.png') 338 | edit_icon = PhotoImage(file='icons/edit.png') 339 | cancel_icon = PhotoImage(file='icons/cancel.png') 340 | 341 | app = Application(master=root) 342 | app.mainloop() --------------------------------------------------------------------------------