diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index 6444bead37..bfb7418d62 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -1319,6 +1319,25 @@ class ReturnOrderDetail(RetrieveUpdateDestroyAPI): return self.serializer_class(*args, **kwargs) +class ReturnOrderExtraLineList(GeneralExtraLineList, ListCreateAPI): + """API endpoint for accessing a list of ReturnOrderExtraLine objects""" + + queryset = models.ReturnOrderExtraLine.objects.all() + serializer_class = serializers.ReturnOrderExtraLineSerializer + + def download_queryset(self, queryset, export_format): + """Download this queryset as a file""" + + raise NotImplementedError("download_queryset not yet implemented") + + +class ReturnOrderExtraLineDetail(RetrieveUpdateDestroyAPI): + """API endpoint for detail view of a ReturnOrderExtraLine object""" + + queryset = models.ReturnOrderExtraLine.objects.all() + serializer_class = serializers.ReturnOrderExtraLineSerializer + + class ReturnOrderAttachmentList(AttachmentMixin, ListCreateDestroyAPIView): """API endpoint for listing (and creating) a ReturnOrderAttachment (file upload)""" @@ -1581,6 +1600,12 @@ order_api_urls = [ # API endpoints for return orders re_path(r'^return/', include([ + # API endpoints for return order extra line + re_path(r'^extra-line/', include([ + path('/', ReturnOrderExtraLineDetail.as_view(), name='api-return-order-extra-line-detail'), + path('', ReturnOrderExtraLineList.as_view(), name='api-return-order-extra-line-list'), + ])), + re_path(r'^attachment/', include([ path('/', ReturnOrderAttachmentDetail.as_view(), name='api-return-order-attachment-detail'), re_path(r'^.*$', ReturnOrderAttachmentList.as_view(), name='api-return-order-attachment-list'), diff --git a/InvenTree/order/migrations/0082_returnorderextraline.py b/InvenTree/order/migrations/0082_returnorderextraline.py new file mode 100644 index 0000000000..5a98c984f8 --- /dev/null +++ b/InvenTree/order/migrations/0082_returnorderextraline.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.18 on 2023-03-16 02:52 + +import InvenTree.fields +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import djmoney.models.fields +import djmoney.models.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0081_auto_20230314_1259'), + ] + + operations = [ + migrations.CreateModel( + name='ReturnOrderExtraLine', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('quantity', InvenTree.fields.RoundingDecimalField(decimal_places=5, default=1, help_text='Item quantity', max_digits=15, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Quantity')), + ('reference', models.CharField(blank=True, help_text='Line item reference', max_length=100, verbose_name='Reference')), + ('notes', models.CharField(blank=True, help_text='Line item notes', max_length=500, verbose_name='Notes')), + ('target_date', models.DateField(blank=True, help_text='Target date for this line item (leave blank to use the target date from the order)', null=True, verbose_name='Target Date')), + ('context', models.JSONField(blank=True, help_text='Additional context for this line', null=True, verbose_name='Context')), + ('price_currency', djmoney.models.fields.CurrencyField(choices=[], default='', editable=False, max_length=3)), + ('price', InvenTree.fields.InvenTreeModelMoneyField(blank=True, currency_choices=[], decimal_places=6, default_currency='', help_text='Unit price', max_digits=19, null=True, validators=[djmoney.models.validators.MinMoneyValidator(0)], verbose_name='Price')), + ('order', models.ForeignKey(help_text='Return Order', on_delete=django.db.models.deletion.CASCADE, related_name='extra_lines', to='order.returnorder', verbose_name='Order')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 305810e452..f4a49a7594 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -1682,6 +1682,21 @@ class ReturnOrder(Order): ) +class ReturnOrderExtraLine(OrderExtraLine): + """Model for a single ExtraLine in a ReturnOrder""" + + @staticmethod + def get_api_url(): + """Return the API URL associated with the ReturnOrderExtraLine model""" + return reverse('api-return-order-extra-line-list') + + order = models.ForeignKey( + ReturnOrder, on_delete=models.CASCADE, + related_name='extra_lines', + verbose_name=_('Order'), help_text=_('Return Order') + ) + + class ReturnOrderAttachment(InvenTreeAttachment): """Model for storing file attachments against a ReturnOrder object""" diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index e8addc3466..0196993c68 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -1441,6 +1441,16 @@ class ReturnOrderSerializer(AbstractOrderSerializer, InvenTreeModelSerializer): customer_detail = CompanyBriefSerializer(source='customer', many=False, read_only=True) +class ReturnOrderExtraLineSerializer(AbstractExtraLineSerializer, InvenTreeModelSerializer): + """Serializer for a ReturnOrderExtraLine object""" + + class Meta(AbstractExtraLineMeta): + """Metaclass options""" + model = order.models.ReturnOrderExtraLine + + order_detail = ReturnOrderSerializer(source='order', many=False, read_only=True) + + class ReturnOrderAttachmentSerializer(InvenTreeAttachmentSerializer): """Serializer for the ReturnOrderAttachment model"""