Programming Assignment 1: Store Inventory

Honor Code

This is an individual assignment. All of the work that you submit must be written by you, based on your own understanding of the material. Representing someone else’s work as your own, in any form, constitutes an honor code violation.

Problem Description

The owner of Serpentes Books has a problem. For years, she has kept inventory using index cards in a old file box, but now that the stationery company has stopped making her favorite cards, she figures it’s time to move on to a computerized system. She has asked you to create such a system for her.

Your implementation will take advantage of the Google Books API to retrieve book information on the basis of an ISBN.

She has the following requirements:

  • She must be able to add to the inventory
  • She must be able to subtract from the inventory
  • She must be able to search the inventory on the basis of book titles
  • The inventory must be able to hold any number of books
  • The inventory must record how many of each book is available
  • The inventory must be saved when the program is quit, and loaded when the program is started

Program Operation

Upon running the program, the user is presented with a prompt: "> ". The user may type any of four commands:

  • list – lists all matching titles in the inventory
  • buy – adds to the inventory
  • sell – subtracts from the inventory
  • q – ends the program

When the list command is executed, the program will request that the user enter a search string. The program will then list all books with titles that contain a (non-case-sensitive) match with the string that is entered. If the user does not enter a search string, then all books will be displayed.

Similarly, the commands buy and sell will require the user to enter two additional pieces of information: the ISBN of the book, and the number of copies to add or subtract.

Sample Output

>>> %Run store_inventory.py
> list
Enter search string (empty for complete list):
Harry Potter and the Cha/ by J. K. Rowling          ISBN: 978-0439064866 QTY: 7
Bloodchild and Other Sto/ by Octavia E. Butler     ISBN: 978-1583226988 QTY: 5
Good Omens                    by Terry Pratchett, Ne/ ISBN: 978-0425132159 QTY: 6
Emma                             by Jane Austen             ISBN: 978-1853260285 QTY: 3
> list
Enter search string (empty for complete list): oOd
Bloodchild and Other Sto/ by Octavia E. Butler ISBN: 978-1583226988 QTY: 5
Good Omens by Terry Pratchett, Ne/ ISBN: 978-0425132159 QTY: 6
> buy
ISBN? 978-0425132159
number? 100
OK
> list
Enter search string (empty for complete list):
Harry Potter and the Cha/ by J. K. Rowling           ISBN: 978-0439064866 QTY: 7
Bloodchild and Other Sto/ by Octavia E. Butler      ISBN: 978-1583226988 QTY: 5
Good Omens                    by Terry Pratchett, Ne/ ISBN: 978-0425132159 QTY: 106
Emma                             by Jane Austen            ISBN: 978-1853260285 QTY: 3
> buy
ISBN? 978-0547928227
number? -1
You can't buy fewer than zero items!
> buy
ISBN? 978-0547928227
number? 8
OK
> list
Enter search string (empty for complete list):
Harry Potter and the Cha/ by J. K. Rowling           ISBN: 978-0439064866  QTY: 7
Bloodchild and Other Sto/ by Octavia E. Butler      ISBN: 978-1583226988  QTY: 5
Good Omens                    by Terry Pratchett, Ne/ ISBN: 978-0425132159  QTY: 106
Emma                             by Jane Austen            ISBN: 978-1853260285  QTY: 3
The Hobbit, Or, There an/ by J. R. R. Tolkien        ISBN: 978-0547928227  QTY: 8
> sell
ISBN? 978-0547928227
number? 9
You can't sell more than you have.
> sell
ISBN? 978-0547928227
number? 8
OK
> list
Enter search string (empty for complete list):
Harry Potter and the Cha/ by J. K. Rowling           ISBN: 978-0439064866 QTY: 7
Bloodchild and Other Sto/ by Octavia E. Butler      ISBN: 978-1583226988 QTY: 5
Good Omens                    by Terry Pratchett, Ne/ ISBN: 978-0425132159 QTY: 106
Emma                             by Jane Austen            ISBN: 978-1853260285 QTY: 3
The Hobbit, Or, There an/ by J. R. R. Tolkien         ISBN: 978-0547928227 QTY: 0
> q
goodbye!
>>> %Run store_inventory.py
> list
Enter search string (empty for complete list):
Harry Potter and the Cha/ by J. K. Rowling            ISBN: 978-0439064866 QTY: 7
Bloodchild and Other Sto/ by Octavia E. Butler      ISBN: 978-1583226988 QTY: 5
Good Omens                    by Terry Pratchett, Ne/ ISBN: 978-0425132159 QTY: 106
Emma                             by Jane Austen            ISBN: 978-1853260285 QTY: 3
The Hobbit, Or, There an/ by J. R. R. Tolkien         ISBN: 978-0547928227 QTY: 0
> foo
Unrecognized action: foo
> q
goodbye!

Design

Your implementation must match the following UML diagram:

UML

Note that various connectors are used to indicate the relationships between classes in UML diagrams. The diamond-headed connector in the diagram above indicates aggregation. We can infer from this diagram that a single StoreInventory object will contain references to zero or more Book objects.

