Skip to content

Project 5 for Code Institute Full Stack Developer (Ecommerce) course.

Notifications You must be signed in to change notification settings

davidindub/coffeecrew

Repository files navigation

Coffee Crew

Link to Live Site

Table of Contents

Table of contents generated with markdown-toc

Introduction

The project is an E-commerce site for a shop selling specialty coffee and brewing equipment.

Users including guests can browse products and add products to their cart.

Registered users can place orders, save products to a wishlist, save their details for future and see their past orders.

The project was built keeping the Agile management principles in mind, and I utilised many of GitHub's features such as Issue and Projects to implement scrum methodology despite working alone.

I wanted to build a front end for the business owner to manage the shop without entering the Django Admin panel.

Kanban Board for project

Closed Issues on GitHub for the project

I used GitHub issues for the product backlog containing the user stories. Issues were also used for bug reports so I could keep track of tricky bugs over time.

I used the tags feature in GitHub Issues for assigning story points, prioritising features based on the MoSCoW method, and categorising the user stories.

I used the Milestones feature to plan sprints and set deadlines.

User Stories

User stories were prepared using GitHub Issues and assigned story points based on estimated completion time.

User Stories can been seen below under User Story Testing, and in the GitHub Issues for full details including screenshots, story points and associated sprints.

UX

I used a colour scheme I based on a mockup by Tanim Khan on Dribble that I had previously used and like for a previous project - Plant Cafe.

I used Bootstrap Icons throughout the project for icons such as the cart, edit buttons etc.

I used CSS Variables to use my chosen colour palette and font across the project easily.

:root {
    --main-bg-color: rgb(223, 228, 227);
    --color-primary: rgb(15, 74, 59);
    --color-primary-lighter: rgb(25, 114, 92);
    --color-secondary: rgb(255, 208, 138);
    --color-tertiary: rgb(218, 217, 205);
    --color-white: rgb(255, 255, 255);
    --color-black: rgb(0, 0, 0);
    --color-off-white: rgb(237, 237, 237);
    --font-display-font: 'Rubik', sans-serif;
    --bs-breadcrumb-divider: ">";
}

I used the latest version of Bootstrap (5.3), which includes support for CSS Variables. I used this new recommended approach along with my own variables to customise bootstrap elements.

An example of this can be seen on one of the custom classes for button-like links:

.btn-cc {
    --bs-btn-color: var(--color-off-white);
    --bs-btn-hover-color: var(--color-off-white);
    --bs-btn-bg: var(--color-primary);
    --bs-btn-hover-bg: var(--color-primary-lighter);
    --bs-btn-border-color: var(--color-primary);
    --bs-btn-active-border-color: var(--color-primary);
    --bs-btn-hover-border-color: var(--color-primary);
}

See: Bootstrap Docs - Root Variables

Typography

I used the sans-serif font Rubik from Google Fonts. I like its subtle rounded corners and it makes a nice readable display font for the logo and headings.

For the body text, I let Bootstrap style the font as it used a native font stack for different devices resulting in a nice native looking appearance. See: Bootstrap Docs - Native Font Stack

Wireframes

I drew some wireframes using Balsamiq of the landing page and products page. I knew I had the elements available in Bootstrap to get this layout up and running fast.

Accessibility

I ensured that every element met AAA level in the Web Content Accessibility Guidelines (WCAG).

WebAim contrast check ![](docs/images/webaim-contast-checker.png)

Buttons featuring icons have appropriate aria-labels where necessary, and notification messages have aria-live tags and are read by screen readers.

I tested navigating the project with VoiceOver on macOS.

I used inline SVGs for icons in the project.

I recently watched Seren Davies' talk Death to Icon Fonts where I learned of the issues that icon fonts can cause for accessibility. I researched the best way to use inline SVG icons, including descriptions where appropriate for screen readers. By using SVGs the icons don't break if a user chooses to use a custom font such as Dyslexie.

SVGs that aren't purely decorative always include an aria-label for screenreaders, and I tested them using VoiceOver on macOS.

See also:

Database Design

I used Miro to design the models. I created a Profile model to associate extra information with users not included in the default Django user model.

Database Diagram

Features

Existing Features

Landing Page

The landing page features and eye catching hero image and slogan, with a call to action to lead the user to see products for sale.

Underneath is a quick paragraph introducing the business and quick links to the Coffee and Equipment products.

Below that, the three newest products on the shop are highlighted.

Screenshot of the full landing page on desktop and mobile

Navbar

The Navbar contains dropdown menus to browse Coffee, Equipment, and Products by Brand.

Guests see links to Register or Login.

Logged in Users will see their username as a dropdown containing:

  • My Account
  • My Orders
  • Wishlist, along with a badge containing the number of items in their wishlist.
  • Log Out
Screenshot of dropdown for users

