Parts Implemented by Mehmet Can Gün

CODE STRUCTURE

We basically implement the MVC pattern, which is Modal, View, Controller approach. This method provides us to use our methods by calling in a structure.

Models Folder

Containing database connection codes for forms.

  • company.py

  • card.py

  • order.py

Pages Folder

Containing pages to be connected with views page.

  • company.py

  • card.py

  • order.py

Forms Folder in Pages Folder

Containing wtfforms forms to be called in pages and used in views.

Also, forms contains validations.

  • company_form.py

  • card_form.py

  • order_form.py

  • comment_form.py

views.py

Containing the pages for import to use in urls.

views.py
1
2
3
from pages.company import *
from pages.card import *
from pages.order import *

util.py

This file is used only for adding ‘list’ into Flask urls in order to convert urls in spite of html markup.
Basically, if you send list with link, then the url shows data seperated by comma.
[util.py] ListConventer is implemented with BaseConverter
In the 4-5 lines of server.py, adding the list to flask map structure
util.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

'''
Code retrieved from : https://exploreflask.com/en/latest/views.html#custom-converters
'''

from werkzeug.routing import BaseConverter

class ListConverter(BaseConverter):
  def to_python(self, value):
    return value.split(',')

  def to_url(self, values):
    return ','.join(BaseConverter.to_url(self, value) for value in values)
server.py
1
2
3
4
5
6
7
## start 
# https://exploreflask.com/en/latest/views.html#custom-converters

from util import ListConverter
app.url_map.converters['list'] = ListConverter

## end

COMPANY

Company class is connected to user class as a founder info and to contact info to keep companies information to the system.

  • Primary Key: COMPANY_ID

  • Non-relational Key

    • NAME

    • INFORMATION

    • MISSION

    • ABBREVATION

    • FOUNDATION_DATE

    • TYPE( Limited or Anonymous )

  • Foreign Key(table_name)

    • USER_ID(USERACCOUNT)

    • CONTACT_ID(CONTACT_INFO)

Database Functions

This method get all companies in index page of company
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def get_all_companies():
  companies = []
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select * from company"
      cursor.execute(query)
      desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
      for i in cursor:
        res = dict(zip(desc, list(i) ))
        companies.append( res )
  return companies
This method get company in detail page of company
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def get_company(company_key):
  res = None
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select * from company where company_id = %s;"
      cursor.execute(query, (company_key, ))
      data = cursor.fetchone()
      if data:
        company = list( data )
        desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
        res = dict(zip(desc, company ))
  return res
This method add company in add page of company
1
2
3
4
5
6
7
8
9
def add_company(company):
  company_id = -1
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "insert into company(name, information, mission, vision, abbrevation, foundation_date, type, user_id, contact_id) values(%s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING company_id;"
      cursor.execute(query, company)
      connection.commit()
      company_id = cursor.fetchone()[0]
  return company_id
This method update company in update page of company
1
2
3
4
5
6
def update_company(company):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "update company set name = %s, information = %s, mission = %s, vision = %s, abbrevation = %s, foundation_date = %s, type = %s where company_id = %s;"
      cursor.execute(query, company)
      connection.commit()
This method delete company in delete page of company
1
2
3
4
5
6
def delete_company(company_key):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "delete from company where company_id = %s;"
      cursor.execute( query, (company_key,) )
      connection.commit()

Other functions

Getting contact information of company by contact_id
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def get_contact_of_company(contact_id):
  res = None
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select * from contactinfo where id = %s;"
      cursor.execute(query, (contact_id, ))
      data = cursor.fetchone()
      if data:
        contact = list( data )
        desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
        res = dict(zip(desc, contact ))
  return res
Getting id and name of companies to show in card list as choices.
1
2
3
4
5
6
def delete_company(company_key):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "delete from company where company_id = %s;"
      cursor.execute( query, (company_key,) )
      connection.commit()
Getting company by user key.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def get_company_by_user(user_key):
  res = None
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select * from company where user_id = %s;"
      cursor.execute(query, (user_key, ))
      data = cursor.fetchone()
      if data:
        company = list( data )
        desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
        res = dict(zip(desc, company ))
  return res
Update the founder information of company.
1
2
3
4
5
6
def delete_company(company_key):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "delete from company where company_id = %s;"
      cursor.execute( query, (company_key,) )
      connection.commit()

Forms

Company and Founder Form using in pages are made with wtfforms components.

import section of company_form.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from flask_wtf import FlaskForm
from wtforms import Field, SubmitField, FormField, StringField, TextAreaField, SelectField, ValidationError, FieldList
from wtforms.validators import DataRequired
from wtforms.fields.html5 import DateField
#from wtforms.fields.html5 import DateTimeLocalField

from datetime import datetime

from ..forms.users_form import UserAccountForm, ContactInfoForm, PersonForm

from models.users import select_users

msgRequired = "The {} must be filled."
msgChosen   = "Must choose one {} of them."

typeChoices = [
  ('-1', 'Choose one!'), 
  ('LTD', 'Limited'), 
  ('AS', 'Anonim')
]
def get_usernames():
  data = list()
  for i in select_users():
    if i['membershiptype'] is 1:
      data.append( ( i['id'], i['username'] ) )
  return data
Company Abstract Class
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Company(FlaskForm):
  
  name = StringField(
    "Name", 
    validators = [ DataRequired(message = msgRequired.format("name") )],
    render_kw = { "class" : "form-control" }
  )

  information = TextAreaField(
    "Information", 
    validators = [ DataRequired(message = msgRequired.format("Information")) ],
    render_kw = { "class" : "form-control" }
  )

  mission = TextAreaField(
    "Mission",
    validators = [ DataRequired(message = msgRequired.format("Mission")) ],
    render_kw = { "class" : "form-control" }
  )

  vision = TextAreaField(
    "Vision",
    validators = [ DataRequired(message = msgRequired.format("Vision")) ],
    render_kw = { "class" : "form-control" }
  )

  abbrevation = StringField(
    "Abbrevation",
    validators = [ DataRequired(message = msgRequired.format("Abbrevation")) ],
    render_kw = { "class" : "form-control" }
  )

  foundation_date = DateField(
    'Founded Date', 
    render_kw = { "class" : "form-control" }
  )

  type = SelectField(
    "Type", 
    choices = typeChoices, 
    validators = [ unselectedValid ],
    render_kw = { "class" : "form-control" }
  )
CompanyForm Class instanced from Company and ContactInfo class
1
2
3
4
class CompanyForm(FlaskForm):
  company   = FormField(Company)
  contact   = FormField(ContactInfoForm)
  submit    = SubmitField( render_kw = { "class" : "btn btn-primary"})
Founder( class )
1
2
3
4
5
6
7
class Founder(FlaskForm):
  username = SelectField(
    "Select your new boss",
    coerce=int,
    choices = get_usernames(),
    render_kw = { "class" : "form-control" }
  )
