stc

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

commit ec2093fcfa57206a7e0239f23f9c7a792d1bdea6
parent 370684c8927dc4e4c8fc167a57786eac7259554a
Author: Brennen T. Mazur <brennen@madis.cool>
Date:   Mon, 20 Mar 2023 01:46:26 -0600

Add new project page, form, seeds, and styles. Updated agreements widget to display proper progress per agreement and associated projects

Diffstat:
Mapp/forms.py | 1+
Mapp/routes.py | 65++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mapp/static/css/main.css | 2+-
Aapp/templates/admin/agreements/projects/newproject.html | 35+++++++++++++++++++++++++++++++++++
Mapp/templates/admin/agreements/widget.html | 33++++++++++++++++++++++-----------
Mseeds.py | 122++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
6 files changed, 227 insertions(+), 31 deletions(-)

diff --git a/app/forms.py b/app/forms.py @@ -48,6 +48,7 @@ class NewRoleForm(FlaskForm): class NewProjectForm(BudgetForm): projectName = StringField('Project Name', validators=[DataRequired()]) agreement = SelectField('Part of Agreement', validators=[DataRequired()]) + createNewProject = SubmitField('Create New Project') class NewAgreementForm(BudgetForm): agreementName = StringField('Agreement Name', validators=[DataRequired()]) diff --git a/app/routes.py b/app/routes.py @@ -4,7 +4,7 @@ from app import app from flask_pymongo import PyMongo from flask_login import LoginManager from flask import render_template, url_for, request, flash, redirect -from app.forms import LoginForm, PunchclockinWidget, PunchclockoutWidget, FleetCheckoutForm, FleetCheckinForm, NewUserForm, AdmnPermissionsForm, DashPermissionsForm, ChangeHoursForm, NewAgreementForm +from app.forms import LoginForm, PunchclockinWidget, PunchclockoutWidget, FleetCheckoutForm, FleetCheckinForm, NewUserForm, AdmnPermissionsForm, DashPermissionsForm, ChangeHoursForm, NewAgreementForm, NewProjectForm from flask import request from werkzeug.urls import url_parse from werkzeug.security import generate_password_hash, check_password_hash @@ -208,10 +208,13 @@ def dashboard(): 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' lastMileage = 103483 +#currently gets ALL projects TODO make filter by available agreements/projects + availableProjects = [] + for project in mongo.db.projects_collection.find(): + availableProjects.append((project['_id'],project['project_name'])) # END default form values clockinform=PunchclockinWidget() @@ -269,10 +272,23 @@ def dashboard(): def admin(): adminperms=mongo.db.permissions_collection.find_one({'label': current_user.role},{'admin':1,'_id':0}) adminperms=adminperms['admin'] + #AgreementsData + allagreements=mongo.db.agreements_collection.find()#All agreements, including outside endDate... filter to active agreements? + agreements = [] + for agreement in allagreements: + 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'] + agreements.append(agreement) #all_permissions=mongo.db.permissions_collection.find_one({"label":current_user.role}) #admnperms=all_permissions.admin - return render_template ('admin/layout.html',permissions=adminperms,ORGNAME=OrganizationName) + return render_template ('admin/layout.html',agreements=agreements,permissions=adminperms,ORGNAME=OrganizationName) #### #### ####### Agreement Report Route ####### @@ -426,7 +442,7 @@ def newagreement(): if form.validate_on_submit(): # create deterministic agreement unique _id? Example being genpasswd in new user validate on submit - mongo.db.agreement_collection.insert_one({ + mongo.db.agreements_collection.insert_one({ 'agreement_name':form.agreementName.data, 'agency':form.agency.data, 'projects':[], @@ -446,6 +462,45 @@ def newagreement(): return render_template('admin/agreements/newagreement.html',form=form,ORGNAME=OrganizationName) +#### #### +####### Project Admin Route ####### +#### #### +####### TODO Need to filter out available agrements key=agreement_name:value=_id(agreement) Assign _id to agreement, and write _id(project) to agreement.projects[] +@app.route("/admin/projects/new", methods=["GET","POST"]) +@login_required +def newproject(): +# Temp values, change to modular db dependent values + availableAgreements = [] + for agreement in mongo.db.agreements_collection.find(): + availableAgreements.append((agreement['_id'],agreement['agreement_name'])) +# END TMP Values + + form = NewProjectForm() + form.agreement.choices = availableAgreements + + if form.validate_on_submit(): + # create deterministic agreement unique _id? Example being genpasswd in new user validate on submit + + mongo.db.projects_collection.insert_one({ + 'project_name':form.projectName.data, + 'agreement':ObjectId('{}').format(form.agreement.data),#TODO FIX Causes errors + 'budget':[{ + 'labor':form.laborBudget.data, + 'travel':form.travelBudget.data, + 'supplies':form.suppliesBudget.data, + 'contact':form.contactBudget.data, + 'equipment':form.equipmentBudget.data, + 'other':form.otherBudget.data + }] # most recent labor budget accessed via budget.0.labor + }) + pj_id = mongo.db.projects_collection.find_one({'project_name':form.projectName.data})['_id'] + mongo.db.agreements_collection.update_one({ '_id':ObjectId('{}').format(form.agreement.data) },{ '$push':{ 'projects':pj_id }})#TODO Fix, causes errors + + flash("{} part of {} added".format(form.projectName.data, form.agreement.data )) #Will need to sendmail password to form.email.data later + return redirect(url_for('newproject')) + + return render_template('admin/agreements/projects/newproject.html',form=form,ORGNAME=OrganizationName) + #### #### ####### Knowlegebase Route ####### #### #### @@ -541,7 +596,7 @@ def timedata(): @app.route("/dev/agreementdata", methods=['GET']) @login_required def agreementdata(): - allagreementdata = mongo.db.agreement_collection.find() + allagreementdata = mongo.db.agreements_collection.find() return render_template('dev/agreementdata.html', allagreementdata=allagreementdata) #### #### diff --git a/app/static/css/main.css b/app/static/css/main.css @@ -90,7 +90,7 @@ header { /* box-shadow: 0px 0px .1em .1em var(--accent);/* probably shouldn't have box-shadow for clean ui at intermediate page sizes (between laptop and phone off ratio) */ } /********** FULL PAGE **********/ -.hours-grid, .new-user-grid, .new-agreement-grid, .role-permissions, .activeusers-grid { +.hours-grid, .new-user-grid, .new-agreement-grid, .new-project-grid, .role-permissions, .activeusers-grid { padding:5rem; margin:1rem; display: grid; diff --git a/app/templates/admin/agreements/projects/newproject.html b/app/templates/admin/agreements/projects/newproject.html @@ -0,0 +1,35 @@ +{% extends 'base.html' %} + +{% block title %}Add New Project{% endblock %} + +{% block content %} +<section class="new-project-grid"> + <h3>Add New Project</h3> + <form action="" method="POST" novalidate> + {{ form.hidden_tag() }} + {% for error in form.errors %} + <span style="color:red;">[{{ error }}]</span> + {% endfor %} + {% for ferror in form.form_errors %} + <span style="color:yellow;">[{{ ferror }}]</span> + {% endfor %} + {{ form.projectName.label }}{{ form.projectName() }}<br> + {{ form.agreement.label }}{{ form.agreement() }}<br> + <h4>Budget</h4> + {{ form.laborBudget.label }}{{ form.laborBudget() }}<br> + {{ form.travelBudget.label }}{{ form.travelBudget() }}<br> + {{ form.suppliesBudget.label }}{{ form.suppliesBudget() }}<br> + {{ form.contactBudget.label }}{{ form.contactBudget() }}<br> + {{ form.equipmentBudget.label }}{{ form.equipmentBudget() }}<br> + {{ form.otherBudget.label }}{{ form.otherBudget() }}<br><br> + {{ form.createNewProject() }} + </form> + {% with messages = get_flashed_messages() %} + {% if messages %} + {% for message in messages %} + <p style='color:green'>{{ message }}</p> + {% endfor %} + {% endif %} + {% endwith %} +</section> +{% endblock %} diff --git a/app/templates/admin/agreements/widget.html b/app/templates/admin/agreements/widget.html @@ -1,14 +1,25 @@ <section class="agreements"> - <h3>Agreements Funding</h3> - <a href="/admin/agreement" onClick="alert('route to /admin/agreement<id>')"><div class="progress">Agreement Bid - <div class="total-progress" style="width:51.71%;">10342/20000</div> - <div class="progress-bar" style="width:5.7%;">Project1:342/6000</div> - <div class="progress-bar" style="width:85.71%;">Project2:6000/7000</div> - <div class="progress-bar" style="width:57.14%;">Project3:4000/7000</div> - </div></a> - <a href="/admin/agreement" onClick="alert('route to /admin/agreement<id>')"><div class="progress">Agreement Bid 2 - <div class="total-progress" style="width:30%;">10000/30000</div> - <div class="progress-bar" style="width:28.94%;">Project1:4342/15000</div> - <div class="progress-bar" style="width:37.72%;">Project3:5658/15000</div> + <h3>Agreements & Funding</h3> + {% for agreement in agreements %} + <a href="/admin/agreement/{{ agreement._id }}"><div class="progress">{{ agreement.agreement_name }} + <div class="total-progress" style="width:{{ (agreement.total_cost/agreement.total_budget)*100 }}%;">{{ agreement.total_cost|round(2,'ceil') }}/{{ agreement.total_budget|round(2, 'ceil') }} | {{ ((agreement.total_cost/agreement.total_budget)*100)|round|int }}%</div> + {% for project in agreement['projects'] %} + <div class="progress-bar" style="width:{{ (project.total_cost/project.total_budget)*100 }}%;">{{ project['project_name'] }}: {{ project.total_cost|round(2,'ceil') }}/{{ project.total_budget|round(2, 'ceil') }} | {{ ((project.total_cost/project.total_budget)*100)|round|int }}%</div> + {% endfor %} </div></a> + {% endfor %} + {% for agreement in agreements %} + {{ agreement.agreement_name }}<br> + {{ agreement['budget'] }}<br> + {% for project in agreement['projects'] %} + {{ project['budget'] }} + {{ project['total_budget'] }} + {{ project['costs'] }} + {{ project['total_cost'] }} + {% endfor %} + {{ agreement['costs'] }} + <br><br> + {% endfor %} + <a href="{{ url_for('newagreement') }}"><input type="submit" value="Add New Agreement"></a> + <a href="{{ url_for('newproject') }}"><input type="submit" value="Add New Project"></a> </section> diff --git a/seeds.py b/seeds.py @@ -8,7 +8,7 @@ db = client.get_database('simple_resource_management_software') user_collection = db.get_collection('user_collection') time_collection = db.get_collection('time_collection') fleet_collection = db.get_collection('fleet_collection') -agreement_collection = db.get_collection('agreement_collection') +agreements_collection = db.get_collection('agreements_collection') projects_collection = db.get_collection('projects_collection') permissions_collection = db.get_collection('permissions_collection') @@ -16,7 +16,7 @@ permissions_collection = db.get_collection('permissions_collection') x = user_collection.delete_many({}) x = time_collection.delete_many({}) x = fleet_collection.delete_many({}) -x = agreement_collection.delete_many({}) +x = agreements_collection.delete_many({}) x = projects_collection.delete_many({}) x = permissions_collection.delete_many({}) @@ -172,68 +172,148 @@ projects1 = { '_id':1, 'project_name': 'Project 1', 'agreement': 2, - 'project_budget': [13.20, 0, 20, 300, 50, 0 + 'budget': [{ + 'labor':1259.40, + 'travel':220.00, + 'supplies':320.00, + 'contact':420.00, + 'equipment':620.00, + 'other':20.00 + }], + 'costs': [{ + 'labor':159.40, + 'travel':20.00, + 'supplies':30.00, + 'contact':40.00, + 'equipment':60.00, + 'other':2.00 + }] + #'project_budget': [13.20, 0, 20, 300, 50, 0 # labor_budget: float | Indexed 0 # travel_budget: float | Indexed 1 # supplies_budget: float | Indexed 2 # contact_budget: float | Indexed 3 # equipment_budget: float | Indexed 4 # other: float | Indexed 5 - ], + #], } projects2 = { '_id':2, 'project_name': 'Project 2', 'agreement': 1, - 'project_budget': [13.20, 0, 20, 300, 50, 0 + 'budget': [{ + 'labor':1259.40, + 'travel':220.00, + 'supplies':320.00, + 'contact':420.00, + 'equipment':620.00, + 'other':20.00 + }], + 'costs': [{ + 'labor':159.40, + 'travel':20.00, + 'supplies':30.00, + 'contact':40.00, + 'equipment':60.00, + 'other':2.00 + }] + #'project_budget': [13.20, 0, 20, 300, 50, 0 # labor_budget: float | Indexed 0 # travel_budget: float | Indexed 1 # supplies_budget: float | Indexed 2 # contact_budget: float | Indexed 3 # equipment_budget: float | Indexed 4 # other: float | Indexed 5 - ], + #], } projects3 = { '_id':3, 'project_name': 'Project 3', 'agreement': 1, - 'project_budget': [13.20, 0, 20, 300, 50, 0 + 'budget': [{ + 'labor':1259.40, + 'travel':220.00, + 'supplies':320.00, + 'contact':420.00, + 'equipment':620.00, + 'other':20.00 + }], + 'costs': [{ + 'labor':159.40, + 'travel':20.00, + 'supplies':30.00, + 'contact':40.00, + 'equipment':60.00, + 'other':2.00 + }] + #'project_budget': [13.20, 0, 20, 300, 50, 0 # labor_budget: float | Indexed 0 # travel_budget: float | Indexed 1 # supplies_budget: float | Indexed 2 # contact_budget: float | Indexed 3 # equipment_budget: float | Indexed 4 # other: float | Indexed 5 - ], + #], } projects4 = { 'project_name': 'Project 4', '_id':4, 'agreement': 1, - 'project_budget': [13.20, 0, 20, 300, 50, 0 + 'budget': [{ + 'labor':1259.40, + 'travel':220.00, + 'supplies':320.00, + 'contact':420.00, + 'equipment':620.00, + 'other':20.00 + }], + 'costs': [{ + 'labor':159.40, + 'travel':20.00, + 'supplies':30.00, + 'contact':40.00, + 'equipment':60.00, + 'other':2.00 + }] + #'project_budget': [13.20, 0, 20, 300, 50, 0 # labor_budget: float | Indexed 0 # travel_budget: float | Indexed 1 # supplies_budget: float | Indexed 2 # contact_budget: float | Indexed 3 # equipment_budget: float | Indexed 4 # other: float | Indexed 5 - ], + #], } projects5 = { '_id':5, 'project_name': 'Project 5', 'agreement': 2, - 'project_budget': [13.20, 0, 20, 300, 50, 0 + 'budget': [{ + 'labor':1259.40, + 'travel':220.00, + 'supplies':320.00, + 'contact':420.00, + 'equipment':620.00, + 'other':20.00 + }], + 'costs': [{ + 'labor':159.40, + 'travel':20.00, + 'supplies':30.00, + 'contact':40.00, + 'equipment':60.00, + 'other':2.00 + }] + #'project_budget': [13.20, 0, 20, 300, 50, 0 # labor_budget: float | Indexed 0 # travel_budget: float | Indexed 1 # supplies_budget: float | Indexed 2 # contact_budget: float | Indexed 3 # equipment_budget: float | Indexed 4 # other: float | Indexed 5 - ], + #], } # Permissions documents (only needs array list of str for each 'service') crew = { @@ -289,7 +369,7 @@ accountant = { user_collection.insert_many([user1, user2]) time_collection.insert_many([time1, time2,time3]) fleet_collection.insert_many([fleet1, fleet2]) -agreement_collection.insert_many([agreement1, agreement2]) +agreements_collection.insert_many([agreement1, agreement2]) projects_collection.insert_many([projects1, projects2, projects3, projects4, projects5]) permissions_collection.insert_many([crew,alead,lead,developer,manager,accountant]) @@ -303,7 +383,7 @@ for x in time_collection.find(): for x in fleet_collection.find(): print(x) -for x in agreement_collection.find(): +for x in agreements_collection.find(): print(x) for x in projects_collection.find(): @@ -311,3 +391,17 @@ for x in projects_collection.find(): for x in permissions_collection.find(): print(x) + +#print('making query on agreements and attempting to inject relavant projects') +#test_agreements = agreements_collection.find() +#fagreements=[] +#for agreement in test_agreements: +# for i in range(len(agreement['projects'])): +# print(agreement['projects'][i]) +# agreement['projects'][i] = projects_collection.find_one({'_id': agreement['projects'][i]}) +# # print(agreement['projects'][i]) +# #for a in agreement: +# #print(a) +# fagreements.append(agreement) +#for agree in fagreements: +# print(agree)