(CTRL + CLICK to open Links in new window)
Deployed site can be found here
Github repository can be found here
This is the fifth project I have completed as part of the Code Institute Full Stack Diploma Course.
This project sets out to create an ecommerce site for a fictitious car-sales business based in Dublin, Ireland.
The site will display all available stock and allow a search of same. Each item of stock should have a specific page giving more information on that vehicle.
The site will have a shopping bag function where users can store items before purchasing them in the stripe enabled checkout.
Users should be able to value a vehicle for possible trade-in, accept this value if desired and apply it as a credit to their shopping bag total.
Staff members will need to be able to add, delete and edit stock items and also to change the trade-in base price for each manufacturer from the front-end.
User Experience/User Interface (UX/UI)
The AGILE methodology for project development will be used to produce this project, this method involves continual collaboration between all parties and improvements at every stage. It helps to ensure good quality products are produced within time and financial constraints.
As a Casual Visitor I want:
- #1 to be easily able to ascertain information on the business and it's locality, to aid my purchasing decision.
- #2 to be able to easily browse and search stock and access data on each item of stock, to aid my purchasing decision.
- #3 to navigate easily around the site, to avoid frustration whilst using the site and to engender positive emotions towards the business.
- #4 to have any incorrect input rejected and the error explained clearly and quickly, so I do not have any frustrating emotions using the site.
- #5 site to be responsive, to provide a positive user experience.
- #6 to be able to value any vehicle as a trade-in, to aid my purchasing decision.
As a Customer I want:
- #7 to easily add a vehicle to my order to make the purchasing process efficient.
- #8 to easily trade-in a vehicle, to make the purchasing process efficient.
- #9 to easily pay for my order, to make the purchasing process efficient.
- #10 to securely pay for my order, to engender trust in the site.
- #11 to be able to create a user account, to track my interaction with the site.
- #12 to be able to manage my user profile, to make site use easy.
- #13 to review my profile details and order details, to engender trust and provide as transparent process as possible.
- #14 to have all orders confirmed by email, to engender trust and provide as transparent a process as possible.
As a Site Owner I want:
- #15 to provide an easy to use website in order to drive sales and increase profits.
- #16 to engage potential customers and ensure they return to the site in the future, to drive sales and increase profits.
- #17 to use the site as a marketing tool, to drive sales and increase profits.
- #18 to enable staff members to perform certain admin tasks from the frontend, to efficiently run the site.
Using the user stories as a frame of reference the following Epics were formulated;
- Epic 01 implement basic html and django structure.
- Epic 02 implement user registration and login.
- Epic 03 implement stock display and search system.
- Epic 04 implement order system.
- Epic 05 implement purchase system using Stripe.
- Epic 06 implement User profile system.
- Epic 07 implement Seo and web-marketing.
- Epic 08 implement staff admin functions.
- Epic 09 implement trade-in function.
The user stories were prioritised using the MoSCoW technique and the Kanban Board feature built-in to Github will be used as an information radiator.
The user stories were broken down into tasks and these were listed under their respective user story in the initial Kanban Board.
The acceptance criteria for each user story are listed in each story in the github project board.
Care was taken to ensure should-have prioritised user stories are not greater than 60% of the total.
An image of the first user story is shown below for illustrative purposes.
User story | Epic |
---|---|
to be easily able to ascertain information on the business | 01 |
to be able to easily browse and search stock | 03 |
to navigate easily around the site | 01 |
to have any incorrect input rejected and the error explained clearly | 01 |
site to be responsive | 01 |
to be able to value any vehicle as a trade-in | 09 |
to easily add a vehicle to my order | 04 |
to easily trade-in a vehicle | 09 |
to easily pay for my order | 05 |
to securely pay for my order | 05 |
to be able to create a user account | 02 |
to be able to manage my user profile | 06 |
to review my profile details and order details | 06 |
to have all orders confirmed by email | 05 |
to provide an easy to use website | 01 |
to engage potential customers | 07 |
to use the site as a marketing tool | 07 |
to enable staff members to perform certain admin tasks from the frontend | 08 |
(CTRL + Click to open in new window) link to wireframes pdf
A full set of wire frames for this Project was produced and can be viewed at the above link, A sample of them are shown below.
Please note some the images have been changed over the development process, the layout reamins as shown below.
Images used in this project were obtained from a number of sources but principaly the Pexels Website.
All images are free to use.
Features
There are contact/location links at the top of each page. The telephone link initiates a voice call on suitable devices, the location opens a google map showing the business location.
The business name is displayed top center on all pages, this title acts as a link to the home page to aid site navigation.
There is a search facility which allows users to search the current stock. The postgress text search is used to implement this search function.
Login/Register links and links to stock page and trade in page are contained in the nav-bar. This nav-bar is responsive and collaspes on smaller screen sizes, it is a standard bootstrap element.
When a user logs in, a user icon is displayed, which is a drop-down menu with links relevant to the authorisation level of the user.
There is a link to the user's shopping cart and the value of goods in it.
If there is a un-used trade-in credit amount, this is also displayed in the nav-bar.
The Django all-auth package is used to handle user registration, login and access levels.
All all-auth templates are customised to match the appearance of the site.
The footer is displayed on all pages.
There is a links section which links to the business's social media pages, to trade representative bodies and to the businesses's privacy policy.
The hours of business are shown on larger screens.
There is a sign-up form for the business newsletter.
In the bottom right corner there is a button which automatically scrolls the user to the top of the page.
The Home page of the site features an image of a car-dealship with a prominent button linking to the stock page.
There is also a carousel of featured vehicles.
The stock page displays all available vehicles in a layout suitable for the viewing device, one per row on smaller screens, two on larger.
Each vehicle image when clicked, links to a page giving more details on that particular vehicle.
The item can be added to the cart from this page.
If the user is staff the item can be edited or deleted from this page.
The checkout is stripe enabled with redundancies built in to accomodate unexpected user action and/or network errors.
Logged in user's delivery details are automatically filled into form, if saved in user's profile.
Upon completion of a successful order the item(s) are marked as sold in the Vehicles datatable and no longer displayed for sale.
A confirmation email is sent to the user.
A profile foregin key and a trade-in foregin key are attached to the order record if neccessary.
The profile page for each user displays the user delivery information and lists that particular users order history.
Each order is linked to the full details of that order.
The delivery information can be changed by the user from this page as can their password.
This page is only available to staff members.
It is used to add new vehicles to stock.
The maker and fuel fields are drop down menus and form fields are validated.
Only available to staff members.
It is used to change the price used to value vehicles for trade-in credit.
The Maker field is prepoulated with manufacturers listed in the Maker datatable.
Htmx is used to populate the price field on a change in the maker field.
This page takes data from the user concerning a vehicle they wish to value as a tradein. The site returns a value to the user who then decides if they want to accept this figure or not.
The user can clear the form and value another vehicle if needed.
The form is validated.
NB. The value returned from the site for each vehicle is calculated using the information input by the user and the base price for that particular manufacturer.
This function was based on several I found online and gives a very approximate value for each vehicle.
The Model type is not used in this calculation as the range of models for each maker is so large. There are several API's which would have given accurate valuations for each vehicle but they were either a paid for service or subject to change so I decided not to use them for this project.
Data Schema
Note: As I review this ERD, it seems to be redundant to have a separate relation for the fuel-type as there is only one field. It may prove useful in a hypothethical future version of the software if other features such as fuel efficency or environmental impact of each fuel needed to be calculated for each vechicle.
Search Engine Optimization
Ensuring the site ranks highly on search engines results is vital to the success of most ecommerce businesses. Seo is a low cost method of marketing and is very effective at directing potential customers to the site.
I considered what topics our potential users most care about and using these created a list of potential keywords as follows;
carsales, value cars, used cars, cheap cars, trade-in, second-hand vehicles, local garage, local car sales, Motordealers, cardealers, car finance, quality used cars, quality second hand vehicles, hybrid used cars, used electric vehicles, best garage near me, guaranteed used vehicles, guaranteed cars.
The 10 best of these were selected based on relevance, authority and volume to the following short-tail and longtail phrases. the website wordtracker was used in this selection process
- used cars dublin
- used cars Ireland
- cars for sale
- second hand cars
- best place to buy used cars near me
- best place to buy new cars near me
- car dealers near me
- cheap used cars near me
- used hybrid cars
- used electric vehicles
The next step in SEO optimisation was to include as many as possible of the keywords into the text of the website. This was done to ensure the language was still relevant and natural. Keywords placed in semantic elements were given higher priority as search engines give these elements greater weight.
As resources allow it is planned to add articles and blog entries which will enhance the websites authority on our area of business, this should boost our ranking further. A website that displays authority, expertise and trustworthiness will rank highly in search engine results, this metric is more important now than pure keyword matching. Relevant articles should also reduce bounce rate and increase session time.
The alt text for all the images on the stock page was changed to give each car a description of its make and model and a used or new classification.
The social links were given the rel="noopener" attribute to ensure their content was ignored by search engines.
A link to SIMI (Motor-Dealers representation body) was provided to further boost rankings.
The meta data tags were created in the html head.
A sitemap.xml file was created using the xml-sitemaps.com website and placed in the root directory of the project. The sitemap file helps search engines to access and analyse the website. It has not been registered with Google as per requirements for this project.
A robots.txt file was created and saved in the root directory. This file specifies which search engines are allowed to crawl the site and which parts should be accessible.
A link is provided to the websites privacy policy to aid transparency and build trust with users.
The privacy policy was generated using privacypolicygenerator.info
Web Marketing
The site is a business to customer model. It will sell new and used vehicles directly to the end-user.
It is planned that the main methods of marketing the business will be through SEO and via organic social media marketing, principally Facebook and a weekly email newsletter.
The reasons these methods were choosen was largely due to budget constraints. Whilst there is plenty of scope for content marketing such as articles/guides to buying vehicles, maintainance tips, weekly video's of new stock, a valuer for trade-in vehicles (api), there are insufficent resources available currently to implement all of these.
Similar websites serving the same market will be looked at and features that are considered to work well will be implemented as a first step.
Paid ads for social media sites and search engines were not considered at this stage due to the cost/value for money. It can be difficult to efficiently target these ads to a relevant audience and the costs can mount up quickly.
The Facebook page is linked from the site and is also shown below.
The Mailchimp app is used to facilitate the newsletter.
Testing
All pages of the app were tested using the WAVE Accessibility testing app.
ALL errors and contrast errors were resolved.
A sample of results is shown below.
Images of all page test can be found here
https://github.com/bobshort4bobby4/PP5-v1/tree/main/media/readme_docs/wave_tests
The Nu HTML checker was used to validate all project html. All errors were cleared
Image of home page result is shown below along with links to other result images.
(CLICK + CTRL to open in new tab)
HTML Checker result stock page
HTML Checker result addstock page
HTML Checker result adjust price page
HTML Checker result bag page
HTML Checker result checkout page
HTML Checker result profile page
HTML Checker result checkout success page
HTML Checker result tradein page
All pages were tested using the Lighthouse app built into the Google Chrome web-browser.
The result for the home page is shown and links to the results from the other pages are given below.
(CLICK + CTRL to open in new tab)
Lighthouse Stock page result
Lighthouse AddStock page result
Lighthouse Adjustprice page result
Lighthouse BAG page result
Lighthouse Checkout page result
Lighthouse Orderhistory page result
Lighthouse Profile page result
Lighthouse Stockdetail page result
The w3s app for validating (jigsaw) was used used to test the css files used in the application.
Results are shown below. All errors were cleared.
The Flake 8 linter was used in the code editor to ensure the python code complied to standard. A few images are shown below of python code syntax checks.
There was a small amount of Javascript used apart from the script supplied by Stripe.
Both were validated by jshint, image of results are shown below.
The website was tested for responsiveness using the built-in tool in the Google Chrome browser. As I worked through each breakpoint I fixed any display issues I encountered.
A set of images of the homepage at each breakpoint is shown.
I used the device emulator built into Google Chrome to test the site on various devices on both portrait and landscape orientation. The home page only has been tested thourghly due to time constaints. Other pages have been tested on an adhoc basis.
Device | Portrait Issues | Landscape Issues | Results |
---|---|---|---|
IPhone 5/se | None | None | Pass |
IPhone6/7/8 | None | None | Pass |
IPhone6/7/8 Plus | None | None | Pass |
Microsoft Lumina 550 | N/A | None | Pass |
Blackberry Z30 | None | None | Pass |
Nokia Lumina 520 | None | None | Pass |
Ipad | None | None | Pass |
Ipad Air | None | None | Pass |
Nest Hub Max | N/A | None | Pass |
I systematically tested all user inputs and functionality in the website to compare feedback/results against expected results. Any unexpected output/outcomes were fixed.
(CTRL + Click to open in new tab) Manual Testing pdf
I implemented those tests I had time resources for, the coverage rate for the app is 80%.
User story | Outcome |
---|---|
to be easily able to ascertain information on the business | Social, telephone and location info provided |
to be able to easily browse and search stock | Link to Stock page prominent, Search function provided |
to navigate easily around the site | Forwards and backwards link on all pages |
to have any incorrect input rejected and the error explained clearly | All Inputs validated and message displayed |
site to be responsive | Site responsive at all screen sizes |
to be able to value any vehicle as a trade-in | Vehicle valuation facility provided |
to easily add a vehicle to my order | One ckick addition to bag, bag easily adjustable |
to easily trade-in a vehicle | Vehicle trade-in facility provided |
to easily pay for my order | Stripe enabled checkout |
to securely pay for my order | Stripe enabled checkout |
to be able to create a user account | All-auth functionality implemented |
to be able to manage my user profile | Profile details editable from profile app |
to review my profile details and order details | Profile and order history viewable from Profile app |
to have all orders confirmed by email | Order and account actions confirmred by email |
to provide an easy to use website | All actions intuitive |
to engage potential customers | Newsletter,social media links to engage users |
to use the site as a marketing tool | SEO used to promote the site to users |
to enable staff members to perform certain admin tasks from the frontend | Required admin tasks acccessible to staff from front-end. |
In error I exposed a Stripe webhook signing secret to github.. Fortunately I had the GIT Guardian feature enabled which sent me an email immediately informing me of my error. I was then immediately able to expire the signing secret via the Stripe dashboard thus minimising any security risk.
Email from Git Guardian
I had a issue when a registered user logged in after an anon user had been using the site(on the same machine). Any bag or trade-in information from the anon user would still be present in the new user's bag.
To fix this I needed to clear the session variables at the point of a successful login. After referencing the allauth documentation here I created a custom login form which inherited the allauth view and added in some code to clear the session variables at login.
The stock page which contains many images has a poor performance score on mobile. I have tried several methods to improve this score with limitied success.
I reduced the image files size as much as possible whilst retaining a good quality image, this improved the score but it is still very variable/inconsistent.
However load times on my personal mobile phone appear ok to me.
I had a problem getting htmx post requests to work. Django was returning the 403 error. After an internet search I added a script which ensures that htmx AJAX requests include a csrf token.
<script> document.body.addEventListener('htmx:configRequest', function(evt) { evt.detail.headers['X-CSRFToken'] = '{{csrf_token}}'; // add a new header into the request }); </script>
I used the USE_THOUSAND_SEPARATOR = True
setting in the settings.py to place a separating comma in all the numbers used on the site.
This had the unwanted side-effect of placing a comma in all the vehicles year of manufacture also.
This was overcome by using the |floatformat:"0u"
template tag on any figures which were not numerical amounts.
There is a slight mis-alignment in the checkout success page, if there is more than one item in the order and these orders have a different number of digits in their price. The prices are aligned to right which means the left edge will be one character mis-aligned.
There is some inconsistency in the styling of the navigation links at the bottom of various pages on the site. I did not have time to standardise these.
It would be preferable for this link to become an ordinary span at larger screen sizes as these generaly will not make telephone calls.
Technologies Used
- Python
- CSS
- HTML
- Javascript
I used the gitpod-full-template for gitpod provided by Code Institute.
The app was built using the Django framework.
I used the Django setup cheat sheet provided as course material to start and set basic settings for the application.
- Balsamiq was used to create wireframes for this project.
- LucidChart used for the ERD in readme file.
- Git Git was used for version control.
- GitHub GitHub is used to store the projects code.
- Heroku Heroku.com was used to deploy the site.
- Chrome Developer Tools used for layout and responsive testing.
- Wave used for accessibility testing.
- W3 Validator used to test css code.
- w3 HTML Validator was used for html validation.
- extendsclass extendsclass python code checker used to validate python code
- Windows snip & sketch used to capture screenshots for readme file.
- techsini.com used to create the mock-up used in the readme file.
- autoprefixer.github.io used to improve browser compatibility.
- Cloudinary.com used to store media and to transform images on download.
- sitelocity.com used to generate critical css and js.
I installed the following libraries.
- Django: The framework used to build the app.
- Pillow:used to handle image files.
- Cloudinary: used to serve/store media and css files.
- Coverage: used in testing to determine how comphrensive testing is.
- Gunicorn:WSGI application server (Web Server Gateway Interface)used to handle interaction between the web server and the app.
- Django-allauth: Handles user verification and authorisation.
- psycopg2:Library used to connect to database.
- dj-database-url: Django utility which allows database URLs to be used to configure the app.
- Django-crispy-forms: used to format forms within Django.
- Stripe: enables secure payments.
- Django-htmx: allows ajax calls without using javascript.
Deployment
Git is an open source version control system and was used for this project. Github was used to store the repository.
Git is run locally whereas Github is cloud based.
Forking a Github repository is the process of making a copy of any repository that you can use without affecting the original, this original is known as the "upstream repository". The process for forking a repository is set out below.
- Go to the Github page that hosts the repository you wish to fork.
- On the top-right of the page there is a button "Fork".
- Click this button.
- This creates a repository in your Github home page which is a copy of the original. You can submit and receive changes to the code by using pull requests and/or syncing with the upstream repository.
(Taken from the Github Docs guide "Forking Projects")
Cloning a repository involves making a full copy of that repository on your local machine. This makes working on the code easier. Changes can be pushed back up to the GitHub site or changes from other sources pulled to your local copy. To make a clone follow the process below.
- Goto the repository page on GitHub.
- Above the file list click on the green button titled "Code".
- You can choose to download a zip file of the repository, unpack it on your local machine and open it in your IDE or,
- Clone using HTTPS by copying the URL under the HTTPS tab.
- Open a terminal window, set current directory to the one you want to contain the clone.
- Type
git clone
and paste the URL copied from the GitHub page. - The repository clone will be created on your machine.
(Taken from the Github Docs guide "Cloning a repository")
Heroku is a cloud based platform that allows the user to deploy and manage apps easily. The completed version of this project was deployed using Heroku.
Heroku is fully managed meaning that all the hardware/server issues are taken care of.
Heroku apps can be deployed either through the website or via the terminal command line.
To deploy my project I followed the steps below.
-
Create a new Heroku app using your chosen app name and choosing appropriate region
-
ADD heroku to the list of allowed hosts in settings.py file,
ALLOWED_HOSTS = ['pp5-carsales.herokuapp.com', 'localhost']
-
Initialise and attach Database, from the Resources tab in Heroku, under add-ons, choose the Heroku Postgress option.
In the project IDE install dj_database_url and psycopy2using
pip3 install dj_database_url psycopg2
Add the following to the settings.pyimport dj_database_url
DATABASES = { 'default': dj_database_url.parse(os.environ.get("DATABASE_URL")) }
and comment out default db.sqlite3 configuration.
copy the database secret key from the heroku app and place it in the env.py file
`os.environ["DATABASE_URL"] = "postgres://tniesqbarwhtjg:******KEY HERE *******" -
Initialise env variables in heroku such as Cloudinary, Database, Email Settings and Stripe Keys. See below for settings for this project.
-
Link the Heroku app to the Github repository (automatic deploys can be enabled if desired)
-
Remove the collectstatic variable from Heroku settings.
-
Moved the sqlite3 database into gitignore so its not visible on the github repo.
git rm --cached
should be used on the file according to my internet research to remove them from github butI will not attempt this as submission time is imminent. -
Set debug to false in settings.py
-
Set email settings in Django settings.py.
-
Set media and static paths in settings.py.
-
Create a runtime.py in the root file of the app specifying python and version,
python-3.8.10
-
Create a Profile file in the root file containing
web: gunicorn pp5_carsales.wsgi
-
Ensure all sensitive passwords/keys are included in the gitignore file.
-
Ensure requiremnets.txt file is updated, using
pip3 freeze --local > requirements.txt
in the terminal. -
Push to Github.
-
From the deploy tab in Heroku choose manual deploy.
These are the configuration variables set on my project, I have not shown the values for obvious reasons.
Variable | Source |
---|---|
CLOUDINARY_URL | Cloudinary Dashboard |
DATABASE_URL | Heroku generated |
DEBUG | Set by User |
DEVELOPEMENT | Set by User |
DISABLE_COLLECTSTATIC | Set by User |
EMAIL_HOST_PASS | Pass from email client |
EMAIL_HOST_USER | Sites email address |
SECRET_KEY | Django random key generated online |
STRIPE_PUBLIC_KEY | API key from Stripe dashboard |
STRIPE_SECRET_KEY | API key from Stripe dashboard |
STRIPE_WH_SECRET | Stripe webhook page in dashboard |
------------------------------- | -------------------------------------------------- |
Credits
- Bootstrap; I used standard bootstrap templates for several of the elements on the site, these were adapted to suit as needed. The Nav-bar and featured vehicles-Slider are all taken from the Bootstrap site.
- The Css used to format the embedded google map on the information page was taken from this blog blog.duda.
- Stackoverflow for general information .
- Javascript script used to close the Django messages was taken from one of the course material examples.
- Script used to include csrf token with htmx requests was taken from Matt Layman Blog.
- Information on how to implement Postgress text search was taken from the django documentation.
- How to use critical path css generator was taken from the sitelocity website.
- Slack users for help regarding getting htmx to pass validation.
- The C.I. tutor team.
- My C.I. Mentor Mr Ben Kavanagh.