In addition to these, staff members have access to:

  • Manage Shop
  • Manage Products
  • Manage Orders
Screenshot of dropdown for staff members

Shopping Cart

Guests and registered users can add products to their shopping cart, and the total of their cart is displayed clearly in the navbar on medium sized screen sizes and up.

I implemented the cart for guest (non-signed in users) by linking their Session ID to a cart in the database. If they log in, the guest cart is merged into their profile's cart.

See: Django Docs - Sessions

I added a way for staff to purge old (not updated in over two weeks) carts from the Database in the Staff Frontend.

On the cart page, users can select if they would like their coffee beans ground.

Screenshots of Shopping Cart on mobile and desktop

Products List

If you're on the page of a Department, you'll see links to click to get to the subcategories of that department.

A blurb/description accompanies the department or category.

Sorting options are available to sort the list by:

  • Newest First
  • Name (A-Z)
  • Name (Z-A)
  • Price (Low to High)
  • Price (High to Low)

If there are more than 8 products to display, the list is paginated to 8 per page and links to the different pages shown.

Screenshots of Product Detail page

Products List with Sort Options:

List Pagination:

Product Detail Page

Users can click the product's brand name to find more products from the same brand.

If the product is out of stock, the add to cart button is disabled and replaced with a message.

Screenshots of Product Detail page

For Staff Only:

  • Staff have access to the Product SKU and an Edit Product button.

Register / Login

Users can either sign up using their Google or directly on the site.

Users signing up with Google don't need to create a password.

After signing up, users need to verify their account by clicking the link in the welcome email.

Handy links to popular Email services are included for quick access.

Screenshot of Verification Email Sent page

Wishlist

Logged in users can save products to a wishlist for future reference.

Checkout

There are four stages to the checkout process, the customer can easily see what stage of the process they are at with the progress bar at the top. I used combination of bootstrap elements to make this semantic progress bar.

  1. Review Order
  2. Shipping Address
  3. Billing Details
  4. Order Confirmation

If the customer has a saved shipping address, they can populate the form with it by checking the box.

Delivery cost is shown when the user has filled out their address.

The Payment page clearly displays the total to be paid.

All information related to Billing is handled by Stripe. If the user has a default billing address saved in their profile, it will be pre-populated in the Stripe form.

Billing Address or Card details are never saved in the database.

Notification Emails

An email is sent to the customer when they make a new order.

I used Stripe's webhooks to only send the email when the payment is successfully completed.

Screenshot of an Order Confirmation Email

Another email is sent to the customer when their order is dispatched.

Screenshot of Customer Dispatch Email

Footer

The Footer includes:

I rearranged the sections on mobile to get the layout I wanted.

Screenshot of Footer on mobile and desktop

Privacy Policy

As the project can collect data from users, I included a Privacy Policy link in the Footer which explains how data may be used. I used GDPR.eu for help writing the policy.

The Privacy Policy is also clearly displayed to users on their first visit in the Cookie Consent popup.

See: Writing a GDPR-compliant privacy notice (template included)

Screenshot of Privacy Policy ![](docs/images/screenshots/screenshot-privacy-policy.png)

Cookie Consent Banner

I implemented a cookie consent banner using handy code from GDPR Compliant Cookie Consent Banner In JavaScript – GlowCookies.

This code is well set up to later implement analytics such as Google Analytics or Meta Pixel.

Screenshot of Cookie Consent banner ![](docs/images/screenshots/screenshot-mobile-cookie-consent.jpeg)

Notifications

Django Messages and Bootstrap's Alerts elements were combined to make elegant dismissible notification messages when the user performs actions.

Screenshot of Notification alert ![](docs/images/screenshots/screenshot-message-notifcations.png)

Favicon

I included metadata for favicons and web app icons

I themed the browser window to match the site with the theme-color <meta> tag for browsers that support it such as Safari on macOS and Chrome on Android.

Screenshot of Themed Browser Window

Staff Only Features

Shop Management Dashboard

I wanted to create a front-end for a business owner to manage the store themselves without needing to code or enter the django-admin panel. I also protected fields in the django-admin panel that shouldn't be manually edited.

Lists of products in the staff dashboard feature lots of extra sorting options to help with managing the shop:

  • Hidden First
  • On Display First
  • Stock (Low to High)
  • Stock (High to Low)
  • Sales (Low to High)
  • Sales (High to Low)
  • Oldest First
  • Newest First
  • Name (A-Z)
  • Name (Z-A)
  • Price (Low to High)
  • Price (High to Low)

Staff members can also easily see stats about the shop such as number of orders, orders yet to dispatch, number of registered users, and more.

Old unused guest carts can be purged from the database here to save on resources.

Screenshot of Shop Management Dashboard ![](docs/images/screenshots/screenshot-manage-shop.png)

Sort options for product list in staff dashboard:

More Screenshots of Shop Management

Warning before deleting a Department that contains categories and products:

