Aug 19 - Update code to catch up with ST

This commit is contained in:
2026-08-19 14:05:18 -04:00
parent c9984e7ae6
commit 12141c2f75
52 changed files with 3321 additions and 342 deletions
+23 -10
View File
@@ -2,7 +2,7 @@ from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed, MultipleFileField
from wtforms import (StringField, PasswordField, SelectField, TextAreaField,
DecimalField, BooleanField, IntegerField, HiddenField,
RadioField)
RadioField, SelectMultipleField)
from wtforms.validators import (DataRequired, Email, Length, EqualTo,
Optional, NumberRange, ValidationError)
import re as _re
@@ -91,13 +91,13 @@ class UserForm(FlaskForm):
('admin', 'Administrator'),
('director', 'Director'),
('inspector', 'Inspector'),
# MT-15 — an inspector employed by the customer or a third party.
# Same capabilities as 'inspector'; scoped to the contracts assigned on
# the Assign Contracts page (see User.INSPECTOR_ROLES).
('external_inspector', 'External Inspector'),
('project_manager', 'Project Manager'),
('auditor', 'Auditor'),
# 'customer' is intentionally excluded — customer accounts are managed via /customers
# Both customer-side roles are intentionally excluded — 'customer'
# (Customer Director) and 'external_inspector' (Customer Inspector) are
# created, edited and switched exclusively in Customer Management
# (/customers). phase51 removed 'external_inspector' from here; see
# User.CUSTOMER_ROLES.
], validators=[Optional()])
# NOTE: Optional() here because directors submit no role value (the field is
# hidden in user_form.html for them). Role enforcement is handled in the
@@ -164,6 +164,11 @@ class InspectionTemplateForm(FlaskForm):
('daily','Daily'), ('weekly','Weekly'),
('monthly','Monthly'), ('quarterly','Quarterly'),
], validators=[DataRequired()])
# phase52 — which contracts may use this form. Choices are populated in the
# route. Selecting NONE leaves the form shared with every contract, which
# is the default and what every pre-phase52 template does.
contract_ids = SelectMultipleField('Available on contracts', coerce=int,
validators=[Optional()])
class ChecklistItemForm(FlaskForm):
@@ -308,14 +313,22 @@ class CustomerUserForm(FlaskForm):
raise ValidationError('Password is required for new accounts.')
class CustomerInviteForm(FlaskForm):
"""Simplified form for creating a customer account via email invitation.
"""Create a customer-side account via email invitation.
Admin enters Full Name and Email only. A username is auto-generated
from the email address. The customer sets their own username and
password via the emailed link.
Admin enters Full Name, Email and which of the two customer roles the
person holds. A username is auto-generated from the email address; the
invitee sets their own username and password via the emailed link.
Both roles use the SAME invitation flow — neither is an account we set a
password for. phase51 folded the Customer Inspector (stored as
'external_inspector') in here from User Management.
"""
full_name = StringField('Full Name', validators=[DataRequired(), Length(max=150)])
email = StringField('Email', validators=[DataRequired(), Email(), Length(max=255)])
role = SelectField('Role', choices=[
('customer', 'Customer Director — portal access for their facilities'),
('external_inspector', 'Customer Inspector — performs inspections on their contracts'),
], default='customer', validators=[DataRequired()])
def validate_email(self, field):
if User.query.filter_by(email=field.data.strip().lower()).first():