Jul 16 - Update issue handler Janitorial staff - add input staff name

This commit is contained in:
2026-07-16 15:39:26 -04:00
parent 5a42b21a04
commit 66dbf31c34
8 changed files with 112 additions and 7 deletions
+4 -1
View File
@@ -109,6 +109,7 @@ def _issue_payload(issue):
'vendor_name': issue.vendor_name or None,
'vendor_contact': issue.vendor_contact or None,
'vendor_notes': issue.vendor_notes or None,
'internal_handler_name': issue.internal_handler_name or None,
}
@@ -423,7 +424,8 @@ def update_issue_handler(issue_id):
"facility_handler_notes": "...", // optional
"vendor_name": "...", // optional (vendor handler)
"vendor_contact": "...", // optional
"vendor_notes": "..." // optional
"vendor_notes": "...", // optional
"internal_handler_name": "..." // optional (janitorial staff name)
}
Only keys present in the body are updated; empty strings clear a field.
@@ -463,6 +465,7 @@ def update_issue_handler(issue_id):
_text_fields = (
'facility_handler_name', 'facility_handler_contact', 'facility_handler_notes',
'vendor_name', 'vendor_contact', 'vendor_notes',
'internal_handler_name',
)
for field in _text_fields:
if field in data:
+4
View File
@@ -95,6 +95,10 @@ class Issue(db.Model):
facility_handler_name = db.Column(db.String(100), nullable=True)
facility_handler_contact = db.Column(db.String(200), nullable=True) # phone or email
facility_handler_notes = db.Column(db.Text, nullable=True)
# Free-text name of the janitorial staff member who will handle the issue,
# used when handler_type == 'internal'. Distinct from assigned_to (the JQC
# User who owns follow-up): the actual crew member may not be a system user.
internal_handler_name = db.Column(db.String(100), nullable=True)
# Relationships
# NOTE: Issue.area is provided by the backref on Area.issues (facility.py).
+3
View File
@@ -469,6 +469,8 @@ def view(issue_id):
issue.facility_handler_contact = (form.facility_handler_contact.data or '').strip() or None
issue.facility_handler_notes = (form.facility_handler_notes.data or '').strip() or None
issue.internal_handler_name = (form.internal_handler_name.data or '').strip() or None
from app.routes.inspections import _save_photo
new_photos = []
for file_obj in request.files.getlist('result_photos'):
@@ -759,6 +761,7 @@ def create():
issue.vendor_name = (form.vendor_name.data or '').strip() or None
issue.vendor_contact = (form.vendor_contact.data or '').strip() or None
issue.vendor_notes = (form.vendor_notes.data or '').strip() or None
issue.internal_handler_name = (form.internal_handler_name.data or '').strip() or None
db.session.add(issue)
db.session.commit()
+12
View File
@@ -52,6 +52,16 @@
{% for e in form.assigned_to.errors %}<div class="text-danger small">{{ e }}</div>{% endfor %}
</div>
{# Janitorial-staff handler — shown when Handled By = Janitorial Staff #}
<div id="internal_handler_block" style="display:none;">
<div class="mb-3">
{{ form.internal_handler_name.label(class="form-label small fw-semibold mb-1") }}
{{ form.internal_handler_name(class="form-control form-control-sm",
placeholder="Name of the crew member who will handle it") }}
<div class="form-text">Optional — the janitorial staff member doing the work.</div>
</div>
</div>
{# Facility-staff handler — shown when Handled By = Facility Staff #}
<div id="facility_handler_block" style="display:none;">
<div class="mb-2">
@@ -166,8 +176,10 @@
function syncHandlerUI() {
if (!handlerSelect) { return; }
var v = handlerSelect.value;
var intBlock = document.getElementById('internal_handler_block');
var facBlock = document.getElementById('facility_handler_block');
var venBlock = document.getElementById('vendor_block');
if (intBlock) { intBlock.style.display = (v === 'internal') ? '' : 'none'; }
if (facBlock) { facBlock.style.display = (v === 'facility') ? '' : 'none'; }
if (venBlock) { venBlock.style.display = (v === 'vendor') ? '' : 'none'; }
var desc = document.getElementById('handler_desc');
+24
View File
@@ -89,6 +89,14 @@
</dt>
<dd class="col-sm-9">{{ issue.assigned_user.display_name if issue.assigned_user else '— Unassigned —' }}</dd>
{% if (issue.handler_type or 'internal') == 'internal' and issue.internal_handler_name %}
<dt class="col-sm-3">Staff</dt>
<dd class="col-sm-9">
<i class="bi bi-people text-secondary me-1"></i>
<strong>{{ issue.internal_handler_name }}</strong>
</dd>
{% endif %}
{% if issue.handler_type == 'facility' and issue.facility_handler_name %}
<dt class="col-sm-3">Facility Contact</dt>
<dd class="col-sm-9">
@@ -394,6 +402,20 @@
{% endif %}
{% if current_user.role in ['admin','director','project_manager','auditor'] %}
{# ── Janitorial-staff handler (shown when Handled By = Janitorial Staff) ── #}
<div id="internal_handler_block" style="display:none;">
<hr class="my-3">
<p class="fw-semibold small mb-2">
<i class="bi bi-people me-1 text-secondary"></i>Janitorial Staff
</p>
<div class="mb-3">
{{ form.internal_handler_name.label(class="form-label small fw-semibold mb-1") }}
{{ form.internal_handler_name(class="form-control form-control-sm",
placeholder="Name of the crew member who will handle it",
value=issue.internal_handler_name or '') }}
</div>
</div>
{# ── Facility-staff handler (shown when Handled By = Facility Staff) ── #}
<div id="facility_handler_block" style="display:none;">
<hr class="my-3">
@@ -564,8 +586,10 @@
function syncHandlerUI() {
if (!handlerSelect) { return; }
var v = handlerSelect.value;
var intBlock = document.getElementById('internal_handler_block');
var facBlock = document.getElementById('facility_handler_block');
var venBlock = document.getElementById('vendor_block');
if (intBlock) { intBlock.style.display = (v === 'internal') ? '' : 'none'; }
if (facBlock) { facBlock.style.display = (v === 'facility') ? '' : 'none'; }
if (venBlock) { venBlock.style.display = (v === 'vendor') ? '' : 'none'; }
+4
View File
@@ -184,6 +184,8 @@ class IssueForm(FlaskForm):
vendor_name = StringField('Contractor Name', validators=[Optional(), Length(max=100)])
vendor_contact = StringField('Contractor Contact', validators=[Optional(), Length(max=200)])
vendor_notes = TextAreaField('Contractor Notes', validators=[Optional(), Length(max=1000)])
# Janitorial staff member's name — used when handler_type == 'internal'
internal_handler_name = StringField('Staff Name', validators=[Optional(), Length(max=100)])
class IssueUpdateForm(FlaskForm):
@@ -212,6 +214,8 @@ class IssueUpdateForm(FlaskForm):
vendor_name = StringField('Contractor Name', validators=[Optional(), Length(max=100)])
vendor_contact = StringField('Contractor Contact', validators=[Optional(), Length(max=200)])
vendor_notes = TextAreaField('Contractor Notes', validators=[Optional(), Length(max=1000)])
# Janitorial staff member's name — used when handler_type == 'internal'
internal_handler_name = StringField('Staff Name', validators=[Optional(), Length(max=100)])
# ── Projects ─────────────────────────────────────────────────────────────────