<${form.component} ref="mainForm"
+                       % if master.has_perm('confirm_price'):
+                       @confirm-price="showConfirmPrice"
+                       % endif
                        % if master.has_perm('change_status'):
                        @change-status="showChangeStatus"
                        % endif
@@ -18,6 +21,45 @@
 <%def name="page_content()">
   ${parent.page_content()}
 
+  % if master.has_perm('confirm_price'):
+      
+      ${h.form(master.get_action_url('confirm_price', instance), ref='confirmPriceForm')}
+      ${h.csrf_token(request)}
+      ${h.hidden('note', **{':value': 'confirmPriceNote'})}
+      ${h.end_form()}
+  % endif
+
   % if master.has_perm('change_status'):
       
         
@@ -190,6 +232,41 @@
 
     ${form.component_studly}Data.notesData = ${json.dumps(notes_data)|n}
 
+    % if master.has_perm('confirm_price'):
+
+        ThisPageData.confirmPriceShowDialog = false
+        ThisPageData.confirmPriceNote = null
+        ThisPageData.confirmPriceSubmitting = false
+
+        ThisPage.computed.confirmPriceSaveDisabled = function() {
+            if (this.confirmPriceSubmitting) {
+                return true
+            }
+            return false
+        }
+
+        ThisPage.computed.confirmPriceSubmitText = function() {
+            if (this.confirmPriceSubmitting) {
+                return "Working, please wait..."
+            }
+            return "Confirm Price"
+        }
+
+        ThisPage.methods.showConfirmPrice = function() {
+            this.confirmPriceNote = null
+            this.confirmPriceShowDialog = true
+            this.$nextTick(() => {
+                this.$refs.confirmPriceNoteField.focus()
+            })
+        }
+
+        ThisPage.methods.confirmPriceSave = function() {
+            this.confirmPriceSubmitting = true
+            this.$refs.confirmPriceForm.submit()
+        }
+
+    % endif
+
     % if master.has_perm('change_status'):
 
         ThisPageData.orderItemStatuses = ${json.dumps(enum.CUSTORDER_ITEM_STATUS)|n}
diff --git a/tailbone/views/custorders/items.py b/tailbone/views/custorders/items.py
index 2dcd43a5..737b1c20 100644
--- a/tailbone/views/custorders/items.py
+++ b/tailbone/views/custorders/items.py
@@ -98,6 +98,7 @@ class CustomerOrderItemView(MasterView):
         'case_quantity',
         'unit_price',
         'total_price',
+        'price_needs_confirmation',
         'paid_amount',
         'status_code',
         'notes',
@@ -135,7 +136,7 @@ class CustomerOrderItemView(MasterView):
         g.set_renderer('person', self.render_person_text)
         g.set_renderer('order_created', self.render_order_created)
 
-        g.set_enum('status_code', self.enum.CUSTORDER_ITEM_STATUS)
+        g.set_renderer('status_code', self.render_status_code_column)
 
         g.set_label('person', "Person Name")
         g.set_label('product_brand', "Brand")
@@ -160,6 +161,13 @@ class CustomerOrderItemView(MasterView):
         value = localtime(self.rattail_config, item.order.created, from_utc=True)
         return raw_datetime(self.rattail_config, value)
 
+    def render_status_code_column(self, item, field):
+        text = self.enum.CUSTORDER_ITEM_STATUS.get(item.status_code,
+                                                   six.text_type(item.status_code))
+        if item.status_text:
+            return HTML.tag('span', title=item.status_text, c=[text])
+        return text
+
     def configure_form(self, f):
         super(CustomerOrderItemView, self).configure_form(f)
         use_buefy = self.get_use_buefy()
@@ -178,12 +186,12 @@ class CustomerOrderItemView(MasterView):
         f.set_type('cases_ordered', 'quantity')
         f.set_type('units_ordered', 'quantity')
         f.set_type('order_quantity', 'quantity')
-
         f.set_enum('order_uom', self.enum.UNIT_OF_MEASURE)
 
-        # currency fields
-        f.set_type('unit_price', 'currency')
-        f.set_type('total_price', 'currency')
+        # price fields
+        f.set_renderer('unit_price', self.render_price_with_confirmation)
+        f.set_renderer('total_price', self.render_price_with_confirmation)
+        f.set_renderer('price_needs_confirmation', self.render_price_needs_confirmation)
         f.set_type('paid_amount', 'currency')
 
         # person
@@ -198,9 +206,37 @@ class CustomerOrderItemView(MasterView):
         else:
             f.remove('notes')
 
+    def render_price_with_confirmation(self, item, field):
+        price = getattr(item, field)
+        app = self.get_rattail_app()
+        text = app.render_currency(price)
+        if item.price_needs_confirmation:
+            return HTML.tag('span', class_='has-background-warning',
+                            c=[text])
+        return text
+
+    def render_price_needs_confirmation(self, item, field):
+
+        value = item.price_needs_confirmation
+        text = "Yes" if value else "No"
+        items = [text]
+
+        if value and self.has_perm('confirm_price'):
+            button = HTML.tag('b-button', type='is-primary', c="Confirm Price",
+                              style='margin-left: 1rem;',
+                              icon_pack='fas', icon_left='check',
+                              **{'@click': "$emit('confirm-price')"})
+            items.append(button)
+
+        left = HTML.tag('div', class_='level-left', c=items)
+        outer = HTML.tag('div', class_='level', c=[left])
+        return outer
+
     def render_status_code(self, item, field):
         use_buefy = self.get_use_buefy()
         text = self.enum.CUSTORDER_ITEM_STATUS[item.status_code]
+        if item.status_text:
+            text = "{} ({})".format(text, item.status_text)
         items = [HTML.tag('span', c=[text])]
 
         if use_buefy and self.has_perm('change_status'):
@@ -298,6 +334,32 @@ class CustomerOrderItemView(MasterView):
             })
         return notes
 
