diff --git a/tailbone/views/customers.py b/tailbone/views/customers.py index 0a4b8649..99e2a6b2 100644 --- a/tailbone/views/customers.py +++ b/tailbone/views/customers.py @@ -31,12 +31,13 @@ import re import sqlalchemy as sa from sqlalchemy import orm -import formalchemy as fa +import colander +from deform import widget as dfwidget from pyramid.httpexceptions import HTTPNotFound +from webhelpers2.html import HTML, tags -from tailbone import forms from tailbone.db import Session -from tailbone.views import MasterView2 as MasterView, AutocompleteView +from tailbone.views import MasterView3 as MasterView, AutocompleteView from rattail.db import model @@ -48,6 +49,15 @@ class CustomersView(MasterView): model_class = model.Customer has_versions = True supports_mobile = True + + labels = { + 'id': "ID", + 'default_phone': "Phone Number", + 'default_email': "Email Address", + 'active_in_pos': "Active in POS", + 'active_in_pos_sticky': "Always Active in POS", + } + grid_columns = [ 'id', 'number', @@ -56,6 +66,17 @@ class CustomersView(MasterView): 'email', ] + form_fields = [ + 'id', + 'name', + 'default_phone', + 'default_email', + 'email_preference', + 'active_in_pos', + 'active_in_pos_sticky', + 'people', + ] + def configure_grid(self, g): super(CustomersView, self).configure_grid(g) @@ -124,40 +145,83 @@ class CustomersView(MasterView): raise HTTPNotFound - def _preconfigure_fieldset(self, fs): - fs.id.set(label="ID") - fs.append(forms.fields.DefaultPhoneField('default_phone', label="Phone Number")) - fs.append(forms.fields.DefaultEmailField('default_email', label="Email Address")) - fs.email_preference.set(renderer=forms.EnumFieldRenderer(self.enum.EMAIL_PREFERENCE), - attrs={'auto-enhance': 'true'}) - fs.email_preference._null_option = ("(no preference)", '') - fs.append(forms.AssociationProxyField('people', renderer=forms.renderers.PeopleFieldRenderer, - readonly=True)) - fs.active_in_pos.set(label="Active in POS") - fs.active_in_pos_sticky.set(label="Always Active in POS") + def configure_form(self, f): + super(CustomersView, self).configure_form(f) + customer = f.model_instance - def configure_fieldset(self, fs): - include = [ - fs.id, - fs.name, - fs.default_phone, - fs.default_email, - fs.email_preference, - fs.active_in_pos, - fs.active_in_pos_sticky, - ] - if not self.creating: - include.extend([ - fs.people, - ]) - fs.configure(include=include) + f.set_renderer('default_email', self.render_default_email) + if not self.creating and customer.emails: + f.set_default('default_email', customer.emails[0].address) - def configure_mobile_fieldset(self, fs): - fs.configure( - include=[ - fs.email, - fs.phone, - ]) + f.set_renderer('default_phone', self.render_default_phone) + if not self.creating and customer.phones: + f.set_default('default_phone', customer.phones[0].number) + + f.set_enum('email_preference', self.enum.EMAIL_PREFERENCE) + preferences = list(self.enum.EMAIL_PREFERENCE.items()) + preferences.insert(0, ('', "(no preference)")) + f.set_widget('email_preference', dfwidget.SelectWidget(values=preferences)) + + f.set_renderer('people', self.render_people) + f.set_readonly('people') + + if self.creating: + f.remove_field('people') + else: + f.set_readonly('id') + + # TODO: something like this should be supported for default_email, default_phone + # def after_edit(self, customer): + # + # if not self.is_readonly(): + # address = self._deserialize() + # contact = self.parent.model + # if contact.emails: + # if address: + # email = contact.emails[0] + # email.address = address + # else: + # contact.emails.pop(0) + # elif address: + # email = contact.add_email_address(address) + # + # if not self.is_readonly(): + # number = self._deserialize() + # contact = self.parent.model + # if contact.phones: + # if number: + # phone = contact.phones[0] + # phone.number = number + # else: + # contact.phones.pop(0) + # elif number: + # phone = contact.add_phone_number(number) + + def render_default_email(self, customer, field): + if customer.emails: + return customer.emails[0].address + + def render_default_phone(self, customer, field): + if customer.phones: + return customer.phones[0].number + + def render_people(self, customer, field): + people = customer.people + if not people: + return "" + + items = [] + for person in people: + link = tags.link_to(person, self.request.route_url('people.view', uuid=person.uuid)) + items.append(HTML.tag('li', link)) + return HTML.tag('ul', HTML.literal('').join(items)) + + # def configure_mobile_fieldset(self, fs): + # fs.configure( + # include=[ + # fs.email, + # fs.phone, + # ]) def get_version_child_classes(self): return [ @@ -168,13 +232,21 @@ class CustomersView(MasterView): ] -def unique_id(value, field): - customer = field.parent.model - query = Session.query(model.Customer).filter(model.Customer.id == value) - if customer.uuid: - query = query.filter(model.Customer.uuid != customer.uuid) - if query.count(): - raise fa.ValidationError("Customer ID must be unique") +# # TODO: this is referenced by some custom apps, but should be moved?? +# def unique_id(value, field): +# customer = field.parent.model +# query = Session.query(model.Customer).filter(model.Customer.id == value) +# if customer.uuid: +# query = query.filter(model.Customer.uuid != customer.uuid) +# if query.count(): +# raise fa.ValidationError("Customer ID must be unique") + + +# TODO: this only works when creating, need to add edit support? +def unique_id(node, value): + customers = Session.query(model.Customer).filter(model.Customer.id == value) + if customers.count(): + raise colander.Invalid(node, "Customer ID must be unique") class CustomerNameAutocomplete(AutocompleteView):