Refactor purchasing batch views to use master3

This commit is contained in:
Lance Edgar 2018-01-27 11:59:52 -06:00
parent d20601c359
commit eac59ba5c8
6 changed files with 233 additions and 154 deletions

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2017 Lance Edgar
# Copyright © 2010-2018 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,17 +26,18 @@ Base views for purchasing batches
from __future__ import unicode_literals, absolute_import
# from sqlalchemy import orm
import six
from rattail.db import model, api
# from rattail.gpc import GPC
from rattail.time import localtime
import formalchemy as fa
import colander
from deform import widget as dfwidget
from pyramid import httpexceptions
from webhelpers2.html import tags
from tailbone import forms
from tailbone.views.batch import BatchMasterView2 as BatchMasterView
from tailbone import forms, forms2
from tailbone.views.batch import BatchMasterView3 as BatchMasterView
class PurchasingBatchView(BatchMasterView):
@ -76,6 +77,33 @@ class PurchasingBatchView(BatchMasterView):
# 'status_code',
# ]
form_fields = [
'id',
'store',
'buyer',
'vendor',
'department',
'purchase',
'vendor_email',
'vendor_fax',
'vendor_contact',
'vendor_phone',
'date_ordered',
'date_received',
'po_number',
'po_total',
'invoice_date',
'invoice_number',
'invoice_total',
'notes',
'created',
'created_by',
'status_code',
'complete',
'executed',
'executed_by',
]
@property
def batch_mode(self):
raise NotImplementedError("Please define `batch_mode` for your purchasing batch view")
@ -118,29 +146,189 @@ class PurchasingBatchView(BatchMasterView):
# form = super(PurchasingBatchView, self).make_form(batch, **kwargs)
# return form
def _preconfigure_fieldset(self, fs):
super(PurchasingBatchView, self)._preconfigure_fieldset(fs)
fs.mode.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.PURCHASE_BATCH_MODE))
fs.store.set(renderer=forms.renderers.StoreFieldRenderer)
fs.purchase.set(renderer=forms.renderers.PurchaseFieldRenderer, options=[])
fs.vendor.set(renderer=forms.renderers.VendorFieldRenderer,
attrs={'selected': 'vendor_selected',
'cleared': 'vendor_cleared'})
fs.department.set(renderer=forms.renderers.DepartmentFieldRenderer,
options=self.get_department_options())
fs.buyer.set(renderer=forms.renderers.EmployeeFieldRenderer)
fs.po_number.set(label="PO Number")
fs.po_total.set(label="PO Total", readonly=True, renderer=forms.renderers.CurrencyFieldRenderer)
fs.invoice_total.set(readonly=True, renderer=forms.renderers.CurrencyFieldRenderer)
def configure_form(self, f):
super(PurchasingBatchView, self).configure_form(f)
batch = f.model_instance
today = localtime(self.rattail_config).date()
fs.append(fa.Field('vendor_email', readonly=True,
value=lambda b: b.vendor.email.address if b.vendor.email else None))
fs.append(fa.Field('vendor_fax', readonly=True,
value=self.get_vendor_fax_number))
fs.append(fa.Field('vendor_contact', readonly=True,
value=lambda b: b.vendor.contact or None))
fs.append(fa.Field('vendor_phone', readonly=True,
value=self.get_vendor_phone_number))
# mode
f.set_enum('mode', self.enum.PURCHASE_BATCH_MODE)
# TODO: this hardly seems complete...
# store
if not self.creating:
f.set_readonly('store')
f.set_renderer('store', self.render_store)
# purchase
f.set_renderer('purchase', self.render_purchase)
if self.editing:
f.set_readonly('purchase')
# vendor
# fs.vendor.set(renderer=forms.renderers.VendorFieldRenderer,
# attrs={'selected': 'vendor_selected',
# 'cleared': 'vendor_cleared'})
f.set_renderer('vendor', self.render_vendor)
if self.creating:
f.replace('vendor', 'vendor_uuid')
f.set_node('vendor_uuid', colander.String())
vendor_display = ""
if self.request.method == 'POST':
if self.request.POST.get('vendor_uuid'):
vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor_uuid'])
if vendor:
vendor_display = six.text_type(vendor)
vendors_url = self.request.route_url('vendors.autocomplete')
f.set_widget('vendor_uuid', forms2.widgets.JQueryAutocompleteWidget(
field_display=vendor_display, service_url=vendors_url))
f.set_label('vendor_uuid', "Vendor")
elif self.editing:
f.set_readonly('vendor')
# department
f.set_renderer('department', self.render_department)
if self.creating:
f.replace('department', 'department_uuid')
f.set_node('department_uuid', colander.String())
dept_options = self.get_department_options()
dept_values = [(v, k) for k, v in dept_options]
f.set_widget('department_uuid', dfwidget.SelectWidget(values=dept_values))
f.set_label('department_uuid', "Department")
else:
f.set_readonly('department')
# buyer
f.set_renderer('buyer', self.render_buyer)
if self.creating or self.editing:
f.replace('buyer', 'buyer_uuid')
f.set_node('buyer_uuid', colander.String(), missing=colander.null)
buyer_display = ""
if self.request.method == 'POST':
if self.request.POST.get('buyer_uuid'):
buyer = self.Session.query(model.Employee).get(self.request.POST['buyer_uuid'])
if buyer:
buyer_display = six.text_type(buyer)
elif self.creating:
buyer = self.request.user.employee
buyer_display = six.text_type(buyer)
f.set_default('buyer_uuid', buyer.uuid)
elif self.editing:
buyer_display = six.text_type(batch.buyer or '')
buyers_url = self.request.route_url('employees.autocomplete')
f.set_widget('buyer_uuid', forms2.widgets.JQueryAutocompleteWidget(
field_display=buyer_display, service_url=buyers_url))
f.set_label('buyer_uuid', "Buyer")
# date_ordered
f.set_type('date_ordered', 'date_jquery')
if self.creating:
f.set_default('date_ordered', today)
# date_received
f.set_type('date_received', 'date_jquery')
if self.creating:
f.set_default('date_received', today)
# invoice_date
f.set_type('invoice_date', 'date_jquery')
# po_number
f.set_label('po_number', "PO Number")
# po_total
f.set_readonly('po_total')
f.set_type('po_total', 'currency')
f.set_label('po_total', "PO Total")
# invoice_total
f.set_readonly('invoice_total')
f.set_type('invoice_total', 'currency')
# vendor_email
f.set_readonly('vendor_email')
f.set_renderer('vendor_email', self.render_vendor_email)
# vendor_fax
f.set_readonly('vendor_fax')
f.set_renderer('vendor_fax', self.render_vendor_fax)
# vendor_contact
f.set_readonly('vendor_contact')
f.set_renderer('vendor_contact', self.render_vendor_contact)
# vendor_phone
f.set_readonly('vendor_phone')
f.set_renderer('vendor_phone', self.render_vendor_phone)
if self.creating:
f.remove_fields('po_total',
'invoice_total',
'complete',
'vendor_email',
'vendor_fax',
'vendor_phone',
'vendor_contact',
'status_code')
def render_store(self, batch, field):
store = batch.store
if not store:
return ""
text = "({}) {}".format(store.id, store.name)
url = self.request.route_url('stores.view', uuid=store.uuid)
return tags.link_to(text, url)
def render_purchase(self, batch, field):
purchase = batch.purchase
if not purchase:
return ""
text = six.text_type(purchase)
url = self.request.route_url('purchases.view', uuid=purchase.uuid)
return tags.link_to(text, url)
def render_vendor(self, batch, field):
vendor = batch.vendor
if not vendor:
return ""
text = "({}) {}".format(vendor.id, vendor.name)
url = self.request.route_url('vendors.view', uuid=vendor.uuid)
return tags.link_to(text, url)
def render_vendor_email(self, batch, field):
if batch.vendor.email:
return batch.vendor.email.address
def render_vendor_fax(self, batch, field):
return self.get_vendor_fax_number(batch)
def render_vendor_contact(self, batch, field):
if batch.vendor.contact:
return six.text_type(batch.vendor.contact)
def render_vendor_phone(self, batch, field):
return self.get_vendor_phone_number(batch)
def render_department(self, batch, field):
department = batch.department
if not department:
return ""
if department.number:
text = "({}) {}".format(department.number, department.name)
else:
text = department.name
url = self.request.route_url('departments.view', uuid=department.uuid)
return tags.link_to(text, url)
def render_buyer(self, batch, field):
employee = batch.buyer
if not employee:
return ""
text = six.text_type(employee)
if self.request.has_perm('employees.view'):
url = self.request.route_url('employees.view', uuid=employee.uuid)
return tags.link_to(text, url)
return text
def get_department_options(self):
departments = self.Session.query(model.Department).order_by(model.Department.number)
@ -156,70 +344,6 @@ class PurchasingBatchView(BatchMasterView):
if phone.type == 'Fax':
return phone.number
def configure_fieldset(self, fs):
fs.configure(
include=[
fs.id,
fs.store,
fs.buyer,
fs.vendor,
fs.department,
fs.purchase,
fs.vendor_email,
fs.vendor_fax,
fs.vendor_contact,
fs.vendor_phone,
fs.date_ordered,
fs.date_received,
fs.po_number,
fs.po_total,
fs.invoice_date,
fs.invoice_number,
fs.invoice_total,
fs.notes,
fs.created,
fs.created_by,
fs.status_code,
fs.complete,
fs.executed,
fs.executed_by,
])
if self.creating:
del fs.po_total
del fs.invoice_total
del fs.complete
del fs.vendor_email
del fs.vendor_fax
del fs.vendor_phone
del fs.vendor_contact
del fs.status_code
# default store may be configured
store = self.rattail_config.get('rattail', 'store')
if store:
store = api.get_store(self.Session(), store)
if store:
fs.model.store = store
# default buyer is current user
if self.request.method != 'POST':
buyer = self.request.user.employee
if buyer:
fs.model.buyer = buyer
# TODO: something tells me this isn't quite safe..
# all dates have today as default
today = localtime(self.rattail_config).date()
fs.model.date_ordered = today
fs.model.date_received = today
elif self.editing:
fs.store.set(readonly=True)
fs.vendor.set(readonly=True)
fs.department.set(readonly=True)
fs.purchase.set(readonly=True)
def eligible_purchases(self, vendor_uuid=None, mode=None):
if not vendor_uuid:
vendor_uuid = self.request.GET.get('vendor_uuid')

View file

@ -86,6 +86,12 @@ class OrderingBatchView(PurchasingBatchView):
def batch_mode(self):
return self.enum.PURCHASE_BATCH_MODE_ORDERING
def configure_form(self, f):
super(OrderingBatchView, self).configure_form(f)
# purchase
f.remove_field('purchase')
def order_form(self):
"""
View for editing batch row data as an order form.