oussamabonnor1 / Heroku-deployment

Retail agency small website

Home Page:https://sagemodeboy.herokuapp.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Retail Agency web app

Heroku link: (https://sagemodeboy.herokuapp.com/)

Warning:

for security purposes, admin and manager access have been disabled which means you cannot add, update or delete any entities within the app, if you want to try, contact me after signing up to the app and i'll give you temporary access.

  • Current login access: mail: admin@mail.io password: Capstone2020

Landing page screenshot:

Getting Started

Installing Dependencies

Python 3.7

Follow instructions to install the latest version of python for your platform in the python docs

PIP Dependencies

Once you have your virtual environment setup and running, install dependencies by running:

pip install -r requirements.txt

This will install all of the required packages we selected within the requirements.txt file.

Running the server

To run the server, execute:

source setup.sh

Retail Agency Description

The Retail Agency models a company that is responsible for selling clients' houses and managing and assigning agents to those houses. You are an Executive Producer within the company and are creating a system to simplify and streamline your process.

Models

House with attributes contain name, rooms, price, picture Agent with attributes name, age and picture Job with attributes agent_id, house_id

Environment Variables

In the setup.sh file, you will find:

  • DATABASE_URL
  • TEST_TOKEN
  • AUTH0_DOMAIN
  • API_AUDIENCE
  • LOGIN_URL: the auth0 login(to handle local and heroku logins)

Roles

USER

  • get:agents
  • get:houses
  • get:jobs

MANAGER

All permissions a user has
  • post:houses
  • post:jobs
  • put:agents
  • put:houses
  • put:jobs
  • delete:jobs

ADMIN

All permissions a manager has
  • delete:agents
  • delete:houses
  • post:agents

Endpoints

Login

GET '/login'
 
this endpoint will help you login in an easy and fast way

Agents

GET '/get-agents'

reponse = {
"success": true,
"agents": [
        {
            "age": 24,
            "id": 80,
            "name": "another agent",
            "picture": ""
        },
        {
            "age": 27,
            "id": 76,
            "name": "some agent",
            "picture": ""
        },
    ]
}

GET '/get-agent/<id>'

params = <id>

reponse = {
"success": true,
"agents": [
        {
            "age": 24,
            "id": 80,
            "name": "another agent",
            "picture": ""
        }
    ]
}


POST '/create-agent'

payload = {
    "age": 24,
    "name": "some agent",
    "picture": ""
}
response = {
"success": true,
"agents": [
        {
            "age": 24,
            "id": 80,
            "name": "another agent",
            "picture": ""
        },
        {
            "age": 27,
            "id": 76,
            "name": "some agent",
            "picture": ""
        },
    ]
}

PUT '/update-agent/<id>'

params = <id>

payload = {
    "age": 24,
    "name": "some agent",
    "picture": ""
}
response = {
"success": true,
"agents": [
        {
            "age": 24,
            "id": 80,
            "name": "another agent",
            "picture": ""
        },
        {
            "age": 27,
            "id": 76,
            "name": "some agent",
            "picture": ""
        },
    ]
}

DELETE '/delete-agent/<id>'

params = <id>

response = {
"success": true,
"agents": [
        {
            "age": 24,
            "id": 80,
            "name": "another agent",
            "picture": ""
        },
        {
            "age": 27,
            "id": 76,
            "name": "some agent",
            "picture": ""
        },
    ]
}

Houses

GET '/get-houses'

reponse = {
"success": true,
"houses": [
        {
            "id": 62,
            "name": "some house",
            "picture": "",
            "price": 120,
            "rooms": 7
        },
        {
            "id": 61,
            "name": "another house",
            "picture": "",
            "price": 999,
            "rooms": 7
        },
    ]
}

GET '/get-house/<id>'

params = <id>

reponse = {
"success": true,
"house": {
        "id": 61,
        "name": "some house",
        "picture": "",
        "price": 999,
        "rooms": 7
    },
}

POST '/create-house'

payload = {
    "name": "some house",
    "picture": "",
    "price": 999,
    "rooms": 7
}
response = {
"success": true,
"houses": [
        {
            "id": 62,
            "name": "some house",
            "picture": "",
            "price": 120,
            "rooms": 7
        },
        {
            "id": 61,
            "name": "another house",
            "picture": "",
            "price": 999,
            "rooms": 7
        },
    ]
}

PUT '/update-house/<id>'

params = <id>

payload = {
            "name": "another house",
            "picture": "",
            "price": 999,
            "rooms": 7
        },
response = {
"success": true,
"houses": [
        {
            "id": 62,
            "name": "some house",
            "picture": "",
            "price": 120,
            "rooms": 7
        },
        {
            "id": 61,
            "name": "another house",
            "picture": "",
            "price": 999,
            "rooms": 7
        },
    ]
}

DELETE '/delete-house/<id>'

params = <id>

response = {
"success": true,
"houses": [
        {
            "id": 62,
            "name": "some house",
            "picture": "",
            "price": 120,
            "rooms": 7
        },
        {
            "id": 61,
            "name": "another house",
            "picture": "",
            "price": 999,
            "rooms": 7
        },
    ]
}

Jobs

GET '/get-jobs'

reponse = {
"success": true,
"jobs": [
        {
            "agent_id": 80,
            "house_id": 62
        },
        {
            "agent_id": 79,
            "house_id": 61
        }
    ],
}

GET '/get-job/<agent_id>&<house_id>'

params = <agent_id>&<house_id>

reponse = {
"success": true,
 "job": {
        "agent_id": 80,
        "house_id": 62
    }
}

POST '/create-job'

payload = {
        "agent_id": 80,
        "house_id": 62
    }

response = {
"success": true,
"jobs": [
        {
            "agent_id": 80,
            "house_id": 62
        },
        {
            "agent_id": 79,
            "house_id": 61
        }
    ]
}

PUT '/update-job/<agent_id>&<house_id>'

params = <agent_id>&<house_id>

payload = {
    "agent_id": 80,
    "house_id": 63
}
response = {
"success": true,
"jobs": [
        {
            "agent_id": 80,
            "house_id": 63
        },
        {
            "agent_id": 79,
            "house_id": 61
        }
    ],
}

DELETE '/delete-job/<agent_id>&<house_id>'

params = <agent_id>&<house_id>

response = {
"success": true,
"jobs": [
        {
            "agent_id": 80,
            "house_id": 63
        },
        {
            "agent_id": 79,
            "house_id": 61
        }
    ]
}

Testing

To run the tests:

python test_app.py

Frontend

Why?:

I added a frontend to the flask app to test my newly acquired skills!

How to navigate the website?:

The home page contains the emails and passwords for premade accounts with different roles.
Write them into the (mail/password) fields in the auth0 login page
* You can login using the login button on the main page
* You can refresh the token using the refresh token button in case it expires
* You can logout using the logout button on the main page
* You can perform all actions using the fronent (provided that you use the correct account role)

Weird specifications:

Due to my limited ability to handle frontend calls using AJAX, each page has 2 endpoints:
* One loader page (requires no auth and it calls instantly the actual page)
* The actual page (contains the correct data and requires proper auth)
This was done due to certain issues with JWT storage in the local storage.

Backend

What is a Job (model)?

A job is the representation that a sales agent is currently trying to sell a house to potential clients.
A job is a direct relationship between one specific agent and one specific house.
An agent can sell multiple houses but a house can be sold by many agents.

Why a many to many relationship?

I used a many to many relationship in order to be able to extend the Job model to include (in the future) many data attributes that has no relation with the house or the agent models, and since each house can be handled by an agent, it would seem appropriate to use a one to one relationship but this would not allow to extend the app's functions in a smooth way (data architecture speaking).
Also a job has no id, the primary keys in a job are the id of the agent and the house.

About

Retail agency small website

https://sagemodeboy.herokuapp.com/

License:Apache License 2.0


Languages

Language:CSS 45.6%Language:JavaScript 25.4%Language:HTML 13.5%Language:PHP 13.1%Language:Python 2.3%Language:Mako 0.0%Language:Shell 0.0%Language:Procfile 0.0%