Refactor handheld batch views to use master3

This commit is contained in:
Lance Edgar 2018-01-27 12:23:47 -06:00
parent eac59ba5c8
commit 8eab3c5b36
3 changed files with 77 additions and 63 deletions

View file

@ -326,7 +326,9 @@ class Form(object):
widgets={}, defaults={}, validators={}, required={}, helptext={}, widgets={}, defaults={}, validators={}, required={}, helptext={},
action_url=None, cancel_url=None): action_url=None, cancel_url=None):
self.fields = FieldList(fields) if fields is not None else None self.fields = None
if fields is not None:
self.set_fields(fields)
self.schema = schema self.schema = schema
self.request = request self.request = request
self.readonly = readonly self.readonly = readonly
@ -336,7 +338,7 @@ class Form(object):
if self.model_instance and not self.model_class: if self.model_instance and not self.model_class:
self.model_class = type(self.model_instance) self.model_class = type(self.model_instance)
if self.model_class and self.fields is None: if self.model_class and self.fields is None:
self.fields = self.make_fields() self.set_fields(self.make_fields())
self.nodes = nodes or {} self.nodes = nodes or {}
self.enums = enums or {} self.enums = enums or {}
self.labels = labels or {} self.labels = labels or {}
@ -352,6 +354,9 @@ class Form(object):
self.action_url = action_url self.action_url = action_url
self.cancel_url = cancel_url self.cancel_url = cancel_url
def set_fields(self, fields):
self.fields = FieldList(fields)
def make_fields(self): def make_fields(self):
""" """
Return a default list of fields, based on :attr:`model_class`. Return a default list of fields, based on :attr:`model_class`.

View file

