save point

This commit is contained in:
Lance Edgar 2012-04-10 22:28:02 -05:00
parent b28631d421
commit 523d7de3e7
13 changed files with 556 additions and 226 deletions

View file

@ -71,7 +71,7 @@ class UpcFieldRenderer(formalchemy.TextFieldRenderer):
if isinstance(value, basestring): if isinstance(value, basestring):
if value.isdigit(): if value.isdigit():
value = int(value) value = int(value)
if isinstance(value, int): if isinstance(value, (int, long)):
return '%013u' % value return '%013u' % value
return self.stringify_value(value, as_html=True) return self.stringify_value(value, as_html=True)

View file

@ -4,7 +4,7 @@
<%def name="crud_name()">Batch</%def> <%def name="crud_name()">Batch</%def>
<%def name="menu()"> <%def name="menu()">
<p>${h.link_to("Back to Batches", url('batches'))}</p> <p>${h.link_to("Back to Batches", url('batch.list'))}</p>
% if fieldset.edit and fieldset.model.rowcount: % if fieldset.edit and fieldset.model.rowcount:
<p>${h.link_to("View Batch Details", url('batch.details', uuid=fieldset.model.uuid))}</p> <p>${h.link_to("View Batch Details", url('batch.details', uuid=fieldset.model.uuid))}</p>
% endif % endif

View file

@ -4,8 +4,8 @@
<%def name="title()">Batch : ${batch.name}</%def> <%def name="title()">Batch : ${batch.name}</%def>
<%def name="menu()"> <%def name="menu()">
<p>${h.link_to("Back to Batches", url('batches'))}</p> <p>${h.link_to("Back to Batches", url('batch.list'))}</p>
<p>${h.link_to("View Batch Properties", url('batch') + '?uuid=' + batch.uuid)}</p> <p>${h.link_to("View Batch Properties", url('batch.edit', uuid=batch.uuid))}</p>
<p>${h.link_to("Execute this Batch", url('batch.execute', uuid=batch.uuid))}</p> <p>${h.link_to("Execute this Batch", url('batch.execute', uuid=batch.uuid))}</p>
</%def> </%def>

View file

@ -4,8 +4,8 @@
<%def name="title()">Batches</%def> <%def name="title()">Batches</%def>
<%def name="menu()"> <%def name="menu()">
<p>${h.link_to("Create a New Batch", url('batch'))}</p> ## <p>${h.link_to("Create a New Batch", url('batch.new'))}</p>
<p>${h.link_to("Manage Terminals", url('batch_terminals'))}</p> <p>${h.link_to("Manage Terminals", url('batch_terminal.list'))}</p>
<p>${h.link_to("View Dictionaries", url('batch_dictionaries'))}</p> <p>${h.link_to("View Dictionaries", url('batch_dictionaries'))}</p>
<p>${h.link_to("SIL Columns", url('sil_columns'))}</p> <p>${h.link_to("SIL Columns", url('sil_columns'))}</p>
</%def> </%def>

View file

@ -2,12 +2,8 @@
<%inherit file="/crud.mako" /> <%inherit file="/crud.mako" />
<%def name="menu()"> <%def name="menu()">
<p>${h.link_to("Back to Batches", url('batches'))}</p> <p>${h.link_to("Back to Batches", url('batch.list'))}</p>
<p>${h.link_to("Back to Batch Terminals", url('batch_terminals'))}</p> <p>${h.link_to("Back to Batch Terminals", url('batch_terminal.list'))}</p>
</%def> </%def>
${parent.body()} ${parent.body()}
% if fieldset.edit:
${terminal_columns|n}
% endif

View file

@ -1,17 +0,0 @@
<h2>Supported Columns</h2>
<table class="fieldset">
<tr class="source_columns">
<td class="label">Source</td>
<td>
${source|n}
</td>
</tr>
<tr class="target_columns">
<td class="label">Target</td>
<td>
${target|n}
</td>
</tr>
</table>

