Show events instead of notes, in field subgrid for custorder item
This commit is contained in:
parent
e930199f83
commit
1cad8b2481
|
@ -280,7 +280,7 @@
|
|||
:disabled="addNoteSaveDisabled"
|
||||
icon-pack="fas"
|
||||
icon-left="save">
|
||||
{{ addNoteSubmitText }}
|
||||
{{ addNoteSubmitting ? "Working, please wait..." : "Save Note" }}
|
||||
</b-button>
|
||||
<b-button @click="showAddNoteDialog = false">
|
||||
Cancel
|
||||
|
@ -295,7 +295,7 @@
|
|||
${parent.modify_this_page_vars()}
|
||||
<script type="text/javascript">
|
||||
|
||||
${form.component_studly}Data.notesData = ${json.dumps(notes_data)|n}
|
||||
${form.component_studly}Data.eventsData = ${json.dumps(events_data)|n}
|
||||
|
||||
% if master.has_perm('confirm_price'):
|
||||
|
||||
|
@ -406,7 +406,6 @@
|
|||
ThisPageData.newNoteText = null
|
||||
ThisPageData.newNoteApplyAll = false
|
||||
ThisPageData.addNoteSubmitting = false
|
||||
ThisPageData.addNoteSubmitText = "Save Note"
|
||||
|
||||
ThisPage.computed.addNoteSaveDisabled = function() {
|
||||
if (!this.newNoteText) {
|
||||
|
@ -429,43 +428,19 @@
|
|||
|
||||
ThisPage.methods.addNoteSave = function() {
|
||||
this.addNoteSubmitting = true
|
||||
this.addNoteSubmitText = "Working, please wait..."
|
||||
|
||||
let url = '${url('{}.add_note'.format(route_prefix), uuid=instance.uuid)}'
|
||||
|
||||
let params = {
|
||||
note: this.newNoteText,
|
||||
apply_all: this.newNoteApplyAll,
|
||||
}
|
||||
|
||||
let headers = {
|
||||
## TODO: should find a better way to handle CSRF token
|
||||
'X-CSRF-TOKEN': this.csrftoken,
|
||||
}
|
||||
|
||||
## TODO: should find a better way to handle CSRF token
|
||||
this.$http.post(url, params, {headers: headers}).then(({ data }) => {
|
||||
if (data.success) {
|
||||
this.$refs.mainForm.notesData = data.notes
|
||||
this.showAddNoteDialog = false
|
||||
} else {
|
||||
this.$buefy.toast.open({
|
||||
message: "Save failed: " + (data.error || "(unknown error)"),
|
||||
type: 'is-danger',
|
||||
duration: 4000, // 4 seconds
|
||||
})
|
||||
}
|
||||
this.simplePOST(url, params, response => {
|
||||
this.$refs.mainForm.eventsData = response.data.events
|
||||
this.showAddNoteDialog = false
|
||||
this.addNoteSubmitting = false
|
||||
this.addNoteSubmitText = "Save Note"
|
||||
}).catch((error) => {
|
||||
// TODO: should handle this better somehow..?
|
||||
this.$buefy.toast.open({
|
||||
message: "Save failed: (unknown error)",
|
||||
type: 'is-danger',
|
||||
duration: 4000, // 4 seconds
|
||||
})
|
||||
}, response => {
|
||||
this.addNoteSubmitting = false
|
||||
this.addNoteSubmitText = "Save Note"
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,7 @@ import datetime
|
|||
|
||||
from sqlalchemy import orm
|
||||
|
||||
from rattail.db import model
|
||||
from rattail.time import localtime
|
||||
from rattail.db.model import CustomerOrderItem
|
||||
|
||||
from webhelpers2.html import HTML, tags
|
||||
|
||||
|
@ -41,7 +40,7 @@ class CustomerOrderItemView(MasterView):
|
|||
"""
|
||||
Master view for customer order items
|
||||
"""
|
||||
model_class = model.CustomerOrderItem
|
||||
model_class = CustomerOrderItem
|
||||
route_prefix = 'custorders.items'
|
||||
url_prefix = '/custorders/items'
|
||||
creatable = False
|
||||
|
@ -72,21 +71,6 @@ class CustomerOrderItemView(MasterView):
|
|||
'flagged',
|
||||
]
|
||||
|
||||
has_rows = True
|
||||
model_row_class = model.CustomerOrderItemEvent
|
||||
rows_title = "Event History"
|
||||
rows_filterable = False
|
||||
rows_sortable = False
|
||||
rows_pageable = False
|
||||
rows_viewable = False
|
||||
|
||||
row_grid_columns = [
|
||||
'occurred',
|
||||
'type_code',
|
||||
'user',
|
||||
'note',
|
||||
]
|
||||
|
||||
form_fields = [
|
||||
'order',
|
||||
'customer',
|
||||
|
@ -98,20 +82,32 @@ class CustomerOrderItemView(MasterView):
|
|||
'product_brand',
|
||||
'product_description',
|
||||
'product_size',
|
||||
'case_quantity',
|
||||
'order_quantity',
|
||||
'order_uom',
|
||||
'case_quantity',
|
||||
'unit_price',
|
||||
'total_price',
|
||||
'special_order',
|
||||
'price_needs_confirmation',
|
||||
'paid_amount',
|
||||
'payment_transaction_number',
|
||||
'status_code',
|
||||
'flagged',
|
||||
'notes',
|
||||
'contact_attempts',
|
||||
'last_contacted',
|
||||
'events',
|
||||
]
|
||||
|
||||
def __init__(self, request):
|
||||
super().__init__(request)
|
||||
app = self.get_rattail_app()
|
||||
self.custorder_handler = app.get_custorder_handler()
|
||||
self.batch_handler = app.get_batch_handler(
|
||||
'custorder',
|
||||
default='rattail.batch.custorder:CustomerOrderBatchHandler')
|
||||
|
||||
def query(self, session):
|
||||
model = self.model
|
||||
return session.query(model.CustomerOrderItem)\
|
||||
.join(model.CustomerOrder)\
|
||||
.options(orm.joinedload(model.CustomerOrderItem.order)\
|
||||
|
@ -119,7 +115,7 @@ class CustomerOrderItemView(MasterView):
|
|||
|
||||
def configure_grid(self, g):
|
||||
super().configure_grid(g)
|
||||
batch_handler = self.get_batch_handler()
|
||||
model = self.model
|
||||
|
||||
# order_id
|
||||
g.set_renderer('order_id', self.render_order_id)
|
||||
|
@ -155,7 +151,7 @@ class CustomerOrderItemView(MasterView):
|
|||
|
||||
# order_uom
|
||||
# nb. this is not relevant if "case orders only"
|
||||
if not batch_handler.allow_unit_orders():
|
||||
if not self.batch_handler.allow_unit_orders():
|
||||
g.remove('order_uom')
|
||||
else:
|
||||
g.set_enum('order_uom', self.enum.UNIT_OF_MEASURE)
|
||||
|
@ -168,6 +164,19 @@ class CustomerOrderItemView(MasterView):
|
|||
# status_code
|
||||
g.set_renderer('status_code', self.render_status_code_column)
|
||||
|
||||
# abbreviate some labels, only in grid header
|
||||
g.set_label('case_quantity', "Case Qty")
|
||||
g.filters['case_quantity'].label = "Case Quantity"
|
||||
g.set_label('order_quantity', "Order Qty")
|
||||
g.filters['order_quantity'].label = "Order Quantity"
|
||||
g.set_label('department_name', "Department")
|
||||
g.filters['department_name'].label = "Department Name"
|
||||
g.set_label('total_price', "Total")
|
||||
g.filters['total_price'].label = "Total Price"
|
||||
g.set_label('order_created', "Ordered")
|
||||
if 'order_created' in g.filters:
|
||||
g.filters['order_created'].label = "Order Created"
|
||||
|
||||
def render_order_id(self, item, field):
|
||||
return item.order.id
|
||||
|
||||
|
@ -178,7 +187,8 @@ class CustomerOrderItemView(MasterView):
|
|||
return text
|
||||
|
||||
def render_order_created(self, item, column):
|
||||
value = localtime(self.rattail_config, item.order.created, from_utc=True)
|
||||
app = self.get_rattail_app()
|
||||
value = app.localtime(item.order.created, from_utc=True)
|
||||
return raw_datetime(self.rattail_config, value)
|
||||
|
||||
def render_status_code_column(self, item, field):
|
||||
|
@ -188,12 +198,6 @@ class CustomerOrderItemView(MasterView):
|
|||
return HTML.tag('span', title=item.status_text, c=[text])
|
||||
return text
|
||||
|
||||
def get_batch_handler(self):
|
||||
app = self.get_rattail_app()
|
||||
return app.get_batch_handler(
|
||||
'custorder',
|
||||
default='rattail.batch.custorder:CustomerOrderBatchHandler')
|
||||
|
||||
def configure_form(self, f):
|
||||
super().configure_form(f)
|
||||
item = f.model_instance
|
||||
|
@ -202,8 +206,7 @@ class CustomerOrderItemView(MasterView):
|
|||
f.set_renderer('order', self.render_order)
|
||||
|
||||
# contact
|
||||
batch_handler = self.get_batch_handler()
|
||||
if batch_handler.new_order_requires_customer():
|
||||
if self.batch_handler.new_order_requires_customer():
|
||||
f.remove('person')
|
||||
else:
|
||||
f.remove('customer')
|
||||
|
@ -221,7 +224,9 @@ class CustomerOrderItemView(MasterView):
|
|||
elif item.pending_product and not item.product:
|
||||
f.remove('product')
|
||||
|
||||
# product uom
|
||||
# product*
|
||||
if not self.creating and item.product:
|
||||
f.remove('product_brand', 'product_description')
|
||||
f.set_enum('product_unit_of_measure', self.enum.UNIT_OF_MEASURE)
|
||||
|
||||
# highlight pending fields
|
||||
|
@ -251,8 +256,8 @@ class CustomerOrderItemView(MasterView):
|
|||
# flagged
|
||||
f.set_renderer('flagged', self.render_flagged)
|
||||
|
||||
# notes
|
||||
f.set_renderer('notes', self.render_notes)
|
||||
# events
|
||||
f.set_renderer('events', self.render_events)
|
||||
|
||||
def render_flagged(self, item, field):
|
||||
text = "Yes" if item.flagged else "No"
|
||||
|
@ -375,27 +380,28 @@ class CustomerOrderItemView(MasterView):
|
|||
|
||||
return False
|
||||
|
||||
def render_notes(self, item, field):
|
||||
def render_events(self, item, field):
|
||||
route_prefix = self.get_route_prefix()
|
||||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key=f'{route_prefix}.notes',
|
||||
key=f'{route_prefix}.events',
|
||||
data=[],
|
||||
columns=[
|
||||
'created',
|
||||
'created_by',
|
||||
'text',
|
||||
'occurred',
|
||||
'type_code',
|
||||
'user',
|
||||
'note',
|
||||
],
|
||||
labels={
|
||||
'created': "Date/Time",
|
||||
'created_by': "Added by",
|
||||
'text': "Note",
|
||||
'occurred': "When",
|
||||
'type_code': "What",
|
||||
'user': "Who",
|
||||
},
|
||||
)
|
||||
|
||||
table = HTML.literal(
|
||||
g.render_buefy_table_element(data_prop='notesData'))
|
||||
g.render_buefy_table_element(data_prop='eventsData'))
|
||||
elements = [table]
|
||||
|
||||
if self.has_perm('add_note'):
|
||||
|
@ -412,12 +418,13 @@ class CustomerOrderItemView(MasterView):
|
|||
c=elements)
|
||||
|
||||
def template_kwargs_view(self, **kwargs):
|
||||
kwargs = super(CustomerOrderItemView, self).template_kwargs_view(**kwargs)
|
||||
kwargs = super().template_kwargs_view(**kwargs)
|
||||
model = self.model
|
||||
app = self.get_rattail_app()
|
||||
item = kwargs['instance']
|
||||
|
||||
# fetch notes for current item
|
||||
kwargs['notes_data'] = self.get_context_notes(item)
|
||||
# fetch events for current item
|
||||
kwargs['events_data'] = self.get_context_events(item)
|
||||
|
||||
# fetch "other" order items, siblings of current one
|
||||
order = item.order
|
||||
|
@ -431,7 +438,7 @@ class CustomerOrderItemView(MasterView):
|
|||
|
||||
order_date = None
|
||||
if order.created:
|
||||
order_date = localtime(self.rattail_config, order.created, from_utc=True).date()
|
||||
order_date = app.localtime(order.created, from_utc=True).date()
|
||||
|
||||
other_data.append({
|
||||
'uuid': other.uuid,
|
||||
|
@ -454,16 +461,18 @@ class CustomerOrderItemView(MasterView):
|
|||
|
||||
return kwargs
|
||||
|
||||
def get_context_notes(self, item):
|
||||
notes = []
|
||||
for note in reversed(item.notes):
|
||||
created = localtime(self.rattail_config, note.created, from_utc=True)
|
||||
notes.append({
|
||||
'created': raw_datetime(self.rattail_config, created),
|
||||
'created_by': note.created_by.display_name,
|
||||
'text': note.text,
|
||||
def get_context_events(self, item):
|
||||
app = self.get_rattail_app()
|
||||
events = []
|
||||
for event in item.events:
|
||||
occurred = app.localtime(event.occurred, from_utc=True)
|
||||
events.append({
|
||||
'occurred': raw_datetime(self.rattail_config, occurred),
|
||||
'type_code': self.enum.CUSTORDER_ITEM_EVENT.get(event.type_code, event.type_code),
|
||||
'user': str(event.user),
|
||||
'note': event.note,
|
||||
})
|
||||
return notes
|
||||
return events
|
||||
|
||||
def confirm_price(self):
|
||||
"""
|
||||
|
@ -517,6 +526,7 @@ class CustomerOrderItemView(MasterView):
|
|||
"""
|
||||
View for changing status of one or more order items.
|
||||
"""
|
||||
model = self.model
|
||||
order_item = self.get_instance()
|
||||
redirect = self.redirect(self.get_action_url('view', order_item))
|
||||
|
||||
|
@ -570,30 +580,15 @@ class CustomerOrderItemView(MasterView):
|
|||
View for adding a new note to current order item, optinally
|
||||
also adding it to all other items under the parent order.
|
||||
"""
|
||||
order_item = self.get_instance()
|
||||
item = self.get_instance()
|
||||
data = self.request.json_body
|
||||
new_note = data['note']
|
||||
apply_all = data['apply_all'] == True
|
||||
user = self.request.user
|
||||
|
||||
if apply_all:
|
||||
order_items = order_item.order.items
|
||||
else:
|
||||
order_items = [order_item]
|
||||
|
||||
for item in order_items:
|
||||
item.notes.append(model.CustomerOrderItemNote(
|
||||
created_by=user, text=new_note))
|
||||
|
||||
# # attach event
|
||||
# item.events.append(model.CustomerOrderItemEvent(
|
||||
# type_code=self.enum.CUSTORDER_ITEM_EVENT_ADDED_NOTE,
|
||||
# user=user, note=new_note))
|
||||
self.custorder_handler.add_note(item, data['note'], self.request.user,
|
||||
apply_all=data['apply_all'] == True)
|
||||
|
||||
self.Session.flush()
|
||||
self.Session.refresh(order_item)
|
||||
return {'success': True,
|
||||
'notes': self.get_context_notes(order_item)}
|
||||
self.Session.refresh(item)
|
||||
return {'events': self.get_context_events(item)}
|
||||
|
||||
def render_order(self, item, field):
|
||||
order = item.order
|
||||
|
@ -610,22 +605,6 @@ class CustomerOrderItemView(MasterView):
|
|||
url = self.request.route_url('people.view', uuid=person.uuid)
|
||||
return tags.link_to(text, url)
|
||||
|
||||
def get_row_data(self, item):
|
||||
return self.Session.query(model.CustomerOrderItemEvent)\
|
||||
.filter(model.CustomerOrderItemEvent.item == item)\
|
||||
.order_by(model.CustomerOrderItemEvent.occurred,
|
||||
model.CustomerOrderItemEvent.type_code)
|
||||
|
||||
def configure_row_grid(self, g):
|
||||
super(CustomerOrderItemView, self).configure_row_grid(g)
|
||||
|
||||
g.set_enum('type_code', self.enum.CUSTORDER_ITEM_EVENT)
|
||||
|
||||
g.set_label('occurred', "When")
|
||||
g.set_label('type_code', "What") # TODO: enum renderer
|
||||
g.set_label('user', "Who")
|
||||
g.set_label('note', "Notes")
|
||||
|
||||
@classmethod
|
||||
def defaults(cls, config):
|
||||
cls._order_item_defaults(config)
|
||||
|
|
Loading…
Reference in a new issue