Skip to content

0davidog/CI_PP3_PazuzuPizza

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pazuzu Pizza

cover-image

Author: David C. O'Gara

Pazuzu Pizza is a command line application. Built in python, that enables users an easy way to keep up to date with sales and stock of their business. The app is created specifically for Pazuzu Pizza, a small pizza counter within a supermarket, and offers its users the ability to input sales data and wastage while automating their production plan and offering access to other useful information such as pizza recipes and menu lists.

Live Site

Pazuzu Pizza via Heroku

Repository

Pazuzu Pizza Repository on Github

Google Sheet

Pazuzu Pizza Google Sheet

User

Pazuzu Pizza, is a small company that rents a counter in the corner of a larger supermarket. They pre-make and wrap a selection of pizzas in various styles and in one of two sizes (small or large). Customers can then purchase these pizzas cold to cook at home, or have them cooked in-store to take-away hot. The owner wants an application to simplify and in some ways automate some of the process of keeping track of sales and stock. The users of this app will be the staff members working on the counter on a given day.

How to Use

deployed-screen-01

  • The user is first asked to log in more detail. This is done by choosing one of these pre-made user accounts: employee-screen
  • The user is then asked to select an option. This is done by inputting the option number. more detail
  • Selecting 1. 'Display Menu' brings up a list of pizza styles the company makes. more detail
  • Selecting 2. 'Input Sales' asks the user to input a number for each pizza. more detail
  • Selecting 3. 'Input Disosals' asks user to input disposal number for each pizza ingredient. more detail
  • Selecting 4. 'View Production Plan' shows the user to amount of pizzas to be made for today's date. more detail
  • Selecting 5. 'View Pizza Recipe' asks the user to choose a pizza by number and then displays the recipe for the chosen pizza. more detail

Features

Login

After the introduction the user is asked to Log in to the app. Employees of Pazuzu Pizza are given log-in information by their management to prevent non-employees accessing and altering the information. This is stored in the employee database which is a worksheet named 'employees' in the Pazuzu_Pizza Google spreadsheet.

worksheet-screen-08

First the user enters a username.

deployed-screen-02

Followed by the password. The characters on the password input are hidden via the python module 'maskpass'.

deployed-screen-03

The app then retrieves the username and password and checks them against the 'employees' worksheet. The username is checked first. If this doesn't exist on the worksheet a warning is given and the user is asked to enter the information again.

deployed-screen-05

Then, if the username is recognised but the password is not a different warning is issued and the user is asked to enter the information again.

deployed-screen-06

This applies too if the inputs are left blank.

deployed-screen-07

Once the username and password are entered correctly the user is taken to the main menu part of the app.

deployed-screen-04

Option Selection

In the main menu the user is asked to select from a list of numbered options. Only the option number is required.

deployed-screen-14

If anything other than a whole number is entered a warning is given and the options are displayed again.

deployed-screen-08

This includes a blank input.

deployed-screen-09

Display Menu

Selecting option 1 displays a list of the pizza styles currently made by Pazuzu Pizza. This is drawn from the Pazuzu Pizza spreadsheet and the pizza_menu worksheet. This is included as reminder should any staff members need to check on the current list of pizza styles as changes may occur on a seasonal basis.

worksheet-screen-07

The pizzas are then displayed in a numbered list.

deployed-screen-10

Input Sales

Selecting option 2 will ask the user to input the days pizza sales one by one. This is to be done at the end of the shift when the business is closed for the day although they can be entered as many times as the user wishes should a mistake be made.

deployed-screen-11

If something other than a whole number is entered a warning is given and the user is asked to enter the number again.

deployed-screen-13

Once succesful the worksheet 'pizza_sales' will be updated in the column coresponding to the day of the week.

worksheet-screen-01

Side by side video demonstration here.

The 'pizza_production' worksheet will also be updated at the end of this function by calling the calculated_production_plan function. This takes today's sales, entered by the user and adds 10% to the number then rounded to an integer.

worksheet-screen-02

Side by side video demonstration here.

Today's Date

from datetime import datetime

The date used in these functions is determined by the datetime python module. The module is imported and then used to display the date at the start of some functions and also used to take today's day and translate it to an uppercase letter for use in determining the cell to update.

