Add basic per-item discount support for custorders

This commit is contained in:
Lance Edgar 2022-09-06 16:31:59 -05:00
parent b37f63a231
commit 2950827c63
3 changed files with 82 additions and 2 deletions

View file

@ -88,6 +88,15 @@
</b-checkbox> </b-checkbox>
</b-field> </b-field>
<b-field>
<b-checkbox name="rattail.custorders.allow_item_discounts"
v-model="simpleSettings['rattail.custorders.allow_item_discounts']"
native-value="true"
@input="settingsNeedSaved = true">
Allow per-item discounts
</b-checkbox>
</b-field>
</div> </div>
</%def> </%def>

View file

@ -805,7 +805,21 @@
</b-field> </b-field>
<b-field grouped> <b-field grouped>
<b-field label="Total Price"> % if allow_item_discounts:
<b-field label="Discount" horizontal>
<div class="level">
<div class="level-item">
<numeric-input v-model="productDiscountPercent"
style="width: 5rem;">
</numeric-input>
</div>
<div class="level-item">
<span>&nbsp;%</span>
</div>
</div>
</b-field>
% endif
<b-field label="Total Price" horizontal expanded>
<span :class="productSalePriceDisplay ? 'has-background-warning': null"> <span :class="productSalePriceDisplay ? 'has-background-warning': null">
{{ getItemTotalPriceDisplay() }} {{ getItemTotalPriceDisplay() }}
</span> </span>
@ -981,6 +995,12 @@
</span> </span>
</b-table-column> </b-table-column>
% if allow_item_discounts:
<b-table-column label="Discount">
{{ props.row.discount_percent }}{{ props.row.discount_percent ? " %" : "" }}
</b-table-column>
% endif
<b-table-column label="Total"> <b-table-column label="Total">
<span <span
% if product_price_may_be_questionable: % if product_price_may_be_questionable:
@ -1099,6 +1119,7 @@
items: ${json.dumps(order_items)|n}, items: ${json.dumps(order_items)|n},
editingItem: null, editingItem: null,
showingItemDialog: false, showingItemDialog: false,
itemDialogSaving: false,
itemDialogTabIndex: 0, itemDialogTabIndex: 0,
pastItemsShowDialog: false, pastItemsShowDialog: false,
pastItemsLoading: false, pastItemsLoading: false,
@ -1133,6 +1154,10 @@
productPriceNeedsConfirmation: false, productPriceNeedsConfirmation: false,
% endif % endif
% if allow_item_discounts:
productDiscountPercent: null,
% endif
pendingProduct: {}, pendingProduct: {},
departmentOptions: ${json.dumps(department_options)|n}, departmentOptions: ${json.dumps(department_options)|n},
@ -1314,6 +1339,9 @@
}, },
itemDialogSaveDisabled() { itemDialogSaveDisabled() {
if (this.itemDialogSaving) {
return true
}
if (this.productIsKnown) { if (this.productIsKnown) {
if (!this.productUUID) { if (!this.productUUID) {
return true return true
@ -1330,6 +1358,9 @@
}, },
itemDialogSaveButtonText() { itemDialogSaveButtonText() {
if (this.itemDialogSaving) {
return "Working, please wait..."
}
return this.editingItem ? "Update Item" : "Add Item" return this.editingItem ? "Update Item" : "Add Item"
}, },
@ -1723,6 +1754,11 @@
if (basePrice) { if (basePrice) {
let totalPrice = basePrice * this.productQuantity let totalPrice = basePrice * this.productQuantity
if (totalPrice) { if (totalPrice) {
% if allow_item_discounts:
if (this.productDiscountPercent) {
totalPrice *= (100 - this.productDiscountPercent) / 100
}
% endif
totalPrice = totalPrice.toFixed(2) totalPrice = totalPrice.toFixed(2)
return "$" + totalPrice return "$" + totalPrice
} }
@ -1790,6 +1826,10 @@
this.productPriceNeedsConfirmation = false this.productPriceNeedsConfirmation = false
% endif % endif
% if allow_item_discounts:
this.productDiscountPercent = null
% endif
this.itemDialogTabIndex = 0 this.itemDialogTabIndex = 0
this.showingItemDialog = true this.showingItemDialog = true
this.$nextTick(() => { this.$nextTick(() => {
@ -1882,6 +1922,10 @@
this.productUnitChoices = row.order_uom_choices this.productUnitChoices = row.order_uom_choices
this.productUOM = row.order_uom this.productUOM = row.order_uom
% if allow_item_discounts:
this.productDiscountPercent = row.discount_percent
% endif
this.itemDialogTabIndex = 1 this.itemDialogTabIndex = 1
this.showingItemDialog = true this.showingItemDialog = true
}, },
@ -1992,6 +2036,7 @@
}, },
itemDialogSave() { itemDialogSave() {
this.itemDialogSaving = true
let params = { let params = {
product_is_known: this.productIsKnown, product_is_known: this.productIsKnown,
@ -2002,6 +2047,10 @@
order_uom: this.productUOM, order_uom: this.productUOM,
} }
% if allow_item_discounts:
params.discount_percent = this.productDiscountPercent
% endif
if (this.productIsKnown) { if (this.productIsKnown) {
params.product_uuid = this.productUUID params.product_uuid = this.productUUID
} else { } else {
@ -2032,6 +2081,7 @@
// also update the batch total price // also update the batch total price
this.batchTotalPriceDisplay = response.data.batch.total_price_display this.batchTotalPriceDisplay = response.data.batch.total_price_display
this.itemDialogSaving = false
this.showingItemDialog = false this.showingItemDialog = false
}) })
}, },

View file

@ -348,6 +348,7 @@ class CustomerOrderView(MasterView):
'department_options': self.get_department_options(), 'department_options': self.get_department_options(),
'default_uom_choices': self.batch_handler.uom_choices_for_product(None), 'default_uom_choices': self.batch_handler.uom_choices_for_product(None),
'default_uom': None, 'default_uom': None,
'allow_item_discounts': self.batch_handler.allow_item_discounts(),
}) })
if self.batch_handler.allow_case_orders(): if self.batch_handler.allow_case_orders():
@ -695,6 +696,7 @@ class CustomerOrderView(MasterView):
'order_quantity': pretty_quantity(row.order_quantity), 'order_quantity': pretty_quantity(row.order_quantity),
'order_uom': row.order_uom, 'order_uom': row.order_uom,
'order_uom_choices': self.uom_choices_for_row(row), 'order_uom_choices': self.uom_choices_for_row(row),
'discount_percent': pretty_quantity(row.discount_percent),
'department_display': row.department_name, 'department_display': row.department_name,
@ -807,6 +809,7 @@ class CustomerOrderView(MasterView):
order_quantity = decimal.Decimal(data.get('order_quantity') or '0') order_quantity = decimal.Decimal(data.get('order_quantity') or '0')
order_uom = data.get('order_uom') order_uom = data.get('order_uom')
discount_percent = decimal.Decimal(data.get('discount_percent') or '0')
if data.get('product_is_known'): if data.get('product_is_known'):
@ -822,6 +825,9 @@ class CustomerOrderView(MasterView):
if self.batch_handler.product_price_may_be_questionable(): if self.batch_handler.product_price_may_be_questionable():
kwargs['price_needs_confirmation'] = data.get('price_needs_confirmation') kwargs['price_needs_confirmation'] = data.get('price_needs_confirmation')
if self.batch_handler.allow_item_discounts():
kwargs['discount_percent'] = discount_percent
row = self.batch_handler.add_product(batch, product, row = self.batch_handler.add_product(batch, product,
order_quantity, order_uom, order_quantity, order_uom,
**kwargs) **kwargs)
@ -838,9 +844,14 @@ class CustomerOrderView(MasterView):
pending_info['user'] = self.request.user pending_info['user'] = self.request.user
kwargs = {}
if self.batch_handler.allow_item_discounts():
kwargs['discount_percent'] = discount_percent
row = self.batch_handler.add_pending_product(batch, row = self.batch_handler.add_pending_product(batch,
pending_info, pending_info,
order_quantity, order_uom) order_quantity, order_uom,
**kwargs)
self.Session.flush() self.Session.flush()
return {'batch': self.normalize_batch(batch), return {'batch': self.normalize_batch(batch),
@ -860,6 +871,7 @@ class CustomerOrderView(MasterView):
order_quantity = decimal.Decimal(data.get('order_quantity') or '0') order_quantity = decimal.Decimal(data.get('order_quantity') or '0')
order_uom = data.get('order_uom') order_uom = data.get('order_uom')
discount_percent = decimal.Decimal(data.get('discount_percent') or '0')
if data.get('product_is_known'): if data.get('product_is_known'):
@ -879,6 +891,9 @@ class CustomerOrderView(MasterView):
if self.batch_handler.product_price_may_be_questionable(): if self.batch_handler.product_price_may_be_questionable():
row.price_needs_confirmation = data.get('price_needs_confirmation') row.price_needs_confirmation = data.get('price_needs_confirmation')
if self.batch_handler.allow_item_discounts():
row.discount_percent = discount_percent
self.batch_handler.refresh_row(row) self.batch_handler.refresh_row(row)
else: # product is not known else: # product is not known
@ -887,6 +902,9 @@ class CustomerOrderView(MasterView):
row.order_quantity = order_quantity row.order_quantity = order_quantity
row.order_uom = order_uom row.order_uom = order_uom
if self.batch_handler.allow_item_discounts():
row.discount_percent = discount_percent
# nb. this will refresh the row # nb. this will refresh the row
pending_info = dict(data['pending_product']) pending_info = dict(data['pending_product'])
self.batch_handler.update_pending_product(row, pending_info) self.batch_handler.update_pending_product(row, pending_info)
@ -965,6 +983,9 @@ class CustomerOrderView(MasterView):
{'section': 'rattail.custorders', {'section': 'rattail.custorders',
'option': 'allow_unknown_product', 'option': 'allow_unknown_product',
'type': bool}, 'type': bool},
{'section': 'rattail.custorders',
'option': 'allow_item_discounts',
'type': bool},
] ]
@classmethod @classmethod