FounderForm( instanced from Founder )
1
2
3
class FounderForm(FlaskForm):
  founder  = FormField(Founder)
  submit   = SubmitField( render_kw = { "class" : "btn btn-primary"})

Pages

Pages connected to forms, views and call database operations.

Company Index Page
1
2
3
4
5
6
7
8
def companies_page():
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    companies = get_all_companies()
    return render_template("/companies/index.html", companies = companies)
Company Add Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def company_add_page():
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    company = CompanyForm()
    if company.validate_on_submit():
      user_id     = session['userid']
      contact_id  = insert_contactinfo(company.contact.data, None)

      company_info = (
        company.company["name"].data,
        company.company["information"].data,
        company.company["mission"].data,
        company.company["vision"].data,
        company.company["abbrevation"].data,
        company.company["foundation_date"].data,
        company.company["type"].data,
        user_id,
        contact_id
      )

      company_key = add_company(company_info)
      return redirect(url_for("company_details_page", company_key = company_key))

    return render_template(
      "/companies/create.html",
      form = company
    )
Company Delete Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def company_delete_page(company_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    if request.method == "POST":
      delete_company(company_key)
      return redirect(url_for("companies_page"))
    return render_template("/companies/delete.html")
Company Update Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
def company_update_page(company_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    _company = get_company(company_key)
    
    if(_company is None):
      return redirect(url_for("not_found_page"))
    
    _contact  = get_contact_of_company(_company['contact_id'])
    company   = CompanyForm()

    if company.validate_on_submit():

      company_info = (
        company.company["name"].data,
        company.company["information"].data,
        company.company["mission"].data,
        company.company["vision"].data,
        company.company["abbrevation"].data,
        company.company["foundation_date"].data,
        company.company["type"].data,
        company_key
      )
      update_contactinfo_with_id(_company["contact_id"], company.contact.data)
      update_company(company_info)

      return redirect( url_for("company_details_page", company_key = company_key) )

    company.company["name"].data             = _company["name"]
    company.company["information"].data      = _company["information"]
    company.company["mission"].data          = _company["mission"]
    company.company["vision"].data           = _company["vision"]
    company.company["abbrevation"].data      = _company["abbrevation"]
    company.company["foundation_date"].data  = _company["foundation_date"]
    company.company["type"].data             = _company["type"] if _company["type"] is not None else -1
    company.contact["phoneNumber"].data      = _contact["phonenumber"]
    company.contact["email"].data            = _contact["email"]
    company.contact["fax"].data              = _contact["fax"]
    company.contact["homePhone"].data        = _contact["homephone"]
    company.contact["workmail"].data         = _contact["workmail"]
    
    return render_template(
      "/companies/update.html",
      form = company
    )
Company Details Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def company_details_page(company_key):

  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:
    company = get_company(company_key)
    contact = get_contact_of_company( company['contact_id'] )
    founder = select_a_user_and_info( company['user_id'])
    if founder:
      founder = founder[0]
    if(company is None):
      return redirect(url_for("not_found_page"))
    return render_template(
      "/companies/details.html",
      company = company,
      contact = contact,
      founder = founder
    )
Company Set Founder Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
def company_setfounder_page(company_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    founder = FounderForm()
    
    if founder.validate_on_submit():
      
      update_company_founder( 
        ( founder.founder["username"].data, company_key )
      )

      return redirect(url_for("companies_page"))

    founder.founder["username"].data = None

    return render_template(
      "/companies/set_founder.html",
      form = founder
    )

Views

List Companies if companies exists.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    {% if companies %}
    <table class="table table-light table-hover">
      <thead>
        <tr>
          <th>Name</th>
          <th>Information</th>
          <th>Mission</th>
          <th>Vision</th>
          <th>Abbrevation</th>
          <th>Founded Date</th>
          <th>Type</th>
          <th>Operations</th>
        </tr>
      </thead>
      <tbody>
        {% for i in companies %}
        <tr>
          <td>{{ i['name'] }}</td>
          <td>{{ i['information'] }}</td>
          <td>{{ i['mission'] }}</td>
          <td>{{ i['vision'] }}</td>
          <td>{{ i['abbrevation'] }}</td>
          <td>{{ i['foundation_date'] }}</td>
          <td>{{ i['type'] }}</td>
          <td>
            <a href="{{ url_for('company_details_page', company_key = i['company_id']) }}" class="btn btn-info">Details </a>
            <a href="{{ url_for('company_update_page', company_key = i['company_id']) }}" class="btn btn-warning">Update</a>
            <a href="{{ url_for('company_delete_page', company_key = i['company_id']) }}" class="btn btn-danger">Delete</a>
            {% if not i['user_id'] %}
            <a href="{{ url_for('company_setfounder_page', company_key = i['company_id']) }}" class="btn btn-warning">Set Founder</a>
            {% endif%}
          </td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
    {% endif %}
Adding Company after join as Boss.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <form method="post" action="{{ request.path }}" >
    {{ form.csrf_token }}
    
    {% for field, msg in form.errors.items() %}
      {% for i in msg: %}
        <div class="alert alert-warning" role="alert">
          <strong>{{ msg[i][0] }}</strong>
        </div>
      {% endfor %}
    {% endfor %}
    <h1 class="display-4">Create <small class="text-muted font-italic">company</small></h1>
    <hr>
    {{ form.company( class_ = "mt-5 table table-hover") }}
    <h1 class="display-4">Complete <small class="text-muted font-italic">contact</small></h1>
    <hr>  
    {{ form.contact( class_ = "mt-5 table table-hover") }}
    <p class="text-right">If you cannot find your location, you can create by using link below</p>
    <a href="{{ url_for('location_page') }}" class="float-right btn btn-dark">Add Location</a>
    <div class="text-center">
      {{ form.submit }}
      <a href="{{ url_for('companies_page') }}" class="btn btn-secondary">Cancel</a>
    </div>
  </form>
Update details about company.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
  <form method="post" action="{{ request.path }}" >
    {{ form.csrf_token }}
    
    {% for field, msg in form.errors.items() %}
      {% for i in msg: %}
        <div class="alert alert-warning" role="alert">
          <strong>{{ msg[i][0] }}</strong>
        </div>
      {% endfor %}
    {% endfor %}
    <h1 class="display-4">Update <small class="text-muted font-italic">company</small></h1>
    <hr>
    {{ form.company( class_ = "mt-5 table table-hover") }}
    <h1 class="display-4">Update <small class="text-muted font-italic">contact</small></h1>
    <hr>  
    {{ form.contact( class_ = "mt-5 table table-hover") }}
    <div class="text-center">
      {{ form.submit }}
      <a href="{{ url_for('companies_page') }}" class="btn btn-secondary">Cancel</a>
    </div>
  </form>
Update details about boss of company.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
  <form method="post" action="{{ request.path }}" >
    {{ form.csrf_token }}
    
    {% for field, msg in form.errors.items() %}
      {% for i in msg: %}
        <div class="alert alert-warning" role="alert">
          <strong>{{ msg[i][0] }}</strong>
        </div>
      {% endfor %}
    {% endfor %}

    <h1 class="display-4">Set Founder to <small class="text-muted font-italic">company</small></h1>
    <hr>
    {{ form.founder(class_ = "mt-5 table table-hover") }}
    <div class="text-center">
      {{ form.submit }}
      <a href="{{ url_for('companies_page') }}" class="btn btn-secondary">Cancel</a>
    </div>
  </form>
Confirm the delete operation.
1
2
3
4
5
6
  <form action="{{ request.path }}" method="POST">
    <h3>Are you sure to delete your company?</h3>
    
    <button type="submit" class="btn btn-primary">Submit</button>
    <a href="{{ url_for('companies_page') }}" class="btn btn-secondary">Cancel</a>
  </form>
Lists details about company information, boss information and contact information
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
{% if company %}

<div class="container">
  <div class="row">
    <div class="col-12 row">
      <div class="col-6">
        <h1 class="display-4">Company </h1>
        <hr >
        <ul>
          <li>Name: {{ company["name"] }}</li>
          <li>Information: {{ company["information"] }}</li>
          <li>Mission: {{ company["mission"] }}</li>
          <li>Vision: {{ company["vision"] }}</li>
          <li>Abbrevation: {{ company["abbrevation"] }}</li>
          <li>Foundation Date: {{ company["foundation_date"] }}</li>
          <li>Company Type: {{ company["type"] }}</li>
        </ul>
      </div>
      <div class="col-6">
        <h1 class="display-4 ">Founder</h1>
        <hr >
        {% if founder %}
          <div class="text-center">
            <img src="{{ founder['path'] }}" class="img-fluid round-circle" width="250" height="250">
          </div>
          <ul>
            <li>Founder: {{ founder['name'] }} {{ founder['surname']  }}  </li>
            <li>Gender: {{ founder['gender'] }}</li>
            <li>Birthday: {{ founder['birthday'] }}</li>
            <li>Education Level: {{ founder['educationlevel'] }}</li>
          </ul>
        {% else %}
          <p>This company has no founder yet.</p>
        {% endif %}
      </div>
    </div>
  </div>
    <h1 class="display-4 ">Contact to Company</h1>
    <hr >
    <ul>
      <li>Phone Number: {{ contact['phonenumber '] }}</li>
      <li>Email: {{ contact['email'] }}</li>
      <li>Fax: {{ contact['fax'] }}</li>
      <li>2nd Phone Number: {{ contact['homephone'] }}</li>
      <li>Work Mail: {{ contact['workmail'] }}</li>
    </ul>
</div>

{% endif %}

CARD

Card class is connected to user class with respect to company and to connect to company for specialize card for the company.
  • Primary Key: CARD_ID

  • Non-relational Key:

    • POINTS

    • CARD_NUMBER( UNIQUE )

    • IS_ACTIVE

    • COLOR

    • ACTIVATION_DATE( now ),

    • EXPIRE_DATE( default = added 1 year from now )

  • Foreign Key(table_name)

    • USER_ID(USERACCOUNT)

    • COMPANY_ID(COMPANY)

Database Functions

This method get all cards in index page of card
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def get_all_cards():
  cards = []
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select card_id, p.name as name, color , p.surname as surname, points, expire_date, card_number, com.name as company from card left outer join company as com on card.company_id = com.company_id left join useraccount as users on card.user_id = users.id inner join person as p on p.id = users.person"
      cursor.execute(query)
      desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
      for i in cursor:
        res = dict(zip(desc, list(i) ))
        cards.append( res )
  return cards
This method get card in detail page of card
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def get_card(card_key):
  res = None
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select username, CONCAT(p.name,' ',p.surname) as person_name, color, ph.path as path, p.birthDay, p.educationLevel, p.gender, card_number, points, is_active, activation_date, expire_date, card.company_id as company_id, c.name as company_name, c.information as company_information from card full join useraccount on card.user_id = useraccount.id full join company as c on c.company_id = card.company_id full join person as p on p.id = useraccount.person full join photo as ph on p.photo = ph.id where card_id = %s;"
      cursor.execute(query, (card_key, ))
      data = cursor.fetchone()
      if data:
        card = list( data )
        desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
        res = dict(zip(desc, card ))
  return res
This method add card in add page of card
1
2
3
4
5
6
7
8
9
def add_card(card):
  card_id = -1
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "insert into card(points, card_number, is_active, color, expire_date, user_id, company_id) values(%s, %s, %s, %s, %s, %s, %s) RETURNING card_id;"
      cursor.execute(query, card)
      connection.commit()
      card_id = cursor.fetchone()[0]
  return card_id
This method update card in update page of card
1
2
3
4
5
6
def update_card(card):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "update card set points = %s, card_number = %s, is_active = %s, color = %s, expire_date = %s, user_id = %s, company_id=%s where card_id = %s;"
      cursor.execute(query, card)
      connection.commit()
This method delete card in delete page of card
1
2
3
4
5
6
def delete_card(card_key):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "delete from card where card_id = %s;"
      cursor.execute( query, (card_key,) )
      connection.commit()

Other functions

This method checks the card number does exist or not in cards.
1
2
3
4
5
6
7
8
def check_card_number(card_number):
  res = None
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select COUNT(*) from card where card_number = %s;"
      cursor.execute(query, (card_number, ))
      res = cursor.fetchone()[0]
  return res
Getting card information by user_key in order to use in my_card page.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def get_card_by_user(user_key):
  res = None
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select username, CONCAT(p.name,' ',p.surname) as person_name, color, ph.path as path, p.birthDay, p.educationLevel, p.gender, card_number, points, is_active, activation_date, expire_date, card.company_id as company_id, c.name as company_name, c.information as company_information from card inner join useraccount on card.user_id = useraccount.id full join company as c on c.company_id = card.company_id full join person as p on p.id = useraccount.person full join photo as ph on p.photo = ph.id where useraccount.id = %s;"
      cursor.execute(query, (user_key, ))
      data = cursor.fetchone()
      if data:
        card = list( data )
        desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
        res = dict(zip(desc, card ))
  return res

Forms

CardForm is used in pages.

import section of card_form
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from flask_wtf import FlaskForm
from wtforms import SelectField, FormField, SubmitField, StringField, RadioField, ValidationError
from wtforms.validators import DataRequired, Optional, Length
from wtforms_components import IntegerField, ColorField
from wtforms.fields.html5 import DateField
#from colour import Color
from datetime import datetime, timedelta

from flask import session

from models.card import check_card_number
from models.users import check_if_user_exists, select_a_user_and_info, get_user_by_username


msgRequired = "The {} must be filled."
msgChosen   = "Must choose one {} of them."
msgValidations = [
  "Username not found.",
  "This user is not a customer!"
]
typeChoices = [
  (0, 'Inactive'), 
  (1, 'Active')
]


def checkUser(form, field):
  
  if not check_if_user_exists( {"username":field.data} ):
    raise ValidationError(msgValidations[0])
  else:
    
    user_id = get_user_by_username(field.data)['id']
    
    t = select_a_user_and_info( user_id )[0]['membershiptype']
    if t != 'Customer':
      raise ValidationError(msgValidations[1])
Card class for Form
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Card(FlaskForm):
  points = IntegerField(
    "Points",
    default = 0,
    validators = [ DataRequired(message = msgRequired.format("points"))],
    render_kw = { "class" : "form-control" }
  )
  
  is_active = RadioField(
    "Is Active",
    default = 1,
    choices = typeChoices, 
    coerce  = int,
    validators = [ DataRequired(message = msgRequired.format("active state") ) ],
    render_kw = { "class" : "list-group list-group-horizontal" }
  )

  color = ColorField(
    "Color", 
    validators = [ Optional() ],
    render_kw = { "class" : "form-control"}
  )

  expire_date = DateField(
    'Expire Date',
    default = ( datetime.now() + timedelta(days=(365)) ),
    render_kw = { "class" : "form-control" }
  )

  card_number = StringField(
    "Card Number",
    validators= [ Length(min=16, max=16, message = "The column size must be 16" )],
    render_kw = {"class": "form-control", "readonly" : True}
  )
CardForm includes Card class
1
2
3
4
5
6
7
8
class CardForm(FlaskForm):
  card      = FormField(Card)
  username  = StringField(
    "Username",
    validators = [ checkUser ],
    render_kw = { "class" : "form-control" }
  )
  submit    = SubmitField( render_kw = { "class" : "btn btn-primary"})

Pages

Pages connected to forms, views and call database operations.

Card Index Page
1
2
3
4
5
6
7
8
def cards_page():
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    cards = get_all_cards()
    return render_template("/cards/index.html", cards = cards)
Card Add Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def card_add_page():
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    card = CardForm()
    x = checkCardNumber(card.card["card_number"].data)
  
    if card.validate_on_submit() and x:
      
      user_key    = get_user_by_username(card.username.data)['id']
      company_key = get_company_by_user(session['userid'])['company_id']
      
      card_info = (
        card.card["points"].data,
        card.card["card_number"].data,
        card.card["is_active"].data,
        str(card.card["color"].data),
        card.card["expire_date"].data,
        user_key,
        company_key
      )

      card_key = add_card(card_info)
      return redirect(url_for("card_details_page", card_key = card_key))
    
    card.card['card_number'].data = uniqueValue()

    return render_template(
      "/cards/create.html",
      form = card
    )
Card Delete Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def card_delete_page(card_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    if request.method == "POST":
      delete_card(card_key)
      return redirect(url_for("cards_page"))
    return render_template("/cards/delete.html")
Card Update Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def card_update_page(card_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  elif session['membershiptype'] != 'Boss':
    return redirect(url_for("access_denied_page"))
  else:
    _card = get_card(card_key)
    if(_card is None):
      return redirect(url_for("not_found_page"))
    card = CardForm()

    if card.validate_on_submit():
      user_key    = get_user_by_username(card.username.data)['id']
      company_key = get_company_by_user(session['userid'])['company_id']
      
      card_info = (
        card.card["points"].data,
        card.card["card_number"].data,
        card.card["is_active"].data,
        str(card.card["color"].data),
        card.card["expire_date"].data,
        user_key,
        company_key,
        card_key
      )
      update_card(card_info)

      return redirect( url_for("card_details_page", card_key = card_key) )
    
    card.card["points"].data           = _card["points"]
    card.card["card_number"].data      = _card["card_number"]
    card.card["is_active"].data        = _card["is_active"]
    card.card["color"].data            = _card["color"]
    card.card["expire_date"].data      = _card["expire_date"]
    card.username.data                 = _card['username']

    return render_template(
      "/cards/update.html",
      form = card
    )
Card Details Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def card_details_page(card_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:
    card = get_card(card_key)
    if(card is None):
      return redirect(url_for("not_found_page"))
    return render_template(
      "/cards/details.html",
      card = card
    )
My Card Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def my_card_page():
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:
    card = get_card_by_user(session['userid'])
    if(card is None):
      return redirect(url_for("not_found_page"))
    return render_template(
      "/cards/details.html",
      card = card
    )

Views

List Cards if cards exists.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<div class="container">
  <h1 class="display-4">Index <small class="text-muted font-italic">cards</small></h1>
  <hr>
</div>
<div class="container mt-2">
    <div class="row">
      <div class="column mr-4">
        <a href="{{ url_for('card_add_page') }}" class="btn btn-primary" title="Add Card">Add Card</a>
      </div>
    </div>
    {% if cards %}
    <table class="table table-light table-hover">
      <thead>
        <tr>
          <th>Name</th>
          <th>Surname</th>
          <th>Expire Date</th>
          <th>Points</th>
          <th>Color</th>
          <th>Card Number</th>
          <th>Company</th>
          <th>Operations</th>
        </tr>
      </thead>
      <tbody>
        {% for i in cards %}
        <tr>
          <td>{{ i['name'] }}</td>
          <td>{{ i['surname'] }}</td>
          <td>{{ i['expire_date'] }}</td>
          <td>{{ i['points'] }}</td>
          <td>{{ i['color'] }}</td>
          <td>{{ i['card_number'] }}</td>
          <td>{{ i['company'] }}</td>
          <td>
            <a href="{{ url_for('card_details_page', card_key = i['card_id']) }}" class="btn btn-outline-info">Details </a>
            <a href="{{ url_for('card_update_page', card_key = i['card_id']) }}" class="btn btn-warning">Update</a>
            <a href="{{ url_for('card_delete_page', card_key = i['card_id']) }}" class="btn btn-danger">Delete</a>
          </td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
    <div class="row">
      <div class="column mr-4">
        <a href="{{ url_for('card_add_page') }}" class="btn btn-primary" title="Add Card">Add Card</a>
      </div>
    </div>
</div>
  {% endif %}
Adding Card after join as Boss and if a user is a customer.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<div class="container">
  <h1 class="display-4">Create <small class="text-muted font-italic">card</small></h1>
  <hr>
  <form method="post" action="{{ request.path }}" >
    {{ form.csrf_token }}
    
    {% for field, msg in form.errors.items() %}
      {% for i in msg: %}
        {% if msg[i] %}
          {% for k in msg[i] %}
          <div class="alert alert-warning" role="alert">
            <strong>{{ k }}</strong>
          </div>  
          {% endfor %}
        {% else %}
          <div class="alert alert-warning" role="alert">
            <strong>{{ msg[0] }}</strong>
          </div>  
        {% endif%}
      {% endfor %}
    {% endfor %}
    <div class="mt-5 form-group">
      <label for="Username"><b>Enter Username</b></label>
      {{ form.username }}
    </div>
    {{ form.card( class_ = " table table-hover") }}
    
    <div class="text-center">
      {{ form.submit }}
      <a href="{{ url_for('cards_page') }}" class="btn btn-secondary">Cancel</a>
    </div>
  </form>
</div>
Update details about card.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<div class="container">
  <h1 class="display-4">Update <small class="text-muted font-italic">card</small></h1>
  <hr>
  <form method="post" action="{{ request.path }}" >
    {{ form.csrf_token }}
    
    {% for field, msg in form.errors.items() %}
      {% for i in msg: %}
        {% if msg[i] %}
          {% for k in msg[i] %}
          <div class="alert alert-warning" role="alert">
            <strong>{{ k }}</strong>
          </div>  
          {% endfor %}
        {% else %}
          <div class="alert alert-warning" role="alert">
            <strong>{{ msg[0] }}</strong>
          </div>  
        {% endif%}
      {% endfor %}
    {% endfor %}
    <div class="mt-5 form-group">
      <label for="Username"><b>Update Username</b></label>
      {{ form.username }}
    </div>
    {{ form.card( class_ = " table table-hover") }}
    
    <div class="text-center">
      {{ form.submit }}
      <a href="{{ url_for('cards_page') }}" class="btn btn-secondary">Cancel</a>
    </div>
  </form>
</div>
Confirm the delete operation.
1
2
3
4
5
6
7
8
9
<div class="container">
  
  <form action="{{ request.path }}" method="POST">
    <h3>Are you sure to delete the card?</h3>
    
    <button type="submit" class="btn btn-primary">Submit</button>
    <a href="{{ url_for('cards_page') }}" class="btn btn-secondary">Cancel</a>
  </form>
</div>
Lists details about card and user information
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{% if card %}
  <div class="container">
    <div class="row">
      <div class="col-12 row">
        <div class="col-6">
          <h1 class="display-4">Card Information {% if card['is_active'] %} <sup>({{ "Active" }})</sup> {% else %} ({{ "Passive" }}) {% endif %}</h1>
          <hr style="padding:5px 0;background-color: {{ card['color'] }}">
          <ul>
            <li>Card Number: {{ card['card_number'] }} </li>
            <li>Points: {{ card['points'] }} </li>
            <li>Activation Date: {{ card['activation_date'] }} </li>
            <li>Expire Date: {{ card['expire_date'] }} </li>
            <li>Connected to <a href="{{ url_for('company_details_page', company_key = card['company_id']) }}" target="_blank">{{ card['name'] }} company</a> </li>
            <li>Company Information: {{card['company_information']}}</li>
          </ul>
        </div>
        <div class="col-6">
          <h1 class="display-4 pb-1">User Information</h1><br>
          <hr style="padding:5px 0;background-color: {{ card['color'] }}" class="mt-5">
          
          <div class="text-center">
            <img src="{{ card['path'] }}" class="img-fluid round-circle" width="250" height="250">
          </div>
          <ul>
            <li>Card Owner: {{ card['person_name']  }}  </li>
            <li>Gender: {{ card['gender'] }}</li>
            <li>Birthday: {{ card['birthday'] }}</li>
            <li>Education Level: {{ card['educationlevel'] }}</li>
          </ul>
        </div>
      </div>
    </div>
  </div>
{% endif %}

ORDER

Order class is connected to restaurant for meals and user account for who ordered the meals.

  • Primary Key: ORDER_ID

  • Non-relational Key

    • PRICE( total price )

    • NOTE

    • TYPE( CASH OR CREDIT CARD )

    • RATE

    • CREATED_AT( now )

    • END_AT

    • is_delivered( 0 means not delievered )

  • Foreign Key(table_name)

    • RESTAURANT_ID(RESTAURANT)

    • USER_ID(USERACCOUNT)

Database Functions

This method get all orders in index page of order
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def get_all_orders():
  orders = []
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select * from orders"
      cursor.execute(query)
      desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
      for i in cursor:
        res = dict(zip(desc, list(i) ))
        orders.append( res )
  return orders
This method get order in detail page of order by type such as restaurant, user or order key.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def get_order(key, type):
  orders = []
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = ""
      if type == "restaurant":
        query = "select * from orders where restaurant_id = %s order by end_at desc;"
      elif type == "user":
        query = "select * from orders where user_id = %s order by end_at desc;"
      else:
        query = "select * from orders where order_id = %s order by end_at desc;"
      cursor.execute(query, (key, ))
      desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
      for i in cursor:
        res = dict(zip(desc, list(i) ))
        orders.append( res )
  return orders
This method get order food details in detail page of order by type such as restaurant, user or order key.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def get_detailed_order_food(key, type):
  orders = []
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = ""
      if type == "restaurant":
        query = "select food_name, brand_name, amount, f.price as price from orders as o full join order_food as of on of.order_id = o.order_id full join food as f on of.food_id = f.food_id where restaurant_id = %s order by end_at desc;"
      elif type == "user":
        query = "select food_name, brand_name, amount, f.price as price from orders as o full join order_food as of on of.order_id = o.order_id full join food as f on of.food_id = f.food_id where user_id = %s order by end_at desc;"
      else:
        query = "select food_name, brand_name, amount, f.price as price from orders as o full join order_food as of on of.order_id = o.order_id full join food as f on of.food_id = f.food_id where o.order_id = %s order by end_at desc;"
      
      cursor.execute(query, (key, ))
      desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
      for i in cursor:
        res = dict(zip(desc, list(i) ))
        orders.append( res )
  return orders
This method get order details in detail page of order
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def get_order_details(order_key):
  res = None
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select note, price, o.type as payment_type, created_at, end_at, manager, CONCAT(p.name, ' ', p.surname) as person_name from orders as o full join restaurant as r on o.restaurant_id = r.restaurant_id full join useraccount as u on u.id = o.user_id full join person as p on p.id = u.person where order_id = %s;"
      cursor.execute(query, (order_key, ))
      data = cursor.fetchone()
      if data:
        card = list( data )
        desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
        res = dict(zip(desc, card ))
  return res
This method get comments of the order in detail page of order
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def get_order_related_comments(key):
  orders = []
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select title, description, case speed when 0 then 'Slow' else 'Fast' end as speed, case taste when 0 then 'Not tasteful' else 'Tasteful' end as taste, CONCAT(p.name, ' ', p.surname) as person_name from comment as c full join useraccount as u on u.id = c.user_id full join person as p on p.id = u.person where order_id = %s;"
      cursor.execute(query, (key, ))
      desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
      for i in cursor:
        res = dict(zip(desc, list(i) ))
        orders.append( res )
  return orders
This method add order in payment page of order
1
2
3
4
5
6
7
8
9
def add_order(order):
  order_id = -1
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "insert into orders(price, note, type, rate, end_at, created_at, restaurant_id, user_id) values(%s, %s, %s, %s, %s, %s, %s, %s) RETURNING order_id;"
      cursor.execute(query, order)
      connection.commit()
      order_id = cursor.fetchone()[0]
  return order_id
This method update order in update page of order
1
2
3
4
5
6
def update_order(order):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "update orders set price = %s, note = %s, type = %s, rate = %s, end_at = %s where order_id = %s;"
      cursor.execute(query, order)
      connection.commit()
This method delete order in cancel page of order
1
2
3
4
5
6
def delete_order(order_key):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "delete from orders where order_id = %s;"
      cursor.execute( query, (order_key,) )
      connection.commit()

Other functions

This method update the delivered status of the order.
1
2
3
4
5
6
def update_order_delivered(order_id):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "update orders set is_delivered = 1 where order_id = %s;"
      cursor.execute(query, (order_id, ))
      connection.commit()
This method calls if the order is delivered to customer, the stock update function from stock model to decrease the amount of foods.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def update_stock_by_order_key(order_id):
  food_list = []
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select food_id, amount from order_food where order_id = %s;"
      cursor.execute(query, (order_id, ))
      for id, amount in cursor:
        for i in range(amount):
          update_stock(id)

Forms

OrderForm is used in pages.

import section of order_form
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from flask import request, session
from flask_wtf import FlaskForm
from wtforms import Field, RadioField, DecimalField, SubmitField, FormField, StringField, TextAreaField, SelectField, ValidationError, FieldList
from wtforms.validators import DataRequired, Length
#from wtforms.fields.html5 import DateField
from wtforms.fields.html5 import DateTimeLocalField

from datetime import datetime, timedelta
from ..forms.users_form import UserAccountForm, ContactInfoForm, PersonForm

from models.users import select_users

msgRequired = "The {} must be filled."
msgChosen   = "Must choose one {} of them."
Order class for Form
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Order(FlaskForm):
  note = TextAreaField(
    "Note", 
    validators = [ DataRequired(message = msgRequired.format("note") )],
    render_kw = { "class" : "form-control" }
  )
  
  price = DecimalField(
    "Price",
    render_kw = {"class": "form-control", "readonly" : True}
  )

  payment_type = SelectField(
    "Payment Type",
    choices = [("CASH", "Cash"), ("CREDIT", "Credit Card")],
    validators = [ DataRequired(message = msgRequired.format("payment type")) ],
    render_kw = { "class" : "form-control"}
  )

  end_at = DateTimeLocalField(
    'End Datetime',
    format = '%Y-%m-%dT%H:%M',
    default = ( datetime.now() + timedelta(minutes=(60)) ),
    render_kw = { "class" : "form-control" }
  )

  rate = RadioField(
    "Rate",
    default = 0,
    coerce=int,
    choices = [ (1, "1"), (2, "2"), (3, "3"), (4, "4"), (5, "5"), ],
    validators = [ DataRequired(message = msgRequired.format("rate"))],
    render_kw = { "class" : "list-group list-group-horizontal" }
  )

OrderForm includes Order class
1
2
3
class OrderForm(FlaskForm):
  order     = FormField(Order)
  submit    = SubmitField( render_kw = { "class" : "btn btn-primary"})

Pages

Pages connected to forms, views and call database operations.

Order Index Page
1
2
3
4
5
6
7
def orders_page():
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:
    orders = get_all_orders()
    return render_template("/orders/index.html", orders = orders,
      date_now = datetime.now())
Payment Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
def payment_page(meals):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:
    if meals is None:
      return redirect(url_for("not_found_page"))
    
    meals_list = list()
    restaurant_id = -1

    for i in meals:
      food          = select_restaurant_price(int(i))
      name          = food[0] ## food name
      restaurant_id = food[1] ## restaurant_id
      price         = food[2] ## food price
      stock         = max_meal_possible( int(i) )
      meals_list.append( ( i, name, stock, price ) )

    order = OrderForm()
    
    if order.validate_on_submit():
      
      ar = []
      for i in range(1, len(meals_list)+1):
        ar.append( request.form.get("amount_of_check_{}".format(i)) ) 

      user_id = session['userid']

      order_info = (
        order.order["price"].data,
        order.order["note"].data,
        order.order["payment_type"].data,
        order.order["rate"].data,
        order.order["end_at"].data,
        datetime.now(),
        restaurant_id,
        user_id
      )

      order_key = add_order(order_info)
      for i in range(0, len(ar)):
        connect_order_and_food( (order_key, meals_list[i][0], ar[i]) )
      
      return redirect(url_for("my_orders_page"))
    
    return render_template(
      "/orders/payment.html",
      form = order,
      meals = meals_list
    )
Order Cancel Page
1
2
3
4
5
6
7
8
def order_cancel_page(order_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:
    if request.method == "POST":
      delete_order(order_key)
      return redirect(url_for("orders_page"))
    return render_template("/orders/cancel.html")
Order Update Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def order_update_page(order_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:
    
    order = OrderForm()
    
    _order = get_order(order_key, "order")[0]

    if order.validate_on_submit():
      
      order_info = (
        order.order["price"].data,
        order.order["note"].data,
        order.order["payment_type"].data,
        order.order["rate"].data,
        order.order["end_at"].data,
        order_key
      )

      update_order(order_info)
      
      return redirect(url_for("order_details_page", order_key = order_key))

    order.order["price"].data = _order["price"]
    order.order["note"].data = _order["note"]
    order.order["payment_type"].data = _order["type"]
    order.order["rate"].data = _order["rate"]
    order.order["end_at"].data = _order["end_at"]

    return render_template(
      "/orders/edit.html",
      form = order
    )
Order Details Page
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def order_details_page(order_key):

  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:
    order = get_detailed_order_food(order_key, "order")
    comment = get_order_related_comments(order_key)
    order_details = get_order_details(order_key)
    
    if(order is None):
      return redirect(url_for("not_found_page"))
    return render_template(
      "/orders/details.html",
      order = order,
      comments = comment,
      order_detail = order_details
    )
My Orders Page shows ordered meals and details about it.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def my_orders_page():
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:

    myorders = get_order(session["userid"], "user")
    
    return render_template(
      "/orders/myorders.html",
      myorders = myorders,
      date_now = datetime.now()
    )
if the method is POST, Order Delivered be called and update the delivered status as 1 and call the update stock function to decrease the stock size.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def my_orders_page():
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:

    myorders = get_order(session["userid"], "user")
    
    return render_template(
      "/orders/myorders.html",
      myorders = myorders,
      date_now = datetime.now()
    )

Views

List Orders if orders exists.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<div class="container">
  <h1 class="display-4">All <small class="text-muted font-italic">orders</small></h1>
  <hr>
</div>
<div class="container mt-2">
    {% if orders %}
    <table class="table table-light table-hover">
      <thead>
        <tr>
          <th>#</th>
          <th>Price</th>
          <th>Note</th>
          <th>Type</th>
          <th>Rate</th>
          <th>Start Date</th>
          <th>End Date</th>
        </tr>
      </thead>
      <tbody>
        {% for i in orders %}
        <tr>
          <td>{{ i['order_id'] }}</td>
          <td>{{ i['price'] }}</td>
          <td>{{ i['note'] }}</td>
          <td>{{ i['type'] }}</td>
          <td>{{ i['rate'] }}</td>
          <td>{{ i['created_at'] }}</td>
          <td>{{ i['end_at'] }}</td>
          <td>
            <a href="{{ url_for('comment_order_page', order_key = i['order_id'] ) }}" class="btn btn-outline-dark">Make Comment </a>
            <a href="{{ url_for('order_update_page', order_key = i['order_id']) }}" class="btn btn-outline-warning">Update Order </a>
            <a href="{{ url_for('order_cancel_page', order_key = i['order_id']) }}" class="btn btn-outline-danger">Cancel Order </a>
            <a href="{{ url_for('order_details_page', order_key = i['order_id']) }}" class="btn btn-outline-info">Details </a>
          </td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
</div>
Get the list from meal page then put the values to views with javascript. Then, the customer sells the food by selecting the amount and the order is starting.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<div class="container">
  <form method="post" action="{{ request.path }}" name="payment_list">
    {{ form.csrf_token }}
    
    {% for field, msg in form.errors.items() %}
      {% for i in msg: %}
        <div class="alert alert-warning" role="alert">
          <strong>{{ msg[i][0] }}</strong>
        </div>
      {% endfor %}
    {% endfor %}

    <h1 class="display-4">Payment <small class="text-muted font-italic">page</small></h1>
    <hr>
    <table class="table table-light">
      <thead>
        <th>Meal Name</th>
        <th>Stock</th>
        <th>Price</th>
      </thead>
      <tbody>
        {% set count = namespace(value=0) %}
        {% for i in meals %}
          {% set count.value = count.value + 1 %}
          <tr>
            <td>{{ i[1] }}</td>
            <td>
              <input type="number" data-key="{{ i[0] }}" data-price="{{ i[3] }}" name="amount_of_check_{{ count.value }}" class="amount_of_check" id="amount_of_check_{{ count.value }}" value=1 min=1 max="{{ i[2]}}" > 
            </td>
            <td>{{ i[3] }}</td>
          </tr>
        {% endfor%}
      </tbody>
    </table>
    {{ form.order( class_ = "mt-5 table table-hover") }}
    
    <div class="text-center">
      {{ form.submit }}
      <a href="{{ url_for('orders_page') }}" class="btn btn-secondary">Cancel</a>
    </div>
  </form>
</div>

<script type="text/javascript">
  $(document).ready(function(){
    var vale = document.getElementsByClassName("amount_of_check")
    var allsum = 0
    for(let i=0;i<vale.length;i++){
      var itm  = parseFloat(vale.item(i).getAttribute('data-price'))
      var stock = parseFloat(vale.item(i).value)
      allsum = allsum + itm * stock
    }
    document.getElementsByName("order-price")[0].value = allsum.toFixed(2)
    
    $(".amount_of_check").change(function(){
      var vale = document.getElementsByClassName("amount_of_check")
      var allsum = 0
      for(let i=0;i<vale.length;i++){
        var itm  = parseFloat(vale.item(i).getAttribute('data-price'))
        var stock = parseFloat(vale.item(i).value)
        allsum = allsum + itm * stock
      }
      document.getElementsByName("order-price")[0].value = allsum.toFixed(2)
    });
  })
</script>
Update details about order.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="container">
  <form method="post" action="{{ request.path }}">
    {{ form.csrf_token }}
    
    {% for field, msg in form.errors.items() %}
      {% for i in msg: %}
        <div class="alert alert-warning" role="alert">
          <strong>{{ msg[i][0] }}</strong>
        </div>
      {% endfor %}
    {% endfor %}

    <h1 class="display-4">Update <small class="text-muted font-italic">order</small></h1>
    <hr>
    
    {{ form.order( class_ = "mt-5 table table-hover") }}
    
    <div class="text-center">
      {{ form.submit }}
      <a href="{{ url_for('orders_page') }}" class="btn btn-secondary">Cancel</a>
    </div>
  </form>
</div>
The customer can cancel if the date between starting date and end date is not over.
1
2
3
4
5
6
7
8
9
<div class="container">
  
  <form action="{{ request.path }}" method="POST">
    <h3>Do you wanna really cancel your order?</h3>
    
    <button type="submit" class="btn btn-primary">Submit</button>
    <a href="{{ url_for('orders_page') }}" class="btn btn-secondary">Cancel</a>
  </form>
</div>
Lists details about order
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{% if order %}

<div class="container">
  <div class="row">
    <div class="col-8">
      <h1 class="display-4">Meal Details</h1>
      <hr >
      <table class="table table-light table-hover">
        <thead>
          <th>Food Name</th>
          <th>Brand Name</th>
          <th>Amount</th>
          <th>Price by food</th>
        </thead>
        <tbody>
        {% for i in order %}
          <tr>
            <td>{{ i['food_name'] }}</td>
            <td>{{ i['brand_name'] }}</td>
            <td>{{ i['amount'] }}</td>
            <td>{{ i['price'] }}</td>
          </tr>
        {% endfor%}
        </tbody>
      </table>
    </div>
    <div class="col-4">
      <h1 class="display-4">Order Details</h1>
      <hr >
      {% if order_detail %}
      <div class="row">
        
        <ul class="list-group list-group-flush">
          <li class="list-group-item">Note: {{ order_detail['note'] }}</li>
          <li class="list-group-item">Total Price: {{ order_detail['price'] }}</li>
          <li class="list-group-item">Payment Type: {{ order_detail['payment_type'] }}</li>
          <li class="list-group-item">Order Date: {{ order_detail['created_at'] }}</li>
          <li class="list-group-item">Delivery Date: {{ order_detail['end_at'] }}</li>
          <li class="list-group-item">Restaurant Manager: {{ order_detail['manager'] }}</li>
          <li class="list-group-item">Ordered by {{ order_detail['person_name'] }} </li>
        </ul>
      </div>
      {% endif %}
    </div>
  </div>
  <div class="row">
    <h1 class="display-4 ">Comments</h1>
    <hr >
    <table class="table table-light table-hover">
      <thead>
        <th>Title</th>
        <th>Description</th>
        <th>Person Info</th>
        <th>Speed</th>
        <th>Taste</th>
      </thead>
      <tbody>
      {% for i in comments %}
        <tr>
          <td>{{ i['title'] }}</td>
          <td>{{ i['description'] }}</td>
          <td>{{ i['person_name'] }}</td>
          <td>{{ i['speed'] }}</td>
          <td>{{ i['taste'] }}</td>
        </tr>
      {% endfor %}
      </tbody>
    </table>
  </div>
</div>

{% endif %}
Lists details about order by the users
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<div class="container">
  <h1 class="display-4">My <small class="text-muted font-italic">orders</small></h1>
  <hr>
</div>

<div class="container mt-2">
    {% if myorders %}
    <table class="table table-light table-hover">
      <thead>
        <tr>
          <th>#</th>
          <th>Price</th>
          <th>Note</th>
          <th>Type</th>
          <th>Rate</th>
          <th>Start Date</th>
          <th>End Date</th>
        </tr>
      </thead>
      <tbody>
        {% for i in myorders %}
        <tr>
          <td>{{ i['order_id'] }}</td>
          <td>{{ i['price'] }}</td>
          <td>{{ i['note'] }}</td>
          <td>{{ i['type'] }}</td>
          <td>{{ i['rate'] }}</td>
          <td>{{ i['created_at'] }}</td>
          <td>{{ i['end_at'] }}</td>
          <td>
            {% if i['end_at'] < date_now %}
              {% if i['is_delivered'] == 0 %}
              <form action="{{ url_for('order_delivered_page') }}" method="POST">
                <input type="hidden" name="order_key" value="{{ i['order_id'] }}">
                <button type="submit" class="btn btn-outline-dark">Deliver</button>
              </form>
              {% else %}
                <a href="{{ url_for('comment_order_page', order_key = i['order_id']) }}" class="btn btn-outline-dark">Make Comment </a>
              {% endif %}
            {% else %}
              <a href="{{ url_for('order_update_page', order_key = i['order_id']) }}" class="btn btn-outline-warning">Update Order </a>
              <a href="{{ url_for('order_cancel_page', order_key = i['order_id']) }}" class="btn btn-outline-danger">Cancel Order </a>
            {% endif %}
            <a href="{{ url_for('order_details_page', order_key = i['order_id']) }}" class="btn btn-outline-info">Details </a>
          </td>
        </tr>
        {% endfor %}
      </tbody>
    </table>
    {% endif %}
</div>

ORDER_FOOD

Order food class is connected to restaurant for meals and user account for who ordered the meals.

  • Primary Key: ORDER_ID, FOOD_ID

  • Non-relational Key: AMOUNT( ordered food amount )

  • Foreign Key(table_name)

    • FOOD_ID(FOOD)

    • ORDER_ID(ORDERS)

Database Functions

This method connect food and order in one table with the amount of food.
1
2
3
4
5
6
def connect_order_and_food(orderfood):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "insert into order_food(order_id, food_id, amount) values(%s, %s, %s);"
      cursor.execute(query, orderfood)
      connection.commit()

COMMENT

Comment class is connected to delivered order and user account who comment.

  • Primary Key: COMMENT_ID

  • Non-relational Key

    • TITLE

    • DESCRIPTION

    • CREATED_AT( now )

    • SPEED ( 0=slow : 1=fast )

    • TASTE( 0=tasteful : 1=not tasteful )

  • Foreign Key(table_name)

    • ORDER_ID(ORDERS)

    • USER_ID(USERACCOUNT)

Database Functions

This method provides to comment the order.
1
2
3
4
5
6
7
def make_comment_to_order(comment):
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "insert into comment(title, description, speed, taste, user_id, order_id) values(%s, %s, %s, %s, %s, %s);"
      cursor.execute(query, comment)
      connection.commit()

This method get comments of the order in detail page of order
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def get_order_related_comments(key):
  orders = []
  with dbapi2.connect(DB_URL) as connection:
    with connection.cursor() as cursor:
      query = "select title, description, case speed when 0 then 'Slow' else 'Fast' end as speed, case taste when 0 then 'Not tasteful' else 'Tasteful' end as taste, CONCAT(p.name, ' ', p.surname) as person_name from comment as c full join useraccount as u on u.id = c.user_id full join person as p on p.id = u.person where order_id = %s;"
      cursor.execute(query, (key, ))
      desc = list( cursor.description[i][0] for i in range(0, len(cursor.description)) )
      for i in cursor:
        res = dict(zip(desc, list(i) ))
        orders.append( res )
  return orders

Forms

CommentForm is used in pages.

import section of comment_form
1
2
3
4
5
6
7
from flask_wtf import FlaskForm
from wtforms import SubmitField, FormField, StringField, TextAreaField, SelectField, ValidationError, FloatField, BooleanField
from wtforms.validators import DataRequired, NumberRange, Length
from wtforms_components import IntegerField

msgRequired = "The {} must be filled."
msgLength   = "The {} has to be between {} and {}"
Comment class for Form
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Comment(FlaskForm):
  title = StringField(
    "Title",
    validators = [ 
      DataRequired(message = msgRequired.format("Title")),
      Length(min=1, max=50, message = msgLength.format("Title", 1, 50))
    ],
    render_kw = { "class" : "form-control" }
  )
  
  description = TextAreaField(
    "Description", 
    validators = [ 
      DataRequired(message = msgRequired.format("Description")),
      Length(min=1, max=300, message = msgLength.format("Description", 1, 300))
    ],
    render_kw = { "class" : "form-control" }
  )
  #BooleanField = checkbox

  speed = BooleanField(
    "speed"
  )
  taste = BooleanField(
    "taste"
  )
CommentForm includes Comment class
1
2
3
class CommentForm(FlaskForm):
  comment = FormField(Comment)
  submit  = SubmitField( render_kw = { "class" : "btn btn-primary"})

Pages

Pages connected to forms, views and call database operations.

Comment to Order
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def comment_order_page(order_key):
  if session and session["logged_in"] == False:
    return redirect(url_for('signin_page'))
  else:

    comment = CommentForm()

    if comment.validate_on_submit():
      
      user_id     = session['userid']

      comment_info = (
        comment.comment["title"].data,
        comment.comment["description"].data,
        int(comment.comment["speed"].data),
        int(comment.comment["taste"].data),
        user_id,
        order_key
      )

      make_comment_to_order(comment_info)

      return redirect(url_for("order_details_page", order_key = order_key))
      
    return render_template(
      "/orders/comment.html",
      form = comment
    )

Views

Creating a comment page.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<div class="container">
  <h1 class="display-4">Make comment to <small class="text-muted font-italic">order</small></h1>
  <hr>
  <form method="post" action="{{ request.path }}" >
    {{ form.csrf_token }}
    
    {% for field, msg in form.errors.items() %}
      {% for i in msg: %}
        {% if msg[i] %}
          {% for k in msg[i] %}
          <div class="alert alert-warning" role="alert">
            <strong>{{ k }}</strong>
          </div>  
          {% endfor %}
        {% else %}
          <div class="alert alert-warning" role="alert">
            <strong>{{ msg[0] }}</strong>
          </div>  
        {% endif%}
      {% endfor %}
    {% endfor %}
    {{ form.comment( class_ = " table table-hover") }}
    <div class="text-center">
      {{ form.submit }}
      <a href="{{ url_for('home_page') }}" class="btn btn-secondary">Cancel</a>
    </div>
  </form>
</div>
util.py

https://exploreflask.com/en/latest/views.html#custom-converters