def convert_day():
    """
    Function imports todays day from python's datetime module.
    Then converts it into a letter for use as column reference.
    This function will be called within other functions.
    """
    day = datetime.now().strftime("%a")
    if day == "Mon":
        return "B"
    elif day == "Tue":
        return "C"
    elif day == "Wed":
        return "D"
    elif day == "Thu":
        return "E"
    elif day == "Fri":
        return "F"
    elif day == "Sat":
        return "G"
    elif day == "Sun":
        return "H"

The formatted string literal bellow then used the letter returned from the convert_day function with an index determined in a for loop to create an A1 notation cell reference. In this instance the {sold} reference is the value input from the user entered in the input_sales function.

                pizza_sales.update(
                    f"{convert_day()}{i + 2}",
                    f"{sold}",
                    value_input_option='USER_ENTERED'
                    )

Input Disposals

Selecting option 3 will ask the user to input the disposal numbers for each pizza ingredient. This is done at the end of the shift also, as there are often ingredients/toppings that reach the end of their allotted life or use by date and must be disposed of. The user is asked to input an integer of the amount of units of each ingredient. To the staff member of Pazuzu Pizza, this unit will relate to different quantities depending on the item. For example, 2 units may mean 2 4oz spoons of grated mozzarella, 2 2oz spoons of passata sauce or just 2 slices of pepperoni. The amount entered will be added to the 'pizza_disposal' worksheet.

worksheet-screen-03

Side by side video demonstration here. The number of disposals entered will also be subtracted from the values in the 'pizza_stock' worksheet.

worksheet-screen-04

Side by side video demonstration here.

Delivery

The 'pizza_stock' worksheet is also updated via a function called 'delivery'. First, the function 'weekly_delivery', checks to see if today is Monday and proceeds to call the delivery function if this is true.

def weekly_delivery():
    """
    Get day today from datetime
    Check if day is Mon
    Call delivery function if true
    """
    day = datetime.now().strftime("%a")
    if day == "Mon":
        delivery()

The delivery function then adds a set amount of units to the 'pizza_stock' worksheet. These pre-set delivery units are accessed from the 'pizza_delivery' worksheet.

def delivery():
    """
    Fetch pizza_stock worksheet
    Fetch pizza_delivery worksheet
    Create list of values from col 1 of pizza_delivery
    for every item in stocklist
        fetch each delivery value
        fetch each stock value
        check if current stock value is greater than delivery value
            break if true
            add delivery value to stock value if false
    """
    pizza_stock = SHEET.worksheet('pizza_stock')
    pizza_delivery = SHEET.worksheet('pizza_delivery')
    stock_list = pizza_delivery.col_values(1)
    for i, stock in enumerate(stock_list[1:]):
        delivery_value = int(pizza_delivery.acell(f'B{i + 2}').value)
        current_stock = int(pizza_stock.acell(f'B{i + 2}').value)
        if current_stock >= delivery_value:
            red_text()
            print('\nNOTICE: No weekly delivery received.')
            reset_color()
            time.sleep(0.5)
            break
        else:
            pizza_stock.update(
                f'B{i + 2}', f'{current_stock + delivery_value}',
                value_input_option='USER_ENTERED'
                )
            red_text()
            print('\nNOTICE: Weekly delivery has been received.')
            time.sleep(0.5)
            print('Stock list updated.')
            reset_color()

worksheet-screen-05

View Production Plan

Selecting option 4 displays for the user today's production plan. This tells the staff member how many pizzas to make for today based on last weeks sales with an aim to make and sell 10% more than last week. This data is retrieved from the pizza_production worksheet with the column reference chosen through the convert_day function.

Screenshot 2023-10-18 at 22-06-26 Python Terminal by Code Institute

View Pizza Recipe

Selecting option 5 displays a chosen pizza recipe for the user. Staff members can use this function to remind themselves what the standard is when creating pizzas, thus helping to create consistency in the pizzas produced by different colleagues. Users are asked first to select the size of pizza they wish to view the recipe for. This is simply to reduce the size of the list and make it easy for the user to see the options within the limited view space. To choose, the user must input either 's' or 'l' in lower case letters.

deployed-screen-15

Choosing the size will then display a numbered list of pizzas.

Small:

deployed-screen-16

Large:

deployed-screen-18

