Add new attechment functionality to new models

- Giving the ol' refactor tractor a fresh coat of paint
This commit is contained in:
Oliver Walters 2020-05-12 21:40:42 +10:00
parent 2369b40bbf
commit 366d4b2143
10 changed files with 70 additions and 46 deletions

View File

@ -8,6 +8,9 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.http import JsonResponse from django.http import JsonResponse
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
from rest_framework import permissions from rest_framework import permissions
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
@ -41,6 +44,28 @@ class InfoView(AjaxView):
return JsonResponse(data) return JsonResponse(data)
class AttachmentMixin:
"""
Mixin for creating attachment objects,
and ensuring the user information is saved correctly.
"""
permission_classes = [permissions.IsAuthenticated]
filter_backends = [
DjangoFilterBackend,
filters.OrderingFilter,
filters.SearchFilter,
]
def perform_create(self, serializer):
""" Save the user information when a file is uploaded """
attachment = serializer.save()
attachment.user = self.request.user
attachment.save()
class ActionPluginView(APIView): class ActionPluginView(APIView):
""" """
Endpoint for running custom action plugins. Endpoint for running custom action plugins.

View File

@ -12,6 +12,7 @@ from rest_framework import filters
from django.conf.urls import url, include from django.conf.urls import url, include
from InvenTree.helpers import str2bool from InvenTree.helpers import str2bool
from InvenTree.api import AttachmentMixin
from part.models import Part from part.models import Part
from company.models import SupplierPart from company.models import SupplierPart
@ -200,7 +201,7 @@ class POLineItemDetail(generics.RetrieveUpdateAPIView):
] ]
class SOAttachmentList(generics.ListCreateAPIView): class SOAttachmentList(generics.ListCreateAPIView, AttachmentMixin):
""" """
API endpoint for listing (and creating) a SalesOrderAttachment (file upload) API endpoint for listing (and creating) a SalesOrderAttachment (file upload)
""" """
@ -208,12 +209,6 @@ class SOAttachmentList(generics.ListCreateAPIView):
queryset = SalesOrderAttachment.objects.all() queryset = SalesOrderAttachment.objects.all()
serializer_class = SOAttachmentSerializer serializer_class = SOAttachmentSerializer
filter_backends = [
DjangoFilterBackend,
filters.OrderingFilter,
filters.SearchFilter,
]
filter_fields = [ filter_fields = [
'order', 'order',
] ]
@ -399,7 +394,7 @@ class SOLineItemDetail(generics.RetrieveUpdateAPIView):
permission_classes = [permissions.IsAuthenticated] permission_classes = [permissions.IsAuthenticated]
class POAttachmentList(generics.ListCreateAPIView): class POAttachmentList(generics.ListCreateAPIView, AttachmentMixin):
""" """
API endpoint for listing (and creating) a PurchaseOrderAttachment (file upload) API endpoint for listing (and creating) a PurchaseOrderAttachment (file upload)
""" """
@ -407,12 +402,6 @@ class POAttachmentList(generics.ListCreateAPIView):
queryset = PurchaseOrderAttachment.objects.all() queryset = PurchaseOrderAttachment.objects.all()
serializer_class = POAttachmentSerializer serializer_class = POAttachmentSerializer
filter_backends = [
DjangoFilterBackend,
filters.OrderingFilter,
filters.SearchFilter,
]
filter_fields = [ filter_fields = [
'order', 'order',
] ]

View File

@ -21,8 +21,9 @@
<table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'> <table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'>
<thead> <thead>
<tr> <tr>
<th data-field='file' data-searchable='true'>{% trans "File" %}</th> <th data-field='file' data-sortable='true' data-searchable='true'>{% trans "File" %}</th>
<th data-field='comment' data-searchable='true'>{% trans "Comment" %}</th> <th data-field='comment' data-sortable='true' data-searchable='true'>{% trans "Comment" %}</th>
<th data-field='user' data-sortable='true' data-searchable='true'>{% trans "Uploaded" %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -31,6 +32,10 @@
<tr> <tr>
<td><a href='/media/{{ attachment.attachment }}'>{{ attachment.basename }}</a></td> <td><a href='/media/{{ attachment.attachment }}'>{{ attachment.basename }}</a></td>
<td>{{ attachment.comment }}</td> <td>{{ attachment.comment }}</td>
<td>
{% if attachment.upload_date %}{{ attachment.upload_date }}{% endif %}
{% if attachment.user %}<span class='badge'>{{ attachment.user.username }}</div>{% endif %}
</td>
<td> <td>
<div class='btn-group' style='float: right;'> <div class='btn-group' style='float: right;'>
<button type='button' class='btn btn-default btn-glyph attachment-edit-button' url="{% url 'po-attachment-edit' attachment.id %}" data-toggle='tooltip' title='{% trans "Edit attachment" %}'> <button type='button' class='btn btn-default btn-glyph attachment-edit-button' url="{% url 'po-attachment-edit' attachment.id %}" data-toggle='tooltip' title='{% trans "Edit attachment" %}'>

View File

@ -8,7 +8,7 @@
{% include 'order/so_tabs.html' with tab='attachments' %} {% include 'order/so_tabs.html' with tab='attachments' %}
<h4>{% trans "Sales Order Attachments" %} <h4>{% trans "Sales Order Attachments" %}</h4>
<hr> <hr>
@ -21,8 +21,9 @@
<table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'> <table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'>
<thead> <thead>
<tr> <tr>
<th data-field='file' data-searchable='true'>{% trans "File" %}</th> <th data-field='file' data-sortable='true' data-searchable='true'>{% trans "File" %}</th>
<th data-field='comment' data-searchable='true'>{% trans "Comment" %}</th> <th data-field='comment' data-sortable='true' data-searchable='true'>{% trans "Comment" %}</th>
<th data-field='user' data-sortable='true' data-sortable='true' data-searchable='true'>{% trans "Uploaded" %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -31,6 +32,10 @@
<tr> <tr>
<td><a href='/media/{{ attachment.attachment }}'>{{ attachment.basename }}</a></td> <td><a href='/media/{{ attachment.attachment }}'>{{ attachment.basename }}</a></td>
<td>{{ attachment.comment }}</td> <td>{{ attachment.comment }}</td>
<td>
{% if attachment.upload_date %}{{ attachment.upload_date }}{% endif %}
{% if attachment.user %}<span class='badge'>{{ attachment.user.username }}</div>{% endif %}
</td>
<td> <td>
<div class='btn-group' style='float: right;'> <div class='btn-group' style='float: right;'>
<button type='button' class='btn btn-default btn-glyph attachment-edit-button' url="{% url 'so-attachment-edit' attachment.id %}" data-toggle='tooltip' title='{% trans "Edit attachment" %}'> <button type='button' class='btn btn-default btn-glyph attachment-edit-button' url="{% url 'so-attachment-edit' attachment.id %}" data-toggle='tooltip' title='{% trans "Edit attachment" %}'>

View File

@ -93,6 +93,10 @@ class PurchaseOrderAttachmentCreate(AjaxCreateView):
ajax_form_title = _("Add Purchase Order Attachment") ajax_form_title = _("Add Purchase Order Attachment")
ajax_template_name = "modal_form.html" ajax_template_name = "modal_form.html"
def post_save(self, **kwargs):
self.object.user = self.request.user
self.object.save()
def get_data(self): def get_data(self):
return { return {
"success": _("Added attachment") "success": _("Added attachment")
@ -133,6 +137,10 @@ class SalesOrderAttachmentCreate(AjaxCreateView):
form_class = order_forms.EditSalesOrderAttachmentForm form_class = order_forms.EditSalesOrderAttachmentForm
ajax_form_title = _('Add Sales Order Attachment') ajax_form_title = _('Add Sales Order Attachment')
def post_save(self, **kwargs):
self.object.user = self.request.user
self.object.save()
def get_data(self): def get_data(self):
return { return {
'success': _('Added attachment') 'success': _('Added attachment')

View File

@ -25,6 +25,7 @@ from . import serializers as part_serializers
from InvenTree.views import TreeSerializer from InvenTree.views import TreeSerializer
from InvenTree.helpers import str2bool, isNull from InvenTree.helpers import str2bool, isNull
from InvenTree.api import AttachmentMixin
class PartCategoryTree(TreeSerializer): class PartCategoryTree(TreeSerializer):
@ -106,7 +107,7 @@ class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = PartCategory.objects.all() queryset = PartCategory.objects.all()
class PartAttachmentList(generics.ListCreateAPIView): class PartAttachmentList(generics.ListCreateAPIView, AttachmentMixin):
""" """
API endpoint for listing (and creating) a PartAttachment (file upload). API endpoint for listing (and creating) a PartAttachment (file upload).
""" """
@ -114,14 +115,6 @@ class PartAttachmentList(generics.ListCreateAPIView):
queryset = PartAttachment.objects.all() queryset = PartAttachment.objects.all()
serializer_class = part_serializers.PartAttachmentSerializer serializer_class = part_serializers.PartAttachmentSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [
DjangoFilterBackend,
filters.OrderingFilter,
filters.SearchFilter,
]
filter_fields = [ filter_fields = [
'part', 'part',
] ]

View File

@ -19,8 +19,9 @@
<table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'> <table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'>
<thead> <thead>
<tr> <tr>
<th data-field='file' data-searchable='true'>{% trans "File" %}</th> <th data-field='file' data-sortable='true' data-searchable='true'>{% trans "File" %}</th>
<th data-field='comment' data-searchable='true'>{% trans "Comment" %}</th> <th data-field='comment' data-sortable='true' data-searchable='true'>{% trans "Comment" %}</th>
<th data-field='user' data-sortable='true' data-searchable='true'>{% trans "Uploaded" %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -29,6 +30,10 @@
<tr> <tr>
<td><a href='/media/{{ attachment.attachment }}'>{{ attachment.basename }}</a></td> <td><a href='/media/{{ attachment.attachment }}'>{{ attachment.basename }}</a></td>
<td>{{ attachment.comment }}</td> <td>{{ attachment.comment }}</td>
<td>
{% if attachment.upload_date %}{{ attachment.upload_date }}{% endif %}
{% if attachment.user %}<span class='badge'>{{ attachment.user.username }}</div>{% endif %}
</td>
<td> <td>
<div class='btn-group' style='float: right;'> <div class='btn-group' style='float: right;'>
<button type='button' class='btn btn-default btn-glyph attachment-edit-button' url="{% url 'part-attachment-edit' attachment.id %}" data-toggle='tooltip' title='{% trans "Edit attachment" %}'> <button type='button' class='btn btn-default btn-glyph attachment-edit-button' url="{% url 'part-attachment-edit' attachment.id %}" data-toggle='tooltip' title='{% trans "Edit attachment" %}'>

View File

@ -74,6 +74,11 @@ class PartAttachmentCreate(AjaxCreateView):
ajax_form_title = _("Add part attachment") ajax_form_title = _("Add part attachment")
ajax_template_name = "modal_form.html" ajax_template_name = "modal_form.html"
def post_save(self):
""" Record the user that uploaded the attachment """
self.object.user = self.request.user
self.object.save()
def get_data(self): def get_data(self):
return { return {
'success': _('Added attachment') 'success': _('Added attachment')

View File

@ -29,6 +29,7 @@ from .serializers import StockItemAttachmentSerializer
from InvenTree.views import TreeSerializer from InvenTree.views import TreeSerializer
from InvenTree.helpers import str2bool, isNull from InvenTree.helpers import str2bool, isNull
from InvenTree.api import AttachmentMixin
from decimal import Decimal, InvalidOperation from decimal import Decimal, InvalidOperation
@ -645,7 +646,7 @@ class StockList(generics.ListCreateAPIView):
] ]
class StockAttachmentList(generics.ListCreateAPIView): class StockAttachmentList(generics.ListCreateAPIView, AttachmentMixin):
""" """
API endpoint for listing (and creating) a StockItemAttachment (file upload) API endpoint for listing (and creating) a StockItemAttachment (file upload)
""" """
@ -653,22 +654,10 @@ class StockAttachmentList(generics.ListCreateAPIView):
queryset = StockItemAttachment.objects.all() queryset = StockItemAttachment.objects.all()
serializer_class = StockItemAttachmentSerializer serializer_class = StockItemAttachmentSerializer
filter_backends = [
DjangoFilterBackend,
filters.OrderingFilter,
filters.SearchFilter,
]
filter_fields = [ filter_fields = [
'stock_item', 'stock_item',
] ]
def perform_create(self, serializer):
attachment = serializer.save()
attachment.user = self.request.user
attachment.save()
class StockTrackingList(generics.ListCreateAPIView): class StockTrackingList(generics.ListCreateAPIView):
""" API endpoint for list view of StockItemTracking objects. """ API endpoint for list view of StockItemTracking objects.

View File

@ -20,9 +20,9 @@
<table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'> <table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'>
<thead> <thead>
<tr> <tr>
<th data-field='file' data-searchable='true'>{% trans "File" %}</th> <th data-field='file' data-sortable='true' data-searchable='true'>{% trans "File" %}</th>
<th data-field='comment' data-searchable='true'>{% trans "Comment" %}</th> <th data-field='comment' data-sortable='true' data-searchable='true'>{% trans "Comment" %}</th>
<th data-field='user' data-searchable='true'>{% trans "Uploaded" %}</th> <th data-field='user' data-sortable='true' data-searchable='true'>{% trans "Uploaded" %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>