Stats, badge alerting to dispatch new orders:

Products Detail

As a staff member, each product page includes the product's SKU and an edit button. Extra fields are displayed for coffees such as harvest year, weight and processed used.

Screenshot of editing a product as staff member ![](docs/images/screenshots/screenshot-manage-shop-edit-product.png)

Printable Order Sheets

I used media queries to create a print friendly layout for Orders so they can be printed out as packing slips by the business owner.

A Print Order button is included on the page for staff only.

Screenshots of Printable Order Sheet Feature

Dispatch Orders

The Order page also includes a button for staff members to mark an order as dispatched.

Screenshot of Dispatching a Customer Order ![](docs/images/screenshots/screenshot-order-dispatch-button.jpg) ![](docs/images/screenshots/screenshot-order-dispatched.jpg)

This updates the order in the database and sends the customer a dispatch notification email.

Screenshot of Customer Dispatch Email

Custom Error Pages

Custom error pages were added for 403, 404, and 500 errors.

Screenshot of custom 404 page

Features Left to Implement

Features I didn't get to implement in this iteration but plan to add in future include:

  • Guests should be able to place orders without registering for an account
  • A Discount Code system or Option for time-based Sales
  • I would like migrate to using Stripe Checkout as some of these features like discount codes come built-in.
  • Control over Delivery Options and Costs through the staff dashboard. I didn't want these to be hard coded in but cut this feature due to time constraints.
  • Mailchimp could be connected to user profiles to include campaigns such as birthday emails with discounts, or follow up emails on completed orders.
  • A "recently viewed" carousel of products to follow the user around the site.
  • Sign in with Google, I had trouble getting this working error-free despite using it on previous projects. I will reinstate it in future.
  • Add a CAPTCHA or some other form of validation to Contact Us form to prevent abuse.

See also: #wont-fix Issues on GitHub

Technologies Used

External Python Packages Used

Ecommerce Business Model

This site sells goods to individual customers, and therefore follows a Business to Customer model. It is of the simplest B2C forms, as it focuses on individual transactions, and doesn't need anything such as monthly/annual subscriptions.

It is still in its early development stages, although it already has a newsletter, and links for social media marketing.

Social media can potentially build a community of users around the business, and boost site visitor numbers, especially when using larger platforms such a Facebook.

A newsletter list can be used to send regular messages to site users who opt in, such as what items are on special offer, new items in stock. See Newsletter Marketing below.

Search Engine Optimization (SEO) & Social Media Marketing

Keywords

I've identified some appropriate keywords to align with my site, that should help users when searching online to find my page easily from a search engine. I made sure to make use of semantic html so these keywords were picked up by search engines.

<meta name="title" content="Coffee Crew">
<meta name="description" content="Dublin based specialty coffee roasters. Fresh coffee and premium brewing kit, fast shipping anywhere in Europe.">

Metadata

I included Metadata to ensure thumbnails and information is presented correctly when shared on Facebook, Twitter and other Social Media.

Screenshot of social cards preview

Sitemap

I've used XML-Sitemaps to generate a sitemap.xml file. This was generated using my deployed site URL: https://coffee-crew-shop.herokuapp.com

After it finished crawling the entire site, it created a sitemap.xml which I've downloaded and included in the repository.

Robots

I've created the robots.txt file at the root-level. Inside, I've included the settings:

User-agent: *
Disallow: /staff/
Disallow: /checkout/
Sitemap: https://coffee-crew-shop.herokuapp.com/sitemap.xml

Further links for future implementation:

Social Media Marketing

Creating a strong social base (with participation) and linking that to the business site can help drive sales.

I included links in the footer which could be used for potential Facebook, Twitter, Instagram and TikTok presences for the business.

I've created a mockup Facebook business account using the Balsamiq template provided by Code Institute.

Facebook Page Mockup ![](docs/images/facebook-mockup.png)

For this business I envision a lot of the social media marketing being very visual, using the current most popular formats like Instagram Reels and TikTok. As these are primarily video based I did not mock any for the purposes of this coding project. However, I used royalty free photos in the project from Unsplash which I felt fit the vibe I would portray on social media, using soft focused earthy tone photos.

Newsletter Marketing

I used Mailchimp to set up a newsletter sign-up form on my application, to allow users to supply their email address if they are interested in learning more and to drive repeat business. As the small lot coffees regularly change, I felt a newsletter for coffee enthusiasts keeping them up to date would work well.

I created a template of a potential welcome email and mapped out a potential customer journey in Mailchimp. There's a lot of power in Mailchimp, and campaigns could be set up such as a discount code near a customer's birthday, or integration with webhooks.

Screenshots of Mailchimp Campaign

Testing

I performed extensive manual testing continuously as the project was being developed, and filed bug reports on GitHub as issues were discovered to keep track of bugs. I kept track of how to recreate bugs, expected behaviour, screenshots of the issue and how it was resolved to help myself in future.

