Add notes to mp and sp (#7667)

* add notes to mp and sp

* bump api version
This commit is contained in:
Lukas 2024-07-17 00:02:47 +02:00 committed by GitHub
parent b783f521de
commit 453254c278
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 124 additions and 3 deletions

View File

@ -1,12 +1,15 @@
"""InvenTree API version information.""" """InvenTree API version information."""
# InvenTree API version # InvenTree API version
INVENTREE_API_VERSION = 223 INVENTREE_API_VERSION = 224
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" """Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """ INVENTREE_API_TEXT = """
v224 - 2024-07-14 : https://github.com/inventree/InvenTree/pull/7667
- Add notes field to ManufacturerPart and SupplierPart API endpoints
v223 - 2024-07-14 : https://github.com/inventree/InvenTree/pull/7649 v223 - 2024-07-14 : https://github.com/inventree/InvenTree/pull/7649
- Allow adjustment of "packaging" field when receiving items against a purchase order - Allow adjustment of "packaging" field when receiving items against a purchase order

View File

@ -0,0 +1,24 @@
# Generated by Django 4.2.11 on 2024-07-16 12:58
import InvenTree.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('company', '0070_remove_manufacturerpartattachment_manufacturer_part_and_more'),
]
operations = [
migrations.AddField(
model_name='manufacturerpart',
name='notes',
field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Markdown notes (optional)', max_length=50000, null=True, verbose_name='Notes'),
),
migrations.AddField(
model_name='supplierpart',
name='notes',
field=InvenTree.fields.InvenTreeNotesField(blank=True, help_text='Markdown notes (optional)', max_length=50000, null=True, verbose_name='Notes'),
),
]

View File

@ -451,6 +451,7 @@ class Address(InvenTree.models.InvenTreeModel):
class ManufacturerPart( class ManufacturerPart(
InvenTree.models.InvenTreeAttachmentMixin, InvenTree.models.InvenTreeAttachmentMixin,
InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.InvenTreeBarcodeMixin,
InvenTree.models.InvenTreeNotesMixin,
InvenTree.models.InvenTreeMetadataModel, InvenTree.models.InvenTreeMetadataModel,
): ):
"""Represents a unique part as provided by a Manufacturer Each ManufacturerPart is identified by a MPN (Manufacturer Part Number) Each ManufacturerPart is also linked to a Part object. A Part may be available from multiple manufacturers. """Represents a unique part as provided by a Manufacturer Each ManufacturerPart is identified by a MPN (Manufacturer Part Number) Each ManufacturerPart is also linked to a Part object. A Part may be available from multiple manufacturers.
@ -624,6 +625,7 @@ class SupplierPartManager(models.Manager):
class SupplierPart( class SupplierPart(
InvenTree.models.MetadataMixin, InvenTree.models.MetadataMixin,
InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.InvenTreeBarcodeMixin,
InvenTree.models.InvenTreeNotesMixin,
common.models.MetaMixin, common.models.MetaMixin,
InvenTree.models.InvenTreeModel, InvenTree.models.InvenTreeModel,
): ):

View File

@ -213,7 +213,7 @@ class ContactSerializer(DataImportExportSerializerMixin, InvenTreeModelSerialize
@register_importer() @register_importer()
class ManufacturerPartSerializer( class ManufacturerPartSerializer(
DataImportExportSerializerMixin, InvenTreeTagModelSerializer DataImportExportSerializerMixin, InvenTreeTagModelSerializer, NotesFieldMixin
): ):
"""Serializer for ManufacturerPart object.""" """Serializer for ManufacturerPart object."""
@ -232,6 +232,7 @@ class ManufacturerPartSerializer(
'MPN', 'MPN',
'link', 'link',
'barcode_hash', 'barcode_hash',
'notes',
'tags', 'tags',
] ]
@ -305,7 +306,7 @@ class ManufacturerPartParameterSerializer(
@register_importer() @register_importer()
class SupplierPartSerializer( class SupplierPartSerializer(
DataImportExportSerializerMixin, InvenTreeTagModelSerializer DataImportExportSerializerMixin, InvenTreeTagModelSerializer, NotesFieldMixin
): ):
"""Serializer for SupplierPart object.""" """Serializer for SupplierPart object."""
@ -340,6 +341,7 @@ class SupplierPartSerializer(
'supplier_detail', 'supplier_detail',
'url', 'url',
'updated', 'updated',
'notes',
'tags', 'tags',
] ]

View File

@ -171,11 +171,40 @@ src="{% static 'img/blank_image.png' %}"
</div> </div>
</div> </div>
<div class='panel panel-hidden' id='panel-manufacturer-part-notes'>
<div class='panel-heading'>
<div class='d-flex flex-wrap'>
<h4>{% trans "Manufacturer Part Notes" %}</h4>
{% include "spacer.html" %}
<div class='btn-group' role='group'>
{% include "notes_buttons.html" %}
</div>
</div>
</div>
<div class='panel-content'>
<textarea id='manufacturer-part-notes'></textarea>
</div>
</div>
{% endblock page_content %} {% endblock page_content %}
{% block js_ready %} {% block js_ready %}
{{ block.super }} {{ block.super }}
// Load the "notes" tab
onPanelLoad('manufacturer-part-notes', function() {
setupNotesField(
'manufacturer-part-notes',
'{% url "api-manufacturer-part-detail" part.pk %}',
{
model_type: "manufacturerpart",
model_id: {{ part.pk }},
editable: {% js_bool roles.purchase_order.change %},
}
);
});
onPanelLoad("attachments", function() { onPanelLoad("attachments", function() {
loadAttachmentTable('manufacturerpart', {{ part.pk }}); loadAttachmentTable('manufacturerpart', {{ part.pk }});
}); });

