mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +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 = {
|
REST_FRAMEWORK = {
|
||||||
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
|
'EXCEPTION_HANDLER': 'InvenTree.exceptions.exception_handler',
|
||||||
'DATETIME_FORMAT': '%Y-%m-%d %H:%M',
|
'DATETIME_FORMAT': '%Y-%m-%d %H:%M',
|
||||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||||
'rest_framework.authentication.BasicAuthentication',
|
'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():
|
def get_api_url():
|
||||||
return reverse('api-so-allocation-list')
|
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):
|
def clean(self):
|
||||||
"""
|
"""
|
||||||
Validate the SalesOrderAllocation object:
|
Validate the SalesOrderAllocation object:
|
||||||
|
@ -1284,14 +1284,18 @@ class SalesOrderShipmentAllocationSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
for entry in items:
|
for entry in items:
|
||||||
|
|
||||||
# Create a new SalesOrderAllocation
|
# Create a new SalesOrderAllocation
|
||||||
order.models.SalesOrderAllocation.objects.create(
|
allocation = order.models.SalesOrderAllocation(
|
||||||
line=entry.get('line_item'),
|
line=entry.get('line_item'),
|
||||||
item=entry.get('stock_item'),
|
item=entry.get('stock_item'),
|
||||||
quantity=entry.get('quantity'),
|
quantity=entry.get('quantity'),
|
||||||
shipment=shipment,
|
shipment=shipment,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
allocation.full_clean()
|
||||||
|
allocation.save()
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderExtraLineSerializer(AbstractExtraLineSerializer, InvenTreeModelSerializer):
|
class SalesOrderExtraLineSerializer(AbstractExtraLineSerializer, InvenTreeModelSerializer):
|
||||||
""" Serializer for a SalesOrderExtraLine object """
|
""" Serializer for a SalesOrderExtraLine object """
|
||||||
|
@ -225,6 +225,20 @@ function showApiError(xhr, url) {
|
|||||||
default:
|
default:
|
||||||
title = '{% trans "Unhandled Error Code" %}';
|
title = '{% trans "Unhandled Error Code" %}';
|
||||||
message = `{% trans "Error code" %}: ${xhr.status}`;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user