From d5086b2fb12014a91e558006905bc779abf77fa9 Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Wed, 21 Aug 2024 23:33:15 +0200 Subject: [PATCH 01/21] User defined states (#7862) * Add custom user defined states * make tests more reliable * fix list options * Adapt version * do not engage if rebuilding * remove unneeded attr * remove unneeded attr * fix enum imports * adapt cove target * Add status_custom_key to all other serializers * fix serializer method * simplify branching * remove unneeded imports * inherit read_only status from leader field * Add more tests * fix tests * add test for function * refactor for easier testing * move test to seperate class * Add options testing * extend serializer * add test for all states and refactor to reuse already build functions * use custom field in PUI too * reset diff * style fix * fix comparison * Add test for str * test color exceptions too * remove user state from tracking * Add intro from model fields too * update docs * simplify implementation * update tests * fix name * rename test * simplify tags and test fully * extend test to machine status * move logic for response formatting over * extend api response with machine status * ensure only direct subclasses are discovered * test for length of total respone too * use new fields on PUI too * fix test assertion with plugins enabled * also observe rendering in filters * Add managment endpoints and APIs * Add contenttypes to PUI renderes * use filteres instead * fix import order * fix api route definition * move status choices to serializer * fix lookup * fix filtering * remove admin integration * cleanup migration * fix migration change * cleanup code location * fix imports * Add docs for custom states * add links to custom status --- docs/docs/concepts/custom_states.md | 15 ++ docs/docs/extend/machines/overview.md | 8 +- docs/docs/order/purchase_order.md | 2 + docs/docs/order/return_order.md | 2 + docs/docs/order/sales_order.md | 2 + docs/docs/stock/status.md | 4 +- docs/mkdocs.yml | 1 + .../InvenTree/InvenTree/api_version.py | 6 +- src/backend/InvenTree/InvenTree/context.py | 9 +- src/backend/InvenTree/InvenTree/helpers.py | 14 +- src/backend/InvenTree/InvenTree/metadata.py | 10 +- ...ld_status_custom_key_alter_build_status.py | 39 +++ src/backend/InvenTree/build/models.py | 3 +- src/backend/InvenTree/build/serializers.py | 55 ++-- src/backend/InvenTree/build/status_codes.py | 12 +- .../build/templates/build/build_base.html | 4 +- .../build/templates/build/detail.html | 2 +- src/backend/InvenTree/common/api.py | 15 +- .../0029_inventreecustomuserstatemodel.py | 97 +++++++ src/backend/InvenTree/common/models.py | 108 ++++++++ src/backend/InvenTree/common/serializers.py | 27 ++ src/backend/InvenTree/common/tests.py | 91 +++++++ .../InvenTree/generic/states/__init__.py | 10 +- src/backend/InvenTree/generic/states/api.py | 72 +++++- .../InvenTree/generic/states/custom.py | 88 +++++++ .../InvenTree/generic/states/fields.py | 241 ++++++++++++++++++ .../InvenTree/generic/states/states.py | 30 ++- src/backend/InvenTree/generic/states/tags.py | 14 +- src/backend/InvenTree/generic/states/tests.py | 96 ++++++- .../InvenTree/importer/status_codes.py | 20 +- .../machine/machine_types/label_printer.py | 13 +- ...urchaseorder_status_custom_key_and_more.py | 100 ++++++++ src/backend/InvenTree/order/models.py | 9 +- src/backend/InvenTree/order/serializers.py | 20 +- src/backend/InvenTree/order/status_codes.py | 54 ++-- .../order/templates/order/order_base.html | 2 +- .../templates/order/return_order_base.html | 2 +- .../templates/order/sales_order_base.html | 2 +- .../plugin/base/label/test_label_mixin.py | 1 + src/backend/InvenTree/report/tests.py | 5 +- src/backend/InvenTree/stock/admin.py | 1 + ...13_stockitem_status_custom_key_and_more.py | 38 +++ src/backend/InvenTree/stock/models.py | 11 +- src/backend/InvenTree/stock/serializers.py | 6 +- src/backend/InvenTree/stock/status_codes.py | 22 +- .../stock/templates/stock/item_base.html | 2 +- src/backend/InvenTree/stock/test_api.py | 97 ++++++- .../templates/js/translated/build.js | 10 +- .../InvenTree/templates/js/translated/part.js | 2 +- .../templates/js/translated/purchase_order.js | 4 +- .../templates/js/translated/return_order.js | 4 +- .../templates/js/translated/sales_order.js | 4 +- .../templates/js/translated/stock.js | 21 +- src/backend/InvenTree/users/models.py | 1 + src/frontend/src/components/render/Build.tsx | 4 +- .../src/components/render/Generic.tsx | 6 + .../src/components/render/Instance.tsx | 9 +- .../src/components/render/ModelType.tsx | 5 + src/frontend/src/components/render/Order.tsx | 6 +- src/frontend/src/enums/ApiEndpoints.tsx | 2 + src/frontend/src/enums/ModelType.tsx | 3 +- src/frontend/src/forms/BuildForms.tsx | 2 +- src/frontend/src/forms/CommonForms.tsx | 12 + src/frontend/src/forms/StockForms.tsx | 4 +- .../Index/Settings/AdminCenter/Index.tsx | 10 + src/frontend/src/pages/build/BuildDetail.tsx | 2 +- .../pages/purchasing/PurchaseOrderDetail.tsx | 2 +- .../src/pages/sales/ReturnOrderDetail.tsx | 2 +- .../src/pages/sales/SalesOrderDetail.tsx | 2 +- src/frontend/src/pages/stock/StockDetail.tsx | 2 +- src/frontend/src/tables/ColumnRenderers.tsx | 2 +- .../src/tables/settings/CustomStateTable.tsx | 137 ++++++++++ 72 files changed, 1553 insertions(+), 187 deletions(-) create mode 100644 docs/docs/concepts/custom_states.md create mode 100644 src/backend/InvenTree/build/migrations/0052_build_status_custom_key_alter_build_status.py create mode 100644 src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py create mode 100644 src/backend/InvenTree/generic/states/custom.py create mode 100644 src/backend/InvenTree/generic/states/fields.py create mode 100644 src/backend/InvenTree/order/migrations/0101_purchaseorder_status_custom_key_and_more.py create mode 100644 src/backend/InvenTree/stock/migrations/0113_stockitem_status_custom_key_and_more.py create mode 100644 src/frontend/src/tables/settings/CustomStateTable.tsx diff --git a/docs/docs/concepts/custom_states.md b/docs/docs/concepts/custom_states.md new file mode 100644 index 0000000000..e72a949faf --- /dev/null +++ b/docs/docs/concepts/custom_states.md @@ -0,0 +1,15 @@ +--- +title: Custom States +--- + +## Custom States + +Several models within InvenTree support the use of custom states. The custom states are display only - the business logic is not affected by the state. + +States can be added in the Admin Center under the "Custom States" section. Each state has a name, label and a color that are used to display the state in the user interface. Changes to these settings will only be reflected in the user interface after a full reload of the interface. + +States need to be assigned to a model, state (for example status on a StockItem) and a logical key - that will be used for business logic. These 3 values combined need to be unique throughout the system. + +Custom states can be used in the following models: +- StockItem +- Orders (PurchaseOrder, SalesOrder, ReturnOrder, ReturnOrderLine) diff --git a/docs/docs/extend/machines/overview.md b/docs/docs/extend/machines/overview.md index 0a5237ff66..f132903cd3 100644 --- a/docs/docs/extend/machines/overview.md +++ b/docs/docs/extend/machines/overview.md @@ -47,6 +47,8 @@ If you want to create your own machine type, please also take a look at the alre ```py from django.utils.translation import gettext_lazy as _ + +from generic.states import ColorEnum from plugin.machine import BaseDriver, BaseMachineType, MachineStatus class ABCBaseDriver(BaseDriver): @@ -72,9 +74,9 @@ class ABCMachine(BaseMachineType): base_driver = ABCBaseDriver class ABCStatus(MachineStatus): - CONNECTED = 100, _('Connected'), 'success' - STANDBY = 101, _('Standby'), 'success' - PRINTING = 110, _('Printing'), 'primary' + CONNECTED = 100, _('Connected'), ColorEnum.success + STANDBY = 101, _('Standby'), ColorEnum.success + PRINTING = 110, _('Printing'), ColorEnum.primary MACHINE_STATUS = ABCStatus default_machine_status = ABCStatus.DISCONNECTED diff --git a/docs/docs/order/purchase_order.md b/docs/docs/order/purchase_order.md index 19169c2298..7639ddcb03 100644 --- a/docs/docs/order/purchase_order.md +++ b/docs/docs/order/purchase_order.md @@ -38,6 +38,8 @@ Refer to the source code for the Purchase Order status codes: show_source: True members: [] +Purchase Order Status supports [custom states](../concepts/custom_states.md). + ### Purchase Order Currency The currency code can be specified for an individual purchase order. If not specified, the default currency specified against the [supplier](./company.md#suppliers) will be used. diff --git a/docs/docs/order/return_order.md b/docs/docs/order/return_order.md index cdbfba88b1..c02653fd17 100644 --- a/docs/docs/order/return_order.md +++ b/docs/docs/order/return_order.md @@ -61,6 +61,8 @@ Refer to the source code for the Return Order status codes: show_source: True members: [] +Return Order Status supports [custom states](../concepts/custom_states.md). + ## Create a Return Order From the Return Order index, click on New Return Order which opens the "Create Return Order" form. diff --git a/docs/docs/order/sales_order.md b/docs/docs/order/sales_order.md index e44666fb02..a8834a2d0d 100644 --- a/docs/docs/order/sales_order.md +++ b/docs/docs/order/sales_order.md @@ -39,6 +39,8 @@ Refer to the source code for the Sales Order status codes: show_source: True members: [] +Sales Order Status supports [custom states](../concepts/custom_states.md). + ### Sales Order Currency The currency code can be specified for an individual sales order. If not specified, the default currency specified against the [customer](./company.md#customers) will be used. diff --git a/docs/docs/stock/status.md b/docs/docs/stock/status.md index 3ae6f12823..aadf175de9 100644 --- a/docs/docs/stock/status.md +++ b/docs/docs/stock/status.md @@ -10,7 +10,7 @@ Certain stock item status codes will restrict the availability of the stock item Below is the list of available stock status codes and their meaning: -| Status | Description | Available | +| Status | Description | Available | | ----------- | ----------- | --- | | OK | Stock item is healthy, nothing wrong to report | Yes | | Attention needed | Stock item hasn't been checked or tested yet | Yes | @@ -38,6 +38,8 @@ Refer to the source code for the Stock status codes: show_source: True members: [] +Stock Status supports [custom states](../concepts/custom_states.md). + ### Default Status Code The default status code for any newly created Stock Item is OK diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index ed0e673d02..059a7fb10b 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -77,6 +77,7 @@ nav: - Core Concepts: - Terminology: concepts/terminology.md - Physical Units: concepts/units.md + - Custom States: concepts/custom_states.md - Development: - Contributing: develop/contributing.md - Devcontainer: develop/devcontainer.md diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 5df3a8beb5..40bff36d69 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,13 +1,17 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 245 +INVENTREE_API_VERSION = 246 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v246 - 2024-08-21 : https://github.com/inventree/InvenTree/pull/7862 + - Adds custom status fields to various serializers + - Adds endpoints to admin custom status fields + v245 - 2024-08-21 : https://github.com/inventree/InvenTree/pull/7520 - Documented pagination fields (no functional changes) diff --git a/src/backend/InvenTree/InvenTree/context.py b/src/backend/InvenTree/InvenTree/context.py index 11bbb52e21..78a9443130 100644 --- a/src/backend/InvenTree/InvenTree/context.py +++ b/src/backend/InvenTree/InvenTree/context.py @@ -3,9 +3,9 @@ """Provides extra global data to all templates.""" import InvenTree.email +import InvenTree.ready import InvenTree.status -from generic.states import StatusCode -from InvenTree.helpers import inheritors +from generic.states.custom import get_custom_classes from users.models import RuleSet, check_user_role @@ -53,7 +53,10 @@ def status_codes(request): return {} request._inventree_status_codes = True - return {cls.__name__: cls.template_context() for cls in inheritors(StatusCode)} + get_custom = InvenTree.ready.isRebuildingData() is False + return { + cls.__name__: cls.template_context() for cls in get_custom_classes(get_custom) + } def user_roles(request): diff --git a/src/backend/InvenTree/InvenTree/helpers.py b/src/backend/InvenTree/InvenTree/helpers.py index 63a1c43f8f..2ddae791cf 100644 --- a/src/backend/InvenTree/InvenTree/helpers.py +++ b/src/backend/InvenTree/InvenTree/helpers.py @@ -953,8 +953,15 @@ def get_objectreference( Inheritors_T = TypeVar('Inheritors_T') -def inheritors(cls: type[Inheritors_T]) -> set[type[Inheritors_T]]: - """Return all classes that are subclasses from the supplied cls.""" +def inheritors( + cls: type[Inheritors_T], subclasses: bool = True +) -> set[type[Inheritors_T]]: + """Return all classes that are subclasses from the supplied cls. + + Args: + cls: The class to search for subclasses + subclasses: Include subclasses of subclasses (default = True) + """ subcls = set() work = [cls] @@ -963,7 +970,8 @@ def inheritors(cls: type[Inheritors_T]) -> set[type[Inheritors_T]]: for child in parent.__subclasses__(): if child not in subcls: subcls.add(child) - work.append(child) + if subclasses: + work.append(child) return subcls diff --git a/src/backend/InvenTree/InvenTree/metadata.py b/src/backend/InvenTree/InvenTree/metadata.py index 7805d73c0a..15a5f2f079 100644 --- a/src/backend/InvenTree/InvenTree/metadata.py +++ b/src/backend/InvenTree/InvenTree/metadata.py @@ -363,7 +363,7 @@ class InvenTreeMetadata(SimpleMetadata): field_info['type'] = 'related field' field_info['model'] = model._meta.model_name - # Special case for 'user' model + # Special case for special models if field_info['model'] == 'user': field_info['api_url'] = '/api/user/' elif field_info['model'] == 'contenttype': @@ -381,6 +381,14 @@ class InvenTreeMetadata(SimpleMetadata): if field_info['type'] == 'dependent field': field_info['depends_on'] = field.depends_on + # Extend field info if the field has a get_field_info method + if ( + not field_info.get('read_only') + and hasattr(field, 'get_field_info') + and callable(field.get_field_info) + ): + field_info = field.get_field_info(field, field_info) + return field_info diff --git a/src/backend/InvenTree/build/migrations/0052_build_status_custom_key_alter_build_status.py b/src/backend/InvenTree/build/migrations/0052_build_status_custom_key_alter_build_status.py new file mode 100644 index 0000000000..9e0776fd09 --- /dev/null +++ b/src/backend/InvenTree/build/migrations/0052_build_status_custom_key_alter_build_status.py @@ -0,0 +1,39 @@ +# Generated by Django 4.2.14 on 2024-08-07 22:40 + +import django.core.validators +from django.db import migrations + +import generic.states.fields +import InvenTree.status_codes + + +class Migration(migrations.Migration): + + dependencies = [ + ("build", "0051_delete_buildorderattachment"), + ] + + operations = [ + migrations.AddField( + model_name="build", + name="status_custom_key", + field=generic.states.fields.ExtraInvenTreeCustomStatusModelField( + blank=True, + default=None, + help_text="Additional status information for this item", + null=True, + verbose_name="Custom status key", + ), + ), + migrations.AlterField( + model_name="build", + name="status", + field=generic.states.fields.InvenTreeCustomStatusModelField( + choices=InvenTree.status_codes.BuildStatus.items(), + default=10, + help_text="Build status code", + validators=[django.core.validators.MinValueValidator(0)], + verbose_name="Build Status", + ), + ), + ] diff --git a/src/backend/InvenTree/build/models.py b/src/backend/InvenTree/build/models.py index adde7080da..899145f98d 100644 --- a/src/backend/InvenTree/build/models.py +++ b/src/backend/InvenTree/build/models.py @@ -43,6 +43,7 @@ import part.models import report.mixins import stock.models import users.models +import generic.states logger = logging.getLogger('inventree') @@ -315,7 +316,7 @@ class Build( help_text=_('Number of stock items which have been completed') ) - status = models.PositiveIntegerField( + status = generic.states.fields.InvenTreeCustomStatusModelField( verbose_name=_('Build Status'), default=BuildStatus.PENDING.value, choices=BuildStatus.items(), diff --git a/src/backend/InvenTree/build/serializers.py b/src/backend/InvenTree/build/serializers.py index ade07fbdf9..473c4b423d 100644 --- a/src/backend/InvenTree/build/serializers.py +++ b/src/backend/InvenTree/build/serializers.py @@ -2,45 +2,53 @@ from decimal import Decimal -from django.db import transaction from django.core.exceptions import ValidationError as DjangoValidationError -from django.utils.translation import gettext_lazy as _ - -from django.db import models -from django.db.models import ExpressionWrapper, F, FloatField -from django.db.models import Case, Sum, When, Value -from django.db.models import BooleanField, Q +from django.db import models, transaction +from django.db.models import ( + BooleanField, + Case, + ExpressionWrapper, + F, + FloatField, + Q, + Sum, + Value, + When, +) from django.db.models.functions import Coalesce +from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from rest_framework.serializers import ValidationError -from InvenTree.serializers import InvenTreeModelSerializer, UserSerializer - -import InvenTree.helpers -import InvenTree.tasks -from InvenTree.serializers import InvenTreeDecimalField, NotesFieldMixin -from stock.status_codes import StockStatus - -from stock.generators import generate_batch_code -from stock.models import StockItem, StockLocation -from stock.serializers import StockItemSerializerBrief, LocationBriefSerializer - import build.tasks import common.models -from common.serializers import ProjectCodeSerializer -from common.settings import get_global_setting -from importer.mixins import DataImportExportSerializerMixin import company.serializers +import InvenTree.helpers +import InvenTree.tasks import part.filters import part.serializers as part_serializers +from common.serializers import ProjectCodeSerializer +from common.settings import get_global_setting +from generic.states.fields import InvenTreeCustomStatusSerializerMixin +from importer.mixins import DataImportExportSerializerMixin +from InvenTree.serializers import ( + InvenTreeDecimalField, + InvenTreeModelSerializer, + NotesFieldMixin, + UserSerializer, +) +from stock.generators import generate_batch_code +from stock.models import StockItem, StockLocation +from stock.serializers import LocationBriefSerializer, StockItemSerializerBrief +from stock.status_codes import StockStatus from users.serializers import OwnerSerializer -from .models import Build, BuildLine, BuildItem +from .models import Build, BuildItem, BuildLine from .status_codes import BuildStatus -class BuildSerializer(NotesFieldMixin, DataImportExportSerializerMixin, InvenTreeModelSerializer): +class BuildSerializer(NotesFieldMixin, DataImportExportSerializerMixin, InvenTreeCustomStatusSerializerMixin, InvenTreeModelSerializer): """Serializes a Build object.""" class Meta: @@ -69,6 +77,7 @@ class BuildSerializer(NotesFieldMixin, DataImportExportSerializerMixin, InvenTre 'quantity', 'status', 'status_text', + 'status_custom_key', 'target_date', 'take_from', 'notes', diff --git a/src/backend/InvenTree/build/status_codes.py b/src/backend/InvenTree/build/status_codes.py index 56c8a3a5d6..bc7fc47ddc 100644 --- a/src/backend/InvenTree/build/status_codes.py +++ b/src/backend/InvenTree/build/status_codes.py @@ -2,17 +2,17 @@ from django.utils.translation import gettext_lazy as _ -from generic.states import StatusCode +from generic.states import ColorEnum, StatusCode class BuildStatus(StatusCode): """Build status codes.""" - PENDING = 10, _('Pending'), 'secondary' # Build is pending / active - PRODUCTION = 20, _('Production'), 'primary' # Build is in production - ON_HOLD = 25, _('On Hold'), 'warning' # Build is on hold - CANCELLED = 30, _('Cancelled'), 'danger' # Build was cancelled - COMPLETE = 40, _('Complete'), 'success' # Build is complete + PENDING = 10, _('Pending'), ColorEnum.secondary # Build is pending / active + PRODUCTION = 20, _('Production'), ColorEnum.primary # Build is in production + ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Build is on hold + CANCELLED = 30, _('Cancelled'), ColorEnum.danger # Build was cancelled + COMPLETE = 40, _('Complete'), ColorEnum.success # Build is complete class BuildStatusGroups: diff --git a/src/backend/InvenTree/build/templates/build/build_base.html b/src/backend/InvenTree/build/templates/build/build_base.html index 6c2760558f..e9c4b5b9d2 100644 --- a/src/backend/InvenTree/build/templates/build/build_base.html +++ b/src/backend/InvenTree/build/templates/build/build_base.html @@ -158,7 +158,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Status" %} - {% status_label 'build' build.status %} + {% display_status_label 'build' build.status_custom_key build.status %} {% if build.target_date %} @@ -225,7 +225,7 @@ src="{% static 'img/blank_image.png' %}" {% block page_data %}

- {% status_label 'build' build.status large=True %} + {% display_status_label 'build' build.status_custom_key build.status large=True %} {% if build.is_overdue %} {% trans "Overdue" %} {% endif %} diff --git a/src/backend/InvenTree/build/templates/build/detail.html b/src/backend/InvenTree/build/templates/build/detail.html index 15e0612d70..df93bd1140 100644 --- a/src/backend/InvenTree/build/templates/build/detail.html +++ b/src/backend/InvenTree/build/templates/build/detail.html @@ -60,7 +60,7 @@ {% trans "Status" %} - {% status_label 'build' build.status %} + {% display_status_label 'build' build.status_custom_key build.status %} diff --git a/src/backend/InvenTree/common/api.py b/src/backend/InvenTree/common/api.py index 8701049231..fe5e622762 100644 --- a/src/backend/InvenTree/common/api.py +++ b/src/backend/InvenTree/common/api.py @@ -29,7 +29,7 @@ import common.models import common.serializers from common.icons import get_icon_packs from common.settings import get_global_setting -from generic.states.api import AllStatusViews, StatusView +from generic.states.api import urlpattern as generic_states_api_urls from importer.mixins import DataExportViewMixin from InvenTree.api import BulkDeleteMixin, MetadataView from InvenTree.config import CONFIG_LOOKUPS @@ -655,6 +655,8 @@ class ContentTypeList(ListAPI): queryset = ContentType.objects.all() serializer_class = common.serializers.ContentTypeSerializer permission_classes = [permissions.IsAuthenticated] + filter_backends = SEARCH_ORDER_FILTER + search_fields = ['app_label', 'model'] class ContentTypeDetail(RetrieveAPI): @@ -965,16 +967,7 @@ common_api_urls = [ ]), ), # Status - path( - 'generic/status/', - include([ - path( - f'/', - include([path('', StatusView.as_view(), name='api-status')]), - ), - path('', AllStatusViews.as_view(), name='api-status-all'), - ]), - ), + path('generic/status/', include(generic_states_api_urls)), # Contenttype path( 'contenttype/', diff --git a/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py b/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py new file mode 100644 index 0000000000..7090b98279 --- /dev/null +++ b/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py @@ -0,0 +1,97 @@ +# Generated by Django 4.2.14 on 2024-08-07 22:40 + +import django.db.models.deletion +from django.db import migrations, models + +from common.models import state_color_mappings + + +class Migration(migrations.Migration): + + dependencies = [ + ("contenttypes", "0002_remove_content_type_name"), + ("common", "0028_colortheme_user_obj"), + ] + + operations = [ + migrations.CreateModel( + name="InvenTreeCustomUserStateModel", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "key", + models.IntegerField( + help_text="Value that will be saved in the models database", + verbose_name="Key", + ), + ), + ( + "name", + models.CharField( + help_text="Name of the state", + max_length=250, + verbose_name="Name", + ), + ), + ( + "label", + models.CharField( + help_text="Label that will be displayed in the frontend", + max_length=250, + verbose_name="label", + ), + ), + ( + "color", + models.CharField( + choices=state_color_mappings(), + default="secondary", + help_text="Color that will be displayed in the frontend", + max_length=10, + verbose_name="Color", + ), + ), + ( + "logical_key", + models.IntegerField( + help_text="State logical key that is equal to this custom state in business logic", + verbose_name="Logical Key", + ), + ), + ( + "reference_status", + models.CharField( + help_text="Status set that is extended with this custom state", + max_length=250, + verbose_name="Reference Status Set", + ), + ), + ( + "model", + models.ForeignKey( + blank=True, + help_text="Model this state is associated with", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="contenttypes.contenttype", + verbose_name="Model", + ), + ), + ], + options={ + "verbose_name": "Custom State", + "verbose_name_plural": "Custom States", + "unique_together": { + ("model", "reference_status", "key", "logical_key") + }, + }, + ), + ] diff --git a/src/backend/InvenTree/common/models.py b/src/backend/InvenTree/common/models.py index 9b34a4c37b..ca3b45c9dc 100644 --- a/src/backend/InvenTree/common/models.py +++ b/src/backend/InvenTree/common/models.py @@ -53,6 +53,8 @@ import order.validators import plugin.base.barcodes.helper import report.helpers import users.models +from generic.states import ColorEnum +from generic.states.custom import get_custom_classes, state_color_mappings from InvenTree.sanitizer import sanitize_svg from plugin import registry @@ -3339,3 +3341,109 @@ class Attachment(InvenTree.models.MetadataMixin, InvenTree.models.InvenTreeModel raise ValidationError(_('Invalid model type specified for attachment')) return model_class.check_attachment_permission(permission, user) + + +class InvenTreeCustomUserStateModel(models.Model): + """Custom model to extends any registered state with extra custom, user defined states.""" + + key = models.IntegerField( + verbose_name=_('Key'), + help_text=_('Value that will be saved in the models database'), + ) + name = models.CharField( + max_length=250, verbose_name=_('Name'), help_text=_('Name of the state') + ) + label = models.CharField( + max_length=250, + verbose_name=_('label'), + help_text=_('Label that will be displayed in the frontend'), + ) + color = models.CharField( + max_length=10, + choices=state_color_mappings(), + default=ColorEnum.secondary.value, + verbose_name=_('Color'), + help_text=_('Color that will be displayed in the frontend'), + ) + logical_key = models.IntegerField( + verbose_name=_('Logical Key'), + help_text=_( + 'State logical key that is equal to this custom state in business logic' + ), + ) + model = models.ForeignKey( + ContentType, + on_delete=models.SET_NULL, + null=True, + blank=True, + verbose_name=_('Model'), + help_text=_('Model this state is associated with'), + ) + reference_status = models.CharField( + max_length=250, + verbose_name=_('Reference Status Set'), + help_text=_('Status set that is extended with this custom state'), + ) + + class Meta: + """Metaclass options for this mixin.""" + + verbose_name = _('Custom State') + verbose_name_plural = _('Custom States') + unique_together = [['model', 'reference_status', 'key', 'logical_key']] + + def __str__(self) -> str: + """Return string representation of the custom state.""" + return f'{self.model.name} ({self.reference_status}): {self.name} | {self.key} ({self.logical_key})' + + def save(self, *args, **kwargs) -> None: + """Ensure that the custom state is valid before saving.""" + self.clean() + return super().save(*args, **kwargs) + + def clean(self) -> None: + """Validate custom state data.""" + if self.model is None: + raise ValidationError({'model': _('Model must be selected')}) + + if self.key is None: + raise ValidationError({'key': _('Key must be selected')}) + + if self.logical_key is None: + raise ValidationError({'logical_key': _('Logical key must be selected')}) + + # Ensure that the key is not the same as the logical key + if self.key == self.logical_key: + raise ValidationError({'key': _('Key must be different from logical key')}) + + if self.reference_status is None or self.reference_status == '': + raise ValidationError({ + 'reference_status': _('Reference status must be selected') + }) + + # Ensure that the key is not in the range of the logical keys of the reference status + ref_set = list( + filter( + lambda x: x.__name__ == self.reference_status, + get_custom_classes(include_custom=False), + ) + ) + if len(ref_set) == 0: + raise ValidationError({ + 'reference_status': _('Reference status set not found') + }) + ref_set = ref_set[0] + if self.key in ref_set.keys(): + raise ValidationError({ + 'key': _( + 'Key must be different from the logical keys of the reference status' + ) + }) + if self.logical_key not in ref_set.keys(): + raise ValidationError({ + 'logical_key': _( + 'Logical key must be in the logical keys of the reference status' + ) + }) + + return super().clean() diff --git a/src/backend/InvenTree/common/serializers.py b/src/backend/InvenTree/common/serializers.py index 4c1f6a30dd..9f69bbffff 100644 --- a/src/backend/InvenTree/common/serializers.py +++ b/src/backend/InvenTree/common/serializers.py @@ -14,6 +14,7 @@ from taggit.serializers import TagListSerializerField import common.models as common_models import common.validators +import generic.states.custom from importer.mixins import DataImportExportSerializerMixin from importer.registry import register_importer from InvenTree.helpers import get_objectreference @@ -308,6 +309,32 @@ class ProjectCodeSerializer(DataImportExportSerializerMixin, InvenTreeModelSeria responsible_detail = OwnerSerializer(source='responsible', read_only=True) +@register_importer() +class CustomStateSerializer(DataImportExportSerializerMixin, InvenTreeModelSerializer): + """Serializer for the custom state model.""" + + class Meta: + """Meta options for CustomStateSerializer.""" + + model = common_models.InvenTreeCustomUserStateModel + fields = [ + 'pk', + 'key', + 'name', + 'label', + 'color', + 'logical_key', + 'model', + 'model_name', + 'reference_status', + ] + + model_name = serializers.CharField(read_only=True, source='model.name') + reference_status = serializers.ChoiceField( + choices=generic.states.custom.state_reference_mappings() + ) + + class FlagSerializer(serializers.Serializer): """Serializer for feature flags.""" diff --git a/src/backend/InvenTree/common/tests.py b/src/backend/InvenTree/common/tests.py index c76d17f5b9..2d6279734d 100644 --- a/src/backend/InvenTree/common/tests.py +++ b/src/backend/InvenTree/common/tests.py @@ -33,6 +33,7 @@ from .models import ( Attachment, ColorTheme, CustomUnit, + InvenTreeCustomUserStateModel, InvenTreeSetting, InvenTreeUserSetting, NotesImage, @@ -1586,3 +1587,93 @@ class ValidatorsTest(TestCase): common.validators.validate_icon('ti:package:non-existing-variant') common.validators.validate_icon('ti:package:outline') + + +class CustomStatusTest(TestCase): + """Unit tests for the custom status model.""" + + def setUp(self): + """Setup for all tests.""" + self.data = { + 'key': 11, + 'name': 'OK - advanced', + 'label': 'OK - adv.', + 'color': 'secondary', + 'logical_key': 10, + 'model': ContentType.objects.get(model='stockitem'), + 'reference_status': 'StockStatus', + } + + def test_validation_model(self): + """Test that model is present.""" + data = self.data + data.pop('model') + with self.assertRaises(ValidationError): + InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 0) + + def test_validation_key(self): + """Tests Model must have a key.""" + data = self.data + data.pop('key') + with self.assertRaises(ValidationError): + InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 0) + + def test_validation_logicalkey(self): + """Tests Logical key must be present.""" + data = self.data + data.pop('logical_key') + with self.assertRaises(ValidationError): + InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 0) + + def test_validation_reference(self): + """Tests Reference status must be present.""" + data = self.data + data.pop('reference_status') + with self.assertRaises(ValidationError): + InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 0) + + def test_validation_logical_unique(self): + """Tests Logical key must be unique.""" + data = self.data + data['logical_key'] = data['key'] + with self.assertRaises(ValidationError): + InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 0) + + def test_validation_reference_exsists(self): + """Tests Reference status set not found.""" + data = self.data + data['reference_status'] = 'abcd' + with self.assertRaises(ValidationError): + InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 0) + + def test_validation_key_unique(self): + """Tests Key must be different from the logical keys of the reference.""" + data = self.data + data['key'] = 50 + with self.assertRaises(ValidationError): + InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 0) + + def test_validation_logical_key_exsists(self): + """Tests Logical key must be in the logical keys of the reference status.""" + data = self.data + data['logical_key'] = 12 + with self.assertRaises(ValidationError): + InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 0) + + def test_validation(self): + """Tests Valid run.""" + data = self.data + instance = InvenTreeCustomUserStateModel.objects.create(**data) + self.assertEqual(data['key'], instance.key) + self.assertEqual(InvenTreeCustomUserStateModel.objects.count(), 1) + self.assertEqual( + instance.__str__(), 'Stock Item (StockStatus): OK - advanced | 11 (10)' + ) diff --git a/src/backend/InvenTree/generic/states/__init__.py b/src/backend/InvenTree/generic/states/__init__.py index 8d5fdfed71..a13139b5ff 100644 --- a/src/backend/InvenTree/generic/states/__init__.py +++ b/src/backend/InvenTree/generic/states/__init__.py @@ -6,7 +6,13 @@ There is a rendered state for each state value. The rendered state is used for d States can be extended with custom options for each InvenTree instance - those options are stored in the database and need to link back to state values. """ -from .states import StatusCode +from .states import ColorEnum, StatusCode from .transition import StateTransitionMixin, TransitionMethod, storage -__all__ = ['StatusCode', 'storage', 'TransitionMethod', 'StateTransitionMixin'] +__all__ = [ + 'ColorEnum', + 'StatusCode', + 'storage', + 'TransitionMethod', + 'StateTransitionMixin', +] diff --git a/src/backend/InvenTree/generic/states/api.py b/src/backend/InvenTree/generic/states/api.py index 203a6dea3a..49c7425335 100644 --- a/src/backend/InvenTree/generic/states/api.py +++ b/src/backend/InvenTree/generic/states/api.py @@ -2,12 +2,22 @@ import inspect +from django.urls import include, path + from drf_spectacular.utils import OpenApiResponse, extend_schema from rest_framework import permissions, serializers from rest_framework.generics import GenericAPIView from rest_framework.response import Response +import common.models +import common.serializers +from generic.states.custom import get_status_api_response +from importer.mixins import DataExportViewMixin +from InvenTree.filters import SEARCH_ORDER_FILTER +from InvenTree.mixins import ListCreateAPI, RetrieveUpdateDestroyAPI +from InvenTree.permissions import IsStaffOrReadOnly from InvenTree.serializers import EmptySerializer +from machine.machine_type import MachineStatus from .states import StatusCode @@ -73,18 +83,52 @@ class AllStatusViews(StatusView): def get(self, request, *args, **kwargs): """Perform a GET request to learn information about status codes.""" - data = {} - - def discover_status_codes(parent_status_class, prefix=None): - """Recursively discover status classes.""" - for status_class in parent_status_class.__subclasses__(): - name = '__'.join([*(prefix or []), status_class.__name__]) - data[name] = { - 'class': status_class.__name__, - 'values': status_class.dict(), - } - discover_status_codes(status_class, [name]) - - discover_status_codes(StatusCode) - + data = get_status_api_response() + # Extend with MachineStatus classes + data.update(get_status_api_response(MachineStatus, prefix=['MachineStatus'])) return Response(data) + + +# Custom states +class CustomStateList(DataExportViewMixin, ListCreateAPI): + """List view for all custom states.""" + + queryset = common.models.InvenTreeCustomUserStateModel.objects.all() + serializer_class = common.serializers.CustomStateSerializer + permission_classes = [permissions.IsAuthenticated, IsStaffOrReadOnly] + filter_backends = SEARCH_ORDER_FILTER + ordering_fields = ['key'] + search_fields = ['key', 'name', 'label', 'reference_status'] + + +class CustomStateDetail(RetrieveUpdateDestroyAPI): + """Detail view for a particular custom states.""" + + queryset = common.models.InvenTreeCustomUserStateModel.objects.all() + serializer_class = common.serializers.CustomStateSerializer + permission_classes = [permissions.IsAuthenticated, IsStaffOrReadOnly] + + +urlpattern = [ + # Custom state + path( + 'custom/', + include([ + path( + '/', CustomStateDetail.as_view(), name='api-custom-state-detail' + ), + path('', CustomStateList.as_view(), name='api-custom-state-list'), + ]), + ), + # Generic status views + path( + '', + include([ + path( + f'/', + include([path('', StatusView.as_view(), name='api-status')]), + ), + path('', AllStatusViews.as_view(), name='api-status-all'), + ]), + ), +] diff --git a/src/backend/InvenTree/generic/states/custom.py b/src/backend/InvenTree/generic/states/custom.py new file mode 100644 index 0000000000..2539eb550e --- /dev/null +++ b/src/backend/InvenTree/generic/states/custom.py @@ -0,0 +1,88 @@ +"""Helper functions for custom status labels.""" + +from InvenTree.helpers import inheritors + +from .states import ColorEnum, StatusCode + + +def get_custom_status_labels(include_custom: bool = True): + """Return a dict of custom status labels.""" + return {cls.tag(): cls for cls in get_custom_classes(include_custom)} + + +def get_status_api_response(base_class=StatusCode, prefix=None): + """Return a dict of status classes (custom and class defined). + + Args: + base_class: The base class to search for subclasses. + prefix: A list of strings to prefix the class names with. + """ + return { + '__'.join([*(prefix or []), k.__name__]): { + 'class': k.__name__, + 'values': k.dict(), + } + for k in get_custom_classes(base_class=base_class, subclass=False) + } + + +def state_color_mappings(): + """Return a list of custom user state colors.""" + return [(a.name, a.value) for a in ColorEnum] + + +def state_reference_mappings(): + """Return a list of custom user state references.""" + return [(a.__name__, a.__name__) for a in get_custom_classes(include_custom=False)] + + +def get_logical_value(value, model: str): + """Return the state model for the selected value.""" + from common.models import InvenTreeCustomUserStateModel + + return InvenTreeCustomUserStateModel.objects.get(key=value, model__model=model) + + +def get_custom_classes( + include_custom: bool = True, base_class=StatusCode, subclass=False +): + """Return a dict of status classes (custom and class defined).""" + discovered_classes = inheritors(base_class, subclass) + + if not include_custom: + return discovered_classes + + # Gather DB settings + from common.models import InvenTreeCustomUserStateModel + + custom_db_states = {} + custom_db_mdls = {} + for item in list(InvenTreeCustomUserStateModel.objects.all()): + if not custom_db_states.get(item.reference_status): + custom_db_states[item.reference_status] = [] + custom_db_states[item.reference_status].append(item) + custom_db_mdls[item.model.app_label] = item.reference_status + custom_db_mdls_keys = custom_db_mdls.keys() + + states = {} + for cls in discovered_classes: + tag = cls.tag() + states[tag] = cls + if custom_db_mdls and tag in custom_db_mdls_keys: + data = [(str(m.name), (m.value, m.label, m.color)) for m in states[tag]] + data_keys = [i[0] for i in data] + + # Extent with non present tags + for entry in custom_db_states[custom_db_mdls[tag]]: + ref_name = str(entry.name.upper().replace(' ', '')) + if ref_name not in data_keys: + data += [ + ( + str(entry.name.upper().replace(' ', '')), + (entry.key, entry.label, entry.color), + ) + ] + + # Re-assemble the enum + states[tag] = base_class(f'{tag.capitalize()}Status', data) + return states.values() diff --git a/src/backend/InvenTree/generic/states/fields.py b/src/backend/InvenTree/generic/states/fields.py new file mode 100644 index 0000000000..99717d4884 --- /dev/null +++ b/src/backend/InvenTree/generic/states/fields.py @@ -0,0 +1,241 @@ +"""Custom model/serializer fields for InvenTree models that support custom states.""" + +from typing import Any, Iterable, Optional + +from django.core.exceptions import ObjectDoesNotExist +from django.db import models +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ + +from rest_framework import serializers +from rest_framework.fields import ChoiceField + +from .custom import get_logical_value + + +class CustomChoiceField(serializers.ChoiceField): + """Custom Choice Field. + + This is not intended to be used directly. + """ + + def __init__(self, choices: Iterable, **kwargs): + """Initialize the field.""" + choice_mdl = kwargs.pop('choice_mdl', None) + choice_field = kwargs.pop('choice_field', None) + is_custom = kwargs.pop('is_custom', False) + kwargs.pop('max_value', None) + kwargs.pop('min_value', None) + super().__init__(choices, **kwargs) + self.choice_mdl = choice_mdl + self.choice_field = choice_field + self.is_custom = is_custom + + def to_internal_value(self, data): + """Map the choice (that might be a custom one) back to the logical value.""" + try: + return super().to_internal_value(data) + except serializers.ValidationError: + try: + logical = get_logical_value(data, self.choice_mdl._meta.model_name) + if self.is_custom: + return logical.key + return logical.logical_key + except ObjectDoesNotExist: + raise serializers.ValidationError('Invalid choice') + + def get_field_info(self, field, field_info): + """Return the field information for the given item.""" + from common.models import InvenTreeCustomUserStateModel + + # Static choices + choices = [ + { + 'value': choice_value, + 'display_name': force_str(choice_name, strings_only=True), + } + for choice_value, choice_name in field.choices.items() + ] + # Dynamic choices from InvenTreeCustomUserStateModel + objs = InvenTreeCustomUserStateModel.objects.filter( + model__model=field.choice_mdl._meta.model_name + ) + dyn_choices = [ + {'value': choice.key, 'display_name': choice.label} for choice in objs.all() + ] + + if dyn_choices: + all_choices = choices + dyn_choices + field_info['choices'] = sorted(all_choices, key=lambda kv: kv['value']) + else: + field_info['choices'] = choices + return field_info + + +class ExtraCustomChoiceField(CustomChoiceField): + """Custom Choice Field that returns value of status if empty. + + This is not intended to be used directly. + """ + + def to_representation(self, value): + """Return the value of the status if it is empty.""" + return super().to_representation(value) or value + + +class InvenTreeCustomStatusModelField(models.PositiveIntegerField): + """Custom model field for extendable status codes. + + Adds a secondary *_custom_key field to the model which can be used to store additional status information. + Models using this model field must also include the InvenTreeCustomStatusSerializerMixin in all serializers that create or update the value. + """ + + def deconstruct(self): + """Deconstruct the field for migrations.""" + name, path, args, kwargs = super().deconstruct() + + return name, path, args, kwargs + + def contribute_to_class(self, cls, name): + """Add the _custom_key field to the model.""" + cls._meta.supports_custom_status = True + + if not hasattr(self, '_custom_key_field'): + self.add_field(cls, name) + + super().contribute_to_class(cls, name) + + def clean(self, value: Any, model_instance: Any) -> Any: + """Ensure that the value is not an empty string.""" + if value == '': + value = None + return super().clean(value, model_instance) + + def add_field(self, cls, name): + """Adds custom_key_field to the model class to save additional status information.""" + custom_key_field = ExtraInvenTreeCustomStatusModelField( + default=None, + verbose_name=_('Custom status key'), + help_text=_('Additional status information for this item'), + blank=True, + null=True, + ) + cls.add_to_class(f'{name}_custom_key', custom_key_field) + self._custom_key_field = custom_key_field + + +class ExtraInvenTreeCustomStatusModelField(models.PositiveIntegerField): + """Custom field used to detect custom extenteded fields. + + This is not intended to be used directly, if you want to support custom states in your model use InvenTreeCustomStatusModelField. + """ + + +class InvenTreeCustomStatusSerializerMixin: + """Mixin to ensure custom status fields are set. + + This mixin must be used to ensure that custom status fields are set correctly when updating a model. + """ + + _custom_fields: Optional[list] = None + _custom_fields_leader: Optional[list] = None + _custom_fields_follower: Optional[list] = None + _is_gathering = False + + def update(self, instance, validated_data): + """Ensure the custom field is updated if the leader was changed.""" + self.gather_custom_fields() + for field in self._custom_fields_leader: + if ( + field in self.initial_data + and self.instance + and self.initial_data[field] + != getattr(self.instance, f'{field}_custom_key', None) + ): + setattr(self.instance, f'{field}_custom_key', self.initial_data[field]) + for field in self._custom_fields_follower: + if ( + field in validated_data + and field.replace('_custom_key', '') not in self.initial_data + ): + reference = get_logical_value( + validated_data[field], + self.fields[field].choice_mdl._meta.model_name, + ) + validated_data[field.replace('_custom_key', '')] = reference.logical_key + return super().update(instance, validated_data) + + def to_representation(self, instance): + """Ensure custom state fields are not served empty.""" + data = super().to_representation(instance) + for field in self.gather_custom_fields(): + if data[field] is None: + data[field] = data[ + field.replace('_custom_key', '') + ] # Use "normal" status field instead + return data + + def gather_custom_fields(self): + """Gather all custom fields on the serializer.""" + if self._custom_fields_follower: + self._is_gathering = False + return self._custom_fields_follower + + if self._is_gathering: + self._custom_fields = {} + else: + self._is_gathering = True + # Gather fields + self._custom_fields = { + k: v.is_custom + for k, v in self.fields.items() + if isinstance(v, CustomChoiceField) + } + + # Separate fields for easier/cheaper access + self._custom_fields_follower = [k for k, v in self._custom_fields.items() if v] + self._custom_fields_leader = [ + k for k, v in self._custom_fields.items() if not v + ] + + return self._custom_fields_follower + + def build_standard_field(self, field_name, model_field): + """Use custom field for custom status model. + + This is required because of DRF overwriting all fields with choice sets. + """ + field_cls, field_kwargs = super().build_standard_field(field_name, model_field) + if issubclass(field_cls, ChoiceField) and isinstance( + model_field, InvenTreeCustomStatusModelField + ): + field_cls = CustomChoiceField + field_kwargs['choice_mdl'] = model_field.model + field_kwargs['choice_field'] = model_field.name + elif isinstance(model_field, ExtraInvenTreeCustomStatusModelField): + field_cls = ExtraCustomChoiceField + field_kwargs['choice_mdl'] = model_field.model + field_kwargs['choice_field'] = model_field.name + field_kwargs['is_custom'] = True + + # Inherit choices from leader + self.gather_custom_fields() + if field_name in self._custom_fields: + leader_field_name = field_name.replace('_custom_key', '') + leader_field = self.fields[leader_field_name] + if hasattr(leader_field, 'choices'): + field_kwargs['choices'] = list(leader_field.choices.items()) + elif hasattr(model_field.model, leader_field_name): + leader_model_field = getattr( + model_field.model, leader_field_name + ).field + if hasattr(leader_model_field, 'choices'): + field_kwargs['choices'] = leader_model_field.choices + + if getattr(leader_field, 'read_only', False) is True: + field_kwargs['read_only'] = True + + if 'choices' not in field_kwargs: + field_kwargs['choices'] = [] + + return field_cls, field_kwargs diff --git a/src/backend/InvenTree/generic/states/states.py b/src/backend/InvenTree/generic/states/states.py index c72b201eca..1ac7de1174 100644 --- a/src/backend/InvenTree/generic/states/states.py +++ b/src/backend/InvenTree/generic/states/states.py @@ -2,6 +2,7 @@ import enum import re +from enum import Enum class BaseEnum(enum.IntEnum): @@ -65,10 +66,23 @@ class StatusCode(BaseEnum): # Normal item definition if len(args) == 1: obj.label = args[0] - obj.color = 'secondary' + obj.color = ColorEnum.secondary else: obj.label = args[1] - obj.color = args[2] if len(args) > 2 else 'secondary' + obj.color = args[2] if len(args) > 2 else ColorEnum.secondary + + # Ensure color is a valid value + if isinstance(obj.color, str): + try: + obj.color = ColorEnum(obj.color) + except ValueError: + raise ValueError( + f"Invalid color value '{obj.color}' for status '{obj.label}'" + ) + + # Set color value as string + obj.color = obj.color.value + obj.color_class = obj.color return obj @@ -181,3 +195,15 @@ class StatusCode(BaseEnum): ret['list'] = cls.list() return ret + + +class ColorEnum(Enum): + """Enum for color values.""" + + primary = 'primary' + secondary = 'secondary' + success = 'success' + danger = 'danger' + warning = 'warning' + info = 'info' + dark = 'dark' diff --git a/src/backend/InvenTree/generic/states/tags.py b/src/backend/InvenTree/generic/states/tags.py index 19e1471b28..f93a6b8a96 100644 --- a/src/backend/InvenTree/generic/states/tags.py +++ b/src/backend/InvenTree/generic/states/tags.py @@ -3,15 +3,21 @@ from django.utils.safestring import mark_safe from generic.templatetags.generic import register -from InvenTree.helpers import inheritors -from .states import StatusCode +from .custom import get_custom_status_labels @register.simple_tag -def status_label(typ: str, key: int, *args, **kwargs): +def status_label(typ: str, key: int, include_custom: bool = False, *args, **kwargs): """Render a status label.""" - state = {cls.tag(): cls for cls in inheritors(StatusCode)}.get(typ, None) + state = get_custom_status_labels(include_custom=include_custom).get(typ, None) if state: return mark_safe(state.render(key, large=kwargs.get('large', False))) raise ValueError(f"Unknown status type '{typ}'") + + +@register.simple_tag +def display_status_label(typ: str, key: int, fallback: int, *args, **kwargs): + """Render a status label.""" + render_key = int(key) if key else fallback + return status_label(typ, render_key, *args, include_custom=True, **kwargs) diff --git a/src/backend/InvenTree/generic/states/tests.py b/src/backend/InvenTree/generic/states/tests.py index c30da83ae3..dbba2d14b2 100644 --- a/src/backend/InvenTree/generic/states/tests.py +++ b/src/backend/InvenTree/generic/states/tests.py @@ -1,11 +1,15 @@ """Tests for the generic states module.""" +from django.contrib.contenttypes.models import ContentType from django.test.client import RequestFactory +from django.urls import reverse from django.utils.translation import gettext_lazy as _ from rest_framework.test import force_authenticate -from InvenTree.unit_test import InvenTreeTestCase +from common.models import InvenTreeCustomUserStateModel +from generic.states import ColorEnum +from InvenTree.unit_test import InvenTreeAPITestCase, InvenTreeTestCase from .api import StatusView from .states import StatusCode @@ -14,9 +18,9 @@ from .states import StatusCode class GeneralStatus(StatusCode): """Defines a set of status codes for tests.""" - PENDING = 10, _('Pending'), 'secondary' + PENDING = 10, _('Pending'), ColorEnum.secondary PLACED = 20, _('Placed'), 'primary' - COMPLETE = 30, _('Complete'), 'success' + COMPLETE = 30, _('Complete'), ColorEnum.success ABC = None # This should be ignored _DEF = None # This should be ignored jkl = None # This should be ignored @@ -120,8 +124,19 @@ class GeneralStateTest(InvenTreeTestCase): # label self.assertEqual(GeneralStatus.label(10), 'Pending') - def test_tag_function(self): - """Test that the status code tag functions.""" + def test_color(self): + """Test that the color enum validation works.""" + with self.assertRaises(ValueError) as e: + + class TTTT(StatusCode): + PENDING = 10, _('Pending'), 'invalid' + + self.assertEqual( + str(e.exception), "Invalid color value 'invalid' for status 'Pending'" + ) + + def test_tag_status_label(self): + """Test that the status_label tag.""" from .tags import status_label self.assertEqual( @@ -137,6 +152,21 @@ class GeneralStateTest(InvenTreeTestCase): # Test non-existent key self.assertEqual(status_label('general', 100), '100') + def test_tag_display_status_label(self): + """Test that the display_status_label tag (mainly the same as status_label).""" + from .tags import display_status_label + + self.assertEqual( + display_status_label('general', 10, 11), + "Pending", + ) + # Fallback + self.assertEqual(display_status_label('general', None, 11), '11') + self.assertEqual( + display_status_label('general', None, 10), + "Pending", + ) + def test_api(self): """Test StatusView API view.""" view = StatusView.as_view() @@ -191,3 +221,59 @@ class GeneralStateTest(InvenTreeTestCase): self.assertEqual( str(e.exception), '`status_class` not a valid StatusCode class' ) + + +class ApiTests(InvenTreeAPITestCase): + """Test the API for the generic states module.""" + + def test_all_states(self): + """Test the API endpoint for listing all status models.""" + response = self.get(reverse('api-status-all')) + self.assertEqual(len(response.data), 12) + + # Test the BuildStatus model + build_status = response.data['BuildStatus'] + self.assertEqual(build_status['class'], 'BuildStatus') + self.assertEqual(len(build_status['values']), 5) + pending = build_status['values']['PENDING'] + self.assertEqual(pending['key'], 10) + self.assertEqual(pending['name'], 'PENDING') + self.assertEqual(pending['label'], 'Pending') + + # Test the StockStatus model (static) + stock_status = response.data['StockStatus'] + self.assertEqual(stock_status['class'], 'StockStatus') + self.assertEqual(len(stock_status['values']), 8) + in_stock = stock_status['values']['OK'] + self.assertEqual(in_stock['key'], 10) + self.assertEqual(in_stock['name'], 'OK') + self.assertEqual(in_stock['label'], 'OK') + + # MachineStatus model + machine_status = response.data['MachineStatus__LabelPrinterStatus'] + self.assertEqual(machine_status['class'], 'LabelPrinterStatus') + self.assertEqual(len(machine_status['values']), 6) + connected = machine_status['values']['CONNECTED'] + self.assertEqual(connected['key'], 100) + self.assertEqual(connected['name'], 'CONNECTED') + + # Add custom status + InvenTreeCustomUserStateModel.objects.create( + key=11, + name='OK - advanced', + label='OK - adv.', + color='secondary', + logical_key=10, + model=ContentType.objects.get(model='stockitem'), + reference_status='StockStatus', + ) + response = self.get(reverse('api-status-all')) + self.assertEqual(len(response.data), 12) + + stock_status_cstm = response.data['StockStatus'] + self.assertEqual(stock_status_cstm['class'], 'StockStatus') + self.assertEqual(len(stock_status_cstm['values']), 9) + ok_advanced = stock_status_cstm['values']['OK'] + self.assertEqual(ok_advanced['key'], 10) + self.assertEqual(ok_advanced['name'], 'OK') + self.assertEqual(ok_advanced['label'], 'OK') diff --git a/src/backend/InvenTree/importer/status_codes.py b/src/backend/InvenTree/importer/status_codes.py index 71d4dfd0e6..2a884cec17 100644 --- a/src/backend/InvenTree/importer/status_codes.py +++ b/src/backend/InvenTree/importer/status_codes.py @@ -2,18 +2,26 @@ from django.utils.translation import gettext_lazy as _ -from generic.states import StatusCode +from generic.states import ColorEnum, StatusCode class DataImportStatusCode(StatusCode): """Defines a set of status codes for a DataImportSession.""" - INITIAL = 0, _('Initializing'), 'secondary' # Import session has been created - MAPPING = 10, _('Mapping Columns'), 'primary' # Import fields are being mapped - IMPORTING = 20, _('Importing Data'), 'primary' # Data is being imported + INITIAL = ( + 0, + _('Initializing'), + ColorEnum.secondary, + ) # Import session has been created + MAPPING = ( + 10, + _('Mapping Columns'), + ColorEnum.primary, + ) # Import fields are being mapped + IMPORTING = 20, _('Importing Data'), ColorEnum.primary # Data is being imported PROCESSING = ( 30, _('Processing Data'), - 'primary', + ColorEnum.primary, ) # Data is being processed by the user - COMPLETE = 40, _('Complete'), 'success' # Import has been completed + COMPLETE = 40, _('Complete'), ColorEnum.success # Import has been completed diff --git a/src/backend/InvenTree/machine/machine_types/label_printer.py b/src/backend/InvenTree/machine/machine_types/label_printer.py index e2817322c5..119da641af 100644 --- a/src/backend/InvenTree/machine/machine_types/label_printer.py +++ b/src/backend/InvenTree/machine/machine_types/label_printer.py @@ -12,6 +12,7 @@ from PIL.Image import Image from rest_framework import serializers from rest_framework.request import Request +from generic.states import ColorEnum from machine.machine_type import BaseDriver, BaseMachineType, MachineStatus from plugin import registry as plg_registry from plugin.base.label.mixins import LabelPrintingMixin @@ -228,12 +229,12 @@ class LabelPrinterStatus(MachineStatus): DISCONNECTED: The driver cannot establish a connection to the printer """ - CONNECTED = 100, _('Connected'), 'success' - UNKNOWN = 101, _('Unknown'), 'secondary' - PRINTING = 110, _('Printing'), 'primary' - NO_MEDIA = 301, _('No media'), 'warning' - PAPER_JAM = 302, _('Paper jam'), 'warning' - DISCONNECTED = 400, _('Disconnected'), 'danger' + CONNECTED = 100, _('Connected'), ColorEnum.success + UNKNOWN = 101, _('Unknown'), ColorEnum.secondary + PRINTING = 110, _('Printing'), ColorEnum.primary + NO_MEDIA = 301, _('No media'), ColorEnum.warning + PAPER_JAM = 302, _('Paper jam'), ColorEnum.warning + DISCONNECTED = 400, _('Disconnected'), ColorEnum.danger class LabelPrinterMachine(BaseMachineType): diff --git a/src/backend/InvenTree/order/migrations/0101_purchaseorder_status_custom_key_and_more.py b/src/backend/InvenTree/order/migrations/0101_purchaseorder_status_custom_key_and_more.py new file mode 100644 index 0000000000..26993943b5 --- /dev/null +++ b/src/backend/InvenTree/order/migrations/0101_purchaseorder_status_custom_key_and_more.py @@ -0,0 +1,100 @@ +# Generated by Django 4.2.14 on 2024-08-07 22:40 + +from django.db import migrations + +import generic.states.fields +import InvenTree.status_codes + + +class Migration(migrations.Migration): + + dependencies = [ + ("order", "0100_remove_returnorderattachment_order_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="purchaseorder", + name="status_custom_key", + field=generic.states.fields.ExtraInvenTreeCustomStatusModelField( + blank=True, + default=None, + help_text="Additional status information for this item", + null=True, + verbose_name="Custom status key", + ), + ), + migrations.AddField( + model_name="returnorder", + name="status_custom_key", + field=generic.states.fields.ExtraInvenTreeCustomStatusModelField( + blank=True, + default=None, + help_text="Additional status information for this item", + null=True, + verbose_name="Custom status key", + ), + ), + migrations.AddField( + model_name="returnorderlineitem", + name="outcome_custom_key", + field=generic.states.fields.ExtraInvenTreeCustomStatusModelField( + blank=True, + default=None, + help_text="Additional status information for this item", + null=True, + verbose_name="Custom status key", + ), + ), + migrations.AddField( + model_name="salesorder", + name="status_custom_key", + field=generic.states.fields.ExtraInvenTreeCustomStatusModelField( + blank=True, + default=None, + help_text="Additional status information for this item", + null=True, + verbose_name="Custom status key", + ), + ), + migrations.AlterField( + model_name="purchaseorder", + name="status", + field=generic.states.fields.InvenTreeCustomStatusModelField( + choices=InvenTree.status_codes.PurchaseOrderStatus.items(), + default=10, + help_text="Purchase order status", + verbose_name="Status", + ), + ), + migrations.AlterField( + model_name="returnorder", + name="status", + field=generic.states.fields.InvenTreeCustomStatusModelField( + choices=InvenTree.status_codes.ReturnOrderStatus.items(), + default=10, + help_text="Return order status", + verbose_name="Status", + ), + ), + migrations.AlterField( + model_name="returnorderlineitem", + name="outcome", + field=generic.states.fields.InvenTreeCustomStatusModelField( + choices=InvenTree.status_codes.ReturnOrderLineStatus.items(), + default=10, + help_text="Outcome for this line item", + verbose_name="Outcome", + ), + ), + migrations.AlterField( + model_name="salesorder", + name="status", + field=generic.states.fields.InvenTreeCustomStatusModelField( + choices=InvenTree.status_codes.SalesOrderStatus.items(), + default=10, + help_text="Sales order status", + verbose_name="Status", + ), + ), + ] diff --git a/src/backend/InvenTree/order/models.py b/src/backend/InvenTree/order/models.py index 1a8124cf5c..88b3325da6 100644 --- a/src/backend/InvenTree/order/models.py +++ b/src/backend/InvenTree/order/models.py @@ -37,6 +37,7 @@ from common.notifications import InvenTreeNotificationBodies from common.settings import get_global_setting from company.models import Address, Company, Contact, SupplierPart from generic.states import StateTransitionMixin +from generic.states.fields import InvenTreeCustomStatusModelField from InvenTree.exceptions import log_error from InvenTree.fields import ( InvenTreeModelMoneyField, @@ -470,7 +471,7 @@ class PurchaseOrder(TotalPriceMixin, Order): validators=[order.validators.validate_purchase_order_reference], ) - status = models.PositiveIntegerField( + status = InvenTreeCustomStatusModelField( default=PurchaseOrderStatus.PENDING.value, choices=PurchaseOrderStatus.items(), verbose_name=_('Status'), @@ -996,7 +997,7 @@ class SalesOrder(TotalPriceMixin, Order): """Accessor helper for Order base.""" return self.customer - status = models.PositiveIntegerField( + status = InvenTreeCustomStatusModelField( default=SalesOrderStatus.PENDING.value, choices=SalesOrderStatus.items(), verbose_name=_('Status'), @@ -2153,7 +2154,7 @@ class ReturnOrder(TotalPriceMixin, Order): """Accessor helper for Order base class.""" return self.customer - status = models.PositiveIntegerField( + status = InvenTreeCustomStatusModelField( default=ReturnOrderStatus.PENDING.value, choices=ReturnOrderStatus.items(), verbose_name=_('Status'), @@ -2404,7 +2405,7 @@ class ReturnOrderLineItem(OrderLineItem): """Return True if this item has been received.""" return self.received_date is not None - outcome = models.PositiveIntegerField( + outcome = InvenTreeCustomStatusModelField( default=ReturnOrderLineStatus.PENDING.value, choices=ReturnOrderLineStatus.items(), verbose_name=_('Outcome'), diff --git a/src/backend/InvenTree/order/serializers.py b/src/backend/InvenTree/order/serializers.py index ebfd0bd8f5..d0d07c14d8 100644 --- a/src/backend/InvenTree/order/serializers.py +++ b/src/backend/InvenTree/order/serializers.py @@ -32,6 +32,7 @@ from company.serializers import ( ContactSerializer, SupplierPartSerializer, ) +from generic.states.fields import InvenTreeCustomStatusSerializerMixin from importer.mixins import DataImportExportSerializerMixin from importer.registry import register_importer from InvenTree.helpers import ( @@ -161,6 +162,7 @@ class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Seria 'address_detail', 'status', 'status_text', + 'status_custom_key', 'notes', 'barcode_hash', 'overdue', @@ -216,7 +218,11 @@ class AbstractExtraLineMeta: @register_importer() class PurchaseOrderSerializer( - NotesFieldMixin, TotalPriceMixin, AbstractOrderSerializer, InvenTreeModelSerializer + NotesFieldMixin, + TotalPriceMixin, + InvenTreeCustomStatusSerializerMixin, + AbstractOrderSerializer, + InvenTreeModelSerializer, ): """Serializer for a PurchaseOrder object.""" @@ -859,7 +865,11 @@ class PurchaseOrderReceiveSerializer(serializers.Serializer): @register_importer() class SalesOrderSerializer( - NotesFieldMixin, TotalPriceMixin, AbstractOrderSerializer, InvenTreeModelSerializer + NotesFieldMixin, + TotalPriceMixin, + InvenTreeCustomStatusSerializerMixin, + AbstractOrderSerializer, + InvenTreeModelSerializer, ): """Serializer for the SalesOrder model class.""" @@ -1642,7 +1652,11 @@ class SalesOrderExtraLineSerializer( @register_importer() class ReturnOrderSerializer( - NotesFieldMixin, AbstractOrderSerializer, TotalPriceMixin, InvenTreeModelSerializer + NotesFieldMixin, + InvenTreeCustomStatusSerializerMixin, + AbstractOrderSerializer, + TotalPriceMixin, + InvenTreeModelSerializer, ): """Serializer for the ReturnOrder model class.""" diff --git a/src/backend/InvenTree/order/status_codes.py b/src/backend/InvenTree/order/status_codes.py index bc5df2bca3..3dcbee01f5 100644 --- a/src/backend/InvenTree/order/status_codes.py +++ b/src/backend/InvenTree/order/status_codes.py @@ -2,20 +2,20 @@ from django.utils.translation import gettext_lazy as _ -from generic.states import StatusCode +from generic.states import ColorEnum, StatusCode class PurchaseOrderStatus(StatusCode): """Defines a set of status codes for a PurchaseOrder.""" # Order status codes - PENDING = 10, _('Pending'), 'secondary' # Order is pending (not yet placed) - PLACED = 20, _('Placed'), 'primary' # Order has been placed with supplier - ON_HOLD = 25, _('On Hold'), 'warning' # Order is on hold - COMPLETE = 30, _('Complete'), 'success' # Order has been completed - CANCELLED = 40, _('Cancelled'), 'danger' # Order was cancelled - LOST = 50, _('Lost'), 'warning' # Order was lost - RETURNED = 60, _('Returned'), 'warning' # Order was returned + PENDING = 10, _('Pending'), ColorEnum.secondary # Order is pending (not yet placed) + PLACED = 20, _('Placed'), ColorEnum.primary # Order has been placed with supplier + ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Order is on hold + COMPLETE = 30, _('Complete'), ColorEnum.success # Order has been completed + CANCELLED = 40, _('Cancelled'), ColorEnum.danger # Order was cancelled + LOST = 50, _('Lost'), ColorEnum.warning # Order was lost + RETURNED = 60, _('Returned'), ColorEnum.warning # Order was returned class PurchaseOrderStatusGroups: @@ -39,18 +39,18 @@ class PurchaseOrderStatusGroups: class SalesOrderStatus(StatusCode): """Defines a set of status codes for a SalesOrder.""" - PENDING = 10, _('Pending'), 'secondary' # Order is pending + PENDING = 10, _('Pending'), ColorEnum.secondary # Order is pending IN_PROGRESS = ( 15, _('In Progress'), - 'primary', + ColorEnum.primary, ) # Order has been issued, and is in progress - SHIPPED = 20, _('Shipped'), 'success' # Order has been shipped to customer - ON_HOLD = 25, _('On Hold'), 'warning' # Order is on hold - COMPLETE = 30, _('Complete'), 'success' # Order is complete - CANCELLED = 40, _('Cancelled'), 'danger' # Order has been cancelled - LOST = 50, _('Lost'), 'warning' # Order was lost - RETURNED = 60, _('Returned'), 'warning' # Order was returned + SHIPPED = 20, _('Shipped'), ColorEnum.success # Order has been shipped to customer + ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Order is on hold + COMPLETE = 30, _('Complete'), ColorEnum.success # Order is complete + CANCELLED = 40, _('Cancelled'), ColorEnum.danger # Order has been cancelled + LOST = 50, _('Lost'), ColorEnum.warning # Order was lost + RETURNED = 60, _('Returned'), ColorEnum.warning # Order was returned class SalesOrderStatusGroups: @@ -71,15 +71,15 @@ class ReturnOrderStatus(StatusCode): """Defines a set of status codes for a ReturnOrder.""" # Order is pending, waiting for receipt of items - PENDING = 10, _('Pending'), 'secondary' + PENDING = 10, _('Pending'), ColorEnum.secondary # Items have been received, and are being inspected - IN_PROGRESS = 20, _('In Progress'), 'primary' + IN_PROGRESS = 20, _('In Progress'), ColorEnum.primary - ON_HOLD = 25, _('On Hold'), 'warning' + ON_HOLD = 25, _('On Hold'), ColorEnum.warning - COMPLETE = 30, _('Complete'), 'success' - CANCELLED = 40, _('Cancelled'), 'danger' + COMPLETE = 30, _('Complete'), ColorEnum.success + CANCELLED = 40, _('Cancelled'), ColorEnum.danger class ReturnOrderStatusGroups: @@ -95,19 +95,19 @@ class ReturnOrderStatusGroups: class ReturnOrderLineStatus(StatusCode): """Defines a set of status codes for a ReturnOrderLineItem.""" - PENDING = 10, _('Pending'), 'secondary' + PENDING = 10, _('Pending'), ColorEnum.secondary # Item is to be returned to customer, no other action - RETURN = 20, _('Return'), 'success' + RETURN = 20, _('Return'), ColorEnum.success # Item is to be repaired, and returned to customer - REPAIR = 30, _('Repair'), 'primary' + REPAIR = 30, _('Repair'), ColorEnum.primary # Item is to be replaced (new item shipped) - REPLACE = 40, _('Replace'), 'warning' + REPLACE = 40, _('Replace'), ColorEnum.warning # Item is to be refunded (cannot be repaired) - REFUND = 50, _('Refund'), 'info' + REFUND = 50, _('Refund'), ColorEnum.info # Item is rejected - REJECT = 60, _('Reject'), 'danger' + REJECT = 60, _('Reject'), ColorEnum.danger diff --git a/src/backend/InvenTree/order/templates/order/order_base.html b/src/backend/InvenTree/order/templates/order/order_base.html index b02aafa19b..77e044120b 100644 --- a/src/backend/InvenTree/order/templates/order/order_base.html +++ b/src/backend/InvenTree/order/templates/order/order_base.html @@ -122,7 +122,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Order Status" %} - {% status_label 'purchase_order' order.status %} + {% display_status_label 'purchase_order' order.status_custom_key order.status %} {% if order.is_overdue %} {% trans "Overdue" %} {% endif %} diff --git a/src/backend/InvenTree/order/templates/order/return_order_base.html b/src/backend/InvenTree/order/templates/order/return_order_base.html index 494701abf1..15755c4199 100644 --- a/src/backend/InvenTree/order/templates/order/return_order_base.html +++ b/src/backend/InvenTree/order/templates/order/return_order_base.html @@ -115,7 +115,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Order Status" %} - {% status_label 'return_order' order.status %} + {% display_status_label 'return_order' order.status_custom_key order.status %} {% if order.is_overdue %} {% trans "Overdue" %} {% endif %} diff --git a/src/backend/InvenTree/order/templates/order/sales_order_base.html b/src/backend/InvenTree/order/templates/order/sales_order_base.html index c8d0179aa1..987b2e49d2 100644 --- a/src/backend/InvenTree/order/templates/order/sales_order_base.html +++ b/src/backend/InvenTree/order/templates/order/sales_order_base.html @@ -124,7 +124,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Order Status" %} - {% status_label 'sales_order' order.status %} + {% display_status_label 'sales_order' order.status_custom_key order.status %} {% if order.is_overdue %} {% trans "Overdue" %} {% endif %} diff --git a/src/backend/InvenTree/plugin/base/label/test_label_mixin.py b/src/backend/InvenTree/plugin/base/label/test_label_mixin.py index 5845163e63..c95fb4036b 100644 --- a/src/backend/InvenTree/plugin/base/label/test_label_mixin.py +++ b/src/backend/InvenTree/plugin/base/label/test_label_mixin.py @@ -125,6 +125,7 @@ class LabelMixinTests(PrintTestMixins, InvenTreeAPITestCase): self.assertGreater(len(plugins), 0) plugin = registry.get_plugin('samplelabelprinter') + self.assertIsNotNone(plugin) config = plugin.plugin_config() # Ensure that the plugin is not active diff --git a/src/backend/InvenTree/report/tests.py b/src/backend/InvenTree/report/tests.py index 8f05fa0041..e534a3ab39 100644 --- a/src/backend/InvenTree/report/tests.py +++ b/src/backend/InvenTree/report/tests.py @@ -491,7 +491,10 @@ class PrintTestMixins: def do_activate_plugin(self): """Activate the 'samplelabel' plugin.""" - config = registry.get_plugin(self.plugin_ref).plugin_config() + plugin = registry.get_plugin(self.plugin_ref) + self.assertIsNotNone(plugin) + config = plugin.plugin_config() + self.assertIsNotNone(config) config.active = True config.save() diff --git a/src/backend/InvenTree/stock/admin.py b/src/backend/InvenTree/stock/admin.py index ced26f60fa..cd1bffab79 100644 --- a/src/backend/InvenTree/stock/admin.py +++ b/src/backend/InvenTree/stock/admin.py @@ -142,6 +142,7 @@ class StockItemResource(InvenTreeResource): 'barcode_hash', 'barcode_data', 'owner', + 'status_custom_key', ] id = Field( diff --git a/src/backend/InvenTree/stock/migrations/0113_stockitem_status_custom_key_and_more.py b/src/backend/InvenTree/stock/migrations/0113_stockitem_status_custom_key_and_more.py new file mode 100644 index 0000000000..5b9bc7e8d6 --- /dev/null +++ b/src/backend/InvenTree/stock/migrations/0113_stockitem_status_custom_key_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 4.2.14 on 2024-08-07 22:40 + +import django.core.validators +from django.db import migrations + +import generic.states +import generic.states.fields +import InvenTree.status_codes + + +class Migration(migrations.Migration): + + dependencies = [ + ("stock", "0112_alter_stocklocation_custom_icon_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="stockitem", + name="status_custom_key", + field=generic.states.fields.ExtraInvenTreeCustomStatusModelField( + blank=True, + default=None, + help_text="Additional status information for this item", + null=True, + verbose_name="Custom status key", + ), + ), + migrations.AlterField( + model_name="stockitem", + name="status", + field=generic.states.fields.InvenTreeCustomStatusModelField( + choices=InvenTree.status_codes.StockStatus.items(), + default=10, + validators=[django.core.validators.MinValueValidator(0)], + ), + ), + ] diff --git a/src/backend/InvenTree/stock/models.py b/src/backend/InvenTree/stock/models.py index 3008f77970..e0482795d5 100644 --- a/src/backend/InvenTree/stock/models.py +++ b/src/backend/InvenTree/stock/models.py @@ -37,13 +37,18 @@ from build import models as BuildModels from common.icons import validate_icon from common.settings import get_global_setting from company import models as CompanyModels +from generic.states.fields import InvenTreeCustomStatusModelField from InvenTree.fields import InvenTreeModelMoneyField, InvenTreeURLField -from order.status_codes import SalesOrderStatusGroups +from InvenTree.status_codes import ( + SalesOrderStatusGroups, + StockHistoryCode, + StockStatus, + StockStatusGroups, +) from part import models as PartModels from plugin.events import trigger_event from stock import models as StockModels from stock.generators import generate_batch_code -from stock.status_codes import StockHistoryCode, StockStatus, StockStatusGroups from users.models import Owner logger = logging.getLogger('inventree') @@ -940,7 +945,7 @@ class StockItem( help_text=_('Delete this Stock Item when stock is depleted'), ) - status = models.PositiveIntegerField( + status = InvenTreeCustomStatusModelField( default=StockStatus.OK.value, choices=StockStatus.items(), validators=[MinValueValidator(0)], diff --git a/src/backend/InvenTree/stock/serializers.py b/src/backend/InvenTree/stock/serializers.py index 8f83b59751..58ed3a2471 100644 --- a/src/backend/InvenTree/stock/serializers.py +++ b/src/backend/InvenTree/stock/serializers.py @@ -27,6 +27,7 @@ import part.serializers as part_serializers import stock.filters import stock.status_codes from common.settings import get_global_setting +from generic.states.fields import InvenTreeCustomStatusSerializerMixin from importer.mixins import DataImportExportSerializerMixin from importer.registry import register_importer from InvenTree.serializers import InvenTreeCurrencySerializer, InvenTreeDecimalField @@ -326,7 +327,9 @@ class StockItemSerializerBrief( @register_importer() class StockItemSerializer( - DataImportExportSerializerMixin, InvenTree.serializers.InvenTreeTagModelSerializer + DataImportExportSerializerMixin, + InvenTreeCustomStatusSerializerMixin, + InvenTree.serializers.InvenTreeTagModelSerializer, ): """Serializer for a StockItem. @@ -373,6 +376,7 @@ class StockItemSerializer( 'serial', 'status', 'status_text', + 'status_custom_key', 'stocktake_date', 'supplier_part', 'sku', diff --git a/src/backend/InvenTree/stock/status_codes.py b/src/backend/InvenTree/stock/status_codes.py index 3c646bc455..d59d622569 100644 --- a/src/backend/InvenTree/stock/status_codes.py +++ b/src/backend/InvenTree/stock/status_codes.py @@ -2,24 +2,28 @@ from django.utils.translation import gettext_lazy as _ -from generic.states import StatusCode +from generic.states import ColorEnum, StatusCode class StockStatus(StatusCode): """Status codes for Stock.""" - OK = 10, _('OK'), 'success' # Item is OK - ATTENTION = 50, _('Attention needed'), 'warning' # Item requires attention - DAMAGED = 55, _('Damaged'), 'warning' # Item is damaged - DESTROYED = 60, _('Destroyed'), 'danger' # Item is destroyed - REJECTED = 65, _('Rejected'), 'danger' # Item is rejected - LOST = 70, _('Lost'), 'dark' # Item has been lost + OK = 10, _('OK'), ColorEnum.success # Item is OK + ATTENTION = 50, _('Attention needed'), ColorEnum.warning # Item requires attention + DAMAGED = 55, _('Damaged'), ColorEnum.warning # Item is damaged + DESTROYED = 60, _('Destroyed'), ColorEnum.danger # Item is destroyed + REJECTED = 65, _('Rejected'), ColorEnum.danger # Item is rejected + LOST = 70, _('Lost'), ColorEnum.dark # Item has been lost QUARANTINED = ( 75, _('Quarantined'), - 'info', + ColorEnum.info, ) # Item has been quarantined and is unavailable - RETURNED = 85, _('Returned'), 'warning' # Item has been returned from a customer + RETURNED = ( + 85, + _('Returned'), + ColorEnum.warning, + ) # Item has been returned from a customer class StockStatusGroups: diff --git a/src/backend/InvenTree/stock/templates/stock/item_base.html b/src/backend/InvenTree/stock/templates/stock/item_base.html index fac0adf14d..8550bc9419 100644 --- a/src/backend/InvenTree/stock/templates/stock/item_base.html +++ b/src/backend/InvenTree/stock/templates/stock/item_base.html @@ -425,7 +425,7 @@ {% trans "Status" %} - {% status_label 'stock' item.status %} + {% display_status_label 'stock' item.status_custom_key item.status %} {% if item.expiry_date %} diff --git a/src/backend/InvenTree/stock/test_api.py b/src/backend/InvenTree/stock/test_api.py index 61a8a43ba7..af73fa1b73 100644 --- a/src/backend/InvenTree/stock/test_api.py +++ b/src/backend/InvenTree/stock/test_api.py @@ -7,6 +7,7 @@ from datetime import datetime, timedelta from enum import IntEnum import django.http +from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from django.urls import reverse @@ -17,7 +18,7 @@ from rest_framework import status import build.models import company.models import part.models -from common.models import InvenTreeSetting +from common.models import InvenTreeCustomUserStateModel, InvenTreeSetting from InvenTree.unit_test import InvenTreeAPITestCase from part.models import Part, PartTestTemplate from stock.models import ( @@ -925,6 +926,100 @@ class StockItemListTest(StockAPITestCase): ) +class CustomStockItemStatusTest(StockAPITestCase): + """Tests for custom stock item statuses.""" + + list_url = reverse('api-stock-list') + + def setUp(self): + """Setup for all tests.""" + super().setUp() + self.status = InvenTreeCustomUserStateModel.objects.create( + key=11, + name='OK - advanced', + label='OK - adv.', + color='secondary', + logical_key=10, + model=ContentType.objects.get(model='stockitem'), + reference_status='StockStatus', + ) + self.status2 = InvenTreeCustomUserStateModel.objects.create( + key=51, + name='attention 2', + label='attention 2', + color='secondary', + logical_key=50, + model=ContentType.objects.get(model='stockitem'), + reference_status='StockStatus', + ) + + def test_custom_status(self): + """Tests interaction with states.""" + # Create a stock item with the custom status code via the API + response = self.post( + self.list_url, + { + 'name': 'Test Type 1', + 'description': 'Test desc 1', + 'quantity': 1, + 'part': 1, + 'status_custom_key': self.status.key, + }, + expected_code=201, + ) + self.assertEqual(response.data['status'], self.status.logical_key) + self.assertEqual(response.data['status_custom_key'], self.status.key) + pk = response.data['pk'] + + # Update the stock item with another custom status code via the API + response = self.patch( + reverse('api-stock-detail', kwargs={'pk': pk}), + {'status_custom_key': self.status2.key}, + expected_code=200, + ) + self.assertEqual(response.data['status'], self.status2.logical_key) + self.assertEqual(response.data['status_custom_key'], self.status2.key) + + # Try if status_custom_key is rewrite with status bying set + response = self.patch( + reverse('api-stock-detail', kwargs={'pk': pk}), + {'status': self.status.logical_key}, + expected_code=200, + ) + self.assertEqual(response.data['status'], self.status.logical_key) + self.assertEqual(response.data['status_custom_key'], self.status.logical_key) + + # Create a stock item with a normal status code via the API + response = self.post( + self.list_url, + { + 'name': 'Test Type 1', + 'description': 'Test desc 1', + 'quantity': 1, + 'part': 1, + 'status_key': self.status.key, + }, + expected_code=201, + ) + self.assertEqual(response.data['status'], self.status.logical_key) + self.assertEqual(response.data['status_custom_key'], self.status.logical_key) + + def test_options(self): + """Test the StockItem OPTIONS endpoint to contain custom StockStatuses.""" + response = self.options(self.list_url) + + self.assertEqual(response.status_code, 200) + + # Check that the response contains the custom StockStatuses + actions = response.data['actions']['POST'] + self.assertIn('status_custom_key', actions) + status_custom_key = actions['status_custom_key'] + self.assertEqual(len(status_custom_key['choices']), 10) + status = status_custom_key['choices'][1] + self.assertEqual(status['value'], self.status.key) + self.assertEqual(status['display_name'], self.status.label) + + class StockItemTest(StockAPITestCase): """Series of API tests for the StockItem API.""" diff --git a/src/backend/InvenTree/templates/js/translated/build.js b/src/backend/InvenTree/templates/js/translated/build.js index ba5b7d58a4..58792bd479 100644 --- a/src/backend/InvenTree/templates/js/translated/build.js +++ b/src/backend/InvenTree/templates/js/translated/build.js @@ -615,7 +615,7 @@ function completeBuildOutputs(build_id, outputs, options={}) { method: 'POST', preFormContent: html, fields: { - status: {}, + status_custom_key: {}, location: { filters: { structural: false, @@ -644,7 +644,7 @@ function completeBuildOutputs(build_id, outputs, options={}) { // Extract data elements from the form var data = { outputs: [], - status: getFormFieldValue('status', {}, opts), + status_custom_key: getFormFieldValue('status_custom_key', {}, opts), location: getFormFieldValue('location', {}, opts), notes: getFormFieldValue('notes', {}, opts), accept_incomplete_allocation: getFormFieldValue('accept_incomplete_allocation', {type: 'boolean'}, opts), @@ -1153,7 +1153,7 @@ function loadBuildOrderAllocationTable(table, options={}) { if (row.build_detail) { html += `- ${row.build_detail.title}`; - html += buildStatusDisplay(row.build_detail.status, { + html += buildStatusDisplay(row.build_detail.status_custom_key, { classes: 'float-right', }); } @@ -1556,7 +1556,7 @@ function loadBuildOutputTable(build_info, options={}) { text += ` ({% trans "Batch" %}: ${row.batch})`; } - text += stockStatusDisplay(row.status, {classes: 'float-right'}); + text += stockStatusDisplay(row.status_custom_key, {classes: 'float-right'}); return text; } @@ -2362,7 +2362,7 @@ function loadBuildTable(table, options) { } }, { - field: 'status', + field: 'status_custom_key', title: '{% trans "Status" %}', sortable: true, formatter: function(value) { diff --git a/src/backend/InvenTree/templates/js/translated/part.js b/src/backend/InvenTree/templates/js/translated/part.js index 1407f7644a..9080b6b27d 100644 --- a/src/backend/InvenTree/templates/js/translated/part.js +++ b/src/backend/InvenTree/templates/js/translated/part.js @@ -1761,7 +1761,7 @@ function loadPartPurchaseOrderTable(table, part_id, options={}) { var html = renderLink(order.reference, `/order/purchase-order/${order.pk}/`); html += purchaseOrderStatusDisplay( - order.status, + order.status_custom_key, { classes: 'float-right', } diff --git a/src/backend/InvenTree/templates/js/translated/purchase_order.js b/src/backend/InvenTree/templates/js/translated/purchase_order.js index 33f3f24f2b..d99223256c 100644 --- a/src/backend/InvenTree/templates/js/translated/purchase_order.js +++ b/src/backend/InvenTree/templates/js/translated/purchase_order.js @@ -1788,12 +1788,12 @@ function loadPurchaseOrderTable(table, options) { } }, { - field: 'status', + field: 'status_custom_key', title: '{% trans "Status" %}', switchable: true, sortable: true, formatter: function(value, row) { - return purchaseOrderStatusDisplay(row.status); + return purchaseOrderStatusDisplay(row.status_custom_key); } }, { diff --git a/src/backend/InvenTree/templates/js/translated/return_order.js b/src/backend/InvenTree/templates/js/translated/return_order.js index c22330c87d..57ac610185 100644 --- a/src/backend/InvenTree/templates/js/translated/return_order.js +++ b/src/backend/InvenTree/templates/js/translated/return_order.js @@ -326,10 +326,10 @@ function loadReturnOrderTable(table, options={}) { }, { sortable: true, - field: 'status', + field: 'status_custom_key', title: '{% trans "Status" %}', formatter: function(value, row) { - return returnOrderStatusDisplay(row.status); + return returnOrderStatusDisplay(row.status_custom_key); } }, { diff --git a/src/backend/InvenTree/templates/js/translated/sales_order.js b/src/backend/InvenTree/templates/js/translated/sales_order.js index 358c91b2ae..542330156d 100644 --- a/src/backend/InvenTree/templates/js/translated/sales_order.js +++ b/src/backend/InvenTree/templates/js/translated/sales_order.js @@ -851,10 +851,10 @@ function loadSalesOrderTable(table, options) { }, { sortable: true, - field: 'status', + field: 'status_custom_key', title: '{% trans "Status" %}', formatter: function(value, row) { - return salesOrderStatusDisplay(row.status); + return salesOrderStatusDisplay(row.status_custom_key); } }, { diff --git a/src/backend/InvenTree/templates/js/translated/stock.js b/src/backend/InvenTree/templates/js/translated/stock.js index f9c5c2b3e3..6c21536343 100644 --- a/src/backend/InvenTree/templates/js/translated/stock.js +++ b/src/backend/InvenTree/templates/js/translated/stock.js @@ -380,7 +380,7 @@ function stockItemFields(options={}) { batch: { icon: 'fa-layer-group', }, - status: {}, + status_custom_key: {}, expiry_date: { icon: 'fa-calendar-alt', }, @@ -698,7 +698,7 @@ function assignStockToCustomer(items, options={}) { var thumbnail = thumbnailImage(part.thumbnail || part.image); - var status = stockStatusDisplay(item.status, {classes: 'float-right'}); + var status = stockStatusDisplay(item.status_custom_key, {classes: 'float-right'}); var quantity = ''; @@ -879,7 +879,7 @@ function mergeStockItems(items, options={}) { quantity = `{% trans "Quantity" %}: ${item.quantity}`; } - quantity += stockStatusDisplay(item.status, {classes: 'float-right'}); + quantity += stockStatusDisplay(item.status_custom_key, {classes: 'float-right'}); let buttons = wrapButtons( makeIconButton( @@ -1113,7 +1113,7 @@ function adjustStock(action, items, options={}) { var thumb = thumbnailImage(item.part_detail.thumbnail || item.part_detail.image); - var status = stockStatusDisplay(item.status, { + var status = stockStatusDisplay(item.status_custom_key, { classes: 'float-right' }); @@ -1922,7 +1922,8 @@ function makeStockActions(table) { } }, { - label: 'status', + + label: 'status_custom_key', icon: 'fa-info-circle icon-blue', title: '{% trans "Change stock status" %}', permission: 'stock.change', @@ -2257,7 +2258,7 @@ function loadStockTable(table, options) { columns.push(col); col = { - field: 'status', + field: 'status_custom_key', title: '{% trans "Status" %}', formatter: function(value) { return stockStatusDisplay(value); @@ -3075,11 +3076,11 @@ function loadStockTrackingTable(table, options) { } // Status information - if (details.status) { + if (details.status_custom_key) { html += `{% trans "Status" %}`; html += ''; - html += stockStatusDisplay(details.status); + html += stockStatusDisplay(details.status_custom_key); html += ''; } @@ -3200,7 +3201,7 @@ function loadInstalledInTable(table, options) { } }, { - field: 'status', + field: 'status_custom_key', title: '{% trans "Status" %}', formatter: function(value) { return stockStatusDisplay(value); @@ -3401,7 +3402,7 @@ function setStockStatus(items, options={}) { method: 'POST', preFormContent: html, fields: { - status: {}, + status_custom_key: {}, note: {}, }, processBeforeUpload: function(data) { diff --git a/src/backend/InvenTree/users/models.py b/src/backend/InvenTree/users/models.py index 1fcfc9d901..cb4af4c592 100644 --- a/src/backend/InvenTree/users/models.py +++ b/src/backend/InvenTree/users/models.py @@ -345,6 +345,7 @@ class RuleSet(models.Model): 'common_projectcode', 'common_webhookendpoint', 'common_webhookmessage', + 'common_inventreecustomuserstatemodel', 'users_owner', # Third-party tables 'error_report_error', diff --git a/src/frontend/src/components/render/Build.tsx b/src/frontend/src/components/render/Build.tsx index 90ddbf6cc3..5a8687ba7e 100644 --- a/src/frontend/src/components/render/Build.tsx +++ b/src/frontend/src/components/render/Build.tsx @@ -19,7 +19,7 @@ export function RenderBuildOrder( primary={instance.reference} secondary={instance.title} suffix={StatusRenderer({ - status: instance.status, + status: instance.status_custom_key, type: ModelType.build })} image={instance.part_detail?.thumbnail || instance.part_detail?.image} @@ -39,7 +39,7 @@ export function RenderBuildLine({ primary={instance.part_detail.full_name} secondary={instance.quantity} suffix={StatusRenderer({ - status: instance.status, + status: instance.status_custom_key, type: ModelType.build })} image={instance.part_detail.thumbnail || instance.part_detail.image} diff --git a/src/frontend/src/components/render/Generic.tsx b/src/frontend/src/components/render/Generic.tsx index e201ee1fc0..3d04f990df 100644 --- a/src/frontend/src/components/render/Generic.tsx +++ b/src/frontend/src/components/render/Generic.tsx @@ -15,6 +15,12 @@ export function RenderProjectCode({ ); } +export function RenderContentType({ + instance +}: Readonly): ReactNode { + return instance && ; +} + export function RenderImportSession({ instance }: { diff --git a/src/frontend/src/components/render/Instance.tsx b/src/frontend/src/components/render/Instance.tsx index 5938eb34ef..c2df42a7d3 100644 --- a/src/frontend/src/components/render/Instance.tsx +++ b/src/frontend/src/components/render/Instance.tsx @@ -16,7 +16,11 @@ import { RenderManufacturerPart, RenderSupplierPart } from './Company'; -import { RenderImportSession, RenderProjectCode } from './Generic'; +import { + RenderContentType, + RenderImportSession, + RenderProjectCode +} from './Generic'; import { ModelInformationDict } from './ModelType'; import { RenderPurchaseOrder, @@ -87,7 +91,8 @@ const RendererLookup: EnumDictionary< [ModelType.importsession]: RenderImportSession, [ModelType.reporttemplate]: RenderReportTemplate, [ModelType.labeltemplate]: RenderLabelTemplate, - [ModelType.pluginconfig]: RenderPlugin + [ModelType.pluginconfig]: RenderPlugin, + [ModelType.contenttype]: RenderContentType }; export type RenderInstanceProps = { diff --git a/src/frontend/src/components/render/ModelType.tsx b/src/frontend/src/components/render/ModelType.tsx index ef30cfa0c2..20b5fa1bb7 100644 --- a/src/frontend/src/components/render/ModelType.tsx +++ b/src/frontend/src/components/render/ModelType.tsx @@ -241,6 +241,11 @@ export const ModelInformationDict: ModelDict = { url_overview: '/pluginconfig', url_detail: '/pluginconfig/:pk/', api_endpoint: ApiEndpoints.plugin_list + }, + contenttype: { + label: t`Content Type`, + label_multiple: t`Content Types`, + api_endpoint: ApiEndpoints.content_type_list } }; diff --git a/src/frontend/src/components/render/Order.tsx b/src/frontend/src/components/render/Order.tsx index 416f45f1fd..72f5544f4f 100644 --- a/src/frontend/src/components/render/Order.tsx +++ b/src/frontend/src/components/render/Order.tsx @@ -21,7 +21,7 @@ export function RenderPurchaseOrder( primary={instance.reference} secondary={instance.description} suffix={StatusRenderer({ - status: instance.status, + status: instance.status_custom_key, type: ModelType.purchaseorder })} image={supplier.thumnbnail || supplier.image} @@ -49,7 +49,7 @@ export function RenderReturnOrder( primary={instance.reference} secondary={instance.description} suffix={StatusRenderer({ - status: instance.status, + status: instance.status_custom_key, type: ModelType.returnorder })} image={customer.thumnbnail || customer.image} @@ -94,7 +94,7 @@ export function RenderSalesOrder( primary={instance.reference} secondary={instance.description} suffix={StatusRenderer({ - status: instance.status, + status: instance.status_custom_key, type: ModelType.salesorder })} image={customer.thumnbnail || customer.image} diff --git a/src/frontend/src/enums/ApiEndpoints.tsx b/src/frontend/src/enums/ApiEndpoints.tsx index a7221d62b7..740b73336e 100644 --- a/src/frontend/src/enums/ApiEndpoints.tsx +++ b/src/frontend/src/enums/ApiEndpoints.tsx @@ -42,11 +42,13 @@ export enum ApiEndpoints { generate_barcode = 'barcode/generate/', news = 'news/', global_status = 'generic/status/', + custom_state_list = 'generic/status/custom/', version = 'version/', license = 'license/', sso_providers = 'auth/providers/', group_list = 'user/group/', owner_list = 'user/owner/', + content_type_list = 'contenttype/', icons = 'icons/', // Data import endpoints diff --git a/src/frontend/src/enums/ModelType.tsx b/src/frontend/src/enums/ModelType.tsx index f20e3f1ec6..15d36d2d36 100644 --- a/src/frontend/src/enums/ModelType.tsx +++ b/src/frontend/src/enums/ModelType.tsx @@ -31,5 +31,6 @@ export enum ModelType { group = 'group', reporttemplate = 'reporttemplate', labeltemplate = 'labeltemplate', - pluginconfig = 'pluginconfig' + pluginconfig = 'pluginconfig', + contenttype = 'contenttype' } diff --git a/src/frontend/src/forms/BuildForms.tsx b/src/frontend/src/forms/BuildForms.tsx index 1590c4a55b..1b6a730191 100644 --- a/src/frontend/src/forms/BuildForms.tsx +++ b/src/frontend/src/forms/BuildForms.tsx @@ -301,7 +301,7 @@ export function useCompleteBuildOutputsForm({ }; }) }, - status: {}, + status_custom_key: {}, location: { filters: { structural: false diff --git a/src/frontend/src/forms/CommonForms.tsx b/src/frontend/src/forms/CommonForms.tsx index 10ce0a082e..40c060b92d 100644 --- a/src/frontend/src/forms/CommonForms.tsx +++ b/src/frontend/src/forms/CommonForms.tsx @@ -12,6 +12,18 @@ export function projectCodeFields(): ApiFormFieldSet { }; } +export function customStateFields(): ApiFormFieldSet { + return { + key: {}, + name: {}, + label: {}, + color: {}, + logical_key: {}, + model: {}, + reference_status: {} + }; +} + export function customUnitsFields(): ApiFormFieldSet { return { name: {}, diff --git a/src/frontend/src/forms/StockForms.tsx b/src/frontend/src/forms/StockForms.tsx index 8688680579..0577233192 100644 --- a/src/frontend/src/forms/StockForms.tsx +++ b/src/frontend/src/forms/StockForms.tsx @@ -138,7 +138,7 @@ export function useStockFields({ value: batchCode, onValueChange: (value) => setBatchCode(value) }, - status: {}, + status_custom_key: {}, expiry_date: { // TODO: icon }, @@ -620,7 +620,7 @@ function stockChangeStatusFields(items: any[]): ApiFormFieldSet { }, headers: [t`Part`, t`Location`, t`In Stock`, t`Actions`] }, - status: {}, + status_custom_key: {}, note: {} }; diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx index 91bc1d8982..8f84261329 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx @@ -68,6 +68,10 @@ const ProjectCodeTable = Loadable( lazy(() => import('../../../../tables/settings/ProjectCodeTable')) ); +const CustomStateTable = Loadable( + lazy(() => import('../../../../tables/settings/CustomStateTable')) +); + const CustomUnitsTable = Loadable( lazy(() => import('../../../../tables/settings/CustomUnitsTable')) ); @@ -135,6 +139,12 @@ export default function AdminCenter() { ) }, + { + name: 'customstates', + label: t`Custom States`, + icon: , + content: + }, { name: 'customunits', label: t`Custom Units`, diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx index ff0f30a8c2..1348ff1e00 100644 --- a/src/frontend/src/pages/build/BuildDetail.tsx +++ b/src/frontend/src/pages/build/BuildDetail.tsx @@ -526,7 +526,7 @@ export default function BuildDetail() { ? [] : [ diff --git a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx index a2eacb9d7b..f1a6076ccd 100644 --- a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx +++ b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx @@ -459,7 +459,7 @@ export default function PurchaseOrderDetail() { ? [] : [ diff --git a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx index f623f35857..2cfb1a47a5 100644 --- a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx +++ b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx @@ -300,7 +300,7 @@ export default function ReturnOrderDetail() { ? [] : [ diff --git a/src/frontend/src/pages/sales/SalesOrderDetail.tsx b/src/frontend/src/pages/sales/SalesOrderDetail.tsx index 73c9173545..e2306df852 100644 --- a/src/frontend/src/pages/sales/SalesOrderDetail.tsx +++ b/src/frontend/src/pages/sales/SalesOrderDetail.tsx @@ -498,7 +498,7 @@ export default function SalesOrderDetail() { ? [] : [ , { + return [ + { + accessor: 'name', + sortable: true + }, + { + accessor: 'label', + title: t`Display Name`, + sortable: true + }, + { + accessor: 'color' + }, + { + accessor: 'key', + sortable: true + }, + { + accessor: 'logical_key', + sortable: true + }, + { + accessor: 'model_name', + title: t`Model`, + sortable: true + }, + { + accessor: 'reference_status', + title: t`Status`, + sortable: true + } + ]; + }, []); + + const newCustomState = useCreateApiFormModal({ + url: ApiEndpoints.custom_state_list, + title: t`Add State`, + fields: customStateFields(), + table: table + }); + + const [selectedCustomState, setSelectedCustomState] = useState< + number | undefined + >(undefined); + + const editCustomState = useEditApiFormModal({ + url: ApiEndpoints.custom_state_list, + pk: selectedCustomState, + title: t`Edit State`, + fields: customStateFields(), + table: table + }); + + const deleteCustomState = useDeleteApiFormModal({ + url: ApiEndpoints.custom_state_list, + pk: selectedCustomState, + title: t`Delete State`, + table: table + }); + + const rowActions = useCallback( + (record: any): RowAction[] => { + return [ + RowEditAction({ + hidden: !user.hasChangeRole(UserRoles.admin), + onClick: () => { + setSelectedCustomState(record.pk); + editCustomState.open(); + } + }), + RowDeleteAction({ + hidden: !user.hasDeleteRole(UserRoles.admin), + onClick: () => { + setSelectedCustomState(record.pk); + deleteCustomState.open(); + } + }) + ]; + }, + [user] + ); + + const tableActions = useMemo(() => { + return [ + newCustomState.open()} + tooltip={t`Add state`} + /> + ]; + }, []); + + return ( + <> + {newCustomState.modal} + {editCustomState.modal} + {deleteCustomState.modal} + + + ); +} From 725181be5fe092f6979222be5fdf22256ef80e9d Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Thu, 22 Aug 2024 01:43:27 +0200 Subject: [PATCH 02/21] [PUI] fix missing key in currency table (#7953) --- src/frontend/src/tables/settings/CurrencyTable.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/src/tables/settings/CurrencyTable.tsx b/src/frontend/src/tables/settings/CurrencyTable.tsx index 59dd8d4cdd..e5ed7533c2 100644 --- a/src/frontend/src/tables/settings/CurrencyTable.tsx +++ b/src/frontend/src/tables/settings/CurrencyTable.tsx @@ -66,6 +66,7 @@ export default function CurrencyTable() { tableState={table} columns={columns} props={{ + idAccessor: 'currency', tableActions: tableActions, dataFormatter: (data: any) => { let rates = data.exchange_rates ?? {}; From b0c7a1aed52e1cb98ae7c7c3b74707ea275df71c Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Thu, 22 Aug 2024 03:01:09 +0200 Subject: [PATCH 03/21] [PUI] Add Link/Unlink Barcode action (#7939) * Add Link/Unlink Barcode action Fixes #7920 * remove unneeded imports * remove duplication * simplify * add testing * refactor type * wait for reload to add coverage * Add warning if custom barcode is used --- .../src/components/items/ActionDropdown.tsx | 106 +++++++++++------- src/frontend/src/components/items/QRCode.tsx | 81 +++++++++++-- src/frontend/src/enums/ApiEndpoints.tsx | 2 + src/frontend/src/pages/build/BuildDetail.tsx | 23 +--- .../src/pages/company/SupplierPartDetail.tsx | 28 +---- src/frontend/src/pages/part/PartDetail.tsx | 24 +--- .../pages/purchasing/PurchaseOrderDetail.tsx | 23 +--- .../src/pages/sales/ReturnOrderDetail.tsx | 23 +--- .../src/pages/sales/SalesOrderDetail.tsx | 23 +--- .../src/pages/stock/LocationDetail.tsx | 17 +-- src/frontend/src/pages/stock/StockDetail.tsx | 26 +---- src/frontend/tests/pages/pui_orders.spec.ts | 27 +++++ 12 files changed, 199 insertions(+), 204 deletions(-) diff --git a/src/frontend/src/components/items/ActionDropdown.tsx b/src/frontend/src/components/items/ActionDropdown.tsx index 2e8a2df425..48603c880c 100644 --- a/src/frontend/src/components/items/ActionDropdown.tsx +++ b/src/frontend/src/components/items/ActionDropdown.tsx @@ -20,7 +20,7 @@ import { ReactNode, useMemo } from 'react'; import { ModelType } from '../../enums/ModelType'; import { identifierString } from '../../functions/conversion'; import { InvenTreeIcon } from '../../functions/icons'; -import { InvenTreeQRCode } from './QRCode'; +import { InvenTreeQRCode, QRCodeLink, QRCodeUnlink } from './QRCode'; export type ActionDropdownItem = { icon?: ReactNode; @@ -112,69 +112,91 @@ export function ActionDropdown({ // Dropdown menu for barcode actions export function BarcodeActionDropdown({ - actions -}: { - actions: ActionDropdownItem[]; -}) { + model, + pk, + hash = null, + actions = [], + perm: permission = true +}: Readonly<{ + model: ModelType; + pk: number; + hash?: boolean | null; + actions?: ActionDropdownItem[]; + perm?: boolean; +}>) { + const hidden = hash === null; + const prop = { model, pk, hash }; return ( } - actions={actions} + actions={[ + GeneralBarcodeAction({ + mdl_prop: prop, + title: t`View`, + icon: , + tooltip: t`View barcode`, + ChildItem: InvenTreeQRCode + }), + GeneralBarcodeAction({ + hidden: hidden || hash || !permission, + mdl_prop: prop, + title: t`Link Barcode`, + icon: , + tooltip: t`Link a custom barcode to this item`, + ChildItem: QRCodeLink + }), + GeneralBarcodeAction({ + hidden: hidden || !hash || !permission, + mdl_prop: prop, + title: t`Unlink Barcode`, + icon: , + tooltip: t`Unlink custom barcode`, + ChildItem: QRCodeUnlink + }), + ...actions + ]} /> ); } -// Common action button for viewing a barcode -export function ViewBarcodeAction({ - hidden = false, - model, - pk -}: { - hidden?: boolean; +export type QrCodeType = { model: ModelType; pk: number; + hash?: boolean | null; +}; + +function GeneralBarcodeAction({ + hidden = false, + mdl_prop, + title, + icon, + tooltip, + ChildItem +}: { + hidden?: boolean; + mdl_prop: QrCodeType; + title: string; + icon: ReactNode; + tooltip: string; + ChildItem: any; }): ActionDropdownItem { const onClick = () => { modals.open({ - title: t`View Barcode`, - children: + title: title, + children: }); }; return { - icon: , - name: t`View`, - tooltip: t`View barcode`, + icon: icon, + name: title, + tooltip: tooltip, onClick: onClick, hidden: hidden }; } -// Common action button for linking a custom barcode -export function LinkBarcodeAction( - props: ActionDropdownItem -): ActionDropdownItem { - return { - ...props, - icon: , - name: t`Link Barcode`, - tooltip: t`Link custom barcode` - }; -} - -// Common action button for un-linking a custom barcode -export function UnlinkBarcodeAction( - props: ActionDropdownItem -): ActionDropdownItem { - return { - ...props, - icon: , - name: t`Unlink Barcode`, - tooltip: t`Unlink custom barcode` - }; -} - // Common action button for editing an item export function EditItemAction(props: ActionDropdownItem): ActionDropdownItem { return { diff --git a/src/frontend/src/components/items/QRCode.tsx b/src/frontend/src/components/items/QRCode.tsx index 1077692314..8038ff8c23 100644 --- a/src/frontend/src/components/items/QRCode.tsx +++ b/src/frontend/src/components/items/QRCode.tsx @@ -1,24 +1,28 @@ import { Trans, t } from '@lingui/macro'; import { + Alert, Box, + Button, Code, Group, Image, Select, Skeleton, Stack, - Text + Text, + TextInput } from '@mantine/core'; +import { modals } from '@mantine/modals'; import { useQuery } from '@tanstack/react-query'; import QR from 'qrcode'; import { useEffect, useMemo, useState } from 'react'; import { api } from '../../App'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; -import { ModelType } from '../../enums/ModelType'; import { apiUrl } from '../../states/ApiState'; import { useGlobalSettingsState } from '../../states/SettingsState'; import { CopyButton } from '../buttons/CopyButton'; +import { QrCodeType } from './ActionDropdown'; type QRCodeProps = { ecl?: 'L' | 'M' | 'Q' | 'H'; @@ -51,15 +55,13 @@ export const QRCode = ({ data, ecl = 'Q', margin = 1 }: QRCodeProps) => { }; type InvenTreeQRCodeProps = { - model: ModelType; - pk: number; + mdl_prop: QrCodeType; showEclSelector?: boolean; } & Omit; export const InvenTreeQRCode = ({ + mdl_prop, showEclSelector = true, - model, - pk, ecl: eclProp = 'Q', ...props }: InvenTreeQRCodeProps) => { @@ -71,11 +73,11 @@ export const InvenTreeQRCode = ({ }, [eclProp]); const { data } = useQuery({ - queryKey: ['qr-code', model, pk], + queryKey: ['qr-code', mdl_prop.model, mdl_prop.pk], queryFn: async () => { const res = await api.post(apiUrl(ApiEndpoints.generate_barcode), { - model, - pk + model: mdl_prop.model, + pk: mdl_prop.pk }); return res.data?.barcode as string; @@ -94,6 +96,15 @@ export const InvenTreeQRCode = ({ return ( + {mdl_prop.hash ? ( + + + A custom barcode is registered for this item. The shown code is not + that custom barcode. + + + ) : null} + {data && settings.getSetting('BARCODE_SHOW_TEXT', 'false') && ( @@ -128,3 +139,55 @@ export const InvenTreeQRCode = ({ ); }; + +export const QRCodeLink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => { + const [barcode, setBarcode] = useState(''); + + function linkBarcode() { + api + .post(apiUrl(ApiEndpoints.barcode_link), { + [mdl_prop.model]: mdl_prop.pk, + barcode: barcode + }) + .then((response) => { + modals.closeAll(); + location.reload(); + }); + } + return ( + + setBarcode(event.currentTarget.value)} + placeholder={t`Scan barcode data here using barcode scanner`} + /> + + + ); +}; + +export const QRCodeUnlink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => { + function unlinkBarcode() { + api + .post(apiUrl(ApiEndpoints.barcode_unlink), { + [mdl_prop.model]: mdl_prop.pk + }) + .then((response) => { + modals.closeAll(); + location.reload(); + }); + } + return ( + + + This will remove the link to the associated barcode + + + + ); +}; diff --git a/src/frontend/src/enums/ApiEndpoints.tsx b/src/frontend/src/enums/ApiEndpoints.tsx index 740b73336e..1908a59577 100644 --- a/src/frontend/src/enums/ApiEndpoints.tsx +++ b/src/frontend/src/enums/ApiEndpoints.tsx @@ -39,6 +39,8 @@ export enum ApiEndpoints { settings_global_list = 'settings/global/', settings_user_list = 'settings/user/', barcode = 'barcode/', + barcode_link = 'barcode/link/', + barcode_unlink = 'barcode/unlink/', generate_barcode = 'barcode/generate/', news = 'news/', global_status = 'generic/status/', diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx index 1348ff1e00..bc9a02981f 100644 --- a/src/frontend/src/pages/build/BuildDetail.tsx +++ b/src/frontend/src/pages/build/BuildDetail.tsx @@ -30,10 +30,7 @@ import { CancelItemAction, DuplicateItemAction, EditItemAction, - HoldItemAction, - LinkBarcodeAction, - UnlinkBarcodeAction, - ViewBarcodeAction + HoldItemAction } from '../../components/items/ActionDropdown'; import InstanceDetail from '../../components/nav/InstanceDetail'; import { PageDetail } from '../../components/nav/PageDetail'; @@ -43,7 +40,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { useBuildOrderFields } from '../../forms/BuildForms'; -import { notYetImplemented } from '../../functions/notifications'; import { useCreateApiFormModal, useEditApiFormModal @@ -472,20 +468,9 @@ export default function BuildDetail() { />, , , , , , , , , , , , , , , , , location.pk ? ( , diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index 5a3f0d00e4..e787d210a4 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -27,10 +27,7 @@ import { BarcodeActionDropdown, DeleteItemAction, DuplicateItemAction, - EditItemAction, - LinkBarcodeAction, - UnlinkBarcodeAction, - ViewBarcodeAction + EditItemAction } from '../../components/items/ActionDropdown'; import { StylishText } from '../../components/items/StylishText'; import InstanceDetail from '../../components/nav/InstanceDetail'; @@ -50,7 +47,6 @@ import { useTransferStockItem } from '../../forms/StockForms'; import { InvenTreeIcon } from '../../functions/icons'; -import { notYetImplemented } from '../../functions/notifications'; import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal, @@ -477,22 +473,10 @@ export default function StockDetail() { () => [ , , { await page.getByRole('cell', { name: 'PO0013' }).click(); await page.getByRole('button', { name: 'Issue Order' }).waitFor(); +}); + +test('PUI - Purchase Orders - Barcodes', async ({ page }) => { + await doQuickLogin(page); + + await page.goto(`${baseUrl}/purchasing/purchase-order/13/detail`); + await page.getByRole('button', { name: 'Issue Order' }).waitFor(); // Display QR code await page.getByLabel('action-menu-barcode-actions').click(); await page.getByLabel('action-menu-barcode-actions-view').click(); await page.getByRole('img', { name: 'QR Code' }).waitFor(); + await page.getByRole('banner').getByRole('button').click(); + + // Link to barcode + await page.getByLabel('action-menu-barcode-actions').click(); + await page.getByLabel('action-menu-barcode-actions-link-barcode').click(); + await page.getByRole('heading', { name: 'Link Barcode' }).waitFor(); + await page + .getByPlaceholder('Scan barcode data here using') + .fill('1234567890'); + await page.getByRole('button', { name: 'Link' }).click(); + await page.getByRole('button', { name: 'Issue Order' }).waitFor(); + + // Unlink barcode + await page.getByLabel('action-menu-barcode-actions').click(); + await page.getByLabel('action-menu-barcode-actions-unlink-barcode').click(); + await page.getByRole('heading', { name: 'Unlink Barcode' }).waitFor(); + await page.getByText('This will remove the link to').waitFor(); + await page.getByRole('button', { name: 'Unlink Barcode' }).click(); + await page.waitForTimeout(500); + await page.getByRole('button', { name: 'Issue Order' }).waitFor(); }); From ca87df3c3dc37a69c9ab37de44a278d7e0861154 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 22 Aug 2024 13:50:04 +1000 Subject: [PATCH 04/21] [PUI] Test result fixes (#7956) * Prevent template adjustment * Prevent template from being edited * Fix 'attachment' field for StockItemTestResultSerializer - Allow 'null' value * Bump API version --- src/backend/InvenTree/InvenTree/api_version.py | 5 ++++- src/backend/InvenTree/stock/serializers.py | 5 ++++- src/frontend/src/forms/StockForms.tsx | 17 +++++++++++++++-- .../src/tables/build/BuildOrderTestTable.tsx | 3 ++- .../tables/stock/StockItemTestResultTable.tsx | 11 ++++++----- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 40bff36d69..181abf41c9 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,12 +1,15 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 246 +INVENTREE_API_VERSION = 247 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v247 - 2024-08-22 : https://github.com/inventree/InvenTree/pull/7956 + - Adjust "attachment" field on StockItemTestResult serializer + - Allow null values for attachment v246 - 2024-08-21 : https://github.com/inventree/InvenTree/pull/7862 - Adds custom status fields to various serializers diff --git a/src/backend/InvenTree/stock/serializers.py b/src/backend/InvenTree/stock/serializers.py index 58ed3a2471..7c80285f6f 100644 --- a/src/backend/InvenTree/stock/serializers.py +++ b/src/backend/InvenTree/stock/serializers.py @@ -239,7 +239,10 @@ class StockItemTestResultSerializer( ) attachment = InvenTree.serializers.InvenTreeAttachmentSerializerField( - required=False + required=False, + allow_null=True, + label=_('Attachment'), + help_text=_('Test result attachment'), ) def validate(self, data): diff --git a/src/frontend/src/forms/StockForms.tsx b/src/frontend/src/forms/StockForms.tsx index 0577233192..7ac947826b 100644 --- a/src/frontend/src/forms/StockForms.tsx +++ b/src/frontend/src/forms/StockForms.tsx @@ -922,10 +922,14 @@ export function stockLocationFields(): ApiFormFieldSet { // Construct a set of fields for export function useTestResultFields({ partId, - itemId + itemId, + templateId, + editTemplate = false }: { partId: number; itemId: number; + templateId: number | undefined; + editTemplate?: boolean; }): ApiFormFieldSet { // Valid field choices const [choices, setChoices] = useState([]); @@ -947,6 +951,7 @@ export function useTestResultFields({ hidden: true }, template: { + disabled: !editTemplate && !!templateId, filters: { include_inherited: true, part: partId @@ -990,5 +995,13 @@ export function useTestResultFields({ hidden: !includeTestStation } }; - }, [choices, fieldType, partId, itemId, includeTestStation]); + }, [ + choices, + editTemplate, + fieldType, + partId, + itemId, + templateId, + includeTestStation + ]); } diff --git a/src/frontend/src/tables/build/BuildOrderTestTable.tsx b/src/frontend/src/tables/build/BuildOrderTestTable.tsx index dc4145ae5c..4905945e9d 100644 --- a/src/frontend/src/tables/build/BuildOrderTestTable.tsx +++ b/src/frontend/src/tables/build/BuildOrderTestTable.tsx @@ -67,7 +67,8 @@ export default function BuildOrderTestTable({ const testResultFields: ApiFormFieldSet = useTestResultFields({ partId: partId, - itemId: selectedOutput + itemId: selectedOutput, + templateId: selectedTemplate }); const createTestResult = useCreateApiFormModal({ diff --git a/src/frontend/src/tables/stock/StockItemTestResultTable.tsx b/src/frontend/src/tables/stock/StockItemTestResultTable.tsx index fe41d0ac12..4eca85588f 100644 --- a/src/frontend/src/tables/stock/StockItemTestResultTable.tsx +++ b/src/frontend/src/tables/stock/StockItemTestResultTable.tsx @@ -238,15 +238,16 @@ export default function StockItemTestResultTable({ ]; }, [itemId]); - const resultFields: ApiFormFieldSet = useTestResultFields({ - partId: partId, - itemId: itemId - }); - const [selectedTemplate, setSelectedTemplate] = useState( undefined ); + const resultFields: ApiFormFieldSet = useTestResultFields({ + partId: partId, + itemId: itemId, + templateId: selectedTemplate + }); + const newTestModal = useCreateApiFormModal({ url: ApiEndpoints.stock_test_result_list, fields: useMemo(() => ({ ...resultFields }), [resultFields]), From 1dff94db75cfeb71c7f6576535c94aacb498d093 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 22 Aug 2024 16:08:41 +1000 Subject: [PATCH 05/21] Table borders (#7957) * Add 'editable' attribute to table column type * Add "editable" attribute for useTable hook * Add column borders to tables --- src/frontend/src/hooks/UseTable.tsx | 8 +++++++- src/frontend/src/tables/Column.tsx | 4 ++++ src/frontend/src/tables/InvenTreeTable.tsx | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/hooks/UseTable.tsx b/src/frontend/src/hooks/UseTable.tsx index b1bf2ce735..4ce0800f28 100644 --- a/src/frontend/src/hooks/UseTable.tsx +++ b/src/frontend/src/hooks/UseTable.tsx @@ -39,6 +39,8 @@ export type TableState = { records: any[]; setRecords: (records: any[]) => void; updateRecord: (record: any) => void; + editable: boolean; + setEditable: (value: boolean) => void; }; /** @@ -131,6 +133,8 @@ export function useTable(tableName: string): TableState { const [isLoading, setIsLoading] = useState(false); + const [editable, setEditable] = useState(false); + return { tableKey, refreshTable, @@ -156,6 +160,8 @@ export function useTable(tableName: string): TableState { setPage, records, setRecords, - updateRecord + updateRecord, + editable, + setEditable }; } diff --git a/src/frontend/src/tables/Column.tsx b/src/frontend/src/tables/Column.tsx index b2ea9fcccd..03366ca1fb 100644 --- a/src/frontend/src/tables/Column.tsx +++ b/src/frontend/src/tables/Column.tsx @@ -1,3 +1,5 @@ +import { ApiFormFieldType } from '../components/forms/fields/ApiFormField'; + export type TableColumnProps = { accessor?: string; // The key in the record to access title?: string; // The title of the column - Note: this may be supplied by the API, and is not required, but it can be overridden if required @@ -5,6 +7,8 @@ export type TableColumnProps = { sortable?: boolean; // Whether the column is sortable switchable?: boolean; // Whether the column is switchable hidden?: boolean; // Whether the column is hidden + editable?: boolean; // Whether the value of this column can be edited + definition?: ApiFormFieldType; // Optional field definition for the column render?: (record: T, index?: number) => any; // A custom render function filter?: any; // A custom filter function filtering?: boolean; // Whether the column is filterable diff --git a/src/frontend/src/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx index 8da06a22e1..7585a7670e 100644 --- a/src/frontend/src/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -697,6 +697,7 @@ export function InvenTreeTable({ Date: Thu, 22 Aug 2024 09:01:25 +0200 Subject: [PATCH 06/21] Add pagination (#7958) --- src/frontend/src/hooks/UseTable.tsx | 5 +++++ src/frontend/src/tables/InvenTreeTable.tsx | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/frontend/src/hooks/UseTable.tsx b/src/frontend/src/hooks/UseTable.tsx index 4ce0800f28..c44cc11d9e 100644 --- a/src/frontend/src/hooks/UseTable.tsx +++ b/src/frontend/src/hooks/UseTable.tsx @@ -36,6 +36,8 @@ export type TableState = { setRecordCount: (count: number) => void; page: number; setPage: (page: number) => void; + pageSize: number; + setPageSize: (pageSize: number) => void; records: any[]; setRecords: (records: any[]) => void; updateRecord: (record: any) => void; @@ -99,6 +101,7 @@ export function useTable(tableName: string): TableState { // Pagination data const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(25); // A list of hidden columns, saved to local storage const [hiddenColumns, setHiddenColumns] = useLocalStorage({ @@ -158,6 +161,8 @@ export function useTable(tableName: string): TableState { setRecordCount, page, setPage, + pageSize, + setPageSize, records, setRecords, updateRecord, diff --git a/src/frontend/src/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx index 7585a7670e..fa74a5f468 100644 --- a/src/frontend/src/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -55,6 +55,7 @@ import { RowAction, RowActions } from './RowActions'; import { TableSearchInput } from './Search'; const defaultPageSize: number = 25; +const PAGE_SIZES = [10, 15, 20, 25, 50, 100, 500]; /** * Set of optional properties which can be passed to an InvenTreeTable component @@ -74,7 +75,6 @@ const defaultPageSize: number = 25; * @param enableRefresh : boolean - Enable refresh actions * @param enableColumnSwitching : boolean - Enable column switching * @param enableColumnCaching : boolean - Enable caching of column names via API - * @param pageSize : number - Number of records per page * @param barcodeActions : any[] - List of barcode actions * @param tableFilters : TableFilter[] - List of custom filters * @param tableActions : any[] - List of custom action groups @@ -100,7 +100,6 @@ export type InvenTreeTableProps = { enableLabels?: boolean; enableReports?: boolean; afterBulkDelete?: () => void; - pageSize?: number; barcodeActions?: React.ReactNode[]; tableFilters?: TableFilter[]; tableActions?: React.ReactNode[]; @@ -129,7 +128,6 @@ const defaultInvenTreeTableProps: InvenTreeTableProps = { enableRefresh: true, enableSearch: true, enableSelection: false, - pageSize: defaultPageSize, defaultSortColumn: '', barcodeActions: [], tableFilters: [], @@ -360,7 +358,8 @@ export function InvenTreeTable({ // Pagination if (tableProps.enablePagination && paginate) { - let pageSize = tableProps.pageSize ?? defaultPageSize; + let pageSize = tableState.pageSize ?? defaultPageSize; + if (pageSize != tableState.pageSize) tableState.setPageSize(pageSize); queryParams.limit = pageSize; queryParams.offset = (tableState.page - 1) * pageSize; } @@ -588,6 +587,12 @@ export function InvenTreeTable({ [props.onRowClick, props.onCellClick] ); + // pagination refresth table if pageSize changes + function updatePageSize(newData: number) { + tableState.setPageSize(newData); + tableState.refreshTable(); + } + return ( <> {deleteRecords.modal} @@ -705,7 +710,7 @@ export function InvenTreeTable({ idAccessor={tableProps.idAccessor} minHeight={300} totalRecords={tableState.recordCount} - recordsPerPage={tableProps.pageSize ?? defaultPageSize} + recordsPerPage={tableState.pageSize} page={tableState.page} onPageChange={tableState.setPage} sortStatus={sortStatus} @@ -733,6 +738,8 @@ export function InvenTreeTable({ overflow: 'hidden' }) }} + recordsPerPageOptions={PAGE_SIZES} + onRecordsPerPageChange={updatePageSize} /> From cf9dcf0556bef79ef6af298e0c4075adf6ea581c Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Fri, 23 Aug 2024 01:49:57 +0200 Subject: [PATCH 07/21] [CI] Switch to using Crowdin GitHub Action (#7929) Fixes #7910 --- .github/workflows/translations.yaml | 30 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml index 0bdcd80517..308e171a98 100644 --- a/.github/workflows/translations.yaml +++ b/.github/workflows/translations.yaml @@ -13,10 +13,11 @@ permissions: contents: read jobs: - build: + synchronize-with-crowdin: runs-on: ubuntu-latest permissions: contents: write + pull-requests: write env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -39,16 +40,19 @@ jobs: apt-dependency: gettext - name: Make Translations run: invoke translate - - name: Commit files - run: | - git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config --local user.name "github-actions[bot]" - git checkout -b l10_local - git add "*.po" - git commit -m "updated translation base" - - name: Push changes - uses: ad-m/github-push-action@d91a481090679876dfc4178fef17f286781251df # pin@v0.8.0 + - name: crowdin action + uses: crowdin/github-action@6ed209d411599a981ccb978df3be9dc9b8a81699 # pin@v2 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: l10 - force: true + upload_sources: true + upload_translations: false + download_translations: true + localization_branch_name: l10_crowdin + create_pull_request: true + pull_request_title: 'New Crowdin updates' + pull_request_body: 'New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)' + pull_request_base_branch_name: 'l10' + pull_request_labels: 'translations' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} From b9b44126de0bae2c8aacc5614e8de49bf8227494 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 23 Aug 2024 11:00:20 +1000 Subject: [PATCH 08/21] Revert status fields for stock items (#7965) * Revert status fields for stock items * Fix PUI fields too * Bump API version --- src/backend/InvenTree/InvenTree/api_version.py | 5 ++++- .../common/migrations/0029_inventreecustomuserstatemodel.py | 2 +- src/backend/InvenTree/common/models.py | 2 +- src/backend/InvenTree/templates/js/translated/stock.js | 2 +- src/frontend/src/forms/StockForms.tsx | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 181abf41c9..f1df853784 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,12 +1,15 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 247 +INVENTREE_API_VERSION = 248 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v248 - 2024-08-23 : https://github.com/inventree/InvenTree/pull/7965 + - Small adjustments to labels for new custom status fields + v247 - 2024-08-22 : https://github.com/inventree/InvenTree/pull/7956 - Adjust "attachment" field on StockItemTestResult serializer - Allow null values for attachment diff --git a/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py b/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py index 7090b98279..408edf6102 100644 --- a/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py +++ b/src/backend/InvenTree/common/migrations/0029_inventreecustomuserstatemodel.py @@ -46,7 +46,7 @@ class Migration(migrations.Migration): models.CharField( help_text="Label that will be displayed in the frontend", max_length=250, - verbose_name="label", + verbose_name="Label", ), ), ( diff --git a/src/backend/InvenTree/common/models.py b/src/backend/InvenTree/common/models.py index ca3b45c9dc..93dd5d11ce 100644 --- a/src/backend/InvenTree/common/models.py +++ b/src/backend/InvenTree/common/models.py @@ -3355,7 +3355,7 @@ class InvenTreeCustomUserStateModel(models.Model): ) label = models.CharField( max_length=250, - verbose_name=_('label'), + verbose_name=_('Label'), help_text=_('Label that will be displayed in the frontend'), ) color = models.CharField( diff --git a/src/backend/InvenTree/templates/js/translated/stock.js b/src/backend/InvenTree/templates/js/translated/stock.js index 6c21536343..2e65072853 100644 --- a/src/backend/InvenTree/templates/js/translated/stock.js +++ b/src/backend/InvenTree/templates/js/translated/stock.js @@ -380,7 +380,7 @@ function stockItemFields(options={}) { batch: { icon: 'fa-layer-group', }, - status_custom_key: {}, + status: {}, expiry_date: { icon: 'fa-calendar-alt', }, diff --git a/src/frontend/src/forms/StockForms.tsx b/src/frontend/src/forms/StockForms.tsx index 7ac947826b..3ed19c8938 100644 --- a/src/frontend/src/forms/StockForms.tsx +++ b/src/frontend/src/forms/StockForms.tsx @@ -138,7 +138,7 @@ export function useStockFields({ value: batchCode, onValueChange: (value) => setBatchCode(value) }, - status_custom_key: {}, + status: {}, expiry_date: { // TODO: icon }, From 8f4929d754ca8cdcbcb87d83637c665bacd25ae4 Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Sat, 24 Aug 2024 00:28:58 +0200 Subject: [PATCH 09/21] [BUG] Order of states in schema descriptions is not stable (#7978) Fixes #7977 --- src/backend/InvenTree/InvenTree/api_version.py | 6 +++++- src/backend/InvenTree/generic/states/custom.py | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index f1df853784..f5e9237627 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,12 +1,16 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 248 +INVENTREE_API_VERSION = 249 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ + +v249 - 2024-08-23 : https://github.com/inventree/InvenTree/pull/7978 + - Sort status enums + v248 - 2024-08-23 : https://github.com/inventree/InvenTree/pull/7965 - Small adjustments to labels for new custom status fields diff --git a/src/backend/InvenTree/generic/states/custom.py b/src/backend/InvenTree/generic/states/custom.py index 2539eb550e..8fc8948c28 100644 --- a/src/backend/InvenTree/generic/states/custom.py +++ b/src/backend/InvenTree/generic/states/custom.py @@ -33,7 +33,8 @@ def state_color_mappings(): def state_reference_mappings(): """Return a list of custom user state references.""" - return [(a.__name__, a.__name__) for a in get_custom_classes(include_custom=False)] + classes = get_custom_classes(include_custom=False) + return [(a.__name__, a.__name__) for a in sorted(classes, key=lambda x: x.__name__)] def get_logical_value(value, model: str): From d647471588bf4b7cdcaa0ac4dd92a28ce4677d6a Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Sat, 24 Aug 2024 01:03:31 +0200 Subject: [PATCH 10/21] Chore: Bump python requirements (#7961) * bump requirements * lower bound on pydyf --- contrib/container/requirements.in | 1 + contrib/container/requirements.txt | 315 +++-- contrib/dev_reqs/requirements.txt | 6 +- src/backend/requirements-dev.txt | 463 ++++---- src/backend/requirements.in | 3 + src/backend/requirements.txt | 1703 ++++++++++++++-------------- 6 files changed, 1283 insertions(+), 1208 deletions(-) diff --git a/contrib/container/requirements.in b/contrib/container/requirements.in index 47968937a5..1a87893d54 100644 --- a/contrib/container/requirements.in +++ b/contrib/container/requirements.in @@ -17,6 +17,7 @@ gunicorn>=22.0.0 # LDAP required packages django-auth-ldap # Django integration for ldap auth python-ldap # LDAP auth support +django<5.0 # Force lower to match main project # Upgraded python package installer uv diff --git a/contrib/container/requirements.txt b/contrib/container/requirements.txt index f519da636b..aa209c88ba 100644 --- a/contrib/container/requirements.txt +++ b/contrib/container/requirements.txt @@ -7,14 +7,16 @@ asgiref==3.8.1 \ django==4.2.15 \ --hash=sha256:61ee4a130efb8c451ef3467c67ca99fdce400fedd768634efc86a68c18d80d30 \ --hash=sha256:c77f926b81129493961e19c0e02188f8d07c112a1162df69bfab178ae447f94a - # via django-auth-ldap + # via + # -r contrib/container/requirements.in + # django-auth-ldap django-auth-ldap==4.8.0 \ --hash=sha256:4b4b944f3c28bce362f33fb6e8db68429ed8fd8f12f0c0c4b1a4344a7ef225ce \ --hash=sha256:604250938ddc9fda619f247c7a59b0b2f06e53a7d3f46a156f28aa30dd71a738 # via -r contrib/container/requirements.in -gunicorn==22.0.0 \ - --hash=sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9 \ - --hash=sha256:4a0b436239ff76fb33f11c07a16482c521a7e09c1ce3cc293c2330afe01bec63 +gunicorn==23.0.0 \ + --hash=sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d \ + --hash=sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec # via -r contrib/container/requirements.in invoke==2.2.0 \ --hash=sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820 \ @@ -44,86 +46,74 @@ mysqlclient==2.2.4 \ --hash=sha256:d43987bb9626096a302ca6ddcdd81feaeca65ced1d5fe892a6a66b808326aa54 \ --hash=sha256:e1ebe3f41d152d7cb7c265349fdb7f1eca86ccb0ca24a90036cde48e00ceb2ab # via -r contrib/container/requirements.in -packaging==24.0 \ - --hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \ - --hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9 +packaging==24.1 \ + --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \ + --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 # via # gunicorn # mariadb -psycopg[binary, pool]==3.1.18 \ - --hash=sha256:31144d3fb4c17d78094d9e579826f047d4af1da6a10427d91dfcfb6ecdf6f12b \ - --hash=sha256:4d5a0a5a8590906daa58ebd5f3cfc34091377354a1acced269dd10faf55da60e +psycopg[binary, pool]==3.2.1 \ + --hash=sha256:dc8da6dc8729dacacda3cc2f17d2c9397a70a66cf0d2b69c91065d60d5f00cb7 \ + --hash=sha256:ece385fb413a37db332f97c49208b36cf030ff02b199d7635ed2fbd378724175 # via -r contrib/container/requirements.in -psycopg-binary==3.1.18 \ - --hash=sha256:02bd4da45d5ee9941432e2e9bf36fa71a3ac21c6536fe7366d1bd3dd70d6b1e7 \ - --hash=sha256:0f68ac2364a50d4cf9bb803b4341e83678668f1881a253e1224574921c69868c \ - --hash=sha256:13bcd3742112446037d15e360b27a03af4b5afcf767f5ee374ef8f5dd7571b31 \ - --hash=sha256:1729d0e3dfe2546d823841eb7a3d003144189d6f5e138ee63e5227f8b75276a5 \ - --hash=sha256:1859aeb2133f5ecdd9cbcee155f5e38699afc06a365f903b1512c765fd8d457e \ - --hash=sha256:1c9b6bd7fb5c6638cb32469674707649b526acfe786ba6d5a78ca4293d87bae4 \ - --hash=sha256:247474af262bdd5559ee6e669926c4f23e9cf53dae2d34c4d991723c72196404 \ - --hash=sha256:258d2f0cb45e4574f8b2fe7c6d0a0e2eb58903a4fd1fbaf60954fba82d595ab7 \ - --hash=sha256:2e2484ae835dedc80cdc7f1b1a939377dc967fed862262cfd097aa9f50cade46 \ - --hash=sha256:320047e3d3554b857e16c2b6b615a85e0db6a02426f4d203a4594a2f125dfe57 \ - --hash=sha256:39242546383f6b97032de7af30edb483d237a0616f6050512eee7b218a2aa8ee \ - --hash=sha256:3c2b039ae0c45eee4cd85300ef802c0f97d0afc78350946a5d0ec77dd2d7e834 \ - --hash=sha256:3c7afcd6f1d55992f26d9ff7b0bd4ee6b475eb43aa3f054d67d32e09f18b0065 \ - --hash=sha256:3e4b0bb91da6f2238dbd4fbb4afc40dfb4f045bb611b92fce4d381b26413c686 \ - --hash=sha256:3e7ce4d988112ca6c75765c7f24c83bdc476a6a5ce00878df6c140ca32c3e16d \ - --hash=sha256:4085f56a8d4fc8b455e8f44380705c7795be5317419aa5f8214f315e4205d804 \ - --hash=sha256:4575da95fc441244a0e2ebaf33a2b2f74164603341d2046b5cde0a9aa86aa7e2 \ - --hash=sha256:489aa4fe5a0b653b68341e9e44af247dedbbc655326854aa34c163ef1bcb3143 \ - --hash=sha256:4e4de16a637ec190cbee82e0c2dc4860fed17a23a35f7a1e6dc479a5c6876722 \ - --hash=sha256:531381f6647fc267383dca88dbe8a70d0feff433a8e3d0c4939201fea7ae1b82 \ - --hash=sha256:55ff0948457bfa8c0d35c46e3a75193906d1c275538877ba65907fd67aa059ad \ - --hash=sha256:59701118c7d8842e451f1e562d08e8708b3f5d14974eefbce9374badd723c4ae \ - --hash=sha256:5c323103dfa663b88204cf5f028e83c77d7a715f9b6f51d2bbc8184b99ddd90a \ - --hash=sha256:5d6e860edf877d4413e4a807e837d55e3a7c7df701e9d6943c06e460fa6c058f \ - --hash=sha256:639dd78ac09b144b0119076783cb64e1128cc8612243e9701d1503c816750b2e \ - --hash=sha256:6432047b8b24ef97e3fbee1d1593a0faaa9544c7a41a2c67d1f10e7621374c83 \ - --hash=sha256:67284e2e450dc7a9e4d76e78c0bd357dc946334a3d410defaeb2635607f632cd \ - --hash=sha256:6ebecbf2406cd6875bdd2453e31067d1bd8efe96705a9489ef37e93b50dc6f09 \ - --hash=sha256:7121acc783c4e86d2d320a7fb803460fab158a7f0a04c5e8c5d49065118c1e73 \ - --hash=sha256:74e498586b72fb819ca8ea82107747d0cb6e00ae685ea6d1ab3f929318a8ce2d \ - --hash=sha256:780a90bcb69bf27a8b08bc35b958e974cb6ea7a04cdec69e737f66378a344d68 \ - --hash=sha256:7ac1785d67241d5074f8086705fa68e046becea27964267ab3abd392481d7773 \ - --hash=sha256:812726266ab96de681f2c7dbd6b734d327f493a78357fcc16b2ac86ff4f4e080 \ - --hash=sha256:824a1bfd0db96cc6bef2d1e52d9e0963f5bf653dd5bc3ab519a38f5e6f21c299 \ - --hash=sha256:87dd9154b757a5fbf6d590f6f6ea75f4ad7b764a813ae04b1d91a70713f414a1 \ - --hash=sha256:887f8d856c91510148be942c7acd702ccf761a05f59f8abc123c22ab77b5a16c \ - --hash=sha256:888a72c2aca4316ca6d4a619291b805677bae99bba2f6e31a3c18424a48c7e4d \ - --hash=sha256:8f54978c4b646dec77fefd8485fa82ec1a87807f334004372af1aaa6de9539a5 \ - --hash=sha256:91074f78a9f890af5f2c786691575b6b93a4967ad6b8c5a90101f7b8c1a91d9c \ - --hash=sha256:9d684227ef8212e27da5f2aff9d4d303cc30b27ac1702d4f6881935549486dd5 \ - --hash=sha256:9e24e7b6a68a51cc3b162d0339ae4e1263b253e887987d5c759652f5692b5efe \ - --hash=sha256:9ffcbbd389e486d3fd83d30107bbf8b27845a295051ccabde240f235d04ed921 \ - --hash=sha256:a87e9eeb80ce8ec8c2783f29bce9a50bbcd2e2342a340f159c3326bf4697afa1 \ - --hash=sha256:ad35ac7fd989184bf4d38a87decfb5a262b419e8ba8dcaeec97848817412c64a \ - --hash=sha256:b15e3653c82384b043d820fc637199b5c6a36b37fa4a4943e0652785bb2bad5d \ - --hash=sha256:b293e01057e63c3ac0002aa132a1071ce0fdb13b9ee2b6b45d3abdb3525c597d \ - --hash=sha256:b2f7f95746efd1be2dc240248cc157f4315db3fd09fef2adfcc2a76e24aa5741 \ - --hash=sha256:bd27f713f2e5ef3fd6796e66c1a5203a27a30ecb847be27a78e1df8a9a5ae68c \ - --hash=sha256:c38a4796abf7380f83b1653c2711cb2449dd0b2e5aca1caa75447d6fa5179c69 \ - --hash=sha256:c76659ae29a84f2c14f56aad305dd00eb685bd88f8c0a3281a9a4bc6bd7d2aa7 \ - --hash=sha256:c84a0174109f329eeda169004c7b7ca2e884a6305acab4a39600be67f915ed38 \ - --hash=sha256:cd2a9f7f0d4dacc5b9ce7f0e767ae6cc64153264151f50698898c42cabffec0c \ - --hash=sha256:d322ba72cde4ca2eefc2196dad9ad7e52451acd2f04e3688d590290625d0c970 \ - --hash=sha256:d4422af5232699f14b7266a754da49dc9bcd45eba244cf3812307934cd5d6679 \ - --hash=sha256:d46ae44d66bf6058a812467f6ae84e4e157dee281bfb1cfaeca07dee07452e85 \ - --hash=sha256:da917f6df8c6b2002043193cb0d74cc173b3af7eb5800ad69c4e1fbac2a71c30 \ - --hash=sha256:dea4a59da7850192fdead9da888e6b96166e90608cf39e17b503f45826b16f84 \ - --hash=sha256:e05f6825f8db4428782135e6986fec79b139210398f3710ed4aa6ef41473c008 \ - --hash=sha256:e1cf59e0bb12e031a48bb628aae32df3d0c98fd6c759cb89f464b1047f0ca9c8 \ - --hash=sha256:e252d66276c992319ed6cd69a3ffa17538943954075051e992143ccbf6dc3d3e \ - --hash=sha256:e262398e5d51563093edf30612cd1e20fedd932ad0994697d7781ca4880cdc3d \ - --hash=sha256:e28ff8f3de7b56588c2a398dc135fd9f157d12c612bd3daa7e6ba9872337f6f5 \ - --hash=sha256:eea5f14933177ffe5c40b200f04f814258cc14b14a71024ad109f308e8bad414 \ - --hash=sha256:f876ebbf92db70125f6375f91ab4bc6b27648aa68f90d661b1fc5affb4c9731c \ - --hash=sha256:f8ff3bc08b43f36fdc24fedb86d42749298a458c4724fb588c4d76823ac39f54 +psycopg-binary==3.2.1 \ + --hash=sha256:059cbd4e6da2337e17707178fe49464ed01de867dc86c677b30751755ec1dc51 \ + --hash=sha256:06a7aae34edfe179ddc04da005e083ff6c6b0020000399a2cbf0a7121a8a22ea \ + --hash=sha256:0879b5d76b7d48678d31278242aaf951bc2d69ca4e4d7cef117e4bbf7bfefda9 \ + --hash=sha256:0ab58213cc976a1666f66bc1cb2e602315cd753b7981a8e17237ac2a185bd4a1 \ + --hash=sha256:0b018631e5c80ce9bc210b71ea885932f9cca6db131e4df505653d7e3873a938 \ + --hash=sha256:101472468d59c74bb8565fab603e032803fd533d16be4b2d13da1bab8deb32a3 \ + --hash=sha256:1d353e028b8f848b9784450fc2abf149d53a738d451eab3ee4c85703438128b9 \ + --hash=sha256:1d6833f607f3fc7b22226a9e121235d3b84c0eda1d3caab174673ef698f63788 \ + --hash=sha256:21927f41c4d722ae8eb30d62a6ce732c398eac230509af5ba1749a337f8a63e2 \ + --hash=sha256:28ada5f610468c57d8a4a055a8ea915d0085a43d794266c4f3b9d02f4288f4db \ + --hash=sha256:2e8213bf50af073b1aa8dc3cff123bfeedac86332a16c1b7274910bc88a847c7 \ + --hash=sha256:302b86f92c0d76e99fe1b5c22c492ae519ce8b98b88d37ef74fda4c9e24c6b46 \ + --hash=sha256:334046a937bb086c36e2c6889fe327f9f29bfc085d678f70fac0b0618949f674 \ + --hash=sha256:33e6669091d09f8ba36e10ce678a6d9916e110446236a9b92346464a3565635e \ + --hash=sha256:3c838806eeb99af39f934b7999e35f947a8e577997cc892c12b5053a97a9057f \ + --hash=sha256:40bb515d042f6a345714ec0403df68ccf13f73b05e567837d80c886c7c9d3805 \ + --hash=sha256:413977d18412ff83486eeb5875eb00b185a9391c57febac45b8993bf9c0ff489 \ + --hash=sha256:415c3b72ea32119163255c6504085f374e47ae7345f14bc3f0ef1f6e0976a879 \ + --hash=sha256:42781ba94e8842ee98bca5a7d0c44cc9d067500fedca2d6a90fa3609b6d16b42 \ + --hash=sha256:463d55345f73ff391df8177a185ad57b552915ad33f5cc2b31b930500c068b22 \ + --hash=sha256:4a42b8f9ab39affcd5249b45cac763ac3cf12df962b67e23fd15a2ee2932afe5 \ + --hash=sha256:4c84fcac8a3a3479ac14673095cc4e1fdba2935499f72c436785ac679bec0d1a \ + --hash=sha256:592b27d6c46a40f9eeaaeea7c1fef6f3c60b02c634365eb649b2d880669f149f \ + --hash=sha256:62b1b7b07e00ee490afb39c0a47d8282a9c2822c7cfed9553a04b0058adf7e7f \ + --hash=sha256:6418712ba63cebb0c88c050b3997185b0ef54173b36568522d5634ac06153040 \ + --hash=sha256:6f9e13600647087df5928875559f0eb8f496f53e6278b7da9511b4b3d0aff960 \ + --hash=sha256:7066d3dca196ed0dc6172f9777b2d62e4f138705886be656cccff2d555234d60 \ + --hash=sha256:73f9c9b984be9c322b5ec1515b12df1ee5896029f5e72d46160eb6517438659c \ + --hash=sha256:74d623261655a169bc84a9669890975c229f2fa6e19a7f2d10a77675dcf1a707 \ + --hash=sha256:788ffc43d7517c13e624c83e0e553b7b8823c9655e18296566d36a829bfb373f \ + --hash=sha256:78c2007caf3c90f08685c5378e3ceb142bafd5636be7495f7d86ec8a977eaeef \ + --hash=sha256:7a84b5eb194a258116154b2a4ff2962ea60ea52de089508db23a51d3d6b1c7d1 \ + --hash=sha256:7ce965caf618061817f66c0906f0452aef966c293ae0933d4fa5a16ea6eaf5bb \ + --hash=sha256:84837e99353d16c6980603b362d0f03302d4b06c71672a6651f38df8a482923d \ + --hash=sha256:8f28ff0cb9f1defdc4a6f8c958bf6787274247e7dfeca811f6e2f56602695fb1 \ + --hash=sha256:921f0c7f39590763d64a619de84d1b142587acc70fd11cbb5ba8fa39786f3073 \ + --hash=sha256:950fd666ec9e9fe6a8eeb2b5a8f17301790e518953730ad44d715b59ffdbc67f \ + --hash=sha256:9a997efbaadb5e1a294fb5760e2f5643d7b8e4e3fe6cb6f09e6d605fd28e0291 \ + --hash=sha256:aa3931f308ab4a479d0ee22dc04bea867a6365cac0172e5ddcba359da043854b \ + --hash=sha256:af0469c00f24c4bec18c3d2ede124bf62688d88d1b8a5f3c3edc2f61046fe0d7 \ + --hash=sha256:b0104a72a17aa84b3b7dcab6c84826c595355bf54bb6ea6d284dcb06d99c6801 \ + --hash=sha256:b09e8a576a2ac69d695032ee76f31e03b30781828b5dd6d18c6a009e5a3d1c35 \ + --hash=sha256:b140182830c76c74d17eba27df3755a46442ce8d4fb299e7f1cf2f74a87c877b \ + --hash=sha256:b1f087bd84bdcac78bf9f024ebdbfacd07fc0a23ec8191448a50679e2ac4a19e \ + --hash=sha256:c1d2b6438fb83376f43ebb798bf0ad5e57bc56c03c9c29c85bc15405c8c0ac5a \ + --hash=sha256:cad2de17804c4cfee8640ae2b279d616bb9e4734ac3c17c13db5e40982bd710d \ + --hash=sha256:cc304a46be1e291031148d9d95c12451ffe783ff0cc72f18e2cc7ec43cdb8c68 \ + --hash=sha256:dc314a47d44fe1a8069b075a64abffad347a3a1d8652fed1bab5d3baea37acb2 \ + --hash=sha256:f092114f10f81fb6bae544a0ec027eb720e2d9c74a4fcdaa9dd3899873136935 \ + --hash=sha256:f34e369891f77d0738e5d25727c307d06d5344948771e5379ea29c76c6d84555 \ + --hash=sha256:f8a509aeaac364fa965454e80cd110fe6d48ba2c80f56c9b8563423f0b5c3cfd \ + --hash=sha256:f8afb07114ea9b924a4a0305ceb15354ccf0ef3c0e14d54b8dbeb03e50182dd7 \ + --hash=sha256:f99e59f8a5f4dcd9cbdec445f3d8ac950a492fc0e211032384d6992ed3c17eb7 # via psycopg -psycopg-pool==3.2.1 \ - --hash=sha256:060b551d1b97a8d358c668be58b637780b884de14d861f4f5ecc48b7563aafb7 \ - --hash=sha256:6509a75c073590952915eddbba7ce8b8332a440a31e77bba69561483492829ad +psycopg-pool==3.2.2 \ + --hash=sha256:273081d0fbfaced4f35e69200c89cb8fbddfe277c38cc86c235b90a2ec2c8153 \ + --hash=sha256:9e22c370045f6d7f2666a5ad1b0caf345f9f1912195b0b25d0d3bcc4f3a7389c # via psycopg pyasn1==0.6.0 \ --hash=sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c \ @@ -140,93 +130,96 @@ python-ldap==3.4.4 \ # via # -r contrib/container/requirements.in # django-auth-ldap -pyyaml==6.0.1 \ - --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ - --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ - --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ - --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ - --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ - --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ - --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ - --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ - --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ - --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ - --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ - --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ - --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ - --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ - --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ - --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ - --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ - --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ - --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ - --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ - --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ - --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ - --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ - --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ - --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ - --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ - --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ - --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ - --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ - --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \ - --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ - --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ - --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ - --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ - --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ - --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ - --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ - --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ - --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ - --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ - --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ - --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ - --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ - --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ - --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ - --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ - --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ - --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ - --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ - --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ - --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f +pyyaml==6.0.2 \ + --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ + --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ + --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \ + --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \ + --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ + --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \ + --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ + --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \ + --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ + --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \ + --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \ + --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \ + --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \ + --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \ + --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \ + --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \ + --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ + --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \ + --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ + --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \ + --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \ + --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \ + --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \ + --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ + --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ + --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \ + --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \ + --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ + --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ + --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \ + --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ + --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \ + --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ + --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \ + --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \ + --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ + --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \ + --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \ + --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \ + --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ + --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ + --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \ + --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ + --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ + --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \ + --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \ + --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \ + --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \ + --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \ + --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ + --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \ + --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \ + --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4 # via -r contrib/container/requirements.in -setuptools==70.3.0 \ - --hash=sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5 \ - --hash=sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc +setuptools==73.0.1 \ + --hash=sha256:b208925fcb9f7af924ed2dc04708ea89791e24bde0d3020b27df0e116088b34e \ + --hash=sha256:d59a3e788ab7e012ab2c4baed1b376da6366883ee20d7a5fc426816e3d7b1193 # via -r contrib/container/requirements.in -sqlparse==0.5.0 \ - --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ - --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 +sqlparse==0.5.1 \ + --hash=sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4 \ + --hash=sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e # via django -typing-extensions==4.11.0 \ - --hash=sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0 \ - --hash=sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a +typing-extensions==4.12.2 \ + --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ + --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 # via # psycopg # psycopg-pool -uv==0.1.38 \ - --hash=sha256:03242a734a572733f2b9a5dbb94517e918fe26fc01114b7c51d12296dfbb8f8b \ - --hash=sha256:067af2d986329db4fa3c7373017d49f0e16ddff23e483b7e5bc3a5a18ce08ea6 \ - --hash=sha256:0937ad16ae0e0b6bb6dd3c386f8fb33141ad08d1762eaacffb4d2b27fb466a17 \ - --hash=sha256:0e1d64ac437b0a14fbcec55b1c3f162fa24860711e0d855fcd9c672b149a122a \ - --hash=sha256:1be7aa46936c0351ccb1400ea95e5381b3f05fef772fa3b9f23af728cc175dea \ - --hash=sha256:309e73a3ec3a5a536a3efaf434270fc94b483069f1425765165c1c9d786c27fd \ - --hash=sha256:4251f9771d392d7badc1e5fb934b397b12ca00fef9d955207ade169cc1f7e872 \ - --hash=sha256:43772e7589f70e954b1ae29230e575ef9e4d8d769138a94dfa5ae7eaf1e26ac5 \ - --hash=sha256:4a6024256d38b77151e32876be9fcb99cf75df7a86b26e0161cc202bed558adf \ - --hash=sha256:5a98d6aacd4b57b7e00daf154919e7c9206fefdf40bd28cfb13efe0e0324d491 \ - --hash=sha256:8de6dbd8f348ee90af044f4cc7b6650521d25ba2d20a813c1e157a3f90069dd9 \ - --hash=sha256:9133e24db9bdd4f412eab69586d03294419825432a9a27ee1b510a4c01eb7b0b \ - --hash=sha256:92f65b6e4e5c8126501785af3629dc537d7c82caa56ac9336a86929c73d0e138 \ - --hash=sha256:afd85029923e712b6b2c45ddc1680c785392220876c766521e45778db3f71f8e \ - --hash=sha256:b0b15e51a0f8240969bc412ed0dd60cfe3f664b30173139ef263d71c596d631f \ - --hash=sha256:ea44c07605d1359a7d82bf42706dd86d341f15f4ca2e1f36e51626a7111c2ad5 \ - --hash=sha256:f87c9711493c53d32012a96b49c4d53aabdf7ed666cbf2c3fb55dd402a6b31a8 +uv==0.3.0 \ + --hash=sha256:084551ee0743339aa5d0d4c76a94c9f9df16c33030b850f0cd98f316db7b42cc \ + --hash=sha256:0da4f060d583325846cde0727a8cc0cb4e8c63b30ac9373dae213a7315056d90 \ + --hash=sha256:160a1f3b01298942d6cfe21f95a9b7daa3eb73231ba1fc4689157eb9f23b3438 \ + --hash=sha256:21ebc6ca30df7ff57a8e17e3abeeba8a9d1d4ac79c1adf842fa42d48a5c7f372 \ + --hash=sha256:24a1388f5e285058f97576b7dfee79bb5007a712a9e368f3fcdcfeb2dfd9ce92 \ + --hash=sha256:2f937ebdf9976ec1ffe7228fd608ef3e6ce2a61ed68cf7b157ae6900a9c80f41 \ + --hash=sha256:39a4276afe0808ca6c033e0cd6cb73249f934b4a0c9d7b18a944f3f8ea635e27 \ + --hash=sha256:3b62e44f61a154303fc9f4aa87ae54891957d49769d21dcf2be9c22e640c3e92 \ + --hash=sha256:4303364d717b1def58e82b11271259d2ee3bb03da0ca6111819ee254f65b38f4 \ + --hash=sha256:503fc619238550be222b41422b415677c9b8045c92a9815f80ff5d7477671fe6 \ + --hash=sha256:52b3a6110705ff27462ddc68657fedf8a296ed545619a90fa73354f130ad632e \ + --hash=sha256:5c826d9daace67d67790503b0c1152093b3cecd35a91de10f5bb9e26afea9de9 \ + --hash=sha256:6d1025349cbaeba9a974d413795d0ce8d37de5ad7fb7654c0519968b2c083ba1 \ + --hash=sha256:a15b2321444f3668bc95863d2b13ce44ea54053189427ea48d112ecd8b3d2f89 \ + --hash=sha256:a71b7080ee6d7658b22f93aa750cbfd19111cd6c8ac643a73d6778598dd06559 \ + --hash=sha256:b44ebf501de5eef33e4f3cf4b6ea9a458d1f1b3cf26737c25ac507ab7914076a \ + --hash=sha256:d3da56b87ec5aa4f2ae572127c754655bad3820dd41a4d37ed4d5e2f67035990 \ + --hash=sha256:d87ff76da5128036c05db0291db7510a85cb8efb86538e8f49adc8074bb292f0 # via -r contrib/container/requirements.in -wheel==0.43.0 \ - --hash=sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85 \ - --hash=sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81 +wheel==0.44.0 \ + --hash=sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f \ + --hash=sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49 # via -r contrib/container/requirements.in diff --git a/contrib/dev_reqs/requirements.txt b/contrib/dev_reqs/requirements.txt index c9d8353ef4..b1f8b7efae 100644 --- a/contrib/dev_reqs/requirements.txt +++ b/contrib/dev_reqs/requirements.txt @@ -104,9 +104,9 @@ jc==1.25.3 \ --hash=sha256:ea17a8578497f2da92f73924d9d403f4563ba59422fbceff7bb4a16cdf84a54f \ --hash=sha256:fa3140ceda6cba1210d1362f363cd79a0514741e8a1dd6167db2b2e2d5f24f7b # via -r contrib/dev_reqs/requirements.in -pygments==2.17.2 \ - --hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \ - --hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367 +pygments==2.18.0 \ + --hash=sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199 \ + --hash=sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a # via jc pyyaml==6.0.2 \ --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ diff --git a/src/backend/requirements-dev.txt b/src/backend/requirements-dev.txt index 72b7aba4b5..d5158f42bf 100644 --- a/src/backend/requirements-dev.txt +++ b/src/backend/requirements-dev.txt @@ -10,59 +10,74 @@ build==1.2.1 \ --hash=sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d \ --hash=sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4 # via pip-tools -cffi==1.16.0 \ - --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ - --hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \ - --hash=sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 \ - --hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \ - --hash=sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520 \ - --hash=sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36 \ - --hash=sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743 \ - --hash=sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8 \ - --hash=sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed \ - --hash=sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684 \ - --hash=sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56 \ - --hash=sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324 \ - --hash=sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d \ - --hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \ - --hash=sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e \ - --hash=sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088 \ - --hash=sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000 \ - --hash=sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7 \ - --hash=sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e \ - --hash=sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673 \ - --hash=sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c \ - --hash=sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe \ - --hash=sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2 \ - --hash=sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098 \ - --hash=sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8 \ - --hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \ - --hash=sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0 \ - --hash=sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b \ - --hash=sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896 \ - --hash=sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e \ - --hash=sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9 \ - --hash=sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2 \ - --hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \ - --hash=sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6 \ - --hash=sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 \ - --hash=sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f \ - --hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0 \ - --hash=sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4 \ - --hash=sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc \ - --hash=sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 \ - --hash=sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba \ - --hash=sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872 \ - --hash=sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb \ - --hash=sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614 \ - --hash=sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1 \ - --hash=sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d \ - --hash=sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969 \ - --hash=sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b \ - --hash=sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4 \ - --hash=sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627 \ - --hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \ - --hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357 +cffi==1.17.0 \ + --hash=sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f \ + --hash=sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab \ + --hash=sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499 \ + --hash=sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058 \ + --hash=sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693 \ + --hash=sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb \ + --hash=sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377 \ + --hash=sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885 \ + --hash=sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2 \ + --hash=sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401 \ + --hash=sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4 \ + --hash=sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b \ + --hash=sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59 \ + --hash=sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f \ + --hash=sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c \ + --hash=sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555 \ + --hash=sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa \ + --hash=sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424 \ + --hash=sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb \ + --hash=sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2 \ + --hash=sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8 \ + --hash=sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e \ + --hash=sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9 \ + --hash=sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82 \ + --hash=sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828 \ + --hash=sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759 \ + --hash=sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc \ + --hash=sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118 \ + --hash=sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf \ + --hash=sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932 \ + --hash=sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a \ + --hash=sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29 \ + --hash=sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206 \ + --hash=sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2 \ + --hash=sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c \ + --hash=sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c \ + --hash=sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0 \ + --hash=sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a \ + --hash=sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195 \ + --hash=sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6 \ + --hash=sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9 \ + --hash=sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc \ + --hash=sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb \ + --hash=sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0 \ + --hash=sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7 \ + --hash=sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb \ + --hash=sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a \ + --hash=sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492 \ + --hash=sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720 \ + --hash=sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42 \ + --hash=sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7 \ + --hash=sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d \ + --hash=sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d \ + --hash=sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb \ + --hash=sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4 \ + --hash=sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2 \ + --hash=sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b \ + --hash=sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8 \ + --hash=sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e \ + --hash=sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204 \ + --hash=sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3 \ + --hash=sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150 \ + --hash=sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4 \ + --hash=sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76 \ + --hash=sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e \ + --hash=sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb \ + --hash=sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91 # via # -c src/backend/requirements.txt # cryptography @@ -168,93 +183,108 @@ click==8.1.7 \ --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de # via pip-tools -coverage[toml]==7.5.4 \ - --hash=sha256:018a12985185038a5b2bcafab04ab833a9a0f2c59995b3cec07e10074c78635f \ - --hash=sha256:02ff6e898197cc1e9fa375581382b72498eb2e6d5fc0b53f03e496cfee3fac6d \ - --hash=sha256:042183de01f8b6d531e10c197f7f0315a61e8d805ab29c5f7b51a01d62782747 \ - --hash=sha256:1014fbf665fef86cdfd6cb5b7371496ce35e4d2a00cda501cf9f5b9e6fced69f \ - --hash=sha256:1137f46adb28e3813dec8c01fefadcb8c614f33576f672962e323b5128d9a68d \ - --hash=sha256:16852febd96acd953b0d55fc842ce2dac1710f26729b31c80b940b9afcd9896f \ - --hash=sha256:2174e7c23e0a454ffe12267a10732c273243b4f2d50d07544a91198f05c48f47 \ - --hash=sha256:2214ee920787d85db1b6a0bd9da5f8503ccc8fcd5814d90796c2f2493a2f4d2e \ - --hash=sha256:3257fdd8e574805f27bb5342b77bc65578e98cbc004a92232106344053f319ba \ - --hash=sha256:3684bc2ff328f935981847082ba4fdc950d58906a40eafa93510d1b54c08a66c \ - --hash=sha256:3a6612c99081d8d6134005b1354191e103ec9705d7ba2754e848211ac8cacc6b \ - --hash=sha256:3d7564cc09dd91b5a6001754a5b3c6ecc4aba6323baf33a12bd751036c998be4 \ - --hash=sha256:44da56a2589b684813f86d07597fdf8a9c6ce77f58976727329272f5a01f99f7 \ - --hash=sha256:5013ed890dc917cef2c9f765c4c6a8ae9df983cd60dbb635df8ed9f4ebc9f555 \ - --hash=sha256:54317c2b806354cbb2dc7ac27e2b93f97096912cc16b18289c5d4e44fc663233 \ - --hash=sha256:56b4eafa21c6c175b3ede004ca12c653a88b6f922494b023aeb1e836df953ace \ - --hash=sha256:581ea96f92bf71a5ec0974001f900db495488434a6928a2ca7f01eee20c23805 \ - --hash=sha256:5cd64adedf3be66f8ccee418473c2916492d53cbafbfcff851cbec5a8454b136 \ - --hash=sha256:5df54843b88901fdc2f598ac06737f03d71168fd1175728054c8f5a2739ac3e4 \ - --hash=sha256:65e528e2e921ba8fd67d9055e6b9f9e34b21ebd6768ae1c1723f4ea6ace1234d \ - --hash=sha256:6aae5cce399a0f065da65c7bb1e8abd5c7a3043da9dceb429ebe1b289bc07806 \ - --hash=sha256:6cfb5a4f556bb51aba274588200a46e4dd6b505fb1a5f8c5ae408222eb416f99 \ - --hash=sha256:7076b4b3a5f6d2b5d7f1185fde25b1e54eb66e647a1dfef0e2c2bfaf9b4c88c8 \ - --hash=sha256:73ca8fbc5bc622e54627314c1a6f1dfdd8db69788f3443e752c215f29fa87a0b \ - --hash=sha256:79b356f3dd5b26f3ad23b35c75dbdaf1f9e2450b6bcefc6d0825ea0aa3f86ca5 \ - --hash=sha256:7a892be37ca35eb5019ec85402c3371b0f7cda5ab5056023a7f13da0961e60da \ - --hash=sha256:8192794d120167e2a64721d88dbd688584675e86e15d0569599257566dec9bf0 \ - --hash=sha256:820bc841faa502e727a48311948e0461132a9c8baa42f6b2b84a29ced24cc078 \ - --hash=sha256:8f894208794b164e6bd4bba61fc98bf6b06be4d390cf2daacfa6eca0a6d2bb4f \ - --hash=sha256:a04e990a2a41740b02d6182b498ee9796cf60eefe40cf859b016650147908029 \ - --hash=sha256:a44963520b069e12789d0faea4e9fdb1e410cdc4aab89d94f7f55cbb7fef0353 \ - --hash=sha256:a6bb74ed465d5fb204b2ec41d79bcd28afccf817de721e8a807d5141c3426638 \ - --hash=sha256:ab73b35e8d109bffbda9a3e91c64e29fe26e03e49addf5b43d85fc426dde11f9 \ - --hash=sha256:aea072a941b033813f5e4814541fc265a5c12ed9720daef11ca516aeacd3bd7f \ - --hash=sha256:b1ccf5e728ccf83acd313c89f07c22d70d6c375a9c6f339233dcf792094bcbf7 \ - --hash=sha256:b385d49609f8e9efc885790a5a0e89f2e3ae042cdf12958b6034cc442de428d3 \ - --hash=sha256:b3d45ff86efb129c599a3b287ae2e44c1e281ae0f9a9bad0edc202179bcc3a2e \ - --hash=sha256:b4a474f799456e0eb46d78ab07303286a84a3140e9700b9e154cfebc8f527016 \ - --hash=sha256:b95c3a8cb0463ba9f77383d0fa8c9194cf91f64445a63fc26fb2327e1e1eb088 \ - --hash=sha256:c5986ee7ea0795a4095ac4d113cbb3448601efca7f158ec7f7087a6c705304e4 \ - --hash=sha256:cdd31315fc20868c194130de9ee6bfd99755cc9565edff98ecc12585b90be882 \ - --hash=sha256:cef4649ec906ea7ea5e9e796e68b987f83fa9a718514fe147f538cfeda76d7a7 \ - --hash=sha256:d05c16cf4b4c2fc880cb12ba4c9b526e9e5d5bb1d81313d4d732a5b9fe2b9d53 \ - --hash=sha256:d2e344d6adc8ef81c5a233d3a57b3c7d5181f40e79e05e1c143da143ccb6377d \ - --hash=sha256:d45d3cbd94159c468b9b8c5a556e3f6b81a8d1af2a92b77320e887c3e7a5d080 \ - --hash=sha256:db14f552ac38f10758ad14dd7b983dbab424e731588d300c7db25b6f89e335b5 \ - --hash=sha256:dbc5958cb471e5a5af41b0ddaea96a37e74ed289535e8deca404811f6cb0bc3d \ - --hash=sha256:ddbd2f9713a79e8e7242d7c51f1929611e991d855f414ca9996c20e44a895f7c \ - --hash=sha256:e16f3d6b491c48c5ae726308e6ab1e18ee830b4cdd6913f2d7f77354b33f91c8 \ - --hash=sha256:e2afe743289273209c992075a5a4913e8d007d569a406ffed0bd080ea02b0633 \ - --hash=sha256:e564c2cf45d2f44a9da56f4e3a26b2236504a496eb4cb0ca7221cd4cc7a9aca9 \ - --hash=sha256:ed550e7442f278af76d9d65af48069f1fb84c9f745ae249c1a183c1e9d1b025c +coverage[toml]==7.6.1 \ + --hash=sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca \ + --hash=sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d \ + --hash=sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6 \ + --hash=sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989 \ + --hash=sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c \ + --hash=sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b \ + --hash=sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223 \ + --hash=sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f \ + --hash=sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56 \ + --hash=sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3 \ + --hash=sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8 \ + --hash=sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb \ + --hash=sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388 \ + --hash=sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0 \ + --hash=sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a \ + --hash=sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8 \ + --hash=sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f \ + --hash=sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a \ + --hash=sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962 \ + --hash=sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8 \ + --hash=sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391 \ + --hash=sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc \ + --hash=sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2 \ + --hash=sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155 \ + --hash=sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb \ + --hash=sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0 \ + --hash=sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c \ + --hash=sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a \ + --hash=sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004 \ + --hash=sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060 \ + --hash=sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232 \ + --hash=sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93 \ + --hash=sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129 \ + --hash=sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163 \ + --hash=sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de \ + --hash=sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6 \ + --hash=sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23 \ + --hash=sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569 \ + --hash=sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d \ + --hash=sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778 \ + --hash=sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d \ + --hash=sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36 \ + --hash=sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a \ + --hash=sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6 \ + --hash=sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34 \ + --hash=sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704 \ + --hash=sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106 \ + --hash=sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9 \ + --hash=sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862 \ + --hash=sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b \ + --hash=sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255 \ + --hash=sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16 \ + --hash=sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3 \ + --hash=sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133 \ + --hash=sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb \ + --hash=sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657 \ + --hash=sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d \ + --hash=sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca \ + --hash=sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36 \ + --hash=sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c \ + --hash=sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e \ + --hash=sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff \ + --hash=sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7 \ + --hash=sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5 \ + --hash=sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02 \ + --hash=sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c \ + --hash=sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df \ + --hash=sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3 \ + --hash=sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a \ + --hash=sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959 \ + --hash=sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234 \ + --hash=sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc # via -r src/backend/requirements-dev.in -cryptography==42.0.8 \ - --hash=sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad \ - --hash=sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583 \ - --hash=sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b \ - --hash=sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c \ - --hash=sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1 \ - --hash=sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648 \ - --hash=sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949 \ - --hash=sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba \ - --hash=sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c \ - --hash=sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9 \ - --hash=sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d \ - --hash=sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c \ - --hash=sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e \ - --hash=sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2 \ - --hash=sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d \ - --hash=sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7 \ - --hash=sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70 \ - --hash=sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2 \ - --hash=sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7 \ - --hash=sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14 \ - --hash=sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe \ - --hash=sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e \ - --hash=sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71 \ - --hash=sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961 \ - --hash=sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7 \ - --hash=sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c \ - --hash=sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28 \ - --hash=sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842 \ - --hash=sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902 \ - --hash=sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801 \ - --hash=sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a \ - --hash=sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e +cryptography==43.0.0 \ + --hash=sha256:0663585d02f76929792470451a5ba64424acc3cd5227b03921dab0e2f27b1709 \ + --hash=sha256:08a24a7070b2b6804c1940ff0f910ff728932a9d0e80e7814234269f9d46d069 \ + --hash=sha256:232ce02943a579095a339ac4b390fbbe97f5b5d5d107f8a08260ea2768be8cc2 \ + --hash=sha256:2905ccf93a8a2a416f3ec01b1a7911c3fe4073ef35640e7ee5296754e30b762b \ + --hash=sha256:299d3da8e00b7e2b54bb02ef58d73cd5f55fb31f33ebbf33bd00d9aa6807df7e \ + --hash=sha256:2c6d112bf61c5ef44042c253e4859b3cbbb50df2f78fa8fae6747a7814484a70 \ + --hash=sha256:31e44a986ceccec3d0498e16f3d27b2ee5fdf69ce2ab89b52eaad1d2f33d8778 \ + --hash=sha256:3d9a1eca329405219b605fac09ecfc09ac09e595d6def650a437523fcd08dd22 \ + --hash=sha256:3dcdedae5c7710b9f97ac6bba7e1052b95c7083c9d0e9df96e02a1932e777895 \ + --hash=sha256:47ca71115e545954e6c1d207dd13461ab81f4eccfcb1345eac874828b5e3eaaf \ + --hash=sha256:4a997df8c1c2aae1e1e5ac49c2e4f610ad037fc5a3aadc7b64e39dea42249431 \ + --hash=sha256:51956cf8730665e2bdf8ddb8da0056f699c1a5715648c1b0144670c1ba00b48f \ + --hash=sha256:5bcb8a5620008a8034d39bce21dc3e23735dfdb6a33a06974739bfa04f853947 \ + --hash=sha256:64c3f16e2a4fc51c0d06af28441881f98c5d91009b8caaff40cf3548089e9c74 \ + --hash=sha256:6e2b11c55d260d03a8cf29ac9b5e0608d35f08077d8c087be96287f43af3ccdc \ + --hash=sha256:7b3f5fe74a5ca32d4d0f302ffe6680fcc5c28f8ef0dc0ae8f40c0f3a1b4fca66 \ + --hash=sha256:844b6d608374e7d08f4f6e6f9f7b951f9256db41421917dfb2d003dde4cd6b66 \ + --hash=sha256:9a8d6802e0825767476f62aafed40532bd435e8a5f7d23bd8b4f5fd04cc80ecf \ + --hash=sha256:aae4d918f6b180a8ab8bf6511a419473d107df4dbb4225c7b48c5c9602c38c7f \ + --hash=sha256:ac1955ce000cb29ab40def14fd1bbfa7af2017cca696ee696925615cafd0dce5 \ + --hash=sha256:b88075ada2d51aa9f18283532c9f60e72170041bba88d7f37e49cbb10275299e \ + --hash=sha256:cb013933d4c127349b3948aa8aaf2f12c0353ad0eccd715ca789c8a0f671646f \ + --hash=sha256:cc70b4b581f28d0a254d006f26949245e3657d40d8857066c2ae22a61222ef55 \ + --hash=sha256:e9c5266c432a1e23738d178e51c2c7a5e2ddf790f248be939448c0ba2021f9d1 \ + --hash=sha256:ea9e57f8ea880eeea38ab5abf9fbe39f923544d7884228ec67d666abd60f5a47 \ + --hash=sha256:ee0c405832ade84d4de74b9029bedb7b31200600fa524d218fc29bfa371e97f5 \ + --hash=sha256:fdcb265de28585de5b859ae13e3846a8e805268a823a12a4da2597f1f5afc9f0 # via # -c src/backend/requirements.txt # pdfminer-six @@ -287,13 +317,13 @@ filelock==3.15.4 \ --hash=sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb \ --hash=sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7 # via virtualenv -identify==2.5.36 \ - --hash=sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa \ - --hash=sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d +identify==2.6.0 \ + --hash=sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf \ + --hash=sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0 # via pre-commit -importlib-metadata==7.1.0 \ - --hash=sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 \ - --hash=sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2 +importlib-metadata==8.0.0 \ + --hash=sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f \ + --hash=sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812 # via # -c src/backend/requirements.txt # build @@ -311,9 +341,9 @@ packaging==24.1 \ # via # -c src/backend/requirements.txt # build -pdfminer-six==20231228 \ - --hash=sha256:6004da3ad1a7a4d45930cb950393df89b068e73be365a6ff64a838d37bcb08c4 \ - --hash=sha256:e8d3c3310e6fbc1fe414090123ab01351634b4ecb021232206c4c9a8ca3e3b8f +pdfminer-six==20240706 \ + --hash=sha256:c631a46d5da957a9ffe4460c5dce21e8431dabb615fee5f9f4400603a58d95a6 \ + --hash=sha256:f4f70e74174b4b3542fcb8406a210b6e2e27cd0f0b5fd04534a8cc0d8951e38c # via -r src/backend/requirements-dev.in pip==24.2 \ --hash=sha256:2cd581cf58ab7fcfca4ce8efa6dcacd0de5bf8d0a3eb9ec927e07405f4d9e2a2 \ @@ -327,9 +357,9 @@ platformdirs==4.2.2 \ --hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \ --hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3 # via virtualenv -pre-commit==3.7.1 \ - --hash=sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a \ - --hash=sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5 +pre-commit==3.8.0 \ + --hash=sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af \ + --hash=sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f # via -r src/backend/requirements-dev.in pycparser==2.22 \ --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ @@ -343,71 +373,73 @@ pyproject-hooks==1.1.0 \ # via # build # pip-tools -pyyaml==6.0.1 \ - --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ - --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ - --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ - --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ - --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ - --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ - --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ - --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ - --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ - --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ - --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ - --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ - --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ - --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ - --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ - --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ - --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ - --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ - --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ - --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ - --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ - --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ - --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ - --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ - --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ - --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ - --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ - --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ - --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ - --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \ - --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ - --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ - --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ - --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ - --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ - --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ - --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ - --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ - --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ - --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ - --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ - --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ - --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ - --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ - --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ - --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ - --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ - --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ - --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ - --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ - --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f +pyyaml==6.0.2 \ + --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ + --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ + --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \ + --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \ + --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ + --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \ + --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ + --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \ + --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ + --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \ + --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \ + --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \ + --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \ + --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \ + --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \ + --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \ + --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ + --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \ + --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ + --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \ + --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \ + --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \ + --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \ + --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ + --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ + --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \ + --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \ + --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ + --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ + --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \ + --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ + --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \ + --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ + --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \ + --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \ + --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ + --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \ + --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \ + --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \ + --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ + --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ + --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \ + --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ + --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ + --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \ + --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \ + --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \ + --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \ + --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \ + --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ + --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \ + --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \ + --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4 # via # -c src/backend/requirements.txt # pre-commit -setuptools==72.1.0 \ - --hash=sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1 \ - --hash=sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec +setuptools==73.0.1 \ + --hash=sha256:b208925fcb9f7af924ed2dc04708ea89791e24bde0d3020b27df0e116088b34e \ + --hash=sha256:d59a3e788ab7e012ab2c4baed1b376da6366883ee20d7a5fc426816e3d7b1193 # via # -c src/backend/requirements.txt # -r src/backend/requirements-dev.in # pip-tools -sqlparse==0.5.0 \ - --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ - --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 +sqlparse==0.5.1 \ + --hash=sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4 \ + --hash=sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e # via # -c src/backend/requirements.txt # django @@ -415,6 +447,7 @@ tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f # via + # -c src/backend/requirements.txt # build # coverage # pip-tools @@ -429,13 +462,13 @@ virtualenv==20.26.3 \ --hash=sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a \ --hash=sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589 # via pre-commit -wheel==0.43.0 \ - --hash=sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85 \ - --hash=sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81 +wheel==0.44.0 \ + --hash=sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f \ + --hash=sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49 # via pip-tools -zipp==3.19.2 \ - --hash=sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19 \ - --hash=sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c +zipp==3.20.0 \ + --hash=sha256:0145e43d89664cfe1a2e533adc75adafed82fe2da404b4bbb6b026c0157bdb31 \ + --hash=sha256:58da6168be89f0be59beb194da1250516fdaa062ccebd30127ac65d30045e10d # via # -c src/backend/requirements.txt # importlib-metadata diff --git a/src/backend/requirements.in b/src/backend/requirements.in index 327047bb49..6c65f19a18 100644 --- a/src/backend/requirements.in +++ b/src/backend/requirements.in @@ -62,3 +62,6 @@ opentelemetry-exporter-otlp opentelemetry-instrumentation-django opentelemetry-instrumentation-requests opentelemetry-instrumentation-redis + +# pinned sub-deps +pydyf==0.10.0 # Fixed 2024-08-22 see https://github.com/inventree/InvenTree/pull/7961/files diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index 9ddd6e42e0..ab3edf91dc 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -10,15 +10,15 @@ async-timeout==4.0.3 \ --hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \ --hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028 # via redis -attrs==23.2.0 \ - --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \ - --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1 +attrs==24.2.0 \ + --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ + --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 # via # jsonschema # referencing -babel==2.15.0 \ - --hash=sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb \ - --hash=sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413 +babel==2.16.0 \ + --hash=sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b \ + --hash=sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316 # via py-moneyed bleach[css]==6.1.0 \ --hash=sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe \ @@ -115,59 +115,74 @@ certifi==2024.7.4 \ # via # requests # sentry-sdk -cffi==1.16.0 \ - --hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \ - --hash=sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a \ - --hash=sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 \ - --hash=sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab \ - --hash=sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520 \ - --hash=sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36 \ - --hash=sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743 \ - --hash=sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8 \ - --hash=sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed \ - --hash=sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684 \ - --hash=sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56 \ - --hash=sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324 \ - --hash=sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d \ - --hash=sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235 \ - --hash=sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e \ - --hash=sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088 \ - --hash=sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000 \ - --hash=sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7 \ - --hash=sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e \ - --hash=sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673 \ - --hash=sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c \ - --hash=sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe \ - --hash=sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2 \ - --hash=sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098 \ - --hash=sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8 \ - --hash=sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a \ - --hash=sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0 \ - --hash=sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b \ - --hash=sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896 \ - --hash=sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e \ - --hash=sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9 \ - --hash=sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2 \ - --hash=sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b \ - --hash=sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6 \ - --hash=sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 \ - --hash=sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f \ - --hash=sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0 \ - --hash=sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4 \ - --hash=sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc \ - --hash=sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 \ - --hash=sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba \ - --hash=sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872 \ - --hash=sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb \ - --hash=sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614 \ - --hash=sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1 \ - --hash=sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d \ - --hash=sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969 \ - --hash=sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b \ - --hash=sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4 \ - --hash=sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627 \ - --hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \ - --hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357 +cffi==1.17.0 \ + --hash=sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f \ + --hash=sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab \ + --hash=sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499 \ + --hash=sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058 \ + --hash=sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693 \ + --hash=sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb \ + --hash=sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377 \ + --hash=sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885 \ + --hash=sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2 \ + --hash=sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401 \ + --hash=sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4 \ + --hash=sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b \ + --hash=sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59 \ + --hash=sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f \ + --hash=sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c \ + --hash=sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555 \ + --hash=sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa \ + --hash=sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424 \ + --hash=sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb \ + --hash=sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2 \ + --hash=sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8 \ + --hash=sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e \ + --hash=sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9 \ + --hash=sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82 \ + --hash=sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828 \ + --hash=sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759 \ + --hash=sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc \ + --hash=sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118 \ + --hash=sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf \ + --hash=sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932 \ + --hash=sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a \ + --hash=sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29 \ + --hash=sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206 \ + --hash=sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2 \ + --hash=sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c \ + --hash=sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c \ + --hash=sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0 \ + --hash=sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a \ + --hash=sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195 \ + --hash=sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6 \ + --hash=sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9 \ + --hash=sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc \ + --hash=sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb \ + --hash=sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0 \ + --hash=sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7 \ + --hash=sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb \ + --hash=sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a \ + --hash=sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492 \ + --hash=sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720 \ + --hash=sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42 \ + --hash=sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7 \ + --hash=sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d \ + --hash=sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d \ + --hash=sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb \ + --hash=sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4 \ + --hash=sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2 \ + --hash=sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b \ + --hash=sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8 \ + --hash=sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e \ + --hash=sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204 \ + --hash=sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3 \ + --hash=sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150 \ + --hash=sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4 \ + --hash=sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76 \ + --hash=sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e \ + --hash=sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb \ + --hash=sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91 # via # cryptography # weasyprint @@ -271,39 +286,34 @@ coreschema==0.0.4 \ --hash=sha256:5e6ef7bf38c1525d5e55a895934ab4273548629f16aed5c0a6caa74ebf45551f \ --hash=sha256:9503506007d482ab0867ba14724b93c18a33b22b6d19fb419ef2d239dd4a1607 # via coreapi -cryptography==42.0.8 \ - --hash=sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad \ - --hash=sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583 \ - --hash=sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b \ - --hash=sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c \ - --hash=sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1 \ - --hash=sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648 \ - --hash=sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949 \ - --hash=sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba \ - --hash=sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c \ - --hash=sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9 \ - --hash=sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d \ - --hash=sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c \ - --hash=sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e \ - --hash=sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2 \ - --hash=sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d \ - --hash=sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7 \ - --hash=sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70 \ - --hash=sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2 \ - --hash=sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7 \ - --hash=sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14 \ - --hash=sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe \ - --hash=sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e \ - --hash=sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71 \ - --hash=sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961 \ - --hash=sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7 \ - --hash=sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c \ - --hash=sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28 \ - --hash=sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842 \ - --hash=sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902 \ - --hash=sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801 \ - --hash=sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a \ - --hash=sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e +cryptography==43.0.0 \ + --hash=sha256:0663585d02f76929792470451a5ba64424acc3cd5227b03921dab0e2f27b1709 \ + --hash=sha256:08a24a7070b2b6804c1940ff0f910ff728932a9d0e80e7814234269f9d46d069 \ + --hash=sha256:232ce02943a579095a339ac4b390fbbe97f5b5d5d107f8a08260ea2768be8cc2 \ + --hash=sha256:2905ccf93a8a2a416f3ec01b1a7911c3fe4073ef35640e7ee5296754e30b762b \ + --hash=sha256:299d3da8e00b7e2b54bb02ef58d73cd5f55fb31f33ebbf33bd00d9aa6807df7e \ + --hash=sha256:2c6d112bf61c5ef44042c253e4859b3cbbb50df2f78fa8fae6747a7814484a70 \ + --hash=sha256:31e44a986ceccec3d0498e16f3d27b2ee5fdf69ce2ab89b52eaad1d2f33d8778 \ + --hash=sha256:3d9a1eca329405219b605fac09ecfc09ac09e595d6def650a437523fcd08dd22 \ + --hash=sha256:3dcdedae5c7710b9f97ac6bba7e1052b95c7083c9d0e9df96e02a1932e777895 \ + --hash=sha256:47ca71115e545954e6c1d207dd13461ab81f4eccfcb1345eac874828b5e3eaaf \ + --hash=sha256:4a997df8c1c2aae1e1e5ac49c2e4f610ad037fc5a3aadc7b64e39dea42249431 \ + --hash=sha256:51956cf8730665e2bdf8ddb8da0056f699c1a5715648c1b0144670c1ba00b48f \ + --hash=sha256:5bcb8a5620008a8034d39bce21dc3e23735dfdb6a33a06974739bfa04f853947 \ + --hash=sha256:64c3f16e2a4fc51c0d06af28441881f98c5d91009b8caaff40cf3548089e9c74 \ + --hash=sha256:6e2b11c55d260d03a8cf29ac9b5e0608d35f08077d8c087be96287f43af3ccdc \ + --hash=sha256:7b3f5fe74a5ca32d4d0f302ffe6680fcc5c28f8ef0dc0ae8f40c0f3a1b4fca66 \ + --hash=sha256:844b6d608374e7d08f4f6e6f9f7b951f9256db41421917dfb2d003dde4cd6b66 \ + --hash=sha256:9a8d6802e0825767476f62aafed40532bd435e8a5f7d23bd8b4f5fd04cc80ecf \ + --hash=sha256:aae4d918f6b180a8ab8bf6511a419473d107df4dbb4225c7b48c5c9602c38c7f \ + --hash=sha256:ac1955ce000cb29ab40def14fd1bbfa7af2017cca696ee696925615cafd0dce5 \ + --hash=sha256:b88075ada2d51aa9f18283532c9f60e72170041bba88d7f37e49cbb10275299e \ + --hash=sha256:cb013933d4c127349b3948aa8aaf2f12c0353ad0eccd715ca789c8a0f671646f \ + --hash=sha256:cc70b4b581f28d0a254d006f26949245e3657d40d8857066c2ae22a61222ef55 \ + --hash=sha256:e9c5266c432a1e23738d178e51c2c7a5e2ddf790f248be939448c0ba2021f9d1 \ + --hash=sha256:ea9e57f8ea880eeea38ab5abf9fbe39f923544d7884228ec67d666abd60f5a47 \ + --hash=sha256:ee0c405832ade84d4de74b9029bedb7b31200600fa524d218fc29bfa371e97f5 \ + --hash=sha256:fdcb265de28585de5b859ae13e3846a8e805268a823a12a4da2597f1f5afc9f0 # via # -r src/backend/requirements.in # djangorestframework-simplejwt @@ -324,6 +334,7 @@ deprecated==1.2.14 \ # opentelemetry-api # opentelemetry-exporter-otlp-proto-grpc # opentelemetry-exporter-otlp-proto-http + # opentelemetry-semantic-conventions diff-match-patch==20230430 \ --hash=sha256:953019cdb9c9d2c9e47b5b12bcff3cf4746fc4598eb406076fa1fc27e6a1f15c \ --hash=sha256:dce43505fb7b1b317de7195579388df0746d90db07015ed47a85e5e44930ef93 @@ -366,8 +377,8 @@ django==4.2.15 \ # djangorestframework # djangorestframework-simplejwt # drf-spectacular -django-allauth[openid, saml]==0.63.3 \ - --hash=sha256:2374164c468a309e6badf70bc3405136df6036f24a20a13387f2a063066bdaa9 +django-allauth[openid, saml]==64.1.0 \ + --hash=sha256:713bfc410021140aefae0f04eeaac5d50ebedad7abaf43174670a9ec002c595c # via # -r src/backend/requirements.in # django-allauth-2fa @@ -395,9 +406,9 @@ django-error-report-2==0.4.2 \ --hash=sha256:1dd99c497af09b7ea99f5fbaf910501838150a9d5390796ea00e187bc62f6c1b \ --hash=sha256:603e1e3b24d01bbfeab6379af948893b2b034031c80fa8b45cf1c4735341c04b # via -r src/backend/requirements.in -django-filter==24.2 \ - --hash=sha256:48e5fc1da3ccd6ca0d5f9bb550973518ce977a4edde9d2a8a154a7f4f0b9f96e \ - --hash=sha256:df2ee9857e18d38bed203c8745f62a803fa0f31688c9fe6f8e868120b1848e48 +django-filter==24.3 \ + --hash=sha256:c4852822928ce17fb699bcfccd644b3574f1a2d80aeb2b4ff4f16b02dd49dc64 \ + --hash=sha256:d8ccaf6732afd21ca0542f6733b11591030fa98669f8d15599b358e24a2cd9c3 # via -r src/backend/requirements.in django-flags==5.0.13 \ --hash=sha256:52df74b86d93f5cb402190ad26b68a5ba0f127e9e016189f1a6f2e8ba3c06a42 \ @@ -435,9 +446,9 @@ django-mptt==0.16.0 \ --hash=sha256:56c9606bf0b329b5f5afd55dd8bfd073612ea1d5999b10903b09de62bee84c8e \ --hash=sha256:8716849ba3318d94e2e100ed0923a05c1ffdf8195f8472b690dbaf737d2af3b5 # via -r src/backend/requirements.in -django-otp==1.5.0 \ - --hash=sha256:e7142139f1e9686be5f396669a3d3d61178cd9b3e9de9de5933888668908b46b \ - --hash=sha256:e88871d2d3b333a86c2cd0cb721be8098d4d6344cb220315a500e5a5c8254295 +django-otp==1.5.2 \ + --hash=sha256:931a4f46f0ec10cab4d25ac8b7dfd6344538320b0489716cabb0da3108dabd75 \ + --hash=sha256:fc6d13025eb659030684728ab55b9343e06069c62a17d5f3be2649d8ee314f0f # via django-allauth-2fa django-picklefield==3.2 \ --hash=sha256:aa463f5d79d497dbe789f14b45180f00a51d0d670067d0729f352a3941cdfa4d \ @@ -473,9 +484,9 @@ django-stdimage==6.0.2 \ --hash=sha256:880ab14828be56b53f711c3afae83c219ddd5d9af00850626736feb48382bf7f \ --hash=sha256:9a73f7da48c48074580e2b032d5bdb7164935dbe4b9dc4fb88a7e112f3d521c8 # via -r src/backend/requirements.in -django-taggit==5.0.1 \ - --hash=sha256:a0ca8a28b03c4b26c2630fd762cb76ec39b5e41abf727a7b66f897a625c5e647 \ - --hash=sha256:edcd7db1e0f35c304e082a2f631ddac2e16ef5296029524eb792af7430cab4cc +django-taggit==6.0.0 \ + --hash=sha256:7094f797b7e5e3727525a0af7bc550860000ddc2248266529d568eca61b39fb1 \ + --hash=sha256:723d98bd5c536daa3c0e1bdae0965f7005a9b15269816bb4053fafec4ebad57e # via -r src/backend/requirements.in django-user-sessions==2.0.0 \ --hash=sha256:0965554279f556b47062965609fa08b3ae45bbc581001dbe84b2ea599cc67748 \ @@ -561,49 +572,49 @@ feedparser==6.0.11 \ --hash=sha256:0be7ee7b395572b19ebeb1d6aafb0028dee11169f1c934e0ed67d54992f4ad45 \ --hash=sha256:c9d0407b64c6f2a065d0ebb292c2b35c01050cc0dc33757461aaabdc4c4184d5 # via -r src/backend/requirements.in -fonttools[woff]==4.53.0 \ - --hash=sha256:099634631b9dd271d4a835d2b2a9e042ccc94ecdf7e2dd9f7f34f7daf333358d \ - --hash=sha256:0c555e039d268445172b909b1b6bdcba42ada1cf4a60e367d68702e3f87e5f64 \ - --hash=sha256:1e677bfb2b4bd0e5e99e0f7283e65e47a9814b0486cb64a41adf9ef110e078f2 \ - --hash=sha256:2367d47816cc9783a28645bc1dac07f8ffc93e0f015e8c9fc674a5b76a6da6e4 \ - --hash=sha256:28d072169fe8275fb1a0d35e3233f6df36a7e8474e56cb790a7258ad822b6fd6 \ - --hash=sha256:31f0e3147375002aae30696dd1dc596636abbd22fca09d2e730ecde0baad1d6b \ - --hash=sha256:3e0ad3c6ea4bd6a289d958a1eb922767233f00982cf0fe42b177657c86c80a8f \ - --hash=sha256:45b4afb069039f0366a43a5d454bc54eea942bfb66b3fc3e9a2c07ef4d617380 \ - --hash=sha256:4a2a6ba400d386e904fd05db81f73bee0008af37799a7586deaa4aef8cd5971e \ - --hash=sha256:4f520d9ac5b938e6494f58a25c77564beca7d0199ecf726e1bd3d56872c59749 \ - --hash=sha256:52a6e0a7a0bf611c19bc8ec8f7592bdae79c8296c70eb05917fd831354699b20 \ - --hash=sha256:5a4788036201c908079e89ae3f5399b33bf45b9ea4514913f4dbbe4fac08efe0 \ - --hash=sha256:6b4f04b1fbc01a3569d63359f2227c89ab294550de277fd09d8fca6185669fa4 \ - --hash=sha256:715b41c3e231f7334cbe79dfc698213dcb7211520ec7a3bc2ba20c8515e8a3b5 \ - --hash=sha256:73121a9b7ff93ada888aaee3985a88495489cc027894458cb1a736660bdfb206 \ - --hash=sha256:74ae2441731a05b44d5988d3ac2cf784d3ee0a535dbed257cbfff4be8bb49eb9 \ - --hash=sha256:7d6166192dcd925c78a91d599b48960e0a46fe565391c79fe6de481ac44d20ac \ - --hash=sha256:7f193f060391a455920d61684a70017ef5284ccbe6023bb056e15e5ac3de11d1 \ - --hash=sha256:907fa0b662dd8fc1d7c661b90782ce81afb510fc4b7aa6ae7304d6c094b27bce \ - --hash=sha256:93156dd7f90ae0a1b0e8871032a07ef3178f553f0c70c386025a808f3a63b1f4 \ - --hash=sha256:93bc9e5aaa06ff928d751dc6be889ff3e7d2aa393ab873bc7f6396a99f6fbb12 \ - --hash=sha256:95db0c6581a54b47c30860d013977b8a14febc206c8b5ff562f9fe32738a8aca \ - --hash=sha256:973d030180eca8255b1bce6ffc09ef38a05dcec0e8320cc9b7bcaa65346f341d \ - --hash=sha256:9cd7a6beec6495d1dffb1033d50a3f82dfece23e9eb3c20cd3c2444d27514068 \ - --hash=sha256:9fe9096a60113e1d755e9e6bda15ef7e03391ee0554d22829aa506cdf946f796 \ - --hash=sha256:a209d2e624ba492df4f3bfad5996d1f76f03069c6133c60cd04f9a9e715595ec \ - --hash=sha256:a239afa1126b6a619130909c8404070e2b473dd2b7fc4aacacd2e763f8597fea \ - --hash=sha256:ba9f09ff17f947392a855e3455a846f9855f6cf6bec33e9a427d3c1d254c712f \ - --hash=sha256:bb7273789f69b565d88e97e9e1da602b4ee7ba733caf35a6c2affd4334d4f005 \ - --hash=sha256:bd5bc124fae781a4422f61b98d1d7faa47985f663a64770b78f13d2c072410c2 \ - --hash=sha256:bff98816cb144fb7b85e4b5ba3888a33b56ecef075b0e95b95bcd0a5fbf20f06 \ - --hash=sha256:c4ee5a24e281fbd8261c6ab29faa7fd9a87a12e8c0eed485b705236c65999109 \ - --hash=sha256:c93ed66d32de1559b6fc348838c7572d5c0ac1e4a258e76763a5caddd8944002 \ - --hash=sha256:d1a24f51a3305362b94681120c508758a88f207fa0a681c16b5a4172e9e6c7a9 \ - --hash=sha256:d8f191a17369bd53a5557a5ee4bab91d5330ca3aefcdf17fab9a497b0e7cff7a \ - --hash=sha256:daaef7390e632283051e3cf3e16aff2b68b247e99aea916f64e578c0449c9c68 \ - --hash=sha256:e40013572bfb843d6794a3ce076c29ef4efd15937ab833f520117f8eccc84fd6 \ - --hash=sha256:eceef49f457253000e6a2d0f7bd08ff4e9fe96ec4ffce2dbcb32e34d9c1b8161 \ - --hash=sha256:ee595d7ba9bba130b2bec555a40aafa60c26ce68ed0cf509983e0f12d88674fd \ - --hash=sha256:ef50ec31649fbc3acf6afd261ed89d09eb909b97cc289d80476166df8438524d \ - --hash=sha256:fa1f3e34373aa16045484b4d9d352d4c6b5f9f77ac77a178252ccbc851e8b2ee \ - --hash=sha256:fca66d9ff2ac89b03f5aa17e0b21a97c21f3491c46b583bb131eb32c7bab33af +fonttools[woff]==4.53.1 \ + --hash=sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122 \ + --hash=sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397 \ + --hash=sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f \ + --hash=sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d \ + --hash=sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60 \ + --hash=sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169 \ + --hash=sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8 \ + --hash=sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31 \ + --hash=sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923 \ + --hash=sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2 \ + --hash=sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb \ + --hash=sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab \ + --hash=sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb \ + --hash=sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a \ + --hash=sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670 \ + --hash=sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8 \ + --hash=sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407 \ + --hash=sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671 \ + --hash=sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88 \ + --hash=sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f \ + --hash=sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f \ + --hash=sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0 \ + --hash=sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb \ + --hash=sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2 \ + --hash=sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d \ + --hash=sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c \ + --hash=sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3 \ + --hash=sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719 \ + --hash=sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749 \ + --hash=sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4 \ + --hash=sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f \ + --hash=sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02 \ + --hash=sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58 \ + --hash=sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1 \ + --hash=sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41 \ + --hash=sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4 \ + --hash=sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb \ + --hash=sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb \ + --hash=sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3 \ + --hash=sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d \ + --hash=sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d \ + --hash=sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2 # via weasyprint googleapis-common-protos==1.63.2 \ --hash=sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945 \ @@ -611,59 +622,59 @@ googleapis-common-protos==1.63.2 \ # via # opentelemetry-exporter-otlp-proto-grpc # opentelemetry-exporter-otlp-proto-http -grpcio==1.64.1 \ - --hash=sha256:03b43d0ccf99c557ec671c7dede64f023c7da9bb632ac65dbc57f166e4970040 \ - --hash=sha256:0a12ddb1678ebc6a84ec6b0487feac020ee2b1659cbe69b80f06dbffdb249122 \ - --hash=sha256:0a2813093ddb27418a4c99f9b1c223fab0b053157176a64cc9db0f4557b69bd9 \ - --hash=sha256:0cc79c982ccb2feec8aad0e8fb0d168bcbca85bc77b080d0d3c5f2f15c24ea8f \ - --hash=sha256:1257b76748612aca0f89beec7fa0615727fd6f2a1ad580a9638816a4b2eb18fd \ - --hash=sha256:1262402af5a511c245c3ae918167eca57342c72320dffae5d9b51840c4b2f86d \ - --hash=sha256:19264fc964576ddb065368cae953f8d0514ecc6cb3da8903766d9fb9d4554c33 \ - --hash=sha256:198908f9b22e2672a998870355e226a725aeab327ac4e6ff3a1399792ece4762 \ - --hash=sha256:1de403fc1305fd96cfa75e83be3dee8538f2413a6b1685b8452301c7ba33c294 \ - --hash=sha256:20405cb8b13fd779135df23fabadc53b86522d0f1cba8cca0e87968587f50650 \ - --hash=sha256:2981c7365a9353f9b5c864595c510c983251b1ab403e05b1ccc70a3d9541a73b \ - --hash=sha256:2c3c1b90ab93fed424e454e93c0ed0b9d552bdf1b0929712b094f5ecfe7a23ad \ - --hash=sha256:39b9d0acaa8d835a6566c640f48b50054f422d03e77e49716d4c4e8e279665a1 \ - --hash=sha256:3b64ae304c175671efdaa7ec9ae2cc36996b681eb63ca39c464958396697daff \ - --hash=sha256:4657d24c8063e6095f850b68f2d1ba3b39f2b287a38242dcabc166453e950c59 \ - --hash=sha256:4d6dab6124225496010bd22690f2d9bd35c7cbb267b3f14e7a3eb05c911325d4 \ - --hash=sha256:55260032b95c49bee69a423c2f5365baa9369d2f7d233e933564d8a47b893027 \ - --hash=sha256:55697ecec192bc3f2f3cc13a295ab670f51de29884ca9ae6cd6247df55df2502 \ - --hash=sha256:5841dd1f284bd1b3d8a6eca3a7f062b06f1eec09b184397e1d1d43447e89a7ae \ - --hash=sha256:58b1041e7c870bb30ee41d3090cbd6f0851f30ae4eb68228955d973d3efa2e61 \ - --hash=sha256:5e42634a989c3aa6049f132266faf6b949ec2a6f7d302dbb5c15395b77d757eb \ - --hash=sha256:5e56462b05a6f860b72f0fa50dca06d5b26543a4e88d0396259a07dc30f4e5aa \ - --hash=sha256:5f8b75f64d5d324c565b263c67dbe4f0af595635bbdd93bb1a88189fc62ed2e5 \ - --hash=sha256:62b4e6eb7bf901719fce0ca83e3ed474ae5022bb3827b0a501e056458c51c0a1 \ - --hash=sha256:6503b64c8b2dfad299749cad1b595c650c91e5b2c8a1b775380fcf8d2cbba1e9 \ - --hash=sha256:6c024ffc22d6dc59000faf8ad781696d81e8e38f4078cb0f2630b4a3cf231a90 \ - --hash=sha256:73819689c169417a4f978e562d24f2def2be75739c4bed1992435d007819da1b \ - --hash=sha256:75dbbf415026d2862192fe1b28d71f209e2fd87079d98470db90bebe57b33179 \ - --hash=sha256:8caee47e970b92b3dd948371230fcceb80d3f2277b3bf7fbd7c0564e7d39068e \ - --hash=sha256:8d51dd1c59d5fa0f34266b80a3805ec29a1f26425c2a54736133f6d87fc4968a \ - --hash=sha256:940e3ec884520155f68a3b712d045e077d61c520a195d1a5932c531f11883489 \ - --hash=sha256:a011ac6c03cfe162ff2b727bcb530567826cec85eb8d4ad2bfb4bd023287a52d \ - --hash=sha256:a3a035c37ce7565b8f4f35ff683a4db34d24e53dc487e47438e434eb3f701b2a \ - --hash=sha256:a5e771d0252e871ce194d0fdcafd13971f1aae0ddacc5f25615030d5df55c3a2 \ - --hash=sha256:ac15b6c2c80a4d1338b04d42a02d376a53395ddf0ec9ab157cbaf44191f3ffdd \ - --hash=sha256:b1a82e0b9b3022799c336e1fc0f6210adc019ae84efb7321d668129d28ee1efb \ - --hash=sha256:bac71b4b28bc9af61efcdc7630b166440bbfbaa80940c9a697271b5e1dabbc61 \ - --hash=sha256:bbc5b1d78a7822b0a84c6f8917faa986c1a744e65d762ef6d8be9d75677af2ca \ - --hash=sha256:c1a786ac592b47573a5bb7e35665c08064a5d77ab88a076eec11f8ae86b3e3f6 \ - --hash=sha256:c84ad903d0d94311a2b7eea608da163dace97c5fe9412ea311e72c3684925602 \ - --hash=sha256:d4d29cc612e1332237877dfa7fe687157973aab1d63bd0f84cf06692f04c0367 \ - --hash=sha256:e3d9f8d1221baa0ced7ec7322a981e28deb23749c76eeeb3d33e18b72935ab62 \ - --hash=sha256:e7cd5c1325f6808b8ae31657d281aadb2a51ac11ab081ae335f4f7fc44c1721d \ - --hash=sha256:ed6091fa0adcc7e4ff944090cf203a52da35c37a130efa564ded02b7aff63bcd \ - --hash=sha256:ee73a2f5ca4ba44fa33b4d7d2c71e2c8a9e9f78d53f6507ad68e7d2ad5f64a22 \ - --hash=sha256:f10193c69fc9d3d726e83bbf0f3d316f1847c3071c8c93d8090cf5f326b14309 +grpcio==1.65.5 \ + --hash=sha256:05f02d68fc720e085f061b704ee653b181e6d5abfe315daef085719728d3d1fd \ + --hash=sha256:078038e150a897e5e402ed3d57f1d31ebf604cbed80f595bd281b5da40762a92 \ + --hash=sha256:0b2944390a496567de9e70418f3742b477d85d8ca065afa90432edc91b4bb8ad \ + --hash=sha256:11f8b16121768c1cb99d7dcb84e01510e60e6a206bf9123e134118802486f035 \ + --hash=sha256:1c4caafe71aef4dabf53274bbf4affd6df651e9f80beedd6b8e08ff438ed3260 \ + --hash=sha256:1cbc208edb9acf1cc339396a1a36b83796939be52f34e591c90292045b579fbf \ + --hash=sha256:238a625f391a1b9f5f069bdc5930f4fd71b74426bea52196fc7b83f51fa97d34 \ + --hash=sha256:2a6d8169812932feac514b420daffae8ab8e36f90f3122b94ae767e633296b17 \ + --hash=sha256:2b91ce647b6307f25650872454a4d02a2801f26a475f90d0b91ed8110baae589 \ + --hash=sha256:3207ae60d07e5282c134b6e02f9271a2cb523c6d7a346c6315211fe2bf8d61ed \ + --hash=sha256:32d60e18ff7c34fe3f6db3d35ad5c6dc99f5b43ff3982cb26fad4174462d10b1 \ + --hash=sha256:33158e56c6378063923c417e9fbdb28660b6e0e2835af42e67f5a7793f587af7 \ + --hash=sha256:47d0aaaab82823f0aa6adea5184350b46e2252e13a42a942db84da5b733f2e05 \ + --hash=sha256:55714ea852396ec9568f45f487639945ab674de83c12bea19d5ddbc3ae41ada3 \ + --hash=sha256:6c4e62bcf297a1568f627f39576dbfc27f1e5338a691c6dd5dd6b3979da51d1c \ + --hash=sha256:76991b7a6fb98630a3328839755181ce7c1aa2b1842aa085fd4198f0e5198960 \ + --hash=sha256:770bd4bd721961f6dd8049bc27338564ba8739913f77c0f381a9815e465ff965 \ + --hash=sha256:7a412959aa5f08c5ac04aa7b7c3c041f5e4298cadd4fcc2acff195b56d185ebc \ + --hash=sha256:84c901cdec16a092099f251ef3360d15e29ef59772150fa261d94573612539b5 \ + --hash=sha256:85ae8f8517d5bcc21fb07dbf791e94ed84cc28f84c903cdc2bd7eaeb437c8f45 \ + --hash=sha256:89c00a18801b1ed9cc441e29b521c354725d4af38c127981f2c950c796a09b6e \ + --hash=sha256:8da58ff80bc4556cf29bc03f5fff1f03b8387d6aaa7b852af9eb65b2cf833be4 \ + --hash=sha256:8e5c4c15ac3fe1eb68e46bc51e66ad29be887479f231f8237cf8416058bf0cc1 \ + --hash=sha256:a101696f9ece90a0829988ff72f1b1ea2358f3df035bdf6d675dd8b60c2c0894 \ + --hash=sha256:a2f80510f99f82d4eb825849c486df703f50652cea21c189eacc2b84f2bde764 \ + --hash=sha256:a70a20eed87bba647a38bedd93b3ce7db64b3f0e8e0952315237f7f5ca97b02d \ + --hash=sha256:a80e9a5e3f93c54f5eb82a3825ea1fc4965b2fa0026db2abfecb139a5c4ecdf1 \ + --hash=sha256:ab5ec837d8cee8dbce9ef6386125f119b231e4333cc6b6d57b6c5c7c82a72331 \ + --hash=sha256:b67d450f1e008fedcd81e097a3a400a711d8be1a8b20f852a7b8a73fead50fe3 \ + --hash=sha256:b7ca419f1462390851eec395b2089aad1e49546b52d4e2c972ceb76da69b10f8 \ + --hash=sha256:b8270b15b99781461b244f5c81d5c2bc9696ab9189fb5ff86c841417fb3b39fe \ + --hash=sha256:bc74f3f745c37e2c5685c9d2a2d5a94de00f286963f5213f763ae137bf4f2358 \ + --hash=sha256:c3655139d7be213c32c79ef6fb2367cae28e56ef68e39b1961c43214b457f257 \ + --hash=sha256:c97962720489ef31b5ad8a916e22bc31bba3664e063fb9f6702dce056d4aa61b \ + --hash=sha256:cabd706183ee08d8026a015af5819a0b3a8959bdc9d1f6fdacd1810f09200f2a \ + --hash=sha256:d3a9e35bcb045e39d7cac30464c285389b9a816ac2067e4884ad2c02e709ef8e \ + --hash=sha256:d750e9330eb14236ca11b78d0c494eed13d6a95eb55472298f0e547c165ee324 \ + --hash=sha256:d7df567b67d16d4177835a68d3f767bbcbad04da9dfb52cbd19171f430c898bd \ + --hash=sha256:ec6f219fb5d677a522b0deaf43cea6697b16f338cb68d009e30930c4aa0d2209 \ + --hash=sha256:ec71fc5b39821ad7d80db7473c8f8c2910f3382f0ddadfbcfc2c6c437107eb67 \ + --hash=sha256:ee6ed64a27588a2c94e8fa84fe8f3b5c89427d4d69c37690903d428ec61ca7e4 \ + --hash=sha256:f17f9fa2d947dbfaca01b3ab2c62eefa8240131fdc67b924eb42ce6032e3e5c1 \ + --hash=sha256:f5b5970341359341d0e4c789da7568264b2a89cd976c05ea476036852b5950cd \ + --hash=sha256:f79c87c114bf37adf408026b9e2e333fe9ff31dfc9648f6f80776c513145c813 \ + --hash=sha256:fa36dd8496d3af0d40165252a669fa4f6fd2db4b4026b9a9411cbf060b9d6a15 \ + --hash=sha256:fe6505376f5b00bb008e4e1418152e3ad3d954b629da286c7913ff3cfc0ff740 # via # -r src/backend/requirements.in # opentelemetry-exporter-otlp-proto-grpc -gunicorn==22.0.0 \ - --hash=sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9 \ - --hash=sha256:4a0b436239ff76fb33f11c07a16482c521a7e09c1ce3cc293c2330afe01bec63 +gunicorn==23.0.0 \ + --hash=sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d \ + --hash=sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec # via -r src/backend/requirements.in html5lib==1.1 \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ @@ -677,9 +688,9 @@ idna==3.7 \ --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 # via requests -importlib-metadata==7.1.0 \ - --hash=sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 \ - --hash=sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2 +importlib-metadata==8.0.0 \ + --hash=sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f \ + --hash=sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812 # via # django-q2 # markdown @@ -700,163 +711,159 @@ jinja2==3.1.4 \ --hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \ --hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d # via coreschema -jsonschema==4.22.0 \ - --hash=sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7 \ - --hash=sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802 +jsonschema==4.23.0 \ + --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \ + --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566 # via drf-spectacular jsonschema-specifications==2023.12.1 \ --hash=sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc \ --hash=sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c # via jsonschema -lxml==5.2.2 \ - --hash=sha256:02437fb7308386867c8b7b0e5bc4cd4b04548b1c5d089ffb8e7b31009b961dc3 \ - --hash=sha256:02f6a8eb6512fdc2fd4ca10a49c341c4e109aa6e9448cc4859af5b949622715a \ - --hash=sha256:05f8757b03208c3f50097761be2dea0aba02e94f0dc7023ed73a7bb14ff11eb0 \ - --hash=sha256:06668e39e1f3c065349c51ac27ae430719d7806c026fec462e5693b08b95696b \ - --hash=sha256:07542787f86112d46d07d4f3c4e7c760282011b354d012dc4141cc12a68cef5f \ - --hash=sha256:08ea0f606808354eb8f2dfaac095963cb25d9d28e27edcc375d7b30ab01abbf6 \ - --hash=sha256:0969e92af09c5687d769731e3f39ed62427cc72176cebb54b7a9d52cc4fa3b73 \ - --hash=sha256:0a028b61a2e357ace98b1615fc03f76eb517cc028993964fe08ad514b1e8892d \ - --hash=sha256:0b3f5016e00ae7630a4b83d0868fca1e3d494c78a75b1c7252606a3a1c5fc2ad \ - --hash=sha256:13e69be35391ce72712184f69000cda04fc89689429179bc4c0ae5f0b7a8c21b \ - --hash=sha256:16a8326e51fcdffc886294c1e70b11ddccec836516a343f9ed0f82aac043c24a \ - --hash=sha256:19b4e485cd07b7d83e3fe3b72132e7df70bfac22b14fe4bf7a23822c3a35bff5 \ - --hash=sha256:1a2569a1f15ae6c8c64108a2cd2b4a858fc1e13d25846be0666fc144715e32ab \ - --hash=sha256:1a7aca7964ac4bb07680d5c9d63b9d7028cace3e2d43175cb50bba8c5ad33316 \ - --hash=sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6 \ - --hash=sha256:1d8a701774dfc42a2f0b8ccdfe7dbc140500d1049e0632a611985d943fcf12df \ - --hash=sha256:1e275ea572389e41e8b039ac076a46cb87ee6b8542df3fff26f5baab43713bca \ - --hash=sha256:2304d3c93f2258ccf2cf7a6ba8c761d76ef84948d87bf9664e14d203da2cd264 \ - --hash=sha256:23441e2b5339bc54dc949e9e675fa35efe858108404ef9aa92f0456929ef6fe8 \ - --hash=sha256:23cfafd56887eaed93d07bc4547abd5e09d837a002b791e9767765492a75883f \ - --hash=sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b \ - --hash=sha256:2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3 \ - --hash=sha256:2fb0ba3e8566548d6c8e7dd82a8229ff47bd8fb8c2da237607ac8e5a1b8312e5 \ - --hash=sha256:303f540ad2dddd35b92415b74b900c749ec2010e703ab3bfd6660979d01fd4ed \ - --hash=sha256:339ee4a4704bc724757cd5dd9dc8cf4d00980f5d3e6e06d5847c1b594ace68ab \ - --hash=sha256:33ce9e786753743159799fdf8e92a5da351158c4bfb6f2db0bf31e7892a1feb5 \ - --hash=sha256:343ab62e9ca78094f2306aefed67dcfad61c4683f87eee48ff2fd74902447726 \ - --hash=sha256:34e17913c431f5ae01d8658dbf792fdc457073dcdfbb31dc0cc6ab256e664a8d \ - --hash=sha256:364d03207f3e603922d0d3932ef363d55bbf48e3647395765f9bfcbdf6d23632 \ - --hash=sha256:38b67afb0a06b8575948641c1d6d68e41b83a3abeae2ca9eed2ac59892b36706 \ - --hash=sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8 \ - --hash=sha256:3b019d4ee84b683342af793b56bb35034bd749e4cbdd3d33f7d1107790f8c472 \ - --hash=sha256:3b6a30a9ab040b3f545b697cb3adbf3696c05a3a68aad172e3fd7ca73ab3c835 \ - --hash=sha256:3d1e35572a56941b32c239774d7e9ad724074d37f90c7a7d499ab98761bd80cf \ - --hash=sha256:3d98de734abee23e61f6b8c2e08a88453ada7d6486dc7cdc82922a03968928db \ - --hash=sha256:453d037e09a5176d92ec0fd282e934ed26d806331a8b70ab431a81e2fbabf56d \ - --hash=sha256:45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545 \ - --hash=sha256:4820c02195d6dfb7b8508ff276752f6b2ff8b64ae5d13ebe02e7667e035000b9 \ - --hash=sha256:49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be \ - --hash=sha256:4aefd911793b5d2d7a921233a54c90329bf3d4a6817dc465f12ffdfe4fc7b8fe \ - --hash=sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905 \ - --hash=sha256:4c30a2f83677876465f44c018830f608fa3c6a8a466eb223535035fbc16f3438 \ - --hash=sha256:50127c186f191b8917ea2fb8b206fbebe87fd414a6084d15568c27d0a21d60db \ - --hash=sha256:50ccb5d355961c0f12f6cf24b7187dbabd5433f29e15147a67995474f27d1776 \ - --hash=sha256:519895c99c815a1a24a926d5b60627ce5ea48e9f639a5cd328bda0515ea0f10c \ - --hash=sha256:54401c77a63cc7d6dc4b4e173bb484f28a5607f3df71484709fe037c92d4f0ed \ - --hash=sha256:546cf886f6242dff9ec206331209db9c8e1643ae642dea5fdbecae2453cb50fd \ - --hash=sha256:55ce6b6d803890bd3cc89975fca9de1dff39729b43b73cb15ddd933b8bc20484 \ - --hash=sha256:56793b7a1a091a7c286b5f4aa1fe4ae5d1446fe742d00cdf2ffb1077865db10d \ - --hash=sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6 \ - --hash=sha256:5b8c041b6265e08eac8a724b74b655404070b636a8dd6d7a13c3adc07882ef30 \ - --hash=sha256:5e097646944b66207023bc3c634827de858aebc226d5d4d6d16f0b77566ea182 \ - --hash=sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61 \ - --hash=sha256:610b5c77428a50269f38a534057444c249976433f40f53e3b47e68349cca1425 \ - --hash=sha256:625e3ef310e7fa3a761d48ca7ea1f9d8718a32b1542e727d584d82f4453d5eeb \ - --hash=sha256:657a972f46bbefdbba2d4f14413c0d079f9ae243bd68193cb5061b9732fa54c1 \ - --hash=sha256:69ab77a1373f1e7563e0fb5a29a8440367dec051da6c7405333699d07444f511 \ - --hash=sha256:6a520b4f9974b0a0a6ed73c2154de57cdfd0c8800f4f15ab2b73238ffed0b36e \ - --hash=sha256:6d68ce8e7b2075390e8ac1e1d3a99e8b6372c694bbe612632606d1d546794207 \ - --hash=sha256:6dcc3d17eac1df7859ae01202e9bb11ffa8c98949dcbeb1069c8b9a75917e01b \ - --hash=sha256:6dfdc2bfe69e9adf0df4915949c22a25b39d175d599bf98e7ddf620a13678585 \ - --hash=sha256:739e36ef7412b2bd940f75b278749106e6d025e40027c0b94a17ef7968d55d56 \ - --hash=sha256:7429e7faa1a60cad26ae4227f4dd0459efde239e494c7312624ce228e04f6391 \ - --hash=sha256:74da9f97daec6928567b48c90ea2c82a106b2d500f397eeb8941e47d30b1ca85 \ - --hash=sha256:74e4f025ef3db1c6da4460dd27c118d8cd136d0391da4e387a15e48e5c975147 \ - --hash=sha256:75a9632f1d4f698b2e6e2e1ada40e71f369b15d69baddb8968dcc8e683839b18 \ - --hash=sha256:76acba4c66c47d27c8365e7c10b3d8016a7da83d3191d053a58382311a8bf4e1 \ - --hash=sha256:79d1fb9252e7e2cfe4de6e9a6610c7cbb99b9708e2c3e29057f487de5a9eaefa \ - --hash=sha256:7ce7ad8abebe737ad6143d9d3bf94b88b93365ea30a5b81f6877ec9c0dee0a48 \ - --hash=sha256:7ed07b3062b055d7a7f9d6557a251cc655eed0b3152b76de619516621c56f5d3 \ - --hash=sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184 \ - --hash=sha256:8268cbcd48c5375f46e000adb1390572c98879eb4f77910c6053d25cc3ac2c67 \ - --hash=sha256:875a3f90d7eb5c5d77e529080d95140eacb3c6d13ad5b616ee8095447b1d22e7 \ - --hash=sha256:89feb82ca055af0fe797a2323ec9043b26bc371365847dbe83c7fd2e2f181c34 \ - --hash=sha256:8a7e24cb69ee5f32e003f50e016d5fde438010c1022c96738b04fc2423e61706 \ - --hash=sha256:8ab6a358d1286498d80fe67bd3d69fcbc7d1359b45b41e74c4a26964ca99c3f8 \ - --hash=sha256:8b8df03a9e995b6211dafa63b32f9d405881518ff1ddd775db4e7b98fb545e1c \ - --hash=sha256:8cf85a6e40ff1f37fe0f25719aadf443686b1ac7652593dc53c7ef9b8492b115 \ - --hash=sha256:8e8d351ff44c1638cb6e980623d517abd9f580d2e53bfcd18d8941c052a5a009 \ - --hash=sha256:9164361769b6ca7769079f4d426a41df6164879f7f3568be9086e15baca61466 \ - --hash=sha256:96e85aa09274955bb6bd483eaf5b12abadade01010478154b0ec70284c1b1526 \ - --hash=sha256:981a06a3076997adf7c743dcd0d7a0415582661e2517c7d961493572e909aa1d \ - --hash=sha256:9cd5323344d8ebb9fb5e96da5de5ad4ebab993bbf51674259dbe9d7a18049525 \ - --hash=sha256:9d6c6ea6a11ca0ff9cd0390b885984ed31157c168565702959c25e2191674a14 \ - --hash=sha256:a02d3c48f9bb1e10c7788d92c0c7db6f2002d024ab6e74d6f45ae33e3d0288a3 \ - --hash=sha256:a233bb68625a85126ac9f1fc66d24337d6e8a0f9207b688eec2e7c880f012ec0 \ - --hash=sha256:a2f6a1bc2460e643785a2cde17293bd7a8f990884b822f7bca47bee0a82fc66b \ - --hash=sha256:a6d17e0370d2516d5bb9062c7b4cb731cff921fc875644c3d751ad857ba9c5b1 \ - --hash=sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f \ - --hash=sha256:ab67ed772c584b7ef2379797bf14b82df9aa5f7438c5b9a09624dd834c1c1aaf \ - --hash=sha256:ac6540c9fff6e3813d29d0403ee7a81897f1d8ecc09a8ff84d2eea70ede1cdbf \ - --hash=sha256:ae4073a60ab98529ab8a72ebf429f2a8cc612619a8c04e08bed27450d52103c0 \ - --hash=sha256:ae791f6bd43305aade8c0e22f816b34f3b72b6c820477aab4d18473a37e8090b \ - --hash=sha256:aef5474d913d3b05e613906ba4090433c515e13ea49c837aca18bde190853dff \ - --hash=sha256:b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88 \ - --hash=sha256:b128092c927eaf485928cec0c28f6b8bead277e28acf56800e972aa2c2abd7a2 \ - --hash=sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40 \ - --hash=sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716 \ - --hash=sha256:b47633251727c8fe279f34025844b3b3a3e40cd1b198356d003aa146258d13a2 \ - --hash=sha256:b537bd04d7ccd7c6350cdaaaad911f6312cbd61e6e6045542f781c7f8b2e99d2 \ - --hash=sha256:b5e4ef22ff25bfd4ede5f8fb30f7b24446345f3e79d9b7455aef2836437bc38a \ - --hash=sha256:b74b9ea10063efb77a965a8d5f4182806fbf59ed068b3c3fd6f30d2ac7bee734 \ - --hash=sha256:bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87 \ - --hash=sha256:bbc4b80af581e18568ff07f6395c02114d05f4865c2812a1f02f2eaecf0bfd48 \ - --hash=sha256:bcc98f911f10278d1daf14b87d65325851a1d29153caaf146877ec37031d5f36 \ - --hash=sha256:be49ad33819d7dcc28a309b86d4ed98e1a65f3075c6acd3cd4fe32103235222b \ - --hash=sha256:bec4bd9133420c5c52d562469c754f27c5c9e36ee06abc169612c959bd7dbb07 \ - --hash=sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c \ - --hash=sha256:c689d0d5381f56de7bd6966a4541bff6e08bf8d3871bbd89a0c6ab18aa699573 \ - --hash=sha256:c7079d5eb1c1315a858bbf180000757db8ad904a89476653232db835c3114001 \ - --hash=sha256:cb3942960f0beb9f46e2a71a3aca220d1ca32feb5a398656be934320804c0df9 \ - --hash=sha256:cd9e78285da6c9ba2d5c769628f43ef66d96ac3085e59b10ad4f3707980710d3 \ - --hash=sha256:cf2a978c795b54c539f47964ec05e35c05bd045db5ca1e8366988c7f2fe6b3ce \ - --hash=sha256:d14a0d029a4e176795cef99c056d58067c06195e0c7e2dbb293bf95c08f772a3 \ - --hash=sha256:d237ba6664b8e60fd90b8549a149a74fcc675272e0e95539a00522e4ca688b04 \ - --hash=sha256:d26a618ae1766279f2660aca0081b2220aca6bd1aa06b2cf73f07383faf48927 \ - --hash=sha256:d28cb356f119a437cc58a13f8135ab8a4c8ece18159eb9194b0d269ec4e28083 \ - --hash=sha256:d4ed0c7cbecde7194cd3228c044e86bf73e30a23505af852857c09c24e77ec5d \ - --hash=sha256:d83e2d94b69bf31ead2fa45f0acdef0757fa0458a129734f59f67f3d2eb7ef32 \ - --hash=sha256:d8bbcd21769594dbba9c37d3c819e2d5847656ca99c747ddb31ac1701d0c0ed9 \ - --hash=sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f \ - --hash=sha256:dc911208b18842a3a57266d8e51fc3cfaccee90a5351b92079beed912a7914c2 \ - --hash=sha256:dfa7c241073d8f2b8e8dbc7803c434f57dbb83ae2a3d7892dd068d99e96efe2c \ - --hash=sha256:e282aedd63c639c07c3857097fc0e236f984ceb4089a8b284da1c526491e3f3d \ - --hash=sha256:e290d79a4107d7d794634ce3e985b9ae4f920380a813717adf61804904dc4393 \ - --hash=sha256:e3d9d13603410b72787579769469af730c38f2f25505573a5888a94b62b920f8 \ - --hash=sha256:e481bba1e11ba585fb06db666bfc23dbe181dbafc7b25776156120bf12e0d5a6 \ - --hash=sha256:e49b052b768bb74f58c7dda4e0bdf7b79d43a9204ca584ffe1fb48a6f3c84c66 \ - --hash=sha256:eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5 \ - --hash=sha256:ec87c44f619380878bd49ca109669c9f221d9ae6883a5bcb3616785fa8f94c97 \ - --hash=sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196 \ - --hash=sha256:f11ae142f3a322d44513de1018b50f474f8f736bc3cd91d969f464b5bfef8836 \ - --hash=sha256:f2a09f6184f17a80897172863a655467da2b11151ec98ba8d7af89f17bf63dae \ - --hash=sha256:f5b65529bb2f21ac7861a0e94fdbf5dc0daab41497d18223b46ee8515e5ad297 \ - --hash=sha256:f60fdd125d85bf9c279ffb8e94c78c51b3b6a37711464e1f5f31078b45002421 \ - --hash=sha256:f61efaf4bed1cc0860e567d2ecb2363974d414f7f1f124b1df368bbf183453a6 \ - --hash=sha256:f90e552ecbad426eab352e7b2933091f2be77115bb16f09f78404861c8322981 \ - --hash=sha256:f956196ef61369f1685d14dad80611488d8dc1ef00be57c0c5a03064005b0f30 \ - --hash=sha256:fb91819461b1b56d06fa4bcf86617fac795f6a99d12239fb0c68dbeba41a0a30 \ - --hash=sha256:fbc9d316552f9ef7bba39f4edfad4a734d3d6f93341232a9dddadec4f15d425f \ - --hash=sha256:ff69a9a0b4b17d78170c73abe2ab12084bdf1691550c5629ad1fe7849433f324 \ - --hash=sha256:ffb2be176fed4457e445fe540617f0252a72a8bc56208fd65a690fdb1f57660b +lxml==5.3.0 \ + --hash=sha256:01220dca0d066d1349bd6a1726856a78f7929f3878f7e2ee83c296c69495309e \ + --hash=sha256:02ced472497b8362c8e902ade23e3300479f4f43e45f4105c85ef43b8db85229 \ + --hash=sha256:052d99051e77a4f3e8482c65014cf6372e61b0a6f4fe9edb98503bb5364cfee3 \ + --hash=sha256:07da23d7ee08577760f0a71d67a861019103e4812c87e2fab26b039054594cc5 \ + --hash=sha256:094cb601ba9f55296774c2d57ad68730daa0b13dc260e1f941b4d13678239e70 \ + --hash=sha256:0a7056921edbdd7560746f4221dca89bb7a3fe457d3d74267995253f46343f15 \ + --hash=sha256:0c120f43553ec759f8de1fee2f4794452b0946773299d44c36bfe18e83caf002 \ + --hash=sha256:0d7b36afa46c97875303a94e8f3ad932bf78bace9e18e603f2085b652422edcd \ + --hash=sha256:0fdf3a3059611f7585a78ee10399a15566356116a4288380921a4b598d807a22 \ + --hash=sha256:109fa6fede314cc50eed29e6e56c540075e63d922455346f11e4d7a036d2b8cf \ + --hash=sha256:146173654d79eb1fc97498b4280c1d3e1e5d58c398fa530905c9ea50ea849b22 \ + --hash=sha256:1473427aff3d66a3fa2199004c3e601e6c4500ab86696edffdbc84954c72d832 \ + --hash=sha256:1483fd3358963cc5c1c9b122c80606a3a79ee0875bcac0204149fa09d6ff2727 \ + --hash=sha256:168f2dfcfdedf611eb285efac1516c8454c8c99caf271dccda8943576b67552e \ + --hash=sha256:17e8d968d04a37c50ad9c456a286b525d78c4a1c15dd53aa46c1d8e06bf6fa30 \ + --hash=sha256:18feb4b93302091b1541221196a2155aa296c363fd233814fa11e181adebc52f \ + --hash=sha256:1afe0a8c353746e610bd9031a630a95bcfb1a720684c3f2b36c4710a0a96528f \ + --hash=sha256:1d04f064bebdfef9240478f7a779e8c5dc32b8b7b0b2fc6a62e39b928d428e51 \ + --hash=sha256:1fdc9fae8dd4c763e8a31e7630afef517eab9f5d5d31a278df087f307bf601f4 \ + --hash=sha256:1ffc23010330c2ab67fac02781df60998ca8fe759e8efde6f8b756a20599c5de \ + --hash=sha256:20094fc3f21ea0a8669dc4c61ed7fa8263bd37d97d93b90f28fc613371e7a875 \ + --hash=sha256:213261f168c5e1d9b7535a67e68b1f59f92398dd17a56d934550837143f79c42 \ + --hash=sha256:218c1b2e17a710e363855594230f44060e2025b05c80d1f0661258142b2add2e \ + --hash=sha256:23e0553b8055600b3bf4a00b255ec5c92e1e4aebf8c2c09334f8368e8bd174d6 \ + --hash=sha256:25f1b69d41656b05885aa185f5fdf822cb01a586d1b32739633679699f220391 \ + --hash=sha256:2b3778cb38212f52fac9fe913017deea2fdf4eb1a4f8e4cfc6b009a13a6d3fcc \ + --hash=sha256:2bc9fd5ca4729af796f9f59cd8ff160fe06a474da40aca03fcc79655ddee1a8b \ + --hash=sha256:2c226a06ecb8cdef28845ae976da407917542c5e6e75dcac7cc33eb04aaeb237 \ + --hash=sha256:2c3406b63232fc7e9b8783ab0b765d7c59e7c59ff96759d8ef9632fca27c7ee4 \ + --hash=sha256:2c86bf781b12ba417f64f3422cfc302523ac9cd1d8ae8c0f92a1c66e56ef2e86 \ + --hash=sha256:2d9b8d9177afaef80c53c0a9e30fa252ff3036fb1c6494d427c066a4ce6a282f \ + --hash=sha256:2dec2d1130a9cda5b904696cec33b2cfb451304ba9081eeda7f90f724097300a \ + --hash=sha256:2dfab5fa6a28a0b60a20638dc48e6343c02ea9933e3279ccb132f555a62323d8 \ + --hash=sha256:2ecdd78ab768f844c7a1d4a03595038c166b609f6395e25af9b0f3f26ae1230f \ + --hash=sha256:315f9542011b2c4e1d280e4a20ddcca1761993dda3afc7a73b01235f8641e903 \ + --hash=sha256:36aef61a1678cb778097b4a6eeae96a69875d51d1e8f4d4b491ab3cfb54b5a03 \ + --hash=sha256:384aacddf2e5813a36495233b64cb96b1949da72bef933918ba5c84e06af8f0e \ + --hash=sha256:3879cc6ce938ff4eb4900d901ed63555c778731a96365e53fadb36437a131a99 \ + --hash=sha256:3c174dc350d3ec52deb77f2faf05c439331d6ed5e702fc247ccb4e6b62d884b7 \ + --hash=sha256:3eb44520c4724c2e1a57c0af33a379eee41792595023f367ba3952a2d96c2aab \ + --hash=sha256:406246b96d552e0503e17a1006fd27edac678b3fcc9f1be71a2f94b4ff61528d \ + --hash=sha256:41ce1f1e2c7755abfc7e759dc34d7d05fd221723ff822947132dc934d122fe22 \ + --hash=sha256:423b121f7e6fa514ba0c7918e56955a1d4470ed35faa03e3d9f0e3baa4c7e492 \ + --hash=sha256:44264ecae91b30e5633013fb66f6ddd05c006d3e0e884f75ce0b4755b3e3847b \ + --hash=sha256:482c2f67761868f0108b1743098640fbb2a28a8e15bf3f47ada9fa59d9fe08c3 \ + --hash=sha256:4b0c7a688944891086ba192e21c5229dea54382f4836a209ff8d0a660fac06be \ + --hash=sha256:4c1fefd7e3d00921c44dc9ca80a775af49698bbfd92ea84498e56acffd4c5469 \ + --hash=sha256:4e109ca30d1edec1ac60cdbe341905dc3b8f55b16855e03a54aaf59e51ec8c6f \ + --hash=sha256:501d0d7e26b4d261fca8132854d845e4988097611ba2531408ec91cf3fd9d20a \ + --hash=sha256:516f491c834eb320d6c843156440fe7fc0d50b33e44387fcec5b02f0bc118a4c \ + --hash=sha256:51806cfe0279e06ed8500ce19479d757db42a30fd509940b1701be9c86a5ff9a \ + --hash=sha256:562e7494778a69086f0312ec9689f6b6ac1c6b65670ed7d0267e49f57ffa08c4 \ + --hash=sha256:56b9861a71575f5795bde89256e7467ece3d339c9b43141dbdd54544566b3b94 \ + --hash=sha256:5b8f5db71b28b8c404956ddf79575ea77aa8b1538e8b2ef9ec877945b3f46442 \ + --hash=sha256:5c2fb570d7823c2bbaf8b419ba6e5662137f8166e364a8b2b91051a1fb40ab8b \ + --hash=sha256:5c54afdcbb0182d06836cc3d1be921e540be3ebdf8b8a51ee3ef987537455f84 \ + --hash=sha256:5d6a6972b93c426ace71e0be9a6f4b2cfae9b1baed2eed2006076a746692288c \ + --hash=sha256:609251a0ca4770e5a8768ff902aa02bf636339c5a93f9349b48eb1f606f7f3e9 \ + --hash=sha256:62d172f358f33a26d6b41b28c170c63886742f5b6772a42b59b4f0fa10526cb1 \ + --hash=sha256:62f7fdb0d1ed2065451f086519865b4c90aa19aed51081979ecd05a21eb4d1be \ + --hash=sha256:658f2aa69d31e09699705949b5fc4719cbecbd4a97f9656a232e7d6c7be1a367 \ + --hash=sha256:65ab5685d56914b9a2a34d67dd5488b83213d680b0c5d10b47f81da5a16b0b0e \ + --hash=sha256:68934b242c51eb02907c5b81d138cb977b2129a0a75a8f8b60b01cb8586c7b21 \ + --hash=sha256:68b87753c784d6acb8a25b05cb526c3406913c9d988d51f80adecc2b0775d6aa \ + --hash=sha256:69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16 \ + --hash=sha256:6a7095eeec6f89111d03dabfe5883a1fd54da319c94e0fb104ee8f23616b572d \ + --hash=sha256:6b038cc86b285e4f9fea2ba5ee76e89f21ed1ea898e287dc277a25884f3a7dfe \ + --hash=sha256:6ba0d3dcac281aad8a0e5b14c7ed6f9fa89c8612b47939fc94f80b16e2e9bc83 \ + --hash=sha256:6e91cf736959057f7aac7adfc83481e03615a8e8dd5758aa1d95ea69e8931dba \ + --hash=sha256:6ee8c39582d2652dcd516d1b879451500f8db3fe3607ce45d7c5957ab2596040 \ + --hash=sha256:6f651ebd0b21ec65dfca93aa629610a0dbc13dbc13554f19b0113da2e61a4763 \ + --hash=sha256:71a8dd38fbd2f2319136d4ae855a7078c69c9a38ae06e0c17c73fd70fc6caad8 \ + --hash=sha256:74068c601baff6ff021c70f0935b0c7bc528baa8ea210c202e03757c68c5a4ff \ + --hash=sha256:7437237c6a66b7ca341e868cda48be24b8701862757426852c9b3186de1da8a2 \ + --hash=sha256:747a3d3e98e24597981ca0be0fd922aebd471fa99d0043a3842d00cdcad7ad6a \ + --hash=sha256:74bcb423462233bc5d6066e4e98b0264e7c1bed7541fff2f4e34fe6b21563c8b \ + --hash=sha256:78d9b952e07aed35fe2e1a7ad26e929595412db48535921c5013edc8aa4a35ce \ + --hash=sha256:7b1cd427cb0d5f7393c31b7496419da594fe600e6fdc4b105a54f82405e6626c \ + --hash=sha256:7d3d1ca42870cdb6d0d29939630dbe48fa511c203724820fc0fd507b2fb46577 \ + --hash=sha256:7e2f58095acc211eb9d8b5771bf04df9ff37d6b87618d1cbf85f92399c98dae8 \ + --hash=sha256:7f41026c1d64043a36fda21d64c5026762d53a77043e73e94b71f0521939cc71 \ + --hash=sha256:81b4e48da4c69313192d8c8d4311e5d818b8be1afe68ee20f6385d0e96fc9512 \ + --hash=sha256:86a6b24b19eaebc448dc56b87c4865527855145d851f9fc3891673ff97950540 \ + --hash=sha256:874a216bf6afaf97c263b56371434e47e2c652d215788396f60477540298218f \ + --hash=sha256:89e043f1d9d341c52bf2af6d02e6adde62e0a46e6755d5eb60dc6e4f0b8aeca2 \ + --hash=sha256:8c72e9563347c7395910de6a3100a4840a75a6f60e05af5e58566868d5eb2d6a \ + --hash=sha256:8dc2c0395bea8254d8daebc76dcf8eb3a95ec2a46fa6fae5eaccee366bfe02ce \ + --hash=sha256:8f0de2d390af441fe8b2c12626d103540b5d850d585b18fcada58d972b74a74e \ + --hash=sha256:92e67a0be1639c251d21e35fe74df6bcc40cba445c2cda7c4a967656733249e2 \ + --hash=sha256:94d6c3782907b5e40e21cadf94b13b0842ac421192f26b84c45f13f3c9d5dc27 \ + --hash=sha256:97acf1e1fd66ab53dacd2c35b319d7e548380c2e9e8c54525c6e76d21b1ae3b1 \ + --hash=sha256:9ada35dd21dc6c039259596b358caab6b13f4db4d4a7f8665764d616daf9cc1d \ + --hash=sha256:9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1 \ + --hash=sha256:9e41506fec7a7f9405b14aa2d5c8abbb4dbbd09d88f9496958b6d00cb4d45330 \ + --hash=sha256:9e4b47ac0f5e749cfc618efdf4726269441014ae1d5583e047b452a32e221920 \ + --hash=sha256:9fb81d2824dff4f2e297a276297e9031f46d2682cafc484f49de182aa5e5df99 \ + --hash=sha256:a0eabd0a81625049c5df745209dc7fcef6e2aea7793e5f003ba363610aa0a3ff \ + --hash=sha256:a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18 \ + --hash=sha256:a87de7dd873bf9a792bf1e58b1c3887b9264036629a5bf2d2e6579fe8e73edff \ + --hash=sha256:aa617107a410245b8660028a7483b68e7914304a6d4882b5ff3d2d3eb5948d8c \ + --hash=sha256:aac0bbd3e8dd2d9c45ceb82249e8bdd3ac99131a32b4d35c8af3cc9db1657179 \ + --hash=sha256:ab6dd83b970dc97c2d10bc71aa925b84788c7c05de30241b9e96f9b6d9ea3080 \ + --hash=sha256:ace2c2326a319a0bb8a8b0e5b570c764962e95818de9f259ce814ee666603f19 \ + --hash=sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d \ + --hash=sha256:b11a5d918a6216e521c715b02749240fb07ae5a1fefd4b7bf12f833bc8b4fe70 \ + --hash=sha256:b1c8c20847b9f34e98080da785bb2336ea982e7f913eed5809e5a3c872900f32 \ + --hash=sha256:b369d3db3c22ed14c75ccd5af429086f166a19627e84a8fdade3f8f31426e52a \ + --hash=sha256:b710bc2b8292966b23a6a0121f7a6c51d45d2347edcc75f016ac123b8054d3f2 \ + --hash=sha256:bd96517ef76c8654446fc3db9242d019a1bb5fe8b751ba414765d59f99210b79 \ + --hash=sha256:c00f323cc00576df6165cc9d21a4c21285fa6b9989c5c39830c3903dc4303ef3 \ + --hash=sha256:c162b216070f280fa7da844531169be0baf9ccb17263cf5a8bf876fcd3117fa5 \ + --hash=sha256:c1a69e58a6bb2de65902051d57fde951febad631a20a64572677a1052690482f \ + --hash=sha256:c1f794c02903c2824fccce5b20c339a1a14b114e83b306ff11b597c5f71a1c8d \ + --hash=sha256:c24037349665434f375645fa9d1f5304800cec574d0310f618490c871fd902b3 \ + --hash=sha256:c300306673aa0f3ed5ed9372b21867690a17dba38c68c44b287437c362ce486b \ + --hash=sha256:c56a1d43b2f9ee4786e4658c7903f05da35b923fb53c11025712562d5cc02753 \ + --hash=sha256:c6379f35350b655fd817cd0d6cbeef7f265f3ae5fedb1caae2eb442bbeae9ab9 \ + --hash=sha256:c802e1c2ed9f0c06a65bc4ed0189d000ada8049312cfeab6ca635e39c9608957 \ + --hash=sha256:cb83f8a875b3d9b458cada4f880fa498646874ba4011dc974e071a0a84a1b033 \ + --hash=sha256:cf120cce539453ae086eacc0130a324e7026113510efa83ab42ef3fcfccac7fb \ + --hash=sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656 \ + --hash=sha256:dd5350b55f9fecddc51385463a4f67a5da829bc741e38cf689f38ec9023f54ab \ + --hash=sha256:df5c7333167b9674aa8ae1d4008fa4bc17a313cc490b2cca27838bbdcc6bb15b \ + --hash=sha256:e63601ad5cd8f860aa99d109889b5ac34de571c7ee902d6812d5d9ddcc77fa7d \ + --hash=sha256:e92ce66cd919d18d14b3856906a61d3f6b6a8500e0794142338da644260595cd \ + --hash=sha256:e99f5507401436fdcc85036a2e7dc2e28d962550afe1cbfc07c40e454256a859 \ + --hash=sha256:ea2e2f6f801696ad7de8aec061044d6c8c0dd4037608c7cab38a9a4d316bfb11 \ + --hash=sha256:eafa2c8658f4e560b098fe9fc54539f86528651f61849b22111a9b107d18910c \ + --hash=sha256:ecd4ad8453ac17bc7ba3868371bffb46f628161ad0eefbd0a855d2c8c32dd81a \ + --hash=sha256:ee70d08fd60c9565ba8190f41a46a54096afa0eeb8f76bd66f2c25d3b1b83005 \ + --hash=sha256:eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654 \ + --hash=sha256:ef0c1fe22171dd7c7c27147f2e9c3e86f8bdf473fed75f16b0c2e84a5030ce80 \ + --hash=sha256:f2901429da1e645ce548bf9171784c0f74f0718c3f6150ce166be39e4dd66c3e \ + --hash=sha256:f422a209d2455c56849442ae42f25dbaaba1c6c3f501d58761c619c7836642ec \ + --hash=sha256:f65e5120863c2b266dbcc927b306c5b78e502c71edf3295dfcb9501ec96e5fc7 \ + --hash=sha256:f7d4a670107d75dfe5ad080bed6c341d18c4442f9378c9f58e5851e86eb79965 \ + --hash=sha256:f914c03e6a31deb632e2daa881fe198461f4d06e57ac3d0e05bbcab8eae01945 \ + --hash=sha256:fb66442c2546446944437df74379e9cf9e9db353e61301d1a0e26482f43f0dd8 # via # python3-saml # xmlsec -markdown==3.6 \ - --hash=sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f \ - --hash=sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224 +markdown==3.7 \ + --hash=sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2 \ + --hash=sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803 # via django-markdownify markuppy==1.14 \ --hash=sha256:1adee2c0a542af378fe84548ff6f6b0168f3cb7f426b46961038a2bcfaad0d5f @@ -926,13 +933,13 @@ markupsafe==2.1.5 \ odfpy==1.4.1 \ --hash=sha256:db766a6e59c5103212f3cc92ec8dd50a0f3a02790233ed0b52148b70d3c438ec # via tablib -openpyxl==3.1.4 \ - --hash=sha256:8d2c8adf5d20d6ce8f9bca381df86b534835e974ed0156dacefa76f68c1d69fb \ - --hash=sha256:ec17f6483f2b8f7c88c57e5e5d3b0de0e3fb9ac70edc084d28e864f5b33bbefd +openpyxl==3.1.5 \ + --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ + --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 # via tablib -opentelemetry-api==1.25.0 \ - --hash=sha256:757fa1aa020a0f8fa139f8959e53dec2051cc26b832e76fa839a6d76ecefd737 \ - --hash=sha256:77c4985f62f2614e42ce77ee4c9da5fa5f0bc1e1821085e9a47533a9323ae869 +opentelemetry-api==1.26.0 \ + --hash=sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce \ + --hash=sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064 # via # -r src/backend/requirements.in # opentelemetry-exporter-otlp-proto-grpc @@ -944,74 +951,74 @@ opentelemetry-api==1.25.0 \ # opentelemetry-instrumentation-wsgi # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-exporter-otlp==1.25.0 \ - --hash=sha256:ce03199c1680a845f82e12c0a6a8f61036048c07ec7a0bd943142aca8fa6ced0 \ - --hash=sha256:d67a831757014a3bc3174e4cd629ae1493b7ba8d189e8a007003cacb9f1a6b60 +opentelemetry-exporter-otlp==1.26.0 \ + --hash=sha256:cf0e093f080011951d9f97431a83869761e4d4ebe83a4195ee92d7806223299c \ + --hash=sha256:f839989f54bda85ee33c5dae033c44dcec9ccbb0dafc6a43d585df44da1d2036 # via -r src/backend/requirements.in -opentelemetry-exporter-otlp-proto-common==1.25.0 \ - --hash=sha256:15637b7d580c2675f70246563363775b4e6de947871e01d0f4e3881d1848d693 \ - --hash=sha256:c93f4e30da4eee02bacd1e004eb82ce4da143a2f8e15b987a9f603e0a85407d3 +opentelemetry-exporter-otlp-proto-common==1.26.0 \ + --hash=sha256:bdbe50e2e22a1c71acaa0c8ba6efaadd58882e5a5978737a44a4c4b10d304c92 \ + --hash=sha256:ee4d8f8891a1b9c372abf8d109409e5b81947cf66423fd998e56880057afbc71 # via # opentelemetry-exporter-otlp-proto-grpc # opentelemetry-exporter-otlp-proto-http -opentelemetry-exporter-otlp-proto-grpc==1.25.0 \ - --hash=sha256:3131028f0c0a155a64c430ca600fd658e8e37043cb13209f0109db5c1a3e4eb4 \ - --hash=sha256:c0b1661415acec5af87625587efa1ccab68b873745ca0ee96b69bb1042087eac +opentelemetry-exporter-otlp-proto-grpc==1.26.0 \ + --hash=sha256:a65b67a9a6b06ba1ec406114568e21afe88c1cdb29c464f2507d529eb906d8ae \ + --hash=sha256:e2be5eff72ebcb010675b818e8d7c2e7d61ec451755b8de67a140bc49b9b0280 # via opentelemetry-exporter-otlp -opentelemetry-exporter-otlp-proto-http==1.25.0 \ - --hash=sha256:2eca686ee11b27acd28198b3ea5e5863a53d1266b91cda47c839d95d5e0541a6 \ - --hash=sha256:9f8723859e37c75183ea7afa73a3542f01d0fd274a5b97487ea24cb683d7d684 +opentelemetry-exporter-otlp-proto-http==1.26.0 \ + --hash=sha256:5801ebbcf7b527377883e6cbbdda35ee712dc55114fff1e93dfee210be56c908 \ + --hash=sha256:ee72a87c48ec977421b02f16c52ea8d884122470e0be573905237b540f4ee562 # via opentelemetry-exporter-otlp -opentelemetry-instrumentation==0.46b0 \ - --hash=sha256:89cd721b9c18c014ca848ccd11181e6b3fd3f6c7669e35d59c48dc527408c18b \ - --hash=sha256:974e0888fb2a1e01c38fbacc9483d024bb1132aad92d6d24e2e5543887a7adda +opentelemetry-instrumentation==0.47b0 \ + --hash=sha256:88974ee52b1db08fc298334b51c19d47e53099c33740e48c4f084bd1afd052d5 \ + --hash=sha256:96f9885e450c35e3f16a4f33145f2ebf620aea910c9fd74a392bbc0f807a350f # via # opentelemetry-instrumentation-django # opentelemetry-instrumentation-redis # opentelemetry-instrumentation-requests # opentelemetry-instrumentation-wsgi -opentelemetry-instrumentation-django==0.46b0 \ - --hash=sha256:cc11b2e24f9bdd20759570390ed8619d9c5acbf788b4a5401e36e280dfc20feb \ - --hash=sha256:ecc85941263122f99dbd96463a981b2d1eeea618ca287a58abe0af9fd67631ee +opentelemetry-instrumentation-django==0.47b0 \ + --hash=sha256:85d5d5dd4047945917b823879933a28efddcf06d5f7fabef5ac806226602b18d \ + --hash=sha256:f23c97ffa9b9b0d06a76e4a5296f189cc6e02f66c29a0ca30a97b0ea121a30b9 # via -r src/backend/requirements.in -opentelemetry-instrumentation-redis==0.46b0 \ - --hash=sha256:8b4639fe52edb6ccdc633c54c01630005ab63faeffd97754cddbf6bdc1f04c5e \ - --hash=sha256:e796530808829a9c32f19eaf470f0b01caef13bd89f1d964f536198de881e460 +opentelemetry-instrumentation-redis==0.47b0 \ + --hash=sha256:15886c725c7e3b6f706964bd72dbfcbefeeeaa1254e98f662516cfed453aaebe \ + --hash=sha256:169de5154cc37ccf402dd43ac06a47f7f883abba7c0a8f99b2731164ec4f1132 # via -r src/backend/requirements.in -opentelemetry-instrumentation-requests==0.46b0 \ - --hash=sha256:a8c2472800d8686f3f286cd524b8746b386154092e85a791ba14110d1acc9b81 \ - --hash=sha256:ef0ad63bfd0d52631daaf7d687e763dbd89b465f5cb052f12a4e67e5e3d181e4 +opentelemetry-instrumentation-requests==0.47b0 \ + --hash=sha256:77fdd13f64fef2cb44665fe6975eadb993d78f96612e55a502e79b34ef7fee47 \ + --hash=sha256:f85ed52cbca21bff226e0e7f1888e5b9bc386657ecf4b0440f328e5b3aba8436 # via -r src/backend/requirements.in -opentelemetry-instrumentation-wsgi==0.46b0 \ - --hash=sha256:2386014b026f5307c802417eeab74265785ae3dd6eee8c5581a830e3b2d3435b \ - --hash=sha256:f4e1001e8477eb546cac7c13cff0b0cf127812b1188a37bcaa3e43eb741451e2 +opentelemetry-instrumentation-wsgi==0.47b0 \ + --hash=sha256:4903c3d686d53ca7ab6545bb4cc42c3de8af5b2f370996e84db2cfec688860af \ + --hash=sha256:9a1a78aa2f5682fe1073c4cc77f24ef4f083b18b66bbb674a995b0b77eef1815 # via opentelemetry-instrumentation-django -opentelemetry-proto==1.25.0 \ - --hash=sha256:35b6ef9dc4a9f7853ecc5006738ad40443701e52c26099e197895cbda8b815a3 \ - --hash=sha256:f07e3341c78d835d9b86665903b199893befa5e98866f63d22b00d0b7ca4972f +opentelemetry-proto==1.26.0 \ + --hash=sha256:6c4d7b4d4d9c88543bcf8c28ae3f8f0448a753dc291c18c5390444c90b76a725 \ + --hash=sha256:c5c18796c0cab3751fc3b98dee53855835e90c0422924b484432ac852d93dc1e # via # opentelemetry-exporter-otlp-proto-common # opentelemetry-exporter-otlp-proto-grpc # opentelemetry-exporter-otlp-proto-http -opentelemetry-sdk==1.25.0 \ - --hash=sha256:ce7fc319c57707ef5bf8b74fb9f8ebdb8bfafbe11898410e0d2a761d08a98ec7 \ - --hash=sha256:d97ff7ec4b351692e9d5a15af570c693b8715ad78b8aafbec5c7100fe966b4c9 +opentelemetry-sdk==1.26.0 \ + --hash=sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85 \ + --hash=sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897 # via # -r src/backend/requirements.in # opentelemetry-exporter-otlp-proto-grpc # opentelemetry-exporter-otlp-proto-http -opentelemetry-semantic-conventions==0.46b0 \ - --hash=sha256:6daef4ef9fa51d51855d9f8e0ccd3a1bd59e0e545abe99ac6203804e36ab3e07 \ - --hash=sha256:fbc982ecbb6a6e90869b15c1673be90bd18c8a56ff1cffc0864e38e2edffaefa +opentelemetry-semantic-conventions==0.47b0 \ + --hash=sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063 \ + --hash=sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e # via # opentelemetry-instrumentation-django # opentelemetry-instrumentation-redis # opentelemetry-instrumentation-requests # opentelemetry-instrumentation-wsgi # opentelemetry-sdk -opentelemetry-util-http==0.46b0 \ - --hash=sha256:03b6e222642f9c7eae58d9132343e045b50aca9761fcb53709bd2b663571fdf6 \ - --hash=sha256:8dc1949ce63caef08db84ae977fdc1848fe6dc38e6bbaad0ae3e6ecd0d451629 +opentelemetry-util-http==0.47b0 \ + --hash=sha256:352a07664c18eef827eb8ddcbd64c64a7284a39dd1655e2f16f577eb046ccb32 \ + --hash=sha256:3d3215e09c4a723b12da6d0233a31395aeb2bb33a64d7b15a1500690ba250f19 # via # opentelemetry-instrumentation-django # opentelemetry-instrumentation-requests @@ -1024,76 +1031,87 @@ pdf2image==1.17.0 \ --hash=sha256:eaa959bc116b420dd7ec415fcae49b98100dda3dd18cd2fdfa86d09f112f6d57 \ --hash=sha256:ecdd58d7afb810dffe21ef2b1bbc057ef434dabbac6c33778a38a3f7744a27e2 # via -r src/backend/requirements.in -pillow==10.3.0 \ - --hash=sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c \ - --hash=sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2 \ - --hash=sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb \ - --hash=sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d \ - --hash=sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa \ - --hash=sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3 \ - --hash=sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1 \ - --hash=sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a \ - --hash=sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd \ - --hash=sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8 \ - --hash=sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999 \ - --hash=sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599 \ - --hash=sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936 \ - --hash=sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375 \ - --hash=sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d \ - --hash=sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b \ - --hash=sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60 \ - --hash=sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572 \ - --hash=sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3 \ - --hash=sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced \ - --hash=sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f \ - --hash=sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b \ - --hash=sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19 \ - --hash=sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f \ - --hash=sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d \ - --hash=sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383 \ - --hash=sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795 \ - --hash=sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355 \ - --hash=sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57 \ - --hash=sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09 \ - --hash=sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b \ - --hash=sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462 \ - --hash=sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf \ - --hash=sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f \ - --hash=sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a \ - --hash=sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad \ - --hash=sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9 \ - --hash=sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d \ - --hash=sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45 \ - --hash=sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994 \ - --hash=sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d \ - --hash=sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338 \ - --hash=sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463 \ - --hash=sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451 \ - --hash=sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591 \ - --hash=sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c \ - --hash=sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd \ - --hash=sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32 \ - --hash=sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9 \ - --hash=sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf \ - --hash=sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5 \ - --hash=sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828 \ - --hash=sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3 \ - --hash=sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5 \ - --hash=sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2 \ - --hash=sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b \ - --hash=sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2 \ - --hash=sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475 \ - --hash=sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3 \ - --hash=sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb \ - --hash=sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef \ - --hash=sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015 \ - --hash=sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002 \ - --hash=sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170 \ - --hash=sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84 \ - --hash=sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57 \ - --hash=sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f \ - --hash=sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27 \ - --hash=sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a +pillow==10.4.0 \ + --hash=sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885 \ + --hash=sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea \ + --hash=sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df \ + --hash=sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5 \ + --hash=sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c \ + --hash=sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d \ + --hash=sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd \ + --hash=sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06 \ + --hash=sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908 \ + --hash=sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a \ + --hash=sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be \ + --hash=sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0 \ + --hash=sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b \ + --hash=sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80 \ + --hash=sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a \ + --hash=sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e \ + --hash=sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9 \ + --hash=sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696 \ + --hash=sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b \ + --hash=sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309 \ + --hash=sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e \ + --hash=sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab \ + --hash=sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d \ + --hash=sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060 \ + --hash=sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d \ + --hash=sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d \ + --hash=sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4 \ + --hash=sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3 \ + --hash=sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6 \ + --hash=sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb \ + --hash=sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94 \ + --hash=sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b \ + --hash=sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496 \ + --hash=sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0 \ + --hash=sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319 \ + --hash=sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b \ + --hash=sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856 \ + --hash=sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef \ + --hash=sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680 \ + --hash=sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b \ + --hash=sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42 \ + --hash=sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e \ + --hash=sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597 \ + --hash=sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a \ + --hash=sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8 \ + --hash=sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3 \ + --hash=sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736 \ + --hash=sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da \ + --hash=sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126 \ + --hash=sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd \ + --hash=sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5 \ + --hash=sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b \ + --hash=sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026 \ + --hash=sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b \ + --hash=sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc \ + --hash=sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46 \ + --hash=sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2 \ + --hash=sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c \ + --hash=sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe \ + --hash=sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984 \ + --hash=sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a \ + --hash=sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70 \ + --hash=sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca \ + --hash=sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b \ + --hash=sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91 \ + --hash=sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3 \ + --hash=sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84 \ + --hash=sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1 \ + --hash=sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5 \ + --hash=sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be \ + --hash=sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f \ + --hash=sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc \ + --hash=sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9 \ + --hash=sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e \ + --hash=sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141 \ + --hash=sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef \ + --hash=sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22 \ + --hash=sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27 \ + --hash=sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e \ + --hash=sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1 # via # -r src/backend/requirements.in # django-stdimage @@ -1105,26 +1123,26 @@ pint==0.21 \ --hash=sha256:3e98bdf01f4dcf840cc0207c0b6f7510d4e0c6288efc1bf470626e875c831172 \ --hash=sha256:998b695e84a34d11702da4a8b9457a39bb5c7ab5ec68db90e948e30878e421f1 # via -r src/backend/requirements.in -pip-licenses==4.4.0 \ - --hash=sha256:996817118375445243a34faafe23c06f6b2d250247c4046571b5a6722d45be69 \ - --hash=sha256:dbad2ac5a25f574cabe2716f2f031a0c5fa359bed9b3ef615301f4e546893b46 +pip-licenses==5.0.0 \ + --hash=sha256:0633a1f9aab58e5a6216931b0e1d5cdded8bcc2709ff563674eb0e2ff9e77e8e \ + --hash=sha256:82c83666753efb86d1af1c405c8ab273413eb10d6689c218df2f09acf40e477d # via -r src/backend/requirements.in -prettytable==3.10.0 \ - --hash=sha256:6536efaf0757fdaa7d22e78b3aac3b69ea1b7200538c2c6995d649365bddab92 \ - --hash=sha256:9665594d137fb08a1117518c25551e0ede1687197cf353a4fdc78d27e1073568 +prettytable==3.11.0 \ + --hash=sha256:7e23ca1e68bbfd06ba8de98bf553bf3493264c96d5e8a615c0471025deeba722 \ + --hash=sha256:aa17083feb6c71da11a68b2c213b04675c4af4ce9c541762632ca3f2cb3546dd # via pip-licenses -protobuf==4.25.3 \ - --hash=sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4 \ - --hash=sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 \ - --hash=sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c \ - --hash=sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d \ - --hash=sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4 \ - --hash=sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa \ - --hash=sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c \ - --hash=sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 \ - --hash=sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9 \ - --hash=sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c \ - --hash=sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2 +protobuf==4.25.4 \ + --hash=sha256:051e97ce9fa6067a4546e75cb14f90cf0232dcb3e3d508c448b8d0e4265b61c1 \ + --hash=sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d \ + --hash=sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040 \ + --hash=sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835 \ + --hash=sha256:7e372cbbda66a63ebca18f8ffaa6948455dfecc4e9c1029312f6c2edcd86c4e1 \ + --hash=sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca \ + --hash=sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f \ + --hash=sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d \ + --hash=sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978 \ + --hash=sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4 \ + --hash=sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b # via # googleapis-common-protos # opentelemetry-proto @@ -1139,14 +1157,16 @@ pycparser==2.22 \ pydyf==0.10.0 \ --hash=sha256:357194593efaf61d7b48ab97c3d59722114934967c3df3d7878ca6dd25b04c30 \ --hash=sha256:ef76b6c0976a091a9e15827fb5800e5e37e7cd1a3ca4d4bd19d10a14ea8c0ae3 - # via weasyprint -pyjwt==2.8.0 \ - --hash=sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de \ - --hash=sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 + # via + # -r src/backend/requirements.in + # weasyprint +pyjwt==2.9.0 \ + --hash=sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850 \ + --hash=sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c # via djangorestframework-simplejwt -pyphen==0.15.0 \ - --hash=sha256:999b430916ab42ae9912537cd95c074e0c6691e89a9d05999f9b610a68f34858 \ - --hash=sha256:a430623decac53dc3691241253263cba36b9dd7a44ffd2680b706af368cda2f2 +pyphen==0.16.0 \ + --hash=sha256:2c006b3ddf072c9571ab97606d9ab3c26a92eaced4c0d59fd1d26988f308f413 \ + --hash=sha256:b4a4c6d7d5654b698b5fc68123148bb799b3debe0175d1d5dc3edfe93066fc4c # via weasyprint pypng==0.20220715.0 \ --hash=sha256:4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c \ @@ -1186,58 +1206,60 @@ pytz==2024.1 \ # django-dbbackup # djangorestframework # icalendar -pyyaml==6.0.1 \ - --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ - --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ - --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ - --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ - --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ - --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ - --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ - --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ - --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ - --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ - --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ - --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ - --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ - --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ - --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ - --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ - --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ - --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ - --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ - --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ - --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ - --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ - --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ - --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ - --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ - --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ - --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ - --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ - --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ - --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \ - --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ - --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ - --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ - --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ - --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ - --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ - --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ - --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ - --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ - --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ - --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ - --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ - --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ - --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ - --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ - --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ - --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ - --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ - --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ - --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ - --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f +pyyaml==6.0.2 \ + --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ + --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ + --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \ + --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \ + --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ + --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \ + --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ + --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \ + --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ + --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \ + --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \ + --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \ + --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \ + --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \ + --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \ + --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \ + --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ + --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \ + --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ + --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \ + --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \ + --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \ + --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \ + --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ + --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ + --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \ + --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \ + --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ + --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ + --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \ + --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ + --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \ + --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ + --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \ + --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \ + --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ + --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \ + --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \ + --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \ + --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ + --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ + --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \ + --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ + --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ + --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \ + --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \ + --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \ + --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \ + --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \ + --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ + --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \ + --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \ + --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4 # via # -r src/backend/requirements.in # drf-spectacular @@ -1248,104 +1270,119 @@ qrcode[pil]==7.4.2 \ # via # -r src/backend/requirements.in # django-allauth-2fa -rapidfuzz==3.9.3 \ - --hash=sha256:05ee0696ebf0dfe8f7c17f364d70617616afc7dafe366532730ca34056065b8a \ - --hash=sha256:0c34139df09a61b1b557ab65782ada971b4a3bce7081d1b2bee45b0a52231adb \ - --hash=sha256:0d055da0e801c71dd74ba81d72d41b2fa32afa182b9fea6b4b199d2ce937450d \ - --hash=sha256:119c010e20e561249b99ca2627f769fdc8305b07193f63dbc07bca0a6c27e892 \ - --hash=sha256:143caf7247449055ecc3c1e874b69e42f403dfc049fc2f3d5f70e1daf21c1318 \ - --hash=sha256:14c9f268ade4c88cf77ab007ad0fdf63699af071ee69378de89fff7aa3cae134 \ - --hash=sha256:153f23c03d4917f6a1fc2fb56d279cc6537d1929237ff08ee7429d0e40464a18 \ - --hash=sha256:15e4158ac4b3fb58108072ec35b8a69165f651ba1c8f43559a36d518dbf9fb3f \ - --hash=sha256:17ff7f7eecdb169f9236e3b872c96dbbaf116f7787f4d490abd34b0116e3e9c8 \ - --hash=sha256:21047f55d674614eb4b0ab34e35c3dc66f36403b9fbfae645199c4a19d4ed447 \ - --hash=sha256:256e07d3465173b2a91c35715a2277b1ee3ae0b9bbab4e519df6af78570741d0 \ - --hash=sha256:282d55700a1a3d3a7980746eb2fcd48c9bbc1572ebe0840d0340d548a54d01fe \ - --hash=sha256:2bc8391749e5022cd9e514ede5316f86e332ffd3cfceeabdc0b17b7e45198a8c \ - --hash=sha256:2c1d3ef3878f871abe6826e386c3d61b5292ef5f7946fe646f4206b85836b5da \ - --hash=sha256:35b7286f177e4d8ba1e48b03612f928a3c4bdac78e5651379cec59f95d8651e6 \ - --hash=sha256:3617d1aa7716c57d120b6adc8f7c989f2d65bc2b0cbd5f9288f1fc7bf469da11 \ - --hash=sha256:378d1744828e27490a823fc6fe6ebfb98c15228d54826bf4e49e4b76eb5f5579 \ - --hash=sha256:3bb6546e7b6bed1aefbe24f68a5fb9b891cc5aef61bca6c1a7b1054b7f0359bb \ - --hash=sha256:3d8a57261ef7996d5ced7c8cba9189ada3fbeffd1815f70f635e4558d93766cb \ - --hash=sha256:3e6d27dad8c990218b8cd4a5c99cbc8834f82bb46ab965a7265d5aa69fc7ced7 \ - --hash=sha256:41a81a9f311dc83d22661f9b1a1de983b201322df0c4554042ffffd0f2040c37 \ - --hash=sha256:505d99131afd21529293a9a7b91dfc661b7e889680b95534756134dc1cc2cd86 \ - --hash=sha256:51fa1ba84653ab480a2e2044e2277bd7f0123d6693051729755addc0d015c44f \ - --hash=sha256:5276df395bd8497397197fca2b5c85f052d2e6a66ffc3eb0544dd9664d661f95 \ - --hash=sha256:53c7f27cdf899e94712972237bda48cfd427646aa6f5d939bf45d084780e4c16 \ - --hash=sha256:53e06e4b81f552da04940aa41fc556ba39dee5513d1861144300c36c33265b76 \ - --hash=sha256:5410dc848c947a603792f4f51b904a3331cf1dc60621586bfbe7a6de72da1091 \ - --hash=sha256:57e7c5bf7b61c7320cfa5dde1e60e678d954ede9bb7da8e763959b2138391401 \ - --hash=sha256:58c6a4936190c558d5626b79fc9e16497e5df7098589a7e80d8bff68148ff096 \ - --hash=sha256:5b422c0a6fe139d5447a0766268e68e6a2a8c2611519f894b1f31f0a392b9167 \ - --hash=sha256:5c7ca5b6050f18fdcacdada2dc5fb7619ff998cd9aba82aed2414eee74ebe6cd \ - --hash=sha256:5d0abbacdb06e27ff803d7ae0bd0624020096802758068ebdcab9bd49cf53115 \ - --hash=sha256:5d0cb272d43e6d3c0dedefdcd9d00007471f77b52d2787a4695e9dd319bb39d2 \ - --hash=sha256:5d6a210347d6e71234af5c76d55eeb0348b026c9bb98fe7c1cca89bac50fb734 \ - --hash=sha256:5e2b827258beefbe5d3f958243caa5a44cf46187eff0c20e0b2ab62d1550327a \ - --hash=sha256:5e33f779391caedcba2ba3089fb6e8e557feab540e9149a5c3f7fea7a3a7df37 \ - --hash=sha256:604e0502a39cf8e67fa9ad239394dddad4cdef6d7008fdb037553817d420e108 \ - --hash=sha256:6073a46f61479a89802e3f04655267caa6c14eb8ac9d81a635a13805f735ebc1 \ - --hash=sha256:6175682a829c6dea4d35ed707f1dadc16513270ef64436568d03b81ccb6bdb74 \ - --hash=sha256:65f45be77ec82da32ce5709a362e236ccf801615cc7163b136d1778cf9e31b14 \ - --hash=sha256:67201c02efc596923ad950519e0b75ceb78d524177ea557134d6567b9ac2c283 \ - --hash=sha256:754b719a4990735f66653c9e9261dcf52fd4d925597e43d6b9069afcae700d21 \ - --hash=sha256:77b5c4f3e72924d7845f0e189c304270066d0f49635cf8a3938e122c437e58de \ - --hash=sha256:790b0b244f3213581d42baa2fed8875f9ee2b2f9b91f94f100ec80d15b140ba9 \ - --hash=sha256:802ca2cc8aa6b8b34c6fdafb9e32540c1ba05fca7ad60b3bbd7ec89ed1797a87 \ - --hash=sha256:8319838fb5b7b5f088d12187d91d152b9386ce3979ed7660daa0ed1bff953791 \ - --hash=sha256:83ea7ca577d76778250421de61fb55a719e45b841deb769351fc2b1740763050 \ - --hash=sha256:858ba57c05afd720db8088a8707079e8d024afe4644001fe0dbd26ef7ca74a65 \ - --hash=sha256:8709918da8a88ad73c9d4dd0ecf24179a4f0ceba0bee21efc6ea21a8b5290349 \ - --hash=sha256:875b581afb29a7213cf9d98cb0f98df862f1020bce9d9b2e6199b60e78a41d14 \ - --hash=sha256:87bb8d84cb41446a808c4b5f746e29d8a53499381ed72f6c4e456fe0f81c80a8 \ - --hash=sha256:8add34061e5cd561c72ed4febb5c15969e7b25bda2bb5102d02afc3abc1f52d0 \ - --hash=sha256:8f917eaadf5388466a95f6a236f678a1588d231e52eda85374077101842e794e \ - --hash=sha256:930b4e6fdb4d914390141a2b99a6f77a52beacf1d06aa4e170cba3a98e24c1bc \ - --hash=sha256:93981895602cf5944d89d317ae3b1b4cc684d175a8ae2a80ce5b65615e72ddd0 \ - --hash=sha256:959a15186d18425d19811bea86a8ffbe19fd48644004d29008e636631420a9b7 \ - --hash=sha256:964c08481aec2fe574f0062e342924db2c6b321391aeb73d68853ed42420fd6d \ - --hash=sha256:a24603dd05fb4e3c09d636b881ce347e5f55f925a6b1b4115527308a323b9f8e \ - --hash=sha256:a39890013f6d5b056cc4bfdedc093e322462ece1027a57ef0c636537bdde7531 \ - --hash=sha256:a4fc7b784cf987dbddc300cef70e09a92ed1bce136f7bb723ea79d7e297fe76d \ - --hash=sha256:a56da3aff97cb56fe85d9ca957d1f55dbac7c27da927a86a2a86d8a7e17f80aa \ - --hash=sha256:a93250bd8fae996350c251e1752f2c03335bb8a0a5b0c7e910a593849121a435 \ - --hash=sha256:a96c5225e840f1587f1bac8fa6f67562b38e095341576e82b728a82021f26d62 \ - --hash=sha256:aca21c0a34adee582775da997a600283e012a608a107398d80a42f9a57ad323d \ - --hash=sha256:acbe4b6f1ccd5b90c29d428e849aa4242e51bb6cab0448d5f3c022eb9a25f7b1 \ - --hash=sha256:ad04a3f5384b82933213bba2459f6424decc2823df40098920856bdee5fd6e88 \ - --hash=sha256:afe7c72d3f917b066257f7ff48562e5d462d865a25fbcabf40fca303a9fa8d35 \ - --hash=sha256:b300708c917ce52f6075bdc6e05b07c51a085733650f14b732c087dc26e0aaad \ - --hash=sha256:b398ea66e8ed50451bce5997c430197d5e4b06ac4aa74602717f792d8d8d06e2 \ - --hash=sha256:b3bd0d9632088c63a241f217742b1cf86e2e8ae573e01354775bd5016d12138c \ - --hash=sha256:b5bc0fdbf419493163c5c9cb147c5fbe95b8e25844a74a8807dcb1a125e630cf \ - --hash=sha256:b770f85eab24034e6ef7df04b2bfd9a45048e24f8a808e903441aa5abde8ecdd \ - --hash=sha256:b777cd910ceecd738adc58593d6ed42e73f60ad04ecdb4a841ae410b51c92e0e \ - --hash=sha256:b80eb7cbe62348c61d3e67e17057cddfd6defab168863028146e07d5a8b24a89 \ - --hash=sha256:b8ab0fa653d9225195a8ff924f992f4249c1e6fa0aea563f685e71b81b9fcccf \ - --hash=sha256:bc1991b4cde6c9d3c0bbcb83d5581dc7621bec8c666c095c65b4277233265a82 \ - --hash=sha256:bdb8c5b8e29238ec80727c2ba3b301efd45aa30c6a7001123a6647b8e6f77ea4 \ - --hash=sha256:c52970f7784518d7c82b07a62a26e345d2de8c2bd8ed4774e13342e4b3ff4200 \ - --hash=sha256:c6e65a301fcd19fbfbee3a514cc0014ff3f3b254b9fd65886e8a9d6957fb7bca \ - --hash=sha256:c8444e921bfc3757c475c4f4d7416a7aa69b2d992d5114fe55af21411187ab0d \ - --hash=sha256:cbe93ba1725a8d47d2b9dca6c1f435174859427fbc054d83de52aea5adc65729 \ - --hash=sha256:cde6b9d9ba5007077ee321ec722fa714ebc0cbd9a32ccf0f4dd3cc3f20952d71 \ - --hash=sha256:d36447d21b05f90282a6f98c5a33771805f9222e5d0441d03eb8824e33e5bbb4 \ - --hash=sha256:d861bf326ee7dabc35c532a40384541578cd1ec1e1b7db9f9ecbba56eb76ca22 \ - --hash=sha256:dc1037507810833646481f5729901a154523f98cbebb1157ba3a821012e16402 \ - --hash=sha256:dd789100fc852cffac1449f82af0da139d36d84fd9faa4f79fc4140a88778343 \ - --hash=sha256:de077c468c225d4c18f7188c47d955a16d65f21aab121cbdd98e3e2011002c37 \ - --hash=sha256:e53ed2e9b32674ce96eed80b3b572db9fd87aae6742941fb8e4705e541d861ce \ - --hash=sha256:e6e4b9380ed4758d0cb578b0d1970c3f32dd9e87119378729a5340cb3169f879 \ - --hash=sha256:efe6e200a75a792d37b960457904c4fce7c928a96ae9e5d21d2bd382fe39066e \ - --hash=sha256:f50fed4a9b0c9825ff37cf0bccafd51ff5792090618f7846a7650f21f85579c9 \ - --hash=sha256:f57e8305c281e8c8bc720515540e0580355100c0a7a541105c6cafc5de71daae \ - --hash=sha256:fd84b7f652a5610733400307dc732f57c4a907080bef9520412e6d9b55bc9adc +rapidfuzz==3.9.6 \ + --hash=sha256:0308b2ad161daf502908a6e21a57c78ded0258eba9a8f5e2545e2dafca312507 \ + --hash=sha256:0542c036cb6acf24edd2c9e0411a67d7ba71e29e4d3001a082466b86fc34ff30 \ + --hash=sha256:0a96b52c9f26857bf009e270dcd829381e7a634f7ddd585fa29b87d4c82146d9 \ + --hash=sha256:0b40ff76ee19b03ebf10a0a87938f86814996a822786c41c3312d251b7927849 \ + --hash=sha256:0d21fc3c0ca507a1180152a6dbd129ebaef48facde3f943db5c1055b6e6be56a \ + --hash=sha256:0d2c2fe19e392dbc22695b6c3b2510527e2b774647e79936bbde49db7742d6f1 \ + --hash=sha256:101bd2df438861a005ed47c032631b7857dfcdb17b82beeeb410307983aac61d \ + --hash=sha256:10f06139142ecde67078ebc9a745965446132b998f9feebffd71acdf218acfcc \ + --hash=sha256:15146301b32e6e3d2b7e8146db1a26747919d8b13690c7f83a4cb5dc111b3a08 \ + --hash=sha256:1611199f178793ca9a060c99b284e11f6d7d124998191f1cace9a0245334d219 \ + --hash=sha256:16122ae448bc89e2bea9d81ce6cb0f751e4e07da39bd1e70b95cae2493857853 \ + --hash=sha256:1629698e68f47609a73bf9e73a6da3a4cac20bc710529215cbdf111ab603665b \ + --hash=sha256:16a6c7997cb5927ced6f617122eb116ba514ec6b6f60f4803e7925ef55158891 \ + --hash=sha256:1a5bd6401bb489e14cbb5981c378d53ede850b7cc84b2464cad606149cc4e17d \ + --hash=sha256:1c59f1c1507b7a557cf3c410c76e91f097460da7d97e51c985343798e9df7a3c \ + --hash=sha256:1d66c247c2d3bb7a9b60567c395a15a929d0ebcc5f4ceedb55bfa202c38c6e0c \ + --hash=sha256:1f93a2f13038700bd245b927c46a2017db3dcd4d4ff94687d74b5123689b873b \ + --hash=sha256:2116fa1fbff21fa52cd46f3cfcb1e193ba1d65d81f8b6e123193451cd3d6c15e \ + --hash=sha256:2185e8e29809b97ad22a7f99281d1669a89bdf5fa1ef4ef1feca36924e675367 \ + --hash=sha256:248f6d2612e661e2b5f9a22bbd5862a1600e720da7bb6ad8a55bb1548cdfa423 \ + --hash=sha256:24d473d00d23a30a85802b502b417a7f5126019c3beec91a6739fe7b95388b24 \ + --hash=sha256:29146cb7a1bf69c87e928b31bffa54f066cb65639d073b36e1425f98cccdebc6 \ + --hash=sha256:29fda70b9d03e29df6fc45cc27cbcc235534b1b0b2900e0a3ae0b43022aaeef5 \ + --hash=sha256:2c0488b1c273be39e109ff885ccac0448b2fa74dea4c4dc676bcf756c15f16d6 \ + --hash=sha256:32848dfe54391636b84cda1823fd23e5a6b1dbb8be0e9a1d80e4ee9903820994 \ + --hash=sha256:39ffe48ffbeedf78d120ddfb9d583f2ca906712159a4e9c3c743c9f33e7b1775 \ + --hash=sha256:3e910cf08944da381159587709daaad9e59d8ff7bca1f788d15928f3c3d49c2a \ + --hash=sha256:3eda91832201b86e3b70835f91522587725bec329ec68f2f7faf5124091e5ca7 \ + --hash=sha256:3f5702828c10768f9281180a7ff8597da1e5002803e1304e9519dd0f06d79a85 \ + --hash=sha256:42b70500bca460264b8141d8040caee22e9cf0418c5388104ff0c73fb69ee28f \ + --hash=sha256:43bb27a57c29dc5fa754496ba6a1a508480d21ae99ac0d19597646c16407e9f3 \ + --hash=sha256:4bb5ff2bd48132ed5e7fbb8f619885facb2e023759f2519a448b2c18afe07e5d \ + --hash=sha256:4dcb7d9afd740370a897c15da61d3d57a8d54738d7c764a99cedb5f746d6a003 \ + --hash=sha256:50b2fb55d7ed58c66d49c9f954acd8fc4a3f0e9fd0ff708299bd8abb68238d0e \ + --hash=sha256:51be6ab5b1d5bb32abd39718f2a5e3835502e026a8272d139ead295c224a6f5e \ + --hash=sha256:52e4675f642fbc85632f691b67115a243cd4d2a47bdcc4a3d9a79e784518ff97 \ + --hash=sha256:58b4ce83f223605c358ae37e7a2d19a41b96aa65b1fede99cc664c9053af89ac \ + --hash=sha256:59c4a61fab676d37329fc3a671618a461bfeef53a4d0b8b12e3bc24a14e166f8 \ + --hash=sha256:59ee78f2ecd53fef8454909cda7400fe2cfcd820f62b8a5d4dfe930102268054 \ + --hash=sha256:5b0c9b227ee0076fb2d58301c505bb837a290ae99ee628beacdb719f0626d749 \ + --hash=sha256:5c3f9fc060160507b2704f7d1491bd58453d69689b580cbc85289335b14fe8ca \ + --hash=sha256:5cf2a7d621e4515fee84722e93563bf77ff2cbe832a77a48b81f88f9e23b9e8d \ + --hash=sha256:5eb1a9272ca71bc72be5415c2fa8448a6302ea4578e181bb7da9db855b367df0 \ + --hash=sha256:624fbe96115fb39addafa288d583b5493bc76dab1d34d0ebba9987d6871afdf9 \ + --hash=sha256:63daaeeea76da17fa0bbe7fb05cba8ed8064bb1a0edf8360636557f8b6511961 \ + --hash=sha256:6792f66d59b86ccfad5e247f2912e255c85c575789acdbad8e7f561412ffed8a \ + --hash=sha256:680dc78a5f889d3b89f74824b89fe357f49f88ad10d2c121e9c3ad37bac1e4eb \ + --hash=sha256:68bc7621843d8e9a7fd1b1a32729465bf94b47b6fb307d906da168413331f8d6 \ + --hash=sha256:68d9cffe710b67f1969cf996983608cee4490521d96ea91d16bd7ea5dc80ea98 \ + --hash=sha256:6a4bec4956e06b170ca896ba055d08d4c457dac745548172443982956a80e118 \ + --hash=sha256:6c4550d0db4931f5ebe9f0678916d1b06f06f5a99ba0b8a48b9457fd8959a7d4 \ + --hash=sha256:6dc37f601865e8407e3a8037ffbc3afe0b0f837b2146f7632bd29d087385babe \ + --hash=sha256:6edd3cd7c4aa8c68c716d349f531bd5011f2ca49ddade216bb4429460151559f \ + --hash=sha256:70591b28b218fff351b88cdd7f2359a01a71f9f7f5a2e465ce3715ed4b3c422b \ + --hash=sha256:708fb675de0f47b9635d1cc6fbbf80d52cb710d0a1abbfae5c84c46e3abbddc3 \ + --hash=sha256:715aeaabafba2709b9dd91acb2a44bad59d60b4616ef90c08f4d4402a3bbca60 \ + --hash=sha256:71cc168c305a4445109cd0d4925406f6e66bcb48fde99a1835387c58af4ecfe9 \ + --hash=sha256:74720c3f24597f76c7c3e2c4abdff55f1664f4766ff5b28aeaa689f8ffba5fab \ + --hash=sha256:7496f53d40560a58964207b52586783633f371683834a8f719d6d965d223a2eb \ + --hash=sha256:7e535a114fa575bc143e175e4ca386a467ec8c42909eff500f5f0f13dc84e3e0 \ + --hash=sha256:82c9722b7dfaa71e8b61f8c89fed0482567fb69178e139fe4151fc71ed7df782 \ + --hash=sha256:83a5ac6547a9d6eedaa212975cb8f2ce2aa07e6e30833b40e54a52b9f9999aa4 \ + --hash=sha256:8502ccdea9084d54b6f737d96a3b60a84e3afed9d016686dc979b49cdac71613 \ + --hash=sha256:88144f5f52ae977df9352029488326afadd7a7f42c6779d486d1f82d43b2b1f2 \ + --hash=sha256:89acbf728b764421036c173a10ada436ecca22999851cdc01d0aa904c70d362d \ + --hash=sha256:8b4afea244102332973377fddbe54ce844d0916e1c67a5123432291717f32ffa \ + --hash=sha256:9196a51d0ec5eaaaf5bca54a85b7b1e666fc944c332f68e6427503af9fb8c49e \ + --hash=sha256:91aaee4c94cb45930684f583ffc4e7c01a52b46610971cede33586cf8a04a12e \ + --hash=sha256:9e53c72d08f0e9c6e4a369e52df5971f311305b4487690c62e8dd0846770260c \ + --hash=sha256:9f469dbc9c4aeaac7dd005992af74b7dff94aa56a3ea063ce64e4b3e6736dd2f \ + --hash=sha256:a0cb157162f0cdd62e538c7bd298ff669847fc43a96422811d5ab933f4c16c3a \ + --hash=sha256:a1e037fb89f714a220f68f902fc6300ab7a33349f3ce8ffae668c3b3a40b0b06 \ + --hash=sha256:a657eee4b94668faf1fa2703bdd803654303f7e468eb9ba10a664d867ed9e779 \ + --hash=sha256:a65c2f63218ea2dedd56fc56361035e189ca123bd9c9ce63a9bef6f99540d681 \ + --hash=sha256:a7a03da59b6c7c97e657dd5cd4bcaab5fe4a2affd8193958d6f4d938bee36679 \ + --hash=sha256:a7ed0d0b9c85720f0ae33ac5efc8dc3f60c1489dad5c29d735fbdf2f66f0431f \ + --hash=sha256:a9ed7ad9adb68d0fe63a156fe752bbf5f1403ed66961551e749641af2874da92 \ + --hash=sha256:ad9462aa2be9f60b540c19a083471fdf28e7cf6434f068b631525b5e6251b35e \ + --hash=sha256:aed13e5edacb0ecadcc304cc66e93e7e77ff24f059c9792ee602c0381808e10c \ + --hash=sha256:af26ebd3714224fbf9bebbc27bdbac14f334c15f5d7043699cd694635050d6ca \ + --hash=sha256:af440e36b828922256d0b4d79443bf2cbe5515fc4b0e9e96017ec789b36bb9fc \ + --hash=sha256:b6b8dd4af6324fc325d9483bec75ecf9be33e590928c9202d408e4eafff6a0a6 \ + --hash=sha256:b8ca862927a0b05bd825e46ddf82d0724ea44b07d898ef639386530bf9b40f15 \ + --hash=sha256:c18897c95c0a288347e29537b63608a8f63a5c3cb6da258ac46fcf89155e723e \ + --hash=sha256:c256fa95d29cbe5aa717db790b231a9a5b49e5983d50dc9df29d364a1db5e35b \ + --hash=sha256:c4e86c2b3827fa6169ad6e7d4b790ce02a20acefb8b78d92fa4249589bbc7a2c \ + --hash=sha256:c608fcba8b14d86c04cb56b203fed31a96e8a1ebb4ce99e7b70313c5bf8cf497 \ + --hash=sha256:c6254c50f15bc2fcc33cb93a95a81b702d9e6590f432a7f7822b8c7aba9ae288 \ + --hash=sha256:cc7a0d4b2cb166bc46d02c8c9f7551cde8e2f3c9789df3827309433ee9771163 \ + --hash=sha256:ccd1763b608fb4629a0b08f00b3c099d6395e67c14e619f6341b2c8429c2f310 \ + --hash=sha256:ce2bce52b5c150878e558a0418c2b637fb3dbb6eb38e4eb27d24aa839920483e \ + --hash=sha256:d214e063bffa13e3b771520b74f674b22d309b5720d4df9918ff3e0c0f037720 \ + --hash=sha256:d41c00ded0e22e9dba88ff23ebe0dc9d2a5f21ba2f88e185ea7374461e61daa9 \ + --hash=sha256:d50acc0e9d67e4ba7a004a14c42d1b1e8b6ca1c515692746f4f8e7948c673167 \ + --hash=sha256:d97d3c9d209d5c30172baea5966f2129e8a198fec4a1aeb2f92abb6e82a2edb1 \ + --hash=sha256:e03fdf0e74f346ed7e798135df5f2a0fb8d6b96582b00ebef202dcf2171e1d1d \ + --hash=sha256:e3a4244f65dbc3580b1275480118c3763f9dc29fc3dd96610560cb5e140a4d4a \ + --hash=sha256:ece873c093aedd87fc07c2a7e333d52e458dc177016afa1edaf157e82b6914d8 \ + --hash=sha256:ed443a2062460f44c0346cb9d269b586496b808c2419bbd6057f54061c9b9c75 \ + --hash=sha256:ee2d8355c7343c631a03e57540ea06e8717c19ecf5ff64ea07e0498f7f161457 \ + --hash=sha256:efa674b407424553024522159296690d99d6e6b1192cafe99ca84592faff16b4 \ + --hash=sha256:f3deff6ab7017ed21b9aec5874a07ad13e6b2a688af055837f88b743c7bfd947 \ + --hash=sha256:f3f42504bdc8d770987fc3d99964766d42b2a03e4d5b0f891decdd256236bae0 \ + --hash=sha256:f6ebb910a702e41641e1e1dada3843bc11ba9107a33c98daef6945a885a40a07 \ + --hash=sha256:f6f0256cb27b6a0fb2e1918477d1b56473cd04acfa245376a342e7c15806a396 \ + --hash=sha256:f982e1aafb4bd8207a5e073b1efef9e68a984e91330e1bbf364f9ed157ed83f0 \ + --hash=sha256:fa742ec60bec53c5a211632cf1d31b9eb5a3c80f1371a46a23ac25a1fa2ab209 \ + --hash=sha256:fb5a514064e02585b1cc09da2fe406a6dc1a7e5f3e92dd4f27c53e5f1465ec81 # via -r src/backend/requirements.in -redis==5.0.7 \ - --hash=sha256:0e479e24da960c690be5d9b96d21f7b918a98c0cf49af3b6fafaa0753f93a0db \ - --hash=sha256:8f611490b93c8109b50adc317b31bfd84fff31def3475b92e7e80bf39f48175b +redis==5.0.8 \ + --hash=sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870 \ + --hash=sha256:56134ee08ea909106090934adc36f65c9bcbbaecea5b21ba704ba6fb561f8eb4 # via django-redis referencing==0.35.1 \ --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \ @@ -1353,86 +1390,86 @@ referencing==0.35.1 \ # via # jsonschema # jsonschema-specifications -regex==2024.4.28 \ - --hash=sha256:05d9b6578a22db7dedb4df81451f360395828b04f4513980b6bd7a1412c679cc \ - --hash=sha256:08a1749f04fee2811c7617fdd46d2e46d09106fa8f475c884b65c01326eb15c5 \ - --hash=sha256:0940038bec2fe9e26b203d636c44d31dd8766abc1fe66262da6484bd82461ccf \ - --hash=sha256:0a2a512d623f1f2d01d881513af9fc6a7c46e5cfffb7dc50c38ce959f9246c94 \ - --hash=sha256:0a54a047b607fd2d2d52a05e6ad294602f1e0dec2291152b745870afc47c1397 \ - --hash=sha256:0dd3f69098511e71880fb00f5815db9ed0ef62c05775395968299cb400aeab82 \ - --hash=sha256:1031a5e7b048ee371ab3653aad3030ecfad6ee9ecdc85f0242c57751a05b0ac4 \ - --hash=sha256:108e2dcf0b53a7c4ab8986842a8edcb8ab2e59919a74ff51c296772e8e74d0ae \ - --hash=sha256:144a1fc54765f5c5c36d6d4b073299832aa1ec6a746a6452c3ee7b46b3d3b11d \ - --hash=sha256:19d6c11bf35a6ad077eb23852827f91c804eeb71ecb85db4ee1386825b9dc4db \ - --hash=sha256:1f687a28640f763f23f8a9801fe9e1b37338bb1ca5d564ddd41619458f1f22d1 \ - --hash=sha256:224803b74aab56aa7be313f92a8d9911dcade37e5f167db62a738d0c85fdac4b \ - --hash=sha256:23a412b7b1a7063f81a742463f38821097b6a37ce1e5b89dd8e871d14dbfd86b \ - --hash=sha256:25f87ae6b96374db20f180eab083aafe419b194e96e4f282c40191e71980c666 \ - --hash=sha256:2630ca4e152c221072fd4a56d4622b5ada876f668ecd24d5ab62544ae6793ed6 \ - --hash=sha256:28e1f28d07220c0f3da0e8fcd5a115bbb53f8b55cecf9bec0c946eb9a059a94c \ - --hash=sha256:2b51739ddfd013c6f657b55a508de8b9ea78b56d22b236052c3a85a675102dc6 \ - --hash=sha256:2cc1b87bba1dd1a898e664a31012725e48af826bf3971e786c53e32e02adae6c \ - --hash=sha256:2fef0b38c34ae675fcbb1b5db760d40c3fc3612cfa186e9e50df5782cac02bcd \ - --hash=sha256:36f392dc7763fe7924575475736bddf9ab9f7a66b920932d0ea50c2ded2f5636 \ - --hash=sha256:374f690e1dd0dbdcddea4a5c9bdd97632cf656c69113f7cd6a361f2a67221cb6 \ - --hash=sha256:3986217ec830c2109875be740531feb8ddafe0dfa49767cdcd072ed7e8927962 \ - --hash=sha256:39fb166d2196413bead229cd64a2ffd6ec78ebab83fff7d2701103cf9f4dfd26 \ - --hash=sha256:4290035b169578ffbbfa50d904d26bec16a94526071ebec3dadbebf67a26b25e \ - --hash=sha256:43548ad74ea50456e1c68d3c67fff3de64c6edb85bcd511d1136f9b5376fc9d1 \ - --hash=sha256:44a22ae1cfd82e4ffa2066eb3390777dc79468f866f0625261a93e44cdf6482b \ - --hash=sha256:457c2cd5a646dd4ed536c92b535d73548fb8e216ebee602aa9f48e068fc393f3 \ - --hash=sha256:459226445c7d7454981c4c0ce0ad1a72e1e751c3e417f305722bbcee6697e06a \ - --hash=sha256:47af45b6153522733aa6e92543938e97a70ce0900649ba626cf5aad290b737b6 \ - --hash=sha256:499334ad139557de97cbc4347ee921c0e2b5e9c0f009859e74f3f77918339257 \ - --hash=sha256:57ba112e5530530fd175ed550373eb263db4ca98b5f00694d73b18b9a02e7185 \ - --hash=sha256:5ce479ecc068bc2a74cb98dd8dba99e070d1b2f4a8371a7dfe631f85db70fe6e \ - --hash=sha256:5dbc1bcc7413eebe5f18196e22804a3be1bfdfc7e2afd415e12c068624d48247 \ - --hash=sha256:6277d426e2f31bdbacb377d17a7475e32b2d7d1f02faaecc48d8e370c6a3ff31 \ - --hash=sha256:66372c2a01782c5fe8e04bff4a2a0121a9897e19223d9eab30c54c50b2ebeb7f \ - --hash=sha256:670fa596984b08a4a769491cbdf22350431970d0112e03d7e4eeaecaafcd0fec \ - --hash=sha256:6f435946b7bf7a1b438b4e6b149b947c837cb23c704e780c19ba3e6855dbbdd3 \ - --hash=sha256:7413167c507a768eafb5424413c5b2f515c606be5bb4ef8c5dee43925aa5718b \ - --hash=sha256:7c3d389e8d76a49923683123730c33e9553063d9041658f23897f0b396b2386f \ - --hash=sha256:7d77b6f63f806578c604dca209280e4c54f0fa9a8128bb8d2cc5fb6f99da4150 \ - --hash=sha256:7e76b9cfbf5ced1aca15a0e5b6f229344d9b3123439ffce552b11faab0114a02 \ - --hash=sha256:7f3502f03b4da52bbe8ba962621daa846f38489cae5c4a7b5d738f15f6443d17 \ - --hash=sha256:7fe9739a686dc44733d52d6e4f7b9c77b285e49edf8570754b322bca6b85b4cc \ - --hash=sha256:83ab366777ea45d58f72593adf35d36ca911ea8bd838483c1823b883a121b0e4 \ - --hash=sha256:84077821c85f222362b72fdc44f7a3a13587a013a45cf14534df1cbbdc9a6796 \ - --hash=sha256:8bb381f777351bd534462f63e1c6afb10a7caa9fa2a421ae22c26e796fe31b1f \ - --hash=sha256:92da587eee39a52c91aebea8b850e4e4f095fe5928d415cb7ed656b3460ae79a \ - --hash=sha256:9301cc6db4d83d2c0719f7fcda37229691745168bf6ae849bea2e85fc769175d \ - --hash=sha256:965fd0cf4694d76f6564896b422724ec7b959ef927a7cb187fc6b3f4e4f59833 \ - --hash=sha256:99d6a550425cc51c656331af0e2b1651e90eaaa23fb4acde577cf15068e2e20f \ - --hash=sha256:99ef6289b62042500d581170d06e17f5353b111a15aa6b25b05b91c6886df8fc \ - --hash=sha256:a1409c4eccb6981c7baabc8888d3550df518add6e06fe74fa1d9312c1838652d \ - --hash=sha256:a74fcf77d979364f9b69fcf8200849ca29a374973dc193a7317698aa37d8b01c \ - --hash=sha256:aaa179975a64790c1f2701ac562b5eeb733946eeb036b5bcca05c8d928a62f10 \ - --hash=sha256:ac69b394764bb857429b031d29d9604842bc4cbfd964d764b1af1868eeebc4f0 \ - --hash=sha256:b45d4503de8f4f3dc02f1d28a9b039e5504a02cc18906cfe744c11def942e9eb \ - --hash=sha256:b7d893c8cf0e2429b823ef1a1d360a25950ed11f0e2a9df2b5198821832e1947 \ - --hash=sha256:b8eb28995771c087a73338f695a08c9abfdf723d185e57b97f6175c5051ff1ae \ - --hash=sha256:b91d529b47798c016d4b4c1d06cc826ac40d196da54f0de3c519f5a297c5076a \ - --hash=sha256:bc365ce25f6c7c5ed70e4bc674f9137f52b7dd6a125037f9132a7be52b8a252f \ - --hash=sha256:bf29304a8011feb58913c382902fde3395957a47645bf848eea695839aa101b7 \ - --hash=sha256:c06bf3f38f0707592898428636cbb75d0a846651b053a1cf748763e3063a6925 \ - --hash=sha256:c77d10ec3c1cf328b2f501ca32583625987ea0f23a0c2a49b37a39ee5c4c4630 \ - --hash=sha256:cd196d056b40af073d95a2879678585f0b74ad35190fac04ca67954c582c6b61 \ - --hash=sha256:d7a353ebfa7154c871a35caca7bfd8f9e18666829a1dc187115b80e35a29393e \ - --hash=sha256:d84308f097d7a513359757c69707ad339da799e53b7393819ec2ea36bc4beb58 \ - --hash=sha256:dd7ef715ccb8040954d44cfeff17e6b8e9f79c8019daae2fd30a8806ef5435c0 \ - --hash=sha256:e672cf9caaf669053121f1766d659a8813bd547edef6e009205378faf45c67b8 \ - --hash=sha256:ecc6148228c9ae25ce403eade13a0961de1cb016bdb35c6eafd8e7b87ad028b1 \ - --hash=sha256:f1c5742c31ba7d72f2dedf7968998730664b45e38827637e0f04a2ac7de2f5f1 \ - --hash=sha256:f1d6e4b7b2ae3a6a9df53efbf199e4bfcff0959dbdb5fd9ced34d4407348e39a \ - --hash=sha256:f2fc053228a6bd3a17a9b0a3f15c3ab3cf95727b00557e92e1cfe094b88cc662 \ - --hash=sha256:f57515750d07e14743db55d59759893fdb21d2668f39e549a7d6cad5d70f9fea \ - --hash=sha256:f85151ec5a232335f1be022b09fbbe459042ea1951d8a48fef251223fc67eee1 \ - --hash=sha256:fb0315a2b26fde4005a7c401707c5352df274460f2f85b209cf6024271373013 \ - --hash=sha256:fc0916c4295c64d6890a46e02d4482bb5ccf33bf1a824c0eaa9e83b148291f90 \ - --hash=sha256:fd24fd140b69f0b0bcc9165c397e9b2e89ecbeda83303abf2a072609f60239e2 \ - --hash=sha256:fdae0120cddc839eb8e3c15faa8ad541cc6d906d3eb24d82fb041cfe2807bc1e \ - --hash=sha256:fe00f4fe11c8a521b173e6324d862ee7ee3412bf7107570c9b564fe1119b56fb +regex==2024.7.24 \ + --hash=sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c \ + --hash=sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535 \ + --hash=sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24 \ + --hash=sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce \ + --hash=sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc \ + --hash=sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5 \ + --hash=sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce \ + --hash=sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53 \ + --hash=sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d \ + --hash=sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c \ + --hash=sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908 \ + --hash=sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8 \ + --hash=sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024 \ + --hash=sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281 \ + --hash=sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a \ + --hash=sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169 \ + --hash=sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364 \ + --hash=sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa \ + --hash=sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be \ + --hash=sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53 \ + --hash=sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759 \ + --hash=sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e \ + --hash=sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b \ + --hash=sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52 \ + --hash=sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610 \ + --hash=sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05 \ + --hash=sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2 \ + --hash=sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca \ + --hash=sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0 \ + --hash=sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293 \ + --hash=sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289 \ + --hash=sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e \ + --hash=sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f \ + --hash=sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c \ + --hash=sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94 \ + --hash=sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad \ + --hash=sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46 \ + --hash=sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9 \ + --hash=sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9 \ + --hash=sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee \ + --hash=sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9 \ + --hash=sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1 \ + --hash=sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9 \ + --hash=sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799 \ + --hash=sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1 \ + --hash=sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b \ + --hash=sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf \ + --hash=sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5 \ + --hash=sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2 \ + --hash=sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e \ + --hash=sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51 \ + --hash=sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506 \ + --hash=sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73 \ + --hash=sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7 \ + --hash=sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5 \ + --hash=sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57 \ + --hash=sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4 \ + --hash=sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd \ + --hash=sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b \ + --hash=sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41 \ + --hash=sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe \ + --hash=sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59 \ + --hash=sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8 \ + --hash=sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f \ + --hash=sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e \ + --hash=sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750 \ + --hash=sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1 \ + --hash=sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96 \ + --hash=sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc \ + --hash=sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440 \ + --hash=sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe \ + --hash=sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38 \ + --hash=sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950 \ + --hash=sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2 \ + --hash=sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd \ + --hash=sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce \ + --hash=sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66 \ + --hash=sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3 \ + --hash=sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86 # via -r src/backend/requirements.in requests==2.32.3 \ --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ @@ -1440,118 +1477,122 @@ requests==2.32.3 \ # via # coreapi # opentelemetry-exporter-otlp-proto-http -rpds-py==0.18.1 \ - --hash=sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee \ - --hash=sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc \ - --hash=sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc \ - --hash=sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944 \ - --hash=sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20 \ - --hash=sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7 \ - --hash=sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4 \ - --hash=sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6 \ - --hash=sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6 \ - --hash=sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93 \ - --hash=sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633 \ - --hash=sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0 \ - --hash=sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360 \ - --hash=sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8 \ - --hash=sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139 \ - --hash=sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7 \ - --hash=sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a \ - --hash=sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9 \ - --hash=sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26 \ - --hash=sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724 \ - --hash=sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72 \ - --hash=sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b \ - --hash=sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09 \ - --hash=sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100 \ - --hash=sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3 \ - --hash=sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261 \ - --hash=sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3 \ - --hash=sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9 \ - --hash=sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b \ - --hash=sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3 \ - --hash=sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de \ - --hash=sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d \ - --hash=sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e \ - --hash=sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8 \ - --hash=sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff \ - --hash=sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5 \ - --hash=sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c \ - --hash=sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e \ - --hash=sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e \ - --hash=sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4 \ - --hash=sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8 \ - --hash=sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922 \ - --hash=sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338 \ - --hash=sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d \ - --hash=sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8 \ - --hash=sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2 \ - --hash=sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72 \ - --hash=sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80 \ - --hash=sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644 \ - --hash=sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae \ - --hash=sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163 \ - --hash=sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104 \ - --hash=sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d \ - --hash=sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60 \ - --hash=sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a \ - --hash=sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d \ - --hash=sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07 \ - --hash=sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49 \ - --hash=sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10 \ - --hash=sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f \ - --hash=sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2 \ - --hash=sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8 \ - --hash=sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7 \ - --hash=sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88 \ - --hash=sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65 \ - --hash=sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0 \ - --hash=sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909 \ - --hash=sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8 \ - --hash=sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c \ - --hash=sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184 \ - --hash=sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397 \ - --hash=sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a \ - --hash=sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346 \ - --hash=sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590 \ - --hash=sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333 \ - --hash=sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb \ - --hash=sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74 \ - --hash=sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e \ - --hash=sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d \ - --hash=sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa \ - --hash=sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f \ - --hash=sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53 \ - --hash=sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1 \ - --hash=sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac \ - --hash=sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0 \ - --hash=sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd \ - --hash=sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611 \ - --hash=sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f \ - --hash=sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c \ - --hash=sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5 \ - --hash=sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab \ - --hash=sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc \ - --hash=sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43 \ - --hash=sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da \ - --hash=sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac \ - --hash=sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843 \ - --hash=sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e \ - --hash=sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89 \ - --hash=sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64 +rpds-py==0.20.0 \ + --hash=sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c \ + --hash=sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585 \ + --hash=sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5 \ + --hash=sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6 \ + --hash=sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef \ + --hash=sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2 \ + --hash=sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29 \ + --hash=sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318 \ + --hash=sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b \ + --hash=sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399 \ + --hash=sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739 \ + --hash=sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee \ + --hash=sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174 \ + --hash=sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a \ + --hash=sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344 \ + --hash=sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2 \ + --hash=sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03 \ + --hash=sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5 \ + --hash=sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22 \ + --hash=sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e \ + --hash=sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96 \ + --hash=sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91 \ + --hash=sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752 \ + --hash=sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075 \ + --hash=sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253 \ + --hash=sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee \ + --hash=sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad \ + --hash=sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5 \ + --hash=sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce \ + --hash=sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7 \ + --hash=sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b \ + --hash=sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8 \ + --hash=sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57 \ + --hash=sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3 \ + --hash=sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec \ + --hash=sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209 \ + --hash=sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921 \ + --hash=sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045 \ + --hash=sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074 \ + --hash=sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580 \ + --hash=sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7 \ + --hash=sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5 \ + --hash=sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3 \ + --hash=sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0 \ + --hash=sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24 \ + --hash=sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139 \ + --hash=sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db \ + --hash=sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc \ + --hash=sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789 \ + --hash=sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f \ + --hash=sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2 \ + --hash=sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c \ + --hash=sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232 \ + --hash=sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6 \ + --hash=sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c \ + --hash=sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29 \ + --hash=sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489 \ + --hash=sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94 \ + --hash=sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751 \ + --hash=sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2 \ + --hash=sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda \ + --hash=sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9 \ + --hash=sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51 \ + --hash=sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c \ + --hash=sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8 \ + --hash=sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989 \ + --hash=sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511 \ + --hash=sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1 \ + --hash=sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2 \ + --hash=sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150 \ + --hash=sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c \ + --hash=sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965 \ + --hash=sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f \ + --hash=sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58 \ + --hash=sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b \ + --hash=sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f \ + --hash=sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d \ + --hash=sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821 \ + --hash=sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de \ + --hash=sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121 \ + --hash=sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855 \ + --hash=sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272 \ + --hash=sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60 \ + --hash=sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02 \ + --hash=sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1 \ + --hash=sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140 \ + --hash=sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879 \ + --hash=sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940 \ + --hash=sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364 \ + --hash=sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4 \ + --hash=sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e \ + --hash=sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420 \ + --hash=sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5 \ + --hash=sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24 \ + --hash=sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c \ + --hash=sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf \ + --hash=sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f \ + --hash=sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e \ + --hash=sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab \ + --hash=sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08 \ + --hash=sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92 \ + --hash=sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a \ + --hash=sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8 # via # jsonschema # referencing -sentry-sdk==2.8.0 \ - --hash=sha256:6051562d2cfa8087bb8b4b8b79dc44690f8a054762a29c07e22588b1f619bfb5 \ - --hash=sha256:aa4314f877d9cd9add5a0c9ba18e3f27f99f7de835ce36bd150e48a41c7c646f +sentry-sdk==2.13.0 \ + --hash=sha256:6beede8fc2ab4043da7f69d95534e320944690680dd9a963178a49de71d726c6 \ + --hash=sha256:8d4a576f7a98eb2fdb40e13106e41f330e5c79d72a68be1316e7852cf4995260 # via # -r src/backend/requirements.in # django-q-sentry -setuptools==72.1.0 \ - --hash=sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1 \ - --hash=sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec +setuptools==73.0.1 \ + --hash=sha256:b208925fcb9f7af924ed2dc04708ea89791e24bde0d3020b27df0e116088b34e \ + --hash=sha256:d59a3e788ab7e012ab2c4baed1b376da6366883ee20d7a5fc426816e3d7b1193 # via # -r src/backend/requirements.in # django-money @@ -1567,9 +1608,9 @@ six==1.16.0 \ # html5lib # isodate # python-dateutil -sqlparse==0.5.0 \ - --hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \ - --hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663 +sqlparse==0.5.1 \ + --hash=sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4 \ + --hash=sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e # via # django # django-sql-utils @@ -1586,6 +1627,10 @@ tinycss2==1.2.1 \ # bleach # cssselect2 # weasyprint +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f + # via pip-licenses typing-extensions==4.12.2 \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 @@ -1773,9 +1818,9 @@ xmlsec==1.3.14 \ --hash=sha256:e732a75fcb6b84872b168f972fbbf3749baf76308635f14015d1d35ed0c5719c \ --hash=sha256:ed4034939d8566ccdcd3b4e4f23c63fd807fb8763ae5668d59a19e11640a8242 # via python3-saml -zipp==3.19.2 \ - --hash=sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19 \ - --hash=sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c +zipp==3.20.0 \ + --hash=sha256:0145e43d89664cfe1a2e533adc75adafed82fe2da404b4bbb6b026c0157bdb31 \ + --hash=sha256:58da6168be89f0be59beb194da1250516fdaa062ccebd30127ac65d30045e10d # via importlib-metadata zopfli==0.2.3 \ --hash=sha256:0574372283befa5af98fb31407e1fe6822f2f9c437ef69e7fa260e49022d8a65 \ From df8efa902e94534187005a0c6bd8d157fd79898a Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Sat, 24 Aug 2024 01:14:38 +0200 Subject: [PATCH 11/21] fix: translation action wrong location (#7975) * set destination * cleanup files before submitting --- .github/workflows/translations.yaml | 8 ++++++++ crowdin.yml | 2 ++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml index 308e171a98..1d29eaaf53 100644 --- a/.github/workflows/translations.yaml +++ b/.github/workflows/translations.yaml @@ -40,6 +40,14 @@ jobs: apt-dependency: gettext - name: Make Translations run: invoke translate + - name: Remove compiled static files + run: rm -rf src/backend/InvenTree/static + - name: Remove all local changes that are not *.po files + run: | + git add /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po /src/frontend/src/locales/en/messages.po + git commit -m "add translations" + git reset --hard + git reset HEAD~ - name: crowdin action uses: crowdin/github-action@6ed209d411599a981ccb978df3be9dc9b8a81699 # pin@v2 with: diff --git a/crowdin.yml b/crowdin.yml index e6851f3632..74125c7681 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -3,6 +3,8 @@ files: - source: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po + dest: /%original_path%/%file_name% translation: /src/backend/InvenTree/locale/%two_letters_code%/LC_MESSAGES/%original_file_name% - source: /src/frontend/src/locales/en/messages.po + dest: /%original_path%/%file_name% translation: /src/frontend/src/locales/%two_letters_code%/%original_file_name% From ed2da62a46963d4202880441812f72dc684249e2 Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Sat, 24 Aug 2024 01:18:09 +0200 Subject: [PATCH 12/21] Fix state changes on stock items (#7976) * Revert changes from https://github.com/inventree/InvenTree/pull/7965 * Add error handling for wrong key * Add e2e test case for error condition Fixes #7964 * Better code code / flow * [BUG] Order of states in schema descriptions is not stable Fixes #7977 --- .../InvenTree/generic/states/fields.py | 32 ++++++++++++------- src/backend/InvenTree/stock/test_api.py | 8 +++++ .../templates/js/translated/stock.js | 2 +- src/frontend/src/forms/StockForms.tsx | 2 +- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/backend/InvenTree/generic/states/fields.py b/src/backend/InvenTree/generic/states/fields.py index 99717d4884..7f67f5c14b 100644 --- a/src/backend/InvenTree/generic/states/fields.py +++ b/src/backend/InvenTree/generic/states/fields.py @@ -41,7 +41,7 @@ class CustomChoiceField(serializers.ChoiceField): if self.is_custom: return logical.key return logical.logical_key - except ObjectDoesNotExist: + except (ObjectDoesNotExist, Exception): raise serializers.ValidationError('Invalid choice') def get_field_info(self, field, field_info): @@ -145,24 +145,32 @@ class InvenTreeCustomStatusSerializerMixin: def update(self, instance, validated_data): """Ensure the custom field is updated if the leader was changed.""" self.gather_custom_fields() + # Mirror values from leader to follower for field in self._custom_fields_leader: + follower_field_name = f'{field}_custom_key' if ( field in self.initial_data and self.instance and self.initial_data[field] - != getattr(self.instance, f'{field}_custom_key', None) + != getattr(self.instance, follower_field_name, None) ): - setattr(self.instance, f'{field}_custom_key', self.initial_data[field]) + setattr(self.instance, follower_field_name, self.initial_data[field]) + + # Mirror values from follower to leader for field in self._custom_fields_follower: - if ( - field in validated_data - and field.replace('_custom_key', '') not in self.initial_data - ): - reference = get_logical_value( - validated_data[field], - self.fields[field].choice_mdl._meta.model_name, - ) - validated_data[field.replace('_custom_key', '')] = reference.logical_key + leader_field_name = field.replace('_custom_key', '') + if field in validated_data and leader_field_name not in self.initial_data: + try: + reference = get_logical_value( + validated_data[field], + self.fields[field].choice_mdl._meta.model_name, + ) + validated_data[leader_field_name] = reference.logical_key + except (ObjectDoesNotExist, Exception): + if validated_data[field] in self.fields[leader_field_name].choices: + validated_data[leader_field_name] = validated_data[field] + else: + raise serializers.ValidationError('Invalid choice') return super().update(instance, validated_data) def to_representation(self, instance): diff --git a/src/backend/InvenTree/stock/test_api.py b/src/backend/InvenTree/stock/test_api.py index af73fa1b73..44e553cacf 100644 --- a/src/backend/InvenTree/stock/test_api.py +++ b/src/backend/InvenTree/stock/test_api.py @@ -1004,6 +1004,14 @@ class CustomStockItemStatusTest(StockAPITestCase): self.assertEqual(response.data['status'], self.status.logical_key) self.assertEqual(response.data['status_custom_key'], self.status.logical_key) + # Test case with wrong key + response = self.patch( + reverse('api-stock-detail', kwargs={'pk': pk}), + {'status_custom_key': 23456789}, + expected_code=400, + ) + self.assertIn('Invalid choice', str(response.data)) + def test_options(self): """Test the StockItem OPTIONS endpoint to contain custom StockStatuses.""" response = self.options(self.list_url) diff --git a/src/backend/InvenTree/templates/js/translated/stock.js b/src/backend/InvenTree/templates/js/translated/stock.js index 2e65072853..6c21536343 100644 --- a/src/backend/InvenTree/templates/js/translated/stock.js +++ b/src/backend/InvenTree/templates/js/translated/stock.js @@ -380,7 +380,7 @@ function stockItemFields(options={}) { batch: { icon: 'fa-layer-group', }, - status: {}, + status_custom_key: {}, expiry_date: { icon: 'fa-calendar-alt', }, diff --git a/src/frontend/src/forms/StockForms.tsx b/src/frontend/src/forms/StockForms.tsx index 3ed19c8938..7ac947826b 100644 --- a/src/frontend/src/forms/StockForms.tsx +++ b/src/frontend/src/forms/StockForms.tsx @@ -138,7 +138,7 @@ export function useStockFields({ value: batchCode, onValueChange: (value) => setBatchCode(value) }, - status: {}, + status_custom_key: {}, expiry_date: { // TODO: icon }, From 8a59829ef15ef22cf7ad8a8af55dd6b9e574cc95 Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Sat, 24 Aug 2024 01:21:06 +0200 Subject: [PATCH 13/21] [PUI] Add currency stats (#7971) * factor out stats overview * move to panel * Add currency stas overview Closes https://github.com/invenhost/InvenTree/issues/115 --- .../components/settings/FactCollection.tsx | 19 ++++++++ .../src/components/settings/FactItem.tsx | 14 ++++++ .../AdminCenter/CurrencyManagmentPanel.tsx} | 40 +++++++++++++---- .../Index/Settings/AdminCenter/Index.tsx | 10 ++--- .../AdminCenter/TaskManagementPanel.tsx | 43 ++++--------------- 5 files changed, 78 insertions(+), 48 deletions(-) create mode 100644 src/frontend/src/components/settings/FactCollection.tsx create mode 100644 src/frontend/src/components/settings/FactItem.tsx rename src/frontend/src/{tables/settings/CurrencyTable.tsx => pages/Index/Settings/AdminCenter/CurrencyManagmentPanel.tsx} (61%) diff --git a/src/frontend/src/components/settings/FactCollection.tsx b/src/frontend/src/components/settings/FactCollection.tsx new file mode 100644 index 0000000000..9c69464eb2 --- /dev/null +++ b/src/frontend/src/components/settings/FactCollection.tsx @@ -0,0 +1,19 @@ +import { SimpleGrid } from '@mantine/core'; + +import { FactItem } from './FactItem'; + +export function FactCollection({ + items, + minItems = 3 +}: { + items: { title: string; value: any }[]; + minItems?: number; +}) { + return ( + + {items.map((item, index) => ( + + ))} + + ); +} diff --git a/src/frontend/src/components/settings/FactItem.tsx b/src/frontend/src/components/settings/FactItem.tsx new file mode 100644 index 0000000000..bc549c3b50 --- /dev/null +++ b/src/frontend/src/components/settings/FactItem.tsx @@ -0,0 +1,14 @@ +import { Paper, Stack, Text } from '@mantine/core'; + +import { StylishText } from '../items/StylishText'; + +export function FactItem({ title, value }: { title: string; value: number }) { + return ( + + + {title} + {value} + + + ); +} diff --git a/src/frontend/src/tables/settings/CurrencyTable.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagmentPanel.tsx similarity index 61% rename from src/frontend/src/tables/settings/CurrencyTable.tsx rename to src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagmentPanel.tsx index e5ed7533c2..e9554d92a0 100644 --- a/src/frontend/src/tables/settings/CurrencyTable.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagmentPanel.tsx @@ -1,21 +1,24 @@ import { t } from '@lingui/macro'; +import { Divider, Stack } from '@mantine/core'; import { showNotification } from '@mantine/notifications'; import { IconReload } from '@tabler/icons-react'; -import { useCallback, useMemo } from 'react'; +import { useCallback, useMemo, useState } from 'react'; -import { api } from '../../App'; -import { ActionButton } from '../../components/buttons/ActionButton'; -import { ApiEndpoints } from '../../enums/ApiEndpoints'; -import { useTable } from '../../hooks/UseTable'; -import { apiUrl } from '../../states/ApiState'; -import { InvenTreeTable } from '../InvenTreeTable'; +import { api } from '../../../../App'; +import { ActionButton } from '../../../../components/buttons/ActionButton'; +import { FactCollection } from '../../../../components/settings/FactCollection'; +import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; +import { useTable } from '../../../../hooks/UseTable'; +import { apiUrl } from '../../../../states/ApiState'; +import { InvenTreeTable } from '../../../../tables/InvenTreeTable'; /* * Table for displaying available currencies */ -export default function CurrencyTable() { +export function CurrencyTable({ + setInfo +}: Readonly<{ setInfo: (info: any) => void }>) { const table = useTable('currency'); - const columns = useMemo(() => { return [ { @@ -53,6 +56,7 @@ export default function CurrencyTable() { const tableActions = useMemo(() => { return [ } @@ -69,6 +73,7 @@ export default function CurrencyTable() { idAccessor: 'currency', tableActions: tableActions, dataFormatter: (data: any) => { + setInfo(data); let rates = data.exchange_rates ?? {}; return Object.entries(rates).map(([currency, rate]) => { @@ -82,3 +87,20 @@ export default function CurrencyTable() { /> ); } + +export default function CurrencyManagmentPanel() { + const [info, setInfo] = useState({}); + + return ( + + + + + + ); +} diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx index 8f84261329..7c0b51c8d7 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx @@ -48,6 +48,10 @@ const TaskManagementPanel = Loadable( lazy(() => import('./TaskManagementPanel')) ); +const CurrencyManagmentPanel = Loadable( + lazy(() => import('./CurrencyManagmentPanel')) +); + const PluginManagementPanel = Loadable( lazy(() => import('./PluginManagementPanel')) ); @@ -88,10 +92,6 @@ const LocationTypesTable = Loadable( lazy(() => import('../../../../tables/stock/LocationTypesTable')) ); -const CurrencyTable = Loadable( - lazy(() => import('../../../../tables/settings/CurrencyTable')) -); - export default function AdminCenter() { const user = useUserState(); @@ -125,7 +125,7 @@ export default function AdminCenter() { name: 'currencies', label: t`Currencies`, icon: , - content: + content: }, { name: 'projectcodes', diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/TaskManagementPanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/TaskManagementPanel.tsx index 3ac9526166..47fb448b1d 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/TaskManagementPanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/TaskManagementPanel.tsx @@ -1,16 +1,9 @@ import { t } from '@lingui/macro'; -import { - Accordion, - Alert, - Divider, - Paper, - SimpleGrid, - Stack, - Text -} from '@mantine/core'; +import { Accordion, Alert, Divider, Stack, Text } from '@mantine/core'; import { lazy } from 'react'; import { StylishText } from '../../../../components/items/StylishText'; +import { FactCollection } from '../../../../components/settings/FactCollection'; import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; import { Loadable } from '../../../../functions/loading'; import { useInstance } from '../../../../hooks/UseInstance'; @@ -27,17 +20,6 @@ const FailedTasksTable = Loadable( lazy(() => import('../../../../tables/settings/FailedTasksTable')) ); -function TaskCountOverview({ title, value }: { title: string; value: number }) { - return ( - - - {title} - {value} - - - ); -} - export default function TaskManagementPanel() { const { instance: taskInfo } = useInstance({ endpoint: ApiEndpoints.task_overview, @@ -55,20 +37,13 @@ export default function TaskManagementPanel() { )} - - - - - + From ebb01c5e5b4d853e3f88d6c4c6cf387bad91e027 Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Sat, 24 Aug 2024 02:28:09 +0200 Subject: [PATCH 14/21] add path (#7979) --- .github/workflows/translations.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml index 1d29eaaf53..201407a97f 100644 --- a/.github/workflows/translations.yaml +++ b/.github/workflows/translations.yaml @@ -44,7 +44,7 @@ jobs: run: rm -rf src/backend/InvenTree/static - name: Remove all local changes that are not *.po files run: | - git add /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po /src/frontend/src/locales/en/messages.po + git add src/backend/InvenTree/locale/en/LC_MESSAGES/django.po src/frontend/src/locales/en/messages.po git commit -m "add translations" git reset --hard git reset HEAD~ From eec53ffd82fca4218150ce42838f8a0b5262feae Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 24 Aug 2024 15:17:05 +1000 Subject: [PATCH 15/21] [PUI] Build actions (#7945) * add table buttons to build line table * Add deallocate row action * Restrict row actions * Add functionality to 'deallocate' stock from build order * Implement 'auto-allocate' * Table column cleanup * Refactor code into new hook: - Helper function to update a set of selected rows - Callback function to remove row * Refactor existing forms to use new hook * Fix for RelatedModelField - Handle callback for null value * Memoize each field instance * Cleanup dead code * Define interfac for TableField row properties * Handle processing of nested errors * Pass form controller through to table field rows * Pass row errors through to individual table rows * Allow Standalone field to render errors * Allow allocation against build lines * Adjust quantity value when stock item is changed * Fix issue related to field name * Add "available" filter * Add "remove row" button * Add field for selecting source location * Filter out consumable items * Adjust form success message --- src/backend/InvenTree/build/serializers.py | 4 +- .../components/buttons/RemoveRowButton.tsx | 22 ++ src/frontend/src/components/forms/ApiForm.tsx | 15 +- .../src/components/forms/StandaloneField.tsx | 26 +- .../components/forms/fields/ApiFormField.tsx | 26 +- .../forms/fields/RelatedModelField.tsx | 2 +- .../components/forms/fields/TableField.tsx | 28 +- .../src/components/items/ProgressBar.tsx | 7 +- src/frontend/src/enums/ApiEndpoints.tsx | 3 + src/frontend/src/forms/BuildForms.tsx | 326 ++++++++++++++---- src/frontend/src/forms/PurchaseOrderForms.tsx | 9 +- src/frontend/src/forms/StockForms.tsx | 16 +- src/frontend/src/hooks/UseSelectedRows.tsx | 37 ++ src/frontend/src/pages/build/BuildDetail.tsx | 2 +- .../src/tables/build/BuildLineTable.tsx | 184 +++++++++- 15 files changed, 595 insertions(+), 112 deletions(-) create mode 100644 src/frontend/src/components/buttons/RemoveRowButton.tsx create mode 100644 src/frontend/src/hooks/UseSelectedRows.tsx diff --git a/src/backend/InvenTree/build/serializers.py b/src/backend/InvenTree/build/serializers.py index 473c4b423d..4471fe0297 100644 --- a/src/backend/InvenTree/build/serializers.py +++ b/src/backend/InvenTree/build/serializers.py @@ -891,8 +891,8 @@ class BuildUnallocationSerializer(serializers.Serializer): data = self.validated_data build.deallocate_stock( - build_line=data['build_line'], - output=data['output'] + build_line=data.get('build_line', None), + output=data.get('output', None), ) diff --git a/src/frontend/src/components/buttons/RemoveRowButton.tsx b/src/frontend/src/components/buttons/RemoveRowButton.tsx new file mode 100644 index 0000000000..f46a928cfc --- /dev/null +++ b/src/frontend/src/components/buttons/RemoveRowButton.tsx @@ -0,0 +1,22 @@ +import { t } from '@lingui/macro'; + +import { InvenTreeIcon } from '../../functions/icons'; +import { ActionButton } from './ActionButton'; + +export default function RemoveRowButton({ + onClick, + tooltip = t`Remove this row` +}: { + onClick: () => void; + tooltip?: string; +}) { + return ( + } + tooltip={tooltip} + tooltipAlignment="top" + color="red" + /> + ); +} diff --git a/src/frontend/src/components/forms/ApiForm.tsx b/src/frontend/src/components/forms/ApiForm.tsx index bfff18714e..a7390f62a1 100644 --- a/src/frontend/src/components/forms/ApiForm.tsx +++ b/src/frontend/src/components/forms/ApiForm.tsx @@ -502,7 +502,20 @@ export function ApiForm({ } if (typeof v === 'object' && Array.isArray(v)) { - form.setError(path, { message: v.join(', ') }); + if (field?.field_type == 'table') { + // Special handling for "table" fields - they have nested errors + v.forEach((item: any, idx: number) => { + for (const [key, value] of Object.entries(item)) { + const path: string = `${k}.${idx}.${key}`; + if (Array.isArray(value)) { + form.setError(path, { message: value.join(', ') }); + } + } + }); + } else { + // Standard error handling for other fields + form.setError(path, { message: v.join(', ') }); + } } else { processErrors(v, path); } diff --git a/src/frontend/src/components/forms/StandaloneField.tsx b/src/frontend/src/components/forms/StandaloneField.tsx index ea1c7c751e..b9f7345a56 100644 --- a/src/frontend/src/components/forms/StandaloneField.tsx +++ b/src/frontend/src/components/forms/StandaloneField.tsx @@ -1,37 +1,53 @@ -import { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { ApiFormField, ApiFormFieldType } from './fields/ApiFormField'; export function StandaloneField({ fieldDefinition, + fieldName = 'field', defaultValue, - hideLabels + hideLabels, + error }: { fieldDefinition: ApiFormFieldType; + fieldName?: string; defaultValue?: any; hideLabels?: boolean; + error?: string; }) { + // Field must have a defined name + const name = useMemo(() => fieldName ?? 'field', [fieldName]); + const defaultValues = useMemo(() => { if (defaultValue) return { - field: defaultValue + [name]: defaultValue }; return {}; }, [defaultValue]); - const form = useForm<{}>({ + const form = useForm({ criteriaMode: 'all', defaultValues }); + useEffect(() => { + form.clearErrors(); + + if (!!error) { + form.setError(name, { message: error }); + } + }, [form, error]); + return ( ); diff --git a/src/frontend/src/components/forms/fields/ApiFormField.tsx b/src/frontend/src/components/forms/fields/ApiFormField.tsx index 3e0147bd45..86539ce64c 100644 --- a/src/frontend/src/components/forms/fields/ApiFormField.tsx +++ b/src/frontend/src/components/forms/fields/ApiFormField.tsx @@ -204,8 +204,8 @@ export function ApiFormField({ }, [value]); // Construct the individual field - function buildField() { - switch (definition.field_type) { + const fieldInstance = useMemo(() => { + switch (fieldDefinition.field_type) { case 'related field': return ( ); } - } + }, [ + booleanValue, + control, + controller, + field, + fieldId, + fieldName, + fieldDefinition, + numericalValue, + onChange, + reducedDefinition, + ref, + setFields, + value + ]); - if (definition.hidden) { + if (fieldDefinition.hidden) { return null; } return ( {definition.preFieldContent} - {buildField()} + {fieldInstance} {definition.postFieldContent} ); diff --git a/src/frontend/src/components/forms/fields/RelatedModelField.tsx b/src/frontend/src/components/forms/fields/RelatedModelField.tsx index 728a32f35e..9a74cc4032 100644 --- a/src/frontend/src/components/forms/fields/RelatedModelField.tsx +++ b/src/frontend/src/components/forms/fields/RelatedModelField.tsx @@ -207,7 +207,7 @@ export function RelatedModelField({ setPk(_pk); // Run custom callback for this field (if provided) - definition.onValueChange?.(_pk, value.data ?? {}); + definition.onValueChange?.(_pk, value?.data ?? {}); }, [field.onChange, definition] ); diff --git a/src/frontend/src/components/forms/fields/TableField.tsx b/src/frontend/src/components/forms/fields/TableField.tsx index c4eadc915b..7fb6e3fa39 100644 --- a/src/frontend/src/components/forms/fields/TableField.tsx +++ b/src/frontend/src/components/forms/fields/TableField.tsx @@ -1,12 +1,21 @@ import { Trans, t } from '@lingui/macro'; import { Container, Group, Table } from '@mantine/core'; -import { useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { FieldValues, UseControllerReturn } from 'react-hook-form'; import { InvenTreeIcon } from '../../../functions/icons'; import { StandaloneField } from '../StandaloneField'; import { ApiFormFieldType } from './ApiFormField'; +export interface TableFieldRowProps { + item: any; + idx: number; + rowErrors: any; + control: UseControllerReturn; + changeFn: (idx: number, key: string, value: any) => void; + removeFn: (idx: number) => void; +} + export function TableField({ definition, fieldName, @@ -34,6 +43,16 @@ export function TableField({ field.onChange(val); }; + // Extract errors associated with the current row + const rowErrors = useCallback( + (idx: number) => { + if (Array.isArray(error)) { + return error[idx]; + } + }, + [error] + ); + return ( @@ -49,18 +68,21 @@ export function TableField({ // Table fields require render function if (!definition.modelRenderer) { return ( - {t`modelRenderer entry required for tables`} + {t`modelRenderer entry required for tables`} ); } + return definition.modelRenderer({ item: item, idx: idx, + rowErrors: rowErrors(idx), + control: control, changeFn: onRowFieldChange, removeFn: removeRow }); }) ) : ( - + ) { let maximum = props.maximum ?? 100; let value = Math.max(props.value, 0); - // Calculate progress as a percentage of the maximum value - return Math.min(100, (value / maximum) * 100); + if (maximum == 0) { + return 0; + } + + return (value / maximum) * 100; }, [props]); return ( diff --git a/src/frontend/src/enums/ApiEndpoints.tsx b/src/frontend/src/enums/ApiEndpoints.tsx index 1908a59577..6ce43aa910 100644 --- a/src/frontend/src/enums/ApiEndpoints.tsx +++ b/src/frontend/src/enums/ApiEndpoints.tsx @@ -74,6 +74,9 @@ export enum ApiEndpoints { build_output_create = 'build/:id/create-output/', build_output_scrap = 'build/:id/scrap-outputs/', build_output_delete = 'build/:id/delete-outputs/', + build_order_auto_allocate = 'build/:id/auto-allocate/', + build_order_allocate = 'build/:id/allocate/', + build_order_deallocate = 'build/:id/unallocate/', build_line_list = 'build/line/', build_item_list = 'build/item/', diff --git a/src/frontend/src/forms/BuildForms.tsx b/src/frontend/src/forms/BuildForms.tsx index 1b6a730191..fd86e6b4b8 100644 --- a/src/frontend/src/forms/BuildForms.tsx +++ b/src/frontend/src/forms/BuildForms.tsx @@ -1,5 +1,5 @@ import { t } from '@lingui/macro'; -import { Alert, Stack, Text } from '@mantine/core'; +import { Alert, Stack, Table, Text } from '@mantine/core'; import { IconCalendar, IconLink, @@ -10,16 +10,26 @@ import { IconUsersGroup } from '@tabler/icons-react'; import { DataTable } from 'mantine-datatable'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; +import { useFormContext } from 'react-hook-form'; import { api } from '../App'; import { ActionButton } from '../components/buttons/ActionButton'; -import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField'; +import RemoveRowButton from '../components/buttons/RemoveRowButton'; +import { StandaloneField } from '../components/forms/StandaloneField'; +import { + ApiFormFieldSet, + ApiFormFieldType +} from '../components/forms/fields/ApiFormField'; +import { TableFieldRowProps } from '../components/forms/fields/TableField'; +import { ProgressBar } from '../components/items/ProgressBar'; import { ApiEndpoints } from '../enums/ApiEndpoints'; import { ModelType } from '../enums/ModelType'; +import { resolveItem } from '../functions/conversion'; import { InvenTreeIcon } from '../functions/icons'; import { useCreateApiFormModal } from '../hooks/UseForm'; import { useBatchCodeGenerator } from '../hooks/UseGenerator'; +import { useSelectedRows } from '../hooks/UseSelectedRows'; import { apiUrl } from '../states/ApiState'; import { useGlobalSettingsState } from '../states/SettingsState'; import { PartColumn, StatusColumn } from '../tables/ColumnRenderers'; @@ -240,7 +250,7 @@ function buildOutputFormTable(outputs: any[], onRemove: (output: any) => void) { tooltip={t`Remove output`} icon={} color="red" - onClick={() => onRemove(record)} + onClick={() => onRemove(record.pk)} disabled={outputs.length <= 1} /> ) @@ -259,13 +269,11 @@ export function useCompleteBuildOutputsForm({ outputs: any[]; onFormSuccess: (response: any) => void; }) { - const [selectedOutputs, setSelectedOutputs] = useState([]); - const [location, setLocation] = useState(null); - useEffect(() => { - setSelectedOutputs(outputs); - }, [outputs]); + const { selectedRows, removeRow } = useSelectedRows({ + rows: outputs + }); useEffect(() => { if (location) { @@ -277,25 +285,15 @@ export function useCompleteBuildOutputsForm({ ); }, [location, build.destination, build.part_detail]); - // Remove a selected output from the list - const removeOutput = useCallback( - (output: any) => { - setSelectedOutputs( - selectedOutputs.filter((item) => item.pk != output.pk) - ); - }, - [selectedOutputs] - ); - const preFormContent = useMemo(() => { - return buildOutputFormTable(selectedOutputs, removeOutput); - }, [selectedOutputs, removeOutput]); + return buildOutputFormTable(selectedRows, removeRow); + }, [selectedRows, removeRow]); const buildOutputCompleteFields: ApiFormFieldSet = useMemo(() => { return { outputs: { hidden: true, - value: selectedOutputs.map((output) => { + value: selectedRows.map((output: any) => { return { output: output.pk }; @@ -314,7 +312,7 @@ export function useCompleteBuildOutputsForm({ notes: {}, accept_incomplete_allocation: {} }; - }, [selectedOutputs, location]); + }, [selectedRows, location]); return useCreateApiFormModal({ url: apiUrl(ApiEndpoints.build_output_complete, build.pk), @@ -327,6 +325,9 @@ export function useCompleteBuildOutputsForm({ }); } +/* + * Dynamic form for scraping multiple build outputs + */ export function useScrapBuildOutputsForm({ build, outputs, @@ -337,21 +338,10 @@ export function useScrapBuildOutputsForm({ onFormSuccess: (response: any) => void; }) { const [location, setLocation] = useState(null); - const [selectedOutputs, setSelectedOutputs] = useState([]); - useEffect(() => { - setSelectedOutputs(outputs); - }, [outputs]); - - // Remove a selected output from the list - const removeOutput = useCallback( - (output: any) => { - setSelectedOutputs( - selectedOutputs.filter((item) => item.pk != output.pk) - ); - }, - [selectedOutputs] - ); + const { selectedRows, removeRow } = useSelectedRows({ + rows: outputs + }); useEffect(() => { if (location) { @@ -364,14 +354,14 @@ export function useScrapBuildOutputsForm({ }, [location, build.destination, build.part_detail]); const preFormContent = useMemo(() => { - return buildOutputFormTable(selectedOutputs, removeOutput); - }, [selectedOutputs, removeOutput]); + return buildOutputFormTable(selectedRows, removeRow); + }, [selectedRows, removeRow]); const buildOutputScrapFields: ApiFormFieldSet = useMemo(() => { return { outputs: { hidden: true, - value: selectedOutputs.map((output) => { + value: selectedRows.map((output: any) => { return { output: output.pk, quantity: output.quantity @@ -387,7 +377,7 @@ export function useScrapBuildOutputsForm({ notes: {}, discard_allocations: {} }; - }, [location, selectedOutputs]); + }, [location, selectedRows]); return useCreateApiFormModal({ url: apiUrl(ApiEndpoints.build_output_scrap, build.pk), @@ -409,21 +399,9 @@ export function useCancelBuildOutputsForm({ outputs: any[]; onFormSuccess: (response: any) => void; }) { - const [selectedOutputs, setSelectedOutputs] = useState([]); - - useEffect(() => { - setSelectedOutputs(outputs); - }, [outputs]); - - // Remove a selected output from the list - const removeOutput = useCallback( - (output: any) => { - setSelectedOutputs( - selectedOutputs.filter((item) => item.pk != output.pk) - ); - }, - [selectedOutputs] - ); + const { selectedRows, removeRow } = useSelectedRows({ + rows: outputs + }); const preFormContent = useMemo(() => { return ( @@ -431,23 +409,23 @@ export function useCancelBuildOutputsForm({ {t`Selected build outputs will be deleted`} - {buildOutputFormTable(selectedOutputs, removeOutput)} + {buildOutputFormTable(selectedRows, removeRow)} ); - }, [selectedOutputs, removeOutput]); + }, [selectedRows, removeRow]); const buildOutputCancelFields: ApiFormFieldSet = useMemo(() => { return { outputs: { hidden: true, - value: selectedOutputs.map((output) => { + value: selectedRows.map((output: any) => { return { output: output.pk }; }) } }; - }, [selectedOutputs]); + }, [selectedRows]); return useCreateApiFormModal({ url: apiUrl(ApiEndpoints.build_output_delete, build.pk), @@ -459,3 +437,231 @@ export function useCancelBuildOutputsForm({ successMessage: t`Build outputs have been cancelled` }); } + +function buildAllocationFormTable( + outputs: any[], + onRemove: (output: any) => void +) { + return ( + PartColumn(record.part_detail) + }, + { + accessor: 'allocated', + title: t`Allocated`, + render: (record: any) => ( + + ) + }, + { + accessor: 'actions', + title: '', + render: (record: any) => ( + } + color="red" + onClick={() => onRemove(record.pk)} + disabled={outputs.length <= 1} + /> + ) + } + ]} + /> + ); +} + +// Construct a single row in the 'allocate stock to build' table +function BuildAllocateLineRow({ + props, + record, + sourceLocation +}: { + props: TableFieldRowProps; + record: any; + sourceLocation: number | undefined; +}) { + const stockField: ApiFormFieldType = useMemo(() => { + return { + field_type: 'related field', + api_url: apiUrl(ApiEndpoints.stock_item_list), + model: ModelType.stockitem, + filters: { + available: true, + part_detail: true, + location_detail: true, + bom_item: record.bom_item, + location: sourceLocation, + cascade: sourceLocation ? true : undefined + }, + value: props.item.stock_item, + name: 'stock_item', + onValueChange: (value: any, instance: any) => { + props.changeFn(props.idx, 'stock_item', value); + + // Update the allocated quantity based on the selected stock item + if (instance) { + let available = instance.quantity - instance.allocated; + + props.changeFn( + props.idx, + 'quantity', + Math.min(props.item.quantity, available) + ); + } + } + }; + }, [props]); + + const quantityField: ApiFormFieldType = useMemo(() => { + return { + field_type: 'number', + name: 'quantity', + required: true, + value: props.item.quantity, + onValueChange: (value: any) => { + props.changeFn(props.idx, 'quantity', value); + } + }; + }, [props]); + + const partDetail = useMemo( + () => PartColumn(record.part_detail), + [record.part_detail] + ); + + return ( + <> + + {partDetail} + + + + + + + + + + + props.removeFn(props.idx)} /> + + + + ); +} + +/* + * Dynamic form for allocating stock against multiple build order line items + */ +export function useAllocateStockToBuildForm({ + buildId, + outputId, + build, + lineItems, + onFormSuccess +}: { + buildId: number; + outputId?: number | null; + build: any; + lineItems: any[]; + onFormSuccess: (response: any) => void; +}) { + const [sourceLocation, setSourceLocation] = useState( + undefined + ); + + const buildAllocateFields: ApiFormFieldSet = useMemo(() => { + const fields: ApiFormFieldSet = { + items: { + field_type: 'table', + value: [], + headers: [t`Part`, t`Allocated`, t`Stock Item`, t`Quantity`], + modelRenderer: (row: TableFieldRowProps) => { + // Find the matching record from the passed 'lineItems' + const record = + lineItems.find((item) => item.pk == row.item.build_line) ?? {}; + return ( + + ); + } + } + }; + + return fields; + }, [lineItems, sourceLocation]); + + useEffect(() => { + setSourceLocation(build.take_from); + }, [build.take_from]); + + const sourceLocationField: ApiFormFieldType = useMemo(() => { + return { + field_type: 'related field', + api_url: apiUrl(ApiEndpoints.stock_location_list), + model: ModelType.stocklocation, + required: false, + label: t`Source Location`, + description: t`Select the source location for the stock allocation`, + name: 'source_location', + value: build.take_from, + onValueChange: (value: any) => { + setSourceLocation(value); + } + }; + }, [build?.take_from]); + + const preFormContent = useMemo(() => { + return ( + + + + ); + }, [sourceLocationField]); + + return useCreateApiFormModal({ + url: ApiEndpoints.build_order_allocate, + pk: buildId, + title: t`Allocate Stock`, + fields: buildAllocateFields, + preFormContent: preFormContent, + successMessage: t`Stock items allocated`, + onFormSuccess: onFormSuccess, + initialData: { + items: lineItems.map((item) => { + return { + build_line: item.pk, + stock_item: undefined, + quantity: Math.max(0, item.quantity - item.allocated), + output: null + }; + }) + }, + size: '80%' + }); +} diff --git a/src/frontend/src/forms/PurchaseOrderForms.tsx b/src/frontend/src/forms/PurchaseOrderForms.tsx index 28feda1a41..a6579a91b9 100644 --- a/src/frontend/src/forms/PurchaseOrderForms.tsx +++ b/src/frontend/src/forms/PurchaseOrderForms.tsx @@ -28,6 +28,7 @@ import { useEffect, useMemo, useState } from 'react'; import { api } from '../App'; import { ActionButton } from '../components/buttons/ActionButton'; +import RemoveRowButton from '../components/buttons/RemoveRowButton'; import { StandaloneField } from '../components/forms/StandaloneField'; import { ApiFormAdjustFilterType, @@ -438,13 +439,7 @@ function LineItemFormRow({ onClick={() => open()} /> )} - input.removeFn(input.idx)} - icon={} - tooltip={t`Remove item from list`} - tooltipAlignment="top" - color="red" - /> + input.removeFn(input.idx)} /> diff --git a/src/frontend/src/forms/StockForms.tsx b/src/frontend/src/forms/StockForms.tsx index 7ac947826b..18de04eb91 100644 --- a/src/frontend/src/forms/StockForms.tsx +++ b/src/frontend/src/forms/StockForms.tsx @@ -7,6 +7,7 @@ import { Suspense, useCallback, useMemo, useState } from 'react'; import { api } from '../App'; import { ActionButton } from '../components/buttons/ActionButton'; +import RemoveRowButton from '../components/buttons/RemoveRowButton'; import { ApiFormAdjustFilterType, ApiFormFieldSet @@ -322,13 +323,6 @@ function StockOperationsRow({ [item] ); - const changeSubItem = useCallback( - (key: string, value: any) => { - input.changeFn(input.idx, key, value); - }, - [input] - ); - const removeAndRefresh = () => { input.removeFn(input.idx); }; @@ -422,13 +416,7 @@ function StockOperationsRow({ variant={packagingOpen ? 'filled' : 'transparent'} /> )} - input.removeFn(input.idx)} - icon={} - tooltip={t`Remove item from list`} - tooltipAlignment="top" - color="red" - /> + input.removeFn(input.idx)} /> diff --git a/src/frontend/src/hooks/UseSelectedRows.tsx b/src/frontend/src/hooks/UseSelectedRows.tsx new file mode 100644 index 0000000000..8a089eec12 --- /dev/null +++ b/src/frontend/src/hooks/UseSelectedRows.tsx @@ -0,0 +1,37 @@ +import { useCallback, useEffect, useState } from 'react'; + +/** + * Hook to manage multiple selected rows in a multi-action modal. + * + * - The hook is initially provided with a list of rows + * - A callback is provided to remove a row, based on the provided ID value + */ +export function useSelectedRows({ + rows, + pkField = 'pk' +}: { + rows: T[]; + pkField?: string; +}) { + const [selectedRows, setSelectedRows] = useState(rows); + + // Update selection whenever input rows are updated + useEffect(() => { + setSelectedRows(rows); + }, [rows]); + + // Callback to remove the selected row + const removeRow = useCallback( + (pk: any) => { + setSelectedRows((rows) => + rows.filter((row: any) => row[pkField ?? 'pk'] !== pk) + ); + }, + [pkField] + ); + + return { + selectedRows, + removeRow + }; +} diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx index bc9a02981f..9e52db71ca 100644 --- a/src/frontend/src/pages/build/BuildDetail.tsx +++ b/src/frontend/src/pages/build/BuildDetail.tsx @@ -253,7 +253,7 @@ export default function BuildDetail() { label: t`Line Items`, icon: , content: build?.pk ? ( - + ) : ( ) diff --git a/src/frontend/src/tables/build/BuildLineTable.tsx b/src/frontend/src/tables/build/BuildLineTable.tsx index 83c87d5804..0ab49f02e6 100644 --- a/src/frontend/src/tables/build/BuildLineTable.tsx +++ b/src/frontend/src/tables/build/BuildLineTable.tsx @@ -1,19 +1,27 @@ import { t } from '@lingui/macro'; -import { Group, Text } from '@mantine/core'; +import { Alert, Group, Text } from '@mantine/core'; import { IconArrowRight, + IconCircleMinus, IconShoppingCart, - IconTool + IconTool, + IconTransferIn, + IconWand } from '@tabler/icons-react'; import { useCallback, useMemo, useState } from 'react'; +import { ActionButton } from '../../components/buttons/ActionButton'; import { ProgressBar } from '../../components/items/ProgressBar'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; -import { useBuildOrderFields } from '../../forms/BuildForms'; +import { + useAllocateStockToBuildForm, + useBuildOrderFields +} from '../../forms/BuildForms'; import { notYetImplemented } from '../../functions/notifications'; import { useCreateApiFormModal } from '../../hooks/UseForm'; +import useStatusCodes from '../../hooks/UseStatusCodes'; import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; @@ -26,15 +34,18 @@ import { TableHoverCard } from '../TableHoverCard'; export default function BuildLineTable({ buildId, + build, outputId, params = {} }: { buildId: number; + build: any; outputId?: number; params?: any; }) { const table = useTable('buildline'); const user = useUserState(); + const buildStatus = useStatusCodes({ modelType: ModelType.build }); const tableFilters: TableFilter[] = useMemo(() => { return [ @@ -211,7 +222,7 @@ export default function BuildLineTable({ ordering: 'unit_quantity', render: (record: any) => { return ( - + {record.bom_item_detail?.quantity} {record?.part_detail?.units && ( [{record.part_detail.units}] @@ -223,9 +234,10 @@ export default function BuildLineTable({ { accessor: 'quantity', sortable: true, + switchable: false, render: (record: any) => { return ( - + {record.quantity} {record?.part_detail?.units && ( [{record.part_detail.units}] @@ -262,6 +274,10 @@ export default function BuildLineTable({ const [initialData, setInitialData] = useState({}); + const [selectedLine, setSelectedLine] = useState(null); + + const [selectedRows, setSelectedRows] = useState([]); + const newBuildOrder = useCreateApiFormModal({ url: ApiEndpoints.build_order_list, title: t`Create Build Order`, @@ -271,6 +287,75 @@ export default function BuildLineTable({ modelType: ModelType.build }); + const autoAllocateStock = useCreateApiFormModal({ + url: ApiEndpoints.build_order_auto_allocate, + pk: build.pk, + title: t`Allocate Stock`, + fields: { + location: { + filters: { + structural: false + } + }, + exclude_location: {}, + interchangeable: {}, + substitutes: {}, + optional_items: {} + }, + initialData: { + location: build.take_from, + interchangeable: true, + substitutes: true, + optional_items: false + }, + successMessage: t`Auto allocation in progress`, + table: table, + preFormContent: ( + + {t`Automatically allocate stock to this build according to the selected options`} + + ) + }); + + const allowcateStock = useAllocateStockToBuildForm({ + build: build, + outputId: null, + buildId: build.pk, + lineItems: selectedRows, + onFormSuccess: () => { + table.refreshTable(); + } + }); + + const deallocateStock = useCreateApiFormModal({ + url: ApiEndpoints.build_order_deallocate, + pk: build.pk, + title: t`Deallocate Stock`, + fields: { + build_line: { + hidden: true + }, + output: { + hidden: true, + value: null + } + }, + initialData: { + build_line: selectedLine + }, + preFormContent: ( + + {selectedLine == undefined ? ( + {t`Deallocate all untracked stock for this build order`} + ) : ( + {t`Deallocate stock from the selected line item`} + )} + + ), + successMessage: t`Stock has been deallocated`, + table: table + }); + const rowActions = useCallback( (record: any): RowAction[] => { let part = record.part_detail ?? {}; @@ -280,6 +365,11 @@ export default function BuildLineTable({ return []; } + // Only allow actions when build is in production + if (!build?.status || build.status != buildStatus.PRODUCTION) { + return []; + } + const hasOutput = !!outputId; // Can allocate @@ -288,6 +378,12 @@ export default function BuildLineTable({ record.allocated < record.quantity && record.trackable == hasOutput; + // Can de-allocate + let canDeallocate = + user.hasChangeRole(UserRoles.build) && + record.allocated > 0 && + record.trackable == hasOutput; + let canOrder = user.hasAddRole(UserRoles.purchase_order) && part.purchaseable; let canBuild = user.hasAddRole(UserRoles.build) && part.assembly; @@ -298,7 +394,20 @@ export default function BuildLineTable({ title: t`Allocate Stock`, hidden: !canAllocate, color: 'green', - onClick: notYetImplemented + onClick: () => { + setSelectedRows([record]); + allowcateStock.open(); + } + }, + { + icon: , + title: t`Deallocate Stock`, + hidden: !canDeallocate, + color: 'red', + onClick: () => { + setSelectedLine(record.pk); + deallocateStock.open(); + } }, { icon: , @@ -323,12 +432,67 @@ export default function BuildLineTable({ } ]; }, - [user, outputId] + [user, outputId, build, buildStatus] ); + const tableActions = useMemo(() => { + const production = build.status == buildStatus.PRODUCTION; + const canEdit = user.hasChangeRole(UserRoles.build); + const visible = production && canEdit; + return [ + } + tooltip={t`Auto Allocate Stock`} + hidden={!visible} + color="blue" + onClick={() => { + autoAllocateStock.open(); + }} + />, + } + tooltip={t`Allocate Stock`} + hidden={!visible} + disabled={!table.hasSelectedRecords} + color="green" + onClick={() => { + setSelectedRows( + table.selectedRecords.filter( + (r) => + r.allocated < r.quantity && + !r.trackable && + !r.bom_item_detail.consumable + ) + ); + allowcateStock.open(); + }} + />, + } + tooltip={t`Deallocate Stock`} + hidden={!visible} + disabled={table.hasSelectedRecords} + color="red" + onClick={() => { + setSelectedLine(null); + deallocateStock.open(); + }} + /> + ]; + }, [ + user, + build, + buildStatus, + table.hasSelectedRecords, + table.selectedRecords + ]); + return ( <> + {autoAllocateStock.modal} {newBuildOrder.modal} + {allowcateStock.modal} + {deallocateStock.modal} From 2cf959cb8d1fd31f8a58e5989b20671614eefb55 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 25 Aug 2024 11:04:18 +1000 Subject: [PATCH 16/21] Forms refactor (#7981) * Refactor "receive stock" table - Display errors - Fix infinite rendering loop - Correctly set values to undefined on close * Refactor stock operations table * Fix for "change stock status" form * Fix default values * Unit test fix --- .../components/forms/fields/TableField.tsx | 4 + src/frontend/src/forms/BuildForms.tsx | 2 + src/frontend/src/forms/PurchaseOrderForms.tsx | 137 +++++++-------- src/frontend/src/forms/StockForms.tsx | 160 +++++++++--------- 4 files changed, 157 insertions(+), 146 deletions(-) diff --git a/src/frontend/src/components/forms/fields/TableField.tsx b/src/frontend/src/components/forms/fields/TableField.tsx index 7fb6e3fa39..333ed40cac 100644 --- a/src/frontend/src/components/forms/fields/TableField.tsx +++ b/src/frontend/src/components/forms/fields/TableField.tsx @@ -34,6 +34,7 @@ export function TableField({ const onRowFieldChange = (idx: number, key: string, value: any) => { const val = field.value; val[idx][key] = value; + field.onChange(val); }; @@ -114,11 +115,13 @@ export function TableFieldExtraRow({ fieldDefinition, defaultValue, emptyValue, + error, onValueChange }: { visible: boolean; fieldDefinition: ApiFormFieldType; defaultValue?: any; + error?: string; emptyValue?: any; onValueChange: (value: any) => void; }) { @@ -151,6 +154,7 @@ export function TableFieldExtraRow({ diff --git a/src/frontend/src/forms/BuildForms.tsx b/src/frontend/src/forms/BuildForms.tsx index fd86e6b4b8..b5b69e718d 100644 --- a/src/frontend/src/forms/BuildForms.tsx +++ b/src/frontend/src/forms/BuildForms.tsx @@ -554,12 +554,14 @@ function BuildAllocateLineRow({ diff --git a/src/frontend/src/forms/PurchaseOrderForms.tsx b/src/frontend/src/forms/PurchaseOrderForms.tsx index a6579a91b9..1d0b4c3019 100644 --- a/src/frontend/src/forms/PurchaseOrderForms.tsx +++ b/src/frontend/src/forms/PurchaseOrderForms.tsx @@ -5,7 +5,6 @@ import { FocusTrap, Group, Modal, - NumberInput, Table, TextInput } from '@mantine/core'; @@ -34,7 +33,10 @@ import { ApiFormAdjustFilterType, ApiFormFieldSet } from '../components/forms/fields/ApiFormField'; -import { TableFieldExtraRow } from '../components/forms/fields/TableField'; +import { + TableFieldExtraRow, + TableFieldRowProps +} from '../components/forms/fields/TableField'; import { Thumbnail } from '../components/images/Thumbnail'; import { ProgressBar } from '../components/items/ProgressBar'; import { StylishText } from '../components/items/StylishText'; @@ -192,67 +194,53 @@ export function usePurchaseOrderFields(): ApiFormFieldSet { * Render a table row for a single TableField entry */ function LineItemFormRow({ - input, + props, record, statuses }: { - input: any; + props: TableFieldRowProps; record: any; statuses: any; }) { // Barcode Modal state - const [opened, { open, close }] = useDisclosure(false); + const [opened, { open, close }] = useDisclosure(false, { + onClose: () => props.changeFn(props.idx, 'barcode', undefined) + }); - // Location value - const [location, setLocation] = useState( - input.item.location ?? - record.part_detail.default_location ?? - record.part_detail.category_default_location - ); - const [locationOpen, locationHandlers] = useDisclosure( - location ? true : false, - { - onClose: () => input.changeFn(input.idx, 'location', null), - onOpen: () => input.changeFn(input.idx, 'location', location) - } - ); - - // Change form value when state is altered - useEffect(() => { - input.changeFn(input.idx, 'location', location); - }, [location]); + const [locationOpen, locationHandlers] = useDisclosure(false, { + onClose: () => props.changeFn(props.idx, 'location', undefined) + }); + // Batch code generator const batchCodeGenerator = useBatchCodeGenerator((value: any) => { - if (!batchCode) { - setBatchCode(value); + if (value) { + props.changeFn(props.idx, 'batch_code', value); } }); + // Serial numbebr generator const serialNumberGenerator = useSerialNumberGenerator((value: any) => { - if (!serials) { - setSerials(value); + if (value) { + props.changeFn(props.idx, 'serial_numbers', value); } }); const [packagingOpen, packagingHandlers] = useDisclosure(false, { onClose: () => { - input.changeFn(input.idx, 'packaging', undefined); + props.changeFn(props.idx, 'packaging', undefined); } }); const [noteOpen, noteHandlers] = useDisclosure(false, { onClose: () => { - input.changeFn(input.idx, 'note', undefined); + props.changeFn(props.idx, 'note', undefined); } }); - // State for serializing - const [batchCode, setBatchCode] = useState(''); - const [serials, setSerials] = useState(''); const [batchOpen, batchHandlers] = useDisclosure(false, { onClose: () => { - input.changeFn(input.idx, 'batch_code', undefined); - input.changeFn(input.idx, 'serial_numbers', ''); + props.changeFn(props.idx, 'batch_code', undefined); + props.changeFn(props.idx, 'serial_numbers', undefined); }, onOpen: () => { // Generate a new batch code @@ -263,23 +251,23 @@ function LineItemFormRow({ // Generate new serial numbers serialNumberGenerator.update({ part: record?.supplier_part_detail?.part, - quantity: input.item.quantity + quantity: props.item.quantity }); } }); // Status value const [statusOpen, statusHandlers] = useDisclosure(false, { - onClose: () => input.changeFn(input.idx, 'status', 10) + onClose: () => props.changeFn(props.idx, 'status', undefined) }); // Barcode value const [barcodeInput, setBarcodeInput] = useState(''); - const [barcode, setBarcode] = useState(null); + const [barcode, setBarcode] = useState(undefined); // Change form value when state is altered useEffect(() => { - input.changeFn(input.idx, 'barcode', barcode); + props.changeFn(props.idx, 'barcode', barcode); }, [barcode]); // Update location field description on state change @@ -371,13 +359,16 @@ function LineItemFormRow({ progressLabel /> - - input.changeFn(input.idx, 'quantity', value)} + + + props.changeFn(props.idx, 'quantity', value) + }} + error={props.rowErrors?.quantity?.message} /> @@ -404,6 +395,7 @@ function LineItemFormRow({ size="sm" icon={} tooltip={t`Adjust Packaging`} + tooltipAlignment="top" onClick={() => packagingHandlers.toggle()} variant={packagingOpen ? 'filled' : 'transparent'} /> @@ -428,7 +420,7 @@ function LineItemFormRow({ tooltipAlignment="top" variant="filled" color="red" - onClick={() => setBarcode(null)} + onClick={() => setBarcode(undefined)} /> ) : ( open()} /> )} - input.removeFn(input.idx)} /> + props.removeFn(props.idx)} /> @@ -459,7 +451,7 @@ function LineItemFormRow({ structural: false }, onValueChange: (value) => { - setLocation(value); + props.changeFn(props.idx, 'location', value); }, description: locationDescription, value: location, @@ -480,7 +472,9 @@ function LineItemFormRow({ icon={} tooltip={t`Store at default location`} onClick={() => - setLocation( + props.changeFn( + props.idx, + 'location', record.part_detail.default_location ?? record.part_detail.category_default_location ) @@ -492,7 +486,9 @@ function LineItemFormRow({ } tooltip={t`Store at line item destination `} - onClick={() => setLocation(record.destination)} + onClick={() => + props.changeFn(props.idx, 'location', record.destination) + } tooltipAlignment="top" /> )} @@ -502,7 +498,13 @@ function LineItemFormRow({ } tooltip={t`Store with already received stock`} - onClick={() => setLocation(record.destination_detail.pk)} + onClick={() => + props.changeFn( + props.idx, + 'location', + record.destination_detail.pk + ) + } tooltipAlignment="top" /> )} @@ -513,51 +515,56 @@ function LineItemFormRow({ )} input.changeFn(input.idx, 'batch', value)} + onValueChange={(value) => props.changeFn(props.idx, 'batch', value)} fieldDefinition={{ field_type: 'string', label: t`Batch Code`, - value: batchCode + value: props.item.batch_code }} + error={props.rowErrors?.batch_code?.message} /> - input.changeFn(input.idx, 'serial_numbers', value) + props.changeFn(props.idx, 'serial_numbers', value) } fieldDefinition={{ field_type: 'string', label: t`Serial numbers`, - value: serials + value: props.item.serial_numbers }} + error={props.rowErrors?.serial_numbers?.message} /> input.changeFn(input.idx, 'packaging', value)} + onValueChange={(value) => props.changeFn(props.idx, 'packaging', value)} fieldDefinition={{ field_type: 'string', label: t`Packaging` }} defaultValue={record?.supplier_part_detail?.packaging} + error={props.rowErrors?.packaging?.message} /> input.changeFn(input.idx, 'status', value)} + onValueChange={(value) => props.changeFn(props.idx, 'status', value)} fieldDefinition={{ field_type: 'choice', api_url: apiUrl(ApiEndpoints.stock_status), choices: statuses, label: t`Status` }} + error={props.rowErrors?.status?.message} /> input.changeFn(input.idx, 'note', value)} + onValueChange={(value) => props.changeFn(props.idx, 'note', value)} fieldDefinition={{ field_type: 'string', label: t`Note` }} + error={props.rowErrors?.note?.message} /> ); @@ -619,12 +626,12 @@ export function useReceiveLineItems(props: LineItemsForm) { barcode: null }; }), - modelRenderer: (instance) => { - const record = records[instance.item.line_item]; + modelRenderer: (row: TableFieldRowProps) => { + const record = records[row.item.line_item]; return ( setBatchCode(value) }, - status_custom_key: {}, + status_custom_key: { + label: t`Stock Status` + }, expiry_date: { // TODO: icon }, @@ -295,47 +301,37 @@ type StockRow = { }; function StockOperationsRow({ - input, + props, transfer = false, add = false, setMax = false, merge = false, record }: { - input: StockRow; + props: TableFieldRowProps; transfer?: boolean; add?: boolean; setMax?: boolean; merge?: boolean; record?: any; }) { - const item = input.item; - - const [value, setValue] = useState( - add ? 0 : item.quantity ?? 0 - ); - - const onChange = useCallback( - (value: any) => { - setValue(value); - input.changeFn(input.idx, 'quantity', value); - }, - [item] + const [quantity, setQuantity] = useState( + add ? 0 : props.item?.quantity ?? 0 ); const removeAndRefresh = () => { - input.removeFn(input.idx); + props.removeFn(props.idx); }; const [packagingOpen, packagingHandlers] = useDisclosure(false, { onOpen: () => { if (transfer) { - input.changeFn(input.idx, 'packaging', record?.packaging || undefined); + props.changeFn(props.idx, 'packaging', record?.packaging || undefined); } }, onClose: () => { if (transfer) { - input.changeFn(input.idx, 'packaging', undefined); + props.changeFn(props.idx, 'packaging', undefined); } } }); @@ -371,25 +367,24 @@ function StockOperationsRow({ {record.location ? record.location_detail?.pathstring : '-'} - - - {stockString} - - - + + {stockString} + + {!merge && ( - { + setQuantity(value); + props.changeFn(props.idx, 'quantity', value); + } + }} + error={props.rowErrors?.quantity?.message} /> )} @@ -397,7 +392,9 @@ function StockOperationsRow({ {transfer && ( moveToDefault(record, value, removeAndRefresh)} + onClick={() => + moveToDefault(record, props.item.quantity, removeAndRefresh) + } icon={} tooltip={t`Move to default location`} tooltipAlignment="top" @@ -416,7 +413,7 @@ function StockOperationsRow({ variant={packagingOpen ? 'filled' : 'transparent'} /> )} - input.removeFn(input.idx)} /> + props.removeFn(props.idx)} /> @@ -424,7 +421,7 @@ function StockOperationsRow({ { - input.changeFn(input.idx, 'packaging', value || undefined); + props.changeFn(props.idx, 'packaging', value || undefined); }} fieldDefinition={{ field_type: 'string', @@ -452,9 +449,9 @@ function mapAdjustmentItems(items: any[]) { return { pk: elem.pk, quantity: elem.quantity, - batch: elem.batch, - status: elem.status, - packaging: elem.packaging, + batch: elem.batch || undefined, + status: elem.status || undefined, + packaging: elem.packaging || undefined, obj: elem }; }); @@ -473,14 +470,16 @@ function stockTransferFields(items: any[]): ApiFormFieldSet { items: { field_type: 'table', value: mapAdjustmentItems(items), - modelRenderer: (val) => { + modelRenderer: (row: TableFieldRowProps) => { + const record = records[row.item.pk]; + return ( ); }, @@ -508,13 +507,16 @@ function stockRemoveFields(items: any[]): ApiFormFieldSet { items: { field_type: 'table', value: mapAdjustmentItems(items), - modelRenderer: (val) => { + modelRenderer: (row: TableFieldRowProps) => { + const record = records[row.item.pk]; + return ( ); }, @@ -537,14 +539,11 @@ function stockAddFields(items: any[]): ApiFormFieldSet { items: { field_type: 'table', value: mapAdjustmentItems(items), - modelRenderer: (val) => { + modelRenderer: (row: TableFieldRowProps) => { + const record = records[row.item.pk]; + return ( - + ); }, headers: [t`Part`, t`Location`, t`In Stock`, t`Add`, t`Actions`] @@ -566,12 +565,12 @@ function stockCountFields(items: any[]): ApiFormFieldSet { items: { field_type: 'table', value: mapAdjustmentItems(items), - modelRenderer: (val) => { + modelRenderer: (row: TableFieldRowProps) => { return ( ); }, @@ -596,19 +595,19 @@ function stockChangeStatusFields(items: any[]): ApiFormFieldSet { value: items.map((elem) => { return elem.pk; }), - modelRenderer: (val) => { + modelRenderer: (row: TableFieldRowProps) => { return ( ); }, headers: [t`Part`, t`Location`, t`In Stock`, t`Actions`] }, - status_custom_key: {}, + status: {}, note: {} }; @@ -631,13 +630,13 @@ function stockMergeFields(items: any[]): ApiFormFieldSet { obj: elem }; }), - modelRenderer: (val) => { + modelRenderer: (row: TableFieldRowProps) => { return ( ); }, @@ -673,13 +672,13 @@ function stockAssignFields(items: any[]): ApiFormFieldSet { obj: elem }; }), - modelRenderer: (val) => { + modelRenderer: (row: TableFieldRowProps) => { return ( ); }, @@ -709,13 +708,15 @@ function stockDeleteFields(items: any[]): ApiFormFieldSet { value: items.map((elem) => { return elem.pk; }), - modelRenderer: (val) => { + modelRenderer: (row: TableFieldRowProps) => { + const record = records[row.item]; + return ( ); }, @@ -803,6 +804,7 @@ function stockOperationModal({ url: endpoint, fields: fields, title: title, + size: '80%', onFormSuccess: () => refresh() }); } From 7e6ca121ec47ec989e5fed4e7fb711febc9e47d5 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 25 Aug 2024 11:54:53 +1000 Subject: [PATCH 17/21] Add git config for CI (#7983) --- .github/workflows/translations.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/translations.yaml b/.github/workflows/translations.yaml index 201407a97f..7d836119b9 100644 --- a/.github/workflows/translations.yaml +++ b/.github/workflows/translations.yaml @@ -44,6 +44,8 @@ jobs: run: rm -rf src/backend/InvenTree/static - name: Remove all local changes that are not *.po files run: | + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" git add src/backend/InvenTree/locale/en/LC_MESSAGES/django.po src/frontend/src/locales/en/messages.po git commit -m "add translations" git reset --hard From 695174810a1085a7c9735e46cbbc5c718a922a6a Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 25 Aug 2024 12:39:50 +1000 Subject: [PATCH 18/21] Try adding option (#7984) --- crowdin.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crowdin.yml b/crowdin.yml index 74125c7681..15be06f36e 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,6 +1,8 @@ "commit_message": "Fix: New translations %original_file_name% from Crowdin" "append_commit_message": false +"preserve_hierarchy": true + files: - source: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po dest: /%original_path%/%file_name% From d98c396f0790f398abc293c91dd7209d0af2d79b Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 25 Aug 2024 13:17:24 +1000 Subject: [PATCH 19/21] Update crowdin.yml (#7985) - Add documentation strings - Attempt to "fix" dest parameters --- crowdin.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crowdin.yml b/crowdin.yml index 15be06f36e..311bbc8e9b 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,12 +1,14 @@ +# Configuration file for Crowdin project integration +# See: https://crowdin.com/project/inventree + "commit_message": "Fix: New translations %original_file_name% from Crowdin" "append_commit_message": false - "preserve_hierarchy": true files: - source: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po - dest: /%original_path%/%file_name% + dest: /%original_path%/%original_file_name% translation: /src/backend/InvenTree/locale/%two_letters_code%/LC_MESSAGES/%original_file_name% - source: /src/frontend/src/locales/en/messages.po - dest: /%original_path%/%file_name% + dest: /%original_path%/%original_file_name% translation: /src/frontend/src/locales/%two_letters_code%/%original_file_name% From 881220cdb34a519decd0f9d01b96d441b5f1b0d6 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 26 Aug 2024 09:40:45 +1000 Subject: [PATCH 20/21] Hide "build orders" tab for inactive parts (#7992) - Otherwise results in a 400 error --- src/frontend/src/pages/part/PartDetail.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx index 8be6048f06..5cd977b477 100644 --- a/src/frontend/src/pages/part/PartDetail.tsx +++ b/src/frontend/src/pages/part/PartDetail.tsx @@ -622,7 +622,7 @@ export default function PartDetail() { name: 'builds', label: t`Build Orders`, icon: , - hidden: !part.assembly, + hidden: !part.assembly || !part.active, content: part?.pk ? : }, { From d1c835485982650dfa4a9c6b51142ab9660584d4 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 26 Aug 2024 15:18:46 +1000 Subject: [PATCH 21/21] Reset page offset when changing page size (#7994) - Prevents table rendering an "empty" page --- src/frontend/src/tables/InvenTreeTable.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/src/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx index fa74a5f468..c5164e1946 100644 --- a/src/frontend/src/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -590,6 +590,7 @@ export function InvenTreeTable({ // pagination refresth table if pageSize changes function updatePageSize(newData: number) { tableState.setPageSize(newData); + tableState.setPage(1); tableState.refreshTable(); }