├── 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 | 
14 |
15 | #### Employee Login PAGE
16 | 
17 |
18 | #### Billing Window
19 | 
20 |
21 | #### Admin DASHBOARD
22 | 
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()
--------------------------------------------------------------------------------