Search Customer

Search Customer

Above UI we are going to create by Tkinter for Search for exesting Customer and open transaction details when click on it in our Bank 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.

    
       
        root = tk.Toplevel()

        root.title("Search Customer")

        root.configure(bg="#585858")
        root.resizable(width=0, height=0)
        win_width = 1280
        win_height = int(1280 * 56.25 / 100)
        root.geometry(str(win_width) + "x" + str(win_height))
        Util.center(root)


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

        self.width = win_width * 96 / 100
        self.height = win_height * 94 / 100
        cornerradius = 40
    

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

    
    bg_canvas = RoundBackgroundFrame(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 / 2)

    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)
            self.width = width
            self.height = height
            self.padding = padding
            self.cornerradius = cornerradius
            self.color = color
  
            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)


    

Once your window is created with custom background, we will create a frame with some reduced dimensions.

    
    self.width = self.width * 98 / 100
    self.height = self.height * 96 / 100
    self.base_frame = Frame(root, width=self.width, height=self.height, bg=self.color)
    bg_canvas.create_window(self.width / 100, self.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="Search Customer", 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")


    add_search_frame(self.base_frame, self.color, self.height, self.width)

    def add_search_frame(base_frame, color, height, width):
        sfw = width * 0.94
        sfh = height * 0.87
        button_font = ("Lucida Grande", AppConstant.FONT_SIZE - 6)

        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.03, y=height * 0.12)




  
        
    

So we are done with all frame and background UI. Now we will add search, list of customer.

    

    # Add Search UI

   
    self.ce_customer_var = CustomEntry(self.base_frame, 300, 55, 10, 2, self.color, "Search Customer","images/ic_search.png")
   
    self.ce_customer_var.place(x=160, y=self.height * 0.20)

    self.ce_customer_var.entry.bind('', self.search_customer)
        

    
Here is our class CustomEntry:

    
class CustomEntry(tk.Canvas):

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

        self.width = width
        self.height = height
        self.cornerradius = cornerradius
        self.padding = padding
        self.color = color
        original = Image.open(icon_path)
        resized = original.resize((int(height * 35 / 100), int(height * 35 / 100)), Image.ANTIALIAS)
        self.image = ImageTk.PhotoImage(resized)  # Keep a reference, prevent GC


        self.create_text(6, 7, anchor=W, font=font.Font(family="Lucida Grande", size=12, weight='bold'),text=text, fill="#000000")
        self.create_image(10, height / 2 - self.image.width() / 2, image=self.image, anchor=NW)
        self.create_line(5, height - 8, width - 5, height - 8, fill="#808080")


        frame = Frame(parent,width=width * 86 / 100, height=height * 50 / 100, bg=color)
        self.entry = Entry(frame, bg=color, bd=0, highlightthickness=0,font=font.Font(family="Lucida Grande", size=13, weight='normal'))


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

        self.create_window(width - width * 86 / 100 - 5, 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 calculate total balance.

    
    def search_customer(self, *arg):


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

            conn = Util.connect_db()
            cursor = conn.cursor()
            balance = 0
            status = "Active"
            cursor.execute("SELECT customer_id, account_number, customer_name, contact_number FROM `customer` WHERE status LIKE ? AND (`customer_name` LIKE ? OR `account_number` LIKE ?)",
                                        (status, '%' + str(self.ce_customer_var.entry.get()) + '%','%' + str(self.ce_customer_var.entry.get()) + '%'))
   
            sql_output = cursor.fetchall()


            count = 0
            room_data_list = []
            for data in sql_output:
            cursor.execute('SELECT credit FROM statement where account_number IS ?', (data[1],))
            sql_outputTwo = cursor.fetchall()


            old_credit = 0
            for amountdata in sql_outputTwo:
                for items in amountdata:
                    old_credit = old_credit + items

                cursor.execute('SELECT  debit FROM statement where account_number IS ?', (data[1],))
                sql_output = cursor.fetchall()

                old_debit = 0
            for debitdata in sql_output:
                for items in debitdata:
                    old_debit = old_debit + items

                    balance = old_credit - old_debit
    
                    numbers_tuple = (balance)
                    room_data_list.append((numbers_tuple, ""))
                    self.tree.insert('', 'end', values=data + room_data_list[count])
                    count += 1

            conn.close()
        else:
            self.reset_customer()

    def reset_customer(self):
        self.tree.delete(*self.tree.get_children())
        self.get_table_data() 
    

Here's the logic to get search table data in table.

    

    def get_table_data(self):
        conn = Util.connect_db()
        cursor = conn.cursor()
        balance = 0
        status = "Active"

        cursor.execute(
            'SELECT customer_id, account_number, customer_name, contact_number FROM customer  where status = ?', (status,))
        sql_output = cursor.fetchall()

        count = 0
        room_data_list = []
        for data in sql_output:
            cursor.execute(
                'SELECT credit FROM statement where account_number IS ?', (data[1],))
            sql_outputTwo = cursor.fetchall()

            # print(sql_outputTwo)
            old_credit = 0
            for amountdata in sql_outputTwo:
                for items in amountdata:
                    if items != "":
                        old_credit = old_credit + items
                    else:
                        old_credit = 0

            cursor.execute(
                'SELECT  debit FROM statement where account_number IS ?', (data[1],))
            sql_output = cursor.fetchall()

            old_debit = 0
            for debitdata in sql_output:
                for items in debitdata:
                    if items != "":
                        old_debit = old_debit + items
                    else:
                        old_debit = 0

            balance = old_credit - old_debit
            # print(balance)

            # print(sql_outputTwo)
            numbers_tuple = (balance)
            room_data_list.append((numbers_tuple, ""))
            self.tree.insert('', 'end', values=data + room_data_list[count])
            count += 1
        # print(room_data_list)



    

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

    

    def table_heading(self):

        heading_y = 203
        bg_color = "#046301"
        text_color = "#ffffff"

        canvas = Canvas(self.base_frame, width=835, height=30)
        canvas.create_rectangle(0, 0, 835, 30, fill=bg_color)
        canvas.place(x=160, y=heading_y - 4)

        customer_id_label = Label(self.base_frame, text="Customer Id",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
                                  background=bg_color,foreground=text_color)
        customer_id_label.place(x=170, y=heading_y, width=130)
        customer_id_label.configure(anchor="center")

        account_no_label = Label(self.base_frame, text="Account No",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
                                 background=bg_color,foreground=text_color)
        account_no_label.place(x=330, y=heading_y, width=120)
        account_no_label.configure(anchor="center")

        customer_name_label = Label(self.base_frame, text="Name",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
                                    background=bg_color,foreground=text_color)
        customer_name_label.place(x=510, y=heading_y, width=110)
        customer_name_label.configure(anchor="center")

        contact_no = Label(self.base_frame, text="Contact No",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
                           background=bg_color,foreground=text_color)
        contact_no.place(x=670, y=heading_y, width=150)
        contact_no.configure(anchor="center")

        balance_label = Label(self.base_frame, text="Balance",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
                              background=bg_color,foreground=text_color)
        balance_label.place(x=830, y=heading_y, width=160)
        balance_label.configure(anchor="center")

        

We have created heading for Transaction page, lets configure it.

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

        

UI part is completed, lets move to funtionality. First we need to show selected account details in Transaction table and also created our own heading for transaction .

      
    def transaction(acc_no, cust_name):
        root = tk.Tk()

        root.title("Transaction")

        root.configure(bg="#585858")
        root.resizable(width=0, height=0)

        root.configure(bg="#FFFFFF")
        root.resizable(width=0, height=0)
        win_width = 1020
        win_height = int(1020 * 56.25 / 100)
        root.geometry(str(win_width) + "x" + str(win_height))
        Util.center(root)

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

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

   

        add_Trans_heading_label(root, color, AppConstant.FONT_SIZE, height, width)

        style = ttk.Style()
    
        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.map("Custom.Treeview.Heading", relief=[('active', 'groove'), ('pressed', 'sunken')])
        style.configure("Custom.Treeview", highlightthickness=0, bd=0, font=('Calibri', 11), rowheight=30)

       

        transaction_tree = ttk.Treeview(root, height=14, columns=("c1", "c2", "c3", "c4", "c5", "c6"),
                                            show='tree', style="Custom.Treeview")
        transaction_tree.tag_configure('odd', background='#DFEBF6', foreground="#000000", )
        transaction_tree.tag_configure('even', background='#FFFFFF', foreground="#000000", )
        transaction_tree.place(x=100, y=height * 0.35)

        transaction_tree.column("#0", width=0)
        transaction_tree.column("#1", width=130)
        transaction_tree.column("#2", width=130)
        transaction_tree.column("#3", width=130)
        transaction_tree.column("#4", width=130)
        transaction_tree.column("#5", width=150)
        transaction_tree.column("#6", width=150)
    

        vsbr = ttk.Scrollbar(root, orient="vertical", command=transaction_tree.yview)
        vsbr.place(x=width - 50, y=height * 0.35, height=280)
        transaction_tree.configure(yscrollcommand=vsbr.set)

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

     
       

        #---------------- account label-------------

        selected_acc_no_label = ttk.Label(root, text="Account No :", width=20,
                                      font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background='white',
                                      foreground="black")
        selected_acc_no_label.place(x=100, y=80)

        selected_acc_label = ttk.Label(root, text=acc_no, width=80,
                                        font=('Calibri', AppConstant.FONT_SIZE - 2), background='white',
                                        foreground="black")
        selected_acc_label.place(x=250, y=80)

        selected_cust_name_label = ttk.Label(root, text="Customer Name :", width=20,
                                      font=('Calibri', AppConstant.FONT_SIZE - 5), background='white',
                                      foreground="black")
        selected_cust_name_label.place(x=100, y=110)

        selected_name_label = ttk.Label(root, text=cust_name, width=80,
                                   font=('Calibri', AppConstant.FONT_SIZE - 4), background='white',
                                   foreground="black")
        selected_name_label.place(x=250, y=110)
    

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

    
        heading_y = height * 0.28
        bg_color = "#2929ff"

        canvas = Canvas(root, width=815, height=30)
        canvas.create_rectangle(0, 0, 815, 30, fill=bg_color)
        canvas.place(x=100, y=heading_y-2)

        transaction_id_label = Label(root, text="Transaction Id",font=('Calibri', AppConstant.FONT_SIZE - 4, 'bold'), 
                                        background=bg_color,foreground="white")
        transaction_id_label.place(x=120, y=heading_y, width=120)
        transaction_id_label.configure(anchor="center")

        credit_label = Label(root, text="Credit",font=('Calibri', AppConstant.FONT_SIZE - 4, 'bold'), 
                                background=bg_color,foreground="white")
        credit_label.place(x=270, y=heading_y, width=100)
        credit_label.configure(anchor="center")

        debit_label = Label(root, text="Debit",font=('Calibri', AppConstant.FONT_SIZE - 4, 'bold'), 
                                background=bg_color,foreground="white")
        debit_label.place(x=400, y=heading_y, width=100)
        debit_label.configure(anchor="center")

        balance_label = Label(root, text="balance",font=('Calibri', AppConstant.FONT_SIZE - 4, 'bold'), 
                                background=bg_color,foreground="white")
        balance_label.place(x=530, y=heading_y, width=100)
        balance_label.configure(anchor="center")

        credit_date_label = Label(root, text="Credit Date",font=('Calibri', AppConstant.FONT_SIZE - 4, 'bold'), 
                                    background=bg_color,foreground="white")
        credit_date_label.place(x=660, y=heading_y, width=120)
        credit_date_label.configure(anchor="center")

        debit_date_label = Label(root, text="Debit Date",font=('Calibri', AppConstant.FONT_SIZE - 4, 'bold'), 
                                    background=bg_color,foreground="white")
        debit_date_label.place(x=787, y=heading_y, width=120)
        debit_date_label.configure(anchor="center")


  
        
    

Here's the logic to get tansaction data in table.

    
    
        conn = Util.connect_db()
        cursor = conn.cursor()
    
        cursor.execute('SELECT transaction_id, credit, debit, balance, credit_date, debit_date FROM statement where account_number IS ?',(acc_no,))
        sql_output = cursor.fetchall()
        
        for data in sql_output:
            transaction_tree.insert('', 'end', values=data)


    

At last we will manage closing of window

    
    def on_closing():
                        
        root.destroy()
        args[0].deiconify()
                       
    root.protocol("WM_DELETE_WINDOW", on_closing)
                       

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.