Convert master view overrides into view supplements

this fixes for all of the core/native tables.  still have a custom
view for purchases though..
This commit is contained in:
Lance Edgar 2022-12-10 09:14:36 -06:00
parent e307328ee5
commit 6da1568ea2
15 changed files with 184 additions and 438 deletions

View file

@ -74,43 +74,6 @@ class TailboneCorePosProvider(TailboneProvider):
def get_provided_views(self):
return {
'rattail': {
'people': {
'tailbone.views.customers': {
'spec': 'tailbone_corepos.views.customers',
},
'tailbone.views.members': {
'spec': 'tailbone_corepos.views.members',
},
# TODO
# 'tailbone.views.people': {
# 'spec': 'tailbone_corepos.views.people',
# },
},
'products': {
'tailbone.views.departments': {
'spec': 'tailbone_corepos.views.departments',
},
'tailbone.views.products': {
'spec': 'tailbone_corepos.views.products',
},
'tailbone.views.subdepartments': {
'spec': 'tailbone_corepos.views.subdepartments',
},
'tailbone.views.vendors': {
'spec': 'tailbone_corepos.views.vendors',
},
},
'other': {
'tailbone.views.stores': {
'spec': 'tailbone_corepos.views.stores',
},
},
},
'corepos': {
'people': {

View file

@ -1,11 +0,0 @@
## -*- coding: utf-8; -*-
<%inherit file="tailbone:templates/departments/view.mako" />
<%namespace file="/corepos-util.mako" import="render_xref_helper" />
<%def name="object_helpers()">
${parent.object_helpers()}
${render_xref_helper()}
</%def>
${parent.body()}

View file

@ -1,27 +0,0 @@
## -*- coding: utf-8; -*-
<%inherit file="tailbone:templates/people/view_profile_buefy.mako" />
<%def name="render_customer_panel_buttons(customer)">
<b-button type="is-primary"
v-if="customer.view_corepos_url"
tag="a" :href="customer.view_corepos_url" target="_blank"
icon-pack="fas"
icon-left="external-link-alt">
View in CORE Office
</b-button>
${parent.render_customer_panel_buttons(customer)}
</%def>
<%def name="render_member_panel_buttons(member)">
<b-button type="is-primary"
v-if="member.view_corepos_url"
tag="a" :href="member.view_corepos_url" target="_blank"
icon-pack="fas"
icon-left="external-link-alt">
View in CORE Office
</b-button>
${parent.render_member_panel_buttons(member)}
</%def>
${parent.body()}

View file

@ -1,27 +0,0 @@
## -*- coding: utf-8; -*-
<%inherit file="tailbone:templates/products/view.mako" />
<%namespace name="corepos" file="/corepos-util.mako" />
<%def name="object_helpers()">
${parent.object_helpers()}
${self.render_xref_helper()}
</%def>
<%def name="render_xref_helper()">
${corepos.render_xref_helper()}
</%def>
<%def name="render_xref_button()">
${corepos.render_xref_button()}
</%def>
<%def name="extra_main_fields(form)">
${parent.extra_main_fields(form)}
${self.extra_main_fields_corepos(form)}
</%def>
<%def name="extra_main_fields_corepos(form)">
${form.render_field_readonly('corepos_id')}
</%def>
${parent.body()}

View file

@ -1,11 +0,0 @@
## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" />
<%namespace file="/corepos-util.mako" import="render_xref_helper" />
<%def name="object_helpers()">
${parent.object_helpers()}
${render_xref_helper()}
</%def>
${parent.body()}

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2019 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,4 +26,11 @@ Web Views
def includeme(config):
config.include('tailbone_corepos.views.corepos')
config.include('tailbone_corepos.views.customers')
config.include('tailbone_corepos.views.departments')
config.include('tailbone_corepos.views.members')
config.include('tailbone_corepos.views.people')
config.include('tailbone_corepos.views.products')
config.include('tailbone_corepos.views.stores')
config.include('tailbone_corepos.views.subdepartments')
config.include('tailbone_corepos.views.vendors')

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -24,62 +24,35 @@
Customer Views
"""
from tailbone.views import customers as base
from tailbone.views import ViewSupplement
class CustomerView(base.CustomerView):
class CustomerViewSupplement(ViewSupplement):
"""
Master view for the Customer class.
Customer view supplement for CORE integration
"""
route_prefix = 'customers'
labels = {
'corepos_account_id': "CORE-POS Account ID",
}
@property
def form_fields(self):
fields = super(CustomerView, self).form_fields
return fields + [
'corepos_account_id',
]
def query(self, session):
query = super(CustomerView, self).query(session)
model = self.rattail_config.get_model()
def get_grid_query(self, query):
model = self.model
return query.outerjoin(model.CoreCustomer)
def configure_grid(self, g):
super(CustomerView, self).configure_grid(g)
model = self.rattail_config.get_model()
model = self.model
g.set_filter('corepos_account_id', model.CoreCustomer.corepos_account_id)
def configure_form(self, f):
super(CustomerView, self).configure_form(f)
f.set_required('corepos_account_id', False)
def objectify(self, form, data=None):
if data is None:
data = form.validated
customer = form.model_instance
# this field lives in an extension table, but the column does not allow
# null, which means we don't want to pass an empty value along unless
# there is already an extension record in place for this customer
if 'corepos_account_id' in data and data['corepos_account_id'] is None:
if self.creating:
data.pop('corepos_account_id')
elif self.editing and not customer._corepos:
data.pop('corepos_account_id')
return super(CustomerView, self).objectify(form, data)
if not self.master.creating:
f.append('corepos_account_id')
def get_version_child_classes(self):
model = self.rattail_config.get_model()
return super(CustomerView, self).get_version_child_classes() + [
model.CoreCustomer,
]
model = self.model
return [model.CoreCustomer]
def includeme(config):
CustomerView.defaults(config)
base.PendingCustomerView.defaults(config)
CustomerViewSupplement.defaults(config)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,65 +26,41 @@ Department Views
from rattail_corepos.config import core_office_url
from tailbone.views import departments as base
from tailbone.views import ViewSupplement
class DepartmentView(base.DepartmentView):
class DepartmentViewSupplement(ViewSupplement):
"""
Master view for the Department class.
Department view supplement for CORE integration
"""
route_prefix = 'departments'
labels = {
'corepos_number': "CORE-POS Number",
}
@property
def form_fields(self):
fields = super(DepartmentView, self).form_fields
return fields + [
'corepos_number',
]
def query(self, session):
query = super(DepartmentView, self).query(session)
model = self.rattail_config.get_model()
def get_grid_query(self, query):
model = self.model
return query.outerjoin(model.CoreDepartment)
def configure_grid(self, g):
super(DepartmentView, self).configure_grid(g)
model = self.rattail_config.get_model()
model = self.model
g.set_filter('corepos_number', model.CoreDepartment.corepos_number)
def configure_form(self, f):
f.append('corepos_number')
def get_version_child_classes(self):
model = self.rattail_config.get_model()
return super(DepartmentView, self).get_version_child_classes() + [
model.CoreDepartment,
]
model = self.model
return [model.CoreDepartment]
def template_kwargs_view(self, **kwargs):
"""
Supplements the default logic as follows:
Adds the URL for viewing the department within CORE Office, or else the
reason for lack of such a URL.
"""
# invoke default/parent logic, if it exists
parent = super(DepartmentView, self)
if hasattr(parent, 'template_kwargs_view'):
kwargs = parent.template_kwargs_view(**kwargs)
department = kwargs['instance']
# CORE Office URL
kwargs['core_office_url'] = None
office_url = core_office_url(self.rattail_config)
if not office_url:
kwargs['core_office_why_no_url'] = "CORE Office URL is not configured"
else:
kwargs['core_office_url'] = '{}/item/departments/DepartmentEditor.php?did={}'.format(
office_url, department.number)
return kwargs
def get_xref_buttons(self, department):
url = core_office_url(self.rattail_config)
if url:
url = '{}/item/departments/DepartmentEditor.php?did={}'.format(
url, department.number)
return [{'url': url, 'text': "View in CORE Office"}]
def includeme(config):
DepartmentView.defaults(config)
DepartmentViewSupplement.defaults(config)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2020 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -24,41 +24,34 @@
Member Views
"""
from tailbone.views import members as base
from tailbone.views import ViewSupplement
class MemberView(base.MemberView):
class MemberViewSupplement(ViewSupplement):
"""
Master view for the Member class.
Member view supplement for CORE integration
"""
route_prefix = 'members'
labels = {
'corepos_account_id': "CORE-POS Account ID",
}
@property
def form_fields(self):
fields = super(MemberView, self).form_fields
return fields + [
'corepos_account_id',
]
def query(self, session):
query = super(MemberView, self).query(session)
model = self.rattail_config.get_model()
def get_grid_query(self, query):
model = self.model
return query.outerjoin(model.CoreMember)
def configure_grid(self, g):
super(MemberView, self).configure_grid(g)
model = self.rattail_config.get_model()
model = self.model
g.set_filter('corepos_account_id', model.CoreMember.corepos_account_id)
def configure_form(self, f):
f.append('corepos_account_id')
def get_version_child_classes(self):
model = self.rattail_config.get_model()
return super(MemberView, self).get_version_child_classes() + [
model.CoreMember,
]
model = self.model
return [model.CoreMember]
def includeme(config):
MemberView.defaults(config)
MemberViewSupplement.defaults(config)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -25,72 +25,64 @@ Person views
"""
from rattail_corepos.config import core_office_customer_account_url
from rattail.util import OrderedDict
from tailbone.views import people as base
from tailbone.views import ViewSupplement
class PersonView(base.PersonView):
class PersonViewSupplement(ViewSupplement):
"""
Expose some extra fields etc. per CORE-POS integration.
Please note that this does include a bit of "business logic" which assumes
that you keep CORE and Rattail in sync! Use at your own risk.
Person view supplement for CORE integration
"""
route_prefix = 'people'
labels = {
'corepos_customer_id': "CORE-POS Customer ID",
}
@property
def form_fields(self):
fields = super(PersonView, self).form_fields
return fields + [
'corepos_customer_id',
]
def query(self, session):
query = super(PersonView, self).query(session)
model = self.rattail_config.get_model()
def get_grid_query(self, query):
model = self.model
return query.outerjoin(model.CorePerson)
def configure_grid(self, g):
super(PersonView, self).configure_grid(g)
model = self.rattail_config.get_model()
model = self.model
g.set_filter('corepos_customer_id', model.CorePerson.corepos_customer_id)
def configure_form(self, f):
super(PersonView, self).configure_form(f)
# corepos_customer_id
if self.creating:
f.remove('corepos_customer_id')
elif self.editing:
f.set_required('corepos_customer_id', False)
if not self.master.creating:
f.append('corepos_customer_id')
def get_version_child_classes(self):
model = self.rattail_config.get_model()
return super(PersonView, self).get_version_child_classes() + [
model.CorePerson,
]
model = self.model
return [model.CorePerson]
def get_context_customers(self, person):
data = super(PersonView, self).get_context_customers(person)
def get_customer_xref_buttons(self, person):
buttons = []
for customer in person.customers:
url = core_office_customer_account_url(
self.rattail_config, customer.number)
buttons.append({'url': url, 'text': "View in CORE Office"})
return buttons
# add CORE Office URL for each customer account
for customer in data:
customer['view_corepos_url'] = core_office_customer_account_url(
self.rattail_config, customer['number'])
def get_member_xref_buttons(self, person):
buttons = OrderedDict()
return data
for member in person.members:
url = core_office_customer_account_url(
self.rattail_config, member.number)
buttons[member.uuid] = {'url': url,
'text': "View in CORE Office"}
def get_context_member(self, member):
data = super(PersonView, self).get_context_member(member)
for customer in person.customers:
for member in customer.members:
if member.uuid not in buttons:
url = core_office_customer_account_url(
self.rattail_config, member.number)
buttons[member.uuid] = {'url': url,
'text': "View in CORE Office"}
# add CORE Office URL for member account
data['view_corepos_url'] = core_office_customer_account_url(
self.rattail_config, member['number'])
return data
return buttons.values()
def includeme(config):
PersonView.defaults(config)
PersonViewSupplement.defaults(config)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,105 +26,66 @@ Product Views
from rattail_corepos.config import core_office_url
from tailbone.views import products as base
from webhelpers2.html import tags
from tailbone.views import ViewSupplement
class ProductView(base.ProductView):
class ProductViewSupplement(ViewSupplement):
"""
Master view for the Product class.
Product view supplement for CORE integration
"""
route_prefix = 'products'
labels = {
'corepos_id': "CORE-POS ID",
}
@property
def form_fields(self):
fields = super(ProductView, self).form_fields
return self.corepos_add_form_fields(fields)
def corepos_add_form_fields(self, fields):
fields.extend([
'corepos_id',
])
return fields
def query(self, session):
query = super(ProductView, self).query(session)
return self.corepos_modify_query(query)
def corepos_modify_query(self, query):
model = self.rattail_config.get_model()
def get_grid_query(self, query):
model = self.model
return query.outerjoin(model.CoreProduct)
def configure_grid(self, g):
super(ProductView, self).configure_grid(g)
self.corepos_configure_grid(g)
def corepos_configure_grid(self, g):
model = self.rattail_config.get_model()
model = self.model
g.set_filter('corepos_id', model.CoreProduct.corepos_id)
def configure_form(self, f):
super(ProductView, self).configure_form(f)
self.corepos_configure_form(f)
if not self.master.creating:
f.append('corepos_id')
def corepos_configure_form(self, f):
f.set_required('corepos_id', False)
if self.creating:
f.remove('corepos_id')
# def objectify(self, form, data=None):
# if data is None:
# data = form.validated
# product = super(ProductView, self).objectify(form, data)
# return self.corepos_objectify(product)
def objectify(self, form, data=None):
if data is None:
data = form.validated
product = super(ProductView, self).objectify(form, data)
return self.corepos_objectify(product)
def corepos_objectify(self, product):
# remove the corepos extension record outright, if we just lost the ID
if product._corepos and not product.corepos_id:
self.Session.delete(product._corepos)
self.Session.flush()
return product
# def corepos_objectify(self, product):
# # remove the corepos extension record outright, if we just lost the ID
# if product._corepos and not product.corepos_id:
# self.Session.delete(product._corepos)
# self.Session.flush()
# return product
def get_version_child_classes(self):
classes = super(ProductView, self).get_version_child_classes()
return self.corepos_add_version_classes(classes)
model = self.model
return [model.CoreProduct]
def corepos_add_version_classes(self, classes):
model = self.rattail_config.get_model()
classes.extend([
model.CoreProduct,
])
return classes
def get_panel_fields_main(self, product):
return ['corepos_id']
def template_kwargs_view(self, **kwargs):
kwargs = super(ProductView, self).template_kwargs_view(**kwargs)
return self.corepos_template_kwargs_view(**kwargs)
def get_xref_buttons(self, product):
url = core_office_url(self.rattail_config)
if url:
url = '{}/item/ItemEditorPage.php?searchupc={}'.format(
url, product.item_id)
return [{'url': url, 'text': "View in CORE Office"}]
def corepos_template_kwargs_view(self, **kwargs):
"""
Adds the URL for viewing the product within CORE Office, or else the
reason for lack of such a URL.
"""
product = kwargs['instance']
# CORE Office URL
kwargs['core_office_url'] = None
office_url = core_office_url(self.rattail_config)
if not office_url:
kwargs['core_office_why_no_url'] = "CORE Office URL is not configured"
else:
kwargs['core_office_url'] = '{}/item/ItemEditorPage.php?searchupc={}'.format(
office_url, product.item_id)
return kwargs
# TODO: this seems awkward here, but makes things less awkward to
# modules using this one as their base
PendingProductView = base.PendingProductView
def get_xref_links(self, product):
if product.corepos_id:
url = self.request.route_url('corepos.products.view',
id=product.corepos_id)
return [tags.link_to("View CORE-POS Product", url)]
def includeme(config):
ProductView.defaults(config)
PendingProductView.defaults(config)
ProductViewSupplement.defaults(config)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -131,4 +131,4 @@ class PurchaseView(base.PurchaseView):
def includeme(config):
PurchaseView.defaults(config)
base.defaults(config, **{'PurchaseView': PurchaseView})

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -24,40 +24,34 @@
Store Views
"""
from tailbone.views import stores as base
from tailbone.views import ViewSupplement
class StoreView(base.StoreView):
class StoreViewSupplement(ViewSupplement):
"""
Master view for the Store class.
Store view supplement for CORE integration
"""
route_prefix = 'stores'
labels = {
'corepos_id': "CORE-POS ID",
}
@property
def form_fields(self):
fields = super(StoreView, self).form_fields
return fields + [
'corepos_id',
]
def query(self, session):
query = super(StoreView, self).query(session)
def get_grid_query(self, query):
model = self.model
return query.outerjoin(model.CoreStore)
def configure_grid(self, g):
super(StoreView, self).configure_grid(g)
model = self.model
g.set_filter('corepos_id', model.CoreStore.corepos_id)
def configure_form(self, f):
f.append('corepos_id')
def get_version_child_classes(self):
model = self.model
return super(StoreView, self).get_version_child_classes() + [
model.CoreStore,
]
return [model.CoreStore]
def includeme(config):
StoreView.defaults(config)
StoreViewSupplement.defaults(config)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -24,42 +24,34 @@
Subdepartment Views
"""
from rattail_corepos.config import core_office_url
from tailbone.views import subdepartments as base
from tailbone.views import ViewSupplement
class SubdepartmentView(base.SubdepartmentView):
class SubdepartmentViewSupplement(ViewSupplement):
"""
Master view for the Subdepartment class.
Subdepartment view supplement for CORE integration
"""
route_prefix = 'subdepartments'
labels = {
'corepos_number': "CORE-POS Number",
}
@property
def form_fields(self):
fields = super(SubdepartmentView, self).form_fields
return fields + [
'corepos_number',
]
def query(self, session):
query = super(SubdepartmentView, self).query(session)
model = self.rattail_config.get_model()
def get_grid_query(self, query):
model = self.model
return query.outerjoin(model.CoreSubdepartment)
def configure_grid(self, g):
super(SubdepartmentView, self).configure_grid(g)
model = self.rattail_config.get_model()
model = self.model
g.set_filter('corepos_number', model.CoreSubdepartment.corepos_number)
def configure_form(self, f):
f.append('corepos_number')
def get_version_child_classes(self):
model = self.rattail_config.get_model()
return super(SubdepartmentView, self).get_version_child_classes() + [
model.CoreSubdepartment,
]
model = self.model
return [model.CoreSubdepartment]
def includeme(config):
SubdepartmentView.defaults(config)
SubdepartmentViewSupplement.defaults(config)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,70 +26,41 @@ Vendor views
from rattail_corepos.config import core_office_url
from tailbone.views import vendors as base
from tailbone.views import ViewSupplement
class VendorView(base.VendorView):
class VendorViewSupplement(ViewSupplement):
"""
Expose some extra fields etc. per CORE-POS integration.
Please note that this does include a bit of "business logic" which assumes
that you keep CORE and Rattail in sync! Use at your own risk.
Vendor view supplement for CORE integration
"""
route_prefix = 'vendors'
labels = {
'corepos_id': "CORE-POS ID",
}
@property
def form_fields(self):
fields = super(VendorView, self).form_fields
return fields + [
'corepos_id',
]
def query(self, session):
query = super(VendorView, self).query(session)
model = self.rattail_config.get_model()
def get_grid_query(self, query):
model = self.model
return query.outerjoin(model.CoreVendor)
def configure_grid(self, g):
super(VendorView, self).configure_grid(g)
model = self.rattail_config.get_model()
model = self.model
g.set_filter('corepos_id', model.CoreVendor.corepos_id)
def configure_form(self, f):
f.append('corepos_id')
def get_version_child_classes(self):
model = self.rattail_config.get_model()
return super(VendorView, self).get_version_child_classes() + [
model.CoreVendor,
]
model = self.model
return [model.CoreVendor]
def template_kwargs_view(self, **kwargs):
"""
Supplements the default logic as follows:
Adds the URL for viewing the vendor within CORE Office, or else the
reason for lack of such a URL.
"""
# invoke default/parent logic, if it exists
parent = super(VendorView, self)
if hasattr(parent, 'template_kwargs_view'):
kwargs = parent.template_kwargs_view(**kwargs)
vendor = kwargs['instance']
# CORE Office URL
kwargs['core_office_url'] = None
office_url = core_office_url(self.rattail_config)
if not office_url:
kwargs['core_office_why_no_url'] = "CORE Office URL is not configured"
elif not vendor.corepos_id:
kwargs['core_office_why_no_url'] = "Vendor has no CORE-POS ID"
else:
kwargs['core_office_url'] = '{}/item/vendors/VendorIndexPage.php?vid={}'.format(
office_url, vendor.corepos_id)
return kwargs
def get_xref_buttons(self, vendor):
url = core_office_url(self.rattail_config)
if url:
url = '{}/item/vendors/VendorIndexPage.php?vid={}'.format(
url, vendor.corepos_id)
return [{'url': url, 'text': "View in CORE Office"}]
def includeme(config):
VendorView.defaults(config)
VendorViewSupplement.defaults(config)