Skip to content

Commit

Permalink
Succesful refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Liam Bates committed Feb 28, 2019
1 parent 61026bc commit 900491e
Show file tree
Hide file tree
Showing 25 changed files with 125 additions and 102 deletions.
39 changes: 39 additions & 0 deletions auto_maint/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
""" Web app to save maintenance schedule of a users vehicle. """
import atexit
import os

from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask, session
from flask_migrate import Migrate
from flask_session import Session
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# DB Configs
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ['DATABASE_URL']
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

# Initiate DB
db = SQLAlchemy(app)

# Initiate session tracking type
app.config["SESSION_TYPE"] = "sqlalchemy"
mksess = Session(app)
mksess.app.session_interface.db.create_all()

migrate = Migrate(app, db)

# Set domain
app.config["SERVER_NAME"] = os.environ['SERVER_NAME']

from auto_maint.helpers import notify_users
import auto_maint.views

# Setup scheduler for to check if users need a notification every 10 minutes
if not app.debug or os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
scheduler = BackgroundScheduler()
scheduler.add_job(func=notify_users, trigger="interval", seconds=10)
scheduler.start()

atexit.register(lambda: scheduler.shutdown())
68 changes: 68 additions & 0 deletions auto_maint/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
""" Helpful functions used in the auto_maint app. """
import datetime
import os
import smtplib
from email.message import EmailMessage
from functools import wraps

from flask import redirect, render_template, session

from auto_maint import app
from auto_maint.models import User

def login_required(f):
"""
Decorate routes to require login.
http://flask.pocoo.org/docs/1.0/patterns/viewdecorators/
"""

@wraps(f)
def decorated_function(*args, **kwargs):
if session.get("user_id") is None:
return redirect("/")
return f(*args, **kwargs)

return decorated_function

def email(message):
""" Sends the provided email message using SMTP. """
# Send message to the email server.
server = smtplib.SMTP(os.environ['SMTP_SERVER'])
server.starttls()
server.login(os.environ['SMTP_LOGIN'], os.environ['SMTP_PASSWORD'])
server.send_message(message)
server.quit()

def notify_users():
""" Routine script to send email notifications when a vehicle is overdue
maintenance. """
# Context to access DB from function
with app.app_context():
print("NOTIFY USERS RUNNING")
for user in User.query.all():
for user_vehicle in user.vehicles:
status = user_vehicle.status()
if 'Soon' in status or 'Overdue' in status:
if user_vehicle.last_notification:
days_since = datetime.datetime.today(
) - user_vehicle.last_notification
if days_since < datetime.timedelta(days=3):
continue

# Generate Email message to send
msg = EmailMessage()
msg['Subject'] = 'Your vehicle is due maintenance'
msg['From'] = '[email protected]'
msg['To'] = user.email

# Generate HTML for email
html = render_template(
'email/reminder.html', vehicle=user_vehicle)
msg.set_content(html, subtype='html')

# Send email
email(msg)

# Update DB to with timestamp
user_vehicle.notification_sent()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 1 addition & 5 deletions models.py → auto_maint/models.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
""" auto_maint app models defined """
import datetime

from flask_sqlalchemy import SQLAlchemy
from auto_maint import db

db = SQLAlchemy()


# Define an object of a user within the context of the DB
class User(db.Model):
"""User of the website"""
__tablename__ = "users"
Expand Down
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
101 changes: 4 additions & 97 deletions app.py → auto_maint/views.py
Original file line number Diff line number Diff line change
@@ -1,104 +1,11 @@
"""Web app to save maintenance schedule of a users vehicle"""
import atexit
import datetime
import os
import smtplib
from email.message import EmailMessage
from functools import wraps

from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask, flash, redirect, render_template, request, session
from flask_migrate import Migrate
from flask_session import Session
from flask import flash, redirect, render_template, request, session
from werkzeug.security import check_password_hash, generate_password_hash

from models import Log, Maintenance, Odometer, User, Vehicle, db

app = Flask(__name__)

# Iniate DB / SQLAlchemy
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ['DATABASE_URL']
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)

# Initiate session tracking type
app.config["SESSION_TYPE"] = "sqlalchemy"
mksess = Session(app)
mksess.app.session_interface.db.create_all()

migrate = Migrate(app, db)

# Set domain
app.config["SERVER_NAME"] = os.environ['SERVER_NAME']


def notify_users():
""" Routine script to send email notifications when a vehicle is overdue
maintenance. """
# Context to access DB from function
with app.app_context():
print("NOTIFY USERS RUNNING")
for user in User.query.all():
for user_vehicle in user.vehicles:
status = user_vehicle.status()
if 'Soon' in status or 'Overdue' in status:
if user_vehicle.last_notification:
days_since = datetime.datetime.today(
) - user_vehicle.last_notification
if days_since < datetime.timedelta(days=3):
continue

# Generate Email message to send
msg = EmailMessage()
msg['Subject'] = 'Your vehicle is due maintenance'
msg['From'] = '[email protected]'
msg['To'] = user.email

# Generate HTML for email
html = render_template(
'email/reminder.html', vehicle=user_vehicle)
msg.set_content(html, subtype='html')

# Send email
email(msg)

# Update DB to with timestamp
user_vehicle.notification_sent()


def email(message):
""" Sends the provided email message using SMTP. """
# Send message to the email server.
server = smtplib.SMTP(os.environ['SMTP_SERVER'])
server.starttls()
server.login(os.environ['SMTP_LOGIN'], os.environ['SMTP_PASSWORD'])
server.send_message(message)
server.quit()


# Setup scheduler for to check if users need a notification every 10 minutes
if not app.debug or os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
scheduler = BackgroundScheduler()
scheduler.add_job(func=notify_users, trigger="interval", minutes=10)
scheduler.start()

atexit.register(lambda: scheduler.shutdown())


def login_required(f):
"""
Decorate routes to require login.
http://flask.pocoo.org/docs/1.0/patterns/viewdecorators/
"""

@wraps(f)
def decorated_function(*args, **kwargs):
if session.get("user_id") is None:
return redirect("/")
return f(*args, **kwargs)

return decorated_function
from auto_maint import app, db
from auto_maint.helpers import email, login_required
from auto_maint.models import Log, Maintenance, Odometer, User, Vehicle


@app.route('/', methods=['GET', 'POST'])
Expand Down
3 changes: 3 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Run a test server.
from auto_maint import app
app.run(host='0.0.0.0', port=8080, debug=True)
10 changes: 10 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from setuptools import setup

setup(
name='auto_maint',
packages=['auto_maint'],
include_package_data=True,
install_requires=[
'flask',
],
)

0 comments on commit 900491e

Please sign in to comment.