Repository: inventree/InvenTree

Issue:
[FR] Owner: Show User's full name instead of username
### Please verify that this feature request has NOT been suggested before.

- [X] I checked and didn't find a similar feature request

### Problem statement

Any Owner field tied to a user currently shows the username when printed in the GUI.

1. It's not always easily discernable who "PikachuLover5000" is
2. In conjunction with PO's, using "Attn: PikachuLover5000" in a report isn't very desirable either


### Suggested solution

By changing what value is returned based on Owner type, any "accidentally" bad usernames are filtered out of the GUI part, and only exposed to the "offending" user and admins.

I propose a very simple solution:
Return different model fields based on `owner_type`.

`owner.name` for Groups
`owner.full_name` for Users

### Describe alternatives you've considered

Pretty much the above

### Examples of other systems

_No response_

### Do you want to develop this?

- [X] I want to develop this.


Discussion:
Seems perfectly reasonable 🙂
just my 2 cents:
1. This is really dependant on your environment. In a business setting SSO usernames come from IT - a 'bad' username is unlikely
2. It can be undesirable to show/print full names. It is pretty common in education and business to use rather nondescript usernames in everything semi-public to protect the user's privacy and make internal processes less transparent for outsiders. Maybe a simple example makes that a bit more clear: You can't just google the warehouse person on your packaging slip and contact them if their username is bes_at_8501 - but everyone in the business unit will have a way to resolve that. In well-integrated IT environments, the same username/shorthand is normally used in every system so ppl know who is who. I know a bunch of colleagues only by their shorthand - not their government name ;-)

Especially considering 2 and the possible implication of mass leakage of student/employee names on all reports I would caution against just changing this and consider it at least breaking.
a few more thoughts:
3. github defaults to usernames - there is probably a good reason for that
4. #5212 gives us an opportunity to easily add hover cards to usernames like GitHub
5. usernames in general tend to be shorter than government names so a change might pose a problem there too. Restricting/shortening government names tends to face pushback in my experience
What if we made it a configurable option?

Sounds like a fine solution, not sure how that would affect response times. If the default changes for existing instances that would need a note somewhere.
All fair points, @matmair 

I suspect this might perhaps be somewhat culture dependent.
Here, usernames are mostly derived from one's government name. Be it in schools, universities, or in business. In some businesses, it's literally your whole name separated by dots.

In this case, I was thinking in terms of display in a "responsible" box, and an opportunity to reference a full name in reports. Most specifically, order reports. 

A PO that is not formalised by web shop, but by email, would prompt you to generate a PO report to send to the supplier's KAM. Around here, it's then common to operate with the purchaser's government name is such a document as a reference to shipment recipient (Aka. "Attention"). Vice versa, you often give the customer a contact for a given SO too.

Implementing it as an option works for me too.
As an extra layer to protect someone yanking all Owners maliciously, we could set up a separate Serializer used only in the areas where name exposure is relevant? 

I would add a note that it is not so exceptional that there are two people with the same full (goverment) name.

Wouldn't it be better to be able to generate usernames based on a full-name during the registration? Often there are some rules how to generate such username: three characters from surname, two characters from first-name and a number providing uniqueness.

I think that the scope of this is complex enough to warrant a custom plugin interface. I would rather offload this to a plugin rather than trying to accommodate everyone's wildly varying requirements. I certainly think it is outside the purview of InvenTree to dictate how usernames are generated or users names displayed.
So the easiest way forward seems to be either:
1. adding a displayname to each user and using that everywhere
2. adding a setting if username or fullname should be used everywhere

@LavissaWoW what do you think? Would either solution work for you and would you be intrested in developing either of them?

