diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py
index 9d92583e1a..b78fe1c2bf 100644
--- a/InvenTree/common/models.py
+++ b/InvenTree/common/models.py
@@ -212,6 +212,20 @@ class InvenTreeSetting(models.Model):
             'validator': bool,
         },
 
+        'PART_INTERNAL_PRICE': {
+            'name': _('Internal Prices'),
+            'description': _('Enable internal prices for parts'),
+            'default': False,
+            'validator': bool
+        },
+
+        'PART_BOM_USE_INTERNAL_PRICE': {
+            'name': _('Internal Price as BOM-Price'),
+            'description': _('Use the internal price (if set) in BOM-price calculations'),
+            'default': False,
+            'validator': bool
+        },
+
         'REPORT_DEBUG_MODE': {
             'name': _('Debug Mode'),
             'description': _('Generate reports in debug mode (HTML output)'),
@@ -733,7 +747,7 @@ class PriceBreak(models.Model):
         return converted.amount
 
 
-def get_price(instance, quantity, moq=True, multiples=True, currency=None):
+def get_price(instance, quantity, moq=True, multiples=True, currency=None, break_name: str = 'price_breaks'):
     """ Calculate the price based on quantity price breaks.
 
     - Don't forget to add in flat-fee cost (base_cost field)
@@ -741,7 +755,10 @@ def get_price(instance, quantity, moq=True, multiples=True, currency=None):
     - If order multiples are to be observed, then we need to calculate based on that, too
     """
 
-    price_breaks = instance.price_breaks.all()
+    if hasattr(instance, break_name):
+        price_breaks = getattr(instance, break_name).all()
+    else:
+        price_breaks = []
 
     # No price break information available?
     if len(price_breaks) == 0:
@@ -763,7 +780,7 @@ def get_price(instance, quantity, moq=True, multiples=True, currency=None):
         currency = currency_code_default()
 
     pb_min = None
-    for pb in instance.price_breaks.all():
+    for pb in price_breaks:
         # Store smallest price break
         if not pb_min:
             pb_min = pb
diff --git a/InvenTree/part/admin.py b/InvenTree/part/admin.py
index 3945b56d7c..637dbbf2cf 100644
--- a/InvenTree/part/admin.py
+++ b/InvenTree/part/admin.py
@@ -14,7 +14,7 @@ from .models import BomItem
 from .models import PartParameterTemplate, PartParameter
 from .models import PartCategoryParameterTemplate
 from .models import PartTestTemplate
-from .models import PartSellPriceBreak
+from .models import PartSellPriceBreak, PartInternalPriceBreak
 
 from stock.models import StockLocation
 from company.models import SupplierPart
@@ -286,6 +286,14 @@ class PartSellPriceBreakAdmin(admin.ModelAdmin):
     list_display = ('part', 'quantity', 'price',)
 
 
+class PartInternalPriceBreakAdmin(admin.ModelAdmin):
+
+    class Meta:
+        model = PartInternalPriceBreak
+
+    list_display = ('part', 'quantity', 'price',)
+
+
 admin.site.register(Part, PartAdmin)
 admin.site.register(PartCategory, PartCategoryAdmin)
 admin.site.register(PartRelated, PartRelatedAdmin)
@@ -297,3 +305,4 @@ admin.site.register(PartParameter, ParameterAdmin)
 admin.site.register(PartCategoryParameterTemplate, PartCategoryParameterAdmin)
 admin.site.register(PartTestTemplate, PartTestTemplateAdmin)
 admin.site.register(PartSellPriceBreak, PartSellPriceBreakAdmin)
+admin.site.register(PartInternalPriceBreak, PartInternalPriceBreakAdmin)
diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py
index 537b0f9e40..c2785b666f 100644
--- a/InvenTree/part/api.py
+++ b/InvenTree/part/api.py
@@ -25,7 +25,7 @@ from django.urls import reverse
 from .models import Part, PartCategory, BomItem
 from .models import PartParameter, PartParameterTemplate
 from .models import PartAttachment, PartTestTemplate
-from .models import PartSellPriceBreak
+from .models import PartSellPriceBreak, PartInternalPriceBreak
 from .models import PartCategoryParameterTemplate
 
 from common.models import InvenTreeSetting
@@ -194,6 +194,24 @@ class PartSalePriceList(generics.ListCreateAPIView):
     ]
 
 
