Merge pull request #1811 from SchrodingersGat/spa

Dynamically switch between navbar selections on pages
This commit is contained in:
Oliver 2021-07-15 23:43:43 +10:00 committed by GitHub
commit bb60eed897
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
102 changed files with 3867 additions and 4997 deletions

View File

@ -781,7 +781,7 @@ input[type="submit"] {
}
.sidenav .list-group-item.active {
background-color: #ddd;
background-color: #b3a997;
border-color: #ccc;
}
@ -912,6 +912,10 @@ input[type="submit"] {
box-shadow: 1px 1px #DDD;
}
.panel-hidden {
display: none;
}
.float-right {
float: right;
}

View File

@ -4678,7 +4678,7 @@ input[type="submit"].btn.btn-mini {
.navbar .btn-navbar:active,
.navbar .btn-navbar.active {
background-color: #cccccc \9;
background-color: #ba8;
}
.navbar .btn-navbar .icon-bar {

View File

@ -104,22 +104,23 @@ settings_urls = [
dynamic_javascript_urls = [
url(r'^api.js', DynamicJsView.as_view(template_name='js/api.js'), name='api.js'),
url(r'^attachment.js', DynamicJsView.as_view(template_name='js/attachment.js'), name='attachment.js'),
url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'),
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'),
url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'),
url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'),
url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'),
url(r'^build.js', DynamicJsView.as_view(template_name='js/build.js'), name='build.js'),
url(r'^calendar.js', DynamicJsView.as_view(template_name='js/calendar.js'), name='calendar.js'),
url(r'^company.js', DynamicJsView.as_view(template_name='js/company.js'), name='company.js'),
url(r'^filters.js', DynamicJsView.as_view(template_name='js/filters.js'), name='filters.js'),
url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'),
url(r'^label.js', DynamicJsView.as_view(template_name='js/label.js'), name='label.js'),
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'),
url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'),
url(r'^nav.js', DynamicJsView.as_view(template_name='js/nav.js'), name='nav.js'),
url(r'^order.js', DynamicJsView.as_view(template_name='js/order.js'), name='order.js'),
url(r'^part.js', DynamicJsView.as_view(template_name='js/part.js'), name='part.js'),
url(r'^label.js', DynamicJsView.as_view(template_name='js/label.js'), name='label.js'),
url(r'^report.js', DynamicJsView.as_view(template_name='js/report.js'), name='report.js'),
url(r'^stock.js', DynamicJsView.as_view(template_name='js/stock.js'), name='stock.js'),
url(r'^tables.js', DynamicJsView.as_view(template_name='js/tables.js'), name='tables.js'),
url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/table_filters.js'), name='table_filters.js'),
url(r'^filters.js', DynamicJsView.as_view(template_name='js/filters.js'), name='filters.js'),
]
urlpatterns = [

View File

@ -68,10 +68,6 @@ class BuildList(generics.ListCreateAPIView):
filters.OrderingFilter,
]
filter_fields = [
'sales_order',
]
ordering_fields = [
'reference',
'part__name',
@ -114,6 +110,12 @@ class BuildList(generics.ListCreateAPIView):
if parent is not None:
queryset = queryset.filter(parent=parent)
# Filter by sales_order
sales_order = params.get('sales_order', None)
if sales_order is not None:
queryset = queryset.filter(sales_order=sales_order)
# Filter by "ancestor" builds
ancestor = params.get('ancestor', None)

View File

@ -1,101 +0,0 @@
{% extends "build/build_base.html" %}
{% load static %}
{% load i18n %}
{% load inventree_extras %}
{% block page_title %}
{% inventree_title %} | {% trans "Allocate Parts" %}
{% endblock %}
{% block menubar %}
{% include "build/navbar.html" with tab='allocate' %}
{% endblock %}
{% block heading %}
{% trans "Allocate Stock to Build" %}
{% endblock %}
{% block details %}
{% if build.has_untracked_bom_items %}
{% if build.active %}
<div class='btn-group' role='group'>
<button class='btn btn-success' type='button' id='btn-auto-allocate' title='{% trans "Allocate stock to build" %}'>
<span class='fas fa-magic'></span> {% trans "Auto Allocate" %}
</button>
<button class='btn btn-danger' type='button' id='btn-unallocate' title='{% trans "Unallocate stock" %}'>
<span class='fas fa-minus-circle'></span> {% trans "Unallocate Stock" %}
</button>
<!--
<button class='btn btn-primary' type='button' id='btn-order-parts' title='{% trans "Order required parts" %}'>
<span class='fas fa-shopping-cart'></span> {% trans "Order Parts" %}
</button>
-->
</div>
{% if build.areUntrackedPartsFullyAllocated %}
<div class='alert alert-block alert-success'>
{% trans "Untracked stock has been fully allocated for this Build Order" %}
</div>
{% else %}
<div class='alert alert-block alert-danger'>
{% trans "Untracked stock has not been fully allocated for this Build Order" %}
</div>
{% endif %}
{% endif %}
<table class='table table-striped table-condensed' id='allocation-table-untracked'></table>
{% else %}
<div class='alert alert-block alert-info'>
{% trans "This Build Order does not have any associated untracked BOM items" %}
</div>
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
var buildInfo = {
pk: {{ build.pk }},
quantity: {{ build.quantity }},
completed: {{ build.completed }},
part: {{ build.part.pk }},
};
{% if build.has_untracked_bom_items %}
// Load allocation table for un-tracked parts
loadBuildOutputAllocationTable(buildInfo, null);
{% endif %}
function reloadTable() {
$('#allocation-table-untracked').bootstrapTable('refresh');
}
{% if build.active %}
$("#btn-auto-allocate").on('click', function() {
launchModalForm(
"{% url 'build-auto-allocate' build.id %}",
{
success: reloadTable,
}
);
});
$('#btn-unallocate').on('click', function() {
launchModalForm(
"{% url 'build-unallocate' build.id %}",
{
success: reloadTable,
}
);
});
$("#btn-order-parts").click(function() {
launchModalForm("/order/purchase-order/order-parts/", {
data: {
build: {{ build.id }},
},
});
});
{% endif %}
{% endblock %}

View File

@ -1,84 +0,0 @@
{% extends "build/build_base.html" %}
{% load static %}
{% load i18n %}
{% load markdownify %}
{% block menubar %}
{% include "build/navbar.html" with tab='attachments' %}
{% endblock %}
{% block heading %}
{% trans "Attachments" %}
{% endblock %}
{% block details %}
{% include "attachment_table.html" with attachments=build.attachments.all %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableDragAndDrop(
'#attachment-dropzone',
'{% url "api-build-attachment-list" %}',
{
data: {
build: {{ build.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
location.reload();
}
}
);
// Callback for creating a new attachment
$('#new-attachment').click(function() {
constructForm('{% url "api-build-attachment-list" %}', {
fields: {
attachment: {},
comment: {},
build: {
value: {{ build.pk }},
hidden: true,
}
},
method: 'POST',
onSuccess: reloadAttachmentTable,
title: '{% trans "Add Attachment" %}',
});
});
loadAttachmentTable(
'{% url "api-build-attachment-list" %}',
{
filters: {
build: {{ build.pk }},
},
onEdit: function(pk) {
var url = `/api/build/attachment/${pk}/`;
constructForm(url, {
fields: {
comment: {},
},
onSuccess: reloadAttachmentTable,
title: '{% trans "Edit Attachment" %}',
});
},
onDelete: function(pk) {
constructForm(`/api/build/attachment/${pk}/`, {
method: 'DELETE',
confirmMessage: '{% trans "Confirm Delete Operation" %}',
title: '{% trans "Delete Attachment" %}',
onSuccess: reloadAttachmentTable,
});
}
}
);
{% endblock %}

View File

@ -126,7 +126,7 @@ src="{% static 'img/blank_image.png' %}"
<tr>
<td><span class='fas fa-shapes'></span></td>
<td>{% trans "Part" %}</td>
<td><a href="{% url 'part-detail' build.part.id %}">{{ build.part.full_name }}</a></td>
<td><a href="{% url 'part-detail' build.part.id %}?display=build-orders">{{ build.part.full_name }}</a></td>
</tr>
<tr>
<td></td>
@ -238,4 +238,10 @@ src="{% static 'img/blank_image.png' %}"
);
});
attachNavCallbacks({
name: 'buildorder',
default: 'details'
});
{% endblock %}

View File

@ -1,40 +0,0 @@
{% extends "build/build_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "build/navbar.html" with tab="children" %}
{% endblock %}
{% block heading %}
{% trans "Child Build Orders" %}
{% endblock %}
{% block details %}
<div id='button-toolbar'>
<div class='button-toolbar container-fluid float-right'>
<div class='filter-list' id='filter-list-sub-build'>
<!-- Empty div for filters -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' id='sub-build-table' data-toolbar='#button-toolbar'></table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadBuildTable($('#sub-build-table'), {
url: '{% url "api-build-list" %}',
filterTarget: "#filter-list-sub-build",
params: {
ancestor: {{ build.pk }},
}
});
{% endblock %}

View File

@ -1,103 +0,0 @@
{% extends "build/build_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "build/navbar.html" with tab='output' %}
{% endblock %}
{% block content_panels %}
{% if not build.is_complete %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>
{% trans "Incomplete Build Outputs" %}
</h4>
</div>
<div class='panel-content'>
<div class='btn-group' role='group'>
{% if build.active %}
<button class='btn btn-primary' type='button' id='btn-create-output' title='{% trans "Create new build output" %}'>
<span class='fas fa-plus-circle'></span> {% trans "Create New Output" %}
</button>
{% endif %}
</div>
{% if build.incomplete_outputs %}
<div class="panel-group" id="build-output-accordion" role="tablist" aria-multiselectable="true">
{% for item in build.incomplete_outputs %}
{% include "build/allocation_card.html" with item=item tracked_items=build.has_tracked_bom_items %}
{% endfor %}
</div>
{% else %}
<div class='alert alert-block alert-info'>
<b>{% trans "Create a new build output" %}</b><br>
{% trans "No incomplete build outputs remain." %}<br>
{% trans "Create a new build output using the button above" %}
</div>
{% endif %}
</div>
</div>
{% endif %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>
{% trans "Completed Build Outputs" %}
</h4>
</div>
<div class='panel-content'>
{% include "stock_table.html" with read_only=True %}
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
$('#btn-create-output').click(function() {
launchModalForm('{% url "build-output-create" build.id %}',
{
reload: true,
}
);
});
loadStockTable($("#stock-table"), {
params: {
location_detail: true,
part_detail: true,
build: {{ build.id }},
},
groupByField: 'location',
buttons: [
'#stock-options',
],
url: "{% url 'api-stock-list' %}",
});
var buildInfo = {
pk: {{ build.pk }},
quantity: {{ build.quantity }},
completed: {{ build.completed }},
part: {{ build.part.pk }},
};
{% for item in build.incomplete_outputs %}
// Get the build output as a javascript object
inventreeGet('{% url 'api-stock-detail' item.pk %}', {},
{
success: function(response) {
loadBuildOutputAllocationTable(buildInfo, response);
}
}
);
{% endfor %}
{% endblock %}

View File

@ -2,142 +2,446 @@
{% load static %}
{% load i18n %}
{% load status_codes %}
{% load markdownify %}
{% block menubar %}
{% include "build/navbar.html" with tab='details' %}
{% include "build/navbar.html" %}
{% endblock %}
{% block heading %}
{% trans "Build Details" %}
{% endblock %}
{% block page_content %}
{% block details %}
<div class='row'>
<div class='col-sm-6'>
<table class='table table-striped'>
<col width='25'>
<tr>
<td><span class='fas fa-info'></span></td>
<td>{% trans "Description" %}</td>
<td>{{ build.title }}{% include "clip.html"%}</td>
</tr>
<tr>
<td><span class='fas fa-shapes'></span></td>
<td>{% trans "Part" %}</td>
<td><a href="{% url 'part-build' build.part.id %}">{{ build.part.full_name }}</a>{% include "clip.html"%}</td>
</tr>
<tr>
<td></td>
<td>{% trans "Quantity" %}</td><td>{{ build.quantity }}</td>
</tr>
<tr>
<td><span class='fas fa-map-marker-alt'></span></td>
<td>{% trans "Stock Source" %}</td>
<td>
{% if build.take_from %}
<a href="{% url 'stock-location-detail' build.take_from.id %}">{{ build.take_from }}</a>{% include "clip.html"%}
{% else %}
<i>{% trans "Stock can be taken from any available location." %}</i>
{% endif %}
</td>
</tr>
<tr>
<td><span class='fas fa-map-marker-alt'></span></td>
<td>{% trans "Destination" %}</td>
<td>
{% if build.destination %}
<a href="{% url 'stock-location-detail' build.destination.id %}">
{{ build.destination }}
</a>{% include "clip.html"%}
{% else %}
<i>{% trans "Destination location not specified" %}</i>
{% endif %}
</td>
</tr>
<tr>
<td><span class='fas fa-info'></span></td>
<td>{% trans "Status" %}</td>
<td>{% build_status_label build.status %}</td>
</tr>
<tr>
<td><span class='fas fa-spinner'></span></td>
<td>{% trans "Progress" %}</td>
<td>{{ build.completed }} / {{ build.quantity }}</td>
</tr>
{% if build.batch %}
<tr>
<td><span class='fas fa-layer-group'></span></td>
<td>{% trans "Batch" %}</td>
<td>{{ build.batch }}{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if build.parent %}
<tr>
<td><span class='fas fa-sitemap'></span></td>
<td>{% trans "Parent Build" %}</td>
<td><a href="{% url 'build-detail' build.parent.id %}">{{ build.parent }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if build.sales_order %}
<tr>
<td><span class='fas fa-dolly'></span></td>
<td>{% trans "Sales Order" %}</td>
<td><a href="{% url 'so-detail' build.sales_order.id %}">{{ build.sales_order }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if build.link %}
<tr>
<td><span class='fas fa-link'></span></td>
<td>{% trans "External Link" %}</td>
<td><a href="{{ build.link }}">{{ build.link }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if build.issued_by %}
<tr>
<td><span class='fas fa-user'></span></td>
<td>{% trans "Issued By" %}</td>
<td>{{ build.issued_by }}</td>
</tr>
{% endif %}
{% if build.responsible %}
<tr>
<td><span class='fas fa-users'></span></td>
<td>{% trans "Responsible" %}</td>
<td>{{ build.responsible }}</td>
</tr>
{% endif %}
</table>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-details'>
<div class='panel-heading'>
<h4>{% trans "Build Details" %}</h4>
</div>
<div class='col-sm-6'>
<table class='table table-striped'>
<col width='25'>
<tr>
<td><span class='fas fa-calendar-alt'></span></td>
<td>{% trans "Created" %}</td>
<td>{{ build.creation_date }}</td>
</tr>
<tr>
<td><span class='fas fa-calendar-alt'></span></td>
<td>{% trans "Target Date" %}</td>
{% if build.target_date %}
<td>
{{ build.target_date }}{% if build.is_overdue %} <span class='fas fa-calendar-times icon-red'></span>{% endif %}
</td>
{% else %}
<td><i>{% trans "No target date set" %}</i></td>
<div class='panel-content'>
<div class='row'>
<div class='col-sm-6'>
<table class='table table-striped'>
<col width='25'>
<tr>
<td><span class='fas fa-info'></span></td>
<td>{% trans "Description" %}</td>
<td>{{ build.title }}{% include "clip.html"%}</td>
</tr>
<tr>
<td><span class='fas fa-shapes'></span></td>
<td>{% trans "Part" %}</td>
<td><a href="{% url 'part-detail' build.part.id %}?display=build-orders">{{ build.part.full_name }}</a>{% include "clip.html"%}</td>
</tr>
<tr>
<td></td>
<td>{% trans "Quantity" %}</td><td>{{ build.quantity }}</td>
</tr>
<tr>
<td><span class='fas fa-map-marker-alt'></span></td>
<td>{% trans "Stock Source" %}</td>
<td>
{% if build.take_from %}
<a href="{% url 'stock-location-detail' build.take_from.id %}">{{ build.take_from }}</a>{% include "clip.html"%}
{% else %}
<i>{% trans "Stock can be taken from any available location." %}</i>
{% endif %}
</td>
</tr>
<tr>
<td><span class='fas fa-map-marker-alt'></span></td>
<td>{% trans "Destination" %}</td>
<td>
{% if build.destination %}
<a href="{% url 'stock-location-detail' build.destination.id %}">
{{ build.destination }}
</a>{% include "clip.html"%}
{% else %}
<i>{% trans "Destination location not specified" %}</i>
{% endif %}
</td>
</tr>
<tr>
<td><span class='fas fa-info'></span></td>
<td>{% trans "Status" %}</td>
<td>{% build_status_label build.status %}</td>
</tr>
<tr>
<td><span class='fas fa-spinner'></span></td>
<td>{% trans "Progress" %}</td>
<td>{{ build.completed }} / {{ build.quantity }}</td>
</tr>
{% if build.batch %}
<tr>
<td><span class='fas fa-layer-group'></span></td>
<td>{% trans "Batch" %}</td>
<td>{{ build.batch }}{% include "clip.html"%}</td>
</tr>
{% endif %}
</tr>
<tr>
<td><span class='fas fa-calendar-alt'></span></td>
<td>{% trans "Completed" %}</td>
{% if build.completion_date %}
<td>{{ build.completion_date }}{% if build.completed_by %}<span class='badge'>{{ build.completed_by }}</span>{% endif %}</td>
{% else %}
<td><i>{% trans "Build not complete" %}</i></td>
{% if build.parent %}
<tr>
<td><span class='fas fa-sitemap'></span></td>
<td>{% trans "Parent Build" %}</td>
<td><a href="{% url 'build-detail' build.parent.id %}">{{ build.parent }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
</tr>
</table>
{% if build.sales_order %}
<tr>
<td><span class='fas fa-dolly'></span></td>
<td>{% trans "Sales Order" %}</td>
<td><a href="{% url 'so-detail' build.sales_order.id %}">{{ build.sales_order }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if build.link %}
<tr>
<td><span class='fas fa-link'></span></td>
<td>{% trans "External Link" %}</td>
<td><a href="{{ build.link }}">{{ build.link }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if build.issued_by %}
<tr>
<td><span class='fas fa-user'></span></td>
<td>{% trans "Issued By" %}</td>
<td>{{ build.issued_by }}</td>
</tr>
{% endif %}
{% if build.responsible %}
<tr>
<td><span class='fas fa-users'></span></td>
<td>{% trans "Responsible" %}</td>
<td>{{ build.responsible }}</td>
</tr>
{% endif %}
</table>
</div>
<div class='col-sm-6'>
<table class='table table-striped'>
<col width='25'>
<tr>
<td><span class='fas fa-calendar-alt'></span></td>
<td>{% trans "Created" %}</td>
<td>{{ build.creation_date }}</td>
</tr>
<tr>
<td><span class='fas fa-calendar-alt'></span></td>
<td>{% trans "Target Date" %}</td>
{% if build.target_date %}
<td>
{{ build.target_date }}{% if build.is_overdue %} <span class='fas fa-calendar-times icon-red'></span>{% endif %}
</td>
{% else %}
<td><i>{% trans "No target date set" %}</i></td>
{% endif %}
</tr>
<tr>
<td><span class='fas fa-calendar-alt'></span></td>
<td>{% trans "Completed" %}</td>
{% if build.completion_date %}
<td>{{ build.completion_date }}{% if build.completed_by %}<span class='badge'>{{ build.completed_by }}</span>{% endif %}</td>
{% else %}
<td><i>{% trans "Build not complete" %}</i></td>
{% endif %}
</tr>
</table>
</div>
</div>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-children'>
<div class='panel-heading'>
<h4>{% trans "Child Build Orders" %}</h4>
</div>
<div class='panel-content'>
<div id='child-button-toolbar'>
<div class='button-toolbar container-fluid float-right'>
<div class='filter-list' id='filter-list-sub-build'>
<!-- Empty div for filters -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' id='sub-build-table' data-toolbar='#child-button-toolbar'></table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-allocate'>
<div class='panel-heading'>
<h4>{% trans "Allocate Stock to Build" %}</h4>
</div>
<div class='panel-content'>
{% if build.has_untracked_bom_items %}
{% if build.active %}
<div class='btn-group' role='group'>
<button class='btn btn-success' type='button' id='btn-auto-allocate' title='{% trans "Allocate stock to build" %}'>
<span class='fas fa-magic'></span> {% trans "Auto Allocate" %}
</button>
<button class='btn btn-danger' type='button' id='btn-unallocate' title='{% trans "Unallocate stock" %}'>
<span class='fas fa-minus-circle'></span> {% trans "Unallocate Stock" %}
</button>
<!--
<button class='btn btn-primary' type='button' id='btn-order-parts' title='{% trans "Order required parts" %}'>
<span class='fas fa-shopping-cart'></span> {% trans "Order Parts" %}
</button>
-->
</div>
{% if build.areUntrackedPartsFullyAllocated %}
<div class='alert alert-block alert-success'>
{% trans "Untracked stock has been fully allocated for this Build Order" %}
</div>
{% else %}
<div class='alert alert-block alert-danger'>
{% trans "Untracked stock has not been fully allocated for this Build Order" %}
</div>
{% endif %}
{% endif %}
<table class='table table-striped table-condensed' id='allocation-table-untracked'></table>
{% else %}
<div class='alert alert-block alert-info'>
{% trans "This Build Order does not have any associated untracked BOM items" %}
</div>
{% endif %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-outputs'>
{% if not build.is_complete %}
<div class='panel-heading'>
<h4>{% trans "Incomplete Build Outputs" %}</h4>
</div>
<div class='panel-content'>
<div class='btn-group' role='group'>
{% if build.active %}
<button class='btn btn-primary' type='button' id='btn-create-output' title='{% trans "Create new build output" %}'>
<span class='fas fa-plus-circle'></span> {% trans "Create New Output" %}
</button>
{% endif %}
</div>
{% if build.incomplete_outputs %}
<div class="panel-group" id="build-output-accordion" role="tablist" aria-multiselectable="true">
{% for item in build.incomplete_outputs %}
{% include "build/allocation_card.html" with item=item tracked_items=build.has_tracked_bom_items %}
{% endfor %}
</div>
{% else %}
<div class='alert alert-block alert-info'>
<b>{% trans "Create a new build output" %}</b><br>
{% trans "No incomplete build outputs remain." %}<br>
{% trans "Create a new build output using the button above" %}
</div>
{% endif %}
</div>
{% endif %}
<div class='panel-heading'>
<h4>
{% trans "Completed Build Outputs" %}
</h4>
</div>
<div class='panel-content'>
{% include "stock_table.html" with read_only=True prefix="build-" %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-attachments'>
<div class='panel-heading'>
<h4>{% trans "Attachments" %}</h4>
</div>
<div class='panel-content'>
{% include "attachment_table.html" %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-notes'>
<div class='panel-heading'>
<div class='row'>
<div class='col-sm-6'>
<h4>{% trans "Build Notes" %}</h4>
</div>
<div class='col-sm-6'>
<div class='btn-group float-right'>
<button type='button' id='edit-notes' title='{% trans "Edit Notes" %}' class='btn btn-small btn-default'>
<span class='fas fa-edit'>
</span>
</button>
</div>
</div>
</div>
</div>
<div class='panel-content'>
{% if build.notes %}
{{ build.notes | markdownify }}
{% endif %}
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
$('#btn-create-output').click(function() {
launchModalForm('{% url "build-output-create" build.id %}',
{
reload: true,
}
);
});
loadStockTable($("#build-stock-table"), {
params: {
location_detail: true,
part_detail: true,
build: {{ build.id }},
},
groupByField: 'location',
buttons: [
'#stock-options',
],
url: "{% url 'api-stock-list' %}",
});
var buildInfo = {
pk: {{ build.pk }},
quantity: {{ build.quantity }},
completed: {{ build.completed }},
part: {{ build.part.pk }},
};
{% for item in build.incomplete_outputs %}
// Get the build output as a javascript object
inventreeGet('{% url 'api-stock-detail' item.pk %}', {},
{
success: function(response) {
loadBuildOutputAllocationTable(buildInfo, response);
}
}
);
{% endfor %}
loadBuildTable($('#sub-build-table'), {
url: '{% url "api-build-list" %}',
filterTarget: "#filter-list-sub-build",
params: {
ancestor: {{ build.pk }},
}
});
enableDragAndDrop(
'#attachment-dropzone',
'{% url "api-build-attachment-list" %}',
{
data: {
build: {{ build.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
location.reload();
}
}
);
// Callback for creating a new attachment
$('#new-attachment').click(function() {
constructForm('{% url "api-build-attachment-list" %}', {
fields: {
attachment: {},
comment: {},
build: {
value: {{ build.pk }},
hidden: true,
}
},
method: 'POST',
onSuccess: reloadAttachmentTable,
title: '{% trans "Add Attachment" %}',
});
});
loadAttachmentTable(
'{% url "api-build-attachment-list" %}',
{
filters: {
build: {{ build.pk }},
},
onEdit: function(pk) {
var url = `/api/build/attachment/${pk}/`;
constructForm(url, {
fields: {
comment: {},
},
onSuccess: reloadAttachmentTable,
title: '{% trans "Edit Attachment" %}',
});
},
onDelete: function(pk) {
constructForm(`/api/build/attachment/${pk}/`, {
method: 'DELETE',
confirmMessage: '{% trans "Confirm Delete Operation" %}',
title: '{% trans "Delete Attachment" %}',
onSuccess: reloadAttachmentTable,
});
}
}
);
$('#edit-notes').click(function() {
constructForm('{% url "api-build-detail" build.pk %}', {
fields: {
notes: {
multiline: true,
}
},
title: '{% trans "Edit Notes" %}',
reload: true,
});
});
var buildInfo = {
pk: {{ build.pk }},
quantity: {{ build.quantity }},
completed: {{ build.completed }},
part: {{ build.part.pk }},
};
{% if build.has_untracked_bom_items %}
// Load allocation table for un-tracked parts
loadBuildOutputAllocationTable(buildInfo, null);
{% endif %}
function reloadTable() {
$('#allocation-table-untracked').bootstrapTable('refresh');
}
{% if build.active %}
$("#btn-auto-allocate").on('click', function() {
launchModalForm(
"{% url 'build-auto-allocate' build.id %}",
{
success: reloadTable,
}
);
});
$('#btn-unallocate').on('click', function() {
launchModalForm(
"{% url 'build-unallocate' build.id %}",
{
success: reloadTable,
}
);
});
$("#btn-order-parts").click(function() {
launchModalForm("/order/purchase-order/order-parts/", {
data: {
build: {{ build.id }},
},
});
});
{% endif %}
{% endblock %}

View File

@ -9,46 +9,45 @@
</a>
</li>
<li class='list-group-item {% if tab == "details" %}active{% endif %}' title='{% trans "Build Order Details" %}'>
<a href='{% url "build-detail" build.id %}'>
<li class='list-group-item' title='{% trans "Build Order Details" %}'>
<a href='#' id='select-details' class='nav-toggle'>
<span class='fas fa-info-circle sidebar-icon'></span>
{% trans "Details" %}
</a>
</li>
{% if build.active %}
<li class='list-group-item {% if tab == "allocate" %}active{% endif %}' title='{% trans "Allocate Stock" %}'>
<a href='{% url "build-allocate" build.id %}'>
<li class='list-group-item' title='{% trans "Allocate Stock" %}'>
<a href='#' id='select-allocate' class='nav-toggle'>
<span class='fas fa-tools sidebar-icon'></span>
{% trans "Allocate Stock" %}
</a>
</li>
{% endif %}
<li class='list-group-item {% if tab == "output" %}active{% endif %}' title='{% trans "Build Outputs" %}'>
<a href='{% url "build-output" build.id %}'>
<li class='list-group-item' title='{% trans "Build Outputs" %}'>
<a href='#' id='select-outputs' class='nav-toggle'>
<span class='fas fa-box sidebar-icon'></span>
{% trans "Build Outputs" %}
</a>
</li>
<li class='list-group-item {% if tab == "children" %}active{% endif %}' title='{% trans "Child Build Orders" %}'>
<a href='{% url "build-children" build.id %}'>
<li class='list-group-item' title='{% trans "Child Build Orders" %}'>
<a href='#' id='select-children' class='nav-toggle'>
<span class='fas fa-sitemap sidebar-icon'></span>
{% trans "Child Builds" %}
</a>
</li>
<li class='list-group-item {% if tab == "attachments" %}active{% endif %}' title='{% trans "Attachments" %}'>
<a href='{% url "build-attachments" build.id %}'>
<li class='list-group-item' title='{% trans "Attachments" %}'>
<a href='#' id='select-attachments' class='nav-toggle'>
<span class='fas fa-paperclip sidebar-icon'></span>
{% trans "Attachments" %}
</a>
</li>
<li class='list-group-item {% if tab == "notes" %}active{% endif %}' title='{% trans "Build Order Notes" %}'>
<a href='{% url "build-notes" build.id %}'>
<li class='list-group-item' title='{% trans "Build Order Notes" %}'>
<a href='#' id='select-notes' class='nav-toggle'>
<span class='fas fa-clipboard sidebar-icon'></span>
{% trans "Notes" %}
</a>

View File

@ -1,49 +0,0 @@
{% extends "build/build_base.html" %}
{% load static %}
{% load i18n %}
{% load markdownify %}
{% block menubar %}
{% include "build/navbar.html" with tab='notes' %}
{% endblock %}
{% block heading %}
{% trans "Build Notes" %}
{% if roles.build.change and not editing %}
<button title='{% trans "Edit notes" %}' class='btn btn-default' id='edit-notes'><span class='fas fa-edit'></span></button>
{% endif %}
{% endblock %}
{% block details %}
{% if editing %}
<hr>
<form method='POST'>
{% csrf_token %}
{{ form }}
<hr>
<button type="submit" class='btn btn-default'>{% trans "Save" %}</button>
</form>
{{ form.media }}
{% else %}
{{ build.notes | markdownify }}
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% if editing %}
{% else %}
$("#edit-notes").click(function() {
location.href = "{% url 'build-notes' build.id %}?edit=1";
});
{% endif %}
{% endblock %}

View File

@ -252,19 +252,6 @@ class TestBuildViews(TestCase):
self.assertIn(build.title, content)
def test_build_allocate(self):
""" Test the part allocation view for a Build """
url = reverse('build-allocate', args=(1,))
# Get the page normally
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
# Get the page in editing mode
response = self.client.get(url, {'edit': 1})
self.assertEqual(response.status_code, 200)
def test_build_item_create(self):
""" Test the BuildItem creation view (ajax form) """

View File

@ -7,30 +7,23 @@ from django.conf.urls import url, include
from . import views
build_detail_urls = [
url(r'^allocate/', views.BuildAllocate.as_view(), name='build-allocate'),
url(r'^cancel/', views.BuildCancel.as_view(), name='build-cancel'),
url(r'^delete/', views.BuildDelete.as_view(), name='build-delete'),
url(r'^create-output/', views.BuildOutputCreate.as_view(), name='build-output-create'),
url(r'^delete-output/', views.BuildOutputDelete.as_view(), name='build-output-delete'),
url(r'^complete-output/?', views.BuildOutputComplete.as_view(), name='build-output-complete'),
url(r'^auto-allocate/?', views.BuildAutoAllocate.as_view(), name='build-auto-allocate'),
url(r'^complete-output/', views.BuildOutputComplete.as_view(), name='build-output-complete'),
url(r'^auto-allocate/', views.BuildAutoAllocate.as_view(), name='build-auto-allocate'),
url(r'^unallocate/', views.BuildUnallocate.as_view(), name='build-unallocate'),
url(r'^complete/', views.BuildComplete.as_view(), name='build-complete'),
url(r'^notes/', views.BuildNotes.as_view(), name='build-notes'),
url(r'^children/', views.BuildDetail.as_view(template_name='build/build_children.html'), name='build-children'),
url(r'^attachments/', views.BuildDetail.as_view(template_name='build/attachments.html'), name='build-attachments'),
url(r'^output/', views.BuildDetail.as_view(template_name='build/build_output.html'), name='build-output'),
url(r'^.*$', views.BuildDetail.as_view(), name='build-detail'),
]
build_urls = [
url(r'item/', include([
url(r'^(?P<pk>\d+)/', include([
url('^edit/?', views.BuildItemEdit.as_view(), name='build-item-edit'),
url('^delete/?', views.BuildItemDelete.as_view(), name='build-item-delete'),
url('^edit/', views.BuildItemEdit.as_view(), name='build-item-edit'),
url('^delete/', views.BuildItemDelete.as_view(), name='build-item-delete'),
])),
url('^new/', views.BuildItemCreate.as_view(), name='build-item-create'),
])),

View File

@ -7,9 +7,8 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
from django.views.generic import DetailView, ListView, UpdateView
from django.views.generic import DetailView, ListView
from django.forms import HiddenInput
from django.urls import reverse
from part.models import Part
from .models import Build, BuildItem
@ -593,31 +592,6 @@ class BuildOutputComplete(AjaxUpdateView):
}
class BuildNotes(InvenTreeRoleMixin, UpdateView):
""" View for editing the 'notes' field of a Build object.
"""
context_object_name = 'build'
template_name = 'build/notes.html'
model = Build
# Override the default permission role for this View
role_required = 'build.view'
fields = ['notes']
def get_success_url(self):
return reverse('build-notes', kwargs={'pk': self.get_object().id})
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['editing'] = str2bool(self.request.GET.get('edit', ''))
return ctx
class BuildDetail(InvenTreeRoleMixin, DetailView):
""" Detail view of a single Build object. """
@ -635,36 +609,15 @@ class BuildDetail(InvenTreeRoleMixin, DetailView):
ctx['BuildStatus'] = BuildStatus
ctx['sub_build_count'] = build.sub_build_count()
return ctx
class BuildAllocate(InvenTreeRoleMixin, DetailView):
""" View for allocating parts to a Build """
model = Build
context_object_name = 'build'
template_name = 'build/allocate.html'
def get_context_data(self, **kwargs):
""" Provide extra context information for the Build allocation page """
context = super(DetailView, self).get_context_data(**kwargs)
build = self.get_object()
part = build.part
bom_items = build.bom_items
context['part'] = part
context['bom_items'] = bom_items
context['has_tracked_bom_items'] = build.has_tracked_bom_items()
context['has_untracked_bom_items'] = build.has_untracked_bom_items()
context['BuildStatus'] = BuildStatus
ctx['part'] = part
ctx['bom_items'] = bom_items
ctx['has_tracked_bom_items'] = build.has_tracked_bom_items()
ctx['has_untracked_bom_items'] = build.has_untracked_bom_items()
context['bom_price'] = build.part.get_price_info(build.quantity, buy=False)
if str2bool(self.request.GET.get('edit', None)):
context['editing'] = True
return context
return ctx
class BuildDelete(AjaxDeleteView):

View File

@ -99,13 +99,18 @@ class FileManager:
self.update_headers()
def guess_header(self, header, threshold=80):
""" Try to match a header (from the file) to a list of known headers
"""
Try to match a header (from the file) to a list of known headers
Args:
header - Header name to look for
threshold - Match threshold for fuzzy search
"""
# Replace null values with empty string
if header is None:
header = ''
# Try for an exact match
for h in self.HEADERS:
if h == header:

View File

@ -1,38 +0,0 @@
{% extends "company/company_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "company/navbar.html" with tab="assigned" %}
{% endblock %}
{% block heading %}
{% trans "Assigned Stock" %}
{% endblock %}
{% block details %}
<div id='button-toolbar'>
<div class='filter-list' id='filter-list-stock'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
<table class='table table-striped table-condensed' id='stock-table' data-toolbar='#button-toolbar'></table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadStockTable($("#stock-table"), {
params: {
customer: {{ company.id }},
part_detail: true,
location_detail: true,
},
url: "{% url 'api-stock-list' %}",
filterKey: "customerstock",
});
{% endblock %}

View File

@ -71,6 +71,17 @@
<td><a href="{{ company.website }}">{{ company.website }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
<tr>
<td><span class='fas fa-dollar-sign'></span></td>
<td>{% trans "Currency" %}</td>
<td>
{% if company.currency %}
{{ company.currency }}
{% else %}
<i>{% trans "Uses default currency" %}</i>
{% endif %}
</td>
</tr>
{% if company.address %}
<tr>
<td><span class='fas fa-map-marked-alt'></span></td>
@ -99,6 +110,22 @@
<td>{{ company.contact }}{% include "clip.html"%}</td>
</tr>
{% endif %}
<tr>
<td><span class='fas fa-industry'></span></td>
<td>{%trans "Manufacturer" %}</td>
<td>{% include "yesnolabel.html" with value=company.is_manufacturer %}</td>
</tr>
<tr>
<td><span class='fas fa-building'></span></td>
<td>{% trans "Supplier" %}</td>
<td>{% include 'yesnolabel.html' with value=company.is_supplier %}</td>
</tr>
<tr>
<td><span class='fas fa-user-tie'></span></td>
<td>{% trans "Customer" %}</td>
<td>{% include 'yesnolabel.html' with value=company.is_customer %}</td>
</tr>
</table>
{% endblock %}

View File

@ -1,79 +1,432 @@
{% extends "company/company_base.html" %}
{% load static %}
{% load i18n %}
{% load markdownify %}
{% block menubar %}
{% include 'company/navbar.html' with tab='details' %}
{% endblock %}
{% block heading %}
{% trans "Company Details" %}
{% endblock %}
{% block page_content %}
{% block details %}
<div class='row'>
<div class='col-sm-6'>
<table class='table table-striped'>
<col width='25'>
<col>
<tr>
<td><span class='fas fa-font'></span></td>
<td>{% trans "Company Name" %}</td>
<td>{{ company.name }}{% include "clip.html"%}</td>
</tr>
{% if company.description %}
<tr>
<td><span class='fas fa-info'></span></td>
<td>{% trans "Description" %}</td>
<td>{{ company.description }}{% include "clip.html"%}</td>
</tr>
{% endif %}
<tr>
<td><span class='fas fa-globe'></span></td>
<td>{% trans "Website" %}</td>
<td>
{% if company.website %}<a href='{{ company.website }}'>{{ company.website }}</a>{% include "clip.html"%}
{% else %}<i>{% trans "No website specified" %}</i>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-supplier-parts'>
<div class='panel-heading'>
<h4>{% trans "Supplier Parts" %}</h4>
</div>
<div class='panel-content'>
{% if roles.purchase_order.change %}
<div id='supplier-part-button-toolbar'>
<div class='button-toolbar container-fluid'>
<div class='btn-group' role='group'>
{% if roles.purchase_order.add %}
<button class="btn btn-success" id='supplier-part-create' title='{% trans "Create new supplier part" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Supplier Part" %}
</button>
{% endif %}
</td>
</tr>
<tr>
<td><span class='fas fa-dollar-sign'></span></td>
<td>{% trans "Currency" %}</td>
<td>
{% if company.currency %}{{ company.currency }}
{% else %}<i>{% trans "Uses default currency" %}</i>
{% endif %}
</td>
</tr>
<div class='btn-group'>
<div class="dropdown" style="float: right;">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
{% if roles.purchase_order.add %}
<li><a href='#' id='multi-part-order' title='{% trans "Order parts" %}'>{% trans "Order Parts" %}</a></li>
{% endif %}
{% if roles.purchase_order.delete %}
<li><a href='#' id='multi-part-delete' title='{% trans "Delete parts" %}'>{% trans "Delete Parts" %}</a></li>
{% endif %}
</ul>
</div>
</div>
</div>
<div class='filter-list' id='filter-list-supplier-part'>
<!-- Empty div (will be filled out with available BOM filters) -->
</div>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed' id='supplier-part-table' data-toolbar='#supplier-part-button-toolbar'>
</table>
</div>
<div class='col-sm-6'>
<table class='table table-striped'>
<col width='25'>
<col>
<tr>
<td><span class='fas fa-industry'></span></td>
<td>{% trans "Manufacturer" %}</td>
<td>{% include "yesnolabel.html" with value=company.is_manufacturer %}</td>
</tr>
<tr>
<td><span class='fas fa-building'></span></td>
<td>{% trans "Supplier" %}</td>
<td>{% include 'yesnolabel.html' with value=company.is_supplier %}</td>
</tr>
<tr>
<td><span class='fas fa-user-tie'></span></td>
<td>{% trans "Customer" %}</td>
<td>{% include 'yesnolabel.html' with value=company.is_customer %}</td>
</tr>
</table>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-manufacturer-parts'>
<div class='panel-heading'>
<h4>{% trans "Manufacturer Parts" %}</h4>
</div>
<div class='panel-content'>
{% if roles.purchase_order.change %}
<div id='manufacturer-part-button-toolbar'>
<div class='button-toolbar container-fluid'>
<div class='btn-group role='group'>
{% if roles.purchase_order.add %}
<button class="btn btn-success" id='manufacturer-part-create' title='{% trans "Create new manufacturer part" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Manufacturer Part" %}
</button>
{% endif %}
<div class='btn-group'>
<div class="dropdown" style="float: right;">
<button class="btn btn-primary dropdown-toggle" id='table-options', type="button" data-toggle="dropdown">{% trans "Options" %}
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
{% if roles.purchase_order.add %}
<li><a href='#' id='multi-part-order' title='{% trans "Order parts" %}'>{% trans "Order Parts" %}</a></li>
{% endif %}
{% if roles.purchase_order.delete %}
<li><a href='#' id='multi-part-delete' title='{% trans "Delete parts" %}'>{% trans "Delete Parts" %}</a></li>
{% endif %}
</ul>
</div>
</div>
</div>
<div class='filter-list' id='filter-list-supplier-part'>
<!-- Empty div (will be filled out with available BOM filters) -->
</div>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed' id='part-table' data-toolbar='#manufacturer-part-button-toolbar'>
</table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-company-stock'>
<div class='panel-heading'>
<h4>{% trans "Supplier Stock" %}</h4>
</div>
<div class='panel-content'>
{% include "stock_table.html" %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-purchase-orders'>
<div class='panel-heading'>
<h4>{% trans "Purchase Orders" %}</h4>
</div>
<div class='panel-content'>
{% if roles.purchase_order.add %}
<div id='po-button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<button class='btn btn-primary' type='button' id='company-order2' title='{% trans "Create new purchase order" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Purchase Order" %}</button>
<div class='filter-list' id='filter-list-purchaseorder'>
<!-- Empty div -->
</div>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#po-button-bar'>
</table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-sales-orders'>
<div class='panel-heading'>
<h4>{% trans "Sales Orders" %}</h4>
</div>
<div class='panel-content'>
{% if roles.sales_order.add %}
<div id='so-button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<button class='btn btn-primary' type='button' id='new-sales-order' title='{% trans "Create new sales order" %}'>
<div class='fas fa-plus-circle'></div> {% trans "New Sales Order" %}
</button>
<div class='filter-list' id='filter-list-salesorder'>
<!-- Empty div -->
</div>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed po-table' id='sales-order-table' data-toolbar='#so-button-bar'>
</table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-assigned-stock'>
<div class='panel-heading'>
<h4>{% trans "Assigned Stock" %}</h4>
</div>
<div class='panel-content'>
<div id='assigned-stock-button-toolbar'>
<div class='filter-list' id='filter-list-stock'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
<table class='table table-striped table-condensed' id='assigned-stock-table' data-toolbar='#bassigned-stock-utton-toolbar'></table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-company-notes'>
<div class='panel-heading'>
<div class='row'>
<div class='col-sm-6'>
<h4>{% trans "Company Notes" %}</h4>
</div>
<div class='col-sm-6'>
<div class='btn-group float-right'>
<button type='button' id='edit-notes' title='{% trans "Edit Notes" %}' class='btn btn-small btn-default'>
<span class='fas fa-edit'>
</span>
</button>
</div>
</div>
</div>
</div>
<div class='panel-content'>
{% if company.notes %}
{{ company.notes | markdownify }}
{% endif %}
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
$('#edit-notes').click(function() {
constructForm('{% url "api-company-detail" company.pk %}', {
fields: {
notes: {
multiline: true,
}
},
title: '{% trans "Edit Notes" %}',
reload: true,
});
});
loadStockTable($("#assigned-stock-table"), {
params: {
customer: {{ company.id }},
part_detail: true,
location_detail: true,
},
url: "{% url 'api-stock-list' %}",
filterKey: "customerstock",
});
{% if company.is_customer %}
loadSalesOrderTable("#sales-order-table", {
url: "{% url 'api-so-list' %}",
params: {
customer: {{ company.id }},
}
});
$("#new-sales-order").click(function() {
createSalesOrder({
customer: {{ company.pk }},
});
});
{% endif %}
{% if company.is_supplier %}
loadPurchaseOrderTable("#purchase-order-table", {
url: "{% url 'api-po-list' %}",
params: {
supplier: {{ company.id }},
}
});
function newOrder() {
createPurchaseOrder({
supplier: {{ company.pk }},
});
}
$("#company-order").click(function() {
newOrder();
});
$("#company-order2").click(function() {
newOrder();
});
{% endif %}
loadStockTable($('#stock-table'), {
url: "{% url 'api-stock-list' %}",
params: {
company: {{ company.id }},
part_detail: true,
supplier_part_detail: true,
location_detail: true,
},
buttons: [
'#stock-options',
],
filterKey: "companystock",
});
$("#stock-export").click(function() {
launchModalForm("{% url 'stock-export-options' %}", {
submit_text: '{% trans "Export" %}',
success: function(response) {
var url = "{% url 'stock-export' %}";
url += "?format=" + response.format;
url += "&supplier={{ company.id }}";
location.href = url;
},
});
});
{% if company.is_manufacturer %}
$("#manufacturer-part-create").click(function () {
constructForm('{% url "api-manufacturer-part-list" %}', {
fields: {
part: {},
manufacturer: {
value: {{ company.pk }},
},
MPN: {
icon: 'fa-hashtag',
},
description: {},
link: {
icon: 'fa-link',
},
},
method: 'POST',
title: '{% trans "Add Manufacturer Part" %}',
onSuccess: function() {
$("#part-table").bootstrapTable("refresh");
}
});
});
loadManufacturerPartTable(
"#part-table",
"{% url 'api-manufacturer-part-list' %}",
{
params: {
part_detail: true,
manufacturer_detail: true,
manufacturer: {{ company.id }},
},
}
);
linkButtonsToSelection($("#manufacturer-table"), ['#table-options']);
$("#multi-part-delete").click(function() {
var selections = $("#part-table").bootstrapTable("getSelections");
deleteManufacturerParts(selections, {
onSuccess: function() {
$("#part-table").bootstrapTable("refresh");
}
});
});
$("#multi-part-order").click(function() {
var selections = $("#part-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.part);
});
launchModalForm("/order/purchase-order/order-parts/", {
data: {
parts: parts,
},
});
});
{% endif %}
{% if company.is_supplier %}
$("#supplier-part-create").click(function () {
launchModalForm(
"{% url 'supplier-part-create' %}",
{
data: {
supplier: {{ company.id }},
},
reload: true,
secondary: [
{
field: 'part',
label: '{% trans "New Part" %}',
title: '{% trans "Create new Part" %}',
url: "{% url 'part-create' %}"
},
{
field: 'supplier',
label: "{% trans 'New Supplier' %}",
title: "{% trans 'Create new Supplier' %}",
},
]
});
});
loadSupplierPartTable(
"#supplier-part-table",
"{% url 'api-supplier-part-list' %}",
{
params: {
part_detail: true,
supplier_detail: true,
manufacturer_detail: true,
supplier: {{ company.id }},
},
}
);
{% endif %}
$("#multi-part-delete").click(function() {
var selections = $("#part-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.pk);
});
var url = "{% url 'supplier-part-delete' %}"
launchModalForm(url, {
data: {
parts: parts,
},
reload: true,
});
});
$("#multi-part-order").click(function() {
var selections = $("#part-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.part);
});
launchModalForm("/order/purchase-order/order-parts/", {
data: {
parts: parts,
},
});
});
attachNavCallbacks({
name: 'company',
default: 'company-stock'
});
{% endblock %}

View File

@ -1,119 +0,0 @@
{% extends "company/company_base.html" %}
{% load static %}
{% load i18n %}
{% load inventree_extras %}
{% block menubar %}
{% include 'company/navbar.html' with tab='manufacturer_parts' %}
{% endblock %}
{% block heading %}
{% trans "Manufacturer Parts" %}
{% endblock %}
{% block details %}
{% if roles.purchase_order.change %}
<div id='button-toolbar'>
<div class='button-toolbar container-fluid'>
<div class='btn-group role='group'>
{% if roles.purchase_order.add %}
<button class="btn btn-success" id='manufacturer-part-create' title='{% trans "Create new manufacturer part" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Manufacturer Part" %}
</button>
{% endif %}
<div class='btn-group'>
<div class="dropdown" style="float: right;">
<button class="btn btn-primary dropdown-toggle" id='table-options', type="button" data-toggle="dropdown">{% trans "Options" %}
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
{% if roles.purchase_order.add %}
<li><a href='#' id='multi-part-order' title='{% trans "Order parts" %}'>{% trans "Order Parts" %}</a></li>
{% endif %}
{% if roles.purchase_order.delete %}
<li><a href='#' id='multi-part-delete' title='{% trans "Delete parts" %}'>{% trans "Delete Parts" %}</a></li>
{% endif %}
</ul>
</div>
</div>
</div>
<div class='filter-list' id='filter-list-supplier-part'>
<!-- Empty div (will be filled out with available BOM filters) -->
</div>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed' id='part-table' data-toolbar='#button-toolbar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
$("#manufacturer-part-create").click(function () {
constructForm('{% url "api-manufacturer-part-list" %}', {
fields: {
part: {},
manufacturer: {
value: {{ company.pk }},
},
MPN: {
icon: 'fa-hashtag',
},
description: {},
link: {
icon: 'fa-link',
},
},
method: 'POST',
title: '{% trans "Add Manufacturer Part" %}',
onSuccess: function() {
$("#part-table").bootstrapTable("refresh");
}
});
});
loadManufacturerPartTable(
"#part-table",
"{% url 'api-manufacturer-part-list' %}",
{
params: {
part_detail: true,
manufacturer_detail: true,
manufacturer: {{ company.id }},
},
}
);
linkButtonsToSelection($("#manufacturer-table"), ['#table-options']);
$("#multi-part-delete").click(function() {
var selections = $("#part-table").bootstrapTable("getSelections");
deleteManufacturerParts(selections, {
onSuccess: function() {
$("#part-table").bootstrapTable("refresh");
}
});
});
$("#multi-part-order").click(function() {
var selections = $("#part-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.part);
});
launchModalForm("/order/purchase-order/order-parts/", {
data: {
parts: parts,
},
});
});
{% endblock %}

View File

@ -1,49 +0,0 @@
{% extends "company/company_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "company/navbar.html" with tab='stock' %}
{% endblock %}
{% block heading %}
{% trans "Supplier Stock" %}
{% endblock %}
{% block details %}
{% include "stock_table.html" %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadStockTable($('#stock-table'), {
url: "{% url 'api-stock-list' %}",
params: {
company: {{ company.id }},
part_detail: true,
supplier_part_detail: true,
location_detail: true,
},
buttons: [
'#stock-options',
],
filterKey: "companystock",
});
$("#stock-export").click(function() {
launchModalForm("{% url 'stock-export-options' %}", {
submit_text: '{% trans "Export" %}',
success: function(response) {
var url = "{% url 'stock-export' %}";
url += "?format=" + response.format;
url += "&supplier={{ company.id }}";
location.href = url;
},
});
});
{% endblock %}

View File

@ -1,127 +0,0 @@
{% extends "company/company_base.html" %}
{% load static %}
{% load i18n %}
{% load inventree_extras %}
{% block menubar %}
{% include 'company/navbar.html' with tab='supplier_parts' %}
{% endblock %}
{% block heading %}
{% trans "Supplier Parts" %}
{% endblock %}
{% block details %}
{% if roles.purchase_order.change %}
<div id='button-toolbar'>
<div class='button-toolbar container-fluid'>
<div class='btn-group' role='group'>
{% if roles.purchase_order.add %}
<button class="btn btn-success" id='supplier-part-create' title='{% trans "Create new supplier part" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Supplier Part" %}
</button>
{% endif %}
<div class='btn-group'>
<div class="dropdown" style="float: right;">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
{% if roles.purchase_order.add %}
<li><a href='#' id='multi-part-order' title='{% trans "Order parts" %}'>{% trans "Order Parts" %}</a></li>
{% endif %}
{% if roles.purchase_order.delete %}
<li><a href='#' id='multi-part-delete' title='{% trans "Delete parts" %}'>{% trans "Delete Parts" %}</a></li>
{% endif %}
</ul>
</div>
</div>
</div>
<div class='filter-list' id='filter-list-supplier-part'>
<!-- Empty div (will be filled out with available BOM filters) -->
</div>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed' id='part-table' data-toolbar='#button-toolbar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
$("#supplier-part-create").click(function () {
launchModalForm(
"{% url 'supplier-part-create' %}",
{
data: {
supplier: {{ company.id }},
},
reload: true,
secondary: [
{
field: 'part',
label: '{% trans "New Part" %}',
title: '{% trans "Create new Part" %}',
url: "{% url 'part-create' %}"
},
{
field: 'supplier',
label: "{% trans 'New Supplier' %}",
title: "{% trans 'Create new Supplier' %}",
},
]
});
});
loadSupplierPartTable(
"#part-table",
"{% url 'api-supplier-part-list' %}",
{
params: {
part_detail: true,
supplier_detail: true,
manufacturer_detail: true,
supplier: {{ company.id }},
},
}
);
$("#multi-part-delete").click(function() {
var selections = $("#part-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.pk);
});
var url = "{% url 'supplier-part-delete' %}"
launchModalForm(url, {
data: {
parts: parts,
},
reload: true,
});
});
$("#multi-part-order").click(function() {
var selections = $("#part-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.part);
});
launchModalForm("/order/purchase-order/order-parts/", {
data: {
parts: parts,
},
});
});
{% endblock %}

View File

@ -0,0 +1,330 @@
{% extends "two_column.html" %}
{% load static %}
{% load i18n %}
{% block page_title %}
InvenTree | {% trans "Manufacturer Part" %}
{% endblock %}
{% block menubar %}
{% include "company/manufacturer_part_navbar.html" %}
{% endblock %}
{% block thumbnail %}
<img class='part-thumb'
{% if part.part.image %}
src='{{ part.part.image.url }}'
{% else %}
src="{% static 'img/blank_image.png' %}"
{% endif %}/>
{% endblock %}
{% block page_data %}
<h3>{% trans "Manufacturer Part" %}</h3>
<hr>
<h4>
{{ part.part.full_name }}
{% if user.is_staff and perms.company.change_company %}
<a href="{% url 'admin:company_supplierpart_change' part.pk %}">
<span title='{% trans "Admin view" %}' class='fas fa-user-shield'></span>
</a>
{% endif %}
</h4>
<p>{{ part.manufacturer.name }} - {{ part.MPN }}</p>
{% if roles.purchase_order.change %}
<div class='btn-row'>
<div class='btn-group action-buttons' role='group'>
{% comment "for later" %}
{% if roles.purchase_order.add %}
<button type='button' class='btn btn-default btn-glyph' id='order-part' title='{% trans "Order part" %}'>
<span class='fas fa-shopping-cart'></span>
</button>
{% endif %}
{% endcomment %}
<button type='button' class='btn btn-default btn-glyph' id='edit-part' title='{% trans "Edit manufacturer part" %}'>
<span class='fas fa-edit icon-green'/>
</button>
{% if roles.purchase_order.delete %}
<button type='button' class='btn btn-default btn-glyph' id='delete-part' title='{% trans "Delete manufacturer part" %}'>
<span class='fas fa-trash-alt icon-red'/>
</button>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}
{% block page_details %}
<h4>{% trans "Manufacturer Part Details" %}</h4>
<table class="table table-striped table-condensed">
<col width='25'>
<tr>
<td><span class='fas fa-shapes'></span></td>
<td>{% trans "Internal Part" %}</td>
<td>
{% if part.part %}
<a href="{% url 'part-detail' part.part.id %}?display=part-suppliers">{{ part.part.full_name }}</a>{% include "clip.html"%}
{% endif %}
</td>
</tr>
{% if part.description %}
<tr>
<td></td>
<td>{% trans "Description" %}</td>
<td>{{ part.description }}{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.link %}
<tr>
<td><span class='fas fa-link'></span></td>
<td>{% trans "External Link" %}</td>
<td><a href="{{ part.link }}">{{ part.link }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
<tr>
<td><span class='fas fa-industry'></span></td>
<td>{% trans "Manufacturer" %}</td>
<td><a href="{% url 'company-detail' part.manufacturer.id %}">{{ part.manufacturer.name }}</a>{% include "clip.html"%}</td></tr>
<tr>
<td><span class='fas fa-hashtag'></span></td>
<td>{% trans "MPN" %}</td>
<td>{{ part.MPN }}{% include "clip.html"%}</td>
</tr>
</table>
{% endblock %}
{% block page_content %}
<div class='panel panel-default panel-inventree panel-hidden' id='panel-supplier-parts'>
<div class='panel-heading'>
<h4>{% trans "Suppliers" %}</h4>
</div>
<div class='panel-content'>
<div id='supplier-button-toolbar'>
<div class='btn-group'>
<button class="btn btn-success" id='supplier-create'>
<span class='fas fa-plus-circle'></span> {% trans "New Supplier Part" %}
</button>
<div id='opt-dropdown' class="btn-group">
<button id='supplier-part-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href='#' id='supplier-part-delete' title='{% trans "Delete supplier parts" %}'>{% trans "Delete" %}</a></li>
</ul>
</div>
</div>
</div>
<table class="table table-striped table-condensed" id='supplier-table' data-toolbar='#supplier-button-toolbar'>
</table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-parameters'>
<div class='panel-heading'>
<h4>{% trans "Parameters" %}</h4>
</div>
<div class='panel-content'>
<div id='parameter-toolbar'>
<div class='btn-group'>
<button class='btn btn-success' id='parameter-create'>
<span class='fas fa-plus-circle'></span> {% trans "New Parameter" %}
</button>
<div id='opt-dropdown' class="btn-group">
<button id='parameter-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href='#' id='multi-parameter-delete' title='{% trans "Delete parameters" %}'>{% trans "Delete" %}</a></li>
</ul>
</div>
</div>
</div>
<table class='table table-striped table-condensed' id='parameter-table' data-toolbar='#parameter-toolbar'></table>
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableNavbar({
label: 'manufacturer-part',
toggleId: '#manufacturer-part-menu-toggle'
});
function reloadParameters() {
$("#parameter-table").bootstrapTable("refresh");
}
$('#parameter-create').click(function() {
constructForm('{% url "api-manufacturer-part-parameter-list" %}', {
method: 'POST',
fields: {
name: {},
value: {},
units: {},
manufacturer_part: {
value: {{ part.pk }},
hidden: true,
}
},
title: '{% trans "Add Parameter" %}',
onSuccess: reloadParameters
});
});
$('#supplier-create').click(function () {
launchModalForm(
"{% url 'supplier-part-create' %}",
{
reload: true,
data: {
manufacturer_part: {{ part.id }}
},
secondary: [
{
field: 'supplier',
label: '{% trans "New Supplier" %}',
title: '{% trans "Create new supplier" %}',
},
]
});
});
$("#supplier-part-delete").click(function() {
var selections = $("#supplier-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.pk);
});
launchModalForm("{% url 'supplier-part-delete' %}", {
data: {
parts: parts,
},
reload: true,
});
});
$("#multi-parameter-delete").click(function() {
var selections = $("#parameter-table").bootstrapTable("getSelections");
var text = `
<div class ='alert alert-block alert-danger'>
<p>{% trans "Selected parameters will be deleted" %}:</p>
<ul>`;
selections.forEach(function(item) {
text += `<li>${item.name} - <i>${item.value}</i></li>`;
});
text += `
</ul>
</div>`;
showQuestionDialog(
'{% trans "Delete Parameters" %}',
text,
{
accept_text: '{% trans "Delete" %}',
accept: function() {
// Delete each parameter via the API
var requests = [];
selections.forEach(function(item) {
var url = `/api/company/part/manufacturer/parameter/${item.pk}/`;
requests.push(inventreeDelete(url));
});
$.when.apply($, requests).then(function() {
$('#parameter-table').bootstrapTable('refresh');
});
}
}
);
});
loadSupplierPartTable(
"#supplier-table",
"{% url 'api-supplier-part-list' %}",
{
params: {
part: {{ part.part.id }},
manufacturer_part: {{ part.id }},
part_detail: false,
supplier_detail: true,
manufacturer_detail: false,
},
}
);
loadManufacturerPartParameterTable(
"#parameter-table",
"{% url 'api-manufacturer-part-parameter-list' %}",
{
params: {
manufacturer_part: {{ part.id }},
}
}
);
linkButtonsToSelection($("#supplier-table"), ['#supplier-part-options']);
linkButtonsToSelection($("#parameter-table"), ['#parameter-options']);
$('#order-part, #order-part2').click(function() {
launchModalForm(
"{% url 'order-parts' %}",
{
data: {
part: {{ part.part.id }},
},
reload: true,
},
);
});
$('#edit-part').click(function () {
constructForm('{% url "api-manufacturer-part-detail" part.pk %}', {
fields: {
part: {},
manufacturer: {},
MPN: {
icon: 'fa-hashtag',
},
description: {},
link: {
icon: 'fa-link',
},
},
title: '{% trans "Edit Manufacturer Part" %}',
reload: true,
});
});
$('#delete-part').click(function() {
constructForm('{% url "api-manufacturer-part-detail" part.pk %}', {
method: 'DELETE',
title: '{% trans "Delete Manufacturer Part" %}',
redirect: "{% url 'company-detail' part.manufacturer.id %}",
});
});
attachNavCallbacks({
name: 'manufacturerpart',
default: 'parameters'
});
{% endblock %}

View File

@ -1,143 +0,0 @@
{% extends "two_column.html" %}
{% load static %}
{% load i18n %}
{% block page_title %}
InvenTree | {% trans "Manufacturer Part" %}
{% endblock %}
{% block thumbnail %}
<img class='part-thumb'
{% if part.part.image %}
src='{{ part.part.image.url }}'
{% else %}
src="{% static 'img/blank_image.png' %}"
{% endif %}/>
{% endblock %}
{% block page_data %}
<h3>{% trans "Manufacturer Part" %}</h3>
<hr>
<h4>
{{ part.part.full_name }}
{% if user.is_staff and perms.company.change_company %}
<a href="{% url 'admin:company_supplierpart_change' part.pk %}">
<span title='{% trans "Admin view" %}' class='fas fa-user-shield'></span>
</a>
{% endif %}
</h4>
<p>{{ part.manufacturer.name }} - {{ part.MPN }}</p>
{% if roles.purchase_order.change %}
<div class='btn-row'>
<div class='btn-group action-buttons' role='group'>
{% comment "for later" %}
{% if roles.purchase_order.add %}
<button type='button' class='btn btn-default btn-glyph' id='order-part' title='{% trans "Order part" %}'>
<span class='fas fa-shopping-cart'></span>
</button>
{% endif %}
{% endcomment %}
<button type='button' class='btn btn-default btn-glyph' id='edit-part' title='{% trans "Edit manufacturer part" %}'>
<span class='fas fa-edit icon-green'/>
</button>
{% if roles.purchase_order.delete %}
<button type='button' class='btn btn-default btn-glyph' id='delete-part' title='{% trans "Delete manufacturer part" %}'>
<span class='fas fa-trash-alt icon-red'/>
</button>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}
{% block page_details %}
<h4>{% trans "Manufacturer Part Details" %}</h4>
<table class="table table-striped table-condensed">
<col width='25'>
<tr>
<td><span class='fas fa-shapes'></span></td>
<td>{% trans "Internal Part" %}</td>
<td>
{% if part.part %}
<a href="{% url 'part-suppliers' part.part.id %}">{{ part.part.full_name }}</a>{% include "clip.html"%}
{% endif %}
</td>
</tr>
{% if part.description %}
<tr>
<td></td>
<td>{% trans "Description" %}</td>
<td>{{ part.description }}{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.link %}
<tr>
<td><span class='fas fa-link'></span></td>
<td>{% trans "External Link" %}</td>
<td><a href="{{ part.link }}">{{ part.link }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
<tr>
<td><span class='fas fa-industry'></span></td>
<td>{% trans "Manufacturer" %}</td>
<td><a href="{% url 'company-detail-manufacturer-parts' part.manufacturer.id %}">{{ part.manufacturer.name }}</a>{% include "clip.html"%}</td></tr>
<tr>
<td><span class='fas fa-hashtag'></span></td>
<td>{% trans "MPN" %}</td>
<td>{{ part.MPN }}{% include "clip.html"%}</td>
</tr>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableNavbar({
label: 'manufacturer-part',
toggleId: '#manufacturer-part-menu-toggle'
})
$('#order-part, #order-part2').click(function() {
launchModalForm(
"{% url 'order-parts' %}",
{
data: {
part: {{ part.part.id }},
},
reload: true,
},
);
});
$('#edit-part').click(function () {
constructForm('{% url "api-manufacturer-part-detail" part.pk %}', {
fields: {
part: {},
manufacturer: {},
MPN: {
icon: 'fa-hashtag',
},
description: {},
link: {
icon: 'fa-link',
},
},
title: '{% trans "Edit Manufacturer Part" %}',
reload: true,
});
});
$('#delete-part').click(function() {
constructForm('{% url "api-manufacturer-part-detail" part.pk %}', {
method: 'DELETE',
title: '{% trans "Delete Manufacturer Part" %}',
redirect: "{% url 'company-detail-manufacturer-parts' part.manufacturer.id %}",
});
});
{% endblock %}

View File

@ -1,17 +0,0 @@
{% extends "modal_form.html" %}
{% load i18n %}
{% block pre_form_content %}
{{ block.super }}
{% if part %}
<div class='alert alert-block alert-info'>
{% include "hover_image.html" with image=part.image %}
{{ part.full_name}}
<br>
<i>{{ part.description }}</i>
</div>
{% endif %}
{% endblock %}

View File

@ -1,38 +0,0 @@
{% extends "company/manufacturer_part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "company/manufacturer_part_navbar.html" with tab='details' %}
{% endblock %}
{% block heading %}
{% trans "Manufacturer Part Details" %}
{% endblock %}
{% block details %}
<table class="table table-striped table-condensed">
<tr>
<td>{% trans "Internal Part" %}</td>
<td>
{% if part.part %}
<a href="{% url 'part-suppliers' part.part.id %}">{{ part.part.full_name }}</a>
{% endif %}
</td>
</tr>
<tr><td>{% trans "Manufacturer" %}</td><td><a href="{% url 'company-detail-manufacturer-parts' part.manufacturer.id %}">{{ part.manufacturer.name }}</a></td></tr>
<tr><td>{% trans "MPN" %}</td><td>{{ part.MPN }}</tr></tr>
{% if part.link %}
<tr><td>{% trans "External Link" %}</td><td><a href="{{ part.link }}">{{ part.link }}</a></td></tr>
{% endif %}
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% endblock %}

View File

@ -8,8 +8,15 @@
</a>
</li>
<li class='list-group-item {% if tab == "suppliers" %}active{% endif %}' title='{% trans "Supplier Parts" %}'>
<a href='{% url "manufacturer-part-suppliers" part.id %}'>
<li class='list-group-item' title='{% trans "Parameters" %}'>
<a href='#' id='select-parameters' class='nav-toggle'>
<span class='fas fa-th-list sidebar-icon'></span>
{% trans "Parameters" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Supplier Parts" %}'>
<a href='#' id='select-supplier-parts' class='nav-toggle'>
<span class='fas fa-building sidebar-icon'></span>
{% trans "Suppliers" %}
</a>
@ -22,7 +29,7 @@
{% trans "Stock" %}
</a>
</li>
<li class='list-group-item {% if tab == "orders" %}active{% endif %}' title='{% trans "Manufacturer Part Orders" %}'>
<a href='{% url "manufacturer-part-orders" part.id %}'>
<span class='fas fa-shopping-cart sidebar-icon'></span>

View File

@ -1,187 +0,0 @@
{% extends "company/manufacturer_part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "company/manufacturer_part_navbar.html" with tab='suppliers' %}
{% endblock %}
{% block heading %}
{% trans "Suppliers" %}
{% endblock %}
{% block details %}
<div id='button-toolbar'>
<div class='btn-group'>
<button class="btn btn-success" id='supplier-create'>
<span class='fas fa-plus-circle'></span> {% trans "New Supplier Part" %}
</button>
<div id='opt-dropdown' class="btn-group">
<button id='supplier-part-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href='#' id='supplier-part-delete' title='{% trans "Delete supplier parts" %}'>{% trans "Delete" %}</a></li>
</ul>
</div>
</div>
</div>
<table class="table table-striped table-condensed" id='supplier-table' data-toolbar='#button-toolbar'>
</table>
{% endblock %}
{% block post_content_panels %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>{% trans "Parameters" %}</h4>
</div>
<div class='panel-content'>
<div id='parameter-toolbar'>
<div class='btn-group'>
<button class='btn btn-success' id='parameter-create'>
<span class='fas fa-plus-circle'></span> {% trans "New Parameter" %}
</button>
<div id='opt-dropdown' class="btn-group">
<button id='parameter-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href='#' id='multi-parameter-delete' title='{% trans "Delete parameters" %}'>{% trans "Delete" %}</a></li>
</ul>
</div>
</div>
</div>
<table class='table table-striped table-condensed' id='parameter-table' data-toolbar='#parameter-toolbar'></table>
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
function reloadParameters() {
$("#parameter-table").bootstrapTable("refresh");
}
$('#parameter-create').click(function() {
constructForm('{% url "api-manufacturer-part-parameter-list" %}', {
method: 'POST',
fields: {
name: {},
value: {},
units: {},
manufacturer_part: {
value: {{ part.pk }},
hidden: true,
}
},
title: '{% trans "Add Parameter" %}',
onSuccess: reloadParameters
});
});
$('#supplier-create').click(function () {
launchModalForm(
"{% url 'supplier-part-create' %}",
{
reload: true,
data: {
manufacturer_part: {{ part.id }}
},
secondary: [
{
field: 'supplier',
label: '{% trans "New Supplier" %}',
title: '{% trans "Create new supplier" %}',
},
]
});
});
$("#supplier-part-delete").click(function() {
var selections = $("#supplier-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.pk);
});
launchModalForm("{% url 'supplier-part-delete' %}", {
data: {
parts: parts,
},
reload: true,
});
});
$("#multi-parameter-delete").click(function() {
var selections = $("#parameter-table").bootstrapTable("getSelections");
var text = `
<div class ='alert alert-block alert-danger'>
<p>{% trans "Selected parameters will be deleted" %}:</p>
<ul>`;
selections.forEach(function(item) {
text += `<li>${item.name} - <i>${item.value}</i></li>`;
});
text += `
</ul>
</div>`;
showQuestionDialog(
'{% trans "Delete Parameters" %}',
text,
{
accept_text: '{% trans "Delete" %}',
accept: function() {
// Delete each parameter via the API
var requests = [];
selections.forEach(function(item) {
var url = `/api/company/part/manufacturer/parameter/${item.pk}/`;
requests.push(inventreeDelete(url));
});
$.when.apply($, requests).then(function() {
$('#parameter-table').bootstrapTable('refresh');
});
}
}
);
});
loadSupplierPartTable(
"#supplier-table",
"{% url 'api-supplier-part-list' %}",
{
params: {
part: {{ part.part.id }},
manufacturer_part: {{ part.id }},
part_detail: false,
supplier_detail: true,
manufacturer_detail: false,
},
}
);
loadManufacturerPartParameterTable(
"#parameter-table",
"{% url 'api-manufacturer-part-parameter-list' %}",
{
params: {
manufacturer_part: {{ part.id }},
}
}
);
linkButtonsToSelection($("#supplier-table"), ['#supplier-part-options'])
linkButtonsToSelection($("#parameter-table"), ['#parameter-options'])
{% endblock %}

View File

@ -9,16 +9,9 @@
</a>
</li>
<li class='list-group-item {% if tab == "details" %}active{% endif %}' title='{% trans "Company Details" %}'>
<a href='{% url "company-detail" company.id %}'>
<span class='fas fa-info-circle sidebar-icon'></span>
{% trans "Details" %}
</a>
</li>
{% if company.is_manufacturer %}
<li class='list-group-item {% if tab == "manufacturer_parts" %}active{% endif %}' title='{% trans "Manufactured Parts" %}'>
<a href='{% url "company-detail-manufacturer-parts" company.id %}'>
<li class='list-group-item' title='{% trans "Manufactured Parts" %}'>
<a href='#' id='select-manufacturer-parts' class='nav-toggle'>
<span class='fas fa-industry sidebar-icon'></span>
{% trans "Manufactured Parts" %}
</a>
@ -26,8 +19,8 @@
{% endif %}
{% if company.is_supplier or company.is_manufacturer %}
<li class='list-group-item {% if tab == "supplier_parts" %}active{% endif %}' title='{% trans "Supplied Parts" %}'>
<a href='{% url "company-detail-supplier-parts" company.id %}'>
<li class='list-group-item' title='{% trans "Supplied Parts" %}'>
<a href='#' id='select-supplier-parts' class='nav-toggle'>
<span class='fas fa-building sidebar-icon'></span>
{% trans "Supplied Parts" %}
</a>
@ -35,8 +28,8 @@
{% endif %}
{% if company.is_manufacturer or company.is_supplier %}
<li class='list-group-item {% if tab == "stock" %}active{% endif %}' title='{% trans "Stock Items" %}'>
<a href='{% url "company-detail-stock" company.id %}'>
<li class='list-group-item' title='{% trans "Stock Items" %}'>
<a href='#' id='select-company-stock' class='nav-toggle'>
<span class='fas fa-boxes sidebar-icon'></span>
{% trans "Stock" %}
</a>
@ -44,8 +37,8 @@
{% endif %}
{% if company.is_supplier %}
<li class='list-group-item {% if tab == "po" %}active{% endif %}' title='{% trans "Sales Orders" %}'>
<a href='{% url "company-detail-purchase-orders" company.id %}'>
<li class='list-group-item' title='{% trans "Purchase Orders" %}'>
<a href='#' id='select-purchase-orders' class='nav-toggle'>
<span class='fas fa-shopping-cart sidebar-icon'></span>
{% trans "Purchase Orders" %}
</a>
@ -53,22 +46,22 @@
{% endif %}
{% if company.is_customer %}
<li class='list-group-item {% if tab == "so" %}active{% endif %}' title='{% trans "Sales Orders" %}'>
<a href='{% url "company-detail-sales-orders" company.id %}'>
<li class='list-group-item' title='{% trans "Sales Orders" %}'>
<a href='#' id='select-sales-orders' class='nav-toggle'>
<span class='fas fa-truck sidebar-icon'></span>
{% trans "Sales Orders" %}
</a>
</li>
<li class='list-group-item {% if tab == "assigned" %}active{% endif %}' title='{% trans "Assigned Stock" %}'>
<a href='{% url "company-detail-assigned-stock" company.id %}'>
<li class='list-group-item' title='{% trans "Assigned Stock" %}'>
<a href='#' id='select-assigned-stock' class='nav-toggle'>
<span class='fas fa-sign-out-alt sidebar-icon'></span>
{% trans "Assigned Stock" %}
</a>
</li>
{% endif %}
<li class='list-group-item {% if tab == "notes" %}active{% endif %}' titl='{% trans "Notes" %}'>
<a href='{% url "company-notes" company.id %}'>
<li class='list-group-item' title='{% trans "Notes" %}'>
<a href='#' id='select-company-notes' class='nav-toggle'>
<span class='fas fa-clipboard sidebar-icon'></span>
{% trans "Notes" %}
</a>

View File

@ -1,47 +0,0 @@
{% extends "company/company_base.html" %}
{% load static %}
{% load i18n %}
{% load markdownify %}
{% block menubar %}
{% include 'company/navbar.html' with tab='notes' %}
{% endblock %}
{% block heading %}
{% trans "Company Notes" %}
{% if not editing %}
<button title='{% trans "Edit notes" %}' class='btn btn-default' id='edit-notes'><span class='fas fa-edit'></span></button>
{% endif %}
{% endblock %}
{% block details %}
{% if editing %}
<form method='POST'>
{% csrf_token %}
{{ form }}
<hr>
<button type="submit" class='btn btn-default'>{% trans "Save" %}</button>
</form>
{{ form.media }}
{% else %}
{{ company.notes | markdownify }}
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% if editing %}
{% else %}
$("#edit-notes").click(function() {
location.href = "{% url 'company-notes' company.id %}?edit=1";
});
{% endif %}
{% endblock %}

View File

@ -1,56 +0,0 @@
{% extends "company/company_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'company/navbar.html' with tab='po' %}
{% endblock %}
{% block heading %}
{% trans "Purchase Orders" %}
{% endblock %}
{% block details %}
{% if roles.purchase_order.add %}
<div id='button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<button class='btn btn-primary' type='button' id='company-order2' title='{% trans "Create new purchase order" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Purchase Order" %}</button>
<div class='filter-list' id='filter-list-purchaseorder'>
<!-- Empty div -->
</div>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#button-bar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadPurchaseOrderTable("#purchase-order-table", {
url: "{% url 'api-po-list' %}",
params: {
supplier: {{ company.id }},
}
});
function newOrder() {
createPurchaseOrder({
supplier: {{ company.pk }},
});
}
$("#company-order").click(function() {
newOrder();
});
$("#company-order2").click(function() {
newOrder();
});
{% endblock %}

View File

@ -1,51 +0,0 @@
{% extends "company/company_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'company/navbar.html' with tab='so' %}
{% endblock %}
{% block heading %}
{% trans "Sales Orders" %}
{% endblock %}
{% block details %}
{% if roles.sales_order.add %}
<div id='button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<button class='btn btn-primary' type='button' id='new-sales-order' title='{% trans "Create new sales order" %}'>
<div class='fas fa-plus-circle'></div> {% trans "New Sales Order" %}
</button>
<div class='filter-list' id='filter-list-salesorder'>
<!-- Empty div -->
</div>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed po-table' id='sales-order-table' data-toolbar='#button-bar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadSalesOrderTable("#sales-order-table", {
url: "{% url 'api-so-list' %}",
params: {
customer: {{ company.id }},
}
});
$("#new-sales-order").click(function() {
createSalesOrder({
customer: {{ company.pk }},
});
});
{% endblock %}

View File

@ -0,0 +1,352 @@
{% extends "two_column.html" %}
{% load static %}
{% load i18n %}
{% load inventree_extras %}
{% block page_title %}
{% inventree_title %} | {% trans "Supplier Part" %}
{% endblock %}
{% block menubar %}
{% include "company/supplier_part_navbar.html" %}
{% endblock %}
{% block thumbnail %}
<img class='part-thumb'
{% if part.part.image %}
src='{{ part.part.image.url }}'
{% else %}
src="{% static 'img/blank_image.png' %}"
{% endif %}/>
{% endblock %}
{% block page_data %}
<h3>{% trans "Supplier Part" %}</h3>
<hr>
<h4>
{{ part.part.full_name }}
{% if user.is_staff and perms.company.change_company %}
<a href="{% url 'admin:company_supplierpart_change' part.pk %}">
<span title='{% trans "Admin view" %}' class='fas fa-user-shield'></span>
</a>
{% endif %}
</h4>
<p>{{ part.supplier.name }} - {{ part.SKU }}</p>
{% if roles.purchase_order.change %}
<div class='btn-row'>
<div class='btn-group action-buttons' role='group'>
{% if roles.purchase_order.add %}
<button type='button' class='btn btn-default btn-glyph' id='order-part' title='{% trans "Order part" %}'>
<span class='fas fa-shopping-cart'></span>
</button>
{% endif %}
<button type='button' class='btn btn-default btn-glyph' id='edit-part' title='{% trans "Edit supplier part" %}'>
<span class='fas fa-edit icon-green'/>
</button>
{% if roles.purchase_order.delete %}
<button type='button' class='btn btn-default btn-glyph' id='delete-part' title='{% trans "Delete supplier part" %}'>
<span class='fas fa-trash-alt icon-red'/>
</button>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}
{% block page_details %}
<h4>{% trans "Supplier Part Details" %}</h4>
<table class="table table-striped table-condensed">
<col width='25'>
<tr>
<td><span class='fas fa-shapes'></span></td>
<td>{% trans "Internal Part" %}</td>
<td>
{% if part.part %}
<a href="{% url 'part-detail' part.part.id %}?display=part-suppliers">{{ part.part.full_name }}</a>{% include "clip.html"%}
{% endif %}
</td>
</tr>
{% if part.description %}
<tr>
<td></td>
<td>{% trans "Description" %}</td>
<td>{{ part.description }}{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.link %}
<tr>
<td><span class='fas fa-link'></span></td>
<td>{% trans "External Link" %}</td>
<td><a href="{{ part.link }}">{{ part.link }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
<tr>
<td><span class='fas fa-building'></span></td>
<td>{% trans "Supplier" %}</td>
<td><a href="{% url 'company-detail' part.supplier.id %}">{{ part.supplier.name }}</a>{% include "clip.html"%}</td></tr>
<tr>
<td><span class='fas fa-hashtag'></span></td>
<td>{% trans "SKU" %}</td>
<td>{{ part.SKU }}{% include "clip.html"%}</tr>
</tr>
{% if part.manufacturer_part.manufacturer %}
<tr>
<td><span class='fas fa-industry'></span></td>
<td>{% trans "Manufacturer" %}</td>
<td><a href="{% url 'company-detail' part.manufacturer_part.manufacturer.id %}">
{{ part.manufacturer_part.manufacturer.name }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.manufacturer_part.MPN %}
<tr>
<td><span class='fas fa-hashtag'></span></td>
<td>{% trans "MPN" %}</td>
<td><a href="{% url 'manufacturer-part-detail' part.manufacturer_part.id %}">{{ part.manufacturer_part.MPN }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.packaging %}
<tr>
<td><span class='fas fa-cube'></span></td>
<td>{% trans "Packaging" %}</td>
<td>{{ part.packaging }}{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.note %}
<tr>
<td><span class='fas fa-sticky-note'></span></td>
<td>{% trans "Note" %}</td>
<td>{{ part.note }}{% include "clip.html"%}</td>
</tr>
{% endif %}
</table>
{% endblock %}
{% block page_content %}
<div class='panel panel-default panel-inventree panel-hidden' id='panel-stock'>
<div class='panel-heading'>
<h4>{% trans "Supplier Part Stock" %}</h4>
</div>
<div class='panel-content'>
{% include "stock_table.html" %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-purchase-orders'>
<div class='panel-heading'>
<h4>{% trans "Supplier Part Orders" %}</h4>
</div>
<div class='panel-content'>
{% if roles.purchase_order.add %}
<div id='button-bar'>
<div class='btn-group'>
<button class='btn btn-primary' type='button' id='order-part2' title='{% trans "Order part" %}'>
<span class='fas fa-shopping-cart'></span> {% trans "Order Part" %}</button>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#button-bar'>
</table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-pricing'>
<div class='panel-heading'>
<h4>{% trans "Pricing Information" %}</h4>
</div>
<div class='panel-content'>
{% if roles.purchase_order.add %}
<div id='price-break-toolbar' class='btn-group'>
<button class='btn btn-primary' id='new-price-break' type='button'>
<span class='fas fa-plus-circle'></span> {% trans "Add Price Break" %}
</button>
</div>
{% endif %}
<table class='table table-striped table-condensed' id='price-break-table' data-toolbar='#price-break-toolbar'>
</table>
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
function reloadPriceBreaks() {
$("#price-break-table").bootstrapTable("refresh");
}
$('#price-break-table').inventreeTable({
name: 'buypricebreaks',
formatNoMatches: function() { return "{% trans "No price break information found" %}"; },
queryParams: {
part: {{ part.id }},
},
url: "{% url 'api-part-supplier-price-list' %}",
onPostBody: function() {
var table = $('#price-break-table');
table.find('.button-price-break-delete').click(function() {
var pk = $(this).attr('pk');
constructForm(`/api/company/price-break/${pk}/`, {
method: 'DELETE',
onSuccess: reloadPriceBreaks,
title: '{% trans "Delete Price Break" %}',
});
});
table.find('.button-price-break-edit').click(function() {
var pk = $(this).attr('pk');
constructForm(`/api/company/price-break/${pk}/`, {
fields: {
quantity: {},
price: {},
price_currency: {},
},
onSuccess: reloadPriceBreaks,
title: '{% trans "Edit Price Break" %}',
});
});
},
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-price-break-edit', row.pk, '{% trans "Edit price break" %}');
html += makeIconButton('fa-trash-alt icon-red', 'button-price-break-delete', row.pk, '{% trans "Delete price break" %}');
html += `</div>`;
return html;
}
},
]
});
$('#new-price-break').click(function() {
constructForm(
'{% url "api-part-supplier-price-list" %}',
{
method: 'POST',
fields: {
quantity: {},
part: {
value: {{ part.pk }},
hidden: true,
},
price: {},
price_currency: {
},
},
title: '{% trans "Add Price Break" %}',
onSuccess: reloadPriceBreaks,
}
);
});
loadPurchaseOrderTable($("#purchase-order-table"), {
url: "{% url 'api-po-list' %}?supplier_part={{ part.id }}",
});
loadStockTable($("#stock-table"), {
params: {
supplier_part: {{ part.id }},
location_detail: true,
part_detail: false,
},
groupByField: 'location',
buttons: ['#stock-options'],
url: "{% url 'api-stock-list' %}",
});
$("#stock-export").click(function() {
launchModalForm("{% url 'stock-export-options' %}", {
submit_text: '{% trans "Export" %}',
success: function(response) {
var url = "{% url 'stock-export' %}";
url += "?format=" + response.format;
url += "&cascade=" + response.cascade;
url += "&supplier_part={{ part.id }}";
location.href = url;
},
});
});
$("#item-create").click(function() {
createNewStockItem({
data: {
part: {{ part.part.id }},
supplier_part: {{ part.id }},
},
reload: true,
});
});
enableNavbar({
label: 'supplier-part',
toggleId: '#supplier-part-menu-toggle'
})
$('#order-part, #order-part2').click(function() {
launchModalForm(
"{% url 'order-parts' %}",
{
data: {
part: {{ part.part.id }},
},
reload: true,
},
);
});
$('#edit-part').click(function () {
launchModalForm(
"{% url 'supplier-part-edit' part.id %}",
{
reload: true
}
);
});
$('#delete-part').click(function() {
launchModalForm(
"{% url 'supplier-part-delete' %}?part={{ part.id }}",
{
redirect: "{% url 'company-detail' part.supplier.id %}"
}
);
});
attachNavCallbacks({
name: 'supplierpart',
default: 'stock'
});
{% endblock %}

View File

@ -1,161 +0,0 @@
{% extends "two_column.html" %}
{% load static %}
{% load i18n %}
{% load inventree_extras %}
{% block page_title %}
{% inventree_title %} | {% trans "Supplier Part" %}
{% endblock %}
{% block thumbnail %}
<img class='part-thumb'
{% if part.part.image %}
src='{{ part.part.image.url }}'
{% else %}
src="{% static 'img/blank_image.png' %}"
{% endif %}/>
{% endblock %}
{% block page_data %}
<h3>{% trans "Supplier Part" %}</h3>
<hr>
<h4>
{{ part.part.full_name }}
{% if user.is_staff and perms.company.change_company %}
<a href="{% url 'admin:company_supplierpart_change' part.pk %}">
<span title='{% trans "Admin view" %}' class='fas fa-user-shield'></span>
</a>
{% endif %}
</h4>
<p>{{ part.supplier.name }} - {{ part.SKU }}</p>
{% if roles.purchase_order.change %}
<div class='btn-row'>
<div class='btn-group action-buttons' role='group'>
{% if roles.purchase_order.add %}
<button type='button' class='btn btn-default btn-glyph' id='order-part' title='{% trans "Order part" %}'>
<span class='fas fa-shopping-cart'></span>
</button>
{% endif %}
<button type='button' class='btn btn-default btn-glyph' id='edit-part' title='{% trans "Edit supplier part" %}'>
<span class='fas fa-edit icon-green'/>
</button>
{% if roles.purchase_order.delete %}
<button type='button' class='btn btn-default btn-glyph' id='delete-part' title='{% trans "Delete supplier part" %}'>
<span class='fas fa-trash-alt icon-red'/>
</button>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}
{% block page_details %}
<h4>{% trans "Supplier Part Details" %}</h4>
<table class="table table-striped table-condensed">
<col width='25'>
<tr>
<td><span class='fas fa-shapes'></span></td>
<td>{% trans "Internal Part" %}</td>
<td>
{% if part.part %}
<a href="{% url 'part-suppliers' part.part.id %}">{{ part.part.full_name }}</a>{% include "clip.html"%}
{% endif %}
</td>
</tr>
{% if part.description %}
<tr>
<td></td>
<td>{% trans "Description" %}</td>
<td>{{ part.description }}{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.link %}
<tr>
<td><span class='fas fa-link'></span></td>
<td>{% trans "External Link" %}</td>
<td><a href="{{ part.link }}">{{ part.link }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
<tr>
<td><span class='fas fa-building'></span></td>
<td>{% trans "Supplier" %}</td>
<td><a href="{% url 'company-detail-supplier-parts' part.supplier.id %}">{{ part.supplier.name }}</a>{% include "clip.html"%}</td></tr>
<tr>
<td><span class='fas fa-hashtag'></span></td>
<td>{% trans "SKU" %}</td>
<td>{{ part.SKU }}{% include "clip.html"%}</tr>
</tr>
{% if part.manufacturer_part.manufacturer %}
<tr>
<td><span class='fas fa-industry'></span></td>
<td>{% trans "Manufacturer" %}</td>
<td><a href="{% url 'company-detail-manufacturer-parts' part.manufacturer_part.manufacturer.id %}">
{{ part.manufacturer_part.manufacturer.name }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.manufacturer_part.MPN %}
<tr>
<td><span class='fas fa-hashtag'></span></td>
<td>{% trans "MPN" %}</td>
<td><a href="{% url 'manufacturer-part-detail' part.manufacturer_part.id %}">{{ part.manufacturer_part.MPN }}</a>{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.packaging %}
<tr>
<td><span class='fas fa-cube'></span></td>
<td>{% trans "Packaging" %}</td>
<td>{{ part.packaging }}{% include "clip.html"%}</td>
</tr>
{% endif %}
{% if part.note %}
<tr>
<td><span class='fas fa-sticky-note'></span></td>
<td>{% trans "Note" %}</td>
<td>{{ part.note }}{% include "clip.html"%}</td>
</tr>
{% endif %}
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableNavbar({
label: 'supplier-part',
toggleId: '#supplier-part-menu-toggle'
})
$('#order-part, #order-part2').click(function() {
launchModalForm(
"{% url 'order-parts' %}",
{
data: {
part: {{ part.part.id }},
},
reload: true,
},
);
});
$('#edit-part').click(function () {
launchModalForm(
"{% url 'supplier-part-edit' part.id %}",
{
reload: true
}
);
});
$('#delete-part').click(function() {
launchModalForm(
"{% url 'supplier-part-delete' %}?part={{ part.id }}",
{
redirect: "{% url 'company-detail-supplier-parts' part.supplier.id %}"
}
);
});
{% endblock %}

View File

@ -1,48 +0,0 @@
{% extends "company/supplier_part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "company/supplier_part_navbar.html" with tab='details' %}
{% endblock %}
{% block heading %}
{% trans "Supplier Part Details" %}
{% endblock %}
{% block details %}
<table class="table table-striped table-condensed">
<tr>
<td>{% trans "Internal Part" %}</td>
<td>
{% if part.part %}
<a href="{% url 'part-suppliers' part.part.id %}">{{ part.part.full_name }}</a>
{% endif %}
</td>
</tr>
<tr><td>{% trans "Supplier" %}</td><td><a href="{% url 'company-detail-supplier-parts' part.supplier.id %}">{{ part.supplier.name }}</a></td></tr>
<tr><td>{% trans "SKU" %}</td><td>{{ part.SKU }}</tr></tr>
{% if part.link %}
<tr><td>{% trans "External Link" %}</td><td><a href="{{ part.link }}">{{ part.link }}</a></td></tr>
{% endif %}
{% if part.description %}
<tr><td>{% trans "Description" %}</td><td>{{ part.description }}{% include "clip.html"%}</td></tr>
{% endif %}
{% if part.manufacturer %}
<tr><td>{% trans "Manufacturer" %}</td><td>{{ part.manufacturer }}{% include "clip.html"%}</td></tr>
<tr><td>{% trans "MPN" %}</td><td>{{ part.MPN }}{% include "clip.html"%}</td></tr>
{% endif %}
{% if part.note %}
<tr><td>{% trans "Note" %}</td><td>{{ part.note }}{% include "clip.html"%}</td></tr>
{% endif %}
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% endblock %}

View File

@ -9,22 +9,22 @@
</a>
</li>
<li class='list-group-item {% if tab == "stock" %}active{% endif %}' title='{% trans "Supplier Part Stock" %}'>
<a href='{% url "supplier-part-stock" part.id %}'>
<li class='list-group-item' title='{% trans "Supplier Part Stock" %}'>
<a href='#' id='select-stock' class='nav-toggle'>
<span class='fas fa-boxes sidebar-icon'></span>
{% trans "Stock" %}
</a>
</li>
<li class='list-group-item {% if tab == "orders" %}active{% endif %}' title='{% trans "Supplier Part Orders" %}'>
<a href='{% url "supplier-part-orders" part.id %}'>
<li class='list-group-item' title='{% trans "Supplier Part Orders" %}'>
<a href='#' id='select-purchase-orders' class='nav-toggle'>
<span class='fas fa-shopping-cart sidebar-icon'></span>
{% trans "Orders" %}
</a>
</li>
<li class='list-group-item {% if tab == "pricing" %}active{% endif %}' title='{% trans "Supplier Part Pricing" %}'>
<a href='{% url "supplier-part-pricing" part.id %}'>
<li class='list-group-item' title='{% trans "Supplier Part Pricing" %}'>
<a href='#' id='select-pricing' class='nav-toggle'>
<span class='fas fa-dollar-sign sidebar-icon'></span>
{% trans "Pricing" %}
</a>

View File

@ -1,35 +0,0 @@
{% extends "company/supplier_part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "company/supplier_part_navbar.html" with tab='orders' %}
{% endblock %}
{% block heading %}
{% trans "Supplier Part Orders" %}
{% endblock %}
{% block details %}
{% if roles.purchase_order.add %}
<div id='button-bar'>
<div class='btn-group'>
<button class='btn btn-primary' type='button' id='order-part2' title='{% trans "Order part" %}'>
<span class='fas fa-shopping-cart'></span> {% trans "Order Part" %}</button>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#button-bar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadPurchaseOrderTable($("#purchase-order-table"), {
url: "{% url 'api-po-list' %}?supplier_part={{ part.id }}",
});
{% endblock %}

View File

@ -1,124 +0,0 @@
{% extends "company/supplier_part_base.html" %}
{% load static %}
{% load i18n %}
{% load inventree_extras %}
{% block menubar %}
{% include "company/supplier_part_navbar.html" with tab='pricing' %}
{% endblock %}
{% block heading %}
{% trans "Pricing Information" %}
{% endblock %}
{% block details %}
{% if roles.purchase_order.add %}
<div id='price-break-toolbar' class='btn-group'>
<button class='btn btn-primary' id='new-price-break' type='button'>
<span class='fas fa-plus-circle'></span> {% trans "Add Price Break" %}
</button>
</div>
{% endif %}
<table class='table table-striped table-condensed' id='price-break-table' data-toolbar='#price-break-toolbar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
function reloadPriceBreaks() {
$("#price-break-table").bootstrapTable("refresh");
}
$('#price-break-table').inventreeTable({
name: 'buypricebreaks',
formatNoMatches: function() { return "{% trans "No price break information found" %}"; },
queryParams: {
part: {{ part.id }},
},
url: "{% url 'api-part-supplier-price-list' %}",
onPostBody: function() {
var table = $('#price-break-table');
table.find('.button-price-break-delete').click(function() {
var pk = $(this).attr('pk');
constructForm(`/api/company/price-break/${pk}/`, {
method: 'DELETE',
onSuccess: reloadPriceBreaks,
title: '{% trans "Delete Price Break" %}',
});
});
table.find('.button-price-break-edit').click(function() {
var pk = $(this).attr('pk');
constructForm(`/api/company/price-break/${pk}/`, {
fields: {
quantity: {},
price: {},
price_currency: {},
},
onSuccess: reloadPriceBreaks,
title: '{% trans "Edit Price Break" %}',
});
});
},
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-price-break-edit', row.pk, '{% trans "Edit price break" %}');
html += makeIconButton('fa-trash-alt icon-red', 'button-price-break-delete', row.pk, '{% trans "Delete price break" %}');
html += `</div>`;
return html;
}
},
]
});
$('#new-price-break').click(function() {
constructForm(
'{% url "api-part-supplier-price-list" %}',
{
method: 'POST',
fields: {
quantity: {},
part: {
value: {{ part.pk }},
hidden: true,
},
price: {},
price_currency: {
},
},
title: '{% trans "Add Price Break" %}',
onSuccess: reloadPriceBreaks,
}
);
});
{% endblock %}

View File

@ -1,58 +0,0 @@
{% extends "company/supplier_part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "company/supplier_part_navbar.html" with tab='stock' %}
{% endblock %}
{% block heading %}
{% trans "Supplier Part Stock" %}
{% endblock %}
{% block details %}
{% include "stock_table.html" %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadStockTable($("#stock-table"), {
params: {
supplier_part: {{ part.id }},
location_detail: true,
part_detail: false,
},
groupByField: 'location',
buttons: ['#stock-options'],
url: "{% url 'api-stock-list' %}",
});
$("#stock-export").click(function() {
launchModalForm("{% url 'stock-export-options' %}", {
submit_text: '{% trans "Export" %}',
success: function(response) {
var url = "{% url 'stock-export' %}";
url += "?format=" + response.format;
url += "&cascade=" + response.cascade;
url += "&supplier_part={{ part.id }}";
location.href = url;
},
});
});
$("#item-create").click(function() {
createNewStockItem({
data: {
part: {{ part.part.id }},
supplier_part: {{ part.id }},
},
reload: true,
});
});
{% endblock %}

View File

@ -8,15 +8,6 @@ from . import views
company_detail_urls = [
# url(r'orders/?', views.CompanyDetail.as_view(template_name='company/orders.html'), name='company-detail-orders'),
url(r'^supplier-parts/', views.CompanyDetail.as_view(template_name='company/detail_supplier_part.html'), name='company-detail-supplier-parts'),
url(r'^manufacturer-parts/', views.CompanyDetail.as_view(template_name='company/detail_manufacturer_part.html'), name='company-detail-manufacturer-parts'),
url(r'^stock/', views.CompanyDetail.as_view(template_name='company/detail_stock.html'), name='company-detail-stock'),
url(r'^purchase-orders/', views.CompanyDetail.as_view(template_name='company/purchase_orders.html'), name='company-detail-purchase-orders'),
url(r'^assigned-stock/', views.CompanyDetail.as_view(template_name='company/assigned_stock.html'), name='company-detail-assigned-stock'),
url(r'^sales-orders/', views.CompanyDetail.as_view(template_name='company/sales_orders.html'), name='company-detail-sales-orders'),
url(r'^notes/', views.CompanyNotes.as_view(), name='company-notes'),
url(r'^thumb-download/', views.CompanyImageDownloadFromURL.as_view(), name='company-image-download'),
@ -40,20 +31,14 @@ company_urls = [
manufacturer_part_urls = [
url(r'^(?P<pk>\d+)/', include([
url(r'^suppliers/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part_suppliers.html'), name='manufacturer-part-suppliers'),
url('^.*$', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part_suppliers.html'), name='manufacturer-part-detail'),
url('^.*$', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part.html'), name='manufacturer-part-detail'),
])),
]
supplier_part_detail_urls = [
url(r'^edit/?', views.SupplierPartEdit.as_view(), name='supplier-part-edit'),
url(r'^manufacturers/', views.SupplierPartDetail.as_view(template_name='company/supplier_part_manufacturers.html'), name='supplier-part-manufacturers'),
url(r'^pricing/', views.SupplierPartDetail.as_view(template_name='company/supplier_part_pricing.html'), name='supplier-part-pricing'),
url(r'^orders/', views.SupplierPartDetail.as_view(template_name='company/supplier_part_orders.html'), name='supplier-part-orders'),
url(r'^stock/', views.SupplierPartDetail.as_view(template_name='company/supplier_part_stock.html'), name='supplier-part-stock'),
url('^.*$', views.SupplierPartDetail.as_view(template_name='company/supplier_part_pricing.html'), name='supplier-part-detail'),
url('^.*$', views.SupplierPartDetail.as_view(template_name='company/supplier_part.html'), name='supplier-part-detail'),
]
supplier_part_urls = [

View File

@ -7,7 +7,7 @@ Django views for interacting with Company app
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django.views.generic import DetailView, ListView, UpdateView
from django.views.generic import DetailView, ListView
from django.urls import reverse
from django.forms import HiddenInput
@ -113,28 +113,6 @@ class CompanyIndex(InvenTreeRoleMixin, ListView):
return queryset
class CompanyNotes(UpdateView):
""" View for editing the 'notes' field of a Company object.
"""
context_object_name = 'company'
template_name = 'company/notes.html'
model = Company
fields = ['notes']
permission_required = 'company.view_company'
def get_success_url(self):
return reverse('company-notes', kwargs={'pk': self.get_object().id})
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['editing'] = str2bool(self.request.GET.get('edit', ''))
return ctx
class CompanyDetail(DetailView):
""" Detail view for Company object """
context_obect_name = 'company'

View File

@ -145,10 +145,6 @@ src="{% static 'img/blank_image.png' %}"
{% block js_ready %}
{{ block.super }}
enableNavbar({
label: 'po',
toggleId: '#po-menu-toggle',
});
{% if order.status == PurchaseOrderStatus.PENDING and order.lines.count > 0 %}
$("#place-order").click(function() {

View File

@ -1,54 +0,0 @@
{% extends "order/order_base.html" %}
{% load inventree_extras %}
{% load i18n %}
{% load static %}
{% load markdownify %}
{% block menubar %}
{% include 'order/po_navbar.html' with tab='notes' %}
{% endblock %}
{% block heading %}
{% trans "Order Notes" %}
{% if roles.purchase_order.change and not editing %}
<button title='{% trans "Edit notes" %}' class='btn btn-default' id='edit-notes'><span class='fas fa-edit'></span></button>
{% endif %}
{% endblock %}
{% block details %}
{% if editing %}
<form method='POST'>
{% csrf_token %}
{{ form }}
<hr>
<button type="submit" class='btn btn-default'>{% trans "Save" %}</button>
</form>
{{ form.media }}
{% else %}
<div class='panel panel-default'>
<div class='panel-content'>
{{ order.notes | markdownify }}
</div>
</div>
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% if editing %}
{% else %}
$("#edit-notes").click(function() {
location.href = "{% url 'po-notes' order.id %}?edit=1";
});
{% endif %}
{% endblock %}

View File

@ -3,10 +3,6 @@
{% load i18n %}
{% load static %}
{% block menubar %}
{% include 'order/po_navbar.html' with tab='upload' %}
{% endblock %}
{% block heading %}
{% trans "Upload File for Purchase Order" %}
{{ wizard.form.media }}

View File

@ -1,83 +0,0 @@
{% extends "order/order_base.html" %}
{% load inventree_extras %}
{% load i18n %}
{% load static %}
{% block menubar %}
{% include 'order/po_navbar.html' with tab='attachments' %}
{% endblock %}
{% block heading %}
{% trans "Purchase Order Attachments" %}
{% endblock %}
{% block details %}
{% include "attachment_table.html" with attachments=order.attachments.all %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableDragAndDrop(
'#attachment-dropzone',
'{% url "api-po-attachment-list" %}',
{
data: {
order: {{ order.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
location.reload();
}
}
);
loadAttachmentTable(
'{% url "api-po-attachment-list" %}',
{
filters: {
order: {{ order.pk }},
},
onEdit: function(pk) {
var url = `/api/order/po/attachment/${pk}/`;
constructForm(url, {
fields: {
comment: {},
},
onSuccess: reloadAttachmentTable,
title: '{% trans "Edit Attachment" %}',
});
},
onDelete: function(pk) {
constructForm(`/api/order/po/attachment/${pk}/`, {
method: 'DELETE',
confirmMessage: '{% trans "Confirm Delete Operation" %}',
title: '{% trans "Delete Attachment" %}',
onSuccess: reloadAttachmentTable,
});
}
}
);
$("#new-attachment").click(function() {
constructForm('{% url "api-po-attachment-list" %}', {
method: 'POST',
fields: {
attachment: {},
comment: {},
order: {
value: {{ order.pk }},
hidden: true,
},
},
reload: true,
title: '{% trans "Add Attachment" %}',
});
});
{% endblock %}

View File

@ -9,34 +9,34 @@
<span class='menu-tab-icon fas fa-expand-arrows-alt'></span>
</a>
</li>
<li class='list-group-item {% if tab == "details" %}active{% endif %}' title='{% trans "Purchase Order Details" %}'>
<a href='{% url "po-detail" order.id %}'>
<span class='fas fa-info-circle side-icon'></span>
{% trans "Details" %}
<li class='list-group-item' title='{% trans "Purchase Order Line Items" %}'>
<a href='#' id='select-order-items' class='nav-toggle'>
<span class='fas fa-list-ol side-icon'></span>
{% trans "Order Items" %}
</a>
</li>
{% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %}
<li class='list-group-item {% if tab == "upload" %}active{% endif %}' title='{% trans "Upload File" %}'>
<li class='list-group-item' title='{% trans "Upload File" %}'>
<a href='{% url "po-upload" order.id %}'>
<span class='fas fa-file-upload side-icon'></span>
{% trans "Upload File" %}
</a>
</li>
{% endif %}
<li class='list-group-item {% if tab == "received" %}active{% endif %}' title='{% trans "Received Stock Items" %}'>
<a href='{% url "po-received" order.id %}'>
<li class='list-group-item' title='{% trans "Received Stock Items" %}'>
<a href='#' id='select-received-items' class='nav-toggle'>
<span class='fas fa-sign-in-alt side-icon'></span>
{% trans "Received Items" %}
</a>
</li>
<li class='list-group-item {% if tab == "attachments" %}active{% endif %}' title='{% trans "Purchase Order Attachments" %}'>
<a href='{% url "po-attachments" order.id %}'>
<li class='list-group-item' title='{% trans "Purchase Order Attachments" %}'>
<a href='#' id='select-order-attachments' class='nav-toggle'>
<span class='fas fa-paperclip side-icon'></span>
{% trans "Attachments" %}
</a>
</li>
<li class='list-group-item {% if tab == "notes" %}active{% endif %}' title='{% trans "Notes" %}'>
<a href='{% url "po-notes" order.id %}'>
<li class='list-group-item' title='{% trans "Notes" %}'>
<a href='#' id='select-order-notes' class='nav-toggle'>
<span class='fas fa-clipboard side-icon'></span>
{% trans "Notes" %}
</a>

View File

@ -1,37 +0,0 @@
{% extends "order/order_base.html" %}
{% load inventree_extras %}
{% load i18n %}
{% load static %}
{% block menubar %}
{% include 'order/po_navbar.html' with tab='received' %}
{% endblock %}
{% block heading %}
{% trans "Received Items" %}
{% endblock %}
{% block details %}
{% include "stock_table.html" with read_only=True %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadStockTable($("#stock-table"), {
params: {
purchase_order: {{ order.id }},
part_detail: true,
supplier_part_detail: true,
location_detail: true,
},
buttons: [
'#stock-options',
],
filterkey: "postock"
});
{% endblock %}

View File

@ -4,31 +4,72 @@
{% load status_codes %}
{% load i18n %}
{% load static %}
{% load markdownify %}
{% block menubar %}
{% include 'order/po_navbar.html' with tab='details' %}
{% include 'order/po_navbar.html' %}
{% endblock %}
{% block heading %}
{% trans "Purchase Order Items" %}
{% endblock %}
{% block page_content %}
{% block details %}
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
{% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %}
<button type='button' class='btn btn-primary' id='new-po-line'>
<span class='fas fa-plus-circle'></span> {% trans "Add Line Item" %}
</button>
{% endif %}
<div class='panel panel-default panel-inventree panel-hidden' id='panel-order-items'>
<div class='panel-heading'>
<h4>{% trans "Purchase Order Items" %}</h4>
</div>
<div class='panel-content'>
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
{% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %}
<button type='button' class='btn btn-primary' id='new-po-line'>
<span class='fas fa-plus-circle'></span> {% trans "Add Line Item" %}
</button>
{% endif %}
</div>
<table class='table table-striped table-condensed' id='po-table' data-toolbar='#order-toolbar-buttons'>
</table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-received-items'>
<div class='panel-heading'>
<h4>{% trans "Received Items" %}</h4>
</div>
<div class='panel-content'>
{% include "stock_table.html" with read_only=True %}
</div>
</div>
<table class='table table-striped table-condensed' id='po-table' data-toolbar='#order-toolbar-buttons'>
</table>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-order-attachments'>
<div class='panel-heading'>
<h4>{% trans "Purchase Order Attachments" %}</h4>
</div>
<div class='panel-content'>
{% include "attachment_table.html" %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-order-notes'>
<div class='panel-heading'>
<div class='row'>
<div class='col-sm-6'>
<h4>{% trans "Order Notes" %}</h4>
</div>
<div class='col-sm-6'>
<div class='btn-group float-right'>
<button type='button' id='edit-notes' title='{% trans "Edit Notes" %}' class='btn btn-small btn-default'>
<span class='fas fa-edit'>
</span>
</button>
</div>
</div>
</div>
</div>
<div class='panel-content'>
{% if order.notes %}
{{ order.notes | markdownify }}
{% endif %}
</div>
</div>
{% endblock %}
@ -36,6 +77,96 @@
{{ block.super }}
enableNavbar({
label: 'po',
toggleId: '#po-menu-toggle',
});
$('#edit-notes').click(function() {
constructForm('{% url "api-po-detail" order.pk %}', {
fields: {
notes: {
multiline: true,
}
},
title: '{% trans "Edit Notes" %}',
reload: true,
});
});
enableDragAndDrop(
'#attachment-dropzone',
'{% url "api-po-attachment-list" %}',
{
data: {
order: {{ order.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
location.reload();
}
}
);
loadAttachmentTable(
'{% url "api-po-attachment-list" %}',
{
filters: {
order: {{ order.pk }},
},
onEdit: function(pk) {
var url = `/api/order/po/attachment/${pk}/`;
constructForm(url, {
fields: {
comment: {},
},
onSuccess: reloadAttachmentTable,
title: '{% trans "Edit Attachment" %}',
});
},
onDelete: function(pk) {
constructForm(`/api/order/po/attachment/${pk}/`, {
method: 'DELETE',
confirmMessage: '{% trans "Confirm Delete Operation" %}',
title: '{% trans "Delete Attachment" %}',
onSuccess: reloadAttachmentTable,
});
}
}
);
$("#new-attachment").click(function() {
constructForm('{% url "api-po-attachment-list" %}', {
method: 'POST',
fields: {
attachment: {},
comment: {},
order: {
value: {{ order.pk }},
hidden: true,
},
},
reload: true,
title: '{% trans "Add Attachment" %}',
});
});
loadStockTable($("#stock-table"), {
params: {
purchase_order: {{ order.id }},
part_detail: true,
supplier_part_detail: true,
location_detail: true,
},
buttons: [
'#stock-options',
],
filterkey: "postock"
});
{% if order.status == PurchaseOrderStatus.PENDING %}
$('#new-po-line').click(function() {
@ -301,4 +432,9 @@ $("#po-table").inventreeTable({
]
});
attachNavCallbacks({
name: 'purchase-order',
default: 'order-items'
});
{% endblock %}

View File

@ -4,38 +4,158 @@
{% load status_codes %}
{% load i18n %}
{% load static %}
{% load markdownify %}
{% block menubar %}
{% include "order/so_navbar.html" with tab='details' %}
{% include "order/so_navbar.html" %}
{% endblock %}
{% block heading %}
{% trans "Sales Order Items" %}
{% endblock %}
{% block page_content %}
{% block details %}
{% if roles.sales_order.change %}
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
<button type='button' class='btn btn-success' id='new-so-line'>
<span class='fas fa-plus-circle'></span> {% trans "Add Line Item" %}
</button>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-order-items'>
<div class='panel-heading'>
<h4>{% trans "Sales Order Items" %}</h4>
</div>
<div class='panel-content'>
{% if roles.sales_order.change %}
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
<button type='button' class='btn btn-success' id='new-so-line'>
<span class='fas fa-plus-circle'></span> {% trans "Add Line Item" %}
</button>
</div>
{% endif %}
<table class='table table-striped table-condensed' id='so-lines-table' data-toolbar='#order-toolbar-buttons'>
</table>
</div>
</div>
{% endif %}
<table class='table table-striped table-condensed' id='so-lines-table' data-toolbar='#order-toolbar-buttons'>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-order-builds'>
<div class='panel-heading'>
<h4>{% trans "Build Orders" %}</h4>
</div>
<div class='panel-content'>
<table class='table table-striped table-condensed' id='builds-table'></table>
</div>
</div>
</table>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-order-attachments'>
<div class='panel-heading'>
<h4>{% trans "Attachments" %}</h4>
</div>
<div class='panel-content'>
{% include "attachment_table.html" %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-order-notes'>
<div class='panel-heading'>
<div class='row'>
<div class='col-sm-6'>
<h4>{% trans "Order Notes" %}</h4>
</div>
<div class='col-sm-6'>
<div class='btn-group float-right'>
<button type='button' id='edit-notes' title='{% trans "Edit Notes" %}' class='btn btn-small btn-default'>
<span class='fas fa-edit'>
</span>
</button>
</div>
</div>
</div>
</div>
<div class='panel-content'>
{% if order.notes %}
{{ order.notes | markdownify }}
{% endif %}
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
function reloadTable() {
$("#so-lines-table").bootstrapTable("refresh");
}
$('#edit-notes').click(function() {
constructForm('{% url "api-so-detail" order.pk %}', {
fields: {
notes: {
multiline: true,
}
},
title: '{% trans "Edit Notes" %}',
reload: true,
});
});
enableDragAndDrop(
'#attachment-dropzone',
'{% url "api-so-attachment-list" %}',
{
data: {
order: {{ order.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
location.reload();
}
}
);
loadAttachmentTable(
'{% url "api-so-attachment-list" %}',
{
filters: {
order: {{ order.pk }},
},
onEdit: function(pk) {
var url = `/api/order/so/attachment/${pk}/`;
constructForm(url, {
fields: {
comment: {},
},
onSuccess: reloadAttachmentTable,
title: '{% trans "Edit Attachment" %}',
});
},
onDelete: function(pk) {
constructForm(`/api/order/so/attachment/${pk}/`, {
method: 'DELETE',
confirmMessage: '{% trans "Confirm Delete Operation" %}',
title: '{% trans "Delete Attachment" %}',
onSuccess: reloadAttachmentTable,
});
}
}
);
$("#new-attachment").click(function() {
constructForm('{% url "api-so-attachment-list" %}', {
method: 'POST',
fields: {
attachment: {},
comment: {},
order: {
value: {{ order.pk }},
hidden: true
}
},
onSuccess: reloadAttachmentTable,
title: '{% trans "Add Attachment" %}'
});
});
loadBuildTable($("#builds-table"), {
url: "{% url 'api-build-list' %}",
params: {
sales_order: {{ order.id }},
},
});
function reloadTable() {
$("#so-lines-table").bootstrapTable("refresh");
}
$("#new-so-line").click(function() {
@ -493,6 +613,11 @@ function setupCallbacks() {
}
);
});
attachNavCallbacks({
name: 'sales-order',
default: 'order-items'
});
}
{% endblock %}

View File

@ -1,56 +0,0 @@
{% extends "order/sales_order_base.html" %}
{% load inventree_extras %}
{% load i18n %}
{% load static %}
{% load markdownify %}
{% load status_codes %}
{% block menubar %}
{% include 'order/so_navbar.html' with tab='notes' %}
{% endblock %}
{% block heading %}
{% trans "Sales Order Notes" %}
{% if roles.sales_order.change and not editing %}
<button title='{% trans "Edit notes" %}' class='btn btn-default' id='edit-notes'><span class='fas fa-edit'></span></button>
{% endif %}
{% endblock %}
{% block details %}
{% if editing %}
<form method='POST'>
{% csrf_token %}
{{ form }}
<hr>
<button type="submit" class='btn btn-default'>{% trans "Save" %}</button>
</form>
{{ form.media }}
{% else %}
<div class='panel panel-default'>
<div class='panel-content'>
{{ order.notes | markdownify }}
</div>
</div>
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% if editing %}
{% else %}
$("#edit-notes").click(function() {
location.href = "{% url 'so-notes' order.id %}?edit=1";
});
{% endif %}
{% endblock %}

View File

@ -1,83 +0,0 @@
{% extends "order/sales_order_base.html" %}
{% load inventree_extras %}
{% load i18n %}
{% load static %}
{% block menubar %}
{% include 'order/so_navbar.html' with tab='attachments' %}
{% endblock %}
{% block heading %}
{% trans "Sales Order Attachments" %}
{% endblock %}
{% block details %}
{% include "attachment_table.html" with attachments=order.attachments.all %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableDragAndDrop(
'#attachment-dropzone',
'{% url "api-so-attachment-list" %}',
{
data: {
order: {{ order.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
location.reload();
}
}
);
loadAttachmentTable(
'{% url "api-so-attachment-list" %}',
{
filters: {
order: {{ order.pk }},
},
onEdit: function(pk) {
var url = `/api/order/so/attachment/${pk}/`;
constructForm(url, {
fields: {
comment: {},
},
onSuccess: reloadAttachmentTable,
title: '{% trans "Edit Attachment" %}',
});
},
onDelete: function(pk) {
constructForm(`/api/order/so/attachment/${pk}/`, {
method: 'DELETE',
confirmMessage: '{% trans "Confirm Delete Operation" %}',
title: '{% trans "Delete Attachment" %}',
onSuccess: reloadAttachmentTable,
});
}
}
);
$("#new-attachment").click(function() {
constructForm('{% url "api-so-attachment-list" %}', {
method: 'POST',
fields: {
attachment: {},
comment: {},
order: {
value: {{ order.pk }},
hidden: true
}
},
onSuccess: reloadAttachmentTable,
title: '{% trans "Add Attachment" %}'
});
});
{% endblock %}

View File

@ -1,33 +0,0 @@
{% extends "order/sales_order_base.html" %}
{% load inventree_extras %}
{% load i18n %}
{% load static %}
{% block menubar %}
{% include 'order/so_navbar.html' with tab='builds' %}
{% endblock %}
{% block heading %}
{% trans "Build Orders" %}
{% endblock %}
{% block details %}
<table class='table table-striped table-condensed' id='builds-table'></table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadBuildTable($("#builds-table"), {
url: "{% url 'api-build-list' %}",
params: {
sales_order: {{ order.id }},
},
});
{% endblock %}

View File

@ -9,29 +9,29 @@
</a>
</li>
<li class='list-group-item {% if tab == "details" %}active{% endif %}' title='{% trans "Sales Order Details" %}'>
<a href='{% url "so-detail" order.id %}'>
<span class='fas fa-info-circle sidebar-icon'></span>
{% trans "Details" %}
<li class='list-group-item' title='{% trans "Sales Order Line Items" %}'>
<a href='#' id='select-order-items' class='nav-toggle'>
<span class='fas fa-list-ol sidebar-icon'></span>
{% trans "Order Items" %}
</a>
</li>
<li class='list-group-item {% if tab == "builds" %}active{% endif %}' title='{% trans "Build Orders" %}'>
<a href='{% url "so-builds" order.id %}'>
<li class='list-group-item' title='{% trans "Build Orders" %}'>
<a href='#' id='select-order-builds' class='nav-toggle'>
<span class='fas fa-tools sidebar-icon'></span>
{% trans "Build Orders" %}
</a>
</li>
<li class='list-group-item {% if tab == "attachments" %}active{% endif %}' title='{% trans "Sales Order Attachments" %}'>
<a href='{% url "so-attachments" order.id %}'>
<li class='list-group-item' title='{% trans "Sales Order Attachments" %}'>
<a href='#' id='select-order-attachments' class='nav-toggle'>
<span class='fas fa-paperclip sidebar-icon'></span>
{% trans "Attachments" %}
</a>
</li>
<li class='list-group-item {% if tab == "notes" %}active{% endif %}' title='{% trans "Notes" %}'>
<a href='{% url "so-notes" order.id %}'>
<li class='list-group-item' title='{% trans "Notes" %}'>
<a href='#' id='select-order-notes' class='nav-toggle'>
<span class='fas fa-clipboard sidebar-icon'></span>
{% trans "Notes" %}
</a>

View File

@ -19,10 +19,6 @@ purchase_order_detail_urls = [
url(r'^upload/', views.PurchaseOrderUpload.as_view(), name='po-upload'),
url(r'^export/', views.PurchaseOrderExport.as_view(), name='po-export'),
url(r'^notes/', views.PurchaseOrderNotes.as_view(), name='po-notes'),
url(r'^received/', views.PurchaseOrderDetail.as_view(template_name='order/po_received_items.html'), name='po-received'),
url(r'^attachments/', views.PurchaseOrderDetail.as_view(template_name='order/po_attachments.html'), name='po-attachments'),
url(r'^.*$', views.PurchaseOrderDetail.as_view(), name='po-detail'),
]
@ -42,10 +38,6 @@ sales_order_detail_urls = [
url(r'^cancel/', views.SalesOrderCancel.as_view(), name='so-cancel'),
url(r'^ship/', views.SalesOrderShip.as_view(), name='so-ship'),
url(r'^builds/', views.SalesOrderDetail.as_view(template_name='order/so_builds.html'), name='so-builds'),
url(r'^attachments/', views.SalesOrderDetail.as_view(template_name='order/so_attachments.html'), name='so-attachments'),
url(r'^notes/', views.SalesOrderNotes.as_view(), name='so-notes'),
url(r'^.*$', views.SalesOrderDetail.as_view(), name='so-detail'),
]

View File

@ -13,7 +13,7 @@ from django.core.exceptions import ValidationError
from django.urls import reverse
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext_lazy as _
from django.views.generic import DetailView, ListView, UpdateView
from django.views.generic import DetailView, ListView
from django.views.generic.edit import FormMixin
from django.forms import HiddenInput, IntegerField
@ -97,53 +97,6 @@ class SalesOrderDetail(InvenTreeRoleMixin, DetailView):
template_name = 'order/sales_order_detail.html'
class PurchaseOrderNotes(InvenTreeRoleMixin, UpdateView):
""" View for updating the 'notes' field of a PurchaseOrder """
context_object_name = 'order'
template_name = 'order/order_notes.html'
model = PurchaseOrder
# Override the default permission roles
role_required = 'purchase_order.view'
fields = ['notes']
def get_success_url(self):
return reverse('po-notes', kwargs={'pk': self.get_object().id})
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['editing'] = str2bool(self.request.GET.get('edit', False))
return ctx
class SalesOrderNotes(InvenTreeRoleMixin, UpdateView):
""" View for editing the 'notes' field of a SalesORder """
context_object_name = 'order'
template_name = 'order/sales_order_notes.html'
model = SalesOrder
role_required = 'sales_order.view'
fields = ['notes']
def get_success_url(self):
return reverse('so-notes', kwargs={'pk': self.get_object().pk})
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['editing'] = str2bool(self.request.GET.get('edit', False))
return ctx
class PurchaseOrderCancel(AjaxUpdateView):
""" View for cancelling a purchase order """

View File

@ -1104,7 +1104,7 @@ part_api_urls = [
url(r'^(?P<pk>\d+)/?', PartThumbsUpdate.as_view(), name='api-part-thumbs-update'),
])),
url(r'^(?P<pk>\d+)/?', PartDetail.as_view(), name='api-part-detail'),
url(r'^(?P<pk>\d+)/', PartDetail.as_view(), name='api-part-detail'),
url(r'^.*$', PartList.as_view(), name='api-part-list'),
]

View File

@ -1,50 +0,0 @@
{% extends "part/part_base.html" %}
{% load status_codes %}
{% load i18n %}
{% load inventree_extras %}
{% block menubar %}
{% include "part/navbar.html" with tab="allocation" %}
{% endblock %}
{% block heading %}
{% trans "Build Order Allocations" %}
{% endblock %}
{% block details %}
<table class='table table-striped table-condensed' id='build-order-table'></table>
{% endblock %}
{% block pre_content_panel %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>{% trans "Sales Order Allocations" %}</h4>
</div>
<div class='panel-content'>
<table class='table table-striped table-condensed' id='sales-order-table'></table>
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadSalesOrderAllocationTable("#sales-order-table", {
params: {
part: {{ part.id }},
}
});
loadBuildOrderAllocationTable("#build-order-table", {
params: {
part: {{ part.id }},
}
});
{% endblock %}

View File

@ -1,16 +1,5 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='bom' %}
{% endblock %}
{% block heading %}
{% trans "Bill of Materials" %}
{% endblock %}
{% block details %}
{% load inventree_extras %}
{% if roles.part.change != True and editing_enabled %}
<div class='alert alert-danger alert-block'>
@ -32,7 +21,7 @@
</div>
{% endif %}
<div id='button-toolbar'>
<div id='bom-button-toolbar'>
<div class="btn-group" role="group" aria-label="...">
{% if editing_enabled %}
<button class='btn btn-default' type='button' title='{% trans "Remove selected BOM items" %}' id='bom-item-delete'>
@ -76,131 +65,6 @@
</div>
</div>
<table class='table table-bom table-condensed' data-toolbar="#button-toolbar" id='bom-table'>
<table class='table table-bom table-condensed' data-toolbar="#bom-button-toolbar" id='bom-table'>
</table>
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
// Load the BOM table data
loadBomTable($("#bom-table"), {
editable: {{ editing_enabled }},
bom_url: "{% url 'api-bom-list' %}",
part_url: "{% url 'api-part-list' %}",
parent_id: {{ part.id }} ,
sub_part_detail: true,
});
linkButtonsToSelection($("#bom-table"),
[
"#bom-item-delete",
]
);
{% if editing_enabled %}
$("#editing-finished").click(function() {
location.href = "{% url 'part-bom' part.id %}";
});
$('#bom-item-delete').click(function() {
// Get a list of the selected BOM items
var rows = $("#bom-table").bootstrapTable('getSelections');
// TODO - In the future, display (in the dialog) which items are going to be deleted
showQuestionDialog(
'{% trans "Delete selected BOM items?" %}',
'{% trans "All selected BOM items will be deleted" %}',
{
accept: function() {
// Keep track of each DELETE request
var requests = [];
rows.forEach(function(row) {
requests.push(
inventreeDelete(
`/api/bom/${row.pk}/`,
)
);
});
// Wait for *all* the requests to complete
$.when.apply($, requests).then(function() {
location.reload();
});
}
}
);
});
$('#bom-upload').click(function() {
location.href = "{% url 'upload-bom' part.id %}";
});
$('#bom-duplicate').click(function() {
launchModalForm(
"{% url 'duplicate-bom' part.id %}",
{
success: function() {
$('#bom-table').bootstrapTable('refresh');
}
}
);
});
$("#bom-item-new").click(function () {
launchModalForm(
"{% url 'bom-item-create' %}?parent={{ part.id }}",
{
success: function() {
$("#bom-table").bootstrapTable('refresh');
},
secondary: [
{
field: 'sub_part',
label: '{% trans "New Part" %}',
title: '{% trans "Create New Part" %}',
url: "{% url 'part-create' %}",
},
]
}
);
});
{% else %}
$("#validate-bom").click(function() {
launchModalForm(
"{% url 'bom-validate' part.id %}",
{
reload: true,
}
);
});
$("#edit-bom").click(function () {
location.href = "{% url 'part-bom' part.id %}?edit=1";
});
$("#download-bom").click(function () {
launchModalForm("{% url 'bom-export' part.id %}",
{
success: function(response) {
location.href = response.url;
},
}
);
});
{% endif %}
$("#print-bom-report").click(function() {
printBomReports([{{ part.pk }}]);
});
{% endblock %}
{% endif %}

View File

@ -3,15 +3,13 @@
{% load i18n %}
{% load inventree_extras %}
{% block menubar %}
{% include "part/navbar.html" with tab='bom' %}
{% endblock %}
{% block heading %}
{% trans "Upload BOM File" %}
{% endblock %}
{% block details %}
{% block page_content %}
<h4>{% trans "Upload Bill of Materials" %}</h4>
{% block form_alert %}
<div class='alert alert-info alert-block'>

View File

@ -1,48 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='build' %}
{% endblock %}
{% block heading %}
{% trans "Part Builds" %}
{% endblock %}
{% block details %}
<div id='button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right';>
{% if part.active %}
{% if roles.build.add %}
<button class="btn btn-success" id='start-build'><span class='fas fa-tools'></span> {% trans "Start New Build" %}</button>
{% endif %}
{% endif %}
<div class='filter-list' id='filter-list-build'>
<!-- Empty div for filters -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='build-table'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
$("#start-build").click(function() {
newBuildOrder({
part: {{ part.pk }},
});
});
loadBuildTable($("#build-table"), {
url: "{% url 'api-build-list' %}",
params: {
part: {{ part.id }},
}
});
{% endblock %}

View File

@ -3,7 +3,7 @@
{% load i18n %}
{% block menubar %}
{% include 'part/category_navbar.html' with tab='parts' %}
{% include 'part/category_navbar.html' %}
{% endblock %}
{% block content %}
@ -115,63 +115,81 @@
</div>
{% block category_content %}
{% block page_content %}
<div id='button-toolbar'>
<div class='btn-group'>
<button class='btn btn-default' id='part-export' title='{% trans "Export Part Data" %}'>
<span class='fas fa-file-download'></span> {% trans "Export" %}
</button>
{% if roles.part.add %}
<button class='btn btn-success' id='part-create' title='{% trans "Create new part" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Part" %}
</button>
{% endif %}
<div class='panel panel-default panel-inventree panel-hidden' id='panel-parts'>
<div class='panel-heading'>
<h4>{% trans "Parts" %}</h4>
</div>
<div id='part-button-toolbar'>
<div class='btn-group'>
<button id='part-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown">{% trans "Options" %}<span class='caret'></span></button>
<ul class='dropdown-menu'>
{% if roles.part.change %}
<li><a href='#' id='multi-part-category' title='{% trans "Set category" %}'>{% trans "Set Category" %}</a></li>
{% endif %}
<li><a href='#' id='multi-part-order' title='{% trans "Order parts" %}'>{% trans "Order Parts" %}</a></li>
<li><a href='#' id='multi-part-export' title='{% trans "Export" %}'>{% trans "Export Data" %}</a></li>
</ul>
</div>
<!-- Buttons to toggle between grid and table view -->
<button id='view-list' class='btn btn-default' type='button' title='{% trans "View list display" %}'>
<span class='fas fa-th-list'></span>
</button>
<button id='view-grid' class='btn btn-default' type='button' title='{% trans "View grid display" %}'>
<span class='fas fa-th'></span>
</button>
<div class='filter-list' id='filter-list-parts'>
<!-- Empty div -->
<button class='btn btn-default' id='part-export' title='{% trans "Export Part Data" %}'>
<span class='fas fa-file-download'></span> {% trans "Export" %}
</button>
{% if roles.part.add %}
<button class='btn btn-success' id='part-create' title='{% trans "Create new part" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Part" %}
</button>
{% endif %}
<div class='btn-group'>
<button id='part-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown">{% trans "Options" %}<span class='caret'></span></button>
<ul class='dropdown-menu'>
{% if roles.part.change %}
<li><a href='#' id='multi-part-category' title='{% trans "Set category" %}'>{% trans "Set Category" %}</a></li>
{% endif %}
<li><a href='#' id='multi-part-order' title='{% trans "Order parts" %}'>{% trans "Order Parts" %}</a></li>
<li><a href='#' id='multi-part-export' title='{% trans "Export" %}'>{% trans "Export Data" %}</a></li>
</ul>
</div>
<!-- Buttons to toggle between grid and table view -->
<button id='view-list' class='btn btn-default' type='button' title='{% trans "View list display" %}'>
<span class='fas fa-th-list'></span>
</button>
<button id='view-grid' class='btn btn-default' type='button' title='{% trans "View grid display" %}'>
<span class='fas fa-th'></span>
</button>
<div class='filter-list' id='filter-list-parts'>
<!-- Empty div -->
</div>
</div>
</div>
<div class='panel-content'>
<table class='table table-striped table-condensed' data-toolbar='#part-button-toolbar' id='part-table'>
</table>
</div>
</div>
<div class='panel panel-default panel-inventree'>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-parameters'>
<div class='panel-heading'>
<h4>
{% block heading %}
{% trans "Parts" %}
{% endblock %}
</h4>
<h4>{% trans "Part Parameters" %}</h4>
</div>
<div class='panel-content'>
{% block details %}
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='part-table'>
</table>
{% endblock %}
<div class='panel-content'>
<table class='table table-striped table-condensed' data-toolbar='#param-button-toolbar' id='parametric-part-table'>
</table>
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-subcategories'>
<div class='panel-heading'>
<h4>{% trans "Subcategories" %}</h4>
</div>
<div class='panel-content'>
<div id='subcategory-button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<div class='filter-list' id='filter-list-category'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' id='subcategory-table' data-toolbar='#subcategory-button-toolbar'></table>
</div>
</div>
{% endblock %}
{% block category_tables %}
{% endblock category_tables %}
{% endblock %}
{% block js_load %}
{{ block.super }}
@ -180,6 +198,26 @@
{% block js_ready %}
{{ block.super }}
loadPartCategoryTable($('#subcategory-table'), {
params: {
{% if category %}
parent: {{ category.pk }}
{% else %}
parent: 'null'
{% endif %}
}
});
{% if category %}
loadParametricPartTable(
"#parametric-part-table",
{
headers: {{ headers|safe }},
data: {{ parameters|safe }},
}
);
{% endif %}
enableNavbar({
label: 'category',
toggleId: '#category-menu-toggle',
@ -206,11 +244,11 @@
"{% url 'category-create' %}",
{
follow: true,
{% if category %}
data: {
{% if category %}
category: {{ category.id }}
{% endif %}
},
{% endif %}
secondary: [
{
field: 'default_location',
@ -328,4 +366,9 @@
$('#view-list').hide();
}
attachNavCallbacks({
name: 'partcategory',
default: 'part-stock'
});
{% endblock %}

View File

@ -11,30 +11,22 @@
</a>
</li>
<li class='list-group-item {% if tab == "subcategories" %}active{% endif %}' title='{% trans "Subcategories" %}'>
{% if category %}
<a href='{% url "category-subcategory" category.id %}'>
{% else %}
<a href='{% url "category-index-subcategory" %}'>
{% endif %}
<li class='list-group-item' title='{% trans "Subcategories" %}'>
<a href='#' id='select-subcategories' class='nav-toggle'>
<span class='fas fa-sitemap sidebar-icon'></span>
{% trans "Subcategories" %}
</a>
</li>
<li class='list-group-item {% if tab == "parts" %}active{% endif %}' title='{% trans "Parts" %}'>
{% if category %}
<a href='{% url "category-detail" category.id %}'>
{% else %}
<a href='{% url "part-index" %}'>
{% endif %}
<li class='list-group-item' title='{% trans "Parts" %}'>
<a href='#' id='select-parts' class='nav-toggle'>
<span class='fas fa-shapes sidebar-icon'></span>
{% trans "Parts" %}
</a>
</li>
{% if show_import and user.is_staff and roles.part.add %}
<li class='list-group-item {% if tab == "import" %}active{% endif %}' title='{% trans "Import Parts" %}'>
<li class='list-group-item' title='{% trans "Import Parts" %}'>
<a href='{% url "part-import" %}'>
<span class='fas fa-file-upload sidebar-icon'></span>
{% trans "Import Parts" %}
@ -43,8 +35,8 @@
{% endif %}
{% if category %}
<li class='list-group-item {% if tab == "parameters" %}active{% endif %}' title='{% trans "Parameters" %}'>
<a href='{% url "category-parametric" category.id %}'>
<li class='list-group-item' title='{% trans "Parameters" %}'>
<a href='#' id='select-parameters' class='nav-toggle'>
<span class='fas fa-tasks sidebar-icon'></span>
{% trans "Parameters" %}
</a>

View File

@ -1,37 +0,0 @@
{% extends "part/category.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/category_navbar.html' with tab='parameters' %}
{% endblock %}
{% block heading %}
{% trans "Part Parameters" %}
{% endblock %}
{% block details %}
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='parametric-part-table'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
/* Hide Button Toolbar */
window.onload = function hideButtonToolbar() {
var toolbar = document.getElementById("button-toolbar");
toolbar.style.display = "none";
};
loadParametricPartTable(
"#parametric-part-table",
{
headers: {{ headers|safe }},
data: {{ parameters|safe }},
}
);
{% endblock %}

View File

@ -1,16 +0,0 @@
{% extends "part/category.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/category_navbar.html' with tab='parts' %}
{% endblock %}
{% block heading %}
{% trans "Parts" %}
{% endblock %}
{% block details %}
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='part-table'>
</table>
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,9 @@
{% extends "part/category.html" %}
{% extends "base.html" %}
{% load inventree_extras %}
{% load i18n %}
{% load static %}
{% block menubar %}
{% include 'part/category_navbar.html' with tab='import' %}
{% endblock %}
{% block category_content %}
{% block content %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>

View File

@ -11,46 +11,36 @@
<span class='menu-tab-icon fas fa-expand-arrows-alt'></span>
</a>
</li>
<li class='list-group-item {% if tab == "details" %}active{% endif %}' title='{% trans "Part Details" %}'>
<a href='{% url "part-detail" part.id %}'>
<span class='menu-tab-icon fas fa-info-circle sidebar-icon'></span>
<span class='tab-text'>
{% trans "Details" %}
</span>
<li class='list-group-item' title='{% trans "Parameters" %}'>
<a href='#' id='select-part-parameters' class='nav-toggle'>
<span class='menu-tab-icon fas fa-th-list sidebar-icon'></span>
{% trans "Parameters" %}
</a>
</li>
{% if part.is_template %}
<li class='list-group-item {% if tab == "variants" %}active{% endif %}' title='{% trans "Part Variants" %}'>
<a href='{% url "part-variants" part.id %}'>
<li class='list-group-item' title='{% trans "Part Variants" %}'>
<a href='#' id='select-variants' class='nav-toggle'>
<span class='menu-tab-icon fas fa-shapes sidebar-icon'></span>
{% trans "Variants" %}
</a>
</li>
{% endif %}
<li class='list-group-item {% if tab == "stock" %}active{% endif %}' title='{% trans "Stock Items" %}'>
<a href='{% url "part-stock" part.id %}'>
<li class='list-group-item' title='{% trans "Stock Items" %}'>
<a href='#' id='select-part-stock' class='nav-toggle'>
<span class='menu-tab-icon fas fa-boxes sidebar-icon'></span>
{% trans "Stock" %}
</a>
</li>
{% if part.component or part.salable %}
<li class='list-group-item {% if tab == "allocation" %}active{% endif %}' title='{% trans "Allocated Stock" %}'>
<a href='{% url "part-allocation" part.id %}'>
<span class='menu-tab-icon fas fa-sign-out-alt sidebar-icon'></span>
{% trans "Allocations" %}
</a>
</li>
{% endif %}
{% if part.assembly %}
<li class='list-group-item {% if tab == "bom" %}active{% endif %}' title='{% trans "Bill of Materials" %}'>
<a href='{% url "part-bom" part.id %}'>
<li class='list-group-item' title='{% trans "Bill of Materials" %}'>
<a href='#' id='select-bom' class='nav-toggle'>
<span class='menu-tab-icon fas fa-list sidebar-icon'></span>
{% trans "Bill of Materials" %}
</a>
</li>
{% if roles.build.view %}
<li class='list-group-item {% if tab == "build" %}active{% endif %}' title='{% trans "Build Orders" %}'>
<a href='{% url "part-build" part.id %}'>
<li class='list-group-item ' title='{% trans "Build Orders" %}'>
<a href='#' id='select-build-orders' class='nav-toggle'>
<span class='menu-tab-icon fas fa-tools sidebar-icon'></span>
{% trans "Build Orders" %}
</a>
@ -58,55 +48,73 @@
{% endif %}
{% endif %}
{% if part.component %}
<li class='list-group-item {% if tab == "used" %}active{% endif %}' title='{% trans "Used In" %}'>
<a href='{% url "part-used-in" part.id %}'>
<li class='list-group-item ' title='{% trans "Used In" %}'>
<a href='#' id='select-used-in' class='nav-toggle'>
<span class='menu-tab-icon fas fa-layer-group sidebar-icon'></span>
{% trans "Used In" %}
</a>
</li>
{% endif %}
<li class='list-group-item {% if tab == "prices" %}active{% endif %}' title='{% trans "Pricing Information" %}'>
<a href='{% url "part-prices" part.id %}'>
<li class='list-group-item' title='{% trans "Pricing Information" %}'>
<a href='#' id='select-pricing' class='nav-toggle'>
<span class='menu-tab-icon fas fa-dollar-sign sidebar-icon'></span>
{% trans "Prices" %}
</a>
</li>
{% if part.purchaseable and roles.purchase_order.view %}
<li class='list-group-item {% if tab == "suppliers" %}active{% endif %}' title='{% trans "Suppliers" %}'>
<a href='{% url "part-suppliers" part.id %}'>
<li class='list-group-item' title='{% trans "Suppliers" %}'>
<a href='#' id='select-part-suppliers' class='nav-toggle'>
<span class='menu-tab-icon fas fa-building sidebar-icon'></span>
{% trans "Suppliers" %}
</a>
</li>
<li class='list-group-item {% if tab == "orders" %}active{% endif %}' title='{% trans "Purchase Orders" %}'>
<a href='{% url "part-orders" part.id %}'>
<li class='list-group-item' title='{% trans "Manufacturers" %}'>
<a href='#' id='select-part-manufacturers' class='nav-toggle'>
<span class='menu-tab-icon fas fa-tools sidebar-icon'></span>
{% trans "Manufacturers" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Purchase Orders" %}'>
<a href='#' id='select-purchase-orders' class='nav-toggle'>
<span class='menu-tab-icon fas fa-shopping-cart sidebar-icon'></span>
{% trans "Purchase Orders" %}
</a>
</li>
{% endif %}
{% if roles.sales_order.view %}
<li class='list-group-item {% if tab == "sales-orders" %}active{% endif %}' title='{% trans "Sales Orders" %}'>
<a href='{% url "part-sales-orders" part.id %}'>
<li class='list-group-item' title='{% trans "Sales Orders" %}'>
<a href='#' id='select-sales-orders' class='nav-toggle'>
<span class='menu-tab-icon fas fa-truck sidebar-icon'></span>
{% trans "Sales Orders" %}
</a>
</li>
{% endif %}
{% if part.trackable %}
<li class='list-group-item {% if tab == "tests" %}active{% endif %}' title='{% trans "Part Test Templates" %}'>
<a href='{% url "part-test-templates" part.id %}'>
<li class='list-group-item' title='{% trans "Part Test Templates" %}'>
<a href='#' id='select-test-templates' class='nav-toggle'>
<span class='menu-tab-icon fas fa-vial sidebar-icon'></span>
{% trans "Test Templates" %}
</a>
</li>
{% endif %}
{% if show_related %}
<li class='list-group-item {% if tab == "related" %}active{% endif %}' title='{% trans "Related Parts" %}'>
<a href='{% url "part-related" part.id %}'>
<li class='list-group-item' title='{% trans "Related Parts" %}'>
<a href='#' id='select-related-parts' class='nav-toggle'>
<span class='menu-tab-icon fas fa-random sidebar-icon'></span>
{% trans "Related Parts" %}
</a>
</li>
{% endif %}
<li class='list-group-item' title='{% trans "Attachments" %}'>
<a href='#' id='select-part-attachments' class='nav-toggle'>
<span class='fas fa-paperclip side-icon'></span>
{% trans "Attachments" %}
</a>
</li>
<li class='list-group-item' title='{% trans "Notes" %}'>
<a href='#' id='select-part-notes' class='nav-toggle'>
<span class='fas fa-clipboard side-icon'></span>
{% trans "Notes" %}
</a>
</li>
</ul>

View File

@ -1,51 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='orders' %}
{% endblock %}
{% block heading %}
{% trans "Purchase Orders" %}
{% endblock %}
{% block details %}
<div id='button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<button class='btn btn-primary' type='button' id='part-order2' title='{% trans "Order part" %}'>
<span class='fas fa-shopping-cart'></span> {% trans "Order Part" %}
</button>
<div class='filter-list' id='filter-list-purchaseorder'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
</div>
<table class='table table-striped table-condensed po-table' id='purchase-order-table' data-toolbar='#button-bar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadPurchaseOrderTable($("#purchase-order-table"), {
url: "{% url 'api-po-list' %}",
params: {
part: {{ part.id }},
},
});
$("#part-order2").click(function() {
launchModalForm("{% url 'order-parts' %}", {
data: {
part: {{ part.id }},
},
reload: true,
});
});
{% endblock %}

View File

@ -27,7 +27,34 @@
</div>
{% endif %}
</h3>
{% if part.description %}
<p><em>{{ part.description }}</em></p>
{% endif %}
<p>
<div id='part-properties' class='btn-group' role='group'>
{% if part.virtual %}
<span class='fas fa-ghost' title='{% trans "Part is virtual (not a physical part)" %}'></span>
{% endif %}
{% if part.is_template %}
<span class='fas fa-clone' title='{% trans "Part is a template part (variants can be made from this part)" %}'></span>
{% endif %}
{% if part.assembly %}
<span class='fas fa-tools' title='{% trans "Part can be assembled from other parts" %}'></span>
{% endif %}
{% if part.component %}
<span class='fas fa-th' title='{% trans "Part can be used in assemblies" %}'></span>
{% endif %}
{% if part.trackable %}
<span class='fas fa-directions' title='{% trans "Part stock is tracked by serial number" %}'></span>
{% endif %}
{% if part.purchaseable %}
<span class='fas fa-shopping-cart' title='{% trans "Part can be purchased from external suppliers" %}'></span>
{% endif %}
{% if part.salable %}
<span class='fas fa-dollar-sign' title='{% trans "Part can be sold to customers" %}'></span>
{% endif %}
</div>
</p>
<div class='btn-group action-buttons' role='group'>
<button type='button' class='btn btn-default' id='toggle-starred' title='{% trans "Star this part" %}'>
@ -97,11 +124,11 @@
</div>
<table class='table table-condensed'>
<col width='25'>
{% if part.IPN %}
{% if part.keywords %}
<tr>
<td></td>
<td>{% trans "IPN" %}</td>
<td>{{ part.IPN }}</td>
<td><span class='fas fa-key'></span></td>
<td>{% trans "Keywords" %}</td>
<td>{{ part.keywords }}</td>
</tr>
{% endif %}
{% if part.link %}
@ -112,7 +139,22 @@
</tr>
{% endif %}
<tr>
<td><span class='fas fa-calendar-alt'></span></td>
<td>{% trans "Creation Date" %}</td>
<td>
{{ part.creation_date }}
{% if part.creation_user %}
<span class='badge'>{{ part.creation_user }}</span>
{% endif %}
</td>
</tr>
{% if part.trackable and part.getLatestSerialNumber %}
<tr>
<td><span class='fas fa-hashtag'></span></td>
<td>{% trans "Latest Serial Number" %}</td>
<td>{{ part.getLatestSerialNumber }}{% include "clip.html"%}</td>
</tr>
{% endif %}
</table>
</div>
</div>
@ -125,7 +167,7 @@
{% endif %}
{% if part.variant_of %}
<div class='alert alert-info alert-block'>
{% object_link 'part-variants' part.variant_of.id part.variant_of.full_name as link %}
{% object_link 'part-detail' part.variant_of.id part.variant_of.full_name as link %}
{% blocktrans %}This part is a variant of {{link}}{% endblocktrans %}
</div>
{% endif %}
@ -197,44 +239,13 @@
{% endif %}
{% endif %}
{% endif %}
{% if part.trackable and part.getLatestSerialNumber %}
<tr><td colspan="3"></td></tr>
<tr>
<td><span class='fas fa-hashtag'></span></td>
<td>{% trans "Latest Serial Number" %}</td>
<td>{{ part.getLatestSerialNumber }}{% include "clip.html"%}</td>
</tr>
{% endif %}
</table>
</div>
</div>
</div>
{% block pre_content_panel %}
{% endblock %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>
{% block heading %}
<!-- Heading goes here -->
{% endblock %}
</h4>
</div>
<div class='panel-content'>
{% block details %}
<!-- Specific part details go here... -->
{% endblock %}
</div>
</div>
{% block post_content_panel %}
{% block page_content %}
{% endblock %}
{% endblock %}
@ -242,11 +253,6 @@
{% block js_ready %}
{{ block.super }}
enableNavbar({
label: 'part',
toggleId: '#part-menu-toggle',
});
{% if part.image %}
$('#part-thumb').click(function() {
showModalImage('{{ part.image.url }}');
@ -410,80 +416,7 @@
$("#part-edit").click(function() {
constructForm('{% url "api-part-detail" part.id %}', {
focus: 'name',
fields: {
category: {
secondary: {
label: '{% trans "New Category" %}',
title: '{% trans "Create New Part Category" %}',
api_url: '{% url "api-part-category-list" %}',
method: 'POST',
fields: {
name: {},
description: {},
parent: {
secondary: {
title: '{% trans "New Parent" %}',
api_url: '{% url "api-part-category-list" %}',
method: 'POST',
fields: {
name: {},
description: {},
parent: {},
}
}
},
}
},
},
name: {
placeholder: 'part name',
},
IPN: {},
description: {},
revision: {},
keywords: {
icon: 'fa-key',
},
variant_of: {},
link: {
icon: 'fa-link',
},
default_location: {
secondary: {
label: '{% trans "New Location" %}',
title: '{% trans "Create new stock location" %}',
},
},
default_supplier: {
filters: {
part: {{ part.pk }},
part_detail: true,
manufacturer_detail: true,
supplier_detail: true,
},
secondary: {
label: '{% trans "New Supplier Part" %}',
title: '{% trans "Create new supplier part" %}',
}
},
units: {},
minimum_stock: {},
},
title: '{% trans "Edit Part" %}',
reload: true,
});
return;
launchModalForm(
"{% url 'part-edit' part.id %}",
{
reload: true,
}
);
editPart({{ part.pk }});
});
{% endif %}

View File

@ -1,96 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='tests' %}
{% endblock %}
{% block heading %}
{% trans "Part Test Templates" %}
{% endblock %}
{% block details %}
<div id='button-toolbar'>
<div class='button-toolbar container-fluid' style="float: right;">
<div class='btn-group' role='group'>
<button type='button' class='btn btn-success' id='add-test-template'>{% trans "Add Test Template" %}</button>
</div>
<div class='filter-list' id='filter-list-parttests'>
<!-- Empty div -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='test-template-table'></table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadPartTestTemplateTable(
$("#test-template-table"),
{
part: {{ part.pk }},
params: {
part: {{ part.pk }},
}
}
);
function reloadTable() {
$("#test-template-table").bootstrapTable("refresh");
}
$("#add-test-template").click(function() {
constructForm('{% url "api-part-test-template-list" %}', {
method: 'POST',
fields: {
test_name: {},
description: {},
required: {},
requires_value: {},
requires_attachment: {},
part: {
value: {{ part.pk }},
hidden: true,
}
},
title: '{% trans "Add Test Result Template" %}',
onSuccess: reloadTable
});
});
$("#test-template-table").on('click', '.button-test-edit', function() {
var pk = $(this).attr('pk');
var url = `/api/part/test-template/${pk}/`;
constructForm(url, {
fields: {
test_name: {},
description: {},
required: {},
requires_value: {},
requires_attachment: {},
},
title: '{% trans "Edit Test Result Template" %}',
onSuccess: reloadTable,
});
});
$("#test-template-table").on('click', '.button-test-delete', function() {
var pk = $(this).attr('pk');
var url = `/api/part/test-template/${pk}/`;
constructForm(url, {
method: 'DELETE',
title: '{% trans "Delete Test Result Template" %}',
onSuccess: reloadTable,
});
});
{% endblock %}

View File

@ -1,176 +1,168 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load inventree_extras %}
{% block menubar %}
{% include 'part/navbar.html' with tab='prices' %}
{% endblock %}
<div class='panel-heading'>
<h4>{% trans "Pricing Information" %}</h4>
</div>
{% block heading %}
{% trans "General Price Information" %}
{% endblock %}
{% block details %}
{% default_currency as currency %}
<div class='panel-content'>
<div class="row">
<a class="anchor" id="overview"></a>
<div class="col col-md-6">
<h4>{% trans "Pricing ranges" %}</h4>
<table class='table table-striped table-condensed'>
{% if part.supplier_count > 0 %}
{% if min_total_buy_price %}
<tr>
<td><b>{% trans 'Supplier Pricing' %}</b>
<a href="#supplier-cost" title='{% trans "Show supplier cost" %}'><span class="fas fa-search-dollar"></span></a>
<a href="#purchase-price" title='{% trans "Show purchase price" %}'><span class="fas fa-chart-bar"></span></a>
</td>
<td>{% trans 'Unit Cost' %}</td>
<td>Min: {% include "price.html" with price=min_unit_buy_price %}</td>
<td>Max: {% include "price.html" with price=max_unit_buy_price %}</td>
</tr>
{% if quantity > 1 %}
<tr>
<td></td>
<td>{% trans 'Total Cost' %}</td>
<td>Min: {% include "price.html" with price=min_total_buy_price %}</td>
<td>Max: {% include "price.html" with price=max_total_buy_price %}</td>
</tr>
{% endif %}
{% else %}
<tr>
<td colspan='4'>
<span class='warning-msg'><i>{% trans 'No supplier pricing available' %}</i></span>
</td>
</tr>
{% endif %}
{% endif %}
{% if part.bom_count > 0 %}
{% if min_total_bom_price %}
<tr>
<td><b>{% trans 'BOM Pricing' %}</b>
<a href="#bom-cost" title='{% trans "Show BOM cost" %}'><span class="fas fa-search-dollar"></span></a>
</td>
<td>{% trans 'Unit Cost' %}</td>
<td>Min: {% include "price.html" with price=min_unit_bom_price %}</td>
<td>Max: {% include "price.html" with price=max_unit_bom_price %}</td>
</tr>
{% if quantity > 1 %}
<div class="row">
<a class="anchor" id="overview"></a>
<div class="col col-md-6">
<h4>{% trans "Pricing ranges" %}</h4>
<table class='table table-striped table-condensed'>
{% if part.supplier_count > 0 %}
{% if min_total_buy_price %}
<tr>
<td><b>{% trans 'Supplier Pricing' %}</b>
<a href="#supplier-cost" title='{% trans "Show supplier cost" %}'><span class="fas fa-search-dollar"></span></a>
<a href="#purchase-price" title='{% trans "Show purchase price" %}'><span class="fas fa-chart-bar"></span></a>
</td>
<td>{% trans 'Unit Cost' %}</td>
<td>Min: {% include "price.html" with price=min_unit_buy_price %}</td>
<td>Max: {% include "price.html" with price=max_unit_buy_price %}</td>
</tr>
{% if quantity > 1 %}
<tr>
<td></td>
<td>{% trans 'Total Cost' %}</td>
<td>Min: {% include "price.html" with price=min_total_bom_price %}</td>
<td>Max: {% include "price.html" with price=max_total_bom_price %}</td>
<td>Min: {% include "price.html" with price=min_total_buy_price %}</td>
<td>Max: {% include "price.html" with price=max_total_buy_price %}</td>
</tr>
{% endif %}
{% if part.has_complete_bom_pricing == False %}
{% endif %}
{% else %}
<tr>
<td colspan='4'>
<span class='warning-msg'><i>{% trans 'Note: BOM pricing is incomplete for this part' %}</i></span>
<span class='warning-msg'><i>{% trans 'No supplier pricing available' %}</i></span>
</td>
</tr>
{% endif %}
{% else %}
{% endif %}
{% if part.bom_count > 0 %}
{% if min_total_bom_price %}
<tr>
<td><b>{% trans 'BOM Pricing' %}</b>
<a href="#bom-cost" title='{% trans "Show BOM cost" %}'><span class="fas fa-search-dollar"></span></a>
</td>
<td>{% trans 'Unit Cost' %}</td>
<td>Min: {% include "price.html" with price=min_unit_bom_price %}</td>
<td>Max: {% include "price.html" with price=max_unit_bom_price %}</td>
</tr>
{% if quantity > 1 %}
<tr>
<td></td>
<td>{% trans 'Total Cost' %}</td>
<td>Min: {% include "price.html" with price=min_total_bom_price %}</td>
<td>Max: {% include "price.html" with price=max_total_bom_price %}</td>
</tr>
{% endif %}
{% if part.has_complete_bom_pricing == False %}
<tr>
<td colspan='4'>
<span class='warning-msg'><i>{% trans 'Note: BOM pricing is incomplete for this part' %}</i></span>
</td>
</tr>
{% endif %}
{% else %}
<tr>
<td colspan='4'>
<span class='warning-msg'><i>{% trans 'No BOM pricing available' %}</i></span>
</td>
</tr>
{% endif %}
{% endif %}
{% if show_internal_price and roles.sales_order.view %}
{% if total_internal_part_price %}
<tr>
<td colspan='4'>
<span class='warning-msg'><i>{% trans 'No BOM pricing available' %}</i></span>
</td>
<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 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>
<a href="#sale-cost" title='{% trans "Show sale cost" %}'><span class="fas fa-search-dollar"></span></a>
<a href="#sale-price" title='{% trans "Show sale price" %}'><span class="fas fa-chart-bar"></span></a>
</td>
<td>{% trans 'Unit Cost' %}</td>
<td colspan='2'>{% include "price.html" with price=unit_part_price %}</td>
</tr>
<tr>
<td></td>
<td>{% trans 'Total Cost' %}</td>
<td colspan='2'>{% include "price.html" with price=total_part_price %}</td>
</tr>
{% endif %}
</table>
{% endif %}
{% if total_part_price %}
<tr>
<td><b>{% trans 'Sale Price' %}</b>
<a href="#sale-cost" title='{% trans "Show sale cost" %}'><span class="fas fa-search-dollar"></span></a>
<a href="#sale-price" title='{% trans "Show sale price" %}'><span class="fas fa-chart-bar"></span></a>
</td>
<td>{% trans 'Unit Cost' %}</td>
<td colspan='2'>{% include "price.html" with price=unit_part_price %}</td>
</tr>
<tr>
<td></td>
<td>{% trans 'Total Cost' %}</td>
<td colspan='2'>{% include "price.html" with price=total_part_price %}</td>
</tr>
{% endif %}
</table>
{% if min_unit_buy_price or min_unit_bom_price %}
{% else %}
<div class='alert alert-danger alert-block'>
{% trans 'No pricing information is available for this part.' %}
</div>
{% endif %}
</div>
{% if min_unit_buy_price or min_unit_bom_price %}
{% else %}
<div class='alert alert-danger alert-block'>
{% trans 'No pricing information is available for this part.' %}
</div>
{% endif %}
</div>
<div class="col col-md-6">
<h4>{% trans "Calculation parameters" %}</h4>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="{% trans 'Calculate' %}" class="btn btn-primary btn-block">
</form>
<div class="col col-md-6">
<h4>{% trans "Calculation parameters" %}</h4>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="{% trans 'Calculate' %}" class="btn btn-primary btn-block">
</form>
</div>
</div>
</div>
{% endblock %}
{% block post_content_panel %}
{% default_currency as currency %}
{% settings_value "PART_INTERNAL_PRICE" as show_internal_price %}
{% if part.purchaseable and roles.purchase_order.view %}
<div class='panel panel-default panel-inventree'>
<a class="anchor" id="supplier-cost"></a>
<div class='panel-heading'>
<h4>{% trans "Supplier Cost" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<a class="anchor" id="supplier-cost"></a>
<div class='panel-heading'>
<h4>{% trans "Supplier Cost" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<div class='panel-content'><div class="row">
<div class="col col-md-6">
<h4>{% trans "Suppliers" %}</h4>
<table class="table table-striped table-condensed" id='supplier-table' data-toolbar='#button-toolbar'></table>
</div>
<div class="col col-md-6">
<h4>{% trans "Manufacturers" %}</h4>
<table class="table table-striped table-condensed" id='manufacturer-table' data-toolbar='#button-toolbar'></table>
</div>
</div></div>
<div class='panel-content'>
<div class="row">
<div class="col col-md-6">
<h4>{% trans "Suppliers" %}</h4>
<table class="table table-striped table-condensed" id='supplier-table' data-toolbar='#button-toolbar'></table>
</div>
<div class="col col-md-6">
<h4>{% trans "Manufacturers" %}</h4>
<table class="table table-striped table-condensed" id='manufacturer-table' data-toolbar='#button-toolbar'></table>
</div>
</div>
</div>
<div class='panel panel-default panel-inventree'>
<a class="anchor" id="purchase-price"></a>
<div class='panel-heading'>
<h4>{% trans "Purchase Price" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
{% if price_history %}
<h4>{% trans 'Stock Pricing' %}<i class="fas fa-info-circle" title="Shows the purchase prices of stock for this part.
The part single price is the current purchase price for that supplier part."></i></h4>
{% if price_history %}
<a class="anchor" id="purchase-price"></a>
<div class='panel-heading'>
<h4>{% trans "Purchase Price" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<div class='panel-content'>
<h4>{% trans 'Stock Pricing' %}
<i class="fas fa-info-circle" title="Shows the purchase prices of stock for this part.
The part single price is the current purchase price for that supplier part."></i>
</h4>
{% if price_history|length > 0 %}
<div style="max-width: 99%; min-height: 300px">
<canvas id="StockPriceChart"></canvas>
@ -180,52 +172,50 @@
{% trans 'No stock pricing history is available for this part.' %}
</div>
{% endif %}
{% endif %}
</div>
{% endif %}
{% endif %}
{% if show_internal_price and roles.sales_order.view %}
<div class='panel panel-default panel-inventree'>
<a class="anchor" id="internal-cost"></a>
<div class='panel-heading'>
<h4>{% trans "Internal Cost" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<a class="anchor" id="internal-cost"></a>
<div class='panel-heading'>
<h4>{% trans "Internal Cost" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<div class='panel-content'><div class="row full-height">
<div class="col col-md-8">
<div style="max-width: 99%; height: 100%;">
<canvas id="InternalPriceBreakChart"></canvas>
</div>
<div class='panel-content'>
<div class="row full-height">
<div class="col col-md-8">
<div style="max-width: 99%; height: 100%;">
<canvas id="InternalPriceBreakChart"></canvas>
</div>
<div class="col col-md-4">
<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'
data-sort-name="quantity" data-sort-order="asc">
</table>
</div>
<div class="col col-md-4">
<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>
</div></div>
<table class='table table-striped table-condensed' id='internal-price-break-table' data-toolbar='#internal-price-break-toolbar'
data-sort-name="quantity" data-sort-order="asc">
</table>
</div>
</div>
</div>
{% endif %}
{% if part.has_bom and roles.sales_order.view %}
<div class='panel panel-default panel-inventree'>
<a class="anchor" id="bom-cost"></a>
<div class='panel-heading'>
<h4>{% trans "BOM Cost" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<a class="anchor" id="bom-cost"></a>
<div class='panel-heading'>
<h4>{% trans "BOM Cost" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<div class='panel-content'><div class="row">
<div class='panel-content'>
<div class="row">
<div class="col col-md-6">
<table class='table table-bom table-condensed' data-toolbar="#button-toolbar" id='bom-table'></table>
</div>
@ -238,251 +228,55 @@
</div>
</div>
{% endif %}
</div></div>
</div>
</div>
{% endif %}
{% if part.salable and roles.sales_order.view %}
<div class='panel panel-default panel-inventree'>
<a class="anchor" id="sale-cost"></a>
<div class='panel-heading'>
<h4>{% trans "Sale Cost" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<a class="anchor" id="sale-cost"></a>
<div class='panel-heading'>
<h4>{% trans "Sale Cost" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<div class='panel-content'><div class="row full-height">
<div class="col col-md-8">
<div style="max-width: 99%; height: 100%;">
<canvas id="SalePriceBreakChart"></canvas>
</div>
<div class='panel-content'>
<div class="row full-height">
<div class="col col-md-8">
<div style="max-width: 99%; height: 100%;">
<canvas id="SalePriceBreakChart"></canvas>
</div>
<div class="col col-md-4">
<div id='price-break-toolbar' class='btn-group'>
<button class='btn btn-primary' id='new-price-break' type='button'>
<span class='fas fa-plus-circle'></span> {% trans "Add Price Break" %}
</button>
</div>
<table class='table table-striped table-condensed' id='price-break-table' data-toolbar='#price-break-toolbar'
data-sort-name="quantity" data-sort-order="asc">
</table>
</div>
<div class="col col-md-4">
<div id='price-break-toolbar' class='btn-group'>
<button class='btn btn-primary' id='new-price-break' type='button'>
<span class='fas fa-plus-circle'></span> {% trans "Add Price Break" %}
</button>
</div>
</div></div>
<table class='table table-striped table-condensed' id='price-break-table' data-toolbar='#price-break-toolbar'
data-sort-name="quantity" data-sort-order="asc">
</table>
</div>
</div>
</div>
<div class='panel panel-default panel-inventree'>
<a class="anchor" id="sale-price"></a>
<div class='panel-heading'>
<h4>{% trans "Sale Price" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<a class="anchor" id="sale-price"></a>
<div class='panel-heading'>
<h4>{% trans "Sale Price" %}
<a href="#overview" title='{% trans "Jump to overview" %}'><span class="fas fa-level-up-alt"></span></a>
</h4>
</div>
<div class='panel-content'>
{% if sale_history|length > 0 %}
<div style="max-width: 99%; min-height: 300px">
<canvas id="SalePriceChart"></canvas>
</div>
{% else %}
<div class='alert alert-danger alert-block'>
{% trans 'No sale pice history available for this part.' %}
</div>
{% endif %}
<div class='panel-content'>
{% if sale_history|length > 0 %}
<div style="max-width: 99%; min-height: 300px">
<canvas id="SalePriceChart"></canvas>
</div>
</div>
{% else %}
<div class='alert alert-danger alert-block'>
{% trans 'No sale pice history available for this part.' %}
</div>
{% endif %}
</div>
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% default_currency as currency %}
loadSupplierPartTable(
"#supplier-table",
"{% url 'api-supplier-part-list' %}",
{
params: {
part: {{ part.id }},
part_detail: false,
supplier_detail: true,
manufacturer_detail: true,
},
}
);
loadManufacturerPartTable(
"#manufacturer-table",
"{% url 'api-manufacturer-part-list' %}",
{
params: {
part: {{ part.id }},
part_detail: false,
manufacturer_detail: true,
},
}
);
// history graphs
{% if price_history %}
var purchasepricedata = {
labels: [
{% for line in price_history %}'{{ line.date }}',{% endfor %}
],
datasets: [{
label: '{% blocktrans %}Single Price - {{currency}}{% endblocktrans %}',
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgb(255, 99, 132)',
yAxisID: 'y',
data: [
{% for line in price_history %}{{ line.price|stringformat:".2f" }},{% endfor %}
],
borderWidth: 1,
type: 'line'
},
{% if 'price_diff' in price_history.0 %}
{
label: '{% blocktrans %}Single Price Difference - {{currency}}{% endblocktrans %}',
backgroundColor: 'rgba(68, 157, 68, 0.2)',
borderColor: 'rgb(68, 157, 68)',
yAxisID: 'y2',
data: [
{% for line in price_history %}{{ line.price_diff|stringformat:".2f" }},{% endfor %}
],
borderWidth: 1,
type: 'line',
hidden: true,
},
{
label: '{% blocktrans %}Part Single Price - {{currency}}{% endblocktrans %}',
backgroundColor: 'rgba(70, 127, 155, 0.2)',
borderColor: 'rgb(70, 127, 155)',
yAxisID: 'y',
data: [
{% for line in price_history %}{{ line.price_part|stringformat:".2f" }},{% endfor %}
],
borderWidth: 1,
type: 'line',
hidden: true,
},
{% endif %}
{
label: '{% trans "Quantity" %}',
backgroundColor: 'rgba(255, 206, 86, 0.2)',
borderColor: 'rgb(255, 206, 86)',
yAxisID: 'y1',
data: [
{% for line in price_history %}{{ line.qty|stringformat:"f" }},{% endfor %}
],
borderWidth: 1
}]
}
var StockPriceChart = loadStockPricingChart($('#StockPriceChart'), purchasepricedata)
{% endif %}
{% if bom_parts %}
var bom_colors = randomColor({hue: 'green', count: {{ bom_parts|length }} })
var bomdata = {
labels: [{% for line in bom_parts %}'{{ line.name }}',{% endfor %}],
datasets: [
{
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 %}
]
};
var BomChart = loadBomChart(document.getElementById('BomChart'), bomdata)
{% endif %}
// Internal pricebreaks
{% settings_value "PART_INTERNAL_PRICE" as show_internal_price %}
{% if show_internal_price and roles.sales_order.view %}
initPriceBreakSet(
$('#internal-price-break-table'),
{
part_id: {{part.id}},
pb_human_name: 'internal price break',
pb_url_slug: 'internal-price',
pb_url: '{% url 'api-part-internal-price-list' %}',
pb_new_btn: $('#new-internal-price-break'),
pb_new_url: '{% url 'internal-price-break-create' %}',
linkedGraph: $('#InternalPriceBreakChart'),
},
);
{% endif %}
// Load the BOM table data
loadBomTable($("#bom-table"), {
editable: {{ editing_enabled }},
bom_url: "{% url 'api-bom-list' %}",
part_url: "{% url 'api-part-list' %}",
parent_id: {{ part.id }} ,
sub_part_detail: true,
});
// Sales pricebreaks
{% if part.salable and roles.sales_order.view %}
initPriceBreakSet(
$('#price-break-table'),
{
part_id: {{part.id}},
pb_human_name: 'sale price break',
pb_url_slug: 'sale-price',
pb_url: "{% url 'api-part-sale-price-list' %}",
pb_new_btn: $('#new-price-break'),
pb_new_url: '{% url 'sale-price-break-create' %}',
linkedGraph: $('#SalePriceBreakChart'),
},
);
{% endif %}
// Sale price history
{% if sale_history %}
var salepricedata = {
labels: [
{% for line in sale_history %}'{{ line.date }}',{% endfor %}
],
datasets: [{
label: '{% blocktrans %}Unit Price - {{currency}}{% endblocktrans %}',
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgb(255, 99, 132)',
yAxisID: 'y',
data: [
{% for line in sale_history %}{{ line.price|stringformat:".2f" }},{% endfor %}
],
borderWidth: 1,
},
{
label: '{% trans "Quantity" %}',
backgroundColor: 'rgba(255, 206, 86, 0.2)',
borderColor: 'rgb(255, 206, 86)',
yAxisID: 'y1',
data: [
{% for line in sale_history %}{{ line.qty|stringformat:"f" }},{% endfor %}
],
borderWidth: 1,
type: 'bar',
}]
}
var SalePriceChart = loadSellPricingChart($('#SalePriceChart'), salepricedata)
{% endif %}
{% endblock %}

View File

@ -1,80 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='related' %}
{% endblock %}
{% block heading %}
{% trans "Related Parts" %}
{% endblock %}
{% block details %}
<div id='button-bar'>
<div class='button-toolbar container-fluid' style='float: left;'>
{% if roles.part.change %}
<button class='btn btn-primary' type='button' id='add-related-part' title='{% trans "Add Related" %}'>{% trans "Add Related" %}</button>
<div class='filter-list' id='filter-list-related'>
<!-- An empty div in which the filter list will be constructed -->
</div>
{% endif %}
</div>
</div>
<table id='table-related-part' class='table table-condensed table-striped' data-toolbar='#button-toolbar'>
<thead>
<tr>
<th data-field='part' data-serachable='true'>{% trans "Part" %}</th>
</tr>
</thead>
<tbody>
{% for item in part.get_related_parts %}
{% with part_related=item.0 part=item.1 %}
<tr>
<td>
<a class='hover-icon'>
<img class='hover-img-thumb' src='{{ part.get_thumbnail_url }}'>
<img class='hover-img-large' src='{{ part.get_thumbnail_url }}'>
</a>
<a href='/part/{{ part.id }}/'>{{ part }}</a>
<div class='btn-group' style='float: right;'>
{% if roles.part.change %}
<button title='{% trans "Delete" %}' class='btn btn-default btn-glyph delete-related-part' url="{% url 'part-related-delete' part_related.id %}" type='button'><span class='fas fa-trash-alt icon-red'/></button>
{% endif %}
</div>
</td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
$('#table-related-part').inventreeTable({
});
$("#add-related-part").click(function() {
launchModalForm("{% url 'part-related-create' %}", {
data: {
part: {{ part.id }},
},
reload: true,
});
});
$('.delete-related-part').click(function() {
var button = $(this);
launchModalForm(button.attr('url'), {
reload: true,
});
});
{% endblock %}

View File

@ -1,41 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='sales-orders' %}
{% endblock %}
{% block heading %}
{% trans "Sales Orders" %}
{% endblock %}
{% block details %}
<div id='button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
{% if 0 %}
<button class='btn btn-primary' type='button' id='part-order2' title='{% trans "New sales order" %}'>{% trans "New Order" %}</button>
{% endif %}
<div class='filter-list' id='filter-list-salesorder'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
</div>
<table class='table table-striped table-condensed po-table' id='sales-order-table' data-toolbar='#button-bar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadSalesOrderTable($("#sales-order-table"), {
url: "{% url 'api-so-list' %}",
params: {
part: {{ part.id }},
},
});
{% endblock %}

View File

@ -1,77 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='stock' %}
{% endblock %}
{% block heading %}
{% trans "Part Stock" %}
{% endblock %}
{% block details %}
{% if part.is_template %}
<div class='alert alert-info alert-block'>
{% blocktrans with full_name=part.full_name%}Showing stock for all variants of <i>{{full_name}}</i>{% endblocktrans %}
</div>
{% endif %}
{% include "stock_table.html" %}
{% endblock %}
{% block js_load %}
{{ block.super }}
{% endblock %}
{% block js_ready %}
{{ block.super }}
$('#add-stock-item').click(function () {
createNewStockItem({
reload: true,
data: {
part: {{ part.id }},
}
});
});
loadStockTable($("#stock-table"), {
params: {
part: {{ part.id }},
location_detail: true,
part_detail: true,
supplier_part_detail: true,
},
groupByField: 'location',
buttons: [
'#stock-options',
],
url: "{% url 'api-stock-list' %}",
});
$("#stock-export").click(function() {
launchModalForm("{% url 'stock-export-options' %}", {
submit_text: "{% trans 'Export' %}",
success: function(response) {
var url = "{% url 'stock-export' %}";
url += "?format=" + response.format;
url += "&cascade=" + response.cascade;
url += "&part={{ part.id }}";
location.href = url;
},
});
});
$('#item-create').click(function () {
createNewStockItem({
reload: true,
data: {
part: {{ part.id }},
}
});
});
{% endblock %}

View File

@ -1,51 +0,0 @@
{% extends "part/category.html" %}
{% load i18n %}
{% load inventree_extras %}
{% load static %}
{% block menubar %}
{% include 'part/category_navbar.html' with tab='subcategories' %}
{% endblock %}
{% block category_content %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>{% trans "Subcategories" %}</h4>
</div>
<div id='button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<div class='filter-list' id='filter-list-category'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' id='subcategory-table' data-toolbar='#button-toolbar'></table>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableNavbar({
label: 'category',
toggleId: '#category-menu-toggle',
});
loadPartCategoryTable($('#subcategory-table'), {
params: {
{% if category %}
parent: {{ category.pk }}
{% else %}
parent: 'null'
{% endif %}
}
});
{% endblock %}

View File

@ -1,171 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='suppliers' %}
{% endblock %}
{% block heading %}
{% trans "Part Suppliers" %}
{% endblock %}
{% block details %}
<div id='supplier-button-toolbar'>
<div class='btn-group'>
<button class="btn btn-success" id='supplier-create'>
<span class='fas fa-plus-circle'></span> {% trans "New Supplier Part" %}
</button>
<div id='opt-dropdown' class="btn-group">
<button id='supplier-part-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href='#' id='supplier-part-delete' title='{% trans "Delete supplier parts" %}'>{% trans "Delete" %}</a></li>
</ul>
</div>
</div>
</div>
<table class="table table-striped table-condensed" id='supplier-table' data-toolbar='#supplier-button-toolbar'>
</table>
{% endblock %}
{% block post_content_panel %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>
{% trans "Part Manufacturers" %}
</h4>
</div>
<div class='panel-content'>
<div id='manufacturer-button-toolbar'>
<div class='btn-group'>
<button class="btn btn-success" id='manufacturer-create'>
<span class='fas fa-plus-circle'></span> {% trans "New Manufacturer Part" %}
</button>
<div id='opt-dropdown' class="btn-group">
<button id='manufacturer-part-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">{% trans "Options" %}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href='#' id='manufacturer-part-delete' title='{% trans "Delete manufacturer parts" %}'>{% trans "Delete" %}</a></li>
</ul>
</div>
</div>
</div>
<table class='table table-condensed table-striped' id='manufacturer-table' data-toolbar='#manufacturer-button-toolbar'></table>
</div>
</div>
{% endblock %}
{% block js_load %}
{{ block.super }}
{% endblock %}
{% block js_ready %}
{{ block.super }}
$('#supplier-create').click(function () {
launchModalForm(
"{% url 'supplier-part-create' %}",
{
reload: true,
data: {
part: {{ part.id }}
},
secondary: [
{
field: 'supplier',
label: '{% trans "New Supplier" %}',
title: '{% trans "Create new supplier" %}',
},
{
field: 'manufacturer',
label: '{% trans "New Manufacturer" %}',
title: '{% trans "Create new manufacturer" %}',
}
]
});
});
$("#supplier-part-delete").click(function() {
var selections = $("#supplier-table").bootstrapTable("getSelections");
var parts = [];
selections.forEach(function(item) {
parts.push(item.pk);
});
launchModalForm("{% url 'supplier-part-delete' %}", {
data: {
parts: parts,
},
reload: true,
});
});
loadSupplierPartTable(
"#supplier-table",
"{% url 'api-supplier-part-list' %}",
{
params: {
part: {{ part.id }},
part_detail: false,
supplier_detail: true,
manufacturer_detail: true,
},
}
);
linkButtonsToSelection($("#supplier-table"), ['#supplier-part-options']);
loadManufacturerPartTable(
'#manufacturer-table',
"{% url 'api-manufacturer-part-list' %}",
{
params: {
part: {{ part.id }},
part_detail: true,
manufacturer_detail: true,
},
}
);
linkButtonsToSelection($("#manufacturer-table"), ['#manufacturer-part-options']);
$("#manufacturer-part-delete").click(function() {
var selections = $("#manufacturer-table").bootstrapTable("getSelections");
deleteManufacturerParts(selections, {
onSuccess: function() {
$("#manufacturer-table").bootstrapTable("refresh");
}
});
});
$('#manufacturer-create').click(function () {
constructForm('{% url "api-manufacturer-part-list" %}', {
fields: {
part: {
value: {{ part.pk }},
hidden: true,
},
manufacturer: {},
MPN: {},
description: {},
link: {},
},
method: 'POST',
title: '{% trans "Add Manufacturer Part" %}',
onSuccess: function() {
$("#manufacturer-table").bootstrapTable("refresh");
}
});
});
{% endblock %}

View File

@ -1,14 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='track' %}
{% endblock %}
{% block heading %}
{% trans "Part Tracking" %}
{% endblock %}
{% block details %}
{% endblock %}

View File

@ -1,39 +0,0 @@
{% extends "part/part_base.html" %}
{% load i18n %}
{% block menubar %}
{% include 'part/navbar.html' with tab='used' %}
{% endblock %}
{% block heading %}
{% trans "Assemblies" %}
{% endblock %}
{% block details %}
<div id='button-toolbar'>
<div class='filter-list' id='filter-list-usedin'>
<!-- Empty div (will be filled out with avilable BOM filters) -->
</div>
</div>
<table class="table table-striped table-condensed" id='used-table' data-toolbar='#button-toolbar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadPartTable('#used-table',
'{% url "api-part-list" %}',
{
params: {
uses: {{ part.pk }},
},
filterTarget: '#filter-list-usedin',
}
);
{% endblock %}

View File

@ -1,49 +0,0 @@
{% extends "part/part_base.html" %}
{% load static %}
{% load i18n %}
{% load inventree_extras %}
{% block menubar %}
{% include "part/navbar.html" with tab='variants' %}
{% endblock %}
{% block heading %}
{% trans "Part Variants" %}
{% endblock %}
{% block details %}
<div id='button-toolbar'>
<div class='button-toolbar container-fluid'>
<div class='btn-group' role='group'>
{% if part.is_template and part.active %}
<button class='btn btn-success' id='new-variant' title='{% trans "Create new variant" %}'>
<span class='fas fa-plus-circle'></span> {% trans "New Variant" %}
</button>
{% endif %}
</div>
<div class='filter-list' id='filter-list-variants'>
<!-- Empty div (will be filled out with available BOM filters) -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' id='variants-table' data-toolbar='#button-toolbar'>
</table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadPartVariantTable($('#variants-table'), {{ part.pk }});
$('#new-variant').click(function() {
launchModalForm(
"{% url 'make-part-variant' part.id %}",
{
follow: true,
}
);
});
{% endblock %}

View File

@ -158,21 +158,6 @@ class PartDetailTest(PartViewTestCase):
class PartTests(PartViewTestCase):
""" Tests for Part forms """
def test_part_edit(self):
response = self.client.get(reverse('part-edit', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest')
keys = response.context.keys()
data = str(response.content)
self.assertEqual(response.status_code, 200)
self.assertIn('part', keys)
self.assertIn('csrf_token', keys)
self.assertIn('html_form', data)
self.assertIn('"title":', data)
def test_part_create(self):
""" Launch form to create a new part """
response = self.client.get(reverse('part-create'), {'category': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')

View File

@ -36,7 +36,6 @@ part_parameter_urls = [
]
part_detail_urls = [
url(r'^edit/?', views.PartEdit.as_view(), name='part-edit'),
url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'),
url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'),
url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
@ -48,20 +47,6 @@ part_detail_urls = [
url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'),
url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'),
url(r'^variants/?', views.PartDetail.as_view(template_name='part/variants.html'), name='part-variants'),
url(r'^stock/?', views.PartDetail.as_view(template_name='part/stock.html'), name='part-stock'),
url(r'^allocation/?', views.PartDetail.as_view(template_name='part/allocation.html'), name='part-allocation'),
url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'),
url(r'^build/?', views.PartDetail.as_view(template_name='part/build.html'), name='part-build'),
url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'),
url(r'^prices/', views.PartPricingView.as_view(template_name='part/prices.html'), name='part-prices'),
url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'),
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'^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'),
url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'),
# Normal thumbnail with form
@ -91,9 +76,6 @@ category_urls = [
url(r'^delete/', views.CategoryDelete.as_view(), name='category-delete'),
url(r'^parameters/', include(category_parameter_urls)),
url(r'^subcategory/', views.CategoryDetail.as_view(template_name='part/subcategory.html'), name='category-subcategory'),
url(r'^parametric/', views.CategoryParametric.as_view(), name='category-parametric'),
# Anything else
url(r'^.*$', views.CategoryDetail.as_view(), name='category-detail'),
]))

View File

@ -754,6 +754,7 @@ class PartDetail(InvenTreeRoleMixin, DetailView):
context_object_name = 'part'
queryset = Part.objects.all().select_related('category')
template_name = 'part/detail.html'
form_class = part_forms.PartPriceForm
# Add in some extra context information based on query params
def get_context_data(self, **kwargs):
@ -774,25 +775,12 @@ class PartDetail(InvenTreeRoleMixin, DetailView):
ctx = part.get_context_data(self.request)
context.update(**ctx)
return context
class PartPricingView(PartDetail):
""" Detail view for Part object
"""
context_object_name = 'part'
template_name = 'part/order_prices.html'
form_class = part_forms.PartPriceForm
# Add in some extra context information based on query params
def get_context_data(self, **kwargs):
""" Provide extra context data to template """
context = super().get_context_data(**kwargs)
# Pricing information
ctx = self.get_pricing(self.get_quantity())
ctx['form'] = self.form_class(initial=self.get_initials())
context.update(ctx)
return context
def get_quantity(self):
@ -1084,40 +1072,6 @@ class PartImageSelect(AjaxUpdateView):
return self.renderJsonResponse(request, form, data)
class PartEdit(AjaxUpdateView):
""" View for editing Part object """
model = Part
form_class = part_forms.EditPartForm
ajax_template_name = 'modal_form.html'
ajax_form_title = _('Edit Part Properties')
context_object_name = 'part'
def get_form(self):
""" Create form for Part editing.
Overrides default get_form() method to limit the choices
for the 'default_supplier' field to SupplierParts that reference this part
"""
form = super(AjaxUpdateView, self).get_form()
# Hide the "default expiry" field if the feature is not enabled
if not inventree_settings.stock_expiry_enabled():
form.fields['default_expiry'].widget = HiddenInput()
part = self.get_object()
form.fields['default_supplier'].queryset = SupplierPart.objects.filter(part=part)
# Check if IPN can be edited
ipn_edit_enable = InvenTreeSetting.get_setting('PART_ALLOW_EDIT_IPN')
if not ipn_edit_enable and not self.request.user.is_superuser:
# Admin can still change IPN
form.fields['IPN'].disabled = True
return form
class BomDuplicate(AjaxUpdateView):
"""
View for duplicating BOM from a parent item.
@ -1475,7 +1429,7 @@ class BomUpload(InvenTreeRoleMixin, FileManagementFormView):
# BomItem already exists
pass
return HttpResponseRedirect(reverse('part-bom', kwargs={'pk': self.kwargs['pk']}))
return HttpResponseRedirect(reverse('part-detail', kwargs={'pk': self.kwargs['pk']}))
class PartExport(AjaxView):
@ -1852,7 +1806,7 @@ class CategoryDetail(InvenTreeRoleMixin, DetailView):
model = PartCategory
context_object_name = 'category'
queryset = PartCategory.objects.all().prefetch_related('children')
template_name = 'part/category_partlist.html'
template_name = 'part/category.html'
def get_context_data(self, **kwargs):
@ -1863,18 +1817,6 @@ class CategoryDetail(InvenTreeRoleMixin, DetailView):
except KeyError:
context['part_count'] = 0
return context
class CategoryParametric(CategoryDetail):
""" Parametric view for PartCategory """
template_name = 'part/category_parametric.html'
def get_context_data(self, **kwargs):
context = super(CategoryParametric, self).get_context_data(**kwargs).copy()
# Get current category
category = kwargs.get('object', None)

View File

@ -3,44 +3,360 @@
{% load static %}
{% load inventree_extras %}
{% load i18n %}
{% load markdownify %}
{% block menubar %}
{% include "stock/navbar.html" with tab="tracking" %}
{% include "stock/navbar.html" %}
{% endblock %}
{% block heading %}
{% trans "Stock Tracking Information" %}
{% endblock %}
{% block page_content %}
{% block details %}
<div class='panel panel-default panel-inventree panel-hidden' id='panel-history'>
<div class='panel-heading'>
<h4>{% trans "Stock Tracking Information" %}</h4>
</div>
<div class='panel-content'>
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners item.owner as owners %}
{% endif %}
<!-- Check permissions and owner -->
{% if owner_control.value == "False" or owner_control.value == "True" and user in owners %}
{% if roles.stock.change and not item.is_building %}
<div id='table-toolbar'>
<div class='btn-group'>
<button class='btn btn-success' type='button' title='New tracking entry' id='new-entry'>
<span class='fas fa-plus-circle'></span> {% trans "New Entry" %}
</button>
</div>
</div>
{% endif %}
{% endif %}
<table class='table table-condensed table-striped' id='track-table' data-toolbar='#table-toolbar'>
</table>
</div>
</div>
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners item.owner as owners %}
{% endif %}
<div class='panel panel-default panel-inventree panel-hidden' id='panel-children'>
<div class='panel-heading'>
<h4>{% trans "Child Stock Items" %}</h4>
</div>
<div class='panel-content'>
{% if item.child_count > 0 %}
{% include "stock_table.html" with prefix="childs-" %}
{% else %}
<div class='alert alert-block alert-info'>
{% trans "This stock item does not have any child items" %}
</div>
{% endif %}
</div>
</div>
<hr>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-test-data'>
<div class='panel-heading'>
<h4>{% trans "Test Data" %}</h4>
</div>
<div class='panel-content'>
<div id='test-button-toolbar'>
<div class='button-toolbar container-fluid' style="float: right;">
<div class='btn-group' role='group'>
{% if user.is_staff %}
<button type='button' class='btn btn-danger' id='delete-test-results'>
<span class='fas fa-trash-alt'></span> {% trans "Delete Test Data" %}
</button>
{% endif %}
<button type='button' class='btn btn-success' id='add-test-result'>
<span class='fas fa-plus-circle'></span> {% trans "Add Test Data" %}
</button>
<button type='button' class='btn btn-default' id='test-report'>
<span class='fas fa-tasks'></span> {% trans "Test Report" %}
</button>
</div>
<div class='filter-list' id='filter-list-stocktests'>
<!-- Empty div -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' data-toolbar='#test-button-toolbar' id='test-result-table'></table>
</div>
</div>
<!-- Check permissions and owner -->
{% if owner_control.value == "False" or owner_control.value == "True" and user in owners %}
{% if roles.stock.change and not item.is_building %}
<div id='table-toolbar'>
<div class='btn-group'>
<button class='btn btn-success' type='button' title='New tracking entry' id='new-entry'>
<span class='fas fa-plus-circle'></span> {% trans "New Entry" %}
</button>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-attachments'>
<div class='panel-heading'>
<h4>{% trans "Attachments" %}</h4>
</div>
<div class='panel-content'>
{% include "attachment_table.html" %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-notes'>
<div class='panel-heading'>
<div class='row'>
<div class='col-sm-6'>
<h4>{% trans "Stock Item Notes" %}</h4>
</div>
<div class='col-sm-6'>
<div class='btn-group float-right'>
<button type='button' id='edit-notes' title='{% trans "Edit Notes" %}' class='btn btn-small btn-default'>
<span class='fas fa-edit'>
</span>
</button>
</div>
</div>
</div>
</div>
{% endif %}
{% endif %}
<table class='table table-condensed table-striped' id='track-table' data-toolbar='#table-toolbar'>
</table>
<div class='panel-content'>
{% if item.notes %}
{{ item.notes | markdownify }}
{% endif %}
</div>
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-installed-items'>
<div class='panel-heading'>
<h4>{% trans "Installed Stock Items" %}</h4>
</div>
<div class='panel-content'>
<table class='table table-striped table-condensed' id='installed-table'></table>
</div>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadInstalledInTable(
$('#installed-table'),
{
stock_item: {{ item.pk }},
part: {{ item.part.pk }},
quantity: {{ item.quantity }},
}
);
$('#multi-item-uninstall').click(function() {
var selections = $('#installed-table').bootstrapTable('getSelections');
var items = [];
selections.forEach(function(item) {
items.push(item.pk);
});
launchModalForm(
"{% url 'stock-item-uninstall' %}",
{
data: {
'items[]': items,
},
reload: true,
}
);
});
$('#edit-notes').click(function() {
constructForm('{% url "api-stock-detail" item.pk %}', {
fields: {
notes: {
multiline: true,
}
},
title: '{% trans "Edit Notes" %}',
reload: true,
});
});
enableDragAndDrop(
'#attachment-dropzone',
"{% url 'api-stock-attachment-list' %}",
{
data: {
stock_item: {{ item.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
reloadAttachmentTable();
}
}
);
loadAttachmentTable(
'{% url "api-stock-attachment-list" %}',
{
filters: {
stock_item: {{ item.pk }},
},
onEdit: function(pk) {
var url = `/api/stock/attachment/${pk}/`;
constructForm(url, {
fields: {
comment: {},
},
title: '{% trans "Edit Attachment" %}',
onSuccess: reloadAttachmentTable
});
},
onDelete: function(pk) {
var url = `/api/stock/attachment/${pk}/`;
constructForm(url, {
method: 'DELETE',
confirmMessage: '{% trans "Confirm Delete Operation" %}',
title: '{% trans "Delete Attachment" %}',
onSuccess: reloadAttachmentTable,
});
}
}
);
$("#new-attachment").click(function() {
constructForm(
'{% url "api-stock-attachment-list" %}',
{
method: 'POST',
fields: {
attachment: {},
comment: {},
stock_item: {
value: {{ item.pk }},
hidden: true,
},
},
reload: true,
title: '{% trans "Add Attachment" %}',
}
);
});
loadStockTestResultsTable(
$("#test-result-table"), {
part: {{ item.part.id }},
stock_item: {{ item.id }},
}
);
function reloadTable() {
$("#test-result-table").bootstrapTable("refresh");
}
{% if item.has_test_reports %}
$("#test-report").click(function() {
printTestReports([{{ item.pk }}]);
});
{% endif %}
{% if user.is_staff %}
$("#delete-test-results").click(function() {
launchModalForm(
"{% url 'stock-item-delete-test-data' item.id %}",
{
success: reloadTable,
}
);
});
{% endif %}
$("#add-test-result").click(function() {
constructForm('{% url "api-stock-test-result-list" %}', {
method: 'POST',
fields: {
test: {},
result: {},
value: {},
attachment: {},
notes: {},
stock_item: {
value: {{ item.pk }},
hidden: true,
}
},
title: '{% trans "Add Test Result" %}',
onSuccess: reloadTable,
});
});
$("#test-result-table").on('click', '.button-test-add', function() {
var button = $(this);
var test_name = button.attr('pk');
constructForm('{% url "api-stock-test-result-list" %}', {
method: 'POST',
fields: {
test: {
value: test_name,
},
result: {},
value: {},
attachment: {},
notes: {},
stock_item: {
value: {{ item.pk }},
hidden: true,
}
},
title: '{% trans "Add Test Result" %}',
onSuccess: reloadTable,
});
});
$("#test-result-table").on('click', '.button-test-edit', function() {
var button = $(this);
var pk = button.attr('pk');
var url = `/api/stock/test/${pk}/`;
constructForm(url, {
fields: {
test: {},
result: {},
value: {},
attachment: {},
notes: {},
},
title: '{% trans "Edit Test Result" %}',
onSuccess: reloadTable,
});
});
$("#test-result-table").on('click', '.button-test-delete', function() {
var button = $(this);
var pk = button.attr('pk');
var url = `/api/stock/test/${pk}/`;
constructForm(url, {
method: 'DELETE',
title: '{% trans "Delete Test Result" %}',
onSuccess: reloadTable,
});
});
{% if item.child_count > 0 %}
loadStockTable($("#childs-stock-table"), {
params: {
location_detail: true,
part_detail: false,
ancestor: {{ item.id }},
},
name: 'item-childs',
groupByField: 'location',
buttons: [
'#stock-options',
],
url: "{% url 'api-stock-list' %}",
});
{% endif %}
$("#new-entry").click(function() {
launchModalForm(
"{% url 'stock-tracking-create' item.id %}",

View File

@ -1,86 +0,0 @@
{% extends "stock/item_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "stock/navbar.html" with tab='attachments' %}
{% endblock %}
{% block heading %}
{% trans "Stock Item Attachments" %}
{% endblock %}
{% block details %}
{% include "attachment_table.html" with attachments=item.attachments.all %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableDragAndDrop(
'#attachment-dropzone',
"{% url 'api-stock-attachment-list' %}",
{
data: {
stock_item: {{ item.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
reloadAttachmentTable();
}
}
);
loadAttachmentTable(
'{% url "api-stock-attachment-list" %}',
{
filters: {
stock_item: {{ item.pk }},
},
onEdit: function(pk) {
var url = `/api/stock/attachment/${pk}/`;
constructForm(url, {
fields: {
comment: {},
},
title: '{% trans "Edit Attachment" %}',
onSuccess: reloadAttachmentTable
});
},
onDelete: function(pk) {
var url = `/api/stock/attachment/${pk}/`;
constructForm(url, {
method: 'DELETE',
confirmMessage: '{% trans "Confirm Delete Operation" %}',
title: '{% trans "Delete Attachment" %}',
onSuccess: reloadAttachmentTable,
});
}
}
);
$("#new-attachment").click(function() {
constructForm(
'{% url "api-stock-attachment-list" %}',
{
method: 'POST',
fields: {
attachment: {},
comment: {},
stock_item: {
value: {{ item.pk }},
hidden: true,
},
},
reload: true,
title: '{% trans "Add Attachment" %}',
}
);
});
{% endblock %}

View File

@ -235,7 +235,7 @@
<td>{% trans "Base Part" %}</td>
<td>
{% if roles.part.view %}
<a href="{% url 'part-stock' item.part.id %}">
<a href="{% url 'part-detail' item.part.id %}">
{% endif %}
{{ item.part.full_name }}
{% if roles.part.view %}
@ -428,6 +428,7 @@
</tr>
{% endif %}
</table>
{% endblock %}
{% block js_ready %}
@ -561,7 +562,7 @@ $("#stock-delete").click(function () {
launchModalForm(
"{% url 'stock-item-delete' item.id %}",
{
redirect: "{% url 'part-stock' item.part.id %}"
redirect: "{% url 'part-detail' item.part.id %}"
}
);
});
@ -610,4 +611,9 @@ $("#stock-return-from-customer").click(function() {
{% endif %}
attachNavCallbacks({
name: 'stockitem',
default: 'history'
});
{% endblock %}

View File

@ -1,45 +0,0 @@
{% extends "stock/item_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "stock/navbar.html" with tab='children' %}
{% endblock %}
{% block heading %}
{% trans "Child Stock Items" %}
{% endblock %}
{% block details %}
{% if item.child_count > 0 %}
{% include "stock_table.html" %}
{% else %}
<div class='alert alert-block alert-info'>
{% trans "This stock item does not have any child items" %}
</div>
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% if item.child_count > 0 %}
loadStockTable($("#stock-table"), {
params: {
location_detail: true,
part_detail: false,
ancestor: {{ item.id }},
},
name: 'item-childs',
groupByField: 'location',
buttons: [
'#stock-options',
],
url: "{% url 'api-stock-list' %}",
});
{% endif %}
{% endblock %}

View File

@ -1,53 +0,0 @@
{% extends "stock/item_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "stock/navbar.html" with tab='installed' %}
{% endblock %}
{% block heading %}
{% trans "Installed Stock Items" %}
{% endblock %}
{% block details %}
<table class='table table-striped table-condensed' id='installed-table'></table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadInstalledInTable(
$('#installed-table'),
{
stock_item: {{ item.pk }},
part: {{ item.part.pk }},
quantity: {{ item.quantity }},
}
);
$('#multi-item-uninstall').click(function() {
var selections = $('#installed-table').bootstrapTable('getSelections');
var items = [];
selections.forEach(function(item) {
items.push(item.pk);
});
launchModalForm(
"{% url 'stock-item-uninstall' %}",
{
data: {
'items[]': items,
},
reload: true,
}
);
});
{% endblock %}

View File

@ -1,51 +0,0 @@
{% extends "stock/item_base.html" %}
{% load static %}
{% load inventree_extras %}
{% load i18n %}
{% load markdownify %}
{% block menubar %}
{% include "stock/navbar.html" with tab="notes" %}
{% endblock %}
{% block heading %}
{% trans "Stock Item Notes" %}
{% if roles.stock.change and not editing %}
<button title='{% trans "Edit notes" %}' class='btn btn-default' id='edit-notes'><span class='fas fa-edit'></span></button>
{% endif %}
{% endblock %}
{% block details %}
{% if editing %}
<form method='POST'>
{% csrf_token %}
{{ form }}
<hr>
<button type="submit" class='btn btn-default'>{% trans "Save" %}</button>
</form>
{{ form.media }}
{% else %}
{% if item.notes %}
{{ item.notes | markdownify }}
{% endif %}
{% endif %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
{% if editing %}
{% else %}
$("#edit-notes").click(function() {
location.href = "{% url 'stock-item-notes' item.id %}?edit=1";
});
{% endif %}
{% endblock %}

View File

@ -1,150 +0,0 @@
{% extends "stock/item_base.html" %}
{% load static %}
{% load i18n %}
{% block menubar %}
{% include "stock/navbar.html" with tab='tests' %}
{% endblock %}
{% block heading %}
{% trans "Test Data" %}
{% endblock %}
{% block details %}
<div id='button-toolbar'>
<div class='button-toolbar container-fluid' style="float: right;">
<div class='btn-group' role='group'>
{% if user.is_staff %}
<button type='button' class='btn btn-danger' id='delete-test-results'>
<span class='fas fa-trash-alt'></span> {% trans "Delete Test Data" %}
</button>
{% endif %}
<button type='button' class='btn btn-success' id='add-test-result'>
<span class='fas fa-plus-circle'></span> {% trans "Add Test Data" %}
</button>
<button type='button' class='btn btn-default' id='test-report'>
<span class='fas fa-tasks'></span> {% trans "Test Report" %}
</button>
</div>
<div class='filter-list' id='filter-list-stocktests'>
<!-- Empty div -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='test-result-table'></table>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadStockTestResultsTable(
$("#test-result-table"), {
part: {{ item.part.id }},
stock_item: {{ item.id }},
}
);
function reloadTable() {
$("#test-result-table").bootstrapTable("refresh");
}
{% if item.has_test_reports %}
$("#test-report").click(function() {
printTestReports([{{ item.pk }}]);
});
{% endif %}
{% if user.is_staff %}
$("#delete-test-results").click(function() {
launchModalForm(
"{% url 'stock-item-delete-test-data' item.id %}",
{
success: reloadTable,
}
);
});
{% endif %}
$("#add-test-result").click(function() {
constructForm('{% url "api-stock-test-result-list" %}', {
method: 'POST',
fields: {
test: {},
result: {},
value: {},
attachment: {},
notes: {},
stock_item: {
value: {{ item.pk }},
hidden: true,
}
},
title: '{% trans "Add Test Result" %}',
onSuccess: reloadTable,
});
});
$("#test-result-table").on('click', '.button-test-add', function() {
var button = $(this);
var test_name = button.attr('pk');
constructForm('{% url "api-stock-test-result-list" %}', {
method: 'POST',
fields: {
test: {
value: test_name,
},
result: {},
value: {},
attachment: {},
notes: {},
stock_item: {
value: {{ item.pk }},
hidden: true,
}
},
title: '{% trans "Add Test Result" %}',
onSuccess: reloadTable,
});
});
$("#test-result-table").on('click', '.button-test-edit', function() {
var button = $(this);
var pk = button.attr('pk');
var url = `/api/stock/test/${pk}/`;
constructForm(url, {
fields: {
test: {},
result: {},
value: {},
attachment: {},
notes: {},
},
title: '{% trans "Edit Test Result" %}',
onSuccess: reloadTable,
});
});
$("#test-result-table").on('click', '.button-test-delete', function() {
var button = $(this);
var pk = button.attr('pk');
var url = `/api/stock/test/${pk}/`;
constructForm(url, {
method: 'DELETE',
title: '{% trans "Delete Test Result" %}',
onSuccess: reloadTable,
});
});
{% endblock %}

View File

@ -4,7 +4,7 @@
{% load i18n %}
{% block menubar %}
{% include "stock/location_navbar.html" with tab="stock" %}
{% include "stock/location_navbar.html" %}
{% endblock %}
{% block content %}
@ -143,13 +143,39 @@
{% block location_content %}
<div class='panel panel-default panel-inventree'>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-stock'>
<div class='panel-heading'>
<h4>{% trans "Stock Items" %}</h4>
</div>
{% include "stock_table.html" %}
</div>
<div class='panel panel-default panel-inventree panel-hidden' id='panel-sublocations'>
<div class='panel-heading'>
<h4>{% trans "Sublocations" %}</h4>
</div>
<div class='panel-content'>
<div id='sublocation-button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<!-- Printing actions menu -->
<div class='btn-group'>
<button id='location-print-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown" title='{% trans "Printing Actions" %}'>
<span class='fas fa-print'></span> <span class='caret'></span>
</button>
<ul class='dropdown-menu'>
<li><a href='#' id='multi-location-print-label' title='{% trans "Print labels" %}'><span class='fas fa-tags'></span> {% trans "Print labels" %}</a></li>
</ul>
</div>
<div class='filter-list' id='filter-list-location'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' data-toolbar='#sublocation-button-toolbar' id='sublocation-table'></table>
</div>
</div>
{% endblock %}
</div>
@ -164,6 +190,36 @@
toggleId: '#location-menu-toggle'
});
loadStockLocationTable($('#sublocation-table'), {
params: {
{% if location %}
parent: {{ location.pk }},
{% else %}
parent: 'null',
{% endif %}
}
});
linkButtonsToSelection(
$('#sublocation-table'),
[
'#location-print-options',
]
);
$('#multi-location-print-label').click(function() {
var selections = $('#sublocation-table').bootstrapTable('getSelections');
var locations = [];
selections.forEach(function(loc) {
locations.push(loc.pk);
});
printStockLocationLabels(locations);
});
{% if location %}
$("#barcode-check-in").click(function() {
barcodeCheckIn({{ location.id }});
@ -301,4 +357,10 @@
},
url: "{% url 'api-stock-list' %}",
});
attachNavCallbacks({
name: 'stocklocation',
default: 'stock'
});
{% endblock %}

View File

@ -8,23 +8,15 @@
</a>
</li>
<li class='list-group-item {% if tab == "sublocations" %}active{% endif %}' title='{% trans "Sublocations" %}'>
{% if location %}
<a href='{% url "stock-location-sublocation" location.id %}'>
{% else %}
<a href='{% url "stock-sublocations" %}'>
{% endif %}
<li class='list-group-item' title='{% trans "Sublocations" %}'>
<a href='#' id='select-sublocations' class='nav-toggle'>
<span class='fas fa-sitemap sidebar-icon'></span>
{% trans "Sublocations" %}
</a>
</li>
<li class='list-group-item {% if tab == "stock" %}active{% endif %}' title='{% trans "Stock Items" %}'>
{% if location %}
<a href='{% url "stock-location-detail" location.id %}'>
{% else %}
<a href='{% url "stock-index" %}'>
{% endif %}
<a href='#' id='select-stock' class='nav-toggle'>
<span class='fas fa-boxes sidebar-icon'></span>
{% trans "Stock Items" %}
</a>

View File

@ -8,24 +8,24 @@
</a>
</li>
<li class='list-group-item {% if tab == "tracking" %}active{% endif %}' title='{% trans "Stock Item Tracking" %}'>
<a href='{% url "stock-item-detail" item.id %}'>
<li class='list-group-item' title='{% trans "Stock Item Tracking" %}'>
<a href='#' id='select-history' class='nav-toggle'>
<span class='fas fa-history sidebar-icon'></span>
{% trans "History" %}
</a>
</li>
{% if item.part.trackable %}
<li class='list-group-item {% if tab == "tests" %}active{% endif %}' title='{% trans "Test Data" %}'>
<a href='{% url "stock-item-test-results" item.id %}'>
<li class='list-group-item' title='{% trans "Test Data" %}'>
<a href='#' id='select-test-data' class='nav-toggle'>
<span class='fas fa-vial sidebar-icon'></span>
{% trans "Test Data" %}
</a>
</li>
{% if item.part.assembly %}
<li class='list-group-item {% if tab == "installed" %}active{% endif %}' title='{% trans "Installed Stock Items" %}'>
<a href='{% url "stock-item-installed" item.id %}'>
<li class='list-group-item' title='{% trans "Installed Stock Items" %}'>
<a href='#' id='select-installed-items' class='nav-toggle'>
<span class='fas fa-sign-in-alt sidebar-icon'></span>
{% trans "Installed Items" %}
</a>
@ -35,8 +35,8 @@
{% endif %}
{% if item.child_count > 0 %}
<li class='list-group-item {% if tab == "children" %}active{% endif %}' title='{% trans "Child Items" %}'>
<a href='{% url "stock-item-children" item.id %}'>
<li class='list-group-item' title='{% trans "Child Items" %}'>
<a href='#' id='select-children' class='nav-toggle'>
<span class='fas fa-sitemap sidebar-icon'></span>
{% trans "Children" %}
</a>
@ -44,15 +44,15 @@
{% endif %}
<li class='list-group-item {% if tab == "attachments" %}active{% endif %}' title='{% trans "Attachments" %}'>
<a href='{% url "stock-item-attachments" item.id %}'>
<li class='list-group-item' title='{% trans "Attachments" %}'>
<a href='#' id='select-attachments' class='nav-toggle'>
<span class='fas fa-paperclip sidebar-icon'></span>
{% trans "Attachments" %}
</a>
</li>
<li class='list-group-item {% if tab == "notes" %}active{% endif %}' title='{% trans "Stock Item Notes" %}'>
<a href='{% url "stock-item-notes" item.id %}'>
<li class='list-group-item' title='{% trans "Stock Item Notes" %}'>
<a href='#' id='select-notes' class='nav-toggle'>
<span class='fas fa-clipboard sidebar-icon'></span>
{% trans "Notes" %}
</a>

View File

@ -1,74 +0,0 @@
{% extends "stock/location.html" %}
{% load static %}
{% load i18n %}
{% load inventree_extras %}
{% block menubar %}
{% include "stock/location_navbar.html" with tab="sublocations" %}
{% endblock %}
{% block location_content %}
<div class='panel panel-default panel-inventree'>
<div class='panel-heading'>
<h4>{% trans "Sublocations" %}</h4>
</div>
<div id='button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'>
<!-- Printing actions menu -->
<div class='btn-group'>
<button id='location-print-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown" title='{% trans "Printing Actions" %}'>
<span class='fas fa-print'></span> <span class='caret'></span>
</button>
<ul class='dropdown-menu'>
<li><a href='#' id='multi-location-print-label' title='{% trans "Print labels" %}'><span class='fas fa-tags'></span> {% trans "Print labels" %}</a></li>
</ul>
</div>
<div class='filter-list' id='filter-list-location'>
<!-- An empty div in which the filter list will be constructed -->
</div>
</div>
</div>
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='sublocation-table'></table>
</div>
{% endblock %}
{% block js_ready %}
{{ block.super }}
loadStockLocationTable($('#sublocation-table'), {
params: {
{% if location %}
parent: {{ location.pk }},
{% else %}
parent: 'null',
{% endif %}
}
});
linkButtonsToSelection(
$('#sublocation-table'),
[
'#location-print-options',
]
);
$('#multi-location-print-label').click(function() {
var selections = $('#sublocation-table').bootstrapTable('getSelections');
var locations = [];
selections.forEach(function(loc) {
locations.push(loc.pk);
});
printStockLocationLabels(locations);
})
{% endblock %}

View File

@ -14,9 +14,7 @@ location_urls = [
url(r'^edit/?', views.StockLocationEdit.as_view(), name='stock-location-edit'),
url(r'^delete/?', views.StockLocationDelete.as_view(), name='stock-location-delete'),
url(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'),
url(r'sublocation/', views.StockLocationDetail.as_view(template_name='stock/sublocation.html'), name='stock-location-sublocation'),
# Anything else
url('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'),
])),
@ -36,12 +34,6 @@ stock_item_detail_urls = [
url(r'^add_tracking/', views.StockItemTrackingCreate.as_view(), name='stock-tracking-create'),
url(r'^test/', views.StockItemDetail.as_view(template_name='stock/item_tests.html'), name='stock-item-test-results'),
url(r'^children/', views.StockItemDetail.as_view(template_name='stock/item_childs.html'), name='stock-item-children'),
url(r'^attachments/', views.StockItemDetail.as_view(template_name='stock/item_attachments.html'), name='stock-item-attachments'),
url(r'^installed/', views.StockItemDetail.as_view(template_name='stock/item_installed.html'), name='stock-item-installed'),
url(r'^notes/', views.StockItemNotes.as_view(), name='stock-item-notes'),
url('^.*$', views.StockItemDetail.as_view(), name='stock-item-detail'),
]

View File

@ -149,22 +149,23 @@
<!-- translated -->
<script type='text/javascript' src="{% i18n_static 'api.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'attachment.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'forms.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'model_renderers.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'barcode.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'bom.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'build.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'calendar.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'company.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'part.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'modals.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'filters.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'forms.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'label.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'nav.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'modals.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'model_renderers.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'order.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'part.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'report.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'stock.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'build.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'order.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'calendar.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'tables.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'table_filters.js' %}"></script>
<script type='text/javascript' src="{% i18n_static 'filters.js' %}"></script>
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>

View File

@ -3,6 +3,14 @@
var jQuery = window.$;
$.urlParam = function(name){
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (results==null) {
return null;
}
return decodeURI(results[1]) || 0;
}
// using jQuery
function getCookie(name) {
var cookieValue = null;

View File

@ -921,7 +921,7 @@ function loadBuildTable(table, options) {
}
else
{
return '{% trans "No user information" %}';
return `<i>{% trans "No user information" %}</i>`;
}
}
},

View File

@ -0,0 +1,84 @@
/*
* Attach callbacks to navigation bar elements.
*
* Searches for elements with the class 'nav-toggle'.
* A callback is added to each element,
* to display the matching panel.
*
* The 'id' of the .nav-toggle element should be of the form "select-<x>",
* and point to a matching "panel-<x>"
*/
function attachNavCallbacks(options={}) {
$('.nav-toggle').click(function() {
var el = $(this);
// Find the matching "panel" element
var panelName = el.attr('id').replace('select-', '');
activatePanel(panelName, options);
});
var panelClass = options.name || 'unknown';
/* Look for a default panel to initialize
* First preference = URL parameter e.g. ?display=part-stock
* Second preference = localStorage
* Third preference = default
*/
var defaultPanel = $.urlParam('display') || localStorage.getItem(`inventree-selected-panel-${panelClass}`) || options.default;
if (defaultPanel) {
activatePanel(defaultPanel);
}
}
function activatePanel(panelName, options={}) {
var panelClass = options.name || 'unknown';
// First, cause any other panels to "fade out"
$('.panel-visible').hide();
$('.panel-visible').removeClass('panel-visible');
// Find the target panel
var panel = `#panel-${panelName}`;
var select = `#select-${panelName}`;
// Check that the selected panel (and select) exist
if ($(panel).length && $(select).length) {
// Yep, both are displayed
} else {
// Either the select or the panel are not displayed!
// Iterate through the available 'select' elements until one matches
panelName = null;
$('.nav-toggle').each(function(item) {
var panel_name = $(this).attr('id').replace('select-', '');
if ($(`#panel-${panel_name}`).length && (panelName == null)) {
panelName = panel_name;
}
panel = `#panel-${panelName}`;
select = `#select-${panelName}`;
});
}
// Save the selected panel
localStorage.setItem(`inventree-selected-panel-${panelClass}`, panelName);
// Display the panel
$(panel).addClass('panel-visible');
$(panel).fadeIn(100);
// Un-select all selectors
$('.list-group-item').removeClass('active');
// Find the associated selector
var select = `#select-${panelName}`;
$(select).parent('.list-group-item').addClass('active');
}

View File

@ -13,6 +13,94 @@ function yesNoLabel(value) {
}
}
function editPart(pk, options={}) {
var url = `/api/part/${pk}/`;
var fields = {
category: {
/*
secondary: {
label: '{% trans "New Category" %}',
title: '{% trans "Create New Part Category" %}',
api_url: '{% url "api-part-category-list" %}',
method: 'POST',
fields: {
name: {},
description: {},
parent: {
secondary: {
title: '{% trans "New Parent" %}',
api_url: '{% url "api-part-category-list" %}',
method: 'POST',
fields: {
name: {},
description: {},
parent: {},
}
}
},
}
},
*/
},
name: {
placeholder: 'part name',
},
IPN: {},
description: {},
revision: {},
keywords: {
icon: 'fa-key',
},
variant_of: {},
link: {
icon: 'fa-link',
},
default_location: {
/*
secondary: {
label: '{% trans "New Location" %}',
title: '{% trans "Create new stock location" %}',
},
*/
},
default_supplier: {
filters: {
part: pk,
part_detail: true,
manufacturer_detail: true,
supplier_detail: true,
},
/*
secondary: {
label: '{% trans "New Supplier Part" %}',
title: '{% trans "Create new supplier part" %}',
}
*/
},
units: {},
minimum_stock: {},
virtual: {},
is_template: {},
assembly: {},
component: {},
trackable: {},
purchaseable: {},
salable: {},
active: {},
};
constructForm(url, {
fields: fields,
title: '{% trans "Edit Part" %}',
reload: true,
});
}
function toggleStar(options) {
/* Toggle the 'starred' status of a part.
* Performs AJAX queries and updates the display on the button.
@ -626,7 +714,7 @@ function loadPartTable(table, url, options={}) {
var html = '';
html = `<div class='row'>`;
html = `<div class='row full-height'>`;
data.forEach(function(row, index) {

View File

@ -1495,7 +1495,7 @@ function loadStockTrackingTable(table, options) {
}
else
{
return '{% trans "No user information" %}';
return `<i>{% trans "No user information" %}</i>`;
}
}
});

Some files were not shown because too many files have changed in this diff Show More