1029 lines
34 KiB
Python
1029 lines
34 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
################################################################################
|
|
#
|
|
# Rattail -- Retail Software Framework
|
|
# Copyright © 2010-2012 Lance Edgar
|
|
#
|
|
# This file is part of Rattail.
|
|
#
|
|
# Rattail is free software: you can redistribute it and/or modify it under the
|
|
# terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, either version 3 of the License, or (at your option)
|
|
# any later version.
|
|
#
|
|
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
|
# more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with Rattail. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
################################################################################
|
|
|
|
"""
|
|
``rattail.pyramid.views.batches`` -- Batch (et al.) Views
|
|
"""
|
|
|
|
import formalchemy
|
|
from sqlalchemy import and_, or_
|
|
from sqlalchemy.orm import joinedload
|
|
|
|
import transaction
|
|
from pyramid.httpexceptions import HTTPFound
|
|
from pyramid.renderers import render
|
|
from pyramid.response import Response
|
|
from pyramid.view import view_config
|
|
|
|
from edbob.exceptions import LoadSpecError
|
|
from edbob.pyramid import filters
|
|
from edbob.pyramid import forms
|
|
from edbob.pyramid import grids
|
|
from edbob.pyramid import Session
|
|
from edbob.pyramid.views.crud import crud
|
|
from edbob.util import prettify
|
|
|
|
import rattail
|
|
from rattail import sil
|
|
from rattail.batches import next_batch_id
|
|
from rattail.pyramid import util
|
|
from rattail.pyramid.forms import (
|
|
BatchIdFieldRenderer,
|
|
unique_batch_terminal_id,
|
|
)
|
|
|
|
|
|
@view_config(route_name='sil_columns', renderer='/batches/sil_columns.mako')
|
|
def sil_columns(context, request):
|
|
"""
|
|
Index page for SIL columns (:class:`rattail.SilColumn`).
|
|
"""
|
|
|
|
fmap = filters.get_filter_map(
|
|
rattail.SilColumn,
|
|
exact=['sil_name'],
|
|
ilike=['display'])
|
|
|
|
config = filters.get_search_config(
|
|
'sil_columns', request, fmap,
|
|
include_filter_sil_name=True,
|
|
filter_type_sil_name='eq',
|
|
include_filter_display=True,
|
|
filter_type_display='lk')
|
|
|
|
search = filters.get_search_form(
|
|
config, sil_name="SIL Name")
|
|
|
|
config = grids.get_grid_config(
|
|
'sil_columns', request, search,
|
|
filter_map=fmap, sort='sil_name')
|
|
|
|
smap = grids.get_sort_map(
|
|
rattail.SilColumn,
|
|
['sil_name', 'display', 'data_type'])
|
|
|
|
def query(config):
|
|
q = Session.query(rattail.SilColumn)
|
|
q = filters.filter_query(q, config)
|
|
q = grids.sort_query(q, config, smap)
|
|
return q
|
|
|
|
columns = grids.get_pager(query, config)
|
|
g = forms.AlchemyGrid(
|
|
rattail.SilColumn, columns, config,
|
|
gridurl=request.route_url('sil_columns'),
|
|
objurl='sil_column', delurl='sil_column')
|
|
|
|
g.configure(
|
|
include=[
|
|
g.sil_name.label("SIL Name"),
|
|
g.display,
|
|
g.data_type,
|
|
])
|
|
|
|
g.readonly = True
|
|
grid = g.render(class_='clickable batch-columns')
|
|
return grids.render_grid(request, grid, search)
|
|
|
|
|
|
@view_config(route_name='sil_column', renderer='/batches/sil_column.mako')
|
|
def sil_column(context, request):
|
|
|
|
def fieldset(column):
|
|
fs = forms.make_fieldset(
|
|
column, crud_title="Batch Column",
|
|
url_action=request.route_url('sil_column'),
|
|
url_cancel=request.route_url('sil_columns'))
|
|
|
|
fs.configure(
|
|
include=[
|
|
fs.sil_name.label("SIL Name"),
|
|
fs.display,
|
|
fs.data_type,
|
|
])
|
|
|
|
if fs.edit:
|
|
fs.sil_name.set(readonly=True)
|
|
return fs
|
|
|
|
|
|
return crud(
|
|
request, rattail.SilColumn, fieldset,
|
|
home=request.route_url('sil_columns'),
|
|
delete=request.route_url('sil_columns'))
|
|
|
|
|
|
@view_config(route_name='batch_dictionaries', renderer='/batches/dictionaries.mako')
|
|
def batch_dictionaries(context, request):
|
|
"""
|
|
Index page for batch dictionaries (:class:`rattail.BatchDictionary`).
|
|
"""
|
|
|
|
fmap = filters.get_filter_map(
|
|
rattail.BatchDictionary,
|
|
exact=['name'],
|
|
ilike=['description'])
|
|
|
|
config = filters.get_search_config(
|
|
'batch_dictionaries', request, fmap,
|
|
include_filter_name=True,
|
|
filter_type_name='eq',
|
|
include_filter_description=True,
|
|
filter_type_description='lk')
|
|
|
|
search = filters.get_search_form(config)
|
|
|
|
config = grids.get_grid_config(
|
|
'batch_dictionaries', request, search,
|
|
filter_map=fmap, sort='description')
|
|
|
|
smap = grids.get_sort_map(
|
|
rattail.BatchDictionary,
|
|
['name', 'description'])
|
|
|
|
def query(config):
|
|
q = Session.query(rattail.BatchDictionary)
|
|
q = filters.filter_query(q, config)
|
|
q = grids.sort_query(q, config, smap)
|
|
return q
|
|
|
|
dictionaries = grids.get_pager(query, config)
|
|
g = forms.AlchemyGrid(
|
|
rattail.BatchDictionary, dictionaries, config,
|
|
gridurl=request.route_url('batch_dictionaries'),
|
|
objurl='batch_dictionary', delurl='batch_dictionary')
|
|
|
|
g.configure(
|
|
include=[
|
|
g.name,
|
|
g.description,
|
|
])
|
|
|
|
g.readonly = True
|
|
grid = g.render(class_='clickable batch-dictionaries')
|
|
return grids.render_grid(request, grid, search)
|
|
|
|
|
|
def _dictionary_columns(request, uuid=None):
|
|
"""
|
|
Returns a rendered grid of columns for a batch dictionary.
|
|
"""
|
|
|
|
if not uuid:
|
|
uuid = request.params.get('uuid')
|
|
dictionary = Session.query(rattail.BatchDictionary).get(uuid) if uuid else None
|
|
assert dictionary
|
|
|
|
fmap = filters.get_filter_map(
|
|
rattail.BatchDictionaryColumn,
|
|
exact=['key'])
|
|
fmap['column'] = filters.filter_exact(rattail.SilColumn.sil_name)
|
|
fmap['display'] = filters.filter_ilike(rattail.SilColumn.display)
|
|
|
|
config = grids.get_grid_config(
|
|
'batch_dictionary.columns', request,
|
|
filter_map=fmap, sort='column')
|
|
|
|
smap = grids.get_sort_map(
|
|
rattail.BatchDictionaryColumn,
|
|
['key'])
|
|
smap['column'] = grids.sorter(rattail.SilColumn.sil_name)
|
|
smap['display'] = grids.sorter(rattail.SilColumn.display)
|
|
|
|
def query(config):
|
|
q = Session.query(rattail.BatchDictionaryColumn)
|
|
q = q.join(rattail.SilColumn)
|
|
q = filters.filter_query(q, config)
|
|
q = grids.sort_query(q, config, smap)
|
|
return q
|
|
|
|
columns = query(config)
|
|
url = (request.route_url('batch_dictionary.columns')
|
|
+ '?uuid=' + dictionary.uuid)
|
|
g = forms.AlchemyGrid(
|
|
rattail.BatchDictionaryColumn, columns, config, url)
|
|
|
|
g.append(
|
|
formalchemy.Field(
|
|
'display',
|
|
value=lambda x: x.sil_column.display))
|
|
|
|
g.configure(
|
|
include=[
|
|
g.sil_column.label("SIL Name"),
|
|
g.display,
|
|
g.key,
|
|
])
|
|
|
|
g.readonly = True
|
|
return g.render(class_='hoverable batch-dictionary-columns')
|
|
|
|
|
|
@view_config(route_name='batch_dictionary.columns')
|
|
def batch_dictionary_columns(context, request):
|
|
return Response(body=_dictionary_columns(request),
|
|
content_type='text/html')
|
|
|
|
|
|
@view_config(route_name='batch_dictionary', renderer='/batches/dictionary.mako')
|
|
def batch_dictionary(context, request):
|
|
|
|
def fieldset(dictionary):
|
|
fs = forms.make_fieldset(
|
|
dictionary, crud_title="Batch Dictionary",
|
|
url_action=request.route_url('batch_dictionary'),
|
|
url_cancel=request.route_url('batch_dictionaries'))
|
|
|
|
fs.configure(
|
|
include=[
|
|
fs.name,
|
|
fs.description,
|
|
])
|
|
|
|
fs.readonly = True
|
|
return fs
|
|
|
|
|
|
def pre_render(fs):
|
|
if fs.edit:
|
|
g = _dictionary_columns(request, fs.model.uuid)
|
|
return {'columns':
|
|
render('/batches/dictionary_columns.mako', {'grid':g})}
|
|
|
|
return crud(
|
|
request, rattail.BatchDictionary, fieldset,
|
|
home=request.route_url('batch_dictionaries'),
|
|
delete=request.route_url('batch_dictionaries'),
|
|
pre_render=pre_render)
|
|
|
|
|
|
def _terminal_columns(request, terminal):
|
|
"""
|
|
Returns a rendered grid of :class:`rattail.BatchTerminalColumn` instances,
|
|
depending on ``terminal``.
|
|
"""
|
|
|
|
config = grids.get_grid_config(
|
|
'batch_terminal.columns', request, sort='dictionary')
|
|
|
|
smap = grids.get_sort_map(
|
|
rattail.BatchTerminalColumn,
|
|
['source', 'target'],
|
|
dictionary=grids.sorter(rattail.BatchDictionary.name),
|
|
sil_column=grids.sorter(rattail.SilColumn.sil_name),
|
|
display=grids.sorter(rattail.SilColumn.display))
|
|
|
|
jmap = dict(
|
|
dictionary=lambda q: q.join(rattail.BatchDictionary),
|
|
sil_column=lambda q: q.join(rattail.SilColumn),
|
|
display=lambda q: q.join(rattail.SilColumn))
|
|
|
|
def query(config):
|
|
q = Session.query(rattail.BatchTerminalColumn)
|
|
q = q.options(joinedload(rattail.BatchTerminalColumn.dictionary))
|
|
q = q.options(joinedload(rattail.BatchTerminalColumn.sil_column))
|
|
q = q.filter(rattail.BatchTerminalColumn.terminal_uuid == terminal.uuid)
|
|
q = grids.sort_query(q, config, smap, jmap)
|
|
return q
|
|
|
|
columns = query(config)
|
|
g = forms.AlchemyGrid(rattail.BatchTerminalColumn, columns, config,
|
|
gridurl=request.route_url('batch_terminal.columns', uuid=terminal.uuid))
|
|
|
|
g.append(
|
|
formalchemy.Field(
|
|
'display',
|
|
value=lambda x: x.sil_column.display))
|
|
|
|
g.configure(
|
|
include=[
|
|
g.dictionary,
|
|
g.sil_column.label("SIL Name"),
|
|
g.display,
|
|
g.source,
|
|
g.target,
|
|
])
|
|
|
|
g.readonly = True
|
|
return g.render(class_='hoverable batch-terminal-columns')
|
|
|
|
|
|
@view_config(route_name='batch_terminal.columns')
|
|
def terminal_columns(context, request):
|
|
uuid = request.matchdict['uuid']
|
|
terminal = Session.query(rattail.BatchTerminal).get(uuid) if uuid else None
|
|
assert terminal
|
|
return Response(
|
|
body=_terminal_columns(request, terminal),
|
|
content_type='text/html')
|
|
|
|
|
|
def update_terminal_info(terminal):
|
|
"""
|
|
This function updates a :class:`rattail.BatchTerminal` instance to reflect
|
|
the reality found by way of inspecting its underlying
|
|
:class:`rattail.batches.BatchTerminal` instance.
|
|
"""
|
|
|
|
# Assume the worst.
|
|
terminal.functional = False
|
|
del terminal.columns[:]
|
|
|
|
# Fetch "real" terminal instance, if we can.
|
|
try:
|
|
true_terminal = terminal.get_terminal()
|
|
except LoadSpecError, err:
|
|
return err
|
|
|
|
# Spec was fine but still no terminal? (This may not be needed?)
|
|
if not true_terminal:
|
|
return
|
|
|
|
# Okay, we have *something*.
|
|
terminal.functional = True
|
|
|
|
if true_terminal.source_columns:
|
|
terminal.source = True
|
|
for dct, cols in true_terminal.source_columns.iteritems():
|
|
dct = util.get_dictionary(dct)
|
|
for col in cols:
|
|
col = rattail.BatchTerminalColumn(
|
|
dictionary=dct,
|
|
sil_column=util.get_column(col),
|
|
source=True,
|
|
target=False)
|
|
terminal.columns.append(col)
|
|
Session.flush()
|
|
|
|
if true_terminal.target_columns:
|
|
terminal.target = True
|
|
for dct, cols in true_terminal.target_columns.iteritems():
|
|
dct = util.get_dictionary(dct)
|
|
for col in cols:
|
|
col = rattail.BatchTerminalColumn(
|
|
dictionary=dct,
|
|
sil_column=util.get_column(col),
|
|
source=False,
|
|
target=True)
|
|
terminal.columns.append(col)
|
|
Session.flush()
|
|
|
|
# Really, why?
|
|
return true_terminal
|
|
|
|
|
|
def terminal_fieldset(terminal, request):
|
|
fs = forms.make_fieldset(
|
|
terminal, crud_title="Batch Terminal",
|
|
url_action=request.current_route_url(),
|
|
url_cancel=request.route_url('batch_terminals'))
|
|
|
|
fs.configure(
|
|
include=[
|
|
fs.sil_id.label("SIL ID").validate(unique_batch_terminal_id),
|
|
fs.description,
|
|
fs.class_spec.validate(forms.required),
|
|
fs.functional.readonly(),
|
|
])
|
|
|
|
if not fs.edit:
|
|
del fs.functional
|
|
|
|
return fs
|
|
|
|
|
|
@view_config(route_name='batch_terminal.new', renderer='/batches/terminal.mako')
|
|
def new_terminal(context, request):
|
|
|
|
fs = terminal_fieldset(rattail.BatchTerminal, request)
|
|
if not fs.readonly and request.POST:
|
|
fs.rebind(data=request.params)
|
|
if fs.validate():
|
|
|
|
with transaction.manager:
|
|
fs.sync()
|
|
terminal = update_terminal_info(fs.model)
|
|
if isinstance(terminal, LoadSpecError):
|
|
request.session.flash(str(terminal))
|
|
elif terminal:
|
|
if not fs.model.sil_id:
|
|
fs.model.sil_id = terminal.name
|
|
if not fs.model.description:
|
|
fs.model.description = terminal.description
|
|
|
|
# fs.model = Session.merge(fs.model)
|
|
Session.add(fs.model)
|
|
Session.flush()
|
|
request.session.flash("%s \"%s\" has been %s." % (
|
|
fs.crud_title, fs.get_display_text(),
|
|
'updated' if fs.edit else 'created'))
|
|
home = request.route_url('batch_terminal.edit', uuid=fs.model.uuid)
|
|
|
|
return HTTPFound(location=home)
|
|
|
|
data = {'fieldset': fs, 'crud': True}
|
|
return data
|
|
|
|
|
|
@view_config(route_name='batch_terminal.edit', renderer='/batches/terminal.mako')
|
|
def edit_terminal(context, request):
|
|
|
|
uuid = request.matchdict['uuid']
|
|
terminal = Session.query(rattail.BatchTerminal).get(uuid) if uuid else None
|
|
assert terminal
|
|
|
|
fs = terminal_fieldset(terminal, request)
|
|
if request.POST:
|
|
fs.rebind(data=request.params)
|
|
if fs.validate():
|
|
|
|
with transaction.manager:
|
|
fs.sync()
|
|
terminal = update_terminal_info(fs.model)
|
|
if isinstance(terminal, LoadSpecError):
|
|
request.session.flash(str(terminal))
|
|
elif terminal:
|
|
if not fs.model.sil_id:
|
|
fs.model.sil_id = terminal.name
|
|
if not fs.model.description:
|
|
fs.model.description = terminal.description
|
|
|
|
# fs.model = Session.merge(fs.model)
|
|
request.session.flash("%s \"%s\" has been %s." % (
|
|
fs.crud_title, fs.get_display_text(),
|
|
'updated' if fs.edit else 'created'))
|
|
home = request.route_url('batch_terminal.edit', uuid=fs.model.uuid)
|
|
|
|
return HTTPFound(location=home)
|
|
|
|
fs.append(forms.ChildGridField('columns', _terminal_columns(request, terminal)))
|
|
|
|
return {'fieldset': fs, 'crud': True}
|
|
|
|
|
|
@view_config(route_name='batch_terminal.delete')
|
|
def delete_terminal(context, request):
|
|
uuid = request.matchdict['uuid']
|
|
terminal = Session.query(rattail.BatchTerminal).get(uuid) if uuid else None
|
|
assert terminal
|
|
with transaction.manager:
|
|
Session.delete(terminal)
|
|
return HTTPFound(location=request.route_url('batch_terminals'))
|
|
|
|
|
|
# @view_config(route_name='batch_terminal', renderer='/batches/terminal.mako')
|
|
# def batch_terminal(context, request):
|
|
|
|
# uuid = request.matchdict.get('uuid')
|
|
|
|
# def fieldset(terminal):
|
|
# fs = forms.make_fieldset(
|
|
# terminal, crud_title="Batch Terminal",
|
|
# url_action=request.current_route_url(),
|
|
# url_cancel=request.route_url('batches.terminals'))
|
|
|
|
# fs.configure(
|
|
# include=[
|
|
# fs.sil_id.label("SIL ID").validate(unique_batch_terminal_id),
|
|
# fs.description,
|
|
# fs.class_spec.validate(forms.required),
|
|
# fs.functional.readonly(),
|
|
# fs.source_kwargs,
|
|
# fs.target_kwargs,
|
|
# ])
|
|
|
|
# if fs.edit:
|
|
# fs.sil_id.set(readonly=True)
|
|
# else:
|
|
# del fs.source_kwargs
|
|
# del fs.target_kwargs
|
|
# return fs
|
|
|
|
# def pre_render(fs):
|
|
# if fs.edit:
|
|
# data = {
|
|
# 'columns': _terminal_columns(request, fs.model),
|
|
# }
|
|
# return {'terminal_columns':
|
|
# render('/batches/terminal_columns.mako', data)}
|
|
|
|
# def post_sync(fs):
|
|
# terminal = update_terminal_info(fs.model)
|
|
# if isinstance(terminal, LoadSpecError):
|
|
# request.session.flash(str(terminal))
|
|
# elif terminal:
|
|
# if not fs.model.sil_id:
|
|
# fs.model.sil_id = terminal.name
|
|
# if not fs.model.description:
|
|
# fs.model.description = terminal.description
|
|
|
|
# return crud(
|
|
# request, rattail.BatchTerminal, fieldset,
|
|
# delete=request.route_url('batches.terminals'),
|
|
# pre_render=pre_render, post_sync=post_sync)
|
|
|
|
|
|
@view_config(route_name='batch_terminals', renderer='/batches/terminals.mako')
|
|
def terminals(context, request):
|
|
|
|
fmap = filters.get_filter_map(
|
|
rattail.BatchTerminal,
|
|
exact=['sil_id'],
|
|
ilike=['description'])
|
|
|
|
config = filters.get_search_config(
|
|
'batch_terminals', request, fmap,
|
|
include_filter_description=True,
|
|
filter_type_description='lk')
|
|
|
|
search = filters.get_search_form(
|
|
config, sil_id="SIL ID")
|
|
|
|
config = grids.get_grid_config(
|
|
'batch_terminals', request, search,
|
|
filter_map=fmap, sort='description', deletable=True)
|
|
|
|
smap = grids.get_sort_map(
|
|
rattail.BatchTerminal,
|
|
['sil_id', 'description'])
|
|
|
|
def query(config):
|
|
q = Session.query(rattail.BatchTerminal)
|
|
q = filters.filter_query(q, config)
|
|
q = grids.sort_query(q, config, smap)
|
|
return q
|
|
|
|
terminals = grids.get_pager(query, config)
|
|
g = forms.AlchemyGrid(
|
|
rattail.BatchTerminal, terminals, config,
|
|
gridurl=request.route_url('batch_terminals'),
|
|
objurl='batch_terminal.edit',
|
|
delurl='batch_terminal.delete')
|
|
|
|
g.configure(
|
|
include=[
|
|
g.sil_id.label("SIL ID"),
|
|
g.description,
|
|
])
|
|
|
|
g.readonly = True
|
|
grid = g.render(class_='clickable batch-terminals')
|
|
return grids.render_grid(request, grid, search)
|
|
|
|
|
|
@view_config(route_name='batch.list', renderer='/batches/index.mako')
|
|
def batches(context, request):
|
|
|
|
fmap = filters.get_filter_map(
|
|
rattail.Batch,
|
|
ilike=['description', 'source_description'],
|
|
target=filters.filter_ilike(rattail.BatchTerminal.description))
|
|
|
|
config = filters.get_search_config(
|
|
'batches', request, fmap,
|
|
include_filter_description=True,
|
|
filter_type_description='lk',
|
|
include_filter_source_description=True,
|
|
filter_type_source_description='lk',
|
|
include_filter_target=True,
|
|
filter_type_target='lk')
|
|
|
|
search = filters.get_search_form(
|
|
config, source_description="Source")
|
|
|
|
config = grids.get_grid_config(
|
|
'batches', request, search,
|
|
filter_map=fmap, deletable=True, sort='target',
|
|
actions=['Execute'])
|
|
|
|
smap = grids.get_sort_map(
|
|
rattail.Batch,
|
|
['source_description', 'batch_id', 'action_type',
|
|
# 'description', 'rowcount', 'effective'],
|
|
'description', 'rowcount'],
|
|
target=grids.sorter(rattail.BatchTerminal.description))
|
|
|
|
def query(config):
|
|
q = Session.query(rattail.Batch)
|
|
q = q.outerjoin((rattail.BatchTerminal,
|
|
rattail.BatchTerminal.uuid == rattail.Batch.target_uuid))
|
|
q = q.filter(or_(
|
|
rattail.Batch.deleted == None,
|
|
and_(
|
|
rattail.Batch.deleted != None,
|
|
rattail.Batch.deleted != True,
|
|
),
|
|
))
|
|
q = filters.filter_query(q, config)
|
|
q = grids.sort_query(q, config, smap)
|
|
return q
|
|
|
|
batches = grids.get_pager(query, config)
|
|
g = forms.AlchemyGrid(
|
|
rattail.Batch, batches, config,
|
|
gridurl=request.route_url('batch.list'),
|
|
# url_object=request.route_url('batch'),
|
|
# url_delete=request.route_url('batch'))
|
|
objurl='batch.edit', delurl='batch.delete')
|
|
|
|
g.configure(
|
|
include=[
|
|
g.source_description.label("Source"),
|
|
g.batch_id.with_renderer(BatchIdFieldRenderer).label("Batch ID"),
|
|
g.target,
|
|
g.action_type.with_renderer(forms.EnumFieldRenderer(rattail.BATCH_ACTION_TYPE)).label("Action"),
|
|
g.description,
|
|
g.rowcount.label("Rows"),
|
|
# g.effective.with_renderer(forms.PrettyDateTimeFieldRenderer),
|
|
])
|
|
|
|
g.readonly = True
|
|
grid = g.render(class_='clickable batches')
|
|
return grids.render_grid(request, grid, search)
|
|
|
|
|
|
def _batch_columns(request, batch):
|
|
"""
|
|
Returns a rendered grid of :class:`rattail.BatchColumn` instances for a
|
|
given :class:`rattail.Batch` instance.
|
|
"""
|
|
|
|
config = grids.get_grid_config(
|
|
'batch.columns', request, sort='ordinal')
|
|
|
|
smap = grids.get_sort_map(
|
|
rattail.BatchColumn,
|
|
['ordinal', 'targeted'])
|
|
smap['sil_column'] = grids.sorter(rattail.SilColumn.sil_name)
|
|
smap['display'] = grids.sorter(rattail.SilColumn.display)
|
|
smap['source'] = grids.sorter(rattail.BatchTerminal.description)
|
|
|
|
def query(config):
|
|
q = Session.query(rattail.BatchColumn)
|
|
q = q.join(rattail.SilColumn)
|
|
q = q.join(rattail.BatchTerminal)
|
|
q = q.filter(rattail.BatchColumn.batch == batch)
|
|
q = grids.sort_query(q, config, smap)
|
|
return q
|
|
|
|
url = request.route_url('batch.columns', uuid=batch.uuid)
|
|
|
|
columns = query(config)
|
|
g = forms.AlchemyGrid(rattail.BatchColumn, columns, config, url)
|
|
|
|
g.append(formalchemy.Field('display', value=lambda x: x.sil_column.display))
|
|
|
|
g.configure(
|
|
include=[
|
|
g.ordinal,
|
|
g.sil_column.label("SIL Name"),
|
|
g.display,
|
|
g.source,
|
|
g.targeted,
|
|
])
|
|
|
|
g.readonly = True
|
|
return g.render(class_='hoverable batch-columns')
|
|
|
|
|
|
@view_config(route_name='batch.columns')
|
|
def batch_columns(context, request):
|
|
uuid = request.matchdict['uuid']
|
|
batch = Session.query(rattail.Batch).get(uuid) if uuid else None
|
|
assert batch
|
|
return Response(
|
|
body=_batch_columns(request, batch),
|
|
content_type='text/html')
|
|
|
|
|
|
def batch_fieldset(batch, request):
|
|
fs = forms.make_fieldset(batch, url=request.route_url,
|
|
url_action=request.current_route_url(),
|
|
route_name='batch.list')
|
|
|
|
# Remove unsupported action types...for now.
|
|
enum = rattail.BATCH_ACTION_TYPE.copy()
|
|
del enum[rattail.BATCH_LOAD]
|
|
|
|
fs.configure(
|
|
include=[
|
|
fs.source.validate(forms.required),
|
|
fs.batch_id.with_renderer(BatchIdFieldRenderer).label("Batch ID").readonly(),
|
|
fs.target.validate(forms.required),
|
|
fs.dictionary.validate(forms.required),
|
|
fs.action_type.with_renderer(forms.EnumFieldRenderer(enum)).validate(forms.required).label("Action"),
|
|
fs.description,
|
|
# fs.effective.with_renderer(forms.PrettyDateTimeFieldRenderer),
|
|
fs.rowcount.label("Rows").readonly(),
|
|
])
|
|
|
|
if fs.edit:
|
|
fs.source.set(readonly=True)
|
|
fs.dictionary.set(readonly=True)
|
|
# if fs.model.target:
|
|
# fs.target.set(readonly=True)
|
|
# fs.action_type.set(readonly=True)
|
|
# fs.effective.set(readonly=True)
|
|
fs.append(forms.ChildGridField('columns', _batch_columns(request, fs.model)))
|
|
else:
|
|
del fs.batch_id
|
|
# del fs.effective
|
|
del fs.rowcount
|
|
return fs
|
|
|
|
|
|
@view_config(route_name='batch.edit', renderer='/batches/batch.mako')
|
|
def edit_batch(context, request):
|
|
uuid = request.matchdict['uuid']
|
|
batch = Session.query(rattail.Batch).get(uuid) if uuid else None
|
|
assert batch
|
|
|
|
fs = batch_fieldset(batch, request)
|
|
if request.POST:
|
|
fs.rebind(data=request.params)
|
|
if fs.validate():
|
|
|
|
with transaction.manager:
|
|
fs.sync()
|
|
# fs.model = Session.merge(fs.model)
|
|
request.session.flash("%s \"%s\" has been %s." % (
|
|
fs.crud_title, fs.get_display_text(),
|
|
'updated' if fs.edit else 'created'))
|
|
home = request.route_url('batch.edit', uuid=fs.model.uuid)
|
|
|
|
return HTTPFound(location=home)
|
|
|
|
fs.append(forms.ChildGridField('columns', _batch_columns(request, batch)))
|
|
|
|
return {'fieldset': fs, 'crud': True}
|
|
|
|
|
|
@view_config(route_name='batch.delete')
|
|
def delete_batch(context, request):
|
|
uuid = request.matchdict['uuid']
|
|
batch = Session.query(rattail.Batch).get(uuid) if uuid else None
|
|
assert batch
|
|
with transaction.manager:
|
|
Session.delete(batch)
|
|
return HTTPFound(location=request.route_url('batch.list'))
|
|
|
|
|
|
# @view_config(route_name='batch', renderer='/batches/batch.mako')
|
|
# def batch(context, request):
|
|
|
|
# def fieldset(batch):
|
|
# fs = forms.make_fieldset(batch, url=request.route_url,
|
|
# url_action=request.route_url('batch'),
|
|
# route_name='batches')
|
|
|
|
# # Remove unsupported action types...for now.
|
|
# enum = rattail.BATCH_ACTION_TYPE.copy()
|
|
# del enum[rattail.BATCH_ADD_REPLACE]
|
|
# del enum[rattail.BATCH_CHANGE]
|
|
# del enum[rattail.BATCH_LOAD]
|
|
# del enum[rattail.BATCH_REMOVE]
|
|
|
|
# fs.configure(
|
|
# include=[
|
|
# fs.source.validate(forms.required),
|
|
# fs.batch_id.with_renderer(BatchIdFieldRenderer).label("Batch ID").readonly(),
|
|
# fs.target.validate(forms.required),
|
|
# fs.dictionary.validate(forms.required),
|
|
# fs.action_type.with_renderer(forms.EnumFieldRenderer(enum)).validate(forms.required).label("Action"),
|
|
# fs.description,
|
|
# fs.effective.with_renderer(forms.PrettyDateTimeFieldRenderer),
|
|
# fs.rowcount.label("Rows").readonly(),
|
|
# ])
|
|
# if fs.edit:
|
|
# fs.source.set(readonly=True)
|
|
# fs.dictionary.set(readonly=True)
|
|
# if fs.model.target:
|
|
# fs.target.set(readonly=True)
|
|
# fs.action_type.set(readonly=True)
|
|
# fs.effective.set(readonly=True)
|
|
# fs.append(forms.ChildGridField('columns', _batch_columns(request, fs.model)))
|
|
# else:
|
|
# del fs.batch_id
|
|
# del fs.effective
|
|
# del fs.rowcount
|
|
# return fs
|
|
|
|
# def post_sync(fs):
|
|
# if not fs.edit:
|
|
# source = Session.query(rattail.BatchTerminal).get(fs.model.source_uuid)
|
|
# target = Session.query(rattail.BatchTerminal).get(fs.model.target_uuid)
|
|
# assert source and target
|
|
# batch = fs.model
|
|
# batch.batch_id = next_batch_id(source.sil_id, consume=True,
|
|
# session=Session())
|
|
# batch.name = '%s.%08u' % (source.sil_id, batch.batch_id)
|
|
# batch.source_description = source.description
|
|
|
|
# for i, col in enumerate(source.source_columns, 1):
|
|
# batch.columns.append(rattail.BatchColumn(
|
|
# ordinal=i,
|
|
# column=col.sil_column,
|
|
# source=source,
|
|
# targeted=True,
|
|
# ))
|
|
|
|
# def pre_render(fs):
|
|
# if not fs.edit:
|
|
|
|
# for field in ('source', 'target'):
|
|
# if not fs.render_fields[field].value:
|
|
# q = Session.query(rattail.BatchTerminal)
|
|
# q = q.filter(getattr(rattail.BatchTerminal, field) == True)
|
|
# count = q.count()
|
|
# if count == 1:
|
|
# setattr(fs.model, field, q.first())
|
|
# fs.render_fields[field].set(required=True) # hack to avoid null option
|
|
# elif not count:
|
|
# request.session.flash("You must create at least one %s Batch Terminal "
|
|
# "before you may create a Batch." % prettify(field))
|
|
# return HTTPFound(location=request.route_url('batches'))
|
|
|
|
# # else:
|
|
# # data = {'columns': _batch_columns(request, fs.model)}
|
|
# # return {'columns': render('/batches/columns.mako', data)}
|
|
|
|
# # def delete(batch):
|
|
# # # jct = batch.target_junction.display if batch.target_junction else batch.target
|
|
# # # batch.table.drop()
|
|
# # # self.request.session.flash("Batch was deleted: %s" % self.batch_display(batch))
|
|
# # self.Session.delete(batch)
|
|
# # # self.Session.flush()
|
|
|
|
# return crud(request, rattail.Batch, fieldset,
|
|
# delete=request.route_url('batches'),
|
|
# post_sync=post_sync, pre_render=pre_render)
|
|
|
|
@view_config(route_name='batch.details', renderer='/batches/details.mako')
|
|
def batch_details(context, request):
|
|
uuid = request.matchdict['uuid']
|
|
batch = Session.query(rattail.Batch).get(uuid) if uuid else None
|
|
assert batch
|
|
request.session['batches.uuid'] = batch.uuid
|
|
name = 'batches.%s' % batch.name
|
|
|
|
# def batch_search_form(batch, name):
|
|
# """
|
|
# Returns a dynamically-assembled search form, specific to the current
|
|
# batch.
|
|
# """
|
|
|
|
# config = filters.get_search_config(name, request, batch_filter_map(batch))
|
|
# labels = {}
|
|
# form = filters.get_search_form(config, **labels)
|
|
# return form
|
|
|
|
# def batch_query(batch):
|
|
|
|
# def query(config):
|
|
# q = Session.query(batch.rowclass)
|
|
# q = filters.filter_query(q, config, batch_filter_map(batch))
|
|
# q = grids.sort_query(q, config, batch_sort_map(batch))
|
|
# return q
|
|
|
|
# return query
|
|
|
|
# def batch_grid(batch):
|
|
|
|
# cls = batch.rowclass
|
|
|
|
# def grid(query, config):
|
|
# rows = grids.get_pager(query, config)
|
|
# g = grids.get_grid(cls, rows, config)
|
|
# include = [getattr(g, x.column.sil_name) for x in batch.columns]
|
|
# # if batch.target_junction:
|
|
# # fnmap = batch.target_junction.fieldname_map_ui
|
|
# # for name in fnmap:
|
|
# # getattr(g, name).set(label=fnmap[name])
|
|
# g.configure(include=include)
|
|
# return g
|
|
|
|
# return grid
|
|
|
|
cls = batch.rowclass
|
|
|
|
fmap = filters.get_filter_map(cls)
|
|
for col in batch.columns:
|
|
fmap.setdefault(col.sil_column.sil_name,
|
|
filters.filter_ilike(getattr(cls, col.sil_column.sil_name)))
|
|
|
|
config = filters.get_search_config('batch.%s' % batch.name, request, fmap)
|
|
|
|
search = filters.get_search_form(config)
|
|
|
|
config = grids.get_grid_config(
|
|
'batch.%s' % batch.name, request, search, filter_map=fmap,
|
|
url=request.route_url('batch.details', uuid=batch.uuid),
|
|
sort=batch.columns[0].sil_column.sil_name)
|
|
|
|
# url = request.route_url('batch.details')
|
|
# grid = forms.AlchemyGrid(name, batch_grid(batch), batch_query(batch),
|
|
# search, url=url, sort='F01', per_page=20)
|
|
# query = batch_query(batch)
|
|
|
|
smap = grids.get_sort_map(cls)
|
|
# cls = batch.rowclass
|
|
# # return {
|
|
# # 'F01': util.sorter(cls.F01),
|
|
# # }
|
|
# sort_map = {}
|
|
# for name in batch.elements.split(','):
|
|
# sort_map[name] = util.sorter(getattr(cls, name))
|
|
|
|
def query(config):
|
|
q = Session.query(batch.rowclass)
|
|
q = filters.filter_query(q, config)
|
|
q = grids.sort_query(q, config, smap)
|
|
return q
|
|
|
|
rows = grids.get_pager(query, config)
|
|
grid = forms.AlchemyGrid(
|
|
cls, rows, config,
|
|
request.route_url('batch.details', uuid=batch.uuid))
|
|
grid.readonly = True
|
|
grid = grid.render(class_='clickable batch-details')
|
|
return grids.render_grid(request, grid, search, batch=batch,
|
|
pretty_datetime=forms.pretty_datetime)
|
|
|
|
@view_config(route_name='batch.execute')
|
|
def execute(context, request):
|
|
"""
|
|
Executes a batch.
|
|
"""
|
|
|
|
uuid = request.matchdict['uuid']
|
|
home = HTTPFound(location=request.route_url('batch.list'))
|
|
|
|
with transaction.manager:
|
|
batch = Session.query(rattail.Batch).get(uuid) if uuid else None
|
|
if not batch:
|
|
return home
|
|
batch.execute()
|
|
|
|
# table = batch.table
|
|
# rowclass = batch.rowclass
|
|
# # self.Session.delete(batch)
|
|
# batch.deleted = True
|
|
# self.Session.flush()
|
|
# print 'deleted batch'
|
|
# q = self.Session.query(rowclass)
|
|
# q.delete(synchronize_session=False)
|
|
# print 'deleted rows'
|
|
# # table.drop(bind=self.Session().bind, checkfirst=False)
|
|
# # print 'dropped table'
|
|
|
|
request.session.flash("The batch was executed: %s, %s" % (
|
|
batch.target, rattail.BATCH_ACTION_TYPE[batch.action_type]))
|
|
return home
|
|
|
|
|
|
def includeme(config):
|
|
config.add_route('sil_columns', '/batches/sil_columns')
|
|
config.add_route('sil_column', '/batches/sil_column')
|
|
config.add_route('batch_dictionaries', '/batches/dictionaries')
|
|
config.add_route('batch_dictionary', '/batches/dictionary')
|
|
config.add_route('batch_dictionary.columns', '/batches/dictionary-columns')
|
|
|
|
config.add_route('batch_terminals', '/batches/terminals')
|
|
config.add_route('batch_terminal.new', '/batches/terminal/new')
|
|
config.add_route('batch_terminal.edit', '/batches/terminal/{uuid}/edit')
|
|
config.add_route('batch_terminal.delete', '/batches/terminal/{uuid}/delete')
|
|
config.add_route('batch_terminal.columns', '/batches/terminal/{uuid}/columns')
|
|
# config.add_route('batch_terminal', '/batches/terminal/{uuid}')
|
|
|
|
config.add_route('batch.list', '/batches')
|
|
# config.add_route('batch', '/batch')
|
|
# config.add_route('batch.new', '/batches/new')
|
|
config.add_route('batch.edit', '/batches/{uuid}/edit')
|
|
config.add_route('batch.delete', '/batches/{uuid}/delete')
|
|
config.add_route('batch.columns', '/batch/{uuid}/columns')
|
|
config.add_route('batch.details', '/batch/{uuid}/details')
|
|
config.add_route('batch.execute', '/batch/{uuid}/execute')
|
|
|
|
config.scan(__name__)
|