stc

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

commit f716544bfe79e1d49202dc869c8a220e60d61013
parent 16fb5b74838a12e590a214f057da5eba41e3c691
Author: Youth Employment Program Production <youthemployment22@gmail.com>
Date:   Tue,  9 Apr 2024 10:37:44 -0600

add updateProjectTime, fix display projects in index.dev.html, BUGFIX admin route missing project for agreement calculation, hoursd limit output in hours, aggregate project data

Diffstat:
Mapp/routes.py | 120++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mapp/templates/dashboard/punchclock/index.dev.html | 14++------------
2 files changed, 78 insertions(+), 56 deletions(-)

diff --git a/app/routes.py b/app/routes.py @@ -313,6 +313,28 @@ def dashboard(): return render_template('dashboard/layout.html',permissions=dashperms,clocked_out=clocked_out,clockoutform=clockoutform,clockinform=clockinform,fleetCheckedOut=fleetCheckedOut,crewform=crewform,vehicle_name=vehicle_name,fleetinform=fleetinform,fleetoutform=fleetoutform,clocked_in_users=clocked_in_users,ORGNAME=OrganizationName) +@app.route("/update/project/<mod_username>/<timeid>",methods=['GET','POST']) +@login_required +def updateProjectTime(mod_username,timeid): + timeid = ObjectId(timeid) + form = updateProject() + if form.validate_on_submit(): + app.logger.info('update project route') + try: + entry = mongo.db.time_collection.find_one({'_id':timeid}) + except: + flash("Issue finding/assigning time_id: {}".format(timeid)) + else: + try: + mongo.db.time_collection.update_one({'_id':timeid},{'$set':{'project':ObjectId(form.projectSel.data)}}) + except: + flash("unable to set project {}".format(ObjectId(form.projectSel.data))) + else: + flash("Updated project to {}".format(ObjectId(form.projectSel.data))) + finally: + return redirect(url_for('dashboard'))#change to hours and mod_username redirect + return render_template('dashboard/punchclock/update/project.html',form=form, ORGNAME=OrganizationName) + @app.route("/update/start/<mod_username>/<timeid>",methods=['GET','POST']) #TODO MAKE OTHER VALUE FOR LAST PAGE, RETURNS LAST PAGE ELSE DASHBOARD @login_required def updateStartTime(mod_username,timeid): @@ -662,11 +684,28 @@ def admin(): agreement['total_budget']=0 agreement['total_cost']=0 for i in range(len(agreement['projects'])): - agreement['projects'][i]= mongo.db.projects_collection.find_one({'_id': agreement['projects'][i]}) - agreement['projects'][i]['total_budget'] = sum(agreement['projects'][i]['budget'][0].values()) - agreement['projects'][i]['total_cost'] = sum(agreement['projects'][i]['costs'][0].values()) - agreement['total_budget']=agreement['total_budget']+agreement['projects'][i]['total_budget'] - agreement['total_cost']=agreement['total_cost']+agreement['projects'][i]['total_cost'] + try: + if mongo.db.projects_collection.find_one({'_id': agreement['projects'][i]}) is None: + flash("could not find project {} in agreement {}".format(agreement['projects'][i],agreement['_id'])) + return redirect(url_for('dashboard')) + else: + agreement['projects'][i]= mongo.db.projects_collection.find_one({'_id': agreement['projects'][i]}) + except: + flash("could not find project {} in agreement {}".format(agreement['projects'][i],agreement['_id'])) + return redirect(url_for('dashboard')) + else: + try: + if agreement['projects'][i]:#['budget'][0] + agreement['projects'][i]['total_budget'] = sum(agreement['projects'][i]['budget'][0].values()) + else: + agreement['projects'][i]['total_budget'] = 1 + except: + flash("could not assign agreement {} total budget") + agreement['projects'][i]['total_budget'] = 1 + finally: + agreement['projects'][i]['total_cost'] = sum(agreement['projects'][i]['costs'][0].values()) + agreement['total_budget']=agreement['total_budget']+agreement['projects'][i]['total_budget'] + agreement['total_cost']=agreement['total_cost']+agreement['projects'][i]['total_cost'] agreements.append(agreement) #all_permissions=mongo.db.permissions_collection.find_one({"label":current_user.role}) @@ -719,50 +758,43 @@ def hoursd(username):#userid goes into call to db to get user[] -> then returns for project in mongo.db.projects_collection.find(): #TODO TO RESOLVE BELOW ISSUE, JUST USE aggregator QUERY, WILL ALLOW SORTING AS WELL AS PROPER SUMMATION OF HOURS availableProjects.append((project['_id'],project['project_name']))#TODO FIND OUT WHY THIS RETURNS THE OBJECTID VALUE .str THROWS AttributeError: 'ObjectId' object has no attribute 'str' #'completed':{'$exists':False} - dbhours = mongo.db.time_collection.find({'modified_by.0':user['username']}) + aghours = mongo.db.time_collection.find({'modified_by.0':username}) + dbhours = mongo.db.time_collection.aggregate( [ + { + "$match":{'modified_by.0':username} + }, + { + '$lookup': { + 'from': 'projects_collection', + 'localField': 'project', + 'foreignField': '_id', + 'as': 'project' + } + }, + { + "$sort":{'clock_in':-1} + }, + { + "$limit":10 #change to ~ 30 days OR to prior 1st or 15th of month + } + + ] ) hours = [] deltas=[] - for hour in dbhours: # Currenty acts wrong with longer than 1 day - for x, y in availableProjects: - if x is ObjectId(hour['project']): - hour['projectName'] = y - if 'clock_out' not in hour: - hour['clock_out']=[datetime.datetime.now()] - time = hour['clock_out'][-1] - hour['clock_in'][-1] - hour['total_time'] = time - hours.append(hour) - deltas.append(time) +# for hour in dbhours: # Currenty acts wrong with longer than 1 day +# for x, y in availableProjects: +# if x is ObjectId(hour['project']): +# hour['projectName'] = y +# if 'clock_out' not in hour: +# hour['clock_out']=[datetime.datetime.now()] +# time = hour['clock_out'][-1] - hour['clock_in'][-1] +# hour['total_time'] = time +# hours.append(hour) +# deltas.append(time) - form = NewHoursForm() - form.dateSel.data = datetime.datetime.today() - form.projectSel.choices = availableProjects - form.startTime.data = datetime.datetime.now() total_hours = sum(deltas,datetime.timedelta()) statement_hours = "{} Hours, {} Minutes".format(total_hours.seconds//3600,(total_hours.seconds//60)%60) - if form.validate_on_submit(): # Possible bug iff user clocks in between page load and form submit... will create additional time_collection entry - indt = datetime.combine(form.dateSel.data,form.startTime.data) - outdt = datetime.combine(form.dateSel.data,form.endTime.data) - if user['username'] is current_user.username and not form.perDiemSel.data and not form.lunchSel.data: - mongo.db.time_collection.insert_one({'clock_in' : [indt], - 'modified_by' : [current_user.username], - 'date' : datetime.datetime.today(), - 'project' : ObjectId(form.projectSel.data), - 'clock_out':[outdt]}) - return redirect(url_for('hours',username=user['username'])) - - if user['username'] is not current_user.username and not form.perDiemSel.data and not form.lunchSel.data: - mongo.db.time_collection.insert_one({'clock_in' : [indt], - 'modified_by' : [user['username'], current_user.username], - 'date' : datetime.datetime.today(), - 'project' : ObjectId(form.projectSel.data), - 'clock_out':[outdt]}) - - return redirect(url_for('hours',username=user['username'])) - - #hours = mongo.db.time_collection.find({'modified_by.0':user.username}) - - tspp = mongo.db.time_collection.aggregate( [ { "$lookup":{ @@ -791,7 +823,7 @@ def hoursd(username):#userid goes into call to db to get user[] -> then returns ] )# Time Spent Per Project (filter entries by username, then group and sum hours by project) - return render_template ('dashboard/punchclock/index.dev.html',form=form,hours=hours,availableProjects=availableProjects,total_hours=total_hours,statement_hours=statement_hours,user=user,tspp=tspp,ORGNAME=OrganizationName) + return render_template ('dashboard/punchclock/index.dev.html',hours=dbhours,availableProjects=availableProjects,total_hours=total_hours,statement_hours=statement_hours,tspp=tspp,ORGNAME=OrganizationName) diff --git a/app/templates/dashboard/punchclock/index.dev.html b/app/templates/dashboard/punchclock/index.dev.html @@ -4,22 +4,12 @@ {% block content %} <section class="hours-grid"> - <h3>{{ user.fname }} {{ user.lname }}</h3><!-- IF logged in user has permission allow this username section to be a dropdown for modifying user time sheets. --> <h1 id="clock"></h1> <div><!-- abstract to payPeriod() --> <h6>$payperiod range</h6> <!--<h5>Total:{# {{ statement_hours }} #}</h5> --> {{availableProjects}} </div> - <a href="{{url_for('new_time',usernm=user.username)}}" style=" border: none; - background: var(--accent); - cursor: pointer; - border-radius: 3px; - padding: 6px; - width: 200px; - color: white; - margin-left: 25px; - box-shadow: 0 3px 6px 0 rgba(0,0,0,0.2);">New Time</a> <form action="" method="POST" novalidate> <table><tr> {% for field in form %}{% if field.widget.input_type != 'hidden' and field.widget.input_type != 'submit' %} @@ -39,7 +29,7 @@ {% for entry in hours %} <tr> <td><a href="{{url_for('updateDate',mod_username=current_user.username,timeid=entry._id)}}">{{ entry.date.date().isoformat() }}</a></td> - <td>{{ entry.projectName }}</td> + <td><a href="{{url_for('updateProjectTime',mod_username=current_user.username,timeid=entry._id)}}">{{ entry.project[0]['project_name'] }}</a></td> <td><a href="{{url_for('updateStartTime',mod_username=current_user.username,timeid=entry._id)}}">{{ entry.clock_in[-1].time().isoformat(timespec='minutes') }}</a></td> <td><a href="{{url_for('updateEndTime',mod_username=current_user.username,timeid=entry._id)}}">{{ entry.clock_out[-1].time().isoformat(timespec='minutes') }}</a></td> {% if entry.lunch %} @@ -60,7 +50,7 @@ <td><a href="{{url_for( 'removetime',timeid=entry._id) }}" class="action-button">Remove</a></td> {#{{ form.hidden_tag() }}#} </tr> - {# {{entry}} #} + {{entry}} {% endfor %} </table> </form>