Compare commits
3 commits
3f27f626df
...
20b3f87dbe
Author | SHA1 | Date | |
---|---|---|---|
20b3f87dbe | |||
9e55717041 | |||
772b6610cb |
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -27,6 +27,8 @@ Tools for displaying data diffs
|
|||
import sqlalchemy as sa
|
||||
import sqlalchemy_continuum as continuum
|
||||
|
||||
from rattail.enum import CONTINUUM_OPERATION
|
||||
|
||||
from pyramid.renderers import render
|
||||
from webhelpers2.html import HTML
|
||||
|
||||
|
@ -273,6 +275,8 @@ class VersionDiff(Diff):
|
|||
return {
|
||||
'key': id(self.version),
|
||||
'model_title': self.title,
|
||||
'operation': CONTINUUM_OPERATION.get(self.version.operation_type,
|
||||
self.version.operation_type),
|
||||
'diff_class': self.nature,
|
||||
'fields': self.fields,
|
||||
'values': values,
|
||||
|
|
|
@ -394,6 +394,11 @@ class TailboneMenuHandler(WuttaMenuHandler):
|
|||
'route': 'products',
|
||||
'perm': 'products.list',
|
||||
},
|
||||
{
|
||||
'title': "Product Costs",
|
||||
'route': 'product_costs',
|
||||
'perm': 'product_costs.list',
|
||||
},
|
||||
{
|
||||
'title': "Departments",
|
||||
'route': 'departments',
|
||||
|
@ -451,6 +456,11 @@ class TailboneMenuHandler(WuttaMenuHandler):
|
|||
'route': 'vendors',
|
||||
'perm': 'vendors.list',
|
||||
},
|
||||
{
|
||||
'title': "Product Costs",
|
||||
'route': 'product_costs',
|
||||
'perm': 'product_costs.list',
|
||||
},
|
||||
{'type': 'sep'},
|
||||
{
|
||||
'title': "Ordering",
|
||||
|
|
|
@ -196,6 +196,7 @@
|
|||
|
||||
<p class="block has-text-weight-bold">
|
||||
{{ version.model_title }}
|
||||
({{ version.operation }})
|
||||
</p>
|
||||
|
||||
<table class="diff monospace is-size-7"
|
||||
|
|
|
@ -903,7 +903,7 @@ class MasterView(View):
|
|||
|
||||
def valid_employee_uuid(self, node, value):
|
||||
if value:
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
employee = self.Session.get(model.Employee, value)
|
||||
if not employee:
|
||||
node.raise_invalid("Employee not found")
|
||||
|
@ -939,7 +939,7 @@ class MasterView(View):
|
|||
|
||||
def valid_vendor_uuid(self, node, value):
|
||||
if value:
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
vendor = self.Session.get(model.Vendor, value)
|
||||
if not vendor:
|
||||
node.raise_invalid("Vendor not found")
|
||||
|
@ -1382,7 +1382,7 @@ class MasterView(View):
|
|||
return classes
|
||||
|
||||
def make_revisions_grid(self, obj, empty_data=False):
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
row_url = lambda txn, i: self.request.route_url(f'{route_prefix}.version',
|
||||
uuid=obj.uuid,
|
||||
|
@ -2153,7 +2153,7 @@ class MasterView(View):
|
|||
Thread target for executing an object.
|
||||
"""
|
||||
app = self.get_rattail_app()
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
session = app.make_session()
|
||||
obj = self.get_instance_for_key(key, session)
|
||||
user = session.get(model.User, user_uuid)
|
||||
|
@ -2594,7 +2594,7 @@ class MasterView(View):
|
|||
"""
|
||||
# nb. self.Session may differ, so use tailbone.db.Session
|
||||
session = Session()
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
info = session.query(model.TailbonePageHelp)\
|
||||
|
@ -2617,7 +2617,7 @@ class MasterView(View):
|
|||
"""
|
||||
# nb. self.Session may differ, so use tailbone.db.Session
|
||||
session = Session()
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
info = session.query(model.TailbonePageHelp)\
|
||||
|
@ -2639,7 +2639,7 @@ class MasterView(View):
|
|||
|
||||
# nb. self.Session may differ, so use tailbone.db.Session
|
||||
session = Session()
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
schema = colander.Schema()
|
||||
|
||||
|
@ -2673,7 +2673,7 @@ class MasterView(View):
|
|||
|
||||
# nb. self.Session may differ, so use tailbone.db.Session
|
||||
session = Session()
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
route_prefix = self.get_route_prefix()
|
||||
schema = colander.Schema()
|
||||
|
||||
|
@ -5541,7 +5541,7 @@ class MasterView(View):
|
|||
input_file_templates=True,
|
||||
output_file_templates=True):
|
||||
app = self.get_rattail_app()
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
names = []
|
||||
|
||||
if simple_settings is None:
|
||||
|
@ -6100,7 +6100,7 @@ class MasterView(View):
|
|||
renderer='json')
|
||||
|
||||
|
||||
class ViewSupplement(object):
|
||||
class ViewSupplement:
|
||||
"""
|
||||
Base class for view "supplements" - which are sort of like plugins
|
||||
which can "supplement" certain aspects of the view.
|
||||
|
@ -6127,6 +6127,7 @@ class ViewSupplement(object):
|
|||
def __init__(self, master):
|
||||
self.master = master
|
||||
self.request = master.request
|
||||
self.app = master.app
|
||||
self.model = master.model
|
||||
self.rattail_config = master.rattail_config
|
||||
self.Session = master.Session
|
||||
|
@ -6160,7 +6161,7 @@ class ViewSupplement(object):
|
|||
This is accomplished by subjecting the current base query to a
|
||||
join, e.g. something like::
|
||||
|
||||
model = self.model
|
||||
model = self.app.model
|
||||
query = query.outerjoin(model.MyExtension)
|
||||
return query
|
||||
"""
|
||||
|
|
|
@ -34,7 +34,7 @@ import sqlalchemy_continuum as continuum
|
|||
|
||||
from rattail import enum, pod, sil
|
||||
from rattail.db import api, auth, Session as RattailSession
|
||||
from rattail.db.model import Product, PendingProduct, CustomerOrderItem
|
||||
from rattail.db.model import Product, PendingProduct, ProductCost, CustomerOrderItem
|
||||
from rattail.gpc import GPC
|
||||
from rattail.threads import Thread
|
||||
from rattail.exceptions import LabelPrintingError
|
||||
|
@ -2668,6 +2668,78 @@ class PendingProductView(MasterView):
|
|||
permission=f'{permission_prefix}.ignore_product')
|
||||
|
||||
|
||||
class ProductCostView(MasterView):
|
||||
"""
|
||||
Master view for Product Costs
|
||||
"""
|
||||
model_class = ProductCost
|
||||
route_prefix = 'product_costs'
|
||||
url_prefix = '/products/costs'
|
||||
has_versions = True
|
||||
|
||||
grid_columns = [
|
||||
'_product_key_',
|
||||
'vendor',
|
||||
'preference',
|
||||
'code',
|
||||
'case_size',
|
||||
'case_cost',
|
||||
'pack_size',
|
||||
'pack_cost',
|
||||
'unit_cost',
|
||||
]
|
||||
|
||||
def query(self, session):
|
||||
""" """
|
||||
query = super().query(session)
|
||||
model = self.app.model
|
||||
|
||||
# always join on Product
|
||||
return query.join(model.Product)
|
||||
|
||||
def configure_grid(self, g):
|
||||
""" """
|
||||
super().configure_grid(g)
|
||||
model = self.app.model
|
||||
|
||||
# product key
|
||||
field = self.get_product_key_field()
|
||||
g.set_renderer(field, self.render_product_key)
|
||||
g.set_sorter(field, getattr(model.Product, field))
|
||||
g.set_sort_defaults(field)
|
||||
g.set_filter(field, getattr(model.Product, field))
|
||||
|
||||
# vendor
|
||||
g.set_joiner('vendor', lambda q: q.join(model.Vendor))
|
||||
g.set_sorter('vendor', model.Vendor.name)
|
||||
g.set_filter('vendor', model.Vendor.name, label="Vendor Name")
|
||||
|
||||
def render_product_key(self, cost, field):
|
||||
""" """
|
||||
handler = self.app.get_products_handler()
|
||||
return handler.render_product_key(cost.product)
|
||||
|
||||
def configure_form(self, f):
|
||||
""" """
|
||||
super().configure_form(f)
|
||||
|
||||
# product
|
||||
f.set_renderer('product', self.render_product)
|
||||
if 'product_uuid' in f and 'product' in f:
|
||||
f.remove('product')
|
||||
f.replace('product_uuid', 'product')
|
||||
|
||||
# vendor
|
||||
f.set_renderer('vendor', self.render_vendor)
|
||||
if 'vendor_uuid' in f and 'vendor' in f:
|
||||
f.remove('vendor')
|
||||
f.replace('vendor_uuid', 'vendor')
|
||||
|
||||
# futures
|
||||
# TODO: should eventually show a subgrid here?
|
||||
f.remove('futures')
|
||||
|
||||
|
||||
def defaults(config, **kwargs):
|
||||
base = globals()
|
||||
|
||||
|
@ -2677,6 +2749,9 @@ def defaults(config, **kwargs):
|
|||
PendingProductView = kwargs.get('PendingProductView', base['PendingProductView'])
|
||||
PendingProductView.defaults(config)
|
||||
|
||||
ProductCostView = kwargs.get('ProductCostView', base['ProductCostView'])
|
||||
ProductCostView.defaults(config)
|
||||
|
||||
|
||||
def includeme(config):
|
||||
defaults(config)
|
||||
|
|
Loading…
Reference in a new issue