# -*- coding: utf-8; -*-
################################################################################
#
# Sideshow -- Case/Special Order Tracker
# Copyright © 2024 Lance Edgar
#
# This file is part of Sideshow.
#
# Sideshow is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Sideshow 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
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Sideshow. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Views for Customers
"""
from wuttaweb.views import MasterView
from wuttaweb.forms.schema import UserRef, WuttaEnum
from sideshow.db.model import LocalCustomer, PendingCustomer
[docs]
class LocalCustomerView(MasterView):
"""
Master view for
:class:`~sideshow.db.model.customers.LocalCustomer`; route prefix
is ``local_customers``.
Notable URLs provided by this class:
* ``/local/customers/``
* ``/local/customers/new``
* ``/local/customers/XXX``
* ``/local/customers/XXX/edit``
* ``/local/customers/XXX/delete``
"""
model_class = LocalCustomer
model_title = "Local Customer"
route_prefix = 'local_customers'
url_prefix = '/local/customers'
labels = {
'external_id': "External ID",
}
grid_columns = [
'external_id',
'full_name',
'first_name',
'last_name',
'phone_number',
'email_address',
]
sort_defaults = 'full_name'
form_fields = [
'external_id',
'full_name',
'first_name',
'last_name',
'phone_number',
'email_address',
'orders',
'new_order_batches',
]
def configure_grid(self, g):
""" """
super().configure_grid(g)
# links
g.set_link('full_name')
g.set_link('first_name')
g.set_link('last_name')
g.set_link('phone_number')
g.set_link('email_address')
def configure_form(self, f):
""" """
super().configure_form(f)
customer = f.model_instance
# external_id
if self.creating:
f.remove('external_id')
else:
f.set_readonly('external_id')
# full_name
if self.creating or self.editing:
f.remove('full_name')
# orders
if self.creating or self.editing:
f.remove('orders')
else:
f.set_grid('orders', self.make_orders_grid(customer))
# new_order_batches
if self.creating or self.editing:
f.remove('new_order_batches')
else:
f.set_grid('new_order_batches', self.make_new_order_batches_grid(customer))
[docs]
def make_orders_grid(self, customer):
"""
Make and return the grid for the Orders field.
"""
model = self.app.model
route_prefix = self.get_route_prefix()
grid = self.make_grid(key=f'{route_prefix}.view.orders',
model_class=model.Order,
data=customer.orders,
columns=[
'order_id',
'total_price',
'created',
'created_by',
],
labels={
'order_id': "Order ID",
})
grid.set_renderer('total_price', grid.render_currency)
if self.request.has_perm('orders.view'):
url = lambda order, i: self.request.route_url('orders.view', uuid=order.uuid)
grid.add_action('view', icon='eye', url=url)
grid.set_link('order_id')
return grid
[docs]
def make_new_order_batches_grid(self, customer):
"""
Make and return the grid for the New Order Batches field.
"""
model = self.app.model
route_prefix = self.get_route_prefix()
grid = self.make_grid(key=f'{route_prefix}.view.new_order_batches',
model_class=model.NewOrderBatch,
data=customer.new_order_batches,
columns=[
'id',
'total_price',
'created',
'created_by',
'executed',
],
labels={
'id': "Batch ID",
},
renderers={
'id': 'batch_id',
'total_price': 'currency',
})
if self.request.has_perm('neworder_batches.view'):
url = lambda batch, i: self.request.route_url('neworder_batches.view', uuid=batch.uuid)
grid.add_action('view', icon='eye', url=url)
grid.set_link('id')
return grid
def objectify(self, form):
""" """
enum = self.app.enum
customer = super().objectify(form)
customer.full_name = self.app.make_full_name(customer.first_name,
customer.last_name)
return customer
[docs]
class PendingCustomerView(MasterView):
"""
Master view for
:class:`~sideshow.db.model.customers.PendingCustomer`; route
prefix is ``pending_customers``.
Notable URLs provided by this class:
* ``/pending/customers/``
* ``/pending/customers/new``
* ``/pending/customers/XXX``
* ``/pending/customers/XXX/edit``
* ``/pending/customers/XXX/delete``
"""
model_class = PendingCustomer
model_title = "Pending Customer"
route_prefix = 'pending_customers'
url_prefix = '/pending/customers'
labels = {
'customer_id': "Customer ID",
}
grid_columns = [
'full_name',
'first_name',
'last_name',
'phone_number',
'email_address',
'customer_id',
'status',
'created',
'created_by',
]
sort_defaults = 'full_name'
form_fields = [
'customer_id',
'full_name',
'first_name',
'last_name',
'phone_number',
'email_address',
'status',
'created',
'created_by',
'orders',
'new_order_batches',
]
def configure_grid(self, g):
""" """
super().configure_grid(g)
enum = self.app.enum
# status
g.set_renderer('status', self.grid_render_enum, enum=enum.PendingCustomerStatus)
# links
g.set_link('full_name')
g.set_link('first_name')
g.set_link('last_name')
g.set_link('phone_number')
g.set_link('email_address')
def configure_form(self, f):
""" """
super().configure_form(f)
enum = self.app.enum
customer = f.model_instance
# customer_id
if self.creating:
f.remove('customer_id')
else:
f.set_readonly('customer_id')
# status
if self.creating:
f.remove('status')
else:
f.set_node('status', WuttaEnum(self.request, enum.PendingCustomerStatus))
f.set_readonly('status')
# created
if self.creating:
f.remove('created')
else:
f.set_readonly('created')
# created_by
if self.creating:
f.remove('created_by')
else:
f.set_node('created_by', UserRef(self.request))
f.set_readonly('created_by')
# orders
if self.creating or self.editing:
f.remove('orders')
else:
f.set_grid('orders', self.make_orders_grid(customer))
# new_order_batches
if self.creating or self.editing:
f.remove('new_order_batches')
else:
f.set_grid('new_order_batches', self.make_new_order_batches_grid(customer))
[docs]
def make_orders_grid(self, customer):
"""
Make and return the grid for the Orders field.
"""
model = self.app.model
route_prefix = self.get_route_prefix()
grid = self.make_grid(key=f'{route_prefix}.view.orders',
model_class=model.Order,
data=customer.orders,
columns=[
'order_id',
'total_price',
'created',
'created_by',
],
labels={
'order_id': "Order ID",
})
grid.set_renderer('total_price', grid.render_currency)
if self.request.has_perm('orders.view'):
url = lambda order, i: self.request.route_url('orders.view', uuid=order.uuid)
grid.add_action('view', icon='eye', url=url)
grid.set_link('order_id')
return grid
[docs]
def make_new_order_batches_grid(self, customer):
"""
Make and return the grid for the New Order Batches field.
"""
model = self.app.model
route_prefix = self.get_route_prefix()
grid = self.make_grid(key=f'{route_prefix}.view.new_order_batches',
model_class=model.NewOrderBatch,
data=customer.new_order_batches,
columns=[
'id',
'total_price',
'created',
'created_by',
'executed',
],
labels={
'id': "Batch ID",
},
renderers={
'id': 'batch_id',
'total_price': 'currency',
})
if self.request.has_perm('neworder_batches.view'):
url = lambda batch, i: self.request.route_url('neworder_batches.view', uuid=batch.uuid)
grid.add_action('view', icon='eye', url=url)
grid.set_link('id')
return grid
def objectify(self, form):
""" """
enum = self.app.enum
customer = super().objectify(form)
if self.creating:
customer.status = enum.PendingCustomerStatus.PENDING
customer.created_by = self.request.user
return customer
def delete_instance(self, customer):
""" """
model_title = self.get_model_title()
# avoid deleting if still referenced by order(s)
for order in customer.orders:
self.request.session.flash(f"Cannot delete {model_title} still attached "
"to Order(s)", 'warning')
raise self.redirect(self.get_action_url('view', customer))
# avoid deleting if still referenced by new order batch(es)
for batch in customer.new_order_batches:
if not batch.executed:
self.request.session.flash(f"Cannot delete {model_title} still attached "
"to New Order Batch(es)", 'warning')
raise self.redirect(self.get_action_url('view', customer))
# go ahead and delete per usual
super().delete_instance(customer)
def defaults(config, **kwargs):
base = globals()
LocalCustomerView = kwargs.get('LocalCustomerView', base['LocalCustomerView'])
LocalCustomerView.defaults(config)
PendingCustomerView = kwargs.get('PendingCustomerView', base['PendingCustomerView'])
PendingCustomerView.defaults(config)
def includeme(config):
defaults(config)