Credit/Debit

root = tk.Toplevel()
root.title("Credit/Debit")
root.configure(bg="#585858")
root.resizable(width=0, height=0)
win_width = 1280
print(1280 * 56.25 / 100)
win_height = int(1280 * 56.25 / 100)
root.geometry(str(win_width) + "x" + str(win_height))
# 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
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)
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="Credit/Debit", 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")
def add_transaction_frame(base_frame, button_font, color, height, width):
sfw = width * 0.638
sfh = height * 0.87
label_frame_search = LabelFrame(base_frame, text="Transaction", 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)
button_font = add_action_frame(self.base_frame, self.color, self.height, self.width)
#Add Action Frame
def add_action_frame(base_frame, color, height, width):
afw = width * 0.35
afh = height * 0.87
button_font = ("Lucida Grande", AppConstant.FONT_SIZE - 6)
label_frame_action = LabelFrame(base_frame, text="Actions", font=button_font, pady=afw * 2 / 100,
padx=afw * 2 / 100, bg=color)
label_frame_action.place(width=afw, height=afh, x=0, y=height * 0.12)
return button_font
add_search_frame(self.base_frame, button_font, self.color, self.height, self.width)
def add_search_frame(base_frame, color, height, width):
afw = width * 0.35
afh = height * 0.87
button_font = ("Lucida Grande", AppConstant.FONT_SIZE - 6)
label_frame_action = LabelFrame(base_frame, text="Search", font=button_font, pady=afw * 2 / 100,
padx=afw * 2 / 100, bg=color)
label_frame_action.place(width=afw, height=afh, x=0, y=height * 0.12)
return button_font
# Add Search UI
self.ce_customer_var = CustomEntry(self.base_frame, 300, 55, 10, 2, self.color, "Search Account No","images/ic_search.png")
self.ce_customer_var.place(x=20, y=self.height * 0.20)
self.customer_var = tk.StringVar
self.ce_customer_var.entry.bind('', self.search_accno)
myColor = '#FFFFFF'
s = ttk.Style()
s.configure('Wild.TRadiobutton', background=myColor, foreground='black')
self.radioBtn_val = StringVar()
self.radioButton1 = ttk.Radiobutton(root, text="Credit", value="Credit", variable=self.radioBtn_val, style = 'Wild.TRadiobutton')
self.radioButton1.place(x=65, y=self.height * 0.70, width=100)
self. radioButton2 = ttk.Radiobutton(root, text="Debit", value="Debit", variable=self.radioBtn_val, style = 'Wild.TRadiobutton')
self.radioButton2.place(x=200, y=self.height * 0.70, width=100)
self.radioButton1.option_clear()
self.radioButton2.option_clear()
self.amount = CustomEntrySimple(self.base_frame, 300, 60, ("Lucida Grande", AppConstant.FONT_SIZE - 6),self.color,"Amount")
self.amount.place(x=20, y=self.height * 0.74)
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, bg=color)
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()
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)
Now Create a Transaction UI for selected Account. First we create a lable to selected Account No.
selected_acc_no_label = Label(self.base_frame, text="Account No :",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
background='white',foreground="black")
selected_acc_no_label.place(x=450, y=110, width=150)
self.selected_acc_no_data = ""
self.selected_acc_label = ttk.Label(self.base_frame, text=self.selected_acc_no_data,font=('Calibri', AppConstant.FONT_SIZE - 2),
background='white',foreground="black")
self.selected_acc_label.place(x=610, y=110, width=250)
Here's the logic to search data in table.
def search_accno(self, *arg):
if self.ce_customer_var.entry.get() != "":
self.account_tree.delete(*self.account_tree.get_children())
conn = Util.connect_db()
cursor = conn.cursor()
balance = 0
status = "Active"
cursor.execute("SELECT account_number, customer_name 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[0],))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[0],))
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.account_tree.insert('', 'end', values=data + room_data_list[count])
count += 1
cursor.close()
conn.close()
else:
self.reset_search()
def reset_search(self):
self.account_tree.delete(*self.account_tree.get_children())
self.get_account_table_data()
Here's the logic to show accounts data in table.
def get_account_table_data(self):
conn = Util.connect_db()
cursor = conn.cursor()
balance = 0
status = "Active"
cursor.execute('SELECT account_number, customer_name 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[0],))
sql_outputTwo = cursor.fetchall()
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[0],))
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
numbers_tuple = (balance)
room_data_list.append((numbers_tuple, ""))
self.account_tree.insert('', 'end', values=data+room_data_list[count])
count += 1
Fetch data from database and show it in both table form with the use of "Treeview" of Tkinter.
conn = Util.connect_db()
cursor = conn.cursor()
status = "Active"
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', 10), rowheight=30)
# Search UI TREE
self.account_tree = ttk.Treeview(self.base_frame, height=8, show="tree")
self.account_tree.place(x=20, y=self.height * 0.36)
self.account_tree["columns"] = "1", "2", "3"
self.account_tree.column("#0", width=0)
self.account_tree.column("#1", width=130)
self.account_tree.column("#2", width=120)
self.account_tree.column("#3", width=120)
self.account_tree.column("#1", anchor=tk.CENTER)
self.account_tree.column("#2", anchor=tk.CENTER)
self.account_tree.column("#3", anchor=tk.CENTER)
vsb = ttk.Scrollbar(self.base_frame, orient="vertical", command=self.account_tree.yview)
vsb.place(x=398, y=self.height * 0.36, height=165)
self.account_tree.configure(yscrollcommand=vsb.set)
self.account_table_heading()
self.get_account_table_data()
self.account_tree.bind('<>', self.on_select_account_no)
# Transaction UI TREE
self.transaction_tree = ttk.Treeview(self.base_frame, height=13, columns=("c1", "c2", "c3", "c4", "c5", "c6"),
show='tree', style="Custom.Treeview")
self.transaction_tree.tag_configure('odd', background='#DFEBF6', foreground="#000000", )
self.transaction_tree.tag_configure('even', background='#FFFFFF', foreground="#000000", )
self.transaction_tree.place(x=450, y=self.height * 0.35)
self.transaction_tree.column("#0", width=0)
self.transaction_tree.column("#1", width=130)
self.transaction_tree.column("#2", width=110)
self.transaction_tree.column("#3", width=110)
self.transaction_tree.column("#4", width=110)
self.transaction_tree.column("#5", width=130)
self.transaction_tree.column("#6", width=130)
vsbr = ttk.Scrollbar(self.base_frame, orient="vertical", command=self.transaction_tree.yview)
vsbr.place(x=self.width-25, y=self.height * 0.35, height=395)
self.transaction_tree.configure(yscrollcommand=vsbr.set)
self.transaction_tree.column("#1", anchor=tk.CENTER)
self.transaction_tree.column("#2", anchor=tk.CENTER)
self.transaction_tree.column("#3", anchor=tk.CENTER)
self.transaction_tree.column("#4", anchor=tk.CENTER)
self.transaction_tree.column("#5", anchor=tk.CENTER)
self.transaction_tree.column("#6", anchor=tk.CENTER)
self.transaction_table_heading()
root.attributes('-alpha', 0.0)
Util.center(root)
root.attributes('-alpha', 1.0)
We have created our own heading for Search table, lets configure it.
def account_table_heading(self):
heading_y = self.height * 0.31
bg_color = "#046301"
canvas = Canvas(self.base_frame, width=375, height=30)
canvas.create_rectangle(0, 0, 375, 30, fill=bg_color)
canvas.place(x=20 , y=heading_y-2)
accno_id_label = Label(self.base_frame, text="Account No",
font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
foreground="white")
accno_id_label.place(x=35 , y=heading_y, width=130)
accno_id_label.configure(anchor="center")
accno_name_label = Label(self.base_frame, text="Name",
font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
foreground="white")
accno_name_label.place(x=175, y=heading_y, width=100)
accno_name_label.configure(anchor="center")
fine_label = Label(self.base_frame, text="Balance",
font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'), background=bg_color,
foreground="white")
fine_label.place(x=290 , y=heading_y, width=100)
fine_label.configure(anchor="center")
We have created our own heading for Transactional table, lets configure it.
def transaction_table_heading(self):
heading_y = self.height * 0.31
bg_color = "#046301"
canvas = Canvas(self.base_frame, width=724, height=30)
canvas.create_rectangle(0, 0, 724, 30, fill=bg_color)
canvas.place(x=450, y=heading_y - 3)
transaction_id_label = Label(self.base_frame, text="Transaction Id",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
background=bg_color,foreground="white")
transaction_id_label.place(x=465, y=heading_y, width=135)
transaction_id_label.configure(anchor="center")
credit_label = Label(self.base_frame, text="Credit",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
background=bg_color,foreground="white")
credit_label.place(x=605, y=heading_y, width=100)
credit_label.configure(anchor="center")
debit_label = Label(self.base_frame, text="Debit",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
background=bg_color,foreground="white")
debit_label.place(x=710, y=heading_y, width=100)
debit_label.configure(anchor="center")
balance_label = Label(self.base_frame, text="balance",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
background=bg_color,foreground="white")
balance_label.place(x=820, y=heading_y, width=100)
balance_label.configure(anchor="center")
credit_date_label = Label(self.base_frame, text="Credit Date",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
background=bg_color,foreground="white")
credit_date_label.place(x=928, y=heading_y, width=120)
credit_date_label.configure(anchor="center")
debit_date_label = Label(self.base_frame, text="Debit Date",font=('Calibri', AppConstant.FONT_SIZE - 3, 'bold'),
background=bg_color,foreground="white")
debit_date_label.place(x=1050, y=heading_y, width=120)
debit_date_label.configure(anchor="center")
def on_select_account_no(self, *args):
current_item = self.account_tree.focus()
self.selected_acc_no_data = self.account_tree.item(current_item)["values"][0]
self.selected_acc_label.config(text=self.selected_acc_no_data)
self.transaction_tree.delete(*self.transaction_tree.get_children())
self.get_transaction_table_data(self.selected_acc_no_data)
self.show_credit_button()
self.show_debit_button()
Here we write code for Credit and Debit Button UI.
def show_credit_button(self):
self.credit_button = RoundedButton(self.base_frame, 180, 130 / 2.56, self.color, "images/button37.png",
"Credit Amount",
font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
command=self.get_update_credit_data)
self.credit_button.place(x=15, y=self.height * 0.88)
def show_debit_button(self):
self.debit_button = RoundedButton(self.base_frame, 180, 130 / 2.56, self.color, "images/button37.png",
"Debit Amount",
font=("Lucida Grande", AppConstant.FONT_SIZE - 2),
command=self.get_update_debit_data)
self.debit_button.place(x=225, y=self.height * 0.88)
Here's the logic to show transaction data in table.
def get_transaction_table_data(self, acc_number):
conn = Util.connect_db()
cursor = conn.cursor()
# acc_no = self.selected_acc_no_data
cursor.execute(
'SELECT transaction_id, credit, debit, balance, credit_date, debit_date FROM statement where account_number IS ?',(acc_number,))
sql_output = cursor.fetchall()
# print(acc_number)
for data in sql_output:
self.transaction_tree.insert('', 'end', values=data)
# print(room_data_list)
Here we write code for "Credit Amount" functionality.
def get_update_credit_data(self):
conn = Util.connect_db()
cursor = conn.cursor()
var = "Seleted credit or debit option."
radio_btn_val = self.radioBtn_val.get()
amount = self.amount.entry.get()
credit_date = datetime.today().strftime('%Y-%m-%d')
debit_date = datetime.today().strftime('%Y-%m-%d')
acc_no = self.selected_acc_no_data
balance = 0
old_credit = 0
old_debit = 0
is_amount_entered = False
if self.amount.entry.get() == "" or self.amount.entry.get() == " ":
var += " Amount Should not be empty, "
else:
amount = self.amount.entry.get()
is_amount_entered = True
if radio_btn_val == "Credit" and is_amount_entered:
cursor.execute('SELECT credit FROM statement where account_number IS ?',(acc_no,))
sql_output = cursor.fetchall()
for data in sql_output:
for items in data:
if items != "":
old_credit = old_credit + items
else:
old_credit = 0
cursor.execute('SELECT debit FROM statement where account_number IS ?', (acc_no,))
sql_output = cursor.fetchall()
for data in sql_output:
for items in data:
if items != "":
old_debit = old_debit + items
else:
old_debit = 0
balance = (old_credit-old_debit) + int(amount)
trans_id = Util.random_with_N_digits(12)
debit = 0
debit_date = ""
cursor.execute('INSERT INTO statement(transaction_id, account_number, credit, debit, balance, credit_date, debit_date) VALUES(?,?,?,?,?,?,?)',
(trans_id, acc_no, amount, debit, balance, credit_date, debit_date))
conn.commit()
self.amount.entry.delete(0, 'end')
self.account_tree.delete(*self.account_tree.get_children())
self.transaction_tree.delete(*self.transaction_tree.get_children())
self.get_account_table_data()
self.get_transaction_table_data(acc_no)
self.radioBtn_val.set("")
self.radioButton1.option_clear()
self.radioButton2.option_clear()
self.credit_button.place_forget()
self.debit_button.place_forget()
else:
print(var)
messagebox.showerror("showerror", var)
Here we write code for "Debit Amount" functionality.
def get_update_debit_data(self):
conn = Util.connect_db()
cursor = conn.cursor()
var = ""
radio_btn_val = self.radioBtn_val.get()
amount = self.amount.entry.get()
credit_date = datetime.today().strftime('%Y-%m-%d')
debit_date = datetime.today().strftime('%Y-%m-%d')
acc_no = self.selected_acc_no_data
balance = 0
old_credit = 0
old_debit = 0
is_amount_entered = False
if self.amount.entry.get() == "" or self.amount.entry.get() == " ":
var += " Amount Should not be empty, "
else:
amount = self.amount.entry.get()
is_amount_entered = True
if radio_btn_val == "Debit" and is_amount_entered:
cursor.execute('SELECT credit FROM statement where account_number IS ?', (acc_no,))
sql_output = cursor.fetchall()
for data in sql_output:
for items in data:
if items != "":
old_credit = old_credit + items
else:
old_credit = 0
cursor.execute('SELECT debit FROM statement where account_number IS ?', (acc_no,))
sql_output = cursor.fetchall()
for data in sql_output:
for items in data:
if items != "":
old_debit = old_debit + items
else:
old_debit = 0
entered_amount = int(amount)
old_balance = (old_credit - old_debit)
if old_balance >= entered_amount:
balance = old_balance - entered_amount
trans_id = Util.random_with_N_digits(12)
credit = 0
credit_date = ""
cursor.execute('INSERT INTO statement(transaction_id, account_number, credit, debit, balance, credit_date, debit_date) VALUES(?,?,?,?,?,?,?)',
(trans_id, acc_no, credit, amount, balance, credit_date, debit_date))
conn.commit()
else:
print(var)
messagebox.showerror("showerror", "Insufficient Balance.")
self.amount.entry.delete(0, 'end')
self.account_tree.delete(*self.account_tree.get_children())
self.transaction_tree.delete(*self.transaction_tree.get_children())
self.get_account_table_data()
self.get_transaction_table_data(acc_no)
self.radioBtn_val.set("")
self.radioButton1.option_clear()
self.radioButton2.option_clear()
self.credit_button.place_forget()
self.debit_button.place_forget()
else:
print(var)
messagebox.showerror("showerror", "Seleted credit or debit option."+ var)
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.