stc

a simple time card webapp
git clone _git@git.brennen.work:stc.git
Log | Files | Refs | README

commit 9c9766c429b18838d0f3b2b1d0e1be83d020f310
parent ec2093fcfa57206a7e0239f23f9c7a792d1bdea6
Author: Brennen T. Mazur <brennen@madis.cool>
Date:   Thu, 23 Mar 2023 10:58:39 -0600

completed funcionality of Crew Clockin list

Diffstat:
Mapp/routes.py | 32+++++++++++++++++++++++++++-----
Mapp/templates/dashboard/activeusers/widget.html | 42++++++++++++++++++------------------------
Mrequirements.txt | 12++++++++++++
Mseeds.py | 73+++++++++++++++++++++++++++++++++++++++++++++----------------------------
4 files changed, 102 insertions(+), 57 deletions(-)

diff --git a/app/routes.py b/app/routes.py @@ -10,6 +10,7 @@ from werkzeug.urls import url_parse from werkzeug.security import generate_password_hash, check_password_hash from flask_login import current_user, login_user, logout_user, login_required from app.models import User, Time, Fleet, Agreement, Projects +from bson.objectid import ObjectId #from .config import EXEMPT_METHODS import functools @@ -144,8 +145,8 @@ def load_user(username): #### #### @app.route('/index') -def hello(): - return redirect(url_for('dashboard')) +#def hello(): +# return redirect(url_for('dashboard')) @app.route("/dashboard", methods=['GET', 'POST']) @login_required def dashboard(): @@ -209,6 +210,10 @@ def dashboard(): # Temp values, change to db dependent values availableVehicles = ['Vehicle 1', 'Vehicle 2', 'Vehicle 3', 'Vehicle 4'] + #availableVehicles = [] + #TODO this needs to be properly coded out + #for vehicle in mongo.db.fleet_collection.find_one('available_vehicles'): + # availableVehicles.append((vehicle['_id'],vehicle['name'])) currentProject = 'Project 2' lastMileage = 103483 #currently gets ALL projects TODO make filter by available agreements/projects @@ -223,12 +228,10 @@ def dashboard(): fleetinform=FleetCheckinForm() clockinform.projectsSel.choices = availableProjects - clockinform.projectsSel.default = currentProject clockoutform.projectsSel.choices = availableProjects - clockoutform.projectsSel.default = currentProject fleetoutform.vehicle.choices = availableVehicles fleetoutform.vehicle.default = availableVehicles[0] - fleetoutform.start_mileage.default = lastMileage + fleetoutform.start_mileage.data = 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__ @@ -263,6 +266,25 @@ def dashboard(): 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) +#TODO +@app.route("/clockoutuser/<modusernm>/<timeid>", methods=['GET','POST']) +def clockout_by_id(modusernm,timeid): + # if modified_by.last != modusernm: modified_by.append(modusernm) + + timeid = ObjectId(timeid) + + def clock_otheruser_out(time_id,mod_username): + if mongo.db.time_collection.find({'_id': time_id}, {'clock_out':{'$exists':False}}): + mongo.db.time_collection.update_one({'_id':time_id},{'$set':{'clock_out':datetime.datetime.utcnow()}}) + mongo.db.time_collection.update_one({'_id':time_id},{'$push':{'modified_by':mod_username}}) + flash('Clocked out') + return redirect(url_for('dashboard')) + else: + flash('No time entry found, or user has checked out already') + + clock_otheruser_out(timeid,modusernm) + + return redirect(url_for('dashboard')) #### #### ####### Admin Route ####### diff --git a/app/templates/dashboard/activeusers/widget.html b/app/templates/dashboard/activeusers/widget.html @@ -1,37 +1,31 @@ <section class="activeusers"> <h3>Clocked in Crew List</h3> + {# {% for user in clocked_in_users %} {%- print(user.modified_by.0) %} {% endfor %} + #} <form> - <input type="submit" value="Clock Crew Out"> + <!-- <input type="submit" value="Clock Crew Out"> --> <table><!-- replace w/ function getUserHours(username) --> - <tr><!-- FOR EACH clocked in user iterate user ...does each user need to be its own form? --> - <td><input type="button" onclick="alert('route to /changehours<user1>')" value="user1.name"></td> - <td><input type="checkbox" name="onCrew" checked><label for="onCrew">On Crew</label></td> + {% for user in clocked_in_users %} + <tr> + <td><button><a href="{{ url_for('hours',username=user.modified_by.0) }}">{{ user.modified_by.0 }}</a></button></td> <td><input type="checkbox" name="lunch"><label for="lunch">Lunch</label></td> <td><input type="checkbox" name="per_diem"><label for="per_diem">Per Diem</label></td> - <td><input type="button" onclick="alert('route to /changehours<user1>')" value="user1.timeIn"></td> - <td><input type="submit" value="Clock Out"></td> - </tr> - <tr><!-- FOR EACH clocked in user iterate user ...does each user need to be its own form? --> - <td><input type="button" onclick="alert('route to /changehours<user2>')" value="user2.name"></td> - <td><input type="checkbox" name="onCrew" checked><label for="onCrew">On Crew</label></td> - <td><input type="checkbox" name="lunch"><label for="lunch">Lunch</label></td> - <td><input type="checkbox" name="per_diem"><label for="per_diem">Per Diem</label></td> - <td><input type="button" onclick="alert('route to /changehours<user2>')" value="user2.timeIn"></td> - <td><input type="submit" value="Clock Out"></td> + <td><button><a href="{{ url_for('hours',username=user.modified_by.0) }}">{{ user.clock_in.0.time().isoformat(timespec='minutes') }}</a></button></td><!-- can format/display non-military time with format %I:%M%p --> + <td><button><a href="{{ url_for('clockout_by_id',modusernm=current_user.username,timeid=user._id) }}">Clock Out</a></button></td> </tr> + {% endfor %} + </table> </form> - <form> - <tr><!-- clock in clocked out user --> - <th><select><option value="user3.name" selected>user3.name</option><option value="user4.name">user4.name</option><option value="user5.name">user5.name</option></select></th> - <td><input type="checkbox" name="onCrew" checked><label for="onCrew">On Crew</label></td> - <td><input type="checkbox" name="lunch"><label for="lunch">Lunch</label></td> - <td><input type="checkbox" name="per_diem"><label for="per_diem">Per Diem</label></td> - <td><input type="time" value="12:12"/></td> - <td><input type="submit" value="Clock in New Member"></td> - </tr> + <form> + <table> + <tr><!-- clock in clocked out user --> + <th><select><option value="user3.name" selected>user3.name</option><option value="user4.name">user4.name</option><option value="user5.name">user5.name</option></select></th> + <td><input type="time" value="12:12"/></td> + <td><input type="submit" value="Clock in"></td> + </tr> </table> - </form> + </form> </section> diff --git a/requirements.txt b/requirements.txt @@ -1,11 +1,23 @@ +anyio==3.6.2 bcrypt==4.0.1 click==8.1.3 dnspython==2.2.1 +fastapi==0.89.1 Flask==2.2.2 Flask-Bcrypt==1.0.1 Flask-Login==0.6.2 +Flask-PyMongo==2.3.0 +Flask-WTF==1.1.1 +idna==3.4 +importlib-metadata==5.1.0 itsdangerous==2.1.2 Jinja2==3.1.2 MarkupSafe==2.1.1 +pydantic==1.10.4 pymongo==4.3.3 +sniffio==1.3.0 +starlette==0.22.0 +typing-extensions==4.4.0 Werkzeug==2.2.2 +WTForms==3.0.1 +zipp==3.11.0 diff --git a/seeds.py b/seeds.py @@ -64,6 +64,23 @@ user2 = { 'is_active':True } +user3 = { + 'fname': 'Hiccup', + 'mname': 'C', + 'lname': 'Mazur', + 'username': 'hiccupcmazur', + 'birthday': '2022-09-14', + 'password_hash': 'pbkdf2:sha256:260000$ukazhSEG3m9xH2oL$5cc00ff3411f614720287c18f615d71578face70abc990ea5def89f520b0ac2c', + 'role': 'Crew', + 'branch': 'Dillon', + 'phonenumber': 3074380491, + 'address': '705 N Railroad Ave, Dillon MT, 59725', + 'email': 'hiccup.mazur@fake.com', + 'pay_period': 'salaried', + 'pay_value': 43000, + 'is_active':True + } + # Time documents time1 = { 'clock_in': datetime.datetime.utcnow(), #System time Clock_out should be optional, but can clock_in? @@ -150,11 +167,11 @@ agreement2 = { 'end_date': '2022-12-13', #'bid_document': '/asset/document/agreements/Old-Agreement.pdf', #Filepath to document 'budget': [{ - 'labor':1259.40, + 'labor':259.40, 'travel':220.00, 'supplies':320.00, - 'contact':420.00, - 'equipment':620.00, + 'contact':420.69, + 'equipment':20.00, 'other':20.00 }], 'costs': [{ @@ -173,12 +190,12 @@ projects1 = { 'project_name': 'Project 1', 'agreement': 2, 'budget': [{ - 'labor':1259.40, - 'travel':220.00, - 'supplies':320.00, - 'contact':420.00, - 'equipment':620.00, - 'other':20.00 + 'labor':159.40, + 'travel':420.00, + 'supplies':20.00, + 'contact':40.00, + 'equipment':60.00, + 'other':2.00 }], 'costs': [{ 'labor':159.40, @@ -203,12 +220,12 @@ projects2 = { 'project_name': 'Project 2', 'agreement': 1, 'budget': [{ - 'labor':1259.40, - 'travel':220.00, - 'supplies':320.00, - 'contact':420.00, - 'equipment':620.00, - 'other':20.00 + 'labor':159.40, + 'travel':820.00, + 'supplies':1120.00, + 'contact':42.00, + 'equipment':75.00, + 'other':12.00 }], 'costs': [{ 'labor':159.40, @@ -233,12 +250,12 @@ projects3 = { 'project_name': 'Project 3', 'agreement': 1, 'budget': [{ - 'labor':1259.40, - 'travel':220.00, - 'supplies':320.00, - 'contact':420.00, - 'equipment':620.00, - 'other':20.00 + 'labor':459.40, + 'travel':510.00, + 'supplies':80.00, + 'contact':94.20, + 'equipment':9.00, + 'other':27.00 }], 'costs': [{ 'labor':159.40, @@ -262,12 +279,12 @@ projects4 = { '_id':4, 'agreement': 1, 'budget': [{ - 'labor':1259.40, - 'travel':220.00, - 'supplies':320.00, - 'contact':420.00, - 'equipment':620.00, - 'other':20.00 + 'labor':258.40, + 'travel':71.00, + 'supplies':20.00, + 'contact':4.00, + 'equipment':66.00, + 'other':59.00 }], 'costs': [{ 'labor':159.40, @@ -366,7 +383,7 @@ accountant = { # Insert documents -user_collection.insert_many([user1, user2]) +user_collection.insert_many([user1, user2, user3]) time_collection.insert_many([time1, time2,time3]) fleet_collection.insert_many([fleet1, fleet2]) agreements_collection.insert_many([agreement1, agreement2])