From 8399eb8f91778a7618b11cd038a555737ad6596d Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 21 Nov 2016 03:37:45 -0600 Subject: [PATCH] Add initial support for 'costing' mode for purchase batches --- .../templates/purchases/batches/create.mako | 14 +++++++- tailbone/views/purchases/batch.py | 25 ++++++++++--- tailbone/views/purchases/core.py | 35 ++++++++++++++----- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/tailbone/templates/purchases/batches/create.mako b/tailbone/templates/purchases/batches/create.mako index 11c1a320..1a9ca0c4 100644 --- a/tailbone/templates/purchases/batches/create.mako +++ b/tailbone/templates/purchases/batches/create.mako @@ -12,18 +12,30 @@ $('.field-wrapper.buyer_uuid').show(); $('.field-wrapper.date_ordered').show(); $('.field-wrapper.date_received').hide(); + $('.field-wrapper.invoice_date').hide(); + $('.field-wrapper.invoice_number').hide(); } else if (mode == ${enum.PURCHASE_BATCH_MODE_RECEIVING}) { $('.field-wrapper.store_uuid').hide(); $('.field-wrapper.purchase_uuid').show(); $('.field-wrapper.buyer_uuid').hide(); $('.field-wrapper.date_ordered').hide(); $('.field-wrapper.date_received').show(); + $('.field-wrapper.invoice_date').show(); + $('.field-wrapper.invoice_number').show(); + } else if (mode == ${enum.PURCHASE_BATCH_MODE_COSTING}) { + $('.field-wrapper.store_uuid').hide(); + $('.field-wrapper.purchase_uuid').show(); + $('.field-wrapper.buyer_uuid').hide(); + $('.field-wrapper.date_ordered').hide(); + $('.field-wrapper.date_received').hide(); + $('.field-wrapper.invoice_date').show(); + $('.field-wrapper.invoice_number').show(); } } function vendor_selected(uuid, name) { var mode = $('.mode select').val(); - if (mode == ${enum.PURCHASE_BATCH_MODE_RECEIVING}) { + if (mode == ${enum.PURCHASE_BATCH_MODE_RECEIVING} || mode == ${enum.PURCHASE_BATCH_MODE_COSTING}) { var purchases = $('.purchase_uuid select'); purchases.empty(); diff --git a/tailbone/views/purchases/batch.py b/tailbone/views/purchases/batch.py index 51fe9847..ea0cf1b2 100644 --- a/tailbone/views/purchases/batch.py +++ b/tailbone/views/purchases/batch.py @@ -143,6 +143,8 @@ class PurchaseBatchView(BatchMasterView): fs.date_received, fs.po_number, fs.po_total, + fs.invoice_date, + fs.invoice_number, fs.invoice_total, fs.created, fs.created_by, @@ -179,9 +181,8 @@ class PurchaseBatchView(BatchMasterView): fs.model.date_ordered = today fs.model.date_received = today - # TODO: temp hack until we support more modes + # TODO: restrict via permission per batch mode? modes = dict(self.enum.PURCHASE_BATCH_MODE) - del modes[self.enum.PURCHASE_BATCH_MODE_COSTING] fs.mode.set(renderer=forms.renderers.EnumFieldRenderer(modes)) elif self.editing: @@ -206,12 +207,21 @@ class PurchaseBatchView(BatchMasterView): if mode == enum.PURCHASE_BATCH_MODE_RECEIVING: purchases = purchases.filter(model.Purchase.status == self.enum.PURCHASE_STATUS_ORDERED)\ .order_by(model.Purchase.date_ordered, model.Purchase.created) + elif mode == enum.PURCHASE_BATCH_MODE_COSTING: + purchases = purchases.filter(model.Purchase.status == self.enum.PURCHASE_STATUS_RECEIVED)\ + .order_by(model.Purchase.date_received, model.Purchase.created) return {'purchases': [{'uuid': p.uuid, 'display': self.render_eligible_purchase(p)} for p in purchases]} def render_eligible_purchase(self, purchase): - return '{} for ${:0,.2f} ({})'.format(purchase.date_ordered, purchase.po_total, purchase.buyer) + if purchase.status == self.enum.PURCHASE_STATUS_ORDERED: + date = purchase.date_ordered + total = purchase.po_total + elif purchase.status == self.enum.PURCHASE_STATUS_RECEIVED: + date = purchase.date_received + total = purchase.invoice_total + return '{} for ${:0,.2f} ({})'.format(date, total, purchase.buyer) def get_batch_kwargs(self, batch): kwargs = super(PurchaseBatchView, self).get_batch_kwargs(batch) @@ -235,6 +245,12 @@ class PurchaseBatchView(BatchMasterView): elif batch.mode == self.enum.PURCHASE_BATCH_MODE_RECEIVING: kwargs['date_received'] = batch.date_received + + elif batch.mode == self.enum.PURCHASE_BATCH_MODE_COSTING: + kwargs['invoice_date'] = batch.invoice_date + + if batch.mode in (self.enum.PURCHASE_BATCH_MODE_RECEIVING, + self.enum.PURCHASE_BATCH_MODE_COSTING): if batch.purchase_uuid: purchase = Session.query(model.Purchase).get(batch.purchase_uuid) assert purchase @@ -293,7 +309,8 @@ class PurchaseBatchView(BatchMasterView): del g.cases_received del g.units_received del g.invoice_total - elif batch.mode == self.enum.PURCHASE_BATCH_MODE_RECEIVING: + elif batch.mode in (self.enum.PURCHASE_BATCH_MODE_RECEIVING, + self.enum.PURCHASE_BATCH_MODE_COSTING): del g.po_total def make_row_grid_tools(self, batch): diff --git a/tailbone/views/purchases/core.py b/tailbone/views/purchases/core.py index 6acaff77..b1c62f51 100644 --- a/tailbone/views/purchases/core.py +++ b/tailbone/views/purchases/core.py @@ -26,7 +26,6 @@ Views for "true" purchase orders from __future__ import unicode_literals, absolute_import -from rattail import enum from rattail.db import model import formalchemy as fa @@ -44,12 +43,20 @@ class BatchesFieldRenderer(fa.FieldRenderer): if not batches: return '' + enum = self.request.rattail_config.get_enum() + def render(batch): - display = '{} ({}){}'.format(batch.id_str, enum.PURCHASE_BATCH_MODE[batch.mode], - '' if batch.executed else ' (pending)') + if batch.executed: + actor = batch.executed_by + pending = '' + else: + actor = batch.created_by + pending = ' (pending)' + display = '{} ({} by {}){}'.format(batch.id_str, + enum.PURCHASE_BATCH_MODE[batch.mode], + actor, pending) return tags.link_to(display, self.request.route_url('purchases.batch.view', uuid=batch.uuid)) - enum = self.request.rattail_config.get_enum() items = [HTML.tag('li', c=render(batch)) for batch in batches] return HTML.tag('ul', c=items) @@ -67,7 +74,13 @@ class PurchaseView(MasterView): row_model_title = 'Purchase Item' def get_instance_title(self, purchase): - if purchase.status >= self.enum.PURCHASE_STATUS_RECEIVED: + if purchase.status >= self.enum.PURCHASE_STATUS_COSTED: + if purchase.invoice_date: + return "{} (invoiced {})".format(purchase.vendor, purchase.invoice_date.strftime('%Y-%m-%d')) + if purchase.date_received: + return "{} (invoiced {})".format(purchase.vendor, purchase.date_received.strftime('%Y-%m-%d')) + return "{} (invoiced)".format(purchase.vendor) + elif purchase.status >= self.enum.PURCHASE_STATUS_RECEIVED: if purchase.date_received: return "{} (received {})".format(purchase.vendor, purchase.date_received.strftime('%Y-%m-%d')) return "{} (received)".format(purchase.vendor) @@ -100,7 +113,8 @@ class PurchaseView(MasterView): g.default_sortdir = 'desc' g.date_ordered.set(label="Ordered") - g.status.set(renderer=forms.renderers.EnumFieldRenderer(enum.PURCHASE_STATUS)) + g.date_received.set(label="Received") + g.status.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.PURCHASE_STATUS)) def configure_grid(self, g): g.configure( @@ -109,13 +123,14 @@ class PurchaseView(MasterView): g.vendor, g.buyer, g.date_ordered, + g.date_received, g.status, ], readonly=True) def _preconfigure_fieldset(self, fs): fs.vendor.set(renderer=forms.renderers.VendorFieldRenderer) - fs.status.set(renderer=forms.renderers.EnumFieldRenderer(enum.PURCHASE_STATUS), + fs.status.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.PURCHASE_STATUS), readonly=True) fs.po_number.set(label="PO Number") fs.po_total.set(label="PO Total", renderer=forms.renderers.CurrencyFieldRenderer) @@ -133,6 +148,7 @@ class PurchaseView(MasterView): fs.date_received, fs.po_number, fs.po_total, + fs.invoice_date, fs.invoice_number, fs.invoice_total, fs.created, @@ -182,11 +198,12 @@ class PurchaseView(MasterView): g.invoice_total, ], readonly=True) - if purchase.status == enum.PURCHASE_STATUS_ORDERED: + if purchase.status == self.enum.PURCHASE_STATUS_ORDERED: del g.cases_received del g.units_received del g.invoice_total - elif purchase.status == enum.PURCHASE_STATUS_RECEIVED: + elif purchase.status in (self.enum.PURCHASE_STATUS_RECEIVED, + self.enum.PURCHASE_STATUS_COSTED): del g.po_total def _preconfigure_row_fieldset(self, fs):