I also asked friends to test registering accounts / making purchases / editing their profiles and report back to try and catch any potential issues.

Browser Compatibility

I tested the website on four different operating systems on four different types of hardware and didn't find any rendering bugs or unexpected behaviour between the browsers tested.

Operating System Chrome Firefox Edge Safari
macOS 13.2
Windows 11 N/A
Android 10
iOS & iPadOS 16.3 N/A N/A N/A

Responsiveness

I tested for responsiveness on many different sized viewports from 320px wide up to Ultrawide resolutions, and using different hardware (Monitors, Laptops, Phones).

I used Polypane during development to test many different viewport sizes at once.

Performance Testing

Performance testing was done in Google Chrome on macOS.

Page Performance Accessibility Best Practices SEO
Landing Page (Mobile) 96 98 92 100
Landing Page (Desktop) 98 100 92 100
Products List (Mobile) 94 98 92 100
Products List (Desktop) 98 99 92 100
Product Detail (Mobile) 84 100 92 100
Product Detail (Desktop) 97 100 92 100
Privacy Policy (Mobile) 96 98 92 100
Privacy Policy (Desktop) 99 98 92 100
Manage Products (Mobile) 90 100 83 100
Manage Products (Desktop) 98 100 92 100
Manage Shop (Mobile) 99 100 92 95
Manage Shop (Desktop) 94 100 92 100
Contact (Mobile) 96 100 92 100
Contact (Desktop) 98 100 92 100

Accessibility Testing

No errors were detected using the WAVE Web Accessibility Evaluation Tool.

WAVE Web Accessibility Evaluation Tool Results

User Story Testing

Easily login or log out As a **Site user** I should be able to **Easily login or log out** so that I can **Access my personal account information**

Acceptance Criteria

  • I can log into the site when not logged in
  • I can log out of the site from any page

Tested 19/03/2022

Result: ✅ Pass

View a list of products As a **shopper** I should be able to **view a list of products** so that I can **select some to purchase**

Acceptance Criteria

  • I can browse a list of products on the site

Tested 19/03/2022

Result: ✅ Pass

View individual products The user story should have a reason to exist: what do I need as the user described in the summary? This part details any detail that could not be passed by the summary.

As a Shopper I should be able to view individual products so that I can see the price, description, ratings, and images

Acceptance Criteria

  • If I click an individual item I can see the price, description, ratings, and images of the item

Tested 19/03/2022

Result: ✅ Pass

Total of basket The user story should have a reason to exist: what do I need as the user described in the summary? This part details any detail that could not be passed by the summary.

As a Shopper I should be able to Easily view the total of my basket at any time so that I can Keep track of what I spend

Acceptance Criteria

  • I can quickly see the total of the items in my basket

Tested 19/03/2022

Result: ✅ Pass

Easily register for an account As a **Site User** I should be able to **Easily register for an account** so that I can **Have an account with my details saved to save re-entering them**

Acceptance Criteria

  • I can register for an account with the site

Tested 19/03/2022

Result: ✅ Pass

Personal User Profile As a **Registered User** I should be able to **have a personalised user profile page** so that I can **View my personal order history and save my payment information**

Acceptance Criteria

  • I can see my order history
  • I can save my payment information
  • I can update my account information
  • I can update my saved addresses

Payment information was offloaded to Stripe not to store any payment info in the database.

Tested 19/03/2022

Result: ✅ Pass

Sort Product List

As a Site User I should be able to Sort the list of available products so that I can Easily identify the best rated, best price and categorically sorted products

Acceptance Criteria

  • I can sort product list by categories such as price, or name

Tested 19/03/2022

Result: ✅ Pass

View Cart As a **Shopper** I should be able to **view the items in my cart** so that I can **Identify the total cost of my purchase and all the items I will receive**

Acceptance Criteria

  • I can see all the items in my cart and the total cost

Tested 19/03/2022

Result: ✅ Pass

Adjust Quantity of Items in Cart As a **Shopper** I should be able to **Adjust the quantity of individual items in my bag** so that I can **Easily make changes to my purchase before checkout**

Acceptance Criteria

  • I can adjust the quantity of items in my cart
  • The total price updates

Tested 19/03/2022

Result: ✅ Pass

Order Confirmation via Email As a **Shopper** I should be able to **Receive an email confirmation after checking out** so that I can **Keep the confirmation of what I've purchased for my records**

Acceptance Criteria

  • If I place an order successfully, I should receive an email confirmation

Tested 19/03/2022

Result: ✅ Pass

Add a product As a **Store Owner** I should be able to **Add a product** so that I can **sell new items on my store**

Acceptance Criteria

  • I can add new items to the site (without using the Django Admin Panel)

Tested 19/03/2022

Result: ✅ Pass