In regards to @roman-dvorak comment: very valid - my surname is on the top 4 in my country so never helpfull. I think that username creation and user managment in general is something that can be improved a lot and deserving of its own FR/EPIC. If you have furthure inputs we could maybe start a discussion around that. 
Just as side mark, our IT creates user names like e34hktp5 which is not useful either :-)
@SergeoLacruz I have been sch13hbt**, csaz4*** and T/98/8/**/**b so there is definitely a governance part to it but InvenTree shouldn't try to solve broken/dumb IT governance
I'm on a longer holiday atm. I'll be back EOM August.
Right,
Reading into the feedback, opinions, and general knowledge here, I propose the following:
Add a setting only editable by superusers.

I see two possibilities with differing implementation requirements:
1. Toggle: ((first name)+(surname)) or username
2. Advanced possibility: Dropdown with selectable properties being: `[username, full name, first name, initials]` (and/or others)

Default functionality  will be how it's currently implemented.
Initials would be calculated by extracting every first char from a `.split('- ')` on the person's full name.

LMK what you think.
I think option 1 sounds good. 2 might also be cool but that is an easy upgrade once 1 is done.
Regarding implementation, I would prefer if the change could be done in the backend (ie. change how the user serialiser work) instead of making API changes. If it would be a frontend function we need to implement it in C UI, P UI and the app so that should be less work. If possible this should just be a general setting, that way you already get an API.
This issue seems stale. Please react to show this is still important.

Resolving patch:
diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py
--- a/InvenTree/common/models.py
+++ b/InvenTree/common/models.py
@@ -1874,6 +1874,12 @@ def save(self, *args, **kwargs):
             ]
         },
 
+        'DISPLAY_FULL_NAMES': {
+            'name': _('Display Users full names'),
+            'description': _('Display Users full names instead of usernames'),
+            'default': False,
+            'validator': bool
+        }
     }
 
     typ = 'inventree'
diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py
--- a/InvenTree/users/models.py
+++ b/InvenTree/users/models.py
@@ -6,7 +6,7 @@
 from django.conf import settings
 from django.contrib import admin
 from django.contrib.auth import get_user_model
-from django.contrib.auth.models import Group, Permission
+from django.contrib.auth.models import Group, Permission, User
 from django.contrib.contenttypes.fields import GenericForeignKey
 from django.contrib.contenttypes.models import ContentType
 from django.core.cache import cache
@@ -21,6 +21,7 @@
 
 from rest_framework.authtoken.models import Token as AuthToken
 
+import common.models as common_models
 import InvenTree.helpers
 import InvenTree.models
 from InvenTree.ready import canAppAccessDatabase
@@ -28,6 +29,22 @@
 logger = logging.getLogger("inventree")
 
 
+#  OVERRIDE START
+# Overrides Django User model __str__ with a custom function to be able to change
+# string representation of a user
+def user_model_str(self):
+    """Function to override the default Django User __str__"""
+
+    if common_models.InvenTreeSetting.get_setting('DISPLAY_FULL_NAMES'):
+        if self.first_name or self.last_name:
+            return f'{self.first_name} {self.last_name}'
+    return self.username
+
+
+User.add_to_class("__str__", user_model_str)  # Overriding User.__str__
+#  OVERRIDE END
+
+
 def default_token():
     """Generate a default value for the token"""
     return ApiToken.generate_key()
@@ -785,10 +802,16 @@ def get_api_url():  # pragma: no cover
 
     def __str__(self):
         """Defines the owner string representation."""
-        return f'{self.owner} ({self.owner_type.name})'
+        if self.owner_type.name == 'user' and common_models.InvenTreeSetting.get_setting('DISPLAY_FULL_NAMES'):
+            display_name = self.owner.get_full_name()
+        else:
+            display_name = str(self.owner)
+        return f'{display_name} ({self.owner_type.name})'
 
     def name(self):
         """Return the 'name' of this owner."""
+        if self.owner_type.name == 'user' and common_models.InvenTreeSetting.get_setting('DISPLAY_FULL_NAMES'):
+            return self.owner.get_full_name()
         return str(self.owner)
 
     def label(self):


Test patch: