Merge branch 'master' into tree-select

This commit is contained in:
Oliver 2026-06-24 22:10:10 +10:00 committed by GitHub
commit ea20dbca09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
136 changed files with 29221 additions and 28395 deletions

View File

@ -1,9 +1,7 @@
# Dockerfile for the InvenTree devcontainer
# This container is used for development of the InvenTree project, and includes all necessary dependencies for both backend and frontend development.
# In contrast with the "production" image (which is based on an Alpine image)
# we use a Debian-based image for the devcontainer
FROM mcr.microsoft.com/devcontainers/python:3.11-bookworm@sha256:e754c29c4e3ffcf6c794c1020e36a0812341d88ec9569a34704b975fa89e8848
FROM mcr.microsoft.com/devcontainers/python:3.14-trixie@sha256:66af9ee0a89e76f83b5c54a0cfdc19966ec8e443e294707f8f9b45f465b42cf1
# InvenTree paths
ENV INVENTREE_HOME="/home/inventree"
@ -25,10 +23,10 @@ RUN chmod +x init.sh
# Install required base packages
RUN apt update && apt install -y \
python3.11-dev python3.11-venv \
python3-dev python3-venv \
postgresql-client \
libldap2-dev libsasl2-dev \
libpango1.0-0 libcairo2 \
libpango-1.0-0 libcairo2 \
poppler-utils weasyprint
# Install packages required for frontend development

View File

@ -14,7 +14,7 @@ pool:
strategy:
matrix:
Python39:
PYTHON_VERSION: '3.11'
PYTHON_VERSION: 3.12
maxParallel: 3
steps:

View File

@ -9,7 +9,7 @@ on:
- l10
env:
python_version: 3.11
python_version: 3.12
permissions:
contents: read

View File

@ -62,7 +62,7 @@ jobs:
contents: read
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: "3.11"
python_version: 3.12
runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps:
@ -134,7 +134,7 @@ jobs:
contents: read
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: "3.11"
python_version: 3.12
runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps:
@ -158,7 +158,7 @@ jobs:
id-token: write
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: "3.11"
python_version: 3.12
runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps:

View File

@ -13,7 +13,7 @@ on:
branches-ignore: ["l10*"]
env:
python_version: 3.11
python_version: 3.12
node_version: 24
# The OS version must be set per job
server_start_sleep: 60
@ -195,6 +195,9 @@ jobs:
--health-interval 10s
--health-timeout 5s
--health-retries 5
permissions:
contents: read # Required for actions/checkout
id-token: write # Required for GitHub OIDC
env:
COVERAGE: true

View File

@ -15,7 +15,7 @@ permissions:
contents: read
env:
python_version: 3.11
python_version: 3.12
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -9,7 +9,7 @@ on:
branches-ignore: ["l10*"]
env:
python_version: 3.11
python_version: 3.12
node_version: 24
# The OS version must be set per job
server_start_sleep: 60
@ -222,7 +222,7 @@ jobs:
echo "Downloaded api.yaml"
- name: Running OpenAPI Spec diff action
id: breaking_changes
uses: oasdiff/oasdiff-action/diff@3530478ec30f84adedbfeb28f0d9527a290f50a9 # pin@main
uses: oasdiff/oasdiff-action/diff@5fbe96ede8d0c53aeadef122d7a0abb79152d493 # pin@main
with:
base: "api.yaml"
revision: "src/backend/InvenTree/schema.yml"
@ -363,7 +363,7 @@ jobs:
pip install .
if: needs.paths-filter.outputs.submit-performance == 'true'
- name: Performance Reporting
uses: CodSpeedHQ/action@9d332c4d90b43981c3e55ae8e38e68709996240f # pin@v4.17.0
uses: CodSpeedHQ/action@c145068895e045cc725ee76fcd2307624b65c3af # pin@v4.17.5
# check if we are in inventree/inventree - reporting only works in that OIDC context
if: github.repository == 'inventree/InvenTree' && needs.paths-filter.outputs.submit-performance == 'true'
with:
@ -379,7 +379,7 @@ jobs:
continue-on-error: true # continue if a step fails so that coverage gets pushed
strategy:
matrix:
python_version: [3.11, 3.14]
python_version: [3.12, 3.14]
env:
INVENTREE_DB_NAME: ./inventree.sqlite
@ -454,7 +454,7 @@ jobs:
env:
node_version: '>=24'
- name: Performance Reporting
uses: CodSpeedHQ/action@9d332c4d90b43981c3e55ae8e38e68709996240f # pin@v4.17.0
uses: CodSpeedHQ/action@c145068895e045cc725ee76fcd2307624b65c3af # pin@v4.17.5
with:
mode: walltime
run: inv dev.test --pytest

View File

@ -7,7 +7,7 @@ on:
permissions:
contents: read
env:
python_version: 3.11
python_version: 3.12
jobs:
stable:
@ -151,9 +151,9 @@ jobs:
fail-fast: false
matrix:
target:
- ubuntu:22.04
- ubuntu:24.04
- debian:12
- ubuntu:26.04
- debian:13
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # pin@v6.0.3

View File

@ -6,7 +6,7 @@ on:
- master
env:
python_version: 3.11
python_version: 3.12
node_version: 24
permissions:
@ -56,7 +56,7 @@ jobs:
echo "Resetting to HEAD~"
git reset HEAD~ || true
- name: crowdin action
uses: crowdin/github-action@8868a33591d21088edfc398968173a3b98d51706 # pin@v2
uses: crowdin/github-action@52aa776766211d83d975df51f3b9c53c2f8ba35f # pin@v2
with:
upload_sources: true
upload_translations: false

View File

@ -21,9 +21,9 @@ before:
dependencies:
- curl
- poppler-utils
- "python3.11 | python3.12 | python3.13 | python3.14"
- "python3.11-venv | python3.12-venv | python3.13-venv | python3.14-venv"
- "python3.11-dev | python3.12-dev | python3.13-dev | python3.14-dev"
- "python3.12 | python3.13 | python3.14"
- "python3.12-venv | python3.13-venv | python3.14-venv"
- "python3.12-dev | python3.13-dev | python3.14-dev"
- python3-pip
- python3-cffi
- python3-brotli
@ -36,6 +36,6 @@ dependencies:
- jq
- "libffi7 | libffi8"
targets:
ubuntu-22.04: true
ubuntu-24.04: true
debian-12: true
ubuntu-26.04: true
debian-13: true

View File

@ -37,7 +37,7 @@ repos:
files: src/backend/requirements-dev\.(in|txt)$
- id: pip-compile
name: pip-compile requirements-dev.in 3.14
args: [src/backend/requirements-dev.in, -o, src/backend/requirements-dev-3.14.txt, -c, src/backend/requirements-3.14.txt, --python-version=3.14, -c, src/backend/requirements.txt]
args: [src/backend/requirements-dev.in, -o, src/backend/requirements-dev-3.14.txt, -c, src/backend/requirements-3.14.txt, --python-version=3.14, -c, src/backend/requirements.txt, -c, src/backend/requirements-dev.txt]
files: src/backend/requirements-dev\.(in|txt)$
- id: pip-compile
name: pip-compile requirements.txt
@ -97,4 +97,4 @@ repos:
rev: 0.4.3
hooks:
- id: teyit
language_version: python3.11
language_version: python3.12

2
.vscode/launch.json vendored
View File

@ -47,7 +47,7 @@
"name": "InvenTree invoke schema",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/.venv/lib/python3.11/site-packages/invoke/__main__.py",
"program": "${workspaceFolder}/.venv/lib/python3.12/site-packages/invoke/__main__.py",
"cwd": "${workspaceFolder}",
"args": [
"dev.schema","--ignore-warnings"

View File

@ -5,7 +5,19 @@ All major notable changes to this project will be documented in this file (start
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased - YYYY-MM-DD
## Unreleased - xxxx.xx.xx
### Breaking Changes
- [#12223](https://github.com/inventree/InvenTree/pull/12223) removes support for python 3.11 and stops providing packages for Debian 11 and Ubuntu 20.04.
### Added
### Changed
### Removed
## 1.4.0 - 2026-06-24
### Breaking Changes

View File

@ -24,7 +24,7 @@ flag_management:
carryforward: true
statuses:
- type: project
target: 40%
target: 38%
- name: web
carryforward: true
statuses:

View File

@ -79,7 +79,7 @@ function detect_python() {
echo "${On_Red}"
echo "# POI07| Python ${SETUP_PYTHON} not found - aborting!"
echo "# POI07| Please ensure python can be executed with the command '$SETUP_PYTHON' by the current user '$USER'."
echo "# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.11'."
echo "# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.12'."
echo "${Color_Off}"
exit 1
fi

View File

@ -26,7 +26,7 @@ export DATA_DIR=${APP_HOME}/data
export SETUP_NGINX_FILE=${SETUP_NGINX_FILE:-/etc/nginx/sites-enabled/inventree.conf}
export SETUP_ADMIN_PASSWORD_FILE=${CONF_DIR}/admin_password.txt
export SETUP_NO_CALLS=${SETUP_NO_CALLS:-false}
export SETUP_PYTHON=${SETUP_PYTHON:-python3.11}
export SETUP_PYTHON=${SETUP_PYTHON:-python3.12}
export SETUP_ADMIN_NOCREATION=${SETUP_ADMIN_NOCREATION:-false}
# SETUP_DEBUG can be set to get debug info
# SETUP_EXTRA_PIP can be set to install extra pip packages

View File

@ -4,10 +4,10 @@ import json
import os
import re
from datetime import datetime
from distutils.version import StrictVersion # type: ignore[import]
from pathlib import Path
import requests
from packaging.version import Version
here = Path(__file__).parent
@ -57,7 +57,7 @@ def fetch_rtd_versions():
print('No RTD token found - skipping RTD version fetch')
# Sort versions by version number
versions = sorted(versions, key=lambda x: StrictVersion(x['version']), reverse=True)
versions = sorted(versions, key=lambda x: Version(x['version']), reverse=True)
# Add "latest" version first
if not any(x['title'] == 'latest' for x in versions):

View File

@ -54,14 +54,14 @@ class InvenTreeBarcodePlugin(BarcodeMixin, InvenTreePlugin):
VERSION = "0.0.1"
AUTHOR = "Michael"
def scan(self, barcode_data):
def scan(self, barcode_data, user, **kwargs):
if barcode_data.startswith("PART-"):
try:
pk = int(barcode_data.split("PART-")[1])
instance = Part.objects.get(pk=pk)
label = Part.barcode_model_type()
return {label: instance.format_matched_response()}
return {label: instance.format_matched_response(user=user)}
except Part.DoesNotExist:
pass
```

View File

@ -325,7 +325,7 @@ ARG INVENTREE_TAG
# prebuild stage - needs a lot of build dependencies
# make sure, the alpine and python version matches the version used in the inventree base image
FROM python:3.11-alpine3.18 as prebuild
FROM python:3.12-alpine3.18 as prebuild
# Install whatever development dependency is needed (e.g. cups-dev, gcc, the musl-dev build tools and the pip pycups package)
RUN apk add --no-cache cups-dev gcc musl-dev && \

View File

@ -366,7 +366,7 @@ extra:
# provider: google
# property: UA-143467500-1
min_python_version: 3.11
min_python_version: 3.12
min_invoke_version: 2.0.0
django_version: 5.2
docker_postgres_version: 17

View File

@ -97,25 +97,25 @@ skip-magic-trailing-comma = true
line-ending = "auto"
[tool.uv.pip]
python-version = "3.11"
python-version = "3.12"
no-strip-extras=true
generate-hashes=true
[tool.ty.environment]
root = ["src/backend/InvenTree"]
extra-paths = ["src/backend/InvenTree"]
[tool.ty.rules]
unresolved-reference="ignore" # 21 # see https://github.com/astral-sh/ty/issues/220
unresolved-attribute="ignore" # 505 # need Plugin Mixin typing
call-non-callable="ignore" # 8 ##
invalid-assignment="ignore" # 17 # need to wait for better django field stubs
# invalid-method-override="ignore" # 99
invalid-method-override="ignore" # 104
invalid-return-type="ignore" # 22 ##
# possibly-missing-attribute="ignore" # 25 # https://github.com/astral-sh/ty/issues/164
unknown-argument="ignore" # 3 # need to wait for better django field stubs
invalid-argument-type="ignore" # 49
no-matching-overload="ignore" # 3 # need to wait for betterdjango field stubs
possibly-unbound-attribute="ignore" # 21
# possibly-unbound-attribute="ignore" # 21
[tool.coverage.run]
source = ["src/backend/InvenTree", "InvenTree"]

View File

@ -9,9 +9,9 @@ python:
- requirements: src/backend/requirements.txt
build:
os: "ubuntu-22.04"
os: "ubuntu-24.04"
tools:
python: "3.11"
python: "3.12"
jobs:
post_install:
- pip install -U invoke

View File

@ -494,7 +494,7 @@ class BulkCreateMixin:
if unique_create_fields := getattr(self, 'unique_create_fields', None):
existing = collections.defaultdict(list)
for idx, item in enumerate(data):
key = tuple(item[v] for v in list(unique_create_fields)) # type: ignore[not-subscriptable]
key = tuple(item[v] for v in list(unique_create_fields)) # ty: ignore[not-subscriptable]
existing[key].append(idx)
unique_errors = [[] for _ in range(len(data))]

View File

@ -19,10 +19,10 @@ logger = structlog.get_logger('inventree')
def log_error(
path,
error_name=None,
error_info=None,
error_data=None,
path: Optional[str] = None,
error_name: Optional[str] = None,
error_info: Optional[str] = None,
error_data: Optional[str] = None,
scope: Optional[str] = None,
plugin: Optional[str] = None,
):

View File

@ -23,6 +23,7 @@ from django_q.models import Task
from error_report.models import Error
from mptt.exceptions import InvalidMove
from mptt.models import MPTTModel, TreeForeignKey
from rest_framework.exceptions import PermissionDenied
from stdimage.models import StdImageField
from taggit.managers import TaggableManager
@ -1334,8 +1335,16 @@ class InvenTreeBarcodeMixin(models.Model):
return generate_barcode(self)
def format_matched_response(self):
def format_matched_response(self, user, **kwargs):
"""Format a standard response for a matched barcode."""
# Check permission for this object
from users.permissions import check_user_permission
if not check_user_permission(user, self, 'view'):
raise PermissionDenied(
_('User does not have permission to view this model')
)
data = {'pk': self.pk}
if hasattr(self, 'get_api_url'):

View File

@ -282,7 +282,7 @@ def postprocess_print_stats(result, generator, request, public):
scopes = {}
for path, details in rlt_dict.items():
if details['oauth']:
for scope in details['oauth']:
for scope in list(details['oauth']):
if scope not in scopes:
scopes[scope] = []
scopes[scope].append(path)
@ -343,7 +343,7 @@ def schema_for_view_output_options(view_class):
return extended_view
def exclude_from_schema(klass: type, alternative_path: str) -> type:
def exclude_from_schema(klass: type[Any], alternative_path: str) -> type[Any]:
"""Decorator to exclude a view from the OpenAPI schema.
This is used to hide legacy endpoints from the schema, while still retaining them for backwards compatibility.

View File

@ -9,8 +9,8 @@ def get_ldap_config(debug: bool = False) -> dict:
The returned settings will be updated into the globals() object,
and will be used to configure the LDAP authentication backend.
"""
import django_auth_ldap.config # type: ignore[unresolved-import]
import ldap # type: ignore[unresolved-import]
import django_auth_ldap.config # ty: ignore[unresolved-import]
import ldap # ty: ignore[unresolved-import]
# get global options from dict and use ldap.OPT_* as keys and values
global_options_dict = get_setting(

View File

@ -15,10 +15,10 @@ from datetime import timedelta as td
from .api_version import INVENTREE_API_TEXT, INVENTREE_API_VERSION
# InvenTree software version
INVENTREE_SW_VERSION = '1.4.0 dev'
INVENTREE_SW_VERSION = '1.5.0 dev'
# Minimum supported Python version
MIN_PYTHON_VERSION = (3, 11)
MIN_PYTHON_VERSION = (3, 12)
logger = logging.getLogger('inventree')

View File

@ -3,7 +3,7 @@
from __future__ import annotations
from django.contrib.auth.models import User
from django.db.models import F, OuterRef, Q, Subquery, Sum
from django.db.models import DecimalField, F, OuterRef, Q, Subquery, Sum
from django.db.models.functions import Coalesce
from django.urls import include, path
from django.utils.translation import gettext_lazy as _
@ -494,9 +494,25 @@ class BuildLineFilter(FilterSet):
def filter_allocated(self, queryset, name, value):
"""Filter by whether each BuildLine is fully allocated."""
allocated_subquery = (
BuildItem.objects
.filter(build_line=OuterRef('pk'))
.values('build_line')
.annotate(total=Sum('quantity'))
.values('total')
)
queryset = queryset.alias(
allocated_quantity=Coalesce(
Subquery(allocated_subquery), 0, output_field=DecimalField()
)
)
if str2bool(value):
return queryset.filter(allocated__gte=F('quantity') - F('consumed'))
return queryset.filter(allocated__lt=F('quantity') - F('consumed'))
return queryset.filter(
allocated_quantity__gte=F('quantity') - F('consumed')
)
return queryset.filter(allocated_quantity__lt=F('quantity') - F('consumed'))
consumed = rest_filters.BooleanFilter(label=_('Consumed'), method='filter_consumed')
@ -528,7 +544,9 @@ class BuildLineFilter(FilterSet):
)
queryset = queryset.alias(
allocated_quantity=Coalesce(Subquery(allocated_subquery), 0)
allocated_quantity=Coalesce(
Subquery(allocated_subquery), 0, output_field=DecimalField()
)
)
# A query filter construct to determine the total quantity available for this BuildLine,

View File

@ -577,7 +577,7 @@ class CustomUnitViewset(DataExportViewMixin, viewsets.ModelViewSet):
return {
'name': k,
'is_alias': reg.get_name(k) == k,
'compatible_units': [str(a) for a in unit.compatible_units()],
'compatible_units': [str(a) for a in unit.compatible_units()], # ty:ignore[missing-argument]
'isdimensionless': unit.dimensionless,
}

View File

@ -1,19 +1,7 @@
"""Types for settings."""
import sys
from collections.abc import Callable
from typing import Any, TypedDict
if sys.version_info >= (3, 11):
from typing import NotRequired # pragma: no cover
else:
class NotRequired: # pragma: no cover
"""NotRequired type helper is only supported with Python 3.11+."""
def __class_getitem__(cls, item):
"""Return the item."""
return item
from typing import Any, NotRequired, TypedDict
class SettingsKeyType(TypedDict, total=False):

View File

@ -15,7 +15,7 @@ TESTING = 'test' in sys.argv
def clear():
if not TESTING: # pragma: no cover
os.system('cls' if os.name == 'nt' else 'clear')
os.system('cls' if os.name == 'nt' else 'clear') # ty:ignore[deprecated]
def reverse_association(apps, schema_editor): # pragma: no cover

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -272,7 +272,7 @@ class ReturnOrderReportContext(report.mixins.BaseReportContext, TypedDict):
customer: Optional[Company]
class TransferOrderReportContext(report.mixins.BaseReportContext, TypedDict):
class TransferOrderReportContext(BaseOrderReportContext, TypedDict):
"""Context for the transfer order model.
Attributes:
@ -639,7 +639,8 @@ class PurchaseOrder(TotalPriceMixin, Order):
def report_context(self) -> PurchaseOrderReportContext:
"""Return report context data for this PurchaseOrder."""
return_ctx = super().report_context()
return_ctx.update({'supplier': self.supplier})
return_ctx.update({'supplier': self.supplier}) # ty:ignore[invalid-key]
return return_ctx
def get_absolute_url(self) -> str:
@ -1372,7 +1373,8 @@ class SalesOrder(TotalPriceMixin, Order):
def report_context(self) -> SalesOrderReportContext:
"""Generate report context data for this SalesOrder."""
return_ctx = super().report_context()
return_ctx.update({'customer': self.customer})
return_ctx.update({'customer': self.customer}) # ty:ignore[invalid-key]
return return_ctx
def get_absolute_url(self) -> str:
@ -2931,7 +2933,8 @@ class ReturnOrder(TotalPriceMixin, Order):
def report_context(self) -> ReturnOrderReportContext:
"""Generate report context data for this ReturnOrder."""
return_ctx = super().report_context()
return_ctx.update({'customer': self.customer})
return_ctx.update({'customer': self.customer}) # ty:ignore[invalid-key]
return return_ctx
def get_absolute_url(self):

View File

@ -153,7 +153,9 @@ class BarcodeView(CreateAPIView):
for current_plugin in plugins:
try:
result = current_plugin.scan(barcode)
result = current_plugin.scan(barcode, user=request.user, **kwargs)
except PermissionDenied as exc:
raise exc
except Exception:
log_error('BarcodeView.scan_barcode', plugin=current_plugin.slug)
continue
@ -282,7 +284,7 @@ class BarcodeAssign(BarcodeView):
# First check if the provided barcode matches an existing database entry
if inventree_barcode_plugin:
result = inventree_barcode_plugin.scan(barcode)
result = inventree_barcode_plugin.scan(barcode, user=request.user, **kwargs)
if result is not None:
result['error'] = _('Barcode matches existing item')
@ -459,7 +461,9 @@ class BarcodePOAllocate(BarcodeView):
manufacturer_part=response.get('manufacturerpart', None),
)
response['success'] = _('Matched supplier part')
response['supplierpart'] = supplier_part.format_matched_response()
response['supplierpart'] = supplier_part.format_matched_response(
user=request.user
)
except ValidationError as e:
response['error'] = str(e)
@ -524,7 +528,7 @@ class BarcodePOReceive(BarcodeView):
filter(lambda plugin: plugin.name == 'InvenTreeBarcode', plugins)
)
if result := internal_barcode_plugin.scan(barcode):
if result := internal_barcode_plugin.scan(barcode, user=request.user, **kwargs):
if 'stockitem' in result:
response['error'] = _('Item has already been received')
self.log_scan(request, response, False)

View File

@ -42,7 +42,7 @@ class BarcodeMixin:
"""Does this plugin have everything needed to process a barcode."""
return True
def scan(self, barcode_data):
def scan(self, barcode_data: str, user, **kwargs) -> dict | None:
"""Scan a barcode against this plugin.
This method is explicitly called from the /scan/ API endpoint,
@ -261,7 +261,7 @@ class SupplierBarcodeMixin(BarcodeMixin):
'extract_barcode_fields must be implemented by each plugin'
)
def scan(self, barcode_data: str) -> dict | None:
def scan(self, barcode_data: str, user, **kwargs) -> dict | None:
"""Perform a generic 'scan' operation on a supplier barcode.
The supplier barcode may provide sufficient information to match against
@ -297,7 +297,7 @@ class SupplierBarcodeMixin(BarcodeMixin):
for k, v in matches.items():
if v and hasattr(v, 'pk'):
has_match = True
data[k] = v.format_matched_response()
data[k] = v.format_matched_response(user=user)
if not has_match:
return None

View File

@ -15,6 +15,7 @@ class BarcodeAPITest(InvenTreeAPITestCase):
"""Tests for barcode api."""
fixtures = ['category', 'part', 'location', 'stock']
roles = ['stock.view', 'stock_location.view', 'part.view']
def setUp(self):
"""Setup for all tests."""
@ -259,6 +260,7 @@ class SOAllocateTest(InvenTreeAPITestCase):
"""Unit tests for the barcode endpoint for allocating items to a sales order."""
fixtures = ['category', 'company', 'part', 'location', 'stock']
roles = ['stock.view']
@classmethod
def setUpTestData(cls):
@ -343,10 +345,14 @@ class SOAllocateTest(InvenTreeAPITestCase):
# Test with barcode which points to a *part* instance
item.part.assign_barcode(barcode_data='abcde')
# missing permission for viewing the part - error
self.postBarcode('abcde', sales_order=self.sales_order.pk, expected_code=403)
# Add part.view role and test again
self.assignRole('part.view')
result = self.postBarcode(
'abcde', sales_order=self.sales_order.pk, expected_code=400
)
self.assertIn('does not match an existing stock item', str(result['error']))
def test_submit(self):

View File

@ -48,11 +48,11 @@ class InvenTreeInternalBarcodePlugin(SettingsMixin, BarcodeMixin, InvenTreePlugi
},
}
def format_matched_response(self, label, model, instance):
def format_matched_response(self, label, model, instance, user, **kwargs):
"""Format a response for the scanned data."""
return {label: instance.format_matched_response()}
return {label: instance.format_matched_response(user=user, **kwargs)}
def scan(self, barcode_data):
def scan(self, barcode_data, user, **kwargs):
"""Scan a barcode against this plugin.
Here we are looking for a dict object which contains a reference to a particular InvenTree database object
@ -79,7 +79,7 @@ class InvenTreeInternalBarcodePlugin(SettingsMixin, BarcodeMixin, InvenTreePlugi
try:
instance = model.objects.get(pk=int(pk))
return self.format_matched_response(label, model, instance)
return self.format_matched_response(label, model, instance, user=user)
except (ValueError, model.DoesNotExist):
pass
@ -111,7 +111,9 @@ class InvenTreeInternalBarcodePlugin(SettingsMixin, BarcodeMixin, InvenTreePlugi
instance = model.objects.get(pk=pk)
return {
**self.format_matched_response(label, model, instance),
**self.format_matched_response(
label, model, instance, user=user
),
'success': succcess_message,
}
except (ValueError, model.DoesNotExist):
@ -129,7 +131,7 @@ class InvenTreeInternalBarcodePlugin(SettingsMixin, BarcodeMixin, InvenTreePlugi
if instance is not None:
return {
**self.format_matched_response(label, model, instance),
**self.format_matched_response(label, model, instance, user=user),
'success': succcess_message,
}

View File

@ -11,6 +11,7 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
"""Tests for the integrated InvenTreeBarcode barcode plugin."""
fixtures = ['category', 'part', 'location', 'stock', 'company', 'supplier_part']
roles = ['stock.view', 'stock_location.view', 'part.view']
def setUp(self):
"""Set up the test case."""

View File

@ -14,6 +14,13 @@ class SupplierBarcodeTests(InvenTreeAPITestCase):
"""Tests barcode parsing for all suppliers."""
SCAN_URL = reverse('api-barcode-scan')
roles = [
'stock.view',
'stock_location.view',
'part.view',
'company.view',
'order.view',
]
@classmethod
def setUpTestData(cls):
@ -176,6 +183,8 @@ class SupplierBarcodeTests(InvenTreeAPITestCase):
class SupplierBarcodePOReceiveTests(InvenTreeAPITestCase):
"""Tests barcode scanning to receive a purchase order item."""
roles = ['stock.view', 'stock_location.view']
def setUp(self):
"""Create supplier part and purchase_order."""
super().setUp()

View File

@ -108,9 +108,6 @@ def handle_error(error, do_raise: bool = True, do_log: bool = True, log_name: st
def get_entrypoints():
"""Returns list for entrypoints for InvenTree plugins."""
# on python before 3.12, we need to use importlib_metadata
if sys.version_info < (3, 12):
return entry_points().get('inventree_plugins', [])
return entry_points(group='inventree_plugins')
@ -190,13 +187,11 @@ def get_modules(pkg, path=None):
continue
try:
if sys.version_info < (3, 12):
module = finder.find_module(name).load_module(name)
else:
spec = finder.find_spec(name)
module = module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
spec = finder.find_spec(name, path)
module = module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
pkg_names = getattr(module, '__all__', None)
for k, v in vars(module).items():
if not k.startswith('_') and (pkg_names is None or k in pkg_names):

View File

@ -117,8 +117,7 @@ def plugins_file_hash():
try:
with pf.open('rb') as f:
# Note: Once we support 3.11 as a minimum, we can use hashlib.file_digest
return hashlib.sha256(f.read()).hexdigest()
return hashlib.file_digest(f, 'sha256').hexdigest()
except Exception:
log_error('plugins_file_hash', scope='plugins')
return None

View File

@ -7,6 +7,7 @@ import warnings
from datetime import datetime
from importlib.metadata import PackageNotFoundError, metadata
from pathlib import Path
from sysconfig import get_path
from typing import Optional
from django.conf import settings
@ -517,7 +518,6 @@ class InvenTreePlugin(VersionMixin, MixinBase, MetaBase):
return InvenTree.helpers.pui_url(f'/settings/admin/plugin/{config.pk}/')
return InvenTree.helpers.pui_url('/settings/admin/plugin/')
# region package info
@mark_final
def _get_package_commit(self):
"""Get last git commit for the plugin."""
@ -527,10 +527,9 @@ class InvenTreePlugin(VersionMixin, MixinBase, MetaBase):
@mark_final
def is_editable(cls):
"""Returns if the current part is editable."""
from distutils.sysconfig import get_python_lib
pkg_name = cls.__name__.split('.')[0]
dist_info = list(Path(get_python_lib()).glob(f'{pkg_name}-*.dist-info'))
py_lib = get_path('platlib')
dist_info = list(Path(py_lib).glob(f'{pkg_name}-*.dist-info'))
return bool(len(dist_info) == 1)
@classmethod

View File

@ -585,15 +585,9 @@ class PluginsRegistry:
# Gather Modules
if parent_path:
# On python 3.12 use new loader method
if sys.version_info < (3, 12):
raw_module = _load_source(
plugin_dir, str(parent_obj.joinpath('__init__.py'))
)
else:
raw_module = SourceFileLoader(
plugin_dir, str(parent_obj.joinpath('__init__.py'))
).load_module()
raw_module = SourceFileLoader(
plugin_dir, str(parent_obj.joinpath('__init__.py'))
).load_module()
else:
raw_module = importlib.import_module(plugin_dir)

View File

@ -66,7 +66,7 @@ class SampleSupplierPlugin(SupplierMixin, InvenTreePlugin):
name=p['name'],
description=p['description'],
exact=p['sku'] == term,
price=f'{p["price"][1][0]:.2f}',
price=f'{p["price"][1][0]:.2f}', # ty:ignore[not-subscriptable]
link=p['link'],
image_url=p['image_url'],
existing_part=getattr(

View File

@ -73,7 +73,9 @@ class ReportConfig(AppConfig):
def cleanup(self):
"""Cleanup old label and report outputs."""
try:
from report.tasks import cleanup_old_report_outputs # type: ignore[import]
from report.tasks import (
cleanup_old_report_outputs, # type: ignore[import] # ty: ignore[unresolved-import]
)
cleanup_old_report_outputs()
except Exception:

View File

@ -1,6 +1,7 @@
"""Template tags for rendering various barcodes."""
from django import template
from django.core.exceptions import ValidationError
from django.utils.safestring import mark_safe
import barcode as python_barcode
@ -70,7 +71,7 @@ def qrcode(data: str, **kwargs) -> str:
data = str(data).strip()
if not data:
raise ValueError("No data provided to 'qrcode' template tag")
raise ValidationError("qrcode: No data provided to 'qrcode' template tag")
# Extract other arguments from kwargs
fill_color = kwargs.pop('fill_color', 'black')
@ -115,7 +116,7 @@ def barcode(data: str, barcode_class='code128', **kwargs) -> str:
data = str(data).strip()
if not data:
raise ValueError("No data provided to 'barcode' template tag")
raise ValidationError("barcode: No data provided to 'barcode' template tag")
constructor = python_barcode.get_barcode_class(barcode_class)
@ -134,17 +135,26 @@ def barcode(data: str, barcode_class='code128', **kwargs) -> str:
@register.simple_tag()
def datamatrix(data: str, **kwargs) -> str:
def datamatrix(
data: str,
rectangular: bool = False,
fill_color: str = 'black',
back_color: str = 'white',
scale: float = 1.0,
border: int = 1,
fmt: str = 'PNG',
**kwargs,
) -> str:
"""Render a DataMatrix barcode.
Arguments:
data: Data to encode
Keyword Arguments:
fill_color (str): Foreground color (default = 'black')
back_color (str): Background color (default = 'white')
scale (float): Matrix scaling factor (default = 1)
border (int): Border width (default = 1)
rectangular: Whether to generate a rectangular DataMatrix (default = False)
fill_color: Foreground color (default = 'black')
back_color: Background color (default = 'white')
scale: Scaling factor (default = 1)
border: Border width (default = 1)
fmt: Generated image format (default = 'PNG')
Returns:
image (str): base64 encoded image data
@ -154,14 +164,11 @@ def datamatrix(data: str, **kwargs) -> str:
data = str(data).strip()
if not data:
raise ValueError("No data provided to 'datamatrix' template tag")
raise ValidationError(
"datamatrix: No data provided to 'datamatrix' template tag"
)
dm = DataMatrix(data)
fill_color = kwargs.pop('fill_color', 'black')
back_color = kwargs.pop('back_color', 'white')
border = kwargs.pop('border', 1)
dm = DataMatrix(data, rect=rectangular)
try:
border = int(border)
@ -180,8 +187,6 @@ def datamatrix(data: str, **kwargs) -> str:
except Exception:
bg = ImageColor.getcolor('white', 'RGB')
scale = kwargs.pop('scale', 1)
height = len(dm.matrix) + 2 * border
width = len(dm.matrix[0]) + 2 * border
@ -193,7 +198,8 @@ def datamatrix(data: str, **kwargs) -> str:
if value:
img.putpixel((x + border, y + border), fg)
if scale != 1:
img = img.resize((int(width * scale), int(height * scale)))
img = img.resize(
(int(width * scale), int(height * scale)), Image.Resampling.NEAREST
)
return image_data(img, fmt='PNG')
return image_data(img, fmt=fmt)

View File

@ -1021,7 +1021,7 @@ def format_number(
number = float(number)
if multiplier is not None:
number *= multiplier
number *= float(multiplier)
if integer:
number = int(number)

View File

@ -440,7 +440,6 @@ class ReportTagTest(PartImageTestMixin, InvenTreeTestCase):
]
for tz, fmt, locale, expected in tests:
print(tz, fmt, locale, expected)
result = report_tags.format_datetime(
time, timezone=tz, fmt=fmt, locale=locale
)
@ -857,7 +856,7 @@ class BarcodeTagTest(TestCase):
self.assertTrue(barcode.startswith('data:image/bmp;'))
# Test empty tag
with self.assertRaises(ValueError):
with self.assertRaises(ValidationError):
barcode_tags.barcode('')
def test_qrcode(self):
@ -877,7 +876,7 @@ class BarcodeTagTest(TestCase):
self.assertEqual(len(qrcode), 309720)
# Test empty tag
with self.assertRaises(ValueError):
with self.assertRaises(ValidationError):
barcode_tags.qrcode('')
def test_clean_barcode(self):
@ -908,7 +907,7 @@ class BarcodeTagTest(TestCase):
)
# Test empty tag
with self.assertRaises(ValueError):
with self.assertRaises(ValidationError):
barcode_tags.datamatrix('')
# Failure cases with wrong args

View File

@ -19,7 +19,7 @@ if __name__ == '__main__':
os.mkdir(STATIC_FOLDER)
print('Downloading tabler icons...')
os.system(f'npm install --prefix {TMP_FOLDER} @tabler/icons @tabler/icons-webfont')
os.system(f'npm install --prefix {TMP_FOLDER} @tabler/icons @tabler/icons-webfont') # ty:ignore[deprecated]
print(f'Copying tabler icons to {STATIC_FOLDER}...')

View File

@ -18,6 +18,7 @@ from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.serializers import ValidationError
import common.filters
import common.models
import common.settings
import InvenTree.helpers

View File

@ -47,9 +47,7 @@ User.add_to_class('__str__', user_model_str) # Overriding User.__str__
if settings.LDAP_AUTH:
from django_auth_ldap.backend import ( # type: ignore[unresolved-import]
populate_user,
)
from django_auth_ldap.backend import populate_user # ty: ignore[unresolved-import]
@receiver(populate_user)
def create_email_address(user, **kwargs):

View File

@ -1,21 +1,25 @@
# This file was autogenerated by uv via the following command:
# uv pip compile src/backend/requirements-dev.in -o src/backend/requirements-dev-3.14.txt -c src/backend/requirements-3.14.txt --python-version=3.14 -c src/backend/requirements.txt
# uv pip compile src/backend/requirements-dev.in -o src/backend/requirements-dev-3.14.txt -c src/backend/requirements-3.14.txt --python-version=3.14 -c src/backend/requirements.txt -c src/backend/requirements-dev.txt
asgiref==3.11.1 \
--hash=sha256:5f184dc43b7e763efe848065441eac62229c9f7b0475f41f80e207a114eda4ce \
--hash=sha256:e8667a091e69529631969fd45dc268fa79b99c92c5fcdda727757e52146ec133
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# django
build==1.5.0 \
--hash=sha256:13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f \
--hash=sha256:302c22c3ba2a0fd5f3911918651341ebb3896176cbdec15bd421f80b1afc7647
# via pip-tools
# via
# -c src/backend/requirements-dev.txt
# pip-tools
certifi==2026.6.17 \
--hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \
--hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# requests
cffi==2.0.0 \
@ -105,6 +109,7 @@ cffi==2.0.0 \
--hash=sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# cryptography
charset-normalizer==3.4.7 \
@ -239,13 +244,16 @@ charset-normalizer==3.4.7 \
--hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# pdfminer-six
# requests
click==8.4.1 \
--hash=sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2 \
--hash=sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96
# via pip-tools
# via
# -c src/backend/requirements-dev.txt
# pip-tools
coverage[toml]==7.14.1 \
--hash=sha256:0177614a0370f227888b4e436a7c55686d6a9f90eb1ade2b624ba685a1686e86 \
--hash=sha256:01b7733daad0237daa01ef80fe2dfceffc911e6a17fa7b55d14aa8214eaaaecd \
@ -353,7 +361,9 @@ coverage[toml]==7.14.1 \
--hash=sha256:fad54e871165f6ec2f536063ac74c3104508a12963e64072ba44bd822de52b0c \
--hash=sha256:fc459e5d73be2d6332fcfe8dbf3d8994671fe33c700f4565988ecfa511547253 \
--hash=sha256:fd86572566fb40189a8260446158235159bc7a82dfbc87a3b39cf4fb57fcec1c
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
cryptography==48.0.1 \
--hash=sha256:08a597acce1ff37f347400087776599e2348a3a8bc53b44120e463cd274efe4a \
--hash=sha256:09f73a725d582cef64b91281a322cd798d14a33b2b6f2b7ad9531dc336d84c02 \
@ -406,6 +416,7 @@ cryptography==48.0.1 \
--hash=sha256:fe0180af5bf9236518a087e35bf2d9a347d5f5f51e63c579d683ddff424e3d46
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# pdfminer-six
django==5.2.15 \
@ -413,6 +424,7 @@ django==5.2.15 \
--hash=sha256:5154a9bf84ac01dde011e367f355c07dbb329532e06810dcf3ef2af269e236e7
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# django-silk
# django-slowtests
@ -420,62 +432,88 @@ django==5.2.15 \
# django-stubs-ext
django-querycount==0.8.3 \
--hash=sha256:0782484e8a1bd29498fa0195a67106e47cdcc98fafe80cebb1991964077cb694
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
django-silk==5.5.0 \
--hash=sha256:41fcabe65d59d31ccdb69daeb3c3e6d30879ab2c00b0875b111fda0f69aec065 \
--hash=sha256:82b5a690d623935be916dd145e2f605a4ac9454d54e03df6a7ffcf38333c8444
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
django-slowtests==1.1.1 \
--hash=sha256:3c6936d420c9df444ac03625b41d97de043c662bbde61fbcd33e4cd407d0c247
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
django-stubs==6.0.5 \
--hash=sha256:7742b8e60afc68a8545158e2bdb103376d5a092f7902c17f370920a9c08eb957 \
--hash=sha256:9fb9eede9b2fc47b36c3dc4a93652eb959dff45466ec4a580e4a22782192d746
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
django-stubs-ext==6.0.5 \
--hash=sha256:1cc325e991303849bce70e19748981b225ef08b37256f263e113caf97cd3bcc0 \
--hash=sha256:a9932c8233d6dd4e34ae0b192026379c1a9be8f0b7c27aa1fa09ae215169773e
# via django-stubs
# via
# -c src/backend/requirements-dev.txt
# django-stubs
django-test-migrations==1.5.0 \
--hash=sha256:1cbff04b1e82c5564a6f635284907b381cc11a2ff883adff46776d9126824f07 \
--hash=sha256:96a08f085fc8bfaa53d44618341d82a2d22fd194c821cd81b147b66f0bec0da8
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
django-types==0.24.0 \
--hash=sha256:af903de8b9ee963b7594459a7a20cb8eaaab176ae2b3244ecaa089e0c570b0d1 \
--hash=sha256:ddb478ca733e0dde5475118dd59ab340156980f9659fd92de2083326ae96100a
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
gprof2dot==2025.4.14 \
--hash=sha256:0742e4c0b4409a5e8777e739388a11e1ed3750be86895655312ea7c20bd0090e \
--hash=sha256:35743e2d2ca027bf48fa7cba37021aaf4a27beeae1ae8e05a50b55f1f921a6ce
# via django-silk
# via
# -c src/backend/requirements-dev.txt
# django-silk
idna==3.18 \
--hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \
--hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# requests
iniconfig==2.3.0 \
--hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \
--hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12
# via pytest
# via
# -c src/backend/requirements-dev.txt
# pytest
isort==8.0.1 \
--hash=sha256:171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d \
--hash=sha256:28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
markdown-it-py==4.2.0 \
--hash=sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49 \
--hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a
# via rich
# via
# -c src/backend/requirements-dev.txt
# rich
mdurl==0.1.2 \
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
# via markdown-it-py
# via
# -c src/backend/requirements-dev.txt
# markdown-it-py
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# build
# pytest
@ -483,19 +521,27 @@ packaging==26.2 \
pdfminer-six==20260107 \
--hash=sha256:366585ba97e80dffa8f00cebe303d2f381884d8637af4ce422f1df3ef38111a9 \
--hash=sha256:96bfd431e3577a55a0efd25676968ca4ce8fd5b53f14565f85716ff363889602
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
pip==26.1.2 \
--hash=sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab \
--hash=sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605
# via pip-tools
# via
# -c src/backend/requirements-dev.txt
# pip-tools
pip-tools==7.5.3 \
--hash=sha256:3aac0c473240ae90db7213c033401f345b05197293ccbdd2704e52e7a783785e \
--hash=sha256:8fa364779ebc010cbfe17cb9de404457ac733e100840423f28f6955de7742d41
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
pluggy==1.6.0 \
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
--hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
# via pytest
# via
# -c src/backend/requirements-dev.txt
# pytest
prek==0.4.5 \
--hash=sha256:14109d37b33e5529db41a3539d4f8f72d295f6eeddede3964994d898b8cec05c \
--hash=sha256:1fd98b986767dafdb6b4305b563ee5a3a8f13bd3c78b98d708626815ea9f147f \
@ -514,30 +560,36 @@ prek==0.4.5 \
--hash=sha256:e491a1a4641d91d8b03dcce5588397e76d2a5b432c9b0a6c70475972b4512ab4 \
--hash=sha256:f7517774c72b001573520dc7111156779fd3e5b4452c11f09ff53c71a067e835 \
--hash=sha256:fccd11613ae92619d1ecda0ab3359ceebeb38898909ec84a8d383733d12158cc
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
pycparser==3.0 \
--hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
--hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# cffi
pygments==2.20.0 \
--hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \
--hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
# via
# -c src/backend/requirements-dev.txt
# pytest
# rich
pyproject-hooks==1.2.0 \
--hash=sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8 \
--hash=sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913
# via
# -c src/backend/requirements-dev.txt
# build
# pip-tools
pytest==9.1.1 \
--hash=sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313 \
--hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c
# via
# -c src/backend/requirements-dev.txt
# pytest-codspeed
# pytest-django
pytest-codspeed==5.0.3 \
@ -570,31 +622,41 @@ pytest-codspeed==5.0.3 \
--hash=sha256:f56d0339cd98d26f6e561987be25bdd2761a5d53d8f73493b1ebe02d0d451093 \
--hash=sha256:f852bee785a7a124cb1720b1915670c6742af87747dc4d838f3ffdbd365ce9d9 \
--hash=sha256:fe2ea83c924c2250675b75686c3ee456b8cf0208d83d552e182a195fdf467378
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
pytest-django==4.12.0 \
--hash=sha256:3ff300c49f8350ba2953b90297d23bf5f589db69545f56f1ec5f8cff5da83e85 \
--hash=sha256:df94ec819a83c8979c8f6de13d9cdfbe76e8c21d39473cfe2b40c9fc9be3c758
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# requests-mock
requests-mock==1.12.1 \
--hash=sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563 \
--hash=sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401
# via -r src/backend/requirements-dev.in
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
rich==15.0.0 \
--hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \
--hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36
# via pytest-codspeed
# via
# -c src/backend/requirements-dev.txt
# pytest-codspeed
setuptools==82.0.1 \
--hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \
--hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# -r src/backend/requirements-dev.in
# pip-tools
@ -603,42 +665,50 @@ sqlparse==0.5.5 \
--hash=sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# django
# django-silk
ty==0.0.1a21 \
--hash=sha256:0efba2e52b58f536f4198ba5c4a36cac2ba67d83ec6f429ebc7704233bcda4c3 \
--hash=sha256:1474d883129bb63da3b2380fc7ead824cd3baf6a9551e6aa476ffefc58057af3 \
--hash=sha256:1f276ceab23a1410aec09508248c76ae0989c67fb7a0c287e0d4564994295531 \
--hash=sha256:218d53e7919e885bd98e9196d9cb952d82178b299aa36da6f7f39333eb7400ed \
--hash=sha256:21f708d02b6588323ffdbfdba38830dd0ecfd626db50aa6006b296b5470e52f9 \
--hash=sha256:334d2a212ebf42a0e55d57561926af7679fe1e878175e11dcb81ad8df892844e \
--hash=sha256:3c3bc66fcae41eff133cfe326dd65d82567a2fb5d4efe2128773b10ec2766819 \
--hash=sha256:5dfc73299d441cc6454e36ed0a976877415024143dfca6592dc36f7701424383 \
--hash=sha256:7505aeb8bf2a62f00f12cfa496f6c965074d75c8126268776565284c8a12d5dd \
--hash=sha256:84243455f295ed850bd53f7089819321807d4e6ee3b1cbff6086137ae0259466 \
--hash=sha256:87a200c21e02962e8a27374d9d152582331d57d709672431be58f4f898bf6cad \
--hash=sha256:9463cac96b8f1bb5ba740fe1d42cd6bd152b43c5b159b2f07f8fd629bcdded34 \
--hash=sha256:a8c769987d00fbc33054ff7e342633f475ea10dc43bc60fb9fb056159d48cb90 \
--hash=sha256:ba13d03b9e095216ceb4e4d554a308517f28ab0a6e4dcd07cfe94563e4c2c489 \
--hash=sha256:be8f457d7841b7ead2a3f6b65ba668abc172a1150a0f1f6c0958af3725dbb61a \
--hash=sha256:cc0880ec344fbdf736b05d8d0da01f0caaaa02409bd9a24b68d18d0127a79b0e \
--hash=sha256:e941e9a9d1e54b03eeaf9c3197c26a19cf76009fd5e41e16e5657c1c827bd6d3 \
--hash=sha256:ecf41706b803827b0de8717f32a434dad1e67be9f4b8caf403e12013179ea06a
# via -r src/backend/requirements-dev.in
ty==0.0.51 \
--hash=sha256:08adbe53fb8bc9e7f00e89bf1d3c875a02cda76d83f109d2e6ab1ff35a7bfa8c \
--hash=sha256:25a5b31e6f23fd5dc63ad29087ded09932409e4154e2fe07bbaed015035990bb \
--hash=sha256:2faed19a8f1505370de071c008df52a994fc03a204f3267c3a33a32ca26f854f \
--hash=sha256:429a997394dac73870d71b87cc90efc54da3efaf319e72ca18aeef35a78aef90 \
--hash=sha256:49a21237f6fd1de56beaff0a3e85fe022a09a3401e67e3abec41ce838a5d4d2e \
--hash=sha256:608d417cd1eaf79bcbd713d9830d5e3db9d57ec225c3af3e4ac9a9ff66b45d70 \
--hash=sha256:61b4b6a003c3ebe53a63a1125c9b6542aa01bc1b6c9a235d01ee328d000d61a9 \
--hash=sha256:62ced5e380284f12b2dc4802a3e4ed3dac39913fc6719afde7978814a4c7f169 \
--hash=sha256:62d94f06e8c317e89b6884f2bde443040e596b88c7c79bd944c84c105b06257a \
--hash=sha256:79d1877e93460f936bc10ed1a31525702b7ce51075763ccba993be17f0b9e905 \
--hash=sha256:947986bd82d324b3a5c58ce03f1dad160cdf36443d3e8f64b3484b861ba9bc64 \
--hash=sha256:abd92913bc90d1705ef9391ff8c6822b61e2e827fa295eb30bf0dfabcf815645 \
--hash=sha256:b90172d46365bb9d51a7011cbb5c60cc4f514f42c86635df6c092b717f85e1ac \
--hash=sha256:bc7459348a253247bbfb2669a021e614281b86bbea24c36112b8a6e1a2499a16 \
--hash=sha256:c1bd1355aee86af01e4e21b0bc16fc460fb05905761f0d8b8d70841de0feade8 \
--hash=sha256:cc233a6235fb23e2a44b14731a10043e37ba2f30f2c361cf49ad3633c5b9da9c \
--hash=sha256:dc5e93695ab5dcbf1eef663aee60ec23a413547cc9cb06adcb0d842e9166bd0f \
--hash=sha256:f8f52952cff665bc52a36147e610c10f5699d30007d7a14ab7f345cff93476ff
# via
# -c src/backend/requirements-dev.txt
# -r src/backend/requirements-dev.in
types-psycopg2==2.9.21.20260518 \
--hash=sha256:2fd728a4fa3860db0a4a9813e5f49c30ed329b3d2e60e73530d9db01b2b98420 \
--hash=sha256:8b1f80d90d6799a4fcdac12198b382a8feee9ed4340d5f69b56fc5ffa0644143
# via django-types
# via
# -c src/backend/requirements-dev.txt
# django-types
types-pyyaml==6.0.12.20260518 \
--hash=sha256:d2150f75a231c9fe9c7463bd29487d93e60bac90400287351384bc2284eba7cd \
--hash=sha256:d917f83fb38462550338c1297faedd860b3ec83912b96b1e3d73255f7473e466
# via django-stubs
# via
# -c src/backend/requirements-dev.txt
# django-stubs
typing-extensions==4.15.0 \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# django-stubs
# django-stubs-ext
@ -648,9 +718,12 @@ urllib3==2.7.0 \
--hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897
# via
# -c src/backend/requirements-3.14.txt
# -c src/backend/requirements-dev.txt
# -c src/backend/requirements.txt
# requests
wheel==0.47.0 \
--hash=sha256:212281cab4dff978f6cedd499cd893e1f620791ca6ff7107cf270781e587eced \
--hash=sha256:cc72bd1009ba0cf63922e28f94d9d83b920aa2bb28f798a31d0691b02fa3c9b3
# via pip-tools
# via
# -c src/backend/requirements-dev.txt
# pip-tools

View File

@ -594,74 +594,25 @@ sqlparse==0.5.5 \
# -c src/backend/requirements.txt
# django
# django-silk
tomli==2.4.1 \
--hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \
--hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \
--hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \
--hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \
--hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \
--hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \
--hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \
--hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \
--hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \
--hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \
--hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \
--hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \
--hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \
--hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \
--hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \
--hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \
--hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \
--hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \
--hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \
--hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \
--hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \
--hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \
--hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \
--hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \
--hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \
--hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \
--hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \
--hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \
--hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \
--hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \
--hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \
--hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \
--hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \
--hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \
--hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \
--hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \
--hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \
--hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \
--hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \
--hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \
--hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \
--hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \
--hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \
--hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \
--hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \
--hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
--hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
# via coverage
ty==0.0.1a21 \
--hash=sha256:0efba2e52b58f536f4198ba5c4a36cac2ba67d83ec6f429ebc7704233bcda4c3 \
--hash=sha256:1474d883129bb63da3b2380fc7ead824cd3baf6a9551e6aa476ffefc58057af3 \
--hash=sha256:1f276ceab23a1410aec09508248c76ae0989c67fb7a0c287e0d4564994295531 \
--hash=sha256:218d53e7919e885bd98e9196d9cb952d82178b299aa36da6f7f39333eb7400ed \
--hash=sha256:21f708d02b6588323ffdbfdba38830dd0ecfd626db50aa6006b296b5470e52f9 \
--hash=sha256:334d2a212ebf42a0e55d57561926af7679fe1e878175e11dcb81ad8df892844e \
--hash=sha256:3c3bc66fcae41eff133cfe326dd65d82567a2fb5d4efe2128773b10ec2766819 \
--hash=sha256:5dfc73299d441cc6454e36ed0a976877415024143dfca6592dc36f7701424383 \
--hash=sha256:7505aeb8bf2a62f00f12cfa496f6c965074d75c8126268776565284c8a12d5dd \
--hash=sha256:84243455f295ed850bd53f7089819321807d4e6ee3b1cbff6086137ae0259466 \
--hash=sha256:87a200c21e02962e8a27374d9d152582331d57d709672431be58f4f898bf6cad \
--hash=sha256:9463cac96b8f1bb5ba740fe1d42cd6bd152b43c5b159b2f07f8fd629bcdded34 \
--hash=sha256:a8c769987d00fbc33054ff7e342633f475ea10dc43bc60fb9fb056159d48cb90 \
--hash=sha256:ba13d03b9e095216ceb4e4d554a308517f28ab0a6e4dcd07cfe94563e4c2c489 \
--hash=sha256:be8f457d7841b7ead2a3f6b65ba668abc172a1150a0f1f6c0958af3725dbb61a \
--hash=sha256:cc0880ec344fbdf736b05d8d0da01f0caaaa02409bd9a24b68d18d0127a79b0e \
--hash=sha256:e941e9a9d1e54b03eeaf9c3197c26a19cf76009fd5e41e16e5657c1c827bd6d3 \
--hash=sha256:ecf41706b803827b0de8717f32a434dad1e67be9f4b8caf403e12013179ea06a
ty==0.0.51 \
--hash=sha256:08adbe53fb8bc9e7f00e89bf1d3c875a02cda76d83f109d2e6ab1ff35a7bfa8c \
--hash=sha256:25a5b31e6f23fd5dc63ad29087ded09932409e4154e2fe07bbaed015035990bb \
--hash=sha256:2faed19a8f1505370de071c008df52a994fc03a204f3267c3a33a32ca26f854f \
--hash=sha256:429a997394dac73870d71b87cc90efc54da3efaf319e72ca18aeef35a78aef90 \
--hash=sha256:49a21237f6fd1de56beaff0a3e85fe022a09a3401e67e3abec41ce838a5d4d2e \
--hash=sha256:608d417cd1eaf79bcbd713d9830d5e3db9d57ec225c3af3e4ac9a9ff66b45d70 \
--hash=sha256:61b4b6a003c3ebe53a63a1125c9b6542aa01bc1b6c9a235d01ee328d000d61a9 \
--hash=sha256:62ced5e380284f12b2dc4802a3e4ed3dac39913fc6719afde7978814a4c7f169 \
--hash=sha256:62d94f06e8c317e89b6884f2bde443040e596b88c7c79bd944c84c105b06257a \
--hash=sha256:79d1877e93460f936bc10ed1a31525702b7ce51075763ccba993be17f0b9e905 \
--hash=sha256:947986bd82d324b3a5c58ce03f1dad160cdf36443d3e8f64b3484b861ba9bc64 \
--hash=sha256:abd92913bc90d1705ef9391ff8c6822b61e2e827fa295eb30bf0dfabcf815645 \
--hash=sha256:b90172d46365bb9d51a7011cbb5c60cc4f514f42c86635df6c092b717f85e1ac \
--hash=sha256:bc7459348a253247bbfb2669a021e614281b86bbea24c36112b8a6e1a2499a16 \
--hash=sha256:c1bd1355aee86af01e4e21b0bc16fc460fb05905761f0d8b8d70841de0feade8 \
--hash=sha256:cc233a6235fb23e2a44b14731a10043e37ba2f30f2c361cf49ad3633c5b9da9c \
--hash=sha256:dc5e93695ab5dcbf1eef663aee60ec23a413547cc9cb06adcb0d842e9166bd0f \
--hash=sha256:f8f52952cff665bc52a36147e610c10f5699d30007d7a14ab7f345cff93476ff
# via -r src/backend/requirements-dev.in
types-psycopg2==2.9.21.20260518 \
--hash=sha256:2fd728a4fa3860db0a4a9813e5f49c30ed329b3d2e60e73530d9db01b2b98420 \

View File

@ -8,10 +8,6 @@ asgiref==3.11.1 \
# django-allauth
# django-cors-headers
# django-structlog
async-timeout==5.0.1 \
--hash=sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c \
--hash=sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3
# via redis
attrs==26.1.0 \
--hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \
--hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32
@ -1929,7 +1925,6 @@ typing-extensions==4.15.0 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via
# django-redis
# dulwich
# flexcache
# flexparser
# grpcio

View File

@ -7,7 +7,7 @@
[build.environment]
VITE_DEMO = "true"
PYTHON_VERSION = "3.11"
PYTHON_VERSION = "3.12"
# Send requests to subpath

View File

@ -306,12 +306,17 @@ function SelectPartsStep({
placeholder: t`Select supplier part`,
required: true,
autoFill: true,
autoFillFilters: {
active: true,
primary: true
},
value: record.supplier_part?.pk,
onValueChange: (value, instance) => {
onSelectSupplierPart(record.part.pk, instance);
},
filters: {
part: record.part.pk,
ordering: '-primary',
active: true,
part_detail: true,
supplier_detail: true

View File

@ -1,5 +1,4 @@
import {
type MantineColorScheme,
type MantineColorSchemeManager,
isMantineColorScheme
} from '@mantine/core';
@ -21,10 +20,18 @@ export function localStorageColorSchemeManager({
}
try {
return (
(window.localStorage.getItem(key) as MantineColorScheme) ||
defaultValue
);
const storedValue = window.localStorage.getItem(key);
// If a value exists in storage, return it
if (storedValue && isMantineColorScheme(storedValue)) {
return storedValue;
}
// If no value, check the system preference
const systemPrefersDark = window.matchMedia(
'(prefers-color-scheme: dark)'
).matches;
return systemPrefersDark ? 'dark' : 'light';
} catch {
return defaultValue;
}

View File

@ -8,7 +8,7 @@ msgstr ""
"Language: ar\n"
"Project-Id-Version: inventree\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-06-17 22:14\n"
"PO-Revision-Date: 2026-06-20 13:53\n"
"Last-Translator: \n"
"Language-Team: Arabic\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
@ -147,7 +147,7 @@ msgstr ""
#: src/forms/StockForms.tsx:1248
#: src/forms/TransferOrderForms.tsx:234
#: src/pages/build/BuildDetail.tsx:260
#: src/pages/part/PartDetail.tsx:1165
#: src/pages/part/PartDetail.tsx:1166
#: src/pages/part/bom/BomCompare.tsx:203
#: src/tables/ColumnRenderers.tsx:93
#: src/tables/build/BuildOrderParametricTable.tsx:29
@ -166,7 +166,7 @@ msgstr ""
#: src/pages/part/CategoryDetail.tsx:138
#: src/pages/part/CategoryDetail.tsx:285
#: src/pages/part/CategoryDetail.tsx:345
#: src/pages/part/CategoryDetail.tsx:387
#: src/pages/part/CategoryDetail.tsx:388
#: src/pages/part/PartDetail.tsx:893
msgid "Parts"
msgstr ""
@ -242,7 +242,7 @@ msgid "Manufacturer Parts"
msgstr ""
#: lib/enums/ModelInformation.tsx:80
#: src/pages/part/CategoryDetail.tsx:387
#: src/pages/part/CategoryDetail.tsx:388
#: src/tables/Filter.tsx:496
msgid "Part Category"
msgstr ""
@ -261,7 +261,7 @@ msgstr ""
#: src/forms/BuildForms.tsx:848
#: src/forms/SalesOrderForms.tsx:438
#: src/forms/TransferOrderForms.tsx:236
#: src/pages/stock/StockDetail.tsx:1075
#: src/pages/stock/StockDetail.tsx:1076
#: src/tables/ColumnRenderers.tsx:132
#: src/tables/part/PartTestResultTable.tsx:256
#: src/tables/stock/InstalledItemsTable.tsx:66
@ -283,7 +283,7 @@ msgstr ""
#: lib/enums/ModelInformation.tsx:99
#: lib/enums/Roles.tsx:51
#: src/pages/stock/LocationDetail.tsx:522
#: src/pages/stock/LocationDetail.tsx:523
msgid "Stock Location"
msgstr ""
@ -644,14 +644,14 @@ msgstr ""
#: src/components/importer/ImporterColumnSelector.tsx:330
#: src/components/importer/ImporterDrawer.tsx:91
#: src/components/modals/LicenseModal.tsx:85
#: src/components/nav/NavigationTree.tsx:211
#: src/components/nav/NavigationTree.tsx:398
#: src/components/nav/NotificationDrawer.tsx:235
#: src/components/nav/SearchDrawer.tsx:588
#: src/components/settings/SettingList.tsx:145
#: src/components/wizards/ImportPartWizard.tsx:574
#: src/components/wizards/ImportPartWizard.tsx:719
#: src/forms/BomForms.tsx:83
#: src/functions/auth.tsx:691
#: src/functions/auth.tsx:693
#: src/pages/ErrorPage.tsx:11
#: src/pages/Index/Settings/AccountSettings/MFASettings.tsx:317
#: src/pages/Index/Settings/AccountSettings/MFASettings.tsx:408
@ -723,6 +723,7 @@ msgstr ""
#: lib/hooks/MonitorDataOutput.tsx:57
#: lib/hooks/MonitorDataOutput.tsx:116
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:76
msgid "Process failed"
msgstr ""
@ -1391,11 +1392,11 @@ msgstr ""
msgid "This widget requires superuser permissions"
msgstr ""
#: src/components/dashboard/widgets/NewsWidget.tsx:133
#: src/components/dashboard/widgets/NewsWidget.tsx:135
msgid "No News"
msgstr ""
#: src/components/dashboard/widgets/NewsWidget.tsx:134
#: src/components/dashboard/widgets/NewsWidget.tsx:136
msgid "There are no unread news items"
msgstr ""
@ -1655,7 +1656,7 @@ msgstr ""
msgid "Error rendering preview"
msgstr ""
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:120
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:124
msgid "Preview not available, click \"Reload Preview\"."
msgstr ""
@ -1728,11 +1729,11 @@ msgstr ""
#~ msgid "to preview"
#~ msgstr "to preview"
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:379
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:380
msgid "Select instance to preview"
msgstr ""
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:423
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:424
msgid "Error rendering template"
msgstr ""
@ -1829,20 +1830,20 @@ msgstr ""
#: src/components/forms/AuthenticationForm.tsx:81
#: src/components/forms/AuthenticationForm.tsx:89
#: src/functions/auth.tsx:133
#: src/functions/auth.tsx:142
#: src/functions/auth.tsx:144
msgid "Login failed"
msgstr ""
#: src/components/forms/AuthenticationForm.tsx:82
#: src/components/forms/AuthenticationForm.tsx:90
#: src/components/forms/AuthenticationForm.tsx:106
#: src/functions/auth.tsx:134
#: src/functions/auth.tsx:354
#: src/functions/auth.tsx:136
#: src/functions/auth.tsx:356
msgid "Check your input and try again."
msgstr ""
#: src/components/forms/AuthenticationForm.tsx:100
#: src/functions/auth.tsx:345
#: src/functions/auth.tsx:347
msgid "Mail delivery successful"
msgstr ""
@ -2128,6 +2129,7 @@ msgstr ""
#: src/components/forms/fields/IconField.tsx:211
#: src/components/nav/Layout.tsx:143
#: src/components/nav/NavigationTree.tsx:378
#: src/tables/part/PartThumbTable.tsx:209
msgid "Search..."
msgstr ""
@ -2153,6 +2155,7 @@ msgid "Loading"
msgstr ""
#: src/components/forms/fields/RelatedModelField.tsx:540
#: src/components/nav/NavigationTree.tsx:403
msgid "No results found"
msgstr ""
@ -2247,7 +2250,7 @@ msgstr ""
#: src/components/importer/ImporterColumnSelector.tsx:299
#: src/components/items/ErrorItem.tsx:12
#: src/functions/api.tsx:60
#: src/functions/auth.tsx:401
#: src/functions/auth.tsx:403
msgid "An error occurred"
msgstr ""
@ -2925,7 +2928,7 @@ msgstr ""
#: src/pages/Index/Settings/SystemSettings.tsx:260
#: src/pages/part/PartDetail.tsx:663
#: src/pages/stock/LocationDetail.tsx:481
#: src/pages/stock/LocationDetail.tsx:522
#: src/pages/stock/LocationDetail.tsx:523
#: src/pages/stock/StockDetail.tsx:689
#: src/pages/stock/TransferOrderDetail.tsx:536
#: src/tables/stock/StockItemTable.tsx:81
@ -2971,7 +2974,11 @@ msgstr ""
msgid "About"
msgstr ""
#: src/components/nav/NavigationTree.tsx:212
#: src/components/nav/NavigationTree.tsx:388
msgid "Clear search"
msgstr ""
#: src/components/nav/NavigationTree.tsx:399
msgid "Error loading navigation tree."
msgstr ""
@ -5539,7 +5546,7 @@ msgstr ""
#~ msgstr "You have been logged out"
#: src/functions/auth.tsx:124
#: src/functions/auth.tsx:220
#: src/functions/auth.tsx:222
msgid "Logged Out"
msgstr ""
@ -5551,97 +5558,97 @@ msgstr ""
#~ msgid "Found an existing login - using it to log you in."
#~ msgstr "Found an existing login - using it to log you in."
#: src/functions/auth.tsx:143
msgid "No response from server."
msgstr ""
#: src/functions/auth.tsx:143
#~ msgid "Found an existing login - welcome back!"
#~ msgstr "Found an existing login - welcome back!"
#: src/functions/auth.tsx:186
#: src/functions/auth.tsx:145
msgid "No response from server."
msgstr ""
#: src/functions/auth.tsx:188
msgid "MFA Login successful"
msgstr ""
#: src/functions/auth.tsx:187
#: src/functions/auth.tsx:189
msgid "MFA details were automatically provided in the browser"
msgstr ""
#: src/functions/auth.tsx:221
#: src/functions/auth.tsx:223
msgid "Successfully logged out"
msgstr ""
#: src/functions/auth.tsx:288
#: src/functions/auth.tsx:290
msgid "Language changed"
msgstr ""
#: src/functions/auth.tsx:289
#: src/functions/auth.tsx:291
msgid "Your active language has been changed to the one set in your profile"
msgstr ""
#: src/functions/auth.tsx:310
#: src/functions/auth.tsx:312
msgid "Theme changed"
msgstr ""
#: src/functions/auth.tsx:311
#: src/functions/auth.tsx:313
msgid "Your active theme has been changed to the one set in your profile"
msgstr ""
#: src/functions/auth.tsx:346
#: src/functions/auth.tsx:348
msgid "Check your inbox for a reset link. This only works if you have an account. Check in spam too."
msgstr ""
#: src/functions/auth.tsx:353
#: src/functions/auth.tsx:617
#: src/functions/auth.tsx:355
#: src/functions/auth.tsx:619
msgid "Reset failed"
msgstr ""
#: src/functions/auth.tsx:380
#: src/functions/auth.tsx:382
msgid "Already logged in"
msgstr ""
#: src/functions/auth.tsx:381
#: src/functions/auth.tsx:383
msgid "There is a conflicting session on the server for this browser. Please logout of that first."
msgstr ""
#: src/functions/auth.tsx:437
#: src/functions/auth.tsx:439
msgid "Logged In"
msgstr ""
#: src/functions/auth.tsx:438
#: src/functions/auth.tsx:440
msgid "Successfully logged in"
msgstr ""
#: src/functions/auth.tsx:572
#: src/functions/auth.tsx:574
msgid "Failed to set up MFA"
msgstr ""
#: src/functions/auth.tsx:591
#: src/functions/auth.tsx:593
msgid "MFA Setup successful"
msgstr ""
#: src/functions/auth.tsx:592
#: src/functions/auth.tsx:594
msgid "MFA via TOTP has been set up successfully; you will need to login again."
msgstr ""
#: src/functions/auth.tsx:607
#: src/functions/auth.tsx:609
msgid "Password set"
msgstr ""
#: src/functions/auth.tsx:608
#: src/functions/auth.tsx:717
#: src/functions/auth.tsx:610
#: src/functions/auth.tsx:719
msgid "The password was set successfully. You can now login with your new password"
msgstr ""
#: src/functions/auth.tsx:682
#: src/functions/auth.tsx:684
msgid "Password could not be changed"
msgstr ""
#: src/functions/auth.tsx:700
#: src/functions/auth.tsx:702
msgid "The two password fields didnt match"
msgstr ""
#: src/functions/auth.tsx:716
#: src/functions/auth.tsx:718
msgid "Password Changed"
msgstr ""
@ -8347,11 +8354,11 @@ msgstr ""
msgid "Part Actions"
msgstr ""
#: src/pages/part/PartDetail.tsx:1182
#: src/pages/part/PartDetail.tsx:1183
msgid "Part locked"
msgstr ""
#: src/pages/part/PartDetail.tsx:1182
#: src/pages/part/PartDetail.tsx:1183
msgid "Part unlocked"
msgstr ""

View File

@ -8,7 +8,7 @@ msgstr ""
"Language: bg\n"
"Project-Id-Version: inventree\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-06-17 22:14\n"
"PO-Revision-Date: 2026-06-20 13:53\n"
"Last-Translator: \n"
"Language-Team: Bulgarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@ -147,7 +147,7 @@ msgstr ""
#: src/forms/StockForms.tsx:1248
#: src/forms/TransferOrderForms.tsx:234
#: src/pages/build/BuildDetail.tsx:260
#: src/pages/part/PartDetail.tsx:1165
#: src/pages/part/PartDetail.tsx:1166
#: src/pages/part/bom/BomCompare.tsx:203
#: src/tables/ColumnRenderers.tsx:93
#: src/tables/build/BuildOrderParametricTable.tsx:29
@ -166,7 +166,7 @@ msgstr ""
#: src/pages/part/CategoryDetail.tsx:138
#: src/pages/part/CategoryDetail.tsx:285
#: src/pages/part/CategoryDetail.tsx:345
#: src/pages/part/CategoryDetail.tsx:387
#: src/pages/part/CategoryDetail.tsx:388
#: src/pages/part/PartDetail.tsx:893
msgid "Parts"
msgstr ""
@ -242,7 +242,7 @@ msgid "Manufacturer Parts"
msgstr ""
#: lib/enums/ModelInformation.tsx:80
#: src/pages/part/CategoryDetail.tsx:387
#: src/pages/part/CategoryDetail.tsx:388
#: src/tables/Filter.tsx:496
msgid "Part Category"
msgstr ""
@ -261,7 +261,7 @@ msgstr ""
#: src/forms/BuildForms.tsx:848
#: src/forms/SalesOrderForms.tsx:438
#: src/forms/TransferOrderForms.tsx:236
#: src/pages/stock/StockDetail.tsx:1075
#: src/pages/stock/StockDetail.tsx:1076
#: src/tables/ColumnRenderers.tsx:132
#: src/tables/part/PartTestResultTable.tsx:256
#: src/tables/stock/InstalledItemsTable.tsx:66
@ -283,7 +283,7 @@ msgstr ""
#: lib/enums/ModelInformation.tsx:99
#: lib/enums/Roles.tsx:51
#: src/pages/stock/LocationDetail.tsx:522
#: src/pages/stock/LocationDetail.tsx:523
msgid "Stock Location"
msgstr ""
@ -644,14 +644,14 @@ msgstr ""
#: src/components/importer/ImporterColumnSelector.tsx:330
#: src/components/importer/ImporterDrawer.tsx:91
#: src/components/modals/LicenseModal.tsx:85
#: src/components/nav/NavigationTree.tsx:211
#: src/components/nav/NavigationTree.tsx:398
#: src/components/nav/NotificationDrawer.tsx:235
#: src/components/nav/SearchDrawer.tsx:588
#: src/components/settings/SettingList.tsx:145
#: src/components/wizards/ImportPartWizard.tsx:574
#: src/components/wizards/ImportPartWizard.tsx:719
#: src/forms/BomForms.tsx:83
#: src/functions/auth.tsx:691
#: src/functions/auth.tsx:693
#: src/pages/ErrorPage.tsx:11
#: src/pages/Index/Settings/AccountSettings/MFASettings.tsx:317
#: src/pages/Index/Settings/AccountSettings/MFASettings.tsx:408
@ -723,6 +723,7 @@ msgstr ""
#: lib/hooks/MonitorDataOutput.tsx:57
#: lib/hooks/MonitorDataOutput.tsx:116
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:76
msgid "Process failed"
msgstr ""
@ -1391,11 +1392,11 @@ msgstr ""
msgid "This widget requires superuser permissions"
msgstr ""
#: src/components/dashboard/widgets/NewsWidget.tsx:133
#: src/components/dashboard/widgets/NewsWidget.tsx:135
msgid "No News"
msgstr ""
#: src/components/dashboard/widgets/NewsWidget.tsx:134
#: src/components/dashboard/widgets/NewsWidget.tsx:136
msgid "There are no unread news items"
msgstr ""
@ -1655,7 +1656,7 @@ msgstr ""
msgid "Error rendering preview"
msgstr ""
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:120
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:124
msgid "Preview not available, click \"Reload Preview\"."
msgstr ""
@ -1728,11 +1729,11 @@ msgstr ""
#~ msgid "to preview"
#~ msgstr "to preview"
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:379
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:380
msgid "Select instance to preview"
msgstr ""
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:423
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:424
msgid "Error rendering template"
msgstr ""
@ -1829,20 +1830,20 @@ msgstr ""
#: src/components/forms/AuthenticationForm.tsx:81
#: src/components/forms/AuthenticationForm.tsx:89
#: src/functions/auth.tsx:133
#: src/functions/auth.tsx:142
#: src/functions/auth.tsx:144
msgid "Login failed"
msgstr ""
#: src/components/forms/AuthenticationForm.tsx:82
#: src/components/forms/AuthenticationForm.tsx:90
#: src/components/forms/AuthenticationForm.tsx:106
#: src/functions/auth.tsx:134
#: src/functions/auth.tsx:354
#: src/functions/auth.tsx:136
#: src/functions/auth.tsx:356
msgid "Check your input and try again."
msgstr ""
#: src/components/forms/AuthenticationForm.tsx:100
#: src/functions/auth.tsx:345
#: src/functions/auth.tsx:347
msgid "Mail delivery successful"
msgstr ""
@ -2128,6 +2129,7 @@ msgstr ""
#: src/components/forms/fields/IconField.tsx:211
#: src/components/nav/Layout.tsx:143
#: src/components/nav/NavigationTree.tsx:378
#: src/tables/part/PartThumbTable.tsx:209
msgid "Search..."
msgstr ""
@ -2153,6 +2155,7 @@ msgid "Loading"
msgstr ""
#: src/components/forms/fields/RelatedModelField.tsx:540
#: src/components/nav/NavigationTree.tsx:403
msgid "No results found"
msgstr ""
@ -2247,7 +2250,7 @@ msgstr ""
#: src/components/importer/ImporterColumnSelector.tsx:299
#: src/components/items/ErrorItem.tsx:12
#: src/functions/api.tsx:60
#: src/functions/auth.tsx:401
#: src/functions/auth.tsx:403
msgid "An error occurred"
msgstr ""
@ -2925,7 +2928,7 @@ msgstr ""
#: src/pages/Index/Settings/SystemSettings.tsx:260
#: src/pages/part/PartDetail.tsx:663
#: src/pages/stock/LocationDetail.tsx:481
#: src/pages/stock/LocationDetail.tsx:522
#: src/pages/stock/LocationDetail.tsx:523
#: src/pages/stock/StockDetail.tsx:689
#: src/pages/stock/TransferOrderDetail.tsx:536
#: src/tables/stock/StockItemTable.tsx:81
@ -2971,7 +2974,11 @@ msgstr ""
msgid "About"
msgstr ""
#: src/components/nav/NavigationTree.tsx:212
#: src/components/nav/NavigationTree.tsx:388
msgid "Clear search"
msgstr ""
#: src/components/nav/NavigationTree.tsx:399
msgid "Error loading navigation tree."
msgstr ""
@ -5539,7 +5546,7 @@ msgstr ""
#~ msgstr "You have been logged out"
#: src/functions/auth.tsx:124
#: src/functions/auth.tsx:220
#: src/functions/auth.tsx:222
msgid "Logged Out"
msgstr ""
@ -5551,97 +5558,97 @@ msgstr ""
#~ msgid "Found an existing login - using it to log you in."
#~ msgstr "Found an existing login - using it to log you in."
#: src/functions/auth.tsx:143
msgid "No response from server."
msgstr ""
#: src/functions/auth.tsx:143
#~ msgid "Found an existing login - welcome back!"
#~ msgstr "Found an existing login - welcome back!"
#: src/functions/auth.tsx:186
#: src/functions/auth.tsx:145
msgid "No response from server."
msgstr ""
#: src/functions/auth.tsx:188
msgid "MFA Login successful"
msgstr ""
#: src/functions/auth.tsx:187
#: src/functions/auth.tsx:189
msgid "MFA details were automatically provided in the browser"
msgstr ""
#: src/functions/auth.tsx:221
#: src/functions/auth.tsx:223
msgid "Successfully logged out"
msgstr ""
#: src/functions/auth.tsx:288
#: src/functions/auth.tsx:290
msgid "Language changed"
msgstr ""
#: src/functions/auth.tsx:289
#: src/functions/auth.tsx:291
msgid "Your active language has been changed to the one set in your profile"
msgstr ""
#: src/functions/auth.tsx:310
#: src/functions/auth.tsx:312
msgid "Theme changed"
msgstr ""
#: src/functions/auth.tsx:311
#: src/functions/auth.tsx:313
msgid "Your active theme has been changed to the one set in your profile"
msgstr ""
#: src/functions/auth.tsx:346
#: src/functions/auth.tsx:348
msgid "Check your inbox for a reset link. This only works if you have an account. Check in spam too."
msgstr ""
#: src/functions/auth.tsx:353
#: src/functions/auth.tsx:617
#: src/functions/auth.tsx:355
#: src/functions/auth.tsx:619
msgid "Reset failed"
msgstr ""
#: src/functions/auth.tsx:380
#: src/functions/auth.tsx:382
msgid "Already logged in"
msgstr ""
#: src/functions/auth.tsx:381
#: src/functions/auth.tsx:383
msgid "There is a conflicting session on the server for this browser. Please logout of that first."
msgstr ""
#: src/functions/auth.tsx:437
#: src/functions/auth.tsx:439
msgid "Logged In"
msgstr ""
#: src/functions/auth.tsx:438
#: src/functions/auth.tsx:440
msgid "Successfully logged in"
msgstr ""
#: src/functions/auth.tsx:572
#: src/functions/auth.tsx:574
msgid "Failed to set up MFA"
msgstr ""
#: src/functions/auth.tsx:591
#: src/functions/auth.tsx:593
msgid "MFA Setup successful"
msgstr ""
#: src/functions/auth.tsx:592
#: src/functions/auth.tsx:594
msgid "MFA via TOTP has been set up successfully; you will need to login again."
msgstr ""
#: src/functions/auth.tsx:607
#: src/functions/auth.tsx:609
msgid "Password set"
msgstr ""
#: src/functions/auth.tsx:608
#: src/functions/auth.tsx:717
#: src/functions/auth.tsx:610
#: src/functions/auth.tsx:719
msgid "The password was set successfully. You can now login with your new password"
msgstr ""
#: src/functions/auth.tsx:682
#: src/functions/auth.tsx:684
msgid "Password could not be changed"
msgstr ""
#: src/functions/auth.tsx:700
#: src/functions/auth.tsx:702
msgid "The two password fields didnt match"
msgstr ""
#: src/functions/auth.tsx:716
#: src/functions/auth.tsx:718
msgid "Password Changed"
msgstr ""
@ -8347,11 +8354,11 @@ msgstr ""
msgid "Part Actions"
msgstr ""
#: src/pages/part/PartDetail.tsx:1182
#: src/pages/part/PartDetail.tsx:1183
msgid "Part locked"
msgstr ""
#: src/pages/part/PartDetail.tsx:1182
#: src/pages/part/PartDetail.tsx:1183
msgid "Part unlocked"
msgstr ""

View File

@ -8,7 +8,7 @@ msgstr ""
"Language: cs\n"
"Project-Id-Version: inventree\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-06-17 22:14\n"
"PO-Revision-Date: 2026-06-23 06:29\n"
"Last-Translator: \n"
"Language-Team: Czech\n"
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
@ -147,7 +147,7 @@ msgstr "Ne"
#: src/forms/StockForms.tsx:1248
#: src/forms/TransferOrderForms.tsx:234
#: src/pages/build/BuildDetail.tsx:260
#: src/pages/part/PartDetail.tsx:1165
#: src/pages/part/PartDetail.tsx:1166
#: src/pages/part/bom/BomCompare.tsx:203
#: src/tables/ColumnRenderers.tsx:93
#: src/tables/build/BuildOrderParametricTable.tsx:29
@ -166,7 +166,7 @@ msgstr "Díl"
#: src/pages/part/CategoryDetail.tsx:138
#: src/pages/part/CategoryDetail.tsx:285
#: src/pages/part/CategoryDetail.tsx:345
#: src/pages/part/CategoryDetail.tsx:387
#: src/pages/part/CategoryDetail.tsx:388
#: src/pages/part/PartDetail.tsx:893
msgid "Parts"
msgstr "Díly"
@ -242,7 +242,7 @@ msgid "Manufacturer Parts"
msgstr "Díly výrobce"
#: lib/enums/ModelInformation.tsx:80
#: src/pages/part/CategoryDetail.tsx:387
#: src/pages/part/CategoryDetail.tsx:388
#: src/tables/Filter.tsx:496
msgid "Part Category"
msgstr "Kategorie dílu"
@ -261,7 +261,7 @@ msgstr "Kategorie dílů"
#: src/forms/BuildForms.tsx:848
#: src/forms/SalesOrderForms.tsx:438
#: src/forms/TransferOrderForms.tsx:236
#: src/pages/stock/StockDetail.tsx:1075
#: src/pages/stock/StockDetail.tsx:1076
#: src/tables/ColumnRenderers.tsx:132
#: src/tables/part/PartTestResultTable.tsx:256
#: src/tables/stock/InstalledItemsTable.tsx:66
@ -283,7 +283,7 @@ msgstr "Skladové položky"
#: lib/enums/ModelInformation.tsx:99
#: lib/enums/Roles.tsx:51
#: src/pages/stock/LocationDetail.tsx:522
#: src/pages/stock/LocationDetail.tsx:523
msgid "Stock Location"
msgstr "Umístění skladu"
@ -644,14 +644,14 @@ msgstr "Výběr záznamů"
#: src/components/importer/ImporterColumnSelector.tsx:330
#: src/components/importer/ImporterDrawer.tsx:91
#: src/components/modals/LicenseModal.tsx:85
#: src/components/nav/NavigationTree.tsx:211
#: src/components/nav/NavigationTree.tsx:398
#: src/components/nav/NotificationDrawer.tsx:235
#: src/components/nav/SearchDrawer.tsx:588
#: src/components/settings/SettingList.tsx:145
#: src/components/wizards/ImportPartWizard.tsx:574
#: src/components/wizards/ImportPartWizard.tsx:719
#: src/forms/BomForms.tsx:83
#: src/functions/auth.tsx:691
#: src/functions/auth.tsx:693
#: src/pages/ErrorPage.tsx:11
#: src/pages/Index/Settings/AccountSettings/MFASettings.tsx:317
#: src/pages/Index/Settings/AccountSettings/MFASettings.tsx:408
@ -723,6 +723,7 @@ msgstr "Vypršel časový limit žádosti."
#: lib/hooks/MonitorDataOutput.tsx:57
#: lib/hooks/MonitorDataOutput.tsx:116
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:76
msgid "Process failed"
msgstr "Proces se nezdařil"
@ -1391,11 +1392,11 @@ msgstr "Vyžadováno aministrátorské oprávnění"
msgid "This widget requires superuser permissions"
msgstr "Tento widget vyžaduje administrátorské oprávnění "
#: src/components/dashboard/widgets/NewsWidget.tsx:133
#: src/components/dashboard/widgets/NewsWidget.tsx:135
msgid "No News"
msgstr "Žádné novinky"
#: src/components/dashboard/widgets/NewsWidget.tsx:134
#: src/components/dashboard/widgets/NewsWidget.tsx:136
msgid "There are no unread news items"
msgstr "Žádné nepřečtené novinky"
@ -1655,7 +1656,7 @@ msgstr "Kód"
msgid "Error rendering preview"
msgstr "Chyba při vykreslování náhledu"
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:120
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:124
msgid "Preview not available, click \"Reload Preview\"."
msgstr "Náhled není k dispozici, klikněte na \"Znovu načíst náhled\"."
@ -1728,11 +1729,11 @@ msgstr "Uložit aktuální šablonu a znovu načíst náhled"
#~ msgid "to preview"
#~ msgstr "to preview"
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:379
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:380
msgid "Select instance to preview"
msgstr "Vyberte instanci pro náhled"
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:423
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:424
msgid "Error rendering template"
msgstr "Chyba při načítání šablony"
@ -1829,20 +1830,20 @@ msgstr "Přihlášení proběhlo úspěšně"
#: src/components/forms/AuthenticationForm.tsx:81
#: src/components/forms/AuthenticationForm.tsx:89
#: src/functions/auth.tsx:133
#: src/functions/auth.tsx:142
#: src/functions/auth.tsx:144
msgid "Login failed"
msgstr "Přihlášení se nezdařilo"
#: src/components/forms/AuthenticationForm.tsx:82
#: src/components/forms/AuthenticationForm.tsx:90
#: src/components/forms/AuthenticationForm.tsx:106
#: src/functions/auth.tsx:134
#: src/functions/auth.tsx:354
#: src/functions/auth.tsx:136
#: src/functions/auth.tsx:356
msgid "Check your input and try again."
msgstr "Zkontrolujte vstup a zkuste to znovu."
#: src/components/forms/AuthenticationForm.tsx:100
#: src/functions/auth.tsx:345
#: src/functions/auth.tsx:347
msgid "Mail delivery successful"
msgstr "E-mail byl doručen úspěšně"
@ -2128,6 +2129,7 @@ msgstr "Nezařazené"
#: src/components/forms/fields/IconField.tsx:211
#: src/components/nav/Layout.tsx:143
#: src/components/nav/NavigationTree.tsx:378
#: src/tables/part/PartThumbTable.tsx:209
msgid "Search..."
msgstr "Hledat..."
@ -2153,6 +2155,7 @@ msgid "Loading"
msgstr "Načítání"
#: src/components/forms/fields/RelatedModelField.tsx:540
#: src/components/nav/NavigationTree.tsx:403
msgid "No results found"
msgstr "Nebyly nalezeny žádné výsledky"
@ -2247,7 +2250,7 @@ msgstr "Zpracovávání dat"
#: src/components/importer/ImporterColumnSelector.tsx:299
#: src/components/items/ErrorItem.tsx:12
#: src/functions/api.tsx:60
#: src/functions/auth.tsx:401
#: src/functions/auth.tsx:403
msgid "An error occurred"
msgstr "Vyskytla se chyba"
@ -2925,7 +2928,7 @@ msgstr "Odhlásit"
#: src/pages/Index/Settings/SystemSettings.tsx:260
#: src/pages/part/PartDetail.tsx:663
#: src/pages/stock/LocationDetail.tsx:481
#: src/pages/stock/LocationDetail.tsx:522
#: src/pages/stock/LocationDetail.tsx:523
#: src/pages/stock/StockDetail.tsx:689
#: src/pages/stock/TransferOrderDetail.tsx:536
#: src/tables/stock/StockItemTable.tsx:81
@ -2971,7 +2974,11 @@ msgstr "Navigace"
msgid "About"
msgstr "O aplikaci"
#: src/components/nav/NavigationTree.tsx:212
#: src/components/nav/NavigationTree.tsx:388
msgid "Clear search"
msgstr "Vymazat vyhledávání"
#: src/components/nav/NavigationTree.tsx:399
msgid "Error loading navigation tree."
msgstr "Chyba při načítání navigačního stromu."
@ -5539,7 +5546,7 @@ msgstr "Interní chyba serveru"
#~ msgstr "You have been logged out"
#: src/functions/auth.tsx:124
#: src/functions/auth.tsx:220
#: src/functions/auth.tsx:222
msgid "Logged Out"
msgstr "Odhlášen(a)"
@ -5551,97 +5558,97 @@ msgstr "Pro tento prohlížeč došlo ke konfliktní relaci, která byla odhlá
#~ msgid "Found an existing login - using it to log you in."
#~ msgstr "Found an existing login - using it to log you in."
#: src/functions/auth.tsx:143
msgid "No response from server."
msgstr "Žádná odezva ze serveru."
#: src/functions/auth.tsx:143
#~ msgid "Found an existing login - welcome back!"
#~ msgstr "Found an existing login - welcome back!"
#: src/functions/auth.tsx:186
#: src/functions/auth.tsx:145
msgid "No response from server."
msgstr "Žádná odezva ze serveru."
#: src/functions/auth.tsx:188
msgid "MFA Login successful"
msgstr "MFA přihlášení úspěšné"
#: src/functions/auth.tsx:187
#: src/functions/auth.tsx:189
msgid "MFA details were automatically provided in the browser"
msgstr "Údaje o MFA byly automaticky poskytnuty v prohlížeči"
#: src/functions/auth.tsx:221
#: src/functions/auth.tsx:223
msgid "Successfully logged out"
msgstr "Úspěšně odhlášen/a"
#: src/functions/auth.tsx:288
#: src/functions/auth.tsx:290
msgid "Language changed"
msgstr "Jazyk změněn"
#: src/functions/auth.tsx:289
#: src/functions/auth.tsx:291
msgid "Your active language has been changed to the one set in your profile"
msgstr "Váš aktivní jazyk byl změněn podle nastavení Vašeho profilu"
#: src/functions/auth.tsx:310
#: src/functions/auth.tsx:312
msgid "Theme changed"
msgstr "Motiv změněn"
#: src/functions/auth.tsx:311
#: src/functions/auth.tsx:313
msgid "Your active theme has been changed to the one set in your profile"
msgstr "Váš aktivní jazyk byl změněn podle nastavení Vašeho profilu"
#: src/functions/auth.tsx:346
#: src/functions/auth.tsx:348
msgid "Check your inbox for a reset link. This only works if you have an account. Check in spam too."
msgstr "Zkontrolujte doručenou poštu pro odkaz pro obnovení. Funguje to pouze v případě, že máte účet. Zkontrolujte také ve spamu."
#: src/functions/auth.tsx:353
#: src/functions/auth.tsx:617
#: src/functions/auth.tsx:355
#: src/functions/auth.tsx:619
msgid "Reset failed"
msgstr "Obnovení selhalo"
#: src/functions/auth.tsx:380
#: src/functions/auth.tsx:382
msgid "Already logged in"
msgstr "Již přihlášeno!"
#: src/functions/auth.tsx:381
#: src/functions/auth.tsx:383
msgid "There is a conflicting session on the server for this browser. Please logout of that first."
msgstr "Vyskytl se konflikt relací na serveru pro tento prohlížeč, prosím nejdřív se odhlašte."
#: src/functions/auth.tsx:437
#: src/functions/auth.tsx:439
msgid "Logged In"
msgstr "Přihlášen"
#: src/functions/auth.tsx:438
#: src/functions/auth.tsx:440
msgid "Successfully logged in"
msgstr "Úspěšně přihlášen/a"
#: src/functions/auth.tsx:572
#: src/functions/auth.tsx:574
msgid "Failed to set up MFA"
msgstr "Nepodařilo se nastavit MFA"
#: src/functions/auth.tsx:591
#: src/functions/auth.tsx:593
msgid "MFA Setup successful"
msgstr "Nastavení MFA bylo úspěšné"
#: src/functions/auth.tsx:592
#: src/functions/auth.tsx:594
msgid "MFA via TOTP has been set up successfully; you will need to login again."
msgstr "MFA přes TOTP bylo úspěšně nastaveno; budete se muset znovu přihlásit."
#: src/functions/auth.tsx:607
#: src/functions/auth.tsx:609
msgid "Password set"
msgstr "Nastavení hesla"
#: src/functions/auth.tsx:608
#: src/functions/auth.tsx:717
#: src/functions/auth.tsx:610
#: src/functions/auth.tsx:719
msgid "The password was set successfully. You can now login with your new password"
msgstr "Heslo bylo úspěšně nastaveno. Nyní se můžete přihlásit s novým heslem"
#: src/functions/auth.tsx:682
#: src/functions/auth.tsx:684
msgid "Password could not be changed"
msgstr "Heslo nelze změnit"
#: src/functions/auth.tsx:700
#: src/functions/auth.tsx:702
msgid "The two password fields didnt match"
msgstr "Dvě pole s hesly se neshodují"
#: src/functions/auth.tsx:716
#: src/functions/auth.tsx:718
msgid "Password Changed"
msgstr "Heslo bylo změněno"
@ -8347,11 +8354,11 @@ msgstr "Vyhledat podle sériového čísla"
msgid "Part Actions"
msgstr "Akce s položkou"
#: src/pages/part/PartDetail.tsx:1182
#: src/pages/part/PartDetail.tsx:1183
msgid "Part locked"
msgstr "Díl uzamčen"
#: src/pages/part/PartDetail.tsx:1182
#: src/pages/part/PartDetail.tsx:1183
msgid "Part unlocked"
msgstr "Díl odemčen"

View File

@ -8,7 +8,7 @@ msgstr ""
"Language: da\n"
"Project-Id-Version: inventree\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-06-17 22:14\n"
"PO-Revision-Date: 2026-06-20 13:53\n"
"Last-Translator: \n"
"Language-Team: Danish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@ -147,7 +147,7 @@ msgstr "Nej"
#: src/forms/StockForms.tsx:1248
#: src/forms/TransferOrderForms.tsx:234
#: src/pages/build/BuildDetail.tsx:260
#: src/pages/part/PartDetail.tsx:1165
#: src/pages/part/PartDetail.tsx:1166
#: src/pages/part/bom/BomCompare.tsx:203
#: src/tables/ColumnRenderers.tsx:93
#: src/tables/build/BuildOrderParametricTable.tsx:29
@ -166,7 +166,7 @@ msgstr "Del"
#: src/pages/part/CategoryDetail.tsx:138
#: src/pages/part/CategoryDetail.tsx:285
#: src/pages/part/CategoryDetail.tsx:345
#: src/pages/part/CategoryDetail.tsx:387
#: src/pages/part/CategoryDetail.tsx:388
#: src/pages/part/PartDetail.tsx:893
msgid "Parts"
msgstr "Dele"
@ -242,7 +242,7 @@ msgid "Manufacturer Parts"
msgstr "Producent Dele"
#: lib/enums/ModelInformation.tsx:80
#: src/pages/part/CategoryDetail.tsx:387
#: src/pages/part/CategoryDetail.tsx:388
#: src/tables/Filter.tsx:496
msgid "Part Category"
msgstr "Del Kategori"
@ -261,7 +261,7 @@ msgstr "Del Kategorier"
#: src/forms/BuildForms.tsx:848
#: src/forms/SalesOrderForms.tsx:438
#: src/forms/TransferOrderForms.tsx:236
#: src/pages/stock/StockDetail.tsx:1075
#: src/pages/stock/StockDetail.tsx:1076
#: src/tables/ColumnRenderers.tsx:132
#: src/tables/part/PartTestResultTable.tsx:256
#: src/tables/stock/InstalledItemsTable.tsx:66
@ -283,7 +283,7 @@ msgstr "Lagervarer"
#: lib/enums/ModelInformation.tsx:99
#: lib/enums/Roles.tsx:51
#: src/pages/stock/LocationDetail.tsx:522
#: src/pages/stock/LocationDetail.tsx:523
msgid "Stock Location"
msgstr "Lagerlokation"
@ -644,14 +644,14 @@ msgstr ""
#: src/components/importer/ImporterColumnSelector.tsx:330
#: src/components/importer/ImporterDrawer.tsx:91
#: src/components/modals/LicenseModal.tsx:85
#: src/components/nav/NavigationTree.tsx:211
#: src/components/nav/NavigationTree.tsx:398
#: src/components/nav/NotificationDrawer.tsx:235
#: src/components/nav/SearchDrawer.tsx:588
#: src/components/settings/SettingList.tsx:145
#: src/components/wizards/ImportPartWizard.tsx:574
#: src/components/wizards/ImportPartWizard.tsx:719
#: src/forms/BomForms.tsx:83
#: src/functions/auth.tsx:691
#: src/functions/auth.tsx:693
#: src/pages/ErrorPage.tsx:11
#: src/pages/Index/Settings/AccountSettings/MFASettings.tsx:317
#: src/pages/Index/Settings/AccountSettings/MFASettings.tsx:408
@ -723,6 +723,7 @@ msgstr "Anmodningen udløb"
#: lib/hooks/MonitorDataOutput.tsx:57
#: lib/hooks/MonitorDataOutput.tsx:116
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:76
msgid "Process failed"
msgstr "Proces fejlede"
@ -1391,11 +1392,11 @@ msgstr "Kræver Superbruger"
msgid "This widget requires superuser permissions"
msgstr "Denne widget kræver superbruger tilladelser"
#: src/components/dashboard/widgets/NewsWidget.tsx:133
#: src/components/dashboard/widgets/NewsWidget.tsx:135
msgid "No News"
msgstr "Ingen Nyheder"
#: src/components/dashboard/widgets/NewsWidget.tsx:134
#: src/components/dashboard/widgets/NewsWidget.tsx:136
msgid "There are no unread news items"
msgstr "Der er ingen ulæste nyheder"
@ -1655,7 +1656,7 @@ msgstr "Kode"
msgid "Error rendering preview"
msgstr "Fejl under visning"
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:120
#: src/components/editors/TemplateEditor/PdfPreview/PdfPreview.tsx:124
msgid "Preview not available, click \"Reload Preview\"."
msgstr "Forhåndsvisning ikke tilgængelig, klik \"Genindlæs forhåndsvisning\"."
@ -1728,11 +1729,11 @@ msgstr "Gem den nuværende skabelon og genindlæs forhåndsvisningen"
#~ msgid "to preview"
#~ msgstr "to preview"
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:379
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:380
msgid "Select instance to preview"
msgstr "Vælg eksempel til forhåndsvisning"
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:423
#: src/components/editors/TemplateEditor/TemplateEditor.tsx:424
msgid "Error rendering template"
msgstr "Render fejl af skabelon"
@ -1829,20 +1830,20 @@ msgstr "Logget ind"
#: src/components/forms/AuthenticationForm.tsx:81
#: src/components/forms/AuthenticationForm.tsx:89
#: src/functions/auth.tsx:133
#: src/functions/auth.tsx:142
#: src/functions/auth.tsx:144
msgid "Login failed"
msgstr "Login mislykkedes"
#: src/components/forms/AuthenticationForm.tsx:82
#: src/components/forms/AuthenticationForm.tsx:90
#: src/components/forms/AuthenticationForm.tsx:106
#: src/functions/auth.tsx:134
#: src/functions/auth.tsx:354
#: src/functions/auth.tsx:136
#: src/functions/auth.tsx:356
msgid "Check your input and try again."
msgstr "Tjek din indtastning og prøv igen."
#: src/components/forms/AuthenticationForm.tsx:100
#: src/functions/auth.tsx:345
#: src/functions/auth.tsx:347
msgid "Mail delivery successful"
msgstr "Mail levering succesfuld"
@ -2128,6 +2129,7 @@ msgstr "Ukategoriseret"
#: src/components/forms/fields/IconField.tsx:211
#: src/components/nav/Layout.tsx:143
#: src/components/nav/NavigationTree.tsx:378
#: src/tables/part/PartThumbTable.tsx:209
msgid "Search..."
msgstr "Søg..."
@ -2153,6 +2155,7 @@ msgid "Loading"
msgstr "Indlæser"
#: src/components/forms/fields/RelatedModelField.tsx:540
#: src/components/nav/NavigationTree.tsx:403
msgid "No results found"
msgstr "Ingen resultater fundet"
@ -2247,7 +2250,7 @@ msgstr "Behandler Data"
#: src/components/importer/ImporterColumnSelector.tsx:299
#: src/components/items/ErrorItem.tsx:12
#: src/functions/api.tsx:60
#: src/functions/auth.tsx:401
#: src/functions/auth.tsx:403
msgid "An error occurred"
msgstr "En feil opstod"
@ -2925,7 +2928,7 @@ msgstr "Log ud"
#: src/pages/Index/Settings/SystemSettings.tsx:260
#: src/pages/part/PartDetail.tsx:663
#: src/pages/stock/LocationDetail.tsx:481
#: src/pages/stock/LocationDetail.tsx:522
#: src/pages/stock/LocationDetail.tsx:523
#: src/pages/stock/StockDetail.tsx:689
#: src/pages/stock/TransferOrderDetail.tsx:536
#: src/tables/stock/StockItemTable.tsx:81
@ -2971,7 +2974,11 @@ msgstr "Navigation"
msgid "About"
msgstr "Omkring"
#: src/components/nav/NavigationTree.tsx:212
#: src/components/nav/NavigationTree.tsx:388
msgid "Clear search"
msgstr ""
#: src/components/nav/NavigationTree.tsx:399
msgid "Error loading navigation tree."
msgstr "Fejl ved indlæsning af navigationstræ."
@ -5539,7 +5546,7 @@ msgstr "Intern serverfejl"
#~ msgstr "You have been logged out"
#: src/functions/auth.tsx:124
#: src/functions/auth.tsx:220
#: src/functions/auth.tsx:222
msgid "Logged Out"
msgstr "Logget af"
@ -5551,97 +5558,97 @@ msgstr ""
#~ msgid "Found an existing login - using it to log you in."
#~ msgstr "Found an existing login - using it to log you in."
#: src/functions/auth.tsx:143
msgid "No response from server."
msgstr "Intet svar fra server."
#: src/functions/auth.tsx:143
#~ msgid "Found an existing login - welcome back!"
#~ msgstr "Found an existing login - welcome back!"
#: src/functions/auth.tsx:186
#: src/functions/auth.tsx:145
msgid "No response from server."
msgstr "Intet svar fra server."
#: src/functions/auth.tsx:188
msgid "MFA Login successful"
msgstr "Multifaktorgodkendelse Login succesfuld"
#: src/functions/auth.tsx:187
#: src/functions/auth.tsx:189
msgid "MFA details were automatically provided in the browser"
msgstr "Multifaktorgodkendelse detaljer blev automatisk givet i browseren"
#: src/functions/auth.tsx:221
#: src/functions/auth.tsx:223
msgid "Successfully logged out"
msgstr "Du er nu logget af"
#: src/functions/auth.tsx:288
#: src/functions/auth.tsx:290
msgid "Language changed"
msgstr "Sprog ændret"
#: src/functions/auth.tsx:289
#: src/functions/auth.tsx:291
msgid "Your active language has been changed to the one set in your profile"
msgstr "Dit aktive sprog er blevet ændret til det der er sat i din profil"
#: src/functions/auth.tsx:310
#: src/functions/auth.tsx:312
msgid "Theme changed"
msgstr "Tema ændret"
#: src/functions/auth.tsx:311
#: src/functions/auth.tsx:313
msgid "Your active theme has been changed to the one set in your profile"
msgstr "Dit aktive tema er blevet ændret til det der er sat i din profil"
#: src/functions/auth.tsx:346
#: src/functions/auth.tsx:348
msgid "Check your inbox for a reset link. This only works if you have an account. Check in spam too."
msgstr "Tjek din indbakke for et nulstillingslink. Dette virker kun, hvis du har en konto. Tjek også spam."
#: src/functions/auth.tsx:353
#: src/functions/auth.tsx:617
#: src/functions/auth.tsx:355
#: src/functions/auth.tsx:619
msgid "Reset failed"
msgstr "Nulstilling fejlede"
#: src/functions/auth.tsx:380
#: src/functions/auth.tsx:382
msgid "Already logged in"
msgstr "Allerede logget ind"
#: src/functions/auth.tsx:381
#: src/functions/auth.tsx:383
msgid "There is a conflicting session on the server for this browser. Please logout of that first."
msgstr "Der er en konfliktfyldt session på serveren for denne browser. Log ud af det først."
#: src/functions/auth.tsx:437
#: src/functions/auth.tsx:439
msgid "Logged In"
msgstr "Logget ind"
#: src/functions/auth.tsx:438
#: src/functions/auth.tsx:440
msgid "Successfully logged in"
msgstr "Logget ind"
#: src/functions/auth.tsx:572
#: src/functions/auth.tsx:574
msgid "Failed to set up MFA"
msgstr "Kunne ikke oprette Multifaktorgodkendelse"
#: src/functions/auth.tsx:591
#: src/functions/auth.tsx:593
msgid "MFA Setup successful"
msgstr ""
#: src/functions/auth.tsx:592
#: src/functions/auth.tsx:594
msgid "MFA via TOTP has been set up successfully; you will need to login again."
msgstr ""
#: src/functions/auth.tsx:607
#: src/functions/auth.tsx:609
msgid "Password set"
msgstr "Adgangskode sat"
#: src/functions/auth.tsx:608
#: src/functions/auth.tsx:717
#: src/functions/auth.tsx:610
#: src/functions/auth.tsx:719
msgid "The password was set successfully. You can now login with your new password"
msgstr "Adgangskoden blev oprettet. Du kan nu logge ind med din nye adgangskode"
#: src/functions/auth.tsx:682
#: src/functions/auth.tsx:684
msgid "Password could not be changed"
msgstr "Adgangskoden kunne ikke ændres"
#: src/functions/auth.tsx:700
#: src/functions/auth.tsx:702
msgid "The two password fields didnt match"
msgstr "De to adgangskodefelter matcher ikke"
#: src/functions/auth.tsx:716
#: src/functions/auth.tsx:718
msgid "Password Changed"
msgstr "Adgangskode ændret"
@ -8347,11 +8354,11 @@ msgstr "Søg på serienummer"
msgid "Part Actions"
msgstr "Del Handlinger"
#: src/pages/part/PartDetail.tsx:1182
#: src/pages/part/PartDetail.tsx:1183
msgid "Part locked"
msgstr ""
#: src/pages/part/PartDetail.tsx:1182
#: src/pages/part/PartDetail.tsx:1183
msgid "Part unlocked"
msgstr ""

Some files were not shown because too many files have changed in this diff Show More