commit 53c5990a822636e6d7534df8dc949c9bd537dffd
parent 6f27d065358383c7566605492a8c14010520d222
Author: Brennen T. Mazur <brennen@madis.cool>
Date: Fri, 10 Mar 2023 23:42:08 -0700
completed fleet checkin checkout logic
Diffstat:
4 files changed, 160 insertions(+), 39 deletions(-)
diff --git a/app/forms.py b/app/forms.py
@@ -60,7 +60,7 @@ class AdmnPermissionsForm(FlaskForm):# for each module make Boolean field. Gets
class FleetCheckoutForm(FlaskForm):
vehicle = SelectField('Vehicle', validators = [DataRequired()])
- start_milage = IntegerField('Starting Milage', validators=[DataRequired()])# Require some sort of validator for check...
+ start_mileage = IntegerField('Starting Mileage', validators=[DataRequired()])# Require some sort of validator for check...
horn = BooleanField('Horn')
signals = BooleanField('Signals')
tires = BooleanField('Tires')
@@ -76,6 +76,6 @@ class FleetCheckoutForm(FlaskForm):
checkout = SubmitField('Checkout Vehicle')#Update to take role name for pass to write fn
class FleetCheckinForm(FlaskForm):
- endmilage = IntegerField('Ending Milage',validators=[DataRequired()])# Require some sort of validator for check...
- additionalnotes = StringField('Additional Notes',validators=[optional()])# May not need this at all?
+ end_mileage = IntegerField('Ending Mileage',validators=[DataRequired()])# Require some sort of validator for check...
+ incident_notes = StringField('Incident Notes',validators=[optional()])# May not need this at all?
checkin = SubmitField('Checkin Vehicle')#Update to take role name for pass to write fn
diff --git a/app/routes.py b/app/routes.py
@@ -15,12 +15,17 @@ import functools
OrganizationName = 'Youth Employment Program' # Maybe pass this as a value though the object for relevant pages???
+#### ####
+####### Application Modules Init #######
+#### ####
# DB Connection & LoginManager init
mongo = PyMongo(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
-# User Routes / Queries
+#### ####
+####### User Routes/Queries #######
+#### ####
@app.route('/user/signup', methods=['GET'])
def signup():
return User().signup()
@@ -32,9 +37,10 @@ def loginModel():
@app.route('/user/signout')
def signout():
return User().signout()
-# User Routes / Queries
-# Time Routes / Queries
+#### ####
+####### Time Routes/Queries #######
+#### ####
@app.route('/time/clockin', methods=['GET', 'POST'])
def clockin():
return Time().clockin()
@@ -42,23 +48,25 @@ def clockin():
@app.route('/time/clockout', methods=['GET', 'POST'])
def clockout():
return Time().clockout()
-# Time Routes / Queries
-# Fleet Routes / Queries
-@app.route('/fleet/vehicle_repair', methods=['GET', 'POST', 'PUT'])
+#### ####
+####### Vehicle Routes/Queries #######
+#### ####
+@app.route('/fleet/vehicle_repair', methods=['GET', 'POST'])
def vehicle_repair():
return Fleet().vehicle_repair()
-# Fleet Routes / Queries
-# Agreement Routes / Queries
+#### ####
+####### Agreement Routes/Queries #######
+#### ####
@app.route('/agreement/document', methods=['GET', 'POST'])
def document():
return Agreement().document()
-# Agreement Routes / Queries
-# Projects Routes / Queries
+#### ####
+####### Project Routes/Queries #######
+#### ####
@app.route('/projects/project', methods=['GET', 'POST', 'PUT'])
-# Projects Routes / Queries
##{{{{{{{{{{{{{{{{{{{{{ Decorator Functions }}}}}}}}}}}}}}}}}}}}}##
#@login_required
@@ -77,13 +85,24 @@ def document():
# return decorated_view
##{{{{{{{{{{{{{{{{{{{{{ END Decorator Functions }}}}}}}}}}}}}}}}}}}}}##
-# Page Routes
+#================================#
+########### ############
+#### PAGE ROUTING ####
+########### ############
+#================================#
+
+#### ####
+####### Logout User Route #######
+#### ####
@app.route("/logout", methods=['GET'])
def logout():
logout_user()
return redirect(url_for('login'))
+#### ####
+####### Login/Root Route #######
+#### ####
@app.route('/')
@app.route("/login", methods=['GET', 'POST'])
def login():
@@ -107,6 +126,9 @@ def login():
return redirect(url_for('login'))
return render_template('login.html',form=form,ORGNAME = OrganizationName)
+#### ####
+####### Load User Data #######
+#### ####
#load user_data into User object iff username == stored username
@login_manager.user_loader
def load_user(username):
@@ -117,15 +139,22 @@ def load_user(username):
user_obj.password_hash = u['password_hash']
return user_obj
+#### ####
+####### Dashboard Route #######
+#### ####
+
@app.route('/index')
def hello():
return redirect(url_for('dashboard'))
@app.route("/dashboard", methods=['GET', 'POST'])
@login_required
def dashboard():
-
- if datetime.datetime.date == current_user.birthday:
- flash("Happy Birthday {}!").format(current_user.fname)
+
+ currentdate = datetime.datetime.now()
+ #Banner, TODO create a MOTD framework, for admin messages
+ if currentdate.strftime('%Y-%m-%d') == current_user.birthday:
+ flash("Happy Birthday {}!".format(current_user.fname))
+ ## END Banner
dashperms=mongo.db.permissions_collection.find_one({'label': current_user.role},{'dashboard':1,'_id':0})
dashperms=dashperms['dashboard']
@@ -152,12 +181,37 @@ def dashboard():
else:
clocked_out = True
#End isUserClockedIn()
+ #Start fleetCheckedOut()
+ if mongo.db.fleet_collection.find_one({'operator': current_user.username,'end_mileage':{'$exists':False}}):
+ fleetCheckedOut = True
+ fleet_id = mongo.db.fleet_collection.find_one({'operator': current_user.username,'end_mileage':{'$exists':False}})["_id"]
+ vehicle_name = mongo.db.fleet_collection.find_one({'operator': current_user.username,'end_mileage':{'$exists':False}})["vehicle"]
+ start_mileage = mongo.db.fleet_collection.find_one({'operator': current_user.username,'end_mileage':{'$exists':False}})["start_mileage"]
+ else:
+ fleetCheckedOut = False
+ vehicle_name = ''
+ #End fleetCheckedOut()
+ def fleet_check_in(fleet_id,start_mileage,end_mileage,notes=''):
+ if mongo.db.fleet_collection.find({'_id': fleet_id}, {'end_mileage':{'$exists':False}}):
+ if end_mileage <= start_mileage:
+ flash('end mileage less than starting mileage')
+ elif notes is not '' and end_mileage >= start_mileage:
+ mongo.db.fleet_collection.update_one({'_id':fleet_id},{'$set':{'end_mileage':end_mileage,'incident_notes':{notes:False}}})#incident_note dict isResolved and string value to display on admin page
+ elif notes == '' and end_mileage >= start_mileage:
+ mongo.db.fleet_collection.update_one({'_id':fleet_id},{'$set':{'end_mileage':end_mileage}})
+ else:
+ flash('uncaught logic updating {} with {}'.format(fleet_id,end_mileage))
+ mongo.db.fleet_collection.update_one({'_id':fleet_id},{'$set':{'end_mileage':end_mileage}})
+ return redirect(url_for('dashboard'))
+ else:
+ flash('Unable to check out vehicle')
+ return redirect(url_for('dashboard'))
# Temp values, change to db dependent values
availableProjects = ['Project 1', 'Project 2', 'Project 3']
availableVehicles = ['Vehicle 1', 'Vehicle 2', 'Vehicle 3', 'Vehicle 4']
currentProject = 'Project 2'
- lastMilage = 103483
+ lastMileage = 103483
# END default form values
clockinform=PunchclockinWidget()
@@ -171,25 +225,20 @@ def dashboard():
clockoutform.projectsSel.default = currentProject
fleetoutform.vehicle.choices = availableVehicles
fleetoutform.vehicle.default = availableVehicles[0]
- fleetoutform.start_milage.default = lastMilage
+ fleetoutform.start_mileage.default = lastMileage
# Currently broken... appears to call constructor(wanted for setting default values) but regenerates csrf_token... clone fn without this call? or overload fn? Haven't looked at documentation yet
+# See: https://wtforms.readthedocs.io/en/3.0.x/forms/#wtforms.form.BaseForm.__init__
#clockinform.process()
#clockoutform.process()
#fleetoutform.process()
- #if clockoutform.validate_on_submit():
- #if request.method == 'POST' and clockoutform.validate():
- # mongo.db.time_collection.insert({'clock_out' : [datetime.datetime.utcnow()],
- # 'lunch' : clockoutform.lunchBox.data,
- # 'per_diem' : clockoutform.per_diemBox.data})
- # return redirect(url_for('dashboard'))
-
- #if clockinform.validate_on_submit(): Currently will submit all present forms...
+ #if clockinform.validate_on_submit(): Currently will submit all present forms... replaced w/ below
if not clocked_out and request.method == 'POST' and clockoutform.validate():
clock_user_out(time_id,clockoutform.lunchBox.data,clockoutform.per_diemBox.data)
return redirect(url_for('dashboard'))
+# Can still clock in without checking current vehicle status!!! TODO FIX ME !!!
if clocked_out and request.method == 'POST' and clockinform.validate():
mongo.db.time_collection.insert_one({'clock_in' : [datetime.datetime.utcnow()],
'modified_by' : [current_user.username],
@@ -198,15 +247,23 @@ def dashboard():
return redirect(url_for('dashboard'))
#if fleetoutform.validate_on_submit():
- if request.method == 'POST' and fleetoutform.validate():
+ if not fleetCheckedOut and request.method == 'POST' and fleetoutform.validate():
mongo.db.fleet_collection.insert_one({'date':datetime.datetime.today(), # NEED to work on modular way of storing safety checks... might condence to single true if all checked. else returns false and records false datavalue.label in incident_report[] If incident report, remove vehicle from available pool and display widget in admin layout
'vehicle':fleetoutform.vehicle.data,
- 'start_milage':fleetoutform.start_milage.data,
+ 'start_mileage':fleetoutform.start_mileage.data,
'operator':current_user.username,
'additional_notes':fleetoutform.additionalnotes.data})
return redirect(url_for('dashboard'))
- return render_template('dashboard/layout.html',permissions=dashperms,clocked_out=clocked_out,clockoutform=clockoutform,clockinform=clockinform,fleetinform=fleetinform,fleetoutform=fleetoutform,clocked_in_users=clocked_in_users,ORGNAME=OrganizationName)
+ if fleetCheckedOut and request.method == 'POST' and fleetinform.validate():
+ fleet_check_in(fleet_id,start_mileage,fleetinform.end_mileage.data,fleetinform.incident_notes.data)
+ return redirect(url_for('dashboard'))
+
+ return render_template('dashboard/layout.html',permissions=dashperms,clocked_out=clocked_out,clockoutform=clockoutform,clockinform=clockinform,fleetCheckedOut=fleetCheckedOut,vehicle_name=vehicle_name,fleetinform=fleetinform,fleetoutform=fleetoutform,clocked_in_users=clocked_in_users,ORGNAME=OrganizationName)
+
+#### ####
+####### Admin Route #######
+#### ####
@app.route("/admin")
#@admin_required
def admin():
@@ -217,28 +274,43 @@ def admin():
#admnperms=all_permissions.admin
return render_template ('admin/layout.html',permissions=adminperms,ORGNAME=OrganizationName)
+#### ####
+####### Agreement Report Route #######
+#### ####
# Report Routes
@app.route('/admin/agreement')
@login_required
def agreement_report():
return render_template ('admin/reports/agreement_report.html', ORGNAME=OrganizationName)
+#### ####
+####### Employee Report Route #######
+#### ####
@app.route('/admin/employee')
@login_required
def employee_report():
return render_template ('admin/reports/employee_report.html', ORGNAME=OrganizationName)
+#### ####
+####### Pay Period Report Route #######
+#### ####
@app.route('/admin/pay-period')
@login_required
def pay_period_report():
return render_template ('admin/reports/pay_period_report.html', ORGNAME=OrganizationName)
+#### ####
+####### Vehicle Report Route #######
+#### ####
@app.route('/admin/vehicle')
@login_required
def vehicle_report():
return render_template ('admin/reports/vehicle_report.html', ORGNAME=OrganizationName)
+#### ####
+####### Hours Route #######
+#### ####
@app.route('/hours/<username>')#modify to take userid ex. /hours<userid> for "admin" currently pulls from current_user... simply always pass username to hours(if possible set a default to current_user)
@login_required
def hours(username):#userid goes into call to db to get user[] -> then returns formatted table (punchclock/index.html
@@ -253,6 +325,9 @@ def hours(username):#userid goes into call to db to get user[] -> then returns f
#def fleet():
# return render_template('dashboard/fleet/index.html',ORGNAME=OrganizationName)
+#### ####
+####### Roles Admin Route #######
+#### ####
@app.route("/admin/roles")
@login_required
def roles():
@@ -260,18 +335,27 @@ def roles():
dashform = DashPermissionsForm()
return render_template('admin/roles/updateroles.html',dashform=dashform,admnform=admnform,ORGNAME=OrganizationName)
+#### ####
+####### Active Users Admin Route #######
+#### ####
@app.route("/admin/users/active")
@login_required
def activeusers():
active = mongo.db.user_collection.find({'is_active':True})
return render_template('admin/users/active.html',activeusers=active,ORGNAME=OrganizationName)
+#### ####
+####### Inactive Users Admin Route #######
+#### ####
@app.route("/admin/users/inactive")
@login_required
def inactiveusers():
inactive = mongo.db.user_collection.find({'is_active':False})
return render_template('admin/users/inactive.html',inactiveusers=inactive,ORGNAME=OrganizationName)
+#### ####
+####### New User Admin Route #######
+#### ####
@app.route("/admin/newuser", methods=["GET","POST"])
@login_required
def newuser():
@@ -318,44 +402,70 @@ def newuser():
return render_template('admin/users/newuser.html',form=form,ORGNAME=OrganizationName)
+#### ####
+####### Agreement Admin Route #######
+#### ####
@app.route("/admin/agreement")
@login_required
def agreement():
return render_template('admin/agreement/index.html',ORGNAME=OrganizationName)
+#### ####
+####### Knowlegebase Route #######
+#### ####
@app.route("/docs")
@login_required
def knowlegebase():
return render_template('knowlegebase/index.html',ORGNAME=OrganizationName)
-# Page Routes
+
+#====================================#
+############# ##############
+#### DEVELOPMENT ROUTES ####
+############# ##############
+#====================================#
# DEVELOPMENT ROUTES, remove/modify permissions before production
+#### ####
+####### Fleet Data Route #######
+#### ####
@app.route("/dev/fleetdata")
@login_required
def fleetdatalist():
allfleetdata = mongo.db.fleet_collection.find()
return render_template('dev/fleetdata.html', allfleetdata=allfleetdata)
+#### ####
+####### User Data Route #######
+#### ####
@app.route("/dev/usrs")
@login_required
def userslist():
allusers = mongo.db.user_collection.find()
return render_template('dev/usrs.html', allusers=allusers)
+#### ####
+####### Time Data Route #######
+#### ####
@app.route("/dev/timedata", methods=['GET'])
@login_required
def timedata():
alltimedata = mongo.db.time_collection.find()
return render_template('dev/timedata.html', alltimedata=alltimedata)
+#### ####
+####### Agreement Data Route #######
+#### ####
@app.route("/dev/agreementdata", methods=['GET'])
@login_required
def agreementdata():
allagreementdata = mongo.db.agreement_collection.find()
return render_template('dev/agreementdata.html', allagreementdata=allagreementdata)
+#### ####
+####### Project Data Route #######
+#### ####
@app.route("/dev/projectdata", methods=['GET'])
@login_required
def projectdata():
diff --git a/app/templates/dashboard/fleet/widget.html b/app/templates/dashboard/fleet/widget.html
@@ -1,14 +1,23 @@
<section class="fleet">
<h3>Fleet</h3>
<form class="widget-form" action="" method="POST" novalidate>
- {{ fleetoutform.hidden_tag() }}
- {% for error in fleetoutform.errors %}
+ {% for error in fleetoutform.errors or fleetinform.errors %}
<span style="color:red;">[{{ error }}]</span>
- {% endfor %}
+ {% endfor %}
+ {% if not fleetCheckedOut %}
+ {{ fleetoutform.hidden_tag() }}
<div class="safetychecks">
{% for field in fleetoutform %}
{{ field }}{% if field.widget.input_type != 'submit' and field.widget.input_type != 'hidden' %}{{ field.label }}{% endif %}<br>
{% endfor %}
</div>
+ {% elif fleetCheckedOut %}
+ {{ fleetinform.hidden_tag() }}
+ <h5> You have {{ vehicle_name }} checked out</h5>
+ {% for field in fleetinform %}
+ {{ field }}{% if field.widget.input_type != 'submit' and field.widget.input_type != 'hidden' %}{{ field.label }}{% endif %}<br>
+ {% endfor %}
+ </div>
+ {% endif %}
</form>
</section>
diff --git a/seeds.py b/seeds.py
@@ -97,21 +97,23 @@ time3 = {
fleet1 = {
'date': datetime.datetime.today(),
'operator': 'brennentmazur', #forign key to userID
+ 'start_mileage': 33,
+ 'end_mileage': 33,
'safety_checks': [True,True,True,True,True],#array for different safety checks
'additional_notes': 'Oil needs checked',
'vehicle': 'The Big Truck', #vehicleID
- 'incident_report': '',
- 'mileage': 33,
+ 'incident_report': ''
}
fleet2 = {
'date': datetime.datetime.today(),
'operator': 'nikolasmmazur', #forign key to userID
+ 'start_mileage': 33,
+ 'end_mileage': 33,
# 'safety_checks': True, #array for different safety checks
'additional_notes': 'Tires need replaced',
'vehicle': 'The Small Truck', #vehicleID
- 'incident_report': 'I dunno what goes in incident reports.',
- 'mileage': 90,
+ 'incident_report': 'I dunno what goes in incident reports.'
}
# Agreement documents