Add support for 'department' field in purchases / batches
Also fix logic for deleting a purchase (delete its batches first)
This commit is contained in:
parent
6c3d221e98
commit
c73ba56505
|
@ -43,8 +43,8 @@ from .users import UserFieldRenderer, PermissionsFieldRenderer
|
|||
|
||||
from .employees import EmployeeFieldRenderer
|
||||
|
||||
from .products import (ProductFieldRenderer, GPCFieldRenderer, BrandFieldRenderer,
|
||||
PriceFieldRenderer, PriceWithExpirationFieldRenderer)
|
||||
from .products import (GPCFieldRenderer, DepartmentFieldRenderer, BrandFieldRenderer,
|
||||
ProductFieldRenderer, PriceFieldRenderer, PriceWithExpirationFieldRenderer)
|
||||
|
||||
from .stores import StoreFieldRenderer
|
||||
|
||||
|
|
|
@ -83,11 +83,16 @@ class DepartmentFieldRenderer(SelectFieldRenderer):
|
|||
"""
|
||||
Shows the department number as well as the name.
|
||||
"""
|
||||
|
||||
def render_readonly(self, **kwargs):
|
||||
dept = self.raw_value
|
||||
if dept:
|
||||
return "{0} - {1}".format(dept.number, dept.name)
|
||||
return ""
|
||||
department = self.raw_value
|
||||
if not department:
|
||||
return ''
|
||||
if department.number:
|
||||
text = '{} {}'.format(department.number, department.name)
|
||||
else:
|
||||
text = department.name
|
||||
return tags.link_to(text, self.request.route_url('departments.view', uuid=department.uuid))
|
||||
|
||||
|
||||
class SubdepartmentFieldRenderer(SelectFieldRenderer):
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
if (mode == ${enum.PURCHASE_BATCH_MODE_NEW}) {
|
||||
$('.field-wrapper.store_uuid').show();
|
||||
$('.field-wrapper.purchase_uuid').hide();
|
||||
$('.field-wrapper.department_uuid').show();
|
||||
$('.field-wrapper.buyer_uuid').show();
|
||||
$('.field-wrapper.date_ordered').show();
|
||||
$('.field-wrapper.date_received').hide();
|
||||
|
@ -17,6 +18,7 @@
|
|||
} else if (mode == ${enum.PURCHASE_BATCH_MODE_RECEIVING}) {
|
||||
$('.field-wrapper.store_uuid').hide();
|
||||
$('.field-wrapper.purchase_uuid').show();
|
||||
$('.field-wrapper.department_uuid').hide();
|
||||
$('.field-wrapper.buyer_uuid').hide();
|
||||
$('.field-wrapper.date_ordered').hide();
|
||||
$('.field-wrapper.date_received').show();
|
||||
|
@ -25,6 +27,7 @@
|
|||
} else if (mode == ${enum.PURCHASE_BATCH_MODE_COSTING}) {
|
||||
$('.field-wrapper.store_uuid').hide();
|
||||
$('.field-wrapper.purchase_uuid').show();
|
||||
$('.field-wrapper.department_uuid').hide();
|
||||
$('.field-wrapper.buyer_uuid').hide();
|
||||
$('.field-wrapper.date_ordered').hide();
|
||||
$('.field-wrapper.date_received').hide();
|
||||
|
@ -76,6 +79,7 @@
|
|||
});
|
||||
|
||||
$('.field-wrapper.purchase_uuid select').selectmenu();
|
||||
$('.field-wrapper.department_uuid select').selectmenu();
|
||||
|
||||
show_mode(${form.fieldset.model.mode or enum.PURCHASE_BATCH_MODE_NEW});
|
||||
|
||||
|
|
|
@ -526,7 +526,12 @@ class MasterView(View):
|
|||
Return a "humanized" (and plural) version of the model name, for
|
||||
display in templates.
|
||||
"""
|
||||
return getattr(cls, 'model_title_plural', '{0}s'.format(cls.get_model_title()))
|
||||
if hasattr(cls, 'model_title_plural'):
|
||||
return cls.model_title_plural
|
||||
try:
|
||||
return cls.get_model_class().get_model_title_plural()
|
||||
except (NotImplementedError, AttributeError):
|
||||
return '{}s'.format(cls.get_model_title())
|
||||
|
||||
@classmethod
|
||||
def get_route_prefix(cls):
|
||||
|
|
|
@ -31,7 +31,7 @@ import logging
|
|||
|
||||
from sqlalchemy import orm
|
||||
|
||||
from rattail import enum, pod
|
||||
from rattail import pod
|
||||
from rattail.db import model, api
|
||||
from rattail.gpc import GPC
|
||||
from rattail.time import localtime
|
||||
|
@ -67,7 +67,6 @@ class PurchaseBatchView(BatchMasterView):
|
|||
Master view for purchase order batches.
|
||||
"""
|
||||
model_class = model.PurchaseBatch
|
||||
model_title_plural = "Purchase Batches"
|
||||
model_row_class = model.PurchaseBatchRow
|
||||
default_handler_spec = 'rattail.batch.purchase:PurchaseBatchHandler'
|
||||
route_prefix = 'purchases.batch'
|
||||
|
@ -87,6 +86,10 @@ class PurchaseBatchView(BatchMasterView):
|
|||
default_active=True, default_verb='contains')
|
||||
g.sorters['vendor'] = g.make_sorter(model.Vendor.name)
|
||||
|
||||
g.joiners['department'] = lambda q: q.join(model.Department)
|
||||
g.filters['department'] = g.make_filter('department', model.Department.name)
|
||||
g.sorters['department'] = g.make_sorter(model.Department.name)
|
||||
|
||||
g.joiners['buyer'] = lambda q: q.join(model.Employee).join(model.Person)
|
||||
g.filters['buyer'] = g.make_filter('buyer', model.Person.display_name,
|
||||
default_active=True, default_verb='contains')
|
||||
|
@ -106,6 +109,7 @@ class PurchaseBatchView(BatchMasterView):
|
|||
g.id,
|
||||
g.mode,
|
||||
g.vendor,
|
||||
g.department,
|
||||
g.buyer,
|
||||
g.date_ordered,
|
||||
g.created,
|
||||
|
@ -121,6 +125,8 @@ class PurchaseBatchView(BatchMasterView):
|
|||
fs.vendor.set(renderer=forms.renderers.VendorFieldRenderer,
|
||||
attrs={'selected': 'vendor_selected',
|
||||
'cleared': 'vendor_cleared'})
|
||||
fs.department.set(renderer=forms.renderers.DepartmentFieldRenderer,
|
||||
options=self.get_department_options())
|
||||
fs.buyer.set(renderer=forms.renderers.EmployeeFieldRenderer)
|
||||
fs.po_number.set(label="PO Number")
|
||||
fs.po_total.set(label="PO Total", readonly=True, renderer=forms.renderers.CurrencyFieldRenderer)
|
||||
|
@ -135,6 +141,10 @@ class PurchaseBatchView(BatchMasterView):
|
|||
fs.append(fa.Field('vendor_phone', readonly=True,
|
||||
value=self.get_vendor_phone_number))
|
||||
|
||||
def get_department_options(self):
|
||||
departments = Session.query(model.Department).order_by(model.Department.number)
|
||||
return [('{} {}'.format(d.number, d.name), d.uuid) for d in departments]
|
||||
|
||||
def get_vendor_phone_number(self, batch):
|
||||
for phone in batch.vendor.phones:
|
||||
if phone.type == 'Voice':
|
||||
|
@ -152,6 +162,7 @@ class PurchaseBatchView(BatchMasterView):
|
|||
fs.mode,
|
||||
fs.store,
|
||||
fs.vendor,
|
||||
fs.department,
|
||||
fs.purchase,
|
||||
fs.vendor_email,
|
||||
fs.vendor_fax,
|
||||
|
@ -208,6 +219,7 @@ class PurchaseBatchView(BatchMasterView):
|
|||
fs.mode.set(readonly=True)
|
||||
fs.store.set(readonly=True)
|
||||
fs.vendor.set(readonly=True)
|
||||
fs.department.set(readonly=True)
|
||||
fs.purchase.set(readonly=True)
|
||||
|
||||
def eligible_purchases(self):
|
||||
|
@ -223,10 +235,10 @@ class PurchaseBatchView(BatchMasterView):
|
|||
|
||||
purchases = Session.query(model.Purchase)\
|
||||
.filter(model.Purchase.vendor == vendor)
|
||||
if mode == enum.PURCHASE_BATCH_MODE_RECEIVING:
|
||||
if mode == self.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:
|
||||
elif mode == self.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)
|
||||
|
||||
|
@ -240,7 +252,7 @@ class PurchaseBatchView(BatchMasterView):
|
|||
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)
|
||||
return '{} for ${:0,.2f} ({})'.format(date, total, purchase.department or purchase.buyer)
|
||||
|
||||
def get_batch_kwargs(self, batch):
|
||||
kwargs = super(PurchaseBatchView, self).get_batch_kwargs(batch)
|
||||
|
@ -253,6 +265,10 @@ class PurchaseBatchView(BatchMasterView):
|
|||
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:
|
||||
|
@ -274,6 +290,8 @@ class PurchaseBatchView(BatchMasterView):
|
|||
purchase = Session.query(model.Purchase).get(batch.purchase_uuid)
|
||||
assert purchase
|
||||
kwargs['purchase'] = purchase
|
||||
kwargs['buyer'] = purchase.buyer
|
||||
kwargs['buyer_uuid'] = purchase.buyer_uuid
|
||||
kwargs['date_ordered'] = purchase.date_ordered
|
||||
kwargs['po_total'] = purchase.po_total
|
||||
|
||||
|
@ -510,7 +528,7 @@ class PurchaseBatchView(BatchMasterView):
|
|||
history = OrderedDict()
|
||||
purchases = Session.query(model.Purchase)\
|
||||
.filter(model.Purchase.vendor == batch.vendor)\
|
||||
.filter(model.Purchase.status >= enum.PURCHASE_STATUS_ORDERED)\
|
||||
.filter(model.Purchase.status >= self.enum.PURCHASE_STATUS_ORDERED)\
|
||||
.order_by(model.Purchase.date_ordered.desc(), model.Purchase.created.desc())\
|
||||
.options(orm.joinedload(model.Purchase.items))[:6]
|
||||
for purchase in purchases[:6]:
|
||||
|
|
|
@ -100,6 +100,10 @@ class PurchaseView(MasterView):
|
|||
default_active=True, default_verb='contains')
|
||||
g.sorters['vendor'] = g.make_sorter(model.Vendor.name)
|
||||
|
||||
g.joiners['department'] = lambda q: q.join(model.Department)
|
||||
g.filters['department'] = g.make_filter('department', model.Department.name)
|
||||
g.sorters['department'] = g.make_sorter(model.Department.name)
|
||||
|
||||
g.joiners['buyer'] = lambda q: q.join(model.Employee).join(model.Person)
|
||||
g.filters['buyer'] = g.make_filter('buyer', model.Person.display_name,
|
||||
default_active=True, default_verb='contains')
|
||||
|
@ -121,6 +125,7 @@ class PurchaseView(MasterView):
|
|||
include=[
|
||||
g.store,
|
||||
g.vendor,
|
||||
g.department,
|
||||
g.buyer,
|
||||
g.date_ordered,
|
||||
g.date_received,
|
||||
|
@ -130,6 +135,7 @@ class PurchaseView(MasterView):
|
|||
|
||||
def _preconfigure_fieldset(self, fs):
|
||||
fs.vendor.set(renderer=forms.renderers.VendorFieldRenderer)
|
||||
fs.department.set(renderer=forms.renderers.DepartmentFieldRenderer)
|
||||
fs.status.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.PURCHASE_STATUS),
|
||||
readonly=True)
|
||||
fs.po_number.set(label="PO Number")
|
||||
|
@ -142,6 +148,7 @@ class PurchaseView(MasterView):
|
|||
include=[
|
||||
fs.store,
|
||||
fs.vendor,
|
||||
fs.department,
|
||||
fs.status,
|
||||
fs.buyer,
|
||||
fs.date_ordered,
|
||||
|
@ -162,6 +169,16 @@ class PurchaseView(MasterView):
|
|||
del fs.invoice_number
|
||||
del fs.invoice_total
|
||||
|
||||
def delete_instance(self, purchase):
|
||||
"""
|
||||
Delete all batches for the purchase, then delete the purchase.
|
||||
"""
|
||||
for batch in list(purchase.batches):
|
||||
self.Session.delete(batch)
|
||||
self.Session.flush()
|
||||
self.Session.delete(purchase)
|
||||
self.Session.flush()
|
||||
|
||||
def get_parent(self, item):
|
||||
return item.purchase
|
||||
|
||||
|
|
Loading…
Reference in a new issue