+class PartInternalPriceList(generics.ListCreateAPIView):
+    """
+    API endpoint for list view of PartInternalPriceBreak model
+    """
+
+    queryset = PartInternalPriceBreak.objects.all()
+    serializer_class = part_serializers.PartInternalPriceSerializer
+    permission_required = 'roles.sales_order.show'
+
+    filter_backends = [
+        DjangoFilterBackend
+    ]
+
+    filter_fields = [
+        'part',
+    ]
+
+
 class PartAttachmentList(generics.ListCreateAPIView, AttachmentMixin):
     """
     API endpoint for listing (and creating) a PartAttachment (file upload).
@@ -1017,6 +1035,11 @@ part_api_urls = [
         url(r'^.*$', PartSalePriceList.as_view(), name='api-part-sale-price-list'),
     ])),
 
+    # Base URL for part internal pricing
+    url(r'^internal-price/', include([
+        url(r'^.*$', PartInternalPriceList.as_view(), name='api-part-internal-price-list'),
+    ])),
+
     # Base URL for PartParameter API endpoints
     url(r'^parameter/', include([
         url(r'^template/$', PartParameterTemplateList.as_view(), name='api-part-param-template-list'),
diff --git a/InvenTree/part/fixtures/part_pricebreaks.yaml b/InvenTree/part/fixtures/part_pricebreaks.yaml
new file mode 100644
index 0000000000..0fd14c84df
--- /dev/null
+++ b/InvenTree/part/fixtures/part_pricebreaks.yaml
@@ -0,0 +1,51 @@
+# Sell price breaks for parts
+
+# Price breaks for R_2K2_0805
+
+- model: part.partsellpricebreak
+  pk: 1
+  fields:
+    part: 3
+    quantity: 1
+    price: 0.15
+
+- model: part.partsellpricebreak
+  pk: 2
+  fields:
+    part: 3
+    quantity: 10
+    price: 0.10
+
+
+# Internal price breaks for parts
+
+# Internal Price breaks for R_2K2_0805
+
+- model: part.partinternalpricebreak
+  pk: 1
+  fields:
+    part: 3
+    quantity: 1
+    price: 0.08
+
+- model: part.partinternalpricebreak
+  pk: 2
+  fields:
+    part: 3
+    quantity: 10
+    price: 0.05
+
+# Internal Price breaks for C_22N_0805
+- model: part.partinternalpricebreak
+  pk: 3
+  fields:
+    part: 5
+    quantity: 1
+    price: 1
+
+- model: part.partinternalpricebreak
+  pk: 4
+  fields:
+    part: 5
+    quantity: 24
+    price: 0.5
diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py
index 95de4961f9..ec799bcf8d 100644
--- a/InvenTree/part/forms.py
+++ b/InvenTree/part/forms.py
@@ -20,7 +20,7 @@ from .models import BomItem
 from .models import PartParameterTemplate, PartParameter
 from .models import PartCategoryParameterTemplate
 from .models import PartTestTemplate
-from .models import PartSellPriceBreak
+from .models import PartSellPriceBreak, PartInternalPriceBreak
 
 
 class PartModelChoiceField(forms.ModelChoiceField):
@@ -394,3 +394,19 @@ class EditPartSalePriceBreakForm(HelperForm):
             'quantity',
             'price',
         ]
+
+
+class EditPartInternalPriceBreakForm(HelperForm):
+    """
+    Form for creating / editing a internal price for a part
+    """
+
+    quantity = RoundingDecimalFormField(max_digits=10, decimal_places=5, label=_('Quantity'))
+
+    class Meta:
+        model = PartInternalPriceBreak
+        fields = [
+            'part',
+            'quantity',
+            'price',
+        ]
diff --git a/InvenTree/part/migrations/0067_partinternalpricebreak.py b/InvenTree/part/migrations/0067_partinternalpricebreak.py
new file mode 100644
index 0000000000..f1b16fe87c
--- /dev/null
+++ b/InvenTree/part/migrations/0067_partinternalpricebreak.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.2 on 2021-06-05 14:13
+
+import InvenTree.fields
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+import djmoney.models.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('part', '0066_bomitem_allow_variants'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='PartInternalPriceBreak',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('quantity', InvenTree.fields.RoundingDecimalField(decimal_places=5, default=1, help_text='Price break quantity', max_digits=15, validators=[django.core.validators.MinValueValidator(1)], verbose_name='Quantity')),
+                ('price_currency', djmoney.models.fields.CurrencyField(choices=[('AUD', 'Australian Dollar'), ('CAD', 'Canadian Dollar'), ('EUR', 'Euro'), ('NZD', 'New Zealand Dollar'), ('GBP', 'Pound Sterling'), ('USD', 'US Dollar'), ('JPY', 'Yen')], default='USD', editable=False, max_length=3)),
+                ('price', djmoney.models.fields.MoneyField(decimal_places=4, default_currency='USD', help_text='Unit price at specified quantity', max_digits=19, null=True, verbose_name='Price')),
+                ('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='internalpricebreaks', to='part.part', verbose_name='Part')),
+            ],
+            options={
+                'unique_together': {('part', 'quantity')},
+            },
+        ),
+    ]
diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py
index 7b9038fecb..6c05d62a7e 100644
--- a/InvenTree/part/models.py
+++ b/InvenTree/part/models.py
@@ -1544,7 +1544,7 @@ class Part(MPTTModel):
 
         return (min_price, max_price)
 
-    def get_bom_price_range(self, quantity=1):
+    def get_bom_price_range(self, quantity=1, internal=False):
         """ Return the price range of the BOM for this part.
         Adds the minimum price for all components in the BOM.
 