+    def confirm_price(self):
+        """
+        View for confirming price of an order item.
+        """
+        item = self.get_instance()
+        redirect = self.redirect(self.get_action_url('view', item))
+
+        # locate user responsible for change
+        user = self.request.user
+
+        # grab user-provided note to attach to event
+        note = self.request.POST.get('note')
+
+        # declare item no longer in need of price confirmation
+        item.price_needs_confirmation = False
+        item.add_event(self.enum.CUSTORDER_ITEM_EVENT_PRICE_CONFIRMED,
+                       user, note=note)
+
+        # advance item to next status
+        if item.status_code == self.enum.CUSTORDER_ITEM_STATUS_INITIATED:
+            item.status_code = self.enum.CUSTORDER_ITEM_STATUS_READY
+            item.status_text = "price has been confirmed"
+
+        self.request.session.flash("Price has been confirmed.")
+        return redirect
+
     def change_status(self):
         """
         View for changing status of one or more order items.
@@ -342,6 +404,9 @@ class CustomerOrderItemView(MasterView):
 
                 # change status
                 item.status_code = new_status_code
+                # nb. must blank this out, b/c user cannot specify new
+                # text and the old text no longer applies
+                item.status_text = None
 
         self.request.session.flash("Status has been updated to: {}".format(
             self.enum.CUSTORDER_ITEM_STATUS[new_status_code]))
@@ -418,11 +483,23 @@ class CustomerOrderItemView(MasterView):
         route_prefix = cls.get_route_prefix()
         instance_url_prefix = cls.get_instance_url_prefix()
         permission_prefix = cls.get_permission_prefix()
+        model_title = cls.get_model_title()
         model_title_plural = cls.get_model_title_plural()
 
         # fix permission group name
         config.add_tailbone_permission_group(permission_prefix, model_title_plural)
 
+        # confirm price
+        config.add_tailbone_permission(permission_prefix,
+                                       '{}.confirm_price'.format(permission_prefix),
+                                       "Confirm price for a {}".format(model_title))
+        config.add_route('{}.confirm_price'.format(route_prefix),
+                         '{}/confirm-price'.format(instance_url_prefix),
+                         request_method='POST')
+        config.add_view(cls, attr='confirm_price',
+                        route_name='{}.confirm_price'.format(route_prefix),
+                        permission='{}.confirm_price'.format(permission_prefix))
+
         # change status
         config.add_tailbone_permission(permission_prefix,
                                        '{}.change_status'.format(permission_prefix),
diff --git a/tailbone/views/custorders/orders.py b/tailbone/views/custorders/orders.py
index 0b72f377..0153126a 100644
--- a/tailbone/views/custorders/orders.py
+++ b/tailbone/views/custorders/orders.py
@@ -36,7 +36,7 @@ from rattail.db import model
 from rattail.util import pretty_quantity
 from rattail.batch import get_batch_handler
 
-from webhelpers2.html import tags
+from webhelpers2.html import tags, HTML
 
 from tailbone.db import Session
 from tailbone.views import MasterView
@@ -189,10 +189,10 @@ class CustomerOrderView(MasterView):
         g.set_type('order_quantity', 'quantity')
         g.set_type('cases_ordered', 'quantity')
         g.set_type('units_ordered', 'quantity')
-        g.set_type('total_price', 'currency')
+        g.set_renderer('total_price', self.render_price_with_confirmation)
 
         g.set_enum('order_uom', self.enum.UNIT_OF_MEASURE)
-        g.set_enum('status_code', self.enum.CUSTORDER_ITEM_STATUS)
+        g.set_renderer('status_code', self.render_row_status_code)
 
         g.set_label('sequence', "Seq.")
         g.filters['sequence'].label = "Sequence"
@@ -206,6 +206,22 @@ class CustomerOrderView(MasterView):
         g.set_link('product_brand')
         g.set_link('product_description')
 
+    def render_price_with_confirmation(self, item, field):
+        price = getattr(item, field)
+        app = self.get_rattail_app()
+        text = app.render_currency(price)
+        if item.price_needs_confirmation:
+            return HTML.tag('span', class_='has-background-warning',
+                            c=[text])
+        return text
+
+    def render_row_status_code(self, item, field):
+        text = self.enum.CUSTORDER_ITEM_STATUS.get(item.status_code,
+                                                   six.text_type(item.status_code))
+        if item.status_text:
+            return HTML.tag('span', title=item.status_text, c=[text])
+        return text
+
     def get_batch_handler(self):
         return get_batch_handler(
             self.rattail_config, 'custorder',
@@ -641,6 +657,7 @@ class CustomerOrderView(MasterView):
             'unit_price_display': "${:0.2f}".format(row.unit_price) if row.unit_price is not None else None,
             'total_price': six.text_type(row.total_price) if row.total_price is not None else None,
             'total_price_display': "${:0.2f}".format(row.total_price) if row.total_price is not None else None,
+            'price_needs_confirmation': row.price_needs_confirmation,
 
             'status_code': row.status_code,
             'status_text': row.status_text,
@@ -684,7 +701,8 @@ class CustomerOrderView(MasterView):
 
             row = self.handler.add_product(batch, product,
                                            decimal.Decimal(data.get('order_quantity') or '0'),
-                                           data.get('order_uom'))
+                                           data.get('order_uom'),
+                                           price_needs_confirmation=data.get('price_needs_confirmation'))
             self.Session.flush()
 
         else: # product is not known
@@ -719,6 +737,7 @@ class CustomerOrderView(MasterView):
             row.product = product
             row.order_quantity = decimal.Decimal(data.get('order_quantity') or '0')
             row.order_uom = data.get('order_uom')
+            row.price_needs_confirmation = data.get('price_needs_confirmation')
             self.handler.refresh_row(row)
             self.Session.flush()
             self.Session.refresh(row)