Defer fetching price, cost history when viewing product details

user can ask for that history if they need it, but it's too expensive to always
fetch by default for initial page load
This commit is contained in:
Lance Edgar 2020-04-06 13:12:38 -05:00
parent f2b5e2302a
commit cc96d9877b
3 changed files with 213 additions and 18 deletions

View file

@ -32,7 +32,8 @@
let ThisPage = {
template: '#this-page-template',
methods: {}
computed: {},
methods: {},
}
let ThisPageData = {

View file

@ -305,7 +305,7 @@
<p class="panel-heading">
Vendor Sources
% if request.rattail_config.versioning_enabled() and master.has_perm('versions'):
<a href="#" @click.prevent="showingCostHistory = true">
<a href="#" @click.prevent="showCostHistory()">
(view cost history)
</a>
% endif
@ -380,7 +380,7 @@
</p>
</header>
<section class="modal-card-body">
${regular_price_history_grid.render_buefy_table_element(data_prop='regularPriceHistoryData')|n}
${regular_price_history_grid.render_buefy_table_element(data_prop='regularPriceHistoryData', loading='regularPriceHistoryLoading')|n}
</section>
<footer class="modal-card-foot">
<b-button @click="showingPriceHistory_regular = false">
@ -399,7 +399,7 @@
</p>
</header>
<section class="modal-card-body">
${current_price_history_grid.render_buefy_table_element(data_prop='currentPriceHistoryData')|n}
${current_price_history_grid.render_buefy_table_element(data_prop='currentPriceHistoryData', loading='currentPriceHistoryLoading')|n}
</section>
<footer class="modal-card-foot">
<b-button @click="showingPriceHistory_current = false">
@ -418,7 +418,7 @@
</p>
</header>
<section class="modal-card-body">
${suggested_price_history_grid.render_buefy_table_element(data_prop='suggestedPriceHistoryData')|n}
${suggested_price_history_grid.render_buefy_table_element(data_prop='suggestedPriceHistoryData', loading='suggestedPriceHistoryLoading')|n}
</section>
<footer class="modal-card-foot">
<b-button @click="showingPriceHistory_suggested = false">
@ -437,7 +437,7 @@
</p>
</header>
<section class="modal-card-body">
${cost_history_grid.render_buefy_table_element(data_prop='costHistoryData')|n}
${cost_history_grid.render_buefy_table_element(data_prop='costHistoryData', loading='costHistoryLoading')|n}
</section>
<footer class="modal-card-foot">
<b-button @click="showingCostHistory = false">
@ -539,16 +539,121 @@
<script type="text/javascript">
ThisPageData.showingPriceHistory_regular = false
ThisPageData.regularPriceHistoryData = ${json.dumps(regular_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.regularPriceHistoryDataRaw = ${json.dumps(regular_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.regularPriceHistoryLoading = false
ThisPage.computed.regularPriceHistoryData = function() {
let data = []
this.regularPriceHistoryDataRaw.forEach(raw => {
data.push({
price: raw.price_display,
since: raw.since,
changed: raw.changed_display_html,
changed_by: raw.changed_by_display,
})
})
return data
}
ThisPage.methods.showPriceHistory_regular = function() {
this.showingPriceHistory_regular = true
this.regularPriceHistoryLoading = true
let url = '${url("products.price_history", uuid=instance.uuid)}'
let params = {'type': 'regular'}
this.$http.get(url, {params: params}).then(response => {
this.regularPriceHistoryDataRaw = response.data
this.regularPriceHistoryLoading = false
})
}
ThisPageData.showingPriceHistory_current = false
ThisPageData.currentPriceHistoryData = ${json.dumps(current_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.currentPriceHistoryDataRaw = ${json.dumps(current_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.currentPriceHistoryLoading = false
ThisPage.computed.currentPriceHistoryData = function() {
let data = []
this.currentPriceHistoryDataRaw.forEach(raw => {
data.push({
price: raw.price_display,
price_type: raw.price_type,
since: raw.since,
changed: raw.changed_display_html,
changed_by: raw.changed_by_display,
})
})
return data
}
ThisPage.methods.showPriceHistory_current = function() {
this.showingPriceHistory_current = true
this.currentPriceHistoryLoading = true
let url = '${url("products.price_history", uuid=instance.uuid)}'
let params = {'type': 'current'}
this.$http.get(url, {params: params}).then(response => {
this.currentPriceHistoryDataRaw = response.data
this.currentPriceHistoryLoading = false
})
}
ThisPageData.showingPriceHistory_suggested = false
ThisPageData.suggestedPriceHistoryData = ${json.dumps(suggested_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.suggestedPriceHistoryDataRaw = ${json.dumps(suggested_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.suggestedPriceHistoryLoading = false
ThisPage.computed.suggestedPriceHistoryData = function() {
let data = []
this.suggestedPriceHistoryDataRaw.forEach(raw => {
data.push({
price: raw.price_display,
since: raw.since,
changed: raw.changed_display_html,
changed_by: raw.changed_by_display,
})
})
return data
}
ThisPage.methods.showPriceHistory_suggested = function() {
this.showingPriceHistory_suggested = true
this.suggestedPriceHistoryLoading = true
let url = '${url("products.price_history", uuid=instance.uuid)}'
let params = {'type': 'suggested'}
this.$http.get(url, {params: params}).then(response => {
this.suggestedPriceHistoryDataRaw = response.data
this.suggestedPriceHistoryLoading = false
})
}
ThisPageData.showingCostHistory = false
ThisPageData.costHistoryData = ${json.dumps(cost_history_grid.get_buefy_data()['data'])|n}
ThisPageData.costHistoryDataRaw = ${json.dumps(cost_history_grid.get_buefy_data()['data'])|n}
ThisPageData.costHistoryLoading = false
ThisPage.computed.costHistoryData = function() {
let data = []
this.costHistoryDataRaw.forEach(raw => {
data.push({
cost: raw.cost_display,
vendor: raw.vendor,
since: raw.since,
changed: raw.changed_display_html,
changed_by: raw.changed_by_display,
})
})
return data
}
ThisPage.methods.showCostHistory = function() {
this.showingCostHistory = true
this.costHistoryLoading = true
let url = '${url("products.cost_history", uuid=instance.uuid)}'
this.$http.get(url).then(response => {
this.costHistoryDataRaw = response.data
this.costHistoryLoading = false
})
}
</script>
% endif

View file

@ -483,7 +483,7 @@ class ProductsView(MasterView):
return text
if self.get_use_buefy():
kwargs = {'@click.prevent': 'showingPriceHistory_{} = true'.format(typ)}
kwargs = {'@click.prevent': 'showPriceHistory_{}()'.format(typ)}
else:
kwargs = {'id': 'view-{}-price-history'.format(typ)}
history = tags.link_to("(view history)", '#', **kwargs)
@ -494,10 +494,17 @@ class ProductsView(MasterView):
br = HTML.tag('br')
return HTML.tag('div', c=[text, br, history])
def show_price_effective_dates(self):
if not self.rattail_config.versioning_enabled():
return False
return self.rattail_config.getbool(
'tailbone', 'products.show_effective_price_dates',
default=True)
def render_regular_price(self, product, field):
text = self.render_price(product, field)
if text and self.rattail_config.versioning_enabled():
if text and self.show_price_effective_dates():
history = self.get_regular_price_history(product)
if history:
date = localtime(self.rattail_config, history[0]['changed'], from_utc=True).date()
@ -508,7 +515,7 @@ class ProductsView(MasterView):
def render_current_price(self, product, field):
text = self.render_price(product, field)
if text and self.rattail_config.versioning_enabled():
if text and self.show_price_effective_dates():
history = self.get_current_price_history(product)
if history:
date = localtime(self.rattail_config, history[0]['changed'], from_utc=True).date()
@ -526,7 +533,7 @@ class ProductsView(MasterView):
def render_suggested_price(self, product, column):
text = self.render_price(product, column)
if text and self.rattail_config.versioning_enabled():
if text and self.show_price_effective_dates():
history = self.get_suggested_price_history(product)
if history:
date = localtime(self.rattail_config, history[0]['changed'], from_utc=True).date()
@ -973,8 +980,63 @@ class ProductsView(MasterView):
return ""
return pretty_quantity(value)
def price_history(self):
"""
AJAX view for fetching various types of price history for a product.
"""
product = self.get_instance()
typ = self.request.params.get('type', 'regular')
assert typ in ('regular', 'current', 'suggested')
getter = getattr(self, 'get_{}_price_history'.format(typ))
data = getter(product)
# make some data JSON-friendly
jsdata = []
for history in data:
history = dict(history)
price = history['price']
history['price'] = float(price)
history['price_display'] = "${:0.2f}".format(price)
changed = localtime(self.rattail_config, history['changed'], from_utc=True)
history['changed'] = six.text_type(changed)
history['changed_display_html'] = raw_datetime(self.rattail_config, changed)
user = history.pop('changed_by')
history['changed_by_uuid'] = user.uuid
history['changed_by_display'] = six.text_type(user)
jsdata.append(history)
return jsdata
def cost_history(self):
"""
AJAX view for fetching cost history for a product.
"""
product = self.get_instance()
data = self.get_cost_history(product)
# make some data JSON-friendly
jsdata = []
for history in data:
history = dict(history)
cost = history['cost']
if cost is not None:
history['cost'] = float(cost)
history['cost_display'] = "${:0.2f}".format(cost)
else:
history['cost_display'] = None
changed = localtime(self.rattail_config, history['changed'], from_utc=True)
history['changed'] = six.text_type(changed)
history['changed_display_html'] = raw_datetime(self.rattail_config, changed)
user = history.pop('changed_by')
history['changed_by_uuid'] = user.uuid
history['changed_by_display'] = six.text_type(user)
jsdata.append(history)
return jsdata
def template_kwargs_view(self, **kwargs):
product = kwargs['instance']
use_buefy = self.get_use_buefy()
# TODO: pretty sure this is no longer needed? guess we'll find out
# kwargs['image'] = False
@ -998,7 +1060,10 @@ class ProductsView(MasterView):
if self.rattail_config.versioning_enabled() and self.has_perm('versions'):
# regular price
data = self.get_regular_price_history(product)
if use_buefy:
data = [] # defer fetching until user asks for it
else:
data = self.get_regular_price_history(product)
grid = grids.Grid('products.regular_price_history', data,
request=self.request,
columns=[
@ -1012,7 +1077,10 @@ class ProductsView(MasterView):
kwargs['regular_price_history_grid'] = grid
# current price
data = self.get_current_price_history(product)
if use_buefy:
data = [] # defer fetching until user asks for it
else:
data = self.get_current_price_history(product)
grid = grids.Grid('products.current_price_history', data,
request=self.request,
columns=[
@ -1030,7 +1098,10 @@ class ProductsView(MasterView):
kwargs['current_price_history_grid'] = grid
# suggested price
data = self.get_suggested_price_history(product)
if use_buefy:
data = [] # defer fetching until user asks for it
else:
data = self.get_suggested_price_history(product)
grid = grids.Grid('products.suggested_price_history', data,
request=self.request,
columns=[
@ -1044,7 +1115,10 @@ class ProductsView(MasterView):
kwargs['suggested_price_history_grid'] = grid
# cost history
data = self.get_cost_history(product)
if use_buefy:
data = [] # defer fetching until user asks for it
else:
data = self.get_cost_history(product)
grid = grids.Grid('products.cost_history', data,
request=self.request,
columns=[
@ -1654,6 +1728,7 @@ class ProductsView(MasterView):
rattail_config = config.registry.settings.get('rattail_config')
route_prefix = cls.get_route_prefix()
url_prefix = cls.get_url_prefix()
instance_url_prefix = cls.get_instance_url_prefix()
template_prefix = cls.get_template_prefix()
permission_prefix = cls.get_permission_prefix()
model_title = cls.get_model_title()
@ -1684,6 +1759,20 @@ class ProductsView(MasterView):
config.add_route('products.image', '/products/{uuid}/image')
config.add_view(cls, attr='image', route_name='products.image')
# price history
config.add_route('{}.price_history'.format(route_prefix), '{}/price-history'.format(instance_url_prefix),
request_method='GET')
config.add_view(cls, attr='price_history', route_name='{}.price_history'.format(route_prefix),
renderer='json',
permission='{}.versions'.format(permission_prefix))
# cost history
config.add_route('{}.cost_history'.format(route_prefix), '{}/cost-history'.format(instance_url_prefix),
request_method='GET')
config.add_view(cls, attr='cost_history', route_name='{}.cost_history'.format(route_prefix),
renderer='json',
permission='{}.versions'.format(permission_prefix))
# mobile quick lookup
if legacy_mobile:
config.add_route('mobile.products.quick_lookup', '/mobile/products/quick-lookup')