diff --git a/apollo/frontend/templates/frontend/macros/submission_list_filter.html b/apollo/frontend/templates/frontend/macros/submission_list_filter.html
index fd6d8e23d..c75d7558f 100644
--- a/apollo/frontend/templates/frontend/macros/submission_list_filter.html
+++ b/apollo/frontend/templates/frontend/macros/submission_list_filter.html
@@ -70,6 +70,10 @@
{{ filter_form.participant_role(class_='form-control custom-select') }}
+
diff --git a/apollo/frontend/templates/frontend/submission_edit.html b/apollo/frontend/templates/frontend/submission_edit.html
index 3116b642e..4070e8e29 100644
--- a/apollo/frontend/templates/frontend/submission_edit.html
+++ b/apollo/frontend/templates/frontend/submission_edit.html
@@ -243,6 +243,25 @@
{{ _('Data Validation Errors') }}
|
{%- endif %}
+
+ | {{ _('Was station opened?') }} |
+
+
+ {%- if readonly %}
+ {{ submission_form.not_opened(**{'class_': 'tracked', 'data-toggle': 'switchbutton', 'data-width': '80', 'data-onlabel': _('Not Opened'), 'data-onstyle': 'danger', 'data-offlabel': _('Opened'), 'data-offstyle': 'primary', 'data-size': 'sm', 'disabled': 'disabled'}) }}
+ {%- else %}
+ {{ submission_form.not_opened(**{'class_': 'tracked', 'data-toggle': 'switchbutton', 'data-width': '80', 'data-onlabel': _('Not Opened'), 'data-onstyle': 'danger', 'data-offlabel': _('Opened'), 'data-offstyle': 'primary', 'data-size': 'sm'}) }}
+ {%- endif %}
+ |
+ {%- if form.form_type == 'CHECKLIST' and not form.untrack_data_conflicts -%}
+ {%- for sibling_form in sibling_forms %}
+
+
+ |
+ {% endfor %}
+ |
+ {%- endif %}
+
{% if perms.edit_submission_quarantine_status.can() %}
| {{ _('Quarantine Status') }} |
diff --git a/apollo/submissions/api/views.py b/apollo/submissions/api/views.py
index c500a454e..482e79dfc 100644
--- a/apollo/submissions/api/views.py
+++ b/apollo/submissions/api/views.py
@@ -342,6 +342,7 @@ def submission():
submission.update_related(data)
if submission.master is not None:
submission.update_master_offline_status()
+ submission.update_master_opened_status()
update_submission_version(submission)
message_text = make_message_text(form, participant, data)
diff --git a/apollo/submissions/filters.py b/apollo/submissions/filters.py
index 81896e82f..0fe9b2f17 100644
--- a/apollo/submissions/filters.py
+++ b/apollo/submissions/filters.py
@@ -376,6 +376,22 @@ def filter(self, query, value, **kwargs):
return (None, None)
+class StationStatusFilter(ChoiceFilter):
+ def filter(self, query, value, **kwargs):
+ if value and value == '1':
+ return (
+ models.Submission.not_opened == True, # noqa
+ None
+ )
+ elif value:
+ return (
+ models.Submission.not_opened == False, # noqa
+ None
+ )
+
+ return (None, None)
+
+
class DateFilter(CharFilter):
def filter(self, query, value, **kwargs):
if value:
@@ -744,6 +760,13 @@ def make_submission_list_filter(event, form, filter_on_locations=False):
('1', _('No Signal'))
)
)
+ attributes['station_status'] = StationStatusFilter(
+ choices=(
+ ('', _('Station Status')),
+ ('0', _('Opened')),
+ ('1', _('Not opened'))
+ )
+ )
attributes['date'] = DateFilter()
attributes['fsn'] = FormSerialNumberFilter()
attributes['participant_role'] = make_participant_role_filter(
@@ -799,6 +822,14 @@ class QualityAssuranceConditionsForm(Form):
)
)
+ attributes['station_status'] = StationStatusFilter(
+ choices=(
+ ('', _('Station Status')),
+ ('0', _('Open')),
+ ('1', _('Not opened'))
+ )
+ )
+
# participant id and location
attributes['participant_id'] = ParticipantIDFilter()
attributes['location'] = AJAXLocationFilter()
diff --git a/apollo/submissions/forms.py b/apollo/submissions/forms.py
index 0c6f28aa5..2a9b8ca8a 100644
--- a/apollo/submissions/forms.py
+++ b/apollo/submissions/forms.py
@@ -203,6 +203,7 @@ def make_submission_edit_form_class(event, form):
form_fields['validate'] = validate_location
form_fields['unreachable'] = fields.BooleanField()
+ form_fields['not_opened'] = fields.BooleanField()
return type(
'SubmissionEditForm',
diff --git a/apollo/submissions/models.py b/apollo/submissions/models.py
index a35353fbf..8b019cb2f 100644
--- a/apollo/submissions/models.py
+++ b/apollo/submissions/models.py
@@ -125,6 +125,7 @@ class Submission(BaseModel):
passive_deletes=True))
conflicts = db.Column(JSONB)
unreachable = db.Column(db.Boolean, default=False, nullable=False)
+ not_opened = db.Column(db.Boolean, default=False, nullable=False)
geom = db.Column(Geometry('POINT', srid=4326))
verified_fields = db.Column(JSONB, default=[])
@@ -335,6 +336,28 @@ def update_master_offline_status(self):
if master_offline_status != self.master.unreachable:
db.session.add(self.master)
+ def update_master_opened_status(self):
+ if self.master is None:
+ return
+
+ siblings = self.siblings
+ master_opened_status = self.master.not_opened
+
+ if siblings:
+ if (
+ all([s.not_opened for s in self.siblings]) and
+ self.not_opened
+ ):
+ self.master.not_opened = True
+ else:
+ self.master.not_opened = False
+ else:
+ self.master.not_opened = self.not_opened
+
+ # if the offline status changed in any way
+ if master_opened_status != self.master.not_opened:
+ db.session.add(self.master)
+
def compute_conflict_tags(self, tags=None):
# don't compute if the 'track conflicts' flag is not set
# on the form
diff --git a/apollo/submissions/utils.py b/apollo/submissions/utils.py
index f41899ac0..909f96cc1 100644
--- a/apollo/submissions/utils.py
+++ b/apollo/submissions/utils.py
@@ -26,7 +26,7 @@ def make_submission_dataframe(query, form, selected_tags=None,
# the 'updated' field is required for results analysis
columns = [
Submission.data[tag].label(tag) for tag in fields] + [
- Submission.updated
+ Submission.not_opened, Submission.updated
]
# alias just in case the query is already joined to the tables below
diff --git a/apollo/submissions/views_submissions.py b/apollo/submissions/views_submissions.py
index 311b95930..01a849728 100644
--- a/apollo/submissions/views_submissions.py
+++ b/apollo/submissions/views_submissions.py
@@ -660,6 +660,7 @@ def submission_edit(submission_id):
initial_data.update(location=submission.location_id)
initial_data.update(participant=submission.participant_id)
initial_data.update(unreachable=submission.unreachable)
+ initial_data.update(not_opened=submission.not_opened)
if submission.quarantine_status:
initial_data.update(
quarantine_status=submission.quarantine_status.code)
@@ -706,6 +707,7 @@ def submission_edit(submission_id):
for sibling in sibling_submissions:
initial_data = sibling.data
initial_data.update(unreachable=sibling.unreachable)
+ initial_data.update(not_opened=sibling.not_opened)
if sibling.quarantine_status:
initial_data.update(
quarantine_status=sibling.quarantine_status.code)
@@ -1015,6 +1017,7 @@ def submission_edit(submission_id):
new_quarantine_status = submission_form.data.get(
'quarantine_status')
new_offline_status = submission_form.unreachable.data
+ new_station_status = submission_form.not_opened.data
if permissions.edit_submission_verification_status.can():
new_verified_fields = \
@@ -1050,6 +1053,9 @@ def submission_edit(submission_id):
if new_offline_status != submission.unreachable:
changed = True
update_params['unreachable'] = new_offline_status
+ if new_station_status != submission.not_opened:
+ changed = True
+ update_params['not_opened'] = new_station_status
changed_fields = []
@@ -1117,6 +1123,7 @@ def submission_edit(submission_id):
submission.update_related(data)
submission.update_master_offline_status()
+ submission.update_master_opened_status()
db.session.add_all(attachments)
for attachment in deleted_attachments:
diff --git a/migrations/versions/b3ccd538959e_add_not_opened_field.py b/migrations/versions/b3ccd538959e_add_not_opened_field.py
new file mode 100644
index 000000000..909fe9e6d
--- /dev/null
+++ b/migrations/versions/b3ccd538959e_add_not_opened_field.py
@@ -0,0 +1,31 @@
+"""add not_opened field
+
+Revision ID: b3ccd538959e
+Revises: c4166678fb79
+Create Date: 2021-08-03 09:41:18.244493
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = 'b3ccd538959e'
+down_revision = 'c4166678fb79'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column(
+ 'submission',
+ sa.Column('not_opened', sa.Boolean(), nullable=False,
+ server_default='False'))
+ op.alter_column('submission', 'not_opened', server_default=None)
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_column('submission', 'not_opened')
+ # ### end Alembic commands ###