Add initial/basic views for customer orders data
This commit is contained in:
parent
9b85a77695
commit
e0521ba8c5
|
@ -46,4 +46,6 @@ from .products import (GPCFieldRenderer, ScancodeFieldRenderer,
|
||||||
BrandFieldRenderer, ProductFieldRenderer,
|
BrandFieldRenderer, ProductFieldRenderer,
|
||||||
PriceFieldRenderer, PriceWithExpirationFieldRenderer)
|
PriceFieldRenderer, PriceWithExpirationFieldRenderer)
|
||||||
|
|
||||||
|
from .custorders import CustomerOrderFieldRenderer
|
||||||
|
|
||||||
from .batch import BatchIDFieldRenderer, HandheldBatchFieldRenderer
|
from .batch import BatchIDFieldRenderer, HandheldBatchFieldRenderer
|
||||||
|
|
|
@ -67,9 +67,16 @@ class DateFieldRenderer(CustomFieldRenderer, fa.DateFieldRenderer):
|
||||||
"""
|
"""
|
||||||
change_year = False
|
change_year = False
|
||||||
|
|
||||||
def init(self, change_year=False):
|
def init(self, date_format=None, change_year=False):
|
||||||
|
self.date_format = date_format
|
||||||
self.change_year = change_year
|
self.change_year = change_year
|
||||||
|
|
||||||
|
def render_readonly(self, **kwargs):
|
||||||
|
value = self.raw_value
|
||||||
|
if value is None:
|
||||||
|
return ''
|
||||||
|
return value.strftime(self.date_format)
|
||||||
|
|
||||||
def render(self, **kwargs):
|
def render(self, **kwargs):
|
||||||
kwargs['name'] = self.name
|
kwargs['name'] = self.name
|
||||||
kwargs['value'] = self.value
|
kwargs['value'] = self.value
|
||||||
|
|
42
tailbone/forms/renderers/custorders.py
Normal file
42
tailbone/forms/renderers/custorders.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Rattail -- Retail Software Framework
|
||||||
|
# Copyright © 2010-2017 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Rattail.
|
||||||
|
#
|
||||||
|
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||||
|
# terms of the GNU Affero General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||||
|
# more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Customer order field renderers
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
|
import formalchemy as fa
|
||||||
|
from webhelpers.html import tags
|
||||||
|
|
||||||
|
|
||||||
|
class CustomerOrderFieldRenderer(fa.fields.SelectFieldRenderer):
|
||||||
|
"""
|
||||||
|
Renders a link to the customer order
|
||||||
|
"""
|
||||||
|
|
||||||
|
def render_readonly(self, **kwargs):
|
||||||
|
order = self.raw_value
|
||||||
|
if not order:
|
||||||
|
return ''
|
||||||
|
return tags.link_to(order, self.request.route_url('custorders.view', uuid=order.uuid))
|
32
tailbone/views/custorders/__init__.py
Normal file
32
tailbone/views/custorders/__init__.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Rattail -- Retail Software Framework
|
||||||
|
# Copyright © 2010-2017 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Rattail.
|
||||||
|
#
|
||||||
|
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||||
|
# terms of the GNU Affero General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||||
|
# more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Customer Order Views
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
config.include('tailbone.views.custorders.orders')
|
||||||
|
config.include('tailbone.views.custorders.items')
|
171
tailbone/views/custorders/items.py
Normal file
171
tailbone/views/custorders/items.py
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Rattail -- Retail Software Framework
|
||||||
|
# Copyright © 2010-2017 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Rattail.
|
||||||
|
#
|
||||||
|
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||||
|
# terms of the GNU Affero General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||||
|
# more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Customer order item views
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from sqlalchemy import orm
|
||||||
|
|
||||||
|
from rattail.db import model
|
||||||
|
from rattail.time import localtime
|
||||||
|
|
||||||
|
import formalchemy as fa
|
||||||
|
|
||||||
|
from tailbone import forms
|
||||||
|
from tailbone.views import MasterView
|
||||||
|
|
||||||
|
|
||||||
|
class CustomerOrderItemsView(MasterView):
|
||||||
|
"""
|
||||||
|
Master view for customer order items
|
||||||
|
"""
|
||||||
|
model_class = model.CustomerOrderItem
|
||||||
|
route_prefix = 'custorders.items'
|
||||||
|
url_prefix = '/custorders/items'
|
||||||
|
creatable = False
|
||||||
|
editable = False
|
||||||
|
deletable = False
|
||||||
|
|
||||||
|
has_rows = True
|
||||||
|
model_row_class = model.CustomerOrderItemEvent
|
||||||
|
rows_title = "Event History"
|
||||||
|
rows_filterable = False
|
||||||
|
rows_sortable = False
|
||||||
|
rows_pageable = False
|
||||||
|
rows_viewable = False
|
||||||
|
|
||||||
|
def query(self, session):
|
||||||
|
return session.query(model.CustomerOrderItem)\
|
||||||
|
.join(model.CustomerOrder)\
|
||||||
|
.options(orm.joinedload(model.CustomerOrderItem.order)\
|
||||||
|
.joinedload(model.CustomerOrder.person))
|
||||||
|
|
||||||
|
def _preconfigure_grid(self, g):
|
||||||
|
|
||||||
|
g.joiners['person'] = lambda q: q.outerjoin(model.Person)
|
||||||
|
g.filters['person'] = g.make_filter('person', model.Person.display_name, label="Person Name",
|
||||||
|
default_active=True, default_verb='contains')
|
||||||
|
g.sorters['person'] = g.make_sorter(model.Person.display_name)
|
||||||
|
|
||||||
|
g.filters['product_brand'].label = "Brand"
|
||||||
|
g.product_brand.set(label="Brand")
|
||||||
|
|
||||||
|
g.filters['product_description'].label = "Description"
|
||||||
|
g.product_description.set(label="Description")
|
||||||
|
|
||||||
|
g.filters['product_size'].label = "Size"
|
||||||
|
g.product_size.set(label="Size")
|
||||||
|
|
||||||
|
g.case_quantity.set(renderer=forms.renderers.QuantityFieldRenderer)
|
||||||
|
g.cases_ordered.set(renderer=forms.renderers.QuantityFieldRenderer)
|
||||||
|
g.units_ordered.set(renderer=forms.renderers.QuantityFieldRenderer)
|
||||||
|
|
||||||
|
g.total_price.set(renderer=forms.renderers.CurrencyFieldRenderer)
|
||||||
|
|
||||||
|
g.status_code.set(label="Status")
|
||||||
|
|
||||||
|
g.append(fa.Field('person', value=lambda i: i.order.person))
|
||||||
|
|
||||||
|
g.sorters['order_created'] = g.make_sorter(model.CustomerOrder.created)
|
||||||
|
g.append(fa.Field('order_created',
|
||||||
|
value=lambda i: localtime(self.rattail_config, i.order.created, from_utc=True),
|
||||||
|
renderer=forms.renderers.DateTimeFieldRenderer))
|
||||||
|
|
||||||
|
g.default_sortkey = 'order_created'
|
||||||
|
g.default_sortdir = 'desc'
|
||||||
|
|
||||||
|
def configure_grid(self, g):
|
||||||
|
g.configure(
|
||||||
|
include=[
|
||||||
|
g.person,
|
||||||
|
g.product_brand,
|
||||||
|
g.product_description,
|
||||||
|
g.product_size,
|
||||||
|
g.case_quantity,
|
||||||
|
g.cases_ordered,
|
||||||
|
g.units_ordered,
|
||||||
|
g.order_created,
|
||||||
|
g.status_code,
|
||||||
|
],
|
||||||
|
readonly=True)
|
||||||
|
|
||||||
|
def _preconfigure_fieldset(self, fs):
|
||||||
|
fs.order.set(renderer=forms.renderers.CustomerOrderFieldRenderer)
|
||||||
|
fs.product.set(renderer=forms.renderers.ProductFieldRenderer)
|
||||||
|
fs.product_unit_of_measure.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.UNIT_OF_MEASURE))
|
||||||
|
fs.case_quantity.set(renderer=forms.renderers.QuantityFieldRenderer)
|
||||||
|
fs.cases_ordered.set(renderer=forms.renderers.QuantityFieldRenderer)
|
||||||
|
fs.units_ordered.set(renderer=forms.renderers.QuantityFieldRenderer)
|
||||||
|
fs.unit_price.set(renderer=forms.renderers.CurrencyFieldRenderer)
|
||||||
|
fs.total_price.set(renderer=forms.renderers.CurrencyFieldRenderer)
|
||||||
|
fs.paid_amount.set(renderer=forms.renderers.CurrencyFieldRenderer)
|
||||||
|
fs.status_code.set(label="Status")
|
||||||
|
fs.append(fa.Field('person', value=lambda i: i.order.person,
|
||||||
|
renderer=forms.renderers.PersonFieldRenderer))
|
||||||
|
|
||||||
|
def configure_fieldset(self, fs):
|
||||||
|
fs.configure(
|
||||||
|
include=[
|
||||||
|
fs.person,
|
||||||
|
fs.product,
|
||||||
|
fs.product_brand,
|
||||||
|
fs.product_description,
|
||||||
|
fs.product_size,
|
||||||
|
fs.case_quantity,
|
||||||
|
fs.cases_ordered,
|
||||||
|
fs.units_ordered,
|
||||||
|
fs.unit_price,
|
||||||
|
fs.total_price,
|
||||||
|
fs.paid_amount,
|
||||||
|
fs.status_code,
|
||||||
|
])
|
||||||
|
|
||||||
|
def get_row_data(self, item):
|
||||||
|
return self.Session.query(model.CustomerOrderItemEvent)\
|
||||||
|
.filter(model.CustomerOrderItemEvent.item == item)\
|
||||||
|
.order_by(model.CustomerOrderItemEvent.occurred,
|
||||||
|
model.CustomerOrderItemEvent.type_code)
|
||||||
|
|
||||||
|
def _preconfigure_row_grid(self, g):
|
||||||
|
g.occurred.set(label="When")
|
||||||
|
g.type_code.set(label="What") # TODO: enum renderer
|
||||||
|
g.user.set(label="Who")
|
||||||
|
g.note.set(label="Notes")
|
||||||
|
|
||||||
|
def configure_row_grid(self, g):
|
||||||
|
g.configure(
|
||||||
|
include=[
|
||||||
|
g.occurred,
|
||||||
|
g.type_code,
|
||||||
|
g.user,
|
||||||
|
g.note,
|
||||||
|
],
|
||||||
|
readonly=True)
|
||||||
|
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
CustomerOrderItemsView.defaults(config)
|
106
tailbone/views/custorders/orders.py
Normal file
106
tailbone/views/custorders/orders.py
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Rattail -- Retail Software Framework
|
||||||
|
# Copyright © 2010-2017 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Rattail.
|
||||||
|
#
|
||||||
|
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||||
|
# terms of the GNU Affero General Public License as published by the Free
|
||||||
|
# Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||||
|
# more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Customer Order Views
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
|
from sqlalchemy import orm
|
||||||
|
|
||||||
|
from rattail.db import model
|
||||||
|
|
||||||
|
from tailbone import forms
|
||||||
|
from tailbone.db import Session
|
||||||
|
from tailbone.views import MasterView
|
||||||
|
from tailbone.newgrids.filters import ChoiceValueRenderer
|
||||||
|
|
||||||
|
|
||||||
|
class CustomerOrdersView(MasterView):
|
||||||
|
"""
|
||||||
|
Master view for customer orders
|
||||||
|
"""
|
||||||
|
model_class = model.CustomerOrder
|
||||||
|
route_prefix = 'custorders'
|
||||||
|
creatable = False
|
||||||
|
editable = False
|
||||||
|
deletable = False
|
||||||
|
|
||||||
|
def query(self, session):
|
||||||
|
return session.query(model.CustomerOrder)\
|
||||||
|
.options(orm.joinedload(model.CustomerOrder.customer))
|
||||||
|
|
||||||
|
def _preconfigure_grid(self, g):
|
||||||
|
g.joiners['customer'] = lambda q: q.outerjoin(model.Customer)
|
||||||
|
g.sorters['customer'] = g.make_sorter(model.Customer.name)
|
||||||
|
g.filters['customer'] = g.make_filter('customer', model.Customer.name,
|
||||||
|
label="Customer Name",
|
||||||
|
default_active=True,
|
||||||
|
default_verb='contains')
|
||||||
|
|
||||||
|
g.joiners['person'] = lambda q: q.outerjoin(model.Person)
|
||||||
|
g.sorters['person'] = g.make_sorter(model.Person.display_name)
|
||||||
|
g.filters['person'] = g.make_filter('person', model.Person.display_name,
|
||||||
|
label="Person Name",
|
||||||
|
default_active=True,
|
||||||
|
default_verb='contains')
|
||||||
|
|
||||||
|
# TODO: enum choices renderer
|
||||||
|
g.filters['status_code'].label = "Status"
|
||||||
|
g.status_code.set(label="Status")
|
||||||
|
|
||||||
|
g.id.set(label="ID")
|
||||||
|
g.default_sortkey = 'created'
|
||||||
|
g.default_sortdir = 'desc'
|
||||||
|
|
||||||
|
def configure_grid(self, g):
|
||||||
|
g.configure(
|
||||||
|
include=[
|
||||||
|
g.id,
|
||||||
|
g.customer,
|
||||||
|
g.person,
|
||||||
|
g.created,
|
||||||
|
g.status_code,
|
||||||
|
],
|
||||||
|
readonly=True)
|
||||||
|
|
||||||
|
def _preconfigure_fieldset(self, fs):
|
||||||
|
fs.customer.set(options=[])
|
||||||
|
fs.id.set(label="ID", readonly=True)
|
||||||
|
fs.person.set(renderer=forms.renderers.PersonFieldRenderer)
|
||||||
|
fs.created.set(readonly=True)
|
||||||
|
fs.status_code.set(label="Status")
|
||||||
|
|
||||||
|
def configure_fieldset(self, fs):
|
||||||
|
fs.configure(
|
||||||
|
include=[
|
||||||
|
fs.id,
|
||||||
|
fs.customer,
|
||||||
|
fs.person,
|
||||||
|
fs.created,
|
||||||
|
fs.status_code,
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
CustomerOrdersView.defaults(config)
|
Loading…
Reference in a new issue