Add a Product As a **Store Owner** I should be able to **Add a product** so that I can **sell new items on my store**

Acceptance Criteria

  • I can add new items to the site (without using the Django Admin Panel)

Tested 19/03/2022

Result: ✅ Pass

Edit Products As a **Store Owner** I should be able to **Edit/Update a product** so that I can **Change product prices, descriptions, images and other product criteria**

Acceptance Criteria

  • I can edit items on the site (without using the Django Admin Panel)

Tested 19/03/2022

Result: ✅ Pass

Delete Products As a **Store Owner** I should be able to **delete a product** so that I can **remove items no longer on sale**

Acceptance Criteria

  • I can edit items on the site (without using the Django Admin Panel)

Tested 19/03/2022

Result: ✅ Pass

Search Products

As a Shopper I should be able to Search for a product by name or description so that I can Find a specific product I'd like to purchase

Acceptance Criteria

  • I can search for items available for purchase

Tested 19/03/2022

Result: ✅ Pass

Wishlist / Favourite Items As a **Shopper** I should be able to **Save products to a wish list** so that I can **find them in future to purchase**

Acceptance Criteria

  • I can click a save/heart icon on an product page
  • I can see a list of all the products I have saved

Tested 19/03/2022

Result: ✅ Pass

Select Grind for Coffee purchases As a **Customer** I should be able to **choose if or how I want my coffee ground** so that I can **receive the right coffee for brewing at home**

Acceptance Criteria

  • I can select a grind type while purchasing coffee
  • I can update the grind size in the cart

Tested 19/03/2022

Result: ✅ Pass

Add to Cart as a Guest As a **Shopper without a registered account** I should be able to **add items to my cart** so that I can **decide if I want to buy them later**

Acceptance Criteria

  • Without being logged in, I can add items to my cart.
  • I click 'Add to cart' and the item is added to my cart
  • I can see a total of all my items in the nav bar

Tested 19/03/2022

Result: ✅ Pass

Printable Order Docket As **the business owner** I should be able to **print a print-friendly order docket** so that I can **include it when dispatching orders by post**

Acceptance Criteria

  • If print the order page in the browser, I get a print-friendly page suitable to include for customers
  • It should include details about the customer's order and their address

Tested 19/03/2022

Result: ✅ Pass

USTORY

Tested 19/03/2022

Result: ✅ Pass

Complete Order with Payment As a *Customer I should be able to **pay for my order with a card or Apple/Google Pay** so that I can **receive products from the business.**

Acceptance Criteria

  • If I enter my payment details correctly
  • My order is completed

Tested 19/03/2022

Result: ✅ Pass

Email Customer when Order Dispatched As a **Shopper** I should be able to **Receive an email confirmation when my order is dispatched** so that I can **know when to expect my order*

Acceptance Criteria

  • I should receive an email when the shop has dispatched my order

Tested 19/03/2022

Result: ✅ Pass

Password Recovery The user story should have a reason to exist: what do I need as the user described in the summary? This part details any detail that could not be passed by the summary.

As a Registered User I should be able to Easily recover my password in case I forget it so that I can Regain access to my account

Acceptance Criteria

  • I can click 'Forgot Password' on the Login Page
  • I am able to reset my password and regain access to my account

Tested 19/03/2022

Result: ✅ Pass

Guest cart items move to user cart on login As a **new registered used** I should be able to **see my cart items in my new profile** so that I can **continue with placing an order**

Acceptance Criteria

  • I have items in my cart as a guest, and I register or log in
  • The items should still be in my cart (with any previous ones)

Result: ✅ Pass

Challenges Faced

  • I ended up revising the models more times than I expected during development, despite spending time planning them out in advance. As I built more interoperability between the different Django apps I found more properties and methods that I hadn't initially thought of.

Code Validation

HTML Validation

Pages were validating using the W3 HTML Validator, and pages with content that varies based on guest/logged in user/admin status were validated in each state.

W3 HTML Validation

Live links to the validator provided for pages as guests, pages requiring authentication checked by pasting rendered HTML from a logged in user into validator.

Page URL Logged In Status Result
Landing Page / Guest ✅ No errors or warnings
Landing Page / User ✅ No errors or warnings
Shopping Cart /cart Guest ✅ No errors or warnings
Shopping Cart /cart User w/cart items ❗️ 1 warning due to using different colspans for mobile/desktop, rendered page passes
Department Page /shop/d/Equipment/ Guest ✅ No errors or warnings
Products by Department Page /shop/d/Equipment/ User ✅ No errors or warnings
Products by Category Page /shop/c/travel Guest ✅ No errors or warnings
Products by Brand Page /shop/b/kinto Guest ✅ No errors or warnings
Sign Up Page /accounts/signup/ Guest ✅ No errors or warnings
Login Page /accounts/login Guest ✅ No errors or warnings
Log Out Page /accounts/logout User ✅ No errors or warnings
All Products List / Guest ✅ No errors or warnings
Product Page, sorted /shop/?sort=date_added Guest ✅ No errors or warnings
Product Detail Page /item/sunrise Guest ✅ No errors or warnings
My Account Page /account Staff ✅ No errors or warnings
My Orders Page /account/orders/ User ✅ No errors or warnings
My Wishlist Page /wishlist Staff ✅ No errors or warnings
Manage Shop Page /staff Staff ✅ No errors or warnings
Manage Products Page /staff/products Staff ✅ No errors or warnings
Manage Orders Page /staff/orders Staff ✅ No errors or warnings
Privacy Policy Page /privacy Guest ✅ No errors or warnings

