Misc. improvements for desktop receiving views

- don't expose "cases" if config says not to
- don't expose "expired" if config says not to
- use `numeric-input` for quantity fields
- add `product_key_field` to global-ish template context
This commit is contained in:
Lance Edgar 2022-07-26 16:30:04 -05:00
parent 92a52133de
commit 17810d9cae
7 changed files with 125 additions and 84 deletions

View file

@ -20,7 +20,7 @@ const NumericInput = {
props: { props: {
name: String, name: String,
value: String, value: [Number, String],
placeholder: String, placeholder: String,
iconPack: String, iconPack: String,
icon: String, icon: String,
@ -53,6 +53,10 @@ const NumericInput = {
} }
}, },
select() {
this.$el.children[0].select()
},
valueChanged(value) { valueChanged(value) {
this.$emit('input', value) this.$emit('input', value)
} }

View file

@ -82,11 +82,11 @@
<div style="display: flex;"> <div style="display: flex;">
<div> <div>
% if row.product: % if row.product:
${form.render_field_readonly('upc')} ${form.render_field_readonly(product_key_field)}
${form.render_field_readonly('product')} ${form.render_field_readonly('product')}
% else: % else:
${form.render_field_readonly('item_entry')} ${form.render_field_readonly('item_entry')}
${form.render_field_readonly('upc')} ${form.render_field_readonly(product_key_field)}
${form.render_field_readonly('brand_name')} ${form.render_field_readonly('brand_name')}
${form.render_field_readonly('description')} ${form.render_field_readonly('description')}
${form.render_field_readonly('size')} ${form.render_field_readonly('size')}
@ -192,15 +192,17 @@
<b-field grouped> <b-field grouped>
<b-field label="Case Qty."> % if allow_cases:
<span class="control"> <b-field label="Case Qty.">
{{ rowData.case_quantity }} <span class="control">
</span> {{ rowData.case_quantity }}
</b-field> </span>
</b-field>
<span class="control"> <span class="control">
&nbsp; &nbsp;
</span> </span>
% endif
<b-field label="Product State" <b-field label="Product State"
:type="accountForProductMode ? null : 'is-danger'"> :type="accountForProductMode ? null : 'is-danger'">
@ -226,31 +228,39 @@
<div class="level-left"> <div class="level-left">
<div class="level-item"> <div class="level-item">
<b-input v-model="accountForProductQuantity" <numeric-input v-model="accountForProductQuantity"
type="number" step="0.0001" ref="accountForProductQuantityInput">
ref="accountForProductQuantityInput"> </numeric-input>
</b-input>
</div> </div>
<div class="level-item"> <div class="level-item">
<b-field> % if allow_cases:
<b-radio-button v-model="accountForProductUOM" <b-field>
@click.native="accountForProductUOMClicked('units')" <b-radio-button v-model="accountForProductUOM"
native-value="units"> @click.native="accountForProductUOMClicked('units')"
Units native-value="units">
</b-radio-button> Units
<b-radio-button v-model="accountForProductUOM" </b-radio-button>
@click.native="accountForProductUOMClicked('cases')" <b-radio-button v-model="accountForProductUOM"
native-value="cases"> @click.native="accountForProductUOMClicked('cases')"
Cases native-value="cases">
</b-radio-button> Cases
</b-field> </b-radio-button>
</b-field>
% else:
<b-field>
<input type="hidden" v-model="accountForProductUOM" />
Units
</b-field>
% endif
</div> </div>
<div class="level-item" % if allow_cases:
v-if="accountForProductUOM == 'cases' && accountForProductQuantity"> <div class="level-item"
= {{ accountForProductTotalUnits }} v-if="accountForProductUOM == 'cases' && accountForProductQuantity">
</div> = {{ accountForProductTotalUnits }}
</div>
% endif
</div> </div>
</div> </div>
@ -325,31 +335,39 @@
<div class="level-left"> <div class="level-left">
<div class="level-item"> <div class="level-item">
<b-input v-model="declareCreditQuantity" <numeric-input v-model="declareCreditQuantity"
type="number" step="0.0001" ref="declareCreditQuantityInput">
ref="declareCreditQuantityInput"> </numeric-input>
</b-input>
</div> </div>
<div class="level-item"> <div class="level-item">
<b-field> % if allow_cases:
<b-radio-button v-model="declareCreditUOM" <b-field>
@click.native="declareCreditUOMClicked('units')" <b-radio-button v-model="declareCreditUOM"
native-value="units"> @click.native="declareCreditUOMClicked('units')"
Units native-value="units">
</b-radio-button> Units
<b-radio-button v-model="declareCreditUOM" </b-radio-button>
@click.native="declareCreditUOMClicked('cases')" <b-radio-button v-model="declareCreditUOM"
native-value="cases"> @click.native="declareCreditUOMClicked('cases')"
Cases native-value="cases">
</b-radio-button> Cases
</b-field> </b-radio-button>
</b-field>
% else:
<b-field>
<input type="hidden" v-model="declareCreditUOM" />
Units
</b-field>
% endif
</div> </div>
<div class="level-item" % if allow_cases:
v-if="declareCreditUOM == 'cases' && declareCreditQuantity"> <div class="level-item"
= {{ declareCreditTotalUnits }} v-if="declareCreditUOM == 'cases' && declareCreditQuantity">
</div> = {{ declareCreditTotalUnits }}
</div>
% endif
</div> </div>
</div> </div>
@ -494,7 +512,7 @@
if (this.accountForProductMode == 'expired' && !this.accountForProductExpiration) { if (this.accountForProductMode == 'expired' && !this.accountForProductExpiration) {
return true return true
} }
if (!this.accountForProductQuantity) { if (!this.accountForProductQuantity || this.accountForProductQuantity == 0) {
return true return true
} }
if (this.accountForProductSubmitting) { if (this.accountForProductSubmitting) {
@ -506,9 +524,13 @@
ThisPage.methods.accountForProductInit = function() { ThisPage.methods.accountForProductInit = function() {
this.accountForProductMode = 'received' this.accountForProductMode = 'received'
this.accountForProductExpiration = null this.accountForProductExpiration = null
this.accountForProductQuantity = null this.accountForProductQuantity = 0
this.accountForProductUOM = 'units' this.accountForProductUOM = 'units'
this.accountForProductShowDialog = true this.accountForProductShowDialog = true
this.$nextTick(() => {
this.$refs.accountForProductQuantityInput.select()
this.$refs.accountForProductQuantityInput.focus()
})
} }
ThisPage.methods.accountForProductUOMClicked = function(uom) { ThisPage.methods.accountForProductUOMClicked = function(uom) {
@ -606,7 +628,7 @@
if (this.declareCreditType == 'expired' && !this.declareCreditExpiration) { if (this.declareCreditType == 'expired' && !this.declareCreditExpiration) {
return true return true
} }
if (!this.declareCreditQuantity) { if (!this.declareCreditQuantity || this.declareCreditQuantity == 0) {
return true return true
} }
if (this.declareCreditSubmitting) { if (this.declareCreditSubmitting) {
@ -618,13 +640,18 @@
ThisPage.methods.declareCreditInit = function() { ThisPage.methods.declareCreditInit = function() {
this.declareCreditType = null this.declareCreditType = null
this.declareCreditExpiration = null this.declareCreditExpiration = null
if (this.rowData.cases_received) { % if allow_cases:
this.declareCreditQuantity = this.rowData.cases_received if (this.rowData.cases_received) {
this.declareCreditUOM = 'cases' this.declareCreditQuantity = this.rowData.cases_received
} else { this.declareCreditUOM = 'cases'
} else {
this.declareCreditQuantity = this.rowData.units_received
this.declareCreditUOM = 'units'
}
% else:
this.declareCreditQuantity = this.rowData.units_received this.declareCreditQuantity = this.rowData.units_received
this.declareCreditUOM = 'units' this.declareCreditUOM = 'units'
} % endif
this.declareCreditShowDialog = true this.declareCreditShowDialog = true
} }
@ -638,11 +665,15 @@
expiration_date: this.declareCreditExpiration, expiration_date: this.declareCreditExpiration,
} }
if (this.declareCreditUOM == 'cases') { % if allow_cases:
params.cases = this.declareCreditQuantity if (this.declareCreditUOM == 'cases') {
} else { params.cases = this.declareCreditQuantity
} else {
params.units = this.declareCreditQuantity
}
% else:
params.units = this.declareCreditQuantity params.units = this.declareCreditQuantity
} % endif
this.submitForm(url, params, response => { this.submitForm(url, params, response => {
this.rowData = response.data.row this.rowData = response.data.row

View file

@ -339,7 +339,6 @@ class CustomerOrderView(MasterView):
'batch': batch, 'batch': batch,
'normalized_batch': self.normalize_batch(batch), 'normalized_batch': self.normalize_batch(batch),
'new_order_requires_customer': self.batch_handler.new_order_requires_customer(), 'new_order_requires_customer': self.batch_handler.new_order_requires_customer(),
'product_key_field': self.rattail_config.product_key(),
'product_price_may_be_questionable': self.batch_handler.product_price_may_be_questionable(), 'product_price_may_be_questionable': self.batch_handler.product_price_may_be_questionable(),
'allow_contact_info_choice': self.batch_handler.allow_contact_info_choice(), 'allow_contact_info_choice': self.batch_handler.allow_contact_info_choice(),
'allow_contact_info_create': self.batch_handler.allow_contact_info_creation(), 'allow_contact_info_create': self.batch_handler.allow_contact_info_creation(),

View file

@ -2208,6 +2208,9 @@ class MasterView(View):
'quickie': None, 'quickie': None,
} }
key = self.rattail_config.product_key()
context['product_key_field'] = self.product_key_fields.get(key, key)
if self.expose_quickie_search: if self.expose_quickie_search:
context['quickie'] = self.get_quickie_context() context['quickie'] = self.get_quickie_context()

View file

@ -1180,9 +1180,6 @@ class ProductView(MasterView):
product = kwargs['instance'] product = kwargs['instance']
use_buefy = self.get_use_buefy() use_buefy = self.get_use_buefy()
key = self.rattail_config.product_key()
kwargs['product_key_field'] = self.product_key_fields.get(key, key)
kwargs['image_url'] = self.products_handler.get_image_url(product) kwargs['image_url'] = self.products_handler.get_image_url(product)
# add price history, if user has access # add price history, if user has access

View file

@ -803,7 +803,9 @@ class PurchasingBatchView(BatchMasterView):
app = self.get_rattail_app() app = self.get_rattail_app()
cases = getattr(row, 'cases_{}'.format(field)) cases = getattr(row, 'cases_{}'.format(field))
units = getattr(row, 'units_{}'.format(field)) units = getattr(row, 'units_{}'.format(field))
return app.render_cases_units(cases, units) # nb. do not render anything if empty quantities
if cases or units:
return app.render_cases_units(cases, units)
def make_row_credits_grid(self, row): def make_row_credits_grid(self, row):
use_buefy = self.get_use_buefy() use_buefy = self.get_use_buefy()
@ -815,8 +817,6 @@ class PurchasingBatchView(BatchMasterView):
data=[] if use_buefy else row.credits, data=[] if use_buefy else row.credits,
columns=[ columns=[
'credit_type', 'credit_type',
# 'cases_shorted',
# 'units_shorted',
'shorted', 'shorted',
'credit_total', 'credit_total',
'expiration_date', 'expiration_date',
@ -827,20 +827,19 @@ class PurchasingBatchView(BatchMasterView):
], ],
labels={ labels={
'credit_type': "Type", 'credit_type': "Type",
'cases_shorted': "Cases",
'units_shorted': "Units",
'shorted': "Quantity", 'shorted': "Quantity",
'credit_total': "Total", 'credit_total': "Total",
'mispick_upc': "Mispick UPC", # 'mispick_upc': "Mispick UPC",
'mispick_brand_name': "MP Brand", # 'mispick_brand_name': "MP Brand",
'mispick_description': "MP Description", # 'mispick_description': "MP Description",
'mispick_size': "MP Size", # 'mispick_size': "MP Size",
}) })
g.set_type('cases_shorted', 'quantity')
g.set_type('units_shorted', 'quantity')
g.set_type('credit_total', 'currency') g.set_type('credit_total', 'currency')
if not self.batch_handler.allow_expired_credits():
g.remove('expiration_date')
return g return g
def render_row_credits(self, row, field): def render_row_credits(self, row, field):

View file

@ -152,8 +152,7 @@ class ReceivingBatchView(PurchasingBatchView):
row_grid_columns = [ row_grid_columns = [
'sequence', 'sequence',
'upc', '_product_key_',
# 'item_id',
'vendor_code', 'vendor_code',
'brand_name', 'brand_name',
'description', 'description',
@ -177,8 +176,7 @@ class ReceivingBatchView(PurchasingBatchView):
row_form_fields = [ row_form_fields = [
'sequence', 'sequence',
'item_entry', 'item_entry',
'upc', '_product_key_',
'item_id',
'vendor_code', 'vendor_code',
'product', 'product',
'brand_name', 'brand_name',
@ -769,6 +767,8 @@ class ReceivingBatchView(PurchasingBatchView):
products_handler = app.get_products_handler() products_handler = app.get_products_handler()
row = kwargs['instance'] row = kwargs['instance']
kwargs['allow_cases'] = self.batch_handler.allow_cases()
if row.product: if row.product:
kwargs['image_url'] = products_handler.get_image_url(row.product) kwargs['image_url'] = products_handler.get_image_url(row.product)
elif row.upc: elif row.upc:
@ -776,8 +776,16 @@ class ReceivingBatchView(PurchasingBatchView):
if use_buefy: if use_buefy:
kwargs['row_context'] = self.get_context_row(row) kwargs['row_context'] = self.get_context_row(row)
kwargs['possible_receiving_modes'] = POSSIBLE_RECEIVING_MODES
kwargs['possible_credit_types'] = POSSIBLE_CREDIT_TYPES modes = list(POSSIBLE_RECEIVING_MODES)
types = list(POSSIBLE_CREDIT_TYPES)
if not self.batch_handler.allow_expired_credits():
if 'expired' in modes:
modes.remove('expired')
if 'expired' in types:
types.remove('expired')
kwargs['possible_receiving_modes'] = modes
kwargs['possible_credit_types'] = types
return kwargs return kwargs