Users are asked to input the number of the pizza they wish to view. The numbers are between 0 and 13. Doing so displays the pizza information.

Number 5 - Small Hot & Spicy:

deployed-screen-17

Number 11 - Large Veggi Feast:

deployed-screen-19

Entering anything other than a whole number will result in a warning and the user will be asked to enter their choice again.

deployed-screen-20

deployed-screen-21

Future Features

Given production time and knowledge this app could provide a number of extra and more advanced features. Here is just a few:

  • Pizza Stock

    The pizza stock list that keeps track of ingredients could be updated according the amound of pizzas made. This could be achieved by multiplying the amount of a particular topping needed for a pizza by the amount of that pizza produced. For example the amount of pepperoni used on a small pepperoni pizza is 8. If 15 small pepperoni pizzas are made that day than 120 slices of pepperoni will need to be subtracted from the stock of pepperoni. This will further simplify the stock ordering process for the company.

Planning Documentation

Flow chart for 'input sales' function: input_sales drawio(1)

Data Model

class-table

Libraries Used

  • gspread
    • gspread was used to access and update google sheets.
  • datetime more detail
  • Google Drive
    • google drive credentials were needed to access google sheets.
  • colorama
    • colorama Fore was used to change the text colour in various placed to add emphasis to inputs and warnings making the experience better for the customer.
    • colorama Style was used to reset any colour effects when needed.
  • pyfiglet
    • pyfiglet provided the title font used to make the app introduction more eye catching.
  • sys
    • sys was imported to set up the sys.exit function for the the user wishes to quit.
  • maskpass
    • maskpass was installed to hide the user's password input.
  • warnings more detail

Testing

Various manual test were done to check that the app works as expected. This includes deliberately entering the wrong inputs and checking the data given against the google sheets.

Function Intention Action No Terminal Error Works as Expected
Login Request and validate username and password. Blank username input gives warning.
Wrong user name gives warning.
Blank password gives warning.
Wrong password gives warning.
[x] [x]
Options Request input of option number. Blank entry gives warning.
String entered gives warning.
Float entered gives warning.
[x] [x]
Display Menu Display list of pizzas Pizza list checked against worksheet. [x] [x]
Input Sales Request input of whole number for each item. String input gives warning.
Blank input gives warning.
[x] [x]
Input Disposals Request input of whole number for each item. String input gives warning.
Blank input gives warning.
[x] [x]
View Production Plan Display list of pizzas for today's date. List matches today. [x] [x]
View Pizza Recipe 1.Request input of s or l.
2.Request input of number between 1 and 13.
1.Blank input gives warning.
1.Wrong letter gives warning.
1.Number entered gives warning.
2.Number above 13 gives warning.
2.Blank input gives warning.
[x] [x]

Bugs

Bug: A warning kept being printed the first time a google sheet was updated in a session. From some investigation it appeared the warning was for some changes being implimented in a future version of gspread.

