05/11 Update: add contract selection when start an inspection

This commit is contained in:
2026-05-11 12:52:58 -04:00
parent 100cfbc988
commit dc9bfb1674
3 changed files with 111 additions and 6 deletions
+38 -4
View File
@@ -10,6 +10,7 @@ from app import db
from app.models.inspection import (Inspection, InspectionTemplate, from app.models.inspection import (Inspection, InspectionTemplate,
ChecklistItem, InspectionResult) ChecklistItem, InspectionResult)
from app.models.facility import Facility, Area from app.models.facility import Facility, Area
from app.models.project import Project
from app.models.issue import Issue from app.models.issue import Issue
from app.models.user import User from app.models.user import User
from app.utils.forms import StartInspectionForm, IssueForm from app.utils.forms import StartInspectionForm, IssueForm
@@ -229,18 +230,39 @@ def index():
def start(): def start():
form = StartInspectionForm() form = StartInspectionForm()
templates = InspectionTemplate.query.order_by(InspectionTemplate.name).all() templates = InspectionTemplate.query.order_by(InspectionTemplate.name).all()
facilities = Facility.query.filter_by(active=True).order_by(Facility.name).all() projects = Project.query.filter_by(active=True).order_by(Project.name).all()
form.template_id.choices = [(t.id, t.name) for t in templates] form.template_id.choices = [(t.id, t.name) for t in templates]
form.facility_id.choices = [(f.id, f.name) for f in facilities] form.project_id.choices = [(p.id, p.name) for p in projects]
# Seed facility choices: use submitted project_id, session value, or first project
from flask import session as _session from flask import session as _session
if form.is_submitted():
selected_project_id = form.project_id.data
elif _session.get('reinspect_facility_id'):
# Derive project from the reinspect facility
_rf = db.session.get(Facility, _session['reinspect_facility_id'])
selected_project_id = _rf.project_id if _rf and _rf.project_id else (projects[0].id if projects else None)
else:
selected_project_id = projects[0].id if projects else None
if selected_project_id:
facilities = Facility.query.filter_by(active=True, project_id=selected_project_id).order_by(Facility.name).all()
else:
facilities = []
form.facility_id.choices = [(f.id, f.name) for f in facilities]
if not form.facility_id.choices:
form.facility_id.choices = [('', '— no facilities —')]
if not form.is_submitted(): if not form.is_submitted():
if _session.get('reinspect_template_id'): if _session.get('reinspect_template_id'):
form.template_id.data = _session['reinspect_template_id'] form.template_id.data = _session['reinspect_template_id']
if _session.get('reinspect_facility_id'): if _session.get('reinspect_facility_id'):
form.facility_id.data = _session['reinspect_facility_id'] form.facility_id.data = _session['reinspect_facility_id']
if selected_project_id:
form.project_id.data = selected_project_id
if form.validate_on_submit(): if form.validate_on_submit():
template = db.session.get(InspectionTemplate, form.template_id.data) template = db.session.get(InspectionTemplate, form.template_id.data)
@@ -272,7 +294,7 @@ def start():
flash('Inspection started. Fill in the form below and submit when complete.', 'info') flash('Inspection started. Fill in the form below and submit when complete.', 'info')
return redirect(url_for('inspections.execute', inspection_id=inspection.id)) return redirect(url_for('inspections.execute', inspection_id=inspection.id))
return render_template('inspections/start.html', form=form, facilities=facilities) return render_template('inspections/start.html', form=form, projects=projects)
# ── AJAX: areas for a given facility ───────────────────────────────────────── # ── AJAX: areas for a given facility ─────────────────────────────────────────
@@ -284,6 +306,18 @@ def areas_for_facility(facility_id):
return jsonify([{'id': a.id, 'name': a.name} for a in areas]) return jsonify([{'id': a.id, 'name': a.name} for a in areas])
# ── AJAX: facilities for a given project/contract ────────────────────────────
@bp.route('/facilities_for_project/<int:project_id>')
@login_required
def facilities_for_project(project_id):
facilities = (Facility.query
.filter_by(active=True, project_id=project_id)
.order_by(Facility.name)
.all())
return jsonify([{'id': f.id, 'name': f.name} for f in facilities])
# ── Execute ─────────────────────────────────────────────────────────────────── # ── Execute ───────────────────────────────────────────────────────────────────
@bp.route('/<int:inspection_id>/execute', methods=['GET', 'POST']) @bp.route('/<int:inspection_id>/execute', methods=['GET', 'POST'])
+71 -1
View File
@@ -17,9 +17,22 @@
{% for e in form.template_id.errors %}<div class="invalid-feedback">{{ e }}</div>{% endfor %} {% for e in form.template_id.errors %}<div class="invalid-feedback">{{ e }}</div>{% endfor %}
</div> </div>
<div class="mb-3">
{{ form.project_id.label(class="form-label fw-semibold") }}
{{ form.project_id(class="form-select" + (" is-invalid" if form.project_id.errors else ""), id="projectSelect") }}
{% for e in form.project_id.errors %}<div class="invalid-feedback">{{ e }}</div>{% endfor %}
</div>
<div class="mb-3"> <div class="mb-3">
{{ form.facility_id.label(class="form-label fw-semibold") }} {{ form.facility_id.label(class="form-label fw-semibold") }}
{{ form.facility_id(class="form-select", id="facilitySelect") }} {{ form.facility_id(class="form-select" + (" is-invalid" if form.facility_id.errors else ""), id="facilitySelect") }}
{% for e in form.facility_id.errors %}<div class="invalid-feedback">{{ e }}</div>{% endfor %}
<div id="facilitySpinner" class="form-text text-muted d-none">
<span class="spinner-border spinner-border-sm" role="status"></span> Loading facilities…
</div>
<div id="facilityEmpty" class="form-text text-warning d-none">
No active facilities found for this contract.
</div>
</div> </div>
<div class="d-grid"> <div class="d-grid">
@@ -32,4 +45,61 @@
</div> </div>
</div> </div>
</div> </div>
<script>
(function () {
const projectSel = document.getElementById('projectSelect');
const facilitySel = document.getElementById('facilitySelect');
const spinner = document.getElementById('facilitySpinner');
const emptyMsg = document.getElementById('facilityEmpty');
function loadFacilities(projectId, selectedFacilityId) {
if (!projectId) return;
spinner.classList.remove('d-none');
emptyMsg.classList.add('d-none');
facilitySel.disabled = true;
fetch(`{{ url_for('inspections.facilities_for_project', project_id=0) }}`.replace('/0', '/' + projectId))
.then(r => r.json())
.then(data => {
facilitySel.innerHTML = '';
if (data.length === 0) {
emptyMsg.classList.remove('d-none');
facilitySel.innerHTML = '<option value="">— no facilities —</option>';
} else {
data.forEach(f => {
const opt = document.createElement('option');
opt.value = f.id;
opt.textContent = f.name;
if (selectedFacilityId && f.id === selectedFacilityId) opt.selected = true;
facilitySel.appendChild(opt);
});
}
})
.catch(() => {
facilitySel.innerHTML = '<option value="">— error loading facilities —</option>';
})
.finally(() => {
spinner.classList.add('d-none');
facilitySel.disabled = false;
});
}
projectSel.addEventListener('change', function () {
loadFacilities(this.value, null);
});
// On page load: if project already selected (e.g. validation error or reinspect),
// reload facility list preserving the currently selected facility value.
const initProject = projectSel.value;
const initFacility = facilitySel.value ? parseInt(facilitySel.value, 10) : null;
if (initProject) {
// Only reload if facility list looks like a placeholder (no real numeric id in options)
const hasRealOptions = Array.from(facilitySel.options).some(o => parseInt(o.value, 10) > 0);
if (!hasRealOptions) {
loadFacilities(initProject, initFacility);
}
}
})();
</script>
{% endblock %} {% endblock %}
+1
View File
@@ -142,6 +142,7 @@ class ChecklistItemForm(FlaskForm):
class StartInspectionForm(FlaskForm): class StartInspectionForm(FlaskForm):
template_id = SelectField('Template', coerce=int, validators=[DataRequired()]) template_id = SelectField('Template', coerce=int, validators=[DataRequired()])
project_id = SelectField('Contract', coerce=int, validators=[DataRequired()])
facility_id = SelectField('Facility', coerce=int, validators=[DataRequired()]) facility_id = SelectField('Facility', coerce=int, validators=[DataRequired()])