mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge pull request #3010 from SchrodingersGat/shipment-assign-fix
SalesOrderShipment allocation fix
This commit is contained in:
commit
a8eef0870c
76
InvenTree/InvenTree/exceptions.py
Normal file
76
InvenTree/InvenTree/exceptions.py
Normal file
@ -0,0 +1,76 @@
|
||||
"""
|
||||
Custom exception handling for the DRF API
|
||||
"""
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import traceback
|
||||
import sys
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.debug import ExceptionReporter
|
||||
|
||||
from error_report.models import Error
|
||||
|
||||
from rest_framework.exceptions import ValidationError as DRFValidationError
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import serializers
|
||||
import rest_framework.views as drfviews
|
||||
|
||||
|
||||
def exception_handler(exc, context):
|
||||
"""
|
||||
Custom exception handler for DRF framework.
|
||||
Ref: https://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling
|
||||
|
||||
Catches any errors not natively handled by DRF, and re-throws as an error DRF can handle
|
||||
"""
|
||||
|
||||
response = None
|
||||
|
||||
# Catch any django validation error, and re-throw a DRF validation error
|
||||
if isinstance(exc, DjangoValidationError):
|
||||
exc = DRFValidationError(detail=serializers.as_serializer_error(exc))
|
||||
|
||||
# Default to the built-in DRF exception handler
|
||||
response = drfviews.exception_handler(exc, context)
|
||||
|
||||
if response is None:
|
||||
# DRF handler did not provide a default response for this exception
|
||||
|
||||
if settings.DEBUG:
|
||||
error_detail = str(exc)
|
||||
else:
|
||||
error_detail = _("Error details can be found in the admin panel")
|
||||
|
||||
response_data = {
|
||||
'error': type(exc).__name__,
|
||||
'error_class': str(type(exc)),
|
||||
'detail': error_detail,
|
||||
'path': context['request'].path,
|
||||
'status_code': 500,
|
||||
}
|
||||
|
||||
response = Response(response_data, status=500)
|
||||
|
||||
# Log the exception to the database, too
|
||||
kind, info, data = sys.exc_info()
|
||||
|
||||
Error.objects.create(
|
||||
kind=kind.__name__,
|
||||
info=info,
|
||||
data='\n'.join(traceback.format_exception(kind, info, data)),
|
||||
path=context['request'].path,
|
||||
html=ExceptionReporter(context['request'], kind, info, data).get_traceback_html(),
|
||||
)
|
||||
|
||||
if response is not None:
|
||||
# Convert errors returned under the label '__all__' to 'non_field_errors'
|
||||
if '__all__' in response.data:
|
||||
response.data['non_field_errors'] = response.data['__all__']
|
||||
del response.data['__all__']
|
||||
|
||||
return response
|
@ -353,7 +353,7 @@ TEMPLATES = [
|
||||
]
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
|
||||
'EXCEPTION_HANDLER': 'InvenTree.exceptions.exception_handler',
|
||||
'DATETIME_FORMAT': '%Y-%m-%d %H:%M',
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
|
@ -0,0 +1,17 @@
|
||||
# Generated by Django 3.2.13 on 2022-05-16 14:35
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0067_auto_20220516_1120'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='salesorderallocation',
|
||||
unique_together=set(),
|
||||
),
|
||||
]
|
@ -1269,12 +1269,6 @@ class SalesOrderAllocation(models.Model):
|
||||
def get_api_url():
|
||||
return reverse('api-so-allocation-list')
|
||||
|
||||
class Meta:
|
||||
unique_together = [
|
||||
# Cannot allocate any given StockItem to the same line more than once
|
||||
('line', 'item'),
|
||||
]
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Validate the SalesOrderAllocation object:
|
||||
|
@ -1284,14 +1284,18 @@ class SalesOrderShipmentAllocationSerializer(serializers.Serializer):
|
||||
|
||||
with transaction.atomic():
|
||||
for entry in items:
|
||||
|
||||
# Create a new SalesOrderAllocation
|
||||
order.models.SalesOrderAllocation.objects.create(
|
||||
allocation = order.models.SalesOrderAllocation(
|
||||
line=entry.get('line_item'),
|
||||
item=entry.get('stock_item'),
|
||||
quantity=entry.get('quantity'),
|
||||
shipment=shipment,
|
||||
)
|
||||
|
||||
allocation.full_clean()
|
||||
allocation.save()
|
||||
|
||||
|
||||
class SalesOrderExtraLineSerializer(AbstractExtraLineSerializer, InvenTreeModelSerializer):
|
||||
""" Serializer for a SalesOrderExtraLine object """
|
||||
|
@ -225,6 +225,20 @@ function showApiError(xhr, url) {
|
||||
default:
|
||||
title = '{% trans "Unhandled Error Code" %}';
|
||||
message = `{% trans "Error code" %}: ${xhr.status}`;
|
||||
|
||||
var response = xhr.responseJSON;
|
||||
|
||||
// The server may have provided some extra information about this error
|
||||
if (response) {
|
||||
if (response.error) {
|
||||
title = response.error;
|
||||
}
|
||||
|
||||
if (response.detail) {
|
||||
message = response.detail;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user