├── Database └── store.db ├── LICENSE ├── README.md ├── admin.py ├── employee.py ├── fonts ├── Podkova-Regular.ttf ├── Poppins-Light.ttf ├── Poppins-Regular.ttf └── Poppins-SemiBold.ttf ├── images ├── 1.png ├── 2.png ├── add_employee.png ├── add_product.png ├── admin.png ├── admin_login.png ├── bill.png ├── bill_window.png ├── employee.png ├── employee_login.png ├── inventory.png ├── invoices.png ├── main.png ├── update_employee.png └── update_product.png └── main.py /Database/store.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/Database/store.db -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Prit Kalariya 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Billing Software with Inventory and Employee Management 2 | 3 | This is a Billing Software project, with Inventory and Employee Management. It is made using Python 3.7. Make sure you star the repo if you like it. 4 | 5 | ## Pre-Requisites 6 | `Python 3.7` 7 | 8 | ## Run / Execute 9 | $ python main.py 10 | 11 | ## Screenshots 12 | #### Main PAGE 13 | ![main window](https://github.com/PritKalariya/Billing-Software/blob/main/images/main.png) 14 | 15 | #### Employee Login PAGE 16 | ![Employee Login window](https://github.com/PritKalariya/Billing-Software/blob/main/images/employee_login.png) 17 | 18 | #### Billing Window 19 | ![Billing window](https://github.com/PritKalariya/Billing-Software/blob/main/images/bill_window.png) 20 | 21 | #### Admin DASHBOARD 22 | ![Admin Dashboard](https://github.com/PritKalariya/Billing-Software/blob/main/images/admin.png) 23 | 24 | ## Login Information 25 | #### Admin Login 26 | id: EMP1000
27 | password: admin01 28 | 29 | #### Employee Login 30 | id: EMP3000
31 | password: emp01 32 | -------------------------------------------------------------------------------- /admin.py: -------------------------------------------------------------------------------- 1 | # ==================imports=================== 2 | import sqlite3 3 | import re 4 | import random 5 | import string 6 | from tkinter import * 7 | from tkinter import messagebox 8 | from tkinter import ttk 9 | from time import strftime 10 | from datetime import date 11 | from tkinter import scrolledtext as tkst 12 | # ============================================ 13 | 14 | root = Tk() 15 | root.geometry("1366x768") 16 | root.title("Billing Software(ADMIN)") 17 | 18 | 19 | user = StringVar() 20 | passwd = StringVar() 21 | fname = StringVar() 22 | lname = StringVar() 23 | 24 | 25 | with sqlite3.connect("./Database/store.db") as db: 26 | cur = db.cursor() 27 | 28 | 29 | def random_emp_id(stringLength): 30 | Digits = string.digits 31 | strr=''.join(random.choice(Digits) for i in range(stringLength-3)) 32 | return ('EMP'+ strr) 33 | 34 | 35 | def valid_phone(phn): 36 | if re.match(r"[789]\d{9}$", phn): 37 | return True 38 | return False 39 | 40 | 41 | def valid_aadhar(aad): 42 | if aad.isdigit() and len(aad) == 12: 43 | return True 44 | return False 45 | 46 | 47 | class login_page: 48 | def __init__(self, top=None): 49 | top.geometry("1366x768") 50 | top.resizable(0, 0) 51 | top.title("Billing Software(ADMIN)") 52 | 53 | 54 | self.label1 = Label(root) 55 | self.label1.place(relx=0, rely=0, width=1366, height=768) 56 | self.img = PhotoImage(file="./images/admin_login.png") 57 | self.label1.configure(image=self.img) 58 | 59 | 60 | self.entry1 = Entry(root) 61 | self.entry1.place(relx=0.403, rely=0.269, width=374, height=24) 62 | self.entry1.configure( 63 | font="-family {Poppins} -size 10", 64 | relief="flat", 65 | textvariable=user 66 | ) 67 | 68 | self.entry2 = Entry(root) 69 | self.entry2.place(relx=0.403, rely=0.384, width=374, height=24) 70 | self.entry2.configure( 71 | font="-family {Poppins} -size 10", 72 | relief="flat", 73 | show="*", 74 | textvariable=passwd 75 | ) 76 | 77 | self.button1 = Button(root) 78 | self.button1.place(relx=0.397, rely=0.683, width=356, height=43) 79 | self.button1.configure( 80 | relief="flat", 81 | overrelief="flat", 82 | activebackground="#D2463E", 83 | cursor="hand2", 84 | foreground="#ffffff", 85 | background="#D2463E", 86 | font="-family {Poppins SemiBold} -size 20", 87 | borderwidth="0", 88 | text="Login", 89 | command=self.login 90 | ) 91 | 92 | def login(self, Event=None): 93 | username = user.get() 94 | password = passwd.get() 95 | 96 | with sqlite3.connect("./Database/store.db") as db: 97 | cur = db.cursor() 98 | find_user = "SELECT * FROM employee WHERE emp_id = ? and password = ?" 99 | cur.execute(find_user, [username, password]) 100 | results = cur.fetchall() 101 | if results: 102 | if results[0][6]=="Admin": 103 | messagebox.showinfo("Login Page", "The login is successful.") 104 | page1.entry1.delete(0, END) 105 | page1.entry2.delete(0, END) 106 | 107 | root.withdraw() 108 | global adm 109 | global page2 110 | adm = Toplevel() 111 | page2 = Admin_Page(adm) 112 | adm.protocol("WM_DELETE_WINDOW", exitt) 113 | adm.mainloop() 114 | else: 115 | messagebox.showerror("Oops!!", "You are not an admin.") 116 | 117 | else: 118 | messagebox.showerror("Error", "Incorrect username or password.") 119 | page1.entry2.delete(0, END) 120 | 121 | 122 | def exitt(): 123 | sure = messagebox.askyesno("Exit","Are you sure you want to exit?", parent=root) 124 | if sure == True: 125 | adm.destroy() 126 | root.destroy() 127 | 128 | 129 | def inventory(): 130 | adm.withdraw() 131 | global inv 132 | global page3 133 | inv = Toplevel() 134 | page3 = Inventory(inv) 135 | page3.time() 136 | inv.protocol("WM_DELETE_WINDOW", exitt) 137 | inv.mainloop() 138 | 139 | 140 | def employee(): 141 | adm.withdraw() 142 | global emp 143 | global page5 144 | emp = Toplevel() 145 | page5 = Employee(emp) 146 | page5.time() 147 | emp.protocol("WM_DELETE_WINDOW", exitt) 148 | emp.mainloop() 149 | 150 | 151 | def invoices(): 152 | adm.withdraw() 153 | global invoice 154 | invoice = Toplevel() 155 | page7 = Invoice(invoice) 156 | page7.time() 157 | invoice.protocol("WM_DELETE_WINDOW", exitt) 158 | invoice.mainloop() 159 | 160 | 161 | def about(): 162 | pass 163 | 164 | 165 | class Admin_Page: 166 | def __init__(self, top=None): 167 | top.geometry("1366x768") 168 | top.resizable(0, 0) 169 | top.title("ADMIN Mode") 170 | 171 | 172 | self.label1 = Label(adm) 173 | self.label1.place(relx=0, rely=0, width=1366, height=768) 174 | self.img = PhotoImage(file="./images/admin.png") 175 | self.label1.configure(image=self.img) 176 | 177 | 178 | self.button1 = Button(adm) 179 | self.button1.place(relx=0.035, rely=0.106, width=76, height=23) 180 | self.button1.configure( 181 | relief="flat", 182 | overrelief="flat", 183 | activebackground="#CF1E14", 184 | cursor="hand2", 185 | foreground="#ffffff", 186 | background="#CF1E14", 187 | font="-family {Poppins SemiBold} -size 12", 188 | borderwidth="0", 189 | text="Logout", 190 | command=self.Logout 191 | ) 192 | 193 | self.button2 = Button(adm) 194 | self.button2.place(relx=0.14, rely=0.508, width=146, height=63) 195 | self.button2.configure( 196 | relief="flat", 197 | overrelief="flat", 198 | activebackground="#ffffff", 199 | cursor="hand2", 200 | foreground="#333333", 201 | background="#ffffff", 202 | font="-family {Poppins SemiBold} -size 12", 203 | borderwidth="0", 204 | text="Inventory", 205 | command=inventory 206 | ) 207 | 208 | self.button3 = Button(adm) 209 | self.button3.place(relx=0.338, rely=0.508, width=146, height=63) 210 | self.button3.configure( 211 | relief="flat", 212 | overrelief="flat", 213 | activebackground="#ffffff", 214 | cursor="hand2", 215 | foreground="#333333", 216 | background="#ffffff", 217 | font="-family {Poppins SemiBold} -size 12", 218 | borderwidth="0", 219 | text="""Employees""", 220 | command=employee 221 | ) 222 | 223 | 224 | self.button4 = Button(adm) 225 | self.button4.place(relx=0.536, rely=0.508, width=146, height=63) 226 | self.button4.configure( 227 | relief="flat", 228 | overrelief="flat", 229 | activebackground="#ffffff", 230 | cursor="hand2", 231 | foreground="#333333", 232 | background="#ffffff", 233 | font="-family {Poppins SemiBold} -size 12", 234 | borderwidth="0", 235 | text="Invoices", 236 | command=invoices 237 | ) 238 | 239 | 240 | self.button5 = Button(adm) 241 | self.button5.place(relx=0.732, rely=0.508, width=146, height=63) 242 | self.button5.configure( 243 | relief="flat", 244 | overrelief="flat", 245 | activebackground="#ffffff", 246 | cursor="hand2", 247 | foreground="#333333", 248 | background="#ffffff", 249 | font="-family {Poppins SemiBold} -size 12", 250 | borderwidth="0", 251 | text="""About Us""", 252 | command=about 253 | ) 254 | 255 | def Logout(self): 256 | sure = messagebox.askyesno("Logout", "Are you sure you want to logout?", parent=adm) 257 | if sure == True: 258 | adm.destroy() 259 | root.deiconify() 260 | page1.entry1.delete(0, END) 261 | page1.entry2.delete(0, END) 262 | 263 | 264 | class Inventory: 265 | def __init__(self, top=None): 266 | top.geometry("1366x768") 267 | top.resizable(0, 0) 268 | top.title("Inventory") 269 | 270 | self.label1 = Label(inv) 271 | self.label1.place(relx=0, rely=0, width=1366, height=768) 272 | self.img = PhotoImage(file="./images/inventory.png") 273 | self.label1.configure(image=self.img) 274 | 275 | self.message = Label(inv) 276 | self.message.place(relx=0.046, rely=0.055, width=136, height=30) 277 | self.message.configure( 278 | font="-family {Poppins} -size 10", 279 | foreground="#000000", 280 | background="#ffffff", 281 | text="ADMIN", 282 | anchor="w" 283 | ) 284 | 285 | self.clock = Label(inv) 286 | self.clock.place(relx=0.9, rely=0.065, width=102, height=36) 287 | self.clock.configure( 288 | font="-family {Poppins Light} -size 12", 289 | foreground="#000000", 290 | background="#ffffff" 291 | ) 292 | 293 | self.entry1 = Entry(inv) 294 | self.entry1.place(relx=0.040, rely=0.286, width=240, height=28) 295 | self.entry1.configure( 296 | font="-family {Poppins} -size 12", 297 | relief="flat" 298 | ) 299 | 300 | self.button1 = Button(inv) 301 | self.button1.place(relx=0.229, rely=0.289, width=76, height=23) 302 | self.button1.configure( 303 | relief="flat", 304 | overrelief="flat", 305 | activebackground="#CF1E14", 306 | cursor="hand2", 307 | foreground="#ffffff", 308 | background="#CF1E14", 309 | font="-family {Poppins SemiBold} -size 10", 310 | borderwidth="0", 311 | text="Search", 312 | command=self.search_product 313 | ) 314 | 315 | self.button2 = Button(inv) 316 | self.button2.place(relx=0.035, rely=0.106, width=76, height=23) 317 | self.button2.configure( 318 | relief="flat", 319 | overrelief="flat", 320 | activebackground="#CF1E14", 321 | cursor="hand2", 322 | foreground="#ffffff", 323 | background="#CF1E14", 324 | font="-family {Poppins SemiBold} -size 10", 325 | borderwidth="0", 326 | text="Logout", 327 | command=self.Logout 328 | ) 329 | 330 | self.button3 = Button(inv) 331 | self.button3.place(relx=0.052, rely=0.432, width=306, height=28) 332 | self.button3.configure( 333 | relief="flat", 334 | overrelief="flat", 335 | activebackground="#CF1E14", 336 | cursor="hand2", 337 | foreground="#ffffff", 338 | background="#CF1E14", 339 | font="-family {Poppins SemiBold} -size 10", 340 | borderwidth="0", 341 | text="ADD PRODUCT", 342 | command=self.add_product 343 | ) 344 | 345 | self.button4 = Button(inv) 346 | self.button4.place(relx=0.052, rely=0.5, width=306, height=28) 347 | self.button4.configure( 348 | relief="flat", 349 | overrelief="flat", 350 | activebackground="#CF1E14", 351 | cursor="hand2", 352 | foreground="#ffffff", 353 | background="#CF1E14", 354 | font="-family {Poppins SemiBold} -size 10", 355 | borderwidth="0", 356 | text="UPDATE PRODUCT", 357 | command=self.update_product 358 | ) 359 | 360 | self.button5 = Button(inv) 361 | self.button5.place(relx=0.052, rely=0.57, width=306, height=28) 362 | self.button5.configure( 363 | relief="flat", 364 | overrelief="flat", 365 | activebackground="#CF1E14", 366 | cursor="hand2", 367 | foreground="#ffffff", 368 | background="#CF1E14", 369 | font="-family {Poppins SemiBold} -size 10", 370 | borderwidth="0", 371 | text="DELETE PRODUCT", 372 | command=self.delete_product 373 | ) 374 | 375 | self.button6 = Button(inv) 376 | self.button6.place(relx=0.135, rely=0.885, width=76, height=23) 377 | self.button6.configure( 378 | relief="flat", 379 | overrelief="flat", 380 | activebackground="#CF1E14", 381 | cursor="hand2", 382 | foreground="#ffffff", 383 | background="#CF1E14", 384 | font="-family {Poppins SemiBold} -size 10", 385 | borderwidth="0", 386 | text="EXIT", 387 | command=self.Exit 388 | ) 389 | 390 | self.scrollbarx = Scrollbar(inv, orient=HORIZONTAL) 391 | self.scrollbary = Scrollbar(inv, orient=VERTICAL) 392 | self.tree = ttk.Treeview(inv) 393 | self.tree.place(relx=0.307, rely=0.203, width=880, height=550) 394 | self.tree.configure( 395 | yscrollcommand=self.scrollbary.set, xscrollcommand=self.scrollbarx.set 396 | ) 397 | self.tree.configure(selectmode="extended") 398 | 399 | self.tree.bind("<>", self.on_tree_select) 400 | 401 | self.scrollbary.configure(command=self.tree.yview) 402 | self.scrollbarx.configure(command=self.tree.xview) 403 | 404 | self.scrollbary.place(relx=0.954, rely=0.203, width=22, height=548) 405 | self.scrollbarx.place(relx=0.307, rely=0.924, width=884, height=22) 406 | 407 | self.tree.configure( 408 | columns=( 409 | "Product ID", 410 | "Name", 411 | "Category", 412 | "Sub-Category", 413 | "In Stock", 414 | "MRP", 415 | "Cost Price", 416 | "Vendor No.", 417 | ) 418 | ) 419 | 420 | self.tree.heading("Product ID", text="Product ID", anchor=W) 421 | self.tree.heading("Name", text="Name", anchor=W) 422 | self.tree.heading("Category", text="Category", anchor=W) 423 | self.tree.heading("Sub-Category", text="Sub-Category", anchor=W) 424 | self.tree.heading("In Stock", text="In Stock", anchor=W) 425 | self.tree.heading("MRP", text="MRP", anchor=W) 426 | self.tree.heading("Cost Price", text="Cost Price", anchor=W) 427 | self.tree.heading("Vendor No.", text="Vendor No.", anchor=W) 428 | 429 | self.tree.column("#0", stretch=NO, minwidth=0, width=0) 430 | self.tree.column("#1", stretch=NO, minwidth=0, width=80) 431 | self.tree.column("#2", stretch=NO, minwidth=0, width=260) 432 | self.tree.column("#3", stretch=NO, minwidth=0, width=100) 433 | self.tree.column("#4", stretch=NO, minwidth=0, width=120) 434 | self.tree.column("#5", stretch=NO, minwidth=0, width=80) 435 | self.tree.column("#6", stretch=NO, minwidth=0, width=80) 436 | self.tree.column("#7", stretch=NO, minwidth=0, width=80) 437 | self.tree.column("#8", stretch=NO, minwidth=0, width=100) 438 | 439 | self.DisplayData() 440 | 441 | 442 | def DisplayData(self): 443 | cur.execute("SELECT * FROM raw_inventory") 444 | fetch = cur.fetchall() 445 | for data in fetch: 446 | self.tree.insert("", "end", values=(data)) 447 | 448 | 449 | def search_product(self): 450 | val = [] 451 | for i in self.tree.get_children(): 452 | val.append(i) 453 | for j in self.tree.item(i)["values"]: 454 | val.append(j) 455 | 456 | try: 457 | to_search = int(self.entry1.get()) 458 | except ValueError: 459 | messagebox.showerror("Oops!!", "Invalid Product Id.", parent=inv) 460 | else: 461 | for search in val: 462 | if search == to_search: 463 | self.tree.selection_set(val[val.index(search) - 1]) 464 | self.tree.focus(val[val.index(search) - 1]) 465 | messagebox.showinfo("Success!!", f"Product ID: {self.entry1.get()} found.", parent=inv) 466 | break 467 | else: 468 | messagebox.showerror("Oops!!", f"Product ID: {self.entry1.get()} not found.", parent=inv) 469 | 470 | 471 | sel = [] 472 | def on_tree_select(self, Event): 473 | self.sel.clear() 474 | for i in self.tree.selection(): 475 | if i not in self.sel: 476 | self.sel.append(i) 477 | 478 | 479 | def delete_product(self): 480 | val = [] 481 | to_delete = [] 482 | 483 | if len(self.sel) != 0: 484 | sure = messagebox.askyesno("Confirm", "Are you sure you want to delete selected products?", parent=inv) 485 | if sure == True: 486 | for i in self.sel: 487 | for j in self.tree.item(i)["values"]: 488 | val.append(j) 489 | 490 | for j in range(len(val)): 491 | if j % 8 == 0: 492 | to_delete.append(val[j]) 493 | 494 | for k in to_delete: 495 | delete = "DELETE FROM raw_inventory WHERE product_id = ?" 496 | cur.execute(delete, [k]) 497 | db.commit() 498 | 499 | messagebox.showinfo("Success!!", "Products deleted from database.", parent=inv) 500 | self.sel.clear() 501 | self.tree.delete(*self.tree.get_children()) 502 | 503 | self.DisplayData() 504 | else: 505 | messagebox.showerror("Error!!","Please select a product.", parent=inv) 506 | 507 | 508 | def update_product(self): 509 | if len(self.sel) == 1: 510 | global p_update 511 | p_update = Toplevel() 512 | page9 = Update_Product(p_update) 513 | page9.time() 514 | p_update.protocol("WM_DELETE_WINDOW", self.ex2) 515 | global valll 516 | valll = [] 517 | for i in self.sel: 518 | for j in self.tree.item(i)["values"]: 519 | valll.append(j) 520 | 521 | page9.entry1.insert(0, valll[1]) 522 | page9.entry2.insert(0, valll[2]) 523 | page9.entry3.insert(0, valll[4]) 524 | page9.entry4.insert(0, valll[5]) 525 | page9.entry5.insert(0, valll[3]) 526 | page9.entry6.insert(0, valll[6]) 527 | page9.entry7.insert(0, valll[7]) 528 | 529 | 530 | elif len(self.sel) == 0: 531 | messagebox.showerror("Error","Please choose a product to update.", parent=inv) 532 | else: 533 | messagebox.showerror("Error","Can only update one product at a time.", parent=inv) 534 | 535 | p_update.mainloop() 536 | 537 | 538 | def add_product(self): 539 | global p_add 540 | global page4 541 | p_add = Toplevel() 542 | page4 = add_product(p_add) 543 | page4.time() 544 | p_add.mainloop() 545 | 546 | 547 | def time(self): 548 | string = strftime("%H:%M:%S %p") 549 | self.clock.config(text=string) 550 | self.clock.after(1000, self.time) 551 | 552 | 553 | def Exit(self): 554 | sure = messagebox.askyesno("Exit","Are you sure you want to exit?", parent=inv) 555 | if sure == True: 556 | inv.destroy() 557 | adm.deiconify() 558 | 559 | 560 | def ex2(self): 561 | sure = messagebox.askyesno("Exit","Are you sure you want to exit?", parent=p_update) 562 | if sure == True: 563 | p_update.destroy() 564 | inv.deiconify() 565 | 566 | 567 | def Logout(self): 568 | sure = messagebox.askyesno("Logout", "Are you sure you want to logout?") 569 | if sure == True: 570 | root.deiconify() 571 | page1.entry1.delete(0, END) 572 | page1.entry2.delete(0, END) 573 | 574 | 575 | class add_product: 576 | def __init__(self, top=None): 577 | top.geometry("1366x768") 578 | top.resizable(0, 0) 579 | top.title("Add Product") 580 | 581 | 582 | self.label1 = Label(p_add) 583 | self.label1.place(relx=0, rely=0, width=1366, height=768) 584 | self.img = PhotoImage(file="./images/add_product.png") 585 | self.label1.configure(image=self.img) 586 | 587 | 588 | self.clock = Label(p_add) 589 | self.clock.place(relx=0.84, rely=0.065, width=102, height=36) 590 | self.clock.configure( 591 | font="-family {Poppins Light} -size 12", 592 | foreground="#000000", 593 | background="#ffffff" 594 | ) 595 | 596 | 597 | self.entry1 = Entry(p_add) 598 | self.entry1.place(relx=0.132, rely=0.296, width=996, height=30) 599 | self.entry1.configure( 600 | font="-family {Poppins} -size 12", 601 | relief="flat" 602 | ) 603 | 604 | self.entry2 = Entry(p_add) 605 | self.entry2.place(relx=0.132, rely=0.413, width=374, height=30) 606 | self.entry2.configure( 607 | font="-family {Poppins} -size 12", 608 | relief="flat" 609 | ) 610 | 611 | self.r2 = p_add.register(self.testint) 612 | 613 | self.entry3 = Entry(p_add) 614 | self.entry3.place(relx=0.132, rely=0.529, width=374, height=30) 615 | self.entry3.configure( 616 | font="-family {Poppins} -size 12", 617 | relief="flat", 618 | validate="key", 619 | validatecommand=(self.r2, "%P") 620 | ) 621 | 622 | self.entry4 = Entry(p_add) 623 | self.entry4.place(relx=0.132, rely=0.646, width=374, height=30) 624 | self.entry4.configure( 625 | font="-family {Poppins} -size 12", 626 | relief="flat" 627 | ) 628 | 629 | self.entry5 = Entry(p_add) 630 | self.entry5.place(relx=0.527, rely=0.413, width=374, height=30) 631 | self.entry5.configure( 632 | font="-family {Poppins} -size 12", 633 | relief="flat" 634 | ) 635 | 636 | self.entry6 = Entry(p_add) 637 | self.entry6.place(relx=0.527, rely=0.529, width=374, height=30) 638 | self.entry6.configure( 639 | font="-family {Poppins} -size 12", 640 | relief="flat" 641 | ) 642 | 643 | self.entry7 = Entry(p_add) 644 | self.entry7.place(relx=0.527, rely=0.646, width=374, height=30) 645 | self.entry7.configure( 646 | font="-family {Poppins} -size 12", 647 | relief="flat", 648 | validate="key", 649 | validatecommand=(self.r2, "%P") 650 | ) 651 | 652 | 653 | self.button1 = Button(p_add) 654 | self.button1.place(relx=0.408, rely=0.836, width=96, height=34) 655 | self.button1.configure( 656 | relief="flat", 657 | overrelief="flat", 658 | activebackground="#CF1E14", 659 | cursor="hand2", 660 | foreground="#ffffff", 661 | background="#CF1E14", 662 | font="-family {Poppins SemiBold} -size 14", 663 | borderwidth="0", 664 | text="ADD", 665 | command=self.add 666 | ) 667 | 668 | self.button2 = Button(p_add) 669 | self.button2.place(relx=0.526, rely=0.836, width=86, height=34) 670 | self.button2.configure( 671 | relief="flat", 672 | overrelief="flat", 673 | activebackground="#CF1E14", 674 | cursor="hand2", 675 | foreground="#ffffff", 676 | background="#CF1E14", 677 | font="-family {Poppins SemiBold} -size 14", 678 | borderwidth="0", 679 | text="CLEAR", 680 | command=self.clearr 681 | ) 682 | 683 | 684 | def add(self): 685 | pname = self.entry1.get() 686 | pcat = self.entry2.get() 687 | pqty = self.entry3.get() 688 | pmrp = self.entry4.get() 689 | psubcat = self.entry5.get() 690 | pcp = self.entry6.get() 691 | pvendor = self.entry7.get() 692 | 693 | if pname.strip(): 694 | if pcat.strip(): 695 | if psubcat.strip(): 696 | if pqty: 697 | if pcp: 698 | try: 699 | float(pcp) 700 | except ValueError: 701 | messagebox.showerror("Oops!", "Invalid cost price.", parent=p_add) 702 | else: 703 | if pmrp: 704 | try: 705 | float(pmrp) 706 | except ValueError: 707 | messagebox.showerror("Oops!", "Invalid MRP.", parent=p_add) 708 | else: 709 | if valid_phone(pvendor): 710 | with sqlite3.connect("./Database/store.db") as db: 711 | cur = db.cursor() 712 | insert = ( 713 | "INSERT INTO raw_inventory(product_name, product_cat, product_subcat, stock, mrp, cost_price, vendor_phn) VALUES(?,?,?,?,?,?,?)" 714 | ) 715 | cur.execute(insert, [pname, pcat, psubcat, int(pqty), float(pmrp), float(pcp), pvendor]) 716 | db.commit() 717 | messagebox.showinfo("Success!!", "Product successfully added in inventory.", parent=p_add) 718 | p_add.destroy() 719 | page3.tree.delete(*page3.tree.get_children()) 720 | page3.DisplayData() 721 | p_add.destroy() 722 | else: 723 | messagebox.showerror("Oops!", "Invalid phone number.", parent=p_add) 724 | else: 725 | messagebox.showerror("Oops!", "Please enter MRP.", parent=p_add) 726 | else: 727 | messagebox.showerror("Oops!", "Please enter product cost price.", parent=p_add) 728 | else: 729 | messagebox.showerror("Oops!", "Please enter product quantity.", parent=p_add) 730 | else: 731 | messagebox.showerror("Oops!", "Please enter product sub-category.", parent=p_add) 732 | else: 733 | messagebox.showerror("Oops!", "Please enter product category.", parent=p_add) 734 | else: 735 | messagebox.showerror("Oops!", "Please enter product name", parent=p_add) 736 | 737 | 738 | def clearr(self): 739 | self.entry1.delete(0, END) 740 | self.entry2.delete(0, END) 741 | self.entry3.delete(0, END) 742 | self.entry4.delete(0, END) 743 | self.entry5.delete(0, END) 744 | self.entry6.delete(0, END) 745 | self.entry7.delete(0, END) 746 | 747 | 748 | def testint(self, val): 749 | if val.isdigit(): 750 | return True 751 | elif val == "": 752 | return True 753 | return False 754 | 755 | 756 | def time(self): 757 | string = strftime("%H:%M:%S %p") 758 | self.clock.config(text=string) 759 | self.clock.after(1000, self.time) 760 | 761 | 762 | class Update_Product: 763 | def __init__(self, top=None): 764 | top.geometry("1366x768") 765 | top.resizable(0, 0) 766 | top.title("Add Product") 767 | 768 | 769 | self.label1 = Label(p_update) 770 | self.label1.place(relx=0, rely=0, width=1366, height=768) 771 | self.img = PhotoImage(file="./images/update_product.png") 772 | self.label1.configure(image=self.img) 773 | 774 | 775 | self.clock = Label(p_update) 776 | self.clock.place(relx=0.84, rely=0.065, width=102, height=36) 777 | self.clock.configure( 778 | font="-family {Poppins Light} -size 12", 779 | foreground="#000000", 780 | background="#ffffff" 781 | ) 782 | 783 | 784 | self.entry1 = Entry(p_update) 785 | self.entry1.place(relx=0.132, rely=0.296, width=996, height=30) 786 | self.entry1.configure( 787 | font="-family {Poppins} -size 12", 788 | relief="flat" 789 | ) 790 | 791 | self.entry2 = Entry(p_update) 792 | self.entry2.place(relx=0.132, rely=0.413, width=374, height=30) 793 | self.entry2.configure( 794 | font="-family {Poppins} -size 12", 795 | relief="flat" 796 | ) 797 | 798 | self.r2 = p_update.register(self.testint) 799 | 800 | self.entry3 = Entry(p_update) 801 | self.entry3.place(relx=0.132, rely=0.529, width=374, height=30) 802 | self.entry3.configure( 803 | font="-family {Poppins} -size 12", 804 | relief="flat", 805 | validate="key", 806 | validatecommand=(self.r2, "%P") 807 | ) 808 | 809 | self.entry4 = Entry(p_update) 810 | self.entry4.place(relx=0.132, rely=0.646, width=374, height=30) 811 | self.entry4.configure( 812 | font="-family {Poppins} -size 12", 813 | relief="flat" 814 | ) 815 | 816 | self.entry5 = Entry(p_update) 817 | self.entry5.place(relx=0.527, rely=0.413, width=374, height=30) 818 | self.entry5.configure( 819 | font="-family {Poppins} -size 12", 820 | relief="flat" 821 | ) 822 | 823 | self.entry6 = Entry(p_update) 824 | self.entry6.place(relx=0.527, rely=0.529, width=374, height=30) 825 | self.entry6.configure( 826 | font="-family {Poppins} -size 12", 827 | relief="flat" 828 | ) 829 | 830 | self.entry7 = Entry(p_update) 831 | self.entry7.place(relx=0.527, rely=0.646, width=374, height=30) 832 | self.entry7.configure( 833 | font="-family {Poppins} -size 12", 834 | relief="flat" 835 | ) 836 | 837 | 838 | self.button1 = Button(p_update) 839 | self.button1.place(relx=0.408, rely=0.836, width=96, height=34) 840 | self.button1.configure( 841 | relief="flat", 842 | overrelief="flat", 843 | activebackground="#CF1E14", 844 | cursor="hand2", 845 | foreground="#ffffff", 846 | background="#CF1E14", 847 | font="-family {Poppins SemiBold} -size 14", 848 | borderwidth="0", 849 | text="UPDATE", 850 | command=self.update 851 | ) 852 | 853 | self.button2 = Button(p_update) 854 | self.button2.place(relx=0.526, rely=0.836, width=86, height=34) 855 | self.button2.configure( 856 | relief="flat", 857 | overrelief="flat", 858 | activebackground="#CF1E14", 859 | cursor="hand2", 860 | foreground="#ffffff", 861 | background="#CF1E14", 862 | font="-family {Poppins SemiBold} -size 14", 863 | borderwidth="0", 864 | text="CLEAR", 865 | command=self.clearr 866 | ) 867 | 868 | 869 | def update(self): 870 | pname = self.entry1.get() 871 | pcat = self.entry2.get() 872 | pqty = self.entry3.get() 873 | pmrp = self.entry4.get() 874 | psubcat = self.entry5.get() 875 | pcp = self.entry6.get() 876 | pvendor = self.entry7.get() 877 | 878 | if pname.strip(): 879 | if pcat.strip(): 880 | if psubcat.strip(): 881 | if pqty: 882 | if pcp: 883 | try: 884 | float(pcp) 885 | except ValueError: 886 | messagebox.showerror("Oops!", "Invalid cost price.", parent=p_update) 887 | else: 888 | if pmrp: 889 | try: 890 | float(pmrp) 891 | except ValueError: 892 | messagebox.showerror("Oops!", "Invalid MRP.", parent=p_update) 893 | else: 894 | if valid_phone(pvendor): 895 | product_id = valll[0] 896 | with sqlite3.connect("./Database/store.db") as db: 897 | cur = db.cursor() 898 | update = ( 899 | "UPDATE raw_inventory SET product_name = ?, product_cat = ?, product_subcat = ?, stock = ?, mrp = ?, cost_price = ?, vendor_phn = ? WHERE product_id = ?" 900 | ) 901 | cur.execute(update, [pname, pcat, psubcat, int(pqty), float(pmrp), float(pcp), pvendor, product_id]) 902 | db.commit() 903 | messagebox.showinfo("Success!!", "Product successfully updated in inventory.", parent=p_update) 904 | valll.clear() 905 | Inventory.sel.clear() 906 | page3.tree.delete(*page3.tree.get_children()) 907 | page3.DisplayData() 908 | p_update.destroy() 909 | else: 910 | messagebox.showerror("Oops!", "Invalid phone number.", parent=p_update) 911 | else: 912 | messagebox.showerror("Oops!", "Please enter MRP.", parent=p_update) 913 | else: 914 | messagebox.showerror("Oops!", "Please enter product cost price.", parent=p_update) 915 | else: 916 | messagebox.showerror("Oops!", "Please enter product quantity.", parent=p_update) 917 | else: 918 | messagebox.showerror("Oops!", "Please enter product sub-category.", parent=p_update) 919 | else: 920 | messagebox.showerror("Oops!", "Please enter product category.", parent=p_update) 921 | else: 922 | messagebox.showerror("Oops!", "Please enter product name", parent=p_update) 923 | 924 | 925 | def clearr(self): 926 | self.entry1.delete(0, END) 927 | self.entry2.delete(0, END) 928 | self.entry3.delete(0, END) 929 | self.entry4.delete(0, END) 930 | self.entry5.delete(0, END) 931 | self.entry6.delete(0, END) 932 | self.entry7.delete(0, END) 933 | 934 | 935 | def testint(self, val): 936 | if val.isdigit(): 937 | return True 938 | elif val == "": 939 | return True 940 | return False 941 | 942 | 943 | def time(self): 944 | string = strftime("%H:%M:%S %p") 945 | self.clock.config(text=string) 946 | self.clock.after(1000, self.time) 947 | 948 | 949 | class Employee: 950 | def __init__(self, top=None): 951 | top.geometry("1366x768") 952 | top.resizable(0, 0) 953 | top.title("Employee Management") 954 | 955 | 956 | self.label1 = Label(emp) 957 | self.label1.place(relx=0, rely=0, width=1366, height=768) 958 | self.img = PhotoImage(file="./images/employee.png") 959 | self.label1.configure(image=self.img) 960 | 961 | 962 | self.message = Label(emp) 963 | self.message.place(relx=0.046, rely=0.055, width=136, height=30) 964 | self.message.configure(font="-family {Poppins} -size 10") 965 | self.message.configure( 966 | foreground="#000000", 967 | background="#ffffff", 968 | text="ADMIN", 969 | anchor="w", 970 | ) 971 | 972 | 973 | self.clock = Label(emp) 974 | self.clock.place(relx=0.9, rely=0.065, width=102, height=36) 975 | self.clock.configure( 976 | font="-family {Poppins Light} -size 12", 977 | foreground="#000000", 978 | background="#ffffff" 979 | ) 980 | 981 | 982 | self.entry1 = Entry(emp) 983 | self.entry1.place(relx=0.040, rely=0.286, width=240, height=28) 984 | self.entry1.configure( 985 | font="-family {Poppins} -size 12", 986 | relief="flat" 987 | ) 988 | 989 | 990 | self.button1 = Button(emp) 991 | self.button1.place(relx=0.229, rely=0.289, width=76, height=23) 992 | self.button1.configure( 993 | relief="flat", 994 | overrelief="flat", 995 | activebackground="#CF1E14", 996 | cursor="hand2", 997 | foreground="#ffffff", 998 | background="#CF1E14", 999 | font="-family {Poppins SemiBold} -size 10", 1000 | borderwidth="0", 1001 | text="Search", 1002 | command=self.search_emp 1003 | ) 1004 | 1005 | self.button2 = Button(emp) 1006 | self.button2.place(relx=0.035, rely=0.106, width=76, height=23) 1007 | self.button2.configure( 1008 | relief="flat", 1009 | overrelief="flat", 1010 | activebackground="#CF1E14", 1011 | cursor="hand2", 1012 | foreground="#ffffff", 1013 | background="#CF1E14", 1014 | font="-family {Poppins SemiBold} -size 12", 1015 | borderwidth="0", 1016 | text="Logout", 1017 | command=self.Logout 1018 | ) 1019 | 1020 | self.button3 = Button(emp) 1021 | self.button3.place(relx=0.052, rely=0.432, width=306, height=28) 1022 | self.button3.configure( 1023 | relief="flat", 1024 | overrelief="flat", 1025 | activebackground="#CF1E14", 1026 | cursor="hand2", 1027 | foreground="#ffffff", 1028 | background="#CF1E14", 1029 | font="-family {Poppins SemiBold} -size 12", 1030 | borderwidth="0", 1031 | text="ADD EMPLOYEE", 1032 | command=self.add_emp 1033 | ) 1034 | 1035 | self.button4 = Button(emp) 1036 | self.button4.place(relx=0.052, rely=0.5, width=306, height=28) 1037 | self.button4.configure( 1038 | relief="flat", 1039 | overrelief="flat", 1040 | activebackground="#CF1E14", 1041 | cursor="hand2", 1042 | foreground="#ffffff", 1043 | background="#CF1E14", 1044 | font="-family {Poppins SemiBold} -size 12", 1045 | borderwidth="0", 1046 | text="UPDATE EMPLOYEE", 1047 | command=self.update_emp 1048 | ) 1049 | 1050 | self.button5 = Button(emp) 1051 | self.button5.place(relx=0.052, rely=0.57, width=306, height=28) 1052 | self.button5.configure( 1053 | relief="flat", 1054 | overrelief="flat", 1055 | activebackground="#CF1E14", 1056 | cursor="hand2", 1057 | foreground="#ffffff", 1058 | background="#CF1E14", 1059 | font="-family {Poppins SemiBold} -size 12", 1060 | borderwidth="0", 1061 | text="DELETE EMPLOYEE", 1062 | command=self.delete_emp 1063 | ) 1064 | 1065 | self.button6 = Button(emp) 1066 | self.button6.place(relx=0.135, rely=0.885, width=76, height=23) 1067 | self.button6.configure( 1068 | relief="flat", 1069 | overrelief="flat", 1070 | activebackground="#CF1E14", 1071 | cursor="hand2", 1072 | foreground="#ffffff", 1073 | background="#CF1E14", 1074 | font="-family {Poppins SemiBold} -size 12", 1075 | borderwidth="0", 1076 | text="EXIT", 1077 | command=self.Exit 1078 | ) 1079 | 1080 | self.scrollbarx = Scrollbar(emp, orient=HORIZONTAL) 1081 | self.scrollbary = Scrollbar(emp, orient=VERTICAL) 1082 | self.tree = ttk.Treeview(emp) 1083 | self.tree.place(relx=0.307, rely=0.203, width=880, height=550) 1084 | self.tree.configure( 1085 | yscrollcommand=self.scrollbary.set, xscrollcommand=self.scrollbarx.set 1086 | ) 1087 | self.tree.configure(selectmode="extended") 1088 | 1089 | self.tree.bind("<>", self.on_tree_select) 1090 | 1091 | self.scrollbary.configure(command=self.tree.yview) 1092 | self.scrollbarx.configure(command=self.tree.xview) 1093 | 1094 | self.scrollbary.place(relx=0.954, rely=0.203, width=22, height=548) 1095 | self.scrollbarx.place(relx=0.307, rely=0.924, width=884, height=22) 1096 | 1097 | self.tree.configure( 1098 | columns=( 1099 | "Employee ID", 1100 | "Employee Name", 1101 | "Contact No.", 1102 | "Address", 1103 | "Aadhar No.", 1104 | "Password", 1105 | "Designation" 1106 | ) 1107 | ) 1108 | 1109 | self.tree.heading("Employee ID", text="Employee ID", anchor=W) 1110 | self.tree.heading("Employee Name", text="Employee Name", anchor=W) 1111 | self.tree.heading("Contact No.", text="Contact No.", anchor=W) 1112 | self.tree.heading("Address", text="Address", anchor=W) 1113 | self.tree.heading("Aadhar No.", text="Aadhar No.", anchor=W) 1114 | self.tree.heading("Password", text="Password", anchor=W) 1115 | self.tree.heading("Designation", text="Designation", anchor=W) 1116 | 1117 | self.tree.column("#0", stretch=NO, minwidth=0, width=0) 1118 | self.tree.column("#1", stretch=NO, minwidth=0, width=80) 1119 | self.tree.column("#2", stretch=NO, minwidth=0, width=260) 1120 | self.tree.column("#3", stretch=NO, minwidth=0, width=100) 1121 | self.tree.column("#4", stretch=NO, minwidth=0, width=198) 1122 | self.tree.column("#5", stretch=NO, minwidth=0, width=80) 1123 | self.tree.column("#6", stretch=NO, minwidth=0, width=80) 1124 | self.tree.column("#7", stretch=NO, minwidth=0, width=80) 1125 | 1126 | self.DisplayData() 1127 | 1128 | 1129 | def DisplayData(self): 1130 | cur.execute("SELECT * FROM employee") 1131 | fetch = cur.fetchall() 1132 | for data in fetch: 1133 | self.tree.insert("", "end", values=(data)) 1134 | 1135 | 1136 | def search_emp(self): 1137 | val = [] 1138 | for i in self.tree.get_children(): 1139 | val.append(i) 1140 | for j in self.tree.item(i)["values"]: 1141 | val.append(j) 1142 | 1143 | to_search = self.entry1.get() 1144 | for search in val: 1145 | if search == to_search: 1146 | self.tree.selection_set(val[val.index(search) - 1]) 1147 | self.tree.focus(val[val.index(search) - 1]) 1148 | messagebox.showinfo("Success!!", f"Employee ID: {self.entry1.get()} found.", parent=emp) 1149 | break 1150 | else: 1151 | messagebox.showerror("Oops!!", f"Employee ID: {self.entry1.get()} not found.", parent=emp) 1152 | 1153 | 1154 | sel = [] 1155 | def on_tree_select(self, Event): 1156 | self.sel.clear() 1157 | for i in self.tree.selection(): 1158 | if i not in self.sel: 1159 | self.sel.append(i) 1160 | 1161 | 1162 | def delete_emp(self): 1163 | val = [] 1164 | to_delete = [] 1165 | 1166 | if len(self.sel) != 0: 1167 | sure = messagebox.askyesno("Confirm", "Are you sure you want to delete selected employee(s)?", parent=emp) 1168 | if sure == True: 1169 | for i in self.sel: 1170 | for j in self.tree.item(i)["values"]: 1171 | val.append(j) 1172 | 1173 | for j in range(len(val)): 1174 | if j % 7 == 0: 1175 | to_delete.append(val[j]) 1176 | 1177 | flag = 1 1178 | 1179 | for k in to_delete: 1180 | if k == "EMP1000": 1181 | flag = 0 1182 | break 1183 | else: 1184 | delete = "DELETE FROM employee WHERE emp_id = ?" 1185 | cur.execute(delete, [k]) 1186 | db.commit() 1187 | 1188 | if flag == 1: 1189 | messagebox.showinfo("Success!!", "Employee(s) deleted from database.", parent=emp) 1190 | self.sel.clear() 1191 | self.tree.delete(*self.tree.get_children()) 1192 | self.DisplayData() 1193 | else: 1194 | messagebox.showerror("Error!!","Cannot delete master admin.") 1195 | else: 1196 | messagebox.showerror("Error!!","Please select an employee.", parent=emp) 1197 | 1198 | 1199 | def update_emp(self): 1200 | if len(self.sel) == 1: 1201 | global e_update 1202 | e_update = Toplevel() 1203 | page8 = Update_Employee(e_update) 1204 | page8.time() 1205 | e_update.protocol("WM_DELETE_WINDOW", self.ex2) 1206 | global vall 1207 | vall = [] 1208 | for i in self.sel: 1209 | for j in self.tree.item(i)["values"]: 1210 | vall.append(j) 1211 | 1212 | page8.entry1.insert(0, vall[1]) 1213 | page8.entry2.insert(0, vall[2]) 1214 | page8.entry3.insert(0, vall[4]) 1215 | page8.entry4.insert(0, vall[6]) 1216 | page8.entry5.insert(0, vall[3]) 1217 | page8.entry6.insert(0, vall[5]) 1218 | 1219 | e_update.mainloop() 1220 | 1221 | elif len(self.sel) == 0: 1222 | messagebox.showerror("Error","Please select an employee to update.") 1223 | else: 1224 | messagebox.showerror("Error","Can only update one employee at a time.") 1225 | 1226 | 1227 | def add_emp(self): 1228 | global e_add 1229 | e_add = Toplevel() 1230 | page6 = add_employee(e_add) 1231 | page6.time() 1232 | e_add.protocol("WM_DELETE_WINDOW", self.ex) 1233 | e_add.mainloop() 1234 | 1235 | 1236 | def ex(self): 1237 | e_add.destroy() 1238 | self.tree.delete(*self.tree.get_children()) 1239 | self.DisplayData() 1240 | 1241 | 1242 | def ex2(self): 1243 | e_update.destroy() 1244 | self.tree.delete(*self.tree.get_children()) 1245 | self.DisplayData() 1246 | 1247 | 1248 | def time(self): 1249 | string = strftime("%H:%M:%S %p") 1250 | self.clock.config(text=string) 1251 | self.clock.after(1000, self.time) 1252 | 1253 | 1254 | def Exit(self): 1255 | sure = messagebox.askyesno("Exit","Are you sure you want to exit?", parent=emp) 1256 | if sure == True: 1257 | emp.destroy() 1258 | adm.deiconify() 1259 | 1260 | 1261 | def Logout(self): 1262 | sure = messagebox.askyesno("Logout", "Are you sure you want to logout?") 1263 | if sure == True: 1264 | emp.destroy() 1265 | root.deiconify() 1266 | 1267 | page1.entry1.delete(0, END) 1268 | page1.entry2.delete(0, END) 1269 | 1270 | 1271 | class add_employee: 1272 | def __init__(self, top=None): 1273 | top.geometry("1366x768") 1274 | top.resizable(0, 0) 1275 | top.title("Add Employee") 1276 | 1277 | 1278 | self.label1 = Label(e_add) 1279 | self.label1.place(relx=0, rely=0, width=1366, height=768) 1280 | self.img = PhotoImage(file="./images/add_employee.png") 1281 | self.label1.configure(image=self.img) 1282 | 1283 | 1284 | self.clock = Label(e_add) 1285 | self.clock.place(relx=0.84, rely=0.065, width=102, height=36) 1286 | self.clock.configure(font="-family {Poppins Light} -size 12") 1287 | self.clock.configure(foreground="#000000") 1288 | self.clock.configure(background="#ffffff") 1289 | 1290 | 1291 | self.r1 = e_add.register(self.testint) 1292 | self.r2 = e_add.register(self.testchar) 1293 | 1294 | 1295 | self.entry1 = Entry(e_add) 1296 | self.entry1.place(relx=0.132, rely=0.296, width=374, height=30) 1297 | self.entry1.configure(font="-family {Poppins} -size 12") 1298 | self.entry1.configure(relief="flat") 1299 | 1300 | self.entry2 = Entry(e_add) 1301 | self.entry2.place(relx=0.132, rely=0.413, width=374, height=30) 1302 | self.entry2.configure( 1303 | font="-family {Poppins} -size 12", 1304 | relief="flat", 1305 | validate="key", 1306 | validatecommand=(self.r1, "%P"), 1307 | ) 1308 | 1309 | self.entry3 = Entry(e_add) 1310 | self.entry3.place(relx=0.132, rely=0.529, width=374, height=30) 1311 | self.entry3.configure( 1312 | font="-family {Poppins} -size 12", 1313 | relief="flat", 1314 | validate="key", 1315 | validatecommand=(self.r1, "%P"), 1316 | ) 1317 | 1318 | self.entry4 = Entry(e_add) 1319 | self.entry4.place(relx=0.527, rely=0.296, width=374, height=30) 1320 | self.entry4.configure( 1321 | font="-family {Poppins} -size 12", 1322 | relief="flat", 1323 | validate="key", 1324 | validatecommand=(self.r2, "%P") 1325 | ) 1326 | 1327 | self.entry5 = Entry(e_add) 1328 | self.entry5.place(relx=0.527, rely=0.413, width=374, height=30) 1329 | self.entry5.configure( 1330 | font="-family {Poppins} -size 12", 1331 | relief="flat" 1332 | ) 1333 | 1334 | self.entry6 = Entry(e_add) 1335 | self.entry6.place(relx=0.527, rely=0.529, width=374, height=30) 1336 | self.entry6.configure( 1337 | font="-family {Poppins} -size 12", 1338 | relief="flat", 1339 | show="*" 1340 | ) 1341 | 1342 | 1343 | self.button1 = Button(e_add) 1344 | self.button1.place(relx=0.408, rely=0.836, width=96, height=34) 1345 | self.button1.configure( 1346 | relief="flat", 1347 | overrelief="flat", 1348 | activebackground="#CF1E14", 1349 | cursor="hand2", 1350 | foreground="#ffffff", 1351 | background="#CF1E14", 1352 | font="-family {Poppins SemiBold} -size 14", 1353 | borderwidth="0", 1354 | text="ADD", 1355 | command=self.add 1356 | ) 1357 | 1358 | self.button2 = Button(e_add) 1359 | self.button2.place(relx=0.526, rely=0.836, width=86, height=34) 1360 | self.button2.configure( 1361 | relief="flat", 1362 | overrelief="flat", 1363 | activebackground="#CF1E14", 1364 | cursor="hand2", 1365 | foreground="#ffffff", 1366 | background="#CF1E14", 1367 | font="-family {Poppins SemiBold} -size 14", 1368 | borderwidth="0", 1369 | text="CLEAR", 1370 | command=self.clearr 1371 | ) 1372 | 1373 | 1374 | def testint(self, val): 1375 | if val.isdigit(): 1376 | return True 1377 | elif val == "": 1378 | return True 1379 | return False 1380 | 1381 | 1382 | def testchar(self, val): 1383 | if val.isalpha(): 1384 | return True 1385 | elif val == "": 1386 | return True 1387 | return False 1388 | 1389 | 1390 | def time(self): 1391 | string = strftime("%H:%M:%S %p") 1392 | self.clock.config(text=string) 1393 | self.clock.after(1000, self.time) 1394 | 1395 | 1396 | def add(self): 1397 | ename = self.entry1.get() 1398 | econtact = self.entry2.get() 1399 | eaddhar = self.entry3.get() 1400 | edes = self.entry4.get() 1401 | eadd = self.entry5.get() 1402 | epass = self.entry6.get() 1403 | 1404 | if ename.strip(): 1405 | if valid_phone(econtact): 1406 | if valid_aadhar(eaddhar): 1407 | if edes: 1408 | if eadd: 1409 | if epass: 1410 | emp_id = random_emp_id(7) 1411 | insert = ( 1412 | "INSERT INTO employee(emp_id, name, contact_num, address, aadhar_num, password, designation) VALUES(?,?,?,?,?,?,?)" 1413 | ) 1414 | cur.execute(insert, [emp_id, ename, econtact, eadd, eaddhar, epass, edes]) 1415 | db.commit() 1416 | messagebox.showinfo("Success!!", f"Employee ID: {emp_id} successfully added in database.", parent=e_add) 1417 | self.clearr() 1418 | else: 1419 | messagebox.showerror("Oops!", "Please enter a password.", parent=e_add) 1420 | else: 1421 | messagebox.showerror("Oops!", "Please enter address.", parent=e_add) 1422 | else: 1423 | messagebox.showerror("Oops!", "Please enter designation.", parent=e_add) 1424 | else: 1425 | messagebox.showerror("Oops!", "Invalid Aadhar number.", parent=e_add) 1426 | else: 1427 | messagebox.showerror("Oops!", "Invalid phone number.", parent=e_add) 1428 | else: 1429 | messagebox.showerror("Oops!", "Please enter employee name.", parent=e_add) 1430 | 1431 | def clearr(self): 1432 | self.entry1.delete(0, END) 1433 | self.entry2.delete(0, END) 1434 | self.entry3.delete(0, END) 1435 | self.entry4.delete(0, END) 1436 | self.entry5.delete(0, END) 1437 | self.entry6.delete(0, END) 1438 | 1439 | 1440 | class Update_Employee: 1441 | def __init__(self, top=None): 1442 | top.geometry("1366x768") 1443 | top.resizable(0, 0) 1444 | top.title("Update Employee") 1445 | 1446 | 1447 | self.label1 = Label(e_update) 1448 | self.label1.place(relx=0, rely=0, width=1366, height=768) 1449 | self.img = PhotoImage(file="./images/update_employee.png") 1450 | self.label1.configure(image=self.img) 1451 | 1452 | 1453 | self.clock = Label(e_update) 1454 | self.clock.place(relx=0.84, rely=0.065, width=102, height=36) 1455 | self.clock.configure(font="-family {Poppins Light} -size 12") 1456 | self.clock.configure( 1457 | foreground="#000000", 1458 | background="#ffffff" 1459 | ) 1460 | 1461 | 1462 | self.r1 = e_update.register(self.testint) 1463 | self.r2 = e_update.register(self.testchar) 1464 | 1465 | 1466 | self.entry1 = Entry(e_update) 1467 | self.entry1.place(relx=0.132, rely=0.296, width=374, height=30) 1468 | self.entry1.configure( 1469 | font="-family {Poppins} -size 12", 1470 | relief="flat" 1471 | ) 1472 | 1473 | self.entry2 = Entry(e_update) 1474 | self.entry2.place(relx=0.132, rely=0.413, width=374, height=30) 1475 | self.entry2.configure( 1476 | font="-family {Poppins} -size 12", 1477 | relief="flat", 1478 | validate="key", 1479 | validatecommand=(self.r1, "%P") 1480 | ) 1481 | 1482 | self.entry3 = Entry(e_update) 1483 | self.entry3.place(relx=0.132, rely=0.529, width=374, height=30) 1484 | self.entry3.configure( 1485 | font="-family {Poppins} -size 12", 1486 | relief="flat", 1487 | validate="key", 1488 | validatecommand=(self.r1, "%P") 1489 | ) 1490 | 1491 | self.entry4 = Entry(e_update) 1492 | self.entry4.place(relx=0.527, rely=0.296, width=374, height=30) 1493 | self.entry4.configure( 1494 | font="-family {Poppins} -size 12", 1495 | relief="flat", 1496 | validate="key", 1497 | validatecommand=(self.r2, "%P") 1498 | ) 1499 | 1500 | self.entry5 = Entry(e_update) 1501 | self.entry5.place(relx=0.527, rely=0.413, width=374, height=30) 1502 | self.entry5.configure( 1503 | font="-family {Poppins} -size 12", 1504 | relief="flat" 1505 | ) 1506 | 1507 | self.entry6 = Entry(e_update) 1508 | self.entry6.place(relx=0.527, rely=0.529, width=374, height=30) 1509 | self.entry6.configure( 1510 | font="-family {Poppins} -size 12", 1511 | relief="flat", 1512 | show="*" 1513 | ) 1514 | 1515 | 1516 | self.button1 = Button(e_update) 1517 | self.button1.place(relx=0.408, rely=0.836, width=96, height=34) 1518 | self.button1.configure( 1519 | relief="flat", 1520 | overrelief="flat", 1521 | activebackground="#CF1E14", 1522 | cursor="hand2", 1523 | foreground="#ffffff", 1524 | background="#CF1E14", 1525 | font="-family {Poppins SemiBold} -size 14", 1526 | borderwidth="0", 1527 | text="UPDATE", 1528 | command=self.update 1529 | ) 1530 | 1531 | self.button2 = Button(e_update) 1532 | self.button2.place(relx=0.526, rely=0.836, width=86, height=34) 1533 | self.button2.configure( 1534 | relief="flat", 1535 | overrelief="flat", 1536 | activebackground="#CF1E14", 1537 | cursor="hand2", 1538 | foreground="#ffffff", 1539 | background="#CF1E14", 1540 | font="-family {Poppins SemiBold} -size 14", 1541 | borderwidth="0", 1542 | text="CLEAR", 1543 | command=self.clearr 1544 | ) 1545 | 1546 | 1547 | def update(self): 1548 | ename = self.entry1.get() 1549 | econtact = self.entry2.get() 1550 | eaddhar = self.entry3.get() 1551 | edes = self.entry4.get() 1552 | eadd = self.entry5.get() 1553 | epass = self.entry6.get() 1554 | 1555 | if ename.strip(): 1556 | if valid_phone(econtact): 1557 | if valid_aadhar(eaddhar): 1558 | if edes: 1559 | if eadd: 1560 | if epass: 1561 | emp_id = vall[0] 1562 | update = ( 1563 | "UPDATE employee SET name = ?, contact_num = ?, address = ?, aadhar_num = ?, password = ?, designation = ? WHERE emp_id = ?" 1564 | ) 1565 | cur.execute(update, [ename, econtact, eadd, eaddhar, epass, edes, emp_id]) 1566 | db.commit() 1567 | messagebox.showinfo("Success!!", f"Employee ID: {emp_id} successfully updated in database.", parent=e_update) 1568 | vall.clear() 1569 | page5.tree.delete(*page5.tree.get_children()) 1570 | page5.DisplayData() 1571 | Employee.sel.clear() 1572 | e_update.destroy() 1573 | else: 1574 | messagebox.showerror("Oops!", "Please enter a password.", parent=e_add) 1575 | else: 1576 | messagebox.showerror("Oops!", "Please enter address.", parent=e_add) 1577 | else: 1578 | messagebox.showerror("Oops!", "Please enter designation.", parent=e_add) 1579 | else: 1580 | messagebox.showerror("Oops!", "Invalid Aadhar number.", parent=e_add) 1581 | else: 1582 | messagebox.showerror("Oops!", "Invalid phone number.", parent=e_add) 1583 | else: 1584 | messagebox.showerror("Oops!", "Please enter employee name.", parent=e_add) 1585 | 1586 | 1587 | def clearr(self): 1588 | self.entry1.delete(0, END) 1589 | self.entry2.delete(0, END) 1590 | self.entry3.delete(0, END) 1591 | self.entry4.delete(0, END) 1592 | self.entry5.delete(0, END) 1593 | self.entry6.delete(0, END) 1594 | 1595 | 1596 | def testint(self, val): 1597 | if val.isdigit(): 1598 | return True 1599 | elif val == "": 1600 | return True 1601 | return False 1602 | 1603 | 1604 | def testchar(self, val): 1605 | if val.isalpha(): 1606 | return True 1607 | elif val == "": 1608 | return True 1609 | return False 1610 | 1611 | 1612 | def time(self): 1613 | string = strftime("%H:%M:%S %p") 1614 | self.clock.config(text=string) 1615 | self.clock.after(1000, self.time) 1616 | 1617 | 1618 | class Invoice: 1619 | def __init__(self, top=None): 1620 | top.geometry("1366x768") 1621 | top.resizable(0, 0) 1622 | top.title("Invoices") 1623 | 1624 | 1625 | self.label1 = Label(invoice) 1626 | self.label1.place(relx=0, rely=0, width=1366, height=768) 1627 | self.img = PhotoImage(file="./images/invoices.png") 1628 | self.label1.configure(image=self.img) 1629 | 1630 | 1631 | self.message = Label(invoice) 1632 | self.message.place(relx=0.046, rely=0.055, width=136, height=30) 1633 | self.message.configure( 1634 | font="-family {Poppins} -size 10", 1635 | foreground="#000000", 1636 | background="#ffffff", 1637 | text="ADMIN", 1638 | anchor="w" 1639 | ) 1640 | 1641 | 1642 | self.clock = Label(invoice) 1643 | self.clock.place(relx=0.9, rely=0.065, width=102, height=36) 1644 | self.clock.configure( 1645 | font="-family {Poppins Light} -size 12", 1646 | foreground="#000000", 1647 | background="#ffffff" 1648 | ) 1649 | 1650 | 1651 | self.entry1 = Entry(invoice) 1652 | self.entry1.place(relx=0.040, rely=0.286, width=240, height=28) 1653 | self.entry1.configure( 1654 | font="-family {Poppins} -size 12", 1655 | relief="flat" 1656 | ) 1657 | 1658 | 1659 | self.button1 = Button(invoice) 1660 | self.button1.place(relx=0.229, rely=0.289, width=76, height=23) 1661 | self.button1.configure( 1662 | relief="flat", 1663 | overrelief="flat", 1664 | activebackground="#CF1E14", 1665 | cursor="hand2", 1666 | foreground="#ffffff", 1667 | background="#CF1E14", 1668 | font="-family {Poppins SemiBold} -size 10", 1669 | borderwidth="0", 1670 | text="Search", 1671 | command=self.search_inv 1672 | ) 1673 | 1674 | self.button2 = Button(invoice) 1675 | self.button2.place(relx=0.035, rely=0.106, width=76, height=23) 1676 | self.button2.configure( 1677 | relief="flat", 1678 | overrelief="flat", 1679 | activebackground="#CF1E14", 1680 | cursor="hand2", 1681 | foreground="#ffffff", 1682 | background="#CF1E14", 1683 | font="-family {Poppins SemiBold} -size 12", 1684 | borderwidth="0", 1685 | text="Logout", 1686 | command=self.Logout 1687 | ) 1688 | 1689 | self.button3 = Button(invoice) 1690 | self.button3.place(relx=0.052, rely=0.432, width=306, height=28) 1691 | self.button3.configure( 1692 | relief="flat", 1693 | overrelief="flat", 1694 | activebackground="#CF1E14", 1695 | cursor="hand2", 1696 | foreground="#ffffff", 1697 | background="#CF1E14", 1698 | font="-family {Poppins SemiBold} -size 12", 1699 | borderwidth="0", 1700 | text="DELETE INVOICE", 1701 | command=self.delete_invoice 1702 | ) 1703 | 1704 | self.button4 = Button(invoice) 1705 | self.button4.place(relx=0.135, rely=0.885, width=76, height=23) 1706 | self.button4.configure( 1707 | relief="flat", 1708 | overrelief="flat", 1709 | activebackground="#CF1E14", 1710 | cursor="hand2", 1711 | foreground="#ffffff", 1712 | background="#CF1E14", 1713 | font="-family {Poppins SemiBold} -size 12", 1714 | borderwidth="0", 1715 | text="EXIT", 1716 | command=self.Exit 1717 | ) 1718 | 1719 | self.scrollbarx = Scrollbar(invoice, orient=HORIZONTAL) 1720 | self.scrollbary = Scrollbar(invoice, orient=VERTICAL) 1721 | self.tree = ttk.Treeview(invoice) 1722 | self.tree.place(relx=0.307, rely=0.203, width=880, height=550) 1723 | self.tree.configure( 1724 | yscrollcommand=self.scrollbary.set, xscrollcommand=self.scrollbarx.set 1725 | ) 1726 | self.tree.configure(selectmode="extended") 1727 | 1728 | self.tree.bind("<>", self.on_tree_select) 1729 | self.tree.bind("", self.double_tap) 1730 | 1731 | self.scrollbary.configure(command=self.tree.yview) 1732 | self.scrollbarx.configure(command=self.tree.xview) 1733 | 1734 | self.scrollbary.place(relx=0.954, rely=0.203, width=22, height=548) 1735 | self.scrollbarx.place(relx=0.307, rely=0.924, width=884, height=22) 1736 | 1737 | self.tree.configure( 1738 | columns=( 1739 | "Bill Number", 1740 | "Date", 1741 | "Customer Name", 1742 | "Customer Phone No.", 1743 | ) 1744 | ) 1745 | 1746 | self.tree.heading("Bill Number", text="Bill Number", anchor=W) 1747 | self.tree.heading("Date", text="Date", anchor=W) 1748 | self.tree.heading("Customer Name", text="Customer Name", anchor=W) 1749 | self.tree.heading("Customer Phone No.", text="Customer Phone No.", anchor=W) 1750 | 1751 | self.tree.column("#0", stretch=NO, minwidth=0, width=0) 1752 | self.tree.column("#1", stretch=NO, minwidth=0, width=219) 1753 | self.tree.column("#2", stretch=NO, minwidth=0, width=219) 1754 | self.tree.column("#3", stretch=NO, minwidth=0, width=219) 1755 | self.tree.column("#4", stretch=NO, minwidth=0, width=219) 1756 | 1757 | self.DisplayData() 1758 | 1759 | 1760 | def DisplayData(self): 1761 | cur.execute("SELECT * FROM bill") 1762 | fetch = cur.fetchall() 1763 | for data in fetch: 1764 | self.tree.insert("", "end", values=(data)) 1765 | 1766 | 1767 | sel = [] 1768 | def on_tree_select(self, Event): 1769 | self.sel.clear() 1770 | for i in self.tree.selection(): 1771 | if i not in self.sel: 1772 | self.sel.append(i) 1773 | 1774 | 1775 | def double_tap(self, Event): 1776 | item = self.tree.identify('item', Event.x, Event.y) 1777 | global bill_num 1778 | bill_num = self.tree.item(item)['values'][0] 1779 | 1780 | global bill 1781 | bill = Toplevel() 1782 | pg = open_bill(bill) 1783 | bill.mainloop() 1784 | 1785 | 1786 | def delete_invoice(self): 1787 | val = [] 1788 | to_delete = [] 1789 | 1790 | if len(self.sel)!=0: 1791 | sure = messagebox.askyesno("Confirm", "Are you sure you want to delete selected invoice(s)?", parent=invoice) 1792 | if sure == True: 1793 | for i in self.sel: 1794 | for j in self.tree.item(i)["values"]: 1795 | val.append(j) 1796 | 1797 | for j in range(len(val)): 1798 | if j % 5 == 0: 1799 | to_delete.append(val[j]) 1800 | 1801 | for k in to_delete: 1802 | delete = "DELETE FROM bill WHERE bill_no = ?" 1803 | cur.execute(delete, [k]) 1804 | db.commit() 1805 | 1806 | messagebox.showinfo("Success!!", "Invoice(s) deleted from database.", parent=invoice) 1807 | self.sel.clear() 1808 | self.tree.delete(*self.tree.get_children()) 1809 | 1810 | self.DisplayData() 1811 | else: 1812 | messagebox.showerror("Error!!","Please select an invoice", parent=invoice) 1813 | 1814 | 1815 | def search_inv(self): 1816 | val = [] 1817 | for i in self.tree.get_children(): 1818 | val.append(i) 1819 | for j in self.tree.item(i)["values"]: 1820 | val.append(j) 1821 | 1822 | to_search = self.entry1.get() 1823 | for search in val: 1824 | if search == to_search: 1825 | self.tree.selection_set(val[val.index(search) - 1]) 1826 | self.tree.focus(val[val.index(search) - 1]) 1827 | messagebox.showinfo("Success!!", f"Bill Number: {self.entry1.get()} found.", parent=invoice) 1828 | break 1829 | else: 1830 | messagebox.showerror("Oops!!", f"Bill NUmber: {self.entry1.get()} not found.", parent=invoice) 1831 | 1832 | 1833 | def Logout(self): 1834 | sure = messagebox.askyesno("Logout", "Are you sure you want to logout?") 1835 | if sure == True: 1836 | invoice.destroy() 1837 | root.deiconify() 1838 | page1.entry1.delete(0, END) 1839 | page1.entry2.delete(0, END) 1840 | 1841 | 1842 | def time(self): 1843 | string = strftime("%H:%M:%S %p") 1844 | self.clock.config(text=string) 1845 | self.clock.after(1000, self.time) 1846 | 1847 | 1848 | def Exit(self): 1849 | sure = messagebox.askyesno("Exit","Are you sure you want to exit?", parent=invoice) 1850 | if sure == True: 1851 | invoice.destroy() 1852 | adm.deiconify() 1853 | 1854 | 1855 | class open_bill: 1856 | def __init__(self, top=None): 1857 | top.geometry("765x488") 1858 | top.resizable(0, 0) 1859 | top.title("Bill") 1860 | 1861 | 1862 | self.label1 = Label(bill) 1863 | self.label1.place(relx=0, rely=0, width=765, height=488) 1864 | self.img = PhotoImage(file="./images/bill.png") 1865 | self.label1.configure(image=self.img) 1866 | 1867 | 1868 | self.name_message = Text(bill) 1869 | self.name_message.place(relx=0.178, rely=0.205, width=176, height=30) 1870 | self.name_message.configure( 1871 | font="-family {Podkova} -size 10", 1872 | borderwidth=0, 1873 | background="#ffffff" 1874 | ) 1875 | 1876 | self.num_message = Text(bill) 1877 | self.num_message.place(relx=0.854, rely=0.205, width=90, height=30) 1878 | self.num_message.configure( 1879 | font="-family {Podkova} -size 10", 1880 | borderwidth=0, 1881 | background="#ffffff" 1882 | ) 1883 | 1884 | 1885 | self.bill_message = Text(bill) 1886 | self.bill_message.place(relx=0.150, rely=0.243, width=176, height=26) 1887 | self.bill_message.configure( 1888 | font="-family {Podkova} -size 10", 1889 | borderwidth=0, 1890 | background="#ffffff" 1891 | ) 1892 | 1893 | self.bill_date_message = Text(bill) 1894 | self.bill_date_message.place(relx=0.780, rely=0.243, width=90, height=26) 1895 | self.bill_date_message.configure( 1896 | font="-family {Podkova} -size 10", 1897 | borderwidth=0, 1898 | background="#ffffff" 1899 | ) 1900 | 1901 | 1902 | self.Scrolledtext1 = tkst.ScrolledText(top) 1903 | self.Scrolledtext1.place(relx=0.044, rely=0.41, width=695, height=284) 1904 | self.Scrolledtext1.configure( 1905 | borderwidth=0, 1906 | font="-family {Podkova} -size 8", 1907 | state="disabled" 1908 | ) 1909 | 1910 | 1911 | find_bill = "SELECT * FROM bill WHERE bill_no = ?" 1912 | cur.execute(find_bill, [bill_num]) 1913 | results = cur.fetchall() 1914 | if results: 1915 | self.name_message.insert(END, results[0][2]) 1916 | self.name_message.configure(state="disabled") 1917 | 1918 | self.num_message.insert(END, results[0][3]) 1919 | self.num_message.configure(state="disabled") 1920 | 1921 | self.bill_message.insert(END, results[0][0]) 1922 | self.bill_message.configure(state="disabled") 1923 | 1924 | self.bill_date_message.insert(END, results[0][1]) 1925 | self.bill_date_message.configure(state="disabled") 1926 | 1927 | self.Scrolledtext1.configure(state="normal") 1928 | self.Scrolledtext1.insert(END, results[0][4]) 1929 | self.Scrolledtext1.configure(state="disabled") 1930 | 1931 | page1 = login_page(root) 1932 | root.bind("", login_page.login) 1933 | root.mainloop() -------------------------------------------------------------------------------- /employee.py: -------------------------------------------------------------------------------- 1 | #==================imports=================== 2 | import sqlite3 3 | import re 4 | import random 5 | import string 6 | from tkinter import * 7 | from tkinter import messagebox 8 | from tkinter import ttk 9 | from time import strftime 10 | from datetime import date 11 | from tkinter import scrolledtext as tkst 12 | #============================================ 13 | 14 | 15 | 16 | root = Tk() 17 | root.geometry("1366x768") 18 | root.title("Billing Software") 19 | 20 | 21 | user = StringVar() 22 | passwd = StringVar() 23 | fname = StringVar() 24 | lname = StringVar() 25 | new_user = StringVar() 26 | new_passwd = StringVar() 27 | 28 | 29 | cust_name = StringVar() 30 | cust_num = StringVar() 31 | cust_new_bill = StringVar() 32 | cust_search_bill = StringVar() 33 | bill_date = StringVar() 34 | 35 | 36 | with sqlite3.connect("./Database/store.db") as db: 37 | cur = db.cursor() 38 | 39 | 40 | def random_bill_number(stringLength): 41 | lettersAndDigits = string.ascii_letters.upper() + string.digits 42 | strr=''.join(random.choice(lettersAndDigits) for i in range(stringLength-2)) 43 | return ('CC'+strr) 44 | 45 | 46 | def valid_phone(phn): 47 | if re.match(r"[789]\d{9}$", phn): 48 | return True 49 | return False 50 | 51 | 52 | def login(Event=None): 53 | global username 54 | username = user.get() 55 | password = passwd.get() 56 | 57 | with sqlite3.connect("./Database/store.db") as db: 58 | cur = db.cursor() 59 | cur.execute("SELECT * FROM employee WHERE emp_id = ? and password = ?", [username, password]) 60 | results = cur.fetchall() 61 | 62 | if results: 63 | messagebox.showinfo("Login Page", "The login is successful") 64 | page1.entry1.delete(0, END) 65 | page1.entry2.delete(0, END) 66 | root.withdraw() 67 | 68 | global biller 69 | global page2 70 | biller = Toplevel() 71 | page2 = bill_window(biller) 72 | page2.time() 73 | biller.protocol("WM_DELETE_WINDOW", exitt) 74 | biller.mainloop() 75 | 76 | else: 77 | messagebox.showerror("Error", "Incorrect username or password.") 78 | page1.entry2.delete(0, END) 79 | 80 | 81 | def logout(): 82 | sure = messagebox.askyesno("Logout", "Are you sure you want to logout?", parent=biller) 83 | if sure == True: 84 | biller.destroy() 85 | root.deiconify() 86 | page1.entry1.delete(0, END) 87 | page1.entry2.delete(0, END) 88 | 89 | class login_page: 90 | def __init__(self, top=None): 91 | top.geometry("1366x768") 92 | top.resizable(0, 0) 93 | top.title("Employee login") 94 | 95 | self.label1 = Label(root) 96 | self.label1.place(relx=0, rely=0, width=1366, height=768) 97 | self.img = PhotoImage(file="./images/employee_login.png") 98 | self.label1.configure(image=self.img) 99 | 100 | self.entry1 = Entry(root) 101 | self.entry1.place(relx=0.373, rely=0.273, width=374, height=24) 102 | self.entry1.configure( 103 | font="-family {Poppins} -size 10", 104 | relief="flat", 105 | textvariable=user 106 | ) 107 | 108 | self.entry2 = Entry(root) 109 | self.entry2.place(relx=0.373, rely=0.384, width=374, height=24) 110 | self.entry2.configure( 111 | font="-family {Poppins} -size 10", 112 | relief="flat", 113 | show="*", 114 | textvariable=passwd 115 | ) 116 | 117 | self.button1 = Button(root) 118 | self.button1.place(relx=0.366, rely=0.685, width=356, height=43) 119 | self.button1.configure( 120 | relief="flat", 121 | overrelief="flat", 122 | activebackground="#D2463E", 123 | cursor="hand2", 124 | foreground="#ffffff", 125 | background="#D2463E", 126 | font="-family {Poppins SemiBold} -size 20", 127 | borderwidth="0", 128 | text="Login", 129 | command=login 130 | ) 131 | 132 | 133 | class Item: 134 | def __init__(self, name, price, qty): 135 | self.product_name = name 136 | self.price = price 137 | self.qty = qty 138 | 139 | class Cart: 140 | def __init__(self): 141 | self.items = [] 142 | self.dictionary = {} 143 | 144 | def add_item(self, item): 145 | self.items.append(item) 146 | 147 | def remove_item(self): 148 | self.items.pop() 149 | 150 | def remove_items(self): 151 | self.items.clear() 152 | 153 | def total(self): 154 | total = 0.0 155 | for i in self.items: 156 | total += i.price * i.qty 157 | return total 158 | 159 | def isEmpty(self): 160 | if len(self.items) == 0: 161 | return True 162 | 163 | def allCart(self): 164 | for i in self.items: 165 | if (i.product_name in self.dictionary): 166 | self.dictionary[i.product_name] += i.qty 167 | else: 168 | self.dictionary.update({i.product_name:i.qty}) 169 | 170 | 171 | def exitt(): 172 | sure = messagebox.askyesno("Exit","Are you sure you want to exit?", parent=biller) 173 | if sure == True: 174 | biller.destroy() 175 | root.destroy() 176 | 177 | 178 | class bill_window: 179 | def __init__(self, top = None): 180 | top.geometry("1366x768") 181 | top.resizable(0, 0) 182 | top.title("Billing Software") 183 | 184 | self.label = Label(biller) 185 | self.label.place(relx=0, rely=0, width=1366, height=768) 186 | self.img = PhotoImage(file="./images/bill_window.png") 187 | self.label.configure(image=self.img) 188 | 189 | self.message = Label(biller) 190 | self.message.place(relx=0.038, rely=0.055, width=136, height=30) 191 | self.message.configure( 192 | font="-family {Poppins} -size 10", 193 | foreground="#000000", 194 | background="#ffffff", 195 | text=username, 196 | anchor="w" 197 | ) 198 | 199 | self.clock = Label(biller) 200 | self.clock.place(relx=0.9, rely=0.065, width=102, height=36) 201 | self.clock.configure( 202 | font="-family {Poppins Light} -size 12", 203 | foreground="#000000", 204 | background="#ffffff" 205 | ) 206 | 207 | self.entry1 = Entry(biller) 208 | self.entry1.place(relx=0.509, rely=0.23, width=240, height=24) 209 | self.entry1.configure( 210 | font="-family {Poppins} -size 12", 211 | relief="flat", 212 | textvariable=cust_name 213 | ) 214 | 215 | self.entry2 = Entry(biller) 216 | self.entry2.place(relx=0.791, rely=0.23, width=240, height=24) 217 | self.entry2.configure( 218 | font="-family {Poppins} -size 12", 219 | relief="flat", 220 | textvariable=cust_num 221 | ) 222 | 223 | self.entry3 = Entry(biller) 224 | self.entry3.place(relx=0.102, rely=0.23, width=240, height=24) 225 | self.entry3.configure( 226 | font="-family {Poppins} -size 12", 227 | relief="flat", 228 | textvariable=cust_search_bill 229 | ) 230 | 231 | self.button1 = Button(biller) 232 | self.button1.place(relx=0.031, rely=0.104, width=76, height=23) 233 | self.button1.configure( 234 | relief="flat", 235 | overrelief="flat", 236 | activebackground="#CF1E14", 237 | cursor="hand2", 238 | foreground="#ffffff", 239 | background="#CF1E14", 240 | font="-family {Poppins SemiBold} -size 12", 241 | borderwidth="0", 242 | text="Logout", 243 | command=logout 244 | ) 245 | 246 | self.button2 = Button(biller) 247 | self.button2.place(relx=0.315, rely=0.234, width=76, height=23) 248 | self.button2.configure( 249 | relief="flat", 250 | overrelief="flat", 251 | activebackground="#CF1E14", 252 | cursor="hand2", 253 | foreground="#ffffff", 254 | background="#CF1E14", 255 | font="-family {Poppins SemiBold} -size 12", 256 | borderwidth="0", 257 | text="Search", 258 | command=self.search_bill 259 | ) 260 | 261 | self.button3 = Button(biller) 262 | self.button3.place(relx=0.048, rely=0.885, width=86, height=25) 263 | self.button3.configure( 264 | relief="flat", 265 | overrelief="flat", 266 | activebackground="#CF1E14", 267 | cursor="hand2", 268 | foreground="#ffffff", 269 | background="#CF1E14", 270 | font="-family {Poppins SemiBold} -size 10", 271 | borderwidth="0", 272 | text="Total", 273 | command=self.total_bill 274 | ) 275 | 276 | self.button4 = Button(biller) 277 | self.button4.place(relx=0.141, rely=0.885, width=84, height=25) 278 | self.button4.configure( 279 | relief="flat", 280 | overrelief="flat", 281 | activebackground="#CF1E14", 282 | cursor="hand2", 283 | foreground="#ffffff", 284 | background="#CF1E14", 285 | font="-family {Poppins SemiBold} -size 10", 286 | borderwidth="0", 287 | text="Generate", 288 | command=self.gen_bill 289 | ) 290 | 291 | self.button5 = Button(biller) 292 | self.button5.place(relx=0.230, rely=0.885, width=86, height=25) 293 | self.button5.configure( 294 | relief="flat", 295 | overrelief="flat", 296 | activebackground="#CF1E14", 297 | cursor="hand2", 298 | foreground="#ffffff", 299 | background="#CF1E14", 300 | font="-family {Poppins SemiBold} -size 10", 301 | borderwidth="0", 302 | text="Clear", 303 | command=self.clear_bill 304 | ) 305 | 306 | self.button6 = Button(biller) 307 | self.button6.place(relx=0.322, rely=0.885, width=86, height=25) 308 | self.button6.configure( 309 | relief="flat", 310 | overrelief="flat", 311 | activebackground="#CF1E14", 312 | cursor="hand2", 313 | foreground="#ffffff", 314 | background="#CF1E14", 315 | font="-family {Poppins SemiBold} -size 10", 316 | borderwidth="0", 317 | text="Exit", 318 | command=exitt 319 | ) 320 | 321 | self.button7 = Button(biller) 322 | self.button7.place(relx=0.098, rely=0.734, width=86, height=26) 323 | self.button7.configure( 324 | relief="flat", 325 | overrelief="flat", 326 | activebackground="#CF1E14", 327 | cursor="hand2", 328 | foreground="#ffffff", 329 | background="#CF1E14", 330 | font="-family {Poppins SemiBold} -size 10", 331 | borderwidth="0", 332 | text="Add To Cart", 333 | command=self.add_to_cart 334 | ) 335 | 336 | self.button8 = Button(biller) 337 | self.button8.place(relx=0.274, rely=0.734, width=84, height=26) 338 | self.button8.configure( 339 | relief="flat", 340 | overrelief="flat", 341 | activebackground="#CF1E14", 342 | cursor="hand2", 343 | foreground="#ffffff", 344 | background="#CF1E14", 345 | font="-family {Poppins SemiBold} -size 10", 346 | borderwidth="0", 347 | text="""Clear""", 348 | command=self.clear_selection 349 | ) 350 | 351 | self.button9 = Button(biller) 352 | self.button9.place(relx=0.194, rely=0.734, width=68, height=26) 353 | self.button9.configure( 354 | relief="flat", 355 | overrelief="flat", 356 | activebackground="#CF1E14", 357 | cursor="hand2", 358 | foreground="#ffffff", 359 | background="#CF1E14", 360 | font="-family {Poppins SemiBold} -size 10", 361 | borderwidth="0", 362 | text="""Remove""", 363 | command=self.remove_product 364 | ) 365 | 366 | text_font = ("Poppins", "8") 367 | self.combo1 = ttk.Combobox(biller) 368 | self.combo1.place(relx=0.035, rely=0.408, width=477, height=26) 369 | 370 | find_category = "SELECT product_cat FROM raw_inventory" 371 | cur.execute(find_category) 372 | result1 = cur.fetchall() 373 | cat = [] 374 | for i in range(len(result1)): 375 | if(result1[i][0] not in cat): 376 | cat.append(result1[i][0]) 377 | 378 | 379 | self.combo1.configure( 380 | values=cat, 381 | state="readonly", 382 | font="-family {Poppins} -size 8", 383 | ) 384 | self.combo1.option_add("*TCombobox*Listbox.font", text_font) 385 | self.combo1.option_add("*TCombobox*Listbox.selectBackground", "#D2463E") 386 | 387 | 388 | self.combo2 = ttk.Combobox(biller) 389 | self.combo2.place(relx=0.035, rely=0.479, width=477, height=26) 390 | self.combo2.configure(font="-family {Poppins} -size 8") 391 | self.combo2.option_add("*TCombobox*Listbox.font", text_font) 392 | self.combo2.configure(state="disabled") 393 | 394 | 395 | self.combo3 = ttk.Combobox(biller) 396 | self.combo3.place(relx=0.035, rely=0.551, width=477, height=26) 397 | self.combo3.configure( 398 | state="disabled", 399 | font="-family {Poppins} -size 8" 400 | ) 401 | self.combo3.option_add("*TCombobox*Listbox.font", text_font) 402 | 403 | self.entry4 = ttk.Entry(biller) 404 | self.entry4.place(relx=0.035, rely=0.629, width=477, height=26) 405 | self.entry4.configure( 406 | font="-family {Poppins} -size 8", 407 | foreground="#000000", 408 | state="disabled" 409 | ) 410 | 411 | self.Scrolledtext1 = tkst.ScrolledText(top) 412 | self.Scrolledtext1.place(relx=0.439, rely=0.586, width=695, height=275) 413 | self.Scrolledtext1.configure( 414 | borderwidth=0, 415 | font="-family {Podkova} -size 8", 416 | state="disabled" 417 | ) 418 | 419 | self.combo1.bind("<>", self.get_category) 420 | 421 | def get_category(self, Event): 422 | self.combo2.configure(state="readonly") 423 | self.combo2.set('') 424 | self.combo3.set('') 425 | find_subcat = "SELECT product_subcat FROM raw_inventory WHERE product_cat = ?" 426 | cur.execute(find_subcat, [self.combo1.get()]) 427 | result2 = cur.fetchall() 428 | subcat = [] 429 | for j in range(len(result2)): 430 | if(result2[j][0] not in subcat): 431 | subcat.append(result2[j][0]) 432 | 433 | self.combo2.configure(values=subcat) 434 | self.combo2.bind("<>", self.get_subcat) 435 | self.combo3.configure(state="disabled") 436 | 437 | def get_subcat(self, Event): 438 | self.combo3.configure(state="readonly") 439 | self.combo3.set('') 440 | find_product = "SELECT product_name FROM raw_inventory WHERE product_cat = ? and product_subcat = ?" 441 | cur.execute(find_product, [self.combo1.get(), self.combo2.get()]) 442 | result3 = cur.fetchall() 443 | pro = [] 444 | for k in range(len(result3)): 445 | pro.append(result3[k][0]) 446 | 447 | self.combo3.configure(values=pro) 448 | self.combo3.bind("<>", self.show_qty) 449 | self.entry4.configure(state="disabled") 450 | 451 | def show_qty(self, Event): 452 | self.entry4.configure(state="normal") 453 | self.qty_label = Label(biller) 454 | self.qty_label.place(relx=0.033, rely=0.664, width=82, height=26) 455 | self.qty_label.configure( 456 | font="-family {Poppins} -size 8", 457 | anchor="w" 458 | ) 459 | 460 | product_name = self.combo3.get() 461 | find_qty = "SELECT stock FROM raw_inventory WHERE product_name = ?" 462 | cur.execute(find_qty, [product_name]) 463 | results = cur.fetchone() 464 | self.qty_label.configure( 465 | text=f"In Stock: {results[0]}", 466 | background="#ffffff", 467 | foreground="#333333" 468 | ) 469 | 470 | cart = Cart() 471 | def add_to_cart(self): 472 | self.Scrolledtext1.configure(state="normal") 473 | strr = self.Scrolledtext1.get('1.0', END) 474 | if strr.find('Total') == -1: 475 | product_name = self.combo3.get() 476 | if(product_name != ""): 477 | product_qty = self.entry4.get() 478 | find_mrp = "SELECT mrp, stock FROM raw_inventory WHERE product_name = ?" 479 | cur.execute(find_mrp, [product_name]) 480 | results = cur.fetchall() 481 | stock = results[0][1] 482 | mrp = results[0][0] 483 | if product_qty.isdigit() == True: 484 | if (stock - int(product_qty)) >= 0: 485 | sp = mrp * int(product_qty) 486 | item = Item(product_name, mrp, int(product_qty)) 487 | self.cart.add_item(item) 488 | self.Scrolledtext1.configure(state="normal") 489 | bill_text = f"{product_name}\t\t\t\t\t\t\t{product_qty}\t\t\t\t\t\t{sp}\n" 490 | self.Scrolledtext1.insert('insert', bill_text) 491 | self.Scrolledtext1.configure(state="disabled") 492 | else: 493 | messagebox.showerror("Oops!", "Out of stock. Check quantity.", parent=biller) 494 | else: 495 | messagebox.showerror("Oops!", "Invalid quantity.", parent=biller) 496 | else: 497 | messagebox.showerror("Oops!", "Choose a product.", parent=biller) 498 | else: 499 | self.Scrolledtext1.delete('1.0', END) 500 | new_li = [] 501 | li = strr.split("\n") 502 | for i in range(len(li)): 503 | if len(li[i]) != 0: 504 | if li[i].find('Total') == -1: 505 | new_li.append(li[i]) 506 | else: 507 | break 508 | for j in range(len(new_li)-1): 509 | self.Scrolledtext1.insert('insert', new_li[j]) 510 | self.Scrolledtext1.insert('insert','\n') 511 | product_name = self.combo3.get() 512 | if(product_name != ""): 513 | product_qty = self.entry4.get() 514 | find_mrp = "SELECT mrp, stock, product_id FROM raw_inventory WHERE product_name = ?" 515 | cur.execute(find_mrp, [product_name]) 516 | results = cur.fetchall() 517 | stock = results[0][1] 518 | mrp = results[0][0] 519 | if product_qty.isdigit() == True: 520 | if (stock - int(product_qty)) >= 0: 521 | sp = results[0][0] * int(product_qty) 522 | item = Item(product_name, mrp, int(product_qty)) 523 | self.cart.add_item(item) 524 | self.Scrolledtext1.configure(state="normal") 525 | bill_text = f"{product_name}\t\t\t\t\t\t\t{product_qty}\t\t\t\t\t\t{sp}\n" 526 | self.Scrolledtext1.insert('insert', bill_text) 527 | self.Scrolledtext1.configure(state="disabled") 528 | else: 529 | messagebox.showerror("Oops!", "Out of stock. Check quantity.", parent=biller) 530 | else: 531 | messagebox.showerror("Oops!", "Invalid quantity.", parent=biller) 532 | else: 533 | messagebox.showerror("Oops!", "Choose a product.", parent=biller) 534 | 535 | def remove_product(self): 536 | if(self.cart.isEmpty() != True): 537 | self.Scrolledtext1.configure(state="normal") 538 | strr = self.Scrolledtext1.get('1.0', END) 539 | if strr.find('Total') == -1: 540 | try: 541 | self.cart.remove_item() 542 | except IndexError: 543 | messagebox.showerror("Oops!", "Cart is empty", parent=biller) 544 | else: 545 | self.Scrolledtext1.configure(state="normal") 546 | get_all_bill = (self.Scrolledtext1.get('1.0', END).split("\n")) 547 | new_string = get_all_bill[:len(get_all_bill)-3] 548 | self.Scrolledtext1.delete('1.0', END) 549 | for i in range(len(new_string)): 550 | self.Scrolledtext1.insert('insert', new_string[i]) 551 | self.Scrolledtext1.insert('insert','\n') 552 | 553 | self.Scrolledtext1.configure(state="disabled") 554 | else: 555 | try: 556 | self.cart.remove_item() 557 | except IndexError: 558 | messagebox.showerror("Oops!", "Cart is empty", parent=biller) 559 | else: 560 | self.Scrolledtext1.delete('1.0', END) 561 | new_li = [] 562 | li = strr.split("\n") 563 | for i in range(len(li)): 564 | if len(li[i]) != 0: 565 | if li[i].find('Total') == -1: 566 | new_li.append(li[i]) 567 | else: 568 | break 569 | new_li.pop() 570 | for j in range(len(new_li) - 1): 571 | self.Scrolledtext1.insert('insert', new_li[j]) 572 | self.Scrolledtext1.insert('insert','\n') 573 | self.Scrolledtext1.configure(state="disabled") 574 | 575 | else: 576 | messagebox.showerror("Oops!", "Add a product.", parent=biller) 577 | 578 | def wel_bill(self): 579 | self.name_message = Text(biller) 580 | self.name_message.place(relx=0.514, rely=0.452, width=176, height=30) 581 | self.name_message.configure( 582 | font="-family {Podkova} -size 10", 583 | borderwidth=0, 584 | background="#ffffff" 585 | ) 586 | 587 | self.num_message = Text(biller) 588 | self.num_message.place(relx=0.894, rely=0.452, width=90, height=30) 589 | self.num_message.configure( 590 | font="-family {Podkova} -size 10", 591 | borderwidth=0, 592 | background="#ffffff" 593 | ) 594 | 595 | self.bill_message = Text(biller) 596 | self.bill_message.place(relx=0.499, rely=0.477, width=176, height=26) 597 | self.bill_message.configure( 598 | font="-family {Podkova} -size 10", 599 | borderwidth=0, 600 | background="#ffffff" 601 | ) 602 | 603 | self.bill_date_message = Text(biller) 604 | self.bill_date_message.place(relx=0.852, rely=0.477, width=90, height=26) 605 | self.bill_date_message.configure( 606 | font="-family {Podkova} -size 10", 607 | borderwidth=0, 608 | background="#ffffff" 609 | ) 610 | 611 | def total_bill(self): 612 | if self.cart.isEmpty(): 613 | messagebox.showerror("Oops!", "Add a product.", parent=biller) 614 | else: 615 | self.Scrolledtext1.configure(state="normal") 616 | strr = self.Scrolledtext1.get('1.0', END) 617 | if strr.find('Total') == -1: 618 | self.Scrolledtext1.configure(state="normal") 619 | divider = "\n\n\n" + ("─"*84) 620 | self.Scrolledtext1.insert('insert', divider) 621 | total = f"\nTotal\t\t\t\t\t\t\t\t\t\t\t\tRs. {self.cart.total()}" 622 | self.Scrolledtext1.insert('insert', total) 623 | divider2 = "\n" + ("─"*84) 624 | self.Scrolledtext1.insert('insert', divider2) 625 | self.Scrolledtext1.configure(state="disabled") 626 | else: 627 | return 628 | 629 | state = 1 630 | def gen_bill(self): 631 | 632 | if self.state == 1: 633 | strr = self.Scrolledtext1.get('1.0', END) 634 | self.wel_bill() 635 | if(cust_name.get() == ""): 636 | messagebox.showerror("Oops!", "Please enter a name.", parent=biller) 637 | elif(cust_num.get() == ""): 638 | messagebox.showerror("Oops!", "Please enter a number.", parent=biller) 639 | elif valid_phone(cust_num.get()) == False: 640 | messagebox.showerror("Oops!", "Please enter a valid number.", parent=biller) 641 | elif(self.cart.isEmpty()): 642 | messagebox.showerror("Oops!", "Cart is empty.", parent=biller) 643 | else: 644 | if strr.find('Total') == -1: 645 | self.total_bill() 646 | self.gen_bill() 647 | else: 648 | self.name_message.insert(END, cust_name.get()) 649 | self.name_message.configure(state="disabled") 650 | 651 | self.num_message.insert(END, cust_num.get()) 652 | self.num_message.configure(state="disabled") 653 | 654 | cust_new_bill.set(random_bill_number(8)) 655 | 656 | self.bill_message.insert(END, cust_new_bill.get()) 657 | self.bill_message.configure(state="disabled") 658 | 659 | bill_date.set(str(date.today())) 660 | 661 | self.bill_date_message.insert(END, bill_date.get()) 662 | self.bill_date_message.configure(state="disabled") 663 | 664 | 665 | with sqlite3.connect("./Database/store.db") as db: 666 | cur = db.cursor() 667 | insert = ( 668 | "INSERT INTO bill(bill_no, date, customer_name, customer_no, bill_details) VALUES(?,?,?,?,?)" 669 | ) 670 | cur.execute(insert, [cust_new_bill.get(), bill_date.get(), cust_name.get(), cust_num.get(), self.Scrolledtext1.get('1.0', END)]) 671 | db.commit() 672 | print(self.cart.allCart()) 673 | for name, qty in self.cart.dictionary.items(): 674 | update_qty = "UPDATE raw_inventory SET stock = stock - ? WHERE product_name = ?" 675 | cur.execute(update_qty, [qty, name]) 676 | db.commit() 677 | messagebox.showinfo("Success!!", "Bill Generated", parent=biller) 678 | self.entry1.configure( 679 | state="disabled", 680 | disabledbackground="#ffffff", 681 | disabledforeground="#000000" 682 | ) 683 | self.entry2.configure( 684 | state="disabled", 685 | disabledbackground="#ffffff", 686 | disabledforeground="#000000" 687 | ) 688 | self.state = 0 689 | else: 690 | return 691 | 692 | def clear_bill(self): 693 | self.wel_bill() 694 | 695 | self.entry1.configure(state="normal") 696 | self.entry2.configure(state="normal") 697 | 698 | self.entry1.delete(0, END) 699 | self.entry2.delete(0, END) 700 | self.entry3.delete(0, END) 701 | 702 | self.name_message.configure(state="normal") 703 | self.num_message.configure(state="normal") 704 | self.bill_message.configure(state="normal") 705 | self.bill_date_message.configure(state="normal") 706 | self.Scrolledtext1.configure(state="normal") 707 | 708 | self.name_message.delete(1.0, END) 709 | self.num_message.delete(1.0, END) 710 | self.bill_message.delete(1.0, END) 711 | self.bill_date_message.delete(1.0, END) 712 | self.Scrolledtext1.delete(1.0, END) 713 | 714 | self.name_message.configure(state="disabled") 715 | self.num_message.configure(state="disabled") 716 | self.bill_message.configure(state="disabled") 717 | self.bill_date_message.configure(state="disabled") 718 | self.Scrolledtext1.configure(state="disabled") 719 | 720 | self.cart.remove_items() 721 | self.state = 1 722 | 723 | def clear_selection(self): 724 | self.entry4.delete(0, END) 725 | 726 | self.combo1.configure(state="normal") 727 | self.combo2.configure(state="normal") 728 | self.combo3.configure(state="normal") 729 | 730 | self.combo1.delete(0, END) 731 | self.combo2.delete(0, END) 732 | self.combo3.delete(0, END) 733 | 734 | self.combo2.configure(state="disabled") 735 | self.combo3.configure(state="disabled") 736 | self.entry4.configure(state="disabled") 737 | try: 738 | self.qty_label.configure(foreground="#ffffff") 739 | except AttributeError: 740 | pass 741 | 742 | def search_bill(self): 743 | cur.execute("SELECT * FROM bill WHERE bill_no = ?", [cust_search_bill.get().rstrip()]) 744 | results = cur.fetchall() 745 | if results: 746 | self.clear_bill() 747 | self.wel_bill() 748 | 749 | self.name_message.insert(END, results[0][2]) 750 | self.name_message.configure(state="disabled") 751 | 752 | self.num_message.insert(END, results[0][3]) 753 | self.num_message.configure(state="disabled") 754 | 755 | self.bill_message.insert(END, results[0][0]) 756 | self.bill_message.configure(state="disabled") 757 | 758 | self.bill_date_message.insert(END, results[0][1]) 759 | self.bill_date_message.configure(state="disabled") 760 | 761 | self.Scrolledtext1.configure(state="normal") 762 | self.Scrolledtext1.insert(END, results[0][4]) 763 | self.Scrolledtext1.configure(state="disabled") 764 | 765 | self.entry1.configure( 766 | state="disabled", 767 | disabledbackground="#ffffff", 768 | disabledforeground="#000000" 769 | ) 770 | self.entry2.configure( 771 | state="disabled", 772 | disabledbackground="#ffffff", 773 | disabledforeground="#000000" 774 | ) 775 | 776 | self.state = 0 777 | 778 | else: 779 | messagebox.showerror("Error!!", "Bill not found.", parent=biller) 780 | self.entry3.delete(0, END) 781 | 782 | def time(self): 783 | string = strftime("%H:%M:%S %p") 784 | self.clock.config(text=string) 785 | self.clock.after(1000, self.time) 786 | 787 | 788 | page1 = login_page(root) 789 | root.bind("", login) 790 | root.mainloop() -------------------------------------------------------------------------------- /fonts/Podkova-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/fonts/Podkova-Regular.ttf -------------------------------------------------------------------------------- /fonts/Poppins-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/fonts/Poppins-Light.ttf -------------------------------------------------------------------------------- /fonts/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/fonts/Poppins-Regular.ttf -------------------------------------------------------------------------------- /fonts/Poppins-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/fonts/Poppins-SemiBold.ttf -------------------------------------------------------------------------------- /images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/1.png -------------------------------------------------------------------------------- /images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/2.png -------------------------------------------------------------------------------- /images/add_employee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/add_employee.png -------------------------------------------------------------------------------- /images/add_product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/add_product.png -------------------------------------------------------------------------------- /images/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/admin.png -------------------------------------------------------------------------------- /images/admin_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/admin_login.png -------------------------------------------------------------------------------- /images/bill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/bill.png -------------------------------------------------------------------------------- /images/bill_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/bill_window.png -------------------------------------------------------------------------------- /images/employee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/employee.png -------------------------------------------------------------------------------- /images/employee_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/employee_login.png -------------------------------------------------------------------------------- /images/inventory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/inventory.png -------------------------------------------------------------------------------- /images/invoices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/invoices.png -------------------------------------------------------------------------------- /images/main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/main.png -------------------------------------------------------------------------------- /images/update_employee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/update_employee.png -------------------------------------------------------------------------------- /images/update_product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PritKalariya/Python-Billing-Software/b279fe33d5a4d0144adb359ae9fee618a6fd8ee5/images/update_product.png -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | from tkinter import * 3 | from tkinter import messagebox 4 | 5 | 6 | main = Tk() 7 | main.geometry("1366x768") 8 | main.title("Billing System") 9 | main.resizable(0, 0) 10 | 11 | 12 | def Exit(): 13 | sure = messagebox.askyesno("Exit","Are you sure you want to exit?", parent=main) 14 | if sure == True: 15 | main.destroy() 16 | 17 | main.protocol("WM_DELETE_WINDOW", Exit) 18 | 19 | 20 | def emp(): 21 | main.withdraw() 22 | os.system("python employee.py") 23 | main.deiconify() 24 | 25 | 26 | def adm(): 27 | main.withdraw() 28 | os.system("python admin.py") 29 | main.deiconify() 30 | 31 | 32 | label1 = Label(main) 33 | label1.place(relx=0, rely=0, width=1366, height=768) 34 | img = PhotoImage(file="./images/main.png") 35 | label1.configure(image=img) 36 | 37 | 38 | button1 = Button(main) 39 | button1.place(relx=0.316, rely=0.446, width=146, height=90) 40 | img2 = PhotoImage(file="./images/1.png") 41 | button1.configure( 42 | relief="flat", 43 | cursor="hand2", 44 | activebackground="#fff", 45 | foreground="#fff", 46 | background="#fff", 47 | borderwidth="0", 48 | image=img2, 49 | command=emp 50 | ) 51 | 52 | 53 | button2 = Button(main) 54 | button2.place(relx=0.566, rely=0.448, width=146, height=90) 55 | img3 = PhotoImage(file="./images/2.png") 56 | button2.configure( 57 | relief="flat", 58 | overrelief="flat", 59 | activebackground="#ffffff", 60 | cursor="hand2", 61 | foreground="#ffffff", 62 | background="#ffffff", 63 | borderwidth="0", 64 | image=img3, 65 | command=adm, 66 | ) 67 | 68 | main.mainloop() --------------------------------------------------------------------------------