CSS Validation

The custom CSS was validated using the W3C CSS Validation Service as CSS level 3 + SVG.

https://jigsaw.w3.org/css-validator/

File Result
base.css ✅ Pass
checkout.css ✅ Pass
glowCookies.css ✅ Pass

Python Validation

All the custom Python files pass PEP8 Validation, which I checked both in the development environment and on CI Python Linter.

# noqa was used in settings.py where line breaks in strings would have broken Django functionality.

App File Result
settings.py ✅ Pass
custom_storages.py ✅ Pass
Cart adapters.py ✅ Pass
Cart context-processor.py ✅ Pass
cart forms.py ✅ Pass
cart models.py ✅ Pass
cart set_cookie.py ✅ Pass
cart urls.py ✅ Pass
cart views.py ✅ Pass
checkout admin.py ✅ Pass
checkout emails.py ✅ Pass
checkout forms.py ✅ Pass
checkout models.py ✅ Pass
checkout orders_urls.py ✅ Pass
checkout urls.py ✅ Pass
checkout views.py ✅ Pass
coffeecrew urls.py ✅ Pass
coffeecrew StaffMemberRequiredMixin.py ✅ Pass
home forms.py ✅ Pass
home views.py ✅ Pass
products admin.py ✅ Pass
products context_processors.py ✅ Pass
products admin.py ✅ Pass
products views.py ✅ Pass
products models.py ✅ Pass
products signals.py ✅ Pass
products urls.py ✅ Pass
profiles admin.py ✅ Pass
profiles context_processors.py ✅ Pass
profiles forms.py ✅ Pass
profiles models.py ✅ Pass
profiles urls.py ✅ Pass
profiles urls_wish_list.py ✅ Pass
profiles views.py ✅ Pass
staff forms.py ✅ Pass
staff urls.py ✅ Pass
staff views.py ✅ Pass

JavaScript

File Result
checkout_delivery.js ✅ Pass
confirm_delete.js ✅ Pass
glowCookies.js ⚠️ Warnings (library)
print_btn.js ✅ Pass
stripe_elements.js ✅ Pass

Deployment

The live deployed application can be found deployed on Heroku.

ElephantSQL Database

This project uses ElephantSQL for the PostgreSQL Database.

To obtain your own Postgres Database, sign-up with your GitHub account, then follow these steps:

  • Click Create New Instance to start a new database.
  • Provide a name (this is commonly the name of the project: coffeecrew).
  • Select the Tiny Turtle (Free) plan.
  • You can leave the Tags blank.
  • Select the Region and Data Center closest to you.
  • Once created, click on the new database name, where you can view the database URL and Password.

Amazon AWS

This project uses AWS to store media and static files online, due to the fact that Heroku doesn't persist this type of data.

Once you've created an AWS account and logged-in, follow these series of steps to get your project connected. Make sure you're on the AWS Management Console page.

Full details of setting up AWS for deployment

