mirror of
https://github.com/inventree/InvenTree.git
synced 2026-04-28 13:54:25 +00:00
[bug] Make "issued_by" field read-only (#11816)
* Fix "issued_by" for BuildOrder model - Automatically capture user information - Mark field as read-only - Remove from frontend forms * Add "created_by" property * Update unit test * Update API and CHANGELOG * Further adjustments to unit tests
This commit is contained in:
@@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Changed
|
||||
|
||||
[#11816](https://github.com/inventree/InvenTree/pull/11816) makes the `issued_by` field on the `Build` API read only, and instead sets the `issued_by` field to the current user when a build is created. This change was made to ensure that the `issued_by` field accurately reflects the user who created the build, and to prevent users from setting this field to an arbitrary value when creating or updating a build.
|
||||
|
||||
### Removed
|
||||
|
||||
## 1.3.0 - 2026-04-11
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
"""InvenTree API version information."""
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 479
|
||||
INVENTREE_API_VERSION = 480
|
||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||
|
||||
INVENTREE_API_TEXT = """
|
||||
|
||||
v480 -> 2026-04-27 : https://github.com/inventree/InvenTree/pull/11816
|
||||
- The "issued_by" field on the Build API endpoint is now read-only, and is automatically set to the current user when a build is created
|
||||
|
||||
v479 -> 2026-04-11 : https://github.com/inventree/InvenTree/pull/11723
|
||||
- POST /api//notifications/readall/ now requires a POST action
|
||||
- POST /api/admin/email/test/ - now returns a 200 on. a successful test
|
||||
|
||||
@@ -386,6 +386,20 @@ class BuildList(
|
||||
kwargs['create'] = True
|
||||
return super().get_serializer(*args, **kwargs)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""Save user information on order creation."""
|
||||
serializer = self.get_serializer(data=self.clean_data(request.data))
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
build = serializer.save()
|
||||
build.issued_by = request.user
|
||||
build.save()
|
||||
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(
|
||||
serializer.data, status=status.HTTP_201_CREATED, headers=headers
|
||||
)
|
||||
|
||||
|
||||
class BuildDetail(BuildMixin, RetrieveUpdateDestroyAPI):
|
||||
"""API endpoint for detail view of a Build object."""
|
||||
|
||||
@@ -403,6 +403,14 @@ class Build(
|
||||
related_name='builds_issued',
|
||||
)
|
||||
|
||||
@property
|
||||
def created_by(self):
|
||||
"""Alias for issued_by field.
|
||||
|
||||
This is used for compatibility with the order models
|
||||
"""
|
||||
return self.issued_by
|
||||
|
||||
responsible = models.ForeignKey(
|
||||
users.models.Owner,
|
||||
on_delete=models.SET_NULL,
|
||||
|
||||
@@ -104,7 +104,8 @@ class BuildSerializer(
|
||||
read_only_fields = [
|
||||
'completed',
|
||||
'creation_date',
|
||||
'completion_data',
|
||||
'issued_by',
|
||||
'completion_date',
|
||||
'status',
|
||||
'status_text',
|
||||
'level',
|
||||
|
||||
@@ -568,6 +568,9 @@ class BuildTest(BuildAPITest):
|
||||
|
||||
self.assertEqual(bo.children.count(), 0)
|
||||
|
||||
self.assertIsNotNone(bo.issued_by)
|
||||
self.assertEqual(bo.issued_by, self.user)
|
||||
|
||||
|
||||
class BuildAllocationTest(BuildAPITest):
|
||||
"""Unit tests for allocation of stock items against a build order.
|
||||
|
||||
@@ -54,12 +54,16 @@ class UserAPITests(InvenTreeAPITestCase):
|
||||
url = reverse('api-build-list')
|
||||
response = self.options(url)
|
||||
actions = response.data['actions']['POST']
|
||||
issued_by = actions['issued_by']
|
||||
|
||||
self.assertEqual(issued_by['pk_field'], 'pk')
|
||||
self.assertEqual(issued_by['model'], 'user')
|
||||
self.assertEqual(issued_by['api_url'], reverse('api-user-list'))
|
||||
self.assertEqual(issued_by['default'], self.user.pk)
|
||||
issued_by = actions['issued_by']
|
||||
self.assertTrue(issued_by['read_only'])
|
||||
|
||||
project_code = actions['project_code']
|
||||
self.assertFalse(project_code['read_only'])
|
||||
self.assertEqual(project_code['type'], 'related field')
|
||||
self.assertEqual(project_code['model'], 'projectcode')
|
||||
self.assertEqual(project_code['api_url'], reverse('api-project-code-list'))
|
||||
self.assertEqual(project_code['pk_field'], 'pk')
|
||||
|
||||
def test_user_api(self):
|
||||
"""Tests for User API endpoints."""
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
IconList,
|
||||
IconSitemap,
|
||||
IconTruckDelivery,
|
||||
IconUser,
|
||||
IconUsersGroup
|
||||
} from '@tabler/icons-react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
@@ -128,12 +127,6 @@ export function useBuildOrderFields({
|
||||
link: {
|
||||
icon: <IconLink />
|
||||
},
|
||||
issued_by: {
|
||||
icon: <IconUser />,
|
||||
filters: {
|
||||
is_active: true
|
||||
}
|
||||
},
|
||||
responsible: {
|
||||
icon: <IconUsersGroup />,
|
||||
filters: {
|
||||
|
||||
Reference in New Issue
Block a user