Remove all views etc. for old-style batches
This commit is contained in:
parent
9e5b43ca66
commit
2d29174772
|
@ -55,14 +55,6 @@
|
||||||
<li>${h.link_to("Vendors", url('vendors'))}</li>
|
<li>${h.link_to("Vendors", url('vendors'))}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
% if request.has_perm('batches.list'):
|
|
||||||
<li>
|
|
||||||
<a>Batches</a>
|
|
||||||
<ul>
|
|
||||||
<li>${h.link_to("Batches", url('batches'))}</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
% endif
|
|
||||||
<li>
|
<li>
|
||||||
<a>Stores</a>
|
<a>Stores</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/crud.mako" />
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
|
||||||
<li>${h.link_to("Back to Batches", url('batches'))}</li>
|
|
||||||
<li>${h.link_to("View Batch Rows", url('batch.rows', uuid=form.fieldset.model.uuid))}</li>
|
|
||||||
% if not form.readonly:
|
|
||||||
<li>${h.link_to("View this Batch", url('batch.read', uuid=form.fieldset.model.uuid))}</li>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
|
|
@ -1,6 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/grid.mako" />
|
|
||||||
|
|
||||||
<%def name="title()">Batches</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
|
|
@ -1,44 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/base.mako" />
|
|
||||||
|
|
||||||
<%def name="title()">Batch Parameters</%def>
|
|
||||||
|
|
||||||
<%def name="head_tags()">
|
|
||||||
${parent.head_tags()}
|
|
||||||
<script language="javascript" type="text/javascript">
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#create-batch').click(function() {
|
|
||||||
disable_button(this, "Creating batch");
|
|
||||||
disable_button('#cancel');
|
|
||||||
$('form').submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="batch_params()"></%def>
|
|
||||||
|
|
||||||
<p>Please provide the following values for your new batch:</p>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<div class="form">
|
|
||||||
|
|
||||||
${h.form(request.get_referrer())}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.hidden('provider', value=provider)}
|
|
||||||
${h.hidden('params', value='True')}
|
|
||||||
|
|
||||||
${self.batch_params()}
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
<button type="button" id="create-batch">Create Batch</button>
|
|
||||||
<button type="button" id="cancel" onclick="location.href = '${request.get_referrer()}';">Cancel</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${h.end_form()}
|
|
||||||
|
|
||||||
</div>
|
|
|
@ -1,20 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/batches/params.mako" />
|
|
||||||
|
|
||||||
<%def name="batch_params()">
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label for="profile">Label Type</label>
|
|
||||||
<div class="field">
|
|
||||||
${h.select('profile', None, label_profiles)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label for="quantity">Quantity</label>
|
|
||||||
<div class="field">${h.text('quantity', value=1)}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
|
|
@ -1,41 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/batches/crud.mako" />
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
|
||||||
${parent.context_menu_items()}
|
|
||||||
<li>${h.link_to("Edit this Batch", url('batch.update', uuid=form.fieldset.model.uuid))}</li>
|
|
||||||
<li>${h.link_to("Delete this Batch", url('batch.delete', uuid=form.fieldset.model.uuid))}</li>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
|
||||||
|
|
||||||
<% batch = form.fieldset.model %>
|
|
||||||
|
|
||||||
<h2>Columns</h2>
|
|
||||||
|
|
||||||
<div class="grid full hoverable">
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>SIL Name</th>
|
|
||||||
<th>Display Name</th>
|
|
||||||
<th>Description</th>
|
|
||||||
<th>Data Type</th>
|
|
||||||
<th>Visible</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
% for i, column in enumerate(batch.columns, 1):
|
|
||||||
<tr class="${'odd' if i % 2 else 'even'}">
|
|
||||||
<td>${column.name}</td>
|
|
||||||
<td>${column.sil_name}</td>
|
|
||||||
<td>${column.display_name}</td>
|
|
||||||
<td>${column.description}</td>
|
|
||||||
<td>${column.data_type}</td>
|
|
||||||
<td>${column.visible}</td>
|
|
||||||
</tr>
|
|
||||||
% endfor
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
|
@ -1,9 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/crud.mako" />
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
|
||||||
<li>${h.link_to("Back to Batch", url('batch.read', uuid=form.fieldset.model.batch.uuid))}</li>
|
|
||||||
<li>${h.link_to("Back to Batch Rows", url('batch.rows', uuid=form.fieldset.model.batch.uuid))}</li>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
|
|
@ -1,47 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/grid.mako" />
|
|
||||||
|
|
||||||
<%def name="title()">Batch Rows : ${batch.description}</%def>
|
|
||||||
|
|
||||||
<%def name="head_tags()">
|
|
||||||
${parent.head_tags()}
|
|
||||||
<script language="javascript" type="text/javascript">
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#delete-results').click(function() {
|
|
||||||
var msg = "This will delete all rows matching the current search.\n\n"
|
|
||||||
+ "PLEASE NOTE that this may include some rows which are not visible "
|
|
||||||
+ "on your screen.\n(I.e., if there is more than one \"page\" of results.)\n\n"
|
|
||||||
+ "Are you sure you wish to delete these rows?";
|
|
||||||
if (confirm(msg)) {
|
|
||||||
disable_button(this, "Deleting rows");
|
|
||||||
location.href = '${url('batch.rows.delete', uuid=batch.uuid)}';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#execute-batch').click(function() {
|
|
||||||
if (confirm("Are you sure you wish to execute this batch?")) {
|
|
||||||
disable_button(this, "Executing batch");
|
|
||||||
location.href = '${url('batch.execute', uuid=batch.uuid)}';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
|
||||||
<li>${h.link_to("Back to Batches", url('batches'))}</li>
|
|
||||||
<li>${h.link_to("Back to Batch", url('batch.read', uuid=batch.uuid))}</li>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="tools()">
|
|
||||||
<div class="buttons">
|
|
||||||
<button type="button" id="delete-results">Delete Results</button>
|
|
||||||
<button type="button" id="execute-batch">Execute Batch</button>
|
|
||||||
</div>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
% if legacy_mode is Undefined:
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
|
@ -29,18 +28,15 @@
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if legacy_mode is Undefined:
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.params-wrapper {
|
.params-wrapper {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<ul id="context-menu">
|
<ul id="context-menu">
|
||||||
|
@ -51,22 +47,6 @@
|
||||||
${h.form(request.current_route_url())}
|
${h.form(request.current_route_url())}
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
|
|
||||||
% if legacy_mode is not Undefined:
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label for="provider">Batch Type</label>
|
|
||||||
<div class="field">
|
|
||||||
${h.select('provider', None, providers)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
${h.submit('create', "Create Batch")}
|
|
||||||
${h.link_to("Cancel", url('products'), class_='button')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% else: ## new-style batches
|
|
||||||
|
|
||||||
${self.wtfield(form, 'batch_type')}
|
${self.wtfield(form, 'batch_type')}
|
||||||
|
|
||||||
% for key, pform in params_forms.items():
|
% for key, pform in params_forms.items():
|
||||||
|
@ -82,7 +62,5 @@
|
||||||
${h.link_to("Cancel", url('products'), class_='button')}
|
${h.link_to("Cancel", url('products'), class_='button')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
% endif
|
|
||||||
|
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -75,5 +75,4 @@ def includeme(config):
|
||||||
config.include('tailbone.views.vendors')
|
config.include('tailbone.views.vendors')
|
||||||
|
|
||||||
# batch views
|
# batch views
|
||||||
config.include('tailbone.views.batches')
|
|
||||||
config.include('tailbone.views.batch.pricing')
|
config.include('tailbone.views.batch.pricing')
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
#!/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/>.
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
"""
|
|
||||||
Batch Views
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .params import *
|
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
|
||||||
config.include('tailbone.views.batches.core')
|
|
||||||
config.include('tailbone.views.batches.params')
|
|
||||||
config.include('tailbone.views.batches.rows')
|
|
|
@ -1,202 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
################################################################################
|
|
||||||
#
|
|
||||||
# Rattail -- Retail Software Framework
|
|
||||||
# Copyright © 2010-2016 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/>.
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
"""
|
|
||||||
Core Batch Views
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
from pyramid.httpexceptions import HTTPFound
|
|
||||||
from pyramid.renderers import render_to_response
|
|
||||||
|
|
||||||
from webhelpers.html import tags
|
|
||||||
|
|
||||||
from tailbone import forms
|
|
||||||
from ...grids.search import BooleanSearchFilter
|
|
||||||
from .. import SearchableAlchemyGridView, CrudView, View
|
|
||||||
from ...progress import SessionProgress
|
|
||||||
|
|
||||||
from rattail import enum
|
|
||||||
from rattail import batches
|
|
||||||
from rattail.db.util import configure_session
|
|
||||||
from ...db import Session
|
|
||||||
from rattail.db.model import Batch
|
|
||||||
from rattail.threads import Thread
|
|
||||||
|
|
||||||
|
|
||||||
class BatchesGrid(SearchableAlchemyGridView):
|
|
||||||
|
|
||||||
mapped_class = Batch
|
|
||||||
config_prefix = 'batches'
|
|
||||||
sort = 'id'
|
|
||||||
|
|
||||||
def filter_map(self):
|
|
||||||
|
|
||||||
def executed_is(q, v):
|
|
||||||
if v == 'True':
|
|
||||||
return q.filter(Batch.executed != None)
|
|
||||||
else:
|
|
||||||
return q.filter(Batch.executed == None)
|
|
||||||
|
|
||||||
def executed_isnot(q, v):
|
|
||||||
if v == 'True':
|
|
||||||
return q.filter(Batch.executed == None)
|
|
||||||
else:
|
|
||||||
return q.filter(Batch.executed != None)
|
|
||||||
|
|
||||||
return self.make_filter_map(
|
|
||||||
exact=['id'],
|
|
||||||
ilike=['source', 'destination', 'description'],
|
|
||||||
executed={
|
|
||||||
'is': executed_is,
|
|
||||||
'nt': executed_isnot,
|
|
||||||
})
|
|
||||||
|
|
||||||
def filter_config(self):
|
|
||||||
return self.make_filter_config(
|
|
||||||
filter_label_id="ID",
|
|
||||||
filter_factory_executed=BooleanSearchFilter,
|
|
||||||
include_filter_executed=True,
|
|
||||||
filter_type_executed='is',
|
|
||||||
executed='False')
|
|
||||||
|
|
||||||
def sort_map(self):
|
|
||||||
return self.make_sort_map('source', 'id', 'destination', 'description', 'executed')
|
|
||||||
|
|
||||||
def grid(self):
|
|
||||||
g = self.make_grid()
|
|
||||||
g.configure(
|
|
||||||
include=[
|
|
||||||
g.source,
|
|
||||||
g.id.label("ID"),
|
|
||||||
g.destination,
|
|
||||||
g.description,
|
|
||||||
g.executed,
|
|
||||||
g.rowcount.label("Row Count"),
|
|
||||||
],
|
|
||||||
readonly=True)
|
|
||||||
if self.request.has_perm('batches.read'):
|
|
||||||
def rows(row):
|
|
||||||
return tags.link_to("View Rows", self.request.route_url(
|
|
||||||
'batch.rows', uuid=row.uuid))
|
|
||||||
g.add_column('rows', "", rows)
|
|
||||||
g.viewable = True
|
|
||||||
g.view_route_name = 'batch.read'
|
|
||||||
if self.request.has_perm('batches.update'):
|
|
||||||
g.editable = True
|
|
||||||
g.edit_route_name = 'batch.update'
|
|
||||||
if self.request.has_perm('batches.delete'):
|
|
||||||
g.deletable = True
|
|
||||||
g.delete_route_name = 'batch.delete'
|
|
||||||
return g
|
|
||||||
|
|
||||||
|
|
||||||
class BatchCrud(CrudView):
|
|
||||||
|
|
||||||
mapped_class = Batch
|
|
||||||
home_route = 'batches'
|
|
||||||
|
|
||||||
def fieldset(self, model):
|
|
||||||
fs = self.make_fieldset(model)
|
|
||||||
fs.action_type.set(renderer=forms.renderers.EnumFieldRenderer(enum.BATCH_ACTION))
|
|
||||||
fs.configure(
|
|
||||||
include=[
|
|
||||||
fs.source,
|
|
||||||
fs.id.label("ID"),
|
|
||||||
fs.destination,
|
|
||||||
fs.action_type,
|
|
||||||
fs.description,
|
|
||||||
fs.rowcount.label("Row Count").readonly(),
|
|
||||||
fs.executed.readonly(),
|
|
||||||
])
|
|
||||||
return fs
|
|
||||||
|
|
||||||
def post_delete(self, batch):
|
|
||||||
batch.drop_table()
|
|
||||||
|
|
||||||
|
|
||||||
class ExecuteBatch(View):
|
|
||||||
|
|
||||||
def execute_batch(self, batch, progress):
|
|
||||||
from rattail.db import Session
|
|
||||||
session = Session()
|
|
||||||
configure_session(self.request.rattail_config, session)
|
|
||||||
batch = session.merge(batch)
|
|
||||||
|
|
||||||
if not batch.execute(self.request.rattail_config, progress):
|
|
||||||
session.rollback()
|
|
||||||
session.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
session.commit()
|
|
||||||
session.refresh(batch)
|
|
||||||
session.close()
|
|
||||||
|
|
||||||
progress.session.load()
|
|
||||||
progress.session['complete'] = True
|
|
||||||
progress.session['success_msg'] = "Batch \"%s\" has been executed." % batch.description
|
|
||||||
progress.session['success_url'] = self.request.route_url('batches')
|
|
||||||
progress.session.save()
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
uuid = self.request.matchdict['uuid']
|
|
||||||
batch = Session.query(Batch).get(uuid) if uuid else None
|
|
||||||
if not batch:
|
|
||||||
return HTTPFound(location=self.request.route_url('batches'))
|
|
||||||
|
|
||||||
progress = SessionProgress(self.request, 'batch.execute')
|
|
||||||
thread = Thread(target=self.execute_batch, args=(batch, progress))
|
|
||||||
thread.start()
|
|
||||||
kwargs = {
|
|
||||||
'key': 'batch.execute',
|
|
||||||
'cancel_url': self.request.route_url('batch.rows', uuid=batch.uuid),
|
|
||||||
'cancel_msg': "Batch execution was canceled.",
|
|
||||||
}
|
|
||||||
return self.render_progress(kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
|
||||||
|
|
||||||
config.add_route('batches', '/batches')
|
|
||||||
config.add_view(BatchesGrid, route_name='batches',
|
|
||||||
renderer='/batches/index.mako',
|
|
||||||
permission='batches.list')
|
|
||||||
|
|
||||||
config.add_route('batch.read', '/batches/{uuid}')
|
|
||||||
config.add_view(BatchCrud, attr='read',
|
|
||||||
route_name='batch.read',
|
|
||||||
renderer='/batches/read.mako',
|
|
||||||
permission='batches.read')
|
|
||||||
|
|
||||||
config.add_route('batch.update', '/batches/{uuid}/edit')
|
|
||||||
config.add_view(BatchCrud, attr='update', route_name='batch.update',
|
|
||||||
renderer='/batches/crud.mako',
|
|
||||||
permission='batches.update')
|
|
||||||
|
|
||||||
config.add_route('batch.delete', '/batches/{uuid}/delete')
|
|
||||||
config.add_view(BatchCrud, attr='delete', route_name='batch.delete',
|
|
||||||
permission='batches.delete')
|
|
||||||
|
|
||||||
config.add_route('batch.execute', '/batches/{uuid}/execute')
|
|
||||||
config.add_view(ExecuteBatch, route_name='batch.execute',
|
|
||||||
permission='batches.execute')
|
|
|
@ -1,52 +0,0 @@
|
||||||
#!/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/>.
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
"""
|
|
||||||
Batch Parameter Views
|
|
||||||
"""
|
|
||||||
|
|
||||||
from ... import View
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['BatchParamsView']
|
|
||||||
|
|
||||||
|
|
||||||
class BatchParamsView(View):
|
|
||||||
|
|
||||||
provider_name = None
|
|
||||||
|
|
||||||
def render_kwargs(self):
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
if self.request.POST:
|
|
||||||
if self.set_batch_params():
|
|
||||||
return HTTPFound(location=self.request.get_referer())
|
|
||||||
kwargs = self.render_kwargs()
|
|
||||||
kwargs['provider'] = self.provider_name
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
|
||||||
config.include('tailbone.views.batches.params.labels')
|
|
|
@ -1,52 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
################################################################################
|
|
||||||
#
|
|
||||||
# Rattail -- Retail Software Framework
|
|
||||||
# Copyright © 2010-2014 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/>.
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
"""
|
|
||||||
Print Labels Batch
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from rattail.db import model
|
|
||||||
|
|
||||||
from tailbone.db import Session
|
|
||||||
from tailbone.views.batches.params import BatchParamsView
|
|
||||||
|
|
||||||
|
|
||||||
class PrintLabels(BatchParamsView):
|
|
||||||
|
|
||||||
provider_name = 'print_labels'
|
|
||||||
|
|
||||||
def render_kwargs(self):
|
|
||||||
q = Session.query(model.LabelProfile)
|
|
||||||
q = q.order_by(model.LabelProfile.ordinal)
|
|
||||||
profiles = [(x.code, x.description) for x in q]
|
|
||||||
return {'label_profiles': profiles}
|
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
|
||||||
|
|
||||||
config.add_route('batch_params.print_labels', '/batches/params/print-labels')
|
|
||||||
config.add_view(PrintLabels, route_name='batch_params.print_labels',
|
|
||||||
renderer='/batches/params/print_labels.mako',
|
|
||||||
permission='batches.print_labels')
|
|
|
@ -1,252 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
################################################################################
|
|
||||||
#
|
|
||||||
# Rattail -- Retail Software Framework
|
|
||||||
# Copyright © 2010-2016 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/>.
|
|
||||||
#
|
|
||||||
################################################################################
|
|
||||||
"""
|
|
||||||
Batch Row Views
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
from pyramid.httpexceptions import HTTPFound
|
|
||||||
|
|
||||||
from tailbone.views import SearchableAlchemyGridView, CrudView
|
|
||||||
from tailbone.forms import GPCFieldRenderer
|
|
||||||
from tailbone.grids.search import BooleanSearchFilter
|
|
||||||
from tailbone.db import Session
|
|
||||||
|
|
||||||
from rattail.db import model
|
|
||||||
from rattail.db.model import Batch, LabelProfile
|
|
||||||
from rattail.gpc import GPC
|
|
||||||
|
|
||||||
|
|
||||||
def field_with_renderer(field, column):
|
|
||||||
|
|
||||||
if column.sil_name == 'F01': # UPC
|
|
||||||
field = field.with_renderer(GPCFieldRenderer)
|
|
||||||
|
|
||||||
elif column.sil_name == 'F95': # Shelf Tag Type
|
|
||||||
q = Session.query(LabelProfile)
|
|
||||||
q = q.order_by(LabelProfile.ordinal)
|
|
||||||
field = field.dropdown(options=[(x.description, x.code) for x in q])
|
|
||||||
|
|
||||||
return field
|
|
||||||
|
|
||||||
|
|
||||||
def BatchRowsGrid(request):
|
|
||||||
uuid = request.matchdict['uuid']
|
|
||||||
batch = Session.query(Batch).get(uuid) if uuid else None
|
|
||||||
if not batch:
|
|
||||||
raise HTTPFound(location=request.route_url('batches'))
|
|
||||||
|
|
||||||
class BatchRowsGrid(SearchableAlchemyGridView):
|
|
||||||
|
|
||||||
mapped_class = batch.rowclass
|
|
||||||
config_prefix = 'batch.%s' % batch.uuid
|
|
||||||
sort = 'ordinal'
|
|
||||||
|
|
||||||
def filter_map(self):
|
|
||||||
|
|
||||||
# TODO: This code is copied from `tailbone.views.products`, which
|
|
||||||
# means we probably should refactor...
|
|
||||||
|
|
||||||
def filter_F01_is(q, v):
|
|
||||||
if not v:
|
|
||||||
return q
|
|
||||||
try:
|
|
||||||
return q.filter(model.Product.upc.in_((
|
|
||||||
GPC(v), GPC(v, calc_check_digit='upc'))))
|
|
||||||
except ValueError:
|
|
||||||
return q
|
|
||||||
|
|
||||||
def filter_F01_not(q, v):
|
|
||||||
if not v:
|
|
||||||
return q
|
|
||||||
try:
|
|
||||||
return q.filter(~model.Product.upc.in_((
|
|
||||||
GPC(v), GPC(v, calc_check_digit='upc'))))
|
|
||||||
except ValueError:
|
|
||||||
return q
|
|
||||||
|
|
||||||
fmap = self.make_filter_map()
|
|
||||||
for column in batch.columns:
|
|
||||||
if column.sil_name == 'F01':
|
|
||||||
fmap[column.name] = {'is': filter_F01_is,
|
|
||||||
'nt': filter_F01_not}
|
|
||||||
elif column.visible:
|
|
||||||
if column.data_type.startswith('CHAR'):
|
|
||||||
fmap[column.name] = self.filter_ilike(
|
|
||||||
getattr(batch.rowclass, column.name))
|
|
||||||
else:
|
|
||||||
fmap[column.name] = self.filter_exact(
|
|
||||||
getattr(batch.rowclass, column.name))
|
|
||||||
return fmap
|
|
||||||
|
|
||||||
def filter_config(self):
|
|
||||||
config = self.make_filter_config()
|
|
||||||
for column in batch.columns:
|
|
||||||
if column.visible:
|
|
||||||
config['filter_label_%s' % column.name] = column.display_name
|
|
||||||
if column.data_type == 'FLAG(1)':
|
|
||||||
config['filter_factory_{0}'.format(column.name)] = BooleanSearchFilter
|
|
||||||
return config
|
|
||||||
|
|
||||||
def grid(self):
|
|
||||||
g = self.make_grid()
|
|
||||||
|
|
||||||
include = [g.ordinal.label("Row")]
|
|
||||||
for column in batch.columns:
|
|
||||||
if column.visible:
|
|
||||||
field = getattr(g, column.name)
|
|
||||||
field = field_with_renderer(field, column)
|
|
||||||
field = field.label(column.display_name)
|
|
||||||
include.append(field)
|
|
||||||
g.column_titles[field.key] = '%s - %s - %s' % (
|
|
||||||
column.sil_name, column.description, column.data_type)
|
|
||||||
|
|
||||||
g.configure(include=include, readonly=True)
|
|
||||||
|
|
||||||
route_kwargs = lambda x: {'batch_uuid': x.batch.uuid, 'uuid': x.uuid}
|
|
||||||
|
|
||||||
if self.request.has_perm('batch_rows.read'):
|
|
||||||
g.viewable = True
|
|
||||||
g.view_route_name = 'batch_row.read'
|
|
||||||
g.view_route_kwargs = route_kwargs
|
|
||||||
|
|
||||||
if self.request.has_perm('batch_rows.update'):
|
|
||||||
g.editable = True
|
|
||||||
g.edit_route_name = 'batch_row.update'
|
|
||||||
g.edit_route_kwargs = route_kwargs
|
|
||||||
|
|
||||||
if self.request.has_perm('batch_rows.delete'):
|
|
||||||
g.deletable = True
|
|
||||||
g.delete_route_name = 'batch_row.delete'
|
|
||||||
g.delete_route_kwargs = route_kwargs
|
|
||||||
|
|
||||||
return g
|
|
||||||
|
|
||||||
def render_kwargs(self):
|
|
||||||
return {'batch': batch}
|
|
||||||
|
|
||||||
grid = BatchRowsGrid(request)
|
|
||||||
grid.batch = batch
|
|
||||||
return grid
|
|
||||||
|
|
||||||
|
|
||||||
def batch_rows_grid(request):
|
|
||||||
result = BatchRowsGrid(request)
|
|
||||||
if isinstance(result, HTTPFound):
|
|
||||||
return result
|
|
||||||
return result()
|
|
||||||
|
|
||||||
|
|
||||||
def batch_rows_delete(request):
|
|
||||||
grid = BatchRowsGrid(request)
|
|
||||||
grid._filter_config = grid.filter_config()
|
|
||||||
rows = grid.make_query()
|
|
||||||
count = rows.count()
|
|
||||||
rows.delete(synchronize_session=False)
|
|
||||||
grid.batch.rowcount -= count
|
|
||||||
request.session.flash("Deleted %d rows from batch." % count)
|
|
||||||
return HTTPFound(location=request.route_url('batch.rows', uuid=grid.batch.uuid))
|
|
||||||
|
|
||||||
|
|
||||||
def batch_row_crud(request, attr):
|
|
||||||
batch_uuid = request.matchdict['batch_uuid']
|
|
||||||
batch = Session.query(Batch).get(batch_uuid)
|
|
||||||
if not batch:
|
|
||||||
return HTTPFound(location=request.route_url('batches'))
|
|
||||||
|
|
||||||
row_uuid = request.matchdict['uuid']
|
|
||||||
row = Session.query(batch.rowclass).get(row_uuid)
|
|
||||||
if not row:
|
|
||||||
return HTTPFound(location=request.route_url('batch.read', uuid=batch.uuid))
|
|
||||||
|
|
||||||
class BatchRowCrud(CrudView):
|
|
||||||
|
|
||||||
mapped_class = batch.rowclass
|
|
||||||
pretty_name = "Batch Row"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def home_url(self):
|
|
||||||
return self.request.route_url('batch.rows', uuid=batch.uuid)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def cancel_url(self):
|
|
||||||
return self.home_url
|
|
||||||
|
|
||||||
def fieldset(self, model):
|
|
||||||
fs = self.make_fieldset(model)
|
|
||||||
|
|
||||||
include = [fs.ordinal.label("Row Number").readonly()]
|
|
||||||
for column in batch.columns:
|
|
||||||
field = getattr(fs, column.name)
|
|
||||||
field = field_with_renderer(field, column)
|
|
||||||
field = field.label(column.display_name)
|
|
||||||
include.append(field)
|
|
||||||
|
|
||||||
fs.configure(include=include)
|
|
||||||
return fs
|
|
||||||
|
|
||||||
def flash_delete(self, row):
|
|
||||||
self.request.session.flash("Batch Row %d has been deleted."
|
|
||||||
% row.ordinal)
|
|
||||||
|
|
||||||
def post_delete(self, model):
|
|
||||||
batch.rowcount -= 1
|
|
||||||
|
|
||||||
crud = BatchRowCrud(request)
|
|
||||||
return getattr(crud, attr)()
|
|
||||||
|
|
||||||
def batch_row_read(request):
|
|
||||||
return batch_row_crud(request, 'read')
|
|
||||||
|
|
||||||
def batch_row_update(request):
|
|
||||||
return batch_row_crud(request, 'update')
|
|
||||||
|
|
||||||
def batch_row_delete(request):
|
|
||||||
return batch_row_crud(request, 'delete')
|
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
|
||||||
|
|
||||||
config.add_route('batch.rows', '/batches/{uuid}/rows')
|
|
||||||
config.add_view(batch_rows_grid, route_name='batch.rows',
|
|
||||||
renderer='/batches/rows/index.mako',
|
|
||||||
permission='batches.read')
|
|
||||||
|
|
||||||
config.add_route('batch.rows.delete', '/batches/{uuid}/rows/delete')
|
|
||||||
config.add_view(batch_rows_delete, route_name='batch.rows.delete',
|
|
||||||
permission='batch_rows.delete')
|
|
||||||
|
|
||||||
config.add_route('batch_row.read', '/batches/{batch_uuid}/{uuid}')
|
|
||||||
config.add_view(batch_row_read, route_name='batch_row.read',
|
|
||||||
renderer='/batches/rows/crud.mako',
|
|
||||||
permission='batch_rows.read')
|
|
||||||
|
|
||||||
config.add_route('batch_row.update', '/batches/{batch_uuid}/{uuid}/edit')
|
|
||||||
config.add_view(batch_row_update, route_name='batch_row.update',
|
|
||||||
renderer='/batches/rows/crud.mako',
|
|
||||||
permission='batch_rows.update')
|
|
||||||
|
|
||||||
config.add_route('batch_row.delete', '/batches/{batch_uuid}/{uuid}/delete')
|
|
||||||
config.add_view(batch_row_delete, route_name='batch_row.delete',
|
|
||||||
permission='batch_rows.delete')
|
|
|
@ -26,14 +26,13 @@ Product Views
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import six
|
import six
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
|
||||||
from rattail import enum, pod, sil, batches
|
from rattail import enum, pod, sil
|
||||||
from rattail.db import model, api, auth, Session as RattailSession
|
from rattail.db import model, api, auth, Session as RattailSession
|
||||||
from rattail.gpc import GPC
|
from rattail.gpc import GPC
|
||||||
from rattail.threads import Thread
|
from rattail.threads import Thread
|
||||||
|
@ -425,14 +424,6 @@ class ProductsView(MasterView):
|
||||||
"""
|
"""
|
||||||
View for making a new batch from current product grid query.
|
View for making a new batch from current product grid query.
|
||||||
"""
|
"""
|
||||||
# maybe do legacy mode
|
|
||||||
enabled = self.rattail_config.getlist('rattail.pyramid', 'batches.providers')
|
|
||||||
if enabled:
|
|
||||||
supported = batches.get_providers()
|
|
||||||
providers = dict([(key, supported[key]) for key in enabled if key in supported])
|
|
||||||
return self.make_batch_legacy(providers)
|
|
||||||
|
|
||||||
# okay then, new-style it is
|
|
||||||
supported = self.get_supported_batches()
|
supported = self.get_supported_batches()
|
||||||
batch_options = []
|
batch_options = []
|
||||||
for key, spec in list(supported.items()):
|
for key, spec in list(supported.items()):
|
||||||
|
@ -512,65 +503,13 @@ class ProductsView(MasterView):
|
||||||
if batch.batch_key == 'pricing':
|
if batch.batch_key == 'pricing':
|
||||||
return self.request.route_url('batch.pricing.view', uuid=batch.uuid)
|
return self.request.route_url('batch.pricing.view', uuid=batch.uuid)
|
||||||
|
|
||||||
def make_batch_legacy(self, providers):
|
|
||||||
if self.request.method == 'POST':
|
|
||||||
provider_key = self.request.POST.get('provider')
|
|
||||||
if provider_key:
|
|
||||||
provider_factory = providers.get(provider_key)
|
|
||||||
if provider_factory:
|
|
||||||
provider = provider_factory(self.rattail_config)
|
|
||||||
|
|
||||||
if self.request.POST.get('params') == 'True':
|
|
||||||
provider.set_params(Session(), **self.request.POST)
|
|
||||||
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
url = self.request.route_url('batch_params.{}'.format(provider.name))
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.request.session['referer'] = self.request.current_route_url()
|
|
||||||
return httpexceptions.HTTPFound(location=url)
|
|
||||||
|
|
||||||
progress = SessionProgress(self.request, 'products.batch')
|
|
||||||
thread = Thread(target=self.make_batch_thread_legacy, args=(provider, progress))
|
|
||||||
thread.start()
|
|
||||||
kwargs = {
|
|
||||||
'key': 'products.batch',
|
|
||||||
'cancel_url': self.request.route_url('products'),
|
|
||||||
'cancel_msg': "Batch creation was canceled.",
|
|
||||||
}
|
|
||||||
return self.render_progress(kwargs)
|
|
||||||
|
|
||||||
providers = [(p.name, p.description)
|
|
||||||
for p in sorted(providers.itervalues(),
|
|
||||||
key=lambda p: p.description)]
|
|
||||||
return {'legacy_mode': True, 'providers': providers}
|
|
||||||
|
|
||||||
def make_batch_thread_legacy(self, provider, progress):
|
|
||||||
"""
|
|
||||||
Threat target for making a batch from current products query.
|
|
||||||
"""
|
|
||||||
session = RattailSession()
|
|
||||||
products = self.get_effective_query(session)
|
|
||||||
batch = provider.make_batch(session, products, progress)
|
|
||||||
if not batch:
|
|
||||||
session.rollback()
|
|
||||||
session.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
session.commit()
|
|
||||||
session.refresh(batch)
|
|
||||||
session.close()
|
|
||||||
|
|
||||||
progress.session.load()
|
|
||||||
progress.session['complete'] = True
|
|
||||||
progress.session['success_url'] = self.request.route_url('batch.read', uuid=batch.uuid)
|
|
||||||
progress.session['success_msg'] = 'Batch "{}" has been created.'.format(batch.description)
|
|
||||||
progress.session.save()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def defaults(cls, config):
|
def defaults(cls, config):
|
||||||
|
route_prefix = cls.get_route_prefix()
|
||||||
|
url_prefix = cls.get_url_prefix()
|
||||||
|
template_prefix = cls.get_template_prefix()
|
||||||
|
permission_prefix = cls.get_permission_prefix()
|
||||||
|
model_title = cls.get_model_title()
|
||||||
|
|
||||||
# print labels
|
# print labels
|
||||||
config.add_tailbone_permission('products', 'products.print_labels',
|
config.add_tailbone_permission('products', 'products.print_labels',
|
||||||
|
@ -581,9 +520,12 @@ class ProductsView(MasterView):
|
||||||
"View products marked as deleted")
|
"View products marked as deleted")
|
||||||
|
|
||||||
# make batch from product query
|
# make batch from product query
|
||||||
config.add_route('products.create_batch', '/products/make-batch')
|
config.add_tailbone_permission(permission_prefix, '{}.make_batch'.format(permission_prefix),
|
||||||
config.add_view(cls, attr='make_batch', route_name='products.create_batch',
|
"Create batch from {} query".format(model_title))
|
||||||
renderer='/products/batch.mako', permission='batches.create')
|
config.add_route('{}.make_batch'.format(route_prefix), '{}/make-batch'.format(url_prefix))
|
||||||
|
config.add_view(cls, attr='make_batch', route_name='{}.make_batch'.format(route_prefix),
|
||||||
|
renderer='{}/batch.mako'.format(template_prefix),
|
||||||
|
permission='{}.make_batch'.format(permission_prefix))
|
||||||
|
|
||||||
# search (by upc)
|
# search (by upc)
|
||||||
config.add_route('products.search', '/products/search')
|
config.add_route('products.search', '/products/search')
|
||||||
|
|
Loading…
Reference in a new issue