@@ -1561,7 +1561,7 @@ class Part(MPTTModel):
                 print("Warning: Item contains itself in BOM")
                 continue
 
-            prices = item.sub_part.get_price_range(quantity * item.quantity)
+            prices = item.sub_part.get_price_range(quantity * item.quantity, internal=internal)
 
             if prices is None:
                 continue
@@ -1585,7 +1585,7 @@ class Part(MPTTModel):
 
         return (min_price, max_price)
 
-    def get_price_range(self, quantity=1, buy=True, bom=True):
+    def get_price_range(self, quantity=1, buy=True, bom=True, internal=False):
 
         """ Return the price range for this part. This price can be either:
 
@@ -1596,8 +1596,13 @@ class Part(MPTTModel):
             Minimum of the supplier price or BOM price. If no pricing available, returns None
         """
 
+        # only get internal price if set and should be used
+        if internal and self.has_internal_price_breaks:
+            internal_price = self.get_internal_price(quantity)
+            return internal_price, internal_price
+
         buy_price_range = self.get_supplier_price_range(quantity) if buy else None
-        bom_price_range = self.get_bom_price_range(quantity) if bom else None
+        bom_price_range = self.get_bom_price_range(quantity, internal=internal) if bom else None
 
         if buy_price_range is None:
             return bom_price_range
@@ -1649,6 +1654,22 @@ class Part(MPTTModel):
             price=price
         )
 
+    def get_internal_price(self, quantity, moq=True, multiples=True, currency=None):
+        return common.models.get_price(self, quantity, moq, multiples, currency, break_name='internal_price_breaks')
+
+    @property
+    def has_internal_price_breaks(self):
+        return self.internal_price_breaks.count() > 0
+
+    @property
+    def internal_price_breaks(self):
+        """ Return the associated price breaks in the correct order """
+        return self.internalpricebreaks.order_by('quantity').all()
+
+    @property
+    def internal_unit_pricing(self):
+        return self.get_internal_price(1)
+
     @transaction.atomic
     def copy_bom_from(self, other, clear=True, **kwargs):
         """
@@ -1983,6 +2004,21 @@ class PartSellPriceBreak(common.models.PriceBreak):
         unique_together = ('part', 'quantity')
 
 
+class PartInternalPriceBreak(common.models.PriceBreak):
+    """
+    Represents a price break for internally selling this part
+    """
+
+    part = models.ForeignKey(
+        Part, on_delete=models.CASCADE,
+        related_name='internalpricebreaks',
+        verbose_name=_('Part')
+    )
+
+    class Meta:
+        unique_together = ('part', 'quantity')
+
+
 class PartStar(models.Model):
     """ A PartStar object creates a relationship between a User and a Part.
 
diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py
index d03a37c6dc..76275bd5e1 100644
--- a/InvenTree/part/serializers.py
+++ b/InvenTree/part/serializers.py
@@ -17,7 +17,8 @@ from stock.models import StockItem
 
 from .models import (BomItem, Part, PartAttachment, PartCategory,
                      PartParameter, PartParameterTemplate, PartSellPriceBreak,
-                     PartStar, PartTestTemplate, PartCategoryParameterTemplate)
+                     PartStar, PartTestTemplate, PartCategoryParameterTemplate,
+                     PartInternalPriceBreak)
 
 
 class CategorySerializer(InvenTreeModelSerializer):
@@ -100,6 +101,25 @@ class PartSalePriceSerializer(InvenTreeModelSerializer):
         ]
 
 
+class PartInternalPriceSerializer(InvenTreeModelSerializer):
+    """
+    Serializer for internal prices for Part model.
+    """
+
+    quantity = serializers.FloatField()
+
+    price = serializers.CharField()
+
+    class Meta:
+        model = PartInternalPriceBreak
+        fields = [
+            'pk',
+            'part',
+            'quantity',
+            'price',
+        ]
+
+
 class PartThumbSerializer(serializers.Serializer):
     """
     Serializer for the 'image' field of the Part model.
diff --git a/InvenTree/part/templates/part/internal_prices.html b/InvenTree/part/templates/part/internal_prices.html
new file mode 100644
index 0000000000..2f54f3bb64
--- /dev/null
+++ b/InvenTree/part/templates/part/internal_prices.html
@@ -0,0 +1,122 @@
+{% extends "part/part_base.html" %}
+{% load static %}
+{% load i18n %}
+{% load inventree_extras %}
+
+{% block menubar %}
+{% include 'part/navbar.html' with tab='internal-prices' %}
+{% endblock %}
+
+{% block heading %}
+{% trans "Internal Price Information" %}
+{% endblock %}
+
+{% block details %}
+{% settings_value "PART_INTERNAL_PRICE" as show_internal_price %}
+{% if show_internal_price and roles.sales_order.view %}
+<div id='internal-price-break-toolbar' class='btn-group'>
+    <button class='btn btn-primary' id='new-internal-price-break' type='button'>
+        <span class='fas fa-plus-circle'></span> {% trans "Add Internal Price Break" %}
+    </button>
+</div>
+
+<table class='table table-striped table-condensed' id='internal-price-break-table' data-toolbar='#internal-price-break-toolbar'>
+</table>
+
+{% else %}
+<div class='container-fluid'>
+    <h3>{% trans "Permission Denied" %}</h3>
+
+    <div class='alert alert-danger alert-block'>
+        {% trans "You do not have permission to view this page." %}
+    </div>
+</div>
+{% endif %}
+{% endblock %}
+
+{% block js_ready %}
+{{ block.super }}
+
+{% settings_value "PART_INTERNAL_PRICE" as show_internal_price %}
+{% if show_internal_price and roles.sales_order.view %}
+function reloadPriceBreaks() {
+    $("#internal-price-break-table").bootstrapTable("refresh");
+}
+
+$('#new-internal-price-break').click(function() {
+    launchModalForm("{% url 'internal-price-break-create' %}",
+        {
+            success: reloadPriceBreaks,
+            data: {
+                part: {{ part.id }},
+            }
+        }
+    );
+});
+
+$('#internal-price-break-table').inventreeTable({
+    name: 'internalprice',
+    formatNoMatches: function() { return "{% trans 'No internal price break information found' %}"; },
+    queryParams: {
+        part: {{ part.id }},
+    },
+    url: "{% url 'api-part-internal-price-list' %}",
+    onPostBody: function() {
+        var table = $('#internal-price-break-table');
+
+        table.find('.button-internal-price-break-delete').click(function() {
+            var pk = $(this).attr('pk');
+
+            launchModalForm(
+                `/part/internal-price/${pk}/delete/`,
+                {
+                    success: reloadPriceBreaks
+                }
+            );
+        });
+
+        table.find('.button-internal-price-break-edit').click(function() {
+            var pk = $(this).attr('pk');
+
+            launchModalForm(
+                `/part/internal-price/${pk}/edit/`,
+                {
+                    success: reloadPriceBreaks
+                }
+            );
+        });
+    },
+    columns: [
+        {
+            field: 'pk',
+            title: 'ID',
+            visible: false,
+            switchable: false,
+        },
+        {
+            field: 'quantity',
+            title: '{% trans "Quantity" %}',
+            sortable: true,
+        },
+        {
+            field: 'price',
+            title: '{% trans "Price" %}',
+            sortable: true,
+            formatter: function(value, row, index) {
+                var html = value;
+
+                html += `<div class='btn-group float-right' role='group'>`
+
+                html += makeIconButton('fa-edit icon-blue', 'button-internal-price-break-edit', row.pk, '{% trans "Edit internal price break" %}');
+                html += makeIconButton('fa-trash-alt icon-red', 'button-internal-price-break-delete', row.pk, '{% trans "Delete internal price break" %}');
+
+                html += `</div>`;
+
+                return html;
+            }
+        },
+    ]
+})
+
+{% endif %}
+{% endblock %}
\ No newline at end of file
diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html
index d1ed7e3d21..c0bc4c96a3 100644
--- a/InvenTree/part/templates/part/navbar.html
+++ b/InvenTree/part/templates/part/navbar.html
@@ -2,6 +2,8 @@
 {% load static %}
 {% load inventree_extras %}
 
+{% settings_value "PART_INTERNAL_PRICE" as show_internal_price %}
+
 <ul class='list-group'>
     <li class='list-group-item'>
         <a href='#' id='part-menu-toggle'>
@@ -94,7 +96,13 @@
         </a>
     </li>
     {% endif %}
-    {% if part.salable and roles.sales_order.view %}
+    {% if show_internal_price and roles.sales_order.view %}
+    <li class='list-group-item {% if tab == "internal-prices" %}active{% endif %}' title='{% trans "Internal Price Information" %}'>
+        <a href='{% url "part-internal-prices" part.id %}'>
+            <span class='menu-tab-icon fas fa-dollar-sign' style='width: 20px;'></span>
+            {% trans "Internal Price" %}
+        </a>
+    </li>
     <li class='list-group-item {% if tab == "sales-prices" %}active{% endif %}' title='{% trans "Sales Price Information" %}'>
         <a href='{% url "part-sale-prices" part.id %}'>
             <span class='menu-tab-icon fas fa-dollar-sign sidebar-icon'></span>
diff --git a/InvenTree/part/templates/part/order_prices.html b/InvenTree/part/templates/part/order_prices.html
index f5af15afef..a9da632a33 100644
--- a/InvenTree/part/templates/part/order_prices.html
+++ b/InvenTree/part/templates/part/order_prices.html
@@ -14,6 +14,7 @@
 
 {% block details %}
 {% default_currency as currency %}
+{% settings_value "PART_INTERNAL_PRICE" as show_internal_price %}
 
 <form method="post" class="form-horizontal">
     {% csrf_token %}
@@ -86,6 +87,21 @@
     {% endif %}
 {% endif %}
 
+{% if show_internal_price and roles.sales_order.view %}
+{% if total_internal_part_price %}
+    <tr>
+        <td><b>{% trans 'Internal Price' %}</b></td>
+        <td>{% trans 'Unit Cost' %}</td>
+        <td colspan='2'>{% include "price.html" with price=unit_internal_part_price %}</td>
+    </tr>
+    <tr>
+        <td></td>
+        <td>{% trans 'Total Cost' %}</td>
+        <td colspan='2'>{% include "price.html" with price=total_internal_part_price %}</td>
+    </tr>
+{% endif %}
+{% endif %}
+
 {% if total_part_price %}
     <tr>
         <td><b>{% trans 'Sale Price' %}</b></td>
@@ -198,18 +214,18 @@ The part single price is the current purchase price for that supplier part."></i
             var bomdata = {
                 labels: [{% for line in bom_parts %}'{{ line.name }}',{% endfor %}],
                 datasets:  [
-                {% if bom_pie_min %}
+                {
+                  label: 'Price',
+                  data: [{% for line in bom_parts %}{{ line.min_price }},{% endfor %}],
+                  backgroundColor: bom_colors,
+                },
+                {% if bom_pie_max %}
                 {
                     label: 'Max Price',
                     data: [{% for line in bom_parts %}{{ line.max_price }},{% endfor %}],
                     backgroundColor: bom_colors,
                   },
                 {% endif %}
-                {
-                  label: 'Price',
-                  data: [{% for line in bom_parts %}{% if bom_pie_min %}{{ line.min_price }}{% else %}{{ line.price }}{% endif%},{% endfor %}],
-                  backgroundColor: bom_colors,
-                }
               ]
             };
             var BomChart = loadBomChart(document.getElementById('BomChart'), bomdata)
diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html
index e035a77162..ce55124bd9 100644
--- a/InvenTree/part/templates/part/part_pricing.html
+++ b/InvenTree/part/templates/part/part_pricing.html
@@ -3,7 +3,10 @@
 {% load i18n inventree_extras %}
 
 {% block pre_form_content %}
+
 {% default_currency as currency %}
+{% settings_value "PART_INTERNAL_PRICE" as show_internal_price %}
+
 <table class='table table-striped table-condensed table-price-two'>
     <tr>
         <td><b>{% trans 'Part' %}</b></td>
@@ -74,6 +77,22 @@
     </table>
 {% endif %}
 
+{% if show_internal_price and roles.sales_order.view %}
+{% if total_internal_part_price %}
+    <h4>{% trans 'Internal Price' %}</h4>
+    <table class='table table-striped table-condensed table-price-two'>
+        <tr>
+            <td><b>{% trans 'Unit Cost' %}</b></td>
+            <td>{% include "price.html" with price=unit_internal_part_price %}</td>
+        </tr>
+        <tr>
+            <td><b>{% trans 'Total Cost' %}</b></td>
+            <td>{% include "price.html" with price=total_internal_part_price %}</td>
+        </tr>
+    </table>
+{% endif %}
+{% endif %}
+
 {% if total_part_price %}
     <h4>{% trans 'Sale Price' %}</h4>
     <table class='table table-striped table-condensed table-price-two'>
diff --git a/InvenTree/part/test_bom_item.py b/InvenTree/part/test_bom_item.py
index 7e553be73a..66897b28fc 100644
--- a/InvenTree/part/test_bom_item.py
+++ b/InvenTree/part/test_bom_item.py
@@ -1,5 +1,6 @@
 from django.test import TestCase
 import django.core.exceptions as django_exceptions
+from decimal import Decimal
 
 from .models import Part, BomItem
 
@@ -11,11 +12,16 @@ class BomItemTest(TestCase):
         'part',
         'location',
         'bom',
+        'company',
+        'supplier_part',
+        'part_pricebreaks',
+        'price_breaks',
     ]
 
     def setUp(self):
         self.bob = Part.objects.get(id=100)
         self.orphan = Part.objects.get(name='Orphan')
+        self.r1 = Part.objects.get(name='R_2K2_0805')
 
     def test_str(self):
         b = BomItem.objects.get(id=1)
@@ -111,3 +117,10 @@ class BomItemTest(TestCase):
         item.validate_hash()
 
         self.assertNotEqual(h1, h2)
+
+    def test_pricing(self):
+        self.bob.get_price(1)
+        self.assertEqual(self.bob.get_bom_price_range(1, internal=True), (Decimal(84.5), Decimal(89.5)))
+        # remove internal price for R_2K2_0805
+        self.r1.internal_price_breaks.delete()
+        self.assertEqual(self.bob.get_bom_price_range(1, internal=True), (Decimal(82.5), Decimal(87.5)))
diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py
index cd8726ccf4..2bc24c3a99 100644
--- a/InvenTree/part/test_part.py
+++ b/InvenTree/part/test_part.py
@@ -51,6 +51,7 @@ class PartTest(TestCase):
         'category',
         'part',
         'location',
+        'part_pricebreaks'
     ]
 
     def setUp(self):
@@ -113,6 +114,22 @@ class PartTest(TestCase):
 
         self.assertTrue(len(matches) > 0)
 
+    def test_sell_pricing(self):
+        # check that the sell pricebreaks were loaded
+        self.assertTrue(self.r1.has_price_breaks)
+        self.assertEqual(self.r1.price_breaks.count(), 2)
+        # check that the sell pricebreaks work
+        self.assertEqual(float(self.r1.get_price(1)), 0.15)
+        self.assertEqual(float(self.r1.get_price(10)), 1.0)
+
+    def test_internal_pricing(self):
+        # check that the sell pricebreaks were loaded
+        self.assertTrue(self.r1.has_internal_price_breaks)
+        self.assertEqual(self.r1.internal_price_breaks.count(), 2)
+        # check that the sell pricebreaks work
+        self.assertEqual(float(self.r1.get_internal_price(1)), 0.08)
+        self.assertEqual(float(self.r1.get_internal_price(10)), 0.5)
+
 
 class TestTemplateTest(TestCase):
 
diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py
index e53ce54782..d12612c604 100644
--- a/InvenTree/part/urls.py
+++ b/InvenTree/part/urls.py
@@ -29,6 +29,12 @@ sale_price_break_urls = [
     url(r'^(?P<pk>\d+)/delete/', views.PartSalePriceBreakDelete.as_view(), name='sale-price-break-delete'),
 ]
 
+internal_price_break_urls = [
+    url(r'^new/', views.PartInternalPriceBreakCreate.as_view(), name='internal-price-break-create'),
+    url(r'^(?P<pk>\d+)/edit/', views.PartInternalPriceBreakEdit.as_view(), name='internal-price-break-edit'),
+    url(r'^(?P<pk>\d+)/delete/', views.PartInternalPriceBreakDelete.as_view(), name='internal-price-break-delete'),
+]
+
 part_parameter_urls = [
     url(r'^template/new/', views.PartParameterTemplateCreate.as_view(), name='part-param-template-create'),
     url(r'^template/(?P<pk>\d+)/edit/', views.PartParameterTemplateEdit.as_view(), name='part-param-template-edit'),
@@ -65,6 +71,7 @@ part_detail_urls = [
     url(r'^orders/?', views.PartDetail.as_view(template_name='part/orders.html'), name='part-orders'),
     url(r'^sales-orders/', views.PartDetail.as_view(template_name='part/sales_orders.html'), name='part-sales-orders'),
     url(r'^sale-prices/', views.PartDetail.as_view(template_name='part/sale_prices.html'), name='part-sale-prices'),
+    url(r'^internal-prices/', views.PartDetail.as_view(template_name='part/internal_prices.html'), name='part-internal-prices'),
     url(r'^tests/', views.PartDetail.as_view(template_name='part/part_tests.html'), name='part-test-templates'),
     url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'),
     url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'),
@@ -145,6 +152,9 @@ part_urls = [
     # Part price breaks
     url(r'^sale-price/', include(sale_price_break_urls)),
 
+    # Part internal price breaks
+    url(r'^internal-price/', include(internal_price_break_urls)),
+
     # Part test templates
     url(r'^test-template/', include([
         url(r'^new/', views.PartTestTemplateCreate.as_view(), name='part-test-template-create'),
diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py
index b4f33c9382..b68c889516 100644
--- a/InvenTree/part/views.py
+++ b/InvenTree/part/views.py
@@ -36,7 +36,7 @@ from .models import PartCategoryParameterTemplate
 from .models import BomItem
 from .models import match_part_names
 from .models import PartTestTemplate
-from .models import PartSellPriceBreak
+from .models import PartSellPriceBreak, PartInternalPriceBreak
 
 from common.models import InvenTreeSetting
 from company.models import SupplierPart
@@ -846,17 +846,26 @@ class PartPricingView(PartDetail):
             ctx['price_history'] = ret
 
         # BOM Information for Pie-Chart
-        bom_items = [{'name': str(a.sub_part), 'price': a.sub_part.get_price_range(quantity), 'q': a.quantity} for a in part.bom_items.all()]
-        if [True for a in bom_items if len(set(a['price'])) == 2]:
-            ctx['bom_parts'] = [{
-                'name': a['name'],
-                'min_price': str((a['price'][0] * a['q']) / quantity),
-                'max_price': str((a['price'][1] * a['q']) / quantity)} for a in bom_items]
-            ctx['bom_pie_min'] = True
-        else:
-            ctx['bom_parts'] = [{
-                'name': a['name'],
-                'price': str((a['price'][0] * a['q']) / quantity)} for a in bom_items]
+        if part.has_bom:
+            ctx_bom_parts = []
+            # iterate over all bom-items
+            for item in part.bom_items.all():
+                ctx_item = {'name': str(item.sub_part)}
+                price, qty = item.sub_part.get_price_range(quantity), item.quantity
+
+                price_min, price_max = 0, 0
+                if price:  # check if price available
+                    price_min = str((price[0] * qty) / quantity)
+                    if len(set(price)) == 2:  # min and max-price present
+                        price_max = str((price[1] * qty) / quantity)
+                        ctx['bom_pie_max'] = True  # enable showing max prices in bom
+
+                ctx_item['max_price'] = price_min
+                ctx_item['min_price'] = price_max if price_max else price_min
+                ctx_bom_parts.append(ctx_item)
+
+            # add to global context
+            ctx['bom_parts'] = ctx_bom_parts
 
         return ctx
 
@@ -2105,7 +2114,8 @@ class PartPricing(AjaxView):
         # BOM pricing information
         if part.bom_count > 0:
 
-            bom_price = part.get_bom_price_range(quantity)
+            use_internal = InvenTreeSetting.get_setting('PART_BOM_USE_INTERNAL_PRICE', False)
+            bom_price = part.get_bom_price_range(quantity, internal=use_internal)
 
             if bom_price is not None:
                 min_bom_price, max_bom_price = bom_price
@@ -2127,6 +2137,12 @@ class PartPricing(AjaxView):
                     ctx['max_total_bom_price'] = max_bom_price
                     ctx['max_unit_bom_price'] = max_unit_bom_price
 
+        # internal part pricing information
+        internal_part_price = part.get_internal_price(quantity)
+        if internal_part_price is not None:
+            ctx['total_internal_part_price'] = round(internal_part_price, 3)
+            ctx['unit_internal_part_price'] = round(internal_part_price / quantity, 3)
+
         # part pricing information
         part_price = part.get_price(quantity)
         if part_price is not None:
@@ -2794,3 +2810,29 @@ class PartSalePriceBreakDelete(AjaxDeleteView):
     model = PartSellPriceBreak
     ajax_form_title = _("Delete Price Break")
     ajax_template_name = "modal_delete_form.html"
+
+
+class PartInternalPriceBreakCreate(PartSalePriceBreakCreate):
+    """ View for creating a internal price break for a part """
+
+    model = PartInternalPriceBreak
+    form_class = part_forms.EditPartInternalPriceBreakForm
+    ajax_form_title = _('Add Internal Price Break')
+    permission_required = 'roles.sales_order.add'
+
+
+class PartInternalPriceBreakEdit(PartSalePriceBreakEdit):
+    """ View for editing a internal price break """
+
+    model = PartInternalPriceBreak
+    form_class = part_forms.EditPartInternalPriceBreakForm
+    ajax_form_title = _('Edit Internal Price Break')
+    permission_required = 'roles.sales_order.change'
+
+
+class PartInternalPriceBreakDelete(PartSalePriceBreakDelete):
+    """ View for deleting a internal price break """
+
+    model = PartInternalPriceBreak
+    ajax_form_title = _("Delete Internal Price Break")
+    permission_required = 'roles.sales_order.delete'
diff --git a/InvenTree/templates/InvenTree/settings/part.html b/InvenTree/templates/InvenTree/settings/part.html
index cb4726bdc4..1bf5f8794a 100644
--- a/InvenTree/templates/InvenTree/settings/part.html
+++ b/InvenTree/templates/InvenTree/settings/part.html
@@ -35,6 +35,9 @@
         {% include "InvenTree/settings/setting.html" with key="PART_COPY_PARAMETERS" %}
         {% include "InvenTree/settings/setting.html" with key="PART_COPY_TESTS" %}
         {% include "InvenTree/settings/setting.html" with key="PART_CATEGORY_PARAMETERS" %}
+        <tr><td colspan='5'></td></tr>
+        {% include "InvenTree/settings/setting.html" with key="PART_INTERNAL_PRICE" %}
+        {% include "InvenTree/settings/setting.html" with key="PART_BOM_USE_INTERNAL_PRICE" %}
     </tbody>
 </table>
 
diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py
index f26a7ee64b..0902b04ccd 100644
--- a/InvenTree/users/models.py
+++ b/InvenTree/users/models.py
@@ -77,6 +77,7 @@ class RuleSet(models.Model):
             'part_bomitem',
             'part_partattachment',
             'part_partsellpricebreak',
+            'part_partinternalpricebreak',
             'part_parttesttemplate',
             'part_partparametertemplate',
             'part_partparameter',