commit 6bfabd811896546f65313bd7d63d67ce20d2f953
parent bf96e08770de0d97021b57eddcf2ded640613d89
Author: Youth Employment Program Production <youthemployment22@gmail.com>
Date: Tue, 23 Apr 2024 22:46:51 -0600
Refactor and abstract equipment fns, newequipment, update_equipment, and MVCs
Diffstat:
11 files changed, 262 insertions(+), 23 deletions(-)
diff --git a/app/equipment/__pycache__/equipment.cpython-310.pyc b/app/equipment/__pycache__/equipment.cpython-310.pyc
Binary files differ.
diff --git a/app/equipment/__pycache__/forms.cpython-310.pyc b/app/equipment/__pycache__/forms.cpython-310.pyc
Binary files differ.
diff --git a/app/equipment/__pycache__/routes.cpython-310.pyc b/app/equipment/__pycache__/routes.cpython-310.pyc
Binary files differ.
diff --git a/app/equipment/equipment.py b/app/equipment/equipment.py
@@ -0,0 +1,53 @@
+from app import app
+from flask_pymongo import PyMongo
+from bson.objectid import ObjectId
+
+mongo = PyMongo(app)
+
+class EquipmentNotFoundError(Exception):
+ pass
+
+def fetch_equipment(equipment_id):
+ equipment = mongo.db.equipment_collection.find_one({"_id":ObjectId(equipment_id)})
+
+ if equipment == None:
+ raise EquipmentNotFoundError(f'Equipment Id {equipment_id} returned None')
+ else:
+ return equipment
+
+# return all past and present equipment
+def get_all_equipment():
+ equipment = mongo.db.equipment_collection.find()
+ return equipment
+
+# return all equipment not damaged, in use, and not in use presently
+def get_usable_equipment():
+ equipment = mongo.db.equipment_collection.find({'retired':{'$exists':False}})
+ return equipment
+
+# return equipment not damaged, and ready to use, does not return equipment in use presently
+def get_available_equipment():
+ equipment = mongo.db.equipment_collection.find({'retired':{'$exists':False},'checked_out':{'$exists':False}})
+ return equipment
+
+# return document of equipment type (_id) and count(number of occurances)
+def get_equipment_types():
+ types = mongo.db.equipment_collection.aggregate( [
+ {
+ '$group':{
+ '_id':'$equipment_type',
+ 'count': {'$count':{} }
+ }
+ },
+ { '$sort':{'equipment_type':1} }
+ ] )
+ return types
+
+# return tuple list ('type','type (count)')
+def count_equipment_types():
+ counts = []
+ for tool in get_equipment_types():
+ label = "{} ({})".format(tool['_id'],tool['count'])
+ counts.append((tool['_id'],label))
+ return counts
+
diff --git a/app/equipment/forms.py b/app/equipment/forms.py
@@ -1,11 +1,21 @@
from flask_wtf import FlaskForm
-from wtforms import StringField, SubmitField, SelectField, DateField, FloatField
+from wtforms import StringField, SubmitField, SelectField, DateField, FloatField, IntegerField
from wtforms.validators import DataRequired, optional, length, InputRequired, EqualTo
class NewEquipment(FlaskForm):
equipment_type = SelectField("Type",validators=[DataRequired()])
+ equipment_type_number = IntegerField("Equipment Number",validators=[optional()])
purchase_timestamp = DateField("Purchase Date",validators=[DataRequired()])
purchase_price = FloatField("Purchase Price", validators=[optional()])
match_percentage = FloatField("Percentage Match",validators=[optional()])
purchasing_project = SelectField("Purchasing Project",validators=[optional()])
submit_equipment = SubmitField("Submit Equipment")
+
+class UpdateEquipment(FlaskForm):
+ equipment_type = SelectField("Type",validators=[optional()])
+ equipment_type_number = IntegerField("Equipment Number",validators=[optional()])
+ purchase_timestamp = DateField("Purchase Date",validators=[optional()])
+ purchase_price = FloatField("Purchase Price", validators=[optional()])
+ match_percentage = FloatField("Percentage Match",validators=[optional()])
+ purchasing_project = SelectField("Purchasing Project",validators=[optional()])
+ submit_equipment = SubmitField("Submit Equipment")
diff --git a/app/equipment/routes.py b/app/equipment/routes.py
@@ -3,15 +3,65 @@ from flask_pymongo import PyMongo
from flask import render_template, redirect, url_for, flash, request
from flask_login import login_required
from bson.objectid import ObjectId
+from app.routes import get_available_projects
from app.equipment import bp
-from app.equipment.forms import NewEquipment
+from app.equipment.forms import NewEquipment, UpdateEquipment
+from app.equipment.equipment import fetch_equipment, EquipmentNotFoundError, get_all_equipment, get_usable_equipment, get_available_equipment, get_equipment_types, count_equipment_types
import datetime
mongo = PyMongo(app)
+#class EquipmentNotFoundError(Exception):
+# pass
+#
+#def fetch_equipment(equipment_id):
+# equipment = mongo.db.equipment_collection.find_one({"_id":ObjectId(equipment_id)})
+#
+# if equipment == None:
+# raise EquipmentNotFoundError(f'Equipment Id {equipment_id} returned None')
+# else:
+# return equipment
+#
+## return all past and present equipment
+#def get_all_equipment():
+# equipment = mongo.db.equipment_collection.find()
+# return equipment
+#
+## return all equipment not damaged, in use, and not in use presently
+#def get_usable_equipment():
+# equipment = mongo.db.equipment_collection.find({'retired':{'$exists':False}})
+# return equipment
+#
+## return equipment not damaged, and ready to use, does not return equipment in use presently
+#def get_available_equipment():
+# equipment = mongo.db.equipment_collection.find({'retired':{'$exists':False},'checked_out':{'$exists':False}})
+# return equipment
+#
+## return document of equipment type (_id) and count(number of occurances)
+#def get_equipment_types():
+# types = mongo.db.equipment_collection.aggregate( [
+# {
+# '$group':{
+# '_id':'$equipment_type',
+# 'count': {'$count':{} }
+# }
+# },
+# { '$sort':{'equipment_type':1} }
+# ] )
+# return types
+#
+## return tuple list ('type','type (count)')
+#def count_equipment_types():
+# counts = []
+# for tool in get_equipment_types():
+# label = "{} ({})".format(tool['_id'],tool['count'])
+# counts.append((tool['_id'],label))
+# return counts
+
## DEV and SEED Routes ##
@bp.route("/dev/equipment",methods=["GET"])
+@bp.route("/dev/equipment/",methods=["GET"])
@login_required
def devEquipment():
equipment = mongo.db.equipment_collection.find({})
@@ -24,8 +74,7 @@ def seedEquipment():
seeds = [
{ # If equipment_type == "vehicle" pass data as params to NewVehicle(FlaskForm) to add additional details like vehicle_number
"equipment_type":"vehicle",
- "branch":"Dillon", #TODO Change all references to branches to branch_id for scaling via a branch_collection
- "vehicle_id": 1,
+ "branch":ObjectId("6627f69645530484ae5a4ade"), #TODO Change all references to branches to branch_id for scaling via a branch_collection
"purchase_timestamp": datetime.datetime.now(),
"purchase_price": 26500.68,
"match_percentage": 10.25,
@@ -33,7 +82,7 @@ def seedEquipment():
},
{
"equipment_type":"shovel",
- "branch":"Salmon",
+ "branch":ObjectId("6627f69645530484ae5a4adf"),
"purchase_timestamp": datetime.datetime.now(),
"purchase_price": 16.68,
"match_percentage": 2.5,
@@ -41,8 +90,7 @@ def seedEquipment():
},
{
"equipment_type":"vehicle",
- "branch":"Salmon",
- "vehicle_id": 2,
+ "branch":ObjectId("6627f69645530484ae5a4adf"),
"purchase_timestamp": datetime.datetime.now(),
"purchase_price": 65238.2,
"match_percentage": 12.5,
@@ -51,8 +99,7 @@ def seedEquipment():
},
{
"equipment_type":"chainsaw",
- "gear_id":1,
- "branch":"Dillon",
+ "branch":ObjectId("6627f69645530484ae5a4ade"),
"purchase_timestamp": datetime.datetime.now(),
"purchase_price": 16.68,
"match_percentage": 2.5,
@@ -60,8 +107,7 @@ def seedEquipment():
},
{
"equipment_type":"chainsaw",
- "gear_id":2,
- "branch":"Dillon",
+ "branch":ObjectId("6627f69645530484ae5a4ade"),
"purchase_timestamp": datetime.datetime.now(),
"purchase_price": 16.68,
"match_percentage": 2.5,
@@ -77,17 +123,25 @@ def seedEquipment():
@bp.route("/equipment")
@bp.route("/equipment/")
@login_required
-def equipment():
+def all_equipment():
equipment = mongo.db.equipment_collection.find({})
return render_template("equipment.html",equipment=equipment)
-#### TODO pymongo.errors.OperationFailure: A pipeline stage specification object must contain exactly one field. errorcode: 40323
-@bp.route("/equipment/<equipmentType>",methods=["GET"])
+@bp.route("/equipment/<equipment_id>")
+@login_required
+def equipment(equipment_id):
+ equipment = mongo.db.equipment_collection.find({'_id':ObjectId(equipment_id)})
+ return render_template("equipment.html",equipment_id=equipment_id,equipment=equipment)
+
+@bp.route("/equipment/t/<equipmentType>",methods=["GET"])
@login_required
def EquipmentType(equipmentType):
equipment = mongo.db.equipment_collection.aggregate( [
{
- "$match": {"equipment_type":equipmentType},
+ "$match": {"equipment_type":equipmentType
+ }
+ },
+ {
"$sort": {
"equipment_type":1,
"purchase_timestamp":1
@@ -95,3 +149,73 @@ def EquipmentType(equipmentType):
}
] )
return render_template("equipment.html",equipment=equipment)
+
+@bp.route("/newequipment")
+@bp.route("/newequipment/")
+@login_required
+def new_equipment():
+ form = NewEquipment()
+
+ types = [('',"Select Type")]
+ for t in count_equipment_types():
+ types.append(t)
+ types.append(('Create New Type','Create New Type'))
+ form.equipment_type.choices = types
+ form.purchasing_project.choices = get_available_projects()
+
+ return render_template("form_equipment.html",form=form,new=True)
+
+# TODO change to retire? How should this work?
+@bp.route("/equipment/<equipment_id>/remove",methods=["GET","POST"])
+@login_required
+def remove_equipment(equipment_id):
+ form = RemoveEquipment()
+ return render_template("form_equipment.html")
+
+@bp.route("/equipment/<equipment_id>/<update>",methods=["GET","POST"])
+@login_required
+def update_equipment(equipment_id,update):
+ form = UpdateEquipment()
+
+ types = [('',"Select Type")]
+ for t in count_equipment_types():
+ types.append(t)
+ types.append(('Create New Type','Create New Type'))
+ form.equipment_type.choices = types
+ form.purchasing_project.choices = get_available_projects()
+
+ try:
+ equipment = fetch_equipment(equipment_id)
+ except EquipmentNotFoundError as e:
+ return render_template('error.html',error=e)
+ else:
+ if form.validate_on_submit():
+ match update:
+ case "equipment_type":
+ mongo.db.equipment_collection.update_one({'_id':equipment['_id']},{'$set':{'equipment_type':form.equipment_type.data}})
+ flash("Updated Equipment Type to {}".format(form.equipment_type.data))
+ return redirect(url_for('equipment.equipment',equipment_id=equipment_id))
+ case "equipment_type_number":
+ mongo.db.equipment_collection.update_one({'_id':equipment['_id']},{'$set':{'equipment_type_number':form.equipment_type_number.data}})
+ flash("Updated Equipment Number for {} to {}".format(equipment['equipment_type'],form.equipment_type_number.data))
+ return redirect(url_for('equipment.equipment',equipment_id=equipment_id))
+ case "purchase_timestamp":
+ timestamp = datetime.datetime.combine(form.date.data,datetime.min.time())
+ mongo.db.equipment_collection.update_one({'_id':equipment['_id']},{'$set':{'purchase_timestamp':form.purchase_timestamp.data}})
+ flash("Updated Purchase Timestamp to {}".format(timestamp))
+ return redirect(url_for('equipment.equipment',equipment_id=equipment_id))
+ case "purchase_price":
+ mongo.db.equipment_collection.update_one({'_id':equipment['_id']},{'$set':{'purchase_price':form.purchase_price.data}})
+ flash("Updated Purchase Price to {}".format(form.purchase_price.data))
+ return redirect(url_for('equipment.equipment',equipment_id=equipment_id))
+ case "match_percentage":
+ mongo.db.equipment_collection.update_one({'_id':equipment['_id']},{'$set':{'match_percentage':form.match_percentage.data}})
+ flash("Updated Match Percentage to {}".format(form.match_percentage.data))
+ return redirect(url_for('equipment.equipment',equipment_id=equipment_id))
+ case "purchasing_project":
+ mongo.db.equipment_collection.update_one({'_id':equipment['_id']},{'$set':{'purchasing_project':form.purchasing_project.data}})
+ flash("Updated Purchasing Project to {}".format(form.purchasing_project.data))
+ return redirect(url_for('equipment.equipment',equipment_id=equipment_id))
+
+ return render_template("form_equipment.html",update=update,form=form,equipment=equipment)
+
diff --git a/app/equipment/templates/dev.html b/app/equipment/templates/dev.html
diff --git a/app/equipment/templates/dev_equipment.html b/app/equipment/templates/dev_equipment.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% block title %}DEV Equipment{% endblock %}
+{% block content %}
+
+ {%- for x in dev_equipment %}
+ {%- print(x) %}
+ </br>
+ </br>
+ {%- endfor %}
+
+{% endblock %}
diff --git a/app/equipment/templates/equipment.html b/app/equipment/templates/equipment.html
@@ -12,20 +12,30 @@
{% endif %}
{% endwith %}
+ {% if equipment_id or dev %}
+ <a href="{{url_for("equipment.all_equipment")}}"><div>back to equipment</div></a>
+ {% endif %}
+
<section>
{% for tool in equipment %}
{% if dev %}
- {{ tool }}
+ <article>{{ tool }}</article>
{% else %}
- <article style="padding-top:2em;margin:0;">
- {% for key,value in tool.items() %}
- <div style="display:grid;grid-gap:2em; grid-auto-flow:column; grid-template-columns:min-content">
- <div>{{ key }}</div>
- <div>{{ value }}</div>
- </div>
- {% endfor %}
+ {% if not equipment_id %}<a href="{{url_for("equipment.equipment",equipment_id=tool['_id'])}}">{%else%}<a href="{{url_for("equipment.remove_equipment",equipment_id=tool['_id'])}}"style="color:red">remove</a>{% endif %}
+ <article style="padding-bottom:1em;padding-top:1em;margin:0;">
+ {% for key,value in tool.items() %}
+ <div style="display:grid;grid-gap:2em; grid-auto-flow:column; grid-template-columns:min-content">
+ <div>{{ key }}</div>
+ <div>{{ value }}</div>
+ {% if equipment_id %}<a href="{{ url_for("equipment.update_equipment",equipment_id=tool['_id'],update=key ) }}"style="color:red;">change</a>{% endif %}
+ </div>
+ {% endfor %}
</article>
+ {% if not equipment_id %}</a>{% endif %}
{% endif %}
{% endfor %}
+ {% if not equipment_id %}
+ <a href="{{url_for("equipment.new_equipment")}}"><div>new equipment</div></a>
+ {% endif %}
</section>
{% endblock %}
diff --git a/app/equipment/templates/form.html b/app/equipment/templates/form.html
diff --git a/app/equipment/templates/form_equipment.html b/app/equipment/templates/form_equipment.html
@@ -0,0 +1,31 @@
+{% extends 'base.html' %}
+{% block title %}Equipment{% endblock %}
+{% block content %}
+
+<a href="{{url_for('equipment.equipment',equipment_id=equipment['_id'])}}">back to {{equipment['equipment_type']}}</a>
+<section>
+ <form action="" method="POST" novalidate>
+ {{ form.hidden_tag() }}
+ {% for error in form.errors %}
+ <span style="color:red;">[ {{ error }} ]</span>
+ {% endfor %}
+ {% if new %}
+ <div>NEW Equipment Block </div>
+ {{ form.equipment_type.label }}{{ form.equipment_type() }}
+ {{ form.purchase_timestamp.label }}{{ form.purchase_timestamp() }}
+ {{ form.purchase_price.label }}{{ form.purchase_price() }}
+ {{ form.match_percentage.label }}{{ form.match_percentage() }}
+ {{ form.purchasing_project.label }}{{ form.purchasing_project() }}
+ {% else %}
+ <div>Update Equipment Block </div>
+ {% if update == 'equipment_type' %}{{ form.equipment_type.label }}{{ form.equipment_type() }}{% endif %}
+ {% if update == 'purchase_timestamp' %}{{ form.purchase_timestamp.label }}{{ form.purchase_timestamp() }}{% endif %}
+ {% if update == 'purchase_price' %}{{ form.purchase_price.label }}{{ form.purchase_price() }}{% endif %}
+ {% if update == 'match_percentage' %}{{ form.match_percentage.label }}{{ form.match_percentage() }}{% endif %}
+ {% if update == 'purchasing_project' %}{{ form.purchasing_project.label }}{{ form.purchasing_project() }}{% endif %}
+ {% endif %}
+ {{ form.submit_equipment() }}
+ </form>
+</section>
+
+{% endblock %}