Checkout and Return system complete
authorJohn Ladan <jladan@uwaterloo.ca>
Mon, 16 Dec 2013 06:39:03 +0000 (01:39 -0500)
committerJohn Ladan <jladan@uwaterloo.ca>
Mon, 16 Dec 2013 06:39:03 +0000 (01:39 -0500)
browser.py
checkout.py [new file with mode: 0644]
db_layer.py
form.py
librarian.py

index 88a78f0..b384728 100644 (file)
@@ -4,6 +4,10 @@ import db_layer as db
 from form import BookForm,CategoryForm
 
 class browserWindow:
+    # These are actually class variables, not member variables? :<
+    _default_height=25
+    _default_width=60
+
     hl=0
     topline = 0
     entries = []
@@ -18,13 +22,21 @@ class browserWindow:
     last_search = ""
     found_index = 0
 
-    def __init__(self,window,helpbar, height=50, width=80):
+    def __init__(self,window,helpbar, height=0, width=0):
+        if not(height and width):
+            height = browserWindow._default_height
+            width = browserWindow._default_width
+            sys.stderr.write(str(height)+', '+str(width)+'\n')
         self.w = window
         self.hb = helpbar
         self.w.resize(height,width)
         self.updateGeometry()
         self.commands = self.cs+self.commands
 
+    def load_data(self, data=[]):
+        self.entries = data
+        self.selected = list(map(lambda x:False, self.entries))
+
     def sortByColumn(self, col):
         self.entries.sort(key=lambda k: k.get(col,"")) # key=dict.get(col))
         self.selected = list(map(lambda x: False, self.selected))
@@ -255,6 +267,7 @@ class trashBrowser(browserWindow):
                   ('Title',60,None)]
     
     cs = [(' r', 'restore selected'), (' d', 'delete selected')]
+
     
     # redefinable functions
     def viewSelection(self,book):
@@ -282,8 +295,7 @@ class trashBrowser(browserWindow):
         db.deleteBooks(books)
 
     def refreshBooks(self):
-        self.entries = db.getRemovedBooks()
-        self.selected = list(map(lambda x:False, self.entries))
+        self.load_data(db.getRemovedBooks())
 
     def handleInput(self,ch):
         browserWindow.handleInput(self,ch)
@@ -320,6 +332,7 @@ class bookBrowser(browserWindow):
                   ('Title',60,None)]
     
     cs = [(' u', 'update'), (' d', 'delete selected')]
+
     
     # redefinable functions
     def updateSelection(self,book):
@@ -362,19 +375,17 @@ class bookBrowser(browserWindow):
         db.removeBooks(books)
 
     def refreshBooks(self):
-        self.entries = db.getBooks()
-        self.selected = list(map(lambda x:False, self.entries))
+        self.load_data(db.get_books())
 
     def refreshBooksInCategory(self,cat):
-        self.entries = db.getBooksByCategory(cat)
-        self.selected = list(map(lambda x:False, self.entries))
+        self.load_data(db.getBooksByCategory(cat))
 
     def handleInput(self,ch):
         browserWindow.handleInput(self,ch)
         if ch == 117: #update on 'u'
             book = self.entries[self.hl]
             self.updateSelection(book)
-            self.entries[self.hl]=db.getBookByID(book['id'])
+            self.entries[self.hl]=db.get_book(book['id'])
             self.refresh()
         elif ch == 10:
             book = self.entries[self.hl]
@@ -400,23 +411,20 @@ class categoryBrowser(browserWindow):
     columnDefs = [('Category',100,None)]
     cs = [(' a', 'add category'), (' d', 'delete selected')]
 
-
     def refreshCategories(self):
-        self.entries = db.getCategories()
+        self.load_data(db.getCategories())
         self.sortByColumn('category')
-        self.selected = list(map(lambda x:False, self.entries))
 
     def addCategory(self):
         w = curses.newwin(1,1,10,10)
         cf = CategoryForm(w,self.hb)
         self.centreChild(w)
-        cats = cf.event_loop()
-        for c in cats:
-            db.addCategory(c)
+        cat = cf.event_loop()
+        db.addCategory(cat)
         cf.clear()
 
     def viewCategory(self):
-        w = curses.newwin(20,80,20,20)
+        w = curses.newwin(3,5)
         b = bookBrowser(w,self.hb)
         self.centreChild(w)
         b.refreshBooksInCategory(self.entries[self.hl])