Book Class (Due Friday 4/15)

  • Constructor: The constructor must simply initialize the instance variables using the provided arguments.
  • __str__: This method must return a single-line string containing appropriately formatted fields for all instance variables. For example:

    >>> book =
    Book("Harry Potter and the Chamber of Secrets", "J. K. Rowling", "978-0439064866", 5)
  •  
  • >>> print(book)
    Harry Potter and the Cha/ by J. K. Rowling ISBN: 978-0439064866 QTY: 5
    • The title field must be exactly 25 characters wide. Titles longer than 25 characters must be truncated to 24 characters, with a ‘/’ symbol appended to make it clear that the title has been cut off.
    • The authors field must be exactly 20 characters wide. Author lists longer than 20 characters must be truncated to 19 characters, with a ‘/’ symbol appended to make it clear that the field has been cut short.
    • The ISBN field must be exactly 15 characters wide. (No truncation is necessary here because ISBNs are guaranteed to be shorter than 15 characters.)
  • __eq__: This method must return true if and only if the other object is an instance of the book class and the ISBN of the books match.

    >>> book = Book("Harry Potter and the Chamber of Secrets", "J. K. Rowling", "978-0439064866", 5)
  • >>> book1 = Book("Harry Potter and the Chamber of Secrets", "J. K. Rowling", "978-0439064866", 5)
  • >>> book2 = Book("Harry", "JK", "978-0439064866", 3)
  • >>> book1 == book2
  • True
  • >>> book1 == "978-0439064866"
  • False
  • >>> book3 = Book("Harry", "JK", "000-0000000000", 3)
  • >>> book1 == book3
  • False

StoreInventory

The StoreInventory class must be defined in a file named store_inventory.py. This class will provide the main logic for the application.

  • Constructor: the constructor must initialize the inventory instance variable to contain a list of Book objects as provided by the load_inventory function defined in the inventory_util.py file.

  • get_book: This method must search the inventory list for a book object with the provided ISBN. If the book is found, this method must return a reference, if the book is not in the inventory, this method must return None.

  • buy: The first argument to this method is an ISBN indicating which book should be purchased and the second is the quantity that should be purchased. There are three possible cases that must be handled by this method:

    1. The quantity provided is negative. In this case the method must return the string 'You can't buy fewer than zero items!' and must not modify the inventory.

    2. The quantity is non-negative and a Book object with the provided ISBN already exists in the inventory. In this case the quantity associated with that object should be increased appropriately. The return value must be 'OK'.

    3. The quantity is non-negative and there is no Book object in the inventory with the provided ISBN. In this case a new Book object must be created and appended to the end of the inventory list. The title and author information must be retrieved using the get_book function described above. The return value must be 'OK'.

  • sell: The first argument to this method is an ISBN indicating which book should be sold and the second is the quantity that should be sold. There are three possible cases that must be handled by this method:

    1. The quantity provided is negative. In this case the method must return the string 'You can't sell fewer than zero items!' and must not modify the inventory.

    2. The quantity provided is greater than the number of books in stock. In this case the method must return the string 'You can't sell more than you have.' and must not modify the inventory.

    3. The quantity is non-negative and a Book object with the provided ISBN exists with a sufficient quantity. In this case the quantity associated with that object must be decreased appropriately. The return value must be 'OK'.

  • search: This method must return a list containing all books in the inventory list that have titles matching the provided search key. The matches should not be case-sensitive, and it should be possible to match at any location in the book title. The books in the returned list must be in the same order as they appear in the inventory list.

  • request_isbn_and_number: This method must prompt the user for the product (“ISBN? ”) and number (“number? ”) and return the two inputs as a tuple. The number input must be returned as an integer.

  • run This method contains the main loop of the program. It must continue prompting for user input until the user enters q. The functionality must match the description in the Program Operationand Sample Output sections above. After the user quits, the saved inventory must be updated using the save_inventory method provided in inventory_util.py. The run method must be called in the if __name == "__main__" block at the bottom of your file:

    if __name__ == "__main__":
        store = StoreInventory()
        store.run()

inventory_util.py

The file inventory_util.py is provided for you. You should not make any changes to this file. It contains three functions:

  • lookup_book(isbn) – This function takes a string representing an ISBN and uses the Google Books API to return the title and authors associated with that book. The return value is a tuple where the first field is the book title and the second is a string containing a comma-separated list of author names.

  • save_inventory(inventory) – Takes a list of Book objects and stores it to a file named inventory.dat. The data is stored in a format that can be read by the load_inventory function.

  • load_inventory() – returns a list of Book objects representing the inventory. If a file has already been created, then this function will load the inventory from that file. If there is no inventory.datfile, then this function will return a small pre-defined list of Book objects for testing purposes. Note that both this function and save_inventory depend on a working implementation of the Bookclass. You won’t be able to use these functions until the Book class is complete.

Grading

  • Gradescope Autograder Score: 80%
  • Instructor Style Points: 20%

    Instructor style points will be based on issues like:
    • Appropriate variable names
    • Meaningful and informative docstrings
    • Clean, readable code that is not overly complex and doesn’t include do-nothing statements

Back to Top