View file

@ -4,8 +4,8 @@
<%def name="title()">Batch Terminals</%def> <%def name="title()">Batch Terminals</%def>
<%def name="menu()"> <%def name="menu()">
<p>${h.link_to("Back to Batches", url('batches'))}</p> <p>${h.link_to("Back to Batches", url('batch.list'))}</p>
<p>${h.link_to("Create a New Terminal", url('batch_terminal'))}</p> <p>${h.link_to("Create a New Terminal", url('batch_terminal.new'))}</p>
</%def> </%def>
${parent.body()} ${parent.body()}

View file

@ -0,0 +1,2 @@
<%inherit file="/base.mako" />
${parent.body()}

View file

@ -0,0 +1,6 @@
<%inherit file="/departments/base.mako" />
<%inherit file="/index.mako" />
<%def name="title()">Departments</%def>
${parent.body()}

View file

@ -0,0 +1,33 @@
#!/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`` -- Pyramid Views
"""
def includeme(config):
config.include('rattail.pyramid.views.batches')
config.include('rattail.pyramid.views.departments')
config.include('rattail.pyramid.views.products')

View file

@ -28,6 +28,7 @@
import formalchemy import formalchemy
from sqlalchemy import and_, or_ from sqlalchemy import and_, or_
from sqlalchemy.orm import joinedload
import transaction import transaction
from pyramid.httpexceptions import HTTPFound from pyramid.httpexceptions import HTTPFound
@ -227,11 +228,11 @@ def _dictionary_columns(request, uuid=None):
g.append( g.append(
formalchemy.Field( formalchemy.Field(
'display', 'display',
value=lambda x: x.column.display)) value=lambda x: x.sil_column.display))
g.configure( g.configure(
include=[ include=[
g.column, g.sil_column.label("SIL Name"),
g.display, g.display,
g.key, g.key,
]) ])
@ -278,49 +279,52 @@ def batch_dictionary(context, request):
pre_render=pre_render) pre_render=pre_render)
def _terminal_columns(request, terminal, column_type): def _terminal_columns(request, terminal):
""" """
Returns a rendered grid of either Returns a rendered grid of :class:`rattail.BatchTerminalColumn` instances,
:class:`rattail.BatchTerminalSourceColumn` or depending on ``terminal``.
:class:`rattail.BatchTerminalTargetColumn` instances, depending on
``column_type`` (and of cource ``terminal``).
""" """
cls = getattr(rattail, 'BatchTerminal%sColumn' % column_type.title())
config = grids.get_grid_config( config = grids.get_grid_config(
'batch_terminal.columns', request, sort='dictionary') 'batch_terminal.columns', request, sort='dictionary')
smap = { smap = grids.get_sort_map(
'dictionary': grids.sorter(rattail.BatchDictionary.name), rattail.BatchTerminalColumn,
'column': grids.sorter(rattail.SilColumn.sil_name), ['source', 'target'],
'display': grids.sorter(rattail.SilColumn.display), 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): def query(config):
q = Session.query(cls) q = Session.query(rattail.BatchTerminalColumn)
q = q.join(rattail.BatchDictionary) # q = q.join(rattail.BatchDictionary)
q = q.join(rattail.SilColumn) q = q.options(joinedload(rattail.BatchTerminalColumn.dictionary))
q = q.filter(cls.terminal == terminal) q = q.options(joinedload(rattail.BatchTerminalColumn.sil_column))
q = grids.sort_query(q, config, smap) q = q.filter(rattail.BatchTerminalColumn.terminal_uuid == terminal.uuid)
q = grids.sort_query(q, config, smap, jmap)
return q return q
url = (request.route_url('batch_terminal.columns')
+ '?uuid=' + terminal.uuid + '&type=' + column_type)
columns = query(config) columns = query(config)
g = forms.AlchemyGrid(cls, columns, config, url) g = forms.AlchemyGrid(rattail.BatchTerminalColumn, columns, config,
gridurl=request.route_url('batch_terminal.columns', uuid=terminal.uuid))
g.append( g.append(
formalchemy.Field( formalchemy.Field(
'display', 'display',
value=lambda x: x.column.display)) value=lambda x: x.sil_column.display))
g.configure( g.configure(
include=[ include=[
g.dictionary, g.dictionary,
g.column, g.sil_column.label("SIL Name"),
g.display, g.display,
g.source,
g.target,
]) ])
g.readonly = True g.readonly = True
@ -328,27 +332,15 @@ def _terminal_columns(request, terminal, column_type):
@view_config(route_name='batch_terminal.columns') @view_config(route_name='batch_terminal.columns')
def batch_terminal_columns(context, request): def terminal_columns(context, request):
uuid = request.params.get('uuid') uuid = request.matchdict['uuid']
terminal = Session.query(rattail.BatchTerminal).get(uuid) if uuid else None terminal = Session.query(rattail.BatchTerminal).get(uuid) if uuid else None
assert terminal assert terminal
return Response( return Response(
body=_terminal_columns(request, terminal, request.params.get('type')), body=_terminal_columns(request, terminal),
content_type='text/html') content_type='text/html')
# @view_config(route_name='batch_terminal.source_columns')
# def batch_terminal_source_columns(context, request):
# return Response(body=_terminal_columns(request, 'source'),
# content_type='text/html')
# @view_config(route_name='batch_terminal.target_columns')
# def batch_terminal_target_columns(context, request):
# return Response(body=_terminal_columns(request, 'target'),
# content_type='text/html')
def update_terminal_info(terminal): def update_terminal_info(terminal):
""" """
Updates the terminal's list of supported source and target columns, based Updates the terminal's list of supported source and target columns, based
@ -364,10 +356,27 @@ def update_terminal_info(terminal):
return err return err
else: else:
if true_terminal: if true_terminal:
# for column_type in ('source', 'target'):
# declared_columns = getattr(true_terminal, '%s_columns' % column_type)
# stored_columns = getattr(terminal, '%s_columns' % column_type)
# cls = getattr(rattail, 'BatchTerminal%sColumn' % column_type.title())
# for dictionary, columns in declared_columns.iteritems():
# q = Session.query(rattail.BatchDictionary)
# q = q.filter_by(name=dictionary)
# dictionary = q.one()
# for col in columns:
# q = Session.query(rattail.SilColumn)
# q = q.filter_by(sil_name=col)
# col = q.one()
# stored_columns.append(cls(
# dictionary=dictionary,
# column=col))
# setattr(terminal, column_type, bool(declared_columns))
stored_columns = {}
for col in terminal.columns:
stored_columns[col.sil_column.sil_name] = col
for column_type in ('source', 'target'): for column_type in ('source', 'target'):
declared_columns = getattr(true_terminal, '%s_columns' % column_type) declared_columns = getattr(true_terminal, '%s_columns' % column_type)
stored_columns = getattr(terminal, '%s_columns' % column_type)
cls = getattr(rattail, 'BatchTerminal%sColumn' % column_type.title())
for dictionary, columns in declared_columns.iteritems(): for dictionary, columns in declared_columns.iteritems():
q = Session.query(rattail.BatchDictionary) q = Session.query(rattail.BatchDictionary)
q = q.filter_by(name=dictionary) q = q.filter_by(name=dictionary)
@ -376,23 +385,36 @@ def update_terminal_info(terminal):
q = Session.query(rattail.SilColumn) q = Session.query(rattail.SilColumn)
q = q.filter_by(sil_name=col) q = q.filter_by(sil_name=col)
col = q.one() col = q.one()
stored_columns.append(cls( if col.sil_name in stored_columns:
setattr(stored_columns[col.sil_name], column_type, True)
else:
col = rattail.BatchTerminalColumn(
dictionary=dictionary, dictionary=dictionary,
column=col)) sil_column=col)
setattr(col, column_type, True)
terminal.columns.append(col)
stored_columns[col.sil_column.sil_name] = col
# Session.add(col)
Session.flush()
# stored_columns.append(rattail.BatchTerminalColumn(
# dictionary=dictionary,
# sil_column=col))
setattr(terminal, column_type, bool(declared_columns)) setattr(terminal, column_type, bool(declared_columns))
for col in terminal.columns:
if not col.source:
col.source = False
if not col.target:
col.target = False
return true_terminal return true_terminal
else: else:
terminal.functional = False terminal.functional = False
@view_config(route_name='batch_terminal', renderer='/batches/terminal.mako') def terminal_fieldset(terminal, request):
def batch_terminal(context, request):
def fieldset(terminal):
fs = forms.make_fieldset( fs = forms.make_fieldset(
terminal, crud_title="Batch Terminal", terminal, crud_title="Batch Terminal",
url_action=request.route_url('batch_terminal'), url_action=request.current_route_url(),
url_cancel=request.route_url('batch_terminals')) url_cancel=request.route_url('batch_terminal.list'))
fs.configure( fs.configure(
include=[ include=[
@ -400,27 +422,26 @@ def batch_terminal(context, request):
fs.description, fs.description,
fs.class_spec.validate(forms.required), fs.class_spec.validate(forms.required),
fs.functional.readonly(), fs.functional.readonly(),
fs.source_kwargs, # fs.source_kwargs,
fs.target_kwargs, # fs.target_kwargs,
]) ])
if fs.edit: # if not fs.edit:
fs.sil_id.set(readonly=True) # del fs.source_kwargs
else: # del fs.target_kwargs
del fs.source_kwargs
del fs.target_kwargs
return fs return fs
def pre_render(fs):
if fs.edit:
data = {
'source': _terminal_columns(request, fs.model, 'source'),
'target': _terminal_columns(request, fs.model, 'target'),
}
return {'terminal_columns':
render('/batches/terminal_columns.mako', data)}
def post_sync(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) terminal = update_terminal_info(fs.model)
if isinstance(terminal, LoadSpecError): if isinstance(terminal, LoadSpecError):
request.session.flash(str(terminal)) request.session.flash(str(terminal))
@ -430,14 +451,120 @@ def batch_terminal(context, request):
if not fs.model.description: if not fs.model.description:
fs.model.description = terminal.description fs.model.description = terminal.description
return crud( # fs.model = Session.merge(fs.model)
request, rattail.BatchTerminal, fieldset, Session.add(fs.model)
delete=request.route_url('batch_terminals'), Session.flush()
pre_render=pre_render, post_sync=post_sync) 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_terminals', renderer='/batches/terminals.mako') @view_config(route_name='batch_terminal.edit', renderer='/batches/terminal.mako')
def batch_terminals(context, request): 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_terminal.list'))
# @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_terminal.list', renderer='/batches/terminals.mako')
def terminals(context, request):
fmap = filters.get_filter_map( fmap = filters.get_filter_map(
rattail.BatchTerminal, rattail.BatchTerminal,
@ -445,7 +572,7 @@ def batch_terminals(context, request):
ilike=['description']) ilike=['description'])
config = filters.get_search_config( config = filters.get_search_config(
'batch_terminals', request, fmap, 'batch_terminal.list', request, fmap,
include_filter_description=True, include_filter_description=True,
filter_type_description='lk') filter_type_description='lk')
@ -453,7 +580,7 @@ def batch_terminals(context, request):
config, sil_id="SIL ID") config, sil_id="SIL ID")
config = grids.get_grid_config( config = grids.get_grid_config(
'batch_terminals', request, search, 'batch_terminal.list', request, search,
filter_map=fmap, sort='description', deletable=True) filter_map=fmap, sort='description', deletable=True)
smap = grids.get_sort_map( smap = grids.get_sort_map(
@ -469,9 +596,9 @@ def batch_terminals(context, request):
terminals = grids.get_pager(query, config) terminals = grids.get_pager(query, config)
g = forms.AlchemyGrid( g = forms.AlchemyGrid(
rattail.BatchTerminal, terminals, config, rattail.BatchTerminal, terminals, config,
request.route_url('batch_terminals'), gridurl=request.route_url('batch_terminal.list'),
url_object=request.route_url('batch_terminal'), objurl='batch_terminal.edit',
url_delete=request.route_url('batch_terminal')) delurl='batch_terminal.delete')
g.configure( g.configure(
include=[ include=[
@ -484,7 +611,7 @@ def batch_terminals(context, request):
return grids.render_grid(request, grid, search) return grids.render_grid(request, grid, search)
@view_config(route_name='batches', renderer='/batches/index.mako') @view_config(route_name='batch.list', renderer='/batches/index.mako')
def batches(context, request): def batches(context, request):
fmap = filters.get_filter_map( fmap = filters.get_filter_map(
@ -532,9 +659,10 @@ def batches(context, request):
batches = grids.get_pager(query, config) batches = grids.get_pager(query, config)
g = forms.AlchemyGrid( g = forms.AlchemyGrid(
rattail.Batch, batches, config, rattail.Batch, batches, config,
request.route_url('batches'), gridurl=request.route_url('batch.list'),
url_object=request.route_url('batch'), # url_object=request.route_url('batch'),
url_delete=request.route_url('batch')) # url_delete=request.route_url('batch'))
objurl='batch.edit', delurl='batch.delete')
g.configure( g.configure(
include=[ include=[
@ -581,12 +709,12 @@ def _batch_columns(request, batch):
columns = query(config) columns = query(config)
g = forms.AlchemyGrid(rattail.BatchColumn, columns, config, url) g = forms.AlchemyGrid(rattail.BatchColumn, columns, config, url)
g.append(formalchemy.Field('display', value=lambda x: x.column.display)) g.append(formalchemy.Field('display', value=lambda x: x.sil_column.display))
g.configure( g.configure(
include=[ include=[
g.ordinal, g.ordinal,
g.column.label("SIL Name"), g.sil_column.label("SIL Name"),
g.display, g.display,
g.source, g.source,
g.targeted, g.targeted,
@ -606,13 +734,10 @@ def batch_columns(context, request):
content_type='text/html') content_type='text/html')
@view_config(route_name='batch', renderer='/batches/batch.mako') def batch_fieldset(batch, request):
def batch(context, request):
def fieldset(batch):
fs = forms.make_fieldset(batch, url=request.route_url, fs = forms.make_fieldset(batch, url=request.route_url,
url_action=request.route_url('batch'), url_action=request.current_route_url(),
route_name='batches') route_name='batch.list')
# Remove unsupported action types...for now. # Remove unsupported action types...for now.
enum = rattail.BATCH_ACTION_TYPE.copy() enum = rattail.BATCH_ACTION_TYPE.copy()
@ -646,55 +771,132 @@ def batch(context, request):
del fs.rowcount del fs.rowcount
return fs 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): @view_config(route_name='batch.edit', renderer='/batches/batch.mako')
batch.columns.append(rattail.BatchColumn( def edit_batch(context, request):
ordinal=i, uuid = request.matchdict['uuid']
column=col.column, batch = Session.query(rattail.Batch).get(uuid) if uuid else None
source=source, assert batch
targeted=True,
))
def pre_render(fs): fs = batch_fieldset(batch, request)
if not fs.edit: if request.POST:
fs.rebind(data=request.params)
if fs.validate():
for field in ('source', 'target'): with transaction.manager:
if not fs.render_fields[field].value: fs.sync()
q = Session.query(rattail.BatchTerminal) # fs.model = Session.merge(fs.model)
q = q.filter(getattr(rattail.BatchTerminal, field) == True) request.session.flash("%s \"%s\" has been %s." % (
count = q.count() fs.crud_title, fs.get_display_text(),
if count == 1: 'updated' if fs.edit else 'created'))
setattr(fs.model, field, q.first()) home = request.route_url('batch.edit', uuid=fs.model.uuid)
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: return HTTPFound(location=home)
# data = {'columns': _batch_columns(request, fs.model)}
# return {'columns': render('/batches/columns.mako', data)}
# def delete(batch): fs.append(forms.ChildGridField('columns', _batch_columns(request, 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, return {'fieldset': fs, 'crud': True}
delete=request.route_url('batches'),
post_sync=post_sync, pre_render=pre_render)
@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') @view_config(route_name='batch.details', renderer='/batches/details.mako')
def batch_details(context, request): def batch_details(context, request):
@ -744,10 +946,10 @@ def batch_details(context, request):
cls = batch.rowclass cls = batch.rowclass
fmap = filters.get_filter_map(cls, exact=['F01']) fmap = filters.get_filter_map(cls)
for col in batch.columns: for col in batch.columns:
fmap.setdefault(col.column.sil_name, fmap.setdefault(col.sil_column.sil_name,
filters.filter_ilike(getattr(cls, col.column.sil_name))) filters.filter_ilike(getattr(cls, col.sil_column.sil_name)))
config = filters.get_search_config('batch.%s' % batch.name, request, fmap) config = filters.get_search_config('batch.%s' % batch.name, request, fmap)
@ -756,7 +958,7 @@ def batch_details(context, request):
config = grids.get_grid_config( config = grids.get_grid_config(
'batch.%s' % batch.name, request, search, filter_map=fmap, 'batch.%s' % batch.name, request, search, filter_map=fmap,
url=request.route_url('batch.details', uuid=batch.uuid), url=request.route_url('batch.details', uuid=batch.uuid),
sort=batch.columns[0].column.sil_name) sort=batch.columns[0].sil_column.sil_name)
# url = request.route_url('batch.details') # url = request.route_url('batch.details')
# grid = forms.AlchemyGrid(name, batch_grid(batch), batch_query(batch), # grid = forms.AlchemyGrid(name, batch_grid(batch), batch_query(batch),
@ -793,7 +995,7 @@ def execute(context, request):
Executes a batch. Executes a batch.
""" """
home = HTTPFound(location=request.route_url('batches')) home = HTTPFound(location=request.route_url('batch.list'))
# batch = self.request.params.get('uuid') # batch = self.request.params.get('uuid')
# batch = self.Session.query(rattail.Batch).get(batch) if batch else None # batch = self.Session.query(rattail.Batch).get(batch) if batch else None
@ -850,12 +1052,21 @@ def includeme(config):
config.add_route('batch_dictionaries', '/batches/dictionaries') config.add_route('batch_dictionaries', '/batches/dictionaries')
config.add_route('batch_dictionary', '/batches/dictionary') config.add_route('batch_dictionary', '/batches/dictionary')
config.add_route('batch_dictionary.columns', '/batches/dictionary-columns') config.add_route('batch_dictionary.columns', '/batches/dictionary-columns')
config.add_route('batch_terminals', '/batches/terminals')
config.add_route('batch_terminal', '/batches/terminal') config.add_route('batch_terminal.list', '/batches/terminals')
config.add_route('batch_terminal.columns', '/batches/terminal-columns') config.add_route('batch_terminal.new', '/batches/terminal')
config.add_route('batches', '/batches') config.add_route('batch_terminal.delete', '/batches/terminal/{uuid}/delete')
config.add_route('batch', '/batch') config.add_route('batch_terminal.edit', '/batches/terminal/{uuid}/edit')
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.columns', '/batch/{uuid}/columns')
config.add_route('batch.details', '/batch/{uuid}/details') config.add_route('batch.details', '/batch/{uuid}/details')
config.add_route('batch.execute', '/batch/{uuid}/execute') config.add_route('batch.execute', '/batch/{uuid}/execute')
config.scan(__name__) config.scan(__name__)

View file

@ -0,0 +1,86 @@
#!/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.departments`` -- Department Views
"""
from pyramid.view import view_config
from edbob.pyramid import filters
from edbob.pyramid import forms
from edbob.pyramid import grids
from edbob.pyramid import Session
import rattail
@view_config(route_name='department.list', renderer='/departments/index.mako')
def list_departments(context, request):
fmap = filters.get_filter_map(
rattail.Department,
exact=['number'],
ilike=['name'])
config = filters.get_search_config(
'department.list', request, fmap,
include_filter_name=True,
filter_type_name='lk')
search = filters.get_search_form(config)
config = grids.get_grid_config(
'department.list', request, search,
filter_map=fmap, sort='name')
smap = grids.get_sort_map(
rattail.Department,
['number', 'name'])
def query(config):
q = Session.query(rattail.Department)
q = filters.filter_query(q, config)
q = grids.sort_query(q, config, smap)
return q
departments = grids.get_pager(query, config)
g = forms.AlchemyGrid(
rattail.Department, departments, config,
gridurl=request.route_url('department.list'))
g.configure(
include=[
g.number,
g.name,
],
readonly=True)
grid = g.render(class_='clickable departments')
return grids.render_grid(request, grid, search)
def includeme(config):
config.add_route('department.list', '/departments')
config.scan(__name__)

