2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 13:05:42 +00:00

Project code support (#4636)

* Support image uploads in the "notes" markdown fields

- Implemented using the existing EasyMDE library
- Copy / paste support
- Drag / drop support

* Remove debug message

* Updated API version

* Better UX when saving notes

* Pin PIP version (for testing)

* Bug fixes

- Fix typo
- Use correct serializer type

* Add unit testing

* Update role permissions

* Typo fix

* Update migration file

* Adds a notes mixin class to be used for refactoring

* Refactor existing models with notes to use the new mixin

* Add helper function for finding all model types with a certain mixin

* Refactor barcode plugin to use new method

* Typo fix

* Add daily task to delete old / unused notes

* Add ProjectCode model

(cherry picked from commit 382a0a2fc32c930d46ed3fe0c6d2cae654c2209d)

* Adds IsStaffOrReadyOnly permissions

- Authenticated users get read-only access
- Staff users get read/write access

(cherry picked from commit 53d04da86c4c866fd9c909d147d93844186470b4)

* Adds API endpoints for project codes

(cherry picked from commit 5ae1da23b2eae4e1168bc6fe28a3544dedc4a1b4)

* Add migration file for projectcode model

(cherry picked from commit 5f8717712c65df853ea69907d33e185fd91df7ee)

* Add project code configuration page to the global settings view

* Add 'project code' field to orders

* Add ability to set / edit the project code for various order models

* Add project code info to order list tables

* Add configuration options for project code integration

* Allow orders to be filtered by project code

* Refactor table_filters.js

- Allow orders to be filtered dynamically by project code

* Bump API version

* Fixes

* Add resource mixin for exporting project code in order list

* Add "has_project_code" filter

* javascript fix

* Edit / delete project codes via API

- Also refactor some existing JS

* Move MetadataMixin to InvenTree.models

To prevent circular imports

(cherry picked from commit d23b013881eaffe612dfbfcdfc5dff6d729068c6)

* Fixes for circular imports

* Add metadata for ProjectCode model

* Add Metadata API endpoint for ProjectCode

* Add unit testing for ProjectCode API endpoints
This commit is contained in:
Oliver
2023-04-20 00:47:07 +10:00
committed by GitHub
parent eafd2ac966
commit 070e2afcea
39 changed files with 1315 additions and 683 deletions

View File

@ -0,0 +1,35 @@
{% extends "panel.html" %}
{% load i18n %}
{% load inventree_extras %}
{% block label %}project-codes{% endblock label %}
{% block heading %}{% trans "Project Code Settings" %}{% endblock heading %}
{% block content %}
<!-- Project code settings -->
<table class='table table-striped table-condensed'>
<tbody>
{% include "InvenTree/settings/setting.html" with key="PROJECT_CODES_ENABLED" icon='fa-toggle-on' %}
</tbody>
</table>
<div class='panel-heading'>
<div class='d-flex flex-span'>
<h4>{% trans "Project Codes" %}</h4>
{% include "spacer.html" %}
<div class='btn-group' role='group'>
<button class='btn btn-success' id='new-project-code'>
<span class='fas fa-plus-circle'></span> {% trans "New Project Code" %}
</button>
</div>
</div>
</div>
<table class='table table-striped table-condensed' id='project-code-table'>
</table>
{% endblock content %}

View File

@ -31,6 +31,7 @@
{% include "InvenTree/settings/global.html" %}
{% include "InvenTree/settings/login.html" %}
{% include "InvenTree/settings/barcode.html" %}
{% include "InvenTree/settings/project_codes.html" %}
{% include "InvenTree/settings/notifications.html" %}
{% include "InvenTree/settings/label.html" %}
{% include "InvenTree/settings/report.html" %}

View File

@ -52,6 +52,78 @@ onPanelLoad('pricing', function() {
});
});
// Javascript for project codes panel
onPanelLoad('project-codes', function() {
// Construct the project code table
$('#project-code-table').bootstrapTable({
url: '{% url "api-project-code-list" %}',
search: true,
sortable: true,
formatNoMatches: function() {
return '{% trans "No project codes found" %}';
},
columns: [
{
field: 'code',
sortable: true,
title: '{% trans "Project Code" %}',
},
{
field: 'description',
sortable: false,
title: '{% trans "Description" %}',
formatter: function(value, row) {
let html = value;
let buttons = '';
buttons += makeEditButton('button-project-code-edit', row.pk, '{% trans "Edit Project Code" %}');
buttons += makeDeleteButton('button-project-code-delete', row.pk, '{% trans "Delete Project Code" %}');
html += wrapButtons(buttons);
return html;
}
}
]
});
$('#project-code-table').on('click', '.button-project-code-edit', function() {
let pk = $(this).attr('pk');
constructForm(`{% url "api-project-code-list" %}${pk}/`, {
title: '{% trans "Edit Project Code" %}',
fields: {
code: {},
description: {},
},
refreshTable: '#project-code-table',
});
});
$('#project-code-table').on('click', '.button-project-code-delete', function() {
let pk = $(this).attr('pk');
constructForm(`{% url "api-project-code-list" %}${pk}/`, {
title: '{% trans "Delete Project Code" %}',
method: 'DELETE',
refreshTable: '#project-code-table',
});
});
$('#new-project-code').click(function() {
// Construct a new project code
constructForm('{% url "api-project-code-list" %}', {
fields: {
code: {},
description: {},
},
title: '{% trans "New Project Code" %}',
method: 'POST',
refreshTable: '#project-code-table',
});
})
});
// Javascript for Part Category panel
onPanelLoad('category', function() {
$('#category-select').select2({
@ -136,11 +208,12 @@ onPanelLoad('category', function() {
title: '{% trans "Default Value" %}',
sortable: 'true',
formatter: function(value, row, index, field) {
var bEdit = "<button title='{% trans "Edit Template" %}' class='template-edit btn btn-outline-secondary' type='button' pk='" + row.pk + "'><span class='fas fa-edit'></span></button>";
var bDel = "<button title='{% trans "Delete Template" %}' class='template-delete btn btn-outline-secondary' type='button' pk='" + row.pk + "'><span class='fas fa-trash-alt icon-red'></span></button>";
let buttons = '';
buttons += makeEditButton('template-edit', row.pk, '{% trans "Edit Template" %}');
buttons += makeDeleteButton('template-delete', row.pk, '{% trans "Delete Template" %}');
var html = value
html += "<div class='btn-group float-right' role='group'>" + bEdit + bDel + "</div>";
let html = value
html += wrapButtons(buttons);
return html;
}
@ -154,6 +227,7 @@ onPanelLoad('category', function() {
var pk = $(this).attr('pk');
constructForm(`/api/part/category/parameters/${pk}/`, {
title: '{% trans "Edit Category Parameter Template" %}',
fields: {
parameter_template: {},
category: {

View File

@ -30,6 +30,8 @@
{% include "sidebar_item.html" with label='login' text=text icon="fa-fingerprint" %}
{% trans "Barcode Support" as text %}
{% include "sidebar_item.html" with label='barcodes' text=text icon="fa-qrcode" %}
{% trans "Project Codes" as text %}
{% include "sidebar_item.html" with label='project-codes' text=text icon="fa-list" %}
{% trans "Notifications" as text %}
{% include "sidebar_item.html" with label='global-notifications' text=text icon="fa-bell" %}
{% trans "Pricing" as text %}

View File

@ -1123,9 +1123,9 @@ function loadSupplierPartTable(table, url, options) {
var params = options.params || {};
// Load filters
var filters = loadTableFilters('supplier-part', params);
var filters = loadTableFilters('supplierpart', params);
setupFilterList('supplier-part', $(table));
setupFilterList('supplierpart', $(table));
$(table).inventreeTable({
url: url,

View File

@ -16,6 +16,7 @@
renderOwner,
renderPart,
renderPartCategory,
renderProjectCode,
renderReturnOrder,
renderStockItem,
renderStockLocation,
@ -78,6 +79,8 @@ function getModelRenderer(model) {
return renderUser;
case 'group':
return renderGroup;
case 'projectcode':
return renderProjectCode;
default:
// Un-handled model type
console.error(`Rendering not implemented for model '${model}'`);
@ -476,3 +479,16 @@ function renderSupplierPart(data, parameters={}) {
parameters
);
}
// Renderer for "ProjectCode" model
function renderProjectCode(data, parameters={}) {
return renderModel(
{
text: data.code,
textSecondary: data.description,
},
parameters
);
}

View File

@ -62,6 +62,9 @@ function purchaseOrderFields(options={}) {
}
},
supplier_reference: {},
project_code: {
icon: 'fa-list',
},
target_date: {
icon: 'fa-calendar-alt',
},
@ -126,6 +129,10 @@ function purchaseOrderFields(options={}) {
};
}
if (!global_settings.PROJECT_CODES_ENABLED) {
delete fields.project_code;
}
return fields;
}
@ -1614,6 +1621,18 @@ function loadPurchaseOrderTable(table, options) {
field: 'description',
title: '{% trans "Description" %}',
},
{
field: 'project_code',
title: '{% trans "Project Code" %}',
switchable: global_settings.PROJECT_CODES_ENABLED,
visible: global_settings.PROJECT_CODES_ENABLED,
sortable: true,
formatter: function(value, row) {
if (row.project_code_detail) {
return `<span title='${row.project_code_detail.description}'>${row.project_code_detail.code}</span>`;
}
}
},
{
field: 'status',
title: '{% trans "Status" %}',

View File

@ -46,6 +46,9 @@ function returnOrderFields(options={}) {
}
},
customer_reference: {},
project_code: {
icon: 'fa-list',
},
target_date: {
icon: 'fa-calendar-alt',
},
@ -69,6 +72,10 @@ function returnOrderFields(options={}) {
}
};
if (!global_settings.PROJECT_CODES_ENABLED) {
delete fields.project_code;
}
return fields;
}
@ -271,6 +278,18 @@ function loadReturnOrderTable(table, options={}) {
field: 'description',
title: '{% trans "Description" %}',
},
{
field: 'project_code',
title: '{% trans "Project Code" %}',
switchable: global_settings.PROJECT_CODES_ENABLED,
visible: global_settings.PROJECT_CODES_ENABLED,
sortable: true,
formatter: function(value, row) {
if (row.project_code_detail) {
return `<span title='${row.project_code_detail.description}'>${row.project_code_detail.code}</span>`;
}
}
},
{
sortable: true,
field: 'status',

View File

@ -59,6 +59,9 @@ function salesOrderFields(options={}) {
}
},
customer_reference: {},
project_code: {
icon: 'fa-list',
},
target_date: {
icon: 'fa-calendar-alt',
},
@ -82,6 +85,10 @@ function salesOrderFields(options={}) {
}
};
if (!global_settings.PROJECT_CODES_ENABLED) {
delete fields.project_code;
}
return fields;
}
@ -739,6 +746,18 @@ function loadSalesOrderTable(table, options) {
field: 'description',
title: '{% trans "Description" %}',
},
{
field: 'project_code',
title: '{% trans "Project Code" %}',
switchable: global_settings.PROJECT_CODES_ENABLED,
visible: global_settings.PROJECT_CODES_ENABLED,
sortable: true,
formatter: function(value, row) {
if (row.project_code_detail) {
return `<span title='${row.project_code_detail.description}'>${row.project_code_detail.code}</span>`;
}
}
},
{
sortable: true,
field: 'status',

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
{% load i18n %}
{% if instance and instance.project_code %}
<tr>
<td><span class='fas fa-list'></span></td>
<td>{% trans "Project Code" %}</td>
<td>
{{ instance.project_code.code }} - <em><small>{{ instance.project_code.description }}</small></em>
</td>
</tr>
{% endif %}