diff --git a/tailbone/templates/batch/view.mako b/tailbone/templates/batch/view.mako index a7da6e54..a1de0863 100644 --- a/tailbone/templates/batch/view.mako +++ b/tailbone/templates/batch/view.mako @@ -57,7 +57,7 @@ <%def name="leading_buttons()"> - % if master.has_worksheet and not batch.executed and request.has_perm('{}.worksheet'.format(permission_prefix)): + % if master.has_worksheet and master.allow_worksheet(batch) and request.has_perm('{}.worksheet'.format(permission_prefix)): % endif diff --git a/tailbone/views/batch/core.py b/tailbone/views/batch/core.py index 24811611..2213163f 100644 --- a/tailbone/views/batch/core.py +++ b/tailbone/views/batch/core.py @@ -113,6 +113,9 @@ class BatchMasterView(MasterView): kwargs['rendered_execution_options'] = self.render_execution_options(batch) return kwargs + def allow_worksheet(self, batch): + return not batch.executed and not batch.complete + def template_kwargs_index(self, **kwargs): kwargs['execute_enabled'] = self.instance_executable(None) if kwargs['execute_enabled'] and self.has_execution_options: @@ -161,7 +164,8 @@ class BatchMasterView(MasterView): fs.cognized_by.set(label="Cognized by", renderer=forms.renderers.UserFieldRenderer) fs.rowcount.set(label="Row Count", readonly=True) fs.status_code.set(label="Status", renderer=StatusRenderer(self.model_class.STATUS)) - fs.executed_by.set(label="Executed by", renderer=forms.renderers.UserFieldRenderer) + fs.executed.set(readonly=True) + fs.executed_by.set(label="Executed by", renderer=forms.renderers.UserFieldRenderer, readonly=True) fs.notes.set(renderer=fa.TextAreaFieldRenderer, size=(80, 10)) if self.creating and self.request.user: @@ -310,7 +314,7 @@ class BatchMasterView(MasterView): """ self.editing = True batch = self.get_instance() - if batch.executed: + if not self.editable_instance(batch): return self.redirect(self.get_action_url('view', batch)) if self.edit_with_rows: @@ -685,20 +689,12 @@ class BatchMasterView(MasterView): batch = row.batch return self.rows_editable and not batch.executed and not batch.complete - def row_edit_action_url(self, row, i): - if self.row_editable(row): - return self.get_row_action_url('edit', row) - def row_deletable(self, row): """ Batch rows are deletable only until batch has been executed. """ return self.rows_deletable and not row.batch.executed - def row_delete_action_url(self, row, i): - if self.row_deletable(row): - return self.get_row_action_url('delete', row) - def _preconfigure_row_fieldset(self, fs): fs.sequence.set(readonly=True) fs.status_code.set(renderer=StatusRenderer(self.model_row_class.STATUS), diff --git a/tailbone/views/inventory.py b/tailbone/views/inventory.py index dff7f435..03ef10ba 100644 --- a/tailbone/views/inventory.py +++ b/tailbone/views/inventory.py @@ -98,6 +98,15 @@ class InventoryBatchView(BatchMasterView): batch.created_by, localtime(self.request.rattail_config, batch.created, from_utc=True).strftime('%Y-%m-%d')) + def editable_instance(self, batch): + return True + + def mutable_batch(self, batch): + return not batch.executed and not batch.complete and batch.mode != self.enum.INVENTORY_MODE_ZERO_ALL + + def allow_worksheet(self, batch): + return self.mutable_batch(batch) + def _preconfigure_fieldset(self, fs): super(InventoryBatchView, self)._preconfigure_fieldset(fs) fs.mode.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.INVENTORY_MODE), @@ -124,6 +133,12 @@ class InventoryBatchView(BatchMasterView): if not self.creating: fs.mode.set(readonly=True) + def row_editable(self, row): + return self.mutable_batch(row.batch) + + def row_deletable(self, row): + return self.mutable_batch(row.batch) + def save_edit_row_form(self, form): row = form.fieldset.model batch = row.batch diff --git a/tailbone/views/master.py b/tailbone/views/master.py index 7d2c943a..2aea4523 100644 --- a/tailbone/views/master.py +++ b/tailbone/views/master.py @@ -634,11 +634,29 @@ class MasterView(View): """ return "{}.rows".format(cls.get_permission_prefix()) + def row_editable(self, row): + """ + Returns boolean indicating whether or not the given row can be + considered "editable". Returns ``True`` by default; override as + necessary. + """ + return True + def row_edit_action_url(self, row, i): - return self.get_row_action_url('edit', row) + if self.row_editable(row): + return self.get_row_action_url('edit', row) + + def row_deletable(self, row): + """ + Returns boolean indicating whether or not the given row can be + considered "deletable". Returns ``True`` by default; override as + necessary. + """ + return True def row_delete_action_url(self, row, i): - return self.get_row_action_url('delete', row) + if self.row_deletable(row): + return self.get_row_action_url('delete', row) def row_grid_row_attrs(self, row, i): return {}