Repository: inventree/InvenTree

Issue:
[FR] Setting to define a default label printer
### Please verify that this feature request has NOT been suggested before.

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

### Problem statement

It would be very convenient to have an option to define a default label printer in the settings. I am using the `inventree-brother-plugin` heavily for all label making where it is a minor hassle to always have to manually change the selection from `Export as PDF` to `Brother Labels - Brother Label Printer` in the label printing modal form.

### Suggested solution

Some kind of configuration setting would be nice - could be a simple "make this printer the default selection" toggle somewhere.
It is unclear to me where to put this, as I am unsure where and how the brother plugin registers itself. Would the main `Label Printing` server configuration page be aware of the available printers? A drop-down to select the default printer seems logical to me.

Or is it a setting that the plugin should enforce somehow? (But that would potentially interfere with multiple plugins that each provide printers).

I am happy to give it a go myself with some pointers regarding these questions...

### Describe alternatives you've considered

This could be a user-specific setting as well - but I think since this is more of an "infrastructure/hardware" setup and should be in the server settings...

### Examples of other systems

_No response_

### Do you want to develop this?

- [X] I want to develop this.


Discussion:
@simonkuehling makes sense. A good solution would be to order the options returned by the API according to a setting in the global/labels tab.
Things to look out for:
- handeling and testing for the case that a plugin  is not available anymore
- settings can be a control that runs a function to gather the options. The function must be defined outside of the settings class scope. See SSO default group setting as a reference

Ping me if you need a review/pointers
Also the setting should allow the user to select "print to pdf" (i.e. no plugin) as an option - and this should be the "default" value
thanks for the feedback!

@matmair the current default selection looks to be created in the front-end at https://github.com/inventree/InvenTree/blob/cde2050236adbadac610c5a3806dde9093a7e7b0/InvenTree/templates/js/translated/label.js#L223 - so, while just sorting the API response sounds like a simple implementation, I think this is not feasable without some refactoring...
I guess I could instead query the new user setting directly in `label.js` through `/api/settings/user/{key}/` and add the `selected` html attribute where it matches, right?

An alternative would be to create a dedicated api endpoint for generating a sorted (default option first) list of available label printers as key/value pairs including the `''/'Print to PDF'` option and change the front end to not deal with generating the PDF option explicitly by itself... sounds cleaner to me, but I'm not quite sure about further implications on other parts of the system here.
an API route for the second idea could be a `GET /api/label/printers/ ` - I actually like that much better than introducing an additional AJAX call just for querying the user setting in the front-end... 
@simonkuehling the plugins are loaded from this a few lines lower https://github.com/inventree/InvenTree/blob/cde2050236adbadac610c5a3806dde9093a7e7b0/InvenTree/templates/js/translated/label.js#L236-L249
I kike the idea of a new API endpoint but think it should live under the `/api/plugin/` namespace.
@matmair as I just learned about the `global_settings` and `user_settings` variables from `settings.js` I am actually reconsidering the simpler first approach for now - to just add the `selected` html attribute in label.js instead of sorting a list of options server-side...

One question on global and user configuration options in /common/models.py: Is it possible to define options as key/value pairs here? I am unsure how to have the option `Print to PDF` shown in the dropdown and being translated, but to save it as `''` in the settings if selected...

as work in progress I have this so far:
```
    def label_printer_options():
        """Build a list of available label printer options."""
        printers = [""]
        printers.append(registry.with_mixin('labelprinting'))
        return 

[...]

        "LABEL_DEFAULT_PRINTER": {
            'name': _('Default label printer'),
            'description': _('Configure which label printer should be selected by default'),
            'default': '',
            'choices': label_printer_options
        },
```
> One question on global and user configuration options in /common/models.py: Is it possible to define options as key/value pairs here? I am unsure how to have the option `Print to PDF` shown in the dropdown and being translated, but to save it as `''` in the settings if selected...

nevermind - I looked again and already found an example in `DATE_DISPLAY_FORMAT`... 
@simonkuehling your work in progress above is exactly the route I would have suggested :) looks good!

Resolving patch:
diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py
--- a/InvenTree/common/models.py
+++ b/InvenTree/common/models.py
@@ -46,6 +46,7 @@
 import InvenTree.tasks
 import InvenTree.validators
 import order.validators
+from plugin import registry
 
 logger = logging.getLogger('inventree')
 
@@ -1628,6 +1629,15 @@ def requires_restart(self):
             return False
 
 
+def label_printer_options():
+    """Build a list of available label printer options."""
+    printers = [('', _('No Printer (Export to PDF)'))]
+    label_printer_plugins = registry.with_mixin('labels')
+    if label_printer_plugins:
+        printers.extend([(p.slug, p.name + ' - ' + p.human_name) for p in label_printer_plugins])
+    return printers
+
+
 class InvenTreeUserSetting(BaseInvenTreeSetting):
     """An InvenTreeSetting object with a usercontext."""
 
@@ -1772,6 +1782,13 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
             'validator': bool,
         },
 
+        "LABEL_DEFAULT_PRINTER": {
+            'name': _('Default label printer'),
+            'description': _('Configure which label printer should be selected by default'),
+            'default': '',
+            'choices': label_printer_options
+        },
+
         "REPORT_INLINE": {
             'name': _('Inline report display'),
             'description': _('Display PDF reports in the browser, instead of downloading as a file'),


Test patch: