Files
ecos/Linux/pecos.py

290 lines
12 KiB
Python

#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# GUI module generated by PAGE version 5.4
# in conjunction with Tcl version 8.6
# Sep 30, 2020 01:32:51 PM CDT platform: Linux
import sys
from PIL import Image, ImageTk
import sqlite3
from datetime import datetime
from datetime import date
import os
import shutil
from tkinter import messagebox
from xlsxwriter.workbook import Workbook
from barcode import Code39
from barcode.writer import ImageWriter
import subprocess
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
import pecos_support
# --- SET UP A TIMESTAMP FUNCTION THAT UPDATES PROPERLY ---
def timestamp():
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
def ReportTime():
return datetime.now().strftime('%H:%M:%S on %A, %B %d, %Y')
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = tk.Tk()
top = Toplevel1 (root)
pecos_support.init(root, top)
root.iconbitmap('PECOS.ico')
root.mainloop()
w = None
def create_Toplevel1(rt, *args, **kwargs):
'''Starting point when module is imported by another module.
Correct form of call: 'create_Toplevel1(root, *args, **kwargs)' .'''
global w, w_win, root
#rt = root
root = rt
w = tk.Toplevel (root)
top = Toplevel1 (w)
pecos_support.init(w, top, *args, **kwargs)
return (w, top)
def destroy_Toplevel1():
global w
w.destroy()
w = None
# Close database connection
conn.close()
class Toplevel1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
top.geometry("600x500+650+150")
top.minsize(1, 1)
top.maxsize(1905, 1050)
top.resizable(0, 0)
top.title("PECOS - Polaris Emergency Check Out System 1.0b (Windows)")
# --- CHECKOUT ITEM AND UPDATE DATABASE ---
def CheckOutItem(event=None):
if len(self.item_entry.get()) == 0:
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO Batches VALUES (:BatchNumber, :PatronID)",
{
'BatchNumber': CurrentBatchNumber,
'PatronID': self.patron_entry.get()
}
)
# Commit changes
conn.commit()
self.patron_entry.delete(0, tk.END)
self.item_entry.delete(0, tk.END)
self.patron_entry.configure(state='normal')
self.patron_entry.delete(0, tk.END)
self.patron_entry.focus_set()
else:
# Set up database connections
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO CheckOuts VALUES (:PatronID, :ItemID, :TransactionDateTime, :ItemLink, :PatronLink, :BatchNumber)",
{
'PatronID': self.patron_entry.get(),
'ItemID': self.item_entry.get(),
'TransactionDateTime': timestamp(),
'ItemLink': ("item/" + self.item_entry.get()),
'PatronLink': ("patron/" + self.patron_entry.get()),
'BatchNumber': CurrentBatchNumber
}
)
# Commit changes
conn.commit()
#PatronBarcode = self.patron_entry.get()
PatCode = Code39(self.patron_entry.get(), add_checksum=False)
PatCode.save("patron/"+self.patron_entry.get())
ItemCode = Code39(self.item_entry.get(), add_checksum=False)
ItemCode.save("item/"+self.item_entry.get())
self.item_entry.delete(0, tk.END)
# --- PATRON SCANNED - MOVE TO ITEM FIELD ---
def ChangeFocus(event):
self.item_entry.focus_set()
self.patron_entry.configure(state='disabled')
# --- FINISH CHECKOUT AND CLEAR FIELDS ---
def CheckOutComplete():
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO Batches VALUES (:BatchNumber, :PatronID)",
{
'BatchNumber': CurrentBatchNumber,
'PatronID': self.patron_entry.get()
}
)
# Commit changes
conn.commit()
self.patron_entry.delete(0, tk.END)
self.item_entry.delete(0, tk.END)
self.patron_entry.configure(state='normal')
self.patron_entry.delete(0, tk.END)
self.patron_entry.focus_set()
# --- DELETE THE CURRENT DATABASE AND SUPPLANT WITH AN EMPTY ONE ---
def ClearDatabase():
self.ClearConfirm = tk.messagebox.askquestion ('PECOS - Clear Database','Are you sure you wish to clear the database? This cannot be undone!')
if self.ClearConfirm == 'yes':
# Next two lines commented out in Windows version - the connection commands work on macOS
#conn = sqlite3.connect('checkouts.db') # Re-establish connection to the database
#conn.close # Close out the current database
self.ConfirmClear = tk.messagebox.askquestion ('PECOS - Confim','Final answer: Are you sure you wish to clear the database?')
if self.ConfirmClear == 'yes':
os.remove("checkouts.db") # Delete the current database
shutil.copy("emptybase.db", "checkouts.db") # Copy over an empty database
shutil.rmtree('item')
shutil.rmtree('patron')
os.makedirs('item')
os.makedirs('patron')
# Next two lines commented out in Windows version - the connection commands work on macOS
#conn = sqlite3.connect('checkouts.db') # Restablish connection to the database
#c = conn.cursor()
else:
messagebox.showinfo('PECOS - Database Retained','Database retained. No changes made.')
# --- EXPORT DATABASE TO HTML ---
def ExportDatabase():
if os.path.exists("export.html"):
os.remove("export.html")
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
with open("export.html", "w") as f:
f.write("<html>\n")
f.write("<head>\n")
f.write("<title>\n")
f.write("PECOS Export - " + ReportTime() + "\n")
f.write("</title>\n")
f.write("<h2>PECOS Export File &ndash; " + ReportTime() + "</h2>\n<hr>\n")
f.write("<style type=\"text/css\">\n")
f.write(".tg {border-collapse:collapse;border-spacing:0;}\n")
f.write(".tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; overflow:hidden;padding:10px 5px;word-break:normal;}\n")
f.write(".tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n")
f.write(".tg .tg-cly1{text-align:left;vertical-align:middle}\n")
f.write("</style>\n")
f.write("<table class=\"tg\">\n")
f.write("<thead>\n")
f.write("<tr>\n")
f.write("<th class=\"tg-cly1\"><strong>Patron Library Card</strong></th>")
f.write("<th class=\"tg-cly1\"><strong>Batch Number</strong></th>")
f.write("<th class=\"tg-cly1\"><strong>Item Barcode</strong>\n")
f.write("</tr>\n")
for row in c.execute("SELECT BatchNumber, PatronLink, ItemLink FROM CheckOuts ORDER By BatchNumber"):
f.write("<tr>\n")
f.write("<th class=\"tg-cly1\"><img src=\"" + row[1] + ".svg\" width=200></th>")
f.write("<th class=\"tg-cly1\"><strong>Batch: </strong>" + str(row[0]) + "</th>")
f.write("<th class=\"tg-cly1\"><img src=\"" + row[2] + ".svg\" width=200>\n")
f.write("</tr>\n")
subprocess.run(['open', 'export.html'], check=True) # Open export.html in the default web browser (macOS)
#os.startfile('export.html') # Open export.html in the default web browser (Windows)
self.Canvas1 = tk.Canvas(top)
self.image = ImageTk.PhotoImage(Image.open("bg-01.png"))
self.Canvas1.create_image(0,0,anchor="nw",image=self.image)
self.Canvas1.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0)
self.Canvas1.configure(borderwidth="2")
self.Canvas1.configure(relief="ridge")
self.Canvas1.configure(selectbackground="blue")
self.Canvas1.configure(selectforeground="white")
self.Frame1 = tk.Frame(self.Canvas1)
self.Frame1.place(relx=0.05, rely=0.06, relheight=0.17, relwidth=0.908)
self.Frame1.configure(relief='sunken')
self.Frame1.configure(borderwidth="2")
self.Frame1.configure(relief="sunken")
self.patron_label = tk.Label(self.Canvas1)
self.patron_label.place(relx=0.067, rely=0.08, height=19, width=100)
self.patron_label.configure(text='''Patron barcode:''')
self.patron_entry = tk.Entry(self.Canvas1)
self.patron_entry.place(relx=0.25, rely=0.08,height=25, relwidth=0.377)
self.patron_entry.configure(background="white")
self.patron_entry.configure(font="TkFixedFont")
self.patron_entry.bind('<Return>', ChangeFocus)
self.item_label = tk.Label(self.Canvas1)
self.item_label.place(relx=0.067, rely=0.16, height=19, width=89)
self.item_label.configure(text='''Item barcode:''')
self.item_entry = tk.Entry(self.Canvas1)
self.item_entry.place(relx=0.25, rely=0.16,height=25, relwidth=0.377)
self.item_entry.configure(background="white")
self.item_entry.configure(font="TkFixedFont")
self.item_entry.bind('<Return>', CheckOutItem)
self.finish_button = tk.Button(self.Canvas1, command=CheckOutComplete)
self.finish_button.place(relx=0.7, rely=0.12, height=29, width=123)
self.finish_button.configure(text='''Finish checkout''')
self.LowerFrame = tk.Frame(self.Canvas1)
self.LowerFrame.place(relx=0.05, rely=0.78, relheight=0.13, relwidth=0.908)
self.LowerFrame.configure(relief='sunken')
self.LowerFrame.configure(borderwidth="2")
self.LowerFrame.configure(relief="sunken")
self.export_button = tk.Button(self.LowerFrame, command=ExportDatabase)
self.export_button.place(relx=0.092, rely=0.308, height=29, width=130)
self.export_button.configure(text='''Export Checkouts''')
self.clear_button = tk.Button(self.LowerFrame, command=ClearDatabase)
self.clear_button.place(relx=0.679, rely=0.308, height=29, width=130)
self.clear_button.configure(text='''Clear Database''')
if __name__ == '__main__':
vp_start_gui()