diff --git a/tailbone/templates/master/edit.mako b/tailbone/templates/master/edit.mako
index 79bc533f..9599a2c2 100644
--- a/tailbone/templates/master/edit.mako
+++ b/tailbone/templates/master/edit.mako
@@ -3,6 +3,23 @@
<%def name="title()">Edit ${model_title}: ${instance_title}%def>
+<%def name="head_tags()">
+ ${parent.head_tags()}
+
+%def>
+
<%def name="context_menu_items()">
${h.link_to("Back to {}".format(model_title_plural), url(route_prefix))}
% if master.viewable and request.has_perm('{}.view'.format(permission_prefix)):
diff --git a/tailbone/templates/master/view_row.mako b/tailbone/templates/master/view_row.mako
index dc5fd532..b03ae6e0 100644
--- a/tailbone/templates/master/view_row.mako
+++ b/tailbone/templates/master/view_row.mako
@@ -11,7 +11,7 @@
% if master.rows_deletable and instance_deletable and request.has_perm('{}.delete'.format(permission_prefix)):
${h.link_to("Delete this {}".format(model_title), action_url('delete', instance))}
% endif
- % if master.rows_creatable and request.has_perm('{}.create'.format(permission_prefix)):
+ % if rows_creatable and request.has_perm('{}.create'.format(permission_prefix)):
${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}
% endif
%def>
diff --git a/tailbone/templates/newbatch/edit.mako b/tailbone/templates/newbatch/edit.mako
index 91ea1dc9..120ec8fa 100644
--- a/tailbone/templates/newbatch/edit.mako
+++ b/tailbone/templates/newbatch/edit.mako
@@ -50,10 +50,16 @@
- ${form.render(buttons=capture(buttons))|n}
-
+ % if master.edit_with_rows:
+ ${form.render(buttons=capture(buttons))|n}
+ % else:
+ ${form.render()|n}
+ % endif
+
-${rows_grid.render_complete(allow_save_defaults=False, tools=capture(self.grid_tools))|n}
+% if master.edit_with_rows:
+ ${rows_grid.render_complete(allow_save_defaults=False, tools=capture(self.grid_tools))|n}
+% endif
diff --git a/tailbone/templates/purchases/batches/view.mako b/tailbone/templates/purchases/batches/view.mako
index f877163d..9a97debd 100644
--- a/tailbone/templates/purchases/batches/view.mako
+++ b/tailbone/templates/purchases/batches/view.mako
@@ -5,6 +5,7 @@
${parent.head_tags()}
%def>
<%def name="leading_buttons()">
- % if not instance.executed and request.has_perm('purchases.batch.order_form'):
+ % if not batch.complete and not batch.executed and request.has_perm('purchases.batch.order_form'):
View as Order Form
% endif
%def>
diff --git a/tailbone/views/batch.py b/tailbone/views/batch.py
index 543d118e..d3912c93 100644
--- a/tailbone/views/batch.py
+++ b/tailbone/views/batch.py
@@ -68,6 +68,7 @@ class BatchMasterView(MasterView):
rows_downloadable = True
refreshable = True
refresh_after_create = False
+ edit_with_rows = True
def __init__(self, request):
super(BatchMasterView, self).__init__(request)
@@ -296,23 +297,24 @@ class BatchMasterView(MasterView):
if batch.executed:
return self.redirect(self.get_action_url('view', batch))
- grid = self.make_row_grid(batch=batch)
+ if self.edit_with_rows:
+ grid = self.make_row_grid(batch=batch)
- # If user just refreshed the page with a reset instruction, issue a
- # redirect in order to clear out the query string.
- if self.request.GET.get('reset-to-default-filters') == 'true':
- return self.redirect(self.request.current_route_url(_query=None))
+ # If user just refreshed the page with a reset instruction, issue a
+ # redirect in order to clear out the query string.
+ if self.request.GET.get('reset-to-default-filters') == 'true':
+ return self.redirect(self.request.current_route_url(_query=None))
- if self.request.params.get('partial'):
- self.request.response.content_type = b'text/html'
- self.request.response.text = grid.render_grid()
- return self.request.response
+ if self.request.params.get('partial'):
+ self.request.response.content_type = b'text/html'
+ self.request.response.text = grid.render_grid()
+ return self.request.response
form = self.make_form(batch)
if self.request.method == 'POST':
if form.validate():
self.save_edit_form(form)
- self.request.session.flash("{0} {1} has been updated.".format(
+ self.request.session.flash("{} has been updated: {}".format(
self.get_model_title(), self.get_instance_title(batch)))
return self.redirect_after_edit(batch)
@@ -322,16 +324,23 @@ class BatchMasterView(MasterView):
'instance_deletable': self.deletable_instance(batch),
'form': form,
'batch': batch,
- 'rows_grid': grid,
'execute_title': self.get_execute_title(batch),
'execute_enabled': self.executable(batch),
}
+ if self.edit_with_rows:
+ context['rows_grid'] = grid
if context['execute_enabled'] and self.has_execution_options:
context['rendered_execution_options'] = self.render_execution_options(batch)
return self.render_to_response('edit', context)
+ def rows_creatable_for(self, batch):
+ """
+ Only allow creating new rows on a batch if it hasn't yet been executed.
+ """
+ return not batch.executed
+
def create_row(self):
"""
Only allow creating a new row if the batch hasn't yet been executed.
@@ -344,9 +353,11 @@ class BatchMasterView(MasterView):
def make_default_row_grid_tools(self, batch):
if self.rows_creatable and not batch.executed:
- link = tags.link_to("Create a new {}".format(self.get_row_model_title()),
- self.get_action_url('create_row', batch))
- return HTML.tag('p', c=link)
+ permission_prefix = self.get_permission_prefix()
+ if self.request.has_perm('{}.create_row'.format(permission_prefix)):
+ link = tags.link_to("Create a new {}".format(self.get_row_model_title()),
+ self.get_action_url('create_row', batch))
+ return HTML.tag('p', c=link)
def make_batch_row_grid_tools(self, batch):
if not batch.executed:
@@ -358,12 +369,13 @@ class BatchMasterView(MasterView):
def redirect_after_edit(self, batch):
"""
- Redirect back to edit batch page after editing a batch, unless the
- refresh flag is set, in which case do that.
+ If refresh flag is set, do that; otherwise go (back) to view/edit page.
"""
if self.request.params.get('refresh') == 'true':
return self.redirect(self.get_action_url('refresh', batch))
- return self.redirect(self.request.current_route_url())
+ if self.edit_with_rows:
+ return self.redirect(self.get_action_url('edit', batch))
+ return self.redirect(self.get_action_url('view', batch))
def delete_instance(self, batch):
"""
diff --git a/tailbone/views/master.py b/tailbone/views/master.py
index ecbc357e..0d0e096b 100644
--- a/tailbone/views/master.py
+++ b/tailbone/views/master.py
@@ -1078,6 +1078,7 @@ class MasterView(View):
'instance_title': self.get_row_instance_title(row),
'instance_editable': self.row_editable(row),
'instance_deletable': self.row_deletable(row),
+ 'rows_creatable': self.rows_creatable and self.rows_creatable_for(parent),
'model_title': self.get_row_model_title(),
'model_title_plural': self.get_row_model_title_plural(),
'parent_model_title': self.get_model_title(),
@@ -1088,6 +1089,13 @@ class MasterView(View):
'action_url': self.get_row_action_url,
'form': form})
+ def rows_creatable_for(self, instance):
+ """
+ Returns boolean indicating whether or not the given instance should
+ allow new rows to be added to it.
+ """
+ return True
+
def edit_row(self):
"""
View for editing an existing model record.
diff --git a/tailbone/views/purchases/batch.py b/tailbone/views/purchases/batch.py
index 7d8db1d1..3b21f21e 100644
--- a/tailbone/views/purchases/batch.py
+++ b/tailbone/views/purchases/batch.py
@@ -51,6 +51,7 @@ class PurchaseBatchView(BatchMasterView):
url_prefix = '/purchases/batches'
rows_creatable = True
rows_editable = True
+ edit_with_rows = False
def _preconfigure_grid(self, g):
super(PurchaseBatchView, self)._preconfigure_grid(g)
@@ -65,6 +66,10 @@ class PurchaseBatchView(BatchMasterView):
default_active=True, default_verb='contains')
g.sorters['buyer'] = g.make_sorter(model.Person.display_name)
+ if self.request.has_perm('purchases.batch.execute'):
+ g.filters['complete'].default_active = True
+ g.filters['complete'].default_verb = 'is_true'
+
g.date_ordered.set(label="Ordered")
def configure_grid(self, g):
@@ -82,26 +87,31 @@ class PurchaseBatchView(BatchMasterView):
def _preconfigure_fieldset(self, fs):
super(PurchaseBatchView, self)._preconfigure_fieldset(fs)
+ fs.vendor.set(renderer=forms.renderers.VendorFieldRenderer)
+ fs.buyer.set(renderer=forms.renderers.EmployeeFieldRenderer)
fs.po_number.set(label="PO Number")
- fs.po_total.set(label="PO Total")
+ fs.po_total.set(label="PO Total", readonly=True)
def configure_fieldset(self, fs):
fs.configure(
include=[
+ fs.id,
fs.store,
- fs.vendor.with_renderer(forms.renderers.VendorFieldRenderer),
- fs.buyer.with_renderer(forms.renderers.EmployeeFieldRenderer),
+ fs.vendor,
+ fs.buyer,
fs.date_ordered,
fs.po_number,
fs.po_total,
fs.created,
fs.created_by,
+ fs.complete,
fs.executed,
fs.executed_by,
])
if self.creating:
del fs.po_total
+ del fs.complete
# default store may be configured
store = self.rattail_config.get('rattail', 'store')
@@ -119,6 +129,10 @@ class PurchaseBatchView(BatchMasterView):
# default order date is today
fs.model.date_ordered = localtime(self.rattail_config).date()
+ elif self.editing:
+ fs.store.set(readonly=True)
+ fs.vendor.set(readonly=True)
+
def template_kwargs_view(self, **kwargs):
kwargs = super(PurchaseBatchView, self).template_kwargs_view(**kwargs)
vendor = kwargs['batch'].vendor