UserWarning: [Deprecated][in version 6.0.0]: method signature will change to: 'Worksheet.update(value = [[]], range_name=)' arguments 'range_name' and 'values' will swap, values will be mandatory of type: 'list(list(...))'
  warnings.warn(

Fix: The problem was solved by importing the warnings module and using it to ignore UserWarnings.

warnings.filterwarnings("ignore", category=UserWarning)
- (error occured because I had Sun in lowercase)

Bug: This error kept occuring when trying to update any of the day-based google sheets:

Error: An unexpected error occurred - {'code': 400, 'message': "Unable to parse range: 'pizza_production'!NONE2", 'status': 'INVALID_ARGUMENT'}

Fix: It happened to be a Sunday when this error appeared and I found "Sun" in the convert_day function had been mistakenly written in lower case.

Remaining Bugs

No known bugs remaining.

Validator Testing

PEP8 validator passed with no issues.

Screenshot 2023-10-18 at 16-38-28 CI Python Linter

PEP8 Validator/ CI Python Linter

Deployment

Google Sheets API

As mentioned throughout Pazuzu Pizza is connected to Google Sheets through an Application Programming Interface.

The Spreadsheet name is Pazuzu_Pizza. link

Sheet names:

  • pizza_sales
  • pizza_production
  • pizza_disposals
  • pizza_stock
  • pizza_delivery
  • pizza_recipe
  • pizza_menu
  • employees

Instructions for setting this up:

(create google account use personal account as more secure file - make a copy)

Method of setting up API
Step Screen
Head over to Google Cloud platform and log-in. api-screen-01
Click 'Select a project'. Then 'New Project'. api-screen-02
Give your new project a name. api-screen-03
Click 'create'. api-screen-04
Click 'Select Project' api-screen-05
You'll be taken to the dashboard. api-screen-06
Using the side menu select 'APIs & Sservices' and then 'Library' api-screen-07
You'll be taken to the API library. api-screen-08
Search for 'Google Drive' and select 'Google Drive API' api-screen-09
Select 'Enable' api-screen-10
In the next screen select 'Create Credentials' api-screen-11
In 'which API are you using?', Select an API should be 'Google Drive API' and the data you'll be accessing is 'application data'. Click 'next'. api-screen-12
Choose a service account name and click 'create' api-screen-13
In 'select a role' chose 'Basic' - 'Editor'. api-screen-14
Select 'continue' api-screen-15
You can leave this blank and click 'done' api-screen-16
Select your service account on the next page. api-screen-18
Then select the keys tab api-screen-19
Select 'add key' api-screen-20
Select 'create new key' api-screen-21
Select 'JSON' and click 'create'. api-screen-22
The json file will be saved to your computer api-screen-23
Back at the API library search for 'Google Sheets' api-screen-24
Simply select 'enable' api-screen-25
And the API will be enabled api-screen-26
Drag and drop the downloaded json file into your project folder. Rename it if you like (e.g. creds.json). Then access the file and copy the client email. api-screen-27
Then you can share you google sheet with your client email to allow access. api-screen-29
Add the json file to the gitignore list to prevent sensitive information being displayed on github. api-screen-28

Gitpod

  • In order for the app to work correctly with all the installed modules the mock terminal needs to know which modules to install ahead of time.
  • To do this we need the file 'requirements.txt'.
  • This file will contain a list of modules and their version.
  • In my case this is the full list:
cachetools==5.3.1
certifi==2023.7.22
charset-normalizer==3.3.0
colorama==0.4.6
google-auth==2.23.2
google-auth-oauthlib==1.1.0
gspread==5.11.3
idna==3.4
maskpass==0.3.7
oauthlib==3.2.2
pyasn1==0.5.0
pyasn1-modules==0.3.0
pyfiglet==1.0.2
requests==2.31.0
requests-oauthlib==1.3.1
rsa==4.9
urllib3==2.0.6

Python can populate this list for you automatically with this command:

pip3 freeze > requirements.txt

Heroku

The project was deployed on Heroku using Code Institute's mock terminal.

Details for deployment:
Step Screen
Head over to heroku and log in. Choose 'create new app'. heroku-screen-01
Choose a name for your app and your location. Hit 'create app'. heroku-screen-02
Select the 'Settings' tab. heroku-screen-04
In Config Vars, reveal config vars. heroku-screen-06
Paste your json file. Make sure the name is the same. heroku-screen-07
Down to the Buildpacks section. heroku-screen-08
Select 'Add Buildpacks' heroku-screen-09
Add Python buildpack. heroku-screen-10
Repeat and add nodejs. heroku-screen-11
Make sure the order is the same. heroku-screen-12
Head over to the Deploy tab. heroku-screen-13
Select Github heroku-screen-14
You will need to authorize this. heroku-screen-15
Choose your repository. heroku-screen-16
Choose your branch in automatic deploys. heroku-screen-17
Confirmation heroku-screen-18
You can now view your app. heroku-screen-19

Credits

Content

For the code used to authorize and access Google Drive and Google sheets I followed the Code Institute Love-Sandwiches walkthrough project. This was due to the code dealing with complicated concepts that needed to be written accurately for the whole project to work.

Here's the code used:

SCOPE = [
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/drive"
    ]

CREDS = Credentials.from_service_account_file('creds.json')
SCOPED_CREDS = CREDS.with_scopes(SCOPE)
GSPREAD_CLIENT = gspread.authorize(SCOPED_CREDS)
SHEET = GSPREAD_CLIENT.open('pazuzu_pizza')

Table of Contents

Table of contents generated with markdown-toc

Mentor

Malia Havlicek

Author

David C. O'Gara 2023

About

Stock and sales managment app built in python.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published