S3 Bucket

  • Search for S3.

  • Create a new bucket, give it a name (matching your Heroku app name), and choose the region closest to you.

  • Uncheck Block all public access, and acknowledge that the bucket will be public (required for it to work on Heroku).

  • From Object Ownership, make sure to have ACLs enabled, and Bucket owner preferred selected.

  • From the Properties tab, turn on static website hosting, and type index.html and error.html in their respective fields, then click Save.

  • From the Permissions tab, paste in the following CORS configuration:

     [
     	{
     		"AllowedHeaders": [
     			"Authorization"
     		],
     		"AllowedMethods": [
     			"GET"
     		],
     		"AllowedOrigins": [
     			"*"
     		],
     		"ExposeHeaders": []
     	}
     ]
  • Copy your ARN string.

  • From the Bucket Policy tab, select the Policy Generator link, and use the following steps:

    • Policy Type: S3 Bucket Policy

    • Effect: Allow

    • Principal: *

    • Actions: GetObject

    • Amazon Resource Name (ARN): paste-your-ARN-here

    • Click Add Statement

    • Click Generate Policy

    • Copy the entire Policy, and paste it into the Bucket Policy Editor

       {
       	"Id": "Policy1234567890",
       	"Version": "2012-10-17",
       	"Statement": [
       		{
       			"Sid": "Stmt1234567890",
       			"Action": [
       				"s3:GetObject"
       			],
       			"Effect": "Allow",
       			"Resource": "arn:aws:s3:::your-bucket-name/*"
       			"Principal": "*",
       		}
       	]
       }
    • Before you click "Save", add /* to the end of the Resource key in the Bucket Policy Editor (like above).

    • Click Save.

  • From the Access Control List (ACL) section, click "Edit" and enable List for Everyone (public access), and accept the warning box.

    • If the edit button is disabled, you need to change the Object Ownership section above to ACLs enabled (mentioned above).

IAM

Back on the AWS Services Menu, search for and open IAM (Identity and Access Management). Once on the IAM page, follow these steps:

  • From User Groups, click Create New Group.
    • Suggested Name: group-coffeecrew (group + the project name)
  • Tags are optional, but you must click it to get to the review policy page.
  • From User Groups, select your newly created group, and go to the Permissions tab.
  • Open the Add Permissions dropdown, and click Attach Policies.
  • Select the policy, then click Add Permissions at the bottom when finished.
  • From the JSON tab, select the Import Managed Policy link.
    • Search for S3, select the AmazonS3FullAccess policy, and then Import.

    • You'll need your ARN from the S3 Bucket copied again, which is pasted into "Resources" key on the Policy.

       {
       	"Version": "2012-10-17",
       	"Statement": [
       		{
       			"Effect": "Allow",
       			"Action": "s3:*",
       			"Resource": [
       				"arn:aws:s3:::your-bucket-name",
       				"arn:aws:s3:::your-bucket-name/*"
       			]
       		}
       	]
       }
    • Click Review Policy.

    • Suggested Name: policy-coffeecrew (policy + the project name)

    • Provide a description:

      • "Access to S3 Bucket for coffeecrew static files."
    • Click Create Policy.

  • From User Groups, click your "group-coffeecrew".
  • Click Attach Policy.
  • Search for the policy you've just created ("policy-coffeecrew") and select it, then Attach Policy.
  • From User Groups, click Add User.
    • Suggested Name: user-coffeecrew (user + the project name)
  • For "Select AWS Access Type", select Programmatic Access.
  • Select the group to add your new user to: group-coffeecrew
  • Tags are optional, but you must click it to get to the review user page.
  • Click Create User once done.
  • You should see a button to Download .csv, so click it to save a copy on your system.
    • IMPORTANT: once you pass this page, you cannot come back to download it again, so do it immediately!
    • This contains the user's Access key ID and Secret access key.
    • AWS_ACCESS_KEY_ID = Access key ID
    • AWS_SECRET_ACCESS_KEY = Secret access key

Final AWS Setup

  • If Heroku Config Vars has DISABLE_COLLECTSTATIC still, this can be removed now, so that AWS will handle the static files.
  • Back within S3, create a new folder called: media.
  • Select any existing media images for your project to prepare them for being uploaded into the new folder.
  • UnderManage Public Permissions, selectGrant public read access to this object(s).
  • No further settings are required, so clickUpload.

Heroku Deployment

This project uses Heroku, a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud.

Deployment steps are as follows, after account setup:

  • SelectNew in the top-right corner of your Heroku Dashboard, and selectCreate new app from the dropdown menu.
  • Your app name must be unique, and then choose a region closest to you (EU or USA), and finally, selectCreate App.
  • From the new appSettings, clickReveal Config Vars, and set your environment variables.
Key Value
AWS_ACCESS_KEY_ID insert your own AWS Access Key ID key here
AWS_SECRET_ACCESS_KEY insert your own AWS Secret Access key here
AWS_S3_REGION_NAME region name of the AWS region used (e.g 'eu-central-2')
AWS_STORAGE_BUCKET_NAME name of the bucket in AWS
DATABASE_URL insert your own ElephantSQL database URL here
DISABLE_COLLECTSTATIC 1 (this is temporary, and can be removed for the final deployment)
SECRET_KEY insert your Django secret key
EMAIL_HOST_PASS insert your own Gmail API key here
EMAIL_HOST_USER insert your own Gmail email address here
SECRET_KEY this can be any random secret key
STRIPE_PUBLIC_KEY insert your own Stripe Public API key here
STRIPE_SECRET_KEY insert your own Stripe Secret API key here
STRIPE_WH_SECRET insert your own Stripe Webhook API key here
EMAIL_HOST_USER insert your email address for sending emails (I used a Gmail account)
EMAIL_HOST_PASS insert your app password for the email address
USE_AWS True
HEROKU_HOSTNAME insert url of deployed project on Heroku

Heroku needs two additional files in order to deploy properly.

  • requirements.txt
  • Procfile

You can install this project's requirements (where applicable) using:

  • pip3 install -r requirements.txt

If you have your own packages that have been installed, then the requirements file needs updated using:

  • pip3 freeze --local > requirements.txt

The Procfile can be created with the following command:

  • echo web: gunicorn app_name.wsgi > Procfile
  • replace app_name with the name of your primary Django app name; the folder where settings.py is located

For Heroku deployment, follow these steps to connect your own GitHub repository to the newly created app:

Either:

  • Select Automatic Deployment from the Heroku app.

Or:

  • In the Terminal/CLI, connect to Heroku using this command: heroku login -i
  • Set the remote for Heroku: heroku git:remote -a app_name (replace app_name with your app name)
  • After performing the standard Git add, commit, and push to GitHub, you can now type:
    • git push heroku main

The project should now be connected and deployed to Heroku!

Local Deployment

This project can be cloned or forked in order to make a local copy on your own system.

For either method, you will need to install any applicable packages found within the requirements.txt file.

  • pip3 install -r requirements.txt.

You will need to create a new file called env.py at the root-level, and include the same environment variables listed above from the Heroku deployment steps.

Sample env.py file:

import os

os.environ.setdefault["AWS_ACCESS_KEY_ID"] = insert your own AWS Access Key ID key here
os.environ.setdefault["AWS_SECRET_ACCESS_KEY"] = insert your own AWS Secret Access key here
os.environ.setdefault["AWS_S3_REGION_NAME"] = insert your AWS bucket region here e.g. 'eu-central-2'
os.environ.setdefault["AWS_STORAGE_BUCKET_NAME"] = insert your own AWS Secret Access key here
os.environ.setdefault["DATABASE_URL"] = insert your own ElephantSQL database URL here
os.environ.setdefault["EMAIL_HOST_PASS"] = insert your own Gmail API key here
os.environ.setdefault["EMAIL_HOST_USER"] = insert your own Gmail email address here
os.environ.setdefault["SECRET_KEY"] = this can be any random secret key
os.environ.setdefault["STRIPE_PUBLIC_KEY"] = insert your own Stripe Public API key here
os.environ.setdefault["STRIPE_SECRET_KEY"] = insert your own Stripe Secret API key here
os.environ.setdefault["STRIPE_WH_SECRET"] = insert your own Stripe Webhook API key here
os.environ.setdefault["STRIPE_RETURN_URL"] = URL for the return address in the Stripe JS
os.environ.setdefault["EMAIL_HOST_USER"] = Email address for email account used to sent emails (I used Gmail)
os.environ.setdefault["EMAIL_HOST_PASS"] = App Password for the email account used
os.environ.setdefault["HEROKU_HOSTNAME"] = insert url of deployed project on Heroku

# local environment only (do not include these in production/deployment!)
os.environ.setdefault("DEBUG", "True")

Once the project is cloned or forked, in order to run it locally, you'll need to follow these steps:

  • Start the Django app: python3 manage.py runserver
  • Stop the app once it's loaded: CTRL+C or ⌘+C (Mac)
  • Make any necessary migrations: python3 manage.py makemigrations
  • Migrate the data to the database: python3 manage.py migrate
  • Create a superuser: python3 manage.py createsuperuser
  • Load fixtures (if applicable): python3 manage.py loaddata file-name.json (repeat for each file)
  • Everything should be ready now, so run the Django app again: python3 manage.py runserver

If you'd like to backup your database models, use the following command for each model you'd like to create a fixture for:

  • python3 manage.py dumpdata your-model > your-model.json
  • repeat this action for each model you wish to backup

Cloning

You can clone the repository by following these steps:

  1. Go to the GitHub repository
  2. Locate the Code button above the list of files and click it
  3. Select if you prefer to clone using HTTPS, SSH, or GitHub CLI and click the copy button to copy the URL to your clipboard
  4. Open Git Bash or Terminal
  5. Change the current working directory to the one where you want the cloned directory
  6. In your IDE Terminal, type the following command to clone my repository:
    • git clone https://github.com/davidindub/coffeecrew.git
  7. Press Enter to create your local clone.

Alternatively, if using Gitpod, you can click below to create your own workspace using this repository.

Open in Gitpod

Please note that in order to directly open the project in Gitpod, you need to have the browser extension installed. A tutorial on how to do that can be found here.

Forking

By forking the GitHub Repository, we make a copy of the original repository on our GitHub account to view and/or make changes without affecting the original owner's repository. You can fork this repository by using the following steps:

  1. Log in to GitHub and locate the GitHub Repository
  2. At the top of the Repository (not top of page) just above the "Settings" Button on the menu, locate the "Fork" Button.
  3. Once clicked, you should now have a copy of the original repository in your own GitHub account!

Credits

Content

Code

Media

Acknowledgements

  • Thank you to my CI Mentor Tim Nelson for his help and suggestions.
  • Thanks to my partner David for his constant support on my journey to a new career.