@ -27,9 +27,13 @@ Base views for maintaining batches
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
import os import os
import tempfile
import six import six
import colander
import deform
from deform import widget as dfwidget
from pyramid_deform import SessionFileUploadTempStore
from webhelpers2.html import tags from webhelpers2.html import tags
from tailbone.views import MasterView3 from tailbone.views import MasterView3
@ -46,8 +50,7 @@ class BatchMasterView3(MasterView3, BatchMasterView2):
'created', 'created',
'created_by', 'created_by',
'rowcount', 'rowcount',
'cognized', 'status_code',
'cognized_by',
'executed', 'executed',
'executed_by', 'executed_by',
'purge', 'purge',
@ -113,7 +116,8 @@ class BatchMasterView3(MasterView3, BatchMasterView2):
def save_create_form(self, form): def save_create_form(self, form):
self.before_create(form) self.before_create(form)
with self.Session.no_autoflush: session = self.Session()
with session.no_autoflush:
# transfer form data to batch instance # transfer form data to batch instance
batch = self.objectify(form, self.form_deserialized) batch = self.objectify(form, self.form_deserialized)
@ -121,23 +125,35 @@ class BatchMasterView3(MasterView3, BatchMasterView2):
# current user is batch creator # current user is batch creator
batch.created_by = self.request.user or self.late_login_user() batch.created_by = self.request.user or self.late_login_user()
# obtain kwargs for making batch via handler, below
kwargs = self.get_batch_kwargs(batch)
# TODO: this needs work yet surely...
filedict = kwargs.pop('filename', None)
filepath = None
if filedict:
kwargs['filename'] = '' # null not allowed
tempdir = tempfile.mkdtemp()
filepath = os.path.join(tempdir, filedict['filename'])
tmpinfo = form.deform_form['filename'].widget.tmpstore.get(filedict['uid'])
tmpdata = tmpinfo['fp'].read()
with open(filepath, 'wb') as f:
f.write(tmpdata)
# TODO: is this still necessary with colander? # TODO: is this still necessary with colander?
# destroy initial batch and re-make using handler # destroy initial batch and re-make using handler
kwargs = self.get_batch_kwargs(batch)
# if batch in self.Session: # if batch in self.Session:
# self.Session.expunge(batch) # self.Session.expunge(batch)
batch = self.handler.make_batch(self.Session(), **kwargs) batch = self.handler.make_batch(session, **kwargs)
self.Session.flush() self.Session.flush()
# TODO: this needs work yet surely... # TODO: this needs work yet surely...
# if batch has input data file, let handler properly establish that # if batch has input data file, let handler properly establish that
filename = getattr(batch, 'filename', None) if filedict:
if filename: self.handler.set_input_file(batch, filepath)
path = os.path.join(self.upload_dir, filename) os.remove(filepath)
if os.path.exists(path): os.rmdir(tempdir)
self.handler.set_input_file(batch, path)
os.remove(path)
return batch return batch
@ -175,11 +191,11 @@ class FileBatchMasterView3(BatchMasterView3, FileBatchMasterView2):
if self.editing: if self.editing:
f.set_readonly('filename') f.set_readonly('filename')
# if creating, let filename be our only field by default
if self.creating: if self.creating:
f.fields = [ if 'filename' not in f.fields:
'filename', f.fields.insert(0, 'filename')
] tmpstore = SessionFileUploadTempStore(self.request)
f.set_node('filename', colander.SchemaNode(deform.FileData(), widget=dfwidget.FileUploadWidget(tmpstore)))
def render_filename(self, batch, field): def render_filename(self, batch, field):
path = batch.filepath(self.rattail_config, filename=batch.filename) path = batch.filepath(self.rattail_config, filename=batch.filename)

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2017 Lance Edgar # Copyright © 2010-2018 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -28,17 +28,15 @@ from __future__ import unicode_literals, absolute_import
import os import os
from rattail import enum
from rattail.db import model from rattail.db import model
from rattail.util import OrderedDict from rattail.util import OrderedDict
import formalchemy as fa
import formencode as fe import formencode as fe
from webhelpers2.html import tags from webhelpers2.html import tags
from tailbone import forms from tailbone import forms
from tailbone.db import Session from tailbone.db import Session
from tailbone.views.batch import FileBatchMasterView2 as FileBatchMasterView from tailbone.views.batch import FileBatchMasterView3 as FileBatchMasterView
ACTION_OPTIONS = OrderedDict([ ACTION_OPTIONS = OrderedDict([
@ -53,21 +51,6 @@ class ExecutionOptions(fe.Schema):
action = fe.validators.OneOf(ACTION_OPTIONS) action = fe.validators.OneOf(ACTION_OPTIONS)
class InventoryBatchFieldRenderer(fa.FieldRenderer):
"""
Renderer for handheld batch's "inventory batch" field.
"""
def render_readonly(self, **kwargs):
batch = self.raw_value
if batch:
return tags.link_to(
batch.id_str,
self.request.route_url('batch.inventory.view', uuid=batch.uuid))
return ''
class HandheldBatchView(FileBatchMasterView): class HandheldBatchView(FileBatchMasterView):
""" """
Master view for handheld batches. Master view for handheld batches.
@ -96,6 +79,19 @@ class HandheldBatchView(FileBatchMasterView):
'executed', 'executed',
] ]
form_fields = [
'id',
'device_type',
'device_name',
'filename',
'created',
'created_by',
'rowcount',
'status_code',
'executed',
'executed_by',
]
row_grid_columns = [ row_grid_columns = [
'sequence', 'sequence',
'upc', 'upc',
@ -117,38 +113,35 @@ class HandheldBatchView(FileBatchMasterView):
if batch.status_code is not None and batch.status_code != batch.STATUS_OK: if batch.status_code is not None and batch.status_code != batch.STATUS_OK:
return 'notice' return 'notice'
def _preconfigure_fieldset(self, fs): def configure_form(self, f):
super(HandheldBatchView, self)._preconfigure_fieldset(fs) super(HandheldBatchView, self).configure_form(f)
batch = f.model_instance
# device_type
device_types = OrderedDict(sorted(self.enum.HANDHELD_DEVICE_TYPE.items(), device_types = OrderedDict(sorted(self.enum.HANDHELD_DEVICE_TYPE.items(),
key=lambda item: item[1])) key=lambda item: item[1]))
fs.device_type.set(renderer=forms.renderers.EnumFieldRenderer(device_types)) f.set_enum('device_type', device_types)
f.widgets['device_type'].values.insert(0, ('', "(none)"))
def configure_fieldset(self, fs):
if self.creating: if self.creating:
fs.configure( f.set_fields([
include=[ 'filename',
fs.filename, 'device_type',
fs.device_type, 'device_name',
fs.device_name,
]) ])
else: if self.viewing:
fs.configure( if batch.inventory_batch:
include=[ f.append('inventory_batch')
fs.id, f.set_renderer('inventory_batch', self.render_inventory_batch)
fs.device_type,
fs.device_name,
fs.filename,
fs.created,
fs.created_by,
fs.rowcount,
fs.status_code,
fs.executed,
fs.executed_by,
])
if self.viewing and fs.model.inventory_batch: def render_inventory_batch(self, handheld_batch, field):
fs.append(fa.Field('inventory_batch', value=fs.model.inventory_batch, renderer=InventoryBatchFieldRenderer)) batch = handheld_batch.inventory_batch
if not batch:
return ""
text = batch.id_str
url = self.request.route_url('batch.inventory.view', uuid=batch.uuid)
return tags.link_to(text, url)
def get_batch_kwargs(self, batch): def get_batch_kwargs(self, batch):
kwargs = super(HandheldBatchView, self).get_batch_kwargs(batch) kwargs = super(HandheldBatchView, self).get_batch_kwargs(batch)