View file

@ -26,6 +26,8 @@
``rattail.pyramid.views.products`` -- Product Views ``rattail.pyramid.views.products`` -- Product Views
""" """
from sqlalchemy.orm import joinedload
from pyramid.view import view_config from pyramid.view import view_config
from edbob.pyramid import filters from edbob.pyramid import filters
@ -43,10 +45,13 @@ def products(context, request):
fmap = filters.get_filter_map( fmap = filters.get_filter_map(
rattail.Product, rattail.Product,
exact=['upc'], exact=['upc'],
ilike=['description']) ilike=['description'],
brand=filters.filter_ilike(rattail.Brand.name))
config = filters.get_search_config( config = filters.get_search_config(
'products', request, fmap, 'products', request, fmap,
include_filter_brand=True,
filter_type_brand='lk',
include_filter_description=True, include_filter_description=True,
filter_type_description='lk') filter_type_description='lk')
@ -59,12 +64,19 @@ def products(context, request):
smap = grids.get_sort_map( smap = grids.get_sort_map(
rattail.Product, rattail.Product,
['upc', 'description']) ['upc', 'description'],
brand=grids.sorter(rattail.Brand.name))
jmap = {
'brand':
lambda q: q.join(rattail.Brand),
}
def query(config): def query(config):
q = Session.query(rattail.Product) q = Session.query(rattail.Product)
q = filters.filter_query(q, config) q = q.options(joinedload(rattail.Product.brand))
q = grids.sort_query(q, config, smap) q = filters.filter_query(q, config, jmap)
q = grids.sort_query(q, config, smap, jmap)
return q return q
products = grids.get_pager(query, config) products = grids.get_pager(query, config)
@ -75,10 +87,11 @@ def products(context, request):
g.configure( g.configure(
include=[ include=[
g.upc.with_renderer(UpcFieldRenderer).label("UPC"), g.upc.with_renderer(UpcFieldRenderer).label("UPC"),
g.brand,
g.description, g.description,
]) ],
readonly=True)
g.readonly = True
grid = g.render(class_='clickable products') grid = g.render(class_='clickable products')
return grids.render_grid(request, grid, search) return grids.render_grid(request, grid, search)