From 136d1813635cb382f903153fc10a4d8e8ec1aba2 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 13 Mar 2020 13:15:27 -0500 Subject: [PATCH] Add basic "ordering worksheet" API display-only for the moment, pending review/feedback --- tailbone/api/batch/ordering.py | 123 +++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/tailbone/api/batch/ordering.py b/tailbone/api/batch/ordering.py index 1b611381..031bccdf 100644 --- a/tailbone/api/batch/ordering.py +++ b/tailbone/api/batch/ordering.py @@ -31,9 +31,12 @@ from __future__ import unicode_literals, absolute_import import six +from rattail.core import Object from rattail.db import model from rattail.util import pretty_quantity +from cornice import Service + from tailbone.api.batch import APIBatchView, APIBatchRowView @@ -84,6 +87,126 @@ class OrderingBatchViews(APIBatchView): batch = super(OrderingBatchViews, self).create_object(data) return batch + def worksheet(self): + """ + Returns primary data for the Ordering Worksheet view. + """ + batch = self.get_object() + if batch.executed: + raise self.forbidden() + + # TODO: much of the logic below was copied from the traditional master + # view for ordering batches. should maybe let them share it somehow? + + # organize existing batch rows by product + order_items = {} + for row in batch.active_rows(): + order_items[row.product_uuid] = row + + # organize vendor catalog costs by dept / subdept + departments = {} + costs = self.handler.get_order_form_costs(self.Session(), batch.vendor) + costs = self.handler.sort_order_form_costs(costs) + costs = list(costs) # we must have a stable list for the rest of this + self.handler.decorate_order_form_costs(batch, costs) + for cost in costs: + + department = cost.product.department + if department: + department_dict = departments.setdefault(department.uuid, { + 'uuid': department.uuid, + 'number': department.number, + 'name': department.name, + }) + else: + if None not in departments: + departments[None] = { + 'uuid': None, + 'number': None, + 'name': "", + } + department_dict = departments[None] + + subdepartments = department_dict.setdefault('subdepartments', {}) + + subdepartment = cost.product.subdepartment + if subdepartment: + subdepartment_dict = subdepartments.setdefault(subdepartment.uuid, { + 'uuid': subdepartment.uuid, + 'number': subdepartment.number, + 'name': subdepartment.name, + }) + else: + if None not in subdepartments: + subdepartments[None] = { + 'uuid': None, + 'number': None, + 'name': "", + } + subdepartment_dict = subdepartments[None] + + subdept_costs = subdepartment_dict.setdefault('costs', []) + product = cost.product + subdept_costs.append({ + 'uuid': cost.uuid, + 'upc': six.text_type(product.upc), + 'upc_pretty': product.upc.pretty() if product.upc else None, + 'brand_name': product.brand.name if product.brand else None, + 'description': product.description, + 'size': product.size, + 'case_size': cost.case_size, + 'uom_display': "LB" if product.weighed else "EA", + 'vendor_item_code': cost.code, + 'preference': cost.preference, + 'preferred': cost.preference == 1, + 'unit_cost': cost.unit_cost, + 'unit_cost_display': "${:0.2f}".format(cost.unit_cost) if cost.unit_cost is not None else "", + # TODO + # 'cases_ordered': None, + # 'units_ordered': None, + # 'po_total': None, + # 'po_total_display': None, + }) + + # sort the (sub)department groupings + sorted_departments = [] + for dept in sorted(six.itervalues(departments), key=lambda d: d['name']): + dept['subdepartments'] = sorted(six.itervalues(dept['subdepartments']), + key=lambda s: s['name']) + sorted_departments.append(dept) + + # fetch recent purchase history, sort/pad for template convenience + history = self.handler.get_order_form_history(batch, costs, 6) + for i in range(6 - len(history)): + history.append(None) + history = list(reversed(history)) + + return { + 'batch': self.normalize(batch), + 'departments': departments, + 'sorted_departments': sorted_departments, + 'history': history, + } + + @classmethod + def defaults(cls, config): + cls._defaults(config) + cls._batch_defaults(config) + cls._ordering_batch_defaults(config) + + @classmethod + def _ordering_batch_defaults(cls, config): + route_prefix = cls.get_route_prefix() + permission_prefix = cls.get_permission_prefix() + object_url_prefix = cls.get_object_url_prefix() + + # worksheet + worksheet = Service(name='{}.worksheet'.format(route_prefix), + path='{}/{{uuid}}/worksheet'.format(object_url_prefix)) + worksheet.add_view('GET', 'worksheet', klass=cls, + permission='{}.worksheet'.format(permission_prefix)) + config.add_cornice_service(worksheet) + class OrderingBatchRowViews(APIBatchRowView):