mirror of
https://github.com/inventree/InvenTree.git
synced 2026-07-05 06:32:55 +00:00
Merge branch 'master' into custom-states
This commit is contained in:
@@ -30,7 +30,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
docker: ${{ steps.filter.outputs.docker }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3.0.2
|
||||
id: filter
|
||||
with:
|
||||
@@ -66,9 +66,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Set Up Python ${{ env.python_version }}
|
||||
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # pin@v5.2.0
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # pin@v5.3.0
|
||||
with:
|
||||
python-version: ${{ env.python_version }}
|
||||
- name: Version Check
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
force: ${{ steps.force.outputs.force }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3.0.2
|
||||
id: filter
|
||||
with:
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
needs: ["pre-commit"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -92,9 +92,9 @@ jobs:
|
||||
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.force == 'true'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Set up Python ${{ env.python_version }}
|
||||
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # pin@v5.2.0
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # pin@v5.3.0
|
||||
with:
|
||||
python-version: ${{ env.python_version }}
|
||||
cache: "pip"
|
||||
@@ -113,9 +113,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Set up Python ${{ env.python_version }}
|
||||
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # pin@v5.2.0
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # pin@v5.3.0
|
||||
with:
|
||||
python-version: ${{ env.python_version }}
|
||||
- name: Check Config
|
||||
@@ -149,7 +149,7 @@ jobs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -211,7 +211,7 @@ jobs:
|
||||
version: ${{ needs.schema.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
name: Checkout Code
|
||||
with:
|
||||
repository: inventree/schema
|
||||
@@ -250,7 +250,7 @@ jobs:
|
||||
INVENTREE_SITE_URL: http://127.0.0.1:12345
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -292,7 +292,7 @@ jobs:
|
||||
python_version: ${{ matrix.python_version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -346,7 +346,7 @@ jobs:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -390,7 +390,7 @@ jobs:
|
||||
- 3306:3306
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -429,7 +429,7 @@ jobs:
|
||||
- 5432:5432
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -460,7 +460,7 @@ jobs:
|
||||
INVENTREE_PLUGINS_ENABLED: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
name: Checkout Code
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
@@ -517,7 +517,7 @@ jobs:
|
||||
VITE_COVERAGE: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -565,7 +565,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Version Check
|
||||
run: |
|
||||
pip install --require-hashes -r contrib/dev_reqs/requirements.txt
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
contents: write
|
||||
attestations: write
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
- name: Build frontend
|
||||
run: cd src/frontend && npm run compile && npm run build
|
||||
- name: Create SBOM for frontend
|
||||
uses: anchore/sbom-action@8d0a6505bf28ced3e85154d13dc6af83299e13f1 # pin@v0
|
||||
uses: anchore/sbom-action@251a468eed47e5082b105c3ba6ee500c0e65a764 # pin@v0
|
||||
with:
|
||||
artifact-name: frontend-build.spdx
|
||||
path: src/frontend
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -67,6 +67,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
|
||||
uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # pin@v4.2.1
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
git reset --hard
|
||||
git reset HEAD~
|
||||
- name: crowdin action
|
||||
uses: crowdin/github-action@95d6e895e871c3c7acf0cfb962f296baa41e63c6 # pin@v2
|
||||
uses: crowdin/github-action@2d540f18b0a416b1fbf2ee5be35841bd380fc1da # pin@v2
|
||||
with:
|
||||
upload_sources: true
|
||||
upload_translations: false
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
@@ -18,6 +18,19 @@ If there are some icons missing in the tabler icons package, users can even inst
|
||||
|
||||
A stock location type represents a specific type of location (e.g. one specific size of drawer, shelf, ... or box) which can be assigned to multiple stock locations. In the first place, it is used to specify an icon and having the icon in sync for all locations that use this location type, but it also serves as a data field to quickly see what type of location this is. It is planned to add e.g. drawer dimension information to the location type to add a "find a matching, empty stock location" tool.
|
||||
|
||||
## External Stock Location
|
||||
An external stock location can be used to indicate that items in there might not be available
|
||||
for immediate usage. Stock items in an external location are marked with an additional icon
|
||||
in the build order line items view where the material is allocated.
|
||||
|
||||
{% with id="stock_external_icon", url="stock/stock_external_icon.png", description="External stock indication" %}
|
||||
{% include 'img.html' %}
|
||||
{% endwith %}
|
||||
|
||||
Anyhow there is no limitation on the stock item. It can be allocated as usual.
|
||||
|
||||
The external flag does not get inherited to sublocations.
|
||||
|
||||
## Stock Item
|
||||
|
||||
A *Stock Item* is an actual instance of a [*Part*](../part/part.md) item. It represents a physical quantity of the *Part* in a specific location.
|
||||
|
||||
@@ -44,7 +44,8 @@ def top_level_path(path: str) -> str:
|
||||
|
||||
path = path.strip()
|
||||
|
||||
key = path.split('/')[1]
|
||||
parts = path.split('/')
|
||||
key = parts[1] if len(parts) > 1 else parts[0]
|
||||
|
||||
if key in SPECIAL_PATHS:
|
||||
return key
|
||||
|
||||
@@ -30,7 +30,6 @@ from .helpers_email import is_email_configured
|
||||
from .mixins import ListAPI, RetrieveUpdateAPI
|
||||
from .status import check_system_health, is_worker_running
|
||||
from .version import inventreeApiText
|
||||
from .views import AjaxView
|
||||
|
||||
logger = logging.getLogger('inventree')
|
||||
|
||||
@@ -196,8 +195,35 @@ class VersionTextView(ListAPI):
|
||||
return JsonResponse(inventreeApiText())
|
||||
|
||||
|
||||
class InfoView(AjaxView):
|
||||
"""Simple JSON endpoint for InvenTree information.
|
||||
class InfoApiSerializer(serializers.Serializer):
|
||||
"""InvenTree server information - some information might be blanked if called without elevated credentials."""
|
||||
|
||||
server = serializers.CharField(read_only=True)
|
||||
version = serializers.CharField(read_only=True)
|
||||
instance = serializers.CharField(read_only=True)
|
||||
apiVersion = serializers.IntegerField(read_only=True) # noqa: N815
|
||||
worker_running = serializers.BooleanField(read_only=True)
|
||||
worker_count = serializers.IntegerField(read_only=True)
|
||||
worker_pending_tasks = serializers.IntegerField(read_only=True)
|
||||
plugins_enabled = serializers.BooleanField(read_only=True)
|
||||
plugins_install_disabled = serializers.BooleanField(read_only=True)
|
||||
active_plugins = serializers.JSONField(read_only=True)
|
||||
email_configured = serializers.BooleanField(read_only=True)
|
||||
debug_mode = serializers.BooleanField(read_only=True)
|
||||
docker_mode = serializers.BooleanField(read_only=True)
|
||||
default_locale = serializers.ChoiceField(
|
||||
choices=settings.LOCALE_CODES, read_only=True
|
||||
)
|
||||
system_health = serializers.BooleanField(read_only=True)
|
||||
database = serializers.CharField(read_only=True)
|
||||
platform = serializers.CharField(read_only=True)
|
||||
installer = serializers.CharField(read_only=True)
|
||||
target = serializers.CharField(read_only=True)
|
||||
django_admin = serializers.CharField(read_only=True)
|
||||
|
||||
|
||||
class InfoView(APIView):
|
||||
"""JSON endpoint for InvenTree server information.
|
||||
|
||||
Use to confirm that the server is running, etc.
|
||||
"""
|
||||
@@ -208,6 +234,13 @@ class InfoView(AjaxView):
|
||||
"""Return the current number of outstanding background tasks."""
|
||||
return OrmQ.objects.count()
|
||||
|
||||
@extend_schema(
|
||||
responses={
|
||||
200: OpenApiResponse(
|
||||
response=InfoApiSerializer, description='InvenTree server information'
|
||||
)
|
||||
}
|
||||
)
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""Serve current server information."""
|
||||
is_staff = request.user.is_staff
|
||||
@@ -261,7 +294,7 @@ class InfoView(AjaxView):
|
||||
return False
|
||||
|
||||
|
||||
class NotFoundView(AjaxView):
|
||||
class NotFoundView(APIView):
|
||||
"""Simple JSON view when accessing an invalid API view."""
|
||||
|
||||
permission_classes = [permissions.AllowAny]
|
||||
@@ -280,22 +313,27 @@ class NotFoundView(AjaxView):
|
||||
"""Return 404."""
|
||||
return self.not_found(request)
|
||||
|
||||
@extend_schema(exclude=True)
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""Return 404."""
|
||||
return self.not_found(request)
|
||||
|
||||
@extend_schema(exclude=True)
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Return 404."""
|
||||
return self.not_found(request)
|
||||
|
||||
@extend_schema(exclude=True)
|
||||
def patch(self, request, *args, **kwargs):
|
||||
"""Return 404."""
|
||||
return self.not_found(request)
|
||||
|
||||
@extend_schema(exclude=True)
|
||||
def put(self, request, *args, **kwargs):
|
||||
"""Return 404."""
|
||||
return self.not_found(request)
|
||||
|
||||
@extend_schema(exclude=True)
|
||||
def delete(self, request, *args, **kwargs):
|
||||
"""Return 404."""
|
||||
return self.not_found(request)
|
||||
|
||||
@@ -1,13 +1,27 @@
|
||||
"""InvenTree API version information."""
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 277
|
||||
INVENTREE_API_VERSION = 280
|
||||
|
||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||
|
||||
|
||||
INVENTREE_API_TEXT = """
|
||||
|
||||
v280 - 2024-11-10 : https://github.com/inventree/InvenTree/pull/8461
|
||||
- Makes schema for API information endpoint more informing
|
||||
- Removes general not found endpoint
|
||||
|
||||
v279 - 2024-11-09 : https://github.com/inventree/InvenTree/pull/8458
|
||||
- Adds "order_outstanding" and "part" filters to the BuildLine API endpoint
|
||||
- Adds "order_outstanding" filter to the SalesOrderLineItem API endpoint
|
||||
|
||||
v278 - 2024-11-07 : https://github.com/inventree/InvenTree/pull/8445
|
||||
- Updates to the SalesOrder API endpoints
|
||||
- Add "shipment count" information to the SalesOrder API endpoints
|
||||
- Allow null value for SalesOrderAllocation.shipment field
|
||||
- Additional filtering options for allocation endpoints
|
||||
|
||||
v277 - 2024-11-01 : https://github.com/inventree/InvenTree/pull/8278
|
||||
- Allow build order list to be filtered by "outstanding" (alias for "active")
|
||||
|
||||
|
||||
@@ -36,6 +36,24 @@ def get_token_from_request(request):
|
||||
return None
|
||||
|
||||
|
||||
# List of target URL endpoints where *do not* want to redirect to
|
||||
urls = [
|
||||
reverse_lazy('account_login'),
|
||||
reverse_lazy('account_logout'),
|
||||
reverse_lazy('admin:login'),
|
||||
reverse_lazy('admin:logout'),
|
||||
]
|
||||
|
||||
# Do not redirect requests to any of these paths
|
||||
paths_ignore = [
|
||||
'/api/',
|
||||
'/auth/',
|
||||
'/js/', # TODO - remove when CUI is removed
|
||||
settings.MEDIA_URL,
|
||||
settings.STATIC_URL,
|
||||
]
|
||||
|
||||
|
||||
class AuthRequiredMiddleware:
|
||||
"""Check for user to be authenticated."""
|
||||
|
||||
@@ -108,23 +126,6 @@ class AuthRequiredMiddleware:
|
||||
if not authorized:
|
||||
path = request.path_info
|
||||
|
||||
# List of URL endpoints we *do not* want to redirect to
|
||||
urls = [
|
||||
reverse_lazy('account_login'),
|
||||
reverse_lazy('account_logout'),
|
||||
reverse_lazy('admin:login'),
|
||||
reverse_lazy('admin:logout'),
|
||||
]
|
||||
|
||||
# Do not redirect requests to any of these paths
|
||||
paths_ignore = [
|
||||
'/api/',
|
||||
'/auth/',
|
||||
'/js/',
|
||||
settings.MEDIA_URL,
|
||||
settings.STATIC_URL,
|
||||
]
|
||||
|
||||
if path not in urls and not any(
|
||||
path.startswith(p) for p in paths_ignore
|
||||
):
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import Http404
|
||||
from django.test import tag
|
||||
from django.urls import reverse
|
||||
|
||||
from error_report.models import Error
|
||||
@@ -11,8 +10,6 @@ from InvenTree.exceptions import log_error
|
||||
from InvenTree.unit_test import InvenTreeTestCase
|
||||
|
||||
|
||||
# TODO change test to not rely on CUI
|
||||
@tag('cui')
|
||||
class MiddlewareTests(InvenTreeTestCase):
|
||||
"""Test for middleware functions."""
|
||||
|
||||
@@ -32,25 +29,17 @@ class MiddlewareTests(InvenTreeTestCase):
|
||||
# logout
|
||||
self.client.logout()
|
||||
|
||||
# check that static files go through
|
||||
# TODO @matmair re-enable this check
|
||||
# self.check_path('/static/css/inventree.css', 302)
|
||||
|
||||
# check that account things go through
|
||||
self.check_path(reverse('account_login'))
|
||||
|
||||
# logout goes directly to login
|
||||
self.check_path(reverse('account_logout'))
|
||||
|
||||
# check that frontend code is redirected to login
|
||||
response = self.check_path(reverse('stats'), 302)
|
||||
self.assertEqual(response.url, '/accounts/login/?next=/stats/')
|
||||
|
||||
# check that a 401 is raised
|
||||
self.check_path(reverse('settings.js'), 401)
|
||||
response = self.check_path(reverse('index'), 302)
|
||||
self.assertEqual(response.url, '/accounts/login/?next=/')
|
||||
|
||||
def test_token_auth(self):
|
||||
"""Test auth with token auth."""
|
||||
target = reverse('settings.js') # for PUI only use 'api-license'
|
||||
|
||||
# get token
|
||||
response = self.client.get(reverse('api-token'), format='json', data={})
|
||||
token = response.data['token']
|
||||
@@ -58,16 +47,17 @@ class MiddlewareTests(InvenTreeTestCase):
|
||||
# logout
|
||||
self.client.logout()
|
||||
# this should raise a 401
|
||||
self.check_path(reverse('settings.js'), 401)
|
||||
|
||||
# request with token
|
||||
self.check_path(reverse('settings.js'), HTTP_Authorization=f'Token {token}')
|
||||
self.check_path(target, 401)
|
||||
|
||||
# Request with broken token
|
||||
self.check_path(reverse('settings.js'), 401, HTTP_Authorization='Token abcd123')
|
||||
self.check_path(target, 401, HTTP_Authorization='Token abcd123')
|
||||
|
||||
# should still fail without token
|
||||
self.check_path(reverse('settings.js'), 401)
|
||||
self.check_path(target, 401)
|
||||
|
||||
# request with token
|
||||
self.check_path(target, HTTP_Authorization=f'Token {token}')
|
||||
|
||||
def test_error_exceptions(self):
|
||||
"""Test that ignored errors are not logged."""
|
||||
@@ -80,7 +70,7 @@ class MiddlewareTests(InvenTreeTestCase):
|
||||
|
||||
# Test normal setup
|
||||
check()
|
||||
response = self.client.get(reverse('part-detail', kwargs={'pk': 9999}))
|
||||
response = self.client.get(reverse('api-part-detail', kwargs={'pk': 9999}))
|
||||
self.assertEqual(response.status_code, 404)
|
||||
check()
|
||||
|
||||
@@ -92,13 +82,8 @@ class MiddlewareTests(InvenTreeTestCase):
|
||||
|
||||
# Test setup without ignored errors
|
||||
settings.IGNORED_ERRORS = []
|
||||
response = self.client.get(reverse('part-detail', kwargs={'pk': 9999}))
|
||||
self.assertEqual(response.status_code, 404)
|
||||
check(1)
|
||||
|
||||
# Test manual logging
|
||||
try:
|
||||
raise Http404
|
||||
except Http404:
|
||||
log_error('testpath')
|
||||
check(2)
|
||||
check(1)
|
||||
|
||||
@@ -11,7 +11,7 @@ from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core import mail
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.test import TestCase, override_settings, tag
|
||||
from django.test import TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
|
||||
@@ -1493,8 +1493,6 @@ class MagicLoginTest(InvenTreeTestCase):
|
||||
self.assertEqual(resp.wsgi_request.user, self.user)
|
||||
|
||||
|
||||
# TODO - refactor to not use CUI
|
||||
@tag('cui')
|
||||
class MaintenanceModeTest(InvenTreeTestCase):
|
||||
"""Unit tests for maintenance mode."""
|
||||
|
||||
|
||||
@@ -477,7 +477,9 @@ if settings.ENABLE_PLATFORM_FRONTEND:
|
||||
frontendpatterns += [
|
||||
path(
|
||||
'accounts/login/',
|
||||
RedirectView.as_view(url=settings.FRONTEND_URL_BASE, permanent=False),
|
||||
RedirectView.as_view(
|
||||
url=f'/{settings.FRONTEND_URL_BASE}', permanent=False
|
||||
),
|
||||
name='account_login',
|
||||
)
|
||||
]
|
||||
|
||||
@@ -357,6 +357,23 @@ class BuildLineFilter(rest_filters.FilterSet):
|
||||
tracked = rest_filters.BooleanFilter(label=_('Tracked'), field_name='bom_item__sub_part__trackable')
|
||||
testable = rest_filters.BooleanFilter(label=_('Testable'), field_name='bom_item__sub_part__testable')
|
||||
|
||||
part = rest_filters.ModelChoiceFilter(
|
||||
queryset=part.models.Part.objects.all(),
|
||||
label=_('Part'),
|
||||
field_name='bom_item__sub_part',
|
||||
)
|
||||
|
||||
order_outstanding = rest_filters.BooleanFilter(
|
||||
label=_('Order Outstanding'),
|
||||
method='filter_order_outstanding'
|
||||
)
|
||||
|
||||
def filter_order_outstanding(self, queryset, name, value):
|
||||
"""Filter by whether the associated BuildOrder is 'outstanding'."""
|
||||
if str2bool(value):
|
||||
return queryset.filter(build__status__in=BuildStatusGroups.ACTIVE_CODES)
|
||||
return queryset.exclude(build__status__in=BuildStatusGroups.ACTIVE_CODES)
|
||||
|
||||
allocated = rest_filters.BooleanFilter(label=_('Allocated'), method='filter_allocated')
|
||||
|
||||
def filter_allocated(self, queryset, name, value):
|
||||
@@ -383,12 +400,28 @@ class BuildLineFilter(rest_filters.FilterSet):
|
||||
return queryset.exclude(flt)
|
||||
|
||||
|
||||
|
||||
class BuildLineEndpoint:
|
||||
"""Mixin class for BuildLine API endpoints."""
|
||||
|
||||
queryset = BuildLine.objects.all()
|
||||
serializer_class = build.serializers.BuildLineSerializer
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""Return the serializer instance for this endpoint."""
|
||||
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
|
||||
try:
|
||||
params = self.request.query_params
|
||||
|
||||
kwargs['part_detail'] = str2bool(params.get('part_detail', True))
|
||||
kwargs['build_detail'] = str2bool(params.get('build_detail', False))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
def get_source_build(self) -> Build:
|
||||
"""Return the source Build object for the BuildLine queryset.
|
||||
|
||||
|
||||
@@ -1278,8 +1278,6 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
'pk',
|
||||
'build',
|
||||
'bom_item',
|
||||
'bom_item_detail',
|
||||
'part_detail',
|
||||
'quantity',
|
||||
|
||||
# Build detail fields
|
||||
@@ -1315,6 +1313,11 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
# Extra fields only for data export
|
||||
'part_description',
|
||||
'part_category_name',
|
||||
|
||||
# Extra detail (related field) serializers
|
||||
'bom_item_detail',
|
||||
'part_detail',
|
||||
'build_detail',
|
||||
]
|
||||
|
||||
read_only_fields = [
|
||||
@@ -1323,6 +1326,19 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
'allocations',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Determine which extra details fields should be included"""
|
||||
part_detail = kwargs.pop('part_detail', True)
|
||||
build_detail = kwargs.pop('build_detail', False)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if not part_detail:
|
||||
self.fields.pop('part_detail', None)
|
||||
|
||||
if not build_detail:
|
||||
self.fields.pop('build_detail', None)
|
||||
|
||||
# Build info fields
|
||||
build_reference = serializers.CharField(source='build.reference', label=_('Build Reference'), read_only=True)
|
||||
|
||||
@@ -1362,6 +1378,7 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
)
|
||||
|
||||
part_detail = part_serializers.PartBriefSerializer(source='bom_item.sub_part', many=False, read_only=True, pricing=False)
|
||||
build_detail = BuildSerializer(source='build', part_detail=False, many=False, read_only=True)
|
||||
|
||||
# Annotated (calculated) fields
|
||||
|
||||
@@ -1404,9 +1421,13 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
"""
|
||||
queryset = queryset.select_related(
|
||||
'build',
|
||||
'build__part',
|
||||
'build__part__pricing_data',
|
||||
'bom_item',
|
||||
'bom_item__part',
|
||||
'bom_item__part__pricing_data',
|
||||
'bom_item__sub_part',
|
||||
'bom_item__sub_part__pricing_data'
|
||||
)
|
||||
|
||||
# Pre-fetch related fields
|
||||
|
||||
@@ -47,6 +47,8 @@ class BuildTestSimple(InvenTreeTestCase):
|
||||
b1 = Build.objects.get(pk=1)
|
||||
if settings.ENABLE_CLASSIC_FRONTEND:
|
||||
self.assertEqual(b1.get_absolute_url(), '/build/1/')
|
||||
else:
|
||||
self.assertEqual(b1.get_absolute_url(), '/platform/manufacturing/build-order/1')
|
||||
|
||||
def test_is_complete(self):
|
||||
"""Test build completion status"""
|
||||
|
||||
@@ -62,6 +62,10 @@ class CompanySimpleTest(TestCase):
|
||||
c = Company.objects.get(pk=1)
|
||||
if settings.ENABLE_CLASSIC_FRONTEND:
|
||||
self.assertEqual(c.get_absolute_url(), '/company/1/')
|
||||
else:
|
||||
self.assertEqual(
|
||||
c.get_absolute_url(), '/platform/purchasing/manufacturer/1'
|
||||
)
|
||||
|
||||
def test_image_renamer(self):
|
||||
"""Test the company image upload functionality."""
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Arabic\n"
|
||||
"Language: ar_SA\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "نقطة نهاية API غير موجودة"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "المستخدم ليس لديه الصلاحية لعرض هذا النموذج"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Bulgarian\n"
|
||||
"Language: bg_BG\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Не е намерена крайна точка на API"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Потребителя няма нужното разрешение, за да вижда този модел"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Czech\n"
|
||||
"Language: cs_CZ\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API endpoint nebyl nalezen"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Uživatel nemá právo zobrazit tento model"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Danish\n"
|
||||
"Language: da_DK\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API endpoint ikke fundet"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Bruger har ikke tilladelse til at se denne model"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"Language: de_DE\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API-Endpunkt nicht gefunden"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Benutzer hat keine Berechtigung, dieses Modell anzuzeigen"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Greek\n"
|
||||
"Language: el_GR\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Το API endpoint δε βρέθηκε"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Δεν έχετε δικαιώματα να το δείτε αυτό"
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 10:24+0000\n"
|
||||
"POT-Creation-Date: 2024-11-08 08:37+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,23 +18,23 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"Language: es_ES\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "endpoint API no encontrado"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "El usuario no tiene permiso para ver este modelo"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish, Mexico\n"
|
||||
"Language: es_MX\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Endpoint de API no encontrado"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "El usuario no tiene permiso para ver este modelo"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Estonian\n"
|
||||
"Language: et_EE\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Teil ei ole selle lehe vaatamiseks luba"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Persian\n"
|
||||
"Language: fa_IR\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Address e API peida nashod"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "کاربر سطح دسترسی نمایش این مدل را ندارد"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Finnish\n"
|
||||
"Language: fi_FI\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API-rajapintaa ei löydy"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Käyttäjän oikeudet eivät riitä kohteen tarkastelemiseen"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 10:27\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"Language: fr_FR\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Point de terminaison de l'API introuvable"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "L'utilisateur n'a pas la permission de voir ce modèle"
|
||||
|
||||
@@ -2249,7 +2249,7 @@ msgstr "Utilisateur ou groupe responsable de ce projet"
|
||||
|
||||
#: common/models.py:783 common/models.py:2236 common/models.py:2613
|
||||
msgid "Settings key"
|
||||
msgstr ""
|
||||
msgstr "Paramétrés des touches"
|
||||
|
||||
#: common/models.py:787
|
||||
msgid "Settings value"
|
||||
@@ -5979,7 +5979,7 @@ msgstr ""
|
||||
|
||||
#: order/serializers.py:93
|
||||
msgid "Copy Lines"
|
||||
msgstr ""
|
||||
msgstr "Copier des lignes"
|
||||
|
||||
#: order/serializers.py:94
|
||||
msgid "Copy line items from the original order"
|
||||
@@ -5987,7 +5987,7 @@ msgstr ""
|
||||
|
||||
#: order/serializers.py:100
|
||||
msgid "Copy Extra Lines"
|
||||
msgstr ""
|
||||
msgstr "Copier les lignes supplémentaires"
|
||||
|
||||
#: order/serializers.py:101
|
||||
msgid "Copy extra line items from the original order"
|
||||
@@ -6168,7 +6168,7 @@ msgstr "Aucune correspondance trouvée pour les numéros de série suivants"
|
||||
|
||||
#: order/serializers.py:1678
|
||||
msgid "The following serial numbers are unavailable"
|
||||
msgstr "Les numéros de série suivants ne sont pas disponibles"
|
||||
msgstr "Les numéros de série suivants sont indisponibles"
|
||||
|
||||
#: order/serializers.py:1904
|
||||
msgid "Return order line item"
|
||||
@@ -7672,7 +7672,7 @@ msgstr ""
|
||||
|
||||
#: part/serializers.py:277
|
||||
msgid "Model ID"
|
||||
msgstr ""
|
||||
msgstr "Identifiant du Modèle"
|
||||
|
||||
#: part/serializers.py:324
|
||||
msgid "Number of parts using this template"
|
||||
@@ -8917,11 +8917,11 @@ msgstr ""
|
||||
|
||||
#: plugin/base/ui/serializers.py:30
|
||||
msgid "Plugin Name"
|
||||
msgstr ""
|
||||
msgstr "Nom de l'extension"
|
||||
|
||||
#: plugin/base/ui/serializers.py:34
|
||||
msgid "Feature Type"
|
||||
msgstr ""
|
||||
msgstr "Type de fonctionnalité"
|
||||
|
||||
#: plugin/base/ui/serializers.py:39
|
||||
msgid "Feature Label"
|
||||
@@ -8929,27 +8929,27 @@ msgstr ""
|
||||
|
||||
#: plugin/base/ui/serializers.py:44
|
||||
msgid "Feature Title"
|
||||
msgstr ""
|
||||
msgstr "Titre de la fonctionnalité"
|
||||
|
||||
#: plugin/base/ui/serializers.py:49
|
||||
msgid "Feature Description"
|
||||
msgstr ""
|
||||
msgstr "Description de la fonctionnalité"
|
||||
|
||||
#: plugin/base/ui/serializers.py:54
|
||||
msgid "Feature Icon"
|
||||
msgstr ""
|
||||
msgstr "Icône de fonctionnalité"
|
||||
|
||||
#: plugin/base/ui/serializers.py:58
|
||||
msgid "Feature Options"
|
||||
msgstr ""
|
||||
msgstr "Options de fonctionnalité"
|
||||
|
||||
#: plugin/base/ui/serializers.py:61
|
||||
msgid "Feature Context"
|
||||
msgstr ""
|
||||
msgstr "Contexte de la fonctionnalité"
|
||||
|
||||
#: plugin/base/ui/serializers.py:64
|
||||
msgid "Feature Source (javascript)"
|
||||
msgstr ""
|
||||
msgstr "Source de la fonctionnalité (javascript)"
|
||||
|
||||
#: plugin/builtin/barcodes/inventree_barcode.py:27
|
||||
msgid "InvenTree Barcodes"
|
||||
@@ -9331,7 +9331,7 @@ msgstr ""
|
||||
|
||||
#: plugin/samples/integration/user_interface_sample.py:33
|
||||
msgid "Enable Purchase Order Panels"
|
||||
msgstr ""
|
||||
msgstr "Activer les panneaux de commande"
|
||||
|
||||
#: plugin/samples/integration/user_interface_sample.py:34
|
||||
msgid "Enable custom panels for Purchase Order views"
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hebrew\n"
|
||||
"Language: he_IL\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "למשתמש אין הרשאה לצפות במוזל הזה"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hindi\n"
|
||||
"Language: hi_IN\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hungarian\n"
|
||||
"Language: hu_HU\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API funkciót nem találom"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Nincs jogosultságod az adatok megtekintéséhez"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Indonesian\n"
|
||||
"Language: id_ID\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API endpoint tidak ditemukan"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Pengguna tidak memiliki izin untuk melihat model ini"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Italian\n"
|
||||
"Language: it_IT\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Endpoint API non trovato"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "L'utente non ha i permessi per vedere questo modello"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Japanese\n"
|
||||
"Language: ja_JP\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "APIエンドポイントが見つかりません"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "ユーザーにこのモデルを表示する権限がありません"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Korean\n"
|
||||
"Language: ko_KR\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Lithuanian\n"
|
||||
"Language: lt_LT\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Latvian\n"
|
||||
"Language: lv_LV\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API galapunkts nav atrasts"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Lietotājam nav atļaujas, lai apskatītu šo modeli"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Dutch\n"
|
||||
"Language: nl_NL\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API eindpunt niet gevonden"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr "Ongeldige items lijst verstrekt"
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr "Ongeldige filters opgegeven"
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr "Geen items gevonden om te verwijderen"
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Gebruiker heeft geen rechten om dit model te bekijken"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Norwegian\n"
|
||||
"Language: no_NO\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API-endepunkt ikke funnet"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Brukeren har ikke rettigheter til å se denne modellen"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Polish\n"
|
||||
"Language: pl_PL\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Nie znaleziono punktu końcowego API"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Użytkownik nie ma uprawnień do przeglądania tego modelu"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"Language: pt_PT\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API endpoint não encontrado"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Usuário não tem permissão para ver este modelo"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese, Brazilian\n"
|
||||
"Language: pt_BR\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API endpoint não encontrado"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
msgstr "Lista de itens inválida fornecida"
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
msgstr "Filtros inválidos fornecidos"
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
msgstr "Nenhum item encontrado para excluir"
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr ""
|
||||
|
||||
@@ -150,7 +150,7 @@ msgstr ""
|
||||
|
||||
#: InvenTree/helpers.py:509
|
||||
msgid "Cannot serialize more than 1000 items at once"
|
||||
msgstr ""
|
||||
msgstr "Não é possível serializar mais de 1000 itens de uma vez"
|
||||
|
||||
#: InvenTree/helpers.py:515
|
||||
msgid "Empty serial number string"
|
||||
@@ -164,7 +164,7 @@ msgstr ""
|
||||
#: InvenTree/helpers.py:644 InvenTree/helpers.py:663
|
||||
#, python-brace-format
|
||||
msgid "Invalid group: {group}"
|
||||
msgstr ""
|
||||
msgstr "Grupo invalido:{group}"
|
||||
|
||||
#: InvenTree/helpers.py:607
|
||||
#, python-brace-format
|
||||
@@ -373,7 +373,7 @@ msgstr "Chinês (tradicional)"
|
||||
|
||||
#: InvenTree/magic_login.py:28
|
||||
msgid "Log in to the app"
|
||||
msgstr ""
|
||||
msgstr "Entrar no aplicativo"
|
||||
|
||||
#: InvenTree/magic_login.py:38 InvenTree/serializers.py:416
|
||||
#: company/models.py:133 company/templates/company/company_base.html:138
|
||||
@@ -522,7 +522,7 @@ msgstr ""
|
||||
|
||||
#: InvenTree/models.py:1112
|
||||
msgid "Task Failure"
|
||||
msgstr ""
|
||||
msgstr "Falha na Tarefa"
|
||||
|
||||
#: InvenTree/models.py:1114
|
||||
#, python-brace-format
|
||||
@@ -643,7 +643,7 @@ msgstr ""
|
||||
|
||||
#: InvenTree/serializers.py:632 common/files.py:63
|
||||
msgid "Unsupported file format"
|
||||
msgstr ""
|
||||
msgstr "Formato de arquivo não suportado"
|
||||
|
||||
#: InvenTree/serializers.py:638
|
||||
msgid "File is too large"
|
||||
@@ -689,7 +689,7 @@ msgstr ""
|
||||
|
||||
#: InvenTree/serializers.py:917
|
||||
msgid "Failed to download image from remote URL"
|
||||
msgstr ""
|
||||
msgstr "Falha ao baixar a imagem da URL remota"
|
||||
|
||||
#: InvenTree/templatetags/inventree_extras.py:184
|
||||
msgid "Unknown database"
|
||||
@@ -6136,7 +6136,7 @@ msgstr ""
|
||||
|
||||
#: order/serializers.py:1260
|
||||
msgid "Allocated Items"
|
||||
msgstr ""
|
||||
msgstr "Itens Alocados"
|
||||
|
||||
#: order/serializers.py:1374
|
||||
msgid "No shipment details provided"
|
||||
@@ -6168,7 +6168,7 @@ msgstr ""
|
||||
|
||||
#: order/serializers.py:1678
|
||||
msgid "The following serial numbers are unavailable"
|
||||
msgstr ""
|
||||
msgstr "Os seguintes números de série não estão disponíveis"
|
||||
|
||||
#: order/serializers.py:1904
|
||||
msgid "Return order line item"
|
||||
@@ -7346,7 +7346,7 @@ msgstr ""
|
||||
|
||||
#: part/models.py:3626
|
||||
msgid "Test templates can only be created for testable parts"
|
||||
msgstr ""
|
||||
msgstr "Modelos de teste só podem ser criados para partes testáveis"
|
||||
|
||||
#: part/models.py:3637
|
||||
msgid "Test template with the same key already exists for part"
|
||||
@@ -7668,11 +7668,11 @@ msgstr ""
|
||||
|
||||
#: part/serializers.py:268
|
||||
msgid "Speculative Quantity"
|
||||
msgstr ""
|
||||
msgstr "Quantidade Especulativa"
|
||||
|
||||
#: part/serializers.py:277
|
||||
msgid "Model ID"
|
||||
msgstr ""
|
||||
msgstr "ID do modelo"
|
||||
|
||||
#: part/serializers.py:324
|
||||
msgid "Number of parts using this template"
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Romanian\n"
|
||||
"Language: ro_RO\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Russian\n"
|
||||
"Language: ru_RU\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Конечная точка API не обнаружена"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "У пользователя недостаточно прав для просмотра этой модели!"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Slovak\n"
|
||||
"Language: sk_SK\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Slovenian\n"
|
||||
"Language: sl_SI\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API vmesnik ni najden"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Uporabnik nima dovoljenja pogleda tega modela"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Serbian (Latin)\n"
|
||||
"Language: sr_CS\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API krajnja tačka nije pronađena"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Korisnik nema dozvolu za pregled ovog modela"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-07 00:24\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Swedish\n"
|
||||
"Language: sv_SE\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API-slutpunkt hittades inte"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Användaren har inte behörighet att se denna modell"
|
||||
|
||||
@@ -373,7 +373,7 @@ msgstr "Kinesiska (Traditionell)"
|
||||
|
||||
#: InvenTree/magic_login.py:28
|
||||
msgid "Log in to the app"
|
||||
msgstr ""
|
||||
msgstr "Logga in på appen"
|
||||
|
||||
#: InvenTree/magic_login.py:38 InvenTree/serializers.py:416
|
||||
#: company/models.py:133 company/templates/company/company_base.html:138
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Thai\n"
|
||||
"Language: th_TH\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "ไม่พบ API endpoint"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Turkish\n"
|
||||
"Language: tr_TR\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API uç noktası bulunamadı"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Kullanıcının bu modeli görüntüleme izni yok"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-07 23:53\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Ukrainian\n"
|
||||
"Language: uk_UA\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "Кінцева точка API не знайдена"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "У користувача немає дозволу на перегляд цієї моделі"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-05 22:31\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Vietnamese\n"
|
||||
"Language: vi_VN\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "API endpoint không tồn tại"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "Người dùng không được phân quyền xem mẫu này"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 10:27\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-07 23:53\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Language: zh_CN\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "未找到 API 端点"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr "提供了无效的单位"
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr "提供了无效的过滤器"
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr "未找到要删除的项目"
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "用户没有权限查阅当前模型。"
|
||||
|
||||
@@ -905,7 +905,7 @@ msgstr "生产订单"
|
||||
#: templates/InvenTree/settings/sidebar.html:55
|
||||
#: templates/js/translated/search.js:186 users/models.py:207
|
||||
msgid "Build Orders"
|
||||
msgstr "生產工單"
|
||||
msgstr "生产订单"
|
||||
|
||||
#: build/models.py:136
|
||||
msgid "Assembly BOM has not been validated"
|
||||
@@ -4926,7 +4926,7 @@ msgstr "新建采购订单"
|
||||
#: templates/js/translated/search.js:219 templates/navbar.html:62
|
||||
#: users/models.py:209
|
||||
msgid "Sales Orders"
|
||||
msgstr "銷售訂單"
|
||||
msgstr "销售订单"
|
||||
|
||||
#: company/templates/company/detail.html:105
|
||||
#: order/templates/order/sales_orders.html:20
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: inventree\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-04 03:11+0000\n"
|
||||
"PO-Revision-Date: 2024-11-04 03:14\n"
|
||||
"POT-Creation-Date: 2024-11-05 22:28+0000\n"
|
||||
"PO-Revision-Date: 2024-11-07 23:53\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Traditional\n"
|
||||
"Language: zh_TW\n"
|
||||
@@ -17,23 +17,23 @@ msgstr ""
|
||||
"X-Crowdin-File: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po\n"
|
||||
"X-Crowdin-File-ID: 250\n"
|
||||
|
||||
#: InvenTree/api.py:270
|
||||
#: InvenTree/api.py:273
|
||||
msgid "API endpoint not found"
|
||||
msgstr "未找到 API 端點"
|
||||
|
||||
#: InvenTree/api.py:387
|
||||
#: InvenTree/api.py:390
|
||||
msgid "Invalid items list provided"
|
||||
msgstr "提供了無效的單位"
|
||||
|
||||
#: InvenTree/api.py:396
|
||||
#: InvenTree/api.py:399
|
||||
msgid "Invalid filters provided"
|
||||
msgstr "提供了無效的過濾器"
|
||||
|
||||
#: InvenTree/api.py:401
|
||||
#: InvenTree/api.py:404
|
||||
msgid "No items found to delete"
|
||||
msgstr "未找到要刪除的項目"
|
||||
|
||||
#: InvenTree/api.py:515
|
||||
#: InvenTree/api.py:518
|
||||
msgid "User does not have permission to view this model"
|
||||
msgstr "用户沒有權限查閲當前模型。"
|
||||
|
||||
|
||||
@@ -816,6 +816,17 @@ class SalesOrderLineItemFilter(LineItemFilter):
|
||||
|
||||
return queryset.exclude(order__status__in=SalesOrderStatusGroups.COMPLETE)
|
||||
|
||||
order_outstanding = rest_filters.BooleanFilter(
|
||||
label=_('Order Outstanding'), method='filter_order_outstanding'
|
||||
)
|
||||
|
||||
def filter_order_outstanding(self, queryset, name, value):
|
||||
"""Filter by whether the order is 'outstanding' or not."""
|
||||
if str2bool(value):
|
||||
return queryset.filter(order__status__in=SalesOrderStatusGroups.OPEN)
|
||||
|
||||
return queryset.exclude(order__status__in=SalesOrderStatusGroups.OPEN)
|
||||
|
||||
|
||||
class SalesOrderLineItemMixin:
|
||||
"""Mixin class for SalesOrderLineItem endpoints."""
|
||||
@@ -978,7 +989,7 @@ class SalesOrderAllocationFilter(rest_filters.FilterSet):
|
||||
"""Metaclass options."""
|
||||
|
||||
model = models.SalesOrderAllocation
|
||||
fields = ['shipment', 'item']
|
||||
fields = ['shipment', 'line', 'item']
|
||||
|
||||
order = rest_filters.ModelChoiceFilter(
|
||||
queryset=models.SalesOrder.objects.all(),
|
||||
@@ -1034,6 +1045,16 @@ class SalesOrderAllocationFilter(rest_filters.FilterSet):
|
||||
line__order__status__in=SalesOrderStatusGroups.OPEN,
|
||||
)
|
||||
|
||||
assigned_to_shipment = rest_filters.BooleanFilter(
|
||||
label=_('Has Shipment'), method='filter_assigned_to_shipment'
|
||||
)
|
||||
|
||||
def filter_assigned_to_shipment(self, queryset, name, value):
|
||||
"""Filter by whether or not the allocation has been assigned to a shipment."""
|
||||
if str2bool(value):
|
||||
return queryset.exclude(shipment=None)
|
||||
return queryset.filter(shipment=None)
|
||||
|
||||
|
||||
class SalesOrderAllocationMixin:
|
||||
"""Mixin class for SalesOrderAllocation endpoints."""
|
||||
@@ -1049,12 +1070,16 @@ class SalesOrderAllocationMixin:
|
||||
'item',
|
||||
'item__sales_order',
|
||||
'item__part',
|
||||
'line__part',
|
||||
'item__location',
|
||||
'line__order',
|
||||
'line__part',
|
||||
'line__order__responsible',
|
||||
'line__order__project_code',
|
||||
'line__order__project_code__responsible',
|
||||
'shipment',
|
||||
'shipment__order',
|
||||
)
|
||||
'shipment__checked_by',
|
||||
).select_related('line__part__pricing_data', 'item__part__pricing_data')
|
||||
|
||||
return queryset
|
||||
|
||||
@@ -1065,7 +1090,15 @@ class SalesOrderAllocationList(SalesOrderAllocationMixin, ListAPI):
|
||||
filterset_class = SalesOrderAllocationFilter
|
||||
filter_backends = SEARCH_ORDER_FILTER_ALIAS
|
||||
|
||||
ordering_fields = ['quantity', 'part', 'serial', 'batch', 'location', 'order']
|
||||
ordering_fields = [
|
||||
'quantity',
|
||||
'part',
|
||||
'serial',
|
||||
'batch',
|
||||
'location',
|
||||
'order',
|
||||
'shipment_date',
|
||||
]
|
||||
|
||||
ordering_field_aliases = {
|
||||
'part': 'item__part__name',
|
||||
@@ -1073,6 +1106,7 @@ class SalesOrderAllocationList(SalesOrderAllocationMixin, ListAPI):
|
||||
'batch': 'item__batch',
|
||||
'location': 'item__location__name',
|
||||
'order': 'line__order__reference',
|
||||
'shipment_date': 'shipment__shipment_date',
|
||||
}
|
||||
|
||||
search_fields = {'item__part__name', 'item__serial', 'item__batch'}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.2.16 on 2024-11-06 04:46
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0102_purchaseorder_destination_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='salesorderallocation',
|
||||
name='shipment',
|
||||
field=models.ForeignKey(blank=True, help_text='Sales order shipment reference', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocations', to='order.salesordershipment', verbose_name='Shipment'),
|
||||
),
|
||||
]
|
||||
@@ -1105,6 +1105,11 @@ class SalesOrder(TotalPriceMixin, Order):
|
||||
_('Order cannot be completed as there are incomplete shipments')
|
||||
)
|
||||
|
||||
if self.pending_allocation_count > 0:
|
||||
raise ValidationError(
|
||||
_('Order cannot be completed as there are incomplete allocations')
|
||||
)
|
||||
|
||||
if not allow_incomplete_lines and self.pending_line_count > 0:
|
||||
raise ValidationError(
|
||||
_('Order cannot be completed as there are incomplete line items')
|
||||
@@ -1297,6 +1302,23 @@ class SalesOrder(TotalPriceMixin, Order):
|
||||
"""Return a queryset of the pending shipments for this order."""
|
||||
return self.shipments.filter(shipment_date=None)
|
||||
|
||||
def allocations(self):
|
||||
"""Return a queryset of all allocations for this order."""
|
||||
return SalesOrderAllocation.objects.filter(line__order=self)
|
||||
|
||||
def pending_allocations(self):
|
||||
"""Return a queryset of any pending allocations for this order.
|
||||
|
||||
Allocations are pending if:
|
||||
|
||||
a) They are not associated with a SalesOrderShipment
|
||||
b) The linked SalesOrderShipment has not been shipped
|
||||
"""
|
||||
Q1 = Q(shipment=None)
|
||||
Q2 = Q(shipment__shipment_date=None)
|
||||
|
||||
return self.allocations().filter(Q1 | Q2).distinct()
|
||||
|
||||
@property
|
||||
def shipment_count(self):
|
||||
"""Return the total number of shipments associated with this order."""
|
||||
@@ -1312,6 +1334,11 @@ class SalesOrder(TotalPriceMixin, Order):
|
||||
"""Return the number of pending shipments associated with this order."""
|
||||
return self.pending_shipments().count()
|
||||
|
||||
@property
|
||||
def pending_allocation_count(self):
|
||||
"""Return the number of pending (non-shipped) allocations."""
|
||||
return self.pending_allocations().count()
|
||||
|
||||
|
||||
@receiver(post_save, sender=SalesOrder, dispatch_uid='sales_order_post_save')
|
||||
def after_save_sales_order(sender, instance: SalesOrder, created: bool, **kwargs):
|
||||
@@ -2030,7 +2057,7 @@ class SalesOrderAllocation(models.Model):
|
||||
if self.item.serial and self.quantity != 1:
|
||||
errors['quantity'] = _('Quantity must be 1 for serialized stock item')
|
||||
|
||||
if self.line.order != self.shipment.order:
|
||||
if self.shipment and self.line.order != self.shipment.order:
|
||||
errors['line'] = _('Sales order does not match shipment')
|
||||
errors['shipment'] = _('Shipment does not match sales order')
|
||||
|
||||
@@ -2047,6 +2074,8 @@ class SalesOrderAllocation(models.Model):
|
||||
shipment = models.ForeignKey(
|
||||
SalesOrderShipment,
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='allocations',
|
||||
verbose_name=_('Shipment'),
|
||||
help_text=_('Sales order shipment reference'),
|
||||
|
||||
@@ -990,6 +990,8 @@ class SalesOrderSerializer(
|
||||
'shipment_date',
|
||||
'total_price',
|
||||
'order_currency',
|
||||
'shipments_count',
|
||||
'completed_shipments_count',
|
||||
])
|
||||
|
||||
read_only_fields = ['status', 'creation_date', 'shipment_date']
|
||||
@@ -1035,12 +1037,26 @@ class SalesOrderSerializer(
|
||||
)
|
||||
)
|
||||
|
||||
# Annotate shipment details
|
||||
queryset = queryset.annotate(
|
||||
shipments_count=SubqueryCount('shipments'),
|
||||
completed_shipments_count=SubqueryCount(
|
||||
'shipments', filter=Q(shipment_date__isnull=False)
|
||||
),
|
||||
)
|
||||
|
||||
return queryset
|
||||
|
||||
customer_detail = CompanyBriefSerializer(
|
||||
source='customer', many=False, read_only=True
|
||||
)
|
||||
|
||||
shipments_count = serializers.IntegerField(read_only=True, label=_('Shipments'))
|
||||
|
||||
completed_shipments_count = serializers.IntegerField(
|
||||
read_only=True, label=_('Completed Shipments')
|
||||
)
|
||||
|
||||
|
||||
class SalesOrderIssueSerializer(OrderAdjustSerializer):
|
||||
"""Serializer for issuing a SalesOrder."""
|
||||
@@ -1246,6 +1262,15 @@ class SalesOrderShipmentSerializer(NotesFieldMixin, InvenTreeModelSerializer):
|
||||
'notes',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialization routine for the serializer."""
|
||||
order_detail = kwargs.pop('order_detail', True)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if not order_detail:
|
||||
self.fields.pop('order_detail', None)
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
"""Annotate the queryset with extra information."""
|
||||
@@ -1276,22 +1301,26 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer):
|
||||
|
||||
fields = [
|
||||
'pk',
|
||||
'line',
|
||||
'customer_detail',
|
||||
'serial',
|
||||
'quantity',
|
||||
'location',
|
||||
'location_detail',
|
||||
'item',
|
||||
'item_detail',
|
||||
'order',
|
||||
'order_detail',
|
||||
'part',
|
||||
'part_detail',
|
||||
'quantity',
|
||||
'shipment',
|
||||
# Annotated read-only fields
|
||||
'line',
|
||||
'part',
|
||||
'order',
|
||||
'serial',
|
||||
'location',
|
||||
# Extra detail fields
|
||||
'item_detail',
|
||||
'part_detail',
|
||||
'order_detail',
|
||||
'customer_detail',
|
||||
'location_detail',
|
||||
'shipment_detail',
|
||||
]
|
||||
|
||||
read_only_fields = ['line', '']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialization routine for the serializer."""
|
||||
order_detail = kwargs.pop('order_detail', False)
|
||||
@@ -1341,7 +1370,7 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer):
|
||||
)
|
||||
|
||||
shipment_detail = SalesOrderShipmentSerializer(
|
||||
source='shipment', many=False, read_only=True
|
||||
source='shipment', order_detail=False, many=False, read_only=True
|
||||
)
|
||||
|
||||
|
||||
@@ -1596,8 +1625,8 @@ class SalesOrderSerialAllocationSerializer(serializers.Serializer):
|
||||
shipment = serializers.PrimaryKeyRelatedField(
|
||||
queryset=order.models.SalesOrderShipment.objects.all(),
|
||||
many=False,
|
||||
allow_null=False,
|
||||
required=True,
|
||||
required=False,
|
||||
allow_null=True,
|
||||
label=_('Shipment'),
|
||||
)
|
||||
|
||||
@@ -1609,10 +1638,10 @@ class SalesOrderSerialAllocationSerializer(serializers.Serializer):
|
||||
"""
|
||||
order = self.context['order']
|
||||
|
||||
if shipment.shipment_date is not None:
|
||||
if shipment and shipment.shipment_date is not None:
|
||||
raise ValidationError(_('Shipment has already been shipped'))
|
||||
|
||||
if shipment.order != order:
|
||||
if shipment and shipment.order != order:
|
||||
raise ValidationError(_('Shipment is not associated with this order'))
|
||||
|
||||
return shipment
|
||||
@@ -1720,8 +1749,8 @@ class SalesOrderShipmentAllocationSerializer(serializers.Serializer):
|
||||
shipment = serializers.PrimaryKeyRelatedField(
|
||||
queryset=order.models.SalesOrderShipment.objects.all(),
|
||||
many=False,
|
||||
allow_null=False,
|
||||
required=True,
|
||||
required=False,
|
||||
allow_null=True,
|
||||
label=_('Shipment'),
|
||||
)
|
||||
|
||||
@@ -1756,7 +1785,7 @@ class SalesOrderShipmentAllocationSerializer(serializers.Serializer):
|
||||
data = self.validated_data
|
||||
|
||||
items = data['items']
|
||||
shipment = data['shipment']
|
||||
shipment = data.get('shipment')
|
||||
|
||||
with transaction.atomic():
|
||||
for entry in items:
|
||||
|
||||
@@ -1877,7 +1877,6 @@ class SalesOrderAllocateTest(OrderTest):
|
||||
response = self.post(self.url, {}, expected_code=400)
|
||||
|
||||
self.assertIn('This field is required', str(response.data['items']))
|
||||
self.assertIn('This field is required', str(response.data['shipment']))
|
||||
|
||||
# Test with a single line items
|
||||
line = self.order.lines.first()
|
||||
|
||||
@@ -46,6 +46,11 @@ class OrderTest(TestCase):
|
||||
self.assertEqual(
|
||||
order.get_absolute_url(), f'/order/purchase-order/{pk}/'
|
||||
)
|
||||
else:
|
||||
self.assertEqual(
|
||||
order.get_absolute_url(),
|
||||
f'/platform/purchasing/purchase-order/{pk}',
|
||||
)
|
||||
|
||||
self.assertEqual(order.reference, f'PO-{pk:04d}')
|
||||
|
||||
|
||||
@@ -130,6 +130,10 @@ class CategoryTest(TestCase):
|
||||
"""Test that the PartCategory URL works."""
|
||||
if settings.ENABLE_CLASSIC_FRONTEND:
|
||||
self.assertEqual(self.capacitors.get_absolute_url(), '/part/category/3/')
|
||||
else:
|
||||
self.assertEqual(
|
||||
self.capacitors.get_absolute_url(), '/platform/part/category/3'
|
||||
)
|
||||
|
||||
def test_part_count(self):
|
||||
"""Test that the Category part count works."""
|
||||
|
||||
@@ -246,6 +246,8 @@ class PartTest(TestCase):
|
||||
self.assertEqual(self.r1.name, 'R_2K2_0805')
|
||||
if settings.ENABLE_CLASSIC_FRONTEND:
|
||||
self.assertEqual(self.r1.get_absolute_url(), '/part/3/')
|
||||
else:
|
||||
self.assertEqual(self.r1.get_absolute_url(), '/platform/part/3')
|
||||
|
||||
def test_category(self):
|
||||
"""Test PartCategory path."""
|
||||
|
||||
@@ -289,6 +289,10 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
||||
self.assertEqual(
|
||||
response.data['stocklocation']['web_url'], '/stock/location/5/'
|
||||
)
|
||||
else:
|
||||
self.assertEqual(
|
||||
response.data['stocklocation']['web_url'], '/platform/stock/location/5'
|
||||
)
|
||||
self.assertEqual(response.data['plugin'], 'InvenTreeBarcode')
|
||||
|
||||
# Scan a Part object
|
||||
@@ -332,6 +336,10 @@ class TestInvenTreeBarcode(InvenTreeAPITestCase):
|
||||
self.assertEqual(
|
||||
response.data['stocklocation']['web_url'], '/stock/location/5/'
|
||||
)
|
||||
else:
|
||||
self.assertEqual(
|
||||
response.data['stocklocation']['web_url'], '/platform/stock/location/5'
|
||||
)
|
||||
self.assertEqual(response.data['plugin'], 'InvenTreeBarcode')
|
||||
|
||||
# Scan a Part object
|
||||
|
||||
@@ -50,7 +50,7 @@ from InvenTree.mixins import (
|
||||
RetrieveAPI,
|
||||
RetrieveUpdateDestroyAPI,
|
||||
)
|
||||
from order.models import PurchaseOrder, ReturnOrder, SalesOrder, SalesOrderAllocation
|
||||
from order.models import PurchaseOrder, ReturnOrder, SalesOrder
|
||||
from order.serializers import (
|
||||
PurchaseOrderSerializer,
|
||||
ReturnOrderSerializer,
|
||||
@@ -101,55 +101,6 @@ class GenerateSerialNumber(GenericAPIView):
|
||||
return Response(data, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class StockDetail(RetrieveUpdateDestroyAPI):
|
||||
"""API detail endpoint for Stock object.
|
||||
|
||||
get:
|
||||
Return a single StockItem object
|
||||
|
||||
post:
|
||||
Update a StockItem
|
||||
|
||||
delete:
|
||||
Remove a StockItem
|
||||
"""
|
||||
|
||||
queryset = StockItem.objects.all()
|
||||
serializer_class = StockSerializers.StockItemSerializer
|
||||
|
||||
def get_queryset(self, *args, **kwargs):
|
||||
"""Annotate queryset."""
|
||||
queryset = super().get_queryset(*args, **kwargs)
|
||||
queryset = StockSerializers.StockItemSerializer.annotate_queryset(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""Extend serializer context."""
|
||||
ctx = super().get_serializer_context()
|
||||
ctx['user'] = getattr(self.request, 'user', None)
|
||||
|
||||
return ctx
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""Set context before returning serializer."""
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
|
||||
try:
|
||||
params = self.request.query_params
|
||||
|
||||
kwargs['part_detail'] = str2bool(params.get('part_detail', True))
|
||||
kwargs['location_detail'] = str2bool(params.get('location_detail', True))
|
||||
kwargs['supplier_part_detail'] = str2bool(
|
||||
params.get('supplier_part_detail', True)
|
||||
)
|
||||
kwargs['path_detail'] = str2bool(params.get('path_detail', False))
|
||||
except AttributeError: # pragma: no cover
|
||||
pass
|
||||
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
|
||||
class StockItemContextMixin:
|
||||
"""Mixin class for adding StockItem object to serializer context."""
|
||||
|
||||
@@ -531,54 +482,88 @@ class StockFilter(rest_filters.FilterSet):
|
||||
)
|
||||
|
||||
supplier = rest_filters.ModelChoiceFilter(
|
||||
label='Supplier',
|
||||
label=_('Supplier'),
|
||||
queryset=Company.objects.filter(is_supplier=True),
|
||||
field_name='supplier_part__supplier',
|
||||
)
|
||||
|
||||
include_variants = rest_filters.BooleanFilter(
|
||||
label=_('Include Variants'), method='filter_include_variants'
|
||||
)
|
||||
|
||||
def filter_include_variants(self, queryset, name, value):
|
||||
"""Filter by whether or not to include variants of the selected part.
|
||||
|
||||
Note:
|
||||
- This filter does nothing by itself, and requires the 'part' filter to be set.
|
||||
- Refer to the 'filter_part' method for more information.
|
||||
"""
|
||||
return queryset
|
||||
|
||||
part = rest_filters.ModelChoiceFilter(
|
||||
label=_('Part'), queryset=Part.objects.all(), method='filter_part'
|
||||
)
|
||||
|
||||
def filter_part(self, queryset, name, part):
|
||||
"""Filter StockItem list by provided Part instance.
|
||||
|
||||
Note:
|
||||
- If "part" is a variant, include all variants of the selected part
|
||||
- Otherwise, filter by the selected part
|
||||
"""
|
||||
include_variants = str2bool(self.data.get('include_variants', True))
|
||||
|
||||
if include_variants:
|
||||
return queryset.filter(part__in=part.get_descendants(include_self=True))
|
||||
else:
|
||||
return queryset.filter(part=part)
|
||||
|
||||
# Part name filters
|
||||
name = rest_filters.CharFilter(
|
||||
label='Part name (case insensitive)',
|
||||
label=_('Part name (case insensitive)'),
|
||||
field_name='part__name',
|
||||
lookup_expr='iexact',
|
||||
)
|
||||
name_contains = rest_filters.CharFilter(
|
||||
label='Part name contains (case insensitive)',
|
||||
label=_('Part name contains (case insensitive)'),
|
||||
field_name='part__name',
|
||||
lookup_expr='icontains',
|
||||
)
|
||||
|
||||
name_regex = rest_filters.CharFilter(
|
||||
label='Part name (regex)', field_name='part__name', lookup_expr='iregex'
|
||||
label=_('Part name (regex)'), field_name='part__name', lookup_expr='iregex'
|
||||
)
|
||||
|
||||
# Part IPN filters
|
||||
IPN = rest_filters.CharFilter(
|
||||
label='Part IPN (case insensitive)',
|
||||
label=_('Part IPN (case insensitive)'),
|
||||
field_name='part__IPN',
|
||||
lookup_expr='iexact',
|
||||
)
|
||||
IPN_contains = rest_filters.CharFilter(
|
||||
label='Part IPN contains (case insensitive)',
|
||||
label=_('Part IPN contains (case insensitive)'),
|
||||
field_name='part__IPN',
|
||||
lookup_expr='icontains',
|
||||
)
|
||||
IPN_regex = rest_filters.CharFilter(
|
||||
label='Part IPN (regex)', field_name='part__IPN', lookup_expr='iregex'
|
||||
label=_('Part IPN (regex)'), field_name='part__IPN', lookup_expr='iregex'
|
||||
)
|
||||
|
||||
# Part attribute filters
|
||||
assembly = rest_filters.BooleanFilter(label='Assembly', field_name='part__assembly')
|
||||
active = rest_filters.BooleanFilter(label='Active', field_name='part__active')
|
||||
salable = rest_filters.BooleanFilter(label='Salable', field_name='part__salable')
|
||||
assembly = rest_filters.BooleanFilter(
|
||||
label=_('Assembly'), field_name='part__assembly'
|
||||
)
|
||||
active = rest_filters.BooleanFilter(label=_('Active'), field_name='part__active')
|
||||
salable = rest_filters.BooleanFilter(label=_('Salable'), field_name='part__salable')
|
||||
|
||||
min_stock = rest_filters.NumberFilter(
|
||||
label='Minimum stock', field_name='quantity', lookup_expr='gte'
|
||||
label=_('Minimum stock'), field_name='quantity', lookup_expr='gte'
|
||||
)
|
||||
max_stock = rest_filters.NumberFilter(
|
||||
label='Maximum stock', field_name='quantity', lookup_expr='lte'
|
||||
label=_('Maximum stock'), field_name='quantity', lookup_expr='lte'
|
||||
)
|
||||
|
||||
status = rest_filters.NumberFilter(label='Status Code', method='filter_status')
|
||||
status = rest_filters.NumberFilter(label=_('Status Code'), method='filter_status')
|
||||
|
||||
def filter_status(self, queryset, name, value):
|
||||
"""Filter by integer status code."""
|
||||
@@ -860,17 +845,25 @@ class StockFilter(rest_filters.FilterSet):
|
||||
return queryset.exclude(stale_filter)
|
||||
|
||||
|
||||
class StockList(DataExportViewMixin, ListCreateDestroyAPIView):
|
||||
"""API endpoint for list view of Stock objects.
|
||||
|
||||
- GET: Return a list of all StockItem objects (with optional query filters)
|
||||
- POST: Create a new StockItem
|
||||
- DELETE: Delete multiple StockItem objects
|
||||
"""
|
||||
class StockApiMixin:
|
||||
"""Mixin class for StockItem API endpoints."""
|
||||
|
||||
serializer_class = StockSerializers.StockItemSerializer
|
||||
queryset = StockItem.objects.all()
|
||||
filterset_class = StockFilter
|
||||
|
||||
def get_queryset(self, *args, **kwargs):
|
||||
"""Annotate queryset."""
|
||||
queryset = super().get_queryset(*args, **kwargs)
|
||||
queryset = StockSerializers.StockItemSerializer.annotate_queryset(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""Extend serializer context."""
|
||||
ctx = super().get_serializer_context()
|
||||
ctx['user'] = getattr(self.request, 'user', None)
|
||||
|
||||
return ctx
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""Set context before returning serializer.
|
||||
@@ -899,12 +892,16 @@ class StockList(DataExportViewMixin, ListCreateDestroyAPIView):
|
||||
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""Extend serializer context."""
|
||||
ctx = super().get_serializer_context()
|
||||
ctx['user'] = getattr(self.request, 'user', None)
|
||||
|
||||
return ctx
|
||||
class StockList(DataExportViewMixin, StockApiMixin, ListCreateDestroyAPIView):
|
||||
"""API endpoint for list view of Stock objects.
|
||||
|
||||
- GET: Return a list of all StockItem objects (with optional query filters)
|
||||
- POST: Create a new StockItem
|
||||
- DELETE: Delete multiple StockItem objects
|
||||
"""
|
||||
|
||||
filterset_class = StockFilter
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""Create a new StockItem object via the API.
|
||||
@@ -1079,14 +1076,6 @@ class StockList(DataExportViewMixin, ListCreateDestroyAPIView):
|
||||
headers=self.get_success_headers(serializer.data),
|
||||
)
|
||||
|
||||
def get_queryset(self, *args, **kwargs):
|
||||
"""Annotate queryset before returning."""
|
||||
queryset = super().get_queryset(*args, **kwargs)
|
||||
|
||||
queryset = StockSerializers.StockItemSerializer.annotate_queryset(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
"""Custom filtering for the StockItem queryset."""
|
||||
params = self.request.query_params
|
||||
@@ -1107,46 +1096,6 @@ class StockList(DataExportViewMixin, ListCreateDestroyAPIView):
|
||||
except (ValueError, StockItem.DoesNotExist): # pragma: no cover
|
||||
pass
|
||||
|
||||
# Exclude StockItems which are already allocated to a particular SalesOrder
|
||||
exclude_so_allocation = params.get('exclude_so_allocation', None)
|
||||
|
||||
if exclude_so_allocation is not None:
|
||||
try:
|
||||
order = SalesOrder.objects.get(pk=exclude_so_allocation)
|
||||
|
||||
# Grab all the active SalesOrderAllocations for this order
|
||||
allocations = SalesOrderAllocation.objects.filter(
|
||||
line__pk__in=[line.pk for line in order.lines.all()]
|
||||
)
|
||||
|
||||
# Exclude any stock item which is already allocated to the sales order
|
||||
queryset = queryset.exclude(pk__in=[a.item.pk for a in allocations])
|
||||
|
||||
except (ValueError, SalesOrder.DoesNotExist): # pragma: no cover
|
||||
pass
|
||||
|
||||
# Does the client wish to filter by the Part ID?
|
||||
part_id = params.get('part', None)
|
||||
|
||||
if part_id:
|
||||
try:
|
||||
part = Part.objects.get(pk=part_id)
|
||||
|
||||
# Do we wish to filter *just* for this part, or also for parts *under* this one?
|
||||
include_variants = str2bool(params.get('include_variants', True))
|
||||
|
||||
if include_variants:
|
||||
# Filter by any parts "under" the given part
|
||||
parts = part.get_descendants(include_self=True)
|
||||
|
||||
queryset = queryset.filter(part__in=parts)
|
||||
|
||||
else:
|
||||
queryset = queryset.filter(part=part)
|
||||
|
||||
except (ValueError, Part.DoesNotExist):
|
||||
raise ValidationError({'part': 'Invalid Part ID specified'})
|
||||
|
||||
# Does the client wish to filter by stock location?
|
||||
loc_id = params.get('location', None)
|
||||
|
||||
@@ -1212,6 +1161,10 @@ class StockList(DataExportViewMixin, ListCreateDestroyAPIView):
|
||||
]
|
||||
|
||||
|
||||
class StockDetail(StockApiMixin, RetrieveUpdateDestroyAPI):
|
||||
"""API detail endpoint for a single StockItem instance."""
|
||||
|
||||
|
||||
class StockItemTestResultMixin:
|
||||
"""Mixin class for the StockItemTestResult API endpoints."""
|
||||
|
||||
|
||||
@@ -266,6 +266,9 @@ class StockTest(StockTestBase):
|
||||
if settings.ENABLE_CLASSIC_FRONTEND:
|
||||
self.assertEqual(it.get_absolute_url(), '/stock/item/2/')
|
||||
self.assertEqual(self.home.get_absolute_url(), '/stock/location/1/')
|
||||
else:
|
||||
self.assertEqual(it.get_absolute_url(), '/platform/stock/item/2')
|
||||
self.assertEqual(self.home.get_absolute_url(), '/platform/stock/location/1')
|
||||
|
||||
def test_strings(self):
|
||||
"""Test str function."""
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
constructField,
|
||||
constructForm,
|
||||
constructOrderTableButtons,
|
||||
disableFormInput,
|
||||
enableFormInput,
|
||||
endDate,
|
||||
formatCurrency,
|
||||
FullCalendar,
|
||||
@@ -1559,17 +1561,35 @@ function showAllocationSubTable(index, row, element, options) {
|
||||
// Add callbacks for 'edit' buttons
|
||||
table.find('.button-allocation-edit').click(function() {
|
||||
|
||||
var pk = $(this).attr('pk');
|
||||
let pk = $(this).attr('pk');
|
||||
let allocation = table.bootstrapTable('getRowByUniqueId', pk);
|
||||
|
||||
let disableShipment = allocation && allocation.shipment_detail?.shipment_date;
|
||||
|
||||
// Edit the sales order allocation
|
||||
constructForm(
|
||||
`/api/order/so-allocation/${pk}/`,
|
||||
{
|
||||
fields: {
|
||||
item: {},
|
||||
quantity: {},
|
||||
shipment: {
|
||||
filters: {
|
||||
order: allocation.order,
|
||||
shipped: false,
|
||||
}
|
||||
}
|
||||
},
|
||||
title: '{% trans "Edit Stock Allocation" %}',
|
||||
refreshTable: options.table,
|
||||
afterRender: function(fields, opts) {
|
||||
disableFormInput('item', opts);
|
||||
if (disableShipment) {
|
||||
disableFormInput('shipment', opts);
|
||||
} else {
|
||||
enableFormInput('shipment', opts);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -1593,6 +1613,8 @@ function showAllocationSubTable(index, row, element, options) {
|
||||
table.bootstrapTable({
|
||||
url: '{% url "api-so-allocation-list" %}',
|
||||
onPostBody: setupCallbacks,
|
||||
uniqueId: 'pk',
|
||||
idField: 'pk',
|
||||
queryParams: {
|
||||
...options.queryParams,
|
||||
part_detail: true,
|
||||
@@ -1614,7 +1636,11 @@ function showAllocationSubTable(index, row, element, options) {
|
||||
field: 'shipment',
|
||||
title: '{% trans "Shipment" %}',
|
||||
formatter: function(value, row) {
|
||||
return row.shipment_detail.reference;
|
||||
if (row.shipment_detail) {
|
||||
return row.shipment_detail.reference;
|
||||
} else {
|
||||
return '{% trans "No shipment" %}';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from django.apps import apps
|
||||
from django.contrib.auth.models import Group
|
||||
from django.test import TestCase, tag
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from common.settings import set_global_setting
|
||||
@@ -166,8 +166,6 @@ class OwnerModelTest(InvenTreeTestCase):
|
||||
self.assertEqual(response.status_code, status_code)
|
||||
return response.data
|
||||
|
||||
# TODO: Find out why this depends on CUI
|
||||
@tag('cui')
|
||||
def test_owner(self):
|
||||
"""Tests for the 'owner' model."""
|
||||
# Check that owner was created for user
|
||||
|
||||
@@ -497,9 +497,9 @@ export function useAllocateStockToBuildForm({
|
||||
lineItems,
|
||||
onFormSuccess
|
||||
}: {
|
||||
buildId: number;
|
||||
buildId?: number;
|
||||
outputId?: number | null;
|
||||
build: any;
|
||||
build?: any;
|
||||
lineItems: any[];
|
||||
onFormSuccess: (response: any) => void;
|
||||
}) {
|
||||
@@ -533,8 +533,8 @@ export function useAllocateStockToBuildForm({
|
||||
}, [lineItems, sourceLocation]);
|
||||
|
||||
useEffect(() => {
|
||||
setSourceLocation(build.take_from);
|
||||
}, [build.take_from]);
|
||||
setSourceLocation(build?.take_from);
|
||||
}, [build?.take_from]);
|
||||
|
||||
const sourceLocationField: ApiFormFieldType = useMemo(() => {
|
||||
return {
|
||||
@@ -545,7 +545,7 @@ export function useAllocateStockToBuildForm({
|
||||
label: t`Source Location`,
|
||||
description: t`Select the source location for the stock allocation`,
|
||||
name: 'source_location',
|
||||
value: build.take_from,
|
||||
value: build?.take_from,
|
||||
onValueChange: (value: any) => {
|
||||
setSourceLocation(value);
|
||||
}
|
||||
|
||||
@@ -356,13 +356,29 @@ export function useSalesOrderShipmentCompleteFields({
|
||||
}
|
||||
|
||||
export function useSalesOrderAllocationFields({
|
||||
shipmentId
|
||||
orderId,
|
||||
shipment
|
||||
}: {
|
||||
shipmentId?: number;
|
||||
orderId?: number;
|
||||
shipment: any | null;
|
||||
}): ApiFormFieldSet {
|
||||
return useMemo(() => {
|
||||
return {
|
||||
quantity: {}
|
||||
item: {
|
||||
// Cannot change item, but display for reference
|
||||
disabled: true
|
||||
},
|
||||
quantity: {},
|
||||
shipment: {
|
||||
// Cannot change shipment once it has been shipped
|
||||
disabled: !!shipment?.shipment_date,
|
||||
// Order ID is required for this field to be accessed
|
||||
hidden: !orderId,
|
||||
filters: {
|
||||
order: orderId,
|
||||
shipped: false
|
||||
}
|
||||
}
|
||||
};
|
||||
}, [shipmentId]);
|
||||
}, [orderId, shipment]);
|
||||
}
|
||||
|
||||
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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user