mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge pull request #2912 from sur5r/issue2314
Implement Attachments for manufacturer parts
This commit is contained in:
commit
d6ebf3fc24
@ -4,11 +4,14 @@ InvenTree API version information
|
||||
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 49
|
||||
INVENTREE_API_VERSION = 50
|
||||
|
||||
"""
|
||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||
|
||||
v50 -> 2022-05-18 : https://github.com/inventree/InvenTree/pull/2912
|
||||
- Implement Attachments for manufacturer parts
|
||||
|
||||
v49 -> 2022-05-09 : https://github.com/inventree/InvenTree/pull/2957
|
||||
- Allows filtering of plugin list by 'active' status
|
||||
- Allows filtering of plugin list by 'mixin' support
|
||||
|
@ -8,7 +8,7 @@ import import_export.widgets as widgets
|
||||
from .models import Company
|
||||
from .models import SupplierPart
|
||||
from .models import SupplierPriceBreak
|
||||
from .models import ManufacturerPart, ManufacturerPartParameter
|
||||
from .models import ManufacturerPart, ManufacturerPartAttachment, ManufacturerPartParameter
|
||||
|
||||
from part.models import Part
|
||||
|
||||
@ -109,6 +109,16 @@ class ManufacturerPartAdmin(ImportExportModelAdmin):
|
||||
autocomplete_fields = ('part', 'manufacturer',)
|
||||
|
||||
|
||||
class ManufacturerPartAttachmentAdmin(ImportExportModelAdmin):
|
||||
"""
|
||||
Admin class for ManufacturerPartAttachment model
|
||||
"""
|
||||
|
||||
list_display = ('manufacturer_part', 'attachment', 'comment')
|
||||
|
||||
autocomplete_fields = ('manufacturer_part',)
|
||||
|
||||
|
||||
class ManufacturerPartParameterResource(ModelResource):
|
||||
"""
|
||||
Class for managing ManufacturerPartParameter data import/export
|
||||
@ -175,4 +185,5 @@ admin.site.register(SupplierPart, SupplierPartAdmin)
|
||||
admin.site.register(SupplierPriceBreak, SupplierPriceBreakAdmin)
|
||||
|
||||
admin.site.register(ManufacturerPart, ManufacturerPartAdmin)
|
||||
admin.site.register(ManufacturerPartAttachment, ManufacturerPartAttachmentAdmin)
|
||||
admin.site.register(ManufacturerPartParameter, ManufacturerPartParameterAdmin)
|
||||
|
@ -12,13 +12,14 @@ from django.urls import include, re_path
|
||||
from django.db.models import Q
|
||||
|
||||
from InvenTree.helpers import str2bool
|
||||
from InvenTree.api import AttachmentMixin
|
||||
|
||||
from .models import Company
|
||||
from .models import ManufacturerPart, ManufacturerPartParameter
|
||||
from .models import ManufacturerPart, ManufacturerPartAttachment, ManufacturerPartParameter
|
||||
from .models import SupplierPart, SupplierPriceBreak
|
||||
|
||||
from .serializers import CompanySerializer
|
||||
from .serializers import ManufacturerPartSerializer, ManufacturerPartParameterSerializer
|
||||
from .serializers import ManufacturerPartSerializer, ManufacturerPartAttachmentSerializer, ManufacturerPartParameterSerializer
|
||||
from .serializers import SupplierPartSerializer, SupplierPriceBreakSerializer
|
||||
|
||||
|
||||
@ -160,6 +161,32 @@ class ManufacturerPartDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
serializer_class = ManufacturerPartSerializer
|
||||
|
||||
|
||||
class ManufacturerPartAttachmentList(AttachmentMixin, generics.ListCreateAPIView):
|
||||
"""
|
||||
API endpoint for listing (and creating) a ManufacturerPartAttachment (file upload).
|
||||
"""
|
||||
|
||||
queryset = ManufacturerPartAttachment.objects.all()
|
||||
serializer_class = ManufacturerPartAttachmentSerializer
|
||||
|
||||
filter_backends = [
|
||||
DjangoFilterBackend,
|
||||
]
|
||||
|
||||
filter_fields = [
|
||||
'manufacturer_part',
|
||||
]
|
||||
|
||||
|
||||
class ManufacturerPartAttachmentDetail(AttachmentMixin, generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
Detail endpooint for ManufacturerPartAttachment model
|
||||
"""
|
||||
|
||||
queryset = ManufacturerPartAttachment.objects.all()
|
||||
serializer_class = ManufacturerPartAttachmentSerializer
|
||||
|
||||
|
||||
class ManufacturerPartParameterList(generics.ListCreateAPIView):
|
||||
"""
|
||||
API endpoint for list view of ManufacturerPartParamater model.
|
||||
@ -387,6 +414,12 @@ class SupplierPriceBreakDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
|
||||
manufacturer_part_api_urls = [
|
||||
|
||||
# Base URL for ManufacturerPartAttachment API endpoints
|
||||
re_path(r'^attachment/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', ManufacturerPartAttachmentDetail.as_view(), name='api-manufacturer-part-attachment-detail'),
|
||||
re_path(r'^$', ManufacturerPartAttachmentList.as_view(), name='api-manufacturer-part-attachment-list'),
|
||||
])),
|
||||
|
||||
re_path(r'^parameter/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', ManufacturerPartParameterDetail.as_view(), name='api-manufacturer-part-parameter-detail'),
|
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
# Generated by Django 3.2.13 on 2022-05-01 12:57
|
||||
|
||||
import InvenTree.fields
|
||||
import InvenTree.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('company', '0042_supplierpricebreak_updated'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ManufacturerPartAttachment',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('attachment', models.FileField(blank=True, help_text='Select file to attach', null=True, upload_to=InvenTree.models.rename_attachment, verbose_name='Attachment')),
|
||||
('link', InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', null=True, verbose_name='Link')),
|
||||
('comment', models.CharField(blank=True, help_text='File comment', max_length=100, verbose_name='Comment')),
|
||||
('upload_date', models.DateField(auto_now_add=True, null=True, verbose_name='upload date')),
|
||||
('manufacturer_part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='company.manufacturerpart', verbose_name='Manufacturer Part')),
|
||||
('user', models.ForeignKey(blank=True, help_text='User', null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
@ -22,6 +22,7 @@ from stdimage.models import StdImageField
|
||||
|
||||
from InvenTree.helpers import getMediaUrl, getBlankImage, getBlankThumbnail
|
||||
from InvenTree.fields import InvenTreeURLField
|
||||
from InvenTree.models import InvenTreeAttachment
|
||||
from InvenTree.status_codes import PurchaseOrderStatus
|
||||
|
||||
import InvenTree.validators
|
||||
@ -380,6 +381,22 @@ class ManufacturerPart(models.Model):
|
||||
return s
|
||||
|
||||
|
||||
class ManufacturerPartAttachment(InvenTreeAttachment):
|
||||
"""
|
||||
Model for storing file attachments against a ManufacturerPart object
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
return reverse('api-manufacturer-part-attachment-list')
|
||||
|
||||
def getSubdir(self):
|
||||
return os.path.join("manufacturer_part_files", str(self.manufacturer_part.id))
|
||||
|
||||
manufacturer_part = models.ForeignKey(ManufacturerPart, on_delete=models.CASCADE,
|
||||
verbose_name=_('Manufacturer Part'), related_name='attachments')
|
||||
|
||||
|
||||
class ManufacturerPartParameter(models.Model):
|
||||
"""
|
||||
A ManufacturerPartParameter represents a key:value parameter for a MnaufacturerPart.
|
||||
|
@ -8,6 +8,7 @@ from rest_framework import serializers
|
||||
|
||||
from sql_util.utils import SubqueryCount
|
||||
|
||||
from InvenTree.serializers import InvenTreeAttachmentSerializer
|
||||
from InvenTree.serializers import InvenTreeDecimalField
|
||||
from InvenTree.serializers import InvenTreeImageSerializerField
|
||||
from InvenTree.serializers import InvenTreeModelSerializer
|
||||
@ -16,7 +17,7 @@ from InvenTree.serializers import InvenTreeMoneySerializer
|
||||
from part.serializers import PartBriefSerializer
|
||||
|
||||
from .models import Company
|
||||
from .models import ManufacturerPart, ManufacturerPartParameter
|
||||
from .models import ManufacturerPart, ManufacturerPartAttachment, ManufacturerPartParameter
|
||||
from .models import SupplierPart, SupplierPriceBreak
|
||||
|
||||
from common.settings import currency_code_default, currency_code_mappings
|
||||
@ -142,6 +143,29 @@ class ManufacturerPartSerializer(InvenTreeModelSerializer):
|
||||
]
|
||||
|
||||
|
||||
class ManufacturerPartAttachmentSerializer(InvenTreeAttachmentSerializer):
|
||||
"""
|
||||
Serializer for the ManufacturerPartAttachment class
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = ManufacturerPartAttachment
|
||||
|
||||
fields = [
|
||||
'pk',
|
||||
'manufacturer_part',
|
||||
'attachment',
|
||||
'filename',
|
||||
'link',
|
||||
'comment',
|
||||
'upload_date',
|
||||
]
|
||||
|
||||
read_only_fields = [
|
||||
'upload_date',
|
||||
]
|
||||
|
||||
|
||||
class ManufacturerPartParameterSerializer(InvenTreeModelSerializer):
|
||||
"""
|
||||
Serializer for the ManufacturerPartParameter model
|
||||
|
@ -144,6 +144,21 @@ src="{% static 'img/blank_image.png' %}"
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='panel panel-hidden' id='panel-attachments'>
|
||||
<div class='panel-heading'>
|
||||
<div class='d-flex flex-wrap'>
|
||||
<h4>{% trans "Attachments" %}</h4>
|
||||
{% include "spacer.html" %}
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "attachment_button.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
{% include "attachment_table.html" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='panel panel-hidden' id='panel-parameters'>
|
||||
<div class='panel-heading'>
|
||||
<div class='d-flex flex-wrap'>
|
||||
@ -178,6 +193,34 @@ src="{% static 'img/blank_image.png' %}"
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
onPanelLoad("attachments", function() {
|
||||
loadAttachmentTable('{% url "api-manufacturer-part-attachment-list" %}', {
|
||||
filters: {
|
||||
manufacturer_part: {{ part.pk }},
|
||||
},
|
||||
fields: {
|
||||
manufacturer_part: {
|
||||
value: {{ part.pk }},
|
||||
hidden: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
enableDragAndDrop(
|
||||
'#attachment-dropzone',
|
||||
'{% url "api-manufacturer-part-attachment-list" %}',
|
||||
{
|
||||
data: {
|
||||
manufacturer_part: {{ part.id }},
|
||||
},
|
||||
label: 'attachment',
|
||||
success: function(data, status, xhr) {
|
||||
reloadAttachmentTable();
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
function reloadParameters() {
|
||||
$("#parameter-table").bootstrapTable("refresh");
|
||||
}
|
||||
|
@ -4,5 +4,7 @@
|
||||
|
||||
{% trans "Parameters" as text %}
|
||||
{% include "sidebar_item.html" with label='parameters' text=text icon="fa-th-list" %}
|
||||
{% trans "Attachments" as text %}
|
||||
{% include "sidebar_item.html" with label='attachments' text=text icon="fa-paperclip" %}
|
||||
{% trans "Supplier Parts" as text %}
|
||||
{% include "sidebar_item.html" with label='supplier-parts' text=text icon="fa-building" %}
|
@ -101,6 +101,7 @@ class RuleSet(models.Model):
|
||||
'company_supplierpart',
|
||||
'company_manufacturerpart',
|
||||
'company_manufacturerpartparameter',
|
||||
'company_manufacturerpartattachment',
|
||||
'label_partlabel',
|
||||
],
|
||||
'stock_location': [
|
||||
|
Loading…
Reference in New Issue
Block a user