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:
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)