Add "most of" support for truck dump receiving
still not complete, but conceptually it sort of is...
This commit is contained in:
parent
805a1afa3f
commit
cd7922f204
|
@ -42,6 +42,7 @@ import deform
|
|||
from colanderalchemy import SQLAlchemySchemaNode
|
||||
from colanderalchemy.schema import _creation_order
|
||||
from deform import widget as dfwidget
|
||||
from pyramid_deform import SessionFileUploadTempStore
|
||||
from pyramid.renderers import render
|
||||
from webhelpers2.html import tags, HTML
|
||||
|
||||
|
@ -585,6 +586,11 @@ class Form(object):
|
|||
self.set_widget(key, dfwidget.TextAreaWidget(cols=80, rows=8))
|
||||
elif type_ == 'text':
|
||||
self.set_widget(key, dfwidget.TextAreaWidget(cols=80, rows=8))
|
||||
elif type_ == 'file':
|
||||
tmpstore = SessionFileUploadTempStore(self.request)
|
||||
self.set_node(key, colander.SchemaNode(deform.FileData(),
|
||||
widget=dfwidget.FileUploadWidget(tmpstore),
|
||||
title=self.get_label(key)))
|
||||
else:
|
||||
raise ValueError("unknown type for '{}' field: {}".format(key, type_))
|
||||
|
||||
|
|
|
@ -61,7 +61,13 @@
|
|||
|
||||
<%def name="execute_button()">
|
||||
% if not batch.executed and request.has_perm('{}.execute'.format(permission_prefix)):
|
||||
<button type="button" id="execute-batch"${'' if execute_enabled else ' disabled="disabled"'}>${execute_title}</button>
|
||||
% if execute_enabled:
|
||||
<button type="button" id="execute-batch">${execute_title}</button>
|
||||
% elif why_not_execute:
|
||||
<button type="button" id="execute-batch" disabled="disabled" title="${why_not_execute}">${execute_title}</button>
|
||||
% else:
|
||||
<button type="button" id="execute-batch" disabled="disabled">${execute_title}</button>
|
||||
% endif
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
|
|
67
tailbone/templates/receiving/create.mako
Normal file
67
tailbone/templates/receiving/create.mako
Normal file
|
@ -0,0 +1,67 @@
|
|||
## -*- coding: utf-8; -*-
|
||||
<%inherit file="/batch/create.mako" />
|
||||
|
||||
<%def name="extra_javascript()">
|
||||
${parent.extra_javascript()}
|
||||
${self.func_show_batch_type()}
|
||||
<script type="text/javascript">
|
||||
|
||||
% if master.allow_truck_dump:
|
||||
var batch_vendor_map = ${json.dumps(batch_vendor_map)|n};
|
||||
% endif
|
||||
|
||||
$(function() {
|
||||
|
||||
$('.batch_type select').on('selectmenuchange', function(event, ui) {
|
||||
show_batch_type(ui.item.value);
|
||||
});
|
||||
|
||||
$('.truck_dump_batch_uuid select').on('selectmenuchange', function(event, ui) {
|
||||
var form = $(this).parents('form');
|
||||
var uuid = ui.item.value ? batch_vendor_map[ui.item.value] : '';
|
||||
form.find('input[name="vendor_uuid"]').val(uuid);
|
||||
});
|
||||
|
||||
show_batch_type();
|
||||
});
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
<%def name="func_show_batch_type()">
|
||||
<script type="text/javascript">
|
||||
|
||||
function show_batch_type(batch_type) {
|
||||
|
||||
if (batch_type === undefined) {
|
||||
batch_type = $('.field-wrapper.batch_type select').val();
|
||||
}
|
||||
|
||||
if (batch_type == 'from_scratch') {
|
||||
$('.field-wrapper.truck_dump_batch_uuid').hide();
|
||||
$('.field-wrapper.invoice_file').hide();
|
||||
$('.field-wrapper.invoice_parser_key').hide();
|
||||
$('.field-wrapper.vendor_uuid').show();
|
||||
$('.field-wrapper.date_ordered').show();
|
||||
$('.field-wrapper.date_received').show();
|
||||
$('.field-wrapper.po_number').show();
|
||||
$('.field-wrapper.invoice_date').show();
|
||||
$('.field-wrapper.invoice_number').show();
|
||||
|
||||
} else if (batch_type == 'truck_dump') {
|
||||
$('.field-wrapper.truck_dump_batch_uuid').show();
|
||||
$('.field-wrapper.invoice_file').show();
|
||||
$('.field-wrapper.invoice_parser_key').show();
|
||||
$('.field-wrapper.vendor_uuid').hide();
|
||||
$('.field-wrapper.date_ordered').hide();
|
||||
$('.field-wrapper.date_received').hide();
|
||||
$('.field-wrapper.po_number').hide();
|
||||
$('.field-wrapper.invoice_date').hide();
|
||||
$('.field-wrapper.invoice_number').hide();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
|
@ -42,11 +42,9 @@ from rattail.util import load_object, prettify
|
|||
|
||||
import colander
|
||||
import deform
|
||||
from deform import widget as dfwidget
|
||||
from pyramid import httpexceptions
|
||||
from pyramid.renderers import render_to_response
|
||||
from pyramid.response import FileResponse
|
||||
from pyramid_deform import SessionFileUploadTempStore
|
||||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from tailbone import forms, grids
|
||||
|
@ -131,6 +129,9 @@ class BatchMasterView(MasterView):
|
|||
return load_object(spec)(self.rattail_config)
|
||||
return self.batch_handler_class(self.rattail_config)
|
||||
|
||||
def download_path(self, batch, filename):
|
||||
return self.rattail_config.batch_filepath(batch.batch_key, batch.uuid, filename)
|
||||
|
||||
def template_kwargs_view(self, **kwargs):
|
||||
batch = kwargs['instance']
|
||||
kwargs['batch'] = batch
|
||||
|
@ -140,6 +141,8 @@ class BatchMasterView(MasterView):
|
|||
if kwargs['execute_enabled']:
|
||||
url = self.get_action_url('execute', batch)
|
||||
kwargs['execute_form'] = self.make_execute_form(batch, action_url=url)
|
||||
else:
|
||||
kwargs['why_not_execute'] = self.handler.why_not_execute(batch)
|
||||
return kwargs
|
||||
|
||||
def allow_worksheet(self, batch):
|
||||
|
@ -278,9 +281,6 @@ class BatchMasterView(MasterView):
|
|||
return status_code_text
|
||||
return render_status
|
||||
|
||||
def download_path(self, batch, filename):
|
||||
return self.rattail_config.batch_filepath(batch.batch_key, batch.uuid, filename)
|
||||
|
||||
def render_user(self, batch, field):
|
||||
user = getattr(batch, field)
|
||||
if not user:
|
||||
|
@ -312,6 +312,7 @@ class BatchMasterView(MasterView):
|
|||
f.remove_field('complete')
|
||||
|
||||
def save_create_form(self, form):
|
||||
uploads = self.normalize_uploads(form, skip=['filename'])
|
||||
self.before_create(form)
|
||||
|
||||
session = self.Session()
|
||||
|
@ -346,17 +347,15 @@ class BatchMasterView(MasterView):
|
|||
batch = self.handler.make_batch(session, **kwargs)
|
||||
|
||||
self.Session.flush()
|
||||
|
||||
# TODO: this needs work yet surely...
|
||||
# if batch has input data file, let handler properly establish that
|
||||
if 'filename' in form.schema:
|
||||
if filedict:
|
||||
self.handler.set_input_file(batch, filepath)
|
||||
os.remove(filepath)
|
||||
os.rmdir(tempdir)
|
||||
|
||||
self.process_uploads(batch, form, uploads)
|
||||
return batch
|
||||
|
||||
def process_uploads(self, batch, form, uploads):
|
||||
for key, upload in six.iteritems(uploads):
|
||||
self.handler.set_input_file(batch, upload['temp_path'], attr=key)
|
||||
os.remove(upload['temp_path'])
|
||||
os.rmdir(upload['tempdir'])
|
||||
|
||||
def save_mobile_create_form(self, form):
|
||||
self.before_create(form)
|
||||
session = self.Session()
|
||||
|
@ -536,6 +535,39 @@ class BatchMasterView(MasterView):
|
|||
url = self.request.route_url('{}.delete_rows'.format(self.get_route_prefix()), uuid=batch.uuid)
|
||||
return HTML.tag('p', c=[tags.link_to("Delete all rows matching current search", url)])
|
||||
|
||||
def make_row_grid_kwargs(self, **kwargs):
|
||||
"""
|
||||
Whether or not rows may be edited or deleted will depend partially on
|
||||
whether the parent batch has been executed.
|
||||
"""
|
||||
batch = self.get_instance()
|
||||
|
||||
# TODO: most of this logic is copied from MasterView, should refactor/merge somehow...
|
||||
if 'main_actions' not in kwargs:
|
||||
actions = []
|
||||
|
||||
# view action
|
||||
if self.rows_viewable:
|
||||
view = lambda r, i: self.get_row_action_url('view', r)
|
||||
actions.append(grids.GridAction('view', icon='zoomin', url=view))
|
||||
|
||||
# edit and delete are NOT allowed after execution, or if batch is "complete"
|
||||
if not batch.executed and not batch.complete:
|
||||
|
||||
# edit action
|
||||
if self.rows_editable:
|
||||
actions.append(grids.GridAction('edit', icon='pencil', url=self.row_edit_action_url))
|
||||
|
||||
# delete action
|
||||
permission_prefix = self.get_permission_prefix()
|
||||
if self.rows_deletable and self.request.has_perm('{}.delete_row'.format(permission_prefix)):
|
||||
actions.append(grids.GridAction('delete', icon='trash', url=self.row_delete_action_url))
|
||||
kwargs.setdefault('delete_speedbump', self.rows_deletable_speedbump)
|
||||
|
||||
kwargs['main_actions'] = actions
|
||||
|
||||
return super(BatchMasterView, self).make_row_grid_kwargs(**kwargs)
|
||||
|
||||
def make_row_grid_tools(self, batch):
|
||||
return (self.make_default_row_grid_tools(batch) or '') + (self.make_batch_row_grid_tools(batch) or '')
|
||||
|
||||
|
@ -555,10 +587,7 @@ class BatchMasterView(MasterView):
|
|||
"""
|
||||
Delete all data (files etc.) for the batch.
|
||||
"""
|
||||
if hasattr(batch, 'delete_data'):
|
||||
batch.delete_data(self.rattail_config)
|
||||
if hasattr(batch, 'data_rows'):
|
||||
del batch.data_rows[:]
|
||||
self.handler.delete(batch)
|
||||
super(BatchMasterView, self).delete_instance(batch)
|
||||
|
||||
def get_fallback_templates(self, template, mobile=False):
|
||||
|
@ -1153,6 +1182,7 @@ class FileBatchMasterView(BatchMasterView):
|
|||
"""
|
||||
Base class for all file-based "batch master" views.
|
||||
"""
|
||||
downloadable = True
|
||||
|
||||
@property
|
||||
def upload_dir(self):
|
||||
|
@ -1171,62 +1201,26 @@ class FileBatchMasterView(BatchMasterView):
|
|||
|
||||
def configure_form(self, f):
|
||||
super(FileBatchMasterView, self).configure_form(f)
|
||||
batch = f.model_instance
|
||||
|
||||
# filename
|
||||
f.set_renderer('filename', self.render_filename)
|
||||
f.set_label('filename', "Data File")
|
||||
if self.editing:
|
||||
f.set_readonly('filename')
|
||||
|
||||
if self.creating:
|
||||
if 'filename' not in f.fields:
|
||||
f.fields.insert(0, 'filename')
|
||||
tmpstore = SessionFileUploadTempStore(self.request)
|
||||
f.set_node('filename', colander.SchemaNode(deform.FileData(), widget=dfwidget.FileUploadWidget(tmpstore)))
|
||||
# TODO: what's up with this re-insertion again..?
|
||||
# if 'filename' not in f.fields:
|
||||
# f.fields.insert(0, 'filename')
|
||||
f.set_type('filename', 'file')
|
||||
else:
|
||||
f.set_readonly('filename')
|
||||
f.set_renderer('filename', self.render_filename)
|
||||
|
||||
def render_filename(self, batch, field):
|
||||
path = batch.filepath(self.rattail_config, filename=batch.filename)
|
||||
filename = getattr(batch, field)
|
||||
if not filename:
|
||||
return ""
|
||||
path = batch.filepath(self.rattail_config, filename=filename)
|
||||
url = self.get_action_url('download', batch)
|
||||
return self.render_file_field(path, url)
|
||||
|
||||
def download(self):
|
||||
"""
|
||||
View for downloading the data file associated with a batch.
|
||||
"""
|
||||
batch = self.get_instance()
|
||||
if not batch:
|
||||
raise httpexceptions.HTTPNotFound()
|
||||
path = batch.filepath(self.rattail_config)
|
||||
response = FileResponse(path, request=self.request)
|
||||
response.headers[b'Content-Length'] = six.binary_type(os.path.getsize(path))
|
||||
filename = os.path.basename(batch.filename).encode('ascii', 'replace')
|
||||
response.headers[b'Content-Disposition'] = b'attachment; filename="{}"'.format(filename)
|
||||
return response
|
||||
|
||||
@classmethod
|
||||
def defaults(cls, config):
|
||||
cls._filebatch_defaults(config)
|
||||
cls._batch_defaults(config)
|
||||
cls._defaults(config)
|
||||
|
||||
@classmethod
|
||||
def _filebatch_defaults(cls, config):
|
||||
route_prefix = cls.get_route_prefix()
|
||||
url_prefix = cls.get_url_prefix()
|
||||
permission_prefix = cls.get_permission_prefix()
|
||||
model_title = cls.get_model_title()
|
||||
model_title_plural = cls.get_model_title_plural()
|
||||
|
||||
# fix permission group title
|
||||
config.add_tailbone_permission_group(permission_prefix, model_title_plural)
|
||||
|
||||
# download batch data file
|
||||
config.add_route('{}.download'.format(route_prefix), '{}/{{uuid}}/download'.format(url_prefix))
|
||||
config.add_view(cls, attr='download', route_name='{}.download'.format(route_prefix),
|
||||
permission='{}.download'.format(permission_prefix))
|
||||
config.add_tailbone_permission(permission_prefix, '{}.download'.format(permission_prefix),
|
||||
"Download existing {} data file".format(model_title))
|
||||
|
||||
|
||||
class MobileBatchStatusFilter(grids.filters.MobileFilter):
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ Model Master View
|
|||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import logging
|
||||
|
||||
import six
|
||||
|
@ -633,14 +634,39 @@ class MasterView(View):
|
|||
return self.render_to_response('create', {'form': form}, mobile=True)
|
||||
|
||||
def save_create_form(self, form):
|
||||
uploads = self.normalize_uploads(form)
|
||||
self.before_create(form)
|
||||
with self.Session().no_autoflush:
|
||||
obj = self.objectify(form, self.form_deserialized)
|
||||
self.before_create_flush(obj, form)
|
||||
self.Session.add(obj)
|
||||
self.Session.flush()
|
||||
self.process_uploads(obj, form, uploads)
|
||||
return obj
|
||||
|
||||
def normalize_uploads(self, form, skip=None):
|
||||
uploads = {}
|
||||
for node in form.schema:
|
||||
if isinstance(node.typ, deform.FileData):
|
||||
if skip and node.name in skip:
|
||||
continue
|
||||
filedict = self.form_deserialized.get(node.name)
|
||||
if filedict:
|
||||
tempdir = tempfile.mkdtemp()
|
||||
filepath = os.path.join(tempdir, filedict['filename'])
|
||||
tmpinfo = form.deform_form[node.name].widget.tmpstore.get(filedict['uid'])
|
||||
tmpdata = tmpinfo['fp'].read()
|
||||
with open(filepath, 'wb') as f:
|
||||
f.write(tmpdata)
|
||||
uploads[node.name] = {
|
||||
'tempdir': tempdir,
|
||||
'temp_path': filepath,
|
||||
}
|
||||
return uploads
|
||||
|
||||
def process_uploads(self, obj, form, uploads):
|
||||
pass
|
||||
|
||||
def before_create_flush(self, obj, form):
|
||||
pass
|
||||
|
||||
|
@ -1230,6 +1256,8 @@ class MasterView(View):
|
|||
"""
|
||||
obj = self.get_instance()
|
||||
filename = self.request.GET.get('filename', None)
|
||||
if not filename:
|
||||
raise self.notfound()
|
||||
path = self.download_path(obj, filename)
|
||||
response = FileResponse(path, request=self.request)
|
||||
response.content_length = os.path.getsize(path)
|
||||
|
@ -2124,6 +2152,14 @@ class MasterView(View):
|
|||
"""
|
||||
return getattr(cls, 'mobile_row_form_factory', forms.Form)
|
||||
|
||||
def render_downloadable_file(self, obj, field):
|
||||
filename = getattr(obj, field)
|
||||
if not filename:
|
||||
return ""
|
||||
path = self.download_path(obj, filename)
|
||||
url = self.get_action_url('download', obj, _query={'filename': filename})
|
||||
return self.render_file_field(path, url)
|
||||
|
||||
def render_file_field(self, path, url=None, filename=None):
|
||||
"""
|
||||
Convenience for rendering a file with optional download link
|
||||
|
|
|
@ -26,6 +26,8 @@ Views for "true" purchase credits
|
|||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import six
|
||||
|
||||
from rattail.db import model
|
||||
|
||||
from webhelpers2.html import tags
|
||||
|
@ -70,12 +72,13 @@ class PurchaseCreditView(MasterView):
|
|||
|
||||
g.set_sort_defaults('date_received', 'desc')
|
||||
|
||||
g.set_enum('status', self.enum.PURCHASE_CREDIT_STATUS)
|
||||
g.filters['status'].set_value_renderer(grids.filters.EnumValueRenderer(self.enum.PURCHASE_CREDIT_STATUS))
|
||||
g.filters['status'].default_active = True
|
||||
g.filters['status'].default_verb = 'not_equal'
|
||||
g.filters['status'].default_value = self.enum.PURCHASE_CREDIT_STATUS_SATISFIED
|
||||
# TODO: should not have to convert value to string!
|
||||
g.filters['status'].default_value = six.text_type(self.enum.PURCHASE_CREDIT_STATUS_SATISFIED)
|
||||
|
||||
g.set_enum('status', self.enum.PURCHASE_CREDIT_STATUS)
|
||||
# g.set_type('upc', 'gpc')
|
||||
g.set_type('cases_shorted', 'quantity')
|
||||
g.set_type('units_shorted', 'quantity')
|
||||
|
|
|
@ -48,6 +48,7 @@ class PurchasingBatchView(BatchMasterView):
|
|||
model_row_class = model.PurchaseBatchRow
|
||||
default_handler_spec = 'rattail.batch.purchase:PurchaseBatchHandler'
|
||||
supports_new_product = False
|
||||
cloneable = True
|
||||
|
||||
grid_columns = [
|
||||
'id',
|
||||
|
@ -513,22 +514,33 @@ class PurchasingBatchView(BatchMasterView):
|
|||
kwargs = super(PurchasingBatchView, self).get_batch_kwargs(batch, mobile=mobile)
|
||||
kwargs['mode'] = self.batch_mode
|
||||
kwargs['truck_dump'] = batch.truck_dump
|
||||
kwargs['invoice_parser_key'] = batch.invoice_parser_key
|
||||
|
||||
if batch.store:
|
||||
kwargs['store'] = batch.store
|
||||
elif batch.store_uuid:
|
||||
kwargs['store_uuid'] = batch.store_uuid
|
||||
|
||||
if batch.truck_dump_batch:
|
||||
kwargs['truck_dump_batch'] = batch.truck_dump_batch
|
||||
elif batch.truck_dump_batch_uuid:
|
||||
kwargs['truck_dump_batch_uuid'] = batch.truck_dump_batch_uuid
|
||||
|
||||
if batch.vendor:
|
||||
kwargs['vendor'] = batch.vendor
|
||||
elif batch.vendor_uuid:
|
||||
kwargs['vendor_uuid'] = batch.vendor_uuid
|
||||
|
||||
if batch.department:
|
||||
kwargs['department'] = batch.department
|
||||
elif batch.department_uuid:
|
||||
kwargs['department_uuid'] = batch.department_uuid
|
||||
|
||||
if batch.buyer:
|
||||
kwargs['buyer'] = batch.buyer
|
||||
elif batch.buyer_uuid:
|
||||
kwargs['buyer_uuid'] = batch.buyer_uuid
|
||||
|
||||
kwargs['po_number'] = batch.po_number
|
||||
kwargs['po_total'] = batch.po_total
|
||||
|
||||
|
@ -600,7 +612,9 @@ class PurchasingBatchView(BatchMasterView):
|
|||
def row_grid_extra_class(self, row, i):
|
||||
if row.status_code == row.STATUS_PRODUCT_NOT_FOUND:
|
||||
return 'warning'
|
||||
if row.status_code in (row.STATUS_INCOMPLETE, row.STATUS_ORDERED_RECEIVED_DIFFER):
|
||||
if row.status_code in (row.STATUS_INCOMPLETE,
|
||||
row.STATUS_ORDERED_RECEIVED_DIFFER,
|
||||
row.STATUS_TRUCKDUMP_UNCLAIMED):
|
||||
return 'notice'
|
||||
|
||||
def configure_row_form(self, f):
|
||||
|
|
|
@ -28,17 +28,19 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
import re
|
||||
|
||||
import six
|
||||
import sqlalchemy as sa
|
||||
|
||||
from rattail import pod
|
||||
from rattail.db import model, api
|
||||
from rattail.gpc import GPC
|
||||
from rattail.util import pretty_quantity, prettify
|
||||
from rattail.vendors.invoices import iter_invoice_parsers, require_invoice_parser
|
||||
|
||||
import colander
|
||||
from deform import widget as dfwidget
|
||||
from pyramid import httpexceptions
|
||||
from webhelpers2.html import tags
|
||||
from webhelpers2.html import tags, HTML
|
||||
|
||||
from tailbone import forms, grids
|
||||
from tailbone.views.purchasing import PurchasingBatchView
|
||||
|
@ -96,9 +98,8 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
model_title = "Receiving Batch"
|
||||
model_title_plural = "Receiving Batches"
|
||||
index_title = "Receiving"
|
||||
creatable = False
|
||||
downloadable = True
|
||||
rows_editable = True
|
||||
rows_deletable = False
|
||||
mobile_creatable = True
|
||||
mobile_rows_filterable = True
|
||||
mobile_rows_creatable = True
|
||||
|
@ -107,6 +108,11 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
allow_from_scratch = True
|
||||
allow_truck_dump = False
|
||||
|
||||
labels = {
|
||||
'truck_dump_batch': "Truck Dump Parent",
|
||||
'invoice_parser_key': "Invoice Parser",
|
||||
}
|
||||
|
||||
grid_columns = [
|
||||
'id',
|
||||
'vendor',
|
||||
|
@ -123,9 +129,14 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
|
||||
form_fields = [
|
||||
'id',
|
||||
'batch_type',
|
||||
'store',
|
||||
'vendor',
|
||||
'truck_dump',
|
||||
'truck_dump_children',
|
||||
'truck_dump_batch',
|
||||
'invoice_file',
|
||||
'invoice_parser_key',
|
||||
'department',
|
||||
'purchase',
|
||||
'vendor_email',
|
||||
|
@ -143,6 +154,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
'created',
|
||||
'created_by',
|
||||
'status_code',
|
||||
'rowcount',
|
||||
'complete',
|
||||
'executed',
|
||||
'executed_by',
|
||||
|
@ -203,12 +215,166 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
def batch_mode(self):
|
||||
return self.enum.PURCHASE_BATCH_MODE_RECEIVING
|
||||
|
||||
def row_editable(self, row):
|
||||
batch = row.batch
|
||||
if batch.truck_dump_batch:
|
||||
return False
|
||||
return True
|
||||
|
||||
def row_deletable(self, row):
|
||||
batch = row.batch
|
||||
if batch.truck_dump:
|
||||
return True
|
||||
return False
|
||||
|
||||
def configure_form(self, f):
|
||||
super(ReceivingBatchView, self).configure_form(f)
|
||||
batch = f.model_instance
|
||||
|
||||
# truck_dump
|
||||
if self.editing:
|
||||
f.set_readonly('truck_dump')
|
||||
# batch_type
|
||||
if self.creating:
|
||||
batch_type_values = [
|
||||
('from_scratch', "New from Scratch"),
|
||||
]
|
||||
if self.allow_truck_dump:
|
||||
batch_type_values.append(('truck_dump', "Invoice for Truck Dump"))
|
||||
f.set_widget('batch_type', forms.widgets.JQuerySelectWidget(values=batch_type_values))
|
||||
else:
|
||||
f.remove_field('batch_type')
|
||||
|
||||
# truck_dump*
|
||||
if self.allow_truck_dump:
|
||||
|
||||
# truck_dump
|
||||
if self.creating:
|
||||
f.remove_field('truck_dump')
|
||||
elif batch.truck_dump_batch:
|
||||
f.remove_field('truck_dump')
|
||||
else:
|
||||
f.set_readonly('truck_dump')
|
||||
|
||||
# truck_dump_children
|
||||
if self.viewing:
|
||||
if batch.truck_dump:
|
||||
f.set_renderer('truck_dump_children', self.render_truck_dump_children)
|
||||
else:
|
||||
f.remove_field('truck_dump_children')
|
||||
else:
|
||||
f.remove_field('truck_dump_children')
|
||||
|
||||
# truck_dump_batch
|
||||
if self.creating:
|
||||
f.replace('truck_dump_batch', 'truck_dump_batch_uuid')
|
||||
batches = self.Session.query(model.PurchaseBatch)\
|
||||
.filter(model.PurchaseBatch.mode == self.enum.PURCHASE_BATCH_MODE_RECEIVING)\
|
||||
.filter(model.PurchaseBatch.truck_dump == True)\
|
||||
.filter(model.PurchaseBatch.complete == True)\
|
||||
.filter(model.PurchaseBatch.executed == None)\
|
||||
.order_by(model.PurchaseBatch.id)
|
||||
batch_values = [(b.uuid, six.text_type(b)) for b in batches]
|
||||
batch_values.insert(0, ('', "(please choose)"))
|
||||
f.set_widget('truck_dump_batch_uuid', forms.widgets.JQuerySelectWidget(values=batch_values))
|
||||
f.set_label('truck_dump_batch_uuid', "Truck Dump Parent")
|
||||
elif batch.truck_dump:
|
||||
f.remove_field('truck_dump_batch')
|
||||
elif batch.truck_dump_batch:
|
||||
f.set_readonly('truck_dump_batch')
|
||||
f.set_renderer('truck_dump_batch', self.render_truck_dump_batch)
|
||||
else:
|
||||
f.remove_field('truck_dump_batch')
|
||||
|
||||
else:
|
||||
f.remove_fields('truck_dump',
|
||||
'truck_dump_children',
|
||||
'truck_dump_batch')
|
||||
|
||||
# invoice_file
|
||||
if self.creating:
|
||||
f.set_type('invoice_file', 'file')
|
||||
else:
|
||||
f.set_readonly('invoice_file')
|
||||
f.set_renderer('invoice_file', self.render_downloadable_file)
|
||||
|
||||
# invoice_parser_key
|
||||
if self.creating:
|
||||
parsers = sorted(iter_invoice_parsers(), key=lambda p: p.display)
|
||||
parser_values = [(p.key, p.display) for p in parsers]
|
||||
parser_values.insert(0, ('', "(please choose)"))
|
||||
f.set_widget('invoice_parser_key', forms.widgets.JQuerySelectWidget(values=parser_values))
|
||||
else:
|
||||
f.remove_field('invoice_parser_key')
|
||||
|
||||
# store
|
||||
if self.creating:
|
||||
store = self.rattail_config.get_store(self.Session())
|
||||
f.set_widget('store_uuid', forms.widgets.ReadonlyWidget())
|
||||
f.set_default('store_uuid', store.uuid)
|
||||
f.set_hidden('store_uuid')
|
||||
|
||||
# purchase
|
||||
if self.creating:
|
||||
f.remove_field('purchase')
|
||||
|
||||
# department
|
||||
if self.creating:
|
||||
f.remove_field('department_uuid')
|
||||
|
||||
def template_kwargs_create(self, **kwargs):
|
||||
kwargs = super(ReceivingBatchView, self).template_kwargs_create(**kwargs)
|
||||
if self.allow_truck_dump:
|
||||
vmap = {}
|
||||
batches = self.Session.query(model.PurchaseBatch)\
|
||||
.filter(model.PurchaseBatch.mode == self.enum.PURCHASE_BATCH_MODE_RECEIVING)\
|
||||
.filter(model.PurchaseBatch.truck_dump == True)\
|
||||
.filter(model.PurchaseBatch.complete == True)
|
||||
for batch in batches:
|
||||
vmap[batch.uuid] = batch.vendor_uuid
|
||||
kwargs['batch_vendor_map'] = vmap
|
||||
return kwargs
|
||||
|
||||
def get_batch_kwargs(self, batch, mobile=False):
|
||||
kwargs = super(ReceivingBatchView, self).get_batch_kwargs(batch, mobile=mobile)
|
||||
if not mobile:
|
||||
batch_type = self.request.POST['batch_type']
|
||||
if batch_type == 'from_scratch':
|
||||
kwargs.pop('truck_dump_batch', None)
|
||||
kwargs.pop('truck_dump_batch_uuid', None)
|
||||
elif batch_type == 'truck_dump':
|
||||
pass
|
||||
else:
|
||||
raise NotImplementedError
|
||||
return kwargs
|
||||
|
||||
def delete_instance(self, batch):
|
||||
"""
|
||||
Delete all data (files etc.) for the batch.
|
||||
"""
|
||||
truck_dump = batch.truck_dump_batch
|
||||
if batch.truck_dump:
|
||||
for child in batch.truck_dump_children:
|
||||
self.delete_instance(child)
|
||||
super(ReceivingBatchView, self).delete_instance(batch)
|
||||
if truck_dump:
|
||||
self.handler.refresh(truck_dump)
|
||||
|
||||
def render_truck_dump_batch(self, batch, field):
|
||||
truck_dump = batch.truck_dump_batch
|
||||
if not truck_dump:
|
||||
return ""
|
||||
text = six.text_type(truck_dump)
|
||||
url = self.request.route_url('receiving.view', uuid=truck_dump.uuid)
|
||||
return tags.link_to(text, url)
|
||||
|
||||
def render_truck_dump_children(self, batch, field):
|
||||
children = batch.truck_dump_children
|
||||
if not children:
|
||||
return ""
|
||||
items = []
|
||||
for child in children:
|
||||
text = six.text_type(child)
|
||||
url = self.request.route_url('receiving.view', uuid=child.uuid)
|
||||
items.append(HTML.tag('li', c=[tags.link_to(text, url)]))
|
||||
return HTML.tag('ul', c=items)
|
||||
|
||||
def render_mobile_listitem(self, batch, i):
|
||||
title = "({}) {} for ${:0,.2f} - {}, {}".format(
|
||||
|
|
Loading…
Reference in a new issue