Initial commit for unified repo.
This commit is contained in:
288
macOS/pecos.py
Normal file
288
macOS/pecos.py
Normal file
@ -0,0 +1,288 @@
|
||||
#! /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
|
||||
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 – " + 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()
|
Reference in New Issue
Block a user