From dfb5e83c7e9b4a9ae7aea5572507f739df490e37 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 10 Sep 2014 19:38:49 -0700 Subject: [PATCH] Add support for `Product.not_for_sale` flag. This involved a couple of ancillary changes: * The price field renderer will not display a price for products marked not for sale. * The "grid" class now allows specifying a custom callable to provide additional CSS class for table rows. * The products grid uses this to add a "not-for-sale" class to table rows for products which are marked thusly. --- tailbone/forms/renderers/products.py | 34 +++++++++++++++------------- tailbone/grids/core.py | 21 +++++++++++++---- tailbone/views/products.py | 5 +++- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/tailbone/forms/renderers/products.py b/tailbone/forms/renderers/products.py index 52916543..dd9deb1b 100644 --- a/tailbone/forms/renderers/products.py +++ b/tailbone/forms/renderers/products.py @@ -1,9 +1,8 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2012 Lance Edgar +# Copyright © 2010-2014 Lance Edgar # # This file is part of Rattail. # @@ -26,6 +25,8 @@ Product Field Renderers """ +from __future__ import unicode_literals + from formalchemy import TextFieldRenderer from rattail.gpc import GPC from .common import AutocompleteFieldRenderer @@ -88,19 +89,20 @@ class PriceFieldRenderer(TextFieldRenderer): def render_readonly(self, **kwargs): price = self.field.raw_value if price: - if price.price is not None and price.pack_price is not None: - if price.multiple > 1: - return literal('$ %0.2f / %u  ($ %0.2f / %u)' % ( - price.price, price.multiple, - price.pack_price, price.pack_multiple)) - return literal('$ %0.2f  ($ %0.2f / %u)' % ( - price.price, price.pack_price, price.pack_multiple)) - if price.price is not None: - if price.multiple > 1: - return '$ %0.2f / %u' % (price.price, price.multiple) - return '$ %0.2f' % price.price - if price.pack_price is not None: - return '$ %0.2f / %u' % (price.pack_price, price.pack_multiple) + if not price.product.not_for_sale: + if price.price is not None and price.pack_price is not None: + if price.multiple > 1: + return literal('$ %0.2f / %u  ($ %0.2f / %u)' % ( + price.price, price.multiple, + price.pack_price, price.pack_multiple)) + return literal('$ %0.2f  ($ %0.2f / %u)' % ( + price.price, price.pack_price, price.pack_multiple)) + if price.price is not None: + if price.multiple > 1: + return '$ %0.2f / %u' % (price.price, price.multiple) + return '$ %0.2f' % price.price + if price.pack_price is not None: + return '$ %0.2f / %u' % (price.pack_price, price.pack_multiple) return '' diff --git a/tailbone/grids/core.py b/tailbone/grids/core.py index 00667e22..1fad4b14 100644 --- a/tailbone/grids/core.py +++ b/tailbone/grids/core.py @@ -61,6 +61,9 @@ class Grid(Object): delete_route_name = None delete_route_kwargs = None + # Set this to a callable to allow ad-hoc row class additions. + extra_row_class = None + def __init__(self, request, **kwargs): kwargs.setdefault('fields', OrderedDict()) kwargs.setdefault('column_titles', {}) @@ -118,6 +121,20 @@ class Grid(Object): attrs = self.row_attrs(row, i) return format_attrs(**attrs) + def row_attrs(self, row, i): + return {'class_': self.get_row_class(row, i)} + + def get_row_class(self, row, i): + class_ = self.default_row_class(row, i) + if callable(self.extra_row_class): + extra = self.extra_row_class(row, i) + if extra: + class_ = '{0} {1}'.format(class_, extra) + return class_ + + def default_row_class(self, row, i): + return 'odd' if i % 2 else 'even' + def iter_fields(self): return self.fields.itervalues() @@ -130,7 +147,3 @@ class Grid(Object): def render_field(self, field): raise NotImplementedError - - def row_attrs(self, row, i): - attrs = {'class_': 'odd' if i % 2 else 'even'} - return attrs diff --git a/tailbone/views/products.py b/tailbone/views/products.py index efa208db..ba317172 100644 --- a/tailbone/views/products.py +++ b/tailbone/views/products.py @@ -190,7 +190,9 @@ class ProductsGrid(SearchableAlchemyGridView): return q def grid(self): - g = self.make_grid() + def extra_row_class(row, i): + return 'not-for-sale' if row.not_for_sale else None + g = self.make_grid(extra_row_class=extra_row_class) g.upc.set(renderer=GPCFieldRenderer) g.regular_price.set(renderer=PriceFieldRenderer) g.current_price.set(renderer=PriceFieldRenderer) @@ -264,6 +266,7 @@ class ProductCrud(CrudView): fs.report_code, fs.regular_price, fs.current_price, + fs.not_for_sale, ]) if not self.readonly: del fs.regular_price