Billing Page

Add Staff

Above UI we are going to create by Tkinter for Billing Syatem in our Inventory management system desktop application. For that first we create a window and configure its title, size and color. Here we are creating a window at Top Level so we can add this window at the top of any other window.

    
    tk.Frame.__init__(self, *args, **kwargs)
        self.root = tk.Toplevel()
        self.root.title("Billing")
        color = "#FFFFFF"
        self.root.configure(bg="#585858")
        self.root.resizable(width=0, height=0)
        win_width = 1536
        print(1280 * 56.25 / 100)
        win_height = int(1536 * 56.25 / 100)
        print(win_width, win_height)

        # self.root.geometry('1366x720+0+0')
        self.root.geometry(str(win_width) + "x" + str(int(win_height * 92 / 100)) + "+" + str(0) + "+" + str(0))

        # Get screen size
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        Util.set_font_size(screen_width, screen_height, win_width, win_height)

        login_root = None

        if args.__sizeof__() > 0:
            login_root = args[0]

        self.width = win_width * 94 / 100
        self.height = win_height * 87 / 100
        cornerradius = 40
        padding = 0
        self.color = "#FFFFFF"

      

        width = self.width * 98 / 100
        height = self.height * 96 / 100


        self.base_frame = Frame(self.root, width=width, height=height, bg=color)
        bg_canvas.create_window(width / 100, height * 2 / 100, anchor=NW, window=self.base_frame)

    

After creation of window, we will add a canvas background.

    
    bg_canvas = RoundBackgroundFrame(self.root, self.width, self.height, padding, cornerradius, self.color,"#585858")
    bg_canvas.place(width=self.width, height=self.height, x=win_width / 2 - self.width / 2,y=win_height / 2 - self.height * 53 / 100)
    label_name = Label(self.base_frame, font=("Lucida Grande", AppConstant.FONT_SIZE - 3), text="Hi, " + AppConstant.STAFF_NAME.title(),anchor=W,bg=color)
    label_name.place(width=self.width * 20 / 100, height=self.height * 5 / 100, x=30, y=self.height * 5 / 100)
   
    class RoundBackgroundFrame(tk.Canvas):

        def __init__(self, parent, width, height, padding, cornerradius, color, bg):
            tk.Canvas.__init__(self, parent, borderwidth=0, relief="flat", highlightthickness=0, bg=bg)

            original = Image.open("images/corner.png") 
            resized = original.resize((int(40), int(40)), Image.ANTIALIAS) 
            self.image_r_t = ImageTk.PhotoImage(resized)

            original = original.rotate(90, expand=0)
            resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
            self.image_l_t = ImageTk.PhotoImage(resized)

            original = original.rotate(90, expand=0)
            resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
            self.image_l_b = ImageTk.PhotoImage(resized)

            original = original.rotate(90, expand=0)
            resized = original.resize((int(40), int(40)), Image.ANTIALIAS)
            self.image_r_b = ImageTk.PhotoImage(resized)

            self.shape(width, height, padding, cornerradius, color)
            (x0, y0, x1, y1) = self.bbox("all")
            width = (x1 - x0)
            height = (y1 - y0)
            self.configure(width=width, height=height)

        def shape(self, width, height, padding, cornerradius, color):
            self.create_polygon((padding, height - cornerradius - padding, padding, cornerradius + padding,
                        padding + cornerradius, padding, width - padding - cornerradius, padding,
                        width - padding, cornerradius + padding, width - padding,
                        height - cornerradius - padding, width - padding - cornerradius, height - padding,
                        padding + cornerradius, height - padding), fill=color, outline=color)

            self.create_image(width - self.image_r_t.width(), 0, image=self.image_r_t, anchor=NW)
            self.create_image(0, 0, image=self.image_l_t, anchor=NW)
            self.create_image(0, height - self.image_l_b.width(), image=self.image_l_b, anchor=NW)
            self.create_image(width - self.image_r_b.width(), height - self.image_r_b.width(), image=self.image_r_b,anchor=NW)

    

in Upper frame we will add the functionality for log out

    
    button_logout = RoundedButton(self.base_frame, 130, 130 / 4.2, color, "images/button3.png", "Logout", font=("Lucida Grande", AppConstant.FONT_SIZE - 6),  command=lambda: logout_click(self.root, login_root))
    button_logout.place(width=self.width * 20 / 100, height=self.height * 5 / 100, x=self.width * 0.85,y=self.height * 5 / 100)

    
    def logout_click(root, login_root):
    db = Util.connect_db()
    cursor = db.cursor()
    key_is_logined = "IS_LOGINED"
    cursor.execute("UPDATE system_info SET value = ? WHERE key = ?",
                   (False, key_is_logined,))
    db.commit()
    root.destroy()
    Util.center(login_root)
    login_root.deiconify()
    
        width = self.width * 98 / 100
        height = self.height * 96 / 100
        self.base_frame = Frame(self.root, width=width, height=height, bg=color)
        bg_canvas.create_window(width / 100, height * 2 / 100, anchor=NW, window=self.base_frame)


    # Add Heading Name
        add_heading_label(self.base_frame, self.color, AppConstant.FONT_SIZE, self.height, self.width)

    def add_heading_label(base_frame, color, font_size, height, width):
        label_heading = Label(base_frame, text="Billing System", anchor=CENTER, bg=color, font=("Lucida Grande", font_size + 6))
        label_heading.place(width=width * 90 / 100, height=height * 7 / 100, x=width * 5 / 100, y=height * 0.5 / 100)

    # Add line
    add_line_border(self.base_frame, self.color, self.height, self.width)

    def add_line_border(base_frame, color, height, width):
        line_canvas = Canvas(base_frame, bg=color, borderwidth=0, relief="flat", highlightthickness=0)
        line_canvas.place(width=width - 4, height=5, x=2, y=height * 10 / 100)
        line_canvas.create_line(0, 0, width, 0, fill="#787878")

    button_font = add_action_frame(self.base_frame, self.color, self.height, self.width)

    def add_action_frame(base_frame, color, height, width):
        afw = width * 0.54
        afh = height * 0.80

        button_font = ("Lucida Grande", AppConstant.FONT_SIZE - 6)
        label_frame_action = LabelFrame(base_frame, text="Bill Window", font=button_font, pady=afw * 2 / 100,
                                        padx=afw * 2 / 100, bg=color)
        label_frame_action.place(width=afw, height=afh, x=width * 0.44, y=height * 0.15)
        return button_font

    add_product_search_frame(self.base_frame, button_font, self.color, self.height, self.width)

    def add_search_frame(base_frame, button_font, color, height, width):
        sfw = width * 0.638
        sfh = height * 0.87
        label_frame_search = LabelFrame(base_frame, text="Search", font=button_font, pady=sfw * 2 / 100,
                                        padx=sfw * 2 / 100, bg=color)
        label_frame_search.place(width=sfw, height=sfh, x=width * 0.36, y=height * 0.12)
        
    

So we are done with all frame and background UI. Now we will add all the Product available box and add to cart button in action frame to add book.

    
    # Add staff UI
        self.std_name = CustomEntrySimple(self.base_frame, 300, 60, ("Lucida Grande", AppConstant.FONT_SIZE - 6), self.color,"Staff Name")
        self.std_name.place(x=50, y=150)

        self.std_contact = CustomEntrySimple(self.base_frame, 300, 60, ("Lucida Grande", AppConstant.FONT_SIZE - 6), self.color,"Contact No")
        self.std_contact.place(x=50, y=230)

        self.std_email = CustomEntrySimple(self.base_frame, 300, 60, ("Lucida Grande", AppConstant.FONT_SIZE - 6), self.color, "Email ID")
        self.std_email.place(x=50, y=310)

        self.std_pass = CustomEntrySimple(self.base_frame, 300, 60, ("Lucida Grande", AppConstant.FONT_SIZE - 6),  self.color,"Password")
        self.std_pass.place(x=50, y=390)

        self.show_add_staff_button()

        
    

So we are done with all frame and background UI. First we create a entry box to search Product with Product Id and Product Name.

    
    # Product Search Box
        self.ce_product_entry = CustomEntry(self.base_frame, 300, 55, 10, 2, self.color, "Search product", "images/ic_search.png")
        self.ce_product_entry.place(x=25, y=170)
        self.ce_product_entry.entry.bind('', self.search_product)
                        

Here is our class CustomEntrySimple:

    
    class CustomEntrySimple(tk.Canvas):

        def __init__(self, parent, width, height, font, color, text):
            tk.Canvas.__init__(self, parent, borderwidth=0, relief="flat", highlightthickness=0, bg=color)

            self.width = width
            self.height = height
            self.color = color

            self.create_text(6, 5, anchor=W, font=font, text=text, fill="#000000")
            self.create_line(5, height - 8, width - 5, height - 8, fill="#808080")

            frame = Frame(parent,width=width * 95 / 100, height=height * 50 / 100)
            self.entry = Entry(frame, bg=color, bd=0, highlightthickness=0, font=font)

            self.entry.place(relwidth=1, relheight=1, x=0, y=0)

            self.create_window(6, height / 2 - (height * 50 / 100) / 2, anchor=NW, window=frame)
            self.update()

            (x0, y0, x1, y1) = self.bbox("all")
            width = (x1 - x0)
            height = (y1 - y0)
            self.configure(width=width, height=height)
        

Here's the logic to search data in table

    
    def search_product(self, *arg):
        print("Search Method")

        if self.ce_product_entry.entry.get() != "":
            self.tree.delete(*self.tree.get_children())
            self.selected_product_tree.delete(*self.selected_product_tree.get_children())

            conn = Util.connect_db()
            cursor = conn.cursor()
            cursor.execute("SELECT * FROM `product` WHERE `product_name` LIKE ? OR `product_id` LIKE ?",
                           ('%' + str(self.ce_product_entry.entry.get()) + '%',
                            '%' + str(self.ce_product_entry.entry.get()) + '%'))
            fetch = cursor.fetchall()

            count = 0
            for data in fetch:
                if count % 2 == 0:
                    self.tree.insert('', 'end', values=data, tags=('even',))
                else:
                    self.tree.insert('', 'end', values=data, tags=('odd',))
                count = count + 1

            # for data in fetch:
            #     self.tree.insert('', 'end', values=data)
            cursor.close()
            conn.close()
        else:
            self.reset_product()
                            

We have created a Database named "inventry.db", lets connect that database and put that code in seperate class "Util" because we are going to use it multiple time in our project.

    
    class Util:

        @staticmethod
        def connect_db():
            db = None
            try:
                db = sql.connect("inventry.db")
                return db
            except sql.Error as error:
                print("Failed to insert data into sqlite table", error)
                

Fetch data from database and show it in table form with the use of "Treeview" of Tkinter.

    
    style = ttk.Style()
        style.element_create("Custom.Treeheading.border", "from", "default")
        style.layout("Custom.Treeview.Heading", [
            ("Custom.Treeheading.cell", {'sticky': 'nswe'}),
            ("Custom.Treeheading.border", {'sticky': 'nswe', 'children': [
                ("Custom.Treeheading.padding", {'sticky': 'nswe', 'children': [
                    ("Custom.Treeheading.image", {'side': 'right', 'sticky': ''}),
                    ("Custom.Treeheading.text", {'sticky': 'we'})
                ]})
            ]}),
        ])
        style.configure("Custom.Treeview", highlightthickness=0, bd=0, font=('Calibri', 11), rowheight=30)

        self.tree = ttk.Treeview(self.base_frame, height=6, columns=("c1", "c2", "c3", "c4", "c5", "c6"),
                                 selectmode="extended", show='tree', style="Custom.Treeview")
        self.tree.tag_configure('odd', background='#d9edcb', foreground="#000000", )
        self.tree.tag_configure('even', background='#FFFFFF', foreground="#000000", )
        self.tree.place(x=20, y=260)
        self.tree.bind('<>', self.on_select)
        self.get_book_data()

        vsby = ttk.Scrollbar(self.base_frame, orient="vertical", command=self.tree.yview)
        vsby.place(x=self.width / 3 + 110, y=255, height=190)
        self.tree.configure(yscrollcommand=vsby.set)

        self.tree.column("#1", anchor=tk.CENTER)
        self.tree.column("#2", anchor=tk.CENTER)
        self.tree.column("#3", anchor=tk.CENTER)
        self.tree.column("#4", anchor=tk.CENTER)
        self.tree.column("#5", anchor=tk.CENTER)
        self.tree.column("#6", anchor=tk.CENTER)

        self.tree.heading("#1", text="product ID", anchor=tk.CENTER)
        self.tree.heading("#2", text="product Name")
        self.tree.heading("#3", text="Category")
        self.tree.heading("#4", text="Available Count")
        self.tree.heading("#5", text="price")
        self.tree.heading("#6", text="GST")
        self.tree.column("#0", width=0)
        self.tree.column("#1", width=70)
        self.tree.column("#2", width=130)
        self.tree.column("#3", width=150)
        self.tree.column("#4", width=70)
        self.tree.column("#5", width=70)
        self.tree.column("#6", width=70)

        self.product_table_heading()
        

Now we will find the Product data from db, lets configure it.

    
   
    
    def get_product_data(self):
        db = Util.connect_db()
        cursor = db.cursor()

        cursor.execute('SELECT * FROM product')
        sql_output = cursor.fetchall()

        count = 0
        for data in sql_output:
            if count % 2 == 0:
                self.tree.insert('', 'end', values=data, tags=('even',))
            else:
                self.tree.insert('', 'end', values=data, tags=('odd',))
            count = count + 1



        

We have created our own heading for table, lets configure it.

    
   
    
    def product_table_heading(self):

        heading_y = 225
        bg_color = "#618645"
        text_color = "#ffffff"

        canvas = Canvas(self.base_frame, width=560, height=30)
        canvas.create_rectangle(0, 0, 1000, 30, fill=bg_color)
        canvas.place(x=20, y=heading_y + 3)

        product_id_label = ttk.Label(self.base_frame, text="Id",
                                     font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                     foreground=text_color)
        product_id_label.place(x=25, y=heading_y + 7, width=100)
        product_id_label.configure(anchor="center")

        product_name_label = ttk.Label(self.base_frame, text="Name",
                                       font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                       foreground=text_color)
        product_name_label.place(x=130, y=heading_y + 7, width=100)
        product_name_label.configure(anchor="center")

        product_contactno_label = ttk.Label(self.base_frame, text="Category",
                                            font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                            foreground=text_color)
        product_contactno_label.place(x=265, y=heading_y + 7,width=100)
        product_contactno_label.configure(anchor="center")

        product_email = ttk.Label(self.base_frame, text="Available",
                                  font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                  foreground=text_color)
        product_email.place(x=370, y=heading_y + 7,width=100)
        product_email.configure(anchor="center")

        product_price = ttk.Label(self.base_frame, text="Price",
                                  font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                  foreground=text_color)
        product_price.place(x=470, y=heading_y + 7,width=55)
        product_price.configure(anchor="center")

        product_gst = ttk.Label(self.base_frame, text="GST",
                                font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
                                foreground=text_color)
        product_gst.place(x=525, y=heading_y + 7,width=55)
        product_gst.configure(anchor="center")


        

Now we will add the edit box where staff can add how many quantity the have to give;

    
    #Select Quality
        self.ce_product_quantity_entry = CustomEntry(self.base_frame, 250, 55, 10, 2, self.color, "Enter Quantity",
                                                     "images/ic_cart.png")
        self.ce_product_quantity_entry.place(x=25, y=465)
        self.ce_product_quantity_entry.entry.config(state='disabled')  # OR entry['state'] = 'disabled'
    

Now we will go forward to adtion Frame. first we will add all the action Frame;

    
    add_allactionButton_frame(self.base_frame, button_font, self.color, self.height, self.width)
    def add_allactionButton_frame(base_frame, button_font, color, height, width):
    sfw = width * 0.43
    sfh = height * 0.20

    label_frame_action_button = LabelFrame(base_frame, text="Action Window", font=button_font, pady=sfw * 2 / 100,
                                           padx=sfw * 2 / 100, bg=color)
    label_frame_action_button.place(width=sfw, height=sfh, x=0, y=height * 0.75)

    
    
    
    def show_button(self):
        self.add_button1 = RoundedButton(self.base_frame, 150, 100 / 2.56, self.color, "images/button3.png",
                                         "Add to Cart",
                                         font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
                                         command=self.slectctedproduct)
        self.add_button1.place(x=400, y=470)
            

Now we will go forward to Billing Frame Frame. In there we will add Shop detail and Customer Details UI;

    
    #Shop Details
        db = Util.connect_db()
        cursor = db.cursor()
        cursor.execute('SELECT value FROM system_info WHERE key IS ?', ("SHOP_NAME",))
        shop_name = cursor.fetchone()
        self.heding_shop_name = shop_name[0]
        print(shop_name[0])
        label_shop_name = Label(self.base_frame, text=shop_name[0], anchor=CENTER, bg=self.color,
                                font=("Lucida Grande", AppConstant.FONT_SIZE - 3))
        label_shop_name.place(width=self.width * 40 / 100, height=self.height * 5 / 100, x=self.width * 52 / 100,
                              y=self.height * 17 / 100)

        cursor.execute('SELECT value FROM system_info WHERE key IS ?', ("SHOP_ADDRESS",))
        shop_address = cursor.fetchone()
        print(shop_address[0])
        self.heding_shop_address = shop_address[0]
        label_shop_address = Label(self.base_frame, text=shop_address[0], anchor=CENTER, bg=self.color,
                                   font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
        label_shop_address.place(width=self.width * 40 / 100, height=self.height * 5 / 100, x=self.width * 52 / 100,
                                 y=self.height * 21 / 100)

        cursor.execute('SELECT value FROM system_info WHERE key IS ?', ("SHOP_GST_NO",))
        shop_gst = cursor.fetchone()
        print(shop_gst[0])
        self.heading_shop_gst = shop_gst[0]
        label_shop_address = Label(self.base_frame, text="GSTIN- " + shop_gst[0], anchor=CENTER, bg=self.color,
                                   font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
        label_shop_address.place(width=self.width * 40 / 100, height=self.height * 5 / 100, x=self.width * 52 / 100,
                                 y=self.height * 25 / 100)

        #Customer Details

        label_customer_name = Label(self.base_frame, text="Customer Name : ", anchor=W, bg=self.color,
                                    font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
        label_customer_name.place(width=self.width * 20 / 100, height=self.height * 5 / 100, x=self.width * 48 / 100,
                                  y=self.height * 33 / 100)

        label_customer_phone_no = Label(self.base_frame, text="Customer Phone : ", anchor=W, bg=self.color,
                                        font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
        label_customer_phone_no.place(width=self.width * 15 / 100, height=self.height * 5 / 100,
                                      x=self.width * 80 / 100,
                                      y=self.height * 33 / 100)

        label_customer_name = Label(self.base_frame, text="Bill No : ", anchor=W, bg=self.color,
                                    font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
        label_customer_name.place(width=self.width * 20 / 100, height=self.height * 5 / 100, x=self.width * 48 / 100,
                                  y=self.height * 37 / 100)

        label_customer_phone_no = Label(self.base_frame, text="Date : ", anchor=W, bg=self.color,
                                        font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
        label_customer_phone_no.place(width=self.width * 15 / 100, height=self.height * 5 / 100,
                                      x=self.width * 80 / 100,
                                      y=self.height * 37 / 100)

    

Shop details And customer details Part is done .now we will add the most imporatnt part Billing. first we will add the selected Product tabel with their price, quantity, product gst and product total cost.

    
    #Selected product

        self.selected_row = []
        self.book_list = []
        self.totalBillammount = [];

        style = ttk.Style()
        style.configure("mystyle.Treeview", highlightthickness=0, bd=0,
                        font=('Calibri', 11))  # Modify the font of the body
        style.configure("mystyle.Treeview.Heading", font=('Calibri', 13, 'bold'))  # Modify the font of the headings
        style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {'sticky': 'nswe'})])

        self.selected_product_tree = ttk.Treeview(self.base_frame, height=12, show="tree", style="mystyle.Treeview")
        self.selected_product_tree.place(x=self.width * 48 / 100, y=self.height * 50 / 100)
        self.selected_product_tree["columns"] = "1", "2", "3", "4"
        self.selected_product_tree.column("#0", width=0)
        self.selected_product_tree.column("#1", width=250)
        self.selected_product_tree.column("#2", width=150)
        self.selected_product_tree.column("#3", width=150)
        self.selected_product_tree.column("#4", width=150)
        self.selected_product_table_heading()

        vsby1 = ttk.Scrollbar(self.base_frame, orient="vertical", command=self.selected_product_tree.yview)
        vsby1.place(x=self.width * 0.96, y=400, height=200)
        self.selected_product_tree.configure(yscrollcommand=vsby1.set)

        # =================Action =================
        self.show_all_action_button()

            
    
    def show_all_action_button(self):
        self.add_button1 = RoundedButton(self.base_frame, 150, 100 / 2.56, self.color, "images/button3.png",
                                         "Generate Bill",
                                         font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
                                         command=self.generateBill)
        self.add_button1.place(x=self.width * 3 / 100, y=self.height * 83 / 100)

        self.add_button1 = RoundedButton(self.base_frame, 150, 100 / 2.56, self.color, "images/button3.png",
                                         "Total",
                                         font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
                                         command=self.totalBill)
        self.add_button1.place(x=self.width * 16 / 100, y=self.height * 83 / 100)

        self.add_button1 = RoundedButton(self.base_frame, 150, 100 / 2.56, self.color, "images/button3.png",
                                         "Clear",
                                         font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
                                         command=self.clear_screen)
        self.add_button1.place(x=self.width * 29 / 100, y=self.height * 83 / 100)
        self.allSelectedProduct=[]
        self.count = 0
            

UI part has Been done. now go for functionality part. firts onselect of product part

    
   
    def on_select(self, *arg):
        self.count = self.count + 1
        self.current_item = self.tree.focus()
        product_id = self.tree.item(self.current_item)["values"][0];
        self.show_button()
        self.ce_product_quantity_entry.entry.config(state='normal')

        db = Util.connect_db()
        cursor = db.cursor()
        cursor.execute('SELECT product_count FROM product WHERE product_id IS ?', (product_id,))
        item_count = cursor.fetchone()
        print(item_count[0])
        self.stock_var = StringVar();
        self.stock_var = item_count[0]
        self.printValue = str(self.stock_var) + " in Stock"

        label_stock = Label(self.base_frame, text=self.printValue, anchor=CENTER, bg=self.color,
                            font=("Lucida Grande", AppConstant.FONT_SIZE - 6))
        label_stock.place(width=100, height=30, x=200, y=460)
    

now add Click on add to cart button

    
    def slectctedproduct(self):
        if self.stock_var <= int(self.ce_product_quantity_entry.entry.get()) - 1:
            messagebox.showerror("Error Doalog", " This Much is not available on our Stock ")

        else:
            current_item = self.tree.focus()
            product_name = self.tree.item(current_item)["values"][1]
            product_price = self.tree.item(current_item)["values"][4]
            product_gst = self.tree.item(current_item)["values"][5]
            quantity = int(self.ce_product_quantity_entry.entry.get())
            total_price = product_price * quantity + product_price * quantity * product_gst / 100
            print(product_name, product_gst, product_price, total_price)
            self.totalBillammount.append(total_price)
            self.selected_row.append(self.tree.item(self.current_item)["values"][0])
            self.selected_product_tree.insert("", 'end', text="",
                                              values=(product_name, product_price, quantity, total_price))


            product=[self.count,product_name,product_gst, product_price, quantity, total_price]
            self.allSelectedProduct.append(product)

    

now add click on Action frame (Total Bill)

    
   
    def totalBill(self):
        self.label_totalBill = ttk.Label(self.base_frame, text="Total bill amount", width=14,
                                    font=('Calibri', AppConstant.FONT_SIZE - 4, 'bold'), background='white',
                                    foreground="black")
        self.label_totalBill.place(width=self.width * 10 / 100, height=self.height * 5 / 100, x=self.width / 2,
                              y=self.height * 85 / 100)

        self.totalBillAmountwithAlladd = 0.0
        for i in self.totalBillammount:
            self.totalBillAmountwithAlladd = self.totalBillAmountwithAlladd + i

        self.label_totalBillAmount = ttk.Label(self.base_frame, text=self.totalBillAmountwithAlladd, width=14,
                                          font=('Calibri', AppConstant.FONT_SIZE - 4, 'bold'), background='white',
                                          foreground="black")

        self.label_totalBillAmount.place(width=100, height=self.height * 5 / 100, x=self.width / 2 + 560,
                                    y=self.height * 85 / 100)

        self.toale_line1_canvas = Canvas(self.base_frame, bg=self.color, borderwidth=0, relief="flat", highlightthickness=0)
        self.toale_line1_canvas.place(width=self.width / 2 - 4, height=5, x=self.width / 2 - 40, y=self.height * 85 / 100)
        self.toale_line1_canvas.create_line(0, 0, self.width, 0, fill="#787878")

        self.total_line2_canvas = Canvas(self.base_frame, bg=self.color, borderwidth=0, relief="flat", highlightthickness=0)
        self.total_line2_canvas.place(width=self.width / 2 - 4, height=5, x=self.width / 2 - 40, y=self.height * 90 / 100)
        self.total_line2_canvas.create_line(0, 0, self.width, 0, fill="#787878")




    

Implement generate Bill Button functionality

    
    def generateBill(self):
        self.second_window()
  
    def second_window(self):
        global top
        top = tk.Toplevel()
        top.title("Customer Details")

        up_width=600;
        up_height=int(600 * 70 / 100);
        top.configure(bg="#585858")
        padding = 0
        cornerradius = 40
        color = "#FFFFFF"
        top.resizable(width=0, height=0)
        top.geometry(str(up_width) + "x" + str(int(up_height * 92 / 100)) + "+" + str(450) + "+" + str(200))
        rounder_area_width=up_width*94/100
        rounded_area_height=up_height*87/100

        bg_up_canvas = RoundBackgroundFrame(top,rounder_area_width , rounded_area_height, padding, cornerradius, color, "#585858")
        bg_up_canvas.place(width=rounder_area_width,height= rounded_area_height,
                           x=(up_width-rounder_area_width)/2,
                           y=(up_height-rounded_area_height)/6)

        frame_width = rounder_area_width* 98 / 100
        frame_height = rounded_area_height * 94 / 100

        up_base_frame = Frame(top, width=frame_width, height=frame_height, bg=color)
        bg_up_canvas.create_window(frame_width / 100, frame_height * 3 / 100, anchor=NW, window=up_base_frame)

        self.customer_name_entry = CustomEntry(up_base_frame, 300, 55, 10, 2, color, "Customer Name",
                                            "images/ic_user_black.png")
        self.customer_name_entry.place(x=150, y=70)

        self.customer_contact_entry = CustomEntry(up_base_frame, 300, 55, 10, 2, color, "Customer Contact No",
                                          "images/ic_user_black.png")
        self.customer_contact_entry.place(x=150, y=170)
        #
        button_submit = RoundedButton(up_base_frame, 130, 130 / 4.2, color, "images/button3.png", "Enter",
                                      font=("Lucida Grande", AppConstant.FONT_SIZE - 6),command=lambda: self.submit_click())
        button_submit.place(width=400, height=80, x=300,y=270)


    
    
def submit_click(self):
        print("Call The Submit Button")
        self.customerName = self.customer_name_entry.entry.get();
        self.customerContactNo = self.customer_contact_entry.entry.get()
        if(self.customer_name_entry.entry.get()=="" or self.customer_contact_entry.entry.get()==""):
            messagebox.showerror("Error messesge","Customer Name and Contact No should not be empty")
        else:
            top.quit()
            top.destroy()
            self.totalBill()
            conn = Util.connect_db()
            cursor = conn.cursor()
            key = "BILL_LAST_COUNT"
            cursor.execute('SELECT value FROM system_info WHERE key IS ?', (key,))
            rows = cursor.fetchone()
            print(rows[0])
            print()

            id_count = Util.convert_string_to_int(rows[0]) + 1
            formatted_time =  datetime.datetime.today().strftime('%d-%m-%Y')

            bill_number = get_Bill_no(id_count) +str(id_count)
            print(bill_number)

            cursor.execute("UPDATE system_info SET value = ? WHERE key = ?",
                           (id_count, key,))
            conn.commit()



            self.customer_name = Label(self.base_frame, text=self.customerName, anchor=W, bg=self.color,
                                        font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
            self.customer_name.place(width=self.width * 20 / 100, height=self.height * 5 / 100,
                                      x=self.width * 55 / 100,
                                      y=self.height * 33 / 100)

            self.customer_phone_no = Label(self.base_frame, text=self.customerContactNo, anchor=W, bg=self.color,
                                            font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
            self.customer_phone_no.place(width=self.width * 9 / 100, height=self.height * 5 / 100,
                                          x=self.width * 88 / 100,
                                          y=self.height * 33 / 100)

            self.bill_number_text = Label(self.base_frame, text=bill_number, anchor=W, bg=self.color,
                                        font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
            self.bill_number_text.place(width=self.width * 20 / 100, height=self.height * 5 / 100,
                                      x=self.width * 53 / 100,
                                      y=self.height * 37 / 100)

            self.bill_date = Label(self.base_frame, text=formatted_time, anchor=W, bg=self.color,
                                            font=("Lucida Grande", AppConstant.FONT_SIZE - 5))
            self.bill_date.place(width=self.width * 12 / 100, height=self.height * 5 / 100,
                                          x=self.width * 85 / 100,
                                          y=self.height * 37 / 100)
            self.generatePdfFile(self.customerName,self.customerContactNo,bill_number,formatted_time)

    
    def get_Bill_no(bill_no):
    bill = "100"
    count = 0

    if bill_no == 0:
        count = 1

    while bill_no > 0:
        count = count + 1
        bill_no = bill_no // 10

    count = 3 - count

    while count > 0:
        bill = bill + "0"
        count = count - 1

    return bill

For Generate the bill in pdf We will add the functionality of We have to add the library (reportlab)

    
   
    def generatePdfFile(self,customer_name,customer_contact_no,bill_no,dateTime):
        print(self.allSelectedProduct)
        shopName=self.heding_shop_name
        shopAddress=self.heding_shop_address
        shopGST=self.heading_shop_gst
        print(customer_name)




        doc = SimpleDocTemplate("pdf/"+str(bill_no)+".pdf", pagesize=A4,
                                rightMargin=72, leftMargin=72,
                                topMargin=72, bottomMargin=18)

        Story = []



        Story.append(Spacer(1, 12))

        styles = getSampleStyleSheet()
        styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY,fontName='Times-Bold'))
        styles.add(ParagraphStyle(name='RIGHT', alignment=TA_RIGHT,fontName='Times-Bold'))
        styles.add(ParagraphStyle(name='CENTER', alignment=TA_CENTER,fontName='Times-Bold'))
        styles.add(ParagraphStyle(name='LEFT', alignment=TA_LEFT,fontName='Times-Bold'))

        ptext = '%s' % shopName
        Story.append(Paragraph(ptext, styles["CENTER"]))
        Story.append(Spacer(1, 3))

        ptext = '%s' % shopAddress
        Story.append(Paragraph(ptext, styles["CENTER"]))
        Story.append(Spacer(1, 5))


        ptext = '%s' % "GSTIN : "+shopGST
        Story.append(Paragraph(ptext, styles["CENTER"]))
        Story.append(Spacer(1, 12))

        customer_data = [
            [Paragraph("Customer Name : "+customer_name, styles["LEFT"]), Paragraph("Contact No : " + customer_contact_no, styles["RIGHT"])],
            [Paragraph("Bill No : "+bill_no, styles["LEFT"]), Paragraph("DateTime : "+str(dateTime), styles["RIGHT"])]
        ]
        tbl = Table(customer_data)
        Story.append(tbl)
        Story.append(Spacer(1, 8))

        d = Drawing(100, 1)
        d.add(Line(0, 0, 450, 0))
        Story.append(d)
        Story.append(Spacer(1, 8))



        data = [[random.random() for i in range(1, 4)] for j in range(1, 8)]
        df = pd.DataFrame(data)


        t_style = TableStyle([('ALIGN', (1, 1), (-2, -2), 'LEFT'),
                              ('TEXTCOLOR', (1, 1), (-2, -2), colors.blue),
                              ('VALIGN', (0, 0), (0, -1), 'TOP'),

                              ])
        s = getSampleStyleSheet()
        s = s["BodyText"]
        s.wordWrap = 'CJK'
        allSelectedProductheading=[]
        product_heading = ["S.NO","Name","GST", "Price", "quantity", "Total"]


        allSelectedProductheading.append(product_heading)
        t2 = Table(allSelectedProductheading, colWidths=[0.5*inch,2.2*inch,0.6*inch,0.6*inch, 1*inch])
        t2.setStyle(t_style)
        Story.append(t2)
        Story.append(Spacer(1, 8))

        d = Drawing(100, 1)
        d.add(Line(0, 0, 450, 0))
        Story.append(d)
        Story.append(Spacer(1, 8))


        t_style = TableStyle([('ALIGN', (3, 1), (-3, -1), 'LEFT'),
                              ('TEXTCOLOR', (1, 1), (-2, -2), colors.black),
                              ('VALIGN', (0, 0), (0, -1), 'TOP'),

                              ])


        t = Table(self.allSelectedProduct,colWidths=[0.5*inch,2.2*inch,0.6*inch,0.6*inch, 1*inch])
        t.setStyle(t_style)

        Story.append(t)
        Story.append(Spacer(1, 12))

        d = Drawing(100, 1)
        d.add(Line(0, 0, 450, 0))
        Story.append(d)
        Story.append(Spacer(1, 10))

        Story.append(Indenter(right=50))
        ptext = '%s'% "Rounded Total(In Rs)  :   "+str(self.totalBillAmountwithAlladd)
        Story.append(Paragraph(ptext, styles["RIGHT"]))
        Story.append(Indenter(right=-50))

        Story.append(Spacer(1, 10))

        d = Drawing(100, 1)
        d.add(Line(0, 0, 450, 0))
        Story.append(d)


        Story.append(Spacer(1, 12))
        ptext = 'Sing Of Shopkeeper,'
        Story.append(Paragraph(ptext, styles["RIGHT"]))
        Story.append(Spacer(1, 48))


        doc.build(Story)
        self.count=1



    

Implement Cancle Button functionality

    
    def reset_product(self):
        conn = Util.connect_db()
        cursor = conn.cursor()
        self.tree.delete(*self.tree.get_children())
        cursor.execute("SELECT * FROM `product` ORDER BY `product_id` ASC")
        fetch = cursor.fetchall()
        for data in fetch:
            self.tree.insert('', 'end', values=(data))
        cursor.close()
        conn.close()
    

Programmer Mirta is for learning and training. Projects might be simple to improve learning. Projects are constantly reviewed to avoid errors, but we cannot assure full correctness of all content. While using Programmer Mitra, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 2021 by Programmer Mitra. All Rights Reserved.