diff --git a/checkout.py b/checkout.py
new file mode 100644 (file)
index 0000000..02227c2
--- /dev/null
@@ -0,0 +1,99 @@
+import sys
+import curses
+from form import FormWindow,BookForm
+import db_layer as db
+
+
+class BookIDForm(FormWindow):
+    caption = "Enter the book ID"
+    blabel = "Check"
+    labels = ["Book ID"]
+
+    def _return_values(self):
+        if self._confirm_book():
+            return self.entries[0].value
+        else:
+            return False
+
+    def _confirm_book(self):
+        self.clear()
+        bookid = self.entries[0].value
+        book = db.get_book(bookid)
+        bf = BookForm(self.w, self.hb, book, width=self.mx-10)
+        (y,x) = self.w.getbegyx()
+        (r,c) = self.w.getmaxyx()
+        self.w.mvwin( y+(self.my-r)//2,x+(self.mx-c)//2)
+        bf.caption='Confirm the Book '+str(bookid)
+        bf.blabel='Correct'
+        result = bf.event_loop()
+        bf.clear()
+        if result:
+            return True
+
+
+class UWIDForm(FormWindow):
+    caption = "Enter the Patron's username"
+    blabel = "Next"
+    labels = ["Username"]
+
+    def _return_values(self):
+        return self.entries[0].value
+
+class FinalCheck(FormWindow):
+    caption = "Is this information correct?"
+    blabel = "Check Out"
+    labels = ["Username", "Book ID"]
+
+    def _return_values(self):
+        return True
+
+def checkout_procedure(w, hb, cy, cx, mx):
+    """Procedure to check out a book
+
+    w:      ncurses window for the routine
+    cy,cx:  centre coordinates of the screen
+    mx:     max width of screen
+    """
+    # Get the book ID
+    step1 = BookIDForm(w,hb,width=mx-20)
+    (r,c)=w.getmaxyx()
+    w.mvwin(cy-r//2,cx-c//2)
+    book_id = step1.event_loop()
+    step1.clear()
+    if not(book_id):
+        return
+
+    # Get the uwid
+    step2 = UWIDForm(w,hb,width=mx-20)
+    (r,c)=w.getmaxyx()
+    w.mvwin(cy-r//2,cx-c//2)
+    username = step2.event_loop()
+    step2.clear()
+    if not(username):
+        return
+
+    # Confirm the result
+    step3 = FinalCheck(w,hb,book={"username":username,"book id":book_id}, width=mx-20)
+    (r,c)=w.getmaxyx()
+    w.mvwin(cy-r//2,cx-c//2)
+    correct = step3.event_loop()
+    step3.clear()
+    if correct:
+        db.checkout_book(book_id,username)
+
+def return_procedure(w, hb, cy, cx, mx):
+    """Procedure to return a book
+
+    w:      ncurses window for the routine
+    cy,cx:  centre coordinates of the screen
+    mx:     max width of screen
+    """
+    # Get the book ID
+    step1 = BookIDForm(w,hb,width=mx-20)
+    (r,c)=w.getmaxyx()
+    w.mvwin(cy-r//2,cx-c//2)
+    book_id = step1.event_loop()
+    step1.clear()
+    if book_id:
+        db.return_book(book_id)
+    
index 0d9111b..47ecf96 100644 (file)
@@ -111,7 +111,7 @@ def updateBook(book, bookID):
     conn.commit()
     c.close()
 
-def getBooks():
+def get_books():
     conn = sqlite3.connect(_catalogue_db_file)
     c = conn.cursor()
     query = "SELECT * FROM "+_book_table+" WHERE deleted=0;"
@@ -144,7 +144,7 @@ def getRemovedBooks():
     c.close()
     return books
 
-def getBookByID(bookid):
+def get_book(bookid):
     conn = sqlite3.connect(_catalogue_db_file)
     c = conn.cursor()
     query = "SELECT * FROM "+_book_table+" WHERE id = "+str(bookid)+";"
@@ -346,7 +346,7 @@ def get_onshelf_books():
              " LEFT JOIN co."+_checkout_table+
              " USING (id) WHERE uwid ISNULL;")
     c.execute(query)
-    books = [_query_to_book_checkout(b) for b in c]
+    books = [_query_to_book(b) for b in c]
     c.close()
     return books
 
diff --git a/form.py b/form.py
index 8e927bf..d084c75 100644 (file)
--- a/form.py
+++ b/form.py
@@ -322,4 +322,4 @@ class CategoryForm(FormWindow):
     labels = ["Category"]
 
     def _return_values(self):
-        return self.entries
+        return self.entries[0].value
index 9415321..edabe4c 100755 (executable)
@@ -8,6 +8,8 @@ import help_bar as helpBar
 
 import book_data
 
+import checkout as co
+
 
 stdscr=0
 hb=0
@@ -20,11 +22,14 @@ def menutest(s, l):
     stdscr=s
     curses.curs_set(0)
     (rows,cols)=stdscr.getmaxyx()
+    # set the default for the browser windows
+    browser.browserWindow._default_height = rows-10
+    browser.browserWindow._default_width = cols-10
     bar = curses.newwin(1,cols-2,rows-1,1)
     hb = helpBar.helpBar(bar)
     hb.command=menu_commands
     hb.refresh()
-    w = curses.newwin(10,40,(rows-10)//2, (cols-40)//2)
+    w = curses.newwin(15,40,(rows-10)//2, (cols-40)//2)
 
     menu(w, l)
     
@@ -94,31 +99,61 @@ def addForm():
     if len(book)!=0:
         db.addBook(book)
 
-def updateMenu():
-    w=curses.newwin(1,50,10,10)
-    w.addstr("I will be used to update or modify book records")
-    w.refresh()
+def browseMenu():
+    w=curses.newwin(3,5)
+    b = browser.bookBrowser(w,hb)
+    (r,c) = w.getmaxyx()
+    (my,mx)=stdscr.getmaxyx()
+    w.mvwin((my-r)//2 -2, (mx-c)//2)
+    b.refreshBooks()
+    b.eventLoop()
+    b.clear()
 
 def trashMenu():
-    (my,mx)=stdscr.getmaxyx()
     w=curses.newwin(3,5)
-    b = browser.trashBrowser(w,hb,my-10,mx-10)
+    b = browser.trashBrowser(w,hb)
     (r,c) = w.getmaxyx()
+    (my,mx)=stdscr.getmaxyx()
     w.mvwin((my-r)//2 -2, (mx-c)//2)
     b.refreshBooks()
     b.eventLoop()
     b.clear()
 
-def browseMenu():
+def checkedout_menu():
+    w=curses.newwin(3,5)
+    b = browser.bookBrowser(w,hb)
+    (r,c) = w.getmaxyx()
     (my,mx)=stdscr.getmaxyx()
+    w.mvwin((my-r)//2 -2, (mx-c)//2)
+    b.load_data(db.get_checkedout_books())
+    b.columnDefs = [("id",0,3),
+                    ("uwid",0,8),
+                    ("date",0,10),
+                    ("title",100,None)]
+    b.calcColWidths()
+    b.eventLoop()
+    b.clear()
+
+def onshelf_menu():
     w=curses.newwin(3,5)
-    b = browser.bookBrowser(w,hb, my-10, mx-10)
+    b = browser.bookBrowser(w,hb)
     (r,c) = w.getmaxyx()
+    (my,mx)=stdscr.getmaxyx()
     w.mvwin((my-r)//2 -2, (mx-c)//2)
-    b.refreshBooks()
+    b.load_data(db.get_onshelf_books())
     b.eventLoop()
     b.clear()
 
+def co_menu():
+    w=curses.newwin(1,1)
+    (my,mx)=stdscr.getmaxyx()
+    co.checkout_procedure(w,hb,my//2,mx//2,mx) 
+
+def return_menu():
+    w=curses.newwin(1,1)
+    (my,mx)=stdscr.getmaxyx()
+    co.return_procedure(w,hb,my//2,mx//2,mx) 
+
 def catMenu():
     (my,mx)=stdscr.getmaxyx()
     w=curses.newwin(3,5)
@@ -138,6 +173,12 @@ if __name__ == "__main__":
          ("Categories", catMenu),
          ("View Trash", trashMenu),
          ("",exit),
+         ("Check Out a Book", co_menu),
+         ("Return a Book", return_menu),
+         ("",exit),
+         ("View Checked Out Books", checkedout_menu),
+         ("View On Shelf Books", onshelf_menu),
+         ("",exit),
          ("Exit", exit)]
     curses.wrapper(menutest, m)