View File

@ -8,3 +8,5 @@
{% include "sidebar_item.html" with label='supplier-parts' text=text icon="fa-building" %} {% include "sidebar_item.html" with label='supplier-parts' text=text icon="fa-building" %}
{% trans "Attachments" as text %} {% trans "Attachments" as text %}
{% include "sidebar_item.html" with label='attachments' text=text icon="fa-paperclip" %} {% include "sidebar_item.html" with label='attachments' text=text icon="fa-paperclip" %}
{% trans "Notes" as text %}
{% include "sidebar_item.html" with label="manufacturer-part-notes" text=text icon="fa-clipboard" %}

View File

@ -264,11 +264,40 @@ src="{% static 'img/blank_image.png' %}"
</div> </div>
</div> </div>
<div class='panel panel-hidden' id='panel-supplier-part-notes'>
<div class='panel-heading'>
<div class='d-flex flex-wrap'>
<h4>{% trans "Supplier Part Notes" %}</h4>
{% include "spacer.html" %}
<div class='btn-group' role='group'>
{% include "notes_buttons.html" %}
</div>
</div>
</div>
<div class='panel-content'>
<textarea id='supplier-part-notes'></textarea>
</div>
</div>
{% endblock page_content %} {% endblock page_content %}
{% block js_ready %} {% block js_ready %}
{{ block.super }} {{ block.super }}
// Load the "notes" tab
onPanelLoad('supplier-part-notes', function() {
setupNotesField(
'supplier-part-notes',
'{% url "api-supplier-part-detail" part.pk %}',
{
model_type: "supplierpart",
model_id: {{ part.pk }},
editable: {% js_bool roles.purchase_order.change %},
}
);
});
{% if barcodes %} {% if barcodes %}
$("#show-qr-code").click(function() { $("#show-qr-code").click(function() {

View File

@ -8,3 +8,5 @@
{% include "sidebar_item.html" with label='purchase-orders' text=text icon="fa-shopping-cart" %} {% include "sidebar_item.html" with label='purchase-orders' text=text icon="fa-shopping-cart" %}
{% trans "Supplier Part Pricing" as text %} {% trans "Supplier Part Pricing" as text %}
{% include "sidebar_item.html" with label='pricing' text=text icon="fa-dollar-sign" %} {% include "sidebar_item.html" with label='pricing' text=text icon="fa-dollar-sign" %}
{% trans "Notes" as text %}
{% include "sidebar_item.html" with label="supplier-part-notes" text=text icon="fa-clipboard" %}

View File

@ -5,6 +5,7 @@ import {
IconDots, IconDots,
IconInfoCircle, IconInfoCircle,
IconList, IconList,
IconNotes,
IconPaperclip IconPaperclip
} from '@tabler/icons-react'; } from '@tabler/icons-react';
import { useMemo } from 'react'; import { useMemo } from 'react';
@ -14,6 +15,7 @@ import AdminButton from '../../components/buttons/AdminButton';
import { DetailsField, DetailsTable } from '../../components/details/Details'; import { DetailsField, DetailsTable } from '../../components/details/Details';
import { DetailsImage } from '../../components/details/DetailsImage'; import { DetailsImage } from '../../components/details/DetailsImage';
import { ItemDetailsGrid } from '../../components/details/ItemDetails'; import { ItemDetailsGrid } from '../../components/details/ItemDetails';
import NotesEditor from '../../components/editors/NotesEditor';
import { import {
ActionDropdown, ActionDropdown,
DeleteItemAction, DeleteItemAction,
@ -179,6 +181,18 @@ export default function ManufacturerPartDetail() {
model_id={manufacturerPart?.pk} model_id={manufacturerPart?.pk}
/> />
) )
},
{
name: 'notes',
label: t`Notes`,
icon: <IconNotes />,
content: (
<NotesEditor
modelType={ModelType.manufacturerpart}
modelId={manufacturerPart.pk}
editable={user.hasChangeRole(UserRoles.purchase_order)}
/>
)
} }
]; ];
}, [manufacturerPart]); }, [manufacturerPart]);

View File

@ -4,6 +4,7 @@ import {
IconCurrencyDollar, IconCurrencyDollar,
IconDots, IconDots,
IconInfoCircle, IconInfoCircle,
IconNotes,
IconPackages, IconPackages,
IconShoppingCart IconShoppingCart
} from '@tabler/icons-react'; } from '@tabler/icons-react';
@ -15,6 +16,7 @@ import { DetailsField, DetailsTable } from '../../components/details/Details';
import DetailsBadge from '../../components/details/DetailsBadge'; import DetailsBadge from '../../components/details/DetailsBadge';
import { DetailsImage } from '../../components/details/DetailsImage'; import { DetailsImage } from '../../components/details/DetailsImage';
import { ItemDetailsGrid } from '../../components/details/ItemDetails'; import { ItemDetailsGrid } from '../../components/details/ItemDetails';
import NotesEditor from '../../components/editors/NotesEditor';
import { import {
ActionDropdown, ActionDropdown,
DeleteItemAction, DeleteItemAction,
@ -240,6 +242,18 @@ export default function SupplierPartDetail() {
) : ( ) : (
<Skeleton /> <Skeleton />
) )
},
{
name: 'notes',
label: t`Notes`,
icon: <IconNotes />,
content: (
<NotesEditor
modelType={ModelType.supplierpart}
modelId={supplierPart.pk}
editable={user.hasChangeRole(UserRoles.purchase_order)}
/>
)
} }
]; ];
}, [